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
@@ -1,79 +0,0 @@
1
- function S(a = {}) {
2
- return {
3
- name: "PaginationPlugin",
4
- priority: 10,
5
- enabled: !0,
6
- hooks: {
7
- transformProps: (e) => {
8
- const t = Math.max(1, Number(e.pageIndex ?? 1)), o = Math.max(1, Number(e.pageSize ?? a.pageSize ?? 20)), s = Array.isArray(e.items) ? e.items : [], n = (t - 1) * o, i = n + o, r = s.slice(n, i);
9
- return { ...e, items: r };
10
- },
11
- onPropsChange: (e, t, o) => {
12
- const s = Math.max(1, Number(t?.pageIndex ?? 1)), n = Math.max(1, Number(o?.pageIndex ?? 1));
13
- if (((typeof o?.scrollToTopOnPageChange == "boolean" ? o.scrollToTopOnPageChange : void 0) ?? !!a.scrollToTop) && s !== n) {
14
- const l = o?.scrollToTopBehavior ?? a.scrollBehavior ?? "auto";
15
- e.scrollToTop?.({ behavior: l });
16
- }
17
- }
18
- }
19
- };
20
- }
21
- const c = "PaginationPlugin", p = "读 `props.pageIndex`(1 基)与 `props.pageSize` 切片。放在数据管线最末端,保证切的是「过滤 + 排序 + 搜索」之后的结果。", g = "2.0.0", d = [
22
- "data",
23
- "数据管线",
24
- "分页"
25
- ], m = [
26
- {
27
- name: "pageSize",
28
- type: "number",
29
- default: "props.pageSize ?? 20",
30
- description: "每页条数"
31
- },
32
- {
33
- name: "scrollToTop",
34
- type: "boolean",
35
- default: "false",
36
- description: "翻页后回顶"
37
- },
38
- {
39
- name: "scrollBehavior",
40
- type: '"auto" | "smooth"',
41
- default: '"auto"',
42
- description: "回顶行为"
43
- }
44
- ], u = `// 按 props.pageIndex / pageSize 切片,页码从 1 开始。
45
- const Waterfall = withPlugins(WaterfallCore, [
46
- createPaginationPlugin({
47
- scrollToTop: false,
48
- scrollBehavior: "auto",
49
- }),
50
- ]);
51
-
52
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, f = [
53
- "InfiniteScrollPlugin"
54
- ], h = [
55
- "1 基页码(与 UI 分页器一致)",
56
- "pageIndex 非法值自动夹到 1",
57
- "翻页自动回顶可选"
58
- ], x = [
59
- "后台列表分页",
60
- "搜索结果分页",
61
- "与 URLSyncPlugin 配合做可分享链接"
62
- ], P = [
63
- "pageSize 优先级:props.pageSize > 工厂 config.pageSize > 20。"
64
- ], T = {
65
- name: c,
66
- description: p,
67
- since: g,
68
- tags: d,
69
- config: m,
70
- example: u,
71
- conflicts: f,
72
- features: h,
73
- useCases: x,
74
- notes: P
75
- };
76
- export {
77
- S as c,
78
- T as d
79
- };
@@ -1,121 +0,0 @@
1
- import { jsxs as r } from "react/jsx-runtime";
2
- function k(l = {}) {
3
- const m = l.showOverlay ?? l.showOverlaySummary ?? !1, a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
4
- let i = !1;
5
- const c = (t) => Array.from(t.values()).reduce((e, s) => e + s, 0);
6
- return {
7
- name: "HeatmapAnalyticsPlugin",
8
- enabled: !0,
9
- getStats: () => {
10
- const t = /* @__PURE__ */ new Set([...a.keys(), ...o.keys()]);
11
- return {
12
- totalViews: c(a),
13
- totalClicks: c(o),
14
- items: Array.from(t).sort((e, s) => e - s).map((e) => ({
15
- index: e,
16
- views: a.get(e) ?? 0,
17
- clicks: o.get(e) ?? 0
18
- }))
19
- };
20
- },
21
- hooks: {
22
- onLayoutComplete: (t) => {
23
- if (i) return;
24
- const { start: e, end: s } = t.visibleRange;
25
- for (let n = e; n <= s; n++)
26
- a.set(n, (a.get(n) || 0) + 1);
27
- i = !0;
28
- },
29
- onItemEnterViewport: (t, e) => {
30
- a.set(e, (a.get(e) || 0) + 1);
31
- },
32
- onItemClick: (t, e) => {
33
- o.set(e, (o.get(e) || 0) + 1), t.forceUpdate?.();
34
- },
35
- renderOverlay: () => {
36
- if (!m) return null;
37
- const t = Array.from(a.values()).reduce((s, n) => s + n, 0), e = Array.from(o.values()).reduce((s, n) => s + n, 0);
38
- return /* @__PURE__ */ r(
39
- "div",
40
- {
41
- style: {
42
- position: "sticky",
43
- top: 0,
44
- zIndex: 100,
45
- display: "flex",
46
- gap: 12,
47
- alignItems: "center",
48
- padding: "6px 10px",
49
- background: "rgba(0,0,0,0.6)",
50
- color: "white",
51
- borderRadius: 8,
52
- fontSize: 12,
53
- marginBottom: 8
54
- },
55
- children: [
56
- /* @__PURE__ */ r("span", { children: [
57
- "曝光总计: ",
58
- t
59
- ] }),
60
- /* @__PURE__ */ r("span", { children: [
61
- "点击总计: ",
62
- e
63
- ] })
64
- ]
65
- }
66
- );
67
- }
68
- }
69
- };
70
- }
71
- const u = "HeatmapAnalyticsPlugin", p = "统计每项进入视口次数与点击次数,可选顶部汇总条,`getStats()` 取出每项明细。曝光是瀑布流里最容易统计错的东西(滚动时反复进出视口),交给插件比自己写 IntersectionObserver 少踩坑。", y = "2.0.0", d = [
72
- "interaction",
73
- "埋点",
74
- "曝光"
75
- ], f = [
76
- {
77
- name: "showOverlay",
78
- type: "boolean",
79
- default: "false",
80
- description: "是否显示顶部汇总条"
81
- },
82
- {
83
- name: "showOverlaySummary",
84
- type: "boolean",
85
- default: "—",
86
- description: "showOverlay 的旧别名"
87
- }
88
- ], g = `// 统计每项曝光次数与点击次数,可显示汇总条。
89
- const Waterfall = withPlugins(WaterfallCore, [
90
- createHeatmapAnalyticsPlugin({
91
- showOverlay: false,
92
- }),
93
- ]);
94
-
95
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, w = [
96
- "按项的曝光 / 点击双计数",
97
- "首屏曝光在 onLayoutComplete 补一次",
98
- "getStats() 输出可上报的扁平结构"
99
- ], v = [
100
- "信息流曝光分析",
101
- "广告位可见性验证",
102
- "调试曝光策略"
103
- ], h = [
104
- "首屏曝光靠 onLayoutComplete 补一次,否则第一帧显示 0。",
105
- "真实上报要自己做去重与批次(插件只负责计数,不区分「同一项第几次进入」)。",
106
- "计数只在内存里,刷新即清零 —— 定时取 getStats() 上报。"
107
- ], O = {
108
- name: u,
109
- description: p,
110
- since: y,
111
- tags: d,
112
- config: f,
113
- example: g,
114
- features: w,
115
- useCases: v,
116
- notes: h
117
- };
118
- export {
119
- k as c,
120
- O as d
121
- };
@@ -1,114 +0,0 @@
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;
10
- };
11
- return {
12
- name: "GroupingPlugin",
13
- enabled: !0,
14
- hooks: {
15
- onMount: (e) => {
16
- r(e);
17
- },
18
- onLayoutComplete: (e) => {
19
- r(e);
20
- },
21
- onPropsChange: (e) => {
22
- r(e);
23
- },
24
- 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(
30
- "div",
31
- {
32
- style: {
33
- position: "absolute",
34
- top: 12,
35
- left: 12,
36
- zIndex: 99,
37
- background: "#111827",
38
- color: "#fff",
39
- padding: "10px 12px",
40
- borderRadius: 8,
41
- boxShadow: "0 4px 12px rgba(0,0,0,0.25)",
42
- border: "1px solid rgba(255,255,255,0.15)",
43
- minWidth: 150,
44
- fontSize: 12,
45
- pointerEvents: "none"
46
- },
47
- children: [
48
- /* @__PURE__ */ a("div", { style: { opacity: 0.85, marginBottom: 6 }, children: [
49
- "分组:",
50
- t.size,
51
- " 组"
52
- ] }),
53
- s.map(([n, o]) => /* @__PURE__ */ a("div", { children: [
54
- String(n),
55
- " · ",
56
- o.length,
57
- " 项"
58
- ] }, String(n)))
59
- ]
60
- }
61
- );
62
- }
63
- }
64
- };
65
- }
66
- const c = "GroupingPlugin", d = "用 groupBy 把项按业务字段分组,结果放进 sharedData 的 `GROUPS`(Map<组键, 索引数组>),供 StickyHeaderPlugin、分组统计条等消费。挂载即算一次,之后 props 变化重算。", g = "2.0.0", f = [
67
- "ui",
68
- "分组"
69
- ], m = [
70
- {
71
- name: "groupBy",
72
- type: "(item, index) => string | number",
73
- default: 'item.category ?? "default"',
74
- description: "分组函数"
75
- },
76
- {
77
- name: "showOverlay",
78
- type: "boolean",
79
- default: "false",
80
- description: "是否显示分组统计角标"
81
- }
82
- ], h = `// 按字段把项分组,结果写进 sharedData(GROUPS) 供吸顶条 / 统计用。
83
- const Waterfall = withPlugins(WaterfallCore, [
84
- createGroupingPlugin({
85
- groupBy: "item.category ?? \\"default\\"",
86
- showOverlay: false,
87
- }),
88
- ]);
89
-
90
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, y = [
91
- "挂载即计算(旧版只在 props 变化时算,首屏永远拿不到分组)",
92
- "结果写 sharedData,跨插件可读",
93
- "统计角标默认关闭"
94
- ], b = [
95
- "按分类分组的信息流",
96
- "按日期分组的时间线",
97
- "吸顶条显示当前分组"
98
- ], P = [
99
- "分组只产出索引映射,不改变渲染顺序;要视觉分组请自己按分组建行。"
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
110
- };
111
- export {
112
- x as c,
113
- w as d
114
- };
@@ -1,91 +0,0 @@
1
- function v(s = {}) {
2
- const c = s.storageKey || "waterfall-bookmark", l = s.scrollBehavior || "smooth", u = (r) => {
3
- const e = r;
4
- if (!e) return !1;
5
- const n = e.tagName?.toLowerCase(), a = (e.getAttribute && e.getAttribute("contenteditable")) === "true";
6
- return n === "input" || n === "textarea" || a;
7
- };
8
- return {
9
- name: "BookmarkPlugin",
10
- enabled: !0,
11
- hooks: {
12
- onMount: (r) => {
13
- const e = (n) => {
14
- if (u(n.target)) return;
15
- const a = (n.key || "").toLowerCase(), i = n.code || "";
16
- if (a === "b" || i === "KeyB") {
17
- const t = r.containerRef?.current || null;
18
- let o = 0;
19
- t && t.scrollHeight > t.clientHeight ? o = t.scrollTop : o = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
20
- try {
21
- localStorage.setItem(c, String(Math.max(0, o)));
22
- } catch {
23
- }
24
- } else if (a === "r" || i === "KeyR") {
25
- let t = 0;
26
- try {
27
- const d = localStorage.getItem(c) || "0";
28
- t = Math.max(0, Number(d) || 0);
29
- } catch {
30
- }
31
- const o = r.containerRef?.current || null;
32
- o && o.scrollHeight > o.clientHeight ? o.scrollTo({ top: t, behavior: l }) : window.scrollTo({ top: t, behavior: l });
33
- }
34
- };
35
- return window.addEventListener("keydown", e, { capture: !0 }), document.addEventListener("keydown", e, { capture: !0 }), () => {
36
- window.removeEventListener("keydown", e, { capture: !0 }), document.removeEventListener("keydown", e, { capture: !0 });
37
- };
38
- }
39
- }
40
- };
41
- }
42
- const m = "BookmarkPlugin", g = "长列表读到一半要跳走时按 **B** 存位置,回来按 **R** 复原。焦点在输入框/可编辑区域时不拦截按键。", f = "2.0.0", k = [
43
- "ui",
44
- "滚动",
45
- "快捷键"
46
- ], p = [
47
- {
48
- name: "storageKey",
49
- type: "string",
50
- default: '"waterfall-bookmark"',
51
- description: "localStorage 键名"
52
- },
53
- {
54
- name: "scrollBehavior",
55
- type: '"auto" | "smooth"',
56
- default: '"smooth"',
57
- description: "恢复时的滚动行为"
58
- }
59
- ], h = `// 按 B 记录滚动位置、按 R 跳回(localStorage),忽略输入框按键。
60
- const Waterfall = withPlugins(WaterfallCore, [
61
- createBookmarkPlugin({
62
- storageKey: "waterfall-bookmark",
63
- scrollBehavior: "smooth",
64
- }),
65
- ]);
66
-
67
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, w = [
68
- "B 存 / R 取,零 UI 侵入",
69
- "自动区分容器滚动与页面滚动",
70
- "输入框内不误触"
71
- ], y = [
72
- "长文列表阅读",
73
- "后台大表格浏览",
74
- "演示时快速复位"
75
- ], b = [
76
- "键名全局共用,一个页面里多处瀑布流请各自传不同的 storageKey。"
77
- ], B = {
78
- name: m,
79
- description: g,
80
- since: f,
81
- tags: k,
82
- config: p,
83
- example: h,
84
- features: w,
85
- useCases: y,
86
- notes: b
87
- };
88
- export {
89
- v as c,
90
- B as d
91
- };
@@ -1,88 +0,0 @@
1
- function C(t = {}) {
2
- const c = t.fields ?? [];
3
- return {
4
- name: "SearchPlugin",
5
- priority: 20,
6
- enabled: !0,
7
- hooks: {
8
- transformProps: (e) => {
9
- const s = String(e.searchQuery ?? "").trim(), o = Array.isArray(e.items) ? e.items : [];
10
- if (!s) return e;
11
- const n = s.toLowerCase(), a = o.filter((r) => {
12
- if (typeof r != "object" || r === null) return !1;
13
- const i = c.length > 0 ? c : Object.keys(r);
14
- for (const l of i) {
15
- const u = r[l];
16
- if (u != null && String(u).toLowerCase().includes(n)) return !0;
17
- }
18
- return !1;
19
- });
20
- return { ...e, items: a };
21
- },
22
- onPropsChange: (e, s, o) => {
23
- const n = String(s?.searchQuery ?? ""), a = String(o?.searchQuery ?? "");
24
- if (((typeof o?.scrollToTopOnSearchChange == "boolean" ? o.scrollToTopOnSearchChange : void 0) ?? !!t.scrollToTop) && n !== a) {
25
- const l = o?.scrollToTopBehavior ?? t.scrollBehavior ?? "auto";
26
- e.scrollToTop?.({ behavior: l });
27
- }
28
- }
29
- }
30
- };
31
- }
32
- const f = "SearchPlugin", d = "读取 `props.searchQuery`,在指定字段上做大小写不敏感的 `includes` 匹配。没指定字段就对对象的全部自有字段匹配。", h = "2.0.0", m = [
33
- "data",
34
- "数据管线",
35
- "搜索"
36
- ], p = [
37
- {
38
- name: "fields",
39
- type: "(keyof T)[]",
40
- default: "[]",
41
- description: "参与匹配的字段;空则匹配全部自有字段"
42
- },
43
- {
44
- name: "scrollToTop",
45
- type: "boolean",
46
- default: "false",
47
- description: "关键词变化后回顶"
48
- },
49
- {
50
- name: "scrollBehavior",
51
- type: '"auto" | "smooth"',
52
- default: '"auto"',
53
- description: "回顶行为"
54
- }
55
- ], y = `// 按 props.searchQuery 做大小写不敏感的多字段包含匹配。
56
- const Waterfall = withPlugins(WaterfallCore, [
57
- createSearchPlugin({
58
- fields: [],
59
- scrollToTop: false,
60
- scrollBehavior: "auto",
61
- }),
62
- ]);
63
-
64
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, g = [
65
- "大小写不敏感",
66
- "多字段 OR 匹配",
67
- "空关键词直接放行(不触发过滤)"
68
- ], T = [
69
- "站内搜索结果页",
70
- "后台列表即时搜索",
71
- "商品名 / 店铺名联合搜索"
72
- ], S = [
73
- "纯前端 `includes`,不排序也不做拼音;要相关性排序请在 Search 之后接 SortPlugin。"
74
- ], b = {
75
- name: f,
76
- description: d,
77
- since: h,
78
- tags: m,
79
- config: p,
80
- example: y,
81
- features: g,
82
- useCases: T,
83
- notes: S
84
- };
85
- export {
86
- C as c,
87
- b as d
88
- };
@@ -1,68 +0,0 @@
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);
6
- };
7
- return {
8
- name: "RecyclePlugin",
9
- enabled: !0,
10
- hooks: {
11
- onItemEnterViewport: (t, n) => {
12
- const i = t.getItemRef(n);
13
- i && (i.style.visibility = "visible"), e.add(n), o();
14
- },
15
- onItemLeaveViewport: (t, n) => {
16
- const i = t.getItemRef(n);
17
- i && (i.style.visibility = "hidden"), e.delete(n);
18
- },
19
- onItemUnmount: (t, n) => {
20
- e.delete(n);
21
- },
22
- onUnmount: () => {
23
- e.clear();
24
- }
25
- }
26
- };
27
- }
28
- const c = "RecyclePlugin", l = "纯绘制层优化:项离开视口就 `visibility: hidden`,回来再显示。DOM 节点不销毁,滚动位置与已加载的图片都保留,适合「项里有视频/Canvas,重建代价高」的场景。", a = "2.0.0", r = [
29
- "interaction",
30
- "性能"
31
- ], u = [
32
- {
33
- name: "poolSize",
34
- type: "number",
35
- default: "—",
36
- description: "同时保持可见的项数上限(超出则回收最早的)"
37
- }
38
- ], m = `// 视口外的项设 \`visibility: hidden\`,降低长列表的绘制压力。
39
- const Waterfall = withPlugins(WaterfallCore, [
40
- createRecyclePlugin(),
41
- ]);
42
-
43
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, d = [
44
- "不销毁 DOM,只隐藏",
45
- "项内媒体不重新加载",
46
- "与虚拟化正交(一个省绘制、一个省节点)"
47
- ], f = [
48
- "项内含视频 / canvas",
49
- "长列表滚动发虚",
50
- "低端设备省电"
51
- ], v = [
52
- "与 Core 的 `virtualize` 同开会让项被卸载又隐藏,收益互相抵消,建议只选一个。",
53
- "只改 visibility 不改布局,所以不会引起重排。"
54
- ], p = {
55
- name: c,
56
- description: l,
57
- since: a,
58
- tags: r,
59
- config: u,
60
- example: m,
61
- features: d,
62
- useCases: f,
63
- notes: v
64
- };
65
- export {
66
- y as c,
67
- p as d
68
- };
@@ -1,111 +0,0 @@
1
- function L(i = {}) {
2
- const h = i.mode || "hash", r = i.keys || ["pageIndex", "pageSize", "searchQuery"];
3
- function l() {
4
- try {
5
- if (h === "hash") {
6
- const s = window.location.hash || "", t = s.indexOf("?"), a = t >= 0 ? s.slice(t + 1) : s.replace(/^#/, ""), e = new URLSearchParams(a), n = {};
7
- return r.forEach((c) => {
8
- const o = e.get(c);
9
- o !== null && (n[c] = o);
10
- }), n;
11
- } else {
12
- const s = new URLSearchParams(window.location.search), t = {};
13
- return r.forEach((a) => {
14
- const e = s.get(a);
15
- e !== null && (t[a] = e);
16
- }), t;
17
- }
18
- } catch {
19
- return {};
20
- }
21
- }
22
- function p(s) {
23
- try {
24
- const t = new URLSearchParams();
25
- r.forEach((e) => {
26
- const n = s[e];
27
- n != null && String(n).length > 0 && t.set(e, String(n));
28
- });
29
- const a = t.toString();
30
- if (h === "hash") {
31
- const e = window.location.hash || "", o = `#${e.replace(/^#/, "").split("?")[0] || ""}${a ? `?${a}` : ""}`;
32
- e !== o && history.replaceState(
33
- null,
34
- "",
35
- `${window.location.pathname}${window.location.search}${o}`
36
- );
37
- } else {
38
- const n = window.location.pathname + (a ? `?${a}` : "") + (window.location.hash || "");
39
- history.replaceState(null, "", n);
40
- }
41
- } catch {
42
- }
43
- }
44
- return {
45
- name: "URLSyncPlugin",
46
- enabled: !0,
47
- hooks: {
48
- onMount: (s) => {
49
- const t = l();
50
- s.bus?.emit("urlsync:init", t);
51
- },
52
- onPropsChange: (s, t, a) => {
53
- const e = {}, n = a ?? {};
54
- r.forEach((c) => {
55
- const o = n[c];
56
- o !== void 0 && (e[c] = o);
57
- }), p(e);
58
- }
59
- }
60
- };
61
- }
62
- const u = "URLSyncPlugin", d = "props 变化时把指定键写进 URL(hash 或 search),挂载时读出来广播 `urlsync:init`。刷新与分享都能还原筛选状态。", m = "2.0.0", w = [
63
- "ui",
64
- "URL",
65
- "可分享"
66
- ], f = [
67
- {
68
- name: "mode",
69
- type: '"hash" | "search"',
70
- default: '"hash"',
71
- description: "写 hash 还是 search"
72
- },
73
- {
74
- name: "keys",
75
- type: "string[]",
76
- default: '["pageIndex","pageSize","searchQuery"]',
77
- description: "要同步的 props 键"
78
- }
79
- ], g = `// 把分页/搜索/排序同步进 URL(hash 或 search),链接可分享。
80
- const Waterfall = withPlugins(WaterfallCore, [
81
- createURLSyncPlugin({
82
- mode: "hash",
83
- keys: ["pageIndex","pageSize","searchQuery"],
84
- }),
85
- ]);
86
-
87
- <Waterfall items={items} renderItem={(item) => <Card data={item} />} />;`, S = [
88
- "hash 模式会保留已有路由路径",
89
- "用 replaceState,不污染后退栈",
90
- "SSR 安全:无 window 时直接跳过"
91
- ], y = [
92
- "搜索结果可分享",
93
- "后台筛选状态可刷新",
94
- "带参数的深链"
95
- ], R = [
96
- "只做单向同步(props → URL)与初始读取;URL 前进后退的监听请页面自己做。"
97
- ], U = {
98
- name: u,
99
- description: d,
100
- since: m,
101
- tags: w,
102
- config: f,
103
- example: g,
104
- features: S,
105
- useCases: y,
106
- notes: R
107
- };
108
- export {
109
- L as c,
110
- U as d
111
- };