@bysages/react 0.0.1 → 0.1.1
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/README.md +2 -2
- package/dist/index.d.mts +1107 -97
- package/dist/index.mjs +2490 -201
- package/package.json +4 -2
package/dist/index.mjs
CHANGED
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
import { injectComponentStyle } from "@bysages/core";
|
|
2
2
|
import { Accordion as Accordion$1 } from "@ark-ui/react/accordion";
|
|
3
|
-
import { renderHtml } from "@tanstack/markdown/html";
|
|
4
|
-
import { Children, cloneElement, createContext, isValidElement, useContext, useEffect, useLayoutEffect, useMemo, useReducer, useRef } from "react";
|
|
5
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Children, cloneElement, createContext, isValidElement, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
5
|
+
import { Field as Field$1, useFieldContext } from "@ark-ui/react/field";
|
|
6
|
+
import { Popover as Popover$1 } from "@ark-ui/react/popover";
|
|
7
|
+
import { Portal } from "@ark-ui/react/portal";
|
|
6
8
|
import { Collapsible as Collapsible$1 } from "@ark-ui/react/collapsible";
|
|
7
|
-
import {
|
|
9
|
+
import { renderHtml } from "@tanstack/markdown/html";
|
|
8
10
|
import { AngleSlider as AngleSlider$1 } from "@ark-ui/react/angle-slider";
|
|
11
|
+
import { createFileTreeCollection, createGridCollection, createTreeCollection, useAsyncList, useListCollection, useListCollection as useListCollection$1, useListSelection } from "@ark-ui/react/collection";
|
|
12
|
+
import { Combobox as Combobox$1 } from "@ark-ui/react/combobox";
|
|
9
13
|
import { Avatar as Avatar$1 } from "@ark-ui/react/avatar";
|
|
10
14
|
import { DatePicker as DatePicker$1 } from "@ark-ui/react/date-picker";
|
|
15
|
+
import { useEnvironmentContext } from "@ark-ui/react/environment";
|
|
16
|
+
import { useLocaleContext } from "@ark-ui/react/locale";
|
|
17
|
+
import * as cascade from "@zag-js/cascade-select";
|
|
18
|
+
import { normalizeProps, useMachine } from "@zag-js/react";
|
|
11
19
|
import { Carousel as Carousel$1 } from "@ark-ui/react/carousel";
|
|
12
20
|
import { Checkbox as Checkbox$1 } from "@ark-ui/react/checkbox";
|
|
13
21
|
import { Clipboard as Clipboard$1 } from "@ark-ui/react/clipboard";
|
|
22
|
+
import { ClientOnly } from "@ark-ui/react/client-only";
|
|
14
23
|
import { ColorPicker as ColorPicker$1 } from "@ark-ui/react/color-picker";
|
|
15
|
-
import { Combobox as Combobox$1 } from "@ark-ui/react/combobox";
|
|
16
|
-
import { DateInput as DateInput$1 } from "@ark-ui/react/date-input";
|
|
17
24
|
import { Dialog as Dialog$1 } from "@ark-ui/react/dialog";
|
|
25
|
+
import { DateInput as DateInput$1 } from "@ark-ui/react/date-input";
|
|
26
|
+
import { DownloadTrigger, useDownload } from "@ark-ui/react/download-trigger";
|
|
18
27
|
import { Drawer as Drawer$1 } from "@ark-ui/react/drawer";
|
|
19
28
|
import { Editable as Editable$1 } from "@ark-ui/react/editable";
|
|
20
29
|
import { Fieldset as Fieldset$1 } from "@ark-ui/react/fieldset";
|
|
21
30
|
import { FileUpload as FileUpload$1 } from "@ark-ui/react/file-upload";
|
|
22
31
|
import { FloatingPanel as FloatingPanel$1 } from "@ark-ui/react/floating-panel";
|
|
32
|
+
import { FocusTrap } from "@ark-ui/react/focus-trap";
|
|
23
33
|
import { Format as Format$1 } from "@ark-ui/react/format";
|
|
24
34
|
import { Frame as Frame$1 } from "@ark-ui/react/frame";
|
|
25
35
|
import { Highlight as Highlight$1 } from "@ark-ui/react/highlight";
|
|
26
36
|
import { HoverCard as HoverCard$1 } from "@ark-ui/react/hover-card";
|
|
27
37
|
import { ImageCropper as ImageCropper$1 } from "@ark-ui/react/image-cropper";
|
|
28
38
|
import { JsonTreeView as JsonTreeView$1 } from "@ark-ui/react/json-tree-view";
|
|
29
|
-
import { Listbox as Listbox$1
|
|
39
|
+
import { Listbox as Listbox$1 } from "@ark-ui/react/listbox";
|
|
30
40
|
import { Marquee as Marquee$1 } from "@ark-ui/react/marquee";
|
|
31
41
|
import { Menu as Menu$1 } from "@ark-ui/react/menu";
|
|
32
42
|
import { NavigationMenu as NavigationMenu$1 } from "@ark-ui/react/navigation-menu";
|
|
@@ -34,7 +44,7 @@ import { NumberInput as NumberInput$1 } from "@ark-ui/react/number-input";
|
|
|
34
44
|
import { Pagination as Pagination$1 } from "@ark-ui/react/pagination";
|
|
35
45
|
import { PasswordInput as PasswordInput$1 } from "@ark-ui/react/password-input";
|
|
36
46
|
import { PinInput as PinInput$1 } from "@ark-ui/react/pin-input";
|
|
37
|
-
import {
|
|
47
|
+
import { Presence, PresenceProvider, usePresence, usePresenceContext } from "@ark-ui/react/presence";
|
|
38
48
|
import { Progress as Progress$1 } from "@ark-ui/react/progress";
|
|
39
49
|
import { QrCode as QrCode$1 } from "@ark-ui/react/qr-code";
|
|
40
50
|
import { RadioGroup as RadioGroup$1 } from "@ark-ui/react/radio-group";
|
|
@@ -59,7 +69,7 @@ import { Toggle as Toggle$1 } from "@ark-ui/react/toggle";
|
|
|
59
69
|
import { ToggleGroup as ToggleGroup$1 } from "@ark-ui/react/toggle-group";
|
|
60
70
|
import { Tooltip as Tooltip$1 } from "@ark-ui/react/tooltip";
|
|
61
71
|
import { Tour as Tour$1, useTour } from "@ark-ui/react/tour";
|
|
62
|
-
import { TreeView as TreeView$1 } from "@ark-ui/react/tree-view";
|
|
72
|
+
import { TreeView as TreeView$1, createTreeCollection as createTreeCollection$1 } from "@ark-ui/react/tree-view";
|
|
63
73
|
export * from "@bysages/core";
|
|
64
74
|
//#region src/components/accordion/index.tsx
|
|
65
75
|
/** Ark's Accordion, dressed in the paper-and-ink system: a ruled sheet
|
|
@@ -68,6 +78,21 @@ export * from "@bysages/core";
|
|
|
68
78
|
const Accordion = Accordion$1;
|
|
69
79
|
injectComponentStyle("accordion");
|
|
70
80
|
//#endregion
|
|
81
|
+
//#region src/components/affix/index.tsx
|
|
82
|
+
function Affix({ offsetTop = "0px", offsetBottom = "0px", ...rest }) {
|
|
83
|
+
return /* @__PURE__ */ jsx("div", {
|
|
84
|
+
...rest,
|
|
85
|
+
style: {
|
|
86
|
+
...rest.style,
|
|
87
|
+
top: offsetTop,
|
|
88
|
+
bottom: offsetBottom
|
|
89
|
+
},
|
|
90
|
+
"data-scope": "affix",
|
|
91
|
+
"data-part": "root"
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
injectComponentStyle("affix");
|
|
95
|
+
//#endregion
|
|
71
96
|
//#region src/components/button/index.tsx
|
|
72
97
|
function Button({ variant = "solid", tone = "ink", size = "md", square = false, asChild = false, disabled = false, type = "button", children, ...rest }) {
|
|
73
98
|
const partProps = {
|
|
@@ -93,12 +118,31 @@ function Button({ variant = "solid", tone = "ink", size = "md", square = false,
|
|
|
93
118
|
}
|
|
94
119
|
injectComponentStyle("button");
|
|
95
120
|
//#endregion
|
|
96
|
-
//#region src/components/
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
121
|
+
//#region src/components/ai-action/index.tsx
|
|
122
|
+
function Action({ label, children, ...rest }) {
|
|
123
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
124
|
+
variant: "ghost",
|
|
125
|
+
size: "sm",
|
|
126
|
+
square: true,
|
|
127
|
+
"aria-label": label,
|
|
128
|
+
title: label,
|
|
129
|
+
...rest,
|
|
130
|
+
children
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
injectComponentStyle("ai");
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/components/ai-message/index.tsx
|
|
136
|
+
function Message({ role = "assistant", children, ...rest }) {
|
|
137
|
+
return /* @__PURE__ */ jsx("article", {
|
|
138
|
+
...rest,
|
|
139
|
+
"data-scope": "ai",
|
|
140
|
+
"data-part": "message",
|
|
141
|
+
"data-role": role,
|
|
142
|
+
children
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
injectComponentStyle("ai");
|
|
102
146
|
//#endregion
|
|
103
147
|
//#region src/components/field/index.tsx
|
|
104
148
|
/** Ark's Field, dressed in the paper-and-ink system: a tracked label, a
|
|
@@ -108,38 +152,308 @@ injectComponentStyle("collapsible");
|
|
|
108
152
|
const Field = Field$1;
|
|
109
153
|
injectComponentStyle("field");
|
|
110
154
|
//#endregion
|
|
111
|
-
//#region src/components/
|
|
112
|
-
/**
|
|
113
|
-
* the
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* `
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
155
|
+
//#region src/components/mentions/use-mentions.ts
|
|
156
|
+
/** The @-detection machinery behind a mention field: watch the caret,
|
|
157
|
+
* offer the matching candidates, and answer for the keys that drive
|
|
158
|
+
* them. The field element arrives as a getter because hosts wrap it
|
|
159
|
+
* differently (a bare textarea, a field part's ref).
|
|
160
|
+
*
|
|
161
|
+
* `onKeydown` answers whether the vessel consumed the key, so a host
|
|
162
|
+
* with its own Enter semantics — a composer that sends — can yield to
|
|
163
|
+
* the candidates first and act only when the vessel stands down. */
|
|
164
|
+
function useMentions(options, textarea, handlers) {
|
|
165
|
+
const [popupOpen, setPopupOpen] = useState(false);
|
|
166
|
+
const [matches, setMatches] = useState([]);
|
|
167
|
+
const [active, setActive] = useState(0);
|
|
168
|
+
const anchorIndex = useRef(0);
|
|
169
|
+
const caretIndex = useRef(0);
|
|
170
|
+
const resolve = () => typeof options === "function" ? options() : options;
|
|
171
|
+
const closePopup = () => {
|
|
172
|
+
setPopupOpen(false);
|
|
173
|
+
setMatches([]);
|
|
174
|
+
};
|
|
175
|
+
const detect = () => {
|
|
176
|
+
const text = handlers.getText();
|
|
177
|
+
const caret = textarea()?.selectionStart ?? text.length;
|
|
178
|
+
caretIndex.current = caret;
|
|
179
|
+
const head = text.slice(0, caret);
|
|
180
|
+
const char = resolve().trigger ?? "@";
|
|
181
|
+
const anchor = head.lastIndexOf(char);
|
|
182
|
+
const token = anchor === -1 ? "" : head.slice(anchor + char.length);
|
|
183
|
+
if (anchor === -1 || /\s/.test(token)) {
|
|
184
|
+
closePopup();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const found = resolve().items.filter((entry) => entry.label.toLowerCase().startsWith(token.toLowerCase()));
|
|
188
|
+
setMatches(found);
|
|
189
|
+
setActive(0);
|
|
190
|
+
anchorIndex.current = anchor;
|
|
191
|
+
setPopupOpen(found.length > 0);
|
|
192
|
+
};
|
|
193
|
+
const insert = (entry) => {
|
|
194
|
+
const text = handlers.getText();
|
|
195
|
+
const char = resolve().trigger ?? "@";
|
|
196
|
+
const next = text.slice(0, anchorIndex.current) + char + entry.label + " " + text.slice(caretIndex.current);
|
|
197
|
+
handlers.setText(next);
|
|
198
|
+
closePopup();
|
|
199
|
+
setTimeout(() => {
|
|
200
|
+
const el = textarea();
|
|
201
|
+
if (!el) return;
|
|
202
|
+
const caret = anchorIndex.current + char.length + entry.label.length + 1;
|
|
203
|
+
el.focus();
|
|
204
|
+
el.setSelectionRange(caret, caret);
|
|
205
|
+
}, 0);
|
|
206
|
+
};
|
|
207
|
+
/** Feed the field's input events through here — the vessel watches
|
|
208
|
+
* the text as it lands, from the element itself. */
|
|
209
|
+
const onInput = () => detect();
|
|
210
|
+
/** Arrows move, Enter inserts, Escape dismisses. Answers `true` when
|
|
211
|
+
* the vessel consumed the key. */
|
|
212
|
+
const onKeydown = (event) => {
|
|
213
|
+
if (!popupOpen || matches.length === 0) return false;
|
|
214
|
+
if (event.key === "ArrowDown") {
|
|
215
|
+
event.preventDefault();
|
|
216
|
+
setActive((current) => (current + 1) % matches.length);
|
|
217
|
+
} else if (event.key === "ArrowUp") {
|
|
218
|
+
event.preventDefault();
|
|
219
|
+
setActive((current) => (current - 1 + matches.length) % matches.length);
|
|
220
|
+
} else if (event.key === "Enter") {
|
|
221
|
+
event.preventDefault();
|
|
222
|
+
insert(matches[active]);
|
|
223
|
+
} else if (event.key === "Escape") closePopup();
|
|
224
|
+
else return false;
|
|
225
|
+
return true;
|
|
226
|
+
};
|
|
227
|
+
return {
|
|
228
|
+
open: popupOpen,
|
|
229
|
+
matches,
|
|
230
|
+
active,
|
|
231
|
+
setActive,
|
|
232
|
+
insert,
|
|
233
|
+
close: closePopup,
|
|
234
|
+
onInput,
|
|
235
|
+
onKeydown
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/components/mentions/index.tsx
|
|
240
|
+
/** The vessel: the candidates themselves as a floating card. The anchor
|
|
241
|
+
* is virtual — a live rectangle off the host's field — so a host keeps
|
|
242
|
+
* its own anatomy (the textarea rides where the host puts it) and the
|
|
243
|
+
* vessel still points at the right place. Shares the detection state
|
|
244
|
+
* with the host through `useMentions`. */
|
|
245
|
+
function MentionsVessel({ open = false, matches = [], active = 0, anchor = null, onInsert, onActiveChange, onOpenChange }) {
|
|
246
|
+
return /* @__PURE__ */ jsx(Popover$1.Root, {
|
|
247
|
+
open,
|
|
248
|
+
onOpenChange: (details) => onOpenChange?.(details.open),
|
|
249
|
+
positioning: {
|
|
250
|
+
placement: "bottom-start",
|
|
251
|
+
getAnchorRect: () => anchor?.getBoundingClientRect() ?? null
|
|
252
|
+
},
|
|
253
|
+
children: /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { children: /* @__PURE__ */ jsx(Popover$1.Content, {
|
|
254
|
+
asChild: true,
|
|
255
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
256
|
+
"data-scope": "mentions",
|
|
257
|
+
"data-part": "popup",
|
|
258
|
+
children: matches.map((entry, index) => /* @__PURE__ */ jsx("div", {
|
|
259
|
+
"data-scope": "mentions",
|
|
260
|
+
"data-part": "option",
|
|
261
|
+
"data-active": index === active ? "" : void 0,
|
|
262
|
+
onMouseEnter: () => onActiveChange?.(index),
|
|
263
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
264
|
+
onClick: () => onInsert?.(entry),
|
|
265
|
+
children: entry.label
|
|
266
|
+
}, entry.value))
|
|
267
|
+
})
|
|
268
|
+
}) }) })
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
function Mentions({ items = [], value, trigger = "@", placeholder, autoresize = false, invalid = false, onValueChange, children, ...rest }) {
|
|
272
|
+
const [internal, setInternal] = useState("");
|
|
273
|
+
const fieldRef = useRef(null);
|
|
274
|
+
const el = () => fieldRef.current;
|
|
275
|
+
const current = value ?? internal;
|
|
276
|
+
const mentions = useMentions({
|
|
277
|
+
items,
|
|
278
|
+
trigger
|
|
279
|
+
}, el, {
|
|
280
|
+
getText: () => el()?.value ?? current,
|
|
281
|
+
setText: (next) => {
|
|
282
|
+
setInternal(next);
|
|
283
|
+
onValueChange?.(next);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
const handleChange = (event) => {
|
|
287
|
+
const node = event.currentTarget;
|
|
288
|
+
setInternal(node.value);
|
|
289
|
+
onValueChange?.(node.value);
|
|
290
|
+
mentions.onInput();
|
|
291
|
+
};
|
|
292
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
122
293
|
...rest,
|
|
123
|
-
"data-scope": "
|
|
124
|
-
"data-part":
|
|
125
|
-
children
|
|
294
|
+
"data-scope": "mentions",
|
|
295
|
+
"data-part": "root",
|
|
296
|
+
children: [
|
|
297
|
+
/* @__PURE__ */ jsx(Field.Textarea, {
|
|
298
|
+
ref: fieldRef,
|
|
299
|
+
autoresize,
|
|
300
|
+
rows: 3,
|
|
301
|
+
placeholder,
|
|
302
|
+
value: current,
|
|
303
|
+
onChange: handleChange,
|
|
304
|
+
onKeyDown: (event) => mentions.onKeydown(event),
|
|
305
|
+
"data-invalid": invalid || void 0,
|
|
306
|
+
"data-scope": "mentions",
|
|
307
|
+
"data-part": "textarea"
|
|
308
|
+
}),
|
|
309
|
+
/* @__PURE__ */ jsx(MentionsVessel, {
|
|
310
|
+
open: mentions.open,
|
|
311
|
+
matches: mentions.matches,
|
|
312
|
+
active: mentions.active,
|
|
313
|
+
anchor: el(),
|
|
314
|
+
onInsert: mentions.insert,
|
|
315
|
+
onActiveChange: mentions.setActive,
|
|
316
|
+
onOpenChange: (open) => {
|
|
317
|
+
if (!open) mentions.close();
|
|
318
|
+
}
|
|
319
|
+
}),
|
|
320
|
+
children
|
|
321
|
+
]
|
|
126
322
|
});
|
|
127
|
-
Component.displayName = "Ai" + name;
|
|
128
|
-
return Component;
|
|
129
323
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
324
|
+
injectComponentStyle("mentions");
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region src/components/ai-prompt-input/index.tsx
|
|
327
|
+
const arrowUpGlyph = /* @__PURE__ */ jsx("svg", {
|
|
328
|
+
viewBox: "0 0 16 16",
|
|
329
|
+
width: 14,
|
|
330
|
+
height: 14,
|
|
331
|
+
"aria-hidden": "true",
|
|
332
|
+
fill: "none",
|
|
333
|
+
stroke: "currentColor",
|
|
334
|
+
strokeWidth: 1.5,
|
|
335
|
+
strokeLinecap: "square",
|
|
336
|
+
children: /* @__PURE__ */ jsx("path", { d: "M8 13V3M3.5 7.5 8 3l4.5 4.5" })
|
|
133
337
|
});
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
338
|
+
const stopGlyph = /* @__PURE__ */ jsx("svg", {
|
|
339
|
+
viewBox: "0 0 16 16",
|
|
340
|
+
width: 14,
|
|
341
|
+
height: 14,
|
|
342
|
+
"aria-hidden": "true",
|
|
343
|
+
children: /* @__PURE__ */ jsx("rect", {
|
|
344
|
+
x: 4.5,
|
|
345
|
+
y: 4.5,
|
|
346
|
+
width: 7,
|
|
347
|
+
height: 7,
|
|
348
|
+
fill: "currentColor"
|
|
349
|
+
})
|
|
140
350
|
});
|
|
351
|
+
/** An empty slot leaves no part in the anatomy — the bare vessel keeps
|
|
352
|
+
* its single-line posture. */
|
|
353
|
+
function row(part, content) {
|
|
354
|
+
if (content == null || Array.isArray(content) && content.length === 0) return null;
|
|
355
|
+
return /* @__PURE__ */ jsx("div", {
|
|
356
|
+
"data-scope": "ai",
|
|
357
|
+
"data-part": part,
|
|
358
|
+
children: content
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder = "Send a message", disabled = false, busy = false, mentions, header, leading, trailing, footer, footerEnd, ...rest }) {
|
|
362
|
+
const fieldRef = useRef(null);
|
|
363
|
+
const mentionState = useMentions(() => ({
|
|
364
|
+
items: mentions?.items ?? [],
|
|
365
|
+
trigger: mentions?.trigger
|
|
366
|
+
}), () => fieldRef.current, {
|
|
367
|
+
getText: () => fieldRef.current?.value ?? value,
|
|
368
|
+
setText: (next) => onValueChange?.(next)
|
|
369
|
+
});
|
|
370
|
+
const mentionsActive = mentions != null;
|
|
371
|
+
const submit = () => {
|
|
372
|
+
const text = value.trim();
|
|
373
|
+
if (!text || disabled || busy) return;
|
|
374
|
+
onSubmit?.(text);
|
|
375
|
+
onValueChange?.("");
|
|
376
|
+
};
|
|
377
|
+
const seal = busy ? /* @__PURE__ */ jsx(Button, {
|
|
378
|
+
variant: "solid",
|
|
379
|
+
size: "sm",
|
|
380
|
+
square: true,
|
|
381
|
+
type: "button",
|
|
382
|
+
"aria-label": "Stop",
|
|
383
|
+
disabled,
|
|
384
|
+
onClick: () => onStop?.(),
|
|
385
|
+
children: stopGlyph
|
|
386
|
+
}) : /* @__PURE__ */ jsx(Button, {
|
|
387
|
+
variant: "solid",
|
|
388
|
+
size: "sm",
|
|
389
|
+
square: true,
|
|
390
|
+
type: "submit",
|
|
391
|
+
"aria-label": "Send",
|
|
392
|
+
disabled: disabled || !value.trim(),
|
|
393
|
+
children: arrowUpGlyph
|
|
394
|
+
});
|
|
395
|
+
const hasFooter = footer != null && (!Array.isArray(footer) || footer.length > 0);
|
|
396
|
+
return /* @__PURE__ */ jsxs("form", {
|
|
397
|
+
...rest,
|
|
398
|
+
"data-scope": "ai",
|
|
399
|
+
"data-part": "prompt",
|
|
400
|
+
onSubmit: (event) => {
|
|
401
|
+
event.preventDefault();
|
|
402
|
+
submit();
|
|
403
|
+
},
|
|
404
|
+
children: [
|
|
405
|
+
row("prompt-header", header),
|
|
406
|
+
/* @__PURE__ */ jsxs("div", {
|
|
407
|
+
"data-scope": "ai",
|
|
408
|
+
"data-part": "prompt-main",
|
|
409
|
+
children: [
|
|
410
|
+
row("prompt-leading", leading),
|
|
411
|
+
/* @__PURE__ */ jsx(Field.Root, { children: /* @__PURE__ */ jsx(Field.Textarea, {
|
|
412
|
+
ref: fieldRef,
|
|
413
|
+
autoresize: true,
|
|
414
|
+
rows: 1,
|
|
415
|
+
value,
|
|
416
|
+
placeholder,
|
|
417
|
+
disabled,
|
|
418
|
+
onChange: (event) => {
|
|
419
|
+
onValueChange?.(event.target.value);
|
|
420
|
+
mentionState.onInput();
|
|
421
|
+
},
|
|
422
|
+
onKeyDown: (event) => {
|
|
423
|
+
if (mentionState.onKeydown(event)) return;
|
|
424
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
425
|
+
event.preventDefault();
|
|
426
|
+
submit();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}) }),
|
|
430
|
+
mentionsActive ? /* @__PURE__ */ jsx(MentionsVessel, {
|
|
431
|
+
open: mentionState.open,
|
|
432
|
+
matches: mentionState.matches,
|
|
433
|
+
active: mentionState.active,
|
|
434
|
+
anchor: fieldRef.current,
|
|
435
|
+
onInsert: mentionState.insert,
|
|
436
|
+
onActiveChange: mentionState.setActive,
|
|
437
|
+
onOpenChange: (open) => {
|
|
438
|
+
if (!open) mentionState.close();
|
|
439
|
+
}
|
|
440
|
+
}) : null,
|
|
441
|
+
row("prompt-trailing", hasFooter ? trailing : trailing ?? seal)
|
|
442
|
+
]
|
|
443
|
+
}),
|
|
444
|
+
hasFooter ? /* @__PURE__ */ jsxs("div", {
|
|
445
|
+
"data-scope": "ai",
|
|
446
|
+
"data-part": "prompt-footer",
|
|
447
|
+
children: [footer, row("prompt-end", footerEnd == null ? seal : /* @__PURE__ */ jsxs(Fragment, { children: [footerEnd, seal] }))]
|
|
448
|
+
}) : null
|
|
449
|
+
]
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
injectComponentStyle("ai");
|
|
453
|
+
//#endregion
|
|
454
|
+
//#region src/components/ai/chevron.tsx
|
|
141
455
|
/** The folding chevron the shared indicator turns. */
|
|
142
|
-
const chevron$
|
|
456
|
+
const chevron$2 = /* @__PURE__ */ jsx("svg", {
|
|
143
457
|
viewBox: "0 0 16 16",
|
|
144
458
|
fill: "none",
|
|
145
459
|
"aria-hidden": "true",
|
|
@@ -151,62 +465,40 @@ const chevron$1 = /* @__PURE__ */ jsx("svg", {
|
|
|
151
465
|
strokeLinejoin: "round"
|
|
152
466
|
})
|
|
153
467
|
});
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
function Response({ content, ...rest }) {
|
|
164
|
-
return /* @__PURE__ */ jsx("div", {
|
|
165
|
-
...rest,
|
|
166
|
-
"data-scope": "ai",
|
|
167
|
-
"data-part": "response",
|
|
168
|
-
dangerouslySetInnerHTML: { __html: renderHtml(content) }
|
|
169
|
-
});
|
|
170
|
-
}
|
|
468
|
+
//#endregion
|
|
469
|
+
//#region src/components/collapsible/index.tsx
|
|
470
|
+
/** Ark's Collapsible, dressed in the paper-and-ink system: one control on
|
|
471
|
+
* the paper, its panel dissolving open to the machine's measured height.
|
|
472
|
+
* The API is Ark's own — Root, Trigger, Content, Indicator. */
|
|
473
|
+
const Collapsible = Collapsible$1;
|
|
474
|
+
injectComponentStyle("collapsible");
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/components/ai-reasoning/index.tsx
|
|
171
477
|
function Reasoning({ label = "Thinking", children, ...rest }) {
|
|
172
478
|
return /* @__PURE__ */ jsxs(Collapsible.Root, {
|
|
173
479
|
...rest,
|
|
174
480
|
"data-ai": "reasoning",
|
|
175
|
-
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, { children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx(Collapsible.Indicator, { children: chevron$
|
|
481
|
+
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, { children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx(Collapsible.Indicator, { children: chevron$2 })] }), /* @__PURE__ */ jsx(Collapsible.Content, { children: /* @__PURE__ */ jsx("div", {
|
|
176
482
|
"data-scope": "ai",
|
|
177
483
|
"data-part": "reasoning-content",
|
|
178
484
|
children
|
|
179
485
|
}) })]
|
|
180
486
|
});
|
|
181
487
|
}
|
|
182
|
-
|
|
183
|
-
|
|
488
|
+
injectComponentStyle("ai");
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region src/components/ai-response/index.tsx
|
|
491
|
+
function Response({ content, highlighter, ...rest }) {
|
|
492
|
+
return /* @__PURE__ */ jsx("div", {
|
|
184
493
|
...rest,
|
|
185
|
-
"data-
|
|
186
|
-
"data-
|
|
187
|
-
|
|
188
|
-
/* @__PURE__ */ jsx("span", { children: label ?? name }),
|
|
189
|
-
status ? /* @__PURE__ */ jsx("span", {
|
|
190
|
-
"data-scope": "ai",
|
|
191
|
-
"data-part": "tool-status",
|
|
192
|
-
children: status.charAt(0).toUpperCase() + status.slice(1)
|
|
193
|
-
}) : null,
|
|
194
|
-
/* @__PURE__ */ jsx(Collapsible.Indicator, { children: chevron$1 })
|
|
195
|
-
] }), /* @__PURE__ */ jsx(Collapsible.Content, { children: /* @__PURE__ */ jsxs("div", {
|
|
196
|
-
"data-scope": "ai",
|
|
197
|
-
"data-part": "tool-body",
|
|
198
|
-
children: [input ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
199
|
-
"data-scope": "ai",
|
|
200
|
-
"data-part": "tool-label",
|
|
201
|
-
children: "Input"
|
|
202
|
-
}), /* @__PURE__ */ jsx("pre", { children: input })] }) : null, output ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
203
|
-
"data-scope": "ai",
|
|
204
|
-
"data-part": "tool-label",
|
|
205
|
-
children: "Output"
|
|
206
|
-
}), /* @__PURE__ */ jsx("pre", { children: output })] }) : null]
|
|
207
|
-
}) })]
|
|
494
|
+
"data-scope": "ai",
|
|
495
|
+
"data-part": "response",
|
|
496
|
+
dangerouslySetInnerHTML: { __html: renderHtml(content, highlighter ? { highlighter } : void 0) }
|
|
208
497
|
});
|
|
209
498
|
}
|
|
499
|
+
injectComponentStyle("ai");
|
|
500
|
+
//#endregion
|
|
501
|
+
//#region src/components/ai-source/index.tsx
|
|
210
502
|
function Source({ href, children, ...rest }) {
|
|
211
503
|
return /* @__PURE__ */ jsx("li", {
|
|
212
504
|
"data-scope": "ai",
|
|
@@ -220,17 +512,17 @@ function Source({ href, children, ...rest }) {
|
|
|
220
512
|
})
|
|
221
513
|
});
|
|
222
514
|
}
|
|
223
|
-
function
|
|
224
|
-
return /* @__PURE__ */ jsx(
|
|
225
|
-
variant: "ghost",
|
|
226
|
-
size: "sm",
|
|
227
|
-
square: true,
|
|
228
|
-
"aria-label": label,
|
|
229
|
-
title: label,
|
|
515
|
+
function Sources({ children, ...rest }) {
|
|
516
|
+
return /* @__PURE__ */ jsx("ol", {
|
|
230
517
|
...rest,
|
|
518
|
+
"data-scope": "ai",
|
|
519
|
+
"data-part": "sources",
|
|
231
520
|
children
|
|
232
521
|
});
|
|
233
522
|
}
|
|
523
|
+
injectComponentStyle("ai");
|
|
524
|
+
//#endregion
|
|
525
|
+
//#region src/components/ai-suggestion/index.tsx
|
|
234
526
|
function Suggestion({ prompt, onSelect, ...rest }) {
|
|
235
527
|
return /* @__PURE__ */ jsx(Button, {
|
|
236
528
|
variant: "outline",
|
|
@@ -240,74 +532,194 @@ function Suggestion({ prompt, onSelect, ...rest }) {
|
|
|
240
532
|
children: prompt
|
|
241
533
|
});
|
|
242
534
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
onValueChange?.("");
|
|
249
|
-
};
|
|
250
|
-
return /* @__PURE__ */ jsxs("form", {
|
|
535
|
+
injectComponentStyle("ai");
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/components/ai-tool/index.tsx
|
|
538
|
+
function Tool({ name, label, status, input, output, ...rest }) {
|
|
539
|
+
return /* @__PURE__ */ jsxs(Collapsible.Root, {
|
|
251
540
|
...rest,
|
|
252
|
-
"data-
|
|
253
|
-
"data-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
disabled,
|
|
264
|
-
onChange: (event) => onValueChange?.(event.target.value),
|
|
265
|
-
onKeyDown: (event) => {
|
|
266
|
-
if (event.key === "Enter" && !event.shiftKey) {
|
|
267
|
-
event.preventDefault();
|
|
268
|
-
send();
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}) }), /* @__PURE__ */ jsx("div", {
|
|
541
|
+
"data-ai": "tool",
|
|
542
|
+
"data-status": status,
|
|
543
|
+
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, { children: [
|
|
544
|
+
/* @__PURE__ */ jsx("span", { children: label ?? name }),
|
|
545
|
+
status ? /* @__PURE__ */ jsx("span", {
|
|
546
|
+
"data-scope": "ai",
|
|
547
|
+
"data-part": "tool-status",
|
|
548
|
+
children: status.charAt(0).toUpperCase() + status.slice(1)
|
|
549
|
+
}) : null,
|
|
550
|
+
/* @__PURE__ */ jsx(Collapsible.Indicator, { children: chevron$2 })
|
|
551
|
+
] }), /* @__PURE__ */ jsx(Collapsible.Content, { children: /* @__PURE__ */ jsxs("div", {
|
|
272
552
|
"data-scope": "ai",
|
|
273
|
-
"data-part": "
|
|
274
|
-
children: /* @__PURE__ */ jsx(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
"
|
|
280
|
-
|
|
281
|
-
children:
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
553
|
+
"data-part": "tool-body",
|
|
554
|
+
children: [input ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
555
|
+
"data-scope": "ai",
|
|
556
|
+
"data-part": "tool-label",
|
|
557
|
+
children: "Input"
|
|
558
|
+
}), /* @__PURE__ */ jsx("pre", { children: input })] }) : null, output ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
559
|
+
"data-scope": "ai",
|
|
560
|
+
"data-part": "tool-label",
|
|
561
|
+
children: "Output"
|
|
562
|
+
}), /* @__PURE__ */ jsx("pre", { children: output })] }) : null]
|
|
563
|
+
}) })]
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
injectComponentStyle("ai");
|
|
567
|
+
//#endregion
|
|
568
|
+
//#region src/components/ai/index.tsx
|
|
569
|
+
/** A conversation column: Root is the log, Message carries a role, and
|
|
570
|
+
* the speaking parts — Response, Reasoning, Tool, Sources — part the
|
|
571
|
+
* stream. The interactive folds are the shared Collapsible wearing a
|
|
572
|
+
* `data-ai` marker, so the machine work is never ours. Parts stay
|
|
573
|
+
* agnostic of any client; consumers map their message format (e.g. the
|
|
574
|
+
* `UIMessage` parts re-exported here) onto these primitives. */
|
|
575
|
+
function part$12(name, tag, extra = {}) {
|
|
576
|
+
const Tag = tag;
|
|
577
|
+
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
578
|
+
...extra,
|
|
579
|
+
...rest,
|
|
580
|
+
"data-scope": "ai",
|
|
581
|
+
"data-part": name.toLowerCase(),
|
|
582
|
+
children
|
|
294
583
|
});
|
|
584
|
+
Component.displayName = "Ai" + name;
|
|
585
|
+
return Component;
|
|
295
586
|
}
|
|
587
|
+
/** The log itself: the column every stroke lands in, a landmark to
|
|
588
|
+
* screen readers. */
|
|
589
|
+
const Conversation = part$12("Conversation", "div", {
|
|
590
|
+
role: "log",
|
|
591
|
+
"aria-label": "Conversation"
|
|
592
|
+
});
|
|
593
|
+
/** The bubble's inner measure — content that belongs to neither side
|
|
594
|
+
* specifically. */
|
|
595
|
+
const MessageContent = part$12("Content", "div");
|
|
596
|
+
/** The quiet row under a message — copy, retry, feedback. */
|
|
597
|
+
const Actions$4 = part$12("Actions", "div");
|
|
598
|
+
/** The while-it-works whisper for the in-flight turns. */
|
|
599
|
+
const Loader = part$12("Loader", "span", {
|
|
600
|
+
role: "status",
|
|
601
|
+
"aria-label": "Loading"
|
|
602
|
+
});
|
|
603
|
+
/** The whole family under one handle — `Ai.Conversation`,
|
|
604
|
+
* `Ai.Message`, and the rest, exactly as before the split. */
|
|
296
605
|
const Ai = Object.assign(Conversation, {
|
|
297
606
|
Conversation,
|
|
298
|
-
Message,
|
|
299
607
|
MessageContent,
|
|
608
|
+
Actions: Actions$4,
|
|
609
|
+
Loader,
|
|
610
|
+
Message,
|
|
300
611
|
Response,
|
|
301
612
|
Reasoning,
|
|
302
613
|
Tool,
|
|
303
614
|
Sources,
|
|
304
615
|
Source,
|
|
305
|
-
Actions: Actions$3,
|
|
306
616
|
Action,
|
|
307
617
|
Suggestion,
|
|
308
|
-
PromptInput
|
|
309
|
-
|
|
618
|
+
PromptInput
|
|
619
|
+
});
|
|
620
|
+
injectComponentStyle("ai");
|
|
621
|
+
//#endregion
|
|
622
|
+
//#region src/components/ai-attachments/index.tsx
|
|
623
|
+
const imageGlyph = /* @__PURE__ */ jsxs("svg", {
|
|
624
|
+
viewBox: "0 0 16 16",
|
|
625
|
+
"aria-hidden": "true",
|
|
626
|
+
fill: "none",
|
|
627
|
+
stroke: "currentColor",
|
|
628
|
+
strokeWidth: 1.5,
|
|
629
|
+
strokeLinecap: "square",
|
|
630
|
+
children: [
|
|
631
|
+
/* @__PURE__ */ jsx("rect", {
|
|
632
|
+
x: 2.5,
|
|
633
|
+
y: 3.5,
|
|
634
|
+
width: 11,
|
|
635
|
+
height: 9
|
|
636
|
+
}),
|
|
637
|
+
/* @__PURE__ */ jsx("path", { d: "M2.5 10.5 6 7l3 3 2-1.5 2.5 2" }),
|
|
638
|
+
/* @__PURE__ */ jsx("circle", {
|
|
639
|
+
cx: 6,
|
|
640
|
+
cy: 6,
|
|
641
|
+
r: .75,
|
|
642
|
+
fill: "currentColor",
|
|
643
|
+
stroke: "none"
|
|
644
|
+
})
|
|
645
|
+
]
|
|
646
|
+
});
|
|
647
|
+
const fileGlyph = /* @__PURE__ */ jsxs("svg", {
|
|
648
|
+
viewBox: "0 0 16 16",
|
|
649
|
+
"aria-hidden": "true",
|
|
650
|
+
fill: "none",
|
|
651
|
+
stroke: "currentColor",
|
|
652
|
+
strokeWidth: 1.5,
|
|
653
|
+
strokeLinecap: "square",
|
|
654
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M4 2.5h5l3 3V13.5H4z" }), /* @__PURE__ */ jsx("path", { d: "M9 2.5v3h3" })]
|
|
655
|
+
});
|
|
656
|
+
const removeGlyph = /* @__PURE__ */ jsx("svg", {
|
|
657
|
+
viewBox: "0 0 16 16",
|
|
658
|
+
width: 12,
|
|
659
|
+
height: 12,
|
|
660
|
+
"aria-hidden": "true",
|
|
661
|
+
fill: "none",
|
|
662
|
+
stroke: "currentColor",
|
|
663
|
+
strokeWidth: 1.5,
|
|
664
|
+
strokeLinecap: "square",
|
|
665
|
+
children: /* @__PURE__ */ jsx("path", { d: "M4 4l8 8M12 4l-8 8" })
|
|
310
666
|
});
|
|
667
|
+
const IMAGE_EXTS = [
|
|
668
|
+
"png",
|
|
669
|
+
"jpg",
|
|
670
|
+
"jpeg",
|
|
671
|
+
"gif",
|
|
672
|
+
"webp",
|
|
673
|
+
"svg",
|
|
674
|
+
"avif",
|
|
675
|
+
"bmp",
|
|
676
|
+
"ico"
|
|
677
|
+
];
|
|
678
|
+
const isImage = (name) => IMAGE_EXTS.includes(name.split(".").pop()?.toLowerCase() ?? "");
|
|
679
|
+
const humanSize = (bytes) => {
|
|
680
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
681
|
+
const units = [
|
|
682
|
+
"KB",
|
|
683
|
+
"MB",
|
|
684
|
+
"GB"
|
|
685
|
+
];
|
|
686
|
+
let value = bytes;
|
|
687
|
+
let unit = -1;
|
|
688
|
+
do {
|
|
689
|
+
value /= 1024;
|
|
690
|
+
unit += 1;
|
|
691
|
+
} while (value >= 1024 && unit < units.length - 1);
|
|
692
|
+
return `${value.toFixed(1)} ${units[unit]}`;
|
|
693
|
+
};
|
|
694
|
+
function Attachment({ name, size, status = "ready", onRemove, ...rest }) {
|
|
695
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
696
|
+
...rest,
|
|
697
|
+
"data-scope": "ai",
|
|
698
|
+
"data-part": "attachment",
|
|
699
|
+
"data-status": status,
|
|
700
|
+
children: [
|
|
701
|
+
isImage(name) ? imageGlyph : fileGlyph,
|
|
702
|
+
/* @__PURE__ */ jsx("span", { children: name }),
|
|
703
|
+
size !== void 0 ? /* @__PURE__ */ jsx("span", { children: humanSize(size) }) : null,
|
|
704
|
+
/* @__PURE__ */ jsx("button", {
|
|
705
|
+
type: "button",
|
|
706
|
+
"data-remove": "",
|
|
707
|
+
"aria-label": `Remove ${name}`,
|
|
708
|
+
onClick: () => onRemove?.(),
|
|
709
|
+
children: removeGlyph
|
|
710
|
+
})
|
|
711
|
+
]
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
/** The row the files ride in — a wrapping line of chips. */
|
|
715
|
+
function Attachments({ children, ...rest }) {
|
|
716
|
+
return /* @__PURE__ */ jsx("span", {
|
|
717
|
+
...rest,
|
|
718
|
+
"data-scope": "ai",
|
|
719
|
+
"data-part": "attachments",
|
|
720
|
+
children
|
|
721
|
+
});
|
|
722
|
+
}
|
|
311
723
|
injectComponentStyle("ai");
|
|
312
724
|
//#endregion
|
|
313
725
|
//#region src/components/alert/index.tsx
|
|
@@ -345,7 +757,7 @@ function AlertRoot({ status = "ink", children, ...rest }) {
|
|
|
345
757
|
})
|
|
346
758
|
});
|
|
347
759
|
}
|
|
348
|
-
function Icon$
|
|
760
|
+
function Icon$2() {
|
|
349
761
|
const status = useContext(StatusContext);
|
|
350
762
|
return /* @__PURE__ */ jsx("span", {
|
|
351
763
|
"data-scope": "alert",
|
|
@@ -379,7 +791,7 @@ function Description$5({ children, ...rest }) {
|
|
|
379
791
|
}
|
|
380
792
|
const Alert = Object.assign(AlertRoot, {
|
|
381
793
|
Root: AlertRoot,
|
|
382
|
-
Icon: Icon$
|
|
794
|
+
Icon: Icon$2,
|
|
383
795
|
Body: Body$2,
|
|
384
796
|
Title: Title$4,
|
|
385
797
|
Description: Description$5
|
|
@@ -394,6 +806,48 @@ injectComponentStyle("alert");
|
|
|
394
806
|
const AngleSlider = AngleSlider$1;
|
|
395
807
|
injectComponentStyle("angle-slider");
|
|
396
808
|
//#endregion
|
|
809
|
+
//#region src/components/aspect-ratio/index.tsx
|
|
810
|
+
function AspectRatio({ ratio = "1 / 1", ...rest }) {
|
|
811
|
+
return /* @__PURE__ */ jsx("div", {
|
|
812
|
+
...rest,
|
|
813
|
+
style: {
|
|
814
|
+
...rest.style,
|
|
815
|
+
"--bs-aspect-ratio": ratio
|
|
816
|
+
},
|
|
817
|
+
"data-scope": "aspect-ratio",
|
|
818
|
+
"data-part": "root"
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
injectComponentStyle("aspect-ratio");
|
|
822
|
+
//#endregion
|
|
823
|
+
//#region src/components/autocomplete/index.tsx
|
|
824
|
+
function AutoComplete({ value = "", items = [], placeholder, filter, onValueChange, ...rest }) {
|
|
825
|
+
const { collection, filter: filterItems } = useListCollection$1({
|
|
826
|
+
initialItems: items,
|
|
827
|
+
filter: (item, input) => filter ? filter(item, input) : item.toLowerCase().includes(input.toLowerCase())
|
|
828
|
+
});
|
|
829
|
+
return /* @__PURE__ */ jsxs(Combobox$1.Root, {
|
|
830
|
+
...rest,
|
|
831
|
+
collection,
|
|
832
|
+
inputValue: value,
|
|
833
|
+
allowCustomValue: true,
|
|
834
|
+
onValueChange: (details) => {
|
|
835
|
+
const [first] = details.value;
|
|
836
|
+
if (first != null) onValueChange?.(first);
|
|
837
|
+
},
|
|
838
|
+
onInputValueChange: (details) => {
|
|
839
|
+
filterItems(details.inputValue);
|
|
840
|
+
onValueChange?.(details.inputValue);
|
|
841
|
+
},
|
|
842
|
+
positioning: { sameWidth: true },
|
|
843
|
+
children: [/* @__PURE__ */ jsx(Combobox$1.Control, { children: /* @__PURE__ */ jsx(Combobox$1.Input, { placeholder }) }), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Combobox$1.Positioner, { children: /* @__PURE__ */ jsxs(Combobox$1.Content, { children: [/* @__PURE__ */ jsx(Combobox$1.Empty, { children: "No matches" }), collection.items.map((item) => /* @__PURE__ */ jsx(Combobox$1.Item, {
|
|
844
|
+
item,
|
|
845
|
+
children: /* @__PURE__ */ jsx(Combobox$1.ItemText, { children: item })
|
|
846
|
+
}, item))] }) }) })]
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
injectComponentStyle("combobox");
|
|
850
|
+
//#endregion
|
|
397
851
|
//#region src/components/avatar/index.tsx
|
|
398
852
|
/** Ark's Avatar, dressed in the paper-and-ink system: a circular seal on
|
|
399
853
|
* inset paper that holds initials until the image loads over them. The
|
|
@@ -410,7 +864,64 @@ function AvatarGroup({ children, ...rest }) {
|
|
|
410
864
|
children
|
|
411
865
|
});
|
|
412
866
|
}
|
|
413
|
-
injectComponentStyle("avatar-group");
|
|
867
|
+
injectComponentStyle("avatar-group");
|
|
868
|
+
//#endregion
|
|
869
|
+
//#region src/components/back-top/index.tsx
|
|
870
|
+
/** The single glyph a way-home control needs: one stroke pointing up. */
|
|
871
|
+
function chevronUp() {
|
|
872
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
873
|
+
width: 16,
|
|
874
|
+
height: 16,
|
|
875
|
+
viewBox: "0 0 24 24",
|
|
876
|
+
fill: "none",
|
|
877
|
+
stroke: "currentColor",
|
|
878
|
+
strokeWidth: 1.75,
|
|
879
|
+
strokeLinecap: "round",
|
|
880
|
+
strokeLinejoin: "round",
|
|
881
|
+
"aria-hidden": "true",
|
|
882
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 14 6-6 6 6" })
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* A way home: after the page has scrolled past `threshold`, a small
|
|
887
|
+
* floating control rises at the page's corner and returns the reader to
|
|
888
|
+
* the top. The scroll itself stays native — `window.scrollTo` defers to
|
|
889
|
+
* the stylesheet's `scroll-behavior: smooth`, which reduced motion turns
|
|
890
|
+
* back into an instant jump. The button stays mounted either way so the
|
|
891
|
+
* entrance is a transition, never a pop.
|
|
892
|
+
*
|
|
893
|
+
* The control itself is the shared `Button` (outline, square) — the
|
|
894
|
+
* paper, hairline and halo are its; this family owns only the floating
|
|
895
|
+
* and the entrance.
|
|
896
|
+
*/
|
|
897
|
+
function BackTop({ threshold = 400, label = "Back to top", ...rest }) {
|
|
898
|
+
const [visible, setVisible] = useState(false);
|
|
899
|
+
useEffect(() => {
|
|
900
|
+
if (typeof window === "undefined") return;
|
|
901
|
+
const onScroll = () => setVisible(window.scrollY > threshold);
|
|
902
|
+
onScroll();
|
|
903
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
904
|
+
return () => window.removeEventListener("scroll", onScroll);
|
|
905
|
+
}, [threshold]);
|
|
906
|
+
return /* @__PURE__ */ jsx("div", {
|
|
907
|
+
"data-scope": "back-top",
|
|
908
|
+
"data-part": "root",
|
|
909
|
+
"data-state": visible ? "shown" : "hidden",
|
|
910
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
911
|
+
...rest,
|
|
912
|
+
variant: "outline",
|
|
913
|
+
square: true,
|
|
914
|
+
size: "lg",
|
|
915
|
+
type: "button",
|
|
916
|
+
"aria-label": label,
|
|
917
|
+
"aria-hidden": visible ? void 0 : "true",
|
|
918
|
+
tabIndex: visible ? 0 : -1,
|
|
919
|
+
onClick: () => window.scrollTo({ top: 0 }),
|
|
920
|
+
children: rest.children ?? chevronUp()
|
|
921
|
+
})
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
injectComponentStyle("back-top");
|
|
414
925
|
//#endregion
|
|
415
926
|
//#region src/components/badge/index.tsx
|
|
416
927
|
function Badge({ tone = "ink", variant = "solid", ...rest }) {
|
|
@@ -428,7 +939,7 @@ injectComponentStyle("badge");
|
|
|
428
939
|
/** A trail of waymarks: Root wraps the nav, List the ordered trail, and
|
|
429
940
|
* each Item carries a Link — or the Current page — parted by a quiet
|
|
430
941
|
* Separator. Links take href and the rest through attributes. */
|
|
431
|
-
function part$
|
|
942
|
+
function part$11(name, tag, extra = {}, fallback) {
|
|
432
943
|
const Tag = tag;
|
|
433
944
|
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
434
945
|
...extra,
|
|
@@ -440,28 +951,50 @@ function part$8(name, tag, extra = {}, fallback) {
|
|
|
440
951
|
Component.displayName = "Breadcrumb" + name;
|
|
441
952
|
return Component;
|
|
442
953
|
}
|
|
443
|
-
const Root$
|
|
444
|
-
const List = part$
|
|
445
|
-
const Item$
|
|
446
|
-
const Link$1 = part$
|
|
447
|
-
const Current = part$
|
|
448
|
-
const Separator$1 = part$
|
|
449
|
-
const Breadcrumb = Object.assign(Root$
|
|
450
|
-
Root: Root$
|
|
451
|
-
List,
|
|
452
|
-
Item: Item$
|
|
954
|
+
const Root$12 = part$11("Root", "nav", { "aria-label": "Breadcrumb" });
|
|
955
|
+
const List$1 = part$11("List", "ol");
|
|
956
|
+
const Item$4 = part$11("Item", "li");
|
|
957
|
+
const Link$1 = part$11("Link", "a");
|
|
958
|
+
const Current = part$11("Current", "span", { "aria-current": "page" });
|
|
959
|
+
const Separator$1 = part$11("Separator", "span", { "aria-hidden": "true" }, "/");
|
|
960
|
+
const Breadcrumb = Object.assign(Root$12, {
|
|
961
|
+
Root: Root$12,
|
|
962
|
+
List: List$1,
|
|
963
|
+
Item: Item$4,
|
|
453
964
|
Link: Link$1,
|
|
454
965
|
Current,
|
|
455
966
|
Separator: Separator$1
|
|
456
967
|
});
|
|
457
968
|
injectComponentStyle("breadcrumb");
|
|
458
969
|
//#endregion
|
|
970
|
+
//#region src/components/button-group/index.tsx
|
|
971
|
+
/**
|
|
972
|
+
* Buttons fused into one control: the group owns only the joinery, so
|
|
973
|
+
* members keep every variant they were given — a solid action can sit
|
|
974
|
+
* beside an outline one and the seam still reads. Selection belongs to
|
|
975
|
+
* the toggle group; this is layout alone.
|
|
976
|
+
*/
|
|
977
|
+
function Root$11({ orientation = "horizontal", size, radius, children, ...rest }) {
|
|
978
|
+
return /* @__PURE__ */ jsx("div", {
|
|
979
|
+
...rest,
|
|
980
|
+
role: "group",
|
|
981
|
+
"data-scope": "button-group",
|
|
982
|
+
"data-part": "root",
|
|
983
|
+
"data-orientation": orientation,
|
|
984
|
+
"data-size": size,
|
|
985
|
+
"data-radius": radius,
|
|
986
|
+
children
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
const ButtonGroup = Object.assign(Root$11, { Root: Root$11 });
|
|
990
|
+
injectComponentStyle("button-group");
|
|
991
|
+
//#endregion
|
|
459
992
|
//#region src/components/banner/index.tsx
|
|
460
993
|
/** A page-level notice, spoken across the full measure: a wash of the
|
|
461
994
|
* status pigment, one heavier hairline on the leading edge, and room
|
|
462
995
|
* for actions and a quiet close. Ink is the neutral register; the four
|
|
463
996
|
* semantic pigments are fixed. */
|
|
464
|
-
const Root$
|
|
997
|
+
const Root$10 = ({ status = "ink", children, ...rest }) => /* @__PURE__ */ jsx("div", {
|
|
465
998
|
...rest,
|
|
466
999
|
role: status === "ink" ? void 0 : "status",
|
|
467
1000
|
"data-scope": "banner",
|
|
@@ -469,7 +1002,7 @@ const Root$6 = ({ status = "ink", children, ...rest }) => /* @__PURE__ */ jsx("d
|
|
|
469
1002
|
"data-status": status,
|
|
470
1003
|
children
|
|
471
1004
|
});
|
|
472
|
-
function part$
|
|
1005
|
+
function part$10(name, tag) {
|
|
473
1006
|
const Tag = tag;
|
|
474
1007
|
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
475
1008
|
...rest,
|
|
@@ -480,14 +1013,14 @@ function part$7(name, tag) {
|
|
|
480
1013
|
Component.displayName = "Banner" + name;
|
|
481
1014
|
return Component;
|
|
482
1015
|
}
|
|
483
|
-
const Icon = part$
|
|
484
|
-
const Body$1 = part$
|
|
485
|
-
const Title$3 = part$
|
|
486
|
-
const Description$4 = part$
|
|
487
|
-
const Actions$
|
|
1016
|
+
const Icon$1 = part$10("Icon", "span");
|
|
1017
|
+
const Body$1 = part$10("Body", "div");
|
|
1018
|
+
const Title$3 = part$10("Title", "p");
|
|
1019
|
+
const Description$4 = part$10("Description", "p");
|
|
1020
|
+
const Actions$3 = part$10("Actions", "div");
|
|
488
1021
|
/** The quiet close: a plain square-cut button; dismissal stays the
|
|
489
1022
|
* consumer's state. */
|
|
490
|
-
const Close = (
|
|
1023
|
+
const Close = (rest) => /* @__PURE__ */ jsx("button", {
|
|
491
1024
|
...rest,
|
|
492
1025
|
type: rest.type ?? "button",
|
|
493
1026
|
"aria-label": rest["aria-label"] ?? "Dismiss",
|
|
@@ -505,19 +1038,19 @@ const Close = ({ children, ...rest }) => /* @__PURE__ */ jsx("button", {
|
|
|
505
1038
|
})
|
|
506
1039
|
})
|
|
507
1040
|
});
|
|
508
|
-
const Banner = Object.assign(Root$
|
|
509
|
-
Root: Root$
|
|
510
|
-
Icon,
|
|
1041
|
+
const Banner = Object.assign(Root$10, {
|
|
1042
|
+
Root: Root$10,
|
|
1043
|
+
Icon: Icon$1,
|
|
511
1044
|
Body: Body$1,
|
|
512
1045
|
Title: Title$3,
|
|
513
1046
|
Description: Description$4,
|
|
514
|
-
Actions: Actions$
|
|
1047
|
+
Actions: Actions$3,
|
|
515
1048
|
Close
|
|
516
1049
|
});
|
|
517
1050
|
injectComponentStyle("banner");
|
|
518
1051
|
//#endregion
|
|
519
1052
|
//#region src/components/calendar/index.tsx
|
|
520
|
-
function chevron(dir) {
|
|
1053
|
+
function chevron$1(dir) {
|
|
521
1054
|
return /* @__PURE__ */ jsx("svg", {
|
|
522
1055
|
width: 16,
|
|
523
1056
|
height: 16,
|
|
@@ -551,9 +1084,9 @@ function Calendar({ value, min, max, onValueChange, children, ...rest }) {
|
|
|
551
1084
|
"data-scope": "calendar",
|
|
552
1085
|
"data-part": "header",
|
|
553
1086
|
children: /* @__PURE__ */ jsxs(DatePicker$1.ViewControl, { children: [
|
|
554
|
-
/* @__PURE__ */ jsx(DatePicker$1.PrevTrigger, { children: chevron("left") }),
|
|
1087
|
+
/* @__PURE__ */ jsx(DatePicker$1.PrevTrigger, { children: chevron$1("left") }),
|
|
555
1088
|
/* @__PURE__ */ jsx(DatePicker$1.Context, { children: (dp) => /* @__PURE__ */ jsx(DatePicker$1.ViewTrigger, { children: title(dp) }) }),
|
|
556
|
-
/* @__PURE__ */ jsx(DatePicker$1.NextTrigger, { children: chevron("right") })
|
|
1089
|
+
/* @__PURE__ */ jsx(DatePicker$1.NextTrigger, { children: chevron$1("right") })
|
|
557
1090
|
] })
|
|
558
1091
|
});
|
|
559
1092
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -606,12 +1139,13 @@ function Calendar({ value, min, max, onValueChange, children, ...rest }) {
|
|
|
606
1139
|
});
|
|
607
1140
|
}
|
|
608
1141
|
injectComponentStyle("calendar");
|
|
1142
|
+
injectComponentStyle("date-picker");
|
|
609
1143
|
//#endregion
|
|
610
1144
|
//#region src/components/card/index.tsx
|
|
611
1145
|
/** A vessel: round, resting at the first elevation, one hairline for its
|
|
612
1146
|
* edge. Root, Header, Title, Description, Content, Footer — sections
|
|
613
1147
|
* carry their own whitespace, so any subset composes. */
|
|
614
|
-
function part$
|
|
1148
|
+
function part$9(name, tag) {
|
|
615
1149
|
const Tag = tag;
|
|
616
1150
|
const Component = ({ asChild, children, ...rest }) => {
|
|
617
1151
|
const partProps = {
|
|
@@ -631,22 +1165,166 @@ function part$6(name, tag) {
|
|
|
631
1165
|
Component.displayName = "Card" + name;
|
|
632
1166
|
return Component;
|
|
633
1167
|
}
|
|
634
|
-
const Root$
|
|
635
|
-
const Header = part$
|
|
636
|
-
const Title$2 = part$
|
|
637
|
-
const Description$3 = part$
|
|
638
|
-
const Content$
|
|
639
|
-
const Footer = part$
|
|
640
|
-
const Card = Object.assign(Root$
|
|
641
|
-
Root: Root$
|
|
642
|
-
Header,
|
|
1168
|
+
const Root$9 = part$9("Root", "section");
|
|
1169
|
+
const Header$1 = part$9("Header", "header");
|
|
1170
|
+
const Title$2 = part$9("Title", "h3");
|
|
1171
|
+
const Description$3 = part$9("Description", "p");
|
|
1172
|
+
const Content$3 = part$9("Content", "div");
|
|
1173
|
+
const Footer$1 = part$9("Footer", "footer");
|
|
1174
|
+
const Card = Object.assign(Root$9, {
|
|
1175
|
+
Root: Root$9,
|
|
1176
|
+
Header: Header$1,
|
|
643
1177
|
Title: Title$2,
|
|
644
1178
|
Description: Description$3,
|
|
645
|
-
Content: Content$
|
|
646
|
-
Footer
|
|
1179
|
+
Content: Content$3,
|
|
1180
|
+
Footer: Footer$1
|
|
647
1181
|
});
|
|
648
1182
|
injectComponentStyle("card");
|
|
649
1183
|
//#endregion
|
|
1184
|
+
//#region src/components/cascade-select/index.tsx
|
|
1185
|
+
const chevronDown$2 = /* @__PURE__ */ jsx("svg", {
|
|
1186
|
+
viewBox: "0 0 24 24",
|
|
1187
|
+
fill: "none",
|
|
1188
|
+
stroke: "currentColor",
|
|
1189
|
+
strokeWidth: 2,
|
|
1190
|
+
strokeLinecap: "round",
|
|
1191
|
+
strokeLinejoin: "round",
|
|
1192
|
+
"aria-hidden": "true",
|
|
1193
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
1194
|
+
});
|
|
1195
|
+
const chevronRight = /* @__PURE__ */ jsx("svg", {
|
|
1196
|
+
viewBox: "0 0 24 24",
|
|
1197
|
+
fill: "none",
|
|
1198
|
+
stroke: "currentColor",
|
|
1199
|
+
strokeWidth: 2,
|
|
1200
|
+
strokeLinecap: "round",
|
|
1201
|
+
strokeLinejoin: "round",
|
|
1202
|
+
"aria-hidden": "true",
|
|
1203
|
+
children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
|
|
1204
|
+
});
|
|
1205
|
+
const checkGlyph$2 = /* @__PURE__ */ jsx("svg", {
|
|
1206
|
+
viewBox: "0 0 24 24",
|
|
1207
|
+
fill: "none",
|
|
1208
|
+
stroke: "currentColor",
|
|
1209
|
+
strokeWidth: 3,
|
|
1210
|
+
strokeLinecap: "round",
|
|
1211
|
+
strokeLinejoin: "round",
|
|
1212
|
+
"aria-hidden": "true",
|
|
1213
|
+
children: /* @__PURE__ */ jsx("path", { d: "m5 12.5 5 5L19 7" })
|
|
1214
|
+
});
|
|
1215
|
+
function CascadeSelect({ value, data, placeholder = "Select…", highlightTrigger, multiple = false, disabled = false, onValueChange, ...rest }) {
|
|
1216
|
+
const id = useId();
|
|
1217
|
+
const locale = useLocaleContext();
|
|
1218
|
+
const env = useEnvironmentContext();
|
|
1219
|
+
const collection = cascade.collection({
|
|
1220
|
+
nodeToValue: (node) => node.value,
|
|
1221
|
+
nodeToString: (node) => node.label,
|
|
1222
|
+
nodeToChildren: (node) => node.children ?? [],
|
|
1223
|
+
rootNode: {
|
|
1224
|
+
value: "ROOT",
|
|
1225
|
+
label: "",
|
|
1226
|
+
children: data
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
const service = useMachine(cascade.machine, {
|
|
1230
|
+
id,
|
|
1231
|
+
collection,
|
|
1232
|
+
dir: locale.dir,
|
|
1233
|
+
getRootNode: env.getRootNode.bind(env),
|
|
1234
|
+
disabled: disabled || void 0,
|
|
1235
|
+
multiple: multiple || void 0,
|
|
1236
|
+
...value !== void 0 ? { value } : {},
|
|
1237
|
+
...highlightTrigger != null ? { highlightTrigger } : {},
|
|
1238
|
+
onValueChange(details) {
|
|
1239
|
+
onValueChange?.(details.value);
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
const api = cascade.connect(service, normalizeProps);
|
|
1243
|
+
/** The machine's `valueAsString` only updates through its select
|
|
1244
|
+
* event, so an externally-set `value` would render the placeholder
|
|
1245
|
+
* forever — resolve the labels from the data instead. */
|
|
1246
|
+
function labelsFor(path) {
|
|
1247
|
+
const out = [];
|
|
1248
|
+
let nodes = data;
|
|
1249
|
+
for (const entry of path) {
|
|
1250
|
+
const node = nodes?.find((n) => n.value === entry);
|
|
1251
|
+
if (!node) return null;
|
|
1252
|
+
out.push(node.label);
|
|
1253
|
+
nodes = node.children;
|
|
1254
|
+
}
|
|
1255
|
+
return out;
|
|
1256
|
+
}
|
|
1257
|
+
const display = (value ?? []).map((path) => labelsFor(path)?.join(" / ")).filter((label) => label != null).join(", ");
|
|
1258
|
+
/** One column per walk of the highlighted path — the list binds to
|
|
1259
|
+
* the node, the next column hangs off its highlighted child. */
|
|
1260
|
+
function renderColumn(node, indexPath, valuePath) {
|
|
1261
|
+
const nodeProps = {
|
|
1262
|
+
item: node,
|
|
1263
|
+
indexPath,
|
|
1264
|
+
value: valuePath
|
|
1265
|
+
};
|
|
1266
|
+
const nodeState = api.getItemState(nodeProps);
|
|
1267
|
+
const children = collection.getNodeChildren(node);
|
|
1268
|
+
const list = /* @__PURE__ */ jsx("ul", {
|
|
1269
|
+
...api.getListProps(nodeProps),
|
|
1270
|
+
children: children.map((item, index) => {
|
|
1271
|
+
const itemValue = collection.getNodeValue(item);
|
|
1272
|
+
const itemProps = {
|
|
1273
|
+
item,
|
|
1274
|
+
indexPath: [...indexPath, index],
|
|
1275
|
+
value: [...valuePath, itemValue]
|
|
1276
|
+
};
|
|
1277
|
+
const itemState = api.getItemState(itemProps);
|
|
1278
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
1279
|
+
...api.getItemProps(itemProps),
|
|
1280
|
+
children: [
|
|
1281
|
+
/* @__PURE__ */ jsx("span", {
|
|
1282
|
+
...api.getItemTextProps(itemProps),
|
|
1283
|
+
children: item.label
|
|
1284
|
+
}),
|
|
1285
|
+
itemState.hasChildren ? /* @__PURE__ */ jsx("span", {
|
|
1286
|
+
"data-part": "branch-indicator",
|
|
1287
|
+
"aria-hidden": "true",
|
|
1288
|
+
children: chevronRight
|
|
1289
|
+
}) : null,
|
|
1290
|
+
/* @__PURE__ */ jsx("span", {
|
|
1291
|
+
...api.getItemIndicatorProps(itemProps),
|
|
1292
|
+
children: checkGlyph$2
|
|
1293
|
+
})
|
|
1294
|
+
]
|
|
1295
|
+
}, itemValue);
|
|
1296
|
+
})
|
|
1297
|
+
});
|
|
1298
|
+
const next = nodeState.highlightedChild;
|
|
1299
|
+
return [list, next != null && collection.isBranchNode(next) ? renderColumn(next, [...indexPath, nodeState.highlightedIndex], [...valuePath, collection.getNodeValue(next)]) : null];
|
|
1300
|
+
}
|
|
1301
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1302
|
+
...rest,
|
|
1303
|
+
...api.getRootProps(),
|
|
1304
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1305
|
+
...api.getControlProps(),
|
|
1306
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
1307
|
+
...api.getTriggerProps(),
|
|
1308
|
+
disabled: disabled || void 0,
|
|
1309
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1310
|
+
...api.getValueTextProps(),
|
|
1311
|
+
children: display || placeholder
|
|
1312
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1313
|
+
...api.getIndicatorProps(),
|
|
1314
|
+
children: chevronDown$2
|
|
1315
|
+
})]
|
|
1316
|
+
})
|
|
1317
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx("div", {
|
|
1318
|
+
...api.getPositionerProps(),
|
|
1319
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1320
|
+
...api.getContentProps(),
|
|
1321
|
+
children: renderColumn(collection.rootNode, [], [])
|
|
1322
|
+
})
|
|
1323
|
+
}) })]
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
injectComponentStyle("cascade-select");
|
|
1327
|
+
//#endregion
|
|
650
1328
|
//#region src/components/carousel/index.tsx
|
|
651
1329
|
/** Ark's Carousel, dressed in the paper-and-ink system: slides ride in one
|
|
652
1330
|
* hairline-clipped lane, the triggers are quiet outline controls, and the
|
|
@@ -664,6 +1342,52 @@ injectComponentStyle("carousel");
|
|
|
664
1342
|
const Checkbox = Checkbox$1;
|
|
665
1343
|
injectComponentStyle("checkbox");
|
|
666
1344
|
//#endregion
|
|
1345
|
+
//#region src/components/checkbox-group/index.tsx
|
|
1346
|
+
const checkGlyph$1 = /* @__PURE__ */ jsx("svg", {
|
|
1347
|
+
viewBox: "0 0 24 24",
|
|
1348
|
+
fill: "none",
|
|
1349
|
+
stroke: "currentColor",
|
|
1350
|
+
strokeWidth: 3,
|
|
1351
|
+
strokeLinecap: "round",
|
|
1352
|
+
strokeLinejoin: "round",
|
|
1353
|
+
"aria-hidden": "true",
|
|
1354
|
+
children: /* @__PURE__ */ jsx("path", { d: "m5 12.5 5 5L19 7" })
|
|
1355
|
+
});
|
|
1356
|
+
/**
|
|
1357
|
+
* One question, many answers: a labelled stack (or row) of the seal-cut
|
|
1358
|
+
* checkboxes bound to a single array. Toggling a box adds or removes its
|
|
1359
|
+
* value; the group itself is semantics (`role="group"`), the boxes stay
|
|
1360
|
+
* the machine-driven originals.
|
|
1361
|
+
*/
|
|
1362
|
+
function CheckboxGroup({ value = [], options, layout = "vertical", disabled = false, onValueChange, ...rest }) {
|
|
1363
|
+
const selected = new Set(value);
|
|
1364
|
+
function toggle(option) {
|
|
1365
|
+
const next = new Set(selected);
|
|
1366
|
+
if (next.has(option)) next.delete(option);
|
|
1367
|
+
else next.add(option);
|
|
1368
|
+
onValueChange?.([...next]);
|
|
1369
|
+
}
|
|
1370
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1371
|
+
...rest,
|
|
1372
|
+
role: "group",
|
|
1373
|
+
"data-scope": "checkbox-group",
|
|
1374
|
+
"data-part": "root",
|
|
1375
|
+
"data-layout": layout,
|
|
1376
|
+
children: options.map((option) => /* @__PURE__ */ jsxs(Checkbox$1.Root, {
|
|
1377
|
+
checked: selected.has(option.value),
|
|
1378
|
+
disabled: disabled || option.disabled === true,
|
|
1379
|
+
onCheckedChange: () => toggle(option.value),
|
|
1380
|
+
children: [
|
|
1381
|
+
/* @__PURE__ */ jsx(Checkbox$1.Control, { children: /* @__PURE__ */ jsx(Checkbox$1.Indicator, { children: checkGlyph$1 }) }),
|
|
1382
|
+
/* @__PURE__ */ jsx(Checkbox$1.Label, { children: option.label }),
|
|
1383
|
+
/* @__PURE__ */ jsx(Checkbox$1.HiddenInput, {})
|
|
1384
|
+
]
|
|
1385
|
+
}, option.value))
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
injectComponentStyle("checkbox-group");
|
|
1389
|
+
injectComponentStyle("checkbox");
|
|
1390
|
+
//#endregion
|
|
667
1391
|
//#region src/components/chip/index.tsx
|
|
668
1392
|
function Chip({ value, max, tone = "ink", variant = "solid", ...rest }) {
|
|
669
1393
|
const text = max != null && value > max ? `${max}+` : String(value);
|
|
@@ -707,6 +1431,227 @@ injectComponentStyle("color-picker");
|
|
|
707
1431
|
const Combobox = Combobox$1;
|
|
708
1432
|
injectComponentStyle("combobox");
|
|
709
1433
|
//#endregion
|
|
1434
|
+
//#region src/components/command/index.tsx
|
|
1435
|
+
function Command({ items = [], placeholder, open, autoFilter = true, inputValue, emptyText = "No matching commands", onSelect, onOpenChange, onInputValueChange }) {
|
|
1436
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
1437
|
+
const [listOpen, setListOpen] = useState(true);
|
|
1438
|
+
const [fieldText, setFieldText] = useState("");
|
|
1439
|
+
const { collection, set, filter } = useListCollection$1({
|
|
1440
|
+
initialItems: items.map((entry) => entry.value),
|
|
1441
|
+
filter: (value, input) => {
|
|
1442
|
+
const entry = items.find((candidate) => candidate.value === value);
|
|
1443
|
+
if (!entry) return false;
|
|
1444
|
+
const query = input.toLowerCase();
|
|
1445
|
+
return entry.label.toLowerCase().includes(query) || value.toLowerCase().includes(query);
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
useEffect(() => {
|
|
1449
|
+
set(items.map((entry) => entry.value));
|
|
1450
|
+
if (autoFilter) filter(fieldText);
|
|
1451
|
+
}, [items]);
|
|
1452
|
+
const currentOpen = open ?? internalOpen;
|
|
1453
|
+
useEffect(() => {
|
|
1454
|
+
if (currentOpen) setListOpen(true);
|
|
1455
|
+
}, [currentOpen]);
|
|
1456
|
+
const setOpen = (value) => {
|
|
1457
|
+
if (open === void 0) setInternalOpen(value);
|
|
1458
|
+
onOpenChange?.(value);
|
|
1459
|
+
};
|
|
1460
|
+
const available = new Set(collection.items);
|
|
1461
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1462
|
+
for (const entry of items) {
|
|
1463
|
+
if (!available.has(entry.value)) continue;
|
|
1464
|
+
const key = entry.group ?? "";
|
|
1465
|
+
if (!groups.has(key)) groups.set(key, []);
|
|
1466
|
+
groups.get(key).push(entry);
|
|
1467
|
+
}
|
|
1468
|
+
const row = (entry) => /* @__PURE__ */ jsx(Combobox$1.Item, {
|
|
1469
|
+
item: entry.value,
|
|
1470
|
+
asChild: true,
|
|
1471
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1472
|
+
"data-scope": "command",
|
|
1473
|
+
"data-part": "item",
|
|
1474
|
+
children: [/* @__PURE__ */ jsx(Combobox$1.ItemText, {
|
|
1475
|
+
asChild: true,
|
|
1476
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
1477
|
+
"data-scope": "command",
|
|
1478
|
+
"data-part": "item-label",
|
|
1479
|
+
children: entry.label
|
|
1480
|
+
})
|
|
1481
|
+
}), entry.hint ? /* @__PURE__ */ jsx("span", {
|
|
1482
|
+
"data-scope": "command",
|
|
1483
|
+
"data-part": "item-hint",
|
|
1484
|
+
children: entry.hint
|
|
1485
|
+
}) : void 0]
|
|
1486
|
+
})
|
|
1487
|
+
}, entry.value);
|
|
1488
|
+
return /* @__PURE__ */ jsx(Dialog$1.Root, {
|
|
1489
|
+
open: currentOpen,
|
|
1490
|
+
onOpenChange: (details) => setOpen(details.open),
|
|
1491
|
+
children: /* @__PURE__ */ jsxs(Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Backdrop, {}), /* @__PURE__ */ jsx(Dialog$1.Positioner, {
|
|
1492
|
+
asChild: true,
|
|
1493
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1494
|
+
"data-scope": "command",
|
|
1495
|
+
"data-part": "positioner",
|
|
1496
|
+
children: /* @__PURE__ */ jsx(Dialog$1.Content, {
|
|
1497
|
+
asChild: true,
|
|
1498
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1499
|
+
"data-scope": "command",
|
|
1500
|
+
"data-part": "content",
|
|
1501
|
+
children: /* @__PURE__ */ jsxs(Combobox$1.Root, {
|
|
1502
|
+
collection,
|
|
1503
|
+
inputValue,
|
|
1504
|
+
open: listOpen,
|
|
1505
|
+
onOpenChange: (details) => setListOpen(details.open),
|
|
1506
|
+
inputBehavior: "autohighlight",
|
|
1507
|
+
loopFocus: true,
|
|
1508
|
+
onInputValueChange: (details) => {
|
|
1509
|
+
setFieldText(details.inputValue);
|
|
1510
|
+
if (autoFilter) filter(details.inputValue);
|
|
1511
|
+
onInputValueChange?.(details.inputValue);
|
|
1512
|
+
},
|
|
1513
|
+
onValueChange: (details) => {
|
|
1514
|
+
const [first] = details.value;
|
|
1515
|
+
if (first == null) return;
|
|
1516
|
+
onSelect?.(first);
|
|
1517
|
+
setOpen(false);
|
|
1518
|
+
},
|
|
1519
|
+
children: [/* @__PURE__ */ jsx(Combobox$1.Input, {
|
|
1520
|
+
asChild: true,
|
|
1521
|
+
children: /* @__PURE__ */ jsx("input", {
|
|
1522
|
+
type: "text",
|
|
1523
|
+
placeholder,
|
|
1524
|
+
"data-scope": "command",
|
|
1525
|
+
"data-part": "input"
|
|
1526
|
+
})
|
|
1527
|
+
}), /* @__PURE__ */ jsx(Combobox$1.Content, {
|
|
1528
|
+
asChild: true,
|
|
1529
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1530
|
+
"data-scope": "command",
|
|
1531
|
+
"data-part": "list",
|
|
1532
|
+
children: [Array.from(groups, ([group, entries]) => group === "" ? entries.map(row) : /* @__PURE__ */ jsx(Combobox$1.ItemGroup, {
|
|
1533
|
+
asChild: true,
|
|
1534
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1535
|
+
"data-scope": "command",
|
|
1536
|
+
"data-part": "group",
|
|
1537
|
+
children: [/* @__PURE__ */ jsx(Combobox$1.ItemGroupLabel, {
|
|
1538
|
+
asChild: true,
|
|
1539
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1540
|
+
"data-scope": "command",
|
|
1541
|
+
"data-part": "group-label",
|
|
1542
|
+
children: group
|
|
1543
|
+
})
|
|
1544
|
+
}), entries.map(row)]
|
|
1545
|
+
})
|
|
1546
|
+
}, group)), groups.size === 0 ? /* @__PURE__ */ jsx("div", {
|
|
1547
|
+
"data-scope": "command",
|
|
1548
|
+
"data-part": "empty",
|
|
1549
|
+
children: emptyText
|
|
1550
|
+
}) : null]
|
|
1551
|
+
})
|
|
1552
|
+
})]
|
|
1553
|
+
})
|
|
1554
|
+
})
|
|
1555
|
+
})
|
|
1556
|
+
})
|
|
1557
|
+
})] })
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
injectComponentStyle("command");
|
|
1561
|
+
injectComponentStyle("dialog");
|
|
1562
|
+
//#endregion
|
|
1563
|
+
//#region src/components/comment/index.tsx
|
|
1564
|
+
function Comment({ author, datetime, avatar, actions, children, ...rest }) {
|
|
1565
|
+
return /* @__PURE__ */ jsxs("article", {
|
|
1566
|
+
...rest,
|
|
1567
|
+
"data-scope": "comment",
|
|
1568
|
+
"data-part": "root",
|
|
1569
|
+
children: [avatar ? /* @__PURE__ */ jsx("div", {
|
|
1570
|
+
"data-scope": "comment",
|
|
1571
|
+
"data-part": "avatar",
|
|
1572
|
+
children: avatar
|
|
1573
|
+
}) : null, /* @__PURE__ */ jsxs("div", {
|
|
1574
|
+
"data-scope": "comment",
|
|
1575
|
+
"data-part": "body",
|
|
1576
|
+
children: [
|
|
1577
|
+
author || datetime ? /* @__PURE__ */ jsxs("header", {
|
|
1578
|
+
"data-scope": "comment",
|
|
1579
|
+
"data-part": "header",
|
|
1580
|
+
children: [author ? /* @__PURE__ */ jsx("span", {
|
|
1581
|
+
"data-scope": "comment",
|
|
1582
|
+
"data-part": "author",
|
|
1583
|
+
children: author
|
|
1584
|
+
}) : null, datetime ? /* @__PURE__ */ jsx("time", {
|
|
1585
|
+
"data-scope": "comment",
|
|
1586
|
+
"data-part": "datetime",
|
|
1587
|
+
dateTime: datetime,
|
|
1588
|
+
children: datetime
|
|
1589
|
+
}) : null]
|
|
1590
|
+
}) : null,
|
|
1591
|
+
/* @__PURE__ */ jsx("div", {
|
|
1592
|
+
"data-scope": "comment",
|
|
1593
|
+
"data-part": "content",
|
|
1594
|
+
children
|
|
1595
|
+
}),
|
|
1596
|
+
actions ? /* @__PURE__ */ jsx("div", {
|
|
1597
|
+
"data-scope": "comment",
|
|
1598
|
+
"data-part": "actions",
|
|
1599
|
+
children: actions
|
|
1600
|
+
}) : null
|
|
1601
|
+
]
|
|
1602
|
+
})]
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
injectComponentStyle("comment");
|
|
1606
|
+
//#endregion
|
|
1607
|
+
//#region src/components/config-provider/index.tsx
|
|
1608
|
+
const ConfigContextImpl = createContext({});
|
|
1609
|
+
/** The nearest provider's snapshot, or an empty one when no provider
|
|
1610
|
+
* wraps the caller — the hook the date and format families will consume
|
|
1611
|
+
* to localize their output. */
|
|
1612
|
+
function useConfig() {
|
|
1613
|
+
return useContext(ConfigContextImpl);
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* The declarative host for global configuration: one element that both
|
|
1617
|
+
* carries the token layer's attributes — `[data-density]` and
|
|
1618
|
+
* `[data-accent]` fire on any element — and provides the same values to
|
|
1619
|
+
* descendants through `useConfig`, so interactive behavior (formatting,
|
|
1620
|
+
* messages) and visual theming stay one decision.
|
|
1621
|
+
*/
|
|
1622
|
+
function ConfigProvider({ density, accent, dir, locale, children, ...rest }) {
|
|
1623
|
+
return /* @__PURE__ */ jsx(ConfigContextImpl.Provider, {
|
|
1624
|
+
value: {
|
|
1625
|
+
density,
|
|
1626
|
+
accent,
|
|
1627
|
+
dir,
|
|
1628
|
+
locale
|
|
1629
|
+
},
|
|
1630
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1631
|
+
...rest,
|
|
1632
|
+
"data-scope": "config-provider",
|
|
1633
|
+
"data-part": "root",
|
|
1634
|
+
...density != null ? { "data-density": density } : {},
|
|
1635
|
+
...accent != null ? { "data-accent": accent } : {},
|
|
1636
|
+
...dir != null ? { dir } : {},
|
|
1637
|
+
...locale != null ? { lang: locale } : {},
|
|
1638
|
+
children
|
|
1639
|
+
})
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1642
|
+
//#endregion
|
|
1643
|
+
//#region src/components/container/index.tsx
|
|
1644
|
+
function Container({ size = "readable", padding = true, ...rest }) {
|
|
1645
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1646
|
+
...rest,
|
|
1647
|
+
"data-scope": "container",
|
|
1648
|
+
"data-part": "root",
|
|
1649
|
+
"data-size": size,
|
|
1650
|
+
"data-padding": padding ? "" : void 0
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
injectComponentStyle("container");
|
|
1654
|
+
//#endregion
|
|
710
1655
|
//#region src/components/date-input/index.tsx
|
|
711
1656
|
/** Ark's DateInput, dressed in the paper-and-ink system: a segmented
|
|
712
1657
|
* field where the focused segment takes the flat ink fill. The API is
|
|
@@ -725,6 +1670,35 @@ injectComponentStyle("date-input");
|
|
|
725
1670
|
const DatePicker = DatePicker$1;
|
|
726
1671
|
injectComponentStyle("date-picker");
|
|
727
1672
|
//#endregion
|
|
1673
|
+
//#region src/components/descriptions/index.tsx
|
|
1674
|
+
function DescriptionsRoot({ layout = "horizontal", children, ...rest }) {
|
|
1675
|
+
return /* @__PURE__ */ jsx("dl", {
|
|
1676
|
+
...rest,
|
|
1677
|
+
"data-scope": "descriptions",
|
|
1678
|
+
"data-part": "root",
|
|
1679
|
+
"data-layout": layout,
|
|
1680
|
+
children
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
function part$8(name, tag) {
|
|
1684
|
+
const Tag = tag;
|
|
1685
|
+
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
1686
|
+
...rest,
|
|
1687
|
+
"data-scope": "descriptions",
|
|
1688
|
+
"data-part": name.toLowerCase(),
|
|
1689
|
+
children
|
|
1690
|
+
});
|
|
1691
|
+
Component.displayName = "Descriptions" + name;
|
|
1692
|
+
return Component;
|
|
1693
|
+
}
|
|
1694
|
+
const Descriptions = {
|
|
1695
|
+
Root: DescriptionsRoot,
|
|
1696
|
+
Item: part$8("Item", "div"),
|
|
1697
|
+
Term: part$8("Term", "dt"),
|
|
1698
|
+
Detail: part$8("Detail", "dd")
|
|
1699
|
+
};
|
|
1700
|
+
injectComponentStyle("descriptions");
|
|
1701
|
+
//#endregion
|
|
728
1702
|
//#region src/components/dialog/index.tsx
|
|
729
1703
|
/** Ark's Dialog, dressed in the paper-and-ink system: the sheet dissolves
|
|
730
1704
|
* in on elevation, the backdrop fades, and nested overlays stack through
|
|
@@ -742,6 +1716,98 @@ injectComponentStyle("dialog");
|
|
|
742
1716
|
const Drawer = Drawer$1;
|
|
743
1717
|
injectComponentStyle("drawer");
|
|
744
1718
|
//#endregion
|
|
1719
|
+
//#region src/components/input/index.tsx
|
|
1720
|
+
function Input({ value, size = "md", invalid = false, onValueChange, ...rest }) {
|
|
1721
|
+
const field = useFieldContext();
|
|
1722
|
+
const fieldProps = field?.getInputProps() ?? {};
|
|
1723
|
+
return /* @__PURE__ */ jsx("input", {
|
|
1724
|
+
...fieldProps,
|
|
1725
|
+
...rest,
|
|
1726
|
+
...value !== void 0 ? { value } : {},
|
|
1727
|
+
"data-scope": "input",
|
|
1728
|
+
"data-part": "root",
|
|
1729
|
+
"data-size": size,
|
|
1730
|
+
"data-invalid": invalid || field?.invalid ? "" : void 0,
|
|
1731
|
+
onChange: (event) => onValueChange?.(event.target.value)
|
|
1732
|
+
});
|
|
1733
|
+
}
|
|
1734
|
+
injectComponentStyle("input");
|
|
1735
|
+
//#endregion
|
|
1736
|
+
//#region src/components/dynamic-input/index.tsx
|
|
1737
|
+
/**
|
|
1738
|
+
* A column of entry rows: one Input per line, each with a quiet remove
|
|
1739
|
+
* seal, and an add row at the tail. The list is controlled — every edit
|
|
1740
|
+
* reports a fresh array through `onValueChange` and the caller's array
|
|
1741
|
+
* stays the only truth. Deleting never drops below `min`, adding never
|
|
1742
|
+
* grows past `max`, and the group always keeps one row: an entry list
|
|
1743
|
+
* that emptied itself would leave the reader no place to type.
|
|
1744
|
+
*/
|
|
1745
|
+
function DynamicInput({ value, min = 0, max, placeholder, addLabel = "Add entry", disabled = false, invalid = false, onValueChange, children: _children, ...rest }) {
|
|
1746
|
+
const values = value ?? [""];
|
|
1747
|
+
const update = (index, next) => {
|
|
1748
|
+
const rows = values.slice();
|
|
1749
|
+
rows[index] = next;
|
|
1750
|
+
onValueChange?.(rows);
|
|
1751
|
+
};
|
|
1752
|
+
const remove = (index) => {
|
|
1753
|
+
const rows = values.filter((_, i) => i !== index);
|
|
1754
|
+
onValueChange?.(rows.length > 0 ? rows : [""]);
|
|
1755
|
+
};
|
|
1756
|
+
const add = () => {
|
|
1757
|
+
onValueChange?.([...values, ""]);
|
|
1758
|
+
};
|
|
1759
|
+
const canRemove = values.length > Math.max(min, 1);
|
|
1760
|
+
const canAdd = max === void 0 || values.length < max;
|
|
1761
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1762
|
+
...rest,
|
|
1763
|
+
"data-scope": "dynamic-input",
|
|
1764
|
+
"data-part": "root",
|
|
1765
|
+
children: [values.map((value, index) => /* @__PURE__ */ jsxs("div", {
|
|
1766
|
+
"data-scope": "dynamic-input",
|
|
1767
|
+
"data-part": "row",
|
|
1768
|
+
children: [/* @__PURE__ */ jsx(Input, {
|
|
1769
|
+
value,
|
|
1770
|
+
placeholder,
|
|
1771
|
+
disabled,
|
|
1772
|
+
invalid,
|
|
1773
|
+
onValueChange: (next) => update(index, next)
|
|
1774
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
1775
|
+
variant: "ghost",
|
|
1776
|
+
square: true,
|
|
1777
|
+
disabled: disabled || !canRemove,
|
|
1778
|
+
"aria-label": `Remove entry ${index + 1}`,
|
|
1779
|
+
onClick: () => remove(index),
|
|
1780
|
+
children: crossIcon()
|
|
1781
|
+
})]
|
|
1782
|
+
}, index)), /* @__PURE__ */ jsx("div", {
|
|
1783
|
+
"data-scope": "dynamic-input",
|
|
1784
|
+
"data-part": "add",
|
|
1785
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
1786
|
+
variant: "ghost",
|
|
1787
|
+
disabled: disabled || !canAdd,
|
|
1788
|
+
onClick: () => add(),
|
|
1789
|
+
children: ["+", addLabel]
|
|
1790
|
+
})
|
|
1791
|
+
})]
|
|
1792
|
+
});
|
|
1793
|
+
}
|
|
1794
|
+
/** The one glyph a remove seal needs: a single crossing stroke. */
|
|
1795
|
+
function crossIcon() {
|
|
1796
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
1797
|
+
width: 16,
|
|
1798
|
+
height: 16,
|
|
1799
|
+
viewBox: "0 0 24 24",
|
|
1800
|
+
fill: "none",
|
|
1801
|
+
stroke: "currentColor",
|
|
1802
|
+
strokeWidth: 1.75,
|
|
1803
|
+
strokeLinecap: "round",
|
|
1804
|
+
strokeLinejoin: "round",
|
|
1805
|
+
"aria-hidden": "true",
|
|
1806
|
+
children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
injectComponentStyle("dynamic-input");
|
|
1810
|
+
//#endregion
|
|
745
1811
|
//#region src/components/editable/index.tsx
|
|
746
1812
|
/** Ark's Editable, dressed in the paper-and-ink system: bare ink while
|
|
747
1813
|
* reading, the full field recipe while editing. The API is Ark's own —
|
|
@@ -750,11 +1816,27 @@ injectComponentStyle("drawer");
|
|
|
750
1816
|
const Editable = Editable$1;
|
|
751
1817
|
injectComponentStyle("editable");
|
|
752
1818
|
//#endregion
|
|
1819
|
+
//#region src/components/ellipsis/index.tsx
|
|
1820
|
+
function Ellipsis({ lines = 1, ...rest }) {
|
|
1821
|
+
const multiline = lines > 1;
|
|
1822
|
+
return /* @__PURE__ */ jsx("span", {
|
|
1823
|
+
...rest,
|
|
1824
|
+
style: multiline ? {
|
|
1825
|
+
...rest.style,
|
|
1826
|
+
"--bs-ellipsis-lines": String(lines)
|
|
1827
|
+
} : rest.style,
|
|
1828
|
+
"data-scope": "ellipsis",
|
|
1829
|
+
"data-part": "root",
|
|
1830
|
+
"data-multiline": multiline ? "" : void 0
|
|
1831
|
+
});
|
|
1832
|
+
}
|
|
1833
|
+
injectComponentStyle("ellipsis");
|
|
1834
|
+
//#endregion
|
|
753
1835
|
//#region src/components/empty/index.tsx
|
|
754
1836
|
/** An empty state: the page holds its breath. Root centers the column,
|
|
755
1837
|
* Visual carries the mark, Title and Description carry the ink, Actions
|
|
756
1838
|
* the way out. Any subset composes. */
|
|
757
|
-
function part$
|
|
1839
|
+
function part$7(name, tag) {
|
|
758
1840
|
const Tag = tag;
|
|
759
1841
|
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
760
1842
|
...rest,
|
|
@@ -765,17 +1847,17 @@ function part$5(name, tag) {
|
|
|
765
1847
|
Component.displayName = "Empty" + name;
|
|
766
1848
|
return Component;
|
|
767
1849
|
}
|
|
768
|
-
const Root$
|
|
769
|
-
const Visual = part$
|
|
770
|
-
const Title$1 = part$
|
|
771
|
-
const Description$2 = part$
|
|
772
|
-
const Actions$
|
|
773
|
-
const Empty = Object.assign(Root$
|
|
774
|
-
Root: Root$
|
|
1850
|
+
const Root$8 = part$7("Root", "div");
|
|
1851
|
+
const Visual = part$7("Visual", "div");
|
|
1852
|
+
const Title$1 = part$7("Title", "h3");
|
|
1853
|
+
const Description$2 = part$7("Description", "p");
|
|
1854
|
+
const Actions$2 = part$7("Actions", "div");
|
|
1855
|
+
const Empty = Object.assign(Root$8, {
|
|
1856
|
+
Root: Root$8,
|
|
775
1857
|
Visual,
|
|
776
1858
|
Title: Title$1,
|
|
777
1859
|
Description: Description$2,
|
|
778
|
-
Actions: Actions$
|
|
1860
|
+
Actions: Actions$2
|
|
779
1861
|
});
|
|
780
1862
|
injectComponentStyle("empty");
|
|
781
1863
|
//#endregion
|
|
@@ -796,6 +1878,85 @@ injectComponentStyle("fieldset");
|
|
|
796
1878
|
const FileUpload = FileUpload$1;
|
|
797
1879
|
injectComponentStyle("file-upload");
|
|
798
1880
|
//#endregion
|
|
1881
|
+
//#region src/components/float-button/index.tsx
|
|
1882
|
+
/** Context for {@link FloatButtonContextValue}, exported so a custom
|
|
1883
|
+
* part can read the group's state. */
|
|
1884
|
+
const FLOAT_BUTTON_CONTEXT = createContext(null);
|
|
1885
|
+
/**
|
|
1886
|
+
* A floating action and its fanned-out alternatives — FAB and speed
|
|
1887
|
+
* dial in one family. The Root moors the group at a page corner and
|
|
1888
|
+
* holds the openness (mirrored from `open` when controlled); the
|
|
1889
|
+
* Trigger flips it; each Item is a round action with its name surfacing
|
|
1890
|
+
* beside it while the group is open. The buttons are the shared recipe
|
|
1891
|
+
* (vessels here: round); this family owns only the mooring, the fan
|
|
1892
|
+
* and the fold.
|
|
1893
|
+
*/
|
|
1894
|
+
function Root$7({ open: openProp, placement = "bottom-end", onOpenChange, children, ...rest }) {
|
|
1895
|
+
const [inner, setInner] = useState(false);
|
|
1896
|
+
const open = openProp !== void 0 ? openProp : inner;
|
|
1897
|
+
const setOpen = (value) => {
|
|
1898
|
+
setInner(value);
|
|
1899
|
+
onOpenChange?.(value);
|
|
1900
|
+
};
|
|
1901
|
+
return /* @__PURE__ */ jsx(FLOAT_BUTTON_CONTEXT.Provider, {
|
|
1902
|
+
value: {
|
|
1903
|
+
open,
|
|
1904
|
+
toggle: () => setOpen(!open),
|
|
1905
|
+
close: () => setOpen(false)
|
|
1906
|
+
},
|
|
1907
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1908
|
+
...rest,
|
|
1909
|
+
"data-scope": "float-button",
|
|
1910
|
+
"data-part": "root",
|
|
1911
|
+
"data-placement": placement,
|
|
1912
|
+
"data-state": open ? "open" : "closed",
|
|
1913
|
+
children
|
|
1914
|
+
})
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
function Trigger({ label, children }) {
|
|
1918
|
+
const context = useContext(FLOAT_BUTTON_CONTEXT);
|
|
1919
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
1920
|
+
variant: "solid",
|
|
1921
|
+
square: true,
|
|
1922
|
+
size: "lg",
|
|
1923
|
+
onClick: () => context?.toggle(),
|
|
1924
|
+
"aria-label": label || "Actions",
|
|
1925
|
+
"aria-expanded": context ? context.open : false,
|
|
1926
|
+
children
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
function Item$2({ label, disabled = false, onClick, children }) {
|
|
1930
|
+
const context = useContext(FLOAT_BUTTON_CONTEXT);
|
|
1931
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1932
|
+
"data-scope": "float-button",
|
|
1933
|
+
"data-part": "item",
|
|
1934
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
1935
|
+
variant: "outline",
|
|
1936
|
+
square: true,
|
|
1937
|
+
size: "md",
|
|
1938
|
+
disabled,
|
|
1939
|
+
"aria-label": label,
|
|
1940
|
+
onClick: () => {
|
|
1941
|
+
onClick?.();
|
|
1942
|
+
context?.close();
|
|
1943
|
+
},
|
|
1944
|
+
children
|
|
1945
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1946
|
+
"data-scope": "float-button",
|
|
1947
|
+
"data-part": "item-label",
|
|
1948
|
+
"aria-hidden": "true",
|
|
1949
|
+
children: label
|
|
1950
|
+
})]
|
|
1951
|
+
});
|
|
1952
|
+
}
|
|
1953
|
+
const FloatButton = Object.assign(Root$7, {
|
|
1954
|
+
Root: Root$7,
|
|
1955
|
+
Trigger,
|
|
1956
|
+
Item: Item$2
|
|
1957
|
+
});
|
|
1958
|
+
injectComponentStyle("float-button");
|
|
1959
|
+
//#endregion
|
|
799
1960
|
//#region src/components/floating-panel/index.tsx
|
|
800
1961
|
/** Ark's FloatingPanel, dressed in the paper-and-ink system: the shared
|
|
801
1962
|
* popup vessel let loose — a draggable, resizable sheet whose header is the
|
|
@@ -805,6 +1966,134 @@ injectComponentStyle("file-upload");
|
|
|
805
1966
|
const FloatingPanel = FloatingPanel$1;
|
|
806
1967
|
injectComponentStyle("floating-panel");
|
|
807
1968
|
//#endregion
|
|
1969
|
+
//#region src/components/form/index.tsx
|
|
1970
|
+
const FormContext = createContext(null);
|
|
1971
|
+
/** Walk a Standard Schema issue's path back to the dotted name the
|
|
1972
|
+
* matching FormField declared. */
|
|
1973
|
+
function issueName(issue) {
|
|
1974
|
+
return (issue.path ?? []).map((segment) => typeof segment === "object" ? segment.key : segment).join(".");
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* The validation scheduler: one error map, a submit that validates
|
|
1978
|
+
* before it fires, live re-validation on the events the `validateOn`
|
|
1979
|
+
* prop names, and the imperative handle. The schema is any Standard
|
|
1980
|
+
* Schema (valibot, zod, arktype, …) — none are bundled; a `validate`
|
|
1981
|
+
* function composes with it for the cases schemas can't express. Errors
|
|
1982
|
+
* reach their field by name, through FormField.
|
|
1983
|
+
*/
|
|
1984
|
+
function Form({ state, schema, validate, validateOn = [
|
|
1985
|
+
"input",
|
|
1986
|
+
"change",
|
|
1987
|
+
"blur"
|
|
1988
|
+
], disabled = false, onSubmit, onError, ref, children, ...rest }) {
|
|
1989
|
+
const [errors, setErrors] = useState(() => /* @__PURE__ */ new Map());
|
|
1990
|
+
const run = useRef(0);
|
|
1991
|
+
async function runValidate() {
|
|
1992
|
+
const seq = ++run.current;
|
|
1993
|
+
const next = /* @__PURE__ */ new Map();
|
|
1994
|
+
if (validate) for (const error of await validate(state)) next.set(error.name, error.message);
|
|
1995
|
+
if (schema) {
|
|
1996
|
+
const result = await schema["~standard"].validate(state);
|
|
1997
|
+
for (const issue of result.issues ?? []) {
|
|
1998
|
+
const name = issueName(issue);
|
|
1999
|
+
if (!next.has(name)) next.set(name, issue.message);
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
if (seq === run.current) setErrors(next);
|
|
2003
|
+
return next;
|
|
2004
|
+
}
|
|
2005
|
+
function clear(name) {
|
|
2006
|
+
if (!name) {
|
|
2007
|
+
setErrors(/* @__PURE__ */ new Map());
|
|
2008
|
+
return;
|
|
2009
|
+
}
|
|
2010
|
+
setErrors((prev) => {
|
|
2011
|
+
const next = new Map(prev);
|
|
2012
|
+
for (const key of next.keys()) if (typeof name === "string" ? key === name : name.test(key)) next.delete(key);
|
|
2013
|
+
return next;
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
function setErrorsFrom(list) {
|
|
2017
|
+
setErrors(new Map(list.map((error) => [error.name, error.message])));
|
|
2018
|
+
}
|
|
2019
|
+
function getErrors(name) {
|
|
2020
|
+
const all = [...errors].map(([entry, message]) => ({
|
|
2021
|
+
name: entry,
|
|
2022
|
+
message
|
|
2023
|
+
}));
|
|
2024
|
+
if (!name) return all;
|
|
2025
|
+
return all.filter((error) => typeof name === "string" ? error.name === name : name.test(error.name));
|
|
2026
|
+
}
|
|
2027
|
+
useImperativeHandle(ref, () => ({
|
|
2028
|
+
validate: runValidate,
|
|
2029
|
+
clear,
|
|
2030
|
+
setErrors: setErrorsFrom,
|
|
2031
|
+
getErrors,
|
|
2032
|
+
errors
|
|
2033
|
+
}));
|
|
2034
|
+
function handleSubmit(event) {
|
|
2035
|
+
event.preventDefault();
|
|
2036
|
+
runValidate().then((map) => {
|
|
2037
|
+
if (map.size === 0) {
|
|
2038
|
+
onSubmit?.(state);
|
|
2039
|
+
return;
|
|
2040
|
+
}
|
|
2041
|
+
onError?.([...map].map(([name, message]) => ({
|
|
2042
|
+
name,
|
|
2043
|
+
message
|
|
2044
|
+
})));
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
const timer = useRef(void 0);
|
|
2048
|
+
function onDelegated(kind, event) {
|
|
2049
|
+
if (!validateOn.includes(kind)) return;
|
|
2050
|
+
const target = event.target;
|
|
2051
|
+
if (!target || !("value" in target)) return;
|
|
2052
|
+
clearTimeout(timer.current);
|
|
2053
|
+
timer.current = setTimeout(() => void runValidate(), kind === "blur" ? 0 : 300);
|
|
2054
|
+
}
|
|
2055
|
+
return /* @__PURE__ */ jsx(FormContext.Provider, {
|
|
2056
|
+
value: {
|
|
2057
|
+
errors,
|
|
2058
|
+
disabled
|
|
2059
|
+
},
|
|
2060
|
+
children: /* @__PURE__ */ jsx("form", {
|
|
2061
|
+
...rest,
|
|
2062
|
+
"data-scope": "form",
|
|
2063
|
+
"data-part": "root",
|
|
2064
|
+
noValidate: true,
|
|
2065
|
+
onSubmit: handleSubmit,
|
|
2066
|
+
onInput: (event) => onDelegated("input", event),
|
|
2067
|
+
onChange: (event) => onDelegated("change", event),
|
|
2068
|
+
onBlurCapture: (event) => onDelegated("blur", event),
|
|
2069
|
+
children
|
|
2070
|
+
})
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
function FormField({ name, label, hint, required = false, invalid = false, disabled = false, children, ...rest }) {
|
|
2074
|
+
const form = useContext(FormContext);
|
|
2075
|
+
const formError = name ? form?.errors.get(name) : void 0;
|
|
2076
|
+
const isInvalid = invalid || formError != null;
|
|
2077
|
+
const isDisabled = disabled || (form?.disabled ?? false);
|
|
2078
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2079
|
+
...rest,
|
|
2080
|
+
"data-form-field": name,
|
|
2081
|
+
children: /* @__PURE__ */ jsxs(Field$1.Root, {
|
|
2082
|
+
invalid: isInvalid,
|
|
2083
|
+
required,
|
|
2084
|
+
disabled: isDisabled,
|
|
2085
|
+
children: [
|
|
2086
|
+
label ? /* @__PURE__ */ jsx(Field$1.Label, { children: label }) : null,
|
|
2087
|
+
children,
|
|
2088
|
+
hint && formError == null ? /* @__PURE__ */ jsx(Field$1.HelperText, { children: hint }) : null,
|
|
2089
|
+
formError != null ? /* @__PURE__ */ jsx(Field$1.ErrorText, { children: formError }) : null
|
|
2090
|
+
]
|
|
2091
|
+
})
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
injectComponentStyle("form");
|
|
2095
|
+
injectComponentStyle("field");
|
|
2096
|
+
//#endregion
|
|
808
2097
|
//#region src/components/format/index.tsx
|
|
809
2098
|
/** Ark's Format, dressed in the paper-and-ink system: Intl formatting for
|
|
810
2099
|
* numbers, currency, bytes and relative time. The components render bare
|
|
@@ -823,6 +2112,34 @@ const Format = Format$1;
|
|
|
823
2112
|
* to hook. The API is Ark's own. */
|
|
824
2113
|
const Frame = Frame$1;
|
|
825
2114
|
//#endregion
|
|
2115
|
+
//#region src/components/grid/index.tsx
|
|
2116
|
+
/** The same named steps of the space ramp the stack uses — one
|
|
2117
|
+
* vocabulary of distance across the layout primitives. */
|
|
2118
|
+
const gapVars$2 = {
|
|
2119
|
+
none: "0",
|
|
2120
|
+
xs: "var(--bs-gap-xs)",
|
|
2121
|
+
sm: "var(--bs-gap-sm)",
|
|
2122
|
+
md: "var(--bs-gap-md)",
|
|
2123
|
+
lg: "var(--bs-gap-lg)",
|
|
2124
|
+
xl: "var(--bs-gap-xl)"
|
|
2125
|
+
};
|
|
2126
|
+
function Grid({ columns = 12, gap = "md", minChildWidth, ...rest }) {
|
|
2127
|
+
const style = {
|
|
2128
|
+
...rest.style,
|
|
2129
|
+
"--bs-grid-columns": String(columns),
|
|
2130
|
+
"--bs-grid-gap": gapVars$2[gap] ?? gapVars$2.md,
|
|
2131
|
+
...minChildWidth != null ? { "--bs-grid-min-child-width": minChildWidth } : {}
|
|
2132
|
+
};
|
|
2133
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2134
|
+
...rest,
|
|
2135
|
+
style,
|
|
2136
|
+
"data-scope": "grid",
|
|
2137
|
+
"data-part": "root",
|
|
2138
|
+
"data-autofill": minChildWidth != null ? "" : void 0
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
injectComponentStyle("grid");
|
|
2142
|
+
//#endregion
|
|
826
2143
|
//#region src/components/highlight/index.tsx
|
|
827
2144
|
/** Ark's Highlight, dressed in the paper-and-ink system: query hits are
|
|
828
2145
|
* strokes of pigment on the page — a quiet tint of the accent behind the
|
|
@@ -831,12 +2148,80 @@ const Frame = Frame$1;
|
|
|
831
2148
|
const Highlight = Highlight$1;
|
|
832
2149
|
injectComponentStyle("highlight");
|
|
833
2150
|
//#endregion
|
|
834
|
-
//#region src/components/hover-card/index.tsx
|
|
835
|
-
/** Ark's HoverCard, dressed in the paper-and-ink system: a preview card
|
|
836
|
-
* that dissolves in over a quiet inline link, never stealing focus. The
|
|
837
|
-
* API is Ark's own — Root, Trigger, Positioner, Content, Arrow, ArrowTip. */
|
|
838
|
-
const HoverCard = HoverCard$1;
|
|
839
|
-
injectComponentStyle("hover-card");
|
|
2151
|
+
//#region src/components/hover-card/index.tsx
|
|
2152
|
+
/** Ark's HoverCard, dressed in the paper-and-ink system: a preview card
|
|
2153
|
+
* that dissolves in over a quiet inline link, never stealing focus. The
|
|
2154
|
+
* API is Ark's own — Root, Trigger, Positioner, Content, Arrow, ArrowTip. */
|
|
2155
|
+
const HoverCard = HoverCard$1;
|
|
2156
|
+
injectComponentStyle("hover-card");
|
|
2157
|
+
//#endregion
|
|
2158
|
+
//#region src/components/icon/index.tsx
|
|
2159
|
+
function Icon({ size = "inherit", label, children, ...rest }) {
|
|
2160
|
+
return /* @__PURE__ */ jsx("span", {
|
|
2161
|
+
...rest,
|
|
2162
|
+
role: label != null ? "img" : void 0,
|
|
2163
|
+
"aria-label": label,
|
|
2164
|
+
"aria-hidden": label != null ? void 0 : "true",
|
|
2165
|
+
"data-scope": "icon",
|
|
2166
|
+
"data-part": "root",
|
|
2167
|
+
"data-size": size,
|
|
2168
|
+
children
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
injectComponentStyle("icon");
|
|
2172
|
+
//#endregion
|
|
2173
|
+
//#region src/components/image/index.tsx
|
|
2174
|
+
/** The mark for a source that never arrived: a quiet mountain-and-sun,
|
|
2175
|
+
* drawn in the stylesheet's stroke and hidden from the reader. */
|
|
2176
|
+
function placeholderGlyph() {
|
|
2177
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
2178
|
+
viewBox: "0 0 24 24",
|
|
2179
|
+
fill: "none",
|
|
2180
|
+
stroke: "currentColor",
|
|
2181
|
+
"aria-hidden": "true",
|
|
2182
|
+
children: [
|
|
2183
|
+
/* @__PURE__ */ jsx("rect", {
|
|
2184
|
+
x: 3,
|
|
2185
|
+
y: 4,
|
|
2186
|
+
width: 18,
|
|
2187
|
+
height: 16,
|
|
2188
|
+
rx: 1.5
|
|
2189
|
+
}),
|
|
2190
|
+
/* @__PURE__ */ jsx("circle", {
|
|
2191
|
+
cx: 9,
|
|
2192
|
+
cy: 10,
|
|
2193
|
+
r: 1.5
|
|
2194
|
+
}),
|
|
2195
|
+
/* @__PURE__ */ jsx("path", { d: "m5.5 17.5 4.5-5 3 3.5 2.5-3 3 4.5" })
|
|
2196
|
+
]
|
|
2197
|
+
});
|
|
2198
|
+
}
|
|
2199
|
+
function Image({ src, alt = "", fit = "cover", loading = "lazy", fallback, ...rest }) {
|
|
2200
|
+
const [state, setState] = useState("loading");
|
|
2201
|
+
useEffect(() => setState("loading"), [src]);
|
|
2202
|
+
return /* @__PURE__ */ jsxs("figure", {
|
|
2203
|
+
...rest,
|
|
2204
|
+
"data-scope": "image",
|
|
2205
|
+
"data-part": "root",
|
|
2206
|
+
"data-state": state,
|
|
2207
|
+
"data-fit": fit,
|
|
2208
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
2209
|
+
"data-scope": "image",
|
|
2210
|
+
"data-part": "img",
|
|
2211
|
+
src,
|
|
2212
|
+
alt,
|
|
2213
|
+
loading,
|
|
2214
|
+
decoding: "async",
|
|
2215
|
+
onLoad: () => setState("loaded"),
|
|
2216
|
+
onError: () => setState("error")
|
|
2217
|
+
}), state === "error" ? /* @__PURE__ */ jsx("div", {
|
|
2218
|
+
"data-scope": "image",
|
|
2219
|
+
"data-part": "fallback",
|
|
2220
|
+
children: fallback ?? placeholderGlyph()
|
|
2221
|
+
}) : null]
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2224
|
+
injectComponentStyle("image");
|
|
840
2225
|
//#endregion
|
|
841
2226
|
//#region src/components/image-cropper/index.tsx
|
|
842
2227
|
/** Ark's ImageCropper, dressed in the paper-and-ink system: a rounded vessel
|
|
@@ -846,6 +2231,136 @@ injectComponentStyle("hover-card");
|
|
|
846
2231
|
const ImageCropper = ImageCropper$1;
|
|
847
2232
|
injectComponentStyle("image-cropper");
|
|
848
2233
|
//#endregion
|
|
2234
|
+
//#region src/components/image-viewer/index.tsx
|
|
2235
|
+
const MIN_SCALE = .5;
|
|
2236
|
+
const MAX_SCALE = 3;
|
|
2237
|
+
const SCALE_STEP = .25;
|
|
2238
|
+
/** The toolbar's line-drawn glyphs, fresh per render. */
|
|
2239
|
+
const TOOL_GLYPHS = {
|
|
2240
|
+
zoomIn: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2241
|
+
/* @__PURE__ */ jsx("circle", {
|
|
2242
|
+
cx: 11,
|
|
2243
|
+
cy: 11,
|
|
2244
|
+
r: 7
|
|
2245
|
+
}),
|
|
2246
|
+
/* @__PURE__ */ jsx("path", { d: "m16.2 16.2 4.8 4.8" }),
|
|
2247
|
+
/* @__PURE__ */ jsx("path", { d: "M8 11h6" }),
|
|
2248
|
+
/* @__PURE__ */ jsx("path", { d: "M11 8v6" })
|
|
2249
|
+
] }),
|
|
2250
|
+
zoomOut: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2251
|
+
/* @__PURE__ */ jsx("circle", {
|
|
2252
|
+
cx: 11,
|
|
2253
|
+
cy: 11,
|
|
2254
|
+
r: 7
|
|
2255
|
+
}),
|
|
2256
|
+
/* @__PURE__ */ jsx("path", { d: "m16.2 16.2 4.8 4.8" }),
|
|
2257
|
+
/* @__PURE__ */ jsx("path", { d: "M8 11h6" })
|
|
2258
|
+
] }),
|
|
2259
|
+
rotate: () => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M20.49 12A8.5 8.5 0 1 1 18 6.06" }), /* @__PURE__ */ jsx("path", { d: "M20.5 3.5v4h-4" })] }),
|
|
2260
|
+
close: () => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" }), /* @__PURE__ */ jsx("path", { d: "M18 6 6 18" })] })
|
|
2261
|
+
};
|
|
2262
|
+
function ImageViewer({ src, alt = "", open, zoomable = true, onOpenChange }) {
|
|
2263
|
+
const [localOpen, setLocalOpen] = useState(false);
|
|
2264
|
+
const [scale, setScale] = useState(1);
|
|
2265
|
+
const [rotation, setRotation] = useState(0);
|
|
2266
|
+
const isOpen = open ?? localOpen;
|
|
2267
|
+
const setOpen = (value) => {
|
|
2268
|
+
if (open === void 0) setLocalOpen(value);
|
|
2269
|
+
onOpenChange?.(value);
|
|
2270
|
+
};
|
|
2271
|
+
useEffect(() => {
|
|
2272
|
+
if (isOpen) {
|
|
2273
|
+
setScale(1);
|
|
2274
|
+
setRotation(0);
|
|
2275
|
+
}
|
|
2276
|
+
}, [isOpen]);
|
|
2277
|
+
function zoom(step) {
|
|
2278
|
+
setScale((current) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, current + step)));
|
|
2279
|
+
}
|
|
2280
|
+
function rotate() {
|
|
2281
|
+
setRotation((current) => (current + 90) % 360);
|
|
2282
|
+
}
|
|
2283
|
+
function toolButton(label, glyph, onClick) {
|
|
2284
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
2285
|
+
variant: "ghost",
|
|
2286
|
+
square: true,
|
|
2287
|
+
size: "lg",
|
|
2288
|
+
"aria-label": label,
|
|
2289
|
+
onClick,
|
|
2290
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
2291
|
+
viewBox: "0 0 24 24",
|
|
2292
|
+
fill: "none",
|
|
2293
|
+
stroke: "currentColor",
|
|
2294
|
+
strokeWidth: 1.5,
|
|
2295
|
+
strokeLinecap: "round",
|
|
2296
|
+
strokeLinejoin: "round",
|
|
2297
|
+
"aria-hidden": "true",
|
|
2298
|
+
children: glyph()
|
|
2299
|
+
})
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
return /* @__PURE__ */ jsx(Dialog$1.Root, {
|
|
2303
|
+
open: isOpen,
|
|
2304
|
+
onOpenChange: (details) => setOpen(details.open),
|
|
2305
|
+
lazyMount: true,
|
|
2306
|
+
unmountOnExit: true,
|
|
2307
|
+
children: /* @__PURE__ */ jsxs(Portal, { children: [/* @__PURE__ */ jsx(Dialog$1.Backdrop, { className: "bs-image-viewer-backdrop" }), /* @__PURE__ */ jsx(Dialog$1.Positioner, {
|
|
2308
|
+
className: "bs-image-viewer-positioner",
|
|
2309
|
+
children: /* @__PURE__ */ jsxs(Dialog$1.Content, {
|
|
2310
|
+
className: "bs-image-viewer-content",
|
|
2311
|
+
"aria-label": alt || "Image preview",
|
|
2312
|
+
onClick: (event) => {
|
|
2313
|
+
if (event.target === event.currentTarget) setOpen(false);
|
|
2314
|
+
},
|
|
2315
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
2316
|
+
"data-scope": "image-viewer",
|
|
2317
|
+
"data-part": "viewport",
|
|
2318
|
+
src,
|
|
2319
|
+
alt,
|
|
2320
|
+
style: { transform: `scale(${scale}) rotate(${rotation}deg)` }
|
|
2321
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2322
|
+
"data-scope": "image-viewer",
|
|
2323
|
+
"data-part": "toolbar",
|
|
2324
|
+
children: /* @__PURE__ */ jsxs(ButtonGroup, { children: [
|
|
2325
|
+
zoomable ? [toolButton("Zoom in", TOOL_GLYPHS.zoomIn, () => zoom(SCALE_STEP)), toolButton("Zoom out", TOOL_GLYPHS.zoomOut, () => zoom(-.25))] : null,
|
|
2326
|
+
toolButton("Rotate 90 degrees", TOOL_GLYPHS.rotate, rotate),
|
|
2327
|
+
toolButton("Close", TOOL_GLYPHS.close, () => setOpen(false))
|
|
2328
|
+
] })
|
|
2329
|
+
})]
|
|
2330
|
+
})
|
|
2331
|
+
})] })
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
injectComponentStyle("image-viewer");
|
|
2335
|
+
//#endregion
|
|
2336
|
+
//#region src/components/input-group/index.tsx
|
|
2337
|
+
function part$6(name) {
|
|
2338
|
+
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx("div", {
|
|
2339
|
+
...rest,
|
|
2340
|
+
"data-scope": "input-group",
|
|
2341
|
+
"data-part": name.toLowerCase(),
|
|
2342
|
+
children
|
|
2343
|
+
});
|
|
2344
|
+
Component.displayName = "InputGroup" + name;
|
|
2345
|
+
return Component;
|
|
2346
|
+
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Merged controls: attachments and the entry fused into one seal. The
|
|
2349
|
+
* Root draws the single hairline and carries the group's focus halo;
|
|
2350
|
+
* the Addon is a recessed cell for the reader's fixed words — a scheme,
|
|
2351
|
+
* a unit, a quiet button — placed before or after the entry. Put our
|
|
2352
|
+
* Input (or Textarea) inside and its own border and halo step aside in
|
|
2353
|
+
* favor of the group's; the stylesheet does the merging, the wrapper
|
|
2354
|
+
* adds no visuals of its own.
|
|
2355
|
+
*/
|
|
2356
|
+
const Root$6 = part$6("Root");
|
|
2357
|
+
const Addon = part$6("Addon");
|
|
2358
|
+
const InputGroup = Object.assign(Root$6, {
|
|
2359
|
+
Root: Root$6,
|
|
2360
|
+
Addon
|
|
2361
|
+
});
|
|
2362
|
+
injectComponentStyle("input-group");
|
|
2363
|
+
//#endregion
|
|
849
2364
|
//#region src/components/json-tree-view/index.tsx
|
|
850
2365
|
/** Ark's JsonTreeView, dressed in the paper-and-ink system: the tree-view
|
|
851
2366
|
* recipes re-scoped, with value nodes reading as tabular data. The API is
|
|
@@ -864,6 +2379,136 @@ function Kbd({ children, ...rest }) {
|
|
|
864
2379
|
}
|
|
865
2380
|
injectComponentStyle("kbd");
|
|
866
2381
|
//#endregion
|
|
2382
|
+
//#region src/components/layout/index.tsx
|
|
2383
|
+
const LAYOUT_CONTEXT = createContext(null);
|
|
2384
|
+
/**
|
|
2385
|
+
* The application skeleton: Root, Header, Sider, Content, Footer —
|
|
2386
|
+
* the admin arrangement (Element Plus / AntD keep the same anatomy)
|
|
2387
|
+
* dressed in the paper-and-ink surfaces. The root is a full-height
|
|
2388
|
+
* grid; a declared `sider` turns the columns around to meet whichever
|
|
2389
|
+
* edge the rail stands on.
|
|
2390
|
+
*/
|
|
2391
|
+
function Root$5({ sider, children, ...rest }) {
|
|
2392
|
+
return /* @__PURE__ */ jsx(LAYOUT_CONTEXT.Provider, {
|
|
2393
|
+
value: { siderPlacement: () => sider },
|
|
2394
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2395
|
+
...rest,
|
|
2396
|
+
"data-scope": "layout",
|
|
2397
|
+
"data-part": "root",
|
|
2398
|
+
"data-sider": sider,
|
|
2399
|
+
children
|
|
2400
|
+
})
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
/** A semantic block of the skeleton — header, footer, and the flow's
|
|
2404
|
+
* main content each land on their native element and their grid area. */
|
|
2405
|
+
function region(name, tag) {
|
|
2406
|
+
const Tag = tag;
|
|
2407
|
+
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
2408
|
+
...rest,
|
|
2409
|
+
"data-scope": "layout",
|
|
2410
|
+
"data-part": name.toLowerCase(),
|
|
2411
|
+
children
|
|
2412
|
+
});
|
|
2413
|
+
Component.displayName = "Layout" + name;
|
|
2414
|
+
return Component;
|
|
2415
|
+
}
|
|
2416
|
+
const Header = region("Header", "header");
|
|
2417
|
+
const Content$2 = region("Content", "main");
|
|
2418
|
+
const Footer = region("Footer", "footer");
|
|
2419
|
+
/** One step of the arrow-key resize, in px. */
|
|
2420
|
+
const RESIZE_STEP = 16;
|
|
2421
|
+
function Sider({ collapsed = false, width: widthProp, collapsedWidth = "3.5rem", resizable = false, minWidth = "12rem", maxWidth = "24rem", style, onCollapsedChange, onWidthChange, children, ...rest }) {
|
|
2422
|
+
const layout = useContext(LAYOUT_CONTEXT);
|
|
2423
|
+
const rail = useRef(null);
|
|
2424
|
+
const [dragging, setDragging] = useState(false);
|
|
2425
|
+
const [innerWidth, setInnerWidth] = useState(widthProp ?? "16rem");
|
|
2426
|
+
const width = widthProp !== void 0 ? widthProp : innerWidth;
|
|
2427
|
+
const prevCollapsed = useRef(collapsed);
|
|
2428
|
+
useEffect(() => {
|
|
2429
|
+
if (prevCollapsed.current === collapsed) return;
|
|
2430
|
+
prevCollapsed.current = collapsed;
|
|
2431
|
+
onCollapsedChange?.(collapsed);
|
|
2432
|
+
}, [collapsed, onCollapsedChange]);
|
|
2433
|
+
const innerWidthRef = useRef(innerWidth);
|
|
2434
|
+
innerWidthRef.current = innerWidth;
|
|
2435
|
+
useEffect(() => {
|
|
2436
|
+
if (widthProp === void 0 || widthProp === innerWidthRef.current) return;
|
|
2437
|
+
setInnerWidth(widthProp);
|
|
2438
|
+
onWidthChange?.(widthProp);
|
|
2439
|
+
}, [widthProp, onWidthChange]);
|
|
2440
|
+
const applyWidth = (next) => {
|
|
2441
|
+
setInnerWidth(next);
|
|
2442
|
+
onWidthChange?.(next);
|
|
2443
|
+
};
|
|
2444
|
+
const dragStart = useRef({
|
|
2445
|
+
x: 0,
|
|
2446
|
+
width: 0
|
|
2447
|
+
});
|
|
2448
|
+
const onPointerDown = (event) => {
|
|
2449
|
+
setDragging(true);
|
|
2450
|
+
dragStart.current = {
|
|
2451
|
+
x: event.clientX,
|
|
2452
|
+
width: rail.current ? rail.current.getBoundingClientRect().width : 0
|
|
2453
|
+
};
|
|
2454
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
2455
|
+
};
|
|
2456
|
+
const onPointerMove = (event) => {
|
|
2457
|
+
if (!dragging) return;
|
|
2458
|
+
const towardFlow = (layout?.siderPlacement() ?? "start") === "end" ? -1 : 1;
|
|
2459
|
+
applyWidth(`${Math.round(dragStart.current.width + towardFlow * (event.clientX - dragStart.current.x))}px`);
|
|
2460
|
+
};
|
|
2461
|
+
const onPointerUp = (event) => {
|
|
2462
|
+
setDragging(false);
|
|
2463
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
2464
|
+
};
|
|
2465
|
+
const onKeyDown = (event) => {
|
|
2466
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
2467
|
+
event.preventDefault();
|
|
2468
|
+
const widen = (layout?.siderPlacement() ?? "start") === "end" ? event.key === "ArrowLeft" : event.key === "ArrowRight";
|
|
2469
|
+
const current = rail.current ? rail.current.getBoundingClientRect().width : 0;
|
|
2470
|
+
applyWidth(`${Math.round(current + (widen ? RESIZE_STEP : -16))}px`);
|
|
2471
|
+
};
|
|
2472
|
+
const handle = resizable && !collapsed ? /* @__PURE__ */ jsx("div", {
|
|
2473
|
+
"data-scope": "layout",
|
|
2474
|
+
"data-part": "sider-resize",
|
|
2475
|
+
"data-dragging": dragging ? "" : void 0,
|
|
2476
|
+
role: "separator",
|
|
2477
|
+
"aria-orientation": "vertical",
|
|
2478
|
+
tabIndex: 0,
|
|
2479
|
+
"aria-label": "Resize sidebar",
|
|
2480
|
+
"aria-valuenow": Math.round(rail.current ? rail.current.getBoundingClientRect().width : 0),
|
|
2481
|
+
onPointerDown,
|
|
2482
|
+
onPointerMove,
|
|
2483
|
+
onPointerUp,
|
|
2484
|
+
onKeyDown
|
|
2485
|
+
}) : null;
|
|
2486
|
+
return /* @__PURE__ */ jsxs("aside", {
|
|
2487
|
+
...rest,
|
|
2488
|
+
ref: rail,
|
|
2489
|
+
style: {
|
|
2490
|
+
...style,
|
|
2491
|
+
"--bs-layout-sider-width": collapsed ? collapsedWidth : width,
|
|
2492
|
+
"--bs-layout-sider-min": collapsed ? collapsedWidth : minWidth,
|
|
2493
|
+
"--bs-layout-sider-max": collapsed ? collapsedWidth : maxWidth
|
|
2494
|
+
},
|
|
2495
|
+
"data-scope": "layout",
|
|
2496
|
+
"data-part": "sider",
|
|
2497
|
+
"data-collapsed": collapsed ? "" : void 0,
|
|
2498
|
+
"data-dragging": dragging ? "" : void 0,
|
|
2499
|
+
"data-resizable": resizable ? "" : void 0,
|
|
2500
|
+
children: [typeof children === "function" ? children({ collapsed }) : children, handle]
|
|
2501
|
+
});
|
|
2502
|
+
}
|
|
2503
|
+
const Layout = Object.assign(Root$5, {
|
|
2504
|
+
Root: Root$5,
|
|
2505
|
+
Header,
|
|
2506
|
+
Sider,
|
|
2507
|
+
Content: Content$2,
|
|
2508
|
+
Footer
|
|
2509
|
+
});
|
|
2510
|
+
injectComponentStyle("layout");
|
|
2511
|
+
//#endregion
|
|
867
2512
|
//#region src/components/link/index.tsx
|
|
868
2513
|
/** A link is ink in the accent's voice: quiet at rest, deepening under
|
|
869
2514
|
* the hand, the halo at focus. The underline follows the prose —
|
|
@@ -879,6 +2524,69 @@ function Link({ underline = "hover", children, ...rest }) {
|
|
|
879
2524
|
}
|
|
880
2525
|
injectComponentStyle("link");
|
|
881
2526
|
//#endregion
|
|
2527
|
+
//#region src/components/list/index.tsx
|
|
2528
|
+
/** A ledger of rows: Root is the list, Item one row, Leading the mark
|
|
2529
|
+
* before the words, Content the title and its quiet echo, Actions the
|
|
2530
|
+
* way out. The bordered variant draws the hairlines; the hoverable
|
|
2531
|
+
* variant gives every row the wash — and any row the caller makes
|
|
2532
|
+
* clickable (role="button") answers the pointer on its own. */
|
|
2533
|
+
function part$5(name, tag) {
|
|
2534
|
+
const Tag = tag;
|
|
2535
|
+
function Component({ children, ...rest }) {
|
|
2536
|
+
return /* @__PURE__ */ jsx(Tag, {
|
|
2537
|
+
...rest,
|
|
2538
|
+
"data-scope": "list",
|
|
2539
|
+
"data-part": name.toLowerCase(),
|
|
2540
|
+
children
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
Component.displayName = "List" + name;
|
|
2544
|
+
return Component;
|
|
2545
|
+
}
|
|
2546
|
+
function Root$4({ bordered = false, hoverable = false, children, ...rest }) {
|
|
2547
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
2548
|
+
...rest,
|
|
2549
|
+
"data-scope": "list",
|
|
2550
|
+
"data-part": "root",
|
|
2551
|
+
"data-bordered": bordered || void 0,
|
|
2552
|
+
"data-hoverable": hoverable || void 0,
|
|
2553
|
+
children
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
Root$4.displayName = "ListRoot";
|
|
2557
|
+
const Item$1 = part$5("Item", "li");
|
|
2558
|
+
const Leading = part$5("Leading", "div");
|
|
2559
|
+
const Actions$1 = part$5("Actions", "div");
|
|
2560
|
+
function Content$1({ title, description, children, ...rest }) {
|
|
2561
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2562
|
+
...rest,
|
|
2563
|
+
"data-scope": "list",
|
|
2564
|
+
"data-part": "content",
|
|
2565
|
+
children: [
|
|
2566
|
+
title ? /* @__PURE__ */ jsx("div", {
|
|
2567
|
+
"data-scope": "list",
|
|
2568
|
+
"data-part": "title",
|
|
2569
|
+
children: title
|
|
2570
|
+
}) : null,
|
|
2571
|
+
description ? /* @__PURE__ */ jsx("div", {
|
|
2572
|
+
"data-scope": "list",
|
|
2573
|
+
"data-part": "description",
|
|
2574
|
+
children: description
|
|
2575
|
+
}) : null,
|
|
2576
|
+
children
|
|
2577
|
+
]
|
|
2578
|
+
});
|
|
2579
|
+
}
|
|
2580
|
+
Content$1.displayName = "ListContent";
|
|
2581
|
+
const List = Object.assign(Root$4, {
|
|
2582
|
+
Root: Root$4,
|
|
2583
|
+
Item: Item$1,
|
|
2584
|
+
Leading,
|
|
2585
|
+
Content: Content$1,
|
|
2586
|
+
Actions: Actions$1
|
|
2587
|
+
});
|
|
2588
|
+
injectComponentStyle("list");
|
|
2589
|
+
//#endregion
|
|
882
2590
|
//#region src/components/listbox/index.tsx
|
|
883
2591
|
/** Ark's Listbox, dressed in the paper-and-ink system: quiet rows of ink
|
|
884
2592
|
* where the checked row alone takes the flat primary fill. The API is
|
|
@@ -895,6 +2603,32 @@ injectComponentStyle("listbox");
|
|
|
895
2603
|
const Marquee = Marquee$1;
|
|
896
2604
|
injectComponentStyle("marquee");
|
|
897
2605
|
//#endregion
|
|
2606
|
+
//#region src/components/masonry/index.tsx
|
|
2607
|
+
/** The same named steps of the space ramp the stack uses — one
|
|
2608
|
+
* vocabulary of distance across the layout primitives. */
|
|
2609
|
+
const gapVars$1 = {
|
|
2610
|
+
none: "0",
|
|
2611
|
+
xs: "var(--bs-gap-xs)",
|
|
2612
|
+
sm: "var(--bs-gap-sm)",
|
|
2613
|
+
md: "var(--bs-gap-md)",
|
|
2614
|
+
lg: "var(--bs-gap-lg)",
|
|
2615
|
+
xl: "var(--bs-gap-xl)"
|
|
2616
|
+
};
|
|
2617
|
+
function Masonry({ columns = 3, gap = "md", ...rest }) {
|
|
2618
|
+
const style = {
|
|
2619
|
+
...rest.style,
|
|
2620
|
+
"--bs-masonry-columns": String(columns),
|
|
2621
|
+
"--bs-masonry-gap": gapVars$1[gap] ?? gapVars$1.md
|
|
2622
|
+
};
|
|
2623
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2624
|
+
...rest,
|
|
2625
|
+
style,
|
|
2626
|
+
"data-scope": "masonry",
|
|
2627
|
+
"data-part": "root"
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
injectComponentStyle("masonry");
|
|
2631
|
+
//#endregion
|
|
898
2632
|
//#region src/components/menu/index.tsx
|
|
899
2633
|
/** Ark's Menu, dressed in the paper-and-ink system: a quiet paper vessel on
|
|
900
2634
|
* elevation, hover as light on the row, checked items as the flat ink fill.
|
|
@@ -904,6 +2638,36 @@ injectComponentStyle("marquee");
|
|
|
904
2638
|
const Menu = Menu$1;
|
|
905
2639
|
injectComponentStyle("menu");
|
|
906
2640
|
//#endregion
|
|
2641
|
+
//#region src/components/menubar/index.tsx
|
|
2642
|
+
function Menubar({ items, onSelect, children, ...rest }) {
|
|
2643
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2644
|
+
...rest,
|
|
2645
|
+
"data-scope": "menubar",
|
|
2646
|
+
"data-part": "root",
|
|
2647
|
+
role: "menubar",
|
|
2648
|
+
children: [items.map((group) => /* @__PURE__ */ jsxs(Menu$1.Root, {
|
|
2649
|
+
positioning: { placement: "bottom-start" },
|
|
2650
|
+
children: [/* @__PURE__ */ jsx(Menu$1.Trigger, {
|
|
2651
|
+
asChild: true,
|
|
2652
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
2653
|
+
type: "button",
|
|
2654
|
+
"data-scope": "menubar",
|
|
2655
|
+
"data-part": "trigger",
|
|
2656
|
+
children: group.label
|
|
2657
|
+
})
|
|
2658
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Menu$1.Positioner, { children: /* @__PURE__ */ jsx(Menu$1.Content, { children: group.items.map((entry) => /* @__PURE__ */ jsx(Menu$1.Item, {
|
|
2659
|
+
value: entry.value,
|
|
2660
|
+
disabled: entry.disabled,
|
|
2661
|
+
"data-danger": entry.danger ? "" : void 0,
|
|
2662
|
+
onSelect: () => onSelect?.(entry.value),
|
|
2663
|
+
children: /* @__PURE__ */ jsx(Menu$1.ItemText, { children: entry.label })
|
|
2664
|
+
}, entry.value)) }) }) })]
|
|
2665
|
+
}, group.label)), children]
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
injectComponentStyle("menubar");
|
|
2669
|
+
injectComponentStyle("menu");
|
|
2670
|
+
//#endregion
|
|
907
2671
|
//#region src/components/meter/index.tsx
|
|
908
2672
|
function part$4(name, tag) {
|
|
909
2673
|
const Tag = tag;
|
|
@@ -918,7 +2682,7 @@ function part$4(name, tag) {
|
|
|
918
2682
|
}
|
|
919
2683
|
const Label$2 = part$4("Label", "span");
|
|
920
2684
|
const ValueText = part$4("ValueText", "span");
|
|
921
|
-
const Track = ({
|
|
2685
|
+
const Track = ({ ...rest }) => /* @__PURE__ */ jsx("span", {
|
|
922
2686
|
...rest,
|
|
923
2687
|
"data-scope": "meter",
|
|
924
2688
|
"data-part": "track",
|
|
@@ -1000,6 +2764,43 @@ injectComponentStyle("password-input");
|
|
|
1000
2764
|
const PinInput = PinInput$1;
|
|
1001
2765
|
injectComponentStyle("pin-input");
|
|
1002
2766
|
//#endregion
|
|
2767
|
+
//#region src/components/popconfirm/index.tsx
|
|
2768
|
+
function Popconfirm({ message, confirmText = "Confirm", cancelText = "Cancel", children, onConfirm, onCancel }) {
|
|
2769
|
+
const [open, setOpen] = useState(false);
|
|
2770
|
+
function settle(confirmed) {
|
|
2771
|
+
setOpen(false);
|
|
2772
|
+
(confirmed ? onConfirm : onCancel)?.();
|
|
2773
|
+
}
|
|
2774
|
+
return /* @__PURE__ */ jsxs(Popover$1.Root, {
|
|
2775
|
+
open,
|
|
2776
|
+
onOpenChange: (details) => setOpen(details.open),
|
|
2777
|
+
positioning: { placement: "top" },
|
|
2778
|
+
children: [/* @__PURE__ */ jsx(Popover$1.Trigger, {
|
|
2779
|
+
asChild: true,
|
|
2780
|
+
children
|
|
2781
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { children: /* @__PURE__ */ jsxs(Popover$1.Content, {
|
|
2782
|
+
className: "bs-popconfirm",
|
|
2783
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
2784
|
+
"data-part": "message",
|
|
2785
|
+
children: message
|
|
2786
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2787
|
+
"data-part": "actions",
|
|
2788
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
2789
|
+
variant: "ghost",
|
|
2790
|
+
size: "sm",
|
|
2791
|
+
onClick: () => settle(false),
|
|
2792
|
+
children: cancelText
|
|
2793
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
2794
|
+
size: "sm",
|
|
2795
|
+
onClick: () => settle(true),
|
|
2796
|
+
children: confirmText
|
|
2797
|
+
})]
|
|
2798
|
+
})]
|
|
2799
|
+
}) }) })]
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2802
|
+
injectComponentStyle("popconfirm");
|
|
2803
|
+
//#endregion
|
|
1003
2804
|
//#region src/components/popover/index.tsx
|
|
1004
2805
|
/** Ark's Popover, dressed in the paper-and-ink system: a paper vessel that
|
|
1005
2806
|
* dissolves in on elevation, anchored to its trigger by a whisker arrow. The
|
|
@@ -1016,6 +2817,59 @@ injectComponentStyle("popover");
|
|
|
1016
2817
|
const Progress = Progress$1;
|
|
1017
2818
|
injectComponentStyle("progress");
|
|
1018
2819
|
//#endregion
|
|
2820
|
+
//#region src/components/progress-group/index.tsx
|
|
2821
|
+
function ProgressGroup({ segments, max, showLegend = true, ...rest }) {
|
|
2822
|
+
const total = max ?? segments.reduce((sum, segment) => sum + segment.value, 0);
|
|
2823
|
+
const share = (value) => total > 0 ? `${value / total * 100}%` : "0%";
|
|
2824
|
+
const nameOf = (segment, index) => segment.label ?? segment.pigment ?? `Segment ${index + 1}`;
|
|
2825
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2826
|
+
...rest,
|
|
2827
|
+
"data-scope": "progress-group",
|
|
2828
|
+
"data-part": "root",
|
|
2829
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2830
|
+
"data-scope": "progress-group",
|
|
2831
|
+
"data-part": "track",
|
|
2832
|
+
children: segments.map((segment, index) => /* @__PURE__ */ jsx("div", {
|
|
2833
|
+
"data-scope": "progress-group",
|
|
2834
|
+
"data-part": "segment",
|
|
2835
|
+
"data-pigment": segment.pigment,
|
|
2836
|
+
role: "progressbar",
|
|
2837
|
+
"aria-valuenow": segment.value,
|
|
2838
|
+
"aria-valuemin": 0,
|
|
2839
|
+
"aria-valuemax": total,
|
|
2840
|
+
"aria-label": nameOf(segment, index),
|
|
2841
|
+
style: { inlineSize: share(segment.value) }
|
|
2842
|
+
}, index))
|
|
2843
|
+
}), showLegend ? /* @__PURE__ */ jsx("div", {
|
|
2844
|
+
"data-scope": "progress-group",
|
|
2845
|
+
"data-part": "legend",
|
|
2846
|
+
children: segments.map((segment, index) => /* @__PURE__ */ jsxs("div", {
|
|
2847
|
+
"data-scope": "progress-group",
|
|
2848
|
+
"data-part": "legend-item",
|
|
2849
|
+
"data-pigment": segment.pigment,
|
|
2850
|
+
children: [
|
|
2851
|
+
/* @__PURE__ */ jsx("span", {
|
|
2852
|
+
"data-scope": "progress-group",
|
|
2853
|
+
"data-part": "swatch",
|
|
2854
|
+
"aria-hidden": "true"
|
|
2855
|
+
}),
|
|
2856
|
+
/* @__PURE__ */ jsx("span", {
|
|
2857
|
+
"data-scope": "progress-group",
|
|
2858
|
+
"data-part": "legend-label",
|
|
2859
|
+
children: nameOf(segment, index)
|
|
2860
|
+
}),
|
|
2861
|
+
/* @__PURE__ */ jsx("span", {
|
|
2862
|
+
"data-scope": "progress-group",
|
|
2863
|
+
"data-part": "legend-value",
|
|
2864
|
+
children: String(segment.value)
|
|
2865
|
+
})
|
|
2866
|
+
]
|
|
2867
|
+
}, index))
|
|
2868
|
+
}) : null]
|
|
2869
|
+
});
|
|
2870
|
+
}
|
|
2871
|
+
injectComponentStyle("progress-group");
|
|
2872
|
+
//#endregion
|
|
1019
2873
|
//#region src/components/qr-code/index.tsx
|
|
1020
2874
|
/** Ark's QrCode, dressed in the paper-and-ink system: the pattern prints in
|
|
1021
2875
|
* ink on the page, with an optional paper badge and a seal-cut download
|
|
@@ -1103,6 +2957,71 @@ injectComponentStyle("skeleton");
|
|
|
1103
2957
|
const Slider = Slider$1;
|
|
1104
2958
|
injectComponentStyle("slider");
|
|
1105
2959
|
//#endregion
|
|
2960
|
+
//#region src/components/split-button/index.tsx
|
|
2961
|
+
/**
|
|
2962
|
+
* A primary action with its alternatives one seam away: the main button
|
|
2963
|
+
* fires `onClick`, the fitted arrow opens a paper vessel of the same
|
|
2964
|
+
* register whose entries report `onSelect` with their value. The arrow
|
|
2965
|
+
* is the menu machine's trigger grafting the button recipe — the
|
|
2966
|
+
* machine keeps the element (positioning, focus, `data-state`), the
|
|
2967
|
+
* button stylesheet's trigger register dresses it. The popup keeps the
|
|
2968
|
+
* menu parts untouched.
|
|
2969
|
+
*/
|
|
2970
|
+
function SplitButton({ label, items = [], variant = "solid", tone = "ink", size = "md", disabled = false, onClick, onSelect, ...rest }) {
|
|
2971
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2972
|
+
...rest,
|
|
2973
|
+
"data-scope": "split-button",
|
|
2974
|
+
"data-part": "root",
|
|
2975
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
2976
|
+
variant,
|
|
2977
|
+
tone,
|
|
2978
|
+
size,
|
|
2979
|
+
disabled,
|
|
2980
|
+
onClick,
|
|
2981
|
+
children: label
|
|
2982
|
+
}), /* @__PURE__ */ jsxs(Menu$1.Root, {
|
|
2983
|
+
positioning: { placement: "bottom-end" },
|
|
2984
|
+
children: [/* @__PURE__ */ jsx(Menu$1.Trigger, {
|
|
2985
|
+
asChild: true,
|
|
2986
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
2987
|
+
type: "button",
|
|
2988
|
+
disabled,
|
|
2989
|
+
"data-variant": variant,
|
|
2990
|
+
"data-tone": tone,
|
|
2991
|
+
"data-size": size,
|
|
2992
|
+
"data-square": "true",
|
|
2993
|
+
"data-motion": "ink-ripple lit",
|
|
2994
|
+
"aria-label": "More actions",
|
|
2995
|
+
children: chevronDown$1()
|
|
2996
|
+
})
|
|
2997
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Menu$1.Positioner, { children: /* @__PURE__ */ jsx(Menu$1.Content, { children: items.map((entry) => /* @__PURE__ */ jsx(Menu$1.Item, {
|
|
2998
|
+
value: entry.value,
|
|
2999
|
+
disabled: entry.disabled,
|
|
3000
|
+
"data-danger": entry.danger ? "" : void 0,
|
|
3001
|
+
onSelect: () => onSelect?.(entry.value),
|
|
3002
|
+
children: /* @__PURE__ */ jsx(Menu$1.ItemText, { children: entry.label })
|
|
3003
|
+
}, entry.value)) }) }) })]
|
|
3004
|
+
})]
|
|
3005
|
+
});
|
|
3006
|
+
}
|
|
3007
|
+
/** One stroke pointing down: all a fitted dropdown arrow needs. */
|
|
3008
|
+
function chevronDown$1() {
|
|
3009
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
3010
|
+
width: 16,
|
|
3011
|
+
height: 16,
|
|
3012
|
+
viewBox: "0 0 24 24",
|
|
3013
|
+
fill: "none",
|
|
3014
|
+
stroke: "currentColor",
|
|
3015
|
+
strokeWidth: 1.75,
|
|
3016
|
+
strokeLinecap: "round",
|
|
3017
|
+
strokeLinejoin: "round",
|
|
3018
|
+
"aria-hidden": "true",
|
|
3019
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
3020
|
+
});
|
|
3021
|
+
}
|
|
3022
|
+
injectComponentStyle("split-button");
|
|
3023
|
+
injectComponentStyle("menu");
|
|
3024
|
+
//#endregion
|
|
1106
3025
|
//#region src/components/splitter/index.tsx
|
|
1107
3026
|
/** Ark's Splitter, dressed in the paper-and-ink system: panels divide on
|
|
1108
3027
|
* a hairline and a small paper-seal thumb answers the hand. The API is
|
|
@@ -1110,6 +3029,35 @@ injectComponentStyle("slider");
|
|
|
1110
3029
|
const Splitter = Splitter$1;
|
|
1111
3030
|
injectComponentStyle("splitter");
|
|
1112
3031
|
//#endregion
|
|
3032
|
+
//#region src/components/stack/index.tsx
|
|
3033
|
+
/** Whitespace chosen by name: the named steps point at the space ramp so
|
|
3034
|
+
* siblings are held apart by one token, never by ad-hoc margins. */
|
|
3035
|
+
const gapVars = {
|
|
3036
|
+
none: "0",
|
|
3037
|
+
xs: "var(--bs-gap-xs)",
|
|
3038
|
+
sm: "var(--bs-gap-sm)",
|
|
3039
|
+
md: "var(--bs-gap-md)",
|
|
3040
|
+
lg: "var(--bs-gap-lg)",
|
|
3041
|
+
xl: "var(--bs-gap-xl)"
|
|
3042
|
+
};
|
|
3043
|
+
function Stack({ direction = "column", gap = "md", wrap = false, align, justify, ...rest }) {
|
|
3044
|
+
const style = {
|
|
3045
|
+
...rest.style,
|
|
3046
|
+
"--bs-stack-gap": gapVars[gap] ?? gapVars.md,
|
|
3047
|
+
alignItems: align,
|
|
3048
|
+
justifyContent: justify,
|
|
3049
|
+
flexWrap: wrap ? "wrap" : void 0
|
|
3050
|
+
};
|
|
3051
|
+
return /* @__PURE__ */ jsx("div", {
|
|
3052
|
+
...rest,
|
|
3053
|
+
style,
|
|
3054
|
+
"data-scope": "stack",
|
|
3055
|
+
"data-part": "root",
|
|
3056
|
+
"data-direction": direction
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
3059
|
+
injectComponentStyle("stack");
|
|
3060
|
+
//#endregion
|
|
1113
3061
|
//#region src/components/page-header/index.tsx
|
|
1114
3062
|
/** The page's face: an eyebrow whisper, a serif title, one line of
|
|
1115
3063
|
* description, and the actions resting beside the title on the same
|
|
@@ -1902,6 +3850,22 @@ function DataTable(rawProps) {
|
|
|
1902
3850
|
}
|
|
1903
3851
|
injectComponentStyle("table");
|
|
1904
3852
|
//#endregion
|
|
3853
|
+
//#region src/components/textarea/index.tsx
|
|
3854
|
+
function Textarea({ value, invalid = false, onValueChange, ...rest }) {
|
|
3855
|
+
const field = useFieldContext();
|
|
3856
|
+
const fieldProps = field?.getTextareaProps() ?? {};
|
|
3857
|
+
return /* @__PURE__ */ jsx("textarea", {
|
|
3858
|
+
...fieldProps,
|
|
3859
|
+
...rest,
|
|
3860
|
+
...value !== void 0 ? { value } : {},
|
|
3861
|
+
"data-scope": "textarea",
|
|
3862
|
+
"data-part": "root",
|
|
3863
|
+
"data-invalid": invalid || field?.invalid ? "" : void 0,
|
|
3864
|
+
onChange: (event) => onValueChange?.(event.target.value)
|
|
3865
|
+
});
|
|
3866
|
+
}
|
|
3867
|
+
injectComponentStyle("textarea");
|
|
3868
|
+
//#endregion
|
|
1905
3869
|
//#region src/components/timeline/index.tsx
|
|
1906
3870
|
/** A line of moments: Root is the ordered thread, Item one moment on it,
|
|
1907
3871
|
* Marker the point where the thread passes, Content what the moment
|
|
@@ -2016,6 +3980,255 @@ injectComponentStyle("tooltip");
|
|
|
2016
3980
|
const Tour = Tour$1;
|
|
2017
3981
|
injectComponentStyle("tour");
|
|
2018
3982
|
//#endregion
|
|
3983
|
+
//#region src/components/transfer/index.tsx
|
|
3984
|
+
const checkGlyph = /* @__PURE__ */ jsx("svg", {
|
|
3985
|
+
viewBox: "0 0 24 24",
|
|
3986
|
+
fill: "none",
|
|
3987
|
+
stroke: "currentColor",
|
|
3988
|
+
strokeWidth: 3,
|
|
3989
|
+
strokeLinecap: "round",
|
|
3990
|
+
strokeLinejoin: "round",
|
|
3991
|
+
"aria-hidden": "true",
|
|
3992
|
+
children: /* @__PURE__ */ jsx("path", { d: "m5 12.5 5 5L19 7" })
|
|
3993
|
+
});
|
|
3994
|
+
function arrowGlyph(direction) {
|
|
3995
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
3996
|
+
viewBox: "0 0 24 24",
|
|
3997
|
+
fill: "none",
|
|
3998
|
+
stroke: "currentColor",
|
|
3999
|
+
strokeWidth: 1.75,
|
|
4000
|
+
strokeLinecap: "round",
|
|
4001
|
+
strokeLinejoin: "round",
|
|
4002
|
+
"aria-hidden": "true",
|
|
4003
|
+
children: /* @__PURE__ */ jsx("path", { d: direction === "right" ? "M5 12h14m-6-6 6 6-6 6" : "M19 12H5m6-6-6 6 6 6" })
|
|
4004
|
+
});
|
|
4005
|
+
}
|
|
4006
|
+
/**
|
|
4007
|
+
* Two ledgers and a crossing: items sit in the source column until the
|
|
4008
|
+
* reader checks them and walks them across — and back, the same way.
|
|
4009
|
+
* `value` is the target column's value list; everything else in `data`
|
|
4010
|
+
* stays on the left. `searchable` adds a filter line to each panel.
|
|
4011
|
+
*/
|
|
4012
|
+
function Transfer({ value = [], data, titles = ["Source", "Target"], searchable = false, disabled = false, onValueChange, ...rest }) {
|
|
4013
|
+
const [checkedSource, setCheckedSource] = useState(() => /* @__PURE__ */ new Set());
|
|
4014
|
+
const [checkedTarget, setCheckedTarget] = useState(() => /* @__PURE__ */ new Set());
|
|
4015
|
+
const [sourceQuery, setSourceQuery] = useState("");
|
|
4016
|
+
const [targetQuery, setTargetQuery] = useState("");
|
|
4017
|
+
const target = new Set(value);
|
|
4018
|
+
function panelItems(values, inTarget, query) {
|
|
4019
|
+
return values.filter((item) => item.label.toLowerCase().includes(query.toLowerCase()) && target.has(item.value) === inTarget);
|
|
4020
|
+
}
|
|
4021
|
+
function toggle(side, option) {
|
|
4022
|
+
(side === "source" ? setCheckedSource : setCheckedTarget)((prev) => {
|
|
4023
|
+
const next = new Set(prev);
|
|
4024
|
+
if (next.has(option)) next.delete(option);
|
|
4025
|
+
else next.add(option);
|
|
4026
|
+
return next;
|
|
4027
|
+
});
|
|
4028
|
+
}
|
|
4029
|
+
function move(toTarget) {
|
|
4030
|
+
const moving = toTarget ? checkedSource : checkedTarget;
|
|
4031
|
+
if (moving.size === 0) return;
|
|
4032
|
+
const next = toTarget ? [...value, ...moving].filter((entry, index, all) => all.indexOf(entry) === index) : value.filter((entry) => !moving.has(entry));
|
|
4033
|
+
if (toTarget) setCheckedSource(/* @__PURE__ */ new Set());
|
|
4034
|
+
else setCheckedTarget(/* @__PURE__ */ new Set());
|
|
4035
|
+
onValueChange?.(next);
|
|
4036
|
+
}
|
|
4037
|
+
function panel(side, title, query, onQuery, checked, items) {
|
|
4038
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4039
|
+
"data-scope": "transfer",
|
|
4040
|
+
"data-part": "panel",
|
|
4041
|
+
"data-side": side,
|
|
4042
|
+
children: [
|
|
4043
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4044
|
+
"data-scope": "transfer",
|
|
4045
|
+
"data-part": "head",
|
|
4046
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4047
|
+
"data-scope": "transfer",
|
|
4048
|
+
"data-part": "title",
|
|
4049
|
+
children: title
|
|
4050
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4051
|
+
"data-scope": "transfer",
|
|
4052
|
+
"data-part": "count",
|
|
4053
|
+
children: items.length
|
|
4054
|
+
})]
|
|
4055
|
+
}),
|
|
4056
|
+
searchable ? /* @__PURE__ */ jsx("div", {
|
|
4057
|
+
"data-scope": "transfer",
|
|
4058
|
+
"data-part": "search",
|
|
4059
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
4060
|
+
size: "sm",
|
|
4061
|
+
value: query,
|
|
4062
|
+
onValueChange: onQuery,
|
|
4063
|
+
placeholder: "Filter…",
|
|
4064
|
+
"aria-label": `Filter ${title}`
|
|
4065
|
+
})
|
|
4066
|
+
}) : null,
|
|
4067
|
+
/* @__PURE__ */ jsx("div", {
|
|
4068
|
+
"data-scope": "transfer",
|
|
4069
|
+
"data-part": "list",
|
|
4070
|
+
children: items.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
4071
|
+
"data-scope": "transfer",
|
|
4072
|
+
"data-part": "empty",
|
|
4073
|
+
children: "Nothing here"
|
|
4074
|
+
}) : items.map((item) => {
|
|
4075
|
+
const locked = disabled || item.disabled === true;
|
|
4076
|
+
return /* @__PURE__ */ jsxs(Checkbox$1.Root, {
|
|
4077
|
+
checked: checked.has(item.value),
|
|
4078
|
+
disabled: locked,
|
|
4079
|
+
onCheckedChange: () => toggle(side, item.value),
|
|
4080
|
+
children: [
|
|
4081
|
+
/* @__PURE__ */ jsx(Checkbox$1.Control, { children: /* @__PURE__ */ jsx(Checkbox$1.Indicator, { children: checkGlyph }) }),
|
|
4082
|
+
/* @__PURE__ */ jsx(Checkbox$1.Label, {
|
|
4083
|
+
"data-part": "label",
|
|
4084
|
+
children: item.label
|
|
4085
|
+
}),
|
|
4086
|
+
/* @__PURE__ */ jsx(Checkbox$1.HiddenInput, {})
|
|
4087
|
+
]
|
|
4088
|
+
}, item.value);
|
|
4089
|
+
})
|
|
4090
|
+
})
|
|
4091
|
+
]
|
|
4092
|
+
});
|
|
4093
|
+
}
|
|
4094
|
+
const items = panelItems(data, false, sourceQuery);
|
|
4095
|
+
const targetItems = panelItems(data, true, targetQuery);
|
|
4096
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4097
|
+
...rest,
|
|
4098
|
+
"data-scope": "transfer",
|
|
4099
|
+
"data-part": "root",
|
|
4100
|
+
children: [
|
|
4101
|
+
panel("source", titles[0], sourceQuery, setSourceQuery, checkedSource, items),
|
|
4102
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4103
|
+
"data-scope": "transfer",
|
|
4104
|
+
"data-part": "operations",
|
|
4105
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
4106
|
+
variant: "outline",
|
|
4107
|
+
size: "sm",
|
|
4108
|
+
square: true,
|
|
4109
|
+
disabled: checkedSource.size === 0 || disabled,
|
|
4110
|
+
"aria-label": "Move right",
|
|
4111
|
+
onClick: () => move(true),
|
|
4112
|
+
children: arrowGlyph("right")
|
|
4113
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
4114
|
+
variant: "outline",
|
|
4115
|
+
size: "sm",
|
|
4116
|
+
square: true,
|
|
4117
|
+
disabled: checkedTarget.size === 0 || disabled,
|
|
4118
|
+
"aria-label": "Move left",
|
|
4119
|
+
onClick: () => move(false),
|
|
4120
|
+
children: arrowGlyph("left")
|
|
4121
|
+
})]
|
|
4122
|
+
}),
|
|
4123
|
+
panel("target", titles[1], targetQuery, setTargetQuery, checkedTarget, targetItems)
|
|
4124
|
+
]
|
|
4125
|
+
});
|
|
4126
|
+
}
|
|
4127
|
+
injectComponentStyle("transfer");
|
|
4128
|
+
injectComponentStyle("checkbox");
|
|
4129
|
+
//#endregion
|
|
4130
|
+
//#region src/components/tree-select/index.tsx
|
|
4131
|
+
const chevron = /* @__PURE__ */ jsx("svg", {
|
|
4132
|
+
viewBox: "0 0 24 24",
|
|
4133
|
+
fill: "none",
|
|
4134
|
+
stroke: "currentColor",
|
|
4135
|
+
strokeWidth: 2,
|
|
4136
|
+
strokeLinecap: "round",
|
|
4137
|
+
strokeLinejoin: "round",
|
|
4138
|
+
"aria-hidden": "true",
|
|
4139
|
+
children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
|
|
4140
|
+
});
|
|
4141
|
+
const chevronDown = /* @__PURE__ */ jsx("span", {
|
|
4142
|
+
"data-part": "chevron",
|
|
4143
|
+
"aria-hidden": "true",
|
|
4144
|
+
children: chevron
|
|
4145
|
+
});
|
|
4146
|
+
function TreeSelectRow({ node, indexPath }) {
|
|
4147
|
+
return /* @__PURE__ */ jsx(TreeView$1.NodeProvider, {
|
|
4148
|
+
node,
|
|
4149
|
+
indexPath,
|
|
4150
|
+
children: node.children ? /* @__PURE__ */ jsxs(TreeView$1.Branch, { children: [/* @__PURE__ */ jsxs(TreeView$1.BranchControl, { children: [/* @__PURE__ */ jsx(TreeView$1.BranchIndicator, { children: chevron }), /* @__PURE__ */ jsx(TreeView$1.BranchText, { children: node.label })] }), /* @__PURE__ */ jsxs(TreeView$1.BranchContent, { children: [/* @__PURE__ */ jsx(TreeView$1.BranchIndentGuide, {}), node.children.map((child, index) => /* @__PURE__ */ jsx(TreeSelectRow, {
|
|
4151
|
+
node: child,
|
|
4152
|
+
indexPath: [...indexPath, index]
|
|
4153
|
+
}, child.value))] })] }) : /* @__PURE__ */ jsx(TreeView$1.Item, {
|
|
4154
|
+
asChild: true,
|
|
4155
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
4156
|
+
style: {
|
|
4157
|
+
display: "flex",
|
|
4158
|
+
inlineSize: "100%"
|
|
4159
|
+
},
|
|
4160
|
+
children: /* @__PURE__ */ jsx(TreeView$1.ItemText, { children: node.label })
|
|
4161
|
+
})
|
|
4162
|
+
})
|
|
4163
|
+
});
|
|
4164
|
+
}
|
|
4165
|
+
function TreeSelect({ value, data, placeholder = "Select…", disabled = false, onValueChange, ...rest }) {
|
|
4166
|
+
const [open, setOpen] = useState(false);
|
|
4167
|
+
const collection = createTreeCollection$1({
|
|
4168
|
+
nodeToValue: (node) => node.value,
|
|
4169
|
+
nodeToString: (node) => node.label,
|
|
4170
|
+
rootNode: {
|
|
4171
|
+
value: "ROOT",
|
|
4172
|
+
label: "",
|
|
4173
|
+
children: data
|
|
4174
|
+
}
|
|
4175
|
+
});
|
|
4176
|
+
const firstLevel = data.map((node) => node.value);
|
|
4177
|
+
let found;
|
|
4178
|
+
const walk = (nodes) => {
|
|
4179
|
+
for (const node of nodes ?? []) {
|
|
4180
|
+
if (node.value === value) found = node.label;
|
|
4181
|
+
walk(node.children);
|
|
4182
|
+
}
|
|
4183
|
+
};
|
|
4184
|
+
walk(data);
|
|
4185
|
+
const label = found;
|
|
4186
|
+
function pick(details) {
|
|
4187
|
+
const [selected] = details.selectedValue;
|
|
4188
|
+
if (selected == null) return;
|
|
4189
|
+
onValueChange?.(selected);
|
|
4190
|
+
setOpen(false);
|
|
4191
|
+
}
|
|
4192
|
+
return /* @__PURE__ */ jsxs(Popover$1.Root, {
|
|
4193
|
+
...rest,
|
|
4194
|
+
open,
|
|
4195
|
+
onOpenChange: (details) => setOpen(details.open),
|
|
4196
|
+
positioning: {
|
|
4197
|
+
sameWidth: true,
|
|
4198
|
+
placement: "bottom-start"
|
|
4199
|
+
},
|
|
4200
|
+
children: [/* @__PURE__ */ jsx(Popover$1.Trigger, {
|
|
4201
|
+
asChild: true,
|
|
4202
|
+
disabled,
|
|
4203
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
4204
|
+
type: "button",
|
|
4205
|
+
"data-scope": "tree-select",
|
|
4206
|
+
"data-part": "control",
|
|
4207
|
+
"data-open": open ? "" : void 0,
|
|
4208
|
+
"data-placeholder": label == null ? "" : void 0,
|
|
4209
|
+
disabled,
|
|
4210
|
+
children: [label ?? placeholder, chevronDown]
|
|
4211
|
+
})
|
|
4212
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { children: /* @__PURE__ */ jsx(Popover$1.Content, {
|
|
4213
|
+
"data-scope": "tree-select",
|
|
4214
|
+
"data-part": "content",
|
|
4215
|
+
children: /* @__PURE__ */ jsx(TreeView$1.Root, {
|
|
4216
|
+
collection,
|
|
4217
|
+
selectionMode: "single",
|
|
4218
|
+
selectedValue: value ? [value] : [],
|
|
4219
|
+
defaultExpandedValue: firstLevel,
|
|
4220
|
+
onSelectionChange: pick,
|
|
4221
|
+
children: /* @__PURE__ */ jsx(TreeView$1.Tree, { children: collection.rootNode.children?.map((node, index) => /* @__PURE__ */ jsx(TreeSelectRow, {
|
|
4222
|
+
node,
|
|
4223
|
+
indexPath: [index]
|
|
4224
|
+
}, node.value)) })
|
|
4225
|
+
})
|
|
4226
|
+
}) }) })]
|
|
4227
|
+
});
|
|
4228
|
+
}
|
|
4229
|
+
injectComponentStyle("tree-select");
|
|
4230
|
+
injectComponentStyle("tree-view");
|
|
4231
|
+
//#endregion
|
|
2019
4232
|
//#region src/components/tree-view/index.tsx
|
|
2020
4233
|
/** Ark's TreeView, dressed in the paper-and-ink system: quiet rows where
|
|
2021
4234
|
* selection is pure light on the paper, one hairline plumb line per depth,
|
|
@@ -2027,4 +4240,80 @@ injectComponentStyle("tour");
|
|
|
2027
4240
|
const TreeView = TreeView$1;
|
|
2028
4241
|
injectComponentStyle("tree-view");
|
|
2029
4242
|
//#endregion
|
|
2030
|
-
|
|
4243
|
+
//#region src/components/watermark/index.tsx
|
|
4244
|
+
/** Font-relative measures ride the root's own measure; absolute units
|
|
4245
|
+
* pass through untouched — the canvas needs a number, the prop may
|
|
4246
|
+
* speak in CSS. */
|
|
4247
|
+
function toPx(size) {
|
|
4248
|
+
const root = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
4249
|
+
const value = Number.parseFloat(size) || 0;
|
|
4250
|
+
if (size.includes("em")) return value * root;
|
|
4251
|
+
return value;
|
|
4252
|
+
}
|
|
4253
|
+
/**
|
|
4254
|
+
* The paper bears its seal beneath the content: a canvas draws the
|
|
4255
|
+
* text once into a tile (rotated, faint, crisp at the screen's pixel
|
|
4256
|
+
* density) and the marks layer repeats it over the children. The seal
|
|
4257
|
+
* redraws itself when a prop turns — and it never takes a pointer.
|
|
4258
|
+
*/
|
|
4259
|
+
function Watermark({ content, opacity = .06, rotate = -20, fontSize = "0.875rem", children, ...rest }) {
|
|
4260
|
+
const [root, setRoot] = useState(null);
|
|
4261
|
+
const [tile, setTile] = useState("");
|
|
4262
|
+
useEffect(() => {
|
|
4263
|
+
if (!root) return;
|
|
4264
|
+
const canvas = document.createElement("canvas");
|
|
4265
|
+
const paint = canvas.getContext("2d");
|
|
4266
|
+
if (!paint) return;
|
|
4267
|
+
const styles = getComputedStyle(root);
|
|
4268
|
+
const fontSizePx = toPx(fontSize);
|
|
4269
|
+
const font = `${styles.fontWeight} ${fontSizePx}px ${styles.fontFamily}`;
|
|
4270
|
+
paint.font = font;
|
|
4271
|
+
const textWidth = paint.measureText(content).width;
|
|
4272
|
+
const margin = fontSizePx;
|
|
4273
|
+
const boxWidth = Math.ceil(textWidth + margin * 2);
|
|
4274
|
+
const boxHeight = Math.ceil(fontSizePx + margin * 2);
|
|
4275
|
+
const radian = rotate * Math.PI / 180;
|
|
4276
|
+
const cos = Math.cos(radian);
|
|
4277
|
+
const sin = Math.sin(radian);
|
|
4278
|
+
const width = Math.ceil(Math.abs(boxWidth * cos) + Math.abs(boxHeight * sin));
|
|
4279
|
+
const height = Math.ceil(Math.abs(boxWidth * sin) + Math.abs(boxHeight * cos));
|
|
4280
|
+
const dpr = window.devicePixelRatio || 1;
|
|
4281
|
+
canvas.width = width * dpr;
|
|
4282
|
+
canvas.height = height * dpr;
|
|
4283
|
+
paint.scale(dpr, dpr);
|
|
4284
|
+
paint.translate(width / 2, height / 2);
|
|
4285
|
+
paint.rotate(radian);
|
|
4286
|
+
paint.globalAlpha = opacity;
|
|
4287
|
+
paint.font = font;
|
|
4288
|
+
paint.textAlign = "center";
|
|
4289
|
+
paint.textBaseline = "middle";
|
|
4290
|
+
paint.fillStyle = styles.getPropertyValue("--bs-color-text-tertiary").trim() || styles.color;
|
|
4291
|
+
paint.fillText(content, 0, 0);
|
|
4292
|
+
setTile(`url(${canvas.toDataURL()})`);
|
|
4293
|
+
}, [
|
|
4294
|
+
root,
|
|
4295
|
+
content,
|
|
4296
|
+
opacity,
|
|
4297
|
+
rotate,
|
|
4298
|
+
fontSize
|
|
4299
|
+
]);
|
|
4300
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4301
|
+
...rest,
|
|
4302
|
+
ref: setRoot,
|
|
4303
|
+
"data-scope": "watermark",
|
|
4304
|
+
"data-part": "root",
|
|
4305
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
4306
|
+
"data-scope": "watermark",
|
|
4307
|
+
"data-part": "content",
|
|
4308
|
+
children
|
|
4309
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
4310
|
+
"data-scope": "watermark",
|
|
4311
|
+
"data-part": "marks",
|
|
4312
|
+
"aria-hidden": "true",
|
|
4313
|
+
style: { backgroundImage: tile }
|
|
4314
|
+
})]
|
|
4315
|
+
});
|
|
4316
|
+
}
|
|
4317
|
+
injectComponentStyle("watermark");
|
|
4318
|
+
//#endregion
|
|
4319
|
+
export { Accordion, Action, Action as AiAction, Affix, Ai, Attachment as AiAttachment, Attachment, Attachments as AiAttachments, Attachments, Message as AiMessage, Message, PromptInput as AiPromptInput, PromptInput, Reasoning as AiReasoning, Reasoning, Response as AiResponse, Response, Source as AiSource, Source, Sources as AiSources, Sources, Suggestion as AiSuggestion, Suggestion, Tool as AiTool, Tool, Alert, AngleSlider, AspectRatio, AutoComplete, Avatar, AvatarGroup, BackTop, Badge, Banner, Breadcrumb, Button, ButtonGroup, Calendar, Card, Carousel, CascadeSelect, Checkbox, CheckboxGroup, Chip, ClientOnly, Clipboard, Collapsible, ColorPicker, Combobox, Command, Comment, ConfigProvider, Container, DataTable, DateInput, DatePicker, Descriptions, DescriptionsRoot, Dialog, DownloadTrigger, Drawer, DynamicInput, Editable, Ellipsis, Empty, FLOAT_BUTTON_CONTEXT, Field, Fieldset, FileUpload, FlexRender, FloatButton, FloatingPanel, FocusTrap, Form, FormField, Format, Frame, Grid, Highlight, HoverCard, Icon, Image, ImageCropper, ImageViewer, Input, InputGroup, JsonTreeView, Kbd, Layout, Link, List, Listbox, Marquee, Masonry, Mentions, MentionsVessel, Menu, Menubar, Meter, NavigationMenu, NumberInput, PageHeader, Pagination, PasswordInput, PinInput, Popconfirm, Popover, Presence, PresenceProvider, Progress, ProgressGroup, QrCode, RadioGroup, RatingGroup, ScrollArea, SegmentGroup, Select, Separator, SignaturePad, Skeleton, Slider, Spinner, SplitButton, Splitter, Stack, Stat, Steps, Swap, Switch, Tabs, TagsInput, Textarea, Timeline, Timer, Toast, Toaster, Toc, Toggle, ToggleGroup, Tooltip, Tour, Transfer, TreeSelect, TreeView, Typography, Watermark, createColumnHelper, createFileTreeCollection, createGridCollection, createToaster, createTreeCollection, useAsyncList, useConfig, useDownload, useListCollection, useListSelection, useMentions, usePresence, usePresenceContext, useTour };
|