vane-waterfall 2.0.1 → 2.0.2

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 (65) hide show
  1. package/README.md +4 -4
  2. package/dist/chunks/WaterfallCore-EdAZuWAY.js +695 -0
  3. package/dist/chunks/{doc-kTbJE7rY.js → doc-BCmEnh39.js} +31 -29
  4. package/dist/chunks/doc-BQQoKNto.js +126 -0
  5. package/dist/chunks/{doc-j4W9SUrY.js → doc-BSnWbrkH.js} +39 -27
  6. package/dist/chunks/{doc-BCGQ8Cp5.js → doc-BXaJl1By.js} +54 -41
  7. package/dist/chunks/{doc-CraXjOaA.js → doc-BindRMfO.js} +30 -26
  8. package/dist/chunks/{doc-78xF08vt.js → doc-BmoijI6q.js} +35 -35
  9. package/dist/chunks/{doc-BtzhgTYj.js → doc-CN4edvn_.js} +27 -27
  10. package/dist/chunks/{doc-NhL4Ux8q.js → doc-CkU5GtLw.js} +65 -54
  11. package/dist/chunks/doc-DAieSXLy.js +86 -0
  12. package/dist/chunks/{doc-BP0DmB7-.js → doc-D_ozEn0Q.js} +27 -27
  13. package/dist/chunks/{doc-f4Uijujv.js → doc-KN6Bvmty.js} +54 -32
  14. package/dist/chunks/{doc-B6kLfMPv.js → doc-a0MK2S3n.js} +61 -40
  15. package/dist/chunks/{index-COaun3nf.js → index-B8o6R4RZ.js} +2 -2
  16. package/dist/chunks/{index-DXAtA2f6.js → index-BFyYpEY_.js} +2 -2
  17. package/dist/chunks/{index-wLI6UXkY.js → index-CF0tYRop.js} +1 -1
  18. package/dist/chunks/{index-gjoCq0yC.js → index-CJR0Buju.js} +4 -4
  19. package/dist/chunks/{index-DsRLmBW-.js → index-DHTB3QEP.js} +3 -3
  20. package/dist/chunks/withPlugins-DG3YpSgL.js +655 -0
  21. package/dist/components/WaterfallPlugin/WaterfallCore.d.ts +19 -0
  22. package/dist/components/WaterfallPlugin/WaterfallCore.d.ts.map +1 -1
  23. package/dist/components/WaterfallPlugin/layout.d.ts +7 -0
  24. package/dist/components/WaterfallPlugin/layout.d.ts.map +1 -1
  25. package/dist/components/WaterfallPlugin/plugins/types.d.ts +3 -0
  26. package/dist/components/WaterfallPlugin/plugins/types.d.ts.map +1 -1
  27. package/dist/components/WaterfallPlugin/withPlugins.d.ts.map +1 -1
  28. package/dist/custom-plugins/A11yPlugin/create.d.ts.map +1 -1
  29. package/dist/custom-plugins/A11yPlugin/index.js +1 -1
  30. package/dist/custom-plugins/BookmarkPlugin/create.d.ts.map +1 -1
  31. package/dist/custom-plugins/BookmarkPlugin/index.js +1 -1
  32. package/dist/custom-plugins/ClickAnalyticsPlugin/create.d.ts +2 -0
  33. package/dist/custom-plugins/ClickAnalyticsPlugin/create.d.ts.map +1 -1
  34. package/dist/custom-plugins/ClickAnalyticsPlugin/index.js +1 -1
  35. package/dist/custom-plugins/GapPlugin/create.d.ts.map +1 -1
  36. package/dist/custom-plugins/GapPlugin/index.js +1 -1
  37. package/dist/custom-plugins/GroupingPlugin/create.d.ts.map +1 -1
  38. package/dist/custom-plugins/GroupingPlugin/index.js +1 -1
  39. package/dist/custom-plugins/HeatmapAnalyticsPlugin/create.d.ts +2 -0
  40. package/dist/custom-plugins/HeatmapAnalyticsPlugin/create.d.ts.map +1 -1
  41. package/dist/custom-plugins/HeatmapAnalyticsPlugin/index.js +1 -1
  42. package/dist/custom-plugins/InfiniteScrollPlugin/create.d.ts.map +1 -1
  43. package/dist/custom-plugins/InfiniteScrollPlugin/index.js +1 -1
  44. package/dist/custom-plugins/PaginationPlugin/create.d.ts.map +1 -1
  45. package/dist/custom-plugins/PaginationPlugin/index.js +1 -1
  46. package/dist/custom-plugins/RecyclePlugin/create.d.ts.map +1 -1
  47. package/dist/custom-plugins/RecyclePlugin/index.js +1 -1
  48. package/dist/custom-plugins/StatePersistencePlugin/create.d.ts.map +1 -1
  49. package/dist/custom-plugins/StatePersistencePlugin/index.js +1 -1
  50. package/dist/custom-plugins/StickyHeaderPlugin/create.d.ts.map +1 -1
  51. package/dist/custom-plugins/StickyHeaderPlugin/index.js +1 -1
  52. package/dist/custom-plugins/URLSyncPlugin/create.d.ts.map +1 -1
  53. package/dist/custom-plugins/URLSyncPlugin/index.js +1 -1
  54. package/dist/custom-plugins/index.js +5 -5
  55. package/dist/entries/core.js +1 -1
  56. package/dist/entries/plugins.js +6 -6
  57. package/dist/index.js +2 -2
  58. package/dist/presets/dashboard/index.js +2 -2
  59. package/dist/presets/photo-feed/index.js +2 -2
  60. package/dist/presets/product-feed/index.js +1 -1
  61. package/package.json +31 -23
  62. package/dist/chunks/WaterfallCore-BSXw7bl_.js +0 -581
  63. package/dist/chunks/doc-B-7dugGv.js +0 -79
  64. package/dist/chunks/doc-DJjxOYzW.js +0 -111
  65. package/dist/chunks/withPlugins-DLoKg4AP.js +0 -559
@@ -1,37 +1,39 @@
1
- import { jsx as c } from "react/jsx-runtime";
2
- function R(n = {}) {
3
- const i = n.containerRole ?? "list", s = n.itemRole ?? "listitem", o = n.enableTabIndex ?? !0, r = n.containerLabel ?? "Waterfall list", a = (e) => {
1
+ import { jsx as d } from "react/jsx-runtime";
2
+ function W(n = {}) {
3
+ const l = n.containerRole ?? "list", c = n.itemRole ?? "listitem", u = n.enableTabIndex ?? !0, b = n.containerLabel ?? "Waterfall list", a = /* @__PURE__ */ new WeakMap(), i = (e) => e.containerRef?.current ?? e.bus, s = (e) => a.get(i(e)) ?? 0, r = (e) => {
4
4
  const t = e.containerRef.current;
5
- t && (t.setAttribute("role", i), t.setAttribute("aria-label", r), t.setAttribute("aria-busy", e.isLayouting ? "true" : "false"));
5
+ t && (t.setAttribute("role", l), t.setAttribute("aria-label", b), t.setAttribute("aria-busy", e.isLayouting ? "true" : "false"));
6
6
  };
7
7
  return {
8
8
  name: "A11yPlugin",
9
9
  enabled: !0,
10
10
  hooks: {
11
11
  onMount: (e) => {
12
- a(e);
12
+ r(e);
13
13
  },
14
14
  onLayoutComplete: (e) => {
15
- a(e);
15
+ r(e);
16
16
  },
17
- renderItemWrapper: (e, t, l) => /* @__PURE__ */ c(
17
+ onItemClick: (e, t) => {
18
+ s(e) !== t && (a.set(i(e), t), e.forceUpdate?.());
19
+ },
20
+ renderItemWrapper: (e, t, o) => /* @__PURE__ */ d(
18
21
  "div",
19
22
  {
20
- role: s,
21
- "aria-posinset": l + 1,
23
+ role: c,
24
+ "aria-posinset": o + 1,
22
25
  "aria-setsize": e.itemCount,
23
- tabIndex: o ? 0 : void 0,
24
- style: { outline: "none" },
26
+ tabIndex: u ? o === s(e) ? 0 : -1 : void 0,
25
27
  children: t
26
28
  }
27
29
  )
28
30
  }
29
31
  };
30
32
  }
31
- const u = "A11yPlugin", d = "把瀑布流补成读屏可理解的列表:容器 `role=list` + `aria-label`,每项 `role=listitem` + `aria-posinset` / `aria-setsize`,并可选加 `tabIndex` 让键盘能逐项聚焦。", b = "2.0.0", m = [
33
+ const m = "A11yPlugin", p = "把瀑布流补成读屏可理解的列表:容器 `role=list` + `aria-label`,每项 `role=listitem` + `aria-posinset` / `aria-setsize`,并可选加 `tabIndex` 让键盘能逐项聚焦。", f = "2.0.0", g = [
32
34
  "ui",
33
35
  "a11y"
34
- ], p = [
36
+ ], y = [
35
37
  {
36
38
  name: "containerRole",
37
39
  type: "string",
@@ -56,7 +58,7 @@ const u = "A11yPlugin", d = "把瀑布流补成读屏可理解的列表:容器
56
58
  default: '"Waterfall list"',
57
59
  description: "容器 aria-label"
58
60
  }
59
- ], f = `// 给容器与项补 ARIA role / label / posinset,支持键盘 Tab 遍历。
61
+ ], I = `// 给容器与项补 ARIA role / label / posinset,支持键盘 Tab 遍历。
60
62
  const Waterfall = withPlugins(WaterfallCore, [
61
63
  createA11yPlugin({
62
64
  containerRole: "list",
@@ -65,28 +67,28 @@ const Waterfall = withPlugins(WaterfallCore, [
65
67
  }),
66
68
  ]);
67
69
 
68
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, y = [
70
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, R = [
69
71
  "容器 / 项 role 成对补齐",
70
72
  "aria-posinset + aria-setsize 正确标注序号",
71
73
  "键盘可逐项聚焦"
72
- ], g = [
74
+ ], A = [
73
75
  "政务 / 金融等合规站点",
74
76
  "读屏用户可用的信息流",
75
77
  "键盘操作优先的桌面端"
76
- ], x = [
78
+ ], C = [
77
79
  "项数很多时 `tabIndex=0` 会让 Tab 变长,建议配合「跳转主内容」链接使用。"
78
- ], A = {
79
- name: u,
80
- description: d,
81
- since: b,
82
- tags: m,
83
- config: p,
84
- example: f,
85
- features: y,
86
- useCases: g,
87
- notes: x
80
+ ], x = {
81
+ name: m,
82
+ description: p,
83
+ since: f,
84
+ tags: g,
85
+ config: y,
86
+ example: I,
87
+ features: R,
88
+ useCases: A,
89
+ notes: C
88
90
  };
89
91
  export {
90
- R as c,
91
- A as d
92
+ W as c,
93
+ x as d
92
94
  };
@@ -0,0 +1,126 @@
1
+ function $(u = {}) {
2
+ const p = u.mode || "hash", o = u.keys || ["pageIndex", "pageSize", "searchQuery"];
3
+ let h = null, d = !1;
4
+ const l = () => (h === null && (h = m()), h);
5
+ function m() {
6
+ try {
7
+ if (p === "hash") {
8
+ const a = window.location.hash || "", s = a.indexOf("?"), n = s >= 0 ? a.slice(s + 1) : a.replace(/^#/, ""), e = new URLSearchParams(n), t = {};
9
+ return o.forEach((c) => {
10
+ const r = e.get(c);
11
+ r !== null && (t[c] = r);
12
+ }), t;
13
+ } else {
14
+ const a = new URLSearchParams(window.location.search), s = {};
15
+ return o.forEach((n) => {
16
+ const e = a.get(n);
17
+ e !== null && (s[n] = e);
18
+ }), s;
19
+ }
20
+ } catch {
21
+ return {};
22
+ }
23
+ }
24
+ function g(a) {
25
+ try {
26
+ const s = new URLSearchParams();
27
+ o.forEach((e) => {
28
+ const t = a[e];
29
+ t != null && String(t).length > 0 && s.set(e, String(t));
30
+ });
31
+ const n = s.toString();
32
+ if (p === "hash") {
33
+ const e = window.location.hash || "", r = `#${e.replace(/^#/, "").split("?")[0] || ""}${n ? `?${n}` : ""}`;
34
+ e !== r && history.replaceState(
35
+ null,
36
+ "",
37
+ `${window.location.pathname}${window.location.search}${r}`
38
+ );
39
+ } else {
40
+ const t = window.location.pathname + (n ? `?${n}` : "") + (window.location.hash || "");
41
+ history.replaceState(null, "", t);
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: (a) => {
53
+ if (d) return a;
54
+ const s = l(), n = { ...a };
55
+ let e = !1;
56
+ return o.forEach((t) => {
57
+ s[t] !== void 0 && (n[t] = s[t], e = !0);
58
+ }), e && (d = !0), n;
59
+ },
60
+ onMount: (a) => {
61
+ a.bus?.emit("urlsync:init", l());
62
+ },
63
+ onPropsChange: (a, s, n) => {
64
+ const e = {}, t = n ?? {};
65
+ o.forEach((i) => {
66
+ const f = t[i];
67
+ f !== void 0 && (e[i] = f);
68
+ });
69
+ const c = l();
70
+ o.some(
71
+ (i) => String(e[i] ?? "") !== String(c[i] ?? "")
72
+ ) && g(e);
73
+ }
74
+ }
75
+ };
76
+ }
77
+ const w = "URLSyncPlugin", S = "props 变化时把指定键写进 URL(hash 或 search),挂载时读出来广播 `urlsync:init`。刷新与分享都能还原筛选状态。", y = "2.0.0", R = [
78
+ "ui",
79
+ "URL",
80
+ "可分享"
81
+ ], L = [
82
+ {
83
+ name: "mode",
84
+ type: '"hash" | "search"',
85
+ default: '"hash"',
86
+ description: "写 hash 还是 search"
87
+ },
88
+ {
89
+ name: "keys",
90
+ type: "string[]",
91
+ default: '["pageIndex","pageSize","searchQuery"]',
92
+ description: "要同步的 props 键"
93
+ }
94
+ ], P = `// 把分页/搜索/排序同步进 URL(hash 或 search),链接可分享。
95
+ const Waterfall = withPlugins(WaterfallCore, [
96
+ createURLSyncPlugin({
97
+ mode: "hash",
98
+ keys: ["pageIndex","pageSize","searchQuery"],
99
+ }),
100
+ ]);
101
+
102
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, U = [
103
+ "hash 模式会保留已有路由路径",
104
+ "用 replaceState,不污染后退栈",
105
+ "SSR 安全:无 window 时直接跳过"
106
+ ], x = [
107
+ "搜索结果可分享",
108
+ "后台筛选状态可刷新",
109
+ "带参数的深链"
110
+ ], v = [
111
+ "只做单向同步(props → URL)与初始读取;URL 前进后退的监听请页面自己做。"
112
+ ], I = {
113
+ name: w,
114
+ description: S,
115
+ since: y,
116
+ tags: R,
117
+ config: L,
118
+ example: P,
119
+ features: U,
120
+ useCases: x,
121
+ notes: v
122
+ };
123
+ export {
124
+ $ as c,
125
+ I as d
126
+ };
@@ -1,30 +1,42 @@
1
- function r(o) {
2
- const e = typeof window < "u" ? window.innerWidth : 1024, n = o.responsive || {};
3
- return e >= 1200 && n.xl ? n.xl : e >= 992 && n.lg ? n.lg : e >= 768 && n.md ? n.md : e < 768 && n.sm ? n.sm : {};
1
+ function p(o, t) {
2
+ const n = o.responsive || {};
3
+ return t >= 1200 && n.xl ? n.xl : t >= 992 && n.lg ? n.lg : t >= 768 && n.md ? n.md : t < 768 && n.sm ? n.sm : {};
4
4
  }
5
- function w(o) {
5
+ function W(o) {
6
+ let t = 0, n = "";
7
+ const i = (e) => {
8
+ const r = e.containerRef?.current?.clientWidth ?? 0;
9
+ if (r <= 0) return;
10
+ const a = t;
11
+ t = r;
12
+ const s = JSON.stringify(p(o, r));
13
+ a > 0 && s !== n && e.bus?.emit("props:invalidate"), n = s;
14
+ };
6
15
  return {
7
16
  name: "GapPlugin",
8
17
  priority: 50,
9
18
  enabled: !0,
10
19
  hooks: {
11
20
  transformProps: (e) => {
12
- const n = { columnGap: o.columnGap, rowGap: o.rowGap }, t = r(o), s = {
13
- columnGap: t.columnGap ?? n.columnGap ?? e.columnGap,
14
- rowGap: t.rowGap ?? n.rowGap ?? e.rowGap
21
+ const r = t > 0 ? t : typeof window < "u" ? window.innerWidth : 1024, a = { columnGap: o.columnGap, rowGap: o.rowGap }, s = p(o, r), c = {
22
+ columnGap: s.columnGap ?? a.columnGap ?? e.columnGap,
23
+ rowGap: s.rowGap ?? a.rowGap ?? e.rowGap
15
24
  };
16
- return { ...e, ...s };
25
+ return { ...e, ...c };
26
+ },
27
+ onMount: (e) => {
28
+ i(e);
17
29
  },
18
30
  onResize: (e) => {
19
- e.relayout?.();
31
+ i(e);
20
32
  }
21
33
  }
22
34
  };
23
35
  }
24
- const a = "GapPlugin", p = "把 rowGap / columnGap 收敛到一处配置,并支持按窗口宽度切换间距(窄屏 8px、宽屏 16px 这类)。", i = "2.0.0", c = [
36
+ const u = "GapPlugin", l = "把 rowGap / columnGap 收敛到一处配置,并支持按窗口宽度切换间距(窄屏 8px、宽屏 16px 这类)。", m = "2.0.0", d = [
25
37
  "layout",
26
38
  "间距"
27
- ], l = [
39
+ ], G = [
28
40
  {
29
41
  name: "columnGap",
30
42
  type: "number",
@@ -43,34 +55,34 @@ const a = "GapPlugin", p = "把 rowGap / columnGap 收敛到一处配置,并
43
55
  default: "—",
44
56
  description: "断点覆盖(按 window 宽度)"
45
57
  }
46
- ], u = `// 统一控制行/列间距,支持按断点给不同间距。
58
+ ], f = `// 统一控制行/列间距,支持按断点给不同间距。
47
59
  const Waterfall = withPlugins(WaterfallCore, [
48
60
  createGapPlugin(),
49
61
  ]);
50
62
 
51
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, m = [
63
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, w = [
52
64
  "行列间距一处配置",
53
65
  "断点覆盖(sm/md/lg/xl)",
54
66
  "不填则回退到 props"
55
- ], d = [
67
+ ], g = [
56
68
  "设计规范里间距随断点变化",
57
69
  "同一组件在不同页面用不同密度"
58
- ], G = [
70
+ ], x = [
59
71
  "断点判断用的是 window.innerWidth(间距通常跟视口走,与列数按容器算不一样)。",
60
72
  "断点是「命中即覆盖」:桌面窗口 ≥1200 又配了 responsive.lg,那就一直是 lg 的值,config.columnGap/rowGap 在这档不起作用;想让手写值生效就别给该档位配 responsive。",
61
73
  "sm 只在小屏(<768)生效,不会被当成兜底档套到桌面端。"
62
- ], f = {
63
- name: a,
64
- description: p,
65
- since: i,
66
- tags: c,
67
- config: l,
68
- example: u,
69
- features: m,
70
- useCases: d,
71
- notes: G
74
+ ], v = {
75
+ name: u,
76
+ description: l,
77
+ since: m,
78
+ tags: d,
79
+ config: G,
80
+ example: f,
81
+ features: w,
82
+ useCases: g,
83
+ notes: x
72
84
  };
73
85
  export {
74
- w as c,
75
- f as d
86
+ W as c,
87
+ v as d
76
88
  };
@@ -1,32 +1,45 @@
1
- import { jsxs as a } from "react/jsx-runtime";
2
- const p = "GROUPS";
3
- function x(i = {}) {
4
- const u = i.groupBy ?? ((e) => e?.category ?? "default"), l = i.showOverlay ?? !1, r = (e) => {
5
- const t = /* @__PURE__ */ new Map();
6
- return (e.props.items ?? []).forEach((s, n) => {
7
- const o = u(s, n);
8
- t.has(o) || t.set(o, []), t.get(o).push(n);
9
- }), e.sharedData.set(p, t), t.size > 0 && e.bus.emit("grouping:change", { groups: t }), t;
1
+ import { jsxs as u } from "react/jsx-runtime";
2
+ const d = "GROUPS", y = "GROUP_INDEX";
3
+ function B(c = {}) {
4
+ const g = c.groupBy ?? ((e) => e?.category ?? "default"), f = c.showOverlay ?? !1;
5
+ let p = null, o = null;
6
+ const m = (e, n) => {
7
+ if (e.size !== n.size) return !1;
8
+ for (const [t, s] of e) {
9
+ const r = n.get(t);
10
+ if (!r || r.length !== s.length) return !1;
11
+ }
12
+ return !0;
13
+ }, i = (e) => {
14
+ const n = e.items ?? [];
15
+ if (o && p === n) return o;
16
+ const t = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
17
+ n.forEach((h, l) => {
18
+ const a = g(h, l);
19
+ s.set(l, a), t.has(a) || t.set(a, []), t.get(a).push(l);
20
+ });
21
+ const r = o ? !m(t, o) : !0;
22
+ return p = n, o = t, e.sharedData.set(d, t), e.sharedData.set(y, s), r && t.size > 0 && e.bus.emit("grouping:change", { groups: t }), t;
10
23
  };
11
24
  return {
12
25
  name: "GroupingPlugin",
13
26
  enabled: !0,
14
27
  hooks: {
15
28
  onMount: (e) => {
16
- r(e);
29
+ i(e);
17
30
  },
18
31
  onLayoutComplete: (e) => {
19
- r(e);
32
+ i(e);
20
33
  },
21
34
  onPropsChange: (e) => {
22
- r(e);
35
+ i(e);
23
36
  },
24
37
  renderOverlay: (e) => {
25
- if (!l) return null;
26
- const t = e.sharedData.get(p) ?? /* @__PURE__ */ new Map();
27
- if (t.size === 0) return null;
28
- const s = Array.from(t.entries()).slice(0, 3);
29
- return /* @__PURE__ */ a(
38
+ if (!f) 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__ */ u(
30
43
  "div",
31
44
  {
32
45
  style: {
@@ -45,17 +58,17 @@ function x(i = {}) {
45
58
  pointerEvents: "none"
46
59
  },
47
60
  children: [
48
- /* @__PURE__ */ a("div", { style: { opacity: 0.85, marginBottom: 6 }, children: [
61
+ /* @__PURE__ */ u("div", { style: { opacity: 0.85, marginBottom: 6 }, children: [
49
62
  "分组:",
50
- t.size,
63
+ n.size,
51
64
  " 组"
52
65
  ] }),
53
- s.map(([n, o]) => /* @__PURE__ */ a("div", { children: [
54
- String(n),
66
+ t.map(([s, r]) => /* @__PURE__ */ u("div", { children: [
67
+ String(s),
55
68
  " · ",
56
- o.length,
69
+ r.length,
57
70
  " 项"
58
- ] }, String(n)))
71
+ ] }, String(s)))
59
72
  ]
60
73
  }
61
74
  );
@@ -63,10 +76,10 @@ function x(i = {}) {
63
76
  }
64
77
  };
65
78
  }
66
- const c = "GroupingPlugin", d = "用 groupBy 把项按业务字段分组,结果放进 sharedData 的 `GROUPS`(Map<组键, 索引数组>),供 StickyHeaderPlugin、分组统计条等消费。挂载即算一次,之后 props 变化重算。", g = "2.0.0", f = [
79
+ const P = "GroupingPlugin", b = "用 groupBy 把项按业务字段分组,结果放进 sharedData 的 `GROUPS`(Map<组键, 索引数组>),供 StickyHeaderPlugin、分组统计条等消费。挂载即算一次,之后 props 变化重算。", G = "2.0.0", v = [
67
80
  "ui",
68
81
  "分组"
69
- ], m = [
82
+ ], w = [
70
83
  {
71
84
  name: "groupBy",
72
85
  type: "(item, index) => string | number",
@@ -79,7 +92,7 @@ const c = "GroupingPlugin", d = "用 groupBy 把项按业务字段分组,结
79
92
  default: "false",
80
93
  description: "是否显示分组统计角标"
81
94
  }
82
- ], h = `// 按字段把项分组,结果写进 sharedData(GROUPS) 供吸顶条 / 统计用。
95
+ ], O = `// 按字段把项分组,结果写进 sharedData(GROUPS) 供吸顶条 / 统计用。
83
96
  const Waterfall = withPlugins(WaterfallCore, [
84
97
  createGroupingPlugin({
85
98
  groupBy: "item.category ?? \\"default\\"",
@@ -87,28 +100,28 @@ const Waterfall = withPlugins(WaterfallCore, [
87
100
  }),
88
101
  ]);
89
102
 
90
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, y = [
103
+ <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, x = [
91
104
  "挂载即计算(旧版只在 props 变化时算,首屏永远拿不到分组)",
92
105
  "结果写 sharedData,跨插件可读",
93
106
  "统计角标默认关闭"
94
- ], b = [
107
+ ], D = [
95
108
  "按分类分组的信息流",
96
109
  "按日期分组的时间线",
97
110
  "吸顶条显示当前分组"
98
- ], P = [
111
+ ], S = [
99
112
  "分组只产出索引映射,不改变渲染顺序;要视觉分组请自己按分组建行。"
100
- ], w = {
101
- name: c,
102
- description: d,
103
- since: g,
104
- tags: f,
105
- config: m,
106
- example: h,
107
- features: y,
108
- useCases: b,
109
- notes: P
113
+ ], C = {
114
+ name: P,
115
+ description: b,
116
+ since: G,
117
+ tags: v,
118
+ config: w,
119
+ example: O,
120
+ features: x,
121
+ useCases: D,
122
+ notes: S
110
123
  };
111
124
  export {
112
- x as c,
113
- w as d
125
+ B as c,
126
+ C as d
114
127
  };
@@ -1,41 +1,45 @@
1
- function y(s) {
2
- const e = /* @__PURE__ */ new Set(), o = () => {
3
- if (e.size <= s.poolSize) return;
4
- const t = e.values().next().value;
5
- typeof t == "number" && e.delete(t);
1
+ function v(s) {
2
+ const i = /* @__PURE__ */ new Set(), o = (n) => {
3
+ if (i.size <= s.poolSize) return;
4
+ const e = i.values().next().value;
5
+ if (typeof e == "number") {
6
+ i.delete(e);
7
+ const t = n.getItemRef(e);
8
+ t && (t.style.visibility = "hidden");
9
+ }
6
10
  };
7
11
  return {
8
12
  name: "RecyclePlugin",
9
13
  enabled: !0,
10
14
  hooks: {
11
- onItemEnterViewport: (t, n) => {
12
- const i = t.getItemRef(n);
13
- i && (i.style.visibility = "visible"), e.add(n), o();
15
+ onItemEnterViewport: (n, e) => {
16
+ const t = n.getItemRef(e);
17
+ t && (t.style.visibility = "visible"), i.add(e), o(n);
14
18
  },
15
- onItemLeaveViewport: (t, n) => {
16
- const i = t.getItemRef(n);
17
- i && (i.style.visibility = "hidden"), e.delete(n);
19
+ onItemLeaveViewport: (n, e) => {
20
+ const t = n.getItemRef(e);
21
+ t && (t.style.visibility = "hidden"), i.delete(e);
18
22
  },
19
- onItemUnmount: (t, n) => {
20
- e.delete(n);
23
+ onItemUnmount: (n, e) => {
24
+ i.delete(e);
21
25
  },
22
26
  onUnmount: () => {
23
- e.clear();
27
+ i.clear();
24
28
  }
25
29
  }
26
30
  };
27
31
  }
28
- const c = "RecyclePlugin", l = "纯绘制层优化:项离开视口就 `visibility: hidden`,回来再显示。DOM 节点不销毁,滚动位置与已加载的图片都保留,适合「项里有视频/Canvas,重建代价高」的场景。", a = "2.0.0", r = [
32
+ const l = "RecyclePlugin", c = "纯绘制层优化:项离开视口就 `visibility: hidden`,回来再显示。DOM 节点不销毁,滚动位置与已加载的图片都保留,适合「项里有视频/Canvas,重建代价高」的场景。", a = "2.0.0", r = [
29
33
  "interaction",
30
34
  "性能"
31
- ], u = [
35
+ ], m = [
32
36
  {
33
37
  name: "poolSize",
34
38
  type: "number",
35
39
  default: "—",
36
40
  description: "同时保持可见的项数上限(超出则回收最早的)"
37
41
  }
38
- ], m = `// 视口外的项设 \`visibility: hidden\`,降低长列表的绘制压力。
42
+ ], u = `// 视口外的项设 \`visibility: hidden\`,降低长列表的绘制压力。
39
43
  const Waterfall = withPlugins(WaterfallCore, [
40
44
  createRecyclePlugin(),
41
45
  ]);
@@ -48,21 +52,21 @@ const Waterfall = withPlugins(WaterfallCore, [
48
52
  "项内含视频 / canvas",
49
53
  "长列表滚动发虚",
50
54
  "低端设备省电"
51
- ], v = [
55
+ ], y = [
52
56
  "与 Core 的 `virtualize` 同开会让项被卸载又隐藏,收益互相抵消,建议只选一个。",
53
57
  "只改 visibility 不改布局,所以不会引起重排。"
54
- ], p = {
55
- name: c,
56
- description: l,
58
+ ], g = {
59
+ name: l,
60
+ description: c,
57
61
  since: a,
58
62
  tags: r,
59
- config: u,
60
- example: m,
63
+ config: m,
64
+ example: u,
61
65
  features: d,
62
66
  useCases: f,
63
- notes: v
67
+ notes: y
64
68
  };
65
69
  export {
66
- y as c,
67
- p as d
70
+ v as c,
71
+ g as d
68
72
  };