vane-waterfall 2.0.1 → 2.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.
Files changed (134) hide show
  1. package/README.md +4 -4
  2. package/dist/chunks/WaterfallCore-EdAZuWAY.js +695 -0
  3. package/dist/chunks/doc-BAhVW3g8.js +150 -0
  4. package/dist/chunks/doc-BU0CKW63.js +156 -0
  5. package/dist/chunks/doc-BrEd0oZB.js +100 -0
  6. package/dist/chunks/{doc-bTHwfIVb.js → doc-Bud0hbaz.js} +39 -25
  7. package/dist/chunks/{doc-DukOmDCo.js → doc-C-B3zK2o.js} +52 -23
  8. package/dist/chunks/{doc-DElLNjIc.js → doc-C206ZwYC.js} +33 -24
  9. package/dist/chunks/doc-C2L8kkeI.js +112 -0
  10. package/dist/chunks/doc-CE1DGMBV.js +166 -0
  11. package/dist/chunks/{doc-BXSy2aPP.js → doc-CHbQXLwY.js} +33 -19
  12. package/dist/chunks/{doc-BfWnfTst.js → doc-CInpKZNU.js} +38 -24
  13. package/dist/chunks/{doc-gTAsLjVx.js → doc-CYxwSuG6.js} +30 -16
  14. package/dist/chunks/{doc-DzvTrZ13.js → doc-CaJ02INP.js} +25 -16
  15. package/dist/chunks/{doc-BXElhF2h.js → doc-CiCso5Ti.js} +44 -30
  16. package/dist/chunks/doc-CkuMr8Ca.js +118 -0
  17. package/dist/chunks/{doc-3Fpag2G8.js → doc-D7m1OFCW.js} +38 -24
  18. package/dist/chunks/doc-DEN2WTDh.js +153 -0
  19. package/dist/chunks/{doc-C5xrHNoC.js → doc-DhICh9S2.js} +37 -23
  20. package/dist/chunks/doc-DlJICsyN.js +100 -0
  21. package/dist/chunks/{doc-BtzhgTYj.js → doc-DtxS1-P0.js} +35 -26
  22. package/dist/chunks/{doc-BIzjYAZW.js → doc-DudYCn_-.js} +25 -16
  23. package/dist/chunks/doc-HoyAFR_m.js +101 -0
  24. package/dist/chunks/doc-RlBMCMNs.js +170 -0
  25. package/dist/chunks/doc-RwKQqySd.js +102 -0
  26. package/dist/chunks/{doc-CTUoMe7o.js → doc-eYhNJy97.js} +31 -22
  27. package/dist/chunks/{doc-CcPFavOs.js → doc-i6FY1We1.js} +27 -13
  28. package/dist/chunks/doc-skPl6ZMP.js +101 -0
  29. package/dist/chunks/index-8gEIzUxi.js +15 -0
  30. package/dist/chunks/index-B96I5CKE.js +21 -0
  31. package/dist/chunks/index-Bjmhy8jW.js +11 -0
  32. package/dist/chunks/index-Cuq0ofv-.js +13 -0
  33. package/dist/chunks/{index-BAWlVYr3.js → index-Cz4YEqRF.js} +1 -1
  34. package/dist/chunks/{index-wLI6UXkY.js → index-FBJVUYmH.js} +1 -1
  35. package/dist/chunks/withPlugins-BOeDFhof.js +743 -0
  36. package/dist/components/WaterfallPlugin/WaterfallCore.d.ts +19 -0
  37. package/dist/components/WaterfallPlugin/WaterfallCore.d.ts.map +1 -1
  38. package/dist/components/WaterfallPlugin/layout.d.ts +7 -0
  39. package/dist/components/WaterfallPlugin/layout.d.ts.map +1 -1
  40. package/dist/components/WaterfallPlugin/plugins/types.d.ts +3 -0
  41. package/dist/components/WaterfallPlugin/plugins/types.d.ts.map +1 -1
  42. package/dist/components/WaterfallPlugin/withPlugins.d.ts.map +1 -1
  43. package/dist/custom-plugins/A11yPlugin/create.d.ts.map +1 -1
  44. package/dist/custom-plugins/A11yPlugin/doc.json.d.ts +64 -40
  45. package/dist/custom-plugins/A11yPlugin/index.js +1 -1
  46. package/dist/custom-plugins/AlignmentPlugin/doc.json.d.ts +42 -28
  47. package/dist/custom-plugins/AlignmentPlugin/index.js +1 -1
  48. package/dist/custom-plugins/AutoColumnPlugin/doc.json.d.ts +53 -44
  49. package/dist/custom-plugins/AutoColumnPlugin/index.js +1 -1
  50. package/dist/custom-plugins/BookmarkPlugin/create.d.ts.map +1 -1
  51. package/dist/custom-plugins/BookmarkPlugin/doc.json.d.ts +44 -35
  52. package/dist/custom-plugins/BookmarkPlugin/index.js +1 -1
  53. package/dist/custom-plugins/ClickAnalyticsPlugin/create.d.ts +2 -0
  54. package/dist/custom-plugins/ClickAnalyticsPlugin/create.d.ts.map +1 -1
  55. package/dist/custom-plugins/ClickAnalyticsPlugin/doc.json.d.ts +29 -0
  56. package/dist/custom-plugins/ClickAnalyticsPlugin/index.js +1 -1
  57. package/dist/custom-plugins/DebounceLayoutPlugin/doc.json.d.ts +37 -28
  58. package/dist/custom-plugins/DebounceLayoutPlugin/index.js +1 -1
  59. package/dist/custom-plugins/DragReorderPlugin/doc.json.d.ts +14 -0
  60. package/dist/custom-plugins/DragReorderPlugin/index.js +1 -1
  61. package/dist/custom-plugins/FilterPlugin/doc.json.d.ts +53 -39
  62. package/dist/custom-plugins/FilterPlugin/index.js +1 -1
  63. package/dist/custom-plugins/FixedHeightPlugin/doc.json.d.ts +42 -28
  64. package/dist/custom-plugins/FixedHeightPlugin/index.js +1 -1
  65. package/dist/custom-plugins/GapPlugin/create.d.ts.map +1 -1
  66. package/dist/custom-plugins/GapPlugin/doc.json.d.ts +61 -37
  67. package/dist/custom-plugins/GapPlugin/index.js +1 -1
  68. package/dist/custom-plugins/GroupingPlugin/create.d.ts.map +1 -1
  69. package/dist/custom-plugins/GroupingPlugin/doc.json.d.ts +61 -32
  70. package/dist/custom-plugins/GroupingPlugin/index.js +1 -1
  71. package/dist/custom-plugins/HeatmapAnalyticsPlugin/create.d.ts +2 -0
  72. package/dist/custom-plugins/HeatmapAnalyticsPlugin/create.d.ts.map +1 -1
  73. package/dist/custom-plugins/HeatmapAnalyticsPlugin/doc.json.d.ts +24 -0
  74. package/dist/custom-plugins/HeatmapAnalyticsPlugin/index.js +1 -1
  75. package/dist/custom-plugins/InfiniteScrollPlugin/create.d.ts.map +1 -1
  76. package/dist/custom-plugins/InfiniteScrollPlugin/doc.json.d.ts +55 -36
  77. package/dist/custom-plugins/InfiniteScrollPlugin/index.js +1 -1
  78. package/dist/custom-plugins/PaginationPlugin/create.d.ts.map +1 -1
  79. package/dist/custom-plugins/PaginationPlugin/doc.json.d.ts +56 -42
  80. package/dist/custom-plugins/PaginationPlugin/index.js +1 -1
  81. package/dist/custom-plugins/PinItemPlugin/doc.json.d.ts +49 -35
  82. package/dist/custom-plugins/PinItemPlugin/index.js +1 -1
  83. package/dist/custom-plugins/RecyclePlugin/create.d.ts.map +1 -1
  84. package/dist/custom-plugins/RecyclePlugin/doc.json.d.ts +57 -28
  85. package/dist/custom-plugins/RecyclePlugin/index.js +1 -1
  86. package/dist/custom-plugins/ReducedMotionPlugin/doc.json.d.ts +29 -0
  87. package/dist/custom-plugins/ReducedMotionPlugin/index.js +1 -1
  88. package/dist/custom-plugins/ResponsiveColumnsPlugin/doc.json.d.ts +40 -31
  89. package/dist/custom-plugins/ResponsiveColumnsPlugin/index.js +1 -1
  90. package/dist/custom-plugins/ScrollAnchorPlugin/doc.json.d.ts +42 -28
  91. package/dist/custom-plugins/ScrollAnchorPlugin/index.js +1 -1
  92. package/dist/custom-plugins/SearchPlugin/doc.json.d.ts +53 -39
  93. package/dist/custom-plugins/SearchPlugin/index.js +1 -1
  94. package/dist/custom-plugins/SortPlugin/doc.json.d.ts +52 -38
  95. package/dist/custom-plugins/SortPlugin/index.js +1 -1
  96. package/dist/custom-plugins/StatePersistencePlugin/create.d.ts.map +1 -1
  97. package/dist/custom-plugins/StatePersistencePlugin/doc.json.d.ts +71 -37
  98. package/dist/custom-plugins/StatePersistencePlugin/index.js +1 -1
  99. package/dist/custom-plugins/StickyHeaderPlugin/create.d.ts.map +1 -1
  100. package/dist/custom-plugins/StickyHeaderPlugin/doc.json.d.ts +43 -34
  101. package/dist/custom-plugins/StickyHeaderPlugin/index.js +1 -1
  102. package/dist/custom-plugins/ThrottlePlugin/doc.json.d.ts +43 -34
  103. package/dist/custom-plugins/ThrottlePlugin/index.js +1 -1
  104. package/dist/custom-plugins/TransitionPlugin/doc.json.d.ts +49 -35
  105. package/dist/custom-plugins/TransitionPlugin/index.js +1 -1
  106. package/dist/custom-plugins/URLSyncPlugin/create.d.ts.map +1 -1
  107. package/dist/custom-plugins/URLSyncPlugin/doc.json.d.ts +57 -33
  108. package/dist/custom-plugins/URLSyncPlugin/index.js +1 -1
  109. package/dist/custom-plugins/index.js +6 -6
  110. package/dist/entries/core.js +1 -1
  111. package/dist/entries/plugins.js +7 -7
  112. package/dist/index.js +2 -2
  113. package/dist/presets/dashboard/index.js +2 -2
  114. package/dist/presets/photo-feed/index.js +3 -3
  115. package/dist/presets/product-feed/index.js +2 -2
  116. package/package.json +16 -8
  117. package/dist/chunks/WaterfallCore-BSXw7bl_.js +0 -581
  118. package/dist/chunks/doc-78xF08vt.js +0 -82
  119. package/dist/chunks/doc-B-7dugGv.js +0 -79
  120. package/dist/chunks/doc-B6kLfMPv.js +0 -121
  121. package/dist/chunks/doc-BCGQ8Cp5.js +0 -114
  122. package/dist/chunks/doc-BP0DmB7-.js +0 -91
  123. package/dist/chunks/doc-CBHjiDG7.js +0 -88
  124. package/dist/chunks/doc-CraXjOaA.js +0 -68
  125. package/dist/chunks/doc-DJjxOYzW.js +0 -111
  126. package/dist/chunks/doc-NhL4Ux8q.js +0 -125
  127. package/dist/chunks/doc-f4Uijujv.js +0 -102
  128. package/dist/chunks/doc-j4W9SUrY.js +0 -76
  129. package/dist/chunks/doc-kTbJE7rY.js +0 -92
  130. package/dist/chunks/index-COaun3nf.js +0 -15
  131. package/dist/chunks/index-DXAtA2f6.js +0 -11
  132. package/dist/chunks/index-DsRLmBW-.js +0 -13
  133. package/dist/chunks/index-gjoCq0yC.js +0 -21
  134. package/dist/chunks/withPlugins-DLoKg4AP.js +0 -559
@@ -0,0 +1,150 @@
1
+ function E(p = {}) {
2
+ const u = p.mode || "hash", o = p.keys || ["pageIndex", "pageSize", "searchQuery"];
3
+ let h = null, d = !1;
4
+ const l = () => (h === null && (h = f()), h);
5
+ function f() {
6
+ try {
7
+ if (u === "hash") {
8
+ const s = window.location.hash || "", a = s.indexOf("?"), t = a >= 0 ? s.slice(a + 1) : s.replace(/^#/, ""), e = new URLSearchParams(t), n = {};
9
+ return o.forEach((c) => {
10
+ const r = e.get(c);
11
+ r !== null && (n[c] = r);
12
+ }), n;
13
+ } else {
14
+ const s = new URLSearchParams(window.location.search), a = {};
15
+ return o.forEach((t) => {
16
+ const e = s.get(t);
17
+ e !== null && (a[t] = e);
18
+ }), a;
19
+ }
20
+ } catch {
21
+ return {};
22
+ }
23
+ }
24
+ function w(s) {
25
+ try {
26
+ const a = new URLSearchParams();
27
+ o.forEach((e) => {
28
+ const n = s[e];
29
+ n != null && String(n).length > 0 && a.set(e, String(n));
30
+ });
31
+ const t = a.toString();
32
+ if (u === "hash") {
33
+ const e = window.location.hash || "", r = `#${e.replace(/^#/, "").split("?")[0] || ""}${t ? `?${t}` : ""}`;
34
+ e !== r && history.replaceState(
35
+ null,
36
+ "",
37
+ `${window.location.pathname}${window.location.search}${r}`
38
+ );
39
+ } else {
40
+ const n = window.location.pathname + (t ? `?${t}` : "") + (window.location.hash || "");
41
+ history.replaceState(null, "", n);
42
+ }
43
+ } catch {
44
+ }
45
+ }
46
+ return {
47
+ name: "URLSyncPlugin",
48
+ enabled: !0,
49
+ hooks: {
50
+ // 首次渲染就把 URL 里的值注入 props:旧实现只广播 `urlsync:init`,
51
+ // 页面不手动订阅时深链参数根本不会生效(「只写不读」,P2-6)
52
+ transformProps: (s) => {
53
+ if (d) return s;
54
+ const a = l(), t = { ...s };
55
+ let e = !1;
56
+ return o.forEach((n) => {
57
+ a[n] !== void 0 && (t[n] = a[n], e = !0);
58
+ }), e && (d = !0), t;
59
+ },
60
+ onMount: (s) => {
61
+ s.bus?.emit("urlsync:init", l());
62
+ },
63
+ onPropsChange: (s, a, t) => {
64
+ const e = {}, n = t ?? {};
65
+ o.forEach((i) => {
66
+ const m = n[i];
67
+ m !== void 0 && (e[i] = m);
68
+ });
69
+ const c = l();
70
+ o.some(
71
+ (i) => String(e[i] ?? "") !== String(c[i] ?? "")
72
+ ) && w(e);
73
+ }
74
+ }
75
+ };
76
+ }
77
+ const g = "URLSyncPlugin", S = "props 变化时把指定键写进 URL(hash 或 search),挂载时读出来广播 `urlsync:init`。刷新与分享都能还原筛选状态。", y = "2.0.0", P = [
78
+ "ui",
79
+ "URL",
80
+ "可分享"
81
+ ], R = [
82
+ {
83
+ name: "onMount",
84
+ when: "瀑布流挂载完成",
85
+ description: "初始化观察器与滚动监听,返回清理函数"
86
+ },
87
+ {
88
+ name: "onPropsChange",
89
+ when: "props 变化后",
90
+ description: "数据或配置变化时请求重排"
91
+ },
92
+ {
93
+ name: "transformProps",
94
+ when: "渲染前链式改写瀑布流 props",
95
+ description: "补 gap / columns 默认值、按断点覆盖配置"
96
+ },
97
+ {
98
+ name: "urlsync:init",
99
+ when: "从 URL 参数初始化完成后",
100
+ description: "广播初始参数快照"
101
+ }
102
+ ], L = [], U = "只读取 context 字段(props / state / data),不调用上下文方法", x = [
103
+ {
104
+ name: "mode",
105
+ type: '"hash" | "search"',
106
+ default: '"hash"',
107
+ description: "写 hash 还是 search"
108
+ },
109
+ {
110
+ name: "keys",
111
+ type: "string[]",
112
+ default: '["pageIndex","pageSize","searchQuery"]',
113
+ description: "要同步的 props 键"
114
+ }
115
+ ], v = `// 把分页/搜索/排序同步进 URL(hash 或 search),链接可分享。
116
+ const Waterfall = withPlugins(WaterfallCore, [
117
+ createURLSyncPlugin({
118
+ mode: "hash",
119
+ keys: ["pageIndex","pageSize","searchQuery"],
120
+ }),
121
+ ]);
122
+
123
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, $ = [
124
+ "hash 模式会保留已有路由路径",
125
+ "用 replaceState,不污染后退栈",
126
+ "SSR 安全:无 window 时直接跳过"
127
+ ], C = [
128
+ "搜索结果可分享",
129
+ "后台筛选状态可刷新",
130
+ "带参数的深链"
131
+ ], I = [
132
+ "只做单向同步(props → URL)与初始读取;URL 前进后退的监听请页面自己做。"
133
+ ], b = {
134
+ name: g,
135
+ description: S,
136
+ since: y,
137
+ tags: P,
138
+ events: R,
139
+ methods: L,
140
+ methodsNote: U,
141
+ config: x,
142
+ example: v,
143
+ features: $,
144
+ useCases: C,
145
+ notes: I
146
+ };
147
+ export {
148
+ E as c,
149
+ b as d
150
+ };
@@ -0,0 +1,156 @@
1
+ import { jsxs as p } from "react/jsx-runtime";
2
+ const d = "GROUPS", y = "GROUP_INDEX";
3
+ function E(u = {}) {
4
+ const g = u.groupBy ?? ((e) => e?.category ?? "default"), h = u.showOverlay ?? !1;
5
+ let l = null, r = null;
6
+ const m = (e, n) => {
7
+ if (e.size !== n.size) return !1;
8
+ for (const [t, s] of e) {
9
+ const o = n.get(t);
10
+ if (!o || o.length !== s.length) return !1;
11
+ }
12
+ return !0;
13
+ }, i = (e) => {
14
+ const n = e.items ?? [];
15
+ if (r && l === n) return r;
16
+ const t = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
17
+ n.forEach((f, c) => {
18
+ const a = g(f, c);
19
+ s.set(c, a), t.has(a) || t.set(a, []), t.get(a).push(c);
20
+ });
21
+ const o = r ? !m(t, r) : !0;
22
+ return l = n, r = t, e.sharedData.set(d, t), e.sharedData.set(y, s), o && t.size > 0 && e.bus.emit("grouping:change", { groups: t }), t;
23
+ };
24
+ return {
25
+ name: "GroupingPlugin",
26
+ enabled: !0,
27
+ hooks: {
28
+ onMount: (e) => {
29
+ i(e);
30
+ },
31
+ onLayoutComplete: (e) => {
32
+ i(e);
33
+ },
34
+ onPropsChange: (e) => {
35
+ i(e);
36
+ },
37
+ renderOverlay: (e) => {
38
+ if (!h) return null;
39
+ const n = e.sharedData.get(d) ?? /* @__PURE__ */ new Map();
40
+ if (n.size === 0) return null;
41
+ const t = Array.from(n.entries()).slice(0, 3);
42
+ return /* @__PURE__ */ p(
43
+ "div",
44
+ {
45
+ style: {
46
+ position: "absolute",
47
+ top: 12,
48
+ left: 12,
49
+ zIndex: 99,
50
+ background: "#111827",
51
+ color: "#fff",
52
+ padding: "10px 12px",
53
+ borderRadius: 8,
54
+ boxShadow: "0 4px 12px rgba(0,0,0,0.25)",
55
+ border: "1px solid rgba(255,255,255,0.15)",
56
+ minWidth: 150,
57
+ fontSize: 12,
58
+ pointerEvents: "none"
59
+ },
60
+ children: [
61
+ /* @__PURE__ */ p("div", { style: { opacity: 0.85, marginBottom: 6 }, children: [
62
+ "分组:",
63
+ n.size,
64
+ " 组"
65
+ ] }),
66
+ t.map(([s, o]) => /* @__PURE__ */ p("div", { children: [
67
+ String(s),
68
+ " · ",
69
+ o.length,
70
+ " 项"
71
+ ] }, String(s)))
72
+ ]
73
+ }
74
+ );
75
+ }
76
+ }
77
+ };
78
+ }
79
+ const w = "GroupingPlugin", v = "用 groupBy 把项按业务字段分组,结果放进 sharedData 的 `GROUPS`(Map<组键, 索引数组>),供 StickyHeaderPlugin、分组统计条等消费。挂载即算一次,之后 props 变化重算。", P = "2.0.0", O = [
80
+ "ui",
81
+ "分组"
82
+ ], b = [
83
+ {
84
+ name: "onMount",
85
+ when: "瀑布流挂载完成",
86
+ description: "初始化观察器与滚动监听,返回清理函数"
87
+ },
88
+ {
89
+ name: "onPropsChange",
90
+ when: "props 变化后",
91
+ description: "数据或配置变化时请求重排"
92
+ },
93
+ {
94
+ name: "onLayoutComplete",
95
+ when: "DOM 落位完成(可安全测量)",
96
+ description: "测量真实高度、懒加载判定、曝光上报"
97
+ },
98
+ {
99
+ name: "renderOverlay",
100
+ when: "每次渲染,滚动容器内的内容层之上",
101
+ description: "回到顶部、加载提示、浮层工具"
102
+ },
103
+ {
104
+ name: "grouping:change",
105
+ when: "分组结果变化时",
106
+ description: "广播 { groups } 分组结构"
107
+ }
108
+ ], G = [], x = "只读取 context 字段(props / state / data),不调用上下文方法", D = [
109
+ {
110
+ name: "groupBy",
111
+ type: "(item, index) => string | number",
112
+ default: 'item.category ?? "default"',
113
+ description: "分组函数"
114
+ },
115
+ {
116
+ name: "showOverlay",
117
+ type: "boolean",
118
+ default: "false",
119
+ description: "是否显示分组统计角标"
120
+ }
121
+ ], C = `// 按字段把项分组,结果写进 sharedData(GROUPS) 供吸顶条 / 统计用。
122
+ const Waterfall = withPlugins(WaterfallCore, [
123
+ createGroupingPlugin({
124
+ groupBy: "item.category ?? \\"default\\"",
125
+ showOverlay: false,
126
+ }),
127
+ ]);
128
+
129
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, M = [
130
+ "挂载即计算(旧版只在 props 变化时算,首屏永远拿不到分组)",
131
+ "结果写 sharedData,跨插件可读",
132
+ "统计角标默认关闭"
133
+ ], S = [
134
+ "按分类分组的信息流",
135
+ "按日期分组的时间线",
136
+ "吸顶条显示当前分组"
137
+ ], z = [
138
+ "分组只产出索引映射,不改变渲染顺序;要视觉分组请自己按分组建行。"
139
+ ], I = {
140
+ name: w,
141
+ description: v,
142
+ since: P,
143
+ tags: O,
144
+ events: b,
145
+ methods: G,
146
+ methodsNote: x,
147
+ config: D,
148
+ example: C,
149
+ features: M,
150
+ useCases: S,
151
+ notes: z
152
+ };
153
+ export {
154
+ E as c,
155
+ I as d
156
+ };
@@ -0,0 +1,100 @@
1
+ function x(s = {}) {
2
+ const c = s.storageKey || "waterfall-bookmark", l = s.scrollBehavior || "smooth", m = (a) => {
3
+ const o = a;
4
+ if (!o) return !1;
5
+ const n = o.tagName?.toLowerCase(), r = (o.getAttribute && o.getAttribute("contenteditable")) === "true";
6
+ return n === "input" || n === "textarea" || r;
7
+ };
8
+ return {
9
+ name: "BookmarkPlugin",
10
+ enabled: !0,
11
+ hooks: {
12
+ onMount: (a) => {
13
+ const o = (n) => {
14
+ if (m(n.target)) return;
15
+ const r = (n.key || "").toLowerCase(), i = n.code || "";
16
+ if (r === "b" || i === "KeyB") {
17
+ const e = a.containerRef?.current || null;
18
+ let t = 0;
19
+ e && e.scrollHeight > e.clientHeight ? t = e.scrollTop : t = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
20
+ try {
21
+ localStorage.setItem(c, String(Math.max(0, t)));
22
+ } catch {
23
+ }
24
+ } else if (r === "r" || i === "KeyR") {
25
+ let e = 0;
26
+ try {
27
+ const u = localStorage.getItem(c) || "0";
28
+ e = Math.max(0, Number(u) || 0);
29
+ } catch {
30
+ }
31
+ const t = a.containerRef?.current || null;
32
+ t && t.scrollHeight > t.clientHeight ? t.scrollTo({ top: e, behavior: l }) : window.scrollTo({ top: e, behavior: l });
33
+ }
34
+ };
35
+ return window.addEventListener("keydown", o, { capture: !0 }), () => {
36
+ window.removeEventListener("keydown", o, { capture: !0 });
37
+ };
38
+ }
39
+ }
40
+ };
41
+ }
42
+ const d = "BookmarkPlugin", g = "长列表读到一半要跳走时按 **B** 存位置,回来按 **R** 复原。焦点在输入框/可编辑区域时不拦截按键。", h = "2.0.0", f = [
43
+ "ui",
44
+ "滚动",
45
+ "快捷键"
46
+ ], p = [
47
+ {
48
+ name: "onMount",
49
+ when: "瀑布流挂载完成",
50
+ description: "初始化观察器与滚动监听,返回清理函数"
51
+ }
52
+ ], k = [], w = "只读取 context 字段(props / state / data),不调用上下文方法", y = [
53
+ {
54
+ name: "storageKey",
55
+ type: "string",
56
+ default: '"waterfall-bookmark"',
57
+ description: "localStorage 键名"
58
+ },
59
+ {
60
+ name: "scrollBehavior",
61
+ type: '"auto" | "smooth"',
62
+ default: '"smooth"',
63
+ description: "恢复时的滚动行为"
64
+ }
65
+ ], b = `// 按 B 记录滚动位置、按 R 跳回(localStorage),忽略输入框按键。
66
+ const Waterfall = withPlugins(WaterfallCore, [
67
+ createBookmarkPlugin({
68
+ storageKey: "waterfall-bookmark",
69
+ scrollBehavior: "smooth",
70
+ }),
71
+ ]);
72
+
73
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, B = [
74
+ "B 存 / R 取,零 UI 侵入",
75
+ "自动区分容器滚动与页面滚动",
76
+ "输入框内不误触"
77
+ ], v = [
78
+ "长文列表阅读",
79
+ "后台大表格浏览",
80
+ "演示时快速复位"
81
+ ], K = [
82
+ "键名全局共用,一个页面里多处瀑布流请各自传不同的 storageKey。"
83
+ ], C = {
84
+ name: d,
85
+ description: g,
86
+ since: h,
87
+ tags: f,
88
+ events: p,
89
+ methods: k,
90
+ methodsNote: w,
91
+ config: y,
92
+ example: b,
93
+ features: B,
94
+ useCases: v,
95
+ notes: K
96
+ };
97
+ export {
98
+ x as c,
99
+ C as d
100
+ };
@@ -1,20 +1,20 @@
1
- function w(s) {
2
- const r = new Set(s.pinnedIndices), e = Math.max(0, s.column ?? 0), n = /* @__PURE__ */ new Map();
1
+ function v(s) {
2
+ const r = new Set(s.pinnedIndices), n = Math.max(0, s.column ?? 0), e = /* @__PURE__ */ new Map();
3
3
  return {
4
4
  name: "PinItemPlugin",
5
5
  priority: 100,
6
6
  enabled: !0,
7
7
  hooks: {
8
- onBeforeLayout: () => (n.clear(), !0),
9
- calculateItemPosition: (i, u, c, t) => {
10
- const l = i.props.rowGap ?? i.props.gap ?? 0;
11
- if (!r.has(u)) {
12
- const o = n.get(t.column);
8
+ onBeforeLayout: () => (e.clear(), !0),
9
+ calculateItemPosition: (i, l, c, t) => {
10
+ const m = i.props.rowGap ?? i.props.gap ?? 0;
11
+ if (!r.has(l)) {
12
+ const o = e.get(t.column);
13
13
  return o !== void 0 && t.y < o ? { y: o } : void 0;
14
14
  }
15
- const a = n.get(e) ?? 0;
16
- return n.set(e, a + c + l), {
17
- column: e,
15
+ const a = e.get(n) ?? 0;
16
+ return e.set(n, a + c + m), {
17
+ column: n,
18
18
  y: a,
19
19
  width: t.width,
20
20
  height: c,
@@ -24,11 +24,22 @@ function w(s) {
24
24
  }
25
25
  };
26
26
  }
27
- const m = "PinItemPlugin", d = "把若干索引的项钉在顶部指定列,其余项从它们下方继续排。走 D1-A 布局钩子(calculateItemPosition),是旧版宣称但从未生效的能力。", p = "2.0.0", f = [
27
+ const u = "PinItemPlugin", d = "把若干索引的项钉在顶部指定列,其余项从它们下方继续排。走 D1-A 布局钩子(calculateItemPosition),是旧版宣称但从未生效的能力。", p = "2.0.0", f = [
28
28
  "layout",
29
29
  "layout-hook",
30
30
  "置顶"
31
- ], g = [
31
+ ], h = [
32
+ {
33
+ name: "onBeforeLayout",
34
+ when: "开始一次布局之前",
35
+ description: "返回 false 可阻止本次布局(如数据仍在加载)"
36
+ },
37
+ {
38
+ name: "calculateItemPosition",
39
+ when: "每个卡片参与布局时(拿到 index / item / columns)",
40
+ description: "返回坐标片段可覆盖列分配结果(置顶、跨列、错位)"
41
+ }
42
+ ], g = [], I = "只读取 context 字段(props / state / data),不调用上下文方法", P = [
32
43
  {
33
44
  name: "pinnedIndices",
34
45
  type: "number[]",
@@ -41,7 +52,7 @@ const m = "PinItemPlugin", d = "把若干索引的项钉在顶部指定列,其
41
52
  default: "0",
42
53
  description: "钉到第几列"
43
54
  }
44
- ], I = `// 把指定索引的项钉在顶部同一列,不参与常规列高推进(广告位 / 公告卡)。
55
+ ], y = `// 把指定索引的项钉在顶部同一列,不参与常规列高推进(广告位 / 公告卡)。
45
56
  const Waterfall = withPlugins(WaterfallCore, [
46
57
  createPinItemPlugin({
47
58
  pinnedIndices: [],
@@ -49,30 +60,33 @@ const Waterfall = withPlugins(WaterfallCore, [
49
60
  }),
50
61
  ]);
51
62
 
52
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, P = [
63
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, w = [
53
64
  "置顶项不占常规列高:后续项从置顶块下方开始",
54
65
  "支持多列分别置顶(column 可不同)",
55
66
  "每次布局前重置偏移,items 变化后不会累加错位"
56
- ], y = [
67
+ ], x = [
57
68
  "信息流首位的推广卡",
58
69
  "公告 / 置顶帖",
59
70
  "需要固定在左上角的活动位"
60
- ], h = [
71
+ ], C = [
61
72
  "置顶项之间按 pinnedIndices 顺序纵向堆叠,同一列多条会依次往下排。",
62
73
  "置顶会挤掉该列的正常网格位置,pinnedIndices 建议控制在 1~2 条。",
63
74
  "换列后的 x 由布局引擎按本轮列宽补齐,插件只返回 column 即可 —— 自己用「列宽 + 间距」反推 x 会在间距由其它插件(GapPlugin)注入时算错。"
64
- ], C = {
65
- name: m,
75
+ ], B = {
76
+ name: u,
66
77
  description: d,
67
78
  since: p,
68
79
  tags: f,
69
- config: g,
70
- example: I,
71
- features: P,
72
- useCases: y,
73
- notes: h
80
+ events: h,
81
+ methods: g,
82
+ methodsNote: I,
83
+ config: P,
84
+ example: y,
85
+ features: w,
86
+ useCases: x,
87
+ notes: C
74
88
  };
75
89
  export {
76
- w as c,
77
- C as d
90
+ v as c,
91
+ B as d
78
92
  };
@@ -1,9 +1,9 @@
1
1
  const l = "(prefers-reduced-motion: reduce)";
2
- function R(c = {}) {
2
+ function C(c = {}) {
3
3
  const i = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia(l) : null;
4
4
  let s = i?.matches ?? !1;
5
- const m = c.disableTransform ?? !0, u = c.removeTransitions ?? !0, o = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map(), a = (e) => {
6
- if (!(!e || !u))
5
+ const m = c.disableTransform ?? !0, d = c.removeTransitions ?? !0, o = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map(), a = (e) => {
6
+ if (!(!e || !d))
7
7
  if (s) {
8
8
  const n = e.style.transitionDuration;
9
9
  n && n !== "0s" ? t.set(e, n) : t.has(e) || t.set(e, n), e.style.setProperty("transition-duration", "0s");
@@ -12,10 +12,10 @@ function R(c = {}) {
12
12
  if (n === void 0) return;
13
13
  n ? e.style.setProperty("transition-duration", n) : e.style.removeProperty("transition-duration"), t.delete(e);
14
14
  }
15
- }, f = () => o.forEach((e) => a(e)), d = (e) => {
15
+ }, f = () => o.forEach((e) => a(e)), u = (e) => {
16
16
  e.matches !== s && (s = e.matches, f());
17
17
  };
18
- return i?.addEventListener?.("change", d), {
18
+ return i?.addEventListener?.("change", u), {
19
19
  name: "ReducedMotionPlugin",
20
20
  priority: 70,
21
21
  enabled: !0,
@@ -23,7 +23,7 @@ function R(c = {}) {
23
23
  transformProps: (e) => {
24
24
  if (!s) return e;
25
25
  const n = { ...e };
26
- return m && (n.useTransform = !1), u && (n.itemStyle = { ...e.itemStyle ?? {}, transitionDuration: "0s" }), n;
26
+ return m && (n.useTransform = !1), d && (n.itemStyle = { ...e.itemStyle ?? {}, transitionDuration: "0s" }), n;
27
27
  },
28
28
  onItemMount: (e, n, r) => {
29
29
  o.set(n, r), a(r);
@@ -37,15 +37,41 @@ function R(c = {}) {
37
37
  });
38
38
  },
39
39
  onUnmount: () => {
40
- i?.removeEventListener?.("change", d), o.clear(), t.clear();
40
+ i?.removeEventListener?.("change", u), o.clear(), t.clear();
41
41
  }
42
42
  }
43
43
  };
44
44
  }
45
- const p = "ReducedMotionPlugin", y = "检测 `prefers-reduced-motion: reduce`,命中后把 useTransform 关掉并清掉项上的 transition。前庭功能敏感用户不会因为滚动时的位置微动而不适。", g = "2.0.0", h = [
45
+ const p = "ReducedMotionPlugin", h = "检测 `prefers-reduced-motion: reduce`,命中后把 useTransform 关掉并清掉项上的 transition。前庭功能敏感用户不会因为滚动时的位置微动而不适。", y = "2.0.0", g = [
46
46
  "perf",
47
47
  "a11y"
48
- ], T = [
48
+ ], w = [
49
+ {
50
+ name: "onUnmount",
51
+ when: "瀑布流卸载前",
52
+ description: "断开观察器、移除滚动监听"
53
+ },
54
+ {
55
+ name: "onItemMount",
56
+ when: "单个卡片挂载并拿到 DOM 元素时",
57
+ description: "按卡片绑定监听、观察器、埋点"
58
+ },
59
+ {
60
+ name: "onItemUnmount",
61
+ when: "单个卡片卸载时",
62
+ description: "解绑该卡片的监听与观察器"
63
+ },
64
+ {
65
+ name: "onLayoutComplete",
66
+ when: "DOM 落位完成(可安全测量)",
67
+ description: "测量真实高度、懒加载判定、曝光上报"
68
+ },
69
+ {
70
+ name: "transformProps",
71
+ when: "渲染前链式改写瀑布流 props",
72
+ description: "补 gap / columns 默认值、按断点覆盖配置"
73
+ }
74
+ ], M = [], P = "只读取 context 字段(props / state / data),不调用上下文方法", T = [
49
75
  {
50
76
  name: "disableTransform",
51
77
  type: "boolean",
@@ -58,7 +84,7 @@ const p = "ReducedMotionPlugin", y = "检测 `prefers-reduced-motion: reduce`,
58
84
  default: "true",
59
85
  description: "命中偏好时清掉项过渡"
60
86
  }
61
- ], P = `// 尊重系统「减少动画」偏好:关掉 transform 定位与项过渡。
87
+ ], v = `// 尊重系统「减少动画」偏好:关掉 transform 定位与项过渡。
62
88
  const Waterfall = withPlugins(WaterfallCore, [
63
89
  createReducedMotionPlugin({
64
90
  disableTransform: true,
@@ -66,30 +92,33 @@ const Waterfall = withPlugins(WaterfallCore, [
66
92
  }),
67
93
  ]);
68
94
 
69
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, M = [
95
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, R = [
70
96
  "系统偏好驱动,零配置生效",
71
97
  "两项能力可分别关闭",
72
98
  "与 TransitionPlugin 同装时优先生效"
73
- ], v = [
99
+ ], b = [
74
100
  "政务 / 医疗类站点",
75
101
  "无障碍合规要求",
76
102
  "低性能设备"
77
- ], w = [
103
+ ], x = [
78
104
  "偏好由 matchMedia 驱动,并监听 change:运行中改系统设置即时生效(定位方式要等下一次重渲染才切过来)。",
79
105
  "只压 `transition-duration`,不写 `transition: none` —— 写简写会把 TransitionPlugin 的过渡整条覆盖,撤销偏好后无从还原。",
80
106
  "与 TransitionPlugin 同装不是冲突:ReducedMotion 优先级更高,会先执行并压住过渡。"
81
- ], b = {
107
+ ], D = {
82
108
  name: p,
83
- description: y,
84
- since: g,
85
- tags: h,
109
+ description: h,
110
+ since: y,
111
+ tags: g,
112
+ events: w,
113
+ methods: M,
114
+ methodsNote: P,
86
115
  config: T,
87
- example: P,
88
- features: M,
89
- useCases: v,
90
- notes: w
116
+ example: v,
117
+ features: R,
118
+ useCases: b,
119
+ notes: x
91
120
  };
92
121
  export {
93
- R as c,
94
- b as d
122
+ C as c,
123
+ D as d
95
124
  };