@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
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/components/list/utils.ts"],"sourcesContent":["/**\n * List 组件工具函数\n */\n\n/** 判断是否为微信小程序 */\nexport const isWeapp = process.env.TARO_ENV === 'weapp'\n\n/** 判断是否为支付宝小程序 */\nexport const isAlipay = process.env.TARO_ENV === 'alipay'\n\n/** 判断是否为 H5 */\nexport const isH5 = process.env.TARO_ENV === 'h5'\n\n/** 判断是否为小程序环境(微信/支付宝/百度/京东/头条等) */\nexport const isMiniProgram = isWeapp || isAlipay || process.env.TARO_ENV === 'swan' || process.env.TARO_ENV === 'tt' || process.env.TARO_ENV === 'jd'\n\n/**\n * 是否支持原生 refresher(ScrollView refresher-*)\n * 以各平台 components 为准:weapp/jd/tt 的 ScrollView 有 refresher-enabled 等;harmony-hybrid 的 harmony-definition 中 refresher-* 为 false,走自定义下拉\n */\nexport const supportsNativeRefresher = isMiniProgram\n"],"names":[],"mappings":"AAAA;;AAEG;AAEH;AACa,MAAA,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAEhD;AACa,MAAA,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAEjD;AACa,MAAA,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAE7C;AACO,MAAM,aAAa,GAAG,OAAO,IAAI,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAEjJ;;;AAGG;AACI,MAAM,uBAAuB,GAAG;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/components/list/utils.ts"],"sourcesContent":["/**\n * List 组件工具函数\n */\n\nimport Taro from '@tarojs/taro'\n\n/** 有 scope 则 `query.in(scope)`,否则与原先一致(page / 根) */\nexport function createSelectorQueryScoped (selectorQueryScope?: object) {\n if (selectorQueryScope != null) {\n return Taro.createSelectorQuery().in(selectorQueryScope as any)\n }\n const instance = Taro.getCurrentInstance()\n return instance?.page\n ? Taro.createSelectorQuery().in(instance.page as any)\n : Taro.createSelectorQuery()\n}\n\n/** IO 作用域,缺省为 page */\nexport function getMiniProgramObserverScope (selectorQueryScope?: object) {\n return (selectorQueryScope ?? Taro.getCurrentInstance().page) as any\n}\n\n/** 判断是否为微信小程序 */\nexport const isWeapp = process.env.TARO_ENV === 'weapp'\n\n/** 判断是否为支付宝小程序 */\nexport const isAlipay = process.env.TARO_ENV === 'alipay'\n\n/** 判断是否为 H5 */\nexport const isH5 = process.env.TARO_ENV === 'h5'\n\n/** 判断是否为小程序环境(微信/支付宝/百度/京东/头条等) */\nexport const isMiniProgram = isWeapp || isAlipay || process.env.TARO_ENV === 'swan' || process.env.TARO_ENV === 'tt' || process.env.TARO_ENV === 'jd'\n\n/**\n * 是否支持原生 refresher(ScrollView refresher-*)\n * 以各平台 components 为准:weapp/jd/tt 的 ScrollView 有 refresher-enabled 等;harmony-hybrid 的 harmony-definition 中 refresher-* 为 false,走自定义下拉\n */\nexport const supportsNativeRefresher = isMiniProgram\n"],"names":[],"mappings":";;AAAA;;AAEG;AAIH;AACM,SAAU,yBAAyB,CAAE,kBAA2B,EAAA;AACpE,IAAA,IAAI,kBAAkB,IAAI,IAAI,EAAE;QAC9B,OAAO,IAAI,CAAC,mBAAmB,EAAE,CAAC,EAAE,CAAC,kBAAyB,CAAC;;AAEjE,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,EAAE;AAC1C,IAAA,OAAO,CAAA,QAAQ,KAAA,IAAA,IAAR,QAAQ,KAAR,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,QAAQ,CAAE,IAAI;UACjB,IAAI,CAAC,mBAAmB,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAW;AACpD,UAAE,IAAI,CAAC,mBAAmB,EAAE;AAChC;AAEA;AACM,SAAU,2BAA2B,CAAE,kBAA2B,EAAA;AACtE,IAAA,QAAQ,kBAAkB,KAAlB,IAAA,IAAA,kBAAkB,cAAlB,kBAAkB,GAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC,IAAI;AAC9D;AAEA;AACa,MAAA,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAEhD;AACa,MAAA,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAEjD;AACa,MAAA,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAE7C;AACO,MAAM,aAAa,GAAG,OAAO,IAAI,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAEjJ;;;AAGG;AACI,MAAM,uBAAuB,GAAG;;;;"}
@@ -2,11 +2,11 @@ import Preset from '../preset';
2
2
  declare const _default: import("vue").DefineComponent<{
3
3
  id: StringConstructor;
4
4
  height: {
5
- type: (StringConstructor | NumberConstructor)[];
5
+ type: (NumberConstructor | StringConstructor)[];
6
6
  required: true;
7
7
  };
8
8
  width: {
9
- type: (StringConstructor | NumberConstructor)[];
9
+ type: (NumberConstructor | StringConstructor)[];
10
10
  required: true;
11
11
  };
12
12
  item: {
@@ -93,11 +93,11 @@ declare const _default: import("vue").DefineComponent<{
93
93
  instance: import("vue").CreateComponentPublicInstance<Readonly<import("vue").ExtractPropTypes<{
94
94
  id: StringConstructor;
95
95
  height: {
96
- type: (StringConstructor | NumberConstructor)[];
96
+ type: (NumberConstructor | StringConstructor)[];
97
97
  required: true;
98
98
  };
99
99
  width: {
100
- type: (StringConstructor | NumberConstructor)[];
100
+ type: (NumberConstructor | StringConstructor)[];
101
101
  required: true;
102
102
  };
103
103
  item: {
@@ -181,11 +181,11 @@ declare const _default: import("vue").DefineComponent<{
181
181
  }>> & {}, {}, {}, {}, import("vue").MethodOptions, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, Readonly<import("vue").ExtractPropTypes<{
182
182
  id: StringConstructor;
183
183
  height: {
184
- type: (StringConstructor | NumberConstructor)[];
184
+ type: (NumberConstructor | StringConstructor)[];
185
185
  required: true;
186
186
  };
187
187
  width: {
188
- type: (StringConstructor | NumberConstructor)[];
188
+ type: (NumberConstructor | StringConstructor)[];
189
189
  required: true;
190
190
  };
191
191
  item: {
@@ -276,11 +276,11 @@ declare const _default: import("vue").DefineComponent<{
276
276
  }, Readonly<import("vue").ExtractPropTypes<{
277
277
  id: StringConstructor;
278
278
  height: {
279
- type: (StringConstructor | NumberConstructor)[];
279
+ type: (NumberConstructor | StringConstructor)[];
280
280
  required: true;
281
281
  };
282
282
  width: {
283
- type: (StringConstructor | NumberConstructor)[];
283
+ type: (NumberConstructor | StringConstructor)[];
284
284
  required: true;
285
285
  };
286
286
  item: {
@@ -394,11 +394,11 @@ declare const _default: import("vue").DefineComponent<{
394
394
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
395
395
  id: StringConstructor;
396
396
  height: {
397
- type: (StringConstructor | NumberConstructor)[];
397
+ type: (NumberConstructor | StringConstructor)[];
398
398
  required: true;
399
399
  };
400
400
  width: {
401
- type: (StringConstructor | NumberConstructor)[];
401
+ type: (NumberConstructor | StringConstructor)[];
402
402
  required: true;
403
403
  };
404
404
  item: {
@@ -2,11 +2,11 @@ import Preset from '../preset';
2
2
  declare const _default: import("vue").DefineComponent<{
3
3
  id: StringConstructor;
4
4
  height: {
5
- type: (StringConstructor | NumberConstructor)[];
5
+ type: (NumberConstructor | StringConstructor)[];
6
6
  required: true;
7
7
  };
8
8
  width: {
9
- type: (StringConstructor | NumberConstructor)[];
9
+ type: (NumberConstructor | StringConstructor)[];
10
10
  required: true;
11
11
  };
12
12
  column: NumberConstructor;
@@ -87,11 +87,11 @@ declare const _default: import("vue").DefineComponent<{
87
87
  instance: import("vue").CreateComponentPublicInstance<Readonly<import("vue").ExtractPropTypes<{
88
88
  id: StringConstructor;
89
89
  height: {
90
- type: (StringConstructor | NumberConstructor)[];
90
+ type: (NumberConstructor | StringConstructor)[];
91
91
  required: true;
92
92
  };
93
93
  width: {
94
- type: (StringConstructor | NumberConstructor)[];
94
+ type: (NumberConstructor | StringConstructor)[];
95
95
  required: true;
96
96
  };
97
97
  column: NumberConstructor;
@@ -169,11 +169,11 @@ declare const _default: import("vue").DefineComponent<{
169
169
  }>> & {}, {}, {}, {}, import("vue").MethodOptions, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, Readonly<import("vue").ExtractPropTypes<{
170
170
  id: StringConstructor;
171
171
  height: {
172
- type: (StringConstructor | NumberConstructor)[];
172
+ type: (NumberConstructor | StringConstructor)[];
173
173
  required: true;
174
174
  };
175
175
  width: {
176
- type: (StringConstructor | NumberConstructor)[];
176
+ type: (NumberConstructor | StringConstructor)[];
177
177
  required: true;
178
178
  };
179
179
  column: NumberConstructor;
@@ -258,11 +258,11 @@ declare const _default: import("vue").DefineComponent<{
258
258
  }, Readonly<import("vue").ExtractPropTypes<{
259
259
  id: StringConstructor;
260
260
  height: {
261
- type: (StringConstructor | NumberConstructor)[];
261
+ type: (NumberConstructor | StringConstructor)[];
262
262
  required: true;
263
263
  };
264
264
  width: {
265
- type: (StringConstructor | NumberConstructor)[];
265
+ type: (NumberConstructor | StringConstructor)[];
266
266
  required: true;
267
267
  };
268
268
  column: NumberConstructor;
@@ -368,11 +368,11 @@ declare const _default: import("vue").DefineComponent<{
368
368
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
369
369
  id: StringConstructor;
370
370
  height: {
371
- type: (StringConstructor | NumberConstructor)[];
371
+ type: (NumberConstructor | StringConstructor)[];
372
372
  required: true;
373
373
  };
374
374
  width: {
375
- type: (StringConstructor | NumberConstructor)[];
375
+ type: (NumberConstructor | StringConstructor)[];
376
376
  required: true;
377
377
  };
378
378
  column: NumberConstructor;
@@ -35,13 +35,15 @@ function FlowItemContainer(_a) {
35
35
  const itemStyle = useMemo(() => {
36
36
  const baseStyle = {
37
37
  width: '100%',
38
- minHeight: node.section.defaultSize,
38
+ position: 'absolute',
39
+ top: 0,
40
+ left: 0,
41
+ transform: `translate3d(0px, ${top$}px, 0px)`,
39
42
  };
40
43
  if (!layouted$) {
41
- return baseStyle;
44
+ return Object.assign(Object.assign({}, baseStyle), { minHeight: node.section.defaultSize });
42
45
  }
43
- Reflect.deleteProperty(baseStyle, 'minHeight');
44
- return Object.assign(Object.assign({}, baseStyle), { height: height$, transition: 'transform 20ms cubic-bezier(0.075, 0.82, 0.165, 1)', willChange: 'transform', position: 'absolute', top: 0, left: 0, transform: `translate3d(0px, ${top$}px, 0px)` });
46
+ return Object.assign(Object.assign({}, baseStyle), { height: height$ });
45
47
  }, [top$, layouted$, height$]);
46
48
  useEffect(() => {
47
49
  let observer;
@@ -1 +1 @@
1
- {"version":3,"file":"flow-item.js","sources":["../../../src/components/water-flow/flow-item.ts"],"sourcesContent":["import { View } from '@tarojs/components'\nimport {\n type CSSProperties,\n type PropsWithChildren,\n createContext,\n createElement,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react'\n\nimport { Node, NodeEvents } from './node'\nimport { useMemoizedFn } from './use-memoized-fn'\nimport { useObservedAttr } from './use-observed-attr'\nimport { isWeb } from './utils'\n\nimport type { FlowItemContainerProps } from './interface'\n\nconst FlowItemContext = createContext<{ node: Node }>(Object.create(null))\nexport const useFlowItemPositioner = () => {\n const nodeModel = useContext(FlowItemContext).node\n const width$ = useObservedAttr(nodeModel, 'width')\n const height$ = useObservedAttr(nodeModel, 'height')\n const top$ = useObservedAttr(nodeModel, 'top')\n const scrollTop$ = useObservedAttr(nodeModel, 'scrollTop')\n\n return {\n resize: useMemoizedFn(() => {\n if (!isWeb()) {\n nodeModel.pub(NodeEvents.Resize)\n }\n }),\n top: top$,\n scrollTop: scrollTop$,\n width: width$,\n height: height$,\n }\n}\n\nexport function FlowItemContainer({\n children,\n ...props\n}: PropsWithChildren<FlowItemContainerProps>) {\n const { node } = props\n const layouted$ = useObservedAttr(node, 'layouted')\n const top$ = useObservedAttr(node, 'top')\n const height$ = useObservedAttr(node, 'height')\n const refFlowItem = useRef<HTMLElement>()\n\n const itemStyle: CSSProperties = useMemo(() => {\n const baseStyle: CSSProperties = {\n width: '100%',\n minHeight: node.section.defaultSize,\n }\n if (!layouted$) {\n return baseStyle\n }\n Reflect.deleteProperty(baseStyle, 'minHeight')\n return {\n ...baseStyle,\n height: height$,\n transition: 'transform 20ms cubic-bezier(0.075, 0.82, 0.165, 1)',\n willChange: 'transform',\n position: 'absolute',\n top: 0,\n left: 0,\n transform: `translate3d(0px, ${top$}px, 0px)`,\n }\n }, [top$, layouted$, height$])\n\n useEffect(() => {\n let observer: ResizeObserver\n if (isWeb() && typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver(() => {\n node.pub(NodeEvents.Resize)\n })\n observer.observe(refFlowItem.current!)\n }\n return () => {\n if (observer) {\n observer.disconnect()\n }\n }\n }, [node])\n\n useLayoutEffect(() => {\n node.measure()\n }, [node])\n\n return createElement(\n View,\n { style: itemStyle, key: node.id },\n createElement(\n View,\n { id: node.id, ref: refFlowItem },\n createElement(FlowItemContext.Provider, { value: { node } }, children)\n )\n )\n}\n\nexport function FlowItem(props: PropsWithChildren) {\n return props.children\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flow-item.js","sources":["../../../src/components/water-flow/flow-item.ts"],"sourcesContent":["import { View } from '@tarojs/components'\nimport {\n type CSSProperties,\n type PropsWithChildren,\n createContext,\n createElement,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react'\n\nimport { Node, NodeEvents } from './node'\nimport { useMemoizedFn } from './use-memoized-fn'\nimport { useObservedAttr } from './use-observed-attr'\nimport { isWeb } from './utils'\n\nimport type { FlowItemContainerProps } from './interface'\n\nconst FlowItemContext = createContext<{ node: Node }>(Object.create(null))\nexport const useFlowItemPositioner = () => {\n const nodeModel = useContext(FlowItemContext).node\n const width$ = useObservedAttr(nodeModel, 'width')\n const height$ = useObservedAttr(nodeModel, 'height')\n const top$ = useObservedAttr(nodeModel, 'top')\n const scrollTop$ = useObservedAttr(nodeModel, 'scrollTop')\n\n return {\n resize: useMemoizedFn(() => {\n if (!isWeb()) {\n nodeModel.pub(NodeEvents.Resize)\n }\n }),\n top: top$,\n scrollTop: scrollTop$,\n width: width$,\n height: height$,\n }\n}\n\nexport function FlowItemContainer({\n children,\n ...props\n}: PropsWithChildren<FlowItemContainerProps>) {\n const { node } = props\n const layouted$ = useObservedAttr(node, 'layouted')\n const top$ = useObservedAttr(node, 'top')\n const height$ = useObservedAttr(node, 'height')\n const refFlowItem = useRef<HTMLElement>()\n\n const itemStyle: CSSProperties = useMemo(() => {\n const baseStyle: CSSProperties = {\n width: '100%',\n position: 'absolute',\n top: 0,\n left: 0,\n transform: `translate3d(0px, ${top$}px, 0px)`,\n }\n if (!layouted$) {\n return {\n ...baseStyle,\n minHeight: node.section.defaultSize,\n }\n }\n return {\n ...baseStyle,\n height: height$,\n }\n }, [top$, layouted$, height$])\n\n useEffect(() => {\n let observer: ResizeObserver\n if (isWeb() && typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver(() => {\n node.pub(NodeEvents.Resize)\n })\n observer.observe(refFlowItem.current!)\n }\n return () => {\n if (observer) {\n observer.disconnect()\n }\n }\n }, [node])\n\n useLayoutEffect(() => {\n node.measure()\n }, [node])\n\n return createElement(\n View,\n { style: itemStyle, key: node.id },\n createElement(\n View,\n { id: node.id, ref: refFlowItem },\n createElement(FlowItemContext.Provider, { value: { node } }, children)\n )\n )\n}\n\nexport function FlowItem(props: PropsWithChildren) {\n return props.children\n}\n"],"names":[],"mappings":"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"}
@@ -58,7 +58,7 @@ function FlowSection(_a) {
58
58
  return createElement(FlowItemContainer, columnProps, childNode);
59
59
  }));
60
60
  });
61
- }, [children, layouted$, section.columnMap, renderRange$, id]);
61
+ }, [children, layouted$, section.columnMap, renderRange$]);
62
62
  return createElement(View, { style: sectionStyle, className, id: id !== null && id !== void 0 ? id : section.id }, columns);
63
63
  }
64
64
 
@@ -1 +1 @@
1
- {"version":3,"file":"flow-section.js","sources":["../../../src/components/water-flow/flow-section.ts"],"sourcesContent":["import { View } from '@tarojs/components'\nimport {\n type CSSProperties,\n type PropsWithChildren,\n Children,\n createElement,\n useMemo,\n} from 'react'\n\nimport { FlowItemContainer } from './flow-item'\nimport { Section } from './section'\nimport { useObservedAttr } from './use-observed-attr'\n\nimport type { FlowSectionProps } from './interface'\n\nexport interface _FlowSectionProps extends FlowSectionProps {\n section: Section\n}\n\nexport function FlowSection({\n children,\n ...props\n}: PropsWithChildren<FlowSectionProps>) {\n const {\n id,\n className,\n style,\n section,\n rowGap = 0,\n columnGap = 0,\n } = props as _FlowSectionProps\n const layouted$ = useObservedAttr(section, 'layouted')\n const height$ = useObservedAttr(section, 'height')\n const renderRange$ = useObservedAttr(section, 'renderRange')\n const scrollTop$ = useObservedAttr(section, 'scrollTop')\n\n const sectionStyle: CSSProperties = useMemo(() => {\n const baseStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'row',\n width: '100%',\n height: height$,\n gap: columnGap,\n visibility: layouted$ ? 'visible' : 'hidden',\n ...style,\n }\n\n if (!layouted$) {\n return baseStyle\n }\n\n return {\n ...baseStyle,\n position: 'absolute',\n top: 0,\n transform: `translate3d(0px, ${scrollTop$}px, 0px)`,\n left: 0,\n }\n }, [height$, style, layouted$, scrollTop$, columnGap])\n\n const columns = useMemo(() => {\n const childNodes = Children.toArray(children)\n const columnStyle: CSSProperties = {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n gap: rowGap,\n flex: 1,\n }\n /** 已经完成布局计算,使用虚拟滚动 */\n if (layouted$) {\n return renderRange$.map(([startIndex, endIndex], colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n {\n style: columnStyle,\n id: columnId,\n key: columnId,\n },\n section.columnMap[colIndex]\n .slice(startIndex, endIndex + 1)\n .map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }\n\n return section.columnMap.map((column, colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n { style: columnStyle, id: columnId, key: columnId },\n column.map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }, [children, layouted$, section.columnMap, renderRange$, id])\n\n return createElement(\n View,\n { style: sectionStyle, className, id: id ?? section.id },\n columns\n )\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flow-section.js","sources":["../../../src/components/water-flow/flow-section.ts"],"sourcesContent":["import { View } from '@tarojs/components'\nimport {\n type CSSProperties,\n type PropsWithChildren,\n Children,\n createElement,\n useMemo,\n} from 'react'\n\nimport { FlowItemContainer } from './flow-item'\nimport { Section } from './section'\nimport { useObservedAttr } from './use-observed-attr'\n\nimport type { FlowSectionProps } from './interface'\n\nexport interface _FlowSectionProps extends FlowSectionProps {\n section: Section\n}\n\nexport function FlowSection({\n children,\n ...props\n}: PropsWithChildren<FlowSectionProps>) {\n const {\n id,\n className,\n style,\n section,\n rowGap = 0,\n columnGap = 0,\n } = props as _FlowSectionProps\n const layouted$ = useObservedAttr(section, 'layouted')\n const height$ = useObservedAttr(section, 'height')\n const renderRange$ = useObservedAttr(section, 'renderRange')\n const scrollTop$ = useObservedAttr(section, 'scrollTop')\n\n const sectionStyle: CSSProperties = useMemo(() => {\n const baseStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'row',\n width: '100%',\n height: height$,\n gap: columnGap,\n visibility: layouted$ ? 'visible' : 'hidden',\n ...style,\n }\n\n if (!layouted$) {\n return baseStyle\n }\n\n return {\n ...baseStyle,\n position: 'absolute',\n top: 0,\n transform: `translate3d(0px, ${scrollTop$}px, 0px)`,\n left: 0,\n }\n }, [height$, style, layouted$, scrollTop$, columnGap])\n\n const columns = useMemo(() => {\n const childNodes = Children.toArray(children)\n const columnStyle: CSSProperties = {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n gap: rowGap,\n flex: 1,\n }\n /** 已经完成布局计算,使用虚拟滚动 */\n if (layouted$) {\n return renderRange$.map(([startIndex, endIndex], colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n {\n style: columnStyle,\n id: columnId,\n key: columnId,\n },\n section.columnMap[colIndex]\n .slice(startIndex, endIndex + 1)\n .map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }\n\n return section.columnMap.map((column, colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n { style: columnStyle, id: columnId, key: columnId },\n column.map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }, [children, layouted$, section.columnMap, renderRange$])\n\n return createElement(\n View,\n { style: sectionStyle, className, id: id ?? section.id },\n columns\n )\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  export { FlowItem, useFlowItemPositioner } from './flow-item';
2
2
  export { FlowSection } from './flow-section';
3
- export type { FlowSectionProps, WaterFlowProps } from './interface';
3
+ export type { FlowSectionProps, WaterFlowProps, WaterFlowRef } from './interface';
4
4
  export { WaterFlow } from './water-flow';
@@ -1,12 +1,12 @@
1
1
  import { ScrollViewProps } from '@tarojs/components';
2
2
  import { Node } from './node';
3
- import type { CSSProperties } from 'react';
3
+ import type { CSSProperties, RefObject } from 'react';
4
4
  export interface BaseProps {
5
5
  id?: string;
6
6
  className?: string;
7
7
  style?: CSSProperties;
8
8
  }
9
- export interface WaterFlowProps extends Omit<ScrollViewProps, 'cacheExtent' | 'upperThreshold' | 'lowerThreshold' | 'style'>, Pick<BaseProps, 'style'> {
9
+ export interface WaterFlowProps extends Omit<ScrollViewProps, 'cacheExtent' | 'upperThreshold' | 'lowerThreshold' | 'style' | 'type'>, Pick<BaseProps, 'style'> {
10
10
  /**
11
11
  * 距顶部多少个FlowItem时,触发 scrolltoupper 事件
12
12
  * @default 0
@@ -22,6 +22,22 @@ export interface WaterFlowProps extends Omit<ScrollViewProps, 'cacheExtent' | 'u
22
22
  * @default 50
23
23
  */
24
24
  cacheCount?: number;
25
+ /** 是否嵌套模式,与 plato 对齐;true=使用父级滚动,需配合 scrollElement 或 Context;不传或 false=default */
26
+ nestedScroll?: boolean;
27
+ /** 自定义滚动容器 ref,nestedScroll 模式下从 props 或 Context 获取 */
28
+ scrollElement?: RefObject<HTMLElement | null>;
29
+ /** WaterFlow 内容在滚动容器中的起始偏移(上方有其他内容时使用) */
30
+ startOffset?: number;
31
+ /** 可视区高度,scrollElement 模式下可选,不传则从 scrollElement.clientHeight 获取 */
32
+ containerHeight?: number;
33
+ /** 瀑布流内容高度变化时回调,便于 List 动高联动(避免底部空白) */
34
+ onScrollHeightChange?: (height: number) => void;
35
+ /** scrollIntoView 滚动完成后回调,便于父组件清空 scrollIntoView 以支持重复点击同一目标 */
36
+ onScrollIntoViewComplete?: () => void;
37
+ }
38
+ /** WaterFlow ref 类型,current 指向内容容器,用于 IntersectionObserver root、SelectorQuery.in 等 */
39
+ export interface WaterFlowRef {
40
+ current: HTMLElement | null;
25
41
  }
26
42
  export interface FlowSectionProps extends BaseProps {
27
43
  /**
@@ -2,7 +2,10 @@ import { Node } from './node';
2
2
  import { Section } from './section';
3
3
  import { StatefulEventBus } from './stateful-event-bus';
4
4
  import type { BaseProps, ScrollDirection, Size, WaterFlowProps } from './interface';
5
- export type RootProps = Pick<WaterFlowProps, 'cacheCount' | 'lowerThresholdCount' | 'upperThresholdCount'> & Required<Pick<BaseProps, 'id'>>;
5
+ export type RootProps = Pick<WaterFlowProps, 'cacheCount' | 'lowerThresholdCount' | 'upperThresholdCount'> & Required<Pick<BaseProps, 'id'>> & {
6
+ /** scrollElement 模式下为 true,不测量自有容器;此时需布局全部 section 以展开完整高度 */
7
+ skipContainerMeasure?: boolean;
8
+ };
6
9
  type RootState = {
7
10
  /** 是否在滚动中 */
8
11
  isScrolling: boolean;
@@ -52,9 +55,17 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
52
55
  */
53
56
  sections: Section[];
54
57
  /**
55
- * 设置预加载的 Item 条数。
58
+ * 设置预加载的 Item 条数(与 props.cacheCount 一致,收敛目标)。
56
59
  */
57
60
  cacheCount: number;
61
+ /**
62
+ * Node 层向上(列索引减小方向)预缓存条数,可与 cacheCount 不同(快速滑动单边放大)。
63
+ */
64
+ nodeCacheBackward: number;
65
+ /**
66
+ * Node 层向下(列索引增大方向)预缓存条数。
67
+ */
68
+ nodeCacheForward: number;
58
69
  upperThresholdCount: number;
59
70
  lowerThresholdCount: number;
60
71
  /**
@@ -65,6 +76,14 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
65
76
  * 触发滚动阈值对应的 scrollTop 值
66
77
  */
67
78
  lowerThresholdScrollTop: number;
79
+ /** scrollElement 模式下为 true,需布局全部 section 以展开完整高度供父容器滚动 */
80
+ skipContainerMeasure: boolean;
81
+ /** 当前是否处于触顶区域;初始为 true(起始在顶部),只有从 false→true 时才触发事件 */
82
+ private _inUpperZone;
83
+ /** 当前是否处于触底区域;初始为 false */
84
+ private _inLowerZone;
85
+ /** scrollHeight 更新防抖(raf),减轻 pushNodes 后测量前后的高度跳变 */
86
+ private _scrollHeightRafId;
68
87
  constructor(props: RootProps);
69
88
  /**
70
89
  * 设置订阅事件
@@ -94,8 +113,15 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
94
113
  /**
95
114
  * 处理滚动到阈值的情况
96
115
  * 检测当前滚动位置是否达到了上下阈值,并触发相应的事件
116
+ * scrollElement 模式:scrollOffset 为内容内偏移(scrollTop - startOffset),upper/lowerThresholdScrollTop 基于本组件内容计算,触顶/触底以本 WaterFlow 内容为基准
97
117
  */
98
118
  private handleReachThreshold;
119
+ /**
120
+ * 列表追加并完成 finalize 后调用:重置触底边沿状态(_inLowerZone),
121
+ * 使用户仍在底部时下一次滚动能再次触发 onScrollToLower,而不必先上滑再下滑。
122
+ * 不在此处同步调用 handleReachThreshold,避免仍在底部时立刻连发触底(与误触区分)。
123
+ */
124
+ resetLowerReachEdgeAfterContentChange(): void;
99
125
  /**
100
126
  * 容器的滚动上边界
101
127
  */
@@ -113,9 +139,10 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
113
139
  */
114
140
  get sectionRange(): number[][];
115
141
  /**
116
- * 计算滚动高度
142
+ * 更新总滚动高度(各 Section 累计)。
143
+ * @param immediate true 时跳过 raf 防抖(如 finalizePushNodesStateIfNeeded),避免高度滞后引起跳动
117
144
  */
118
- updateScrollHeight(): void;
145
+ updateScrollHeight(immediate?: boolean): void;
119
146
  /**
120
147
  * 注册分组
121
148
  */
@@ -132,6 +159,10 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
132
159
  * 查找节点
133
160
  */
134
161
  findNode(id: string): Node;
162
+ /**
163
+ * 设置 Node 层上下方向预缓存条数,并刷新可见分组内的列渲染区间。
164
+ */
165
+ setNodeCacheRange(backward: number, forward: number): void;
135
166
  /**
136
167
  * 获取分组渲染区间
137
168
  */
@@ -1,3 +1,4 @@
1
+ import { cancelAnimationFrame, requestAnimationFrame } from '@tarojs/runtime';
1
2
  import { nextTick } from '@tarojs/taro';
2
3
  import '../../utils/index.js';
3
4
  import { StatefulEventBus } from './stateful-event-bus.js';
@@ -18,7 +19,7 @@ const RootEvents = {
18
19
  */
19
20
  class Root extends StatefulEventBus {
20
21
  constructor(props) {
21
- const { id, cacheCount, lowerThresholdCount, upperThresholdCount } = props;
22
+ const { id, cacheCount, lowerThresholdCount, upperThresholdCount, skipContainerMeasure } = props;
22
23
  super({
23
24
  isScrolling: false,
24
25
  scrollOffset: 0,
@@ -43,9 +44,17 @@ class Root extends StatefulEventBus {
43
44
  */
44
45
  this.sections = [];
45
46
  /**
46
- * 设置预加载的 Item 条数。
47
+ * 设置预加载的 Item 条数(与 props.cacheCount 一致,收敛目标)。
47
48
  */
48
49
  this.cacheCount = 1;
50
+ /**
51
+ * Node 层向上(列索引减小方向)预缓存条数,可与 cacheCount 不同(快速滑动单边放大)。
52
+ */
53
+ this.nodeCacheBackward = 1;
54
+ /**
55
+ * Node 层向下(列索引增大方向)预缓存条数。
56
+ */
57
+ this.nodeCacheForward = 1;
49
58
  this.upperThresholdCount = 0;
50
59
  this.lowerThresholdCount = 0;
51
60
  /**
@@ -56,48 +65,56 @@ class Root extends StatefulEventBus {
56
65
  * 触发滚动阈值对应的 scrollTop 值
57
66
  */
58
67
  this.lowerThresholdScrollTop = Infinity;
68
+ /** scrollElement 模式下为 true,需布局全部 section 以展开完整高度供父容器滚动 */
69
+ this.skipContainerMeasure = false;
70
+ /** 当前是否处于触顶区域;初始为 true(起始在顶部),只有从 false→true 时才触发事件 */
71
+ this._inUpperZone = true;
72
+ /** 当前是否处于触底区域;初始为 false */
73
+ this._inLowerZone = false;
74
+ /** scrollHeight 更新防抖(raf),减轻 pushNodes 后测量前后的高度跳变 */
75
+ this._scrollHeightRafId = null;
59
76
  Object.assign(this, {
60
77
  id,
61
78
  cacheCount,
62
79
  lowerThresholdCount,
63
80
  upperThresholdCount,
81
+ skipContainerMeasure: !!skipContainerMeasure,
64
82
  });
83
+ this.nodeCacheBackward = cacheCount;
84
+ this.nodeCacheForward = cacheCount;
65
85
  this.setupSubscriptions();
66
- getRectSizeSync(`#${id}`, 100).then(({ width = windowWidth, height = windowHeight }) => {
67
- this.setStateIn('containerSize', {
68
- width,
69
- height,
86
+ if (!skipContainerMeasure) {
87
+ getRectSizeSync(`#${id}`, 100).then(({ width = windowWidth, height = windowHeight }) => {
88
+ this.setStateIn('containerSize', {
89
+ width,
90
+ height,
91
+ });
70
92
  });
71
- });
93
+ }
72
94
  this.renderInitialLayout();
73
95
  }
74
96
  /**
75
97
  * 设置订阅事件
76
98
  */
77
99
  setupSubscriptions() {
78
- /**
79
- * 滚动过程中计算渲染的分组区间
80
- * 滚动过程中分组的最大高度会发生更新,可以在这时计算滚动高度
81
- */
82
- this.sub('scrollOffset', () => {
83
- this.setStateIn('renderRange', this.getSectionRenderRange());
84
- this.handleReachThreshold();
85
- if (this.getState().scrollDirection === 'forward') {
86
- this.updateScrollHeight();
87
- }
88
- });
100
+ /** 滚动:先更新触底阈值,再判触顶/触底并更新分组与总高度,避免同一帧内沿用无效阈值。 */
89
101
  this.sub('scrollOffset', () => {
90
102
  const sectionSize = this.sections.length;
91
103
  const lastSection = this.sections[sectionSize - 1];
92
- // 最后一个分组的每一列最后一行都已经完成了布局计算,那么这个时候的总高度应该是准确的
93
- if (lastSection.columnMap.every((column) => column[column.length - 1].getState().layouted)) {
104
+ if (lastSection === null || lastSection === void 0 ? void 0 : lastSection.columnMap.every((column) => { var _a; return (_a = column[column.length - 1]) === null || _a === void 0 ? void 0 : _a.getState().layouted; })) {
94
105
  this.setLowerThresholdScrollTop();
95
106
  }
107
+ this.setStateIn('renderRange', this.getSectionRenderRange());
108
+ this.handleReachThreshold();
109
+ this.updateScrollHeight();
96
110
  });
97
111
  this.sub(RootEvents.AllSectionsLayouted, () => {
112
+ this.updateScrollHeight();
98
113
  this.setUpperThresholdScrollTop();
114
+ this.setLowerThresholdScrollTop();
99
115
  });
100
116
  this.sub(RootEvents.Resize, () => {
117
+ this.updateScrollHeight();
101
118
  this.setUpperThresholdScrollTop();
102
119
  this.setLowerThresholdScrollTop();
103
120
  });
@@ -122,8 +139,10 @@ class Root extends StatefulEventBus {
122
139
  const section = this.sections[i];
123
140
  section.layoutedSignal.promise.then(() => {
124
141
  this.setStateIn('renderRange', [0, i + 1 > sectionSize ? sectionSize - 1 : i + 1]);
125
- // 容器可视区域已经填满了,没必要再继续
126
- if (section.getState().scrollTop > this.getState().containerSize.height) {
142
+ // skipContainerMeasure(nestedScroll 模式):需布局全部 section,使 scrollHeight 展开供父容器滚动
143
+ // default 模式:容器可视区域已填满则提前终止,减少首屏渲染
144
+ if (!this.skipContainerMeasure &&
145
+ section.getState().scrollTop > this.getState().containerSize.height) {
127
146
  this.pub(RootEvents.InitialRenderCompleted, section);
128
147
  return;
129
148
  }
@@ -189,8 +208,14 @@ class Root extends StatefulEventBus {
189
208
  * 当距底部还有 lowerThresholdCount 个 FlowItem 时的 scrollTop 值
190
209
  */
191
210
  setLowerThresholdScrollTop() {
192
- if (this.lowerThresholdCount === 0) {
193
- this.lowerThresholdScrollTop = this.getState().scrollHeight - this.getState().containerSize.height;
211
+ // setUpperThresholdScrollTop 一致:0 或 undefined 时用「内容底 - 容器高」作为触底阈值
212
+ if (!this.lowerThresholdCount) {
213
+ // 必须用 sectionRange 实时计算,避免依赖可能未更新的 scrollHeight 状态
214
+ const range = this.sectionRange;
215
+ const totalHeight = range.length > 0 ? range[range.length - 1][1] : 0;
216
+ // 触底判定:scrollOffset + containerSize.height >= lowerThresholdScrollTop
217
+ // 须存内容底边 totalHeight(H)。若误存 H-h,则顶部时 h 与 H-h 比较,当 2h>=H 会恒判为在触底区,误触 onScrollToLower。
218
+ this.lowerThresholdScrollTop = totalHeight;
194
219
  return 0;
195
220
  }
196
221
  const sectionSize = this.sections.length;
@@ -238,20 +263,26 @@ class Root extends StatefulEventBus {
238
263
  /**
239
264
  * 处理滚动到阈值的情况
240
265
  * 检测当前滚动位置是否达到了上下阈值,并触发相应的事件
266
+ * scrollElement 模式:scrollOffset 为内容内偏移(scrollTop - startOffset),upper/lowerThresholdScrollTop 基于本组件内容计算,触顶/触底以本 WaterFlow 内容为基准
241
267
  */
242
268
  handleReachThreshold() {
243
- const { upperThresholdScrollTop } = this;
244
- const { scrollOffset, scrollDirection, containerSize } = this.getState();
245
- if (scrollDirection === 'backward' &&
246
- this.upperThresholdScrollTop !== -Infinity &&
247
- scrollOffset <= upperThresholdScrollTop) {
269
+ const { scrollOffset, containerSize } = this.getState();
270
+ const inUpper = this.upperThresholdScrollTop !== -Infinity && scrollOffset <= this.upperThresholdScrollTop;
271
+ const inLower = this.lowerThresholdScrollTop !== Infinity && scrollOffset + containerSize.height >= this.lowerThresholdScrollTop;
272
+ if (inUpper && !this._inUpperZone)
248
273
  this.pub(RootEvents.ReachUpperThreshold);
249
- }
250
- if (scrollDirection === 'forward' &&
251
- this.lowerThresholdCount !== Infinity &&
252
- scrollOffset + containerSize.height >= this.lowerThresholdScrollTop) {
274
+ if (inLower && !this._inLowerZone)
253
275
  this.pub(RootEvents.ReachLowerThreshold);
254
- }
276
+ this._inUpperZone = inUpper;
277
+ this._inLowerZone = inLower;
278
+ }
279
+ /**
280
+ * 列表追加并完成 finalize 后调用:重置触底边沿状态(_inLowerZone),
281
+ * 使用户仍在底部时下一次滚动能再次触发 onScrollToLower,而不必先上滑再下滑。
282
+ * 不在此处同步调用 handleReachThreshold,避免仍在底部时立刻连发触底(与误触区分)。
283
+ */
284
+ resetLowerReachEdgeAfterContentChange() {
285
+ this._inLowerZone = false;
255
286
  }
256
287
  /**
257
288
  * 容器的滚动上边界
@@ -273,21 +304,44 @@ class Root extends StatefulEventBus {
273
304
  * @returns [number,number][]
274
305
  */
275
306
  get sectionRange() {
307
+ var _a;
276
308
  const length = this.sections.length;
277
309
  if (length === 0)
278
310
  return [];
279
311
  const range = Array.from({ length }, () => [0, this.sections[0].maxColumnHeight]);
280
312
  for (let i = 1; i < length; i++) {
281
313
  const previous = range[i - 1];
282
- range[i] = [previous[1], previous[1] + this.sections[i].maxColumnHeight];
314
+ const prevSection = this.sections[i - 1];
315
+ const gap = (_a = prevSection.rowGap) !== null && _a !== void 0 ? _a : 0;
316
+ range[i] = [previous[1] + gap, previous[1] + gap + this.sections[i].maxColumnHeight];
283
317
  }
284
318
  return range;
285
319
  }
286
320
  /**
287
- * 计算滚动高度
321
+ * 更新总滚动高度(各 Section 累计)。
322
+ * @param immediate true 时跳过 raf 防抖(如 finalizePushNodesStateIfNeeded),避免高度滞后引起跳动
288
323
  */
289
- updateScrollHeight() {
290
- this.setStateIn('scrollHeight', this.sectionRange[this.sectionRange.length - 1][1]);
324
+ updateScrollHeight(immediate = false) {
325
+ const flush = () => {
326
+ var _a, _b;
327
+ const next = (_b = (_a = this.sectionRange[this.sectionRange.length - 1]) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : 0;
328
+ this.setStateIn('scrollHeight', next);
329
+ };
330
+ if (immediate) {
331
+ if (this._scrollHeightRafId != null) {
332
+ cancelAnimationFrame(this._scrollHeightRafId);
333
+ this._scrollHeightRafId = null;
334
+ }
335
+ flush();
336
+ return;
337
+ }
338
+ if (this._scrollHeightRafId != null) {
339
+ cancelAnimationFrame(this._scrollHeightRafId);
340
+ }
341
+ this._scrollHeightRafId = requestAnimationFrame(() => {
342
+ this._scrollHeightRafId = null;
343
+ flush();
344
+ });
291
345
  }
292
346
  /**
293
347
  * 注册分组
@@ -315,6 +369,23 @@ class Root extends StatefulEventBus {
315
369
  findNode(id) {
316
370
  return this.nodeMap.get(id);
317
371
  }
372
+ /**
373
+ * 设置 Node 层上下方向预缓存条数,并刷新可见分组内的列渲染区间。
374
+ */
375
+ setNodeCacheRange(backward, forward) {
376
+ const b = Math.max(0, Math.floor(backward));
377
+ const f = Math.max(0, Math.floor(forward));
378
+ if (this.nodeCacheBackward === b && this.nodeCacheForward === f) {
379
+ return;
380
+ }
381
+ this.nodeCacheBackward = b;
382
+ this.nodeCacheForward = f;
383
+ for (const section of this.sections) {
384
+ if (section.isInRange) {
385
+ section.setStateIn('renderRange', section.getNodeRenderRange());
386
+ }
387
+ }
388
+ }
318
389
  /**
319
390
  * 获取分组渲染区间
320
391
  */
@@ -333,15 +404,16 @@ class Root extends StatefulEventBus {
333
404
  if (result[1] === -Infinity) {
334
405
  result[1] = this.sections.length - 1;
335
406
  }
336
- const scrollDirection = this.getState().scrollDirection;
337
407
  const [backwardCache, forwardCache] = this.calcCacheSection(result);
338
- const backwardDistance = scrollDirection === 'backward' ? backwardCache : 0;
339
- const forwardDistance = scrollDirection === 'forward' ? forwardCache : 0;
408
+ // 双向预缓存,避免反向滚动时出现空白(原逻辑仅在滚动方向缓存,反向时未预渲染)
409
+ const backwardDistance = backwardCache;
410
+ const forwardDistance = forwardCache;
340
411
  const overscanBackward = result[0] - backwardDistance;
341
412
  const overscanForward = result[1] + forwardDistance;
342
413
  result[0] = overscanBackward < 0 ? 0 : overscanBackward;
343
414
  result[1] = overscanForward > this.sections.length ? this.sections.length - 1 : overscanForward;
344
- return isSameRenderRange(result, this.getState().renderRange) ? this.getState().renderRange : result;
415
+ const prevRange = this.getState().renderRange;
416
+ return isSameRenderRange(result, prevRange) ? prevRange : result;
345
417
  }
346
418
  /**
347
419
  * 计算预渲染的分组个数