bj-web-components 0.2.26 → 0.2.28

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 (109) hide show
  1. package/dist/favicon.ico +0 -0
  2. package/dist/file.svg +1 -0
  3. package/dist/globe.svg +1 -0
  4. package/dist/index.d.ts +1141 -0
  5. package/dist/index.js +51 -0
  6. package/dist/index.mjs +51 -0
  7. package/dist/miniapp.d.ts +1 -0
  8. package/dist/miniapp.js +1 -0
  9. package/dist/miniapp.mjs +1 -0
  10. package/dist/mobile.d.ts +1 -0
  11. package/dist/mobile.js +1 -0
  12. package/dist/mobile.mjs +1 -0
  13. package/dist/next.svg +1 -0
  14. package/dist/react.d.ts +1 -0
  15. package/dist/react.js +1 -0
  16. package/dist/react.mjs +1 -0
  17. package/dist/shared.d.ts +1 -0
  18. package/dist/shared.js +1 -0
  19. package/dist/shared.mjs +1 -0
  20. package/dist/style.css +3744 -0
  21. package/dist/vercel.svg +1 -0
  22. package/dist/web/BasicInput/BInput.js +208 -0
  23. package/dist/web/BasicInput/BInput.mjs +209 -0
  24. package/dist/web/BasicInput/utils.js +47 -0
  25. package/dist/web/BasicInput/utils.mjs +47 -0
  26. package/dist/web/CategoryDropdown/CategoryDropdown.js +307 -0
  27. package/dist/web/CategoryDropdown/CategoryDropdown.mjs +308 -0
  28. package/dist/web/CheckBox/BCheckBox.js +116 -0
  29. package/dist/web/CheckBox/BCheckBox.mjs +117 -0
  30. package/dist/web/CheckBox/Group.js +73 -0
  31. package/dist/web/CheckBox/Group.mjs +74 -0
  32. package/dist/web/CheckBox/context.js +5 -0
  33. package/dist/web/CheckBox/context.mjs +5 -0
  34. package/dist/web/CheckBox/index.js +8 -0
  35. package/dist/web/CheckBox/index.mjs +8 -0
  36. package/dist/web/Dropdown/BDropdown.js +186 -0
  37. package/dist/web/Dropdown/BDropdown.mjs +186 -0
  38. package/dist/web/EmptyInputBox/EmptyInputBox.js +77 -0
  39. package/dist/web/EmptyInputBox/EmptyInputBox.mjs +78 -0
  40. package/dist/web/FileCard/FileCard.js +157 -0
  41. package/dist/web/FileCard/FileCard.mjs +158 -0
  42. package/dist/web/Icon/Icon.js +9 -0
  43. package/dist/web/Icon/Icon.mjs +10 -0
  44. package/dist/web/Input/Input.js +181 -0
  45. package/dist/web/Input/Input.mjs +182 -0
  46. package/dist/web/InputNumber/BInputNumber.js +311 -0
  47. package/dist/web/InputNumber/BInputNumber.mjs +312 -0
  48. package/dist/web/InputNumber/StepHandler.js +69 -0
  49. package/dist/web/InputNumber/StepHandler.mjs +70 -0
  50. package/dist/web/InputNumber/hooks/useCursor.js +40 -0
  51. package/dist/web/InputNumber/hooks/useCursor.mjs +41 -0
  52. package/dist/web/InputNumber/hooks/useFrame.js +12 -0
  53. package/dist/web/InputNumber/hooks/useFrame.mjs +13 -0
  54. package/dist/web/InputNumber/utils/decimal.js +147 -0
  55. package/dist/web/InputNumber/utils/decimal.mjs +147 -0
  56. package/dist/web/Modal/Modal.js +84 -0
  57. package/dist/web/Modal/Modal.mjs +85 -0
  58. package/dist/web/OverlayScrollbar/BOverlayScrollbar.js +232 -0
  59. package/dist/web/OverlayScrollbar/BOverlayScrollbar.mjs +233 -0
  60. package/dist/web/Pagination/Pagination.js +328 -0
  61. package/dist/web/Pagination/Pagination.mjs +329 -0
  62. package/dist/web/ProductField/ProductField.js +272 -0
  63. package/dist/web/ProductField/ProductField.mjs +273 -0
  64. package/dist/web/ProductField/arrow-up.svg.js +3 -0
  65. package/dist/web/ProductField/arrow-up.svg.mjs +4 -0
  66. package/dist/web/ProductField/checkbox-no.svg.js +3 -0
  67. package/dist/web/ProductField/checkbox-no.svg.mjs +4 -0
  68. package/dist/web/ProductField/checkbox-ok.svg.js +3 -0
  69. package/dist/web/ProductField/checkbox-ok.svg.mjs +4 -0
  70. package/dist/web/ProductField/no_data_light.svg.js +3 -0
  71. package/dist/web/ProductField/no_data_light.svg.mjs +4 -0
  72. package/dist/web/ProductField/search.svg.js +3 -0
  73. package/dist/web/ProductField/search.svg.mjs +4 -0
  74. package/dist/web/ProductField/sort.svg.js +3 -0
  75. package/dist/web/ProductField/sort.svg.mjs +4 -0
  76. package/dist/web/SkuInputCard/SkuInputCard.js +276 -0
  77. package/dist/web/SkuInputCard/SkuInputCard.mjs +277 -0
  78. package/dist/web/SkuInputCard/spin_loading_red.gif.js +3 -0
  79. package/dist/web/SkuInputCard/spin_loading_red.gif.mjs +4 -0
  80. package/dist/web/Switch/Switch.js +70 -0
  81. package/dist/web/Switch/Switch.mjs +71 -0
  82. package/dist/web/Table/BTable.js +950 -0
  83. package/dist/web/Table/BTable.mjs +950 -0
  84. package/dist/web/Table/Column.js +5 -0
  85. package/dist/web/Table/Column.mjs +6 -0
  86. package/dist/web/Table/ColumnGroup.js +5 -0
  87. package/dist/web/Table/ColumnGroup.mjs +6 -0
  88. package/dist/web/Table/utils/columns.js +48 -0
  89. package/dist/web/Table/utils/columns.mjs +48 -0
  90. package/dist/web/Table/utils/sortFilter.js +84 -0
  91. package/dist/web/Table/utils/sortFilter.mjs +84 -0
  92. package/dist/web/Tabs/BTabs.js +150 -0
  93. package/dist/web/Tabs/BTabs.mjs +150 -0
  94. package/dist/web/Tabs/TabPane.js +8 -0
  95. package/dist/web/Tabs/TabPane.mjs +8 -0
  96. package/dist/web/Tooltip/ConfirmTooltip.js +26 -0
  97. package/dist/web/Tooltip/ConfirmTooltip.mjs +27 -0
  98. package/dist/web/Tooltip/ContentTooltip.js +94 -0
  99. package/dist/web/Tooltip/ContentTooltip.mjs +95 -0
  100. package/dist/web/Tooltip/ProgressTooltip.js +36 -0
  101. package/dist/web/Tooltip/ProgressTooltip.mjs +37 -0
  102. package/dist/web/Tooltip/TooltipWrapper.js +12 -0
  103. package/dist/web/Tooltip/TooltipWrapper.mjs +13 -0
  104. package/dist/web/Tooltip/useAutoPlacement.js +41 -0
  105. package/dist/web/Tooltip/useAutoPlacement.mjs +41 -0
  106. package/dist/web.d.ts +1141 -0
  107. package/dist/web.js +51 -0
  108. package/dist/web.mjs +51 -0
  109. package/package.json +1 -1
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const react = require("react");
4
+ const reactDom = require("react-dom");
5
+ ;/* empty css */
6
+ ;/* empty css */
7
+ const ContentTooltip = require("../Tooltip/ContentTooltip.js");
8
+ const TooltipWrapper = require("../Tooltip/TooltipWrapper.js");
9
+ function TruncatedTooltip({
10
+ text,
11
+ spanClassName,
12
+ wrapperStyle,
13
+ placement = "top",
14
+ getPopupContainer,
15
+ trailing
16
+ }) {
17
+ const [visible, setVisible] = react.useState(false);
18
+ const wrapperRef = react.useRef(null);
19
+ const spanRef = react.useRef(null);
20
+ const [anchorRect, setAnchorRect] = react.useState(null);
21
+ function handleMouseEnter() {
22
+ var _a;
23
+ const el = spanRef.current;
24
+ if (el && el.scrollWidth > el.offsetWidth) {
25
+ setAnchorRect(((_a = wrapperRef.current) == null ? void 0 : _a.getBoundingClientRect()) ?? null);
26
+ setVisible(true);
27
+ }
28
+ }
29
+ return /* @__PURE__ */ jsxRuntime.jsxs(TooltipWrapper, { ref: wrapperRef, style: wrapperStyle, children: [
30
+ /* @__PURE__ */ jsxRuntime.jsx(
31
+ "span",
32
+ {
33
+ ref: spanRef,
34
+ className: spanClassName,
35
+ onMouseEnter: handleMouseEnter,
36
+ onMouseLeave: () => setVisible(false),
37
+ children: text
38
+ }
39
+ ),
40
+ trailing,
41
+ visible && anchorRect && reactDom.createPortal(
42
+ /* @__PURE__ */ jsxRuntime.jsx(
43
+ "span",
44
+ {
45
+ style: {
46
+ position: "fixed",
47
+ top: anchorRect.top,
48
+ left: anchorRect.left,
49
+ width: anchorRect.width,
50
+ height: anchorRect.height,
51
+ display: "block",
52
+ pointerEvents: "none",
53
+ zIndex: 9999999999
54
+ },
55
+ children: /* @__PURE__ */ jsxRuntime.jsx(ContentTooltip, { content: text, placement, className: "bu-category-dropdown__tooltip" })
56
+ }
57
+ ),
58
+ (getPopupContainer == null ? void 0 : getPopupContainer()) ?? document.body
59
+ )
60
+ ] });
61
+ }
62
+ function ChevronDown() {
63
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.57345 8.828C5.41074 8.66528 5.41074 8.40152 5.57345 8.2388C5.73617 8.07608 5.99993 8.07608 6.16265 8.2388L10.0323 12.1084L13.8349 8.24124C13.9963 8.0772 14.26 8.07503 14.4241 8.23636C14.5881 8.39771 14.5903 8.66149 14.429 8.82555L10.5282 12.7924C10.2576 13.0675 9.81477 13.0694 9.54196 12.7966L5.57345 8.828Z", fill: "#333333" }) });
64
+ }
65
+ function ChevronRight() {
66
+ return (
67
+ // <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
68
+ // <path d="M6 3.5L10.5 8L6 12.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
69
+ // </svg>
70
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { class: "icon", viewBox: "0 0 1024 1024", version: "1.1", xmlns: "http://www.w3.org/2000/svg", "p-id": "55697", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M451.854222 285.361778A21.333333 21.333333 0 1 0 421.688889 315.52l198.115555 198.122667-197.994666 194.702222a21.333333 21.333333 0 0 0 29.916444 30.414222l203.107556-199.722667a35.555556 35.555556 0 0 0 0.213333-50.488888L451.854222 285.354667z", "p-id": "55698" }) })
71
+ );
72
+ }
73
+ function buildColumns(data, value) {
74
+ var _a;
75
+ const cols = [data];
76
+ let current = data;
77
+ for (let i = 0; i < value.length; i++) {
78
+ const selected = current.find((item) => item.value === value[i]);
79
+ if ((_a = selected == null ? void 0 : selected.children) == null ? void 0 : _a.length) {
80
+ cols.push(selected.children);
81
+ current = selected.children;
82
+ } else {
83
+ break;
84
+ }
85
+ }
86
+ return cols;
87
+ }
88
+ function buildPath(data, value) {
89
+ const path = [];
90
+ let items = data;
91
+ for (const v of value) {
92
+ const found = items.find((x) => x.value === v);
93
+ if (!found) break;
94
+ path.push(found);
95
+ items = found.children ?? [];
96
+ }
97
+ return path;
98
+ }
99
+ function BuCategoryDropdown({
100
+ data,
101
+ value = [],
102
+ onChange,
103
+ placeholder = "请选择分类",
104
+ disabled = false,
105
+ maxVisible = 6,
106
+ className,
107
+ style,
108
+ getPopupContainer,
109
+ dropdownStyle: customDropdownStyle
110
+ }) {
111
+ const [open, setOpen] = react.useState(false);
112
+ const [navValue, setNavValue] = react.useState(value);
113
+ const rootRef = react.useRef(null);
114
+ const dropdownRef = react.useRef(null);
115
+ const panelRef = react.useRef(null);
116
+ const wasOpenRef = react.useRef(false);
117
+ const [dropdownStyle, setDropdownStyle] = react.useState({});
118
+ const [colWidth, setColWidth] = react.useState();
119
+ const updatePosition = react.useCallback(() => {
120
+ var _a;
121
+ if (!rootRef.current) return;
122
+ const rect = rootRef.current.getBoundingClientRect();
123
+ let maxZ = 0;
124
+ let el = rootRef.current.parentElement;
125
+ while (el && el !== document.documentElement) {
126
+ const selfZ = parseInt(window.getComputedStyle(el).zIndex, 10);
127
+ if (!isNaN(selfZ) && selfZ > maxZ) maxZ = selfZ;
128
+ if (el.parentElement) {
129
+ for (const sibling of el.parentElement.children) {
130
+ if (sibling === el || !(sibling instanceof HTMLElement)) continue;
131
+ const sibZ = parseInt(window.getComputedStyle(sibling).zIndex, 10);
132
+ if (!isNaN(sibZ) && sibZ > maxZ) maxZ = sibZ;
133
+ }
134
+ }
135
+ el = el.parentElement;
136
+ }
137
+ const panelHeight = ((_a = panelRef.current) == null ? void 0 : _a.offsetHeight) ?? 0;
138
+ const spaceBelow = window.innerHeight - rect.bottom;
139
+ const spaceAbove = rect.top;
140
+ const flipToTop = panelHeight > 0 && spaceBelow < panelHeight + 4 && spaceAbove > spaceBelow;
141
+ setDropdownStyle({
142
+ position: "fixed",
143
+ top: flipToTop ? rect.top - panelHeight - 4 : rect.bottom + 4,
144
+ left: rect.left,
145
+ zIndex: maxZ > 0 ? maxZ + 10 : 1100,
146
+ ...customDropdownStyle
147
+ });
148
+ }, [customDropdownStyle]);
149
+ react.useLayoutEffect(() => {
150
+ if (open) {
151
+ updatePosition();
152
+ }
153
+ }, [open, navValue, updatePosition]);
154
+ react.useLayoutEffect(() => {
155
+ const justOpened = open && !wasOpenRef.current;
156
+ wasOpenRef.current = open;
157
+ if (!open || !panelRef.current) return;
158
+ const cols = panelRef.current.querySelectorAll(".bu-category-dropdown__col");
159
+ cols.forEach((col) => {
160
+ col.style.width = "";
161
+ });
162
+ let max = 0;
163
+ cols.forEach((col) => {
164
+ if (col.offsetWidth > max) max = col.offsetWidth;
165
+ });
166
+ const next = justOpened ? max : Math.max(colWidth ?? 0, max);
167
+ cols.forEach((col) => {
168
+ col.style.width = next ? `${next}px` : "";
169
+ });
170
+ if (next !== colWidth) setColWidth(next || void 0);
171
+ }, [open, navValue]);
172
+ react.useEffect(() => {
173
+ if (!open) return;
174
+ function handleClickOutside(e) {
175
+ var _a, _b;
176
+ const target = e.target;
177
+ if (((_a = rootRef.current) == null ? void 0 : _a.contains(target)) || ((_b = dropdownRef.current) == null ? void 0 : _b.contains(target))) {
178
+ return;
179
+ }
180
+ setOpen(false);
181
+ }
182
+ function handleScroll() {
183
+ setOpen(false);
184
+ }
185
+ document.addEventListener("mousedown", handleClickOutside);
186
+ document.addEventListener("scroll", handleScroll, true);
187
+ window.addEventListener("resize", updatePosition);
188
+ return () => {
189
+ document.removeEventListener("mousedown", handleClickOutside);
190
+ document.removeEventListener("scroll", handleScroll, true);
191
+ window.removeEventListener("resize", updatePosition);
192
+ };
193
+ }, [open, updatePosition]);
194
+ const path = buildPath(data, value);
195
+ const hasValue = path.length > 0;
196
+ const triggerLabel = hasValue ? path.map((item) => item.label).join(" / ") : null;
197
+ const columns = buildColumns(data, navValue);
198
+ function handleSelect(colIndex, item) {
199
+ var _a;
200
+ if (item.disabled) return;
201
+ const newNavValue = navValue.slice(0, colIndex + 1);
202
+ newNavValue[colIndex] = item.value;
203
+ setNavValue(newNavValue);
204
+ if (!((_a = item.children) == null ? void 0 : _a.length)) {
205
+ const newPath = buildPath(data, newNavValue);
206
+ onChange == null ? void 0 : onChange(newNavValue, newPath);
207
+ setOpen(false);
208
+ }
209
+ }
210
+ function handleOpen() {
211
+ setNavValue(value);
212
+ setOpen(true);
213
+ }
214
+ const triggerClass = [
215
+ "bu-category-dropdown__trigger",
216
+ open ? "bu-category-dropdown__trigger--open" : "",
217
+ hasValue ? "bu-category-dropdown__trigger--has-value" : ""
218
+ ].filter(Boolean).join(" ");
219
+ return /* @__PURE__ */ jsxRuntime.jsxs(
220
+ "div",
221
+ {
222
+ ref: rootRef,
223
+ className: `bu-category-dropdown${className ? ` ${className}` : ""}`,
224
+ style,
225
+ children: [
226
+ /* @__PURE__ */ jsxRuntime.jsx(
227
+ "button",
228
+ {
229
+ type: "button",
230
+ className: triggerClass,
231
+ disabled,
232
+ onClick: () => open ? setOpen(false) : handleOpen(),
233
+ children: /* @__PURE__ */ jsxRuntime.jsx(
234
+ TruncatedTooltip,
235
+ {
236
+ text: triggerLabel ?? placeholder,
237
+ spanClassName: `bu-category-dropdown__trigger-label${!hasValue ? " bu-category-dropdown__trigger-label--placeholder" : ""}`,
238
+ wrapperStyle: { flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8 },
239
+ getPopupContainer,
240
+ trailing: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `bu-category-dropdown__trigger-chevron${open ? " bu-category-dropdown__trigger-chevron--open" : ""}`, children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {}) })
241
+ }
242
+ )
243
+ }
244
+ ),
245
+ open && reactDom.createPortal(
246
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: dropdownRef, style: dropdownStyle, className: "bu-category-dropdown__portal", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bu-category-dropdown__panel", ref: panelRef, children: columns.map((col, colIndex) => {
247
+ const isScrollable = col.length > maxVisible;
248
+ const isLast = colIndex === columns.length - 1;
249
+ const colClass = [
250
+ "bu-category-dropdown__col",
251
+ colIndex > 0 ? "bu-category-dropdown__col--indent" : "",
252
+ isScrollable ? "bu-category-dropdown__col--scrollable" : "",
253
+ isLast && colIndex > 0 ? "bu-category-dropdown__col--last" : ""
254
+ ].filter(Boolean).join(" ");
255
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "contents" }, children: [
256
+ colIndex > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bu-category-dropdown__divider" }),
257
+ /* @__PURE__ */ jsxRuntime.jsx(
258
+ "div",
259
+ {
260
+ className: colClass,
261
+ style: colWidth ? { width: colWidth } : void 0,
262
+ onMouseEnter: isScrollable ? (e) => e.currentTarget.classList.add("bu-category-dropdown__col--scrollbar-visible") : void 0,
263
+ onMouseLeave: isScrollable ? (e) => e.currentTarget.classList.remove("bu-category-dropdown__col--scrollbar-visible") : void 0,
264
+ children: col.map((item) => {
265
+ var _a;
266
+ const isSelected = navValue[colIndex] === item.value;
267
+ const hasBranch = !!((_a = item.children) == null ? void 0 : _a.length);
268
+ const itemClass = [
269
+ "bu-category-dropdown__item",
270
+ isSelected && hasBranch ? "bu-category-dropdown__item--selected-branch" : "",
271
+ isSelected && !hasBranch ? "bu-category-dropdown__item--selected-leaf" : "",
272
+ item.disabled ? "bu-category-dropdown__item--disabled" : ""
273
+ ].filter(Boolean).join(" ");
274
+ return /* @__PURE__ */ jsxRuntime.jsxs(
275
+ "button",
276
+ {
277
+ type: "button",
278
+ className: itemClass,
279
+ disabled: item.disabled,
280
+ onClick: () => handleSelect(colIndex, item),
281
+ children: [
282
+ /* @__PURE__ */ jsxRuntime.jsx(
283
+ TruncatedTooltip,
284
+ {
285
+ text: item.label,
286
+ spanClassName: "bu-category-dropdown__item-label",
287
+ wrapperStyle: { flex: 1, minWidth: 0, display: "block" },
288
+ getPopupContainer
289
+ }
290
+ ),
291
+ hasBranch && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bu-category-dropdown__item-arrow", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, {}) })
292
+ ]
293
+ },
294
+ item.value
295
+ );
296
+ })
297
+ }
298
+ )
299
+ ] }, colIndex);
300
+ }) }) }),
301
+ document.body
302
+ )
303
+ ]
304
+ }
305
+ );
306
+ }
307
+ module.exports = BuCategoryDropdown;
@@ -0,0 +1,308 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useCallback, useLayoutEffect, useEffect } from "react";
3
+ import { createPortal } from "react-dom";
4
+ /* empty css */
5
+ /* empty css */
6
+ import BTooltip from "../Tooltip/ContentTooltip.mjs";
7
+ import TooltipWrapper from "../Tooltip/TooltipWrapper.mjs";
8
+ function TruncatedTooltip({
9
+ text,
10
+ spanClassName,
11
+ wrapperStyle,
12
+ placement = "top",
13
+ getPopupContainer,
14
+ trailing
15
+ }) {
16
+ const [visible, setVisible] = useState(false);
17
+ const wrapperRef = useRef(null);
18
+ const spanRef = useRef(null);
19
+ const [anchorRect, setAnchorRect] = useState(null);
20
+ function handleMouseEnter() {
21
+ var _a;
22
+ const el = spanRef.current;
23
+ if (el && el.scrollWidth > el.offsetWidth) {
24
+ setAnchorRect(((_a = wrapperRef.current) == null ? void 0 : _a.getBoundingClientRect()) ?? null);
25
+ setVisible(true);
26
+ }
27
+ }
28
+ return /* @__PURE__ */ jsxs(TooltipWrapper, { ref: wrapperRef, style: wrapperStyle, children: [
29
+ /* @__PURE__ */ jsx(
30
+ "span",
31
+ {
32
+ ref: spanRef,
33
+ className: spanClassName,
34
+ onMouseEnter: handleMouseEnter,
35
+ onMouseLeave: () => setVisible(false),
36
+ children: text
37
+ }
38
+ ),
39
+ trailing,
40
+ visible && anchorRect && createPortal(
41
+ /* @__PURE__ */ jsx(
42
+ "span",
43
+ {
44
+ style: {
45
+ position: "fixed",
46
+ top: anchorRect.top,
47
+ left: anchorRect.left,
48
+ width: anchorRect.width,
49
+ height: anchorRect.height,
50
+ display: "block",
51
+ pointerEvents: "none",
52
+ zIndex: 9999999999
53
+ },
54
+ children: /* @__PURE__ */ jsx(BTooltip, { content: text, placement, className: "bu-category-dropdown__tooltip" })
55
+ }
56
+ ),
57
+ (getPopupContainer == null ? void 0 : getPopupContainer()) ?? document.body
58
+ )
59
+ ] });
60
+ }
61
+ function ChevronDown() {
62
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M5.57345 8.828C5.41074 8.66528 5.41074 8.40152 5.57345 8.2388C5.73617 8.07608 5.99993 8.07608 6.16265 8.2388L10.0323 12.1084L13.8349 8.24124C13.9963 8.0772 14.26 8.07503 14.4241 8.23636C14.5881 8.39771 14.5903 8.66149 14.429 8.82555L10.5282 12.7924C10.2576 13.0675 9.81477 13.0694 9.54196 12.7966L5.57345 8.828Z", fill: "#333333" }) });
63
+ }
64
+ function ChevronRight() {
65
+ return (
66
+ // <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
67
+ // <path d="M6 3.5L10.5 8L6 12.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
68
+ // </svg>
69
+ /* @__PURE__ */ jsx("svg", { class: "icon", viewBox: "0 0 1024 1024", version: "1.1", xmlns: "http://www.w3.org/2000/svg", "p-id": "55697", children: /* @__PURE__ */ jsx("path", { d: "M451.854222 285.361778A21.333333 21.333333 0 1 0 421.688889 315.52l198.115555 198.122667-197.994666 194.702222a21.333333 21.333333 0 0 0 29.916444 30.414222l203.107556-199.722667a35.555556 35.555556 0 0 0 0.213333-50.488888L451.854222 285.354667z", "p-id": "55698" }) })
70
+ );
71
+ }
72
+ function buildColumns(data, value) {
73
+ var _a;
74
+ const cols = [data];
75
+ let current = data;
76
+ for (let i = 0; i < value.length; i++) {
77
+ const selected = current.find((item) => item.value === value[i]);
78
+ if ((_a = selected == null ? void 0 : selected.children) == null ? void 0 : _a.length) {
79
+ cols.push(selected.children);
80
+ current = selected.children;
81
+ } else {
82
+ break;
83
+ }
84
+ }
85
+ return cols;
86
+ }
87
+ function buildPath(data, value) {
88
+ const path = [];
89
+ let items = data;
90
+ for (const v of value) {
91
+ const found = items.find((x) => x.value === v);
92
+ if (!found) break;
93
+ path.push(found);
94
+ items = found.children ?? [];
95
+ }
96
+ return path;
97
+ }
98
+ function BuCategoryDropdown({
99
+ data,
100
+ value = [],
101
+ onChange,
102
+ placeholder = "请选择分类",
103
+ disabled = false,
104
+ maxVisible = 6,
105
+ className,
106
+ style,
107
+ getPopupContainer,
108
+ dropdownStyle: customDropdownStyle
109
+ }) {
110
+ const [open, setOpen] = useState(false);
111
+ const [navValue, setNavValue] = useState(value);
112
+ const rootRef = useRef(null);
113
+ const dropdownRef = useRef(null);
114
+ const panelRef = useRef(null);
115
+ const wasOpenRef = useRef(false);
116
+ const [dropdownStyle, setDropdownStyle] = useState({});
117
+ const [colWidth, setColWidth] = useState();
118
+ const updatePosition = useCallback(() => {
119
+ var _a;
120
+ if (!rootRef.current) return;
121
+ const rect = rootRef.current.getBoundingClientRect();
122
+ let maxZ = 0;
123
+ let el = rootRef.current.parentElement;
124
+ while (el && el !== document.documentElement) {
125
+ const selfZ = parseInt(window.getComputedStyle(el).zIndex, 10);
126
+ if (!isNaN(selfZ) && selfZ > maxZ) maxZ = selfZ;
127
+ if (el.parentElement) {
128
+ for (const sibling of el.parentElement.children) {
129
+ if (sibling === el || !(sibling instanceof HTMLElement)) continue;
130
+ const sibZ = parseInt(window.getComputedStyle(sibling).zIndex, 10);
131
+ if (!isNaN(sibZ) && sibZ > maxZ) maxZ = sibZ;
132
+ }
133
+ }
134
+ el = el.parentElement;
135
+ }
136
+ const panelHeight = ((_a = panelRef.current) == null ? void 0 : _a.offsetHeight) ?? 0;
137
+ const spaceBelow = window.innerHeight - rect.bottom;
138
+ const spaceAbove = rect.top;
139
+ const flipToTop = panelHeight > 0 && spaceBelow < panelHeight + 4 && spaceAbove > spaceBelow;
140
+ setDropdownStyle({
141
+ position: "fixed",
142
+ top: flipToTop ? rect.top - panelHeight - 4 : rect.bottom + 4,
143
+ left: rect.left,
144
+ zIndex: maxZ > 0 ? maxZ + 10 : 1100,
145
+ ...customDropdownStyle
146
+ });
147
+ }, [customDropdownStyle]);
148
+ useLayoutEffect(() => {
149
+ if (open) {
150
+ updatePosition();
151
+ }
152
+ }, [open, navValue, updatePosition]);
153
+ useLayoutEffect(() => {
154
+ const justOpened = open && !wasOpenRef.current;
155
+ wasOpenRef.current = open;
156
+ if (!open || !panelRef.current) return;
157
+ const cols = panelRef.current.querySelectorAll(".bu-category-dropdown__col");
158
+ cols.forEach((col) => {
159
+ col.style.width = "";
160
+ });
161
+ let max = 0;
162
+ cols.forEach((col) => {
163
+ if (col.offsetWidth > max) max = col.offsetWidth;
164
+ });
165
+ const next = justOpened ? max : Math.max(colWidth ?? 0, max);
166
+ cols.forEach((col) => {
167
+ col.style.width = next ? `${next}px` : "";
168
+ });
169
+ if (next !== colWidth) setColWidth(next || void 0);
170
+ }, [open, navValue]);
171
+ useEffect(() => {
172
+ if (!open) return;
173
+ function handleClickOutside(e) {
174
+ var _a, _b;
175
+ const target = e.target;
176
+ if (((_a = rootRef.current) == null ? void 0 : _a.contains(target)) || ((_b = dropdownRef.current) == null ? void 0 : _b.contains(target))) {
177
+ return;
178
+ }
179
+ setOpen(false);
180
+ }
181
+ function handleScroll() {
182
+ setOpen(false);
183
+ }
184
+ document.addEventListener("mousedown", handleClickOutside);
185
+ document.addEventListener("scroll", handleScroll, true);
186
+ window.addEventListener("resize", updatePosition);
187
+ return () => {
188
+ document.removeEventListener("mousedown", handleClickOutside);
189
+ document.removeEventListener("scroll", handleScroll, true);
190
+ window.removeEventListener("resize", updatePosition);
191
+ };
192
+ }, [open, updatePosition]);
193
+ const path = buildPath(data, value);
194
+ const hasValue = path.length > 0;
195
+ const triggerLabel = hasValue ? path.map((item) => item.label).join(" / ") : null;
196
+ const columns = buildColumns(data, navValue);
197
+ function handleSelect(colIndex, item) {
198
+ var _a;
199
+ if (item.disabled) return;
200
+ const newNavValue = navValue.slice(0, colIndex + 1);
201
+ newNavValue[colIndex] = item.value;
202
+ setNavValue(newNavValue);
203
+ if (!((_a = item.children) == null ? void 0 : _a.length)) {
204
+ const newPath = buildPath(data, newNavValue);
205
+ onChange == null ? void 0 : onChange(newNavValue, newPath);
206
+ setOpen(false);
207
+ }
208
+ }
209
+ function handleOpen() {
210
+ setNavValue(value);
211
+ setOpen(true);
212
+ }
213
+ const triggerClass = [
214
+ "bu-category-dropdown__trigger",
215
+ open ? "bu-category-dropdown__trigger--open" : "",
216
+ hasValue ? "bu-category-dropdown__trigger--has-value" : ""
217
+ ].filter(Boolean).join(" ");
218
+ return /* @__PURE__ */ jsxs(
219
+ "div",
220
+ {
221
+ ref: rootRef,
222
+ className: `bu-category-dropdown${className ? ` ${className}` : ""}`,
223
+ style,
224
+ children: [
225
+ /* @__PURE__ */ jsx(
226
+ "button",
227
+ {
228
+ type: "button",
229
+ className: triggerClass,
230
+ disabled,
231
+ onClick: () => open ? setOpen(false) : handleOpen(),
232
+ children: /* @__PURE__ */ jsx(
233
+ TruncatedTooltip,
234
+ {
235
+ text: triggerLabel ?? placeholder,
236
+ spanClassName: `bu-category-dropdown__trigger-label${!hasValue ? " bu-category-dropdown__trigger-label--placeholder" : ""}`,
237
+ wrapperStyle: { flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8 },
238
+ getPopupContainer,
239
+ trailing: /* @__PURE__ */ jsx("span", { className: `bu-category-dropdown__trigger-chevron${open ? " bu-category-dropdown__trigger-chevron--open" : ""}`, children: /* @__PURE__ */ jsx(ChevronDown, {}) })
240
+ }
241
+ )
242
+ }
243
+ ),
244
+ open && createPortal(
245
+ /* @__PURE__ */ jsx("div", { ref: dropdownRef, style: dropdownStyle, className: "bu-category-dropdown__portal", children: /* @__PURE__ */ jsx("div", { className: "bu-category-dropdown__panel", ref: panelRef, children: columns.map((col, colIndex) => {
246
+ const isScrollable = col.length > maxVisible;
247
+ const isLast = colIndex === columns.length - 1;
248
+ const colClass = [
249
+ "bu-category-dropdown__col",
250
+ colIndex > 0 ? "bu-category-dropdown__col--indent" : "",
251
+ isScrollable ? "bu-category-dropdown__col--scrollable" : "",
252
+ isLast && colIndex > 0 ? "bu-category-dropdown__col--last" : ""
253
+ ].filter(Boolean).join(" ");
254
+ return /* @__PURE__ */ jsxs("div", { style: { display: "contents" }, children: [
255
+ colIndex > 0 && /* @__PURE__ */ jsx("div", { className: "bu-category-dropdown__divider" }),
256
+ /* @__PURE__ */ jsx(
257
+ "div",
258
+ {
259
+ className: colClass,
260
+ style: colWidth ? { width: colWidth } : void 0,
261
+ onMouseEnter: isScrollable ? (e) => e.currentTarget.classList.add("bu-category-dropdown__col--scrollbar-visible") : void 0,
262
+ onMouseLeave: isScrollable ? (e) => e.currentTarget.classList.remove("bu-category-dropdown__col--scrollbar-visible") : void 0,
263
+ children: col.map((item) => {
264
+ var _a;
265
+ const isSelected = navValue[colIndex] === item.value;
266
+ const hasBranch = !!((_a = item.children) == null ? void 0 : _a.length);
267
+ const itemClass = [
268
+ "bu-category-dropdown__item",
269
+ isSelected && hasBranch ? "bu-category-dropdown__item--selected-branch" : "",
270
+ isSelected && !hasBranch ? "bu-category-dropdown__item--selected-leaf" : "",
271
+ item.disabled ? "bu-category-dropdown__item--disabled" : ""
272
+ ].filter(Boolean).join(" ");
273
+ return /* @__PURE__ */ jsxs(
274
+ "button",
275
+ {
276
+ type: "button",
277
+ className: itemClass,
278
+ disabled: item.disabled,
279
+ onClick: () => handleSelect(colIndex, item),
280
+ children: [
281
+ /* @__PURE__ */ jsx(
282
+ TruncatedTooltip,
283
+ {
284
+ text: item.label,
285
+ spanClassName: "bu-category-dropdown__item-label",
286
+ wrapperStyle: { flex: 1, minWidth: 0, display: "block" },
287
+ getPopupContainer
288
+ }
289
+ ),
290
+ hasBranch && /* @__PURE__ */ jsx("span", { className: "bu-category-dropdown__item-arrow", children: /* @__PURE__ */ jsx(ChevronRight, {}) })
291
+ ]
292
+ },
293
+ item.value
294
+ );
295
+ })
296
+ }
297
+ )
298
+ ] }, colIndex);
299
+ }) }) }),
300
+ document.body
301
+ )
302
+ ]
303
+ }
304
+ );
305
+ }
306
+ export {
307
+ BuCategoryDropdown as default
308
+ };