@jc-times/business-ui 0.2.43

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 (154) hide show
  1. package/AGENTS.md +6 -0
  2. package/CHANGELOG.md +267 -0
  3. package/README.md +55 -0
  4. package/THIRD_PARTY_NOTICES.md +29 -0
  5. package/bin/business-ui-gate.mjs +171 -0
  6. package/dist/Alert.js +47 -0
  7. package/dist/AsyncDirectoryPicker.js +134 -0
  8. package/dist/AsyncSearchPicker.js +155 -0
  9. package/dist/AutoComplete.js +34 -0
  10. package/dist/Badge.js +14 -0
  11. package/dist/Button.js +54 -0
  12. package/dist/Cascader.js +141 -0
  13. package/dist/Combobox.js +106 -0
  14. package/dist/ConfirmDialog.js +48 -0
  15. package/dist/DataTableHorizontalScrollbar.js +38 -0
  16. package/dist/DataTableIcons.js +37 -0
  17. package/dist/DataTableMergedRows.js +45 -0
  18. package/dist/DataTableTheme.js +135 -0
  19. package/dist/DateInput.js +223 -0
  20. package/dist/DropdownMenu.js +130 -0
  21. package/dist/EmptyState.js +27 -0
  22. package/dist/ExplainableButton.js +68 -0
  23. package/dist/FileDropzone.js +70 -0
  24. package/dist/FilePreparationDialog.js +33 -0
  25. package/dist/FloatingControls.js +120 -0
  26. package/dist/FormField.js +143 -0
  27. package/dist/MetricCard.js +38 -0
  28. package/dist/ModalShell.js +139 -0
  29. package/dist/MultiSelect.js +137 -0
  30. package/dist/NumericInput.js +97 -0
  31. package/dist/OverlayContainer.js +9 -0
  32. package/dist/PageHeader.js +36 -0
  33. package/dist/Pagination.js +115 -0
  34. package/dist/PreparedFileDropzone.js +30 -0
  35. package/dist/RecoverableAsyncState.js +35 -0
  36. package/dist/RovingTabs.js +54 -0
  37. package/dist/SectionCard.js +35 -0
  38. package/dist/SegmentedControl.js +46 -0
  39. package/dist/Select.js +73 -0
  40. package/dist/Skeleton.js +25 -0
  41. package/dist/SortableList.js +55 -0
  42. package/dist/StructuredAddressInput.js +157 -0
  43. package/dist/Toast.js +100 -0
  44. package/dist/ToggleSwitch.js +34 -0
  45. package/dist/TreeSelect.js +444 -0
  46. package/dist/amount-format.js +20 -0
  47. package/dist/business-ui.js +44 -0
  48. package/dist/chinese-address-regions.js +15 -0
  49. package/dist/classNames.js +6 -0
  50. package/dist/data-table.js +257 -0
  51. package/dist/document-render-budget.js +22 -0
  52. package/dist/document-viewer/ContinuousPdfViewer.js +145 -0
  53. package/dist/document-viewer/DocumentViewer.js +123 -0
  54. package/dist/document-viewer/DocumentViewerViewport.js +36 -0
  55. package/dist/document-viewer/ImagePage.js +39 -0
  56. package/dist/document-viewer/PdfCanvasPage.js +26 -0
  57. package/dist/document-viewer/PdfThumbnailRail.js +116 -0
  58. package/dist/document-viewer/PdfToolbar.js +61 -0
  59. package/dist/document-viewer/PdfWorkspace.js +42 -0
  60. package/dist/document-viewer/pdf-render-budget.js +7 -0
  61. package/dist/document-viewer/usePdfCanvas.js +69 -0
  62. package/dist/document-viewer/usePdfViewport.js +48 -0
  63. package/dist/document-viewer-v2/DocumentViewerV2.js +171 -0
  64. package/dist/document-viewer-v2/HeadlessPdfViewer.js +420 -0
  65. package/dist/document-viewer-v2/HeadlessSearch.js +66 -0
  66. package/dist/document-viewer-v2.js +13 -0
  67. package/dist/document-viewer.js +12 -0
  68. package/dist/pdfium-viewer.js +18 -0
  69. package/dist/styles.css +2 -0
  70. package/dist/types/Alert.d.ts +11 -0
  71. package/dist/types/AmountFormat.d.ts +15 -0
  72. package/dist/types/AsyncDirectoryPicker.d.ts +32 -0
  73. package/dist/types/AsyncSearchPicker.d.ts +26 -0
  74. package/dist/types/AutoComplete.d.ts +9 -0
  75. package/dist/types/Badge.d.ts +13 -0
  76. package/dist/types/Button.d.ts +36 -0
  77. package/dist/types/Cascader.d.ts +57 -0
  78. package/dist/types/ChineseAddressRegions.d.ts +4 -0
  79. package/dist/types/Combobox.d.ts +37 -0
  80. package/dist/types/ConfirmDialog.d.ts +20 -0
  81. package/dist/types/DataTable.d.ts +68 -0
  82. package/dist/types/DataTableHorizontalScrollbar.d.ts +8 -0
  83. package/dist/types/DataTableIcons.d.ts +19 -0
  84. package/dist/types/DataTableMergedRows.d.ts +11 -0
  85. package/dist/types/DataTableTheme.d.ts +4 -0
  86. package/dist/types/DateInput.d.ts +25 -0
  87. package/dist/types/DocumentRenderBudget.d.ts +9 -0
  88. package/dist/types/DocumentViewer.d.ts +11 -0
  89. package/dist/types/DocumentViewerV2.d.ts +10 -0
  90. package/dist/types/DropdownMenu.d.ts +73 -0
  91. package/dist/types/EmptyState.d.ts +9 -0
  92. package/dist/types/ExplainableButton.d.ts +7 -0
  93. package/dist/types/FileDropzone.d.ts +20 -0
  94. package/dist/types/FilePreparationDialog.d.ts +12 -0
  95. package/dist/types/FloatingControls.d.ts +39 -0
  96. package/dist/types/FormField.d.ts +35 -0
  97. package/dist/types/MetricCard.d.ts +17 -0
  98. package/dist/types/ModalShell.d.ts +33 -0
  99. package/dist/types/MultiSelect.d.ts +12 -0
  100. package/dist/types/NumericInput.d.ts +54 -0
  101. package/dist/types/OverlayContainer.d.ts +2 -0
  102. package/dist/types/PageHeader.d.ts +23 -0
  103. package/dist/types/Pagination.d.ts +14 -0
  104. package/dist/types/PdfiumViewer.d.ts +5 -0
  105. package/dist/types/PreparedFileDropzone.d.ts +7 -0
  106. package/dist/types/RecoverableAsyncState.d.ts +11 -0
  107. package/dist/types/RovingTabs.d.ts +21 -0
  108. package/dist/types/SectionCard.d.ts +18 -0
  109. package/dist/types/SegmentedControl.d.ts +26 -0
  110. package/dist/types/Select.d.ts +31 -0
  111. package/dist/types/Skeleton.d.ts +11 -0
  112. package/dist/types/SortableList.d.ts +17 -0
  113. package/dist/types/StructuredAddressInput.d.ts +57 -0
  114. package/dist/types/Toast.d.ts +22 -0
  115. package/dist/types/ToggleSwitch.d.ts +15 -0
  116. package/dist/types/TreeSelect.d.ts +58 -0
  117. package/dist/types/classNames.d.ts +1 -0
  118. package/dist/types/document-viewer/ContinuousPdfViewer.d.ts +16 -0
  119. package/dist/types/document-viewer/DocumentViewer.d.ts +31 -0
  120. package/dist/types/document-viewer/DocumentViewerViewport.d.ts +23 -0
  121. package/dist/types/document-viewer/ImagePage.d.ts +9 -0
  122. package/dist/types/document-viewer/PdfCanvasPage.d.ts +7 -0
  123. package/dist/types/document-viewer/PdfThumbnailRail.d.ts +12 -0
  124. package/dist/types/document-viewer/PdfToolbar.d.ts +13 -0
  125. package/dist/types/document-viewer/PdfWorkspace.d.ts +5 -0
  126. package/dist/types/document-viewer/pdf-render-budget.d.ts +2 -0
  127. package/dist/types/document-viewer/usePdfCanvas.d.ts +22 -0
  128. package/dist/types/document-viewer/usePdfViewport.d.ts +14 -0
  129. package/dist/types/document-viewer-v2/DocumentViewerV2.d.ts +50 -0
  130. package/dist/types/document-viewer-v2/HeadlessPdfViewer.d.ts +39 -0
  131. package/dist/types/document-viewer-v2/HeadlessSearch.d.ts +9 -0
  132. package/dist/types/index.d.ts +41 -0
  133. package/dist/types/useDebouncedValue.d.ts +2 -0
  134. package/dist/types/useFilePreparation.d.ts +28 -0
  135. package/dist/types/useModalFocusTrap.d.ts +3 -0
  136. package/dist/useDebouncedValue.js +16 -0
  137. package/dist/useFilePreparation.js +51 -0
  138. package/dist/useModalFocusTrap.js +71 -0
  139. package/docs/agent-guide.md +145 -0
  140. package/docs/api.md +220 -0
  141. package/docs/cascader.md +56 -0
  142. package/docs/component-strategy.md +94 -0
  143. package/docs/data-table.md +123 -0
  144. package/docs/dependencies.md +57 -0
  145. package/docs/document-viewer-v2.md +259 -0
  146. package/docs/document-viewer.md +28 -0
  147. package/docs/file-preparation.md +11 -0
  148. package/docs/maturity-migration.md +62 -0
  149. package/docs/modal-shell-migration.md +43 -0
  150. package/docs/mrt-poc.md +205 -0
  151. package/docs/release.md +32 -0
  152. package/docs/viewport-qa.md +99 -0
  153. package/licenses/rc-cascader-MIT.txt +21 -0
  154. package/package.json +163 -0
@@ -0,0 +1,68 @@
1
+ import { Button as e } from "./Button.js";
2
+ import { CircleHelp as t } from "lucide-react";
3
+ import { useEffect as n, useId as r, useRef as i, useState as a } from "react";
4
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
5
+ //#region src/ExplainableButton.tsx
6
+ function c({ disabled: c = !1, disabledReason: l, reasonPresentation: u = "inline", onClick: d, onFocus: f, onBlur: p, onKeyDown: m, children: h, ...g }) {
7
+ let _ = `ui-action-reason-${r().replace(/:/g, "")}`, v = c && !!l, y = v && u === "popover", [b, x] = a(!1), S = i(null), C = [g["aria-describedby"], v ? _ : void 0].filter(Boolean).join(" ") || void 0;
8
+ n(() => {
9
+ if (!y || !b) return;
10
+ let e = (e) => {
11
+ S.current?.contains(e.target) || x(!1);
12
+ }, t = (e) => {
13
+ e.key === "Escape" && x(!1);
14
+ };
15
+ return window.addEventListener("pointerdown", e), window.addEventListener("keydown", t), () => {
16
+ window.removeEventListener("pointerdown", e), window.removeEventListener("keydown", t);
17
+ };
18
+ }, [y, b]), n(() => {
19
+ y || x(!1);
20
+ }, [y]);
21
+ function w(e) {
22
+ if (c) {
23
+ e.preventDefault(), e.stopPropagation(), y && x(!0);
24
+ return;
25
+ }
26
+ d?.(e);
27
+ }
28
+ function T(e) {
29
+ y && x(!0), f?.(e);
30
+ }
31
+ function E(e) {
32
+ S.current?.contains(e.relatedTarget) || x(!1), p?.(e);
33
+ }
34
+ function D(e) {
35
+ y && e.key === "Escape" && (e.stopPropagation(), x(!1)), m?.(e);
36
+ }
37
+ let O = {
38
+ ...g,
39
+ disabled: c && !v,
40
+ "aria-disabled": v || void 0,
41
+ "aria-describedby": C,
42
+ "aria-expanded": y ? b : void 0,
43
+ "aria-controls": y ? _ : void 0,
44
+ onClick: w,
45
+ onFocus: T,
46
+ onBlur: E,
47
+ onKeyDown: D
48
+ };
49
+ return /* @__PURE__ */ s("span", {
50
+ ref: S,
51
+ className: `ui-explainable-action${v ? " is-blocked" : ""}${y ? " reason-popover" : ""}${b ? " reason-open" : ""}`,
52
+ children: [/* @__PURE__ */ o(e, {
53
+ ...O,
54
+ children: h
55
+ }), v && /* @__PURE__ */ s("small", {
56
+ className: "ui-explainable-reason",
57
+ id: _,
58
+ role: y ? "tooltip" : "note",
59
+ "aria-live": y ? "polite" : void 0,
60
+ children: [/* @__PURE__ */ o(t, {
61
+ "aria-hidden": "true",
62
+ size: 14
63
+ }), /* @__PURE__ */ o("span", { children: l })]
64
+ })]
65
+ });
66
+ }
67
+ //#endregion
68
+ export { c as ExplainableButton };
@@ -0,0 +1,70 @@
1
+ import { useRef as e, useState as t } from "react";
2
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
3
+ //#region src/FileDropzone.tsx
4
+ function i({ children: i, accept: s, multiple: c = !1, disabled: l = !1, inputRef: u, inputProps: d, maxFileSize: f, maxFiles: p, onRejections: m, onFilesSelected: h, onFilesRejected: g, className: _ = "", onDragEnter: v, onDragLeave: y, onDragOver: b, onDrop: x, onKeyDown: S, ...C }) {
5
+ if (p !== void 0 && (!Number.isSafeInteger(p) || p < 0)) throw RangeError("maxFiles must be a non-negative safe integer");
6
+ if (f !== void 0 && (!Number.isFinite(f) || f < 0)) throw RangeError("maxFileSize must be non-negative and finite");
7
+ let [w, T] = t(!1), E = e(0), D = e(null);
8
+ function O(e) {
9
+ if (l) return;
10
+ let t = [], n = [], r = c ? p === void 0 ? Infinity : Math.max(0, Math.floor(p)) : Math.min(1, p ?? 1);
11
+ for (let i of Array.from(e)) {
12
+ let e = a(i, s) ? f !== void 0 && i.size > f ? "size" : t.length >= r ? "count" : null : "type";
13
+ e ? n.push({
14
+ file: i,
15
+ reason: e
16
+ }) : t.push(i);
17
+ }
18
+ n.length && (g?.(n.map((e) => e.file)), m?.(n)), t.length && h(t);
19
+ }
20
+ function k(e) {
21
+ S?.(e), !(e.defaultPrevented || l || e.key !== "Enter" && e.key !== " ") && (e.preventDefault(), D.current?.click());
22
+ }
23
+ return /* @__PURE__ */ r("label", {
24
+ ...C,
25
+ role: "button",
26
+ tabIndex: l ? -1 : C.tabIndex ?? 0,
27
+ "aria-disabled": l || void 0,
28
+ className: `ui-file-dropzone${w ? " dragging" : ""} ${_}`.trim(),
29
+ onKeyDown: k,
30
+ onDragEnter: (e) => {
31
+ v?.(e), e.preventDefault(), !l && (E.current += 1, T(!0));
32
+ },
33
+ onDragOver: (e) => {
34
+ b?.(e), e.preventDefault(), !l && (e.dataTransfer.dropEffect = "copy");
35
+ },
36
+ onDragLeave: (e) => {
37
+ y?.(e), e.preventDefault(), !l && (E.current = Math.max(0, E.current - 1), E.current || T(!1));
38
+ },
39
+ onDrop: (e) => {
40
+ x?.(e), e.preventDefault(), E.current = 0, T(!1), l || O(e.dataTransfer.files);
41
+ },
42
+ children: [i, /* @__PURE__ */ n("input", {
43
+ ...d,
44
+ ref: (e) => {
45
+ D.current = e, o(u, e);
46
+ },
47
+ className: "ui-file-dropzone-input",
48
+ type: "file",
49
+ accept: s,
50
+ multiple: c,
51
+ disabled: l,
52
+ tabIndex: -1,
53
+ "aria-hidden": "true",
54
+ onChange: (e) => {
55
+ O(e.currentTarget.files ?? []), e.currentTarget.value = "";
56
+ }
57
+ })]
58
+ });
59
+ }
60
+ function a(e, t) {
61
+ let n = t?.split(",").map((e) => e.trim().toLocaleLowerCase()).filter(Boolean) ?? [];
62
+ if (!n.length) return !0;
63
+ let r = e.name.toLocaleLowerCase(), i = e.type.toLocaleLowerCase();
64
+ return n.some((e) => e.startsWith(".") ? r.endsWith(e) : e.endsWith("/*") ? i.startsWith(e.slice(0, -1)) : i === e);
65
+ }
66
+ function o(e, t) {
67
+ typeof e == "function" ? e(t) : e && (e.current = t);
68
+ }
69
+ //#endregion
70
+ export { i as FileDropzone, a as acceptsFile };
@@ -0,0 +1,33 @@
1
+ import { Button as e } from "./Button.js";
2
+ import { ModalShell as t } from "./ModalShell.js";
3
+ import { useId as n } from "react";
4
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
+ //#region src/FilePreparationDialog.tsx
6
+ function a({ preparation: a, labels: o }) {
7
+ let s = n(), { state: c, cancel: l } = a;
8
+ if (c.kind === "idle") return null;
9
+ let u = c.kind === "preparing", d = u ? o.cancel : o.close;
10
+ return /* @__PURE__ */ r(t, {
11
+ titleId: s,
12
+ panelClassName: "ui-file-preparation-dialog",
13
+ title: u ? o.preparingTitle : o.failedTitle,
14
+ description: u ? o.preparingDescription : void 0,
15
+ closeLabel: d,
16
+ onClose: l,
17
+ footer: /* @__PURE__ */ r(e, {
18
+ variant: "secondary",
19
+ onClick: l,
20
+ children: d
21
+ }),
22
+ children: /* @__PURE__ */ i("div", {
23
+ role: u ? "status" : "alert",
24
+ "aria-live": "polite",
25
+ children: [/* @__PURE__ */ r("p", {
26
+ className: "ui-file-preparation-name",
27
+ children: c.fileName
28
+ }), /* @__PURE__ */ r("p", { children: c.kind === "preparing" ? `${c.index} / ${c.total}` : c.message })]
29
+ })
30
+ });
31
+ }
32
+ //#endregion
33
+ export { a as FilePreparationDialog };
@@ -0,0 +1,120 @@
1
+ import { Button as e } from "./Button.js";
2
+ import { useOverlayContainer as t } from "./OverlayContainer.js";
3
+ import { X as n } from "lucide-react";
4
+ import { useId as r, useState as i } from "react";
5
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
+ import * as s from "@radix-ui/react-popover";
7
+ import * as c from "@radix-ui/react-tooltip";
8
+ //#region src/FloatingControls.tsx
9
+ function l({ children: e, content: n, side: r = "top", delayDuration: i = 450, disabled: s = !1, contentClassName: l = "" }) {
10
+ let u = t();
11
+ return s ? e : /* @__PURE__ */ a(c.Provider, {
12
+ delayDuration: i,
13
+ skipDelayDuration: 250,
14
+ children: /* @__PURE__ */ o(c.Root, { children: [/* @__PURE__ */ a(c.Trigger, {
15
+ asChild: !0,
16
+ children: e
17
+ }), /* @__PURE__ */ a(c.Portal, {
18
+ container: u,
19
+ children: /* @__PURE__ */ o(c.Content, {
20
+ className: `ui-tooltip ${l}`.trim(),
21
+ side: r,
22
+ sideOffset: 7,
23
+ collisionPadding: 10,
24
+ children: [n, /* @__PURE__ */ a(c.Arrow, {
25
+ className: "ui-floating-arrow",
26
+ width: 10,
27
+ height: 5
28
+ })]
29
+ })
30
+ })] })
31
+ });
32
+ }
33
+ function u({ trigger: e, children: i, title: c, closeLabel: l = "关闭", side: u = "bottom", align: d = "start", open: f, defaultOpen: p, modal: m = !1, onOpenChange: h, contentClassName: g = "" }) {
34
+ let _ = t(), v = `ui-popover-title-${r().replaceAll(":", "")}`;
35
+ return /* @__PURE__ */ o(s.Root, {
36
+ open: f,
37
+ defaultOpen: p,
38
+ modal: m,
39
+ onOpenChange: h,
40
+ children: [/* @__PURE__ */ a(s.Trigger, {
41
+ asChild: !0,
42
+ children: e
43
+ }), /* @__PURE__ */ a(s.Portal, {
44
+ container: _,
45
+ children: /* @__PURE__ */ o(s.Content, {
46
+ className: `ui-popover ${g}`.trim(),
47
+ side: u,
48
+ align: d,
49
+ sideOffset: 8,
50
+ collisionPadding: 12,
51
+ "aria-labelledby": c === void 0 ? void 0 : v,
52
+ children: [
53
+ c === void 0 ? null : /* @__PURE__ */ o("div", {
54
+ className: "ui-popover-heading",
55
+ children: [/* @__PURE__ */ a("strong", {
56
+ id: v,
57
+ children: c
58
+ }), /* @__PURE__ */ a(s.Close, {
59
+ className: "ui-floating-close",
60
+ "aria-label": l,
61
+ children: /* @__PURE__ */ a(n, { size: 16 })
62
+ })]
63
+ }),
64
+ /* @__PURE__ */ a("div", {
65
+ className: "ui-popover-body",
66
+ children: i
67
+ }),
68
+ /* @__PURE__ */ a(s.Arrow, {
69
+ className: "ui-floating-arrow",
70
+ width: 12,
71
+ height: 6
72
+ })
73
+ ]
74
+ })
75
+ })]
76
+ });
77
+ }
78
+ function d({ title: t, description: n, confirmLabel: r = "确认", cancelLabel: s = "取消", confirmVariant: c = "danger", onConfirm: l, onConfirmError: d, open: f, defaultOpen: p, onOpenChange: m, ...h }) {
79
+ let [g, _] = i(p ?? !1), [v, y] = i(!1), b = f ?? g, x = (e) => {
80
+ v || (_(e), m?.(e));
81
+ };
82
+ async function S() {
83
+ y(!0);
84
+ try {
85
+ await l(), _(!1), m?.(!1);
86
+ } catch (e) {
87
+ d?.(e);
88
+ } finally {
89
+ y(!1);
90
+ }
91
+ }
92
+ return /* @__PURE__ */ o(u, {
93
+ ...h,
94
+ open: b,
95
+ onOpenChange: x,
96
+ title: t,
97
+ children: [n === void 0 ? null : /* @__PURE__ */ a("div", {
98
+ className: "ui-popconfirm-description",
99
+ children: n
100
+ }), /* @__PURE__ */ o("div", {
101
+ className: "ui-popconfirm-actions",
102
+ children: [/* @__PURE__ */ a(e, {
103
+ size: "compact",
104
+ variant: "outline",
105
+ disabled: v,
106
+ onClick: () => x(!1),
107
+ children: s
108
+ }), /* @__PURE__ */ a(e, {
109
+ size: "compact",
110
+ variant: c,
111
+ busy: v,
112
+ busyLabel: "处理中",
113
+ onClick: S,
114
+ children: r
115
+ })]
116
+ })]
117
+ });
118
+ }
119
+ //#endregion
120
+ export { d as Popconfirm, u as Popover, l as Tooltip };
@@ -0,0 +1,143 @@
1
+ import { forwardRef as e, useCallback as t, useId as n, useRef as r } from "react";
2
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
3
+ //#region src/FormField.tsx
4
+ function o({ controlId: e, label: t, required: n, helpText: r, error: o, containerClassName: s = "", children: c }) {
5
+ return /* @__PURE__ */ a("div", {
6
+ className: `ui-form-field ${s}`.trim(),
7
+ children: [
8
+ t === void 0 ? null : /* @__PURE__ */ a("label", {
9
+ className: "ui-form-label",
10
+ htmlFor: e,
11
+ children: [t, n && /* @__PURE__ */ i("span", {
12
+ className: "ui-form-required",
13
+ "aria-hidden": "true",
14
+ children: "*"
15
+ })]
16
+ }),
17
+ c,
18
+ r === void 0 ? null : /* @__PURE__ */ i("small", {
19
+ className: "ui-form-help",
20
+ id: `${e}-help`,
21
+ children: r
22
+ }),
23
+ o === void 0 || o === "" ? null : /* @__PURE__ */ i("small", {
24
+ className: "ui-form-error",
25
+ id: `${e}-error`,
26
+ role: "alert",
27
+ children: o
28
+ })
29
+ ]
30
+ });
31
+ }
32
+ var s = e(function({ label: e, helpText: s, error: c, containerClassName: l, className: u = "", id: h, required: g, startAdornment: _, endAdornment: v, "aria-describedby": y, ...b }, x) {
33
+ let S = n(), C = h ?? S, w = r(null), T = !!c || f(b["aria-invalid"]), E = t((e) => {
34
+ w.current = e, m(x, e);
35
+ }, [x]), D = /* @__PURE__ */ i("input", {
36
+ ...b,
37
+ ref: E,
38
+ id: C,
39
+ required: g,
40
+ className: `ui-input ${u}`.trim(),
41
+ "aria-invalid": c ? !0 : b["aria-invalid"],
42
+ "aria-describedby": d(C, s, c, y)
43
+ }), O = _ == null && v == null ? D : /* @__PURE__ */ a("span", {
44
+ className: "ui-input-affix",
45
+ "data-disabled": b.disabled || void 0,
46
+ "data-invalid": T || void 0,
47
+ onMouseDown: (e) => p(e, w.current),
48
+ children: [
49
+ _ == null ? null : /* @__PURE__ */ i("span", {
50
+ className: "ui-input-adornment ui-input-adornment-start",
51
+ children: _
52
+ }),
53
+ D,
54
+ v == null ? null : /* @__PURE__ */ i("span", {
55
+ className: "ui-input-adornment ui-input-adornment-end",
56
+ children: v
57
+ })
58
+ ]
59
+ });
60
+ return e === void 0 && s === void 0 && !c ? O : /* @__PURE__ */ i(o, {
61
+ controlId: C,
62
+ label: e,
63
+ required: g,
64
+ helpText: s,
65
+ error: c,
66
+ containerClassName: l,
67
+ children: O
68
+ });
69
+ }), c = e(function({ label: e, helpText: t, error: r, containerClassName: a, className: s = "", id: c, required: l, "aria-describedby": u, children: f, ...p }, m) {
70
+ let h = n(), g = c ?? h, _ = /* @__PURE__ */ i("select", {
71
+ ...p,
72
+ ref: m,
73
+ id: g,
74
+ required: l,
75
+ className: `ui-select ${s}`.trim(),
76
+ "aria-invalid": r ? !0 : p["aria-invalid"],
77
+ "aria-describedby": d(g, t, r, u),
78
+ children: f
79
+ });
80
+ return e === void 0 && t === void 0 && !r ? _ : /* @__PURE__ */ i(o, {
81
+ controlId: g,
82
+ label: e,
83
+ required: l,
84
+ helpText: t,
85
+ error: r,
86
+ containerClassName: a,
87
+ children: _
88
+ });
89
+ }), l = e(function({ label: e, helpText: t, error: r, containerClassName: a, className: s = "", id: c, required: l, "aria-describedby": u, ...f }, p) {
90
+ let m = n(), h = c ?? m, g = /* @__PURE__ */ i("textarea", {
91
+ ...f,
92
+ ref: p,
93
+ id: h,
94
+ required: l,
95
+ className: `ui-textarea ${s}`.trim(),
96
+ "aria-invalid": r ? !0 : f["aria-invalid"],
97
+ "aria-describedby": d(h, t, r, u)
98
+ });
99
+ return e === void 0 && t === void 0 && !r ? g : /* @__PURE__ */ i(o, {
100
+ controlId: h,
101
+ label: e,
102
+ required: l,
103
+ helpText: t,
104
+ error: r,
105
+ containerClassName: a,
106
+ children: g
107
+ });
108
+ }), u = e(function({ label: e, description: t, containerClassName: r = "", className: o = "", id: s, ...c }, l) {
109
+ let u = n(), d = s ?? u;
110
+ return /* @__PURE__ */ a("label", {
111
+ className: `ui-checkbox ${r}`.trim(),
112
+ htmlFor: d,
113
+ children: [/* @__PURE__ */ i("input", {
114
+ ...c,
115
+ ref: l,
116
+ id: d,
117
+ type: "checkbox",
118
+ className: o
119
+ }), /* @__PURE__ */ a("span", {
120
+ className: "ui-checkbox-copy",
121
+ children: [/* @__PURE__ */ i("span", { children: e }), t === void 0 ? null : /* @__PURE__ */ i("small", { children: t })]
122
+ })]
123
+ });
124
+ });
125
+ function d(e, t, n, r) {
126
+ return [
127
+ r,
128
+ t === void 0 ? "" : `${e}-help`,
129
+ n === void 0 || n === "" ? "" : `${e}-error`
130
+ ].filter(Boolean).join(" ") || void 0;
131
+ }
132
+ function f(e) {
133
+ return e !== void 0 && e !== !1 && e !== "false";
134
+ }
135
+ function p(e, t) {
136
+ let n = e.target;
137
+ n === t || n.closest("button,a,[role='button'],input,select,textarea") || (e.preventDefault(), t?.focus());
138
+ }
139
+ function m(e, t) {
140
+ typeof e == "function" ? e(t) : e && (e.current = t);
141
+ }
142
+ //#endregion
143
+ export { u as Checkbox, o as FormField, c as SelectInput, l as TextArea, s as TextInput };
@@ -0,0 +1,38 @@
1
+ import { joinClassNames as e } from "./classNames.js";
2
+ import { forwardRef as t, useId as n } from "react";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
+ //#region src/MetricCard.tsx
5
+ var a = t(function({ label: t, value: a, description: o, icon: s, tone: c = "neutral", className: l, "aria-label": u, "aria-labelledby": d, ...f }, p) {
6
+ let m = n(), h = u === void 0 ? d ?? m : d;
7
+ return /* @__PURE__ */ i("article", {
8
+ ...f,
9
+ ref: p,
10
+ "aria-label": u,
11
+ "aria-labelledby": h,
12
+ className: e("ui-metric-card", `ui-metric-card-${c}`, l),
13
+ children: [
14
+ /* @__PURE__ */ i("div", {
15
+ className: "ui-metric-card-heading",
16
+ children: [/* @__PURE__ */ r("div", {
17
+ id: m,
18
+ className: "ui-metric-card-label",
19
+ children: t
20
+ }), s === void 0 ? null : /* @__PURE__ */ r("div", {
21
+ className: "ui-metric-card-icon",
22
+ "aria-hidden": "true",
23
+ children: s
24
+ })]
25
+ }),
26
+ /* @__PURE__ */ r("div", {
27
+ className: "ui-metric-card-value",
28
+ children: a
29
+ }),
30
+ o === void 0 ? null : /* @__PURE__ */ r("div", {
31
+ className: "ui-metric-card-description",
32
+ children: o
33
+ })
34
+ ]
35
+ });
36
+ });
37
+ //#endregion
38
+ export { a as MetricCard };
@@ -0,0 +1,139 @@
1
+ import { Button as e } from "./Button.js";
2
+ import { OverlayContainerContext as t } from "./OverlayContainer.js";
3
+ import { X as n } from "lucide-react";
4
+ import { Children as r, Fragment as i, isValidElement as a, useCallback as o, useEffect as s, useRef as c, useState as l } from "react";
5
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
6
+ import * as f from "@radix-ui/react-dialog";
7
+ //#region src/ModalShell.tsx
8
+ function p({ backdropClassName: e = "", panelClassName: n = "", titleId: r, eyebrow: i, title: a, description: p, closeLabel: _, onClose: b, closeDisabled: x = !1, showCloseButton: S = !0, closeIconSize: C = 20, closeOnBackdrop: w = !1, rootRef: T, closeOnEscape: E = !0, initialFocus: D, returnFocus: O, role: k = "dialog", describedBy: A, children: j, footer: M, contentClassName: N = "", contentProps: P, footerClassName: F = "" }) {
9
+ let I = c(null), [L, R] = l(null), z = c(typeof document > "u" ? null : document.activeElement), B = o((e) => {
10
+ I.current = e, v(T, e);
11
+ }, [T]), V = c(!1), { ref: H, ...U } = P ?? {};
12
+ function W() {
13
+ return [...document.querySelectorAll("[role='dialog'][aria-modal='true'],[role='alertdialog'][aria-modal='true']")].at(-1) === I.current;
14
+ }
15
+ function G() {
16
+ !x && W() && b();
17
+ }
18
+ s(() => {
19
+ h() && M === void 0 && !V.current && m(j) && (V.current = !0, console.warn("[business-ui] ModalShell 的直接 <footer> child 会位于可滚动正文区。固定底栏请改用 footer 属性,并用 footerClassName 定制样式;组件不会自动搬运 children。"));
20
+ }, [j, M]);
21
+ function K(e) {
22
+ w && e.target === e.currentTarget && G(), e.target.closest("button,a[href],input,select,textarea,[tabindex]") || e.preventDefault();
23
+ }
24
+ return /* @__PURE__ */ u(f.Root, {
25
+ open: !0,
26
+ onOpenChange: (e) => {
27
+ e || G();
28
+ },
29
+ children: /* @__PURE__ */ u(f.Overlay, {
30
+ asChild: !0,
31
+ children: /* @__PURE__ */ u(f.Content, {
32
+ asChild: !0,
33
+ onEscapeKeyDown: (e) => {
34
+ (x || !E || I.current?.querySelector("[data-ui-aria-overlay]")) && e.preventDefault();
35
+ },
36
+ onInteractOutside: (e) => e.preventDefault(),
37
+ onOpenAutoFocus: (e) => {
38
+ let t = y(D);
39
+ t && !t.hasAttribute("disabled") && (e.preventDefault(), t.focus());
40
+ },
41
+ onCloseAutoFocus: (e) => {
42
+ if (e.preventDefault(), O !== !1) {
43
+ let e = y(O) ?? z.current;
44
+ e?.isConnected && e.focus();
45
+ }
46
+ },
47
+ children: /* @__PURE__ */ u("div", {
48
+ ref: B,
49
+ "data-ui-focus-managed": "radix",
50
+ className: `ui-modal-backdrop ${e}`.trim(),
51
+ role: k,
52
+ "aria-modal": "true",
53
+ "aria-labelledby": r,
54
+ "aria-describedby": A ?? (p === void 0 ? void 0 : `${r}-description`),
55
+ onMouseDown: K,
56
+ tabIndex: -1,
57
+ children: /* @__PURE__ */ d(t.Provider, {
58
+ value: L,
59
+ children: [/* @__PURE__ */ d("section", {
60
+ className: `ui-modal ${n}`.trim(),
61
+ children: [
62
+ /* @__PURE__ */ d("header", {
63
+ className: "ui-modal-header",
64
+ children: [/* @__PURE__ */ d("div", { children: [
65
+ i === void 0 ? null : /* @__PURE__ */ u("span", {
66
+ className: "ui-modal-eyebrow",
67
+ children: i
68
+ }),
69
+ /* @__PURE__ */ u(f.Title, {
70
+ asChild: !0,
71
+ children: /* @__PURE__ */ u("h2", {
72
+ id: r,
73
+ children: a
74
+ })
75
+ }),
76
+ p === void 0 ? null : /* @__PURE__ */ u(f.Description, {
77
+ asChild: !0,
78
+ children: /* @__PURE__ */ u("p", {
79
+ id: `${r}-description`,
80
+ children: p
81
+ })
82
+ })
83
+ ] }), S && /* @__PURE__ */ u(g, {
84
+ label: _,
85
+ disabled: x,
86
+ size: C,
87
+ onClose: G
88
+ })]
89
+ }),
90
+ /* @__PURE__ */ u("div", {
91
+ ...U,
92
+ ref: H,
93
+ className: `ui-modal-content ${N}`.trim(),
94
+ children: j
95
+ }),
96
+ M === void 0 ? null : /* @__PURE__ */ u("footer", {
97
+ className: `ui-modal-footer ${F}`.trim(),
98
+ children: M
99
+ })
100
+ ]
101
+ }), /* @__PURE__ */ u("div", {
102
+ ref: R,
103
+ className: "ui-overlay-container"
104
+ })]
105
+ })
106
+ })
107
+ })
108
+ })
109
+ });
110
+ }
111
+ function m(e) {
112
+ return r.toArray(e).some((e) => a(e) ? e.type === "footer" || e.type === i && m(e.props.children) : !1);
113
+ }
114
+ function h() {
115
+ return typeof process < "u" && process.env.NODE_ENV !== "production";
116
+ }
117
+ function g({ label: t, disabled: r, size: i, onClose: a }) {
118
+ return /* @__PURE__ */ u(e, {
119
+ className: "ui-modal-close",
120
+ variant: "ghost",
121
+ iconOnly: !0,
122
+ "aria-label": t,
123
+ onClick: a,
124
+ disabled: r,
125
+ children: /* @__PURE__ */ u(n, {
126
+ size: i,
127
+ "aria-hidden": "true"
128
+ })
129
+ });
130
+ }
131
+ var _ = p;
132
+ function v(e, t) {
133
+ typeof e == "function" ? e(t) : e && (e.current = t);
134
+ }
135
+ function y(e) {
136
+ return e && "current" in e ? e.current : e || null;
137
+ }
138
+ //#endregion
139
+ export { _ as Dialog, p as ModalShell };