@v-c/virtual-list 1.0.2 → 1.0.4

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.
package/dist/Filler.cjs CHANGED
@@ -1,8 +1,11 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("./_virtual/rolldown_runtime.cjs");
3
6
  let vue = require("vue");
4
- let __v_c_resize_observer = require("@v-c/resize-observer");
5
- __v_c_resize_observer = require_rolldown_runtime.__toESM(__v_c_resize_observer);
7
+ let _v_c_resize_observer = require("@v-c/resize-observer");
8
+ _v_c_resize_observer = require_rolldown_runtime.__toESM(_v_c_resize_observer);
6
9
  var Filler_default = /* @__PURE__ */ (0, vue.defineComponent)({
7
10
  name: "Filler",
8
11
  props: {
@@ -39,7 +42,7 @@ var Filler_default = /* @__PURE__ */ (0, vue.defineComponent)({
39
42
  top: 0
40
43
  };
41
44
  }
42
- return (0, vue.createVNode)("div", { "style": outerStyle }, [(0, vue.createVNode)(__v_c_resize_observer.default, { "onResize": ({ offsetHeight }) => {
45
+ return (0, vue.createVNode)("div", { "style": outerStyle }, [(0, vue.createVNode)(_v_c_resize_observer.default, { "onResize": ({ offsetHeight }) => {
43
46
  if (offsetHeight && props.onInnerResize) props.onInnerResize();
44
47
  } }, { default: () => [(0, vue.createVNode)("div", (0, vue.mergeProps)({
45
48
  "style": innerStyle,
package/dist/Item.cjs CHANGED
@@ -1,7 +1,10 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("./_virtual/rolldown_runtime.cjs");
3
6
  let vue = require("vue");
4
- let __v_c_util_dist_props_util = require("@v-c/util/dist/props-util");
7
+ let _v_c_util_dist_props_util = require("@v-c/util/dist/props-util");
5
8
  var Item_default = /* @__PURE__ */ (0, vue.defineComponent)({
6
9
  name: "Item",
7
10
  props: { setRef: {
@@ -17,7 +20,7 @@ var Item_default = /* @__PURE__ */ (0, vue.defineComponent)({
17
20
  }
18
21
  };
19
22
  return () => {
20
- const child = (0, __v_c_util_dist_props_util.filterEmpty)(slots.default?.() ?? [])[0];
23
+ const child = (0, _v_c_util_dist_props_util.filterEmpty)(slots.default?.() ?? [])[0];
21
24
  if (!child) return null;
22
25
  return (0, vue.cloneVNode)(child, { ref: refFunc });
23
26
  };
package/dist/List.cjs CHANGED
@@ -1,7 +1,11 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("./_virtual/rolldown_runtime.cjs");
3
6
  const require_Filler = require("./Filler.cjs");
4
- const require_Item = require("./Item.cjs");
7
+ const require_useChildren = require("./hooks/useChildren.cjs");
8
+ const require_useDiffItem = require("./hooks/useDiffItem.cjs");
5
9
  const require_useFrameWheel = require("./hooks/useFrameWheel.cjs");
6
10
  const require_useGetSize = require("./hooks/useGetSize.cjs");
7
11
  const require_useHeights = require("./hooks/useHeights.cjs");
@@ -11,12 +15,9 @@ const require_useScrollTo = require("./hooks/useScrollTo.cjs");
11
15
  const require_ScrollBar = require("./ScrollBar.cjs");
12
16
  const require_scrollbarUtil = require("./utils/scrollbarUtil.cjs");
13
17
  let vue = require("vue");
14
- let __v_c_resize_observer = require("@v-c/resize-observer");
15
- __v_c_resize_observer = require_rolldown_runtime.__toESM(__v_c_resize_observer);
16
- let __v_c_util_dist_props_util = require("@v-c/util/dist/props-util");
17
- function _isSlot(s) {
18
- return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !(0, vue.isVNode)(s);
19
- }
18
+ let _v_c_resize_observer = require("@v-c/resize-observer");
19
+ _v_c_resize_observer = require_rolldown_runtime.__toESM(_v_c_resize_observer);
20
+ let _v_c_util_dist_props_util = require("@v-c/util/dist/props-util");
20
21
  var EMPTY_DATA = [];
21
22
  var ScrollStyle = {
22
23
  overflowY: "auto",
@@ -68,10 +69,12 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
68
69
  inheritAttrs: false,
69
70
  setup(props, { expose, attrs, slots }) {
70
71
  const itemHeight = (0, vue.computed)(() => props.itemHeight);
71
- const itemKey = (0, vue.toRef)(props, "itemKey");
72
+ let itemKeyProp = props.itemKey;
73
+ (0, vue.watch)(() => props.itemKey, (val) => {
74
+ itemKeyProp = val;
75
+ });
72
76
  const getKey = (item) => {
73
- item = (0, vue.toRaw)(item);
74
- const _itemKey = itemKey.value;
77
+ const _itemKey = itemKeyProp;
75
78
  if (typeof _itemKey === "function") return _itemKey(item);
76
79
  return item?.[_itemKey];
77
80
  };
@@ -81,10 +84,9 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
81
84
  mergedData.value = props?.data || EMPTY_DATA;
82
85
  });
83
86
  const useVirtual = (0, vue.computed)(() => !!(props.virtual !== false && props.height && props.itemHeight));
84
- const containerHeight = (0, vue.computed)(() => Object.values(heights.maps).reduce((total, curr) => total + curr, 0));
85
87
  const inVirtual = (0, vue.computed)(() => {
86
88
  const data = mergedData.value;
87
- return useVirtual.value && data && (Math.max(props.itemHeight * data.length, containerHeight.value) > props.height || !!props.scrollWidth);
89
+ return useVirtual.value && data && (props.itemHeight * data.length > props.height || !!props.scrollWidth);
88
90
  });
89
91
  const componentRef = (0, vue.ref)();
90
92
  const fillerInnerRef = (0, vue.ref)();
@@ -125,7 +127,6 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
125
127
  fillerOffset.value = void 0;
126
128
  return;
127
129
  }
128
- const { itemHeight: itemHeight$1, height } = props;
129
130
  if (!inVirtual.value) {
130
131
  scrollHeight.value = fillerInnerRef.value?.offsetHeight || 0;
131
132
  start.value = 0;
@@ -133,35 +134,53 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
133
134
  fillerOffset.value = void 0;
134
135
  return;
135
136
  }
137
+ const { itemHeight: itemHeight$1, height } = props;
138
+ const dataLen = mergedData.value.length;
139
+ if (!dataLen) {
140
+ scrollHeight.value = 0;
141
+ start.value = 0;
142
+ end.value = -1;
143
+ fillerOffset.value = 0;
144
+ return;
145
+ }
146
+ if (heights.id === 0) {
147
+ const safeItemHeight = itemHeight$1;
148
+ const safeListHeight = height;
149
+ const startIndex$1 = Math.max(0, Math.floor(offsetTop.value / safeItemHeight));
150
+ const startOffset$1 = startIndex$1 * safeItemHeight;
151
+ let endIndex$1 = startIndex$1 + Math.ceil(safeListHeight / safeItemHeight);
152
+ endIndex$1 = Math.min(endIndex$1 + 1, dataLen - 1);
153
+ scrollHeight.value = dataLen * safeItemHeight;
154
+ start.value = startIndex$1;
155
+ end.value = endIndex$1;
156
+ fillerOffset.value = startOffset$1;
157
+ return;
158
+ }
136
159
  let itemTop = 0;
137
160
  let startIndex;
138
161
  let startOffset;
139
162
  let endIndex;
140
- const dataLen = mergedData.value.length;
141
163
  const data = (0, vue.toRaw)(mergedData.value);
164
+ const _offsetTop = offsetTop.value;
142
165
  for (let i = 0; i < dataLen; i += 1) {
143
166
  const item = data[i];
144
167
  const key = getKey(item);
145
168
  const cacheHeight = heights.get(key);
146
169
  const currentItemBottom = itemTop + (cacheHeight === void 0 ? itemHeight$1 : cacheHeight);
147
- if (currentItemBottom >= offsetTop.value && startIndex === void 0) {
170
+ if (currentItemBottom >= _offsetTop && startIndex === void 0) {
148
171
  startIndex = i;
149
172
  startOffset = itemTop;
150
173
  }
151
- if (currentItemBottom > offsetTop.value + height && endIndex === void 0) endIndex = i;
174
+ if (currentItemBottom > _offsetTop + height && endIndex === void 0) endIndex = i;
152
175
  itemTop = currentItemBottom;
153
- if (startIndex !== void 0 && endIndex !== void 0) {
154
- itemTop = currentItemBottom + (dataLen - 1 - i) * itemHeight$1;
155
- break;
156
- }
157
176
  }
158
177
  if (startIndex === void 0) {
159
178
  startIndex = 0;
160
179
  startOffset = 0;
161
180
  endIndex = Math.ceil(height / itemHeight$1);
162
181
  }
163
- if (endIndex === void 0) endIndex = mergedData.value.length - 1;
164
- endIndex = Math.min(endIndex + 1, mergedData.value.length - 1);
182
+ if (endIndex === void 0) endIndex = data.length - 1;
183
+ endIndex = Math.min(endIndex + 1, data.length - 1);
165
184
  scrollHeight.value = itemTop;
166
185
  start.value = startIndex;
167
186
  end.value = endIndex;
@@ -180,6 +199,10 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
180
199
  }
181
200
  }
182
201
  }
202
+ if (useVirtual.value && props.height) {
203
+ const maxScrollTop = Math.max(0, scrollHeight.value - props.height);
204
+ if (offsetTop.value > maxScrollTop) syncScrollTop(maxScrollTop);
205
+ }
183
206
  heights.resetRecord();
184
207
  });
185
208
  const size = (0, vue.ref)({
@@ -258,6 +281,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
258
281
  const onScrollbarStopMove = () => {
259
282
  scrollMoving.value = false;
260
283
  };
284
+ require_useDiffItem.default(mergedData, getKey);
261
285
  (0, vue.watch)([
262
286
  () => props.height,
263
287
  scrollHeight,
@@ -266,7 +290,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
266
290
  ], () => {
267
291
  if (inVirtual.value && props.height && scrollHeight.value) verticalScrollBarSpinSize.value = require_scrollbarUtil.getSpinSize(size.value.height, scrollHeight.value);
268
292
  }, { immediate: true });
269
- (0, vue.watch)([() => size.value.width, () => contentScrollWidth.value], () => {
293
+ (0, vue.watch)([() => size.value.width, contentScrollWidth], () => {
270
294
  if (inVirtual.value && contentScrollWidth.value) horizontalScrollBarSpinSize.value = require_scrollbarUtil.getSpinSize(size.value.width, contentScrollWidth.value);
271
295
  }, { immediate: true });
272
296
  (0, vue.watch)(() => props.scrollWidth, (val) => {
@@ -275,11 +299,18 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
275
299
  }, { immediate: true });
276
300
  function onFallbackScroll(e) {
277
301
  const newScrollTop = e.currentTarget.scrollTop;
278
- if (newScrollTop !== offsetTop.value) syncScrollTop(newScrollTop);
302
+ if (!useVirtual.value || !inVirtual.value) offsetTop.value = newScrollTop;
303
+ else if (newScrollTop !== offsetTop.value) syncScrollTop(newScrollTop);
279
304
  props.onScroll?.(e);
280
305
  triggerScroll();
281
306
  }
282
- const scrollTo = require_useScrollTo.default(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), syncScrollTop, delayHideScrollBar);
307
+ const [scrollTo, getTotalHeight] = require_useScrollTo.default(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), (newTop) => {
308
+ const totalHeight = getTotalHeight();
309
+ const maxScrollHeight = Math.max(scrollHeight.value, totalHeight) - props.height;
310
+ const alignedTop = Math.max(0, Math.min(newTop, maxScrollHeight || 0));
311
+ if (componentRef.value) componentRef.value.scrollTop = alignedTop;
312
+ offsetTop.value = alignedTop;
313
+ }, delayHideScrollBar);
283
314
  expose({
284
315
  nativeElement: containerRef,
285
316
  getScrollInfo: getVirtualScrollInfo,
@@ -302,41 +333,38 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
302
333
  const renderList = mergedData.value.slice(start.value, end.value + 1);
303
334
  props.onVisibleChange(renderList, mergedData.value);
304
335
  }
305
- });
336
+ }, { flush: "post" });
306
337
  const getSize = require_useGetSize.useGetSize(mergedData, getKey, heights, itemHeight);
338
+ const listChildren = require_useChildren.default(mergedData, start, end, contentScrollWidth, offsetLeft, setInstanceRef, (item, index, props$1) => slots.default?.({
339
+ item,
340
+ index,
341
+ ...props$1
342
+ }), { getKey });
307
343
  return () => {
308
- let _slot;
309
- const renderChildren = () => {
310
- const children = [];
311
- const data = mergedData.value;
312
- const defaultSlot = slots.default;
313
- if (!defaultSlot) return children;
314
- for (let i = start.value; i <= end.value; i += 1) {
315
- const item = data[i];
316
- const key = getKey(item);
317
- const nodes = defaultSlot({
318
- item,
319
- index: i,
320
- style: {},
321
- offsetX: offsetLeft.value
322
- });
323
- const node = Array.isArray(nodes) ? nodes[0] : nodes;
324
- if (node) children.push((0, vue.createVNode)(require_Item.default, {
325
- "key": key,
326
- "setRef": (ele) => setInstanceRef(item, ele)
327
- }, _isSlot(node) ? node : { default: () => [node] }));
344
+ const componentStyle = {};
345
+ const getHolderSizeStyle = (style) => {
346
+ if (!style) return {};
347
+ if (Array.isArray(style)) return style.reduce((acc, item) => Object.assign(acc, getHolderSizeStyle(item)), {});
348
+ if (typeof style === "object") {
349
+ const { height, maxHeight } = style;
350
+ const sizeStyle = {};
351
+ if (height !== void 0) sizeStyle.height = height;
352
+ if (maxHeight !== void 0) sizeStyle.maxHeight = maxHeight;
353
+ return sizeStyle;
328
354
  }
329
- return children;
355
+ return {};
330
356
  };
331
- const componentStyle = {};
332
357
  if (props.height) {
333
358
  componentStyle[props.fullHeight ? "height" : "maxHeight"] = `${props.height}px`;
334
359
  Object.assign(componentStyle, ScrollStyle);
335
- if (useVirtual.value) {
360
+ if (inVirtual.value) {
336
361
  componentStyle.overflowY = "hidden";
337
362
  if (horizontalRange.value > 0) componentStyle.overflowX = "hidden";
338
363
  if (scrollMoving.value) componentStyle.pointerEvents = "none";
339
364
  }
365
+ } else {
366
+ const holderSizeStyle = getHolderSizeStyle(attrs.style);
367
+ if (holderSizeStyle.height !== void 0 || holderSizeStyle.maxHeight !== void 0) Object.assign(componentStyle, holderSizeStyle, ScrollStyle);
340
368
  }
341
369
  const extraContent = props.extraRender?.({
342
370
  start: start.value,
@@ -348,7 +376,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
348
376
  getSize: getSize.value
349
377
  });
350
378
  const Component = props.component;
351
- return (0, vue.createVNode)("div", (0, vue.mergeProps)({ "ref": containerRef }, (0, __v_c_util_dist_props_util.pureAttrs)(attrs), {
379
+ return (0, vue.createVNode)("div", (0, vue.mergeProps)({ "ref": containerRef }, (0, _v_c_util_dist_props_util.pureAttrs)(attrs), {
352
380
  "style": {
353
381
  position: "relative",
354
382
  ...attrs.style
@@ -360,7 +388,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
360
388
  attrs.class
361
389
  ]
362
390
  }), [
363
- (0, vue.createVNode)(__v_c_resize_observer.default, { "onResize": onHolderResize }, { default: () => [(0, vue.createVNode)(Component, {
391
+ (0, vue.createVNode)(_v_c_resize_observer.default, { "onResize": onHolderResize }, { default: () => [(0, vue.createVNode)(Component, {
364
392
  "class": `${props.prefixCls}-holder`,
365
393
  "style": componentStyle,
366
394
  "ref": componentRef,
@@ -378,7 +406,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
378
406
  "innerProps": props.innerProps,
379
407
  "rtl": isRTL.value,
380
408
  "extra": extraContent
381
- }, _isSlot(_slot = renderChildren()) ? _slot : { default: () => [_slot] })] })] }),
409
+ }, { default: () => [listChildren.value] })] })] }),
382
410
  inVirtual.value && scrollHeight.value > (props.height || 0) && (0, vue.createVNode)(require_ScrollBar.default, {
383
411
  "ref": verticalScrollBarRef,
384
412
  "prefixCls": props.prefixCls,
package/dist/List.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import Filler_default from "./Filler.js";
2
- import Item_default from "./Item.js";
2
+ import useChildren from "./hooks/useChildren.js";
3
+ import useDiffItem from "./hooks/useDiffItem.js";
3
4
  import useFrameWheel from "./hooks/useFrameWheel.js";
4
5
  import { useGetSize } from "./hooks/useGetSize.js";
5
6
  import useHeights from "./hooks/useHeights.js";
@@ -8,12 +9,9 @@ import useScrollDrag from "./hooks/useScrollDrag.js";
8
9
  import useScrollTo from "./hooks/useScrollTo.js";
9
10
  import ScrollBar_default from "./ScrollBar.js";
10
11
  import { getSpinSize } from "./utils/scrollbarUtil.js";
11
- import { computed, createVNode, defineComponent, isVNode, mergeProps, ref, shallowRef, toRaw, toRef, watch } from "vue";
12
+ import { computed, createVNode, defineComponent, mergeProps, ref, shallowRef, toRaw, watch } from "vue";
12
13
  import ResizeObserver from "@v-c/resize-observer";
13
14
  import { pureAttrs } from "@v-c/util/dist/props-util";
14
- function _isSlot(s) {
15
- return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
16
- }
17
15
  var EMPTY_DATA = [];
18
16
  var ScrollStyle = {
19
17
  overflowY: "auto",
@@ -65,10 +63,12 @@ var List_default = /* @__PURE__ */ defineComponent({
65
63
  inheritAttrs: false,
66
64
  setup(props, { expose, attrs, slots }) {
67
65
  const itemHeight = computed(() => props.itemHeight);
68
- const itemKey = toRef(props, "itemKey");
66
+ let itemKeyProp = props.itemKey;
67
+ watch(() => props.itemKey, (val) => {
68
+ itemKeyProp = val;
69
+ });
69
70
  const getKey = (item) => {
70
- item = toRaw(item);
71
- const _itemKey = itemKey.value;
71
+ const _itemKey = itemKeyProp;
72
72
  if (typeof _itemKey === "function") return _itemKey(item);
73
73
  return item?.[_itemKey];
74
74
  };
@@ -78,10 +78,9 @@ var List_default = /* @__PURE__ */ defineComponent({
78
78
  mergedData.value = props?.data || EMPTY_DATA;
79
79
  });
80
80
  const useVirtual = computed(() => !!(props.virtual !== false && props.height && props.itemHeight));
81
- const containerHeight = computed(() => Object.values(heights.maps).reduce((total, curr) => total + curr, 0));
82
81
  const inVirtual = computed(() => {
83
82
  const data = mergedData.value;
84
- return useVirtual.value && data && (Math.max(props.itemHeight * data.length, containerHeight.value) > props.height || !!props.scrollWidth);
83
+ return useVirtual.value && data && (props.itemHeight * data.length > props.height || !!props.scrollWidth);
85
84
  });
86
85
  const componentRef = ref();
87
86
  const fillerInnerRef = ref();
@@ -122,7 +121,6 @@ var List_default = /* @__PURE__ */ defineComponent({
122
121
  fillerOffset.value = void 0;
123
122
  return;
124
123
  }
125
- const { itemHeight: itemHeight$1, height } = props;
126
124
  if (!inVirtual.value) {
127
125
  scrollHeight.value = fillerInnerRef.value?.offsetHeight || 0;
128
126
  start.value = 0;
@@ -130,35 +128,53 @@ var List_default = /* @__PURE__ */ defineComponent({
130
128
  fillerOffset.value = void 0;
131
129
  return;
132
130
  }
131
+ const { itemHeight: itemHeight$1, height } = props;
132
+ const dataLen = mergedData.value.length;
133
+ if (!dataLen) {
134
+ scrollHeight.value = 0;
135
+ start.value = 0;
136
+ end.value = -1;
137
+ fillerOffset.value = 0;
138
+ return;
139
+ }
140
+ if (heights.id === 0) {
141
+ const safeItemHeight = itemHeight$1;
142
+ const safeListHeight = height;
143
+ const startIndex$1 = Math.max(0, Math.floor(offsetTop.value / safeItemHeight));
144
+ const startOffset$1 = startIndex$1 * safeItemHeight;
145
+ let endIndex$1 = startIndex$1 + Math.ceil(safeListHeight / safeItemHeight);
146
+ endIndex$1 = Math.min(endIndex$1 + 1, dataLen - 1);
147
+ scrollHeight.value = dataLen * safeItemHeight;
148
+ start.value = startIndex$1;
149
+ end.value = endIndex$1;
150
+ fillerOffset.value = startOffset$1;
151
+ return;
152
+ }
133
153
  let itemTop = 0;
134
154
  let startIndex;
135
155
  let startOffset;
136
156
  let endIndex;
137
- const dataLen = mergedData.value.length;
138
157
  const data = toRaw(mergedData.value);
158
+ const _offsetTop = offsetTop.value;
139
159
  for (let i = 0; i < dataLen; i += 1) {
140
160
  const item = data[i];
141
161
  const key = getKey(item);
142
162
  const cacheHeight = heights.get(key);
143
163
  const currentItemBottom = itemTop + (cacheHeight === void 0 ? itemHeight$1 : cacheHeight);
144
- if (currentItemBottom >= offsetTop.value && startIndex === void 0) {
164
+ if (currentItemBottom >= _offsetTop && startIndex === void 0) {
145
165
  startIndex = i;
146
166
  startOffset = itemTop;
147
167
  }
148
- if (currentItemBottom > offsetTop.value + height && endIndex === void 0) endIndex = i;
168
+ if (currentItemBottom > _offsetTop + height && endIndex === void 0) endIndex = i;
149
169
  itemTop = currentItemBottom;
150
- if (startIndex !== void 0 && endIndex !== void 0) {
151
- itemTop = currentItemBottom + (dataLen - 1 - i) * itemHeight$1;
152
- break;
153
- }
154
170
  }
155
171
  if (startIndex === void 0) {
156
172
  startIndex = 0;
157
173
  startOffset = 0;
158
174
  endIndex = Math.ceil(height / itemHeight$1);
159
175
  }
160
- if (endIndex === void 0) endIndex = mergedData.value.length - 1;
161
- endIndex = Math.min(endIndex + 1, mergedData.value.length - 1);
176
+ if (endIndex === void 0) endIndex = data.length - 1;
177
+ endIndex = Math.min(endIndex + 1, data.length - 1);
162
178
  scrollHeight.value = itemTop;
163
179
  start.value = startIndex;
164
180
  end.value = endIndex;
@@ -177,6 +193,10 @@ var List_default = /* @__PURE__ */ defineComponent({
177
193
  }
178
194
  }
179
195
  }
196
+ if (useVirtual.value && props.height) {
197
+ const maxScrollTop = Math.max(0, scrollHeight.value - props.height);
198
+ if (offsetTop.value > maxScrollTop) syncScrollTop(maxScrollTop);
199
+ }
180
200
  heights.resetRecord();
181
201
  });
182
202
  const size = ref({
@@ -255,6 +275,7 @@ var List_default = /* @__PURE__ */ defineComponent({
255
275
  const onScrollbarStopMove = () => {
256
276
  scrollMoving.value = false;
257
277
  };
278
+ useDiffItem(mergedData, getKey);
258
279
  watch([
259
280
  () => props.height,
260
281
  scrollHeight,
@@ -263,7 +284,7 @@ var List_default = /* @__PURE__ */ defineComponent({
263
284
  ], () => {
264
285
  if (inVirtual.value && props.height && scrollHeight.value) verticalScrollBarSpinSize.value = getSpinSize(size.value.height, scrollHeight.value);
265
286
  }, { immediate: true });
266
- watch([() => size.value.width, () => contentScrollWidth.value], () => {
287
+ watch([() => size.value.width, contentScrollWidth], () => {
267
288
  if (inVirtual.value && contentScrollWidth.value) horizontalScrollBarSpinSize.value = getSpinSize(size.value.width, contentScrollWidth.value);
268
289
  }, { immediate: true });
269
290
  watch(() => props.scrollWidth, (val) => {
@@ -272,11 +293,18 @@ var List_default = /* @__PURE__ */ defineComponent({
272
293
  }, { immediate: true });
273
294
  function onFallbackScroll(e) {
274
295
  const newScrollTop = e.currentTarget.scrollTop;
275
- if (newScrollTop !== offsetTop.value) syncScrollTop(newScrollTop);
296
+ if (!useVirtual.value || !inVirtual.value) offsetTop.value = newScrollTop;
297
+ else if (newScrollTop !== offsetTop.value) syncScrollTop(newScrollTop);
276
298
  props.onScroll?.(e);
277
299
  triggerScroll();
278
300
  }
279
- const scrollTo = useScrollTo(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), syncScrollTop, delayHideScrollBar);
301
+ const [scrollTo, getTotalHeight] = useScrollTo(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), (newTop) => {
302
+ const totalHeight = getTotalHeight();
303
+ const maxScrollHeight = Math.max(scrollHeight.value, totalHeight) - props.height;
304
+ const alignedTop = Math.max(0, Math.min(newTop, maxScrollHeight || 0));
305
+ if (componentRef.value) componentRef.value.scrollTop = alignedTop;
306
+ offsetTop.value = alignedTop;
307
+ }, delayHideScrollBar);
280
308
  expose({
281
309
  nativeElement: containerRef,
282
310
  getScrollInfo: getVirtualScrollInfo,
@@ -299,41 +327,38 @@ var List_default = /* @__PURE__ */ defineComponent({
299
327
  const renderList = mergedData.value.slice(start.value, end.value + 1);
300
328
  props.onVisibleChange(renderList, mergedData.value);
301
329
  }
302
- });
330
+ }, { flush: "post" });
303
331
  const getSize = useGetSize(mergedData, getKey, heights, itemHeight);
332
+ const listChildren = useChildren(mergedData, start, end, contentScrollWidth, offsetLeft, setInstanceRef, (item, index, props$1) => slots.default?.({
333
+ item,
334
+ index,
335
+ ...props$1
336
+ }), { getKey });
304
337
  return () => {
305
- let _slot;
306
- const renderChildren = () => {
307
- const children = [];
308
- const data = mergedData.value;
309
- const defaultSlot = slots.default;
310
- if (!defaultSlot) return children;
311
- for (let i = start.value; i <= end.value; i += 1) {
312
- const item = data[i];
313
- const key = getKey(item);
314
- const nodes = defaultSlot({
315
- item,
316
- index: i,
317
- style: {},
318
- offsetX: offsetLeft.value
319
- });
320
- const node = Array.isArray(nodes) ? nodes[0] : nodes;
321
- if (node) children.push(createVNode(Item_default, {
322
- "key": key,
323
- "setRef": (ele) => setInstanceRef(item, ele)
324
- }, _isSlot(node) ? node : { default: () => [node] }));
338
+ const componentStyle = {};
339
+ const getHolderSizeStyle = (style) => {
340
+ if (!style) return {};
341
+ if (Array.isArray(style)) return style.reduce((acc, item) => Object.assign(acc, getHolderSizeStyle(item)), {});
342
+ if (typeof style === "object") {
343
+ const { height, maxHeight } = style;
344
+ const sizeStyle = {};
345
+ if (height !== void 0) sizeStyle.height = height;
346
+ if (maxHeight !== void 0) sizeStyle.maxHeight = maxHeight;
347
+ return sizeStyle;
325
348
  }
326
- return children;
349
+ return {};
327
350
  };
328
- const componentStyle = {};
329
351
  if (props.height) {
330
352
  componentStyle[props.fullHeight ? "height" : "maxHeight"] = `${props.height}px`;
331
353
  Object.assign(componentStyle, ScrollStyle);
332
- if (useVirtual.value) {
354
+ if (inVirtual.value) {
333
355
  componentStyle.overflowY = "hidden";
334
356
  if (horizontalRange.value > 0) componentStyle.overflowX = "hidden";
335
357
  if (scrollMoving.value) componentStyle.pointerEvents = "none";
336
358
  }
359
+ } else {
360
+ const holderSizeStyle = getHolderSizeStyle(attrs.style);
361
+ if (holderSizeStyle.height !== void 0 || holderSizeStyle.maxHeight !== void 0) Object.assign(componentStyle, holderSizeStyle, ScrollStyle);
337
362
  }
338
363
  const extraContent = props.extraRender?.({
339
364
  start: start.value,
@@ -375,7 +400,7 @@ var List_default = /* @__PURE__ */ defineComponent({
375
400
  "innerProps": props.innerProps,
376
401
  "rtl": isRTL.value,
377
402
  "extra": extraContent
378
- }, _isSlot(_slot = renderChildren()) ? _slot : { default: () => [_slot] })] })] }),
403
+ }, { default: () => [listChildren.value] })] })] }),
379
404
  inVirtual.value && scrollHeight.value > (props.height || 0) && createVNode(ScrollBar_default, {
380
405
  "ref": verticalScrollBarRef,
381
406
  "prefixCls": props.prefixCls,
@@ -1,8 +1,11 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("./_virtual/rolldown_runtime.cjs");
3
6
  let vue = require("vue");
4
- let __v_c_util_dist_raf = require("@v-c/util/dist/raf");
5
- __v_c_util_dist_raf = require_rolldown_runtime.__toESM(__v_c_util_dist_raf);
7
+ let _v_c_util_dist_raf = require("@v-c/util/dist/raf");
8
+ _v_c_util_dist_raf = require_rolldown_runtime.__toESM(_v_c_util_dist_raf);
6
9
  function getPageXY(e, horizontal) {
7
10
  return ("touches" in e ? e.touches[0] : e)[horizontal ? "pageX" : "pageY"] - window[horizontal ? "scrollX" : "scrollY"];
8
11
  }
@@ -149,7 +152,7 @@ var ScrollBar_default = /* @__PURE__ */ (0, vue.defineComponent)({
149
152
  let moveRafId = null;
150
153
  const onMouseMove = (e) => {
151
154
  const { dragging: stateDragging, pageY: statePageY, startTop: stateStartTop } = stateRef.value;
152
- __v_c_util_dist_raf.default.cancel(moveRafId);
155
+ _v_c_util_dist_raf.default.cancel(moveRafId);
153
156
  const rect = scrollbarRef.value.getBoundingClientRect();
154
157
  const scale = props.containerSize / (props.horizontal ? rect.width : rect.height);
155
158
  if (stateDragging) {
@@ -163,7 +166,7 @@ var ScrollBar_default = /* @__PURE__ */ (0, vue.defineComponent)({
163
166
  let newScrollTop = Math.ceil(ptg * tmpEnableScrollRange);
164
167
  newScrollTop = Math.max(newScrollTop, 0);
165
168
  newScrollTop = Math.min(newScrollTop, tmpEnableScrollRange);
166
- moveRafId = (0, __v_c_util_dist_raf.default)(() => {
169
+ moveRafId = (0, _v_c_util_dist_raf.default)(() => {
167
170
  props?.onScroll?.(newScrollTop, props.horizontal);
168
171
  });
169
172
  }
@@ -181,7 +184,7 @@ var ScrollBar_default = /* @__PURE__ */ (0, vue.defineComponent)({
181
184
  window.removeEventListener("touchmove", onMouseMove);
182
185
  window.removeEventListener("mouseup", onMouseUp);
183
186
  window.removeEventListener("touchend", onMouseUp);
184
- __v_c_util_dist_raf.default.cancel(moveRafId);
187
+ _v_c_util_dist_raf.default.cancel(moveRafId);
185
188
  });
186
189
  }
187
190
  });
@@ -0,0 +1,26 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
6
+ const require_Item = require("../Item.cjs");
7
+ let vue = require("vue");
8
+ function _isSlot(s) {
9
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !(0, vue.isVNode)(s);
10
+ }
11
+ function useChildren(list, startIndex, endIndex, scrollWidth, offsetX, setNodeRef, renderFunc, { getKey }) {
12
+ return (0, vue.computed)(() => {
13
+ return list.value.slice(startIndex.value, endIndex.value + 1).map((item, index) => {
14
+ const node = renderFunc(item, startIndex.value + index, {
15
+ style: { width: `${scrollWidth.value}px` },
16
+ offsetX: offsetX.value
17
+ });
18
+ const key = getKey(item);
19
+ return (0, vue.createVNode)(require_Item.default, {
20
+ "key": key,
21
+ "setRef": (ele) => setNodeRef(item, ele)
22
+ }, _isSlot(node) ? node : { default: () => [node] });
23
+ });
24
+ });
25
+ }
26
+ exports.default = useChildren;
@@ -0,0 +1,3 @@
1
+ import { Ref } from 'vue';
2
+ import { SharedConfig } from '../interface';
3
+ export default function useChildren(list: Ref<any[]>, startIndex: Ref<number>, endIndex: Ref<number>, scrollWidth: Ref<number>, offsetX: Ref<number>, setNodeRef: (item: any, element: HTMLElement | null) => void, renderFunc: any, { getKey }: SharedConfig<any>): import('vue').ComputedRef<import("vue/jsx-runtime").JSX.Element[]>;
@@ -0,0 +1,21 @@
1
+ import Item_default from "../Item.js";
2
+ import { computed, createVNode, isVNode } from "vue";
3
+ function _isSlot(s) {
4
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
5
+ }
6
+ function useChildren(list, startIndex, endIndex, scrollWidth, offsetX, setNodeRef, renderFunc, { getKey }) {
7
+ return computed(() => {
8
+ return list.value.slice(startIndex.value, endIndex.value + 1).map((item, index) => {
9
+ const node = renderFunc(item, startIndex.value + index, {
10
+ style: { width: `${scrollWidth.value}px` },
11
+ offsetX: offsetX.value
12
+ });
13
+ const key = getKey(item);
14
+ return createVNode(Item_default, {
15
+ "key": key,
16
+ "setRef": (ele) => setNodeRef(item, ele)
17
+ }, _isSlot(node) ? node : { default: () => [node] });
18
+ });
19
+ });
20
+ }
21
+ export { useChildren as default };
@@ -1,18 +1,20 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
6
+ const require_algorithmUtil = require("../utils/algorithmUtil.cjs");
3
7
  let vue = require("vue");
4
- function useDiffItem(data, getKey) {
5
- const prevDataRef = (0, vue.ref)([]);
6
- const diffItem = (0, vue.ref)();
8
+ function useDiffItem(data, getKey, onDiff) {
9
+ const prevData = (0, vue.shallowRef)(data.value);
10
+ const diffItem = (0, vue.shallowRef)();
7
11
  (0, vue.watch)(data, (newData) => {
8
- const prevData = prevDataRef.value;
9
- if (newData !== prevData) {
10
- diffItem.value = newData.find((item) => {
11
- const key = getKey(item);
12
- return !prevData.some((prevItem) => getKey(prevItem) === key);
13
- });
14
- prevDataRef.value = newData;
12
+ const diff = require_algorithmUtil.findListDiffIndex(prevData.value || [], data.value || [], getKey);
13
+ if (diff?.index !== void 0) {
14
+ onDiff?.(diff.index);
15
+ diffItem.value = newData[diff.index];
15
16
  }
17
+ prevData.value = newData;
16
18
  }, { immediate: true });
17
19
  return diffItem;
18
20
  }
@@ -1,2 +1,2 @@
1
1
  import { Ref } from 'vue';
2
- export default function useDiffItem<T>(data: Ref<T[]>, getKey: (item: T) => any): Ref<T | undefined>;
2
+ export default function useDiffItem<T>(data: Ref<T[]>, getKey: (item: T) => any, onDiff?: (diffIndex: number) => void): Ref<T | undefined>;
@@ -1,16 +1,15 @@
1
- import { ref, watch } from "vue";
2
- function useDiffItem(data, getKey) {
3
- const prevDataRef = ref([]);
4
- const diffItem = ref();
1
+ import { findListDiffIndex } from "../utils/algorithmUtil.js";
2
+ import { shallowRef, watch } from "vue";
3
+ function useDiffItem(data, getKey, onDiff) {
4
+ const prevData = shallowRef(data.value);
5
+ const diffItem = shallowRef();
5
6
  watch(data, (newData) => {
6
- const prevData = prevDataRef.value;
7
- if (newData !== prevData) {
8
- diffItem.value = newData.find((item) => {
9
- const key = getKey(item);
10
- return !prevData.some((prevItem) => getKey(prevItem) === key);
11
- });
12
- prevDataRef.value = newData;
7
+ const diff = findListDiffIndex(prevData.value || [], data.value || [], getKey);
8
+ if (diff?.index !== void 0) {
9
+ onDiff?.(diff.index);
10
+ diffItem.value = newData[diff.index];
13
11
  }
12
+ prevData.value = newData;
14
13
  }, { immediate: true });
15
14
  return diffItem;
16
15
  }
@@ -1,4 +1,7 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
6
  const require_isFirefox = require("../utils/isFirefox.cjs");
4
7
  const require_useOriginScroll = require("./useOriginScroll.cjs");
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
1
2
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
2
3
  let vue = require("vue");
3
4
  function useGetSize(mergedData, getKey, heights, itemHeight) {
@@ -1,7 +1,11 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
6
  const require_CacheMap = require("../utils/CacheMap.cjs");
4
7
  let vue = require("vue");
8
+ let _v_c_util_dist_Dom_findDOMNode = require("@v-c/util/dist/Dom/findDOMNode");
5
9
  function parseNumber(value) {
6
10
  const num = parseFloat(value);
7
11
  return isNaN(num) ? 0 : num;
@@ -9,8 +13,12 @@ function parseNumber(value) {
9
13
  function useHeights(getKey, onItemAdd, onItemRemove) {
10
14
  const updatedMark = (0, vue.ref)(0);
11
15
  const instanceRef = (0, vue.ref)(/* @__PURE__ */ new Map());
12
- const heightsRef = new require_CacheMap.default();
16
+ const heightsRef = (0, vue.markRaw)(new require_CacheMap.default());
13
17
  const promiseIdRef = (0, vue.ref)(0);
18
+ const observedElements = /* @__PURE__ */ new Map();
19
+ const resizeObserver = typeof window !== "undefined" && "ResizeObserver" in window ? new window.ResizeObserver(() => {
20
+ collectHeight();
21
+ }) : null;
14
22
  function cancelRaf() {
15
23
  promiseIdRef.value += 1;
16
24
  }
@@ -19,6 +27,7 @@ function useHeights(getKey, onItemAdd, onItemRemove) {
19
27
  const doCollect = () => {
20
28
  let changed = false;
21
29
  instanceRef.value.forEach((element, key) => {
30
+ element = (0, _v_c_util_dist_Dom_findDOMNode.getDOM)(element);
22
31
  if (element && element.offsetParent) {
23
32
  const { offsetHeight } = element;
24
33
  const { marginTop, marginBottom } = getComputedStyle(element);
@@ -46,15 +55,27 @@ function useHeights(getKey, onItemAdd, onItemRemove) {
46
55
  const key = getKey(item);
47
56
  const origin = instanceRef.value.get(key);
48
57
  if (origin === instance) return;
58
+ const prevObserved = observedElements.get(key);
59
+ if (prevObserved && resizeObserver) {
60
+ resizeObserver.unobserve(prevObserved);
61
+ observedElements.delete(key);
62
+ }
49
63
  if (instance) {
50
64
  instanceRef.value.set(key, instance);
51
65
  collectHeight();
66
+ const element = (0, _v_c_util_dist_Dom_findDOMNode.getDOM)(instance);
67
+ if (element && element.nodeType === 1 && resizeObserver) {
68
+ resizeObserver.observe(element);
69
+ observedElements.set(key, element);
70
+ }
52
71
  } else instanceRef.value.delete(key);
53
72
  if (!origin !== !instance) if (instance) onItemAdd?.(item);
54
73
  else onItemRemove?.(item);
55
74
  }
56
75
  (0, vue.onUnmounted)(() => {
57
76
  cancelRaf();
77
+ resizeObserver?.disconnect?.();
78
+ observedElements.clear();
58
79
  });
59
80
  return [
60
81
  setInstanceRef,
@@ -1,5 +1,6 @@
1
1
  import CacheMap_default from "../utils/CacheMap.js";
2
- import { onUnmounted, ref } from "vue";
2
+ import { markRaw, onUnmounted, ref } from "vue";
3
+ import { getDOM } from "@v-c/util/dist/Dom/findDOMNode";
3
4
  function parseNumber(value) {
4
5
  const num = parseFloat(value);
5
6
  return isNaN(num) ? 0 : num;
@@ -7,8 +8,12 @@ function parseNumber(value) {
7
8
  function useHeights(getKey, onItemAdd, onItemRemove) {
8
9
  const updatedMark = ref(0);
9
10
  const instanceRef = ref(/* @__PURE__ */ new Map());
10
- const heightsRef = new CacheMap_default();
11
+ const heightsRef = markRaw(new CacheMap_default());
11
12
  const promiseIdRef = ref(0);
13
+ const observedElements = /* @__PURE__ */ new Map();
14
+ const resizeObserver = typeof window !== "undefined" && "ResizeObserver" in window ? new window.ResizeObserver(() => {
15
+ collectHeight();
16
+ }) : null;
12
17
  function cancelRaf() {
13
18
  promiseIdRef.value += 1;
14
19
  }
@@ -17,6 +22,7 @@ function useHeights(getKey, onItemAdd, onItemRemove) {
17
22
  const doCollect = () => {
18
23
  let changed = false;
19
24
  instanceRef.value.forEach((element, key) => {
25
+ element = getDOM(element);
20
26
  if (element && element.offsetParent) {
21
27
  const { offsetHeight } = element;
22
28
  const { marginTop, marginBottom } = getComputedStyle(element);
@@ -44,15 +50,27 @@ function useHeights(getKey, onItemAdd, onItemRemove) {
44
50
  const key = getKey(item);
45
51
  const origin = instanceRef.value.get(key);
46
52
  if (origin === instance) return;
53
+ const prevObserved = observedElements.get(key);
54
+ if (prevObserved && resizeObserver) {
55
+ resizeObserver.unobserve(prevObserved);
56
+ observedElements.delete(key);
57
+ }
47
58
  if (instance) {
48
59
  instanceRef.value.set(key, instance);
49
60
  collectHeight();
61
+ const element = getDOM(instance);
62
+ if (element && element.nodeType === 1 && resizeObserver) {
63
+ resizeObserver.observe(element);
64
+ observedElements.set(key, element);
65
+ }
50
66
  } else instanceRef.value.delete(key);
51
67
  if (!origin !== !instance) if (instance) onItemAdd?.(item);
52
68
  else onItemRemove?.(item);
53
69
  }
54
70
  onUnmounted(() => {
55
71
  cancelRaf();
72
+ resizeObserver?.disconnect?.();
73
+ observedElements.clear();
56
74
  });
57
75
  return [
58
76
  setInstanceRef,
@@ -1,4 +1,7 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
6
  let vue = require("vue");
4
7
  var SMOOTH_PTG = 14 / 15;
@@ -1,4 +1,7 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
6
  let vue = require("vue");
4
7
  function useOriginScroll(isScrollAtTop, isScrollAtBottom, isScrollAtLeft, isScrollAtRight) {
@@ -1,4 +1,7 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
6
  let vue = require("vue");
4
7
  function smoothScrollOffset(offset) {
@@ -1,14 +1,23 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
6
  let vue = require("vue");
4
- let __v_c_util = require("@v-c/util");
5
- let __v_c_util_dist_raf = require("@v-c/util/dist/raf");
6
- __v_c_util_dist_raf = require_rolldown_runtime.__toESM(__v_c_util_dist_raf);
7
+ let _v_c_util = require("@v-c/util");
7
8
  var MAX_TIMES = 10;
8
9
  function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHeight, syncScrollTop, triggerFlash) {
9
- const scrollRef = (0, vue.shallowRef)();
10
10
  const syncState = (0, vue.shallowRef)(null);
11
- (0, vue.watch)([syncState, containerRef], () => {
11
+ const getTotalHeight = () => {
12
+ let totalHeight = 0;
13
+ for (let i = 0; i < data.value.length; i += 1) {
14
+ const key = getKey(data.value[i]);
15
+ const cacheHeight = heights.get(key);
16
+ totalHeight += cacheHeight === void 0 ? itemHeight.value : cacheHeight;
17
+ }
18
+ return totalHeight;
19
+ };
20
+ (0, vue.watch)(syncState, () => {
12
21
  if (syncState.value && syncState.value.times < MAX_TIMES) {
13
22
  if (!containerRef.value) {
14
23
  syncState.value = { ...syncState.value };
@@ -67,17 +76,16 @@ function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHei
67
76
  targetAlign: newTargetAlign,
68
77
  lastTop: targetTop
69
78
  };
70
- } else if (process.env.NODE_ENV !== "production" && syncState.value?.times === MAX_TIMES) (0, __v_c_util.warning)(false, "Seems `scrollTo` with `rc-virtual-list` reach the max limitation. Please fire issue for us. Thanks.");
79
+ } else if (process.env.NODE_ENV !== "production" && syncState.value?.times === MAX_TIMES) (0, _v_c_util.warning)(false, "Seems `scrollTo` with `rc-virtual-list` reach the max limitation. Please fire issue for us. Thanks.");
71
80
  }, {
72
81
  immediate: true,
73
82
  flush: "post"
74
83
  });
75
- return (arg) => {
84
+ const scrollTo = (arg) => {
76
85
  if (arg === null || arg === void 0) {
77
86
  triggerFlash();
78
87
  return;
79
88
  }
80
- __v_c_util_dist_raf.default.cancel(scrollRef.value);
81
89
  if (typeof arg === "number") syncScrollTop(arg);
82
90
  else if (arg && typeof arg === "object") {
83
91
  let index;
@@ -93,5 +101,6 @@ function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHei
93
101
  };
94
102
  }
95
103
  };
104
+ return [scrollTo, getTotalHeight];
96
105
  }
97
106
  exports.default = useScrollTo;
@@ -1,7 +1,7 @@
1
1
  import { Key } from '@v-c/util/dist/type';
2
2
  import { Ref } from 'vue';
3
- import { GetKey } from '../interface.ts';
4
- import { default as CacheMap } from '../utils/CacheMap.ts';
3
+ import { GetKey } from '../interface';
4
+ import { default as CacheMap } from '../utils/CacheMap';
5
5
  export type ScrollAlign = 'top' | 'bottom' | 'auto';
6
6
  export interface ScrollPos {
7
7
  left?: number;
@@ -16,4 +16,4 @@ export type ScrollTarget = {
16
16
  align?: ScrollAlign;
17
17
  offset?: number;
18
18
  };
19
- export default function useScrollTo(containerRef: Ref<HTMLDivElement>, data: Ref<any[]>, heights: CacheMap, itemHeight: Ref<number>, getKey: GetKey<any>, collectHeight: () => void, syncScrollTop: (newTop: number) => void, triggerFlash: () => void): (arg: number | ScrollTarget) => void;
19
+ export default function useScrollTo(containerRef: Ref<HTMLDivElement>, data: Ref<any[]>, heights: CacheMap, itemHeight: Ref<number>, getKey: GetKey<any>, collectHeight: () => void, syncScrollTop: (newTop: number) => void, triggerFlash: () => void): [(arg: number | ScrollTarget) => void, () => number];
@@ -1,11 +1,18 @@
1
1
  import { shallowRef, watch } from "vue";
2
2
  import { warning } from "@v-c/util";
3
- import raf from "@v-c/util/dist/raf";
4
3
  var MAX_TIMES = 10;
5
4
  function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHeight, syncScrollTop, triggerFlash) {
6
- const scrollRef = shallowRef();
7
5
  const syncState = shallowRef(null);
8
- watch([syncState, containerRef], () => {
6
+ const getTotalHeight = () => {
7
+ let totalHeight = 0;
8
+ for (let i = 0; i < data.value.length; i += 1) {
9
+ const key = getKey(data.value[i]);
10
+ const cacheHeight = heights.get(key);
11
+ totalHeight += cacheHeight === void 0 ? itemHeight.value : cacheHeight;
12
+ }
13
+ return totalHeight;
14
+ };
15
+ watch(syncState, () => {
9
16
  if (syncState.value && syncState.value.times < MAX_TIMES) {
10
17
  if (!containerRef.value) {
11
18
  syncState.value = { ...syncState.value };
@@ -69,12 +76,11 @@ function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHei
69
76
  immediate: true,
70
77
  flush: "post"
71
78
  });
72
- return (arg) => {
79
+ const scrollTo = (arg) => {
73
80
  if (arg === null || arg === void 0) {
74
81
  triggerFlash();
75
82
  return;
76
83
  }
77
- raf.cancel(scrollRef.value);
78
84
  if (typeof arg === "number") syncScrollTop(arg);
79
85
  else if (arg && typeof arg === "object") {
80
86
  let index;
@@ -90,5 +96,6 @@ function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHei
90
96
  };
91
97
  }
92
98
  };
99
+ return [scrollTo, getTotalHeight];
93
100
  }
94
101
  export { useScrollTo as default };
package/dist/index.cjs CHANGED
@@ -1,4 +1,7 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  const require_List = require("./List.cjs");
3
6
  var src_default = require_List.default;
4
7
  exports.default = src_default;
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
@@ -1,4 +1,7 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  var CacheMap = class {
3
6
  maps;
4
7
  id = 0;
@@ -0,0 +1,47 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ function getIndexByStartLoc(min, max, start, index) {
3
+ const beforeCount = start - min;
4
+ const afterCount = max - start;
5
+ if (index <= Math.min(beforeCount, afterCount) * 2) {
6
+ const stepIndex = Math.floor(index / 2);
7
+ if (index % 2) return start + stepIndex + 1;
8
+ return start - stepIndex;
9
+ }
10
+ if (beforeCount > afterCount) return start - (index - afterCount);
11
+ return start + (index - beforeCount);
12
+ }
13
+ function findListDiffIndex(originList, targetList, getKey) {
14
+ const originLen = originList.length;
15
+ const targetLen = targetList.length;
16
+ let shortList;
17
+ let longList;
18
+ if (originLen === 0 && targetLen === 0) return null;
19
+ if (originLen < targetLen) {
20
+ shortList = originList;
21
+ longList = targetList;
22
+ } else {
23
+ shortList = targetList;
24
+ longList = originList;
25
+ }
26
+ const notExistKey = { __EMPTY_ITEM__: true };
27
+ function getItemKey(item) {
28
+ if (item !== void 0) return getKey(item);
29
+ return notExistKey;
30
+ }
31
+ let diffIndex = null;
32
+ let multiple = Math.abs(originLen - targetLen) !== 1;
33
+ for (let i = 0; i < longList.length; i += 1) {
34
+ const shortKey = getItemKey(shortList[i]);
35
+ if (shortKey !== getItemKey(longList[i])) {
36
+ diffIndex = i;
37
+ multiple = multiple || shortKey !== getItemKey(longList[i + 1]);
38
+ break;
39
+ }
40
+ }
41
+ return diffIndex === null ? null : {
42
+ index: diffIndex,
43
+ multiple
44
+ };
45
+ }
46
+ exports.findListDiffIndex = findListDiffIndex;
47
+ exports.getIndexByStartLoc = getIndexByStartLoc;
@@ -0,0 +1,23 @@
1
+ import { Key } from '@v-c/util/dist/type';
2
+ /**
3
+ * Get index with specific start index one by one. e.g.
4
+ * min: 3, max: 9, start: 6
5
+ *
6
+ * Return index is:
7
+ * [0]: 6
8
+ * [1]: 7
9
+ * [2]: 5
10
+ * [3]: 8
11
+ * [4]: 4
12
+ * [5]: 9
13
+ * [6]: 3
14
+ */
15
+ export declare function getIndexByStartLoc(min: number, max: number, start: number, index: number): number;
16
+ /**
17
+ * We assume that 2 list has only 1 item diff and others keeping the order.
18
+ * So we can use dichotomy algorithm to find changed one.
19
+ */
20
+ export declare function findListDiffIndex<T>(originList: T[], targetList: T[], getKey: (item: T) => Key): {
21
+ index: number;
22
+ multiple: boolean;
23
+ } | null;
@@ -0,0 +1,45 @@
1
+ function getIndexByStartLoc(min, max, start, index) {
2
+ const beforeCount = start - min;
3
+ const afterCount = max - start;
4
+ if (index <= Math.min(beforeCount, afterCount) * 2) {
5
+ const stepIndex = Math.floor(index / 2);
6
+ if (index % 2) return start + stepIndex + 1;
7
+ return start - stepIndex;
8
+ }
9
+ if (beforeCount > afterCount) return start - (index - afterCount);
10
+ return start + (index - beforeCount);
11
+ }
12
+ function findListDiffIndex(originList, targetList, getKey) {
13
+ const originLen = originList.length;
14
+ const targetLen = targetList.length;
15
+ let shortList;
16
+ let longList;
17
+ if (originLen === 0 && targetLen === 0) return null;
18
+ if (originLen < targetLen) {
19
+ shortList = originList;
20
+ longList = targetList;
21
+ } else {
22
+ shortList = targetList;
23
+ longList = originList;
24
+ }
25
+ const notExistKey = { __EMPTY_ITEM__: true };
26
+ function getItemKey(item) {
27
+ if (item !== void 0) return getKey(item);
28
+ return notExistKey;
29
+ }
30
+ let diffIndex = null;
31
+ let multiple = Math.abs(originLen - targetLen) !== 1;
32
+ for (let i = 0; i < longList.length; i += 1) {
33
+ const shortKey = getItemKey(shortList[i]);
34
+ if (shortKey !== getItemKey(longList[i])) {
35
+ diffIndex = i;
36
+ multiple = multiple || shortKey !== getItemKey(longList[i + 1]);
37
+ break;
38
+ }
39
+ }
40
+ return diffIndex === null ? null : {
41
+ index: diffIndex,
42
+ multiple
43
+ };
44
+ }
45
+ export { findListDiffIndex, getIndexByStartLoc };
@@ -1,4 +1,7 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
2
5
  var isFF = typeof navigator === "object" && /Firefox/i.test(navigator.userAgent);
3
6
  var isFirefox_default = isFF;
4
7
  exports.default = isFirefox_default;
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
1
2
  var MIN_SIZE = 20;
2
3
  function getSpinSize(containerSize = 0, scrollRange = 0) {
3
4
  let baseSize = containerSize / scrollRange * containerSize;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@v-c/virtual-list",
3
3
  "type": "module",
4
- "version": "1.0.2",
4
+ "version": "1.0.4",
5
5
  "description": "Vue Virtual List Component",
6
6
  "author": "",
7
7
  "license": "MIT",
@@ -31,8 +31,8 @@
31
31
  "vue": "^3.0.0"
32
32
  },
33
33
  "dependencies": {
34
- "@v-c/resize-observer": "^1.0.0",
35
- "@v-c/util": "^1.0.2"
34
+ "@v-c/resize-observer": "^1.0.3",
35
+ "@v-c/util": "^1.0.4"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "vite build",