@v-c/virtual-list 1.0.2 → 1.0.3

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/List.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
2
  const require_rolldown_runtime = require("./_virtual/rolldown_runtime.cjs");
3
3
  const require_Filler = require("./Filler.cjs");
4
- const require_Item = require("./Item.cjs");
4
+ const require_useChildren = require("./hooks/useChildren.cjs");
5
+ const require_useDiffItem = require("./hooks/useDiffItem.cjs");
5
6
  const require_useFrameWheel = require("./hooks/useFrameWheel.cjs");
6
7
  const require_useGetSize = require("./hooks/useGetSize.cjs");
7
8
  const require_useHeights = require("./hooks/useHeights.cjs");
@@ -14,9 +15,6 @@ let vue = require("vue");
14
15
  let __v_c_resize_observer = require("@v-c/resize-observer");
15
16
  __v_c_resize_observer = require_rolldown_runtime.__toESM(__v_c_resize_observer);
16
17
  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
- }
20
18
  var EMPTY_DATA = [];
21
19
  var ScrollStyle = {
22
20
  overflowY: "auto",
@@ -125,7 +123,6 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
125
123
  fillerOffset.value = void 0;
126
124
  return;
127
125
  }
128
- const { itemHeight: itemHeight$1, height } = props;
129
126
  if (!inVirtual.value) {
130
127
  scrollHeight.value = fillerInnerRef.value?.offsetHeight || 0;
131
128
  start.value = 0;
@@ -133,6 +130,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
133
130
  fillerOffset.value = void 0;
134
131
  return;
135
132
  }
133
+ const { itemHeight: itemHeight$1, height } = props;
136
134
  let itemTop = 0;
137
135
  let startIndex;
138
136
  let startOffset;
@@ -258,6 +256,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
258
256
  const onScrollbarStopMove = () => {
259
257
  scrollMoving.value = false;
260
258
  };
259
+ require_useDiffItem.default(mergedData, getKey);
261
260
  (0, vue.watch)([
262
261
  () => props.height,
263
262
  scrollHeight,
@@ -266,7 +265,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
266
265
  ], () => {
267
266
  if (inVirtual.value && props.height && scrollHeight.value) verticalScrollBarSpinSize.value = require_scrollbarUtil.getSpinSize(size.value.height, scrollHeight.value);
268
267
  }, { immediate: true });
269
- (0, vue.watch)([() => size.value.width, () => contentScrollWidth.value], () => {
268
+ (0, vue.watch)([() => size.value.width, contentScrollWidth], () => {
270
269
  if (inVirtual.value && contentScrollWidth.value) horizontalScrollBarSpinSize.value = require_scrollbarUtil.getSpinSize(size.value.width, contentScrollWidth.value);
271
270
  }, { immediate: true });
272
271
  (0, vue.watch)(() => props.scrollWidth, (val) => {
@@ -279,7 +278,13 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
279
278
  props.onScroll?.(e);
280
279
  triggerScroll();
281
280
  }
282
- const scrollTo = require_useScrollTo.default(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), syncScrollTop, delayHideScrollBar);
281
+ const [scrollTo, getTotalHeight] = require_useScrollTo.default(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), (newTop) => {
282
+ const totalHeight = getTotalHeight();
283
+ const maxScrollHeight = Math.max(scrollHeight.value, totalHeight) - props.height;
284
+ const alignedTop = Math.max(0, Math.min(newTop, maxScrollHeight || 0));
285
+ if (componentRef.value) componentRef.value.scrollTop = alignedTop;
286
+ offsetTop.value = alignedTop;
287
+ }, delayHideScrollBar);
283
288
  expose({
284
289
  nativeElement: containerRef,
285
290
  getScrollInfo: getVirtualScrollInfo,
@@ -304,30 +309,12 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
304
309
  }
305
310
  });
306
311
  const getSize = require_useGetSize.useGetSize(mergedData, getKey, heights, itemHeight);
312
+ const listChildren = require_useChildren.default(mergedData, start, end, contentScrollWidth, offsetLeft, setInstanceRef, (item, index, props$1) => slots.default?.({
313
+ item,
314
+ index,
315
+ ...props$1
316
+ }), { getKey });
307
317
  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] }));
328
- }
329
- return children;
330
- };
331
318
  const componentStyle = {};
332
319
  if (props.height) {
333
320
  componentStyle[props.fullHeight ? "height" : "maxHeight"] = `${props.height}px`;
@@ -378,7 +365,7 @@ var List_default = /* @__PURE__ */ (0, vue.defineComponent)({
378
365
  "innerProps": props.innerProps,
379
366
  "rtl": isRTL.value,
380
367
  "extra": extraContent
381
- }, _isSlot(_slot = renderChildren()) ? _slot : { default: () => [_slot] })] })] }),
368
+ }, { default: () => [listChildren.value] })] })] }),
382
369
  inVirtual.value && scrollHeight.value > (props.height || 0) && (0, vue.createVNode)(require_ScrollBar.default, {
383
370
  "ref": verticalScrollBarRef,
384
371
  "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, toRef, 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",
@@ -122,7 +120,6 @@ var List_default = /* @__PURE__ */ defineComponent({
122
120
  fillerOffset.value = void 0;
123
121
  return;
124
122
  }
125
- const { itemHeight: itemHeight$1, height } = props;
126
123
  if (!inVirtual.value) {
127
124
  scrollHeight.value = fillerInnerRef.value?.offsetHeight || 0;
128
125
  start.value = 0;
@@ -130,6 +127,7 @@ var List_default = /* @__PURE__ */ defineComponent({
130
127
  fillerOffset.value = void 0;
131
128
  return;
132
129
  }
130
+ const { itemHeight: itemHeight$1, height } = props;
133
131
  let itemTop = 0;
134
132
  let startIndex;
135
133
  let startOffset;
@@ -255,6 +253,7 @@ var List_default = /* @__PURE__ */ defineComponent({
255
253
  const onScrollbarStopMove = () => {
256
254
  scrollMoving.value = false;
257
255
  };
256
+ useDiffItem(mergedData, getKey);
258
257
  watch([
259
258
  () => props.height,
260
259
  scrollHeight,
@@ -263,7 +262,7 @@ var List_default = /* @__PURE__ */ defineComponent({
263
262
  ], () => {
264
263
  if (inVirtual.value && props.height && scrollHeight.value) verticalScrollBarSpinSize.value = getSpinSize(size.value.height, scrollHeight.value);
265
264
  }, { immediate: true });
266
- watch([() => size.value.width, () => contentScrollWidth.value], () => {
265
+ watch([() => size.value.width, contentScrollWidth], () => {
267
266
  if (inVirtual.value && contentScrollWidth.value) horizontalScrollBarSpinSize.value = getSpinSize(size.value.width, contentScrollWidth.value);
268
267
  }, { immediate: true });
269
268
  watch(() => props.scrollWidth, (val) => {
@@ -276,7 +275,13 @@ var List_default = /* @__PURE__ */ defineComponent({
276
275
  props.onScroll?.(e);
277
276
  triggerScroll();
278
277
  }
279
- const scrollTo = useScrollTo(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), syncScrollTop, delayHideScrollBar);
278
+ const [scrollTo, getTotalHeight] = useScrollTo(componentRef, mergedData, heights, itemHeight, getKey, () => collectHeight(true), (newTop) => {
279
+ const totalHeight = getTotalHeight();
280
+ const maxScrollHeight = Math.max(scrollHeight.value, totalHeight) - props.height;
281
+ const alignedTop = Math.max(0, Math.min(newTop, maxScrollHeight || 0));
282
+ if (componentRef.value) componentRef.value.scrollTop = alignedTop;
283
+ offsetTop.value = alignedTop;
284
+ }, delayHideScrollBar);
280
285
  expose({
281
286
  nativeElement: containerRef,
282
287
  getScrollInfo: getVirtualScrollInfo,
@@ -301,30 +306,12 @@ var List_default = /* @__PURE__ */ defineComponent({
301
306
  }
302
307
  });
303
308
  const getSize = useGetSize(mergedData, getKey, heights, itemHeight);
309
+ const listChildren = useChildren(mergedData, start, end, contentScrollWidth, offsetLeft, setInstanceRef, (item, index, props$1) => slots.default?.({
310
+ item,
311
+ index,
312
+ ...props$1
313
+ }), { getKey });
304
314
  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] }));
325
- }
326
- return children;
327
- };
328
315
  const componentStyle = {};
329
316
  if (props.height) {
330
317
  componentStyle[props.fullHeight ? "height" : "maxHeight"] = `${props.height}px`;
@@ -375,7 +362,7 @@ var List_default = /* @__PURE__ */ defineComponent({
375
362
  "innerProps": props.innerProps,
376
363
  "rtl": isRTL.value,
377
364
  "extra": extraContent
378
- }, _isSlot(_slot = renderChildren()) ? _slot : { default: () => [_slot] })] })] }),
365
+ }, { default: () => [listChildren.value] })] })] }),
379
366
  inVirtual.value && scrollHeight.value > (props.height || 0) && createVNode(ScrollBar_default, {
380
367
  "ref": verticalScrollBarRef,
381
368
  "prefixCls": props.prefixCls,
@@ -0,0 +1,23 @@
1
+ Object.defineProperty(exports, "__esModule", { value: true });
2
+ const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
+ const require_Item = require("../Item.cjs");
4
+ let vue = require("vue");
5
+ function _isSlot(s) {
6
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !(0, vue.isVNode)(s);
7
+ }
8
+ function useChildren(list, startIndex, endIndex, scrollWidth, offsetX, setNodeRef, renderFunc, { getKey }) {
9
+ return (0, vue.computed)(() => {
10
+ return list.value.slice(startIndex.value, endIndex.value + 1).map((item, index) => {
11
+ const node = renderFunc(item, startIndex.value + index, {
12
+ style: { width: `${scrollWidth.value}px` },
13
+ offsetX: offsetX.value
14
+ });
15
+ const key = getKey(item);
16
+ return (0, vue.createVNode)(require_Item.default, {
17
+ "key": key,
18
+ "setRef": (ele) => setNodeRef(item, ele)
19
+ }, _isSlot(node) ? node : { default: () => [node] });
20
+ });
21
+ });
22
+ }
23
+ 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,17 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
2
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
+ const require_algorithmUtil = require("../utils/algorithmUtil.cjs");
3
4
  let vue = require("vue");
4
- function useDiffItem(data, getKey) {
5
- const prevDataRef = (0, vue.ref)([]);
6
- const diffItem = (0, vue.ref)();
5
+ function useDiffItem(data, getKey, onDiff) {
6
+ const prevData = (0, vue.shallowRef)(data.value);
7
+ const diffItem = (0, vue.shallowRef)();
7
8
  (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;
9
+ const diff = require_algorithmUtil.findListDiffIndex(prevData.value || [], data.value || [], getKey);
10
+ if (diff?.index !== void 0) {
11
+ onDiff?.(diff.index);
12
+ diffItem.value = newData[diff.index];
15
13
  }
14
+ prevData.value = newData;
16
15
  }, { immediate: true });
17
16
  return diffItem;
18
17
  }
@@ -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
  }
@@ -2,13 +2,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
2
2
  const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
3
3
  let vue = require("vue");
4
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
5
  var MAX_TIMES = 10;
8
6
  function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHeight, syncScrollTop, triggerFlash) {
9
- const scrollRef = (0, vue.shallowRef)();
10
7
  const syncState = (0, vue.shallowRef)(null);
11
- (0, vue.watch)([syncState, containerRef], () => {
8
+ const getTotalHeight = () => {
9
+ let totalHeight = 0;
10
+ for (let i = 0; i < data.value.length; i += 1) {
11
+ const key = getKey(data.value[i]);
12
+ const cacheHeight = heights.get(key);
13
+ totalHeight += cacheHeight === void 0 ? itemHeight.value : cacheHeight;
14
+ }
15
+ return totalHeight;
16
+ };
17
+ (0, vue.watch)(syncState, () => {
12
18
  if (syncState.value && syncState.value.times < MAX_TIMES) {
13
19
  if (!containerRef.value) {
14
20
  syncState.value = { ...syncState.value };
@@ -72,12 +78,11 @@ function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHei
72
78
  immediate: true,
73
79
  flush: "post"
74
80
  });
75
- return (arg) => {
81
+ const scrollTo = (arg) => {
76
82
  if (arg === null || arg === void 0) {
77
83
  triggerFlash();
78
84
  return;
79
85
  }
80
- __v_c_util_dist_raf.default.cancel(scrollRef.value);
81
86
  if (typeof arg === "number") syncScrollTop(arg);
82
87
  else if (arg && typeof arg === "object") {
83
88
  let index;
@@ -93,5 +98,6 @@ function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHei
93
98
  };
94
99
  }
95
100
  };
101
+ return [scrollTo, getTotalHeight];
96
102
  }
97
103
  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 };
@@ -0,0 +1,46 @@
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
+ exports.findListDiffIndex = findListDiffIndex;
46
+ 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 };
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.3",
5
5
  "description": "Vue Virtual List Component",
6
6
  "author": "",
7
7
  "license": "MIT",
@@ -31,7 +31,7 @@
31
31
  "vue": "^3.0.0"
32
32
  },
33
33
  "dependencies": {
34
- "@v-c/resize-observer": "^1.0.0",
34
+ "@v-c/resize-observer": "^1.0.1",
35
35
  "@v-c/util": "^1.0.2"
36
36
  },
37
37
  "scripts": {