@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,137 @@
1
+ import { useOverlayContainer as e } from "./OverlayContainer.js";
2
+ import { Check as t, ChevronDown as n, LoaderCircle as r } from "lucide-react";
3
+ import { useMemo as i, useState as a } from "react";
4
+ import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
5
+ import { Button as l, ComboBox as u, ComboBoxValue as d, Input as ee, Label as f, ListBox as te, ListBoxItem as ne, Popover as p, Tag as m, TagGroup as h, TagList as g, Text as _ } from "react-aria-components";
6
+ import { ListLayout as v, Virtualizer as y } from "react-aria-components/Virtualizer";
7
+ //#region src/MultiSelect.tsx
8
+ var b = [], x = [], re = {
9
+ rowSize: 48,
10
+ gap: 2,
11
+ padding: 4
12
+ };
13
+ function S({ values: S, defaultValues: C = x, onValuesChange: ie, name: w, selectedItems: T = b, items: E, disabled: D, clearLabel: O = "清空选择", selectionLabel: k = "已选项", maxSelected: A, inputValue: j, defaultInputValue: M, onInputChange: N, required: P, label: F, placeholder: I = "搜索或选择", helpText: L, error: R, loading: z, emptyText: B = "没有匹配项", inputRef: V, inputProps: H, placement: U = "bottom start", portalContainer: W, virtualized: G = E.length > 100, className: K = "" }) {
14
+ let [q, J] = a(C), Y = S ?? q, ae = e(W), X = i(() => {
15
+ let e = /* @__PURE__ */ new Map();
16
+ for (let t of T) e.set(t.id, t);
17
+ for (let t of E) e.set(t.id, t);
18
+ return e;
19
+ }, [T, E]), Z = i(() => [...Y], [Y]), oe = i(() => new Set(Y), [Y]), se = i(() => Z.map((e) => X.get(e) ?? {
20
+ id: e,
21
+ label: e
22
+ }), [Z, X]), ce = i(() => [...E], [E]), le = A !== void 0 && Y.length >= A;
23
+ function Q(e) {
24
+ D || A !== void 0 && e.length > A && e.length > Y.length || (S === void 0 && J(e), ie?.(e));
25
+ }
26
+ let $ = /* @__PURE__ */ s(te, {
27
+ items: ce,
28
+ className: "ui-combobox-list",
29
+ layout: G ? "grid" : "stack",
30
+ renderEmptyState: () => /* @__PURE__ */ s("div", {
31
+ className: "ui-combobox-empty",
32
+ children: z ? "正在加载…" : B
33
+ }),
34
+ children: (e) => /* @__PURE__ */ s(ne, {
35
+ id: e.id,
36
+ textValue: e.label,
37
+ isDisabled: e.disabled || le && !oe.has(e.id),
38
+ className: "ui-combobox-item",
39
+ children: ({ isSelected: n }) => /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ c("span", { children: [/* @__PURE__ */ s("strong", { children: e.label }), e.description && /* @__PURE__ */ s("small", { children: e.description })] }), n && /* @__PURE__ */ s(t, { size: 15 })] })
40
+ })
41
+ });
42
+ return /* @__PURE__ */ c(u, {
43
+ selectionMode: "multiple",
44
+ value: Z,
45
+ onChange: (e) => Q(e.map(String)),
46
+ inputValue: j,
47
+ defaultInputValue: M,
48
+ onInputChange: N,
49
+ isDisabled: D,
50
+ isRequired: P,
51
+ isInvalid: !!R,
52
+ menuTrigger: "focus",
53
+ allowsEmptyCollection: !0,
54
+ "aria-label": F === void 0 ? H?.["aria-label"] : void 0,
55
+ className: `ui-combobox ui-multi-select ${K}`.trim(),
56
+ children: [
57
+ F !== void 0 && /* @__PURE__ */ c(f, {
58
+ className: "ui-form-label",
59
+ children: [F, P && /* @__PURE__ */ s("span", {
60
+ className: "ui-form-required",
61
+ "aria-hidden": "true",
62
+ children: "*"
63
+ })]
64
+ }),
65
+ /* @__PURE__ */ c("div", {
66
+ className: "ui-combobox-control",
67
+ children: [/* @__PURE__ */ s(ee, {
68
+ ...H,
69
+ ref: V,
70
+ className: "ui-input",
71
+ placeholder: I
72
+ }), /* @__PURE__ */ s(l, {
73
+ className: "ui-combobox-trigger",
74
+ "aria-label": "展开选项",
75
+ children: s(z ? r : n, { size: 16 })
76
+ })]
77
+ }),
78
+ /* @__PURE__ */ s(d, { children: () => Y.length > 0 ? /* @__PURE__ */ c("div", {
79
+ className: "ui-multi-selection",
80
+ children: [/* @__PURE__ */ s(h, {
81
+ "aria-label": k,
82
+ onRemove: (e) => Q(Y.filter((t) => !e.has(t))),
83
+ disabledKeys: D ? Z : x,
84
+ children: /* @__PURE__ */ s(g, {
85
+ items: se,
86
+ children: (e) => /* @__PURE__ */ c(m, {
87
+ id: e.id,
88
+ textValue: e.label,
89
+ className: "ui-selection-tag",
90
+ children: [e.label, /* @__PURE__ */ s(l, {
91
+ slot: "remove",
92
+ "aria-label": `移除 ${e.label}`,
93
+ children: "×"
94
+ })]
95
+ })
96
+ })
97
+ }), /* @__PURE__ */ s("button", {
98
+ type: "button",
99
+ disabled: D,
100
+ className: "ui-selection-clear",
101
+ onClick: () => Q([]),
102
+ children: O
103
+ })]
104
+ }) : null }),
105
+ L !== void 0 && /* @__PURE__ */ s(_, {
106
+ slot: "description",
107
+ className: "ui-form-help",
108
+ children: L
109
+ }),
110
+ R && /* @__PURE__ */ s(_, {
111
+ slot: "errorMessage",
112
+ className: "ui-form-error",
113
+ children: R
114
+ }),
115
+ w && Y.map((e) => /* @__PURE__ */ s("input", {
116
+ type: "hidden",
117
+ name: w,
118
+ value: e,
119
+ disabled: D
120
+ }, e)),
121
+ /* @__PURE__ */ s(p, {
122
+ className: "ui-combobox-popover",
123
+ "data-ui-aria-overlay": "",
124
+ maxHeight: 320,
125
+ placement: U,
126
+ UNSTABLE_portalContainer: ae,
127
+ children: G ? /* @__PURE__ */ s(y, {
128
+ layout: v,
129
+ layoutOptions: re,
130
+ children: $
131
+ }) : $
132
+ })
133
+ ]
134
+ });
135
+ }
136
+ //#endregion
137
+ export { S as MultiSelect };
@@ -0,0 +1,97 @@
1
+ import { TextInput as e } from "./FormField.js";
2
+ import { formatDecimalAmount as t } from "./amount-format.js";
3
+ import { forwardRef as n, useLayoutEffect as r, useRef as i, useState as a } from "react";
4
+ import { jsx as o } from "react/jsx-runtime";
5
+ //#region src/NumericInput.tsx
6
+ var s = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/, c = /^[+-]?\d*(?:\.\d*)?$/, l = (e) => e.replace(/[,,\s]/gu, "");
7
+ function u(e, t) {
8
+ let n = e.startsWith("-"), [r, i = ""] = e.replace(/^[+-]/, "").split("."), a = (i + "0".repeat(t)).slice(0, t), o = BigInt(r || "0") * 10n ** BigInt(t) + BigInt(a || "0");
9
+ return Number(i[t] || "0") >= 5 && (o += 1n), n ? -o : o;
10
+ }
11
+ function d(e, t) {
12
+ let n = (e < 0n ? -e : e).toString().padStart(t + 1, "0"), r = t ? `${n.slice(0, -t)}.${n.slice(-t)}`.replace(/\.?0+$/, "") : n;
13
+ return `${e < 0n ? "-" : ""}${r}`;
14
+ }
15
+ function f(e, t, n) {
16
+ if (!Number.isInteger(e) || e < 0 || e > 100) throw RangeError("decimalPlaces must be an integer from 0 to 100");
17
+ for (let r of [t, n]) if (r !== void 0 && (!s.test(r) || d(u(r, e), e) !== p(r))) throw RangeError("Bounds must be decimal strings representable at decimalPlaces");
18
+ if (t !== void 0 && n !== void 0 && u(t, e) > u(n, e)) throw RangeError("min must not exceed max");
19
+ }
20
+ function p(e) {
21
+ let t = e.split(".")[1]?.length ?? 0;
22
+ return d(u(e, t), t);
23
+ }
24
+ function m(e, t, n, r) {
25
+ if (!s.test(e)) return "";
26
+ let i = u(e, t);
27
+ return n !== void 0 && i < u(n, t) && (i = u(n, t)), r !== void 0 && i > u(r, t) && (i = u(r, t)), d(i, t);
28
+ }
29
+ var h = n(function({ value: n, onValueCommit: s, onDraftChange: u, decimalPlaces: d = 2, moneyFormat: p, minimumFractionDigits: h = p ? Math.min(2, d) : 0, min: g, max: _, useGrouping: v = !0, selectAllOnFocus: y = !1, selectAllOnClick: b = !1, onFocus: x, onBlur: S, onChange: C, onClick: w, onKeyDown: T, onCompositionStart: E, onCompositionEnd: D, disabled: O, readOnly: k, inputMode: A = "decimal", ...j }, M) {
30
+ if (f(d, g, _), !Number.isInteger(h) || h < 0 || h > d) throw RangeError("minimumFractionDigits must be an integer between 0 and decimalPlaces");
31
+ let [N, P] = a(!1), [F, I] = a(""), L = i(!1), R = i(null);
32
+ r(() => {
33
+ R.current?.select(), R.current = null;
34
+ }, [N, F]);
35
+ let z = m(l(n), d, g, _), B = () => {
36
+ if (!N || O || k) return;
37
+ let e = m(l(F), d, g, _);
38
+ P(!1), s(e);
39
+ };
40
+ return /* @__PURE__ */ o(e, {
41
+ ...j,
42
+ ref: M,
43
+ type: "text",
44
+ inputMode: A,
45
+ disabled: O,
46
+ readOnly: k,
47
+ value: N ? F : t(z, {
48
+ moneyFormat: p,
49
+ useGrouping: v,
50
+ minimumFractionDigits: h
51
+ }),
52
+ onFocus: (e) => {
53
+ !O && !k && (I(z), P(!0)), y && (e.currentTarget.select(), R.current = e.currentTarget), x?.(e);
54
+ },
55
+ onClick: (e) => {
56
+ b && e.currentTarget.select(), w?.(e);
57
+ },
58
+ onChange: (e) => {
59
+ if (O || k) return;
60
+ let t = l(e.currentTarget.value);
61
+ (L.current || c.test(t)) && (P(!0), I(t), u?.(t)), C?.(e);
62
+ },
63
+ onCompositionStart: (e) => {
64
+ L.current = !0, E?.(e);
65
+ },
66
+ onCompositionEnd: (e) => {
67
+ L.current = !1;
68
+ let t = l(e.currentTarget.value);
69
+ c.test(t) || I(z), D?.(e);
70
+ },
71
+ onBlur: (e) => {
72
+ B(), S?.(e);
73
+ },
74
+ onKeyDown: (e) => {
75
+ T?.(e), e.key === "Enter" && !e.defaultPrevented && !L.current && !e.nativeEvent.isComposing && (e.preventDefault(), e.currentTarget.blur());
76
+ }
77
+ });
78
+ }), g = n(function({ value: e, onValueCommit: t, scale: n = 100, min: r = -(2 ** 53 - 1), max: i = 2 ** 53 - 1, ...a }, s) {
79
+ let c = Math.log10(n);
80
+ if (!Number.isSafeInteger(n) || !Number.isInteger(c) || c < 0) throw RangeError("scale must be a positive safe integer power of ten");
81
+ for (let t of [
82
+ e,
83
+ r,
84
+ i
85
+ ]) if (t !== null && !Number.isSafeInteger(t)) throw RangeError("Scaled values and bounds must be safe integers");
86
+ return /* @__PURE__ */ o(h, {
87
+ ...a,
88
+ ref: s,
89
+ decimalPlaces: c,
90
+ value: e === null ? "" : d(BigInt(e), c),
91
+ min: d(BigInt(r), c),
92
+ max: d(BigInt(i), c),
93
+ onValueCommit: (e) => t(e === "" ? null : Number(u(e, c)))
94
+ });
95
+ });
96
+ //#endregion
97
+ export { h as NumericInput, g as ScaledNumericInput };
@@ -0,0 +1,9 @@
1
+ import { createContext as e, useContext as t } from "react";
2
+ //#region src/OverlayContainer.tsx
3
+ var n = e(null);
4
+ function r(e) {
5
+ let r = t(n);
6
+ return e ?? r ?? void 0;
7
+ }
8
+ //#endregion
9
+ export { n as OverlayContainerContext, r as useOverlayContainer };
@@ -0,0 +1,36 @@
1
+ import { joinClassNames as e } from "./classNames.js";
2
+ import { forwardRef as t } from "react";
3
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
4
+ //#region src/PageHeader.tsx
5
+ var i = t(function({ eyebrow: t, title: i, titleId: a, description: o, actions: s, copyProps: c, actionsProps: l, className: u, ...d }, f) {
6
+ return /* @__PURE__ */ r("header", {
7
+ ...d,
8
+ ref: f,
9
+ className: e("ui-page-header", u),
10
+ children: [/* @__PURE__ */ r("div", {
11
+ ...c,
12
+ className: e("ui-page-header-copy", c?.className),
13
+ children: [
14
+ t === void 0 ? null : /* @__PURE__ */ n("div", {
15
+ className: "ui-page-header-eyebrow",
16
+ children: t
17
+ }),
18
+ /* @__PURE__ */ n("h1", {
19
+ id: a,
20
+ className: "ui-page-header-title",
21
+ children: i
22
+ }),
23
+ o === void 0 ? null : /* @__PURE__ */ n("div", {
24
+ className: "ui-page-header-description",
25
+ children: o
26
+ })
27
+ ]
28
+ }), s === void 0 ? null : /* @__PURE__ */ n("div", {
29
+ ...l,
30
+ className: e("ui-page-header-actions", l?.className),
31
+ children: s
32
+ })]
33
+ });
34
+ });
35
+ //#endregion
36
+ export { i as PageHeader };
@@ -0,0 +1,115 @@
1
+ import { ChevronLeft as e, ChevronRight as t } from "lucide-react";
2
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
3
+ //#region src/Pagination.tsx
4
+ function i({ totalItems: i, page: c, pageSize: l, onPageChange: u, onPageSizeChange: d, itemLabel: f = "条记录", pageSizeOptions: p = [
5
+ 10,
6
+ 20,
7
+ 50
8
+ ], compact: m = !1 }) {
9
+ let h = a(i, l), g = o(c, i, l), _ = i ? (g - 1) * l + 1 : 0, v = Math.min(g * l, i);
10
+ return /* @__PURE__ */ r("nav", {
11
+ className: `ui-pagination${m ? " compact" : ""}`,
12
+ "aria-label": "列表分页",
13
+ children: [
14
+ /* @__PURE__ */ r("span", {
15
+ className: "ui-pagination-summary",
16
+ children: [
17
+ "共 ",
18
+ i,
19
+ " ",
20
+ f,
21
+ ",当前 ",
22
+ _,
23
+ "–",
24
+ v
25
+ ]
26
+ }),
27
+ /* @__PURE__ */ r("div", {
28
+ className: "ui-pagination-pages",
29
+ children: [
30
+ /* @__PURE__ */ n("button", {
31
+ type: "button",
32
+ "aria-label": "上一页",
33
+ disabled: g <= 1,
34
+ onClick: () => u(g - 1),
35
+ children: /* @__PURE__ */ n(e, { size: 15 })
36
+ }),
37
+ !m && s(g, h).map((e, t) => e === "ellipsis" ? /* @__PURE__ */ n("i", {
38
+ className: "ui-page-ellipsis",
39
+ children: "…"
40
+ }, `ellipsis-${t}`) : /* @__PURE__ */ n("button", {
41
+ type: "button",
42
+ className: `ui-page-number${e === g ? " active" : ""}`,
43
+ "aria-current": e === g ? "page" : void 0,
44
+ "aria-label": `第 ${e} 页`,
45
+ onClick: () => u(e),
46
+ children: e
47
+ }, e)),
48
+ m && /* @__PURE__ */ r("span", { children: [
49
+ "第 ",
50
+ g,
51
+ " / ",
52
+ h,
53
+ " 页"
54
+ ] }),
55
+ !m && /* @__PURE__ */ r("span", {
56
+ className: "ui-pagination-auto-compact",
57
+ children: [
58
+ "第 ",
59
+ g,
60
+ " / ",
61
+ h,
62
+ " 页"
63
+ ]
64
+ }),
65
+ /* @__PURE__ */ n("button", {
66
+ type: "button",
67
+ "aria-label": "下一页",
68
+ disabled: g >= h,
69
+ onClick: () => u(g + 1),
70
+ children: /* @__PURE__ */ n(t, { size: 15 })
71
+ })
72
+ ]
73
+ }),
74
+ d && /* @__PURE__ */ r("label", {
75
+ className: "ui-pagination-size",
76
+ children: [
77
+ /* @__PURE__ */ n("span", { children: "每页" }),
78
+ /* @__PURE__ */ n("select", {
79
+ "aria-label": "每页显示数量",
80
+ value: l,
81
+ onChange: (e) => d(Number(e.target.value)),
82
+ children: p.map((e) => /* @__PURE__ */ n("option", {
83
+ value: e,
84
+ children: e
85
+ }, e))
86
+ }),
87
+ /* @__PURE__ */ n("span", { children: "条" })
88
+ ]
89
+ })
90
+ ]
91
+ });
92
+ }
93
+ function a(e, t) {
94
+ return Math.max(1, Math.ceil(e / Math.max(1, t)));
95
+ }
96
+ function o(e, t, n) {
97
+ return Math.min(Math.max(1, e), a(t, n));
98
+ }
99
+ function s(e, t) {
100
+ if (t <= 7) return Array.from({ length: t }, (e, t) => t + 1);
101
+ let n = [.../* @__PURE__ */ new Set([
102
+ 1,
103
+ t,
104
+ e - 1,
105
+ e,
106
+ e + 1
107
+ ])].filter((e) => e >= 1 && e <= t).sort((e, t) => e - t), r = [];
108
+ for (let e of n) {
109
+ let t = r.at(-1);
110
+ typeof t == "number" && e - t > 1 && r.push("ellipsis"), r.push(e);
111
+ }
112
+ return r;
113
+ }
114
+ //#endregion
115
+ export { i as Pagination, o as clampPage, a as pageCount, s as visiblePages };
@@ -0,0 +1,30 @@
1
+ import { FileDropzone as e, acceptsFile as t } from "./FileDropzone.js";
2
+ import { useFilePreparation as n } from "./useFilePreparation.js";
3
+ import { FilePreparationDialog as r } from "./FilePreparationDialog.js";
4
+ import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ //#region src/PreparedFileDropzone.tsx
6
+ function s({ ownerKey: s, prepareFile: c, errorMessage: l, labels: u, onFilesSelected: d, ...f }) {
7
+ let p = n({
8
+ ownerKey: s,
9
+ disabled: f.disabled,
10
+ errorMessage: l,
11
+ onFilesSelected: d,
12
+ prepareFile: async (e, n) => {
13
+ let r = await c(e, n);
14
+ if (!t(r, f.accept) || f.maxFileSize !== void 0 && r.size > f.maxFileSize) throw Error("PREPARED_FILE_REJECTED");
15
+ return r;
16
+ }
17
+ });
18
+ return /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ a(e, {
19
+ ...f,
20
+ disabled: f.disabled || p.busy,
21
+ onFilesSelected: (e) => {
22
+ p.selectFiles(e);
23
+ }
24
+ }), /* @__PURE__ */ a(r, {
25
+ preparation: p,
26
+ labels: u
27
+ })] });
28
+ }
29
+ //#endregion
30
+ export { s as PreparedFileDropzone };
@@ -0,0 +1,35 @@
1
+ import { Button as e } from "./Button.js";
2
+ import { AlertCircle as t, LoaderCircle as n, RefreshCw as r } from "lucide-react";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ //#region src/RecoverableAsyncState.tsx
5
+ function o(o) {
6
+ let s = o.phase === "error";
7
+ return /* @__PURE__ */ a("div", {
8
+ className: `ui-async-state${o.compact ? " compact" : ""}`,
9
+ role: s ? "alert" : "status",
10
+ "aria-live": s ? "assertive" : "polite",
11
+ children: [
12
+ s ? /* @__PURE__ */ i(t, {
13
+ "aria-hidden": "true",
14
+ size: 18
15
+ }) : /* @__PURE__ */ i(n, {
16
+ "aria-hidden": "true",
17
+ className: "spin",
18
+ size: 18
19
+ }),
20
+ /* @__PURE__ */ a("span", { children: [/* @__PURE__ */ i("strong", { children: s ? o.errorTitle : o.loadingTitle }), o.detail && /* @__PURE__ */ i("small", { children: o.detail })] }),
21
+ s && o.onRetry && /* @__PURE__ */ a(e, {
22
+ variant: "outline",
23
+ size: "compact",
24
+ onClick: o.onRetry,
25
+ children: [/* @__PURE__ */ i(r, {
26
+ "aria-hidden": "true",
27
+ size: 15
28
+ }), o.retryLabel ?? "重新加载"]
29
+ })
30
+ ]
31
+ });
32
+ }
33
+ var s = o;
34
+ //#endregion
35
+ export { s as AsyncState, o as RecoverableAsyncState };
@@ -0,0 +1,54 @@
1
+ import { useRef as e } from "react";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/RovingTabs.tsx
4
+ function n(n) {
5
+ let r = e(/* @__PURE__ */ new Map()), s = n.options.map((e) => e.value);
6
+ function c(e) {
7
+ let t = i(s, n.value, e.key);
8
+ t !== null && (e.preventDefault(), n.onChange(t), r.current.get(t)?.focus());
9
+ }
10
+ return /* @__PURE__ */ t("div", {
11
+ className: `ui-tabs ${n.className ?? ""}`.trim(),
12
+ role: "tablist",
13
+ "aria-label": n.label,
14
+ "aria-orientation": "horizontal",
15
+ children: n.options.map((e) => {
16
+ let i = e.value === n.value;
17
+ return /* @__PURE__ */ t("button", {
18
+ id: a(n.groupId, e.value),
19
+ type: "button",
20
+ role: "tab",
21
+ "aria-selected": i,
22
+ "aria-controls": o(n.groupId, e.value),
23
+ tabIndex: i ? 0 : -1,
24
+ className: i ? "active" : "",
25
+ ref: (t) => {
26
+ t ? r.current.set(e.value, t) : r.current.delete(e.value);
27
+ },
28
+ onKeyDown: c,
29
+ onClick: () => n.onChange(e.value),
30
+ children: e.label
31
+ }, e.value);
32
+ })
33
+ });
34
+ }
35
+ function r({ groupId: e, value: n, className: r, children: i }) {
36
+ return /* @__PURE__ */ t("section", {
37
+ id: o(e, n),
38
+ role: "tabpanel",
39
+ "aria-labelledby": a(e, n),
40
+ className: r,
41
+ children: i
42
+ });
43
+ }
44
+ function i(e, t, n) {
45
+ return e.length ? n === "Home" ? e[0] : n === "End" ? e[e.length - 1] : n !== "ArrowLeft" && n !== "ArrowRight" ? null : e[(Math.max(0, e.indexOf(t)) + (n === "ArrowRight" ? 1 : -1) + e.length) % e.length] : null;
46
+ }
47
+ function a(e, t) {
48
+ return `${e}-tab-${t}`;
49
+ }
50
+ function o(e, t) {
51
+ return `${e}-panel-${t}`;
52
+ }
53
+ //#endregion
54
+ export { n as RovingTabList, r as RovingTabPanel, i as nextRovingTabValue };
@@ -0,0 +1,35 @@
1
+ import { joinClassNames as e } from "./classNames.js";
2
+ import { createElement as t, forwardRef as n, useId as r } from "react";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ //#region src/SectionCard.tsx
5
+ var o = n(function({ title: n, description: o, actions: s, children: c, headingId: l, headingLevel: u = 2, className: d, "aria-label": f, "aria-labelledby": p, ...m }, h) {
6
+ let g = r(), _ = l ?? g, v = f === void 0 ? p ?? _ : p, y = t(`h${u}`, {
7
+ id: _,
8
+ className: "ui-section-card-title"
9
+ }, n);
10
+ return /* @__PURE__ */ a("section", {
11
+ ...m,
12
+ ref: h,
13
+ "aria-label": f,
14
+ "aria-labelledby": v,
15
+ className: e("ui-section-card", d),
16
+ children: [/* @__PURE__ */ a("div", {
17
+ className: "ui-section-card-header",
18
+ children: [/* @__PURE__ */ a("div", {
19
+ className: "ui-section-card-copy",
20
+ children: [y, o === void 0 ? null : /* @__PURE__ */ i("div", {
21
+ className: "ui-section-card-description",
22
+ children: o
23
+ })]
24
+ }), s === void 0 ? null : /* @__PURE__ */ i("div", {
25
+ className: "ui-section-card-actions",
26
+ children: s
27
+ })]
28
+ }), /* @__PURE__ */ i("div", {
29
+ className: "ui-section-card-body",
30
+ children: c
31
+ })]
32
+ });
33
+ });
34
+ //#endregion
35
+ export { o as SectionCard };
@@ -0,0 +1,46 @@
1
+ import { useId as e } from "react";
2
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
+ //#region src/SegmentedControl.tsx
4
+ function r({ value: r, options: i, onChange: a, name: o, disabled: s = !1, className: c, size: l = "default", variant: u = "solid", block: d = !0, orientation: f = "horizontal", shape: p = "default", ...m }) {
5
+ let h = e();
6
+ return /* @__PURE__ */ t("div", {
7
+ role: "radiogroup",
8
+ "aria-label": m["aria-label"],
9
+ "aria-disabled": s || void 0,
10
+ className: [
11
+ "ui-segmented-control",
12
+ `ui-segmented-${l}`,
13
+ `ui-segmented-${u}`,
14
+ !d && "ui-segmented-inline",
15
+ `ui-segmented-${f}`,
16
+ `ui-segmented-shape-${p}`,
17
+ c
18
+ ].filter(Boolean).join(" "),
19
+ children: i.map((e) => /* @__PURE__ */ n("label", {
20
+ className: "ui-segmented-option",
21
+ children: [/* @__PURE__ */ t("input", {
22
+ type: "radio",
23
+ name: o ?? h,
24
+ value: e.value,
25
+ checked: e.value === r,
26
+ "aria-label": e["aria-label"],
27
+ disabled: s || e.disabled,
28
+ onChange: () => {
29
+ !s && !e.disabled && a(e.value);
30
+ }
31
+ }), /* @__PURE__ */ n("span", {
32
+ className: "ui-segmented-content",
33
+ children: [e.icon != null && /* @__PURE__ */ t("span", {
34
+ className: "ui-segmented-icon",
35
+ "aria-hidden": "true",
36
+ children: e.icon
37
+ }), /* @__PURE__ */ t("span", {
38
+ className: "ui-segmented-label",
39
+ children: e.label
40
+ })]
41
+ })]
42
+ }, e.value))
43
+ });
44
+ }
45
+ //#endregion
46
+ export { r as SegmentedControl };
package/dist/Select.js ADDED
@@ -0,0 +1,73 @@
1
+ import { useOverlayContainer as e } from "./OverlayContainer.js";
2
+ import { FormField as t } from "./FormField.js";
3
+ import { Check as n, ChevronDown as r, ChevronUp as i } from "lucide-react";
4
+ import { useId as a } from "react";
5
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
6
+ import * as c from "@radix-ui/react-select";
7
+ //#region src/Select.tsx
8
+ function l({ value: l, defaultValue: f, onValueChange: p, options: m, label: h, placeholder: g = "请选择", helpText: _, error: v, required: y, disabled: b, name: x, id: S, className: C = "", triggerRef: w, triggerProps: T, portalContainer: E, placement: D }) {
9
+ let O = a(), k = S ?? O, A = e(E), j = /* @__PURE__ */ s(c.Root, {
10
+ value: l,
11
+ defaultValue: f,
12
+ onValueChange: p,
13
+ disabled: b,
14
+ name: x,
15
+ required: y,
16
+ children: [/* @__PURE__ */ s(c.Trigger, {
17
+ ...T,
18
+ ref: w,
19
+ id: k,
20
+ className: `ui-select-trigger ${C}`.trim(),
21
+ "aria-invalid": v ? !0 : T?.["aria-invalid"],
22
+ "aria-describedby": d(T?.["aria-describedby"], u(k, _, v)),
23
+ children: [/* @__PURE__ */ o(c.Value, { placeholder: g }), /* @__PURE__ */ o(c.Icon, { children: /* @__PURE__ */ o(r, { size: 16 }) })]
24
+ }), /* @__PURE__ */ o(c.Portal, {
25
+ container: A,
26
+ children: /* @__PURE__ */ s(c.Content, {
27
+ className: "ui-select-content",
28
+ position: "popper",
29
+ sideOffset: 6,
30
+ collisionPadding: 10,
31
+ ...D,
32
+ children: [
33
+ /* @__PURE__ */ o(c.ScrollUpButton, {
34
+ className: "ui-select-scroll",
35
+ children: /* @__PURE__ */ o(i, { size: 16 })
36
+ }),
37
+ /* @__PURE__ */ o(c.Viewport, {
38
+ className: "ui-select-viewport",
39
+ children: m.map((e) => /* @__PURE__ */ s(c.Item, {
40
+ value: e.value,
41
+ disabled: e.disabled,
42
+ className: "ui-select-item",
43
+ children: [/* @__PURE__ */ o(c.ItemText, { children: e.label }), /* @__PURE__ */ o(c.ItemIndicator, {
44
+ className: "ui-select-indicator",
45
+ children: /* @__PURE__ */ o(n, { size: 15 })
46
+ })]
47
+ }, e.value))
48
+ }),
49
+ /* @__PURE__ */ o(c.ScrollDownButton, {
50
+ className: "ui-select-scroll",
51
+ children: /* @__PURE__ */ o(r, { size: 16 })
52
+ })
53
+ ]
54
+ })
55
+ })]
56
+ });
57
+ return h === void 0 && _ === void 0 && !v ? j : /* @__PURE__ */ o(t, {
58
+ controlId: k,
59
+ label: h,
60
+ required: y,
61
+ helpText: _,
62
+ error: v,
63
+ children: j
64
+ });
65
+ }
66
+ function u(e, t, n) {
67
+ return [t === void 0 ? "" : `${e}-help`, n === void 0 || n === "" ? "" : `${e}-error`].filter(Boolean).join(" ") || void 0;
68
+ }
69
+ function d(...e) {
70
+ return e.filter(Boolean).join(" ") || void 0;
71
+ }
72
+ //#endregion
73
+ export { l as Select };