@v-c/virtual-list 0.0.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/Filler.cjs +51 -1
  2. package/dist/Filler.js +47 -56
  3. package/dist/Item.cjs +26 -1
  4. package/dist/Item.js +23 -26
  5. package/dist/List.cjs +412 -1
  6. package/dist/List.d.ts +45 -9
  7. package/dist/List.js +407 -274
  8. package/dist/ScrollBar.cjs +259 -1
  9. package/dist/ScrollBar.d.ts +3 -97
  10. package/dist/ScrollBar.js +254 -191
  11. package/dist/_virtual/rolldown_runtime.cjs +21 -0
  12. package/dist/hooks/useDiffItem.cjs +19 -1
  13. package/dist/hooks/useDiffItem.js +16 -20
  14. package/dist/hooks/useFrameWheel.cjs +63 -1
  15. package/dist/hooks/useFrameWheel.js +60 -51
  16. package/dist/hooks/useGetSize.cjs +29 -1
  17. package/dist/hooks/useGetSize.d.ts +2 -2
  18. package/dist/hooks/useGetSize.js +27 -23
  19. package/dist/hooks/useHeights.cjs +66 -1
  20. package/dist/hooks/useHeights.d.ts +1 -1
  21. package/dist/hooks/useHeights.js +62 -41
  22. package/dist/hooks/useMobileTouchMove.cjs +82 -1
  23. package/dist/hooks/useMobileTouchMove.js +79 -43
  24. package/dist/hooks/useOriginScroll.cjs +23 -1
  25. package/dist/hooks/useOriginScroll.js +20 -16
  26. package/dist/hooks/useScrollDrag.cjs +83 -1
  27. package/dist/hooks/useScrollDrag.js +77 -48
  28. package/dist/hooks/useScrollTo.cjs +97 -0
  29. package/dist/hooks/useScrollTo.d.ts +19 -0
  30. package/dist/hooks/useScrollTo.js +94 -0
  31. package/dist/index.cjs +4 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.js +3 -4
  34. package/dist/interface.cjs +0 -1
  35. package/dist/interface.d.ts +1 -1
  36. package/dist/interface.js +0 -1
  37. package/dist/utils/CacheMap.cjs +25 -1
  38. package/dist/utils/CacheMap.d.ts +1 -1
  39. package/dist/utils/CacheMap.js +23 -28
  40. package/dist/utils/isFirefox.cjs +4 -1
  41. package/dist/utils/isFirefox.js +2 -4
  42. package/dist/utils/scrollbarUtil.cjs +8 -1
  43. package/dist/utils/scrollbarUtil.js +7 -6
  44. package/package.json +19 -13
  45. package/docs/basic.vue +0 -175
  46. package/docs/height.vue +0 -48
  47. package/docs/nest.vue +0 -60
  48. package/docs/no-virtual.vue +0 -127
  49. package/docs/switch.vue +0 -101
  50. package/docs/virtual-list.stories.vue +0 -31
  51. package/src/Filler.tsx +0 -72
  52. package/src/Item.tsx +0 -34
  53. package/src/List.tsx +0 -577
  54. package/src/ScrollBar.tsx +0 -298
  55. package/src/__tests__/List.test.ts +0 -59
  56. package/src/hooks/useDiffItem.ts +0 -27
  57. package/src/hooks/useFrameWheel.ts +0 -141
  58. package/src/hooks/useGetSize.ts +0 -44
  59. package/src/hooks/useHeights.ts +0 -106
  60. package/src/hooks/useMobileTouchMove.ts +0 -131
  61. package/src/hooks/useOriginScroll.ts +0 -47
  62. package/src/hooks/useScrollDrag.ts +0 -123
  63. package/src/index.ts +0 -5
  64. package/src/interface.ts +0 -32
  65. package/src/utils/CacheMap.ts +0 -42
  66. package/src/utils/isFirefox.ts +0 -3
  67. package/src/utils/scrollbarUtil.ts +0 -10
  68. package/vite.config.ts +0 -18
  69. package/vitest.config.ts +0 -11
package/dist/List.js CHANGED
@@ -1,276 +1,409 @@
1
- import { defineComponent as ae, computed as y, ref as r, shallowRef as ue, watch as T, createVNode as b, isVNode as re } from "vue";
2
- import ce from "@v-c/resize-observer";
3
- import se from "./Filler.js";
4
- import fe from "./hooks/useDiffItem.js";
5
- import ve from "./hooks/useFrameWheel.js";
6
- import { useGetSize as he } from "./hooks/useGetSize.js";
7
- import de from "./hooks/useHeights.js";
8
- import me from "./hooks/useMobileTouchMove.js";
9
- import ge from "./hooks/useScrollDrag.js";
10
- import Se from "./Item.js";
11
- import ye from "./ScrollBar.js";
12
- import { getSpinSize as xe } from "./utils/scrollbarUtil.js";
13
- function W(l) {
14
- return typeof l == "function" || Object.prototype.toString.call(l) === "[object Object]" && !re(l);
1
+ import Filler_default from "./Filler.js";
2
+ import Item_default from "./Item.js";
3
+ import useDiffItem from "./hooks/useDiffItem.js";
4
+ import useFrameWheel from "./hooks/useFrameWheel.js";
5
+ import { useGetSize } from "./hooks/useGetSize.js";
6
+ import useHeights from "./hooks/useHeights.js";
7
+ import useMobileTouchMove from "./hooks/useMobileTouchMove.js";
8
+ import useScrollDrag from "./hooks/useScrollDrag.js";
9
+ import useScrollTo from "./hooks/useScrollTo.js";
10
+ import ScrollBar_default from "./ScrollBar.js";
11
+ import { getSpinSize } from "./utils/scrollbarUtil.js";
12
+ import { computed, createVNode, defineComponent, isVNode, mergeProps, ref, shallowRef, toRaw, toRef, watch } from "vue";
13
+ import ResizeObserver from "@v-c/resize-observer";
14
+ import { pureAttrs } from "@v-c/util/dist/props-util";
15
+ function _isSlot(s) {
16
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
15
17
  }
16
- const He = [], be = {
17
- overflowY: "auto",
18
- overflowAnchor: "none"
19
- }, Ke = /* @__PURE__ */ ae({
20
- name: "VirtualList",
21
- props: {
22
- prefixCls: {
23
- type: String,
24
- default: "vc-virtual-list"
25
- },
26
- data: {
27
- type: Array
28
- },
29
- height: Number,
30
- itemHeight: Number,
31
- fullHeight: {
32
- type: Boolean,
33
- default: !0
34
- },
35
- itemKey: {
36
- type: [String, Number, Function],
37
- required: !0
38
- },
39
- component: {
40
- type: String,
41
- default: "div"
42
- },
43
- virtual: {
44
- type: Boolean,
45
- default: !0
46
- },
47
- onScroll: Function,
48
- onVirtualScroll: Function,
49
- onVisibleChange: Function,
50
- innerProps: Object,
51
- extraRender: Function
52
- },
53
- setup(l, {
54
- expose: Y,
55
- attrs: k,
56
- slots: _
57
- }) {
58
- const h = (e) => typeof l.itemKey == "function" ? l.itemKey(e) : e?.[l.itemKey], [D, P, m, X] = de(h, void 0, void 0), o = y(() => l.data || He), M = y(() => !!(l.virtual !== !1 && l.height && l.itemHeight)), E = y(() => Object.values(m.maps).reduce((e, t) => e + t, 0)), d = y(() => {
59
- const e = o.value;
60
- return M.value && e && Math.max(l.itemHeight * e.length, E.value) > l.height;
61
- }), R = r(), B = r(), F = r(), K = ue(), f = r(0), x = r(0), V = r(!1), j = r(0), L = r(0);
62
- function g(e) {
63
- let t;
64
- typeof e == "function" ? t = e(f.value) : t = e;
65
- const i = c.value - l.height, n = Math.max(0, Math.min(t, i || 0));
66
- R.value && (R.value.scrollTop = n), f.value = n;
67
- }
68
- fe(o, h);
69
- const c = r(0), S = r(0), H = r(0), C = r(void 0);
70
- T([() => d.value, () => M.value, () => f.value, () => o.value, () => X.value, () => l.height], () => {
71
- if (!M.value) {
72
- c.value = 0, S.value = 0, H.value = o.value.length - 1, C.value = void 0;
73
- return;
74
- }
75
- if (!d.value) {
76
- c.value = B.value?.offsetHeight || 0, S.value = 0, H.value = o.value.length - 1, C.value = void 0;
77
- return;
78
- }
79
- let e = 0, t, i, n;
80
- const u = o.value.length, v = o.value;
81
- for (let a = 0; a < u; a += 1) {
82
- const s = v[a], w = h(s), N = m.get(w), A = e + (N === void 0 ? l.itemHeight : N);
83
- A >= f.value && t === void 0 && (t = a, i = e), A > f.value + l.height && n === void 0 && (n = a), e = A;
84
- }
85
- t === void 0 && (t = 0, i = 0, n = Math.ceil(l.height / l.itemHeight)), n === void 0 && (n = o.value.length - 1), n = Math.min(n + 1, o.value.length - 1), c.value = e, S.value = t, H.value = n, C.value = i;
86
- }, {
87
- immediate: !0
88
- }), T(() => c.value, () => {
89
- const e = m.getRecord();
90
- if (e.size === 1) {
91
- const t = Array.from(e.keys())[0], i = e.get(t), n = o.value[S.value];
92
- if (n && i === void 0 && h(n) === t) {
93
- const a = m.get(t) - l.itemHeight;
94
- g((s) => s + a);
95
- }
96
- }
97
- m.resetRecord();
98
- });
99
- const I = r({
100
- width: 0,
101
- height: l.height || 0
102
- }), $ = (e) => {
103
- I.value = {
104
- width: e.offsetWidth,
105
- height: e.offsetHeight
106
- };
107
- }, z = () => ({
108
- x: x.value,
109
- y: f.value
110
- }), O = r(z()), q = (e) => {
111
- if (l.onVirtualScroll) {
112
- const t = {
113
- ...z(),
114
- ...e
115
- };
116
- (O.value.x !== t.x || O.value.y !== t.y) && (l.onVirtualScroll(t), O.value = t);
117
- }
118
- }, G = y(() => f.value === 0), U = y(() => f.value + l.height >= c.value), J = y(() => x.value === 0), Q = y(() => x.value + I.value.width >= L.value), Z = () => {
119
- K.value?.delayHidden();
120
- }, [p] = ve(
121
- d,
122
- G,
123
- U,
124
- J,
125
- Q,
126
- !1,
127
- // horizontalScroll
128
- (e, t) => {
129
- t || g((i) => i + e);
130
- }
131
- );
132
- me(d, R, (e, t, i, n) => e ? !1 : (g((u) => u + t), !0)), ge(d, R, (e) => {
133
- g((t) => t + e);
134
- });
135
- const ee = (e, t) => {
136
- t || g(e);
137
- }, te = () => {
138
- V.value = !0;
139
- }, le = () => {
140
- V.value = !1;
141
- };
142
- T([() => l.height, () => c.value, () => d.value, () => I.value.height], () => {
143
- d.value && l.height && c.value && (j.value = xe(I.value.height, c.value));
144
- }, {
145
- immediate: !0
146
- });
147
- function ne(e) {
148
- const i = e.currentTarget.scrollTop;
149
- i !== f.value && g(i), l.onScroll?.(e), q();
150
- }
151
- Y({
152
- nativeElement: F,
153
- getScrollInfo: z,
154
- scrollTo: (e) => {
155
- if (e != null) {
156
- if (typeof e == "number")
157
- g(e);
158
- else if (e && typeof e == "object") {
159
- let t;
160
- if ("left" in e && (x.value = e.left || 0), "top" in e)
161
- t = e.top;
162
- else if ("index" in e) {
163
- const i = e.index || 0;
164
- if (o.value[i]) {
165
- let u = 0;
166
- for (let v = 0; v < i; v += 1) {
167
- const a = h(o.value[v]), s = m.get(a);
168
- u += s === void 0 ? l.itemHeight : s;
169
- }
170
- t = u;
171
- }
172
- } else if ("key" in e) {
173
- const i = o.value.findIndex((n) => h(n) === e.key);
174
- if (i >= 0) {
175
- let n = 0;
176
- for (let u = 0; u < i; u += 1) {
177
- const v = h(o.value[u]), a = m.get(v);
178
- n += a === void 0 ? l.itemHeight : a;
179
- }
180
- t = n;
181
- }
182
- }
183
- t !== void 0 && g(t);
184
- }
185
- }
186
- }
187
- }), T([() => S.value, () => H.value, () => o.value], () => {
188
- if (l.onVisibleChange) {
189
- const e = o.value.slice(S.value, H.value + 1);
190
- l.onVisibleChange(e, o.value);
191
- }
192
- });
193
- const ie = () => {
194
- const e = [], t = o.value, i = _.default;
195
- if (!i)
196
- return e;
197
- for (let n = S.value; n <= H.value; n += 1) {
198
- const u = t[n], v = h(u), a = i({
199
- item: u,
200
- index: n,
201
- style: {},
202
- offsetX: x.value
203
- }), s = Array.isArray(a) ? a[0] : a;
204
- s && e.push(b(Se, {
205
- key: v,
206
- setRef: (w) => D(u, w)
207
- }, W(s) ? s : {
208
- default: () => [s]
209
- }));
210
- }
211
- return e;
212
- }, oe = he(o, h, m, l.itemHeight);
213
- return () => {
214
- let e;
215
- const t = {};
216
- l.height && (t[l.fullHeight ? "height" : "maxHeight"] = `${l.height}px`, Object.assign(t, be), M.value && (t.overflowY = "hidden", L.value && (t.overflowX = "hidden"), V.value && (t.pointerEvents = "none")));
217
- const i = l.extraRender?.({
218
- start: S.value,
219
- end: H.value,
220
- virtual: d.value,
221
- offsetX: x.value,
222
- offsetY: C.value || 0,
223
- rtl: !1,
224
- getSize: oe.value
225
- }), n = l.component;
226
- return b("div", {
227
- ref: F,
228
- style: {
229
- position: "relative",
230
- ...k.style
231
- },
232
- class: [l.prefixCls, k.class]
233
- }, [b(ce, {
234
- onResize: $
235
- }, {
236
- default: () => [b(n, {
237
- class: `${l.prefixCls}-holder`,
238
- style: t,
239
- ref: R,
240
- onScroll: ne,
241
- onWheel: p,
242
- onMouseenter: Z
243
- }, {
244
- default: () => [b(se, {
245
- prefixCls: l.prefixCls,
246
- height: c.value,
247
- offsetX: x.value,
248
- offsetY: C.value,
249
- onInnerResize: P,
250
- ref: B,
251
- innerProps: l.innerProps,
252
- rtl: !1,
253
- extra: i
254
- }, W(e = ie()) ? e : {
255
- default: () => [e]
256
- })]
257
- })]
258
- }), d.value && c.value > (l.height || 0) && b(ye, {
259
- ref: K,
260
- prefixCls: l.prefixCls,
261
- scrollOffset: f.value,
262
- scrollRange: c.value,
263
- rtl: !1,
264
- onScroll: ee,
265
- onStartMove: te,
266
- onStopMove: le,
267
- spinSize: j.value,
268
- containerSize: I.value.height,
269
- showScrollBar: "optional"
270
- }, null)]);
271
- };
272
- }
273
- });
274
- export {
275
- Ke as default
18
+ var EMPTY_DATA = [];
19
+ var ScrollStyle = {
20
+ overflowY: "auto",
21
+ overflowAnchor: "none"
276
22
  };
23
+ var List_default = /* @__PURE__ */ defineComponent({
24
+ name: "VirtualList",
25
+ props: {
26
+ prefixCls: {
27
+ type: String,
28
+ default: "vc-virtual-list"
29
+ },
30
+ data: { type: Array },
31
+ height: Number,
32
+ itemHeight: Number,
33
+ fullHeight: {
34
+ type: Boolean,
35
+ default: true
36
+ },
37
+ itemKey: {
38
+ type: [
39
+ String,
40
+ Number,
41
+ Function
42
+ ],
43
+ required: true
44
+ },
45
+ component: {
46
+ type: String,
47
+ default: "div"
48
+ },
49
+ direction: { type: String },
50
+ scrollWidth: Number,
51
+ styles: Object,
52
+ showScrollBar: {
53
+ type: [Boolean, String],
54
+ default: "optional"
55
+ },
56
+ virtual: {
57
+ type: Boolean,
58
+ default: true
59
+ },
60
+ onScroll: Function,
61
+ onVirtualScroll: Function,
62
+ onVisibleChange: Function,
63
+ innerProps: Object,
64
+ extraRender: Function
65
+ },
66
+ inheritAttrs: false,
67
+ setup(props, { expose, attrs, slots }) {
68
+ const itemHeight = computed(() => props.itemHeight);
69
+ const itemKey = toRef(props, "itemKey");
70
+ const getKey = (item) => {
71
+ item = toRaw(item);
72
+ const _itemKey = itemKey.value;
73
+ if (typeof _itemKey === "function") return _itemKey(item);
74
+ return item?.[_itemKey];
75
+ };
76
+ const [setInstanceRef, collectHeight, heights, heightUpdatedMark] = useHeights(getKey, void 0, void 0);
77
+ const mergedData = computed(() => props.data || EMPTY_DATA);
78
+ const useVirtual = computed(() => !!(props.virtual !== false && props.height && props.itemHeight));
79
+ const containerHeight = computed(() => Object.values(heights.maps).reduce((total, curr) => total + curr, 0));
80
+ const inVirtual = computed(() => {
81
+ const data = mergedData.value;
82
+ return useVirtual.value && data && (Math.max(props.itemHeight * data.length, containerHeight.value) > props.height || !!props.scrollWidth);
83
+ });
84
+ const componentRef = ref();
85
+ const fillerInnerRef = ref();
86
+ const containerRef = ref();
87
+ const verticalScrollBarRef = shallowRef();
88
+ const horizontalScrollBarRef = shallowRef();
89
+ const offsetTop = ref(0);
90
+ const offsetLeft = ref(0);
91
+ const scrollMoving = ref(false);
92
+ const verticalScrollBarSpinSize = ref(0);
93
+ const horizontalScrollBarSpinSize = ref(0);
94
+ const contentScrollWidth = ref(props.scrollWidth || 0);
95
+ const scrollHeight = ref(0);
96
+ const start = ref(0);
97
+ const end = ref(0);
98
+ const fillerOffset = ref(void 0);
99
+ function syncScrollTop(newTop) {
100
+ let value;
101
+ if (typeof newTop === "function") value = newTop(offsetTop.value);
102
+ else value = newTop;
103
+ const maxScrollHeight = scrollHeight.value - props.height;
104
+ const alignedTop = Math.max(0, Math.min(value, maxScrollHeight || 0));
105
+ if (componentRef.value) componentRef.value.scrollTop = alignedTop;
106
+ offsetTop.value = alignedTop;
107
+ }
108
+ useDiffItem(mergedData, getKey);
109
+ watch([
110
+ inVirtual,
111
+ useVirtual,
112
+ offsetTop,
113
+ mergedData,
114
+ heightUpdatedMark,
115
+ () => props.height
116
+ ], () => {
117
+ if (!useVirtual.value) {
118
+ scrollHeight.value = 0;
119
+ start.value = 0;
120
+ end.value = mergedData.value.length - 1;
121
+ fillerOffset.value = void 0;
122
+ return;
123
+ }
124
+ const { itemHeight: itemHeight$1, height } = props;
125
+ if (!inVirtual.value) {
126
+ scrollHeight.value = fillerInnerRef.value?.offsetHeight || 0;
127
+ start.value = 0;
128
+ end.value = mergedData.value.length - 1;
129
+ fillerOffset.value = void 0;
130
+ return;
131
+ }
132
+ let itemTop = 0;
133
+ let startIndex;
134
+ let startOffset;
135
+ let endIndex;
136
+ const dataLen = mergedData.value.length;
137
+ const data = toRaw(mergedData.value);
138
+ for (let i = 0; i < dataLen; i += 1) {
139
+ const item = data[i];
140
+ const key = getKey(item);
141
+ const cacheHeight = heights.get(key);
142
+ const currentItemBottom = itemTop + (cacheHeight === void 0 ? itemHeight$1 : cacheHeight);
143
+ if (currentItemBottom >= offsetTop.value && startIndex === void 0) {
144
+ startIndex = i;
145
+ startOffset = itemTop;
146
+ }
147
+ if (currentItemBottom > offsetTop.value + height && endIndex === void 0) endIndex = i;
148
+ itemTop = currentItemBottom;
149
+ }
150
+ if (startIndex === void 0) {
151
+ startIndex = 0;
152
+ startOffset = 0;
153
+ endIndex = Math.ceil(height / itemHeight$1);
154
+ }
155
+ if (endIndex === void 0) endIndex = mergedData.value.length - 1;
156
+ endIndex = Math.min(endIndex + 1, mergedData.value.length - 1);
157
+ scrollHeight.value = itemTop;
158
+ start.value = startIndex;
159
+ end.value = endIndex;
160
+ fillerOffset.value = startOffset;
161
+ }, { immediate: true });
162
+ watch(scrollHeight, () => {
163
+ const changedRecord = heights.getRecord();
164
+ if (changedRecord.size === 1) {
165
+ const recordKey = Array.from(changedRecord.keys())[0];
166
+ const prevCacheHeight = changedRecord.get(recordKey);
167
+ const startItem = mergedData.value[start.value];
168
+ if (startItem && prevCacheHeight === void 0) {
169
+ if (getKey(startItem) === recordKey) {
170
+ const diffHeight = heights.get(recordKey) - props.itemHeight;
171
+ syncScrollTop((ori) => ori + diffHeight);
172
+ }
173
+ }
174
+ }
175
+ heights.resetRecord();
176
+ });
177
+ const size = ref({
178
+ width: 0,
179
+ height: props.height || 0
180
+ });
181
+ const onHolderResize = (sizeInfo) => {
182
+ size.value = {
183
+ width: sizeInfo.offsetWidth,
184
+ height: sizeInfo.offsetHeight
185
+ };
186
+ contentScrollWidth.value = props.scrollWidth ?? sizeInfo.offsetWidth;
187
+ };
188
+ const isRTL = computed(() => props.direction === "rtl");
189
+ const getVirtualScrollInfo = () => ({
190
+ x: isRTL.value ? -offsetLeft.value : offsetLeft.value,
191
+ y: offsetTop.value
192
+ });
193
+ const lastVirtualScrollInfo = ref(getVirtualScrollInfo());
194
+ const triggerScroll = (params) => {
195
+ if (props.onVirtualScroll) {
196
+ const nextInfo = {
197
+ ...getVirtualScrollInfo(),
198
+ ...params
199
+ };
200
+ if (lastVirtualScrollInfo.value.x !== nextInfo.x || lastVirtualScrollInfo.value.y !== nextInfo.y) {
201
+ props.onVirtualScroll(nextInfo);
202
+ lastVirtualScrollInfo.value = nextInfo;
203
+ }
204
+ }
205
+ };
206
+ const horizontalRange = computed(() => Math.max(0, (contentScrollWidth.value || 0) - size.value.width));
207
+ const isScrollAtTop = computed(() => offsetTop.value === 0);
208
+ const isScrollAtBottom = computed(() => offsetTop.value + props.height >= scrollHeight.value);
209
+ const isScrollAtLeft = computed(() => offsetLeft.value === 0);
210
+ const isScrollAtRight = computed(() => offsetLeft.value >= horizontalRange.value);
211
+ const keepInHorizontalRange = (nextOffsetLeft) => {
212
+ const max = horizontalRange.value;
213
+ return Math.max(0, Math.min(nextOffsetLeft, max));
214
+ };
215
+ const delayHideScrollBar = () => {
216
+ verticalScrollBarRef.value?.delayHidden();
217
+ horizontalScrollBarRef.value?.delayHidden();
218
+ };
219
+ const [onWheel] = useFrameWheel(inVirtual, isScrollAtTop, isScrollAtBottom, isScrollAtLeft, isScrollAtRight, horizontalRange.value > 0, (offsetY, isHorizontal) => {
220
+ if (isHorizontal) {
221
+ const aligned = keepInHorizontalRange(isRTL.value ? offsetLeft.value - offsetY : offsetLeft.value + offsetY);
222
+ offsetLeft.value = aligned;
223
+ triggerScroll({ x: isRTL.value ? -aligned : aligned });
224
+ } else syncScrollTop((top) => top + offsetY);
225
+ });
226
+ useMobileTouchMove(inVirtual, componentRef, (isHorizontal, offset, _smoothOffset, _e) => {
227
+ if (isHorizontal) {
228
+ const aligned = keepInHorizontalRange(isRTL.value ? offsetLeft.value - offset : offsetLeft.value + offset);
229
+ offsetLeft.value = aligned;
230
+ triggerScroll({ x: isRTL.value ? -aligned : aligned });
231
+ return true;
232
+ } else {
233
+ syncScrollTop((top) => top + offset);
234
+ return true;
235
+ }
236
+ });
237
+ useScrollDrag(inVirtual, componentRef, (offset) => {
238
+ syncScrollTop((top) => top + offset);
239
+ });
240
+ const onScrollBar = (newScrollOffset, horizontal) => {
241
+ const newOffset = newScrollOffset;
242
+ if (horizontal) {
243
+ offsetLeft.value = newOffset;
244
+ triggerScroll({ x: isRTL.value ? -newOffset : newOffset });
245
+ } else syncScrollTop(newOffset);
246
+ };
247
+ const onScrollbarStartMove = () => {
248
+ scrollMoving.value = true;
249
+ };
250
+ const onScrollbarStopMove = () => {
251
+ scrollMoving.value = false;
252
+ };
253
+ watch([
254
+ () => props.height,
255
+ scrollHeight,
256
+ inVirtual,
257
+ () => size.value.height
258
+ ], () => {
259
+ if (inVirtual.value && props.height && scrollHeight.value) verticalScrollBarSpinSize.value = getSpinSize(size.value.height, scrollHeight.value);
260
+ }, { immediate: true });
261
+ watch([() => size.value.width, () => contentScrollWidth.value], () => {
262
+ if (inVirtual.value && contentScrollWidth.value) horizontalScrollBarSpinSize.value = getSpinSize(size.value.width, contentScrollWidth.value);
263
+ }, { immediate: true });
264
+ watch(() => props.scrollWidth, (val) => {
265
+ contentScrollWidth.value = val ?? size.value.width;
266
+ offsetLeft.value = keepInHorizontalRange(offsetLeft.value);
267
+ }, { immediate: true });
268
+ function onFallbackScroll(e) {
269
+ const newScrollTop = e.currentTarget.scrollTop;
270
+ if (newScrollTop !== offsetTop.value) syncScrollTop(newScrollTop);
271
+ props.onScroll?.(e);
272
+ triggerScroll();
273
+ }
274
+ const scrollTo = useScrollTo(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), syncScrollTop, delayHideScrollBar);
275
+ expose({
276
+ nativeElement: containerRef,
277
+ getScrollInfo: getVirtualScrollInfo,
278
+ scrollTo: (config) => {
279
+ function isPosScroll(arg) {
280
+ return arg && typeof arg === "object" && ("left" in arg || "top" in arg);
281
+ }
282
+ if (isPosScroll(config)) {
283
+ if (config.left !== void 0) offsetLeft.value = keepInHorizontalRange(config.left);
284
+ scrollTo(config.top);
285
+ } else scrollTo(config);
286
+ }
287
+ });
288
+ watch([
289
+ start,
290
+ end,
291
+ mergedData
292
+ ], () => {
293
+ if (props.onVisibleChange) {
294
+ const renderList = mergedData.value.slice(start.value, end.value + 1);
295
+ props.onVisibleChange(renderList, mergedData.value);
296
+ }
297
+ });
298
+ const getSize = useGetSize(mergedData, getKey, heights, itemHeight);
299
+ return () => {
300
+ let _slot;
301
+ const renderChildren = () => {
302
+ const children = [];
303
+ const data = mergedData.value;
304
+ const defaultSlot = slots.default;
305
+ if (!defaultSlot) return children;
306
+ for (let i = start.value; i <= end.value; i += 1) {
307
+ const item = data[i];
308
+ const key = getKey(item);
309
+ const nodes = defaultSlot({
310
+ item,
311
+ index: i,
312
+ style: {},
313
+ offsetX: offsetLeft.value
314
+ });
315
+ const node = Array.isArray(nodes) ? nodes[0] : nodes;
316
+ if (node) children.push(createVNode(Item_default, {
317
+ "key": key,
318
+ "setRef": (ele) => setInstanceRef(item, ele)
319
+ }, _isSlot(node) ? node : { default: () => [node] }));
320
+ }
321
+ return children;
322
+ };
323
+ const componentStyle = {};
324
+ if (props.height) {
325
+ componentStyle[props.fullHeight ? "height" : "maxHeight"] = `${props.height}px`;
326
+ Object.assign(componentStyle, ScrollStyle);
327
+ if (useVirtual.value) {
328
+ componentStyle.overflowY = "hidden";
329
+ if (horizontalRange.value > 0) componentStyle.overflowX = "hidden";
330
+ if (scrollMoving.value) componentStyle.pointerEvents = "none";
331
+ }
332
+ }
333
+ const extraContent = props.extraRender?.({
334
+ start: start.value,
335
+ end: end.value,
336
+ virtual: inVirtual.value,
337
+ offsetX: offsetLeft.value,
338
+ offsetY: fillerOffset.value || 0,
339
+ rtl: isRTL.value,
340
+ getSize: getSize.value
341
+ });
342
+ const Component = props.component;
343
+ return createVNode("div", mergeProps({ "ref": containerRef }, pureAttrs(attrs), {
344
+ "style": {
345
+ position: "relative",
346
+ ...attrs.style
347
+ },
348
+ "dir": isRTL.value ? "rtl" : void 0,
349
+ "class": [
350
+ props.prefixCls,
351
+ { [`${props.prefixCls}-rtl`]: isRTL.value },
352
+ attrs.class
353
+ ]
354
+ }), [
355
+ createVNode(ResizeObserver, { "onResize": onHolderResize }, { default: () => [createVNode(Component, {
356
+ "class": `${props.prefixCls}-holder`,
357
+ "style": componentStyle,
358
+ "ref": componentRef,
359
+ "onScroll": onFallbackScroll,
360
+ "onWheel": onWheel,
361
+ "onMouseenter": delayHideScrollBar
362
+ }, { default: () => [createVNode(Filler_default, {
363
+ "prefixCls": props.prefixCls,
364
+ "height": scrollHeight.value,
365
+ "offsetX": offsetLeft.value,
366
+ "offsetY": fillerOffset.value,
367
+ "scrollWidth": contentScrollWidth.value,
368
+ "onInnerResize": collectHeight,
369
+ "ref": fillerInnerRef,
370
+ "innerProps": props.innerProps,
371
+ "rtl": isRTL.value,
372
+ "extra": extraContent
373
+ }, _isSlot(_slot = renderChildren()) ? _slot : { default: () => [_slot] })] })] }),
374
+ inVirtual.value && scrollHeight.value > (props.height || 0) && createVNode(ScrollBar_default, {
375
+ "ref": verticalScrollBarRef,
376
+ "prefixCls": props.prefixCls,
377
+ "scrollOffset": offsetTop.value,
378
+ "scrollRange": scrollHeight.value,
379
+ "rtl": isRTL.value,
380
+ "onScroll": onScrollBar,
381
+ "onStartMove": onScrollbarStartMove,
382
+ "onStopMove": onScrollbarStopMove,
383
+ "spinSize": verticalScrollBarSpinSize.value,
384
+ "containerSize": size.value.height,
385
+ "showScrollBar": props.showScrollBar,
386
+ "style": props.styles?.verticalScrollBar,
387
+ "thumbStyle": props.styles?.verticalScrollBarThumb
388
+ }, null),
389
+ inVirtual.value && contentScrollWidth.value > size.value.width && createVNode(ScrollBar_default, {
390
+ "ref": horizontalScrollBarRef,
391
+ "prefixCls": props.prefixCls,
392
+ "scrollOffset": offsetLeft.value,
393
+ "scrollRange": contentScrollWidth.value,
394
+ "rtl": isRTL.value,
395
+ "onScroll": onScrollBar,
396
+ "onStartMove": onScrollbarStartMove,
397
+ "onStopMove": onScrollbarStopMove,
398
+ "spinSize": horizontalScrollBarSpinSize.value,
399
+ "containerSize": size.value.width,
400
+ "horizontal": true,
401
+ "showScrollBar": props.showScrollBar,
402
+ "style": props.styles?.horizontalScrollBar,
403
+ "thumbStyle": props.styles?.horizontalScrollBarThumb
404
+ }, null)
405
+ ]);
406
+ };
407
+ }
408
+ });
409
+ export { List_default as default };