@hxdhxd/harmony-flow-ui 0.1.0

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.
package/dist/index.js ADDED
@@ -0,0 +1,3200 @@
1
+ // src/theme/tokens.ts
2
+ var defaultTheme = {
3
+ colorPrimary: "#0a7cff",
4
+ colorPrimaryHover: "#006fe8",
5
+ colorBackground: "#f5faff",
6
+ colorSurface: "#ffffff",
7
+ colorText: "#142033",
8
+ colorTextMuted: "#66758c",
9
+ colorBorder: "#dce9f7",
10
+ radiusMd: "14px",
11
+ radiusLg: "24px",
12
+ shadowElevated: "0 18px 48px rgba(41, 106, 168, 0.16)",
13
+ motionDuration: "180ms"
14
+ };
15
+ var darkTheme = { ...defaultTheme, colorPrimary: "#58a9ff", colorPrimaryHover: "#7cbbff", colorBackground: "#0d1724", colorSurface: "#152337", colorText: "#f4f8fc", colorTextMuted: "#a9bad0", colorBorder: "#30445b", shadowElevated: "0 20px 54px rgba(0,0,0,.46)" };
16
+ var highContrastTheme = { ...defaultTheme, colorPrimary: "#005fcc", colorPrimaryHover: "#004a9f", colorBackground: "#ffffff", colorSurface: "#ffffff", colorText: "#000000", colorTextMuted: "#303030", colorBorder: "#000000", shadowElevated: "0 0 0 2px #000000", motionDuration: "0ms" };
17
+ var tokenVariables = {
18
+ colorPrimary: "--hf-color-primary",
19
+ colorPrimaryHover: "--hf-color-primary-hover",
20
+ colorBackground: "--hf-color-background",
21
+ colorSurface: "--hf-color-surface",
22
+ colorText: "--hf-color-text",
23
+ colorTextMuted: "--hf-color-text-muted",
24
+ colorBorder: "--hf-color-border",
25
+ radiusMd: "--hf-radius-md",
26
+ radiusLg: "--hf-radius-lg",
27
+ shadowElevated: "--hf-shadow-elevated",
28
+ motionDuration: "--hf-motion-duration"
29
+ };
30
+ function tokensToStyle(tokens) {
31
+ return Object.fromEntries(
32
+ Object.entries(tokens).map(([key, value]) => [tokenVariables[key], value])
33
+ );
34
+ }
35
+
36
+ // src/theme/ThemeProvider.tsx
37
+ import { jsx } from "react/jsx-runtime";
38
+ function ThemeProvider({ children, tokens, mode = "light", className = "", style, ...props }) {
39
+ const mergedTokens = { ...mode === "dark" ? darkTheme : mode === "high-contrast" ? highContrastTheme : defaultTheme, ...tokens };
40
+ return /* @__PURE__ */ jsx(
41
+ "div",
42
+ {
43
+ className: `hf-theme hf-theme--${mode} ${className}`.trim(),
44
+ style: { ...tokensToStyle(mergedTokens), ...style },
45
+ ...props,
46
+ children
47
+ }
48
+ );
49
+ }
50
+
51
+ // src/components/Button.tsx
52
+ import { forwardRef } from "react";
53
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
54
+ var Button = forwardRef(function Button2({ children, className = "", variant = "primary", size = "md", shape = "pill", fullWidth = false, loading = false, leadingIcon, trailingIcon, iconOnly = false, disabled, ...props }, ref) {
55
+ return /* @__PURE__ */ jsxs(
56
+ "button",
57
+ {
58
+ ref,
59
+ className: `hf-button hf-button--${variant} hf-button--${size} hf-button--${shape} ${fullWidth ? "hf-button--full" : ""} ${iconOnly ? "hf-button--icon" : ""} ${className}`.trim(),
60
+ disabled: disabled || loading,
61
+ "aria-busy": loading || void 0,
62
+ ...props,
63
+ children: [
64
+ loading ? /* @__PURE__ */ jsx2("span", { className: "hf-spinner", "aria-hidden": "true" }) : leadingIcon,
65
+ !iconOnly && /* @__PURE__ */ jsx2("span", { children: loading ? "\u5904\u7406\u4E2D" : children }),
66
+ !loading && trailingIcon
67
+ ]
68
+ }
69
+ );
70
+ });
71
+
72
+ // src/components/SplitButton.tsx
73
+ import { useState } from "react";
74
+
75
+ // src/foundations/Icon.tsx
76
+ import { jsx as jsx3 } from "react/jsx-runtime";
77
+ var paths = {
78
+ check: "M5 12.5 9.2 17 19 7",
79
+ close: "m7 7 10 10M17 7 7 17",
80
+ info: "M12 11v6M12 7.5h.01",
81
+ warning: "M12 4 3.5 19h17L12 4Zm0 5v4.5m0 2.5h.01",
82
+ error: "M8 8l8 8m0-8-8 8",
83
+ search: "m20 20-4.5-4.5m2.5-4A7 7 0 1 1 4 11a7 7 0 0 1 14 0Z",
84
+ "chevron-down": "m7 10 5 5 5-5",
85
+ "arrow-right": "M5 12h14m-5-5 5 5-5 5",
86
+ user: "M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm7 8a7 7 0 0 0-14 0",
87
+ inbox: "M4 5h16v13H4V5Zm0 9h4l2 2h4l2-2h4"
88
+ };
89
+ function Icon({ name, size = 20, label, className = "", ...props }) {
90
+ return /* @__PURE__ */ jsx3("svg", { className: `hf-icon ${className}`, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", role: label ? "img" : void 0, "aria-label": label, "aria-hidden": label ? void 0 : true, ...props, children: /* @__PURE__ */ jsx3("path", { d: paths[name] }) });
91
+ }
92
+
93
+ // src/overlays/useOverlay.ts
94
+ import { useEffect, useRef } from "react";
95
+ var focusableSelector = [
96
+ "a[href]",
97
+ "button:not([disabled])",
98
+ "input:not([disabled])",
99
+ "select:not([disabled])",
100
+ "textarea:not([disabled])",
101
+ '[tabindex]:not([tabindex="-1"])'
102
+ ].join(",");
103
+ var layerStack = [];
104
+ var scrollLockCount = 0;
105
+ var previousBodyOverflow = "";
106
+ function isTopLayer(id) {
107
+ return layerStack.at(-1)?.id === id;
108
+ }
109
+ function addLayer(id) {
110
+ layerStack.push({ id });
111
+ }
112
+ function removeLayer(id) {
113
+ const index = layerStack.findIndex((layer) => layer.id === id);
114
+ if (index >= 0) layerStack.splice(index, 1);
115
+ }
116
+ function lockBodyScroll() {
117
+ if (scrollLockCount === 0) {
118
+ previousBodyOverflow = document.body.style.overflow;
119
+ document.body.style.overflow = "hidden";
120
+ }
121
+ scrollLockCount += 1;
122
+ }
123
+ function unlockBodyScroll() {
124
+ scrollLockCount = Math.max(0, scrollLockCount - 1);
125
+ if (scrollLockCount === 0) document.body.style.overflow = previousBodyOverflow;
126
+ }
127
+ function focusInitialElement(root) {
128
+ const target = root.querySelector("[data-autofocus], [autofocus]") ?? root.querySelector(focusableSelector) ?? root;
129
+ target.focus();
130
+ }
131
+ function trapTabKey(event, root) {
132
+ const nodes = [...root.querySelectorAll(focusableSelector)].filter((node) => !node.hasAttribute("disabled") && node.getAttribute("aria-hidden") !== "true");
133
+ if (!nodes.length) {
134
+ event.preventDefault();
135
+ root.focus();
136
+ return;
137
+ }
138
+ const first = nodes[0];
139
+ const last = nodes[nodes.length - 1];
140
+ if (event.shiftKey && document.activeElement === first) {
141
+ event.preventDefault();
142
+ last.focus();
143
+ } else if (!event.shiftKey && document.activeElement === last) {
144
+ event.preventDefault();
145
+ first.focus();
146
+ }
147
+ }
148
+ function useDismissibleLayer(open, onClose, modalOrOptions = false) {
149
+ const ref = useRef(null);
150
+ const idRef = useRef(/* @__PURE__ */ Symbol("dismissible-layer"));
151
+ const closeRef = useRef(onClose);
152
+ closeRef.current = onClose;
153
+ const options = typeof modalOrOptions === "boolean" ? { modal: modalOrOptions } : modalOrOptions;
154
+ const modal = options.modal ?? false;
155
+ const closeOnOutside = options.closeOnOutside ?? !modal;
156
+ const trapFocus = options.trapFocus ?? modal;
157
+ const lockScroll = options.lockScroll ?? modal;
158
+ const autoFocus = options.autoFocus ?? true;
159
+ const restoreFocus = options.restoreFocus ?? true;
160
+ useEffect(() => {
161
+ if (!open) return void 0;
162
+ const id = idRef.current;
163
+ const previousFocus = document.activeElement;
164
+ addLayer(id);
165
+ if (lockScroll) lockBodyScroll();
166
+ const handlePointerDown = (event) => {
167
+ if (!isTopLayer(id) || !closeOnOutside) return;
168
+ if (!ref.current?.contains(event.target)) closeRef.current();
169
+ };
170
+ const handleKeyDown = (event) => {
171
+ if (!isTopLayer(id)) return;
172
+ if (event.key === "Escape") {
173
+ event.preventDefault();
174
+ event.stopPropagation();
175
+ closeRef.current();
176
+ } else if (event.key === "Tab" && trapFocus && ref.current) {
177
+ trapTabKey(event, ref.current);
178
+ }
179
+ };
180
+ document.addEventListener("pointerdown", handlePointerDown);
181
+ document.addEventListener("keydown", handleKeyDown, true);
182
+ const animationFrame = autoFocus ? requestAnimationFrame(() => ref.current && focusInitialElement(ref.current)) : void 0;
183
+ return () => {
184
+ if (animationFrame !== void 0) cancelAnimationFrame(animationFrame);
185
+ document.removeEventListener("pointerdown", handlePointerDown);
186
+ document.removeEventListener("keydown", handleKeyDown, true);
187
+ removeLayer(id);
188
+ if (lockScroll) unlockBodyScroll();
189
+ if (restoreFocus && previousFocus?.isConnected) previousFocus.focus();
190
+ };
191
+ }, [autoFocus, closeOnOutside, lockScroll, modal, open, restoreFocus, trapFocus]);
192
+ return ref;
193
+ }
194
+
195
+ // src/components/SplitButton.tsx
196
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
197
+ function SplitButton({ label, options, onPrimaryAction, onOptionSelect, variant = "primary", size = "md", disabled }) {
198
+ const [open, setOpen] = useState(false);
199
+ const ref = useDismissibleLayer(open, () => setOpen(false), { autoFocus: false });
200
+ return /* @__PURE__ */ jsxs2("div", { className: "hf-split-button", ref, children: [
201
+ /* @__PURE__ */ jsx4(Button, { variant, size, shape: "rounded", disabled, onClick: onPrimaryAction, children: label }),
202
+ /* @__PURE__ */ jsx4(Button, { variant, size, shape: "rounded", disabled, iconOnly: true, leadingIcon: /* @__PURE__ */ jsx4(Icon, { name: "chevron-down", size: 16 }), "aria-label": "\u66F4\u591A\u64CD\u4F5C", "aria-expanded": open, onClick: () => setOpen(!open) }),
203
+ open && /* @__PURE__ */ jsx4("div", { className: "hf-split-button__menu", role: "menu", children: options.map((option) => /* @__PURE__ */ jsx4("button", { role: "menuitem", type: "button", disabled: option.disabled, className: option.danger ? "is-danger" : "", onClick: () => {
204
+ onOptionSelect(option.key);
205
+ setOpen(false);
206
+ }, children: option.label }, option.key)) })
207
+ ] });
208
+ }
209
+
210
+ // src/components/Input.tsx
211
+ import { forwardRef as forwardRef2, useId } from "react";
212
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
213
+ var Input = forwardRef2(function Input2({ className = "", id, label, hint, error, prefix, disabled, ...props }, ref) {
214
+ const generatedId = useId();
215
+ const inputId = id ?? generatedId;
216
+ const descriptionId = `${inputId}-description`;
217
+ return /* @__PURE__ */ jsxs3("label", { className: `hf-field ${className}`.trim(), htmlFor: inputId, children: [
218
+ label && /* @__PURE__ */ jsx5("span", { className: "hf-field__label", children: label }),
219
+ /* @__PURE__ */ jsxs3("span", { className: `hf-input-shell ${error ? "hf-input-shell--error" : ""}`, children: [
220
+ prefix && /* @__PURE__ */ jsx5("span", { className: "hf-input-shell__prefix", "aria-hidden": "true", children: prefix }),
221
+ /* @__PURE__ */ jsx5(
222
+ "input",
223
+ {
224
+ ref,
225
+ id: inputId,
226
+ className: "hf-input",
227
+ disabled,
228
+ "aria-invalid": Boolean(error),
229
+ "aria-describedby": hint || error ? descriptionId : void 0,
230
+ ...props
231
+ }
232
+ )
233
+ ] }),
234
+ (error || hint) && /* @__PURE__ */ jsx5("span", { id: descriptionId, className: `hf-field__hint ${error ? "hf-field__hint--error" : ""}`, children: error ?? hint })
235
+ ] });
236
+ });
237
+
238
+ // src/components/Switch.tsx
239
+ import { forwardRef as forwardRef3 } from "react";
240
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
241
+ var Switch = forwardRef3(function Switch2({ label, className = "", ...props }, ref) {
242
+ return /* @__PURE__ */ jsxs4("label", { className: `hf-switch ${className}`.trim(), children: [
243
+ /* @__PURE__ */ jsx6("input", { ref, className: "hf-switch__input", type: "checkbox", role: "switch", ...props }),
244
+ /* @__PURE__ */ jsx6("span", { className: "hf-switch__track", "aria-hidden": "true", children: /* @__PURE__ */ jsx6("span", { className: "hf-switch__thumb" }) }),
245
+ /* @__PURE__ */ jsx6("span", { className: "hf-switch__label", children: label })
246
+ ] });
247
+ });
248
+
249
+ // src/components/SegmentedControl.tsx
250
+ import { useId as useId2 } from "react";
251
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
252
+ function SegmentedControl({ label, options, value, onChange, className = "" }) {
253
+ const name = useId2();
254
+ return /* @__PURE__ */ jsxs5("fieldset", { className: `hf-segmented ${className}`.trim(), "aria-label": label, children: [
255
+ /* @__PURE__ */ jsx7("legend", { className: "hf-sr-only", children: label }),
256
+ options.map((option) => /* @__PURE__ */ jsxs5("label", { className: "hf-segmented__option", children: [
257
+ /* @__PURE__ */ jsx7(
258
+ "input",
259
+ {
260
+ type: "radio",
261
+ name,
262
+ value: option.value,
263
+ checked: value === option.value,
264
+ onChange: () => onChange(option.value)
265
+ }
266
+ ),
267
+ /* @__PURE__ */ jsx7("span", { children: option.label })
268
+ ] }, option.value))
269
+ ] });
270
+ }
271
+
272
+ // src/components/Card.tsx
273
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
274
+ function Card({ children, title, eyebrow, action, interactive = false, className = "", ...props }) {
275
+ return /* @__PURE__ */ jsxs6("article", { className: `hf-card ${interactive ? "hf-card--interactive" : ""} ${className}`.trim(), ...props, children: [
276
+ (eyebrow || title || action) && /* @__PURE__ */ jsxs6("header", { className: "hf-card__header", children: [
277
+ /* @__PURE__ */ jsxs6("div", { children: [
278
+ eyebrow && /* @__PURE__ */ jsx8("p", { className: "hf-card__eyebrow", children: eyebrow }),
279
+ title && /* @__PURE__ */ jsx8("h3", { className: "hf-card__title", children: title })
280
+ ] }),
281
+ action
282
+ ] }),
283
+ /* @__PURE__ */ jsx8("div", { className: "hf-card__body", children })
284
+ ] });
285
+ }
286
+
287
+ // src/components/Modal.tsx
288
+ import { useId as useId3 } from "react";
289
+ import { createPortal } from "react-dom";
290
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
291
+ function Modal({ open, title, children, onClose, footer }) {
292
+ const titleId = useId3();
293
+ const dialogRef = useDismissibleLayer(open, onClose, true);
294
+ if (!open) return null;
295
+ return createPortal(
296
+ /* @__PURE__ */ jsx9("div", { className: "hf-modal-backdrop", onMouseDown: (event) => event.target === event.currentTarget && onClose(), children: /* @__PURE__ */ jsxs7("div", { ref: dialogRef, className: "hf-modal", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, tabIndex: -1, children: [
297
+ /* @__PURE__ */ jsxs7("header", { className: "hf-modal__header", children: [
298
+ /* @__PURE__ */ jsx9("h2", { id: titleId, children: title }),
299
+ /* @__PURE__ */ jsx9(Button, { variant: "quiet", size: "sm", onClick: onClose, "aria-label": "\u5173\u95ED\u5F39\u7A97", children: "\xD7" })
300
+ ] }),
301
+ /* @__PURE__ */ jsx9("div", { className: "hf-modal__body", children }),
302
+ footer && /* @__PURE__ */ jsx9("footer", { className: "hf-modal__footer", children: footer })
303
+ ] }) }),
304
+ document.body
305
+ );
306
+ }
307
+
308
+ // src/components/Toast.tsx
309
+ import { useEffect as useEffect2 } from "react";
310
+ import { createPortal as createPortal2 } from "react-dom";
311
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
312
+ function Toast({ open, message, tone = "info", duration = 2600, onClose }) {
313
+ useEffect2(() => {
314
+ if (!open || duration <= 0) return;
315
+ const timer = window.setTimeout(onClose, duration);
316
+ return () => window.clearTimeout(timer);
317
+ }, [duration, onClose, open]);
318
+ if (!open) return null;
319
+ return createPortal2(
320
+ /* @__PURE__ */ jsxs8("div", { className: `hf-toast hf-toast--${tone}`, role: tone === "error" ? "alert" : "status", children: [
321
+ /* @__PURE__ */ jsx10("span", { className: "hf-toast__mark", "aria-hidden": "true" }),
322
+ message
323
+ ] }),
324
+ document.body
325
+ );
326
+ }
327
+
328
+ // src/components/Content.tsx
329
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
330
+ function Divider({ orientation = "horizontal", label, className = "" }) {
331
+ return /* @__PURE__ */ jsx11("div", { className: `hf-divider hf-divider--${orientation}${label ? " hf-divider--labelled" : ""} ${className}`, role: "separator", "aria-orientation": orientation, children: label && /* @__PURE__ */ jsx11("span", { children: label }) });
332
+ }
333
+ function Link({ external, className = "", children, ...props }) {
334
+ return /* @__PURE__ */ jsxs9("a", { className: `hf-link ${className}`, target: external ? "_blank" : props.target, rel: external ? "noreferrer" : props.rel, ...props, children: [
335
+ children,
336
+ external && /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", children: "\u2197" })
337
+ ] });
338
+ }
339
+ function Badge({ tone = "neutral", dot, className = "", ...props }) {
340
+ return /* @__PURE__ */ jsxs9("span", { className: `hf-badge hf-tone--${tone} ${className}`, ...props, children: [
341
+ dot && /* @__PURE__ */ jsx11("i", { "aria-hidden": "true" }),
342
+ props.children
343
+ ] });
344
+ }
345
+ function Tag({ tone = "neutral", onRemove, removeLabel = "\u79FB\u9664\u6807\u7B7E", className = "", children, ...props }) {
346
+ return /* @__PURE__ */ jsxs9("span", { className: `hf-tag hf-tone--${tone} ${className}`, ...props, children: [
347
+ children,
348
+ onRemove && /* @__PURE__ */ jsx11("button", { type: "button", "aria-label": removeLabel, onClick: onRemove, children: /* @__PURE__ */ jsx11(Icon, { name: "close", size: 14 }) })
349
+ ] });
350
+ }
351
+ function Avatar({ src, name, alt = "", size = "md", status, className = "" }) {
352
+ const initials = name.trim().split(/\s+/).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
353
+ return /* @__PURE__ */ jsxs9("span", { className: `hf-avatar hf-avatar--${size} ${className}`, title: name, children: [
354
+ src ? /* @__PURE__ */ jsx11("img", { src, alt: alt || name }) : /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", children: initials }),
355
+ status && /* @__PURE__ */ jsx11("i", { className: `hf-avatar__status hf-avatar__status--${status}`, "aria-label": { online: "\u5728\u7EBF", busy: "\u5FD9\u788C", away: "\u79BB\u5F00" }[status] })
356
+ ] });
357
+ }
358
+
359
+ // src/components/Accordion.tsx
360
+ import { useState as useState2 } from "react";
361
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
362
+ function Accordion({ items, value, defaultValue = [], onChange, multiple = false }) {
363
+ const [inner, setInner] = useState2([...defaultValue]);
364
+ const active = value ? [...value] : inner;
365
+ const toggle = (key) => {
366
+ const next = active.includes(key) ? active.filter((item) => item !== key) : multiple ? [...active, key] : [key];
367
+ if (!value) setInner(next);
368
+ onChange?.(next);
369
+ };
370
+ return /* @__PURE__ */ jsx12("div", { className: "hf-accordion", children: items.map((item) => {
371
+ const open = active.includes(item.key);
372
+ return /* @__PURE__ */ jsxs10("section", { className: open ? "is-open" : "", children: [
373
+ /* @__PURE__ */ jsx12("h3", { children: /* @__PURE__ */ jsxs10("button", { type: "button", "aria-expanded": open, disabled: item.disabled, onClick: () => toggle(item.key), children: [
374
+ /* @__PURE__ */ jsx12("span", { children: item.title }),
375
+ /* @__PURE__ */ jsx12("span", { "aria-hidden": "true", children: "\u2304" })
376
+ ] }) }),
377
+ open && /* @__PURE__ */ jsx12("div", { className: "hf-accordion__panel", children: item.content })
378
+ ] }, item.key);
379
+ }) });
380
+ }
381
+
382
+ // src/components/Dropdown.tsx
383
+ import { cloneElement, useState as useState3 } from "react";
384
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
385
+ function Dropdown({ trigger, items, onSelect, placement = "left", label = "\u64CD\u4F5C\u83DC\u5355" }) {
386
+ const [open, setOpen] = useState3(false);
387
+ const root = useDismissibleLayer(open, () => setOpen(false));
388
+ return /* @__PURE__ */ jsxs11("span", { className: "hf-dropdown", ref: root, children: [
389
+ cloneElement(trigger, { onClick: () => setOpen((value) => !value), "aria-expanded": open, "aria-haspopup": "menu" }),
390
+ open && /* @__PURE__ */ jsx13("div", { className: `hf-dropdown__menu hf-dropdown__menu--${placement}`, role: "menu", "aria-label": label, children: items.map((item) => /* @__PURE__ */ jsxs11("button", { type: "button", role: "menuitem", className: `${item.danger ? "is-danger" : ""}${item.separatorBefore ? " has-separator" : ""}`, disabled: item.disabled, onClick: () => {
391
+ onSelect(item.key);
392
+ setOpen(false);
393
+ }, children: [
394
+ item.icon,
395
+ /* @__PURE__ */ jsxs11("span", { children: [
396
+ /* @__PURE__ */ jsx13("strong", { children: item.label }),
397
+ item.description && /* @__PURE__ */ jsx13("small", { children: item.description })
398
+ ] })
399
+ ] }, item.key)) })
400
+ ] });
401
+ }
402
+
403
+ // src/components/IconButton.tsx
404
+ import { forwardRef as forwardRef4 } from "react";
405
+ import { jsx as jsx14 } from "react/jsx-runtime";
406
+ var IconButton = forwardRef4(function IconButton2({ label, icon, variant = "quiet", size = "md", className = "", ...props }, ref) {
407
+ return /* @__PURE__ */ jsx14("button", { ref, className: `hf-button hf-button--${variant} hf-button--${size} hf-button--square hf-button--icon ${className}`.trim(), "aria-label": label, title: label, ...props, children: icon });
408
+ });
409
+
410
+ // src/components/AdvancedUtility.tsx
411
+ import { useState as useState4 } from "react";
412
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
413
+ function ButtonGroup({ children, orientation = "horizontal", attached = true, className = "", ...props }) {
414
+ return /* @__PURE__ */ jsx15("div", { role: "group", className: `hf-button-group hf-button-group--${orientation}${attached ? " is-attached" : ""} ${className}`.trim(), ...props, children });
415
+ }
416
+ function ColorPicker({ value, onChange, label, presets = ["#0a7cff", "#19a989", "#7657e6", "#f0a11a", "#e5484d"], disabled }) {
417
+ const [open, setOpen] = useState4(false);
418
+ const root = useDismissibleLayer(open, () => setOpen(false));
419
+ return /* @__PURE__ */ jsxs12("div", { className: "hf-field hf-color-picker", ref: root, children: [
420
+ label && /* @__PURE__ */ jsx15("span", { className: "hf-field__label", children: label }),
421
+ /* @__PURE__ */ jsxs12("button", { type: "button", className: "hf-color-picker__trigger", disabled, "aria-expanded": open, onClick: () => setOpen(!open), children: [
422
+ /* @__PURE__ */ jsx15("span", { style: { background: value } }),
423
+ /* @__PURE__ */ jsx15("code", { children: value.toUpperCase() }),
424
+ /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", children: "\u2304" })
425
+ ] }),
426
+ open && /* @__PURE__ */ jsxs12("div", { className: "hf-color-picker__panel", children: [
427
+ /* @__PURE__ */ jsx15("input", { type: "color", "aria-label": "\u9009\u62E9\u989C\u8272", value, onChange: (event) => onChange(event.target.value) }),
428
+ /* @__PURE__ */ jsx15("div", { children: presets.map((color) => /* @__PURE__ */ jsx15("button", { type: "button", "aria-label": `\u9009\u62E9\u989C\u8272 ${color}`, "aria-pressed": value.toLowerCase() === color.toLowerCase(), style: { background: color }, onClick: () => onChange(color) }, color)) }),
429
+ /* @__PURE__ */ jsx15("input", { "aria-label": "\u989C\u8272\u503C", value, onChange: (event) => /^#[0-9a-f]{0,6}$/i.test(event.target.value) && onChange(event.target.value) })
430
+ ] })
431
+ ] });
432
+ }
433
+ function ContextMenu({ items, onSelect, label = "\u4E0A\u4E0B\u6587\u83DC\u5355", children }) {
434
+ const [position, setPosition] = useState4();
435
+ const root = useDismissibleLayer(Boolean(position), () => setPosition(void 0));
436
+ const open = (event) => {
437
+ event.preventDefault();
438
+ setPosition({ x: event.clientX, y: event.clientY });
439
+ };
440
+ return /* @__PURE__ */ jsxs12("div", { className: "hf-context-target", onContextMenu: open, children: [
441
+ children,
442
+ position && /* @__PURE__ */ jsx15("div", { ref: root, className: "hf-context-menu", role: "menu", "aria-label": label, style: { left: position.x, top: position.y }, children: items.map((item) => /* @__PURE__ */ jsxs12("button", { type: "button", role: "menuitem", disabled: item.disabled, className: item.danger ? "is-danger" : "", onClick: () => {
443
+ onSelect(item.key);
444
+ setPosition(void 0);
445
+ }, children: [
446
+ item.icon,
447
+ /* @__PURE__ */ jsx15("span", { children: item.label })
448
+ ] }, item.key)) })
449
+ ] });
450
+ }
451
+
452
+ // src/components/Editors.tsx
453
+ import { useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState5 } from "react";
454
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
455
+ function RichTextEditor({ value, onChange, label, placeholder = "\u8F93\u5165\u5185\u5BB9\u2026", disabled }) {
456
+ const editor = useRef2(null);
457
+ useEffect3(() => {
458
+ if (editor.current && editor.current.innerHTML !== value) editor.current.innerHTML = value;
459
+ }, [value]);
460
+ const format = (command) => {
461
+ editor.current?.focus();
462
+ document.execCommand(command);
463
+ onChange(editor.current?.innerHTML ?? "");
464
+ };
465
+ return /* @__PURE__ */ jsxs13("div", { className: "hf-rich-editor", children: [
466
+ /* @__PURE__ */ jsxs13("div", { className: "hf-rich-editor__header", children: [
467
+ label && /* @__PURE__ */ jsx16("strong", { children: label }),
468
+ /* @__PURE__ */ jsxs13("div", { role: "toolbar", "aria-label": "\u6587\u672C\u683C\u5F0F", children: [
469
+ /* @__PURE__ */ jsx16("button", { type: "button", "aria-label": "\u7C97\u4F53", disabled, onClick: () => format("bold"), children: /* @__PURE__ */ jsx16("b", { children: "B" }) }),
470
+ /* @__PURE__ */ jsx16("button", { type: "button", "aria-label": "\u659C\u4F53", disabled, onClick: () => format("italic"), children: /* @__PURE__ */ jsx16("i", { children: "I" }) }),
471
+ /* @__PURE__ */ jsx16("button", { type: "button", "aria-label": "\u65E0\u5E8F\u5217\u8868", disabled, onClick: () => format("insertUnorderedList"), children: "\u2022 \u5217\u8868" })
472
+ ] })
473
+ ] }),
474
+ /* @__PURE__ */ jsx16("div", { ref: editor, className: "hf-rich-editor__content", contentEditable: !disabled, role: "textbox", "aria-multiline": "true", "aria-label": label ?? "\u5BCC\u6587\u672C\u7F16\u8F91\u5668", "data-placeholder": placeholder, onInput: (event) => onChange(event.currentTarget.innerHTML) })
475
+ ] });
476
+ }
477
+ function MentionInput({ value, onChange, options, label, placeholder = "\u8F93\u5165 @ \u63D0\u53CA\u6210\u5458", disabled }) {
478
+ const [active, setActive] = useState5(0);
479
+ const match = value.match(/(?:^|\s)@([^\s@]*)$/);
480
+ const query = match?.[1]?.toLowerCase();
481
+ const results = useMemo(() => query === void 0 ? [] : options.filter((item) => `${item.label} ${item.value}`.toLowerCase().includes(query)).slice(0, 6), [options, query]);
482
+ useEffect3(() => setActive(0), [query]);
483
+ const choose = (item) => {
484
+ if (!match) return;
485
+ onChange(`${value.slice(0, match.index)}${match[0].startsWith(" ") ? " " : ""}@${item.label} `);
486
+ };
487
+ const keyDown = (event) => {
488
+ if (!results.length) return;
489
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
490
+ event.preventDefault();
491
+ setActive((index) => (index + (event.key === "ArrowDown" ? 1 : -1) + results.length) % results.length);
492
+ } else if (event.key === "Enter" || event.key === "Tab") {
493
+ event.preventDefault();
494
+ choose(results[active]);
495
+ } else if (event.key === "Escape") {
496
+ event.preventDefault();
497
+ onChange(`${value} `);
498
+ }
499
+ };
500
+ return /* @__PURE__ */ jsxs13("label", { className: "hf-field hf-mention-input", children: [
501
+ label && /* @__PURE__ */ jsx16("span", { className: "hf-field__label", children: label }),
502
+ /* @__PURE__ */ jsx16("textarea", { value, placeholder, disabled, "aria-autocomplete": "list", "aria-expanded": Boolean(results.length), onChange: (event) => onChange(event.target.value), onKeyDown: keyDown }),
503
+ results.length > 0 && /* @__PURE__ */ jsx16("div", { className: "hf-mention-input__menu", role: "listbox", children: results.map((item, index) => /* @__PURE__ */ jsxs13("button", { type: "button", role: "option", "aria-selected": index === active, onMouseDown: (event) => event.preventDefault(), onClick: () => choose(item), children: [
504
+ /* @__PURE__ */ jsxs13("span", { children: [
505
+ "@",
506
+ item.label
507
+ ] }),
508
+ item.description && /* @__PURE__ */ jsx16("small", { children: item.description })
509
+ ] }, item.value)) })
510
+ ] });
511
+ }
512
+ function CodeEditor({ value, onChange, language = "text", label = "\u4EE3\u7801\u7F16\u8F91\u5668", readOnly, height = 260 }) {
513
+ const lines = value.split("\n").length;
514
+ return /* @__PURE__ */ jsxs13("div", { className: "hf-code-editor", children: [
515
+ /* @__PURE__ */ jsxs13("header", { children: [
516
+ /* @__PURE__ */ jsx16("strong", { children: label }),
517
+ /* @__PURE__ */ jsx16("span", { children: language })
518
+ ] }),
519
+ /* @__PURE__ */ jsxs13("div", { style: { height }, children: [
520
+ /* @__PURE__ */ jsx16("pre", { "aria-hidden": "true", children: Array.from({ length: lines }, (_, index) => `${index + 1}
521
+ `) }),
522
+ /* @__PURE__ */ jsx16("textarea", { spellCheck: false, readOnly, "aria-label": label, value, onChange: (event) => onChange(event.target.value), onKeyDown: (event) => {
523
+ if (event.key === "Tab" && !readOnly) {
524
+ event.preventDefault();
525
+ const input = event.currentTarget;
526
+ const next = `${value.slice(0, input.selectionStart)} ${value.slice(input.selectionEnd)}`;
527
+ onChange(next);
528
+ requestAnimationFrame(() => input.setSelectionRange(input.selectionStart + 2, input.selectionStart + 2));
529
+ }
530
+ } })
531
+ ] })
532
+ ] });
533
+ }
534
+
535
+ // src/components/AIInteraction.tsx
536
+ import { useState as useState6 } from "react";
537
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
538
+ function ChatMessage({ role, children, avatar, name, timestamp, actions, streaming, error }) {
539
+ return /* @__PURE__ */ jsxs14("article", { className: `hf-chat-message hf-chat-message--${role}`, "aria-live": streaming ? "polite" : void 0, children: [
540
+ /* @__PURE__ */ jsx17("div", { className: "hf-chat-message__avatar", "aria-hidden": "true", children: avatar ?? (role === "assistant" ? "AI" : role === "system" ? "S" : "U") }),
541
+ /* @__PURE__ */ jsxs14("div", { className: "hf-chat-message__body", children: [
542
+ /* @__PURE__ */ jsxs14("header", { children: [
543
+ name && /* @__PURE__ */ jsx17("strong", { children: name }),
544
+ timestamp && /* @__PURE__ */ jsx17("time", { children: timestamp })
545
+ ] }),
546
+ /* @__PURE__ */ jsxs14("div", { className: "hf-chat-message__content", children: [
547
+ children,
548
+ streaming && /* @__PURE__ */ jsx17("span", { className: "hf-chat-message__cursor", "aria-label": "\u6B63\u5728\u751F\u6210" })
549
+ ] }),
550
+ error && /* @__PURE__ */ jsx17("div", { className: "hf-chat-message__error", role: "alert", children: error }),
551
+ actions && /* @__PURE__ */ jsx17("footer", { children: actions })
552
+ ] })
553
+ ] });
554
+ }
555
+ function ChatComposer({ value, onChange, onSend, attachments = [], onRemoveAttachment, onAttach, placeholder = "\u8F93\u5165\u6D88\u606F\uFF0CEnter \u53D1\u9001\uFF0CShift + Enter \u6362\u884C", disabled, sending, footer, maxLength }) {
556
+ const send = () => {
557
+ const content = value.trim();
558
+ if (content && !disabled && !sending) onSend(content);
559
+ };
560
+ const submit = (event) => {
561
+ event.preventDefault();
562
+ send();
563
+ };
564
+ const keyDown = (event) => {
565
+ if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
566
+ event.preventDefault();
567
+ send();
568
+ }
569
+ };
570
+ return /* @__PURE__ */ jsxs14("form", { className: "hf-chat-composer", onSubmit: submit, children: [
571
+ attachments.length > 0 && /* @__PURE__ */ jsx17("div", { className: "hf-chat-composer__attachments", children: attachments.map((item) => /* @__PURE__ */ jsxs14("span", { children: [
572
+ item.icon,
573
+ /* @__PURE__ */ jsx17("strong", { children: item.name }),
574
+ item.size && /* @__PURE__ */ jsx17("small", { children: item.size }),
575
+ onRemoveAttachment && /* @__PURE__ */ jsx17("button", { type: "button", "aria-label": `\u79FB\u9664\u9644\u4EF6 ${item.name}`, onClick: () => onRemoveAttachment(item.id), children: "\xD7" })
576
+ ] }, item.id)) }),
577
+ /* @__PURE__ */ jsx17("textarea", { "aria-label": "\u6D88\u606F\u5185\u5BB9", value, maxLength, disabled, placeholder, onChange: (event) => onChange(event.target.value), onKeyDown: keyDown }),
578
+ /* @__PURE__ */ jsxs14("footer", { children: [
579
+ /* @__PURE__ */ jsxs14("div", { children: [
580
+ onAttach && /* @__PURE__ */ jsx17("button", { type: "button", className: "hf-chat-composer__attach", "aria-label": "\u6DFB\u52A0\u9644\u4EF6", disabled, onClick: onAttach, children: "\uFF0B" }),
581
+ footer
582
+ ] }),
583
+ maxLength && /* @__PURE__ */ jsxs14("small", { children: [
584
+ value.length,
585
+ "/",
586
+ maxLength
587
+ ] }),
588
+ /* @__PURE__ */ jsxs14("button", { type: "submit", className: "hf-chat-composer__send", disabled: disabled || sending || !value.trim(), children: [
589
+ sending ? /* @__PURE__ */ jsx17("span", { className: "hf-spinner" }) : "\u2191",
590
+ /* @__PURE__ */ jsx17("span", { className: "hf-sr-only", children: "\u53D1\u9001\u6D88\u606F" })
591
+ ] })
592
+ ] })
593
+ ] });
594
+ }
595
+ function PromptSuggestions({ items, onSelect, title, columns = 2 }) {
596
+ return /* @__PURE__ */ jsxs14("section", { className: `hf-prompt-suggestions hf-prompt-suggestions--${columns}`, children: [
597
+ title && /* @__PURE__ */ jsx17("header", { children: title }),
598
+ /* @__PURE__ */ jsx17("div", { children: items.map((item) => /* @__PURE__ */ jsxs14("button", { type: "button", onClick: () => onSelect(item), children: [
599
+ item.icon && /* @__PURE__ */ jsx17("span", { children: item.icon }),
600
+ /* @__PURE__ */ jsx17("strong", { children: item.title }),
601
+ item.description && /* @__PURE__ */ jsx17("small", { children: item.description }),
602
+ /* @__PURE__ */ jsx17("i", { "aria-hidden": "true", children: "\u2192" })
603
+ ] }, item.id)) })
604
+ ] });
605
+ }
606
+ var toolStatusLabel = { queued: "\u7B49\u5F85\u4E2D", running: "\u6267\u884C\u4E2D", success: "\u5DF2\u5B8C\u6210", error: "\u6267\u884C\u5931\u8D25", cancelled: "\u5DF2\u53D6\u6D88" };
607
+ function ToolCallCard({ name, status, description, input, output, duration, icon, defaultExpanded = false, onRetry, onCancel }) {
608
+ const [open, setOpen] = useState6(defaultExpanded);
609
+ return /* @__PURE__ */ jsxs14("section", { className: `hf-tool-call is-${status}`, children: [
610
+ /* @__PURE__ */ jsxs14("button", { type: "button", className: "hf-tool-call__summary", "aria-expanded": open, onClick: () => setOpen(!open), children: [
611
+ /* @__PURE__ */ jsx17("span", { className: "hf-tool-call__icon", children: status === "running" ? /* @__PURE__ */ jsx17("span", { className: "hf-spinner" }) : icon ?? "\u25C7" }),
612
+ /* @__PURE__ */ jsxs14("span", { children: [
613
+ /* @__PURE__ */ jsx17("strong", { children: name }),
614
+ description && /* @__PURE__ */ jsx17("small", { children: description })
615
+ ] }),
616
+ /* @__PURE__ */ jsx17("i", { children: toolStatusLabel[status] }),
617
+ duration && /* @__PURE__ */ jsx17("time", { children: duration }),
618
+ /* @__PURE__ */ jsx17("b", { "aria-hidden": "true", children: "\u2304" })
619
+ ] }),
620
+ open && /* @__PURE__ */ jsxs14("div", { className: "hf-tool-call__detail", children: [
621
+ input && /* @__PURE__ */ jsxs14("section", { children: [
622
+ /* @__PURE__ */ jsx17("strong", { children: "\u8F93\u5165" }),
623
+ /* @__PURE__ */ jsx17("div", { children: input })
624
+ ] }),
625
+ output && /* @__PURE__ */ jsxs14("section", { children: [
626
+ /* @__PURE__ */ jsx17("strong", { children: "\u8F93\u51FA" }),
627
+ /* @__PURE__ */ jsx17("div", { children: output })
628
+ ] }),
629
+ status === "error" && onRetry || status === "running" && onCancel ? /* @__PURE__ */ jsxs14("footer", { children: [
630
+ status === "error" && onRetry && /* @__PURE__ */ jsx17("button", { type: "button", onClick: onRetry, children: "\u91CD\u65B0\u6267\u884C" }),
631
+ status === "running" && onCancel && /* @__PURE__ */ jsx17("button", { type: "button", onClick: onCancel, children: "\u505C\u6B62\u6267\u884C" })
632
+ ] }) : null
633
+ ] })
634
+ ] });
635
+ }
636
+ function CitationList({ items, title = "\u53C2\u8003\u6765\u6E90", onSelect }) {
637
+ return /* @__PURE__ */ jsxs14("section", { className: "hf-citation-list", children: [
638
+ /* @__PURE__ */ jsxs14("header", { children: [
639
+ /* @__PURE__ */ jsx17("strong", { children: title }),
640
+ /* @__PURE__ */ jsx17("span", { children: items.length })
641
+ ] }),
642
+ /* @__PURE__ */ jsx17("ol", { children: items.map((item, index) => /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs14("a", { href: item.url, target: item.url ? "_blank" : void 0, rel: item.url ? "noreferrer" : void 0, onClick: (event) => {
643
+ if (!item.url) event.preventDefault();
644
+ onSelect?.(item);
645
+ }, children: [
646
+ /* @__PURE__ */ jsx17("span", { children: item.favicon ?? index + 1 }),
647
+ /* @__PURE__ */ jsxs14("div", { children: [
648
+ /* @__PURE__ */ jsx17("strong", { children: item.title }),
649
+ item.source && /* @__PURE__ */ jsx17("small", { children: item.source }),
650
+ item.excerpt && /* @__PURE__ */ jsx17("p", { children: item.excerpt })
651
+ ] }),
652
+ /* @__PURE__ */ jsx17("i", { "aria-hidden": "true", children: "\u2197" })
653
+ ] }) }, item.id)) })
654
+ ] });
655
+ }
656
+ function AgentRunTimeline({ steps, activeId, onSelect, label = "Agent \u6267\u884C\u8FC7\u7A0B" }) {
657
+ return /* @__PURE__ */ jsx17("ol", { className: "hf-agent-run", "aria-label": label, children: steps.map((step) => /* @__PURE__ */ jsx17("li", { className: `is-${step.status}${activeId === step.id ? " is-active" : ""}`, children: /* @__PURE__ */ jsxs14("button", { type: "button", "aria-pressed": activeId === step.id, onClick: () => onSelect?.(step.id), children: [
658
+ /* @__PURE__ */ jsx17("span", { children: step.status === "success" ? "\u2713" : step.status === "error" ? "!" : step.status === "running" ? /* @__PURE__ */ jsx17("i", { className: "hf-spinner" }) : "\xB7" }),
659
+ /* @__PURE__ */ jsxs14("div", { children: [
660
+ /* @__PURE__ */ jsxs14("header", { children: [
661
+ /* @__PURE__ */ jsx17("strong", { children: step.title }),
662
+ step.timestamp && /* @__PURE__ */ jsx17("time", { children: step.timestamp })
663
+ ] }),
664
+ step.description && /* @__PURE__ */ jsx17("p", { children: step.description }),
665
+ step.detail && /* @__PURE__ */ jsx17("div", { children: step.detail })
666
+ ] })
667
+ ] }) }, step.id)) });
668
+ }
669
+
670
+ // src/components/AIAdvanced.tsx
671
+ import { Fragment, useMemo as useMemo2, useState as useState7 } from "react";
672
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
673
+ function inlineMarkdown(text) {
674
+ const pattern = /(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\(https?:\/\/[^\s)]+\))/g;
675
+ return text.split(pattern).filter(Boolean).map((part, index) => {
676
+ if (part.startsWith("**") && part.endsWith("**")) return /* @__PURE__ */ jsx18("strong", { children: part.slice(2, -2) }, index);
677
+ if (part.startsWith("`") && part.endsWith("`")) return /* @__PURE__ */ jsx18("code", { children: part.slice(1, -1) }, index);
678
+ const link = part.match(/^\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)$/);
679
+ return link ? /* @__PURE__ */ jsx18("a", { href: link[2], target: "_blank", rel: "noreferrer", children: link[1] }, index) : /* @__PURE__ */ jsx18(Fragment, { children: part }, index);
680
+ });
681
+ }
682
+ function MarkdownContent({ content, className = "" }) {
683
+ const blocks = useMemo2(() => {
684
+ const lines = content.split("\n");
685
+ const result = [];
686
+ let code, language = "";
687
+ let list = [];
688
+ const flushList = () => {
689
+ if (list.length) result.push(/* @__PURE__ */ jsx18("ul", { children: list.map((item, index) => /* @__PURE__ */ jsx18("li", { children: inlineMarkdown(item) }, index)) }, `list-${result.length}`));
690
+ list = [];
691
+ };
692
+ lines.forEach((line) => {
693
+ if (line.startsWith("```")) {
694
+ if (code) {
695
+ result.push(/* @__PURE__ */ jsx18(CodeBlock, { code: code.join("\n"), language }, `code-${result.length}`));
696
+ code = void 0;
697
+ language = "";
698
+ } else {
699
+ flushList();
700
+ code = [];
701
+ language = line.slice(3).trim();
702
+ }
703
+ return;
704
+ }
705
+ if (code) {
706
+ code.push(line);
707
+ return;
708
+ }
709
+ if (line.startsWith("- ")) {
710
+ list.push(line.slice(2));
711
+ return;
712
+ }
713
+ flushList();
714
+ if (!line.trim()) return;
715
+ const heading = line.match(/^(#{1,3})\s+(.+)$/);
716
+ if (heading) {
717
+ const Tag2 = `h${heading[1].length}`;
718
+ result.push(/* @__PURE__ */ jsx18(Tag2, { children: inlineMarkdown(heading[2]) }, result.length));
719
+ } else if (line.startsWith("> ")) result.push(/* @__PURE__ */ jsx18("blockquote", { children: inlineMarkdown(line.slice(2)) }, result.length));
720
+ else result.push(/* @__PURE__ */ jsx18("p", { children: inlineMarkdown(line) }, result.length));
721
+ });
722
+ flushList();
723
+ if (code) result.push(/* @__PURE__ */ jsx18(CodeBlock, { code: code.join("\n"), language }, "code-last"));
724
+ return result;
725
+ }, [content]);
726
+ return /* @__PURE__ */ jsx18("div", { className: `hf-markdown ${className}`.trim(), children: blocks });
727
+ }
728
+ function CodeBlock({ code, language = "text", filename, wrap, showLineNumbers = true, onCopy }) {
729
+ const [copied, setCopied] = useState7(false);
730
+ const lines = code.split("\n");
731
+ const copy = async () => {
732
+ try {
733
+ await navigator.clipboard.writeText(code);
734
+ } catch {
735
+ }
736
+ onCopy?.(code);
737
+ setCopied(true);
738
+ window.setTimeout(() => setCopied(false), 1500);
739
+ };
740
+ return /* @__PURE__ */ jsxs15("section", { className: `hf-code-block${wrap ? " is-wrapped" : ""}`, children: [
741
+ /* @__PURE__ */ jsxs15("header", { children: [
742
+ /* @__PURE__ */ jsx18("span", { children: filename ?? language }),
743
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: copy, children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u4EE3\u7801" })
744
+ ] }),
745
+ /* @__PURE__ */ jsxs15("div", { children: [
746
+ showLineNumbers && /* @__PURE__ */ jsx18("pre", { "aria-hidden": "true", children: lines.map((_, index) => `${index + 1}
747
+ `) }),
748
+ /* @__PURE__ */ jsx18("pre", { children: /* @__PURE__ */ jsx18("code", { children: code }) })
749
+ ] })
750
+ ] });
751
+ }
752
+ function VoiceInput({ state = "idle", duration = "00:00", level = 0.45, disabled, onStart, onStop, onCancel, error }) {
753
+ const active = state === "listening";
754
+ return /* @__PURE__ */ jsxs15("div", { className: `hf-voice-input is-${state}`, role: "status", "aria-label": active ? "\u6B63\u5728\u5F55\u97F3" : state === "processing" ? "\u6B63\u5728\u8BC6\u522B\u8BED\u97F3" : "\u8BED\u97F3\u8F93\u5165", children: [
755
+ /* @__PURE__ */ jsx18("button", { type: "button", className: "hf-voice-input__main", disabled: disabled || state === "processing", onClick: active ? onStop : onStart, children: state === "processing" ? /* @__PURE__ */ jsx18("span", { className: "hf-spinner" }) : active ? "\u25A0" : "\u25CF" }),
756
+ /* @__PURE__ */ jsxs15("div", { children: [
757
+ /* @__PURE__ */ jsx18("div", { className: "hf-voice-input__wave", "aria-hidden": "true", children: Array.from({ length: 18 }, (_, index) => /* @__PURE__ */ jsx18("i", { style: { height: `${Math.max(12, index * 17 % 75 * level + 12)}%` } }, index)) }),
758
+ /* @__PURE__ */ jsx18("span", { children: active ? duration : state === "processing" ? "\u6B63\u5728\u8F6C\u6362\u6587\u5B57\u2026" : error ?? "\u70B9\u51FB\u5F00\u59CB\u8BED\u97F3\u8F93\u5165" })
759
+ ] }),
760
+ (active || state === "error") && onCancel && /* @__PURE__ */ jsx18("button", { type: "button", className: "hf-voice-input__cancel", onClick: onCancel, children: "\u53D6\u6D88" })
761
+ ] });
762
+ }
763
+ function ModelSelector({ models, value, onChange, label = "\u9009\u62E9\u6A21\u578B", disabled }) {
764
+ const [open, setOpen] = useState7(false);
765
+ const root = useDismissibleLayer(open, () => setOpen(false));
766
+ const selected = models.find((item) => item.id === value);
767
+ return /* @__PURE__ */ jsxs15("div", { className: "hf-model-selector", ref: root, children: [
768
+ /* @__PURE__ */ jsxs15("button", { type: "button", className: "hf-model-selector__trigger", disabled, "aria-expanded": open, onClick: () => setOpen(!open), children: [
769
+ /* @__PURE__ */ jsx18("span", { children: selected?.icon ?? "\u2726" }),
770
+ /* @__PURE__ */ jsxs15("span", { children: [
771
+ /* @__PURE__ */ jsx18("strong", { children: selected?.name ?? label }),
772
+ selected?.description && /* @__PURE__ */ jsx18("small", { children: selected.description })
773
+ ] }),
774
+ /* @__PURE__ */ jsx18("i", { "aria-hidden": "true", children: "\u2304" })
775
+ ] }),
776
+ open && /* @__PURE__ */ jsx18("div", { className: "hf-model-selector__menu", role: "listbox", "aria-label": label, children: models.map((model) => /* @__PURE__ */ jsxs15("button", { type: "button", role: "option", "aria-selected": model.id === value, disabled: model.disabled, onClick: () => {
777
+ onChange(model.id);
778
+ setOpen(false);
779
+ }, children: [
780
+ /* @__PURE__ */ jsx18("span", { children: model.icon ?? "\u2726" }),
781
+ /* @__PURE__ */ jsxs15("span", { children: [
782
+ /* @__PURE__ */ jsx18("strong", { children: model.name }),
783
+ model.description && /* @__PURE__ */ jsx18("small", { children: model.description }),
784
+ model.tags?.length ? /* @__PURE__ */ jsx18("i", { children: model.tags.map((tag) => /* @__PURE__ */ jsx18("b", { children: tag }, tag)) }) : null
785
+ ] }),
786
+ model.id === value && /* @__PURE__ */ jsx18("em", { children: "\u2713" })
787
+ ] }, model.id)) })
788
+ ] });
789
+ }
790
+ function ConversationBranch({ current, total, onChange, label = "\u56DE\u7B54\u5206\u652F" }) {
791
+ const safeTotal = Math.max(1, total), safeCurrent = Math.min(safeTotal - 1, Math.max(0, current));
792
+ return /* @__PURE__ */ jsxs15("nav", { className: "hf-conversation-branch", "aria-label": String(label), children: [
793
+ /* @__PURE__ */ jsx18("button", { type: "button", "aria-label": "\u4E0A\u4E00\u4E2A\u5206\u652F", disabled: safeCurrent === 0, onClick: () => onChange(safeCurrent - 1), children: "\u2039" }),
794
+ /* @__PURE__ */ jsxs15("span", { children: [
795
+ safeCurrent + 1,
796
+ " / ",
797
+ safeTotal
798
+ ] }),
799
+ /* @__PURE__ */ jsx18("button", { type: "button", "aria-label": "\u4E0B\u4E00\u4E2A\u5206\u652F", disabled: safeCurrent >= safeTotal - 1, onClick: () => onChange(safeCurrent + 1), children: "\u203A" })
800
+ ] });
801
+ }
802
+ function TokenUsage({ used, limit, input, output, cached, label = "\u4E0A\u4E0B\u6587\u7528\u91CF", compact }) {
803
+ const percent = Math.max(0, Math.min(100, limit ? used / limit * 100 : 0));
804
+ return /* @__PURE__ */ jsxs15("section", { className: `hf-token-usage${compact ? " is-compact" : ""}`, children: [
805
+ /* @__PURE__ */ jsx18("div", { className: "hf-token-usage__ring", role: "progressbar", "aria-label": String(label), "aria-valuemin": 0, "aria-valuemax": limit, "aria-valuenow": used, style: { "--hf-token-percent": `${percent * 3.6}deg` }, children: /* @__PURE__ */ jsxs15("span", { children: [
806
+ Math.round(percent),
807
+ "%"
808
+ ] }) }),
809
+ /* @__PURE__ */ jsxs15("div", { children: [
810
+ /* @__PURE__ */ jsxs15("header", { children: [
811
+ /* @__PURE__ */ jsx18("strong", { children: label }),
812
+ /* @__PURE__ */ jsxs15("span", { children: [
813
+ used.toLocaleString(),
814
+ " / ",
815
+ limit.toLocaleString()
816
+ ] })
817
+ ] }),
818
+ !compact && /* @__PURE__ */ jsxs15("div", { className: "hf-token-usage__details", children: [
819
+ input !== void 0 && /* @__PURE__ */ jsxs15("span", { children: [
820
+ /* @__PURE__ */ jsx18("i", {}),
821
+ "\u8F93\u5165 ",
822
+ input.toLocaleString()
823
+ ] }),
824
+ output !== void 0 && /* @__PURE__ */ jsxs15("span", { children: [
825
+ /* @__PURE__ */ jsx18("i", {}),
826
+ "\u8F93\u51FA ",
827
+ output.toLocaleString()
828
+ ] }),
829
+ cached !== void 0 && /* @__PURE__ */ jsxs15("span", { children: [
830
+ /* @__PURE__ */ jsx18("i", {}),
831
+ "\u7F13\u5B58 ",
832
+ cached.toLocaleString()
833
+ ] })
834
+ ] })
835
+ ] })
836
+ ] });
837
+ }
838
+
839
+ // src/components/Collaboration.tsx
840
+ import { useState as useState8 } from "react";
841
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
842
+ var presenceLabel = { online: "\u5728\u7EBF", away: "\u79BB\u5F00", busy: "\u5FD9\u788C", offline: "\u79BB\u7EBF" };
843
+ function Presence({ status, label, showLabel = true, pulse = true }) {
844
+ return /* @__PURE__ */ jsxs16("span", { className: `hf-presence is-${status}${pulse && status === "online" ? " is-pulsing" : ""}`, role: "status", children: [
845
+ /* @__PURE__ */ jsx19("i", { "aria-hidden": "true" }),
846
+ /* @__PURE__ */ jsx19("span", { children: label ?? (showLabel ? presenceLabel[status] : /* @__PURE__ */ jsx19("span", { className: "hf-sr-only", children: presenceLabel[status] })) })
847
+ ] });
848
+ }
849
+ function AvatarGroup({ items, max = 4, size = "md", onMore, label = "\u534F\u4F5C\u6210\u5458" }) {
850
+ const shown = items.slice(0, max), remaining = Math.max(0, items.length - shown.length);
851
+ return /* @__PURE__ */ jsxs16("div", { className: `hf-avatar-group hf-avatar-group--${size}`, "aria-label": label, children: [
852
+ shown.map((item) => /* @__PURE__ */ jsx19(Avatar, { src: item.src, name: item.name, size, status: item.status }, item.id)),
853
+ remaining > 0 && /* @__PURE__ */ jsxs16("button", { type: "button", "aria-label": `\u67E5\u770B\u5176\u4F59 ${remaining} \u4F4D\u6210\u5458`, onClick: onMore, children: [
854
+ "+",
855
+ remaining
856
+ ] })
857
+ ] });
858
+ }
859
+ function Comment({ item, onReply, onReact, onDelete, depth = 0 }) {
860
+ const [replying, setReplying] = useState8(false), [value, setValue] = useState8("");
861
+ return /* @__PURE__ */ jsxs16("article", { className: "hf-comment", style: { "--hf-comment-depth": Math.min(depth, 3) }, children: [
862
+ /* @__PURE__ */ jsx19(Avatar, { src: item.author.avatar, name: item.author.name, size: "sm" }),
863
+ /* @__PURE__ */ jsxs16("div", { children: [
864
+ /* @__PURE__ */ jsxs16("header", { children: [
865
+ /* @__PURE__ */ jsx19("strong", { children: item.author.name }),
866
+ item.timestamp && /* @__PURE__ */ jsx19("time", { children: item.timestamp }),
867
+ item.edited && /* @__PURE__ */ jsx19("small", { children: "\u5DF2\u7F16\u8F91" })
868
+ ] }),
869
+ /* @__PURE__ */ jsx19("div", { className: "hf-comment__content", children: item.content }),
870
+ /* @__PURE__ */ jsxs16("footer", { children: [
871
+ item.reactions?.map((reaction) => /* @__PURE__ */ jsxs16("button", { type: "button", className: reaction.active ? "is-active" : "", "aria-pressed": reaction.active, onClick: () => onReact?.(item.id, reaction.emoji), children: [
872
+ reaction.emoji,
873
+ " ",
874
+ reaction.count
875
+ ] }, reaction.emoji)),
876
+ onReply && /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => setReplying(!replying), children: "\u56DE\u590D" }),
877
+ onDelete && /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => onDelete(item.id), children: "\u5220\u9664" })
878
+ ] }),
879
+ replying && /* @__PURE__ */ jsxs16("form", { className: "hf-comment__reply", onSubmit: (event) => {
880
+ event.preventDefault();
881
+ if (value.trim()) {
882
+ onReply?.(item.id, value.trim());
883
+ setValue("");
884
+ setReplying(false);
885
+ }
886
+ }, children: [
887
+ /* @__PURE__ */ jsx19("textarea", { autoFocus: true, "aria-label": `\u56DE\u590D ${item.author.name}`, value, onChange: (event) => setValue(event.target.value) }),
888
+ /* @__PURE__ */ jsxs16("div", { children: [
889
+ /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => setReplying(false), children: "\u53D6\u6D88" }),
890
+ /* @__PURE__ */ jsx19("button", { type: "submit", disabled: !value.trim(), children: "\u53D1\u9001\u56DE\u590D" })
891
+ ] })
892
+ ] }),
893
+ item.replies?.map((reply) => /* @__PURE__ */ jsx19(Comment, { item: reply, onReply, onReact, onDelete, depth: depth + 1 }, reply.id))
894
+ ] })
895
+ ] });
896
+ }
897
+ function CommentThread({ comments, onReply, onReact, onDelete, empty = "\u6682\u65E0\u8BC4\u8BBA\uFF0C\u5F00\u59CB\u8BA8\u8BBA\u5427" }) {
898
+ return /* @__PURE__ */ jsx19("section", { className: "hf-comment-thread", "aria-label": "\u8BC4\u8BBA\u8BA8\u8BBA", children: comments.length ? comments.map((item) => /* @__PURE__ */ jsx19(Comment, { item, onReply, onReact, onDelete }, item.id)) : /* @__PURE__ */ jsx19("div", { className: "hf-comment-thread__empty", children: empty }) });
899
+ }
900
+ function ActivityFeed({ items, grouped, empty = "\u6682\u65E0\u52A8\u6001" }) {
901
+ if (!items.length) return /* @__PURE__ */ jsx19("div", { className: "hf-activity-feed__empty", children: empty });
902
+ return /* @__PURE__ */ jsx19("ol", { className: `hf-activity-feed${grouped ? " is-grouped" : ""}`, children: items.map((item) => /* @__PURE__ */ jsxs16("li", { children: [
903
+ /* @__PURE__ */ jsx19("span", { className: "hf-activity-feed__marker", children: item.avatar ?? item.icon ?? "\u2022" }),
904
+ /* @__PURE__ */ jsxs16("div", { children: [
905
+ /* @__PURE__ */ jsxs16("p", { children: [
906
+ /* @__PURE__ */ jsx19("strong", { children: item.actor }),
907
+ " ",
908
+ item.action,
909
+ " ",
910
+ item.target && /* @__PURE__ */ jsx19("b", { children: item.target })
911
+ ] }),
912
+ item.timestamp && /* @__PURE__ */ jsx19("time", { children: item.timestamp }),
913
+ item.detail && /* @__PURE__ */ jsx19("div", { children: item.detail })
914
+ ] })
915
+ ] }, item.id)) });
916
+ }
917
+ function ApprovalFlow({ steps, currentId, onApprove, onReject, orientation = "vertical" }) {
918
+ return /* @__PURE__ */ jsx19("ol", { className: `hf-approval-flow hf-approval-flow--${orientation}`, children: steps.map((step, index) => /* @__PURE__ */ jsxs16("li", { className: `is-${step.status}${currentId === step.id ? " is-current" : ""}`, children: [
919
+ /* @__PURE__ */ jsx19("span", { children: step.status === "approved" ? "\u2713" : step.status === "rejected" ? "\xD7" : index + 1 }),
920
+ /* @__PURE__ */ jsxs16("div", { children: [
921
+ /* @__PURE__ */ jsxs16("header", { children: [
922
+ /* @__PURE__ */ jsx19("strong", { children: step.title }),
923
+ /* @__PURE__ */ jsx19("i", { children: { pending: "\u5F85\u5BA1\u6279", approved: "\u5DF2\u901A\u8FC7", rejected: "\u5DF2\u62D2\u7EDD", skipped: "\u5DF2\u8DF3\u8FC7" }[step.status] })
924
+ ] }),
925
+ step.approver && /* @__PURE__ */ jsx19("p", { children: step.approver }),
926
+ step.comment && /* @__PURE__ */ jsx19("blockquote", { children: step.comment }),
927
+ step.timestamp && /* @__PURE__ */ jsx19("time", { children: step.timestamp }),
928
+ step.status === "pending" && currentId === step.id && (onApprove || onReject) && /* @__PURE__ */ jsxs16("footer", { children: [
929
+ onReject && /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => onReject(step.id), children: "\u62D2\u7EDD" }),
930
+ onApprove && /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => onApprove(step.id), children: "\u901A\u8FC7" })
931
+ ] })
932
+ ] })
933
+ ] }, step.id)) });
934
+ }
935
+ function AuditLog({ events, onSelect, empty = "\u6682\u65E0\u5BA1\u8BA1\u8BB0\u5F55", caption = "\u5BA1\u8BA1\u65E5\u5FD7" }) {
936
+ return /* @__PURE__ */ jsx19("div", { className: "hf-audit-log", children: /* @__PURE__ */ jsxs16("table", { children: [
937
+ /* @__PURE__ */ jsx19("caption", { children: caption }),
938
+ /* @__PURE__ */ jsx19("thead", { children: /* @__PURE__ */ jsxs16("tr", { children: [
939
+ /* @__PURE__ */ jsx19("th", { children: "\u65F6\u95F4" }),
940
+ /* @__PURE__ */ jsx19("th", { children: "\u64CD\u4F5C\u8005" }),
941
+ /* @__PURE__ */ jsx19("th", { children: "\u64CD\u4F5C" }),
942
+ /* @__PURE__ */ jsx19("th", { children: "\u8D44\u6E90" }),
943
+ /* @__PURE__ */ jsx19("th", { children: "\u7ED3\u679C" }),
944
+ /* @__PURE__ */ jsx19("th", { children: "IP" })
945
+ ] }) }),
946
+ /* @__PURE__ */ jsxs16("tbody", { children: [
947
+ events.map((event) => /* @__PURE__ */ jsxs16("tr", { tabIndex: onSelect ? 0 : void 0, onClick: () => onSelect?.(event.id), onKeyDown: (key) => {
948
+ if (onSelect && (key.key === "Enter" || key.key === " ")) {
949
+ key.preventDefault();
950
+ onSelect(event.id);
951
+ }
952
+ }, children: [
953
+ /* @__PURE__ */ jsx19("td", { children: event.timestamp }),
954
+ /* @__PURE__ */ jsx19("td", { children: event.actor }),
955
+ /* @__PURE__ */ jsxs16("td", { children: [
956
+ /* @__PURE__ */ jsx19("strong", { children: event.action }),
957
+ event.detail && /* @__PURE__ */ jsx19("small", { children: event.detail })
958
+ ] }),
959
+ /* @__PURE__ */ jsx19("td", { children: event.resource ?? "\u2014" }),
960
+ /* @__PURE__ */ jsx19("td", { children: /* @__PURE__ */ jsx19("span", { className: `is-${event.result ?? "success"}`, children: event.result === "failure" ? "\u5931\u8D25" : event.result === "warning" ? "\u8B66\u544A" : "\u6210\u529F" }) }),
961
+ /* @__PURE__ */ jsx19("td", { children: /* @__PURE__ */ jsx19("code", { children: event.ip ?? "\u2014" }) })
962
+ ] }, event.id)),
963
+ !events.length && /* @__PURE__ */ jsx19("tr", { children: /* @__PURE__ */ jsx19("td", { colSpan: 6, className: "hf-audit-log__empty", children: empty }) })
964
+ ] })
965
+ ] }) });
966
+ }
967
+
968
+ // src/components/Assets.tsx
969
+ import { useMemo as useMemo3, useRef as useRef3, useState as useState9 } from "react";
970
+ import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
971
+ function FileExplorer({ items, selectedId, onSelect, empty = "\u6682\u65E0\u6587\u4EF6" }) {
972
+ const [open, setOpen] = useState9([]);
973
+ const itemRefs = useRef3(/* @__PURE__ */ new Map());
974
+ const visible = useMemo3(() => {
975
+ const result = [];
976
+ const visit = (nodes, level, parentId) => nodes.forEach((item) => {
977
+ result.push({ item, level, parentId });
978
+ if (item.children?.length && open.includes(item.id)) visit(item.children, level + 1, item.id);
979
+ });
980
+ visit(items, 1);
981
+ return result;
982
+ }, [items, open]);
983
+ const toggle = (id) => setOpen((value) => value.includes(id) ? value.filter((key) => key !== id) : [...value, id]);
984
+ const focusAt = (index) => itemRefs.current.get(visible[Math.max(0, Math.min(visible.length - 1, index))]?.item.id ?? "")?.focus();
985
+ const onKeyDown = (event, entry, index) => {
986
+ const expandable = Boolean(entry.item.children?.length);
987
+ if (event.key === "ArrowDown") focusAt(index + 1);
988
+ else if (event.key === "ArrowUp") focusAt(index - 1);
989
+ else if (event.key === "Home") focusAt(0);
990
+ else if (event.key === "End") focusAt(visible.length - 1);
991
+ else if (event.key === "ArrowRight" && expandable) open.includes(entry.item.id) ? focusAt(index + 1) : toggle(entry.item.id);
992
+ else if (event.key === "ArrowLeft") {
993
+ if (expandable && open.includes(entry.item.id)) toggle(entry.item.id);
994
+ else if (entry.parentId) itemRefs.current.get(entry.parentId)?.focus();
995
+ else return;
996
+ } else return;
997
+ event.preventDefault();
998
+ };
999
+ return /* @__PURE__ */ jsx20("div", { className: "hf-file-explorer", role: "tree", "aria-label": "\u6587\u4EF6\u76EE\u5F55", children: items.length ? /* @__PURE__ */ jsx20("ul", { role: "none", children: visible.map((entry, index) => {
1000
+ const { item, level } = entry;
1001
+ const expandable = Boolean(item.children?.length);
1002
+ const expanded = expandable && open.includes(item.id);
1003
+ return /* @__PURE__ */ jsx20("li", { role: "none", children: /* @__PURE__ */ jsxs17("div", { className: selectedId === item.id ? "is-selected" : "", style: { paddingLeft: (level - 1) * 18 + 7 }, children: [
1004
+ /* @__PURE__ */ jsx20("span", { className: "hf-file-explorer__toggle", "aria-hidden": "true", children: expandable ? expanded ? "\u2304" : "\u203A" : "" }),
1005
+ /* @__PURE__ */ jsxs17("button", { type: "button", role: "treeitem", "aria-level": level, "aria-selected": selectedId === item.id, "aria-expanded": expandable ? expanded : void 0, ref: (node) => {
1006
+ if (node) itemRefs.current.set(item.id, node);
1007
+ else itemRefs.current.delete(item.id);
1008
+ }, onClick: () => {
1009
+ if (expandable) toggle(item.id);
1010
+ onSelect?.(item.id);
1011
+ }, onKeyDown: (event) => onKeyDown(event, entry, index), children: [
1012
+ item.icon ?? (item.type === "folder" ? "\u25B0" : "\u25A4"),
1013
+ /* @__PURE__ */ jsxs17("span", { children: [
1014
+ /* @__PURE__ */ jsx20("strong", { children: item.name }),
1015
+ item.modified && /* @__PURE__ */ jsx20("small", { children: item.modified })
1016
+ ] }),
1017
+ item.size && /* @__PURE__ */ jsx20("i", { children: item.size })
1018
+ ] })
1019
+ ] }) }, item.id);
1020
+ }) }) : /* @__PURE__ */ jsx20("div", { children: empty }) });
1021
+ }
1022
+ function FilePreview({ name, type, children, size, modified, actions, empty = "\u9009\u62E9\u6587\u4EF6\u540E\u5728\u6B64\u9884\u89C8" }) {
1023
+ return /* @__PURE__ */ jsx20("section", { className: "hf-file-preview", children: name ? /* @__PURE__ */ jsxs17(Fragment2, { children: [
1024
+ /* @__PURE__ */ jsxs17("header", { children: [
1025
+ /* @__PURE__ */ jsxs17("div", { children: [
1026
+ /* @__PURE__ */ jsx20("strong", { children: name }),
1027
+ /* @__PURE__ */ jsx20("span", { children: [type, size, modified].filter(Boolean).join(" \xB7 ") })
1028
+ ] }),
1029
+ actions
1030
+ ] }),
1031
+ /* @__PURE__ */ jsx20("div", { className: "hf-file-preview__body", children })
1032
+ ] }) : /* @__PURE__ */ jsxs17("div", { className: "hf-file-preview__empty", children: [
1033
+ "\u25A4",
1034
+ /* @__PURE__ */ jsx20("span", { children: empty })
1035
+ ] }) });
1036
+ }
1037
+ function VersionHistory({ versions, selectedId, onSelect, onRestore }) {
1038
+ return /* @__PURE__ */ jsx20("ol", { className: "hf-version-history", children: versions.map((item) => /* @__PURE__ */ jsxs17("li", { className: `${item.current ? "is-current" : ""}${selectedId === item.id ? " is-selected" : ""}`, children: [
1039
+ /* @__PURE__ */ jsxs17("button", { type: "button", onClick: () => onSelect?.(item.id), children: [
1040
+ /* @__PURE__ */ jsx20("span", {}),
1041
+ /* @__PURE__ */ jsxs17("div", { children: [
1042
+ /* @__PURE__ */ jsxs17("header", { children: [
1043
+ /* @__PURE__ */ jsx20("strong", { children: item.version }),
1044
+ item.current && /* @__PURE__ */ jsx20("i", { children: "\u5F53\u524D\u7248\u672C" }),
1045
+ /* @__PURE__ */ jsx20("time", { children: item.timestamp })
1046
+ ] }),
1047
+ /* @__PURE__ */ jsxs17("p", { children: [
1048
+ /* @__PURE__ */ jsx20(Avatar, { name: item.author.name, src: item.author.avatar, size: "sm" }),
1049
+ item.author.name
1050
+ ] }),
1051
+ item.description && /* @__PURE__ */ jsx20("div", { children: item.description }),
1052
+ item.tags?.map((tag) => /* @__PURE__ */ jsx20("small", { children: tag }, tag))
1053
+ ] })
1054
+ ] }),
1055
+ onRestore && !item.current && /* @__PURE__ */ jsx20("button", { type: "button", onClick: () => onRestore(item.id), children: "\u6062\u590D" })
1056
+ ] }, item.id)) });
1057
+ }
1058
+ function PermissionMatrix({ subjects, resources, value, onChange, disabled }) {
1059
+ return /* @__PURE__ */ jsx20("div", { className: "hf-permission-matrix", children: /* @__PURE__ */ jsxs17("table", { children: [
1060
+ /* @__PURE__ */ jsx20("thead", { children: /* @__PURE__ */ jsxs17("tr", { children: [
1061
+ /* @__PURE__ */ jsx20("th", { children: "\u6210\u5458\u6216\u89D2\u8272" }),
1062
+ resources.map((item) => /* @__PURE__ */ jsx20("th", { children: item.name }, item.id))
1063
+ ] }) }),
1064
+ /* @__PURE__ */ jsx20("tbody", { children: subjects.map((subject) => /* @__PURE__ */ jsxs17("tr", { children: [
1065
+ /* @__PURE__ */ jsxs17("th", { children: [
1066
+ /* @__PURE__ */ jsx20("span", { children: subject.avatar }),
1067
+ /* @__PURE__ */ jsxs17("div", { children: [
1068
+ /* @__PURE__ */ jsx20("strong", { children: subject.name }),
1069
+ subject.description && /* @__PURE__ */ jsx20("small", { children: subject.description })
1070
+ ] })
1071
+ ] }),
1072
+ resources.map((resource) => /* @__PURE__ */ jsx20("td", { children: /* @__PURE__ */ jsxs17("select", { "aria-label": `${String(subject.name)} \u5BF9 ${String(resource.name)} \u7684\u6743\u9650`, disabled, value: value[subject.id]?.[resource.id] ?? "none", onChange: (event) => onChange(subject.id, resource.id, event.target.value), children: [
1073
+ /* @__PURE__ */ jsx20("option", { value: "none", children: "\u65E0\u6743\u9650" }),
1074
+ /* @__PURE__ */ jsx20("option", { value: "view", children: "\u67E5\u770B" }),
1075
+ /* @__PURE__ */ jsx20("option", { value: "comment", children: "\u8BC4\u8BBA" }),
1076
+ /* @__PURE__ */ jsx20("option", { value: "edit", children: "\u7F16\u8F91" }),
1077
+ /* @__PURE__ */ jsx20("option", { value: "admin", children: "\u7BA1\u7406" })
1078
+ ] }) }, resource.id))
1079
+ ] }, subject.id)) })
1080
+ ] }) });
1081
+ }
1082
+ function MemberPicker({ members, value, onChange, label = "\u6DFB\u52A0\u6210\u5458", disabled }) {
1083
+ const [query, setQuery] = useState9("");
1084
+ const results = useMemo3(() => members.filter((item) => !value.includes(item.id) && `${item.name} ${String(item.description ?? "")}`.toLowerCase().includes(query.toLowerCase())), [members, query, value]);
1085
+ return /* @__PURE__ */ jsxs17("div", { className: "hf-member-picker", children: [
1086
+ /* @__PURE__ */ jsx20("div", { children: value.map((id) => {
1087
+ const item = members.find((member) => member.id === id);
1088
+ return item && /* @__PURE__ */ jsxs17("span", { children: [
1089
+ /* @__PURE__ */ jsx20(Avatar, { name: item.name, src: item.avatar, size: "sm" }),
1090
+ item.name,
1091
+ /* @__PURE__ */ jsx20("button", { type: "button", disabled, "aria-label": `\u79FB\u9664 ${item.name}`, onClick: () => onChange(value.filter((key) => key !== id)), children: "\xD7" })
1092
+ ] }, id);
1093
+ }) }),
1094
+ /* @__PURE__ */ jsx20("input", { "aria-label": label, value: query, disabled, placeholder: label, onChange: (event) => setQuery(event.target.value) }),
1095
+ query && /* @__PURE__ */ jsxs17("div", { className: "hf-member-picker__menu", children: [
1096
+ results.map((item) => /* @__PURE__ */ jsxs17("button", { type: "button", onClick: () => {
1097
+ onChange([...value, item.id]);
1098
+ setQuery("");
1099
+ }, children: [
1100
+ /* @__PURE__ */ jsx20(Avatar, { name: item.name, src: item.avatar, size: "sm" }),
1101
+ /* @__PURE__ */ jsxs17("span", { children: [
1102
+ /* @__PURE__ */ jsx20("strong", { children: item.name }),
1103
+ item.description && /* @__PURE__ */ jsx20("small", { children: item.description })
1104
+ ] })
1105
+ ] }, item.id)),
1106
+ !results.length && /* @__PURE__ */ jsx20("p", { children: "\u6CA1\u6709\u5339\u914D\u6210\u5458" })
1107
+ ] })
1108
+ ] });
1109
+ }
1110
+ function SharePanel({ scope, onScopeChange, members, onCopyLink, linkCopied, footer }) {
1111
+ return /* @__PURE__ */ jsxs17("section", { className: "hf-share-panel", children: [
1112
+ /* @__PURE__ */ jsxs17("header", { children: [
1113
+ /* @__PURE__ */ jsx20("strong", { children: "\u5171\u4EAB\u8BBE\u7F6E" }),
1114
+ /* @__PURE__ */ jsx20("span", { children: "\u63A7\u5236\u8C01\u53EF\u4EE5\u8BBF\u95EE\u6B64\u5185\u5BB9" })
1115
+ ] }),
1116
+ /* @__PURE__ */ jsx20("div", { className: "hf-share-panel__scope", children: ["restricted", "organization", "public"].map((item) => /* @__PURE__ */ jsxs17("label", { children: [
1117
+ /* @__PURE__ */ jsx20("input", { type: "radio", name: "hf-share-scope", checked: scope === item, onChange: () => onScopeChange(item) }),
1118
+ /* @__PURE__ */ jsxs17("span", { children: [
1119
+ /* @__PURE__ */ jsx20("strong", { children: { restricted: "\u4EC5\u53D7\u9080\u6210\u5458", organization: "\u7EC4\u7EC7\u5185\u6210\u5458", public: "\u62E5\u6709\u94FE\u63A5\u7684\u4EFB\u4F55\u4EBA" }[item] }),
1120
+ /* @__PURE__ */ jsx20("small", { children: { restricted: "\u53EA\u6709\u5217\u8868\u4E2D\u7684\u6210\u5458\u53EF\u4EE5\u8BBF\u95EE", organization: "\u540C\u4E00\u7EC4\u7EC7\u6210\u5458\u5747\u53EF\u8BBF\u95EE", public: "\u65E0\u9700\u767B\u5F55\u5373\u53EF\u8BBF\u95EE" }[item] })
1121
+ ] })
1122
+ ] }, item)) }),
1123
+ members && /* @__PURE__ */ jsx20("div", { className: "hf-share-panel__members", children: members }),
1124
+ /* @__PURE__ */ jsxs17("footer", { children: [
1125
+ /* @__PURE__ */ jsx20("button", { type: "button", onClick: onCopyLink, children: linkCopied ? "\u94FE\u63A5\u5DF2\u590D\u5236" : "\u590D\u5236\u94FE\u63A5" }),
1126
+ footer
1127
+ ] })
1128
+ ] });
1129
+ }
1130
+
1131
+ // src/components/Scheduling.tsx
1132
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1133
+ function EventCard({
1134
+ event,
1135
+ onClick
1136
+ }) {
1137
+ return /* @__PURE__ */ jsxs18(
1138
+ "button",
1139
+ {
1140
+ type: "button",
1141
+ className: "hf-event-card",
1142
+ onClick: () => onClick?.(event.id),
1143
+ children: [
1144
+ /* @__PURE__ */ jsx21("strong", { children: event.title }),
1145
+ /* @__PURE__ */ jsxs18("time", { children: [
1146
+ event.start,
1147
+ "\u2013",
1148
+ event.end
1149
+ ] })
1150
+ ]
1151
+ }
1152
+ );
1153
+ }
1154
+ function Scheduler({
1155
+ days,
1156
+ events,
1157
+ onEventClick
1158
+ }) {
1159
+ return /* @__PURE__ */ jsx21("div", { className: "hf-scheduler", children: days.map((day2) => /* @__PURE__ */ jsxs18("section", { children: [
1160
+ /* @__PURE__ */ jsx21("strong", { children: day2 }),
1161
+ events.filter((e) => e.start.startsWith(day2)).map((e) => /* @__PURE__ */ jsx21(EventCard, { event: e, onClick: onEventClick }, e.id))
1162
+ ] }, day2)) });
1163
+ }
1164
+ function ResourceCalendar({
1165
+ resources,
1166
+ events
1167
+ }) {
1168
+ return /* @__PURE__ */ jsx21("div", { className: "hf-resource-calendar", children: resources.map((r) => /* @__PURE__ */ jsxs18("section", { children: [
1169
+ /* @__PURE__ */ jsx21("strong", { children: r.name }),
1170
+ events.filter((e) => e.resourceId === r.id).map((e) => /* @__PURE__ */ jsx21(EventCard, { event: e }, e.id))
1171
+ ] }, r.id)) });
1172
+ }
1173
+ function RecurrenceEditor({
1174
+ value,
1175
+ onChange
1176
+ }) {
1177
+ return /* @__PURE__ */ jsxs18("div", { className: "hf-recurrence", children: [
1178
+ /* @__PURE__ */ jsxs18(
1179
+ "select",
1180
+ {
1181
+ "aria-label": "\u91CD\u590D\u9891\u7387",
1182
+ value: value.frequency,
1183
+ onChange: (e) => onChange({
1184
+ ...value,
1185
+ frequency: e.target.value
1186
+ }),
1187
+ children: [
1188
+ /* @__PURE__ */ jsx21("option", { value: "none", children: "\u4E0D\u91CD\u590D" }),
1189
+ /* @__PURE__ */ jsx21("option", { value: "daily", children: "\u6BCF\u5929" }),
1190
+ /* @__PURE__ */ jsx21("option", { value: "weekly", children: "\u6BCF\u5468" }),
1191
+ /* @__PURE__ */ jsx21("option", { value: "monthly", children: "\u6BCF\u6708" })
1192
+ ]
1193
+ }
1194
+ ),
1195
+ /* @__PURE__ */ jsx21(
1196
+ "input",
1197
+ {
1198
+ "aria-label": "\u91CD\u590D\u95F4\u9694",
1199
+ type: "number",
1200
+ min: 1,
1201
+ value: value.interval,
1202
+ onChange: (e) => onChange({ ...value, interval: +e.target.value })
1203
+ }
1204
+ )
1205
+ ] });
1206
+ }
1207
+ function TimezoneSelect({
1208
+ options,
1209
+ value,
1210
+ onChange
1211
+ }) {
1212
+ return /* @__PURE__ */ jsx21(
1213
+ "select",
1214
+ {
1215
+ "aria-label": "\u65F6\u533A",
1216
+ className: "hf-timezone",
1217
+ value,
1218
+ onChange: (e) => onChange(e.target.value),
1219
+ children: options.map((o) => /* @__PURE__ */ jsxs18("option", { value: o.value, children: [
1220
+ o.label,
1221
+ " (",
1222
+ o.offset,
1223
+ ")"
1224
+ ] }, o.value))
1225
+ }
1226
+ );
1227
+ }
1228
+ function AvailabilityGrid({
1229
+ people,
1230
+ slots,
1231
+ value
1232
+ }) {
1233
+ return /* @__PURE__ */ jsx21("div", { className: "hf-availability", children: /* @__PURE__ */ jsxs18("table", { children: [
1234
+ /* @__PURE__ */ jsx21("thead", { children: /* @__PURE__ */ jsxs18("tr", { children: [
1235
+ /* @__PURE__ */ jsx21("th", { children: "\u6210\u5458" }),
1236
+ slots.map((s) => /* @__PURE__ */ jsx21("th", { children: s }, s))
1237
+ ] }) }),
1238
+ /* @__PURE__ */ jsx21("tbody", { children: people.map((p) => /* @__PURE__ */ jsxs18("tr", { children: [
1239
+ /* @__PURE__ */ jsx21("th", { children: p.name }),
1240
+ slots.map((s) => /* @__PURE__ */ jsx21("td", { children: /* @__PURE__ */ jsx21("i", { className: `is-${value[p.id]?.[s] ?? "unavailable"}` }) }, s))
1241
+ ] }, p.id)) })
1242
+ ] }) });
1243
+ }
1244
+
1245
+ // src/foundations/Typography.tsx
1246
+ import { jsx as jsx22 } from "react/jsx-runtime";
1247
+ function Typography({ as, variant = "body", muted, truncate, className = "", ...props }) {
1248
+ const defaults = { display: "h1", h1: "h1", h2: "h2", h3: "h3", code: "code" };
1249
+ const Tag2 = as ?? defaults[variant] ?? "p";
1250
+ return /* @__PURE__ */ jsx22(Tag2, { className: `hf-typography hf-typography--${variant}${muted ? " is-muted" : ""}${truncate ? " is-truncated" : ""} ${className}`, ...props });
1251
+ }
1252
+
1253
+ // src/navigation/types.ts
1254
+ function activateNavigationItem(item, onItemSelect) {
1255
+ onItemSelect?.(item);
1256
+ }
1257
+
1258
+ // src/navigation/FloatingNav.tsx
1259
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
1260
+ function FloatingNav({ brand, items, action, activeKey, onItemSelect, className = "", ...props }) {
1261
+ return /* @__PURE__ */ jsxs19("nav", { className: `hf-floating-nav ${className}`.trim(), "aria-label": "\u4E3B\u5BFC\u822A", ...props, children: [
1262
+ /* @__PURE__ */ jsx23("div", { className: "hf-floating-nav__brand", children: brand }),
1263
+ /* @__PURE__ */ jsx23("div", { className: "hf-floating-nav__items", children: items.map((item) => /* @__PURE__ */ jsx23("a", { href: item.href ?? "#", "aria-current": activeKey === item.key ? "page" : void 0, onClick: () => activateNavigationItem(item, onItemSelect), children: item.label }, item.key)) }),
1264
+ action && /* @__PURE__ */ jsx23("div", { className: "hf-floating-nav__action", children: action })
1265
+ ] });
1266
+ }
1267
+
1268
+ // src/navigation/Sidebar.tsx
1269
+ import { useState as useState10 } from "react";
1270
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
1271
+ function Sidebar({ brand, items, activeKey, collapsed, defaultCollapsed = false, onCollapsedChange, onItemSelect, appearance = "flush", className = "", ...props }) {
1272
+ const [internalCollapsed, setInternalCollapsed] = useState10(defaultCollapsed);
1273
+ const isCollapsed = collapsed ?? internalCollapsed;
1274
+ const toggle = () => {
1275
+ const next = !isCollapsed;
1276
+ if (collapsed === void 0) setInternalCollapsed(next);
1277
+ onCollapsedChange?.(next);
1278
+ };
1279
+ return /* @__PURE__ */ jsxs20("aside", { className: `hf-sidebar hf-sidebar--${appearance} ${isCollapsed ? "hf-sidebar--collapsed" : ""} ${className}`.trim(), ...props, children: [
1280
+ /* @__PURE__ */ jsxs20("div", { className: "hf-sidebar__top", children: [
1281
+ brand && /* @__PURE__ */ jsx24("div", { className: "hf-sidebar__brand", children: brand }),
1282
+ /* @__PURE__ */ jsx24("button", { type: "button", onClick: toggle, "aria-label": isCollapsed ? "\u5C55\u5F00\u4FA7\u8FB9\u680F" : "\u6536\u8D77\u4FA7\u8FB9\u680F", "aria-expanded": !isCollapsed, children: "\u2039" })
1283
+ ] }),
1284
+ /* @__PURE__ */ jsx24("nav", { "aria-label": "\u4FA7\u8FB9\u5BFC\u822A", children: items.map((item) => /* @__PURE__ */ jsxs20("a", { href: item.href ?? "#", "aria-current": activeKey === item.key ? "page" : void 0, title: isCollapsed ? item.label : void 0, onClick: () => activateNavigationItem(item, onItemSelect), children: [
1285
+ /* @__PURE__ */ jsx24("span", { className: "hf-sidebar__icon", children: item.icon ?? item.label.slice(0, 1) }),
1286
+ /* @__PURE__ */ jsx24("span", { className: "hf-sidebar__label", children: item.label })
1287
+ ] }, item.key)) })
1288
+ ] });
1289
+ }
1290
+
1291
+ // src/navigation/Breadcrumb.tsx
1292
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
1293
+ function Breadcrumb({ items, separator = "/", onItemSelect, className = "", ...props }) {
1294
+ return /* @__PURE__ */ jsx25("nav", { className: `hf-breadcrumb ${className}`.trim(), "aria-label": "\u9762\u5305\u5C51", ...props, children: /* @__PURE__ */ jsx25("ol", { children: items.map((item, index) => {
1295
+ const current = index === items.length - 1;
1296
+ return /* @__PURE__ */ jsxs21("li", { children: [
1297
+ current ? /* @__PURE__ */ jsx25("span", { "aria-current": "page", children: item.label }) : /* @__PURE__ */ jsx25("a", { href: item.href ?? "#", onClick: () => activateNavigationItem(item, onItemSelect), children: item.label }),
1298
+ !current && /* @__PURE__ */ jsx25("i", { "aria-hidden": "true", children: separator })
1299
+ ] }, item.key);
1300
+ }) }) });
1301
+ }
1302
+
1303
+ // src/navigation/Menu.tsx
1304
+ import { useState as useState11 } from "react";
1305
+ import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
1306
+ function DropdownMenu({ label, items, activeKey, onItemSelect, className = "", ...props }) {
1307
+ const [open, setOpen] = useState11(false);
1308
+ const ref = useDismissibleLayer(open, () => setOpen(false), { autoFocus: false });
1309
+ return /* @__PURE__ */ jsxs22("div", { ref, className: `hf-menu ${className}`.trim(), ...props, children: [
1310
+ /* @__PURE__ */ jsxs22("button", { type: "button", "aria-expanded": open, "aria-haspopup": "menu", onClick: () => setOpen((value) => !value), children: [
1311
+ label,
1312
+ /* @__PURE__ */ jsx26("span", { "aria-hidden": "true", children: "\u2304" })
1313
+ ] }),
1314
+ open && /* @__PURE__ */ jsx26("div", { className: "hf-menu__panel", role: "menu", children: items.map((item) => /* @__PURE__ */ jsx26("a", { role: "menuitem", href: item.href ?? "#", "aria-current": activeKey === item.key ? "page" : void 0, onClick: () => {
1315
+ activateNavigationItem(item, onItemSelect);
1316
+ setOpen(false);
1317
+ }, children: item.label }, item.key)) })
1318
+ ] });
1319
+ }
1320
+ function MegaMenu({ label, items, onItemSelect, className = "", ...props }) {
1321
+ const [open, setOpen] = useState11(false);
1322
+ const ref = useDismissibleLayer(open, () => setOpen(false), { autoFocus: false });
1323
+ return /* @__PURE__ */ jsxs22("div", { ref, className: `hf-menu hf-mega-menu ${className}`.trim(), ...props, children: [
1324
+ /* @__PURE__ */ jsxs22("button", { type: "button", "aria-expanded": open, "aria-haspopup": "menu", onClick: () => setOpen((value) => !value), children: [
1325
+ label,
1326
+ /* @__PURE__ */ jsx26("span", { "aria-hidden": "true", children: "\u2304" })
1327
+ ] }),
1328
+ open && /* @__PURE__ */ jsx26("div", { className: "hf-mega-menu__panel", role: "menu", children: items.map((group) => /* @__PURE__ */ jsxs22("section", { children: [
1329
+ /* @__PURE__ */ jsx26("h3", { children: group.label }),
1330
+ group.children?.map((item) => /* @__PURE__ */ jsxs22("a", { role: "menuitem", href: item.href ?? "#", onClick: () => {
1331
+ activateNavigationItem(item, onItemSelect);
1332
+ setOpen(false);
1333
+ }, children: [
1334
+ /* @__PURE__ */ jsx26("span", { children: item.icon }),
1335
+ /* @__PURE__ */ jsxs22("span", { children: [
1336
+ /* @__PURE__ */ jsx26("strong", { children: item.label }),
1337
+ item.description && /* @__PURE__ */ jsx26("small", { children: item.description })
1338
+ ] })
1339
+ ] }, item.key))
1340
+ ] }, group.key)) })
1341
+ ] });
1342
+ }
1343
+
1344
+ // src/navigation/MobileNavigation.tsx
1345
+ import { useId as useId4, useState as useState12 } from "react";
1346
+ import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
1347
+ function MobileNavigation({ brand, items, mode = "drawer", activeKey, open, onOpenChange, onItemSelect, className = "", ...props }) {
1348
+ const [internalOpen, setInternalOpen] = useState12(false);
1349
+ const isOpen = open ?? internalOpen;
1350
+ const panelId = useId4();
1351
+ const setOpen = (next) => {
1352
+ if (open === void 0) setInternalOpen(next);
1353
+ onOpenChange?.(next);
1354
+ };
1355
+ const panelRef = useDismissibleLayer(isOpen, () => setOpen(false), true);
1356
+ return /* @__PURE__ */ jsxs23("div", { className: `hf-mobile-nav ${className}`.trim(), ...props, children: [
1357
+ /* @__PURE__ */ jsxs23("div", { className: "hf-mobile-nav__bar", children: [
1358
+ /* @__PURE__ */ jsx27("div", { children: brand }),
1359
+ /* @__PURE__ */ jsxs23("button", { type: "button", "aria-label": "\u6253\u5F00\u5BFC\u822A", "aria-expanded": isOpen, "aria-controls": panelId, onClick: () => setOpen(true), children: [
1360
+ /* @__PURE__ */ jsx27("i", {}),
1361
+ /* @__PURE__ */ jsx27("i", {}),
1362
+ /* @__PURE__ */ jsx27("i", {})
1363
+ ] })
1364
+ ] }),
1365
+ isOpen && /* @__PURE__ */ jsx27("div", { className: `hf-mobile-nav__backdrop hf-mobile-nav__backdrop--${mode}`, onMouseDown: (event) => event.target === event.currentTarget && setOpen(false), children: /* @__PURE__ */ jsxs23("nav", { ref: panelRef, id: panelId, className: "hf-mobile-nav__panel", "aria-label": "\u79FB\u52A8\u5BFC\u822A", tabIndex: -1, children: [
1366
+ /* @__PURE__ */ jsxs23("header", { children: [
1367
+ /* @__PURE__ */ jsx27("div", { children: brand }),
1368
+ /* @__PURE__ */ jsx27("button", { type: "button", "aria-label": "\u5173\u95ED\u5BFC\u822A", onClick: () => setOpen(false), children: "\xD7" })
1369
+ ] }),
1370
+ /* @__PURE__ */ jsx27("div", { className: "hf-mobile-nav__links", children: items.map((item, index) => /* @__PURE__ */ jsxs23("a", { href: item.href ?? "#", "aria-current": activeKey === item.key ? "page" : void 0, style: { "--hf-nav-index": index }, onClick: () => {
1371
+ activateNavigationItem(item, onItemSelect);
1372
+ setOpen(false);
1373
+ }, children: [
1374
+ /* @__PURE__ */ jsx27("span", { children: item.label }),
1375
+ item.description && /* @__PURE__ */ jsx27("small", { children: item.description })
1376
+ ] }, item.key)) })
1377
+ ] }) })
1378
+ ] });
1379
+ }
1380
+
1381
+ // src/navigation/Scrollspy.tsx
1382
+ import { useEffect as useEffect4, useState as useState13 } from "react";
1383
+ import { jsx as jsx28 } from "react/jsx-runtime";
1384
+ function Scrollspy({ items, activeKey, onItemSelect, rootMargin = "-20% 0px -65%", className = "", ...props }) {
1385
+ const [observedKey, setObservedKey] = useState13(items[0]?.key);
1386
+ const currentKey = activeKey ?? observedKey;
1387
+ useEffect4(() => {
1388
+ if (activeKey || !("IntersectionObserver" in window)) return;
1389
+ const observer = new IntersectionObserver((entries) => {
1390
+ const visible = entries.find((entry) => entry.isIntersecting);
1391
+ if (visible?.target.id) setObservedKey(visible.target.id);
1392
+ }, { rootMargin });
1393
+ items.forEach((item) => {
1394
+ const section = document.getElementById(item.key);
1395
+ if (section) observer.observe(section);
1396
+ });
1397
+ return () => observer.disconnect();
1398
+ }, [activeKey, items, rootMargin]);
1399
+ return /* @__PURE__ */ jsx28("nav", { className: `hf-scrollspy ${className}`.trim(), "aria-label": "\u9875\u5185\u5BFC\u822A", ...props, children: items.map((item) => /* @__PURE__ */ jsx28("a", { href: item.href ?? `#${item.key}`, "aria-current": currentKey === item.key ? "location" : void 0, onClick: () => onItemSelect?.(item), children: item.label }, item.key)) });
1400
+ }
1401
+
1402
+ // src/navigation/ShrinkNav.tsx
1403
+ import { useEffect as useEffect5, useState as useState14 } from "react";
1404
+ import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
1405
+ function ShrinkNav({ brand, items, threshold = 48, action, activeKey, onItemSelect, className = "", ...props }) {
1406
+ const [compact, setCompact] = useState14(false);
1407
+ useEffect5(() => {
1408
+ let frame = 0;
1409
+ const update = () => {
1410
+ cancelAnimationFrame(frame);
1411
+ frame = requestAnimationFrame(() => setCompact(window.scrollY > threshold));
1412
+ };
1413
+ update();
1414
+ window.addEventListener("scroll", update, { passive: true });
1415
+ return () => {
1416
+ cancelAnimationFrame(frame);
1417
+ window.removeEventListener("scroll", update);
1418
+ };
1419
+ }, [threshold]);
1420
+ return /* @__PURE__ */ jsxs24("nav", { className: `hf-shrink-nav ${compact ? "hf-shrink-nav--compact" : ""} ${className}`.trim(), "aria-label": "\u6EDA\u52A8\u5BFC\u822A", ...props, children: [
1421
+ /* @__PURE__ */ jsx29("div", { className: "hf-shrink-nav__brand", children: brand }),
1422
+ /* @__PURE__ */ jsx29("div", { className: "hf-shrink-nav__items", children: items.map((item) => /* @__PURE__ */ jsx29("a", { href: item.href ?? "#", "aria-current": activeKey === item.key ? "page" : void 0, onClick: () => onItemSelect?.(item), children: item.label }, item.key)) }),
1423
+ action
1424
+ ] });
1425
+ }
1426
+
1427
+ // src/navigation/Tabs.tsx
1428
+ import { useId as useId5 } from "react";
1429
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
1430
+ function Tabs({ items, value, onChange, variant = "line", label = "\u5185\u5BB9\u6807\u7B7E" }) {
1431
+ const id = useId5();
1432
+ const active = items.find((item) => item.key === value) ?? items[0];
1433
+ const onKeyDown = (event) => {
1434
+ if (!["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key)) return;
1435
+ event.preventDefault();
1436
+ const enabled = items.filter((item) => !item.disabled);
1437
+ const current = enabled.findIndex((item) => item.key === value);
1438
+ const offset = event.key === "ArrowLeft" || event.key === "ArrowUp" ? -1 : 1;
1439
+ const next = enabled[(current + offset + enabled.length) % enabled.length];
1440
+ if (next) onChange(next.key);
1441
+ };
1442
+ return /* @__PURE__ */ jsxs25("div", { className: `hf-tabs hf-tabs--${variant}`, children: [
1443
+ /* @__PURE__ */ jsx30("div", { role: "tablist", "aria-label": label, onKeyDown, children: items.map((item) => /* @__PURE__ */ jsxs25("button", { type: "button", role: "tab", id: `${id}-${item.key}`, "aria-controls": `${id}-${item.key}-panel`, "aria-selected": item.key === value, tabIndex: item.key === value ? 0 : -1, disabled: item.disabled, onClick: () => onChange(item.key), children: [
1444
+ item.icon,
1445
+ /* @__PURE__ */ jsx30("span", { children: item.label }),
1446
+ item.badge && /* @__PURE__ */ jsx30("small", { children: item.badge })
1447
+ ] }, item.key)) }),
1448
+ active && /* @__PURE__ */ jsx30("div", { role: "tabpanel", id: `${id}-${active.key}-panel`, "aria-labelledby": `${id}-${active.key}`, tabIndex: 0, children: active.content })
1449
+ ] });
1450
+ }
1451
+
1452
+ // src/navigation/Steps.tsx
1453
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
1454
+ function Steps({ items, current, onChange, orientation = "horizontal" }) {
1455
+ const currentIndex = Math.max(0, items.findIndex((item) => item.key === current));
1456
+ return /* @__PURE__ */ jsx31("ol", { className: `hf-steps hf-steps--${orientation}`, children: items.map((item, index) => {
1457
+ const state = index < currentIndex ? "complete" : index === currentIndex ? "current" : "upcoming";
1458
+ return /* @__PURE__ */ jsx31("li", { className: `is-${state}`, "aria-current": state === "current" ? "step" : void 0, children: /* @__PURE__ */ jsxs26("button", { type: "button", disabled: item.disabled || !onChange, onClick: () => onChange?.(item.key), children: [
1459
+ /* @__PURE__ */ jsx31("span", { children: state === "complete" ? "\u2713" : index + 1 }),
1460
+ /* @__PURE__ */ jsxs26("span", { children: [
1461
+ /* @__PURE__ */ jsx31("strong", { children: item.title }),
1462
+ item.optional && /* @__PURE__ */ jsx31("small", { children: "\u53EF\u9009" }),
1463
+ item.description && /* @__PURE__ */ jsx31("small", { children: item.description })
1464
+ ] })
1465
+ ] }) }, item.key);
1466
+ }) });
1467
+ }
1468
+
1469
+ // src/navigation/CommandPalette.tsx
1470
+ import { useEffect as useEffect6, useMemo as useMemo4, useState as useState15 } from "react";
1471
+ import { createPortal as createPortal3 } from "react-dom";
1472
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
1473
+ function CommandPalette({ open, onOpenChange, items, onSelect, placeholder = "\u8F93\u5165\u547D\u4EE4\u6216\u641C\u7D22\u2026" }) {
1474
+ const [query, setQuery] = useState15("");
1475
+ const [active, setActive] = useState15(0);
1476
+ const enabled = useMemo4(() => items.filter((item) => !item.disabled && `${item.label} ${item.description ?? ""} ${item.group ?? ""}`.toLowerCase().includes(query.toLowerCase())), [items, query]);
1477
+ const dialogRef = useDismissibleLayer(open, () => onOpenChange(false), true);
1478
+ useEffect6(() => {
1479
+ if (!open) {
1480
+ setQuery("");
1481
+ setActive(0);
1482
+ }
1483
+ }, [open]);
1484
+ const keydown = (event) => {
1485
+ if (!enabled.length) return;
1486
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1487
+ event.preventDefault();
1488
+ setActive((current) => (current + (event.key === "ArrowDown" ? 1 : -1) + enabled.length) % enabled.length);
1489
+ } else if (event.key === "Home" || event.key === "End") {
1490
+ event.preventDefault();
1491
+ setActive(event.key === "Home" ? 0 : enabled.length - 1);
1492
+ } else if (event.key === "Enter") {
1493
+ event.preventDefault();
1494
+ const item = enabled[active];
1495
+ if (item) {
1496
+ onSelect(item.key);
1497
+ onOpenChange(false);
1498
+ }
1499
+ }
1500
+ };
1501
+ if (!open) return null;
1502
+ return createPortal3(/* @__PURE__ */ jsx32("div", { className: "hf-command-backdrop", onMouseDown: (event) => event.target === event.currentTarget && onOpenChange(false), children: /* @__PURE__ */ jsxs27("div", { ref: dialogRef, tabIndex: -1, className: "hf-command", role: "dialog", "aria-modal": "true", "aria-label": "\u547D\u4EE4\u9762\u677F", children: [
1503
+ /* @__PURE__ */ jsxs27("div", { className: "hf-command__search", children: [
1504
+ /* @__PURE__ */ jsx32("span", { "aria-hidden": "true", children: "\u2315" }),
1505
+ /* @__PURE__ */ jsx32("input", { autoFocus: true, role: "combobox", "aria-expanded": "true", "aria-controls": "hf-command-list", value: query, placeholder, onChange: (event) => {
1506
+ setQuery(event.target.value);
1507
+ setActive(0);
1508
+ }, onKeyDown: keydown }),
1509
+ /* @__PURE__ */ jsx32("kbd", { children: "Esc" })
1510
+ ] }),
1511
+ /* @__PURE__ */ jsxs27("div", { id: "hf-command-list", className: "hf-command__list", role: "listbox", children: [
1512
+ enabled.map((item, index) => /* @__PURE__ */ jsxs27("button", { type: "button", role: "option", "aria-selected": index === active, onPointerMove: () => setActive(index), onClick: () => {
1513
+ onSelect(item.key);
1514
+ onOpenChange(false);
1515
+ }, children: [
1516
+ item.icon,
1517
+ /* @__PURE__ */ jsxs27("span", { children: [
1518
+ /* @__PURE__ */ jsx32("strong", { children: item.label }),
1519
+ item.description && /* @__PURE__ */ jsx32("small", { children: item.description })
1520
+ ] }),
1521
+ item.shortcut && /* @__PURE__ */ jsx32("kbd", { children: item.shortcut })
1522
+ ] }, item.key)),
1523
+ !enabled.length && /* @__PURE__ */ jsx32("div", { className: "hf-command__empty", children: "\u6CA1\u6709\u5339\u914D\u547D\u4EE4" })
1524
+ ] })
1525
+ ] }) }), document.body);
1526
+ }
1527
+
1528
+ // src/layout/Layout.tsx
1529
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
1530
+ function Container({ size = "lg", padding = 24, className = "", style, ...props }) {
1531
+ return /* @__PURE__ */ jsx33("div", { className: `hf-container hf-container--${size} ${className}`.trim(), style: { "--hf-container-padding": `${padding}px`, ...style }, ...props });
1532
+ }
1533
+ function Stack({ direction = "column", gap = 12, align, justify, wrap = false, className = "", style, ...props }) {
1534
+ return /* @__PURE__ */ jsx33("div", { className: `hf-stack hf-stack--${direction} ${className}`.trim(), style: { "--hf-stack-gap": `${gap}px`, alignItems: align, justifyContent: justify, flexWrap: wrap ? "wrap" : void 0, ...style }, ...props });
1535
+ }
1536
+ function Grid({ columns = "auto", minItemWidth = 240, gap = 16, className = "", style, ...props }) {
1537
+ const gridStyle = {
1538
+ "--hf-grid-columns": columns === "auto" ? `repeat(auto-fit, minmax(min(100%, ${minItemWidth}px), 1fr))` : `repeat(${columns}, minmax(0, 1fr))`,
1539
+ "--hf-grid-gap": `${gap}px`,
1540
+ ...style
1541
+ };
1542
+ return /* @__PURE__ */ jsx33("div", { className: `hf-grid ${className}`.trim(), style: gridStyle, ...props });
1543
+ }
1544
+ function Masonry({ columns, minColumnWidth = 260, gap = 16, className = "", style, children, ...props }) {
1545
+ const masonryStyle = {
1546
+ "--hf-masonry-columns": columns ?? "auto",
1547
+ "--hf-masonry-width": `${minColumnWidth}px`,
1548
+ "--hf-masonry-gap": `${gap}px`,
1549
+ ...style
1550
+ };
1551
+ return /* @__PURE__ */ jsx33("div", { className: `hf-masonry ${className}`.trim(), style: masonryStyle, ...props, children });
1552
+ }
1553
+ function PageLayout({ variant = "single", sidebar, header, sidebarWidth = 280, className = "", style, children, ...props }) {
1554
+ const layoutStyle = { "--hf-layout-sidebar": `${sidebarWidth}px`, ...style };
1555
+ return /* @__PURE__ */ jsxs28("div", { className: `hf-page-layout hf-page-layout--${variant} ${className}`.trim(), style: layoutStyle, ...props, children: [
1556
+ header && /* @__PURE__ */ jsx33("header", { className: "hf-page-layout__header", children: header }),
1557
+ sidebar && /* @__PURE__ */ jsx33("aside", { className: "hf-page-layout__sidebar", children: sidebar }),
1558
+ /* @__PURE__ */ jsx33("main", { className: "hf-page-layout__main", children })
1559
+ ] });
1560
+ }
1561
+
1562
+ // src/layout/Skeleton.tsx
1563
+ import { jsx as jsx34 } from "react/jsx-runtime";
1564
+ function Skeleton({ width = "100%", height = 16, radius, circle, animated = true, className = "", style, ...props }) {
1565
+ const value = (input) => typeof input === "number" ? `${input}px` : input;
1566
+ return /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", className: `hf-skeleton ${animated ? "is-animated" : ""} ${circle ? "is-circle" : ""} ${className}`.trim(), style: { width: value(width), height: value(height), borderRadius: radius ? value(radius) : void 0, ...style }, ...props });
1567
+ }
1568
+
1569
+ // src/feedback/Loading.tsx
1570
+ import { jsx as jsx35, jsxs as jsxs29 } from "react/jsx-runtime";
1571
+ function Spinner({ label = "\u6B63\u5728\u52A0\u8F7D", size = 20, className = "" }) {
1572
+ return /* @__PURE__ */ jsx35("span", { className: `hf-loading-spinner ${className}`.trim(), role: "status", "aria-label": label, style: { "--hf-loading-size": `${size}px` } });
1573
+ }
1574
+ function LoadingDots({ label = "\u6B63\u5728\u52A0\u8F7D" }) {
1575
+ return /* @__PURE__ */ jsxs29("span", { className: "hf-loading-dots", role: "status", "aria-label": label, children: [
1576
+ /* @__PURE__ */ jsx35("i", {}),
1577
+ /* @__PURE__ */ jsx35("i", {}),
1578
+ /* @__PURE__ */ jsx35("i", {})
1579
+ ] });
1580
+ }
1581
+ function ProgressBar({ value, label, indeterminate = false, className = "" }) {
1582
+ const percent = Math.min(100, Math.max(0, value ?? 0));
1583
+ return /* @__PURE__ */ jsxs29("div", { className: `hf-progress ${indeterminate ? "is-indeterminate" : ""} ${className}`.trim(), children: [
1584
+ label && /* @__PURE__ */ jsxs29("div", { className: "hf-progress__label", children: [
1585
+ /* @__PURE__ */ jsx35("span", { children: label }),
1586
+ !indeterminate && /* @__PURE__ */ jsxs29("strong", { children: [
1587
+ percent,
1588
+ "%"
1589
+ ] })
1590
+ ] }),
1591
+ /* @__PURE__ */ jsx35("div", { className: "hf-progress__track", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": indeterminate ? void 0 : percent, children: /* @__PURE__ */ jsx35("i", { style: { "--hf-progress": `${percent}%` } }) })
1592
+ ] });
1593
+ }
1594
+ function ProgressRing({ value, size = 72, label }) {
1595
+ const percent = Math.min(100, Math.max(0, value));
1596
+ return /* @__PURE__ */ jsx35("span", { className: "hf-progress-ring", role: "progressbar", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": percent, style: { "--hf-ring-value": `${percent * 3.6}deg`, "--hf-ring-size": `${size}px` }, children: /* @__PURE__ */ jsxs29("strong", { children: [
1597
+ percent,
1598
+ "%"
1599
+ ] }) });
1600
+ }
1601
+ function LoadingOverlay({ active = true, label = "\u6B63\u5728\u51C6\u5907\u5185\u5BB9", className = "", children, ...props }) {
1602
+ return /* @__PURE__ */ jsxs29("div", { className: `hf-loading-overlay ${className}`.trim(), "aria-busy": active, ...props, children: [
1603
+ children,
1604
+ active && /* @__PURE__ */ jsxs29("div", { className: "hf-loading-overlay__veil", role: "status", children: [
1605
+ /* @__PURE__ */ jsx35(Spinner, { label, size: 28 }),
1606
+ /* @__PURE__ */ jsx35("span", { children: label })
1607
+ ] })
1608
+ ] });
1609
+ }
1610
+
1611
+ // src/forms/Select.tsx
1612
+ import { forwardRef as forwardRef5, useEffect as useEffect7, useId as useId6, useRef as useRef4, useState as useState16 } from "react";
1613
+ import { jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
1614
+ var Select = forwardRef5(function Select2({ id, label, hint, error, options, placeholder, className = "", value, defaultValue, onChange, disabled, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }, forwardedRef) {
1615
+ const generatedId = useId6();
1616
+ const inputId = id ?? generatedId;
1617
+ const triggerId = `${inputId}-trigger`;
1618
+ const listboxId = `${inputId}-listbox`;
1619
+ const descriptionId = `${inputId}-description`;
1620
+ const [open, setOpen] = useState16(false);
1621
+ const rootRef = useDismissibleLayer(open, () => setOpen(false), { autoFocus: false });
1622
+ const nativeRef = useRef4(null);
1623
+ const [innerValue, setInnerValue] = useState16(() => String(defaultValue ?? (placeholder ? "" : options.find((option) => !option.disabled)?.value ?? "")));
1624
+ const selectedValue = value === void 0 ? innerValue : String(value);
1625
+ const selectedOption = options.find((option) => option.value === selectedValue);
1626
+ const enabledIndices = options.map((option, index) => option.disabled ? -1 : index).filter((index) => index >= 0);
1627
+ const selectedIndex = options.findIndex((option) => option.value === selectedValue);
1628
+ const [activeIndex, setActiveIndex] = useState16(selectedIndex >= 0 ? selectedIndex : enabledIndices[0] ?? -1);
1629
+ const assignRef = (node) => {
1630
+ nativeRef.current = node;
1631
+ if (typeof forwardedRef === "function") forwardedRef(node);
1632
+ else if (forwardedRef) forwardedRef.current = node;
1633
+ };
1634
+ const handleNativeChange = (event) => {
1635
+ if (value === void 0) setInnerValue(event.currentTarget.value);
1636
+ onChange?.(event);
1637
+ };
1638
+ const choose = (nextValue) => {
1639
+ const native = nativeRef.current;
1640
+ if (!native) return;
1641
+ Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype, "value")?.set?.call(native, nextValue);
1642
+ native.dispatchEvent(new Event("change", { bubbles: true }));
1643
+ if (value === void 0) setInnerValue(nextValue);
1644
+ setOpen(false);
1645
+ window.requestAnimationFrame(() => document.getElementById(triggerId)?.focus());
1646
+ };
1647
+ useEffect7(() => {
1648
+ if (selectedIndex >= 0) setActiveIndex(selectedIndex);
1649
+ }, [selectedIndex]);
1650
+ const move = (direction) => {
1651
+ if (!enabledIndices.length) return;
1652
+ const current = enabledIndices.indexOf(activeIndex);
1653
+ const next = current < 0 ? 0 : (current + direction + enabledIndices.length) % enabledIndices.length;
1654
+ setActiveIndex(enabledIndices[next]);
1655
+ };
1656
+ const handleKeyDown = (event) => {
1657
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1658
+ event.preventDefault();
1659
+ if (!open) setOpen(true);
1660
+ move(event.key === "ArrowDown" ? 1 : -1);
1661
+ } else if ((event.key === "Enter" || event.key === " ") && open) {
1662
+ event.preventDefault();
1663
+ const option = options[activeIndex];
1664
+ if (option && !option.disabled) choose(option.value);
1665
+ } else if (event.key === "Escape" && open) {
1666
+ event.preventDefault();
1667
+ setOpen(false);
1668
+ } else if (event.key === "Home" && open && enabledIndices.length) {
1669
+ event.preventDefault();
1670
+ setActiveIndex(enabledIndices[0]);
1671
+ } else if (event.key === "End" && open && enabledIndices.length) {
1672
+ event.preventDefault();
1673
+ setActiveIndex(enabledIndices[enabledIndices.length - 1]);
1674
+ } else if (event.key === "Tab") setOpen(false);
1675
+ };
1676
+ return /* @__PURE__ */ jsxs30("div", { className: `hf-field ${className}`.trim(), ref: rootRef, children: [
1677
+ label && /* @__PURE__ */ jsx36("label", { className: "hf-field__label", htmlFor: triggerId, children: label }),
1678
+ /* @__PURE__ */ jsxs30("div", { className: `hf-select-shell ${open ? "hf-select-shell--open" : ""} ${error ? "hf-select-shell--error" : ""}`, children: [
1679
+ /* @__PURE__ */ jsxs30("select", { ref: assignRef, id: inputId, className: "hf-select-native", tabIndex: -1, "aria-hidden": "true", value: selectedValue, disabled, onChange: handleNativeChange, ...props, children: [
1680
+ placeholder && /* @__PURE__ */ jsx36("option", { value: "", disabled: true, children: placeholder }),
1681
+ options.map((option) => /* @__PURE__ */ jsx36("option", { value: option.value, disabled: option.disabled, children: typeof option.label === "string" ? option.label : option.value }, option.value))
1682
+ ] }),
1683
+ /* @__PURE__ */ jsxs30("button", { id: triggerId, type: "button", className: "hf-select", disabled, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : void 0, "aria-activedescendant": open && activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : void 0, "aria-invalid": Boolean(error), "aria-describedby": hint || error ? descriptionId : void 0, onClick: () => {
1684
+ setActiveIndex(selectedIndex >= 0 ? selectedIndex : enabledIndices[0] ?? -1);
1685
+ setOpen((current) => !current);
1686
+ }, onKeyDown: handleKeyDown, children: [
1687
+ /* @__PURE__ */ jsx36("span", { className: !selectedOption ? "hf-select__placeholder" : "", children: selectedOption?.label ?? placeholder ?? "\u8BF7\u9009\u62E9" }),
1688
+ /* @__PURE__ */ jsx36("svg", { className: "hf-select__chevron", viewBox: "0 0 16 16", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx36("path", { d: open ? "m4.5 9.75 3.5-3.5 3.5 3.5" : "m4.5 6.25 3.5 3.5 3.5-3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
1689
+ ] }),
1690
+ open && /* @__PURE__ */ jsx36("div", { id: listboxId, className: "hf-select-menu", role: "listbox", "aria-labelledby": triggerId, children: options.map((option, index) => /* @__PURE__ */ jsxs30("button", { id: `${listboxId}-option-${index}`, type: "button", role: "option", "aria-selected": option.value === selectedValue, disabled: option.disabled, className: index === activeIndex ? "is-active" : "", onPointerMove: () => !option.disabled && setActiveIndex(index), onClick: () => choose(option.value), children: [
1691
+ /* @__PURE__ */ jsx36("span", { children: option.label }),
1692
+ option.value === selectedValue && /* @__PURE__ */ jsx36("svg", { viewBox: "0 0 16 16", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx36("path", { d: "m3.5 8 3 3 6-6", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) })
1693
+ ] }, option.value)) })
1694
+ ] }),
1695
+ (error || hint) && /* @__PURE__ */ jsx36("span", { id: descriptionId, className: `hf-field__hint ${error ? "hf-field__hint--error" : ""}`, children: error ?? hint })
1696
+ ] });
1697
+ });
1698
+
1699
+ // src/forms/MultiSelect.tsx
1700
+ import { useId as useId7, useState as useState17 } from "react";
1701
+ import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
1702
+ function MultiSelect({ label, options, value, onChange, placeholder = "\u8BF7\u9009\u62E9", max, hint, disabled }) {
1703
+ const [open, setOpen] = useState17(false);
1704
+ const rootRef = useDismissibleLayer(open, () => setOpen(false), { autoFocus: false });
1705
+ const listId = useId7();
1706
+ const toggle = (next) => {
1707
+ const selected = value.includes(next);
1708
+ if (!selected && max && value.length >= max) return;
1709
+ onChange(selected ? value.filter((item) => item !== next) : [...value, next]);
1710
+ };
1711
+ return /* @__PURE__ */ jsxs31("div", { className: "hf-field hf-multiselect", ref: rootRef, children: [
1712
+ label && /* @__PURE__ */ jsx37("span", { className: "hf-field__label", children: label }),
1713
+ /* @__PURE__ */ jsxs31("div", { className: "hf-multiselect__trigger", role: "combobox", tabIndex: disabled ? -1 : 0, "aria-disabled": disabled, "aria-expanded": open, "aria-controls": listId, onClick: () => !disabled && setOpen(!open), onKeyDown: (event) => {
1714
+ if (!disabled && (event.key === "Enter" || event.key === " ")) {
1715
+ event.preventDefault();
1716
+ setOpen(!open);
1717
+ }
1718
+ }, children: [
1719
+ /* @__PURE__ */ jsx37("span", { children: value.length ? value.map((item) => {
1720
+ const option = options.find((candidate) => candidate.value === item);
1721
+ return /* @__PURE__ */ jsxs31("i", { children: [
1722
+ option?.label,
1723
+ /* @__PURE__ */ jsx37("button", { type: "button", "aria-label": `\u79FB\u9664 ${String(option?.label)}`, onClick: (event) => {
1724
+ event.stopPropagation();
1725
+ toggle(item);
1726
+ }, children: "\xD7" })
1727
+ ] }, item);
1728
+ }) : /* @__PURE__ */ jsx37("em", { children: placeholder }) }),
1729
+ /* @__PURE__ */ jsx37(Icon, { name: "chevron-down", size: 16, className: "hf-multiselect__chevron" })
1730
+ ] }),
1731
+ open && /* @__PURE__ */ jsx37("div", { id: listId, className: "hf-multiselect__menu", role: "listbox", "aria-multiselectable": "true", children: options.map((option) => /* @__PURE__ */ jsxs31("button", { type: "button", role: "option", "aria-selected": value.includes(option.value), disabled: option.disabled, onClick: () => toggle(option.value), children: [
1732
+ /* @__PURE__ */ jsx37("span", { children: option.label }),
1733
+ /* @__PURE__ */ jsx37("i", { children: value.includes(option.value) ? "\u2713" : "" })
1734
+ ] }, option.value)) }),
1735
+ hint && /* @__PURE__ */ jsx37("span", { className: "hf-field__hint", children: hint })
1736
+ ] });
1737
+ }
1738
+
1739
+ // src/forms/ChoiceGroup.tsx
1740
+ import { useId as useId8 } from "react";
1741
+ import { jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
1742
+ function ChoiceGroup({ label, options, value, defaultValue, onChange, type = "radio", direction = "column", disabled, name }) {
1743
+ const id = useId8();
1744
+ const groupName = name ?? id;
1745
+ const values = Array.isArray(value) ? value : value ? [value] : void 0;
1746
+ const defaults = Array.isArray(defaultValue) ? defaultValue : defaultValue ? [defaultValue] : [];
1747
+ return /* @__PURE__ */ jsxs32("fieldset", { className: `hf-choice-group hf-choice-group--${direction}`, disabled, children: [
1748
+ label && /* @__PURE__ */ jsx38("legend", { children: label }),
1749
+ options.map((option) => {
1750
+ const checked = values?.includes(option.value);
1751
+ return /* @__PURE__ */ jsxs32("label", { className: "hf-choice", children: [
1752
+ /* @__PURE__ */ jsx38("input", { type, name: type === "radio" ? groupName : `${groupName}-${option.value}`, value: option.value, checked, defaultChecked: values ? void 0 : defaults.includes(option.value), disabled: option.disabled, onChange: (event) => {
1753
+ if (type === "radio") onChange?.(option.value);
1754
+ else {
1755
+ const next = new Set(values ?? defaults);
1756
+ event.currentTarget.checked ? next.add(option.value) : next.delete(option.value);
1757
+ onChange?.([...next]);
1758
+ }
1759
+ } }),
1760
+ /* @__PURE__ */ jsx38("span", { className: "hf-choice__control", "aria-hidden": "true" }),
1761
+ /* @__PURE__ */ jsxs32("span", { className: "hf-choice__copy", children: [
1762
+ /* @__PURE__ */ jsx38("strong", { children: option.label }),
1763
+ option.description && /* @__PURE__ */ jsx38("small", { children: option.description })
1764
+ ] })
1765
+ ] }, option.value);
1766
+ })
1767
+ ] });
1768
+ }
1769
+ function RadioGroup(props) {
1770
+ return /* @__PURE__ */ jsx38(ChoiceGroup, { ...props, type: "radio", onChange: (next) => props.onChange?.(next) });
1771
+ }
1772
+ function CheckboxGroup(props) {
1773
+ return /* @__PURE__ */ jsx38(ChoiceGroup, { ...props, type: "checkbox", onChange: (next) => props.onChange?.(next) });
1774
+ }
1775
+
1776
+ // src/forms/ValidatedInput.tsx
1777
+ import { useState as useState18 } from "react";
1778
+ import { jsx as jsx39 } from "react/jsx-runtime";
1779
+ function validateValue(value, rules) {
1780
+ return rules.find((rule) => !rule.validate(value))?.message;
1781
+ }
1782
+ function ValidatedInput({ value, rules, validateOn = "blur", onChange, onValidityChange, ...props }) {
1783
+ const [touched, setTouched] = useState18(false);
1784
+ const error = touched ? validateValue(value, rules) : void 0;
1785
+ const update = (next) => {
1786
+ onChange(next);
1787
+ if (validateOn === "change") setTouched(true);
1788
+ onValidityChange?.(!validateValue(next, rules));
1789
+ };
1790
+ return /* @__PURE__ */ jsx39(Input, { ...props, value, error, onChange: (event) => update(event.target.value), onBlur: () => setTouched(true) });
1791
+ }
1792
+ function validateForm(event) {
1793
+ if (!event.currentTarget.checkValidity()) {
1794
+ event.preventDefault();
1795
+ event.currentTarget.reportValidity();
1796
+ return false;
1797
+ }
1798
+ return true;
1799
+ }
1800
+
1801
+ // src/forms/Textarea.tsx
1802
+ import { forwardRef as forwardRef6, useId as useId9 } from "react";
1803
+ import { jsx as jsx40, jsxs as jsxs33 } from "react/jsx-runtime";
1804
+ var Textarea = forwardRef6(function Textarea2({ label, hint, error, resize = "vertical", id, className = "", ...props }, ref) {
1805
+ const generated = useId9();
1806
+ const fieldId = id ?? generated;
1807
+ const message = error ?? hint;
1808
+ const messageId = message ? `${fieldId}-message` : void 0;
1809
+ return /* @__PURE__ */ jsxs33("label", { className: "hf-field", htmlFor: fieldId, children: [
1810
+ label && /* @__PURE__ */ jsx40("span", { className: "hf-field__label", children: label }),
1811
+ /* @__PURE__ */ jsx40("textarea", { ref, id: fieldId, className: `hf-textarea hf-textarea--${resize}${error ? " hf-textarea--error" : ""} ${className}`, "aria-invalid": error ? true : void 0, "aria-describedby": messageId, ...props }),
1812
+ message && /* @__PURE__ */ jsx40("span", { id: messageId, className: `hf-field__hint${error ? " hf-field__hint--error" : ""}`, children: message })
1813
+ ] });
1814
+ });
1815
+
1816
+ // src/forms/Choice.tsx
1817
+ import { forwardRef as forwardRef7, useEffect as useEffect8, useRef as useRef5 } from "react";
1818
+ import { jsx as jsx41, jsxs as jsxs34 } from "react/jsx-runtime";
1819
+ var Checkbox = forwardRef7(function Checkbox2({ label, description, indeterminate, className = "", ...props }, forwardedRef) {
1820
+ const local = useRef5(null);
1821
+ useEffect8(() => {
1822
+ if (local.current) local.current.indeterminate = Boolean(indeterminate);
1823
+ }, [indeterminate]);
1824
+ const setRef = (node) => {
1825
+ local.current = node;
1826
+ if (typeof forwardedRef === "function") forwardedRef(node);
1827
+ else if (forwardedRef) forwardedRef.current = node;
1828
+ };
1829
+ return /* @__PURE__ */ jsxs34("label", { className: `hf-choice-control ${className}`, children: [
1830
+ /* @__PURE__ */ jsx41("input", { ref: setRef, type: "checkbox", ...props }),
1831
+ /* @__PURE__ */ jsx41("span", { className: "hf-choice-control__mark", children: /* @__PURE__ */ jsx41(IconCheck, {}) }),
1832
+ /* @__PURE__ */ jsxs34("span", { children: [
1833
+ /* @__PURE__ */ jsx41("strong", { children: label }),
1834
+ description && /* @__PURE__ */ jsx41("small", { children: description })
1835
+ ] })
1836
+ ] });
1837
+ });
1838
+ var Radio = forwardRef7(function Radio2({ label, description, className = "", ...props }, ref) {
1839
+ return /* @__PURE__ */ jsxs34("label", { className: `hf-choice-control hf-choice-control--radio ${className}`, children: [
1840
+ /* @__PURE__ */ jsx41("input", { ref, type: "radio", ...props }),
1841
+ /* @__PURE__ */ jsx41("span", { className: "hf-choice-control__mark", children: /* @__PURE__ */ jsx41("i", {}) }),
1842
+ /* @__PURE__ */ jsxs34("span", { children: [
1843
+ /* @__PURE__ */ jsx41("strong", { children: label }),
1844
+ description && /* @__PURE__ */ jsx41("small", { children: description })
1845
+ ] })
1846
+ ] });
1847
+ });
1848
+ function IconCheck() {
1849
+ return /* @__PURE__ */ jsx41("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx41("path", { d: "m3.5 8 3 3 6-6" }) });
1850
+ }
1851
+
1852
+ // src/forms/Advanced.tsx
1853
+ import {
1854
+ useState as useState19
1855
+ } from "react";
1856
+ import { jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
1857
+ var iso = (date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
1858
+ function Calendar({ value, onChange, min, max, className = "" }) {
1859
+ const initial = value ? /* @__PURE__ */ new Date(`${value}T00:00:00`) : /* @__PURE__ */ new Date();
1860
+ const [view, setView] = useState19(new Date(initial.getFullYear(), initial.getMonth(), 1));
1861
+ const first = view.getDay();
1862
+ const days = new Date(view.getFullYear(), view.getMonth() + 1, 0).getDate();
1863
+ const cells = Array.from(
1864
+ { length: Math.ceil((first + days) / 7) * 7 },
1865
+ (_, index) => index - first + 1
1866
+ );
1867
+ return /* @__PURE__ */ jsxs35("div", { className: `hf-calendar ${className}`, children: [
1868
+ /* @__PURE__ */ jsxs35("header", { children: [
1869
+ /* @__PURE__ */ jsx42(
1870
+ "button",
1871
+ {
1872
+ type: "button",
1873
+ "aria-label": "\u4E0A\u4E2A\u6708",
1874
+ onClick: () => setView(new Date(view.getFullYear(), view.getMonth() - 1, 1)),
1875
+ children: /* @__PURE__ */ jsx42(Icon, { name: "chevron-down", className: "hf-calendar__prev" })
1876
+ }
1877
+ ),
1878
+ /* @__PURE__ */ jsxs35("strong", { children: [
1879
+ view.getFullYear(),
1880
+ " \u5E74 ",
1881
+ view.getMonth() + 1,
1882
+ " \u6708"
1883
+ ] }),
1884
+ /* @__PURE__ */ jsx42(
1885
+ "button",
1886
+ {
1887
+ type: "button",
1888
+ "aria-label": "\u4E0B\u4E2A\u6708",
1889
+ onClick: () => setView(new Date(view.getFullYear(), view.getMonth() + 1, 1)),
1890
+ children: /* @__PURE__ */ jsx42(Icon, { name: "chevron-down", className: "hf-calendar__next" })
1891
+ }
1892
+ )
1893
+ ] }),
1894
+ /* @__PURE__ */ jsx42("div", { className: "hf-calendar__week", children: "\u65E5\u4E00\u4E8C\u4E09\u56DB\u4E94\u516D".split("").map((day2) => /* @__PURE__ */ jsx42("span", { children: day2 }, day2)) }),
1895
+ /* @__PURE__ */ jsx42("div", { className: "hf-calendar__days", children: cells.map((day2, index) => {
1896
+ if (day2 < 1 || day2 > days) return /* @__PURE__ */ jsx42("span", {}, index);
1897
+ const date = iso(new Date(view.getFullYear(), view.getMonth(), day2));
1898
+ const disabled = Boolean(min && date < min || max && date > max);
1899
+ const stateClass = date === value ? "is-selected" : date === iso(/* @__PURE__ */ new Date()) ? "is-today" : "";
1900
+ return /* @__PURE__ */ jsx42(
1901
+ "button",
1902
+ {
1903
+ type: "button",
1904
+ disabled,
1905
+ className: stateClass,
1906
+ "aria-pressed": date === value,
1907
+ onClick: () => onChange?.(date),
1908
+ children: day2
1909
+ },
1910
+ date
1911
+ );
1912
+ }) })
1913
+ ] });
1914
+ }
1915
+ function DatePicker({
1916
+ label,
1917
+ value,
1918
+ onChange,
1919
+ placeholder = "\u9009\u62E9\u65E5\u671F",
1920
+ min,
1921
+ max,
1922
+ error
1923
+ }) {
1924
+ const [open, setOpen] = useState19(false);
1925
+ const rootRef = useDismissibleLayer(open, () => setOpen(false), {
1926
+ autoFocus: false
1927
+ });
1928
+ return /* @__PURE__ */ jsxs35("div", { ref: rootRef, className: "hf-field hf-date-picker", children: [
1929
+ label && /* @__PURE__ */ jsx42("span", { className: "hf-field__label", children: label }),
1930
+ /* @__PURE__ */ jsxs35(
1931
+ "button",
1932
+ {
1933
+ type: "button",
1934
+ className: `hf-picker-trigger${error ? " is-error" : ""}`,
1935
+ "aria-expanded": open,
1936
+ onClick: () => setOpen(!open),
1937
+ children: [
1938
+ /* @__PURE__ */ jsx42("span", { className: value ? "" : "is-placeholder", children: value || placeholder }),
1939
+ /* @__PURE__ */ jsx42(Icon, { name: "chevron-down", size: 16 })
1940
+ ]
1941
+ }
1942
+ ),
1943
+ open && /* @__PURE__ */ jsx42("div", { className: "hf-date-picker__panel", children: /* @__PURE__ */ jsx42(
1944
+ Calendar,
1945
+ {
1946
+ value,
1947
+ min,
1948
+ max,
1949
+ onChange: (next) => {
1950
+ onChange(next);
1951
+ setOpen(false);
1952
+ }
1953
+ }
1954
+ ) }),
1955
+ error && /* @__PURE__ */ jsx42("span", { className: "hf-field__hint hf-field__hint--error", children: error })
1956
+ ] });
1957
+ }
1958
+ function TimePicker({ label, value, onChange, step = 30 }) {
1959
+ const [open, setOpen] = useState19(false);
1960
+ const rootRef = useDismissibleLayer(open, () => setOpen(false), {
1961
+ autoFocus: false
1962
+ });
1963
+ const times = Array.from({ length: Math.ceil(1440 / step) }, (_, index) => {
1964
+ const minutes = index * step;
1965
+ return `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
1966
+ });
1967
+ return /* @__PURE__ */ jsxs35("div", { ref: rootRef, className: "hf-field hf-time-picker", children: [
1968
+ label && /* @__PURE__ */ jsx42("span", { className: "hf-field__label", children: label }),
1969
+ /* @__PURE__ */ jsxs35(
1970
+ "button",
1971
+ {
1972
+ type: "button",
1973
+ className: "hf-picker-trigger",
1974
+ "aria-expanded": open,
1975
+ onClick: () => setOpen(!open),
1976
+ children: [
1977
+ /* @__PURE__ */ jsx42("span", { className: value ? "" : "is-placeholder", children: value || "\u9009\u62E9\u65F6\u95F4" }),
1978
+ /* @__PURE__ */ jsx42(Icon, { name: "chevron-down", size: 16 })
1979
+ ]
1980
+ }
1981
+ ),
1982
+ open && /* @__PURE__ */ jsx42("div", { className: "hf-time-picker__panel", role: "listbox", children: times.map((time) => /* @__PURE__ */ jsx42(
1983
+ "button",
1984
+ {
1985
+ type: "button",
1986
+ role: "option",
1987
+ "aria-selected": time === value,
1988
+ onClick: () => {
1989
+ onChange(time);
1990
+ setOpen(false);
1991
+ },
1992
+ children: time
1993
+ },
1994
+ time
1995
+ )) })
1996
+ ] });
1997
+ }
1998
+ function Slider({
1999
+ label,
2000
+ value,
2001
+ min = 0,
2002
+ max = 100,
2003
+ step = 1,
2004
+ onChange,
2005
+ showValue = true,
2006
+ ...props
2007
+ }) {
2008
+ const percent = (value - Number(min)) / (Number(max) - Number(min)) * 100;
2009
+ return /* @__PURE__ */ jsxs35("label", { className: "hf-slider", children: [
2010
+ /* @__PURE__ */ jsxs35("span", { children: [
2011
+ label,
2012
+ showValue && /* @__PURE__ */ jsx42("strong", { children: value })
2013
+ ] }),
2014
+ /* @__PURE__ */ jsx42(
2015
+ "input",
2016
+ {
2017
+ type: "range",
2018
+ value,
2019
+ min,
2020
+ max,
2021
+ step,
2022
+ style: { "--hf-slider-value": `${percent}%` },
2023
+ onChange: (event) => onChange(Number(event.target.value)),
2024
+ ...props
2025
+ }
2026
+ )
2027
+ ] });
2028
+ }
2029
+
2030
+ // src/forms/Form.tsx
2031
+ import {
2032
+ createContext,
2033
+ useContext
2034
+ } from "react";
2035
+ import { jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
2036
+ var FormContext = createContext({});
2037
+ function Form({
2038
+ layout = "vertical",
2039
+ disabled,
2040
+ className = "",
2041
+ children,
2042
+ ...props
2043
+ }) {
2044
+ return /* @__PURE__ */ jsx43(FormContext.Provider, { value: { disabled }, children: /* @__PURE__ */ jsx43(
2045
+ "form",
2046
+ {
2047
+ className: `hf-form hf-form--${layout} ${className}`.trim(),
2048
+ "aria-disabled": disabled || void 0,
2049
+ ...props,
2050
+ children: /* @__PURE__ */ jsx43("fieldset", { className: "hf-form__fieldset", disabled, children })
2051
+ }
2052
+ ) });
2053
+ }
2054
+ function FormItem({
2055
+ label,
2056
+ required,
2057
+ hint,
2058
+ error,
2059
+ children,
2060
+ className = "",
2061
+ ...props
2062
+ }) {
2063
+ const { disabled } = useContext(FormContext);
2064
+ return /* @__PURE__ */ jsxs36(
2065
+ "div",
2066
+ {
2067
+ className: `hf-form-item${error ? " is-error" : ""} ${className}`.trim(),
2068
+ "aria-disabled": disabled || void 0,
2069
+ ...props,
2070
+ children: [
2071
+ label && /* @__PURE__ */ jsxs36("div", { className: "hf-form-item__label", children: [
2072
+ label,
2073
+ required && /* @__PURE__ */ jsx43("span", { "aria-hidden": "true", children: "*" })
2074
+ ] }),
2075
+ /* @__PURE__ */ jsxs36("div", { children: [
2076
+ children,
2077
+ (error || hint) && /* @__PURE__ */ jsx43("small", { className: error ? "is-error" : "", children: error || hint })
2078
+ ] })
2079
+ ]
2080
+ }
2081
+ );
2082
+ }
2083
+
2084
+ // src/forms/Upload.tsx
2085
+ import {
2086
+ useId as useId10,
2087
+ useRef as useRef6,
2088
+ useState as useState20
2089
+ } from "react";
2090
+ import { jsx as jsx44, jsxs as jsxs37 } from "react/jsx-runtime";
2091
+ function formatFileSize(bytes) {
2092
+ if (bytes >= 1024 * 1024) {
2093
+ const megabytes = bytes / (1024 * 1024);
2094
+ return `${Number.isInteger(megabytes) ? megabytes : megabytes.toFixed(1)} MB`;
2095
+ }
2096
+ if (bytes >= 1024) return `${Math.ceil(bytes / 1024)} KB`;
2097
+ return `${bytes} B`;
2098
+ }
2099
+ function acceptsFile(file, accept) {
2100
+ if (!accept?.trim()) return true;
2101
+ const fileName = file.name.toLowerCase();
2102
+ const mimeType = file.type.toLowerCase();
2103
+ return accept.split(",").map((value) => value.trim().toLowerCase()).filter(Boolean).some((rule) => {
2104
+ if (rule.startsWith(".")) return fileName.endsWith(rule);
2105
+ if (rule.endsWith("/*")) return mimeType.startsWith(rule.slice(0, -1));
2106
+ return mimeType === rule;
2107
+ });
2108
+ }
2109
+ function validateUploadFiles(files, options = {}) {
2110
+ const accepted = [];
2111
+ const rejected = [];
2112
+ const limit = options.maxFiles ?? Number.POSITIVE_INFINITY;
2113
+ files.forEach((file) => {
2114
+ if (!acceptsFile(file, options.accept)) {
2115
+ rejected.push({ file, reason: "file-type-not-accepted", message: "\u4E0D\u652F\u6301\u8BE5\u6587\u4EF6\u7C7B\u578B" });
2116
+ return;
2117
+ }
2118
+ if (options.maxSize !== void 0 && file.size > options.maxSize) {
2119
+ rejected.push({
2120
+ file,
2121
+ reason: "file-too-large",
2122
+ message: `\u6587\u4EF6\u4E0D\u80FD\u8D85\u8FC7 ${formatFileSize(options.maxSize)}`
2123
+ });
2124
+ return;
2125
+ }
2126
+ if (accepted.length >= limit) {
2127
+ rejected.push({
2128
+ file,
2129
+ reason: "too-many-files",
2130
+ message: `\u6700\u591A\u53EA\u80FD\u9009\u62E9 ${limit} \u4E2A\u6587\u4EF6`
2131
+ });
2132
+ return;
2133
+ }
2134
+ accepted.push(file);
2135
+ });
2136
+ return { accepted, rejected };
2137
+ }
2138
+ function Upload({
2139
+ label = "\u4E0A\u4F20\u6587\u4EF6",
2140
+ accept,
2141
+ multiple,
2142
+ maxFiles,
2143
+ maxSize,
2144
+ onFiles,
2145
+ onReject,
2146
+ hint,
2147
+ disabled
2148
+ }) {
2149
+ const id = useId10();
2150
+ const ref = useRef6(null);
2151
+ const [dragging, setDragging] = useState20(false);
2152
+ const [rejections, setRejections] = useState20([]);
2153
+ const takeFiles = (list) => {
2154
+ const result = validateUploadFiles(Array.from(list ?? []), {
2155
+ accept,
2156
+ maxFiles,
2157
+ maxSize
2158
+ });
2159
+ setRejections(result.rejected);
2160
+ onFiles(result.accepted);
2161
+ if (result.rejected.length) onReject?.(result.rejected);
2162
+ };
2163
+ return /* @__PURE__ */ jsxs37("div", { className: "hf-upload", children: [
2164
+ /* @__PURE__ */ jsx44(
2165
+ "input",
2166
+ {
2167
+ ref,
2168
+ id,
2169
+ type: "file",
2170
+ accept,
2171
+ multiple,
2172
+ disabled,
2173
+ onChange: (event) => takeFiles(event.target.files)
2174
+ }
2175
+ ),
2176
+ /* @__PURE__ */ jsxs37(
2177
+ "button",
2178
+ {
2179
+ type: "button",
2180
+ disabled,
2181
+ className: dragging ? "is-dragging" : "",
2182
+ onClick: () => ref.current?.click(),
2183
+ onDragOver: (event) => {
2184
+ event.preventDefault();
2185
+ if (!disabled) setDragging(true);
2186
+ },
2187
+ onDragLeave: () => setDragging(false),
2188
+ onDrop: (event) => {
2189
+ event.preventDefault();
2190
+ setDragging(false);
2191
+ if (!disabled) takeFiles(event.dataTransfer.files);
2192
+ },
2193
+ children: [
2194
+ /* @__PURE__ */ jsx44(Icon, { name: "inbox", size: 24 }),
2195
+ /* @__PURE__ */ jsx44("strong", { children: label }),
2196
+ /* @__PURE__ */ jsx44("span", { children: "\u62D6\u653E\u5230\u8FD9\u91CC\uFF0C\u6216\u70B9\u51FB\u9009\u62E9" })
2197
+ ]
2198
+ }
2199
+ ),
2200
+ rejections.length > 0 && /* @__PURE__ */ jsx44("div", { className: "hf-upload__errors", role: "alert", children: rejections.map(({ file, reason, message }, index) => /* @__PURE__ */ jsxs37("span", { children: [
2201
+ file.name,
2202
+ "\uFF1A",
2203
+ message
2204
+ ] }, `${file.name}-${reason}-${index}`)) }),
2205
+ hint && /* @__PURE__ */ jsx44("small", { children: hint })
2206
+ ] });
2207
+ }
2208
+
2209
+ // src/forms/Combobox.tsx
2210
+ import { useId as useId11, useMemo as useMemo5, useState as useState21 } from "react";
2211
+ import { jsx as jsx45, jsxs as jsxs38 } from "react/jsx-runtime";
2212
+ function Combobox({ label, options, value = "", onChange, placeholder = "\u641C\u7D22\u6216\u9009\u62E9", hint, error, disabled, emptyText = "\u6CA1\u6709\u5339\u914D\u9879" }) {
2213
+ const id = useId11();
2214
+ const [open, setOpen] = useState21(false);
2215
+ const root = useDismissibleLayer(open, () => setOpen(false), { autoFocus: false });
2216
+ const [query, setQuery] = useState21("");
2217
+ const [active, setActive] = useState21(0);
2218
+ const selected = options.find((item) => item.value === value);
2219
+ const filtered = useMemo5(() => options.filter((item) => `${typeof item.label === "string" ? item.label : item.value} ${item.keywords ?? ""}`.toLowerCase().includes(query.toLowerCase())), [options, query]);
2220
+ const choose = (next) => {
2221
+ onChange(next);
2222
+ setQuery("");
2223
+ setOpen(false);
2224
+ };
2225
+ const onKeyDown = (event) => {
2226
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2227
+ event.preventDefault();
2228
+ setOpen(true);
2229
+ setActive((current) => Math.max(0, Math.min(filtered.length - 1, current + (event.key === "ArrowDown" ? 1 : -1))));
2230
+ } else if (event.key === "Enter" && open) {
2231
+ event.preventDefault();
2232
+ const option = filtered[active];
2233
+ if (option && !option.disabled) choose(option.value);
2234
+ } else if (event.key === "Escape") setOpen(false);
2235
+ };
2236
+ return /* @__PURE__ */ jsxs38("div", { className: "hf-field hf-combobox", ref: root, children: [
2237
+ label && /* @__PURE__ */ jsx45("label", { className: "hf-field__label", htmlFor: id, children: label }),
2238
+ /* @__PURE__ */ jsxs38("div", { className: `hf-combobox__control${open ? " is-open" : ""}${error ? " is-error" : ""}`, children: [
2239
+ /* @__PURE__ */ jsx45("input", { id, role: "combobox", "aria-expanded": open, "aria-controls": `${id}-listbox`, "aria-autocomplete": "list", "aria-invalid": Boolean(error), disabled, placeholder: selected && !open ? String(selected.label) : placeholder, value: open ? query : selected ? String(selected.label) : "", onFocus: () => setOpen(true), onChange: (event) => {
2240
+ setQuery(event.target.value);
2241
+ setActive(0);
2242
+ setOpen(true);
2243
+ }, onKeyDown }),
2244
+ /* @__PURE__ */ jsx45("button", { type: "button", "aria-label": open ? "\u5173\u95ED\u9009\u9879" : "\u6253\u5F00\u9009\u9879", disabled, onClick: () => setOpen((current) => !current), children: "\u2304" })
2245
+ ] }),
2246
+ open && /* @__PURE__ */ jsx45("div", { id: `${id}-listbox`, className: "hf-combobox__menu", role: "listbox", children: filtered.length ? filtered.map((option, index) => /* @__PURE__ */ jsxs38("button", { type: "button", role: "option", "aria-selected": option.value === value, disabled: option.disabled, className: index === active ? "is-active" : "", onPointerMove: () => setActive(index), onClick: () => choose(option.value), children: [
2247
+ /* @__PURE__ */ jsx45("span", { children: option.label }),
2248
+ option.value === value && /* @__PURE__ */ jsx45("span", { "aria-hidden": "true", children: "\u2713" })
2249
+ ] }, option.value)) : /* @__PURE__ */ jsx45("div", { className: "hf-combobox__empty", children: emptyText }) }),
2250
+ (error || hint) && /* @__PURE__ */ jsx45("span", { className: `hf-field__hint${error ? " hf-field__hint--error" : ""}`, children: error ?? hint })
2251
+ ] });
2252
+ }
2253
+
2254
+ // src/forms/NumberInput.tsx
2255
+ import { useId as useId12 } from "react";
2256
+ import { jsx as jsx46, jsxs as jsxs39 } from "react/jsx-runtime";
2257
+ function NumberInput({ label, value, onChange, min, max, step = 1, prefix, suffix, hint, error, disabled }) {
2258
+ const id = useId12();
2259
+ const clamp = (next) => Math.min(max ?? Infinity, Math.max(min ?? -Infinity, next));
2260
+ return /* @__PURE__ */ jsxs39("div", { className: "hf-field hf-number-input", children: [
2261
+ label && /* @__PURE__ */ jsx46("label", { className: "hf-field__label", htmlFor: id, children: label }),
2262
+ /* @__PURE__ */ jsxs39("div", { className: `hf-number-input__control${error ? " is-error" : ""}`, children: [
2263
+ prefix && /* @__PURE__ */ jsx46("span", { children: prefix }),
2264
+ /* @__PURE__ */ jsx46("input", { id, type: "number", value, min, max, step, disabled, "aria-invalid": Boolean(error), onChange: (event) => {
2265
+ const next = event.currentTarget.valueAsNumber;
2266
+ if (!Number.isNaN(next)) onChange(clamp(next));
2267
+ } }),
2268
+ /* @__PURE__ */ jsxs39("div", { children: [
2269
+ /* @__PURE__ */ jsx46("button", { type: "button", disabled: disabled || max !== void 0 && value >= max, "aria-label": "\u589E\u52A0", onClick: () => onChange(clamp(value + step)), children: "\uFF0B" }),
2270
+ /* @__PURE__ */ jsx46("button", { type: "button", disabled: disabled || min !== void 0 && value <= min, "aria-label": "\u51CF\u5C11", onClick: () => onChange(clamp(value - step)), children: "\u2212" })
2271
+ ] }),
2272
+ suffix && /* @__PURE__ */ jsx46("span", { children: suffix })
2273
+ ] }),
2274
+ (error || hint) && /* @__PURE__ */ jsx46("span", { className: `hf-field__hint${error ? " hf-field__hint--error" : ""}`, children: error ?? hint })
2275
+ ] });
2276
+ }
2277
+
2278
+ // src/forms/NextBatch.tsx
2279
+ import { useState as useState22 } from "react";
2280
+ import { jsx as jsx47, jsxs as jsxs40 } from "react/jsx-runtime";
2281
+ function Cascader({ options, value = [], onChange, label }) {
2282
+ const levels = [options];
2283
+ let current = options;
2284
+ for (const key of value) {
2285
+ const next = current.find((item) => item.value === key)?.children;
2286
+ if (!next) break;
2287
+ levels.push(next);
2288
+ current = next;
2289
+ }
2290
+ return /* @__PURE__ */ jsxs40("div", { className: "hf-field hf-cascader", children: [
2291
+ label && /* @__PURE__ */ jsx47("span", { className: "hf-field__label", children: label }),
2292
+ /* @__PURE__ */ jsx47("div", { children: levels.map((items, level) => /* @__PURE__ */ jsxs40("select", { "aria-label": `\u7B2C ${level + 1} \u7EA7`, value: value[level] ?? "", onChange: (event) => onChange([...value.slice(0, level), event.target.value]), children: [
2293
+ /* @__PURE__ */ jsx47("option", { value: "", children: "\u8BF7\u9009\u62E9" }),
2294
+ items.map((item) => /* @__PURE__ */ jsx47("option", { disabled: item.disabled, value: item.value, children: item.label }, item.value))
2295
+ ] }, level)) })
2296
+ ] });
2297
+ }
2298
+ function TreeSelect({ options, value, onChange, label, placeholder = "\u9009\u62E9\u8282\u70B9" }) {
2299
+ const [open, setOpen] = useState22(false);
2300
+ const flatten = (nodes, depth = 0) => nodes.flatMap((node) => [{ node, depth }, ...flatten(node.children ?? [], depth + 1)]);
2301
+ const all = flatten(options);
2302
+ return /* @__PURE__ */ jsxs40("div", { className: "hf-field hf-tree-select", children: [
2303
+ label && /* @__PURE__ */ jsx47("span", { className: "hf-field__label", children: label }),
2304
+ /* @__PURE__ */ jsxs40("button", { type: "button", className: "hf-picker-trigger", "aria-expanded": open, onClick: () => setOpen(!open), children: [
2305
+ all.find((item) => item.node.key === value)?.node.label ?? placeholder,
2306
+ /* @__PURE__ */ jsx47("span", { children: "\u2304" })
2307
+ ] }),
2308
+ open && /* @__PURE__ */ jsx47("div", { role: "listbox", children: all.map(({ node, depth }) => /* @__PURE__ */ jsx47("button", { type: "button", role: "option", "aria-selected": node.key === value, disabled: node.disabled, style: { paddingLeft: 12 + depth * 18 }, onClick: () => {
2309
+ onChange(node.key);
2310
+ setOpen(false);
2311
+ }, children: node.label }, node.key)) })
2312
+ ] });
2313
+ }
2314
+ function Transfer({ items, value, onChange, titles = ["\u53EF\u9009\u9879", "\u5DF2\u9009\u62E9"] }) {
2315
+ const [marked, setMarked] = useState22([]);
2316
+ const pane = (selected) => /* @__PURE__ */ jsxs40("section", { children: [
2317
+ /* @__PURE__ */ jsx47("strong", { children: titles[selected ? 1 : 0] }),
2318
+ items.filter((item) => value.includes(item.key) === selected).map((item) => /* @__PURE__ */ jsxs40("label", { children: [
2319
+ /* @__PURE__ */ jsx47("input", { type: "checkbox", disabled: item.disabled, checked: marked.includes(item.key), onChange: () => setMarked((keys) => keys.includes(item.key) ? keys.filter((key) => key !== item.key) : [...keys, item.key]) }),
2320
+ item.label
2321
+ ] }, item.key))
2322
+ ] });
2323
+ return /* @__PURE__ */ jsxs40("div", { className: "hf-transfer", children: [
2324
+ pane(false),
2325
+ /* @__PURE__ */ jsxs40("div", { children: [
2326
+ /* @__PURE__ */ jsx47("button", { type: "button", "aria-label": "\u79FB\u81F3\u5DF2\u9009\u62E9", onClick: () => {
2327
+ onChange([.../* @__PURE__ */ new Set([...value, ...marked])]);
2328
+ setMarked([]);
2329
+ }, children: "\u2192" }),
2330
+ /* @__PURE__ */ jsx47("button", { type: "button", "aria-label": "\u79FB\u56DE\u53EF\u9009\u9879", onClick: () => {
2331
+ onChange(value.filter((key) => !marked.includes(key)));
2332
+ setMarked([]);
2333
+ }, children: "\u2190" })
2334
+ ] }),
2335
+ pane(true)
2336
+ ] });
2337
+ }
2338
+ function DateRangePicker({ label, value, onChange, min, max }) {
2339
+ return /* @__PURE__ */ jsxs40("div", { className: "hf-field hf-date-range", children: [
2340
+ label && /* @__PURE__ */ jsx47("span", { className: "hf-field__label", children: label }),
2341
+ /* @__PURE__ */ jsxs40("div", { children: [
2342
+ /* @__PURE__ */ jsx47("input", { "aria-label": "\u5F00\u59CB\u65E5\u671F", type: "date", value: value[0], min, max: value[1] || max, onChange: (event) => onChange([event.target.value, value[1]]) }),
2343
+ /* @__PURE__ */ jsx47("span", { children: "\u81F3" }),
2344
+ /* @__PURE__ */ jsx47("input", { "aria-label": "\u7ED3\u675F\u65E5\u671F", type: "date", value: value[1], min: value[0] || min, max, onChange: (event) => onChange([value[0], event.target.value]) })
2345
+ ] })
2346
+ ] });
2347
+ }
2348
+ function SearchInput({ onSearch, loading, clearable = true, ...props }) {
2349
+ const [value, setValue] = useState22(String(props.defaultValue ?? props.value ?? ""));
2350
+ return /* @__PURE__ */ jsxs40("form", { className: "hf-search-input", role: "search", onSubmit: (event) => {
2351
+ event.preventDefault();
2352
+ onSearch(value);
2353
+ }, children: [
2354
+ /* @__PURE__ */ jsx47("span", { "aria-hidden": "true", children: "\u2315" }),
2355
+ /* @__PURE__ */ jsx47("input", { ...props, value, onChange: (event) => {
2356
+ setValue(event.target.value);
2357
+ props.onChange?.(event);
2358
+ } }),
2359
+ clearable && value && /* @__PURE__ */ jsx47("button", { type: "button", "aria-label": "\u6E05\u9664\u641C\u7D22", onClick: () => setValue(""), children: "\xD7" }),
2360
+ /* @__PURE__ */ jsx47("button", { type: "submit", disabled: loading, children: loading ? "\u641C\u7D22\u4E2D" : "\u641C\u7D22" })
2361
+ ] });
2362
+ }
2363
+
2364
+ // src/feedback/Drawer.tsx
2365
+ import { useId as useId13 } from "react";
2366
+ import { createPortal as createPortal4 } from "react-dom";
2367
+ import { jsx as jsx48, jsxs as jsxs41 } from "react/jsx-runtime";
2368
+ function Drawer({ open, title, children, onClose, footer, side = "right", size = "md" }) {
2369
+ const titleId = useId13();
2370
+ const drawerRef = useDismissibleLayer(open, onClose, true);
2371
+ if (!open) return null;
2372
+ return createPortal4(/* @__PURE__ */ jsx48("div", { className: "hf-drawer-backdrop", onMouseDown: (event) => event.target === event.currentTarget && onClose(), children: /* @__PURE__ */ jsxs41("div", { ref: drawerRef, className: `hf-drawer hf-drawer--${side} hf-drawer--${size}`, role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, tabIndex: -1, children: [
2373
+ /* @__PURE__ */ jsxs41("header", { children: [
2374
+ /* @__PURE__ */ jsx48("h2", { id: titleId, children: title }),
2375
+ /* @__PURE__ */ jsx48(Button, { variant: "quiet", size: "sm", onClick: onClose, "aria-label": "\u5173\u95ED\u62BD\u5C49", children: "\xD7" })
2376
+ ] }),
2377
+ /* @__PURE__ */ jsx48("div", { className: "hf-drawer__body", children }),
2378
+ footer && /* @__PURE__ */ jsx48("footer", { children: footer })
2379
+ ] }) }), document.body);
2380
+ }
2381
+
2382
+ // src/feedback/Popover.tsx
2383
+ import { cloneElement as cloneElement2, isValidElement, useId as useId14, useState as useState23 } from "react";
2384
+ import { jsx as jsx49, jsxs as jsxs42 } from "react/jsx-runtime";
2385
+ function Popover({ trigger, children, open, defaultOpen = false, onOpenChange, placement = "bottom", label = "\u66F4\u591A\u5185\u5BB9" }) {
2386
+ const [innerOpen, setInnerOpen] = useState23(defaultOpen);
2387
+ const controlled = open !== void 0;
2388
+ const visible = controlled ? open : innerOpen;
2389
+ const contentId = useId14();
2390
+ const update = (next) => {
2391
+ if (!controlled) setInnerOpen(next);
2392
+ onOpenChange?.(next);
2393
+ };
2394
+ const rootRef = useDismissibleLayer(visible, () => update(false));
2395
+ const triggerProps = { "aria-expanded": visible, "aria-controls": visible ? contentId : void 0, "aria-haspopup": "dialog", onClick: () => update(!visible) };
2396
+ return /* @__PURE__ */ jsxs42("span", { className: "hf-popover", ref: rootRef, children: [
2397
+ isValidElement(trigger) && cloneElement2(trigger, triggerProps),
2398
+ visible && /* @__PURE__ */ jsx49("span", { id: contentId, role: "dialog", "aria-label": label, className: `hf-popover__content hf-popover__content--${placement}`, children })
2399
+ ] });
2400
+ }
2401
+
2402
+ // src/feedback/Status.tsx
2403
+ import { cloneElement as cloneElement3, useId as useId15, useState as useState24 } from "react";
2404
+ import { jsx as jsx50, jsxs as jsxs43 } from "react/jsx-runtime";
2405
+ function Tooltip({ content, children, placement = "top" }) {
2406
+ const [open, setOpen] = useState24(false);
2407
+ const id = useId15();
2408
+ const trigger = cloneElement3(children, { "aria-describedby": open ? id : void 0 });
2409
+ return /* @__PURE__ */ jsxs43("span", { className: "hf-tooltip", onMouseEnter: () => setOpen(true), onMouseLeave: () => setOpen(false), onFocus: () => setOpen(true), onBlur: () => setOpen(false), children: [
2410
+ trigger,
2411
+ open && /* @__PURE__ */ jsx50("span", { id, role: "tooltip", className: `hf-tooltip__bubble hf-tooltip__bubble--${placement}`, children: content })
2412
+ ] });
2413
+ }
2414
+ function Alert({ tone = "info", title, children, onClose, action }) {
2415
+ const icon = { info: "info", success: "check", warning: "warning", danger: "error" };
2416
+ return /* @__PURE__ */ jsxs43("div", { className: `hf-alert hf-alert--${tone}`, role: tone === "danger" ? "alert" : "status", children: [
2417
+ /* @__PURE__ */ jsx50(Icon, { name: icon[tone] }),
2418
+ /* @__PURE__ */ jsxs43("div", { children: [
2419
+ /* @__PURE__ */ jsx50("strong", { children: title }),
2420
+ children && /* @__PURE__ */ jsx50("div", { children }),
2421
+ action && /* @__PURE__ */ jsx50("div", { className: "hf-alert__action", children: action })
2422
+ ] }),
2423
+ onClose && /* @__PURE__ */ jsx50("button", { type: "button", onClick: onClose, "aria-label": "\u5173\u95ED\u63D0\u793A", children: /* @__PURE__ */ jsx50(Icon, { name: "close", size: 16 }) })
2424
+ ] });
2425
+ }
2426
+
2427
+ // src/feedback/Essentials.tsx
2428
+ import { cloneElement as cloneElement4, isValidElement as isValidElement2, useState as useState25 } from "react";
2429
+ import { jsx as jsx51, jsxs as jsxs44 } from "react/jsx-runtime";
2430
+ function Popconfirm({ trigger, title, description, confirmText = "\u786E\u8BA4", cancelText = "\u53D6\u6D88", tone = "primary", onConfirm }) {
2431
+ const [open, setOpen] = useState25(false);
2432
+ const root = useDismissibleLayer(open, () => setOpen(false), { autoFocus: false });
2433
+ return /* @__PURE__ */ jsxs44("span", { className: "hf-popconfirm", ref: root, children: [
2434
+ isValidElement2(trigger) && cloneElement4(trigger, { onClick: () => setOpen(true), "aria-expanded": open }),
2435
+ open && /* @__PURE__ */ jsxs44("div", { role: "alertdialog", "aria-modal": "false", className: "hf-popconfirm__panel", children: [
2436
+ /* @__PURE__ */ jsx51("strong", { children: title }),
2437
+ description && /* @__PURE__ */ jsx51("p", { children: description }),
2438
+ /* @__PURE__ */ jsxs44("div", { children: [
2439
+ /* @__PURE__ */ jsx51(Button, { size: "sm", variant: "quiet", onClick: () => setOpen(false), children: cancelText }),
2440
+ /* @__PURE__ */ jsx51(Button, { size: "sm", variant: tone === "danger" ? "danger" : "primary", onClick: () => {
2441
+ onConfirm();
2442
+ setOpen(false);
2443
+ }, children: confirmText })
2444
+ ] })
2445
+ ] })
2446
+ ] });
2447
+ }
2448
+ function Notification({ title, children, tone = "info", time, unread, action, onClose }) {
2449
+ const icons = { info: "info", success: "check", warning: "warning", danger: "error" };
2450
+ return /* @__PURE__ */ jsxs44("article", { className: `hf-notification hf-notification--${tone}${unread ? " is-unread" : ""}`, children: [
2451
+ /* @__PURE__ */ jsx51("span", { className: "hf-notification__icon", children: /* @__PURE__ */ jsx51(Icon, { name: icons[tone], size: 18 }) }),
2452
+ /* @__PURE__ */ jsxs44("div", { children: [
2453
+ /* @__PURE__ */ jsxs44("header", { children: [
2454
+ /* @__PURE__ */ jsx51("strong", { children: title }),
2455
+ time && /* @__PURE__ */ jsx51("time", { children: time })
2456
+ ] }),
2457
+ children && /* @__PURE__ */ jsx51("p", { children }),
2458
+ action && /* @__PURE__ */ jsx51("div", { className: "hf-notification__action", children: action })
2459
+ ] }),
2460
+ onClose && /* @__PURE__ */ jsx51("button", { type: "button", "aria-label": "\u5173\u95ED\u901A\u77E5", onClick: onClose, children: "\xD7" })
2461
+ ] });
2462
+ }
2463
+ function Result({ status = "info", title, description, actions, extra }) {
2464
+ const icon = status === "success" ? "\u2713" : status === "error" ? "\xD7" : status === "warning" ? "!" : status === "info" ? "i" : status;
2465
+ return /* @__PURE__ */ jsxs44("section", { className: `hf-result hf-result--${status}`, children: [
2466
+ /* @__PURE__ */ jsx51("span", { className: "hf-result__icon", "aria-hidden": "true", children: icon }),
2467
+ /* @__PURE__ */ jsx51("h2", { children: title }),
2468
+ description && /* @__PURE__ */ jsx51("p", { children: description }),
2469
+ actions && /* @__PURE__ */ jsx51("div", { className: "hf-result__actions", children: actions }),
2470
+ extra && /* @__PURE__ */ jsx51("div", { className: "hf-result__extra", children: extra })
2471
+ ] });
2472
+ }
2473
+
2474
+ // src/data-display/DataDisplay.tsx
2475
+ import { Fragment as Fragment3, jsx as jsx52, jsxs as jsxs45 } from "react/jsx-runtime";
2476
+ function StatisticCard({ label, value, trend, icon, tone = "blue", className = "", ...props }) {
2477
+ return /* @__PURE__ */ jsxs45("article", { className: `hf-stat hf-stat--${tone} ${className}`.trim(), ...props, children: [
2478
+ /* @__PURE__ */ jsxs45("div", { className: "hf-stat__top", children: [
2479
+ /* @__PURE__ */ jsx52("span", { children: label }),
2480
+ icon && /* @__PURE__ */ jsx52("i", { children: icon })
2481
+ ] }),
2482
+ /* @__PURE__ */ jsx52("strong", { children: value }),
2483
+ trend && /* @__PURE__ */ jsx52("small", { children: trend }),
2484
+ /* @__PURE__ */ jsx52("span", { className: "hf-stat__glow", "aria-hidden": "true" })
2485
+ ] });
2486
+ }
2487
+ var Stat = StatisticCard;
2488
+ function Progress({ value, max = 100, label, showValue = true, size = "md", tone = "primary", className = "", ...props }) {
2489
+ const percent = Math.min(100, Math.max(0, max ? value / max * 100 : 0));
2490
+ return /* @__PURE__ */ jsxs45("div", { className: `hf-progress hf-progress--${size} hf-progress--${tone} ${className}`.trim(), ...props, children: [
2491
+ (label || showValue) && /* @__PURE__ */ jsxs45("div", { className: "hf-progress__meta", children: [
2492
+ /* @__PURE__ */ jsx52("span", { children: label }),
2493
+ showValue && /* @__PURE__ */ jsxs45("strong", { children: [
2494
+ Math.round(percent),
2495
+ "%"
2496
+ ] })
2497
+ ] }),
2498
+ /* @__PURE__ */ jsx52("div", { className: "hf-progress__track", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": max, "aria-valuenow": value, children: /* @__PURE__ */ jsx52("span", { style: { "--hf-progress": `${percent}%` } }) })
2499
+ ] });
2500
+ }
2501
+ function CircularProgress({ value, max = 100, label, size = 92, thickness = 8, className = "", ...props }) {
2502
+ const percent = Math.min(100, Math.max(0, max ? value / max * 100 : 0));
2503
+ return /* @__PURE__ */ jsx52("div", { className: `hf-circular-progress ${className}`.trim(), style: { "--hf-circle": `${percent * 3.6}deg`, "--hf-circle-size": `${size}px`, "--hf-circle-thickness": `${thickness}px` }, role: "progressbar", "aria-valuemin": 0, "aria-valuemax": max, "aria-valuenow": value, ...props, children: /* @__PURE__ */ jsxs45("span", { children: [
2504
+ /* @__PURE__ */ jsxs45("strong", { children: [
2505
+ Math.round(percent),
2506
+ "%"
2507
+ ] }),
2508
+ label && /* @__PURE__ */ jsx52("small", { children: label })
2509
+ ] }) });
2510
+ }
2511
+ function StepProgress({ steps, current, className = "", ...props }) {
2512
+ return /* @__PURE__ */ jsx52("ol", { className: `hf-step-progress ${className}`.trim(), ...props, children: steps.map((step, index) => /* @__PURE__ */ jsxs45("li", { className: index < current ? "is-complete" : index === current ? "is-current" : "", children: [
2513
+ /* @__PURE__ */ jsx52("span", { children: index < current ? "\u2713" : index + 1 }),
2514
+ /* @__PURE__ */ jsx52("small", { children: step })
2515
+ ] }, index)) });
2516
+ }
2517
+ function ActivityIndicator({ variant = "spinner", label = "\u6B63\u5728\u52A0\u8F7D", size = "md", className = "", ...props }) {
2518
+ return /* @__PURE__ */ jsxs45("span", { className: `hf-activity hf-activity--${variant} hf-activity--${size} ${className}`.trim(), role: "status", "aria-label": label, ...props, children: [
2519
+ variant === "dots" && /* @__PURE__ */ jsxs45(Fragment3, { children: [
2520
+ /* @__PURE__ */ jsx52("i", {}),
2521
+ /* @__PURE__ */ jsx52("i", {}),
2522
+ /* @__PURE__ */ jsx52("i", {})
2523
+ ] }),
2524
+ variant === "wave" && Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx52("i", {}, index)),
2525
+ variant === "radar" && /* @__PURE__ */ jsx52("i", {})
2526
+ ] });
2527
+ }
2528
+ function Sparkline({ data, width = 160, height = 48, label = "\u8D8B\u52BF\u56FE", filled = true, ...props }) {
2529
+ const min = Math.min(...data);
2530
+ const max = Math.max(...data);
2531
+ const range = max - min || 1;
2532
+ const points = data.map((value, index) => `${data.length === 1 ? width / 2 : index / (data.length - 1) * width},${height - ((value - min) / range * (height - 8) + 4)}`).join(" ");
2533
+ const area = `0,${height} ${points} ${width},${height}`;
2534
+ return /* @__PURE__ */ jsxs45("svg", { className: "hf-sparkline", viewBox: `0 0 ${width} ${height}`, role: "img", "aria-label": label, ...props, children: [
2535
+ filled && /* @__PURE__ */ jsx52("polygon", { points: area, className: "hf-sparkline__area" }),
2536
+ /* @__PURE__ */ jsx52("polyline", { points, className: "hf-sparkline__line" })
2537
+ ] });
2538
+ }
2539
+
2540
+ // src/data-display/Collections.tsx
2541
+ import { jsx as jsx53, jsxs as jsxs46 } from "react/jsx-runtime";
2542
+ function Table({ columns, data, rowKey, caption, empty = "\u6682\u65E0\u6570\u636E", striped, onRowClick, className = "", ...props }) {
2543
+ const keyOf = (item, index) => typeof rowKey === "function" ? rowKey(item, index) : String(item[rowKey]);
2544
+ return /* @__PURE__ */ jsx53("div", { className: `hf-table-wrap ${className}`, ...props, children: /* @__PURE__ */ jsxs46("table", { className: `hf-table${striped ? " hf-table--striped" : ""}`, children: [
2545
+ caption && /* @__PURE__ */ jsx53("caption", { children: caption }),
2546
+ /* @__PURE__ */ jsx53("thead", { children: /* @__PURE__ */ jsx53("tr", { children: columns.map((column) => /* @__PURE__ */ jsx53("th", { style: { textAlign: column.align, width: column.width }, children: column.header }, column.key)) }) }),
2547
+ /* @__PURE__ */ jsxs46("tbody", { children: [
2548
+ data.map((item, index) => /* @__PURE__ */ jsx53("tr", { className: onRowClick ? "is-clickable" : "", onClick: () => onRowClick?.(item, index), tabIndex: onRowClick ? 0 : void 0, onKeyDown: (event) => {
2549
+ if (onRowClick && (event.key === "Enter" || event.key === " ")) {
2550
+ event.preventDefault();
2551
+ onRowClick(item, index);
2552
+ }
2553
+ }, children: columns.map((column) => /* @__PURE__ */ jsx53("td", { style: { textAlign: column.align }, children: column.render ? column.render(item, index) : String(item[column.key] ?? "") }, column.key)) }, keyOf(item, index))),
2554
+ !data.length && /* @__PURE__ */ jsx53("tr", { children: /* @__PURE__ */ jsx53("td", { className: "hf-table__empty", colSpan: columns.length, children: empty }) })
2555
+ ] })
2556
+ ] }) });
2557
+ }
2558
+ function Pagination({ page, total, pageSize = 10, siblingCount = 1, onChange, className = "", ...props }) {
2559
+ const count = Math.max(1, Math.ceil(total / pageSize));
2560
+ const current = Math.min(count, Math.max(1, page));
2561
+ const visible = Array.from({ length: count }, (_, i) => i + 1).filter((value) => value === 1 || value === count || Math.abs(value - current) <= siblingCount);
2562
+ const parts = [];
2563
+ visible.forEach((value, index) => {
2564
+ if (index && value - visible[index - 1] > 1) parts.push("ellipsis");
2565
+ parts.push(value);
2566
+ });
2567
+ return /* @__PURE__ */ jsxs46("nav", { className: `hf-pagination ${className}`, "aria-label": "\u5206\u9875", ...props, children: [
2568
+ /* @__PURE__ */ jsx53("button", { disabled: current === 1, onClick: () => onChange(current - 1), "aria-label": "\u4E0A\u4E00\u9875", children: /* @__PURE__ */ jsx53(Icon, { name: "chevron-down", size: 16, className: "hf-pagination__prev" }) }),
2569
+ parts.map((part, index) => part === "ellipsis" ? /* @__PURE__ */ jsx53("span", { "aria-hidden": "true", children: "\u2026" }, `e-${index}`) : /* @__PURE__ */ jsx53("button", { className: part === current ? "is-active" : "", "aria-current": part === current ? "page" : void 0, onClick: () => onChange(part), children: part }, part)),
2570
+ /* @__PURE__ */ jsx53("button", { disabled: current === count, onClick: () => onChange(current + 1), "aria-label": "\u4E0B\u4E00\u9875", children: /* @__PURE__ */ jsx53(Icon, { name: "chevron-down", size: 16, className: "hf-pagination__next" }) })
2571
+ ] });
2572
+ }
2573
+ function List({ items, divided = true, className = "", ...props }) {
2574
+ return /* @__PURE__ */ jsx53("ul", { className: `hf-list${divided ? " hf-list--divided" : ""} ${className}`, ...props, children: items.map((item) => /* @__PURE__ */ jsxs46("li", { children: [
2575
+ item.leading && /* @__PURE__ */ jsx53("span", { className: "hf-list__leading", children: item.leading }),
2576
+ /* @__PURE__ */ jsxs46("div", { children: [
2577
+ /* @__PURE__ */ jsx53("strong", { children: item.title }),
2578
+ item.description && /* @__PURE__ */ jsx53("small", { children: item.description })
2579
+ ] }),
2580
+ item.trailing && /* @__PURE__ */ jsx53("span", { className: "hf-list__trailing", children: item.trailing })
2581
+ ] }, item.key)) });
2582
+ }
2583
+ function Descriptions({ items, columns = 2, bordered, className = "", ...props }) {
2584
+ return /* @__PURE__ */ jsx53("dl", { className: `hf-descriptions hf-descriptions--${columns}${bordered ? " hf-descriptions--bordered" : ""} ${className}`, ...props, children: items.map((item) => /* @__PURE__ */ jsxs46("div", { style: { gridColumn: `span ${Math.min(item.span ?? 1, columns)}` }, children: [
2585
+ /* @__PURE__ */ jsx53("dt", { children: item.label }),
2586
+ /* @__PURE__ */ jsx53("dd", { children: item.value })
2587
+ ] }, item.key)) });
2588
+ }
2589
+
2590
+ // src/data-display/Insight.tsx
2591
+ import { jsx as jsx54, jsxs as jsxs47 } from "react/jsx-runtime";
2592
+ function Timeline({ items, label = "\u65F6\u95F4\u8F74" }) {
2593
+ return /* @__PURE__ */ jsx54("ol", { className: "hf-timeline", "aria-label": label, children: items.map((item) => /* @__PURE__ */ jsxs47("li", { className: `hf-timeline--${item.status ?? "upcoming"}`, children: [
2594
+ /* @__PURE__ */ jsx54("i", { "aria-hidden": "true" }),
2595
+ /* @__PURE__ */ jsxs47("div", { children: [
2596
+ /* @__PURE__ */ jsx54("strong", { children: item.title }),
2597
+ item.description && /* @__PURE__ */ jsx54("p", { children: item.description })
2598
+ ] }),
2599
+ item.time && /* @__PURE__ */ jsx54("time", { children: item.time })
2600
+ ] }, item.key)) });
2601
+ }
2602
+ function InsightBoard({ summary, trend, detail, heading, filters }) {
2603
+ return /* @__PURE__ */ jsxs47("section", { className: "hf-insight-board", children: [
2604
+ (heading || filters) && /* @__PURE__ */ jsxs47("header", { children: [
2605
+ /* @__PURE__ */ jsx54("div", { children: heading }),
2606
+ filters
2607
+ ] }),
2608
+ /* @__PURE__ */ jsx54("div", { className: "hf-insight-board__summary", "aria-label": "\u6838\u5FC3\u7ED3\u679C", children: summary }),
2609
+ /* @__PURE__ */ jsx54("div", { className: "hf-insight-board__trend", "aria-label": "\u53D8\u5316\u8D8B\u52BF", children: trend }),
2610
+ /* @__PURE__ */ jsx54("div", { className: "hf-insight-board__detail", "aria-label": "\u660E\u7EC6\u4E0E\u539F\u56E0", children: detail })
2611
+ ] });
2612
+ }
2613
+
2614
+ // src/data-display/EmptyState.tsx
2615
+ import { jsx as jsx55, jsxs as jsxs48 } from "react/jsx-runtime";
2616
+ function EmptyState({ icon = "inbox", title, description, action, size = "md" }) {
2617
+ return /* @__PURE__ */ jsxs48("div", { className: `hf-empty hf-empty--${size}`, children: [
2618
+ /* @__PURE__ */ jsx55("span", { className: "hf-empty__icon", children: /* @__PURE__ */ jsx55(Icon, { name: icon, size: size === "sm" ? 22 : 28 }) }),
2619
+ /* @__PURE__ */ jsx55("strong", { children: title }),
2620
+ description && /* @__PURE__ */ jsx55("p", { children: description }),
2621
+ action && /* @__PURE__ */ jsx55("div", { children: action })
2622
+ ] });
2623
+ }
2624
+
2625
+ // src/data-display/DataGrid.tsx
2626
+ import { useMemo as useMemo6, useState as useState26 } from "react";
2627
+ import { jsx as jsx56, jsxs as jsxs49 } from "react/jsx-runtime";
2628
+ function DataGrid({ columns, data, rowKey, selectedKeys = [], onSelectionChange, empty = "\u6682\u65E0\u6570\u636E", caption }) {
2629
+ const [sort, setSort] = useState26();
2630
+ const keyOf = (item) => typeof rowKey === "function" ? rowKey(item) : String(item[rowKey]);
2631
+ const rows = useMemo6(() => {
2632
+ if (!sort) return [...data];
2633
+ const column = columns.find((item) => item.key === sort.key);
2634
+ if (!column) return [...data];
2635
+ return [...data].sort((a, b) => {
2636
+ const av = column.value?.(a) ?? String(a[column.key] ?? "");
2637
+ const bv = column.value?.(b) ?? String(b[column.key] ?? "");
2638
+ const compared = typeof av === "number" && typeof bv === "number" ? av - bv : String(av).localeCompare(String(bv), "zh-CN");
2639
+ return sort.direction === "asc" ? compared : -compared;
2640
+ });
2641
+ }, [columns, data, sort]);
2642
+ const all = data.length > 0 && data.every((item) => selectedKeys.includes(keyOf(item)));
2643
+ const changeAll = () => onSelectionChange?.(all ? [] : data.map(keyOf));
2644
+ return /* @__PURE__ */ jsx56("div", { className: "hf-data-grid", onKeyDown: (event) => {
2645
+ if (!["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key)) return;
2646
+ const controls = [...event.currentTarget.querySelectorAll("button,input")];
2647
+ const current = controls.indexOf(event.target);
2648
+ if (current < 0) return;
2649
+ event.preventDefault();
2650
+ const direction = event.key === "ArrowLeft" || event.key === "ArrowUp" ? -1 : 1;
2651
+ controls[(current + direction + controls.length) % controls.length]?.focus();
2652
+ }, children: /* @__PURE__ */ jsxs49("table", { children: [
2653
+ caption && /* @__PURE__ */ jsx56("caption", { children: caption }),
2654
+ /* @__PURE__ */ jsx56("thead", { children: /* @__PURE__ */ jsxs49("tr", { children: [
2655
+ onSelectionChange && /* @__PURE__ */ jsx56("th", { className: "hf-data-grid__check", children: /* @__PURE__ */ jsx56("input", { type: "checkbox", "aria-label": "\u9009\u62E9\u5168\u90E8", checked: all, onChange: changeAll }) }),
2656
+ columns.map((column) => /* @__PURE__ */ jsx56("th", { style: { width: column.width }, children: column.sortable ? /* @__PURE__ */ jsxs49("button", { type: "button", onClick: () => setSort((current) => ({ key: column.key, direction: current?.key === column.key && current.direction === "asc" ? "desc" : "asc" })), children: [
2657
+ column.header,
2658
+ /* @__PURE__ */ jsx56("span", { "aria-hidden": "true", children: sort?.key === column.key ? sort.direction === "asc" ? "\u2191" : "\u2193" : "\u2195" })
2659
+ ] }) : column.header }, column.key))
2660
+ ] }) }),
2661
+ /* @__PURE__ */ jsxs49("tbody", { children: [
2662
+ rows.map((item) => {
2663
+ const key = keyOf(item);
2664
+ return /* @__PURE__ */ jsxs49("tr", { className: selectedKeys.includes(key) ? "is-selected" : "", children: [
2665
+ onSelectionChange && /* @__PURE__ */ jsx56("td", { children: /* @__PURE__ */ jsx56("input", { type: "checkbox", "aria-label": `\u9009\u62E9\u884C ${key}`, checked: selectedKeys.includes(key), onChange: () => onSelectionChange(selectedKeys.includes(key) ? selectedKeys.filter((item2) => item2 !== key) : [...selectedKeys, key]) }) }),
2666
+ columns.map((column) => /* @__PURE__ */ jsx56("td", { children: column.render ? column.render(item) : String(item[column.key] ?? "") }, column.key))
2667
+ ] }, key);
2668
+ }),
2669
+ !rows.length && /* @__PURE__ */ jsx56("tr", { children: /* @__PURE__ */ jsx56("td", { className: "hf-data-grid__empty", colSpan: columns.length + (onSelectionChange ? 1 : 0), children: empty }) })
2670
+ ] })
2671
+ ] }) });
2672
+ }
2673
+
2674
+ // src/data-display/Tree.tsx
2675
+ import { useState as useState27 } from "react";
2676
+ import { jsx as jsx57, jsxs as jsxs50 } from "react/jsx-runtime";
2677
+ function Tree({ nodes, selectedKey, onSelect, defaultExpandedKeys = [], label = "\u6811\u5F62\u5217\u8868" }) {
2678
+ const [expanded, setExpanded] = useState27([...defaultExpandedKeys]);
2679
+ const render = (items, level) => /* @__PURE__ */ jsx57("ul", { role: level ? "group" : "tree", "aria-label": level ? void 0 : label, children: items.map((node) => {
2680
+ const open = expanded.includes(node.key);
2681
+ const branch = Boolean(node.children?.length);
2682
+ return /* @__PURE__ */ jsxs50("li", { role: "treeitem", "aria-level": level + 1, "aria-expanded": branch ? open : void 0, "aria-selected": node.key === selectedKey, children: [
2683
+ /* @__PURE__ */ jsxs50("div", { className: node.key === selectedKey ? "is-selected" : "", style: { paddingLeft: level * 18 + 8 }, children: [
2684
+ branch ? /* @__PURE__ */ jsx57("button", { type: "button", "aria-label": open ? "\u6536\u8D77" : "\u5C55\u5F00", onClick: () => setExpanded((keys) => open ? keys.filter((key) => key !== node.key) : [...keys, node.key]), children: open ? "\u2304" : "\u203A" }) : /* @__PURE__ */ jsx57("span", {}),
2685
+ node.icon,
2686
+ /* @__PURE__ */ jsx57("button", { type: "button", disabled: node.disabled, onClick: () => onSelect?.(node.key), children: node.label })
2687
+ ] }),
2688
+ branch && open && render(node.children, level + 1)
2689
+ ] }, node.key);
2690
+ }) });
2691
+ return /* @__PURE__ */ jsx57("div", { className: "hf-tree", onKeyDown: (event) => {
2692
+ const labels = [...event.currentTarget.querySelectorAll("li[role=treeitem]>div>button:last-child:not(:disabled)")];
2693
+ const current = labels.indexOf(event.target);
2694
+ if (current < 0) return;
2695
+ if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
2696
+ event.preventDefault();
2697
+ const next = event.key === "Home" ? 0 : event.key === "End" ? labels.length - 1 : (current + (event.key === "ArrowDown" ? 1 : -1) + labels.length) % labels.length;
2698
+ labels[next]?.focus();
2699
+ }
2700
+ }, children: render(nodes, 0) });
2701
+ }
2702
+
2703
+ // src/layout/AuthLayout.tsx
2704
+ import { jsx as jsx58, jsxs as jsxs51 } from "react/jsx-runtime";
2705
+ function AuthLayout({ children, brand, aside, footer, variant = "card", backgroundImage, currentStep = 1, steps = 1 }) {
2706
+ const style = backgroundImage ? { "--hf-auth-image": `url("${backgroundImage}")` } : void 0;
2707
+ return /* @__PURE__ */ jsxs51("section", { className: `hf-auth hf-auth--${variant}`, style, children: [
2708
+ brand && /* @__PURE__ */ jsx58("header", { className: "hf-auth__brand", children: brand }),
2709
+ aside && /* @__PURE__ */ jsx58("aside", { className: "hf-auth__aside", children: aside }),
2710
+ /* @__PURE__ */ jsxs51("main", { className: "hf-auth__main", children: [
2711
+ variant === "step" && /* @__PURE__ */ jsx58("div", { className: "hf-auth__steps", "aria-label": `\u7B2C ${currentStep} \u6B65\uFF0C\u5171 ${steps} \u6B65`, children: Array.from({ length: steps }, (_, index) => /* @__PURE__ */ jsx58("span", { className: index < currentStep ? "is-active" : "" }, index)) }),
2712
+ /* @__PURE__ */ jsx58("div", { className: "hf-auth__card", children }),
2713
+ footer && /* @__PURE__ */ jsx58("footer", { children: footer })
2714
+ ] })
2715
+ ] });
2716
+ }
2717
+
2718
+ // src/layout/Hero.tsx
2719
+ import { jsx as jsx59, jsxs as jsxs52 } from "react/jsx-runtime";
2720
+ function Hero({ eyebrow, title, description, primaryAction, secondaryAction, visual, proof, align = "left", kind = "product" }) {
2721
+ return /* @__PURE__ */ jsxs52("section", { className: `hf-hero hf-hero--${align} hf-hero--${kind}`, children: [
2722
+ /* @__PURE__ */ jsxs52("div", { className: "hf-hero__content", children: [
2723
+ eyebrow && /* @__PURE__ */ jsx59("div", { className: "hf-hero__eyebrow", children: eyebrow }),
2724
+ /* @__PURE__ */ jsx59("h1", { children: title }),
2725
+ description && /* @__PURE__ */ jsx59("p", { children: description }),
2726
+ (primaryAction || secondaryAction) && /* @__PURE__ */ jsxs52("div", { className: "hf-hero__actions", children: [
2727
+ primaryAction,
2728
+ secondaryAction
2729
+ ] }),
2730
+ proof && /* @__PURE__ */ jsx59("div", { className: "hf-hero__proof", children: proof })
2731
+ ] }),
2732
+ visual && /* @__PURE__ */ jsx59("div", { className: "hf-hero__visual", children: visual })
2733
+ ] });
2734
+ }
2735
+
2736
+ // src/layout/ResizablePanel.tsx
2737
+ import { useState as useState28 } from "react";
2738
+ import { jsx as jsx60, jsxs as jsxs53 } from "react/jsx-runtime";
2739
+ function ResizablePanel({ primary, secondary, defaultSize = 50, minSize = 20, maxSize = 80, direction = "horizontal", onResize }) {
2740
+ const [size, setSize] = useState28(defaultSize);
2741
+ const start = (event) => {
2742
+ const root = event.currentTarget.parentElement;
2743
+ event.currentTarget.setPointerCapture(event.pointerId);
2744
+ const move = (next) => {
2745
+ const rect = root.getBoundingClientRect();
2746
+ const raw = direction === "horizontal" ? (next.clientX - rect.left) / rect.width * 100 : (next.clientY - rect.top) / rect.height * 100;
2747
+ const value = Math.min(maxSize, Math.max(minSize, raw));
2748
+ setSize(value);
2749
+ onResize?.(value);
2750
+ };
2751
+ const end = () => {
2752
+ document.removeEventListener("pointermove", move);
2753
+ document.removeEventListener("pointerup", end);
2754
+ };
2755
+ document.addEventListener("pointermove", move);
2756
+ document.addEventListener("pointerup", end);
2757
+ };
2758
+ return /* @__PURE__ */ jsxs53("div", { className: `hf-resizable hf-resizable--${direction}`, children: [
2759
+ /* @__PURE__ */ jsx60("div", { style: { flexBasis: `${size}%` }, children: primary }),
2760
+ /* @__PURE__ */ jsx60("div", { className: "hf-resizable__handle", role: "separator", "aria-orientation": direction, "aria-valuemin": minSize, "aria-valuemax": maxSize, "aria-valuenow": Math.round(size), tabIndex: 0, onPointerDown: start, onKeyDown: (event) => {
2761
+ if (!["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key)) return;
2762
+ event.preventDefault();
2763
+ const grow = event.key === "ArrowRight" || event.key === "ArrowDown";
2764
+ const value = Math.min(maxSize, Math.max(minSize, size + (grow ? 2 : -2)));
2765
+ setSize(value);
2766
+ onResize?.(value);
2767
+ } }),
2768
+ /* @__PURE__ */ jsx60("div", { children: secondary })
2769
+ ] });
2770
+ }
2771
+
2772
+ // src/feedback/NotificationCenter.tsx
2773
+ import { jsx as jsx61, jsxs as jsxs54 } from "react/jsx-runtime";
2774
+ function NotificationCenter({ items, onRead, onDismiss, onReadAll, empty = "\u6682\u65E0\u901A\u77E5", title = "\u901A\u77E5\u4E2D\u5FC3" }) {
2775
+ const unread = items.filter((item) => item.unread).length;
2776
+ return /* @__PURE__ */ jsxs54("section", { className: "hf-notification-center", children: [
2777
+ /* @__PURE__ */ jsxs54("header", { children: [
2778
+ /* @__PURE__ */ jsxs54("div", { children: [
2779
+ /* @__PURE__ */ jsx61("strong", { children: title }),
2780
+ unread > 0 && /* @__PURE__ */ jsx61("span", { children: unread })
2781
+ ] }),
2782
+ unread > 0 && onReadAll && /* @__PURE__ */ jsx61("button", { type: "button", onClick: onReadAll, children: "\u5168\u90E8\u5DF2\u8BFB" })
2783
+ ] }),
2784
+ /* @__PURE__ */ jsx61("div", { children: items.length ? items.map(({ key, content, ...item }) => /* @__PURE__ */ jsx61("div", { onClick: () => item.unread && onRead?.(key), children: /* @__PURE__ */ jsx61(Notification, { ...item, onClose: onDismiss ? () => onDismiss(key) : void 0, children: content }) }, key)) : /* @__PURE__ */ jsx61("p", { className: "hf-notification-center__empty", children: empty }) })
2785
+ ] });
2786
+ }
2787
+
2788
+ // src/data-display/VirtualList.tsx
2789
+ import { useState as useState29 } from "react";
2790
+ import { jsx as jsx62 } from "react/jsx-runtime";
2791
+ function VirtualList({ items, itemHeight, height, renderItem, itemKey, overscan = 3, label = "\u865A\u62DF\u5217\u8868" }) {
2792
+ const [scrollTop, setScrollTop] = useState29(0);
2793
+ const start = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
2794
+ const end = Math.min(items.length, Math.ceil((scrollTop + height) / itemHeight) + overscan);
2795
+ return /* @__PURE__ */ jsx62("div", { className: "hf-virtual-list", role: "list", "aria-label": label, style: { height }, onScroll: (event) => setScrollTop(event.currentTarget.scrollTop), children: /* @__PURE__ */ jsx62("div", { style: { height: items.length * itemHeight, position: "relative" }, children: items.slice(start, end).map((item, offset) => {
2796
+ const index = start + offset;
2797
+ return /* @__PURE__ */ jsx62("div", { role: "listitem", style: { height: itemHeight, left: 0, position: "absolute", right: 0, top: index * itemHeight }, children: renderItem(item, index) }, itemKey(item, index));
2798
+ }) }) });
2799
+ }
2800
+
2801
+ // src/data-display/DeveloperView.tsx
2802
+ import { useState as useState30 } from "react";
2803
+ import { jsx as jsx63, jsxs as jsxs55 } from "react/jsx-runtime";
2804
+ function JsonNode({ name, value, depth, defaultExpanded, maxDepth }) {
2805
+ const complex = value !== null && typeof value === "object";
2806
+ const [open, setOpen] = useState30(defaultExpanded && depth < maxDepth);
2807
+ if (!complex) return /* @__PURE__ */ jsxs55("div", { className: "hf-json-viewer__row", children: [
2808
+ /* @__PURE__ */ jsx63("span", { children: name !== void 0 && `${name}: ` }),
2809
+ /* @__PURE__ */ jsx63("code", { className: `is-${value === null ? "null" : typeof value}`, children: value === null ? "null" : JSON.stringify(value) })
2810
+ ] });
2811
+ const entries = Object.entries(value);
2812
+ return /* @__PURE__ */ jsxs55("div", { className: "hf-json-viewer__node", children: [
2813
+ /* @__PURE__ */ jsxs55("button", { type: "button", "aria-expanded": open, onClick: () => setOpen(!open), children: [
2814
+ /* @__PURE__ */ jsx63("span", { children: open ? "\u2304" : "\u203A" }),
2815
+ /* @__PURE__ */ jsx63("strong", { children: name ?? (Array.isArray(value) ? "Array" : "Object") }),
2816
+ /* @__PURE__ */ jsx63("small", { children: Array.isArray(value) ? `[${entries.length}]` : `{${entries.length}}` })
2817
+ ] }),
2818
+ open && /* @__PURE__ */ jsx63("div", { children: entries.map(([key, item]) => /* @__PURE__ */ jsx63(JsonNode, { name: key, value: item, depth: depth + 1, defaultExpanded, maxDepth }, key)) })
2819
+ ] });
2820
+ }
2821
+ function JsonViewer({ data, name, defaultExpanded = true, maxDepth = 2 }) {
2822
+ return /* @__PURE__ */ jsx63("div", { className: "hf-json-viewer", role: "tree", "aria-label": name ?? "JSON \u67E5\u770B\u5668", children: /* @__PURE__ */ jsx63(JsonNode, { name, value: data, depth: 0, defaultExpanded, maxDepth }) });
2823
+ }
2824
+ function compareLines(before, after) {
2825
+ const a = before.split("\n"), b = after.split("\n"), matrix = Array.from({ length: a.length + 1 }, () => Array(b.length + 1).fill(0));
2826
+ for (let i2 = a.length - 1; i2 >= 0; i2--) for (let j2 = b.length - 1; j2 >= 0; j2--) matrix[i2][j2] = a[i2] === b[j2] ? matrix[i2 + 1][j2 + 1] + 1 : Math.max(matrix[i2 + 1][j2], matrix[i2][j2 + 1]);
2827
+ const rows = [];
2828
+ let i = 0, j = 0, leftNo = 1, rightNo = 1;
2829
+ while (i < a.length || j < b.length) {
2830
+ if (i < a.length && j < b.length && a[i] === b[j]) {
2831
+ rows.push({ kind: "same", left: a[i++], right: b[j++], leftNo: leftNo++, rightNo: rightNo++ });
2832
+ } else if (j < b.length && (i === a.length || matrix[i][j + 1] >= matrix[i + 1][j])) {
2833
+ rows.push({ kind: "add", right: b[j++], rightNo: rightNo++ });
2834
+ } else {
2835
+ rows.push({ kind: "remove", left: a[i++], leftNo: leftNo++ });
2836
+ }
2837
+ }
2838
+ return rows;
2839
+ }
2840
+ function DiffCell({ number, marker, children }) {
2841
+ return /* @__PURE__ */ jsxs55("div", { className: "hf-diff-viewer__cell", children: [
2842
+ /* @__PURE__ */ jsx63("span", { children: number ?? "" }),
2843
+ /* @__PURE__ */ jsx63("i", { children: marker }),
2844
+ /* @__PURE__ */ jsx63("code", { children: children ?? "" })
2845
+ ] });
2846
+ }
2847
+ function DiffViewer({ before, after, beforeLabel = "\u4FEE\u6539\u524D", afterLabel = "\u4FEE\u6539\u540E", mode = "split" }) {
2848
+ const rows = compareLines(before, after);
2849
+ return /* @__PURE__ */ jsxs55("div", { className: `hf-diff-viewer hf-diff-viewer--${mode}`, children: [
2850
+ /* @__PURE__ */ jsxs55("header", { children: [
2851
+ /* @__PURE__ */ jsx63("strong", { children: beforeLabel }),
2852
+ mode === "split" && /* @__PURE__ */ jsx63("strong", { children: afterLabel })
2853
+ ] }),
2854
+ /* @__PURE__ */ jsx63("div", { children: rows.map((row, index) => mode === "split" ? /* @__PURE__ */ jsxs55("div", { className: `is-${row.kind}`, children: [
2855
+ /* @__PURE__ */ jsx63(DiffCell, { number: row.leftNo, marker: row.kind === "remove" ? "\u2212" : " ", children: row.left }),
2856
+ /* @__PURE__ */ jsx63(DiffCell, { number: row.rightNo, marker: row.kind === "add" ? "+" : " ", children: row.right })
2857
+ ] }, index) : /* @__PURE__ */ jsx63("div", { className: `is-${row.kind}`, children: /* @__PURE__ */ jsx63(DiffCell, { number: row.leftNo ?? row.rightNo, marker: row.kind === "add" ? "+" : row.kind === "remove" ? "\u2212" : " ", children: row.kind === "add" ? row.right : row.left }) }, index)) })
2858
+ ] });
2859
+ }
2860
+
2861
+ // src/forms/QueryBuilder.tsx
2862
+ import { jsx as jsx64, jsxs as jsxs56 } from "react/jsx-runtime";
2863
+ var defaultOperators = [{ value: "equals", label: "\u7B49\u4E8E" }, { value: "notEquals", label: "\u4E0D\u7B49\u4E8E" }, { value: "contains", label: "\u5305\u542B" }];
2864
+ function QueryBuilder({ fields, rules, onChange, conjunction = "and", onConjunctionChange, disabled }) {
2865
+ const update = (id, patch) => onChange(rules.map((rule) => rule.id === id ? { ...rule, ...patch } : rule));
2866
+ const add = () => {
2867
+ const field = fields[0];
2868
+ if (!field) return;
2869
+ const operator = (field.operators ?? defaultOperators)[0]?.value ?? "equals";
2870
+ onChange([...rules, { id: `rule-${Date.now()}`, field: field.key, operator, value: "" }]);
2871
+ };
2872
+ return /* @__PURE__ */ jsxs56("div", { className: "hf-query-builder", children: [
2873
+ /* @__PURE__ */ jsxs56("header", { children: [
2874
+ /* @__PURE__ */ jsx64("strong", { children: "\u6EE1\u8DB3" }),
2875
+ /* @__PURE__ */ jsxs56("select", { "aria-label": "\u6761\u4EF6\u5173\u7CFB", value: conjunction, disabled, onChange: (event) => onConjunctionChange?.(event.target.value), children: [
2876
+ /* @__PURE__ */ jsx64("option", { value: "and", children: "\u5168\u90E8\u6761\u4EF6" }),
2877
+ /* @__PURE__ */ jsx64("option", { value: "or", children: "\u4EFB\u4E00\u6761\u4EF6" })
2878
+ ] })
2879
+ ] }),
2880
+ /* @__PURE__ */ jsx64("div", { children: rules.map((rule, index) => {
2881
+ const field = fields.find((item) => item.key === rule.field) ?? fields[0];
2882
+ const operators = field?.operators ?? defaultOperators;
2883
+ return /* @__PURE__ */ jsxs56("div", { className: "hf-query-builder__rule", children: [
2884
+ /* @__PURE__ */ jsx64("span", { children: index + 1 }),
2885
+ /* @__PURE__ */ jsx64("select", { "aria-label": `\u6761\u4EF6 ${index + 1} \u5B57\u6BB5`, value: rule.field, disabled, onChange: (event) => {
2886
+ const next = fields.find((item) => item.key === event.target.value);
2887
+ update(rule.id, { field: next.key, operator: (next.operators ?? defaultOperators)[0]?.value ?? "equals", value: "" });
2888
+ }, children: fields.map((item) => /* @__PURE__ */ jsx64("option", { value: item.key, children: item.label }, item.key)) }),
2889
+ /* @__PURE__ */ jsx64("select", { "aria-label": `\u6761\u4EF6 ${index + 1} \u8FD0\u7B97\u7B26`, value: rule.operator, disabled, onChange: (event) => update(rule.id, { operator: event.target.value }), children: operators.map((item) => /* @__PURE__ */ jsx64("option", { value: item.value, children: item.label }, item.value)) }),
2890
+ /* @__PURE__ */ jsx64("input", { "aria-label": `\u6761\u4EF6 ${index + 1} \u503C`, type: field?.type ?? "text", value: rule.value, disabled, onChange: (event) => update(rule.id, { value: event.target.value }) }),
2891
+ /* @__PURE__ */ jsx64("button", { type: "button", "aria-label": `\u5220\u9664\u6761\u4EF6 ${index + 1}`, disabled, onClick: () => onChange(rules.filter((item) => item.id !== rule.id)), children: "\xD7" })
2892
+ ] }, rule.id);
2893
+ }) }),
2894
+ /* @__PURE__ */ jsx64("button", { type: "button", className: "hf-query-builder__add", disabled: disabled || !fields.length, onClick: add, children: "\uFF0B \u6DFB\u52A0\u6761\u4EF6" })
2895
+ ] });
2896
+ }
2897
+
2898
+ // src/data-display/WorkflowViews.tsx
2899
+ import { useMemo as useMemo7 } from "react";
2900
+ import { jsx as jsx65, jsxs as jsxs57 } from "react/jsx-runtime";
2901
+ function FlowCanvas({ nodes, edges, width = 900, height = 420, selectedId, onSelect, empty = "\u6682\u65E0\u6D41\u7A0B\u8282\u70B9" }) {
2902
+ const map = new Map(nodes.map((node) => [node.id, node]));
2903
+ if (!nodes.length) return /* @__PURE__ */ jsx65("div", { className: "hf-flow-canvas hf-flow-canvas__empty", children: empty });
2904
+ return /* @__PURE__ */ jsx65("div", { className: "hf-flow-canvas", role: "group", "aria-label": "\u6D41\u7A0B\u753B\u5E03", children: /* @__PURE__ */ jsxs57("div", { style: { width, height }, children: [
2905
+ /* @__PURE__ */ jsx65("svg", { viewBox: `0 0 ${width} ${height}`, "aria-hidden": "true", children: edges.map((edge, index) => {
2906
+ const from = map.get(edge.from), to = map.get(edge.to);
2907
+ if (!from || !to) return null;
2908
+ const x1 = from.x + 82, y1 = from.y + 28, x2 = to.x, y2 = to.y + 28, bend = Math.max(30, Math.abs(x2 - x1) / 2);
2909
+ return /* @__PURE__ */ jsxs57("g", { children: [
2910
+ /* @__PURE__ */ jsx65("path", { d: `M${x1} ${y1} C${x1 + bend} ${y1},${x2 - bend} ${y2},${x2} ${y2}` }),
2911
+ /* @__PURE__ */ jsx65("circle", { cx: x2, cy: y2, r: "3" }),
2912
+ edge.label && /* @__PURE__ */ jsx65("text", { x: (x1 + x2) / 2, y: (y1 + y2) / 2 - 8, children: edge.label })
2913
+ ] }, edge.id ?? index);
2914
+ }) }),
2915
+ nodes.map((node) => /* @__PURE__ */ jsxs57("button", { type: "button", className: `hf-flow-canvas__node is-${node.status ?? "default"}${selectedId === node.id ? " is-selected" : ""}`, style: { left: node.x, top: node.y }, "aria-pressed": selectedId === node.id, onClick: () => onSelect?.(node.id), children: [
2916
+ /* @__PURE__ */ jsx65("strong", { children: node.label }),
2917
+ node.description && /* @__PURE__ */ jsx65("small", { children: node.description })
2918
+ ] }, node.id))
2919
+ ] }) });
2920
+ }
2921
+ function KanbanBoard({ columns, onMove, onCardClick, empty = "\u6682\u65E0\u770B\u677F\u5217" }) {
2922
+ const drop = (event, target) => {
2923
+ event.preventDefault();
2924
+ const card = event.dataTransfer.getData("application/x-hf-card"), from = event.dataTransfer.getData("application/x-hf-column");
2925
+ if (card && from && from !== target) onMove?.(card, from, target);
2926
+ };
2927
+ if (!columns.length) return /* @__PURE__ */ jsx65("div", { className: "hf-kanban-board__empty", children: empty });
2928
+ return /* @__PURE__ */ jsx65("div", { className: "hf-kanban-board", "aria-label": "\u770B\u677F", children: columns.map((column) => /* @__PURE__ */ jsxs57("section", { style: { "--hf-kanban-accent": column.accent }, onDragOver: (event) => event.preventDefault(), onDrop: (event) => drop(event, column.id), children: [
2929
+ /* @__PURE__ */ jsxs57("header", { children: [
2930
+ /* @__PURE__ */ jsx65("strong", { children: column.title }),
2931
+ /* @__PURE__ */ jsxs57("span", { children: [
2932
+ column.cards.length,
2933
+ column.limit ? ` / ${column.limit}` : ""
2934
+ ] })
2935
+ ] }),
2936
+ /* @__PURE__ */ jsx65("div", { children: column.cards.map((card) => /* @__PURE__ */ jsxs57("button", { type: "button", draggable: Boolean(onMove), className: "hf-kanban-card", onDragStart: (event) => {
2937
+ event.dataTransfer.setData("application/x-hf-card", card.id);
2938
+ event.dataTransfer.setData("application/x-hf-column", column.id);
2939
+ }, onClick: () => onCardClick?.(card.id, column.id), children: [
2940
+ /* @__PURE__ */ jsx65("strong", { children: card.title }),
2941
+ card.description && /* @__PURE__ */ jsx65("p", { children: card.description }),
2942
+ card.tags?.length ? /* @__PURE__ */ jsx65("span", { children: card.tags.map((tag) => /* @__PURE__ */ jsx65("i", { children: tag }, tag)) }) : null,
2943
+ card.meta && /* @__PURE__ */ jsx65("small", { children: card.meta })
2944
+ ] }, card.id)) })
2945
+ ] }, column.id)) });
2946
+ }
2947
+ var day = 864e5;
2948
+ var toTime = (value) => new Date(value).setHours(0, 0, 0, 0);
2949
+ function GanttChart({ tasks, start, end, onTaskClick, empty = "\u6682\u65E0\u6392\u671F\u4EFB\u52A1" }) {
2950
+ const range = useMemo7(() => {
2951
+ const starts = tasks.map((task) => toTime(task.start)), ends = tasks.map((task) => toTime(task.end));
2952
+ const from = start ? toTime(start) : Math.min(...starts), to = end ? toTime(end) : Math.max(...ends);
2953
+ return { from, days: Math.max(1, Math.round((to - from) / day) + 1) };
2954
+ }, [tasks, start, end]);
2955
+ if (!tasks.length) return /* @__PURE__ */ jsx65("div", { className: "hf-gantt-chart__empty", children: empty });
2956
+ return /* @__PURE__ */ jsxs57("div", { className: "hf-gantt-chart", children: [
2957
+ /* @__PURE__ */ jsxs57("header", { children: [
2958
+ /* @__PURE__ */ jsx65("strong", { children: "\u4EFB\u52A1" }),
2959
+ /* @__PURE__ */ jsx65("div", { children: Array.from({ length: Math.min(range.days, 31) }, (_, index) => /* @__PURE__ */ jsx65("span", { children: new Date(range.from + index * day).getDate() }, index)) })
2960
+ ] }),
2961
+ tasks.map((task) => {
2962
+ const offset = Math.max(0, (toTime(task.start) - range.from) / day), length = Math.max(1, (toTime(task.end) - toTime(task.start)) / day + 1);
2963
+ return /* @__PURE__ */ jsxs57("div", { className: "hf-gantt-chart__row", children: [
2964
+ /* @__PURE__ */ jsxs57("span", { children: [
2965
+ /* @__PURE__ */ jsx65("strong", { children: task.label }),
2966
+ task.group && /* @__PURE__ */ jsx65("small", { children: task.group })
2967
+ ] }),
2968
+ /* @__PURE__ */ jsx65("div", { children: /* @__PURE__ */ jsxs57("button", { type: "button", style: { left: `${offset / range.days * 100}%`, width: `${length / range.days * 100}%`, "--hf-gantt-color": task.color }, onClick: () => onTaskClick?.(task.id), children: [
2969
+ /* @__PURE__ */ jsx65("i", { style: { width: `${Math.max(0, Math.min(100, task.progress ?? 0))}%` } }),
2970
+ /* @__PURE__ */ jsxs57("span", { children: [
2971
+ task.progress ?? 0,
2972
+ "%"
2973
+ ] })
2974
+ ] }) })
2975
+ ] }, task.id);
2976
+ })
2977
+ ] });
2978
+ }
2979
+ function ChartContainer({ title, description, actions, legend, children, height = 320, loading, empty, emptyContent = "\u6682\u65E0\u56FE\u8868\u6570\u636E" }) {
2980
+ return /* @__PURE__ */ jsxs57("section", { className: "hf-chart-container", children: [
2981
+ /* @__PURE__ */ jsxs57("header", { children: [
2982
+ /* @__PURE__ */ jsxs57("div", { children: [
2983
+ title && /* @__PURE__ */ jsx65("strong", { children: title }),
2984
+ description && /* @__PURE__ */ jsx65("p", { children: description })
2985
+ ] }),
2986
+ actions
2987
+ ] }),
2988
+ legend?.length ? /* @__PURE__ */ jsx65("div", { className: "hf-chart-container__legend", children: legend.map((item, index) => /* @__PURE__ */ jsxs57("span", { children: [
2989
+ /* @__PURE__ */ jsx65("i", { style: { background: item.color } }),
2990
+ item.label,
2991
+ item.value && /* @__PURE__ */ jsx65("strong", { children: item.value })
2992
+ ] }, index)) }) : null,
2993
+ /* @__PURE__ */ jsx65("div", { className: "hf-chart-container__body", style: { height }, children: loading ? /* @__PURE__ */ jsxs57("div", { className: "hf-chart-container__state", children: [
2994
+ /* @__PURE__ */ jsx65("span", { className: "hf-spinner" }),
2995
+ "\u6B63\u5728\u52A0\u8F7D\u56FE\u8868"
2996
+ ] }) : empty ? /* @__PURE__ */ jsx65("div", { className: "hf-chart-container__state", children: emptyContent }) : children })
2997
+ ] });
2998
+ }
2999
+ function PivotTable({ data, row, column, values, rowLabel = "\u9879\u76EE", showTotals = true, empty = "\u6682\u65E0\u900F\u89C6\u6570\u636E" }) {
3000
+ const rows = [...new Set(data.map(row))], columns = [...new Set(data.map(column))];
3001
+ const calculate = (items, metric) => {
3002
+ if (metric.aggregate === "count") return items.length;
3003
+ const sum = items.reduce((total, item) => total + metric.value(item), 0);
3004
+ return metric.aggregate === "average" ? items.length ? sum / items.length : 0 : sum;
3005
+ };
3006
+ if (!data.length || !values.length) return /* @__PURE__ */ jsx65("div", { className: "hf-pivot-table__empty", children: empty });
3007
+ return /* @__PURE__ */ jsx65("div", { className: "hf-pivot-table", children: /* @__PURE__ */ jsxs57("table", { children: [
3008
+ /* @__PURE__ */ jsxs57("thead", { children: [
3009
+ /* @__PURE__ */ jsxs57("tr", { children: [
3010
+ /* @__PURE__ */ jsx65("th", { rowSpan: 2, children: rowLabel }),
3011
+ columns.map((item) => /* @__PURE__ */ jsx65("th", { colSpan: values.length, children: item }, item)),
3012
+ showTotals && /* @__PURE__ */ jsx65("th", { colSpan: values.length, children: "\u5408\u8BA1" })
3013
+ ] }),
3014
+ /* @__PURE__ */ jsx65("tr", { children: [...columns, ...showTotals ? ["__total"] : []].flatMap((col) => values.map((metric) => /* @__PURE__ */ jsx65("th", { children: metric.label }, `${col}-${metric.key}`))) })
3015
+ ] }),
3016
+ /* @__PURE__ */ jsx65("tbody", { children: rows.map((rowName) => /* @__PURE__ */ jsxs57("tr", { children: [
3017
+ /* @__PURE__ */ jsx65("th", { children: rowName }),
3018
+ [...columns, ...showTotals ? ["__total"] : []].flatMap((columnName) => values.map((metric) => {
3019
+ const items = data.filter((item) => row(item) === rowName && (columnName === "__total" || column(item) === columnName));
3020
+ const result = calculate(items, metric);
3021
+ return /* @__PURE__ */ jsx65("td", { children: metric.format?.(result) ?? result }, `${columnName}-${metric.key}`);
3022
+ }))
3023
+ ] }, rowName)) })
3024
+ ] }) });
3025
+ }
3026
+
3027
+ // src/forms/FilterBuilder.tsx
3028
+ import { jsx as jsx66, jsxs as jsxs58 } from "react/jsx-runtime";
3029
+ function FilterBuilder({ fields, value, onChange, disabled, addLabel = "\u6DFB\u52A0\u7B5B\u9009" }) {
3030
+ const add = () => {
3031
+ const field = fields.find((item) => !value.some((filter) => filter.field === item.key)) ?? fields[0];
3032
+ if (field) onChange([...value, { id: `filter-${Date.now()}`, field: field.key, value: "" }]);
3033
+ };
3034
+ const update = (id, patch) => onChange(value.map((item) => item.id === id ? { ...item, ...patch } : item));
3035
+ return /* @__PURE__ */ jsxs58("div", { className: "hf-filter-builder", role: "group", "aria-label": "\u7B5B\u9009\u6761\u4EF6", children: [
3036
+ /* @__PURE__ */ jsx66("div", { children: value.map((filter, index) => {
3037
+ const field = fields.find((item) => item.key === filter.field) ?? fields[0];
3038
+ return /* @__PURE__ */ jsxs58("div", { className: "hf-filter-builder__item", children: [
3039
+ /* @__PURE__ */ jsx66("select", { "aria-label": `\u7B5B\u9009 ${index + 1} \u5B57\u6BB5`, value: filter.field, disabled, onChange: (event) => update(filter.id, { field: event.target.value, value: "" }), children: fields.map((item) => /* @__PURE__ */ jsx66("option", { value: item.key, children: item.label }, item.key)) }),
3040
+ field?.options ? /* @__PURE__ */ jsxs58("select", { "aria-label": `\u7B5B\u9009 ${index + 1} \u503C`, value: filter.value, disabled, onChange: (event) => update(filter.id, { value: event.target.value }), children: [
3041
+ /* @__PURE__ */ jsx66("option", { value: "", children: "\u8BF7\u9009\u62E9" }),
3042
+ field.options.map((item) => /* @__PURE__ */ jsx66("option", { value: item.value, children: item.label }, item.value))
3043
+ ] }) : /* @__PURE__ */ jsx66("input", { "aria-label": `\u7B5B\u9009 ${index + 1} \u503C`, type: field?.type ?? "text", value: filter.value, disabled, onChange: (event) => update(filter.id, { value: event.target.value }) }),
3044
+ /* @__PURE__ */ jsx66("button", { type: "button", "aria-label": `\u5220\u9664\u7B5B\u9009 ${index + 1}`, disabled, onClick: () => onChange(value.filter((item) => item.id !== filter.id)), children: "\xD7" })
3045
+ ] }, filter.id);
3046
+ }) }),
3047
+ /* @__PURE__ */ jsxs58("button", { type: "button", className: "hf-filter-builder__add", disabled: disabled || !fields.length, onClick: add, children: [
3048
+ "\uFF0B ",
3049
+ addLabel
3050
+ ] }),
3051
+ value.length > 0 && /* @__PURE__ */ jsx66("button", { type: "button", className: "hf-filter-builder__clear", disabled, onClick: () => onChange([]), children: "\u6E05\u7A7A" })
3052
+ ] });
3053
+ }
3054
+ export {
3055
+ Accordion,
3056
+ ActivityFeed,
3057
+ ActivityIndicator,
3058
+ AgentRunTimeline,
3059
+ Alert,
3060
+ ApprovalFlow,
3061
+ AuditLog,
3062
+ AuthLayout,
3063
+ AvailabilityGrid,
3064
+ Avatar,
3065
+ AvatarGroup,
3066
+ Badge,
3067
+ Breadcrumb,
3068
+ Button,
3069
+ ButtonGroup,
3070
+ Calendar,
3071
+ Card,
3072
+ Cascader,
3073
+ ChartContainer,
3074
+ ChatComposer,
3075
+ ChatMessage,
3076
+ Checkbox,
3077
+ CheckboxGroup,
3078
+ ChoiceGroup,
3079
+ CircularProgress,
3080
+ CitationList,
3081
+ CodeBlock,
3082
+ CodeEditor,
3083
+ ColorPicker,
3084
+ Combobox,
3085
+ CommandPalette,
3086
+ CommentThread,
3087
+ Container,
3088
+ ContextMenu,
3089
+ ConversationBranch,
3090
+ DataGrid,
3091
+ DatePicker,
3092
+ DateRangePicker,
3093
+ Descriptions,
3094
+ DiffViewer,
3095
+ Divider,
3096
+ Drawer,
3097
+ Dropdown,
3098
+ DropdownMenu,
3099
+ EmptyState,
3100
+ EventCard,
3101
+ FileExplorer,
3102
+ FilePreview,
3103
+ FilterBuilder,
3104
+ FloatingNav,
3105
+ FlowCanvas,
3106
+ Form,
3107
+ FormItem,
3108
+ GanttChart,
3109
+ Grid,
3110
+ Hero,
3111
+ Icon,
3112
+ IconButton,
3113
+ Input,
3114
+ InsightBoard,
3115
+ JsonViewer,
3116
+ KanbanBoard,
3117
+ Link,
3118
+ List,
3119
+ LoadingDots,
3120
+ LoadingOverlay,
3121
+ MarkdownContent,
3122
+ Masonry,
3123
+ MegaMenu,
3124
+ MemberPicker,
3125
+ MentionInput,
3126
+ MobileNavigation,
3127
+ Modal,
3128
+ ModelSelector,
3129
+ MultiSelect,
3130
+ Notification,
3131
+ NotificationCenter,
3132
+ NumberInput,
3133
+ PageLayout,
3134
+ Pagination,
3135
+ PermissionMatrix,
3136
+ PivotTable,
3137
+ Popconfirm,
3138
+ Popover,
3139
+ Presence,
3140
+ Progress,
3141
+ ProgressBar,
3142
+ ProgressRing,
3143
+ PromptSuggestions,
3144
+ QueryBuilder,
3145
+ Radio,
3146
+ RadioGroup,
3147
+ RecurrenceEditor,
3148
+ ResizablePanel,
3149
+ ResourceCalendar,
3150
+ Result,
3151
+ RichTextEditor,
3152
+ Scheduler,
3153
+ Scrollspy,
3154
+ SearchInput,
3155
+ SegmentedControl,
3156
+ Select,
3157
+ SharePanel,
3158
+ ShrinkNav,
3159
+ Sidebar,
3160
+ Skeleton,
3161
+ Slider,
3162
+ Sparkline,
3163
+ Spinner,
3164
+ SplitButton,
3165
+ Stack,
3166
+ Stat,
3167
+ StatisticCard,
3168
+ StepProgress,
3169
+ Steps,
3170
+ Switch,
3171
+ Table,
3172
+ Tabs,
3173
+ Tag,
3174
+ Textarea,
3175
+ ThemeProvider,
3176
+ TimePicker,
3177
+ Timeline,
3178
+ TimezoneSelect,
3179
+ Toast,
3180
+ TokenUsage,
3181
+ ToolCallCard,
3182
+ Tooltip,
3183
+ Transfer,
3184
+ Tree,
3185
+ TreeSelect,
3186
+ Typography,
3187
+ Upload,
3188
+ ValidatedInput,
3189
+ VersionHistory,
3190
+ VirtualList,
3191
+ VoiceInput,
3192
+ activateNavigationItem,
3193
+ darkTheme,
3194
+ defaultTheme,
3195
+ highContrastTheme,
3196
+ tokensToStyle,
3197
+ validateForm,
3198
+ validateValue
3199
+ };
3200
+ //# sourceMappingURL=index.js.map