@tarojs/components-advanced 4.1.12-beta.4 → 4.1.12-beta.40

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 (73) hide show
  1. package/dist/components/index.js +1 -0
  2. package/dist/components/index.js.map +1 -1
  3. package/dist/components/list/hooks/useItemSizeCache.d.ts +1 -13
  4. package/dist/components/list/hooks/useItemSizeCache.js +6 -50
  5. package/dist/components/list/hooks/useItemSizeCache.js.map +1 -1
  6. package/dist/components/list/hooks/useListNestedScroll.d.ts +18 -0
  7. package/dist/components/list/hooks/useListNestedScroll.js +61 -0
  8. package/dist/components/list/hooks/useListNestedScroll.js.map +1 -0
  9. package/dist/components/list/hooks/useListScrollElementAttach.d.ts +25 -0
  10. package/dist/components/list/hooks/useListScrollElementAttach.js +88 -0
  11. package/dist/components/list/hooks/useListScrollElementAttach.js.map +1 -0
  12. package/dist/components/list/hooks/useListScrollElementAttachWeapp.d.ts +14 -0
  13. package/dist/components/list/hooks/useListScrollElementAttachWeapp.js +134 -0
  14. package/dist/components/list/hooks/useListScrollElementAttachWeapp.js.map +1 -0
  15. package/dist/components/list/hooks/useMeasureStartOffset.d.ts +12 -0
  16. package/dist/components/list/hooks/useMeasureStartOffset.js +84 -0
  17. package/dist/components/list/hooks/useMeasureStartOffset.js.map +1 -0
  18. package/dist/components/list/hooks/useMeasureStartOffsetWeapp.d.ts +14 -0
  19. package/dist/components/list/hooks/useMeasureStartOffsetWeapp.js +82 -0
  20. package/dist/components/list/hooks/useMeasureStartOffsetWeapp.js.map +1 -0
  21. package/dist/components/list/hooks/useRefresher.d.ts +10 -2
  22. package/dist/components/list/hooks/useRefresher.js +150 -69
  23. package/dist/components/list/hooks/useRefresher.js.map +1 -1
  24. package/dist/components/list/hooks/useResizeObserver.d.ts +1 -0
  25. package/dist/components/list/hooks/useResizeObserver.js +37 -31
  26. package/dist/components/list/hooks/useResizeObserver.js.map +1 -1
  27. package/dist/components/list/hooks/useScrollCorrection.d.ts +3 -2
  28. package/dist/components/list/hooks/useScrollCorrection.js +7 -5
  29. package/dist/components/list/hooks/useScrollCorrection.js.map +1 -1
  30. package/dist/components/list/hooks/useScrollParentAutoFind.d.ts +20 -0
  31. package/dist/components/list/hooks/useScrollParentAutoFind.js +81 -0
  32. package/dist/components/list/hooks/useScrollParentAutoFind.js.map +1 -0
  33. package/dist/components/list/index.d.ts +16 -6
  34. package/dist/components/list/index.js +435 -498
  35. package/dist/components/list/index.js.map +1 -1
  36. package/dist/components/list/utils.d.ts +5 -0
  37. package/dist/components/list/utils.js +17 -1
  38. package/dist/components/list/utils.js.map +1 -1
  39. package/dist/components/virtual-list/vue/list.d.ts +10 -10
  40. package/dist/components/virtual-waterfall/vue/waterfall.d.ts +10 -10
  41. package/dist/components/water-flow/flow-item.js +6 -4
  42. package/dist/components/water-flow/flow-item.js.map +1 -1
  43. package/dist/components/water-flow/flow-section.js +1 -1
  44. package/dist/components/water-flow/flow-section.js.map +1 -1
  45. package/dist/components/water-flow/index.d.ts +1 -1
  46. package/dist/components/water-flow/interface.d.ts +18 -2
  47. package/dist/components/water-flow/root.d.ts +35 -4
  48. package/dist/components/water-flow/root.js +114 -42
  49. package/dist/components/water-flow/root.js.map +1 -1
  50. package/dist/components/water-flow/section.d.ts +7 -1
  51. package/dist/components/water-flow/section.js +54 -9
  52. package/dist/components/water-flow/section.js.map +1 -1
  53. package/dist/components/water-flow/utils.d.ts +4 -0
  54. package/dist/components/water-flow/utils.js +5 -1
  55. package/dist/components/water-flow/utils.js.map +1 -1
  56. package/dist/components/water-flow/water-flow-node-cache.d.ts +24 -0
  57. package/dist/components/water-flow/water-flow-node-cache.js +161 -0
  58. package/dist/components/water-flow/water-flow-node-cache.js.map +1 -0
  59. package/dist/components/water-flow/water-flow.d.ts +2 -3
  60. package/dist/components/water-flow/water-flow.js +286 -31
  61. package/dist/components/water-flow/water-flow.js.map +1 -1
  62. package/dist/index.js +2 -0
  63. package/dist/index.js.map +1 -1
  64. package/dist/utils/index.d.ts +1 -0
  65. package/dist/utils/index.js +1 -0
  66. package/dist/utils/index.js.map +1 -1
  67. package/dist/utils/scrollElementContext.d.ts +15 -0
  68. package/dist/utils/scrollElementContext.js +14 -0
  69. package/dist/utils/scrollElementContext.js.map +1 -0
  70. package/dist/utils/scrollParent.d.ts +33 -0
  71. package/dist/utils/scrollParent.js +88 -0
  72. package/dist/utils/scrollParent.js.map +1 -0
  73. package/package.json +9 -8
@@ -2,6 +2,7 @@ export { List, accumulate, isShaking } from './list/index.js';
2
2
  export { VirtualList } from './virtual-list/index.js';
3
3
  export { VirtualWaterfall } from './virtual-waterfall/index.js';
4
4
  import './water-flow/index.js';
5
+ export { ScrollElementContextOrFallback as ListScrollElementContext } from '../utils/scrollElementContext.js';
5
6
  export { ListItem } from './list/ListItem.js';
6
7
  export { NoMore } from './list/NoMore.js';
7
8
  export { StickyHeader } from './list/StickyHeader.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
@@ -1,6 +1,6 @@
1
1
  interface UseItemSizeCacheOptions {
2
2
  isHorizontal: boolean;
3
- estimatedItemSize: number;
3
+ estimatedSize: number;
4
4
  itemCount: number;
5
5
  }
6
6
  interface UseItemSizeCacheReturn {
@@ -8,18 +8,6 @@ interface UseItemSizeCacheReturn {
8
8
  getItemSize: (index: number) => number;
9
9
  /** 设置项的尺寸 */
10
10
  setItemSize: (index: number, size: number) => void;
11
- /** 获取指定索引的累积偏移 */
12
- getItemOffset: (index: number) => number;
13
- /** 清空缓存 */
14
- clearCache: () => void;
15
- /** 获取缓存统计信息 */
16
- getCacheStats: () => {
17
- totalItems: number;
18
- measuredItems: number;
19
- estimatedItems: number;
20
- };
21
- /** 维度名称('height' 或 'width') */
22
- dimension: 'height' | 'width';
23
11
  }
24
12
  export declare function useItemSizeCache(options: UseItemSizeCacheOptions): UseItemSizeCacheReturn;
25
13
  export {};
@@ -1,11 +1,9 @@
1
1
  import { useRef, useCallback } from 'react';
2
2
 
3
3
  function useItemSizeCache(options) {
4
- const { isHorizontal, estimatedItemSize, itemCount } = options;
4
+ const { estimatedSize } = options;
5
5
  // 缓存 Map:key = 索引,value = 尺寸信息
6
6
  const cacheRef = useRef(new Map());
7
- // 维度名称
8
- const dimension = isHorizontal ? 'width' : 'height';
9
7
  /**
10
8
  * 获取项的尺寸
11
9
  * 优先返回实际测量值,否则返回估算值
@@ -15,8 +13,8 @@ function useItemSizeCache(options) {
15
13
  if ((cached === null || cached === void 0 ? void 0 : cached.isMeasured) && cached.measuredSize !== null) {
16
14
  return cached.measuredSize;
17
15
  }
18
- return estimatedItemSize;
19
- }, [estimatedItemSize]);
16
+ return estimatedSize;
17
+ }, [estimatedSize]);
20
18
  /**
21
19
  * 设置项的尺寸(实际测量后调用)
22
20
  */
@@ -28,55 +26,13 @@ function useItemSizeCache(options) {
28
26
  }
29
27
  cacheRef.current.set(index, {
30
28
  measuredSize: size,
31
- estimatedSize: estimatedItemSize,
29
+ estimatedSize,
32
30
  isMeasured: true
33
31
  });
34
- }, [estimatedItemSize]);
35
- /**
36
- * 获取指定索引的累积偏移
37
- * 计算从 0 到 index-1 的所有项尺寸之和
38
- */
39
- const getItemOffset = useCallback((index) => {
40
- let offset = 0;
41
- for (let i = 0; i < index; i++) {
42
- offset += getItemSize(i);
43
- }
44
- return offset;
45
- }, [getItemSize]);
46
- /**
47
- * 清空缓存
48
- */
49
- const clearCache = useCallback(() => {
50
- cacheRef.current.clear();
51
- }, []);
52
- /**
53
- * 获取缓存统计信息
54
- */
55
- const getCacheStats = useCallback(() => {
56
- let measuredItems = 0;
57
- let estimatedItems = 0;
58
- for (let i = 0; i < itemCount; i++) {
59
- const cached = cacheRef.current.get(i);
60
- if (cached === null || cached === void 0 ? void 0 : cached.isMeasured) {
61
- measuredItems++;
62
- }
63
- else {
64
- estimatedItems++;
65
- }
66
- }
67
- return {
68
- totalItems: itemCount,
69
- measuredItems,
70
- estimatedItems
71
- };
72
- }, [itemCount]);
32
+ }, [estimatedSize]);
73
33
  return {
74
34
  getItemSize,
75
- setItemSize,
76
- getItemOffset,
77
- clearCache,
78
- getCacheStats,
79
- dimension
35
+ setItemSize
80
36
  };
81
37
  }
82
38
 
@@ -1 +1 @@
1
- {"version":3,"file":"useItemSizeCache.js","sources":["../../../../src/components/list/hooks/useItemSizeCache.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\n\n/**\n * useItemSizeCache Hook - 动态尺寸缓存管理\n *\n * 支持垂直滚动(高度)和水平滚动(宽度)两种模式\n */\n\n/** 单个项的尺寸缓存 */\ninterface ItemMeasureCache {\n measuredSize: number | null // 实际测量尺寸\n estimatedSize: number // 估算尺寸\n isMeasured: boolean // 是否已测量\n}\n\ninterface UseItemSizeCacheOptions {\n isHorizontal: boolean // 是否水平滚动\n estimatedItemSize: number // 估算尺寸\n itemCount: number // 项总数\n}\n\ninterface UseItemSizeCacheReturn {\n /** 获取项的尺寸(高度或宽度) */\n getItemSize: (index: number) => number\n\n /** 设置项的尺寸 */\n setItemSize: (index: number, size: number) => void\n\n /** 获取指定索引的累积偏移 */\n getItemOffset: (index: number) => number\n\n /** 清空缓存 */\n clearCache: () => void\n\n /** 获取缓存统计信息 */\n getCacheStats: () => {\n totalItems: number\n measuredItems: number\n estimatedItems: number\n }\n\n /** 维度名称('height' 或 'width') */\n dimension: 'height' | 'width'\n}\n\nexport function useItemSizeCache(\n options: UseItemSizeCacheOptions\n): UseItemSizeCacheReturn {\n const { isHorizontal, estimatedItemSize, itemCount } = options\n\n // 缓存 Map:key = 索引,value = 尺寸信息\n const cacheRef = useRef<Map<number, ItemMeasureCache>>(new Map())\n\n // 维度名称\n const dimension: 'height' | 'width' = isHorizontal ? 'width' : 'height'\n\n /**\n * 获取项的尺寸\n * 优先返回实际测量值,否则返回估算值\n */\n const getItemSize = useCallback((index: number): number => {\n const cached = cacheRef.current.get(index)\n\n if (cached?.isMeasured && cached.measuredSize !== null) {\n return cached.measuredSize\n }\n\n return estimatedItemSize\n }, [estimatedItemSize])\n\n /**\n * 设置项的尺寸(实际测量后调用)\n */\n const setItemSize = useCallback((index: number, size: number) => {\n const cached = cacheRef.current.get(index)\n\n // 尺寸变化小于 1px,忽略(避免微小抖动)\n if (cached?.measuredSize && Math.abs(cached.measuredSize - size) < 1) {\n return\n }\n\n cacheRef.current.set(index, {\n measuredSize: size,\n estimatedSize: estimatedItemSize,\n isMeasured: true\n })\n }, [estimatedItemSize])\n\n /**\n * 获取指定索引的累积偏移\n * 计算从 0 到 index-1 的所有项尺寸之和\n */\n const getItemOffset = useCallback((index: number): number => {\n let offset = 0\n\n for (let i = 0; i < index; i++) {\n offset += getItemSize(i)\n }\n\n return offset\n }, [getItemSize])\n\n /**\n * 清空缓存\n */\n const clearCache = useCallback(() => {\n cacheRef.current.clear()\n }, [])\n\n /**\n * 获取缓存统计信息\n */\n const getCacheStats = useCallback(() => {\n let measuredItems = 0\n let estimatedItems = 0\n\n for (let i = 0; i < itemCount; i++) {\n const cached = cacheRef.current.get(i)\n if (cached?.isMeasured) {\n measuredItems++\n } else {\n estimatedItems++\n }\n }\n\n return {\n totalItems: itemCount,\n measuredItems,\n estimatedItems\n }\n }, [itemCount])\n\n return {\n getItemSize,\n setItemSize,\n getItemOffset,\n clearCache,\n getCacheStats,\n dimension\n }\n}\n"],"names":[],"mappings":";;AA6CM,SAAU,gBAAgB,CAC9B,OAAgC,EAAA;IAEhC,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,GAAG,OAAO;;IAG9D,MAAM,QAAQ,GAAG,MAAM,CAAgC,IAAI,GAAG,EAAE,CAAC;;IAGjE,MAAM,SAAS,GAAuB,YAAY,GAAG,OAAO,GAAG,QAAQ;AAEvE;;;AAGG;AACH,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,KAAa,KAAY;QACxD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AAE1C,QAAA,IAAI,CAAA,MAAM,KAAN,IAAA,IAAA,MAAM,uBAAN,MAAM,CAAE,UAAU,KAAI,MAAM,CAAC,YAAY,KAAK,IAAI,EAAE;YACtD,OAAO,MAAM,CAAC,YAAY;;AAG5B,QAAA,OAAO,iBAAiB;AAC1B,KAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;AAEvB;;AAEG;IACH,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,KAAa,EAAE,IAAY,KAAI;QAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;;QAG1C,IAAI,CAAA,MAAM,KAAN,IAAA,IAAA,MAAM,uBAAN,MAAM,CAAE,YAAY,KAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;YACpE;;AAGF,QAAA,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE;AAC1B,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,aAAa,EAAE,iBAAiB;AAChC,YAAA,UAAU,EAAE;AACb,SAAA,CAAC;AACJ,KAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;AAEvB;;;AAGG;AACH,IAAA,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,KAAa,KAAY;QAC1D,IAAI,MAAM,GAAG,CAAC;AAEd,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;AAC9B,YAAA,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC;;AAG1B,QAAA,OAAO,MAAM;AACf,KAAC,EAAE,CAAC,WAAW,CAAC,CAAC;AAEjB;;AAEG;AACH,IAAA,MAAM,UAAU,GAAG,WAAW,CAAC,MAAK;AAClC,QAAA,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE;KACzB,EAAE,EAAE,CAAC;AAEN;;AAEG;AACH,IAAA,MAAM,aAAa,GAAG,WAAW,CAAC,MAAK;QACrC,IAAI,aAAa,GAAG,CAAC;QACrB,IAAI,cAAc,GAAG,CAAC;AAEtB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE;YAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YACtC,IAAI,MAAM,aAAN,MAAM,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAN,MAAM,CAAE,UAAU,EAAE;AACtB,gBAAA,aAAa,EAAE;;iBACV;AACL,gBAAA,cAAc,EAAE;;;QAIpB,OAAO;AACL,YAAA,UAAU,EAAE,SAAS;YACrB,aAAa;YACb;SACD;AACH,KAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAEf,OAAO;QACL,WAAW;QACX,WAAW;QACX,aAAa;QACb,UAAU;QACV,aAAa;QACb;KACD;AACH;;;;"}
1
+ {"version":3,"file":"useItemSizeCache.js","sources":["../../../../src/components/list/hooks/useItemSizeCache.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\n\n/**\n * useItemSizeCache Hook - 动态尺寸缓存管理\n *\n * 支持垂直滚动(高度)和水平滚动(宽度)两种模式\n */\n\n/** 单个项的尺寸缓存 */\ninterface ItemMeasureCache {\n measuredSize: number | null // 实际测量尺寸\n estimatedSize: number // 估算尺寸\n isMeasured: boolean // 是否已测量\n}\n\ninterface UseItemSizeCacheOptions {\n isHorizontal: boolean // 是否水平滚动\n estimatedSize: number // 估算尺寸\n itemCount: number // 项总数\n}\n\ninterface UseItemSizeCacheReturn {\n /** 获取项的尺寸(高度或宽度) */\n getItemSize: (index: number) => number\n\n /** 设置项的尺寸 */\n setItemSize: (index: number, size: number) => void\n}\n\nexport function useItemSizeCache(\n options: UseItemSizeCacheOptions\n): UseItemSizeCacheReturn {\n const { estimatedSize } = options\n\n // 缓存 Map:key = 索引,value = 尺寸信息\n const cacheRef = useRef<Map<number, ItemMeasureCache>>(new Map())\n\n /**\n * 获取项的尺寸\n * 优先返回实际测量值,否则返回估算值\n */\n const getItemSize = useCallback((index: number): number => {\n const cached = cacheRef.current.get(index)\n\n if (cached?.isMeasured && cached.measuredSize !== null) {\n return cached.measuredSize\n }\n\n return estimatedSize\n }, [estimatedSize])\n\n /**\n * 设置项的尺寸(实际测量后调用)\n */\n const setItemSize = useCallback((index: number, size: number) => {\n const cached = cacheRef.current.get(index)\n\n // 尺寸变化小于 1px,忽略(避免微小抖动)\n if (cached?.measuredSize && Math.abs(cached.measuredSize - size) < 1) {\n return\n }\n\n cacheRef.current.set(index, {\n measuredSize: size,\n estimatedSize,\n isMeasured: true\n })\n }, [estimatedSize])\n\n return {\n getItemSize,\n setItemSize\n }\n}\n"],"names":[],"mappings":";;AA6BM,SAAU,gBAAgB,CAC9B,OAAgC,EAAA;AAEhC,IAAA,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO;;IAGjC,MAAM,QAAQ,GAAG,MAAM,CAAgC,IAAI,GAAG,EAAE,CAAC;AAEjE;;;AAGG;AACH,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,KAAa,KAAY;QACxD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AAE1C,QAAA,IAAI,CAAA,MAAM,KAAN,IAAA,IAAA,MAAM,uBAAN,MAAM,CAAE,UAAU,KAAI,MAAM,CAAC,YAAY,KAAK,IAAI,EAAE;YACtD,OAAO,MAAM,CAAC,YAAY;;AAG5B,QAAA,OAAO,aAAa;AACtB,KAAC,EAAE,CAAC,aAAa,CAAC,CAAC;AAEnB;;AAEG;IACH,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,KAAa,EAAE,IAAY,KAAI;QAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;;QAG1C,IAAI,CAAA,MAAM,KAAN,IAAA,IAAA,MAAM,uBAAN,MAAM,CAAE,YAAY,KAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;YACpE;;AAGF,QAAA,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE;AAC1B,YAAA,YAAY,EAAE,IAAI;YAClB,aAAa;AACb,YAAA,UAAU,EAAE;AACb,SAAA,CAAC;AACJ,KAAC,EAAE,CAAC,aAAa,CAAC,CAAC;IAEnB,OAAO;QACL,WAAW;QACX;KACD;AACH;;;;"}
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import type { RefObject } from 'react';
3
+ export interface UseListNestedScrollResult {
4
+ effectiveScrollElement: RefObject<HTMLElement | null> | null;
5
+ effectiveStartOffset: number;
6
+ /** 小程序用:实时读取 startOffset,避免 useState 异步更新导致 useListScrollElementAttachWeapp 读到 0 */
7
+ effectiveStartOffsetRef: React.MutableRefObject<number>;
8
+ useScrollElementMode: boolean;
9
+ needAutoFind: boolean;
10
+ autoFindStatus: 'pending' | 'found' | 'not-found';
11
+ contentWrapperRef: RefObject<HTMLDivElement | null>;
12
+ /** 小程序自动查找用:content 节点的 id,需挂到 contentWrapper 对应的 View 上 */
13
+ contentId: string;
14
+ }
15
+ /**
16
+ * 合并嵌套滚动相关逻辑:Context、自动查找、startOffset 测量、scrollElement 解析
17
+ */
18
+ export declare function useListNestedScroll(listType: 'default' | 'nested', scrollElement?: RefObject<HTMLElement | null>, startOffsetProp?: number, isHorizontal?: boolean, selectorQueryScope?: object): UseListNestedScrollResult;
@@ -0,0 +1,61 @@
1
+ import { useRef, useMemo, useContext } from 'react';
2
+ import { ScrollElementContextOrFallback } from '../../../utils/scrollElementContext.js';
3
+ import { isH5, isWeapp } from '../utils.js';
4
+ import { useMeasureStartOffset } from './useMeasureStartOffset.js';
5
+ import { useMeasureStartOffsetWeapp } from './useMeasureStartOffsetWeapp.js';
6
+ import { useScrollParentAutoFind } from './useScrollParentAutoFind.js';
7
+
8
+ const EMPTY_SCROLL_REF = { current: null };
9
+ /**
10
+ * 合并嵌套滚动相关逻辑:Context、自动查找、startOffset 测量、scrollElement 解析
11
+ */
12
+ function useListNestedScroll(listType, scrollElement, startOffsetProp, isHorizontal = false, selectorQueryScope) {
13
+ var _a, _b, _c, _d;
14
+ const contentWrapperRef = useRef(null);
15
+ const contentId = useMemo(() => `list-content-${Math.random().toString(36).slice(2, 11)}`, []);
16
+ const scrollElementCtx = useContext(ScrollElementContextOrFallback);
17
+ const ctxStart = scrollElementCtx === null || scrollElementCtx === void 0 ? void 0 : scrollElementCtx.startOffset;
18
+ const hasExplicitCtxStartOffset = ctxStart != null && ctxStart > 0;
19
+ const needAutoFind = listType === 'nested' &&
20
+ !scrollElement &&
21
+ !(scrollElementCtx === null || scrollElementCtx === void 0 ? void 0 : scrollElementCtx.scrollRef) &&
22
+ (isH5 || isWeapp);
23
+ const { scrollParentRef: autoFoundRef, status: autoFindStatus } = useScrollParentAutoFind(contentWrapperRef, { enabled: !!needAutoFind, isHorizontal, contentId: isWeapp ? contentId : undefined });
24
+ const effectiveScrollElement = (_a = scrollElement !== null && scrollElement !== void 0 ? scrollElement : scrollElementCtx === null || scrollElementCtx === void 0 ? void 0 : scrollElementCtx.scrollRef) !== null && _a !== void 0 ? _a : (needAutoFind && autoFindStatus === 'found' ? autoFoundRef : null);
25
+ const needMeasure = listType === 'nested' &&
26
+ effectiveScrollElement &&
27
+ isH5 &&
28
+ startOffsetProp == null &&
29
+ !hasExplicitCtxStartOffset;
30
+ const needMeasureWeapp = listType === 'nested' &&
31
+ effectiveScrollElement &&
32
+ isWeapp &&
33
+ startOffsetProp == null &&
34
+ !hasExplicitCtxStartOffset;
35
+ const effectiveStartOffsetRef = useRef(0);
36
+ const measuredStartOffset = useMeasureStartOffset(effectiveScrollElement !== null && effectiveScrollElement !== void 0 ? effectiveScrollElement : EMPTY_SCROLL_REF, contentWrapperRef, { enabled: !!needMeasure, isHorizontal });
37
+ const measuredStartOffsetWeapp = useMeasureStartOffsetWeapp(effectiveScrollElement !== null && effectiveScrollElement !== void 0 ? effectiveScrollElement : EMPTY_SCROLL_REF, contentId, { enabled: !!needMeasureWeapp, isHorizontal, startOffsetRef: effectiveStartOffsetRef, selectorQueryScope });
38
+ const effectiveStartOffset = (_d = (_c = (_b = startOffsetProp !== null && startOffsetProp !== void 0 ? startOffsetProp : (ctxStart != null && ctxStart > 0 ? ctxStart : null)) !== null && _b !== void 0 ? _b : measuredStartOffset) !== null && _c !== void 0 ? _c : measuredStartOffsetWeapp) !== null && _d !== void 0 ? _d : 0;
39
+ // needMeasureWeapp 时由 useMeasureStartOffsetWeapp 的 exec 回调更新 ref,不在此覆盖,避免 re-render 用 stale 0 覆盖已测量的值
40
+ if (!needMeasureWeapp) {
41
+ effectiveStartOffsetRef.current = effectiveStartOffset;
42
+ }
43
+ const useScrollElementMode = listType === 'nested' && !!(effectiveScrollElement && (isH5 || isWeapp));
44
+ if (listType === 'nested' && !effectiveScrollElement && (isH5 || isWeapp) && autoFindStatus === 'not-found') {
45
+ // eslint-disable-next-line no-console
46
+ console.warn('[List] nestedScroll 模式但无 scrollElement(props/Context/自动查找),回退为 default');
47
+ }
48
+ return {
49
+ effectiveScrollElement,
50
+ effectiveStartOffset,
51
+ effectiveStartOffsetRef,
52
+ useScrollElementMode,
53
+ needAutoFind,
54
+ autoFindStatus,
55
+ contentWrapperRef,
56
+ contentId,
57
+ };
58
+ }
59
+
60
+ export { useListNestedScroll };
61
+ //# sourceMappingURL=useListNestedScroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useListNestedScroll.js","sources":["../../../../src/components/list/hooks/useListNestedScroll.ts"],"sourcesContent":["import React, { useContext, useMemo, useRef } from 'react'\n\nimport {\n type ScrollElementContextValueShape,\n ScrollElementContextOrFallback,\n} from '../../../utils/scrollElementContext'\nimport { isH5, isWeapp } from '../utils'\nimport { useMeasureStartOffset } from './useMeasureStartOffset'\nimport { useMeasureStartOffsetWeapp } from './useMeasureStartOffsetWeapp'\nimport { useScrollParentAutoFind } from './useScrollParentAutoFind'\n\nimport type { RefObject } from 'react'\n\nconst EMPTY_SCROLL_REF = { current: null as HTMLElement | null }\n\nexport interface UseListNestedScrollResult {\n effectiveScrollElement: RefObject<HTMLElement | null> | null\n effectiveStartOffset: number\n /** 小程序用:实时读取 startOffset,避免 useState 异步更新导致 useListScrollElementAttachWeapp 读到 0 */\n effectiveStartOffsetRef: React.MutableRefObject<number>\n useScrollElementMode: boolean\n needAutoFind: boolean\n autoFindStatus: 'pending' | 'found' | 'not-found'\n contentWrapperRef: RefObject<HTMLDivElement | null>\n /** 小程序自动查找用:content 节点的 id,需挂到 contentWrapper 对应的 View 上 */\n contentId: string\n}\n\n/**\n * 合并嵌套滚动相关逻辑:Context、自动查找、startOffset 测量、scrollElement 解析\n */\nexport function useListNestedScroll(\n listType: 'default' | 'nested',\n scrollElement?: RefObject<HTMLElement | null>,\n startOffsetProp?: number,\n isHorizontal: boolean = false,\n selectorQueryScope?: object\n): UseListNestedScrollResult {\n const contentWrapperRef = useRef<HTMLDivElement>(null)\n const contentId = useMemo(() => `list-content-${Math.random().toString(36).slice(2, 11)}`, [])\n const scrollElementCtx = useContext(ScrollElementContextOrFallback) as ScrollElementContextValueShape | null\n const ctxStart = scrollElementCtx?.startOffset\n const hasExplicitCtxStartOffset = ctxStart != null && ctxStart > 0\n\n const needAutoFind =\n listType === 'nested' &&\n !scrollElement &&\n !scrollElementCtx?.scrollRef &&\n (isH5 || isWeapp)\n const { scrollParentRef: autoFoundRef, status: autoFindStatus } = useScrollParentAutoFind(\n contentWrapperRef,\n { enabled: !!needAutoFind, isHorizontal, contentId: isWeapp ? contentId : undefined }\n )\n\n const effectiveScrollElement =\n scrollElement ??\n scrollElementCtx?.scrollRef ??\n (needAutoFind && autoFindStatus === 'found' ? autoFoundRef : null)\n\n const needMeasure =\n listType === 'nested' &&\n effectiveScrollElement &&\n isH5 &&\n startOffsetProp == null &&\n !hasExplicitCtxStartOffset\n const needMeasureWeapp =\n listType === 'nested' &&\n effectiveScrollElement &&\n isWeapp &&\n startOffsetProp == null &&\n !hasExplicitCtxStartOffset\n const effectiveStartOffsetRef = useRef(0)\n const measuredStartOffset = useMeasureStartOffset(\n effectiveScrollElement ?? EMPTY_SCROLL_REF,\n contentWrapperRef,\n { enabled: !!needMeasure, isHorizontal }\n )\n const measuredStartOffsetWeapp = useMeasureStartOffsetWeapp(\n effectiveScrollElement ?? EMPTY_SCROLL_REF,\n contentId,\n { enabled: !!needMeasureWeapp, isHorizontal, startOffsetRef: effectiveStartOffsetRef, selectorQueryScope }\n )\n\n const effectiveStartOffset =\n startOffsetProp ??\n (ctxStart != null && ctxStart > 0 ? ctxStart : null) ??\n measuredStartOffset ??\n measuredStartOffsetWeapp ??\n 0\n\n // needMeasureWeapp 时由 useMeasureStartOffsetWeapp 的 exec 回调更新 ref,不在此覆盖,避免 re-render 用 stale 0 覆盖已测量的值\n if (!needMeasureWeapp) {\n effectiveStartOffsetRef.current = effectiveStartOffset\n }\n\n const useScrollElementMode = listType === 'nested' && !!(effectiveScrollElement && (isH5 || isWeapp))\n\n if (listType === 'nested' && !effectiveScrollElement && (isH5 || isWeapp) && autoFindStatus === 'not-found') {\n // eslint-disable-next-line no-console\n console.warn('[List] nestedScroll 模式但无 scrollElement(props/Context/自动查找),回退为 default')\n }\n\n return {\n effectiveScrollElement,\n effectiveStartOffset,\n effectiveStartOffsetRef,\n useScrollElementMode,\n needAutoFind,\n autoFindStatus,\n contentWrapperRef,\n contentId,\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { RefObject } from 'react';
2
+ export interface ListScrollElementAttachRefs {
3
+ scrollCorrection: {
4
+ markUserScrolling: () => void;
5
+ };
6
+ onScroll: ((e: {
7
+ scrollTop: number;
8
+ scrollLeft: number;
9
+ detail: {
10
+ scrollTop: number;
11
+ scrollLeft: number;
12
+ };
13
+ }) => void) | undefined;
14
+ onScrollToUpper: (() => void) | undefined;
15
+ onScrollToLower: (() => void) | undefined;
16
+ threshold: {
17
+ upper: number;
18
+ lower: number;
19
+ };
20
+ listContentLength: number;
21
+ }
22
+ /**
23
+ * scrollElement 模式下:监听外部滚动驱动 renderOffset,并从 scrollElement 获取 containerLength
24
+ */
25
+ export declare function useListScrollElementAttach(enabled: boolean, effectiveScrollElement: RefObject<HTMLElement | null> | null, effectiveStartOffset: number, isHorizontal: boolean, setContainerLength: (v: number) => void, updateRenderOffset: (offset: number, sync?: boolean, source?: string) => void, scrollRefProp: React.MutableRefObject<HTMLElement | null> | undefined, refsRef: RefObject<ListScrollElementAttachRefs>): void;
@@ -0,0 +1,88 @@
1
+ import { useRef, useEffect } from 'react';
2
+
3
+ /**
4
+ * scrollElement 模式下:监听外部滚动驱动 renderOffset,并从 scrollElement 获取 containerLength
5
+ */
6
+ function useListScrollElementAttach(enabled, effectiveScrollElement, effectiveStartOffset, isHorizontal, setContainerLength, updateRenderOffset, scrollRefProp, refsRef) {
7
+ const effectiveStartOffsetRef = useRef(effectiveStartOffset);
8
+ effectiveStartOffsetRef.current = effectiveStartOffset;
9
+ useEffect(() => {
10
+ if (!enabled || !effectiveScrollElement)
11
+ return;
12
+ const el = effectiveScrollElement.current;
13
+ if (!el || typeof ResizeObserver === 'undefined')
14
+ return;
15
+ const update = () => {
16
+ const measured = isHorizontal ? el.clientWidth : el.clientHeight;
17
+ if (measured > 0)
18
+ setContainerLength(measured);
19
+ if (scrollRefProp)
20
+ scrollRefProp.current = el;
21
+ };
22
+ update();
23
+ const ro = new ResizeObserver(update);
24
+ ro.observe(el);
25
+ return () => ro.disconnect();
26
+ }, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength]);
27
+ useEffect(() => {
28
+ if (!enabled || !effectiveScrollElement)
29
+ return;
30
+ let cancelled = false;
31
+ let teardown = null;
32
+ const maxRetries = 20;
33
+ const tryAttach = (retryCount = 0) => {
34
+ if (cancelled)
35
+ return;
36
+ const target = effectiveScrollElement.current;
37
+ if (!target) {
38
+ if (retryCount < maxRetries) {
39
+ requestAnimationFrame(() => tryAttach(retryCount + 1));
40
+ }
41
+ return;
42
+ }
43
+ const refs = refsRef.current;
44
+ if (!refs)
45
+ return;
46
+ let inUpperZone = true;
47
+ let inLowerZone = false;
48
+ const handler = () => {
49
+ var _a, _b, _c;
50
+ const r = refsRef.current;
51
+ if (!r)
52
+ return;
53
+ const scrollPos = isHorizontal ? target.scrollLeft : target.scrollTop;
54
+ const adjustedPos = scrollPos - effectiveStartOffsetRef.current;
55
+ const effectiveAdjusted = Math.max(0, adjustedPos);
56
+ const clientSize = isHorizontal ? target.clientWidth : target.clientHeight;
57
+ r.scrollCorrection.markUserScrolling();
58
+ updateRenderOffset(effectiveAdjusted, false, 'scrollElement');
59
+ const scrollTop = isHorizontal ? 0 : scrollPos;
60
+ const scrollLeft = isHorizontal ? scrollPos : 0;
61
+ (_a = r.onScroll) === null || _a === void 0 ? void 0 : _a.call(r, { scrollTop, scrollLeft, detail: { scrollTop, scrollLeft } });
62
+ const { upper, lower } = r.threshold;
63
+ const innerContentLen = r.listContentLength;
64
+ const nowInUpper = effectiveAdjusted <= upper;
65
+ const nowInLower = innerContentLen > 0 && effectiveAdjusted + clientSize >= innerContentLen - lower;
66
+ if (nowInUpper && !inUpperZone)
67
+ (_b = r.onScrollToUpper) === null || _b === void 0 ? void 0 : _b.call(r);
68
+ if (nowInLower && !inLowerZone)
69
+ (_c = r.onScrollToLower) === null || _c === void 0 ? void 0 : _c.call(r);
70
+ inUpperZone = nowInUpper;
71
+ inLowerZone = nowInLower;
72
+ };
73
+ const initialScroll = isHorizontal ? target.scrollLeft : target.scrollTop;
74
+ const initialAdjusted = Math.max(0, initialScroll - effectiveStartOffsetRef.current);
75
+ updateRenderOffset(initialAdjusted, false, 'scrollElement');
76
+ target.addEventListener('scroll', handler, { passive: true });
77
+ teardown = () => target.removeEventListener('scroll', handler);
78
+ };
79
+ tryAttach();
80
+ return () => {
81
+ cancelled = true;
82
+ teardown === null || teardown === void 0 ? void 0 : teardown();
83
+ };
84
+ }, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffset, updateRenderOffset, refsRef]);
85
+ }
86
+
87
+ export { useListScrollElementAttach };
88
+ //# sourceMappingURL=useListScrollElementAttach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useListScrollElementAttach.js","sources":["../../../../src/components/list/hooks/useListScrollElementAttach.ts"],"sourcesContent":["import { useEffect, useRef } from 'react'\n\nimport type { RefObject } from 'react'\n\nexport interface ListScrollElementAttachRefs {\n scrollCorrection: { markUserScrolling: () => void }\n onScroll: ((e: { scrollTop: number, scrollLeft: number, detail: { scrollTop: number, scrollLeft: number } }) => void) | undefined\n onScrollToUpper: (() => void) | undefined\n onScrollToLower: (() => void) | undefined\n threshold: { upper: number, lower: number }\n listContentLength: number\n}\n\n/**\n * scrollElement 模式下:监听外部滚动驱动 renderOffset,并从 scrollElement 获取 containerLength\n */\nexport function useListScrollElementAttach(\n enabled: boolean,\n effectiveScrollElement: RefObject<HTMLElement | null> | null,\n effectiveStartOffset: number,\n isHorizontal: boolean,\n setContainerLength: (v: number) => void,\n updateRenderOffset: (offset: number, sync?: boolean, source?: string) => void,\n scrollRefProp: React.MutableRefObject<HTMLElement | null> | undefined,\n refsRef: RefObject<ListScrollElementAttachRefs>\n) {\n const effectiveStartOffsetRef = useRef(effectiveStartOffset)\n effectiveStartOffsetRef.current = effectiveStartOffset\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n const el = effectiveScrollElement.current\n if (!el || typeof ResizeObserver === 'undefined') return\n\n const update = () => {\n const measured = isHorizontal ? el.clientWidth : el.clientHeight\n if (measured > 0) setContainerLength(measured)\n if (scrollRefProp) scrollRefProp.current = el\n }\n update()\n const ro = new ResizeObserver(update)\n ro.observe(el)\n return () => ro.disconnect()\n }, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength])\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n\n let cancelled = false\n let teardown: (() => void) | null = null\n const maxRetries = 20\n\n const tryAttach = (retryCount = 0) => {\n if (cancelled) return\n const target = effectiveScrollElement.current\n if (!target) {\n if (retryCount < maxRetries) {\n requestAnimationFrame(() => tryAttach(retryCount + 1))\n }\n return\n }\n\n const refs = refsRef.current\n if (!refs) return\n\n let inUpperZone = true\n let inLowerZone = false\n\n const handler = () => {\n const r = refsRef.current\n if (!r) return\n const scrollPos = isHorizontal ? target.scrollLeft : target.scrollTop\n const adjustedPos = scrollPos - effectiveStartOffsetRef.current\n const effectiveAdjusted = Math.max(0, adjustedPos)\n const clientSize = isHorizontal ? target.clientWidth : target.clientHeight\n r.scrollCorrection.markUserScrolling()\n updateRenderOffset(effectiveAdjusted, false, 'scrollElement')\n const scrollTop = isHorizontal ? 0 : scrollPos\n const scrollLeft = isHorizontal ? scrollPos : 0\n r.onScroll?.({ scrollTop, scrollLeft, detail: { scrollTop, scrollLeft } })\n\n const { upper, lower } = r.threshold\n const innerContentLen = r.listContentLength\n const nowInUpper = effectiveAdjusted <= upper\n const nowInLower = innerContentLen > 0 && effectiveAdjusted + clientSize >= innerContentLen - lower\n if (nowInUpper && !inUpperZone) r.onScrollToUpper?.()\n if (nowInLower && !inLowerZone) r.onScrollToLower?.()\n inUpperZone = nowInUpper\n inLowerZone = nowInLower\n }\n\n const initialScroll = isHorizontal ? target.scrollLeft : target.scrollTop\n const initialAdjusted = Math.max(0, initialScroll - effectiveStartOffsetRef.current)\n updateRenderOffset(initialAdjusted, false, 'scrollElement')\n\n target.addEventListener('scroll', handler, { passive: true })\n teardown = () => target.removeEventListener('scroll', handler)\n }\n\n tryAttach()\n return () => {\n cancelled = true\n teardown?.()\n }\n }, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffset, updateRenderOffset, refsRef])\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { MutableRefObject, RefObject } from 'react';
2
+ import type { ListScrollElementAttachRefs } from './useListScrollElementAttach';
3
+ /**
4
+ * 小程序版 scrollElement 模式:监听外部 scroll-view 的滚动事件驱动 renderOffset,
5
+ * 并通过 createSelectorQuery 测量容器尺寸。
6
+ *
7
+ * 与 H5 版 useListScrollElementAttach 的区别:
8
+ * - 容器尺寸通过 createSelectorQuery 测量(无 ResizeObserver)
9
+ * - 滚动事件通过 TaroElement.addEventListener,格式为 TaroEvent(detail 合并到 target 上)
10
+ * - 若 scroll-view 无 id,自动分配临时 id 供 SelectorQuery 使用
11
+ */
12
+ export declare function useListScrollElementAttachWeapp(enabled: boolean, effectiveScrollElement: RefObject<HTMLElement | null> | null, effectiveStartOffsetRef: MutableRefObject<number>, effectiveStartOffset: number, isHorizontal: boolean, setContainerLength: (v: number) => void, updateRenderOffset: (offset: number, sync?: boolean, source?: string) => void, scrollRefProp: React.MutableRefObject<HTMLElement | null> | undefined, refsRef: RefObject<ListScrollElementAttachRefs>,
13
+ /** 测量未就绪或失败时的容器长度兜底,宜与 initialContainerLength 一致 */
14
+ fallbackContainerLength?: number, selectorQueryScope?: object): void;
@@ -0,0 +1,134 @@
1
+ import { useRef, useEffect } from 'react';
2
+ import { createSelectorQueryScoped } from '../utils.js';
3
+
4
+ /**
5
+ * 小程序版 scrollElement 模式:监听外部 scroll-view 的滚动事件驱动 renderOffset,
6
+ * 并通过 createSelectorQuery 测量容器尺寸。
7
+ *
8
+ * 与 H5 版 useListScrollElementAttach 的区别:
9
+ * - 容器尺寸通过 createSelectorQuery 测量(无 ResizeObserver)
10
+ * - 滚动事件通过 TaroElement.addEventListener,格式为 TaroEvent(detail 合并到 target 上)
11
+ * - 若 scroll-view 无 id,自动分配临时 id 供 SelectorQuery 使用
12
+ */
13
+ function useListScrollElementAttachWeapp(enabled, effectiveScrollElement, effectiveStartOffsetRef, effectiveStartOffset, isHorizontal, setContainerLength, updateRenderOffset, scrollRefProp, refsRef,
14
+ /** 测量未就绪或失败时的容器长度兜底,宜与 initialContainerLength 一致 */
15
+ fallbackContainerLength, selectorQueryScope) {
16
+ const containerLengthRef = useRef(0);
17
+ const autoIdRef = useRef(`_ls_${Math.random().toString(36).slice(2, 9)}`);
18
+ useEffect(() => {
19
+ if (!enabled || !effectiveScrollElement)
20
+ return;
21
+ const el = effectiveScrollElement.current;
22
+ if (!el)
23
+ return;
24
+ if (scrollRefProp)
25
+ scrollRefProp.current = el;
26
+ if (!el.id) {
27
+ el.id = autoIdRef.current;
28
+ }
29
+ const scrollViewId = el.id;
30
+ const measure = () => {
31
+ const query = createSelectorQueryScoped(selectorQueryScope);
32
+ query
33
+ .select(`#${scrollViewId}`)
34
+ .boundingClientRect()
35
+ .exec((res) => {
36
+ const rect = res === null || res === void 0 ? void 0 : res[0];
37
+ if (rect) {
38
+ const measured = isHorizontal ? rect.width : rect.height;
39
+ if (measured > 0) {
40
+ containerLengthRef.current = measured;
41
+ setContainerLength(measured);
42
+ return;
43
+ }
44
+ }
45
+ // 兜底:rect 为空或 measured≤0 时,使用 fallback 避免 containerLengthRef 长期为 0
46
+ if (fallbackContainerLength != null && fallbackContainerLength > 0) {
47
+ containerLengthRef.current = fallbackContainerLength;
48
+ setContainerLength(fallbackContainerLength);
49
+ }
50
+ });
51
+ };
52
+ measure();
53
+ const interval = setInterval(measure, 150);
54
+ return () => clearInterval(interval);
55
+ }, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength, fallbackContainerLength, selectorQueryScope]);
56
+ useEffect(() => {
57
+ if (!enabled || !effectiveScrollElement)
58
+ return;
59
+ let cancelled = false;
60
+ let teardown = null;
61
+ const maxRetries = 20;
62
+ const tryAttach = (retryCount = 0) => {
63
+ if (cancelled)
64
+ return;
65
+ const target = effectiveScrollElement.current;
66
+ if (!target) {
67
+ if (retryCount < maxRetries) {
68
+ setTimeout(() => tryAttach(retryCount + 1), 50);
69
+ }
70
+ return;
71
+ }
72
+ let inUpperZone = true;
73
+ let inLowerZone = false;
74
+ const handler = (e) => {
75
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
76
+ const r = refsRef.current;
77
+ if (!r)
78
+ return;
79
+ const scrollPos = isHorizontal
80
+ ? ((_e = (_b = (_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.scrollLeft) !== null && _b !== void 0 ? _b : (_d = (_c = e === null || e === void 0 ? void 0 : e.mpEvent) === null || _c === void 0 ? void 0 : _c.detail) === null || _d === void 0 ? void 0 : _d.scrollLeft) !== null && _e !== void 0 ? _e : 0)
81
+ : ((_k = (_g = (_f = e === null || e === void 0 ? void 0 : e.target) === null || _f === void 0 ? void 0 : _f.scrollTop) !== null && _g !== void 0 ? _g : (_j = (_h = e === null || e === void 0 ? void 0 : e.mpEvent) === null || _h === void 0 ? void 0 : _h.detail) === null || _j === void 0 ? void 0 : _j.scrollTop) !== null && _k !== void 0 ? _k : 0);
82
+ const startOffset = effectiveStartOffsetRef.current;
83
+ const adjustedPos = scrollPos - startOffset;
84
+ const effectiveAdjusted = Math.max(0, adjustedPos);
85
+ r.scrollCorrection.markUserScrolling();
86
+ updateRenderOffset(effectiveAdjusted, false, 'scrollElement');
87
+ const scrollTop = isHorizontal ? 0 : scrollPos;
88
+ const scrollLeft = isHorizontal ? scrollPos : 0;
89
+ (_l = r.onScroll) === null || _l === void 0 ? void 0 : _l.call(r, { scrollTop, scrollLeft, detail: { scrollTop, scrollLeft } });
90
+ // 兜底:measure 未完成时 containerLengthRef 为 0,用 fallback 参与触顶/触底判断,避免漏触发
91
+ const clientSize = containerLengthRef.current || fallbackContainerLength || 0;
92
+ if (clientSize > 0) {
93
+ const { upper, lower } = r.threshold;
94
+ const innerContentLen = r.listContentLength;
95
+ const nowInUpper = effectiveAdjusted <= upper;
96
+ const nowInLower = innerContentLen > 0 && effectiveAdjusted + clientSize >= innerContentLen - lower;
97
+ if (nowInUpper && !inUpperZone)
98
+ (_m = r.onScrollToUpper) === null || _m === void 0 ? void 0 : _m.call(r);
99
+ if (nowInLower && !inLowerZone)
100
+ (_o = r.onScrollToLower) === null || _o === void 0 ? void 0 : _o.call(r);
101
+ inUpperZone = nowInUpper;
102
+ inLowerZone = nowInLower;
103
+ }
104
+ };
105
+ target.addEventListener('scroll', handler);
106
+ teardown = () => target.removeEventListener('scroll', handler);
107
+ // 初始 renderOffset:weapp 无法直接读 target.scrollTop,需通过 SelectorQuery 查询
108
+ const scrollViewId = target.id || autoIdRef.current;
109
+ if (!target.id)
110
+ target.id = scrollViewId;
111
+ const query = createSelectorQueryScoped(selectorQueryScope);
112
+ query.select(`#${scrollViewId}`).scrollOffset().exec((res) => {
113
+ var _a, _b;
114
+ const info = res === null || res === void 0 ? void 0 : res[0];
115
+ if (info) {
116
+ const scrollTopVal = (_a = info.scrollTop) !== null && _a !== void 0 ? _a : 0;
117
+ const scrollLeftVal = (_b = info.scrollLeft) !== null && _b !== void 0 ? _b : 0;
118
+ const scrollPos = isHorizontal ? scrollLeftVal : scrollTopVal;
119
+ const startOffset = effectiveStartOffsetRef.current;
120
+ const initialAdjusted = Math.max(0, scrollPos - startOffset);
121
+ updateRenderOffset(initialAdjusted, false, 'scrollElement');
122
+ }
123
+ });
124
+ };
125
+ tryAttach();
126
+ return () => {
127
+ cancelled = true;
128
+ teardown === null || teardown === void 0 ? void 0 : teardown();
129
+ };
130
+ }, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffsetRef, effectiveStartOffset, updateRenderOffset, refsRef, fallbackContainerLength, selectorQueryScope]);
131
+ }
132
+
133
+ export { useListScrollElementAttachWeapp };
134
+ //# sourceMappingURL=useListScrollElementAttachWeapp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useListScrollElementAttachWeapp.js","sources":["../../../../src/components/list/hooks/useListScrollElementAttachWeapp.ts"],"sourcesContent":["import { useEffect, useRef } from 'react'\n\nimport { createSelectorQueryScoped } from '../utils'\n\nimport type { MutableRefObject, RefObject } from 'react'\nimport type { ListScrollElementAttachRefs } from './useListScrollElementAttach'\n\n/**\n * 小程序版 scrollElement 模式:监听外部 scroll-view 的滚动事件驱动 renderOffset,\n * 并通过 createSelectorQuery 测量容器尺寸。\n *\n * 与 H5 版 useListScrollElementAttach 的区别:\n * - 容器尺寸通过 createSelectorQuery 测量(无 ResizeObserver)\n * - 滚动事件通过 TaroElement.addEventListener,格式为 TaroEvent(detail 合并到 target 上)\n * - 若 scroll-view 无 id,自动分配临时 id 供 SelectorQuery 使用\n */\nexport function useListScrollElementAttachWeapp(\n enabled: boolean,\n effectiveScrollElement: RefObject<HTMLElement | null> | null,\n effectiveStartOffsetRef: MutableRefObject<number>,\n effectiveStartOffset: number,\n isHorizontal: boolean,\n setContainerLength: (v: number) => void,\n updateRenderOffset: (offset: number, sync?: boolean, source?: string) => void,\n scrollRefProp: React.MutableRefObject<HTMLElement | null> | undefined,\n refsRef: RefObject<ListScrollElementAttachRefs>,\n /** 测量未就绪或失败时的容器长度兜底,宜与 initialContainerLength 一致 */\n fallbackContainerLength?: number,\n selectorQueryScope?: object\n) {\n const containerLengthRef = useRef(0)\n const autoIdRef = useRef(`_ls_${Math.random().toString(36).slice(2, 9)}`)\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n const el = effectiveScrollElement.current as any\n if (!el) return\n if (scrollRefProp) scrollRefProp.current = el\n\n if (!el.id) {\n el.id = autoIdRef.current\n }\n const scrollViewId = el.id\n\n const measure = () => {\n const query = createSelectorQueryScoped(selectorQueryScope)\n query\n .select(`#${scrollViewId}`)\n .boundingClientRect()\n .exec((res) => {\n const rect = res?.[0]\n if (rect) {\n const measured = isHorizontal ? rect.width : rect.height\n if (measured > 0) {\n containerLengthRef.current = measured\n setContainerLength(measured)\n return\n }\n }\n // 兜底:rect 为空或 measured≤0 时,使用 fallback 避免 containerLengthRef 长期为 0\n if (fallbackContainerLength != null && fallbackContainerLength > 0) {\n containerLengthRef.current = fallbackContainerLength\n setContainerLength(fallbackContainerLength)\n }\n })\n }\n\n measure()\n const interval = setInterval(measure, 150)\n return () => clearInterval(interval)\n }, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength, fallbackContainerLength, selectorQueryScope])\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n\n let cancelled = false\n let teardown: (() => void) | null = null\n const maxRetries = 20\n\n const tryAttach = (retryCount = 0) => {\n if (cancelled) return\n const target = effectiveScrollElement.current as any\n if (!target) {\n if (retryCount < maxRetries) {\n setTimeout(() => tryAttach(retryCount + 1), 50)\n }\n return\n }\n\n let inUpperZone = true\n let inLowerZone = false\n\n const handler = (e: any) => {\n const r = refsRef.current\n if (!r) return\n\n const scrollPos = isHorizontal\n ? (e?.target?.scrollLeft ?? e?.mpEvent?.detail?.scrollLeft ?? 0)\n : (e?.target?.scrollTop ?? e?.mpEvent?.detail?.scrollTop ?? 0)\n const startOffset = effectiveStartOffsetRef.current\n const adjustedPos = scrollPos - startOffset\n const effectiveAdjusted = Math.max(0, adjustedPos)\n\n r.scrollCorrection.markUserScrolling()\n updateRenderOffset(effectiveAdjusted, false, 'scrollElement')\n const scrollTop = isHorizontal ? 0 : scrollPos\n const scrollLeft = isHorizontal ? scrollPos : 0\n r.onScroll?.({ scrollTop, scrollLeft, detail: { scrollTop, scrollLeft } })\n\n // 兜底:measure 未完成时 containerLengthRef 为 0,用 fallback 参与触顶/触底判断,避免漏触发\n const clientSize = containerLengthRef.current || fallbackContainerLength || 0\n if (clientSize > 0) {\n const { upper, lower } = r.threshold\n const innerContentLen = r.listContentLength\n const nowInUpper = effectiveAdjusted <= upper\n const nowInLower = innerContentLen > 0 && effectiveAdjusted + clientSize >= innerContentLen - lower\n if (nowInUpper && !inUpperZone) r.onScrollToUpper?.()\n if (nowInLower && !inLowerZone) r.onScrollToLower?.()\n inUpperZone = nowInUpper\n inLowerZone = nowInLower\n }\n }\n\n target.addEventListener('scroll', handler)\n teardown = () => target.removeEventListener('scroll', handler)\n\n // 初始 renderOffset:weapp 无法直接读 target.scrollTop,需通过 SelectorQuery 查询\n const scrollViewId = target.id || autoIdRef.current\n if (!target.id) target.id = scrollViewId\n const query = createSelectorQueryScoped(selectorQueryScope)\n query.select(`#${scrollViewId}`).scrollOffset().exec((res) => {\n const info = res?.[0]\n if (info) {\n const scrollTopVal = info.scrollTop ?? 0\n const scrollLeftVal = info.scrollLeft ?? 0\n const scrollPos = isHorizontal ? scrollLeftVal : scrollTopVal\n const startOffset = effectiveStartOffsetRef.current\n const initialAdjusted = Math.max(0, scrollPos - startOffset)\n updateRenderOffset(initialAdjusted, false, 'scrollElement')\n }\n })\n }\n\n tryAttach()\n return () => {\n cancelled = true\n teardown?.()\n }\n }, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffsetRef, effectiveStartOffset, updateRenderOffset, refsRef, fallbackContainerLength, selectorQueryScope])\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { RefObject } from 'react';
2
+ /**
3
+ * 测量 scrollElement 内 content 节点之前所有兄弟的高度/宽度之和,作为 startOffset。
4
+ * 用于 scrollElement 模式下无 Context/props 时自动计算上方内容高度。
5
+ * - 直接子节点:累加前兄弟尺寸(更稳定)
6
+ * - 非直接子节点:getBoundingClientRect 回退,并 warning 建议传 startOffset
7
+ * - ref 未就绪时自动重试,确保绑定到最外层滚动容器后能正确测量
8
+ */
9
+ export declare function useMeasureStartOffset(scrollElRef: RefObject<HTMLElement | null>, contentRef: RefObject<HTMLElement | null>, options: {
10
+ enabled: boolean;
11
+ isHorizontal?: boolean;
12
+ }): number;