@@ -77,6 +77,11 @@ const props = defineProps({
77
77
required: false ,
78
78
default: 300 ,
79
79
},
80
+ scrollBoundary: {
81
+ type: Number ,
82
+ required: false ,
83
+ default: 0 ,
84
+ },
80
85
showProgress: {
81
86
type: Boolean ,
82
87
required: false ,
@@ -117,25 +122,46 @@ defineExpose({
117
122
list: listRef ,
118
123
});
119
124
120
- const { items, loading, pagination, scrollThreshold, listOptions, backdrop, hidePoster } =
121
- toRefs (props );
125
+ const {
126
+ items,
127
+ loading,
128
+ pagination,
129
+ scrollThreshold,
130
+ listOptions,
131
+ backdrop,
132
+ hidePoster,
133
+ scrollBoundary,
134
+ } = toRefs (props );
122
135
123
136
const scrolled = ref (false );
124
137
138
+ const isCompact = watchMedia (' (max-width: 600px)' );
139
+ const showBackdrop = computed (() => backdrop ?.value && ! isCompact .value );
140
+
141
+ const isTiny = watchMedia (' (max-width: 350px)' );
142
+ const showPoster = computed (() => ! hidePoster ?.value && ! isTiny .value );
143
+
144
+ const defaultSize = computed (() => (showPoster .value ? 145 : 130 ));
145
+ const listItemSize = computed (() => listOptions ?.value ?.itemSize ?? defaultSize .value );
146
+ const scrollBoundarySize = computed (
147
+ () => (scrollBoundary ?.value ?? 0 ) * listItemSize .value ,
148
+ );
149
+
125
150
const onScrollHandler = async (e : Event ) => {
126
151
if (loading .value ) return ;
127
152
if (! e ?.target ) return ;
128
153
const { scrollTop, scrollHeight, clientHeight } = e .target as HTMLElement ;
129
154
if (scrollHeight === clientHeight ) return ;
130
- if (! scrollTop ) {
155
+ if (! scrollTop || scrollTop < scrollBoundarySize . value ) {
131
156
scrolled .value = false ;
132
157
return emits (' onScrollTop' , listRef );
133
158
}
134
159
if (! scrolled .value && scrollTop > scrollThreshold .value ) {
135
160
emits (' onScroll' , listRef );
136
161
scrolled .value = true ;
137
162
}
138
- if (scrollHeight !== scrollTop + clientHeight ) return ;
163
+ const scrollBottom = scrollTop + clientHeight + scrollBoundarySize .value ;
164
+ if (scrollHeight > scrollBottom ) return ;
139
165
if (pagination ?.value && pagination ?.value ?.page === pagination ?.value ?.pageCount ) {
140
166
return ;
141
167
}
@@ -156,8 +182,6 @@ const onLoadMore = (payload: { page: number; pageCount: number; pageSize: number
156
182
};
157
183
158
184
const isEmpty = computed (() => ! items .value .length && ! loading .value );
159
- const defaultSize = computed (() => (hidePoster .value ? 130 : 145 ));
160
- const listItemSize = computed (() => listOptions ?.value ?.itemSize ?? defaultSize .value );
161
185
162
186
const topInset = computed (() => {
163
187
const listElementRef = listRef .value ?.$el ;
@@ -172,12 +196,6 @@ const listPaddingTop = computed(
172
196
() => topInset .value + (listOptions ?.value ?.paddingTop ?? 60 ),
173
197
);
174
198
const listPaddingBottom = computed (() => listOptions ?.value ?.paddingBottom ?? 32 );
175
-
176
- const isCompact = watchMedia (' (max-width: 600px)' );
177
- const showBackdrop = computed (() => backdrop ?.value && ! isCompact .value );
178
-
179
- const isTiny = watchMedia (' (max-width: 350px)' );
180
- const showPoster = computed (() => ! hidePoster ?.value && ! isTiny .value );
181
199
</script >
182
200
183
201
<template >
0 commit comments