vane-waterfall 2.0.0 → 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 (121) hide show
  1. package/README.md +6 -6
  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 +4 -1
  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.d.ts +1 -1
  30. package/dist/custom-plugins/A11yPlugin/index.d.ts.map +1 -1
  31. package/dist/custom-plugins/A11yPlugin/index.js +1 -1
  32. package/dist/custom-plugins/AlignmentPlugin/index.d.ts +1 -1
  33. package/dist/custom-plugins/AlignmentPlugin/index.d.ts.map +1 -1
  34. package/dist/custom-plugins/AutoColumnPlugin/index.d.ts +1 -1
  35. package/dist/custom-plugins/AutoColumnPlugin/index.d.ts.map +1 -1
  36. package/dist/custom-plugins/BookmarkPlugin/create.d.ts.map +1 -1
  37. package/dist/custom-plugins/BookmarkPlugin/index.d.ts +1 -1
  38. package/dist/custom-plugins/BookmarkPlugin/index.d.ts.map +1 -1
  39. package/dist/custom-plugins/BookmarkPlugin/index.js +1 -1
  40. package/dist/custom-plugins/ClickAnalyticsPlugin/create.d.ts +2 -0
  41. package/dist/custom-plugins/ClickAnalyticsPlugin/create.d.ts.map +1 -1
  42. package/dist/custom-plugins/ClickAnalyticsPlugin/index.d.ts +1 -1
  43. package/dist/custom-plugins/ClickAnalyticsPlugin/index.d.ts.map +1 -1
  44. package/dist/custom-plugins/ClickAnalyticsPlugin/index.js +1 -1
  45. package/dist/custom-plugins/DebounceLayoutPlugin/index.d.ts +1 -1
  46. package/dist/custom-plugins/DebounceLayoutPlugin/index.d.ts.map +1 -1
  47. package/dist/custom-plugins/DragReorderPlugin/index.d.ts +1 -1
  48. package/dist/custom-plugins/DragReorderPlugin/index.d.ts.map +1 -1
  49. package/dist/custom-plugins/FilterPlugin/index.d.ts +1 -1
  50. package/dist/custom-plugins/FilterPlugin/index.d.ts.map +1 -1
  51. package/dist/custom-plugins/FixedHeightPlugin/index.d.ts +1 -1
  52. package/dist/custom-plugins/FixedHeightPlugin/index.d.ts.map +1 -1
  53. package/dist/custom-plugins/GapPlugin/create.d.ts.map +1 -1
  54. package/dist/custom-plugins/GapPlugin/index.d.ts +1 -1
  55. package/dist/custom-plugins/GapPlugin/index.d.ts.map +1 -1
  56. package/dist/custom-plugins/GapPlugin/index.js +1 -1
  57. package/dist/custom-plugins/GroupingPlugin/create.d.ts.map +1 -1
  58. package/dist/custom-plugins/GroupingPlugin/index.d.ts +1 -1
  59. package/dist/custom-plugins/GroupingPlugin/index.d.ts.map +1 -1
  60. package/dist/custom-plugins/GroupingPlugin/index.js +1 -1
  61. package/dist/custom-plugins/HeatmapAnalyticsPlugin/create.d.ts +2 -0
  62. package/dist/custom-plugins/HeatmapAnalyticsPlugin/create.d.ts.map +1 -1
  63. package/dist/custom-plugins/HeatmapAnalyticsPlugin/index.d.ts +1 -1
  64. package/dist/custom-plugins/HeatmapAnalyticsPlugin/index.d.ts.map +1 -1
  65. package/dist/custom-plugins/HeatmapAnalyticsPlugin/index.js +1 -1
  66. package/dist/custom-plugins/InfiniteScrollPlugin/create.d.ts.map +1 -1
  67. package/dist/custom-plugins/InfiniteScrollPlugin/index.d.ts +1 -1
  68. package/dist/custom-plugins/InfiniteScrollPlugin/index.d.ts.map +1 -1
  69. package/dist/custom-plugins/InfiniteScrollPlugin/index.js +1 -1
  70. package/dist/custom-plugins/PaginationPlugin/create.d.ts.map +1 -1
  71. package/dist/custom-plugins/PaginationPlugin/index.d.ts +1 -1
  72. package/dist/custom-plugins/PaginationPlugin/index.d.ts.map +1 -1
  73. package/dist/custom-plugins/PaginationPlugin/index.js +1 -1
  74. package/dist/custom-plugins/PinItemPlugin/index.d.ts +1 -1
  75. package/dist/custom-plugins/PinItemPlugin/index.d.ts.map +1 -1
  76. package/dist/custom-plugins/RecyclePlugin/create.d.ts.map +1 -1
  77. package/dist/custom-plugins/RecyclePlugin/index.d.ts +1 -1
  78. package/dist/custom-plugins/RecyclePlugin/index.d.ts.map +1 -1
  79. package/dist/custom-plugins/RecyclePlugin/index.js +1 -1
  80. package/dist/custom-plugins/ReducedMotionPlugin/index.d.ts +1 -1
  81. package/dist/custom-plugins/ReducedMotionPlugin/index.d.ts.map +1 -1
  82. package/dist/custom-plugins/ResponsiveColumnsPlugin/index.d.ts +1 -1
  83. package/dist/custom-plugins/ResponsiveColumnsPlugin/index.d.ts.map +1 -1
  84. package/dist/custom-plugins/ScrollAnchorPlugin/index.d.ts +1 -1
  85. package/dist/custom-plugins/ScrollAnchorPlugin/index.d.ts.map +1 -1
  86. package/dist/custom-plugins/SearchPlugin/index.d.ts +1 -1
  87. package/dist/custom-plugins/SearchPlugin/index.d.ts.map +1 -1
  88. package/dist/custom-plugins/SortPlugin/index.d.ts +1 -1
  89. package/dist/custom-plugins/SortPlugin/index.d.ts.map +1 -1
  90. package/dist/custom-plugins/StatePersistencePlugin/create.d.ts.map +1 -1
  91. package/dist/custom-plugins/StatePersistencePlugin/index.d.ts +1 -1
  92. package/dist/custom-plugins/StatePersistencePlugin/index.d.ts.map +1 -1
  93. package/dist/custom-plugins/StatePersistencePlugin/index.js +1 -1
  94. package/dist/custom-plugins/StickyHeaderPlugin/create.d.ts.map +1 -1
  95. package/dist/custom-plugins/StickyHeaderPlugin/index.d.ts +1 -1
  96. package/dist/custom-plugins/StickyHeaderPlugin/index.d.ts.map +1 -1
  97. package/dist/custom-plugins/StickyHeaderPlugin/index.js +1 -1
  98. package/dist/custom-plugins/ThrottlePlugin/index.d.ts +1 -1
  99. package/dist/custom-plugins/ThrottlePlugin/index.d.ts.map +1 -1
  100. package/dist/custom-plugins/TransitionPlugin/index.d.ts +1 -1
  101. package/dist/custom-plugins/TransitionPlugin/index.d.ts.map +1 -1
  102. package/dist/custom-plugins/URLSyncPlugin/create.d.ts.map +1 -1
  103. package/dist/custom-plugins/URLSyncPlugin/index.d.ts +1 -1
  104. package/dist/custom-plugins/URLSyncPlugin/index.d.ts.map +1 -1
  105. package/dist/custom-plugins/URLSyncPlugin/index.js +1 -1
  106. package/dist/custom-plugins/index.js +5 -5
  107. package/dist/entries/core.js +1 -1
  108. package/dist/entries/plugins.d.ts +1 -1
  109. package/dist/entries/plugins.d.ts.map +1 -1
  110. package/dist/entries/plugins.js +6 -6
  111. package/dist/index.d.ts +1 -1
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +2 -2
  114. package/dist/presets/dashboard/index.js +2 -2
  115. package/dist/presets/photo-feed/index.js +2 -2
  116. package/dist/presets/product-feed/index.js +1 -1
  117. package/package.json +32 -25
  118. package/dist/chunks/WaterfallCore-BSXw7bl_.js +0 -581
  119. package/dist/chunks/doc-B-7dugGv.js +0 -79
  120. package/dist/chunks/doc-DJjxOYzW.js +0 -111
  121. 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
  };