jvdm-ui 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +221 -0
  3. package/bin/jvdm-ui.mjs +49 -0
  4. package/dist/atoms/index.d.ts +343 -0
  5. package/dist/atoms/index.js +3 -0
  6. package/dist/atoms/index.js.map +1 -0
  7. package/dist/chunk-AHE2576G.js +682 -0
  8. package/dist/chunk-AHE2576G.js.map +1 -0
  9. package/dist/chunk-CGDYSB4G.js +3 -0
  10. package/dist/chunk-CGDYSB4G.js.map +1 -0
  11. package/dist/chunk-JYNDKPAH.js +362 -0
  12. package/dist/chunk-JYNDKPAH.js.map +1 -0
  13. package/dist/chunk-WWOXGKLF.js +724 -0
  14. package/dist/chunk-WWOXGKLF.js.map +1 -0
  15. package/dist/client/code-block.d.ts +9 -0
  16. package/dist/client/code-block.js +65 -0
  17. package/dist/client/code-block.js.map +1 -0
  18. package/dist/client/confirm-dialog.d.ts +16 -0
  19. package/dist/client/confirm-dialog.js +181 -0
  20. package/dist/client/confirm-dialog.js.map +1 -0
  21. package/dist/client/date-picker.d.ts +10 -0
  22. package/dist/client/date-picker.js +236 -0
  23. package/dist/client/date-picker.js.map +1 -0
  24. package/dist/client/file-upload.d.ts +12 -0
  25. package/dist/client/file-upload.js +58 -0
  26. package/dist/client/file-upload.js.map +1 -0
  27. package/dist/client/gallery.d.ts +14 -0
  28. package/dist/client/gallery.js +122 -0
  29. package/dist/client/gallery.js.map +1 -0
  30. package/dist/client/menu.d.ts +24 -0
  31. package/dist/client/menu.js +115 -0
  32. package/dist/client/menu.js.map +1 -0
  33. package/dist/client/modal.d.ts +19 -0
  34. package/dist/client/modal.js +147 -0
  35. package/dist/client/modal.js.map +1 -0
  36. package/dist/client/multi-select.d.ts +16 -0
  37. package/dist/client/multi-select.js +84 -0
  38. package/dist/client/multi-select.js.map +1 -0
  39. package/dist/client/number-input.d.ts +6 -0
  40. package/dist/client/number-input.js +59 -0
  41. package/dist/client/number-input.js.map +1 -0
  42. package/dist/client/password-input.d.ts +16 -0
  43. package/dist/client/password-input.js +103 -0
  44. package/dist/client/password-input.js.map +1 -0
  45. package/dist/client/pin-input.d.ts +10 -0
  46. package/dist/client/pin-input.js +55 -0
  47. package/dist/client/pin-input.js.map +1 -0
  48. package/dist/client/theme-toggle.d.ts +8 -0
  49. package/dist/client/theme-toggle.js +126 -0
  50. package/dist/client/theme-toggle.js.map +1 -0
  51. package/dist/client/theme.d.ts +8 -0
  52. package/dist/client/theme.js +32 -0
  53. package/dist/client/theme.js.map +1 -0
  54. package/dist/client/time-picker.d.ts +10 -0
  55. package/dist/client/time-picker.js +140 -0
  56. package/dist/client/time-picker.js.map +1 -0
  57. package/dist/index.d.ts +5 -0
  58. package/dist/index.js +6 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/molecules/index.d.ts +309 -0
  61. package/dist/molecules/index.js +4 -0
  62. package/dist/molecules/index.js.map +1 -0
  63. package/dist/organisms/index.d.ts +113 -0
  64. package/dist/organisms/index.js +4 -0
  65. package/dist/organisms/index.js.map +1 -0
  66. package/dist/presets/gavel.css +19 -0
  67. package/dist/theme/index.d.ts +60 -0
  68. package/dist/theme/index.js +85 -0
  69. package/dist/theme/index.js.map +1 -0
  70. package/dist/tokens/index.d.ts +8 -0
  71. package/dist/tokens/index.js +3 -0
  72. package/dist/tokens/index.js.map +1 -0
  73. package/dist/tokens.css +129 -0
  74. package/package.json +114 -0
@@ -0,0 +1,682 @@
1
+ import { ChevronIcon, Button, Input, Kbd, IconButton, CloseIcon, buttonClass, Card, Label } from './chunk-WWOXGKLF.js';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ export * from 'jvdm-ui/client/code-block';
4
+ import { useState, useRef, useEffect, useMemo, useId, isValidElement, cloneElement } from 'react';
5
+ export * from 'jvdm-ui/client/confirm-dialog';
6
+ export { Gallery } from 'jvdm-ui/client/gallery';
7
+ export * from 'jvdm-ui/client/modal';
8
+ export { Menu } from 'jvdm-ui/client/menu';
9
+
10
+ function Accordion({
11
+ items,
12
+ exclusive = false,
13
+ name = "accordion",
14
+ className = ""
15
+ }) {
16
+ return /* @__PURE__ */ jsx(
17
+ "div",
18
+ {
19
+ className: `divide-y divide-line overflow-hidden rounded-md border border-line ${className}`,
20
+ children: items.map((item) => /* @__PURE__ */ jsxs(
21
+ "details",
22
+ {
23
+ name: exclusive ? name : void 0,
24
+ open: item.defaultOpen,
25
+ className: "group bg-surface",
26
+ children: [
27
+ /* @__PURE__ */ jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between gap-3 px-4 text-sm text-ink transition-colors duration-(--duration-fast) ease-out hover:bg-raised focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent", children: [
28
+ item.title,
29
+ /* @__PURE__ */ jsx(
30
+ ChevronIcon,
31
+ {
32
+ className: "text-ink-muted transition-transform duration-(--duration-fast) ease-out group-open:-rotate-180",
33
+ size: "md"
34
+ }
35
+ )
36
+ ] }),
37
+ /* @__PURE__ */ jsx("div", { className: "px-4 pb-4 text-sm text-ink-soft", children: item.content })
38
+ ]
39
+ },
40
+ item.id
41
+ ))
42
+ }
43
+ );
44
+ }
45
+ var TONES = {
46
+ info: "border-info/40 bg-info-soft text-info",
47
+ ok: "border-ok/40 bg-ok-soft text-ok",
48
+ warn: "border-warn/40 bg-warn-soft text-warn",
49
+ danger: "border-danger/40 bg-danger-soft text-danger"
50
+ };
51
+ function Banner({
52
+ tone = "info",
53
+ title,
54
+ children,
55
+ action,
56
+ className = ""
57
+ }) {
58
+ return /* @__PURE__ */ jsxs(
59
+ "aside",
60
+ {
61
+ className: `flex flex-wrap items-center gap-4 rounded-md border px-4 py-3 ${TONES[tone]} ${className}`,
62
+ children: [
63
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
64
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: title }),
65
+ children ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs opacity-80", children }) : null
66
+ ] }),
67
+ action
68
+ ]
69
+ }
70
+ );
71
+ }
72
+
73
+ // src/molecules/breadcrumb/locales.ts
74
+ var locales = {
75
+ label: "Breadcrumb"
76
+ };
77
+ function Breadcrumb({
78
+ items,
79
+ label = locales.label,
80
+ className = ""
81
+ }) {
82
+ return /* @__PURE__ */ jsx("nav", { "aria-label": label, className, children: /* @__PURE__ */ jsx("ol", { className: "flex flex-wrap items-center gap-1 text-xs", children: items.map((item, index) => {
83
+ const last = index === items.length - 1;
84
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1", children: [
85
+ index > 0 ? /* @__PURE__ */ jsx(ChevronIcon, { className: "-rotate-90 text-ink-dim", size: "sm" }) : null,
86
+ last || !item.href ? /* @__PURE__ */ jsx(
87
+ "span",
88
+ {
89
+ "aria-current": last ? "page" : void 0,
90
+ className: last ? "font-medium text-ink" : "text-ink-muted",
91
+ children: item.label
92
+ }
93
+ ) : /* @__PURE__ */ jsx(
94
+ "a",
95
+ {
96
+ href: item.href,
97
+ className: "rounded-xs px-1 py-0.5 text-ink-muted transition-colors duration-(--duration-fast) ease-out hover:bg-raised hover:text-ink-soft focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
98
+ children: item.label
99
+ }
100
+ )
101
+ ] }, item.id);
102
+ }) }) });
103
+ }
104
+ var TONES2 = {
105
+ info: "border-info/35 bg-info-soft text-info",
106
+ ok: "border-ok/35 bg-ok-soft text-ok",
107
+ warn: "border-warn/35 bg-warn-soft text-warn",
108
+ danger: "border-danger/35 bg-danger-soft text-danger"
109
+ };
110
+ function Callout({
111
+ tone = "info",
112
+ title,
113
+ children,
114
+ className = ""
115
+ }) {
116
+ return /* @__PURE__ */ jsxs("aside", { className: `rounded-md border px-4 py-3 ${TONES2[tone]} ${className}`, children: [
117
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: title }),
118
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm opacity-80", children })
119
+ ] });
120
+ }
121
+ function CardTitle({ children, hint }) {
122
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [
123
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children }),
124
+ hint ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-ink-muted", children: hint }) : null
125
+ ] });
126
+ }
127
+
128
+ // src/molecules/command-menu/locales.ts
129
+ var locales2 = { empty: "No matching commands", open: "Open command menu" };
130
+ function CommandMenu({
131
+ items,
132
+ onSelect,
133
+ label = "Search commands",
134
+ global = false
135
+ }) {
136
+ const [query, setQuery] = useState("");
137
+ const [open, setOpen] = useState(!global);
138
+ const inputRef = useRef(null);
139
+ useEffect(() => {
140
+ if (!global) return;
141
+ function handleKey(event) {
142
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
143
+ event.preventDefault();
144
+ setOpen(true);
145
+ }
146
+ if (event.key === "Escape") setOpen(false);
147
+ }
148
+ document.addEventListener("keydown", handleKey);
149
+ return () => document.removeEventListener("keydown", handleKey);
150
+ }, [global]);
151
+ useEffect(() => {
152
+ if (open) inputRef.current?.focus();
153
+ }, [open]);
154
+ const filtered = useMemo(
155
+ () => items.filter(
156
+ (item) => `${item.label} ${item.description ?? ""}`.toLowerCase().includes(query.toLowerCase())
157
+ ),
158
+ [items, query]
159
+ );
160
+ if (global && !open)
161
+ return /* @__PURE__ */ jsx(Button, { onClick: () => setOpen(true), variant: "secondary", children: locales2.open });
162
+ const menu = /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-lg flex-col gap-3 rounded-xl border border-line bg-surface p-3 shadow-modal", children: [
163
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
164
+ /* @__PURE__ */ jsx(
165
+ Input,
166
+ {
167
+ "aria-label": label,
168
+ ref: inputRef,
169
+ onChange: (event) => setQuery(event.target.value),
170
+ placeholder: label,
171
+ value: query
172
+ }
173
+ ),
174
+ /* @__PURE__ */ jsx(Kbd, { children: "\u2318K" })
175
+ ] }),
176
+ /* @__PURE__ */ jsx("div", { className: "flex max-h-72 flex-col gap-1 overflow-y-auto", children: filtered.length ? filtered.map((item) => /* @__PURE__ */ jsx(
177
+ Button,
178
+ {
179
+ className: "justify-start text-left",
180
+ onClick: () => onSelect?.(item),
181
+ variant: "ghost",
182
+ children: /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col items-start", children: [
183
+ item.label,
184
+ item.description ? /* @__PURE__ */ jsx("span", { className: "text-2xs text-ink-dim", children: item.description }) : null
185
+ ] })
186
+ },
187
+ item.id
188
+ )) : /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-sm text-ink-muted", children: locales2.empty }) })
189
+ ] });
190
+ return global ? /* @__PURE__ */ jsx(
191
+ "div",
192
+ {
193
+ className: "fixed inset-0 z-30 flex items-start justify-center bg-app/70 p-4 pt-24 backdrop-blur-sm",
194
+ onClick: () => setOpen(false),
195
+ children: /* @__PURE__ */ jsx("div", { onClick: (event) => event.stopPropagation(), children: menu })
196
+ }
197
+ ) : menu;
198
+ }
199
+
200
+ // src/molecules/drawer/locales.ts
201
+ var locales3 = { close: "Close drawer" };
202
+ function Drawer({
203
+ isOpen,
204
+ onClose,
205
+ title,
206
+ children,
207
+ closeLabel = locales3.close
208
+ }) {
209
+ const ref = useRef(null);
210
+ useEffect(() => {
211
+ const dialog = ref.current;
212
+ if (!dialog) return;
213
+ if (isOpen && !dialog.open) dialog.showModal();
214
+ if (!isOpen && dialog.open) dialog.close();
215
+ }, [isOpen]);
216
+ useEffect(() => {
217
+ const dialog = ref.current;
218
+ if (!dialog) return;
219
+ dialog.addEventListener("close", onClose);
220
+ return () => dialog.removeEventListener("close", onClose);
221
+ }, [onClose]);
222
+ return /* @__PURE__ */ jsx(
223
+ "dialog",
224
+ {
225
+ ref,
226
+ className: "fixed inset-y-0 right-0 left-auto m-0 h-full max-h-none w-full max-w-md border-y-0 border-r-0 border-line bg-surface p-0 text-ink shadow-modal backdrop:bg-app/70 backdrop:backdrop-blur-sm sm:rounded-l-xl",
227
+ "aria-modal": "true",
228
+ children: /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col", children: [
229
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 border-b border-line px-5 py-4", children: [
230
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold", children: title }),
231
+ /* @__PURE__ */ jsx(IconButton, { label: closeLabel, onClick: onClose, children: /* @__PURE__ */ jsx(CloseIcon, { size: "md" }) })
232
+ ] }),
233
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-5 py-5", children })
234
+ ] })
235
+ }
236
+ );
237
+ }
238
+ function DropdownMenu({
239
+ trigger,
240
+ children,
241
+ align = "start",
242
+ className = ""
243
+ }) {
244
+ return /* @__PURE__ */ jsxs("details", { className: `group relative ${className}`, children: [
245
+ /* @__PURE__ */ jsx("summary", { className: "list-none [&::-webkit-details-marker]:hidden", children: trigger }),
246
+ /* @__PURE__ */ jsx(
247
+ "div",
248
+ {
249
+ className: `absolute top-full z-20 mt-2 min-w-48 rounded-md border border-line bg-surface p-1 shadow-popover ${align === "end" ? "right-0" : "left-0"}`,
250
+ children
251
+ }
252
+ )
253
+ ] });
254
+ }
255
+ function Empty({ title, description }) {
256
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2 py-16 text-center", children: [
257
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-ink-soft", children: title }),
258
+ description ? /* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-ink-muted", children: description }) : null
259
+ ] });
260
+ }
261
+ function Field({
262
+ label,
263
+ htmlFor,
264
+ error,
265
+ action,
266
+ className = "",
267
+ children
268
+ }) {
269
+ const errorId = useId();
270
+ const control = isValidElement(children) ? (() => {
271
+ const child = children;
272
+ const props = child.props;
273
+ return cloneElement(child, {
274
+ "aria-describedby": error ? [props["aria-describedby"], errorId].filter(Boolean).join(" ") : props["aria-describedby"],
275
+ "aria-invalid": error ? true : props["aria-invalid"]
276
+ });
277
+ })() : children;
278
+ return /* @__PURE__ */ jsxs("div", { className: `flex min-w-0 flex-col gap-2 ${className}`, children: [
279
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [
280
+ /* @__PURE__ */ jsx("label", { htmlFor, className: "text-xs font-medium text-ink-soft", children: label }),
281
+ action
282
+ ] }),
283
+ control,
284
+ error ? /* @__PURE__ */ jsx("span", { className: "text-2xs text-danger", id: errorId, children: error }) : null
285
+ ] });
286
+ }
287
+
288
+ // src/molecules/filter-bar/locales.ts
289
+ var locales4 = { clear: "Clear filters" };
290
+ function FilterBar({
291
+ children,
292
+ resultLabel,
293
+ onClear,
294
+ className = ""
295
+ }) {
296
+ return /* @__PURE__ */ jsxs(
297
+ "div",
298
+ {
299
+ className: `flex flex-wrap items-center gap-3 rounded-md border border-line bg-panel p-3 ${className}`,
300
+ children: [
301
+ /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-3", children }),
302
+ resultLabel ? /* @__PURE__ */ jsx("span", { className: "text-xs text-ink-muted", children: resultLabel }) : null,
303
+ onClear ? /* @__PURE__ */ jsx(
304
+ "button",
305
+ {
306
+ className: "text-xs text-accent-ink underline underline-offset-4",
307
+ onClick: onClear,
308
+ type: "button",
309
+ children: locales4.clear
310
+ }
311
+ ) : null
312
+ ]
313
+ }
314
+ );
315
+ }
316
+
317
+ // src/molecules/load-error/locales.ts
318
+ var LOAD_ERROR = {
319
+ retry: "Try again"
320
+ };
321
+ function LoadError({
322
+ message,
323
+ onRetry,
324
+ retryLabel = LOAD_ERROR.retry
325
+ }) {
326
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-3 py-16 text-center", children: [
327
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-danger", children: message }),
328
+ onRetry ? /* @__PURE__ */ jsx("button", { type: "button", onClick: onRetry, className: buttonClass({ variant: "secondary" }), children: retryLabel }) : null
329
+ ] });
330
+ }
331
+ function ImagePreview({
332
+ src,
333
+ alt,
334
+ fallback,
335
+ className = ""
336
+ }) {
337
+ return /* @__PURE__ */ jsxs("details", { className: `group ${className}`, children: [
338
+ /* @__PURE__ */ jsx("summary", { className: "cursor-zoom-in list-none overflow-hidden rounded-md bg-raised [&::-webkit-details-marker]:hidden", children: src ? /* @__PURE__ */ jsx(
339
+ "img",
340
+ {
341
+ alt,
342
+ className: "aspect-[4/3] w-full object-cover transition-transform duration-(--duration-base) ease-out group-hover:scale-[1.02]",
343
+ src
344
+ }
345
+ ) : fallback }),
346
+ src ? /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-30 flex items-center justify-center bg-app/85 p-6 backdrop-blur-sm", children: /* @__PURE__ */ jsx(
347
+ "img",
348
+ {
349
+ alt,
350
+ className: "max-h-[90dvh] max-w-full rounded-md object-contain shadow-modal",
351
+ src
352
+ }
353
+ ) }) : null
354
+ ] });
355
+ }
356
+ function TreeNodeView({ node }) {
357
+ return node.children?.length ? /* @__PURE__ */ jsxs("details", { className: "group", open: true, children: [
358
+ /* @__PURE__ */ jsxs("summary", { className: "cursor-pointer list-none rounded-sm px-3 py-2 text-sm text-ink-soft hover:bg-raised [&::-webkit-details-marker]:hidden", children: [
359
+ /* @__PURE__ */ jsx("span", { className: "mr-2 text-ink-dim transition-transform duration-(--duration-fast) ease-out group-open:rotate-90", children: "\u203A" }),
360
+ node.label
361
+ ] }),
362
+ /* @__PURE__ */ jsx("div", { className: "ml-4 border-l border-line pl-2", children: node.children.map((child) => /* @__PURE__ */ jsx(TreeNodeView, { node: child }, child.id)) })
363
+ ] }) : /* @__PURE__ */ jsx("div", { className: "rounded-sm px-3 py-2 text-sm text-ink-muted hover:bg-raised", children: node.label });
364
+ }
365
+
366
+ // src/molecules/tree-view/locales.ts
367
+ var locales5 = { label: "Tree" };
368
+ function TreeView({
369
+ nodes,
370
+ className = ""
371
+ }) {
372
+ return /* @__PURE__ */ jsx("nav", { "aria-label": locales5.label, className: `flex flex-col gap-1 ${className}`, children: nodes.map((node) => /* @__PURE__ */ jsx(TreeNodeView, { node }, node.id)) });
373
+ }
374
+ function MetricCard({
375
+ label,
376
+ value,
377
+ change,
378
+ trend = "neutral",
379
+ hint,
380
+ children,
381
+ className = ""
382
+ }) {
383
+ const trendColor = trend === "up" ? "text-ok" : trend === "down" ? "text-danger" : "text-ink-muted";
384
+ return /* @__PURE__ */ jsxs("article", { className: `rounded-md border border-line bg-surface p-5 ${className}`, children: [
385
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
386
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-ink-muted", children: label }),
387
+ change ? /* @__PURE__ */ jsx("span", { className: `text-xs font-medium ${trendColor}`, children: change }) : null
388
+ ] }),
389
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-2xl font-bold text-ink", children: value }),
390
+ hint ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-ink-dim", children: hint }) : null,
391
+ children ? /* @__PURE__ */ jsx("div", { className: "mt-4", children }) : null
392
+ ] });
393
+ }
394
+
395
+ // src/molecules/menu/menu-item-style.ts
396
+ var TONES3 = {
397
+ neutral: "text-ink-soft hover:bg-raised hover:text-ink",
398
+ danger: "text-danger hover:bg-danger-soft"
399
+ };
400
+ var BASE = "flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-xs transition-colors duration-(--duration-fast) ease-out focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent";
401
+ function menuItemClass({ tone = "neutral", className = "" } = {}) {
402
+ return `${BASE} ${TONES3[tone]} ${className}`;
403
+ }
404
+ function PageHeader({
405
+ title,
406
+ subtitle,
407
+ children,
408
+ className = ""
409
+ }) {
410
+ return /* @__PURE__ */ jsxs(
411
+ "div",
412
+ {
413
+ className: `flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between sm:gap-4 ${className}`,
414
+ children: [
415
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
416
+ /* @__PURE__ */ jsx("h1", { className: "truncate text-xl font-bold", children: title }),
417
+ subtitle ? /* @__PURE__ */ jsx("p", { className: "text-sm text-ink-muted", children: subtitle }) : null
418
+ ] }),
419
+ children ? /* @__PURE__ */ jsx("div", { className: "flex w-full flex-wrap gap-3 sm:w-auto", children }) : null
420
+ ]
421
+ }
422
+ );
423
+ }
424
+
425
+ // src/molecules/pagination/locales.ts
426
+ var PAGINATION = {
427
+ label: { "en-US": "Pagination"},
428
+ previous: { "en-US": "Previous"},
429
+ next: { "en-US": "Next"},
430
+ page: { "en-US": (page) => `Page ${page}`}
431
+ };
432
+ function Pagination({
433
+ page,
434
+ pages,
435
+ onPageChange,
436
+ previousLabel = PAGINATION.previous["en-US"],
437
+ nextLabel = PAGINATION.next["en-US"],
438
+ pageLabel = PAGINATION.page["en-US"],
439
+ label = PAGINATION.label["en-US"],
440
+ className = ""
441
+ }) {
442
+ const current = Math.min(Math.max(page, 1), Math.max(pages, 1));
443
+ return /* @__PURE__ */ jsxs("nav", { "aria-label": label, className: `flex flex-wrap items-center gap-2 ${className}`, children: [
444
+ /* @__PURE__ */ jsx(
445
+ "button",
446
+ {
447
+ className: "min-h-10 rounded-md border border-line-strong px-3 text-sm text-ink-soft transition-colors duration-(--duration-fast) ease-out hover:bg-raised disabled:pointer-events-none disabled:opacity-40",
448
+ disabled: current === 1,
449
+ onClick: () => onPageChange(current - 1),
450
+ type: "button",
451
+ children: previousLabel
452
+ }
453
+ ),
454
+ /* @__PURE__ */ jsx("span", { className: "min-h-10 px-2 text-sm text-ink-muted", "aria-current": "page", children: pageLabel(current) }),
455
+ /* @__PURE__ */ jsx(
456
+ "button",
457
+ {
458
+ className: "min-h-10 rounded-md border border-line-strong px-3 text-sm text-ink-soft transition-colors duration-(--duration-fast) ease-out hover:bg-raised disabled:pointer-events-none disabled:opacity-40",
459
+ disabled: current === pages,
460
+ onClick: () => onPageChange(current + 1),
461
+ type: "button",
462
+ children: nextLabel
463
+ }
464
+ )
465
+ ] });
466
+ }
467
+
468
+ // src/molecules/snackbar-stack/locales.ts
469
+ var locales6 = { dismiss: "Dismiss notification" };
470
+ var TONES4 = {
471
+ neutral: "border-line-strong",
472
+ ok: "border-ok/50",
473
+ warn: "border-warn/50",
474
+ danger: "border-danger/50"
475
+ };
476
+ function SnackbarStack({
477
+ items,
478
+ onDismiss,
479
+ className = ""
480
+ }) {
481
+ return /* @__PURE__ */ jsx(
482
+ "div",
483
+ {
484
+ "aria-live": "polite",
485
+ className: `fixed right-4 bottom-4 z-20 flex w-[min(24rem,calc(100vw-2rem))] flex-col gap-2 ${className}`,
486
+ children: items.map((item) => /* @__PURE__ */ jsxs(
487
+ "div",
488
+ {
489
+ className: `flex items-start gap-3 rounded-md border bg-surface p-4 text-ink shadow-popover ${TONES4[item.tone ?? "neutral"]}`,
490
+ children: [
491
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
492
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: item.title }),
493
+ item.message ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-ink-muted", children: item.message }) : null
494
+ ] }),
495
+ onDismiss ? /* @__PURE__ */ jsx(
496
+ "button",
497
+ {
498
+ "aria-label": locales6.dismiss,
499
+ className: "text-xs text-ink-muted hover:text-ink",
500
+ onClick: () => onDismiss(item.id),
501
+ type: "button",
502
+ children: "\xD7"
503
+ }
504
+ ) : null
505
+ ]
506
+ },
507
+ item.id
508
+ ))
509
+ }
510
+ );
511
+ }
512
+ function StatCard({
513
+ label,
514
+ value,
515
+ hint,
516
+ color = "",
517
+ attention = false,
518
+ className = ""
519
+ }) {
520
+ const length = String(value).length;
521
+ const size = length <= 7 ? "text-2xl" : length <= 12 ? "text-lg" : "text-sm";
522
+ return /* @__PURE__ */ jsxs(
523
+ Card,
524
+ {
525
+ padding: "sm",
526
+ className: `flex flex-col gap-1 ${attention ? "attention" : ""} ${className}`,
527
+ children: [
528
+ /* @__PURE__ */ jsx(Label, { children: label }),
529
+ /* @__PURE__ */ jsx("span", { className: `truncate ${size} leading-tight font-bold ${color}`, children: value }),
530
+ hint ? /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-ink-muted", children: hint }) : null
531
+ ]
532
+ }
533
+ );
534
+ }
535
+ function Stepper({
536
+ steps,
537
+ current,
538
+ className = ""
539
+ }) {
540
+ return /* @__PURE__ */ jsx("ol", { className: `flex flex-col gap-4 sm:flex-row sm:items-start sm:gap-0 ${className}`, children: steps.map((step, index) => /* @__PURE__ */ jsxs(
541
+ "li",
542
+ {
543
+ className: "relative flex flex-1 items-start gap-3 sm:flex-col sm:items-center sm:text-center",
544
+ children: [
545
+ index < steps.length - 1 ? /* @__PURE__ */ jsx("span", { className: "absolute top-5 left-5 h-full w-px bg-line sm:top-5 sm:left-1/2 sm:h-px sm:w-full" }) : null,
546
+ /* @__PURE__ */ jsx(
547
+ "span",
548
+ {
549
+ className: `relative z-1 flex size-10 shrink-0 items-center justify-center rounded-full border text-sm font-medium ${index < current ? "border-accent bg-accent text-on-accent" : index === current ? "border-accent text-accent-ink ring-4 ring-accent-soft" : "border-line-strong text-ink-dim"}`,
550
+ children: index + 1
551
+ }
552
+ ),
553
+ /* @__PURE__ */ jsxs("span", { className: "relative z-1 flex flex-col pt-2 sm:pt-3", children: [
554
+ /* @__PURE__ */ jsx("strong", { className: "text-sm text-ink", children: step.label }),
555
+ step.description ? /* @__PURE__ */ jsx("span", { className: "mt-1 text-xs text-ink-muted", children: step.description }) : null
556
+ ] })
557
+ ]
558
+ },
559
+ step.id
560
+ )) });
561
+ }
562
+
563
+ // src/molecules/tabs/locales.ts
564
+ var TABS = {
565
+ label: { "en-US": "Tabs"}
566
+ };
567
+ function Tabs({
568
+ items,
569
+ value,
570
+ onValueChange,
571
+ label = TABS.label["en-US"],
572
+ className = ""
573
+ }) {
574
+ const active = items.find((item) => item.value === value) ?? items[0];
575
+ function onKeyDown(event) {
576
+ const index = items.findIndex((item) => item.value === active?.value);
577
+ const direction = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0;
578
+ const target = event.key === "Home" ? items[0] : event.key === "End" ? items.at(-1) : direction ? items[(index + direction + items.length) % items.length] : void 0;
579
+ if (!target || target.disabled) return;
580
+ event.preventDefault();
581
+ onValueChange(target.value);
582
+ }
583
+ return /* @__PURE__ */ jsxs("div", { className: `flex min-w-0 flex-col gap-4 ${className}`, children: [
584
+ /* @__PURE__ */ jsx(
585
+ "div",
586
+ {
587
+ "aria-label": label,
588
+ className: "flex min-w-0 gap-1 overflow-x-auto border-b border-line",
589
+ role: "tablist",
590
+ children: items.map((item) => /* @__PURE__ */ jsx(
591
+ "button",
592
+ {
593
+ "aria-selected": item.value === active?.value,
594
+ id: `tab-${item.value}`,
595
+ className: `min-h-10 shrink-0 border-b-2 px-3 text-sm transition-colors duration-(--duration-fast) ease-out ${item.value === active?.value ? "border-accent font-medium text-ink" : "border-transparent text-ink-muted hover:border-line-strong hover:text-ink"}`,
596
+ disabled: item.disabled,
597
+ onClick: () => onValueChange(item.value),
598
+ onKeyDown,
599
+ role: "tab",
600
+ tabIndex: item.value === active?.value ? 0 : -1,
601
+ type: "button",
602
+ children: item.label
603
+ },
604
+ item.value
605
+ ))
606
+ }
607
+ ),
608
+ active ? /* @__PURE__ */ jsx("div", { "aria-labelledby": `tab-${active.value}`, role: "tabpanel", children: active.content }) : null
609
+ ] });
610
+ }
611
+ var SIDES = {
612
+ top: "bottom-full left-1/2 mb-2 -translate-x-1/2",
613
+ bottom: "top-full left-1/2 mt-2 -translate-x-1/2",
614
+ left: "right-full top-1/2 mr-2 -translate-y-1/2",
615
+ right: "left-full top-1/2 ml-2 -translate-y-1/2"
616
+ };
617
+ function Tooltip({
618
+ id,
619
+ content,
620
+ side = "top",
621
+ children,
622
+ className = ""
623
+ }) {
624
+ return /* @__PURE__ */ jsxs("span", { className: `group relative inline-flex ${className}`, children: [
625
+ /* @__PURE__ */ jsx("span", { "aria-describedby": id, className: "inline-flex", children }),
626
+ /* @__PURE__ */ jsx(
627
+ "span",
628
+ {
629
+ id,
630
+ role: "tooltip",
631
+ className: `pointer-events-none absolute z-50 w-max max-w-64 rounded-sm border border-line-strong bg-raised px-2 py-1 text-2xs text-ink-soft opacity-0 shadow-popover transition-opacity duration-(--duration-fast) ease-out group-focus-within:opacity-100 group-hover:opacity-100 ${SIDES[side]}`,
632
+ children: content
633
+ }
634
+ )
635
+ ] });
636
+ }
637
+
638
+ // src/molecules/toast/locales.ts
639
+ var locales7 = { dismiss: "Dismiss notification" };
640
+ var TONES5 = {
641
+ info: "border-info/35 bg-surface",
642
+ ok: "border-ok/35 bg-surface",
643
+ warn: "border-warn/35 bg-surface",
644
+ danger: "border-danger/35 bg-surface"
645
+ };
646
+ function Toast({
647
+ tone = "info",
648
+ title,
649
+ children,
650
+ onDismiss,
651
+ dismissLabel = locales7.dismiss,
652
+ className = ""
653
+ }) {
654
+ return /* @__PURE__ */ jsxs(
655
+ "div",
656
+ {
657
+ "aria-live": "polite",
658
+ className: `flex items-start gap-4 rounded-md border p-4 shadow-popover ${TONES5[tone]} ${className}`,
659
+ role: "status",
660
+ children: [
661
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
662
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-ink", children: title }),
663
+ children ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-ink-muted", children }) : null
664
+ ] }),
665
+ onDismiss ? /* @__PURE__ */ jsx(
666
+ "button",
667
+ {
668
+ "aria-label": dismissLabel,
669
+ className: "rounded-xs px-1 text-xs text-ink-muted transition-colors duration-(--duration-fast) ease-out hover:text-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
670
+ onClick: onDismiss,
671
+ type: "button",
672
+ children: "\xD7"
673
+ }
674
+ ) : null
675
+ ]
676
+ }
677
+ );
678
+ }
679
+
680
+ export { Accordion, Banner, Breadcrumb, Callout, CardTitle, CommandMenu, Drawer, DropdownMenu, Empty, Field, FilterBar, ImagePreview, LoadError, MetricCard, PageHeader, Pagination, SnackbarStack, StatCard, Stepper, Tabs, Toast, Tooltip, TreeView, menuItemClass };
681
+ //# sourceMappingURL=chunk-AHE2576G.js.map
682
+ //# sourceMappingURL=chunk-AHE2576G.js.map