@bysages/solid 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/dist/index.mjs CHANGED
@@ -1,40 +1,49 @@
1
1
  import { injectComponentStyle } from "@bysages/core";
2
2
  import { Accordion as Accordion$1 } from "@ark-ui/solid/accordion";
3
- import { addEventListener, createComponent, delegateEvents, effect, insert, memo, mergeProps, setAttribute, setStyleProperty, spread, style, template, use } from "solid-js/web";
4
- import { renderHtml } from "@tanstack/markdown/html";
5
- import { For, Show, createContext, createMemo, createSignal, mergeProps as mergeProps$1, onCleanup, onMount, splitProps as splitProps$1, useContext } from "solid-js";
3
+ import { Portal, addEventListener, createComponent, delegateEvents, effect, insert, memo, mergeProps, setAttribute, setStyleProperty, spread, style, template, use } from "solid-js/web";
4
+ import { For, Index, Show, createContext, createEffect, createMemo, createSignal, createUniqueId, mergeProps as mergeProps$1, on, onCleanup, onMount, splitProps, useContext } from "solid-js";
5
+ import { Field as Field$1, useFieldContext } from "@ark-ui/solid/field";
6
6
  import { Collapsible as Collapsible$1 } from "@ark-ui/solid/collapsible";
7
- import { Field as Field$1 } from "@ark-ui/solid/field";
7
+ import { renderHtml } from "@tanstack/markdown/html";
8
8
  import { AngleSlider as AngleSlider$1 } from "@ark-ui/solid/angle-slider";
9
+ import { createFileTreeCollection, createGridCollection, createTreeCollection, useAsyncList, useListCollection, useListCollection as useListCollection$1, useListSelection } from "@ark-ui/solid/collection";
10
+ import { Combobox as Combobox$1 } from "@ark-ui/solid/combobox";
9
11
  import { Avatar as Avatar$1 } from "@ark-ui/solid/avatar";
10
12
  import { DatePicker as DatePicker$1 } from "@ark-ui/solid/date-picker";
11
13
  import { Carousel as Carousel$1 } from "@ark-ui/solid/carousel";
14
+ import { useEnvironmentContext } from "@ark-ui/solid/environment";
15
+ import { useLocaleContext } from "@ark-ui/solid/locale";
16
+ import * as cascade from "@zag-js/cascade-select";
17
+ import { normalizeProps, useMachine } from "@zag-js/solid";
12
18
  import { Checkbox as Checkbox$1 } from "@ark-ui/solid/checkbox";
19
+ import { ClientOnly } from "@ark-ui/solid/client-only";
13
20
  import { Clipboard as Clipboard$1 } from "@ark-ui/solid/clipboard";
14
21
  import { ColorPicker as ColorPicker$1 } from "@ark-ui/solid/color-picker";
15
- import { Combobox as Combobox$1 } from "@ark-ui/solid/combobox";
16
- import { DateInput as DateInput$1 } from "@ark-ui/solid/date-input";
17
22
  import { Dialog as Dialog$1 } from "@ark-ui/solid/dialog";
23
+ import { DateInput as DateInput$1 } from "@ark-ui/solid/date-input";
24
+ import { DownloadTrigger, useDownload } from "@ark-ui/solid/download-trigger";
18
25
  import { Drawer as Drawer$1 } from "@ark-ui/solid/drawer";
19
26
  import { Editable as Editable$1 } from "@ark-ui/solid/editable";
20
27
  import { Fieldset as Fieldset$1 } from "@ark-ui/solid/fieldset";
21
28
  import { FileUpload as FileUpload$1 } from "@ark-ui/solid/file-upload";
22
29
  import { FloatingPanel as FloatingPanel$1 } from "@ark-ui/solid/floating-panel";
30
+ import { FocusTrap } from "@ark-ui/solid/focus-trap";
23
31
  import { Format as Format$1 } from "@ark-ui/solid/format";
24
32
  import { Frame as Frame$1 } from "@ark-ui/solid/frame";
25
33
  import { Highlight as Highlight$1 } from "@ark-ui/solid/highlight";
26
34
  import { HoverCard as HoverCard$1 } from "@ark-ui/solid/hover-card";
27
35
  import { ImageCropper as ImageCropper$1 } from "@ark-ui/solid/image-cropper";
28
36
  import { JsonTreeView as JsonTreeView$1 } from "@ark-ui/solid/json-tree-view";
29
- import { Listbox as Listbox$1, createListCollection } from "@ark-ui/solid/listbox";
37
+ import { Listbox as Listbox$1 } from "@ark-ui/solid/listbox";
30
38
  import { Marquee as Marquee$1 } from "@ark-ui/solid/marquee";
31
39
  import { Menu as Menu$1 } from "@ark-ui/solid/menu";
40
+ import { Popover as Popover$1 } from "@ark-ui/solid/popover";
32
41
  import { NavigationMenu as NavigationMenu$1 } from "@ark-ui/solid/navigation-menu";
33
42
  import { NumberInput as NumberInput$1 } from "@ark-ui/solid/number-input";
34
43
  import { Pagination as Pagination$1 } from "@ark-ui/solid/pagination";
35
44
  import { PasswordInput as PasswordInput$1 } from "@ark-ui/solid/password-input";
36
45
  import { PinInput as PinInput$1 } from "@ark-ui/solid/pin-input";
37
- import { Popover as Popover$1 } from "@ark-ui/solid/popover";
46
+ import { Presence, PresenceProvider, usePresence, usePresenceContext } from "@ark-ui/solid/presence";
38
47
  import { Progress as Progress$1 } from "@ark-ui/solid/progress";
39
48
  import { QrCode as QrCode$1 } from "@ark-ui/solid/qr-code";
40
49
  import { RadioGroup as RadioGroup$1 } from "@ark-ui/solid/radio-group";
@@ -59,7 +68,7 @@ import { Toggle as Toggle$1 } from "@ark-ui/solid/toggle";
59
68
  import { ToggleGroup as ToggleGroup$1 } from "@ark-ui/solid/toggle-group";
60
69
  import { Tooltip as Tooltip$1 } from "@ark-ui/solid/tooltip";
61
70
  import { Tour as Tour$1, useTour } from "@ark-ui/solid/tour";
62
- import { TreeView as TreeView$1 } from "@ark-ui/solid/tree-view";
71
+ import { TreeView as TreeView$1, createTreeCollection as createTreeCollection$1 } from "@ark-ui/solid/tree-view";
63
72
  export * from "@bysages/core";
64
73
  //#region src/components/accordion/index.ts
65
74
  /** Ark's Accordion, dressed in the paper-and-ink system: a ruled sheet
@@ -68,10 +77,41 @@ export * from "@bysages/core";
68
77
  const Accordion = Accordion$1;
69
78
  injectComponentStyle("accordion");
70
79
  //#endregion
80
+ //#region src/components/affix/index.tsx
81
+ var _tmpl$$58 = /*#__PURE__*/ template(`<div>`);
82
+ /**
83
+ * A nail: the wrapped content travels with the page until it reaches its
84
+ * offset, then stays put while the page moves on. The semantics are
85
+ * plain `position: sticky` — pinning is relative to the nearest
86
+ * *scrolling* ancestor, so the element works inside a scrollable panel
87
+ * exactly as it does on the page itself, and a parent with
88
+ * `overflow: hidden` clips the pin. Both offsets may be given: the
89
+ * content then holds its place inside that band.
90
+ */
91
+ function Affix(props) {
92
+ const [own, rest] = splitProps(props, ["offsetTop", "offsetBottom"]);
93
+ return (() => {
94
+ var _el$ = _tmpl$$58();
95
+ spread(_el$, mergeProps(rest, {
96
+ get style() {
97
+ return {
98
+ ...rest.style,
99
+ top: own.offsetTop ?? "0px",
100
+ bottom: own.offsetBottom ?? "0px"
101
+ };
102
+ },
103
+ "data-scope": "affix",
104
+ "data-part": "root"
105
+ }), false, false);
106
+ return _el$;
107
+ })();
108
+ }
109
+ injectComponentStyle("affix");
110
+ //#endregion
71
111
  //#region src/components/button/index.tsx
72
- var _tmpl$$18 = /*#__PURE__*/ template(`<button>`);
112
+ var _tmpl$$57 = /*#__PURE__*/ template(`<button>`);
73
113
  function Button(props) {
74
- const [own, rest] = splitProps$1(props, [
114
+ const [own, rest] = splitProps(props, [
75
115
  "variant",
76
116
  "tone",
77
117
  "size",
@@ -80,7 +120,7 @@ function Button(props) {
80
120
  "disabled"
81
121
  ]);
82
122
  return (() => {
83
- var _el$ = _tmpl$$18();
123
+ var _el$ = _tmpl$$57();
84
124
  spread(_el$, mergeProps(rest, {
85
125
  get type() {
86
126
  return own.type ?? "button";
@@ -109,193 +149,12 @@ function Button(props) {
109
149
  }
110
150
  injectComponentStyle("button");
111
151
  //#endregion
112
- //#region src/components/collapsible/index.ts
113
- /** Ark's Collapsible, dressed in the paper-and-ink system: one control on
114
- * the paper, its panel dissolving open to the machine's measured height.
115
- * The API is Ark's own — Root, Trigger, Content, Indicator. */
116
- const Collapsible = Collapsible$1;
117
- injectComponentStyle("collapsible");
118
- //#endregion
119
- //#region src/components/field/index.ts
120
- /** Ark's Field, dressed in the paper-and-ink system: a tracked label, a
121
- * border-and-halo control, and quiet help text. The API is Ark's own —
122
- * Root, Label, Input, Textarea, Select, HelperText, ErrorText,
123
- * RequiredIndicator. */
124
- const Field = Field$1;
125
- injectComponentStyle("field");
126
- //#endregion
127
- //#region src/components/ai/index.tsx
128
- var _tmpl$$17 = /*#__PURE__*/ template(`<div>`);
129
- var _tmpl$2$6 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"fill=none aria-hidden=true><path d="M6 4l4 4-4 4"stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round>`);
130
- var _tmpl$3$5 = /*#__PURE__*/ template(`<article>`);
131
- var _tmpl$4$2 = /*#__PURE__*/ template(`<span>`);
132
- var _tmpl$5$1 = /*#__PURE__*/ template(`<div data-scope=ai data-part=reasoning-content>`);
133
- var _tmpl$6$1 = /*#__PURE__*/ template(`<div data-scope=ai data-part=tool-body>`);
134
- var _tmpl$7$1 = /*#__PURE__*/ template(`<span data-scope=ai data-part=tool-status>`);
135
- var _tmpl$8$1 = /*#__PURE__*/ template(`<span data-scope=ai data-part=tool-label>Input`);
136
- var _tmpl$9$1 = /*#__PURE__*/ template(`<pre>`);
137
- var _tmpl$0$1 = /*#__PURE__*/ template(`<span data-scope=ai data-part=tool-label>Output`);
138
- var _tmpl$1$1 = /*#__PURE__*/ template(`<li data-scope=ai data-part=source><a>`);
139
- var _tmpl$10$1 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"width=14 height=14 aria-hidden=true fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=square><path d="M8 13V3M3.5 7.5 8 3l4.5 4.5">`);
140
- var _tmpl$11$1 = /*#__PURE__*/ template(`<form><div data-scope=ai data-part=prompt-footer>`);
141
- /** A conversation column: Root is the log, Message carries a role, and
142
- * the speaking parts — Response, Reasoning, Tool, Sources — part the
143
- * stream. The interactive folds are the shared Collapsible wearing a
144
- * `data-ai` marker, so the machine work is never ours. Parts stay
145
- * agnostic of any client; consumers map their message format (e.g. the
146
- * `UIMessage` parts re-exported below) onto these primitives. */
147
- function part$9(name, tag, extra = {}) {
148
- function Component(props) {
149
- return (() => {
150
- var _el$ = _tmpl$$17();
151
- spread(_el$, mergeProps(extra, props, {
152
- "data-scope": "ai",
153
- get ["data-part"]() {
154
- return name.toLowerCase();
155
- }
156
- }), false, false);
157
- return _el$;
158
- })();
159
- }
160
- return Component;
161
- }
162
- const Conversation = part$9("Conversation", "div", {
163
- role: "log",
164
- "aria-label": "Conversation"
165
- });
166
- const Content$2 = part$9("Content", "div");
167
- const Sources = part$9("Sources", "ol");
168
- const Actions$3 = part$9("Actions", "div");
169
- const Loader = part$9("Loader", "span", {
170
- role: "status",
171
- "aria-label": "Loading"
172
- });
173
- /** The folding chevron the shared indicator turns. */
174
- const chevron$1 = _tmpl$2$6();
175
- /** Whose stroke this is — the user's words sit in a recessed bubble,
176
- * the assistant speaks flat on the paper. */
177
- function Message(props) {
178
- const [own, rest] = splitProps$1(props, ["role"]);
179
- return (() => {
180
- var _el$3 = _tmpl$3$5();
181
- spread(_el$3, mergeProps(rest, {
182
- "data-scope": "ai",
183
- "data-part": "message",
184
- get ["data-role"]() {
185
- return own.role ?? "assistant";
186
- }
187
- }), false, false);
188
- return _el$3;
189
- })();
190
- }
191
- /** Markdown set on the paper. Rendering goes through
192
- * `@tanstack/markdown`, whose defaults leave raw HTML and executable
193
- * links inert — streaming-safe by construction. */
194
- function Response(props) {
195
- const [own, rest] = splitProps$1(props, ["content"]);
196
- const html = createMemo(() => renderHtml(own.content));
197
- return (() => {
198
- var _el$4 = _tmpl$$17();
199
- spread(_el$4, mergeProps(rest, {
200
- "data-scope": "ai",
201
- "data-part": "response",
202
- get innerHTML() {
203
- return html();
204
- }
205
- }), false, false);
206
- return _el$4;
207
- })();
208
- }
209
- /** The model's thought, folded by the shared collapsible in its quiet
210
- * register: bare ink for a trigger, the thought on one hairline. */
211
- function Reasoning(props) {
212
- const [own, rest] = splitProps$1(props, ["label", "children"]);
213
- return createComponent(Collapsible.Root, mergeProps(rest, {
214
- "data-ai": "reasoning",
215
- get children() {
216
- return [createComponent(Collapsible.Trigger, { get children() {
217
- return [(() => {
218
- var _el$5 = _tmpl$4$2();
219
- insert(_el$5, () => own.label ?? "Thinking");
220
- return _el$5;
221
- })(), createComponent(Collapsible.Indicator, { children: chevron$1 })];
222
- } }), createComponent(Collapsible.Content, { get children() {
223
- var _el$6 = _tmpl$5$1();
224
- insert(_el$6, () => own.children);
225
- return _el$6;
226
- } })];
227
- }
228
- }));
229
- }
230
- /** A tool call: the shared collapsible as the vessel — the name it was
231
- * reached by and the state it reached in on the trigger, its input and
232
- * output folded inside. */
233
- function Tool(props) {
234
- const [own, rest] = splitProps$1(props, [
235
- "name",
236
- "label",
237
- "status",
238
- "input",
239
- "output"
240
- ]);
241
- return createComponent(Collapsible.Root, mergeProps(rest, { "data-ai": "tool" }, () => own.status ? { "data-status": own.status } : {}, { get children() {
242
- return [createComponent(Collapsible.Trigger, { get children() {
243
- return [
244
- (() => {
245
- var _el$7 = _tmpl$4$2();
246
- insert(_el$7, () => own.label ?? own.name);
247
- return _el$7;
248
- })(),
249
- memo(() => memo(() => !!own.status)() ? (() => {
250
- var _el$9 = _tmpl$7$1();
251
- insert(_el$9, () => own.status.charAt(0).toUpperCase() + own.status.slice(1));
252
- return _el$9;
253
- })() : null),
254
- createComponent(Collapsible.Indicator, { children: chevron$1 })
255
- ];
256
- } }), createComponent(Collapsible.Content, { get children() {
257
- var _el$8 = _tmpl$6$1();
258
- insert(_el$8, (() => {
259
- var _c$ = memo(() => own.input !== void 0);
260
- return () => _c$() ? [_tmpl$8$1(), (() => {
261
- var _el$1 = _tmpl$9$1();
262
- insert(_el$1, () => own.input);
263
- return _el$1;
264
- })()] : null;
265
- })(), null);
266
- insert(_el$8, (() => {
267
- var _c$2 = memo(() => own.output !== void 0);
268
- return () => _c$2() ? [_tmpl$0$1(), (() => {
269
- var _el$11 = _tmpl$9$1();
270
- insert(_el$11, () => own.output);
271
- return _el$11;
272
- })()] : null;
273
- })(), null);
274
- return _el$8;
275
- } })];
276
- } }));
277
- }
278
- /** One place the ink came from; href and the rest ride the anchor. */
279
- function Source(props) {
280
- const [own, rest] = splitProps$1(props, ["href", "children"]);
281
- return (() => {
282
- var _el$12 = _tmpl$1$1(), _el$13 = _el$12.firstChild;
283
- spread(_el$13, mergeProps(rest, {
284
- get href() {
285
- return own.href;
286
- },
287
- "target": "_blank",
288
- "rel": "noreferrer"
289
- }), false, true);
290
- insert(_el$13, () => own.children ?? own.href);
291
- return _el$12;
292
- })();
293
- }
152
+ //#region src/components/ai-action/index.tsx
294
153
  /** A quiet icon button — copy, retry, thumbs. The label names it to
295
154
  * assistive tech and as the hover title. The control itself is the
296
155
  * shared Button in its ghost register. */
297
156
  function Action(props) {
298
- const [own, rest] = splitProps$1(props, ["label", "children"]);
157
+ const [own, rest] = splitProps(props, ["label", "children"]);
299
158
  return createComponent(Button, mergeProps({
300
159
  variant: "ghost",
301
160
  size: "sm",
@@ -310,41 +169,117 @@ function Action(props) {
310
169
  return own.children;
311
170
  } }));
312
171
  }
313
- /** A seal-cut button proposing the next stroke; selection hands back
314
- * the prompt. The shared Button in its outline register. */
315
- function Suggestion(props) {
316
- const [own, rest] = splitProps$1(props, ["prompt", "onSelect"]);
317
- return createComponent(Button, mergeProps({
318
- variant: "outline",
319
- size: "sm"
320
- }, rest, {
321
- onClick: () => own.onSelect?.(own.prompt),
322
- get children() {
323
- return own.prompt;
324
- }
325
- }));
172
+ injectComponentStyle("ai");
173
+ //#endregion
174
+ //#region src/components/ai-message/index.tsx
175
+ var _tmpl$$56 = /*#__PURE__*/ template(`<article>`);
176
+ /** Whose stroke this is — the user's words sit in a recessed bubble,
177
+ * the assistant speaks flat on the paper. */
178
+ function Message(props) {
179
+ const [own, rest] = splitProps(props, ["role"]);
180
+ return (() => {
181
+ var _el$ = _tmpl$$56();
182
+ spread(_el$, mergeProps(rest, {
183
+ "data-scope": "ai",
184
+ "data-part": "message",
185
+ get ["data-role"]() {
186
+ return own.role ?? "assistant";
187
+ }
188
+ }), false, false);
189
+ return _el$;
190
+ })();
191
+ }
192
+ injectComponentStyle("ai");
193
+ //#endregion
194
+ //#region src/components/field/index.ts
195
+ /** Ark's Field, dressed in the paper-and-ink system: a tracked label, a
196
+ * border-and-halo control, and quiet help text. The API is Ark's own —
197
+ * Root, Label, Input, Textarea, Select, HelperText, ErrorText,
198
+ * RequiredIndicator. */
199
+ const Field = Field$1;
200
+ injectComponentStyle("field");
201
+ //#endregion
202
+ //#region src/components/ai-prompt-input/index.tsx
203
+ var _tmpl$$55 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"width=14 height=14 aria-hidden=true fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=square><path d="M8 13V3M3.5 7.5 8 3l4.5 4.5">`);
204
+ var _tmpl$2$28 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"width=14 height=14 aria-hidden=true><rect x=4.5 y=4.5 width=7 height=7 fill=currentColor>`);
205
+ var _tmpl$3$18 = /*#__PURE__*/ template(`<div data-scope=ai>`);
206
+ var _tmpl$4$13 = /*#__PURE__*/ template(`<div data-scope=ai data-part=prompt-footer><div data-scope=ai data-part=prompt-end>`);
207
+ var _tmpl$5$10 = /*#__PURE__*/ template(`<form><div data-scope=ai data-part=prompt-main>`);
208
+ function arrowUpGlyph() {
209
+ return _tmpl$$55();
210
+ }
211
+ function stopGlyph() {
212
+ return _tmpl$2$28();
326
213
  }
327
214
  /** The prompt vessel: the shared field textarea — self-growing on the
328
- * machine's autoresize — over a footer row carrying the submit seal.
329
- * Controlled — bind `value` and take the text on `onSubmit`. Enter
330
- * sends; Shift+Enter breaks the line. */
215
+ * machine's autoresize — with the submit seal riding its last line.
216
+ * Around the body, the slot props answer the composer's anatomy:
217
+ * `header` for attachments riding above, `leading` for the tools at
218
+ * the text's left, `trailing` for the seal itself, `footer` for the
219
+ * tools beneath, and `footerEnd` for the controls that close the
220
+ * footer row — the seal falls there by default, so a model picker
221
+ * dropped in rides the send's shoulder. An empty slot renders no part,
222
+ * so the bare vessel stays one quiet line. Controlled — bind `value`
223
+ * and take the text on `onSubmit`. Enter sends; Shift+Enter breaks the
224
+ * line. While `busy` the seal becomes a stop seal and Enter holds its
225
+ * breath. */
331
226
  function PromptInput(props) {
332
- const [own, rest] = splitProps$1(props, [
227
+ const [own, rest] = splitProps(props, [
333
228
  "value",
334
229
  "onValueChange",
335
230
  "onSubmit",
231
+ "onStop",
336
232
  "placeholder",
337
- "disabled"
233
+ "disabled",
234
+ "busy",
235
+ "header",
236
+ "leading",
237
+ "trailing",
238
+ "footer",
239
+ "footerEnd"
338
240
  ]);
339
241
  const send = () => {
340
- const text = own.value.trim();
341
- if (!text || own.disabled) return;
342
- own.onSubmit?.(text);
242
+ const value = (own.value ?? "").trim();
243
+ if (!value || own.disabled || own.busy) return;
244
+ own.onSubmit?.(value);
343
245
  own.onValueChange?.("");
344
246
  };
247
+ const row = (part, content) => content != null ? (() => {
248
+ var _el$3 = _tmpl$3$18();
249
+ setAttribute(_el$3, "data-part", part);
250
+ insert(_el$3, content);
251
+ return _el$3;
252
+ })() : null;
253
+ const seal = () => own.busy ? createComponent(Button, {
254
+ variant: "solid",
255
+ size: "sm",
256
+ square: true,
257
+ type: "button",
258
+ "aria-label": "Stop",
259
+ get disabled() {
260
+ return own.disabled;
261
+ },
262
+ onClick: () => own.onStop?.(),
263
+ get children() {
264
+ return stopGlyph();
265
+ }
266
+ }) : createComponent(Button, {
267
+ variant: "solid",
268
+ size: "sm",
269
+ square: true,
270
+ type: "submit",
271
+ "aria-label": "Send",
272
+ get disabled() {
273
+ return own.disabled || !(own.value ?? "").trim();
274
+ },
275
+ get children() {
276
+ return arrowUpGlyph();
277
+ }
278
+ });
279
+ const trailing = () => own.footer != null ? own.trailing : own.trailing ?? seal();
345
280
  return (() => {
346
- var _el$14 = _tmpl$11$1(), _el$15 = _el$14.firstChild;
347
- spread(_el$14, mergeProps(rest, {
281
+ var _el$4 = _tmpl$5$10(), _el$5 = _el$4.firstChild;
282
+ spread(_el$4, mergeProps(rest, {
348
283
  "data-scope": "ai",
349
284
  "data-part": "prompt",
350
285
  "onSubmit": (event) => {
@@ -352,12 +287,14 @@ function PromptInput(props) {
352
287
  send();
353
288
  }
354
289
  }), false, true);
355
- insert(_el$14, createComponent(Field.Root, { get children() {
290
+ insert(_el$4, () => row("prompt-header", own.header), _el$5);
291
+ insert(_el$5, () => row("prompt-leading", own.leading), null);
292
+ insert(_el$5, createComponent(Field.Root, { get children() {
356
293
  return createComponent(Field.Textarea, {
357
294
  autoresize: true,
358
295
  rows: 1,
359
296
  get value() {
360
- return own.value;
297
+ return own.value ?? "";
361
298
  },
362
299
  get placeholder() {
363
300
  return own.placeholder ?? "Send a message";
@@ -365,7 +302,7 @@ function PromptInput(props) {
365
302
  get disabled() {
366
303
  return own.disabled;
367
304
  },
368
- onValueChange: (details) => own.onValueChange?.(details.value),
305
+ onInput: (event) => own.onValueChange?.(event.currentTarget.value),
369
306
  onKeyDown: (event) => {
370
307
  if (event.key === "Enter" && !event.shiftKey) {
371
308
  event.preventDefault();
@@ -373,92 +310,414 @@ function PromptInput(props) {
373
310
  }
374
311
  }
375
312
  });
376
- } }), _el$15);
377
- insert(_el$15, createComponent(Button, {
378
- variant: "solid",
379
- size: "sm",
380
- square: true,
381
- type: "submit",
382
- "aria-label": "Send",
383
- get disabled() {
384
- return own.disabled || !own.value.trim();
313
+ } }), null);
314
+ insert(_el$5, () => row("prompt-trailing", trailing()), null);
315
+ insert(_el$4, createComponent(Show, {
316
+ get when() {
317
+ return own.footer != null;
385
318
  },
386
319
  get children() {
387
- return _tmpl$10$1();
320
+ var _el$6 = _tmpl$4$13(), _el$7 = _el$6.firstChild;
321
+ insert(_el$6, () => own.footer, _el$7);
322
+ insert(_el$7, () => own.footerEnd, null);
323
+ insert(_el$7, seal, null);
324
+ return _el$6;
388
325
  }
389
- }));
390
- return _el$14;
326
+ }), null);
327
+ return _el$4;
391
328
  })();
392
329
  }
393
- const Ai = Object.assign(Conversation, {
394
- Conversation,
395
- Message,
396
- Content: Content$2,
397
- Response,
398
- Reasoning,
399
- Tool,
400
- Sources,
401
- Source,
402
- Actions: Actions$3,
403
- Action,
404
- Suggestion,
405
- PromptInput,
406
- Loader
407
- });
408
330
  injectComponentStyle("ai");
409
331
  //#endregion
410
- //#region src/components/alert/index.tsx
411
- var _tmpl$$16 = /*#__PURE__*/ template(`<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path>`);
412
- var _tmpl$2$5 = /*#__PURE__*/ template(`<div>`);
413
- var _tmpl$3$4 = /*#__PURE__*/ template(`<span data-scope=alert data-part=icon>`);
414
- var _tmpl$4$1 = /*#__PURE__*/ template(`<p>`);
415
- const StatusContext = createContext(() => "ink");
416
- function glyph(status) {
417
- const paths = {
418
- info: "M12 8v5m0 3v.01M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Z",
419
- success: "m4 12.5 5 5L20 6.5",
420
- warning: "M12 4 2.5 20h19L12 4Zm0 6v4m0 3v.01",
421
- danger: "M6 6l12 12M18 6 6 18",
422
- ink: "M12 8v5m0 3v.01M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Z"
423
- };
424
- return (() => {
425
- var _el$ = _tmpl$$16(), _el$2 = _el$.firstChild;
426
- effect(() => setAttribute(_el$2, "d", paths[status]));
427
- return _el$;
428
- })();
332
+ //#region src/components/ai/chevron.tsx
333
+ var _tmpl$$54 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"fill=none aria-hidden=true><path d="M6 4l4 4-4 4"stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round>`);
334
+ /** The folding chevron the shared indicator turns. */
335
+ function chevron$2() {
336
+ return _tmpl$$54();
429
337
  }
430
- function AlertRoot(props) {
431
- const [own, rest] = splitProps$1(props, ["status"]);
432
- const status = () => own.status ?? "ink";
433
- return createComponent(StatusContext.Provider, {
434
- value: status,
338
+ //#endregion
339
+ //#region src/components/collapsible/index.ts
340
+ /** Ark's Collapsible, dressed in the paper-and-ink system: one control on
341
+ * the paper, its panel dissolving open to the machine's measured height.
342
+ * The API is Ark's own — Root, Trigger, Content, Indicator. */
343
+ const Collapsible = Collapsible$1;
344
+ injectComponentStyle("collapsible");
345
+ //#endregion
346
+ //#region src/components/ai-reasoning/index.tsx
347
+ var _tmpl$$53 = /*#__PURE__*/ template(`<span>`);
348
+ var _tmpl$2$27 = /*#__PURE__*/ template(`<div data-scope=ai data-part=reasoning-content>`);
349
+ /** The model's thought, folded by the shared collapsible in its quiet
350
+ * register: bare ink for a trigger, the thought on one hairline. */
351
+ function Reasoning(props) {
352
+ const [own, rest] = splitProps(props, ["label", "children"]);
353
+ return createComponent(Collapsible.Root, mergeProps(rest, {
354
+ "data-ai": "reasoning",
435
355
  get children() {
436
- var _el$3 = _tmpl$2$5();
437
- spread(_el$3, mergeProps(rest, {
438
- get role() {
439
- return status() === "ink" || status() === "info" ? "status" : "alert";
440
- },
441
- "data-scope": "alert",
442
- "data-part": "root",
443
- get ["data-status"]() {
444
- return status();
356
+ return [createComponent(Collapsible.Trigger, { get children() {
357
+ return [(() => {
358
+ var _el$ = _tmpl$$53();
359
+ insert(_el$, () => own.label ?? "Thinking");
360
+ return _el$;
361
+ })(), createComponent(Collapsible.Indicator, { get children() {
362
+ return chevron$2();
363
+ } })];
364
+ } }), createComponent(Collapsible.Content, { get children() {
365
+ var _el$2 = _tmpl$2$27();
366
+ insert(_el$2, () => own.children);
367
+ return _el$2;
368
+ } })];
369
+ }
370
+ }));
371
+ }
372
+ injectComponentStyle("ai");
373
+ //#endregion
374
+ //#region src/components/ai-response/index.tsx
375
+ var _tmpl$$52 = /*#__PURE__*/ template(`<div>`);
376
+ /** Markdown set on the paper. Rendering goes through
377
+ * `@tanstack/markdown`, whose defaults leave raw HTML and executable
378
+ * links inert — streaming-safe by construction. */
379
+ function Response(props) {
380
+ const [own, rest] = splitProps(props, ["content", "highlighter"]);
381
+ const html = createMemo(() => renderHtml(own.content, own.highlighter ? { highlighter: own.highlighter } : void 0));
382
+ return (() => {
383
+ var _el$ = _tmpl$$52();
384
+ spread(_el$, mergeProps(rest, {
385
+ "data-scope": "ai",
386
+ "data-part": "response",
387
+ get innerHTML() {
388
+ return html();
389
+ }
390
+ }), false, false);
391
+ return _el$;
392
+ })();
393
+ }
394
+ injectComponentStyle("ai");
395
+ //#endregion
396
+ //#region src/components/ai-source/index.tsx
397
+ var _tmpl$$51 = /*#__PURE__*/ template(`<li data-scope=ai data-part=source><a>`);
398
+ var _tmpl$2$26 = /*#__PURE__*/ template(`<ol>`);
399
+ /** One place the ink came from; href and the rest ride the anchor. */
400
+ function Source(props) {
401
+ const [own, rest] = splitProps(props, ["href", "children"]);
402
+ return (() => {
403
+ var _el$ = _tmpl$$51(), _el$2 = _el$.firstChild;
404
+ spread(_el$2, mergeProps(rest, {
405
+ get href() {
406
+ return own.href;
407
+ },
408
+ "target": "_blank",
409
+ "rel": "noreferrer"
410
+ }), false, true);
411
+ insert(_el$2, () => own.children ?? own.href);
412
+ return _el$;
413
+ })();
414
+ }
415
+ /** The reading list under a response: where this ink came from. */
416
+ function Sources(props) {
417
+ return (() => {
418
+ var _el$3 = _tmpl$2$26();
419
+ spread(_el$3, mergeProps(props, {
420
+ "data-scope": "ai",
421
+ "data-part": "sources"
422
+ }), false, false);
423
+ return _el$3;
424
+ })();
425
+ }
426
+ injectComponentStyle("ai");
427
+ //#endregion
428
+ //#region src/components/ai-suggestion/index.tsx
429
+ /** A seal-cut button proposing the next stroke; selection hands back
430
+ * the prompt. The shared Button in its outline register. */
431
+ function Suggestion(props) {
432
+ const [own, rest] = splitProps(props, ["prompt", "onSelect"]);
433
+ return createComponent(Button, mergeProps({
434
+ variant: "outline",
435
+ size: "sm"
436
+ }, rest, {
437
+ onClick: () => own.onSelect?.(own.prompt),
438
+ get children() {
439
+ return own.prompt;
440
+ }
441
+ }));
442
+ }
443
+ injectComponentStyle("ai");
444
+ //#endregion
445
+ //#region src/components/ai-tool/index.tsx
446
+ var _tmpl$$50 = /*#__PURE__*/ template(`<span>`);
447
+ var _tmpl$2$25 = /*#__PURE__*/ template(`<span data-scope=ai data-part=tool-status>`);
448
+ var _tmpl$3$17 = /*#__PURE__*/ template(`<span data-scope=ai data-part=tool-label>Input`);
449
+ var _tmpl$4$12 = /*#__PURE__*/ template(`<pre>`);
450
+ var _tmpl$5$9 = /*#__PURE__*/ template(`<span data-scope=ai data-part=tool-label>Output`);
451
+ var _tmpl$6$6 = /*#__PURE__*/ template(`<div data-scope=ai data-part=tool-body>`);
452
+ /** A tool call: the shared collapsible as the vessel — the name it was
453
+ * reached by and the state it reached in on the trigger, its input and
454
+ * output folded inside. */
455
+ function Tool(props) {
456
+ const [own, rest] = splitProps(props, [
457
+ "name",
458
+ "label",
459
+ "status",
460
+ "input",
461
+ "output"
462
+ ]);
463
+ return createComponent(Collapsible.Root, mergeProps(rest, { "data-ai": "tool" }, () => own.status ? { "data-status": own.status } : {}, { get children() {
464
+ return [createComponent(Collapsible.Trigger, { get children() {
465
+ return [
466
+ (() => {
467
+ var _el$ = _tmpl$$50();
468
+ insert(_el$, () => own.label ?? own.name);
469
+ return _el$;
470
+ })(),
471
+ createComponent(Show, {
472
+ get when() {
473
+ return own.status;
474
+ },
475
+ get children() {
476
+ var _el$2 = _tmpl$2$25();
477
+ insert(_el$2, () => own.status.charAt(0).toUpperCase() + own.status.slice(1));
478
+ return _el$2;
479
+ }
480
+ }),
481
+ createComponent(Collapsible.Indicator, { get children() {
482
+ return chevron$2();
483
+ } })
484
+ ];
485
+ } }), createComponent(Collapsible.Content, { get children() {
486
+ var _el$3 = _tmpl$6$6();
487
+ insert(_el$3, createComponent(Show, {
488
+ get when() {
489
+ return own.input !== void 0;
490
+ },
491
+ get children() {
492
+ return [_tmpl$3$17(), (() => {
493
+ var _el$5 = _tmpl$4$12();
494
+ insert(_el$5, () => own.input);
495
+ return _el$5;
496
+ })()];
497
+ }
498
+ }), null);
499
+ insert(_el$3, createComponent(Show, {
500
+ get when() {
501
+ return own.output !== void 0;
502
+ },
503
+ get children() {
504
+ return [_tmpl$5$9(), (() => {
505
+ var _el$7 = _tmpl$4$12();
506
+ insert(_el$7, () => own.output);
507
+ return _el$7;
508
+ })()];
509
+ }
510
+ }), null);
511
+ return _el$3;
512
+ } })];
513
+ } }));
514
+ }
515
+ injectComponentStyle("ai");
516
+ //#endregion
517
+ //#region src/components/ai/index.tsx
518
+ var _tmpl$$49 = /*#__PURE__*/ template(`<div>`);
519
+ /** A conversation column: Root is the log, Message carries a role, and
520
+ * the speaking parts — Response, Reasoning, Tool, Sources — part the
521
+ * stream. The interactive folds are the shared Collapsible wearing a
522
+ * `data-ai` marker, so the machine work is never ours. Parts stay
523
+ * agnostic of any client; consumers map their message format (e.g. the
524
+ * `UIMessage` parts re-exported here) onto these primitives. */
525
+ function part$11(name, extra = {}) {
526
+ function Component(props) {
527
+ return (() => {
528
+ var _el$ = _tmpl$$49();
529
+ spread(_el$, mergeProps(extra, props, {
530
+ "data-scope": "ai",
531
+ get ["data-part"]() {
532
+ return name.toLowerCase();
533
+ }
534
+ }), false, false);
535
+ return _el$;
536
+ })();
537
+ }
538
+ return Component;
539
+ }
540
+ /** The log itself: the column every stroke lands in, a landmark to
541
+ * screen readers. */
542
+ const AiConversation = part$11("Conversation", {
543
+ role: "log",
544
+ "aria-label": "Conversation"
545
+ });
546
+ /** The bubble's inner measure — content that belongs to neither side
547
+ * specifically. */
548
+ const AiContent = part$11("Content");
549
+ /** The quiet row under a message — copy, retry, feedback. */
550
+ const AiActions = part$11("Actions");
551
+ /** The while-it-works whisper for the in-flight turns. */
552
+ const AiLoader = part$11("Loader", {
553
+ role: "status",
554
+ "aria-label": "Loading"
555
+ });
556
+ /** The whole family under one handle — `Ai.Conversation`,
557
+ * `Ai.MessageContent`, and the rest. */
558
+ const Ai = Object.assign(AiConversation, {
559
+ Conversation: AiConversation,
560
+ MessageContent: AiContent,
561
+ Actions: AiActions,
562
+ Loader: AiLoader,
563
+ Message,
564
+ Response,
565
+ Reasoning,
566
+ Tool,
567
+ Sources,
568
+ Source,
569
+ Action,
570
+ Suggestion,
571
+ PromptInput
572
+ });
573
+ injectComponentStyle("ai");
574
+ //#endregion
575
+ //#region src/components/ai-attachments/index.tsx
576
+ var _tmpl$$48 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"aria-hidden=true fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=square><rect x=2.5 y=3.5 width=11 height=9></rect><path d="M2.5 10.5 6 7l3 3 2-1.5 2.5 2"></path><circle cx=6 cy=6 r=0.75 fill=currentColor stroke=none>`);
577
+ var _tmpl$2$24 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"aria-hidden=true fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=square><path d="M4 2.5h5l3 3V13.5H4z"></path><path d="M9 2.5v3h3">`);
578
+ var _tmpl$3$16 = /*#__PURE__*/ template(`<svg viewBox="0 0 16 16"width=12 height=12 aria-hidden=true fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=square><path d="M4 4l8 8M12 4l-8 8">`);
579
+ var _tmpl$4$11 = /*#__PURE__*/ template(`<span><span></span><button type=button data-remove>`);
580
+ var _tmpl$5$8 = /*#__PURE__*/ template(`<span>`);
581
+ function imageGlyph() {
582
+ return _tmpl$$48();
583
+ }
584
+ function fileGlyph() {
585
+ return _tmpl$2$24();
586
+ }
587
+ function removeGlyph() {
588
+ return _tmpl$3$16();
589
+ }
590
+ const IMAGE_EXTS = [
591
+ "png",
592
+ "jpg",
593
+ "jpeg",
594
+ "gif",
595
+ "webp",
596
+ "svg",
597
+ "avif",
598
+ "bmp",
599
+ "ico"
600
+ ];
601
+ const isImage = (name) => IMAGE_EXTS.includes(name.split(".").pop()?.toLowerCase() ?? "");
602
+ const humanSize = (bytes) => {
603
+ if (bytes < 1024) return `${bytes} B`;
604
+ const units = [
605
+ "KB",
606
+ "MB",
607
+ "GB"
608
+ ];
609
+ let value = bytes;
610
+ let unit = -1;
611
+ do {
612
+ value /= 1024;
613
+ unit += 1;
614
+ } while (value >= 1024 && unit < units.length - 1);
615
+ return `${value.toFixed(1)} ${units[unit]}`;
616
+ };
617
+ /** One file riding the prompt: its glyph by extension, its name and
618
+ * human size, and a quiet way to take it back off. Uploading reads as
619
+ * a dashed ghost, error as danger ink. */
620
+ function Attachment(props) {
621
+ const [own, rest] = splitProps(props, [
622
+ "name",
623
+ "size",
624
+ "status",
625
+ "onRemove"
626
+ ]);
627
+ return (() => {
628
+ var _el$4 = _tmpl$4$11(), _el$5 = _el$4.firstChild, _el$6 = _el$5.nextSibling;
629
+ spread(_el$4, mergeProps(rest, {
630
+ "data-scope": "ai",
631
+ "data-part": "attachment",
632
+ get ["data-status"]() {
633
+ return own.status ?? "ready";
634
+ }
635
+ }), false, true);
636
+ insert(_el$4, (() => {
637
+ var _c$ = memo(() => !!isImage(own.name));
638
+ return () => _c$() ? imageGlyph() : fileGlyph();
639
+ })(), _el$5);
640
+ insert(_el$5, () => own.name);
641
+ insert(_el$4, (() => {
642
+ var _c$2 = memo(() => own.size !== void 0);
643
+ return () => _c$2() ? (() => {
644
+ var _el$7 = _tmpl$5$8();
645
+ insert(_el$7, () => humanSize(own.size));
646
+ return _el$7;
647
+ })() : null;
648
+ })(), _el$6);
649
+ _el$6.$$click = () => own.onRemove?.();
650
+ insert(_el$6, removeGlyph);
651
+ effect(() => setAttribute(_el$6, "aria-label", `Remove ${own.name}`));
652
+ return _el$4;
653
+ })();
654
+ }
655
+ /** The row the files ride in — a wrapping line of chips. */
656
+ function Attachments(props) {
657
+ return (() => {
658
+ var _el$8 = _tmpl$5$8();
659
+ spread(_el$8, mergeProps(props, {
660
+ "data-scope": "ai",
661
+ "data-part": "attachments"
662
+ }), false, false);
663
+ return _el$8;
664
+ })();
665
+ }
666
+ injectComponentStyle("ai");
667
+ delegateEvents(["click"]);
668
+ //#endregion
669
+ //#region src/components/alert/index.tsx
670
+ var _tmpl$$47 = /*#__PURE__*/ template(`<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path>`);
671
+ var _tmpl$2$23 = /*#__PURE__*/ template(`<div>`);
672
+ var _tmpl$3$15 = /*#__PURE__*/ template(`<span data-scope=alert data-part=icon>`);
673
+ var _tmpl$4$10 = /*#__PURE__*/ template(`<p>`);
674
+ const StatusContext = createContext(() => "ink");
675
+ function glyph(status) {
676
+ const paths = {
677
+ info: "M12 8v5m0 3v.01M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Z",
678
+ success: "m4 12.5 5 5L20 6.5",
679
+ warning: "M12 4 2.5 20h19L12 4Zm0 6v4m0 3v.01",
680
+ danger: "M6 6l12 12M18 6 6 18",
681
+ ink: "M12 8v5m0 3v.01M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Z"
682
+ };
683
+ return (() => {
684
+ var _el$ = _tmpl$$47(), _el$2 = _el$.firstChild;
685
+ effect(() => setAttribute(_el$2, "d", paths[status]));
686
+ return _el$;
687
+ })();
688
+ }
689
+ function AlertRoot(props) {
690
+ const [own, rest] = splitProps(props, ["status"]);
691
+ const status = () => own.status ?? "ink";
692
+ return createComponent(StatusContext.Provider, {
693
+ value: status,
694
+ get children() {
695
+ var _el$3 = _tmpl$2$23();
696
+ spread(_el$3, mergeProps(rest, {
697
+ get role() {
698
+ return status() === "ink" || status() === "info" ? "status" : "alert";
699
+ },
700
+ "data-scope": "alert",
701
+ "data-part": "root",
702
+ get ["data-status"]() {
703
+ return status();
445
704
  }
446
705
  }), false, false);
447
706
  return _el$3;
448
707
  }
449
708
  });
450
709
  }
451
- function Icon$1() {
710
+ function Icon$2() {
452
711
  const status = useContext(StatusContext);
453
712
  return (() => {
454
- var _el$4 = _tmpl$3$4();
713
+ var _el$4 = _tmpl$3$15();
455
714
  insert(_el$4, () => glyph(status()));
456
715
  return _el$4;
457
716
  })();
458
717
  }
459
718
  function Body$2(props) {
460
719
  return (() => {
461
- var _el$5 = _tmpl$2$5();
720
+ var _el$5 = _tmpl$2$23();
462
721
  spread(_el$5, mergeProps(props, {
463
722
  "data-scope": "alert",
464
723
  "data-part": "body"
@@ -468,7 +727,7 @@ function Body$2(props) {
468
727
  }
469
728
  function Title$4(props) {
470
729
  return (() => {
471
- var _el$6 = _tmpl$4$1();
730
+ var _el$6 = _tmpl$4$10();
472
731
  spread(_el$6, mergeProps(props, {
473
732
  "data-scope": "alert",
474
733
  "data-part": "title"
@@ -478,7 +737,7 @@ function Title$4(props) {
478
737
  }
479
738
  function Description$5(props) {
480
739
  return (() => {
481
- var _el$7 = _tmpl$4$1();
740
+ var _el$7 = _tmpl$4$10();
482
741
  spread(_el$7, mergeProps(props, {
483
742
  "data-scope": "alert",
484
743
  "data-part": "description"
@@ -488,7 +747,7 @@ function Description$5(props) {
488
747
  }
489
748
  const Alert = Object.assign(AlertRoot, {
490
749
  Root: AlertRoot,
491
- Icon: Icon$1,
750
+ Icon: Icon$2,
492
751
  Body: Body$2,
493
752
  Title: Title$4,
494
753
  Description: Description$5
@@ -503,6 +762,92 @@ injectComponentStyle("alert");
503
762
  const AngleSlider = AngleSlider$1;
504
763
  injectComponentStyle("angle-slider");
505
764
  //#endregion
765
+ //#region src/components/aspect-ratio/index.tsx
766
+ var _tmpl$$46 = /*#__PURE__*/ template(`<div>`);
767
+ function AspectRatio(props) {
768
+ const [own, rest] = splitProps(props, ["ratio"]);
769
+ return (() => {
770
+ var _el$ = _tmpl$$46();
771
+ spread(_el$, mergeProps(rest, {
772
+ get style() {
773
+ return {
774
+ ...rest.style,
775
+ "--bs-aspect-ratio": own.ratio ?? "1 / 1"
776
+ };
777
+ },
778
+ "data-scope": "aspect-ratio",
779
+ "data-part": "root"
780
+ }), false, false);
781
+ return _el$;
782
+ })();
783
+ }
784
+ injectComponentStyle("aspect-ratio");
785
+ //#endregion
786
+ //#region src/components/autocomplete/index.tsx
787
+ /**
788
+ * Free text with suggestions: the reader types anything, the list
789
+ * narrows to help, and both a pick and a custom value end up in the
790
+ * same `value`. A preset of the combobox machinery — same parts,
791
+ * same styling, one job. `items` seeds the suggestion list once;
792
+ * matching is a case-insensitive substring unless `filter` says
793
+ * otherwise.
794
+ */
795
+ function AutoComplete(props) {
796
+ const [own, rest] = splitProps(props, [
797
+ "value",
798
+ "items",
799
+ "placeholder",
800
+ "filter",
801
+ "onValueChange"
802
+ ]);
803
+ const { collection, filter } = useListCollection$1({
804
+ initialItems: own.items ?? [],
805
+ filter: (item, input) => own.filter ? own.filter(item, input) : item.toLowerCase().includes(input.toLowerCase())
806
+ });
807
+ return createComponent(Combobox$1.Root, mergeProps(rest, {
808
+ get collection() {
809
+ return collection();
810
+ },
811
+ get inputValue() {
812
+ return own.value;
813
+ },
814
+ allowCustomValue: true,
815
+ onValueChange: (details) => {
816
+ const [first] = details.value;
817
+ if (first != null) own.onValueChange?.(first);
818
+ },
819
+ onInputValueChange: (details) => {
820
+ filter(details.inputValue);
821
+ own.onValueChange?.(details.inputValue);
822
+ },
823
+ positioning: { sameWidth: true },
824
+ get children() {
825
+ return [createComponent(Combobox$1.Control, { get children() {
826
+ return createComponent(Combobox$1.Input, { get placeholder() {
827
+ return own.placeholder;
828
+ } });
829
+ } }), createComponent(Portal, { get children() {
830
+ return createComponent(Combobox$1.Positioner, { get children() {
831
+ return createComponent(Combobox$1.Content, { get children() {
832
+ return [createComponent(Combobox$1.Empty, { children: "No matches" }), createComponent(For, {
833
+ get each() {
834
+ return collection().items;
835
+ },
836
+ children: (item) => createComponent(Combobox$1.Item, {
837
+ item,
838
+ get children() {
839
+ return createComponent(Combobox$1.ItemText, { children: item });
840
+ }
841
+ })
842
+ })];
843
+ } });
844
+ } });
845
+ } })];
846
+ }
847
+ }));
848
+ }
849
+ injectComponentStyle("combobox");
850
+ //#endregion
506
851
  //#region src/components/avatar/index.ts
507
852
  /** Ark's Avatar, dressed in the paper-and-ink system: a circular seal on
508
853
  * inset paper that holds initials until the image loads over them. The
@@ -511,10 +856,10 @@ const Avatar = Avatar$1;
511
856
  injectComponentStyle("avatar");
512
857
  //#endregion
513
858
  //#region src/components/avatar-group/index.tsx
514
- var _tmpl$$15 = /*#__PURE__*/ template(`<div>`);
859
+ var _tmpl$$45 = /*#__PURE__*/ template(`<div>`);
515
860
  function AvatarGroup(props) {
516
861
  return (() => {
517
- var _el$ = _tmpl$$15();
862
+ var _el$ = _tmpl$$45();
518
863
  spread(_el$, mergeProps(props, {
519
864
  "data-scope": "avatar-group",
520
865
  "data-part": "root"
@@ -524,12 +869,68 @@ function AvatarGroup(props) {
524
869
  }
525
870
  injectComponentStyle("avatar-group");
526
871
  //#endregion
872
+ //#region src/components/back-top/index.tsx
873
+ var _tmpl$$44 = /*#__PURE__*/ template(`<div data-scope=back-top data-part=root>`);
874
+ var _tmpl$2$22 = /*#__PURE__*/ template(`<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m6 14 6-6 6 6">`);
875
+ /**
876
+ * A way home: after the page has scrolled past `threshold`, a small
877
+ * floating control rises at the page's corner and returns the reader to
878
+ * the top. The scroll itself stays native — `window.scrollTo` defers to
879
+ * the stylesheet's `scroll-behavior: smooth`, which reduced motion turns
880
+ * back into an instant jump. The button stays mounted either way so the
881
+ * entrance is a transition, never a pop.
882
+ *
883
+ * The control itself is the shared `Button` (outline, square) — the
884
+ * paper, hairline and halo are its; this family owns only the floating
885
+ * and the entrance.
886
+ */
887
+ function BackTop(props) {
888
+ const [own, rest] = splitProps(props, ["threshold", "label"]);
889
+ const [visible, setVisible] = createSignal(false);
890
+ const onScroll = () => {
891
+ setVisible(window.scrollY > (own.threshold ?? 400));
892
+ };
893
+ onMount(() => {
894
+ onScroll();
895
+ window.addEventListener("scroll", onScroll, { passive: true });
896
+ });
897
+ onCleanup(() => window.removeEventListener("scroll", onScroll));
898
+ return (() => {
899
+ var _el$ = _tmpl$$44();
900
+ insert(_el$, createComponent(Button, mergeProps(rest, {
901
+ variant: "outline",
902
+ square: true,
903
+ size: "lg",
904
+ get ["aria-label"]() {
905
+ return own.label ?? "Back to top";
906
+ },
907
+ get ["aria-hidden"]() {
908
+ return visible() ? void 0 : "true";
909
+ },
910
+ get tabindex() {
911
+ return visible() ? 0 : -1;
912
+ },
913
+ onClick: () => window.scrollTo({ top: 0 }),
914
+ get children() {
915
+ return rest.children ?? chevronUp();
916
+ }
917
+ })));
918
+ effect(() => setAttribute(_el$, "data-state", visible() ? "shown" : "hidden"));
919
+ return _el$;
920
+ })();
921
+ }
922
+ /** The single glyph a way-home control needs: one stroke pointing up. */
923
+ function chevronUp() {
924
+ return _tmpl$2$22();
925
+ }
926
+ injectComponentStyle("back-top");
927
+ //#endregion
527
928
  //#region src/components/badge/index.tsx
528
- var _tmpl$$14 = /*#__PURE__*/ template(`<span>`);
929
+ var _tmpl$$43 = /*#__PURE__*/ template(`<span>`);
529
930
  function Badge(props) {
530
- const [own, rest] = splitProps$1(props, ["tone", "variant"]);
931
+ const [own, rest] = splitProps(props, ["tone", "variant"]);
531
932
  return (() => {
532
- var _el$ = _tmpl$$14();
933
+ var _el$ = _tmpl$$43();
533
934
  spread(_el$, mergeProps(rest, {
534
935
  "data-scope": "badge",
535
936
  "data-part": "root",
@@ -546,18 +947,17 @@ function Badge(props) {
546
947
  injectComponentStyle("badge");
547
948
  //#endregion
548
949
  //#region src/components/banner/index.tsx
549
- var _tmpl$$13 = /*#__PURE__*/ template(`<div>`);
550
- var _tmpl$2$4 = /*#__PURE__*/ template(`<tag>`);
551
- var _tmpl$3$3 = /*#__PURE__*/ template(`<button><svg viewBox="0 0 16 16"fill=none aria-hidden=true><path d="M4 4l8 8M12 4l-8 8"stroke=currentColor stroke-width=1.5 stroke-linecap=round>`);
950
+ var _tmpl$$42 = /*#__PURE__*/ template(`<div>`);
951
+ var _tmpl$2$21 = /*#__PURE__*/ template(`<button><svg viewBox="0 0 16 16"fill=none aria-hidden=true><path d="M4 4l8 8M12 4l-8 8"stroke=currentColor stroke-width=1.5 stroke-linecap=round>`);
552
952
  /** A page-level notice, spoken across the full measure: a wash of the
553
953
  * status pigment, one heavier hairline on the leading edge, and room
554
954
  * for actions and a quiet close. Ink is the neutral register; the four
555
955
  * semantic pigments are fixed. */
556
- function Root$7(props) {
557
- const [own, rest] = splitProps$1(props, ["status"]);
956
+ function Root$9(props) {
957
+ const [own, rest] = splitProps(props, ["status"]);
558
958
  const status = own.status ?? "ink";
559
959
  return (() => {
560
- var _el$ = _tmpl$$13();
960
+ var _el$ = _tmpl$$42();
561
961
  spread(_el$, mergeProps(rest, {
562
962
  "role": status === "ink" ? void 0 : "status",
563
963
  "data-scope": "banner",
@@ -567,33 +967,29 @@ function Root$7(props) {
567
967
  return _el$;
568
968
  })();
569
969
  }
570
- function part$8(name, tag) {
970
+ function part$10(name, tag) {
571
971
  function Component(props) {
572
- return (() => {
573
- var _el$2 = _tmpl$2$4();
574
- spread(_el$2, mergeProps(props, {
575
- "data-scope": "banner",
576
- get ["data-part"]() {
577
- return name.toLowerCase();
578
- }
579
- }), false, false);
580
- return _el$2;
581
- })();
972
+ return createComponent(tag, mergeProps(props, {
973
+ "data-scope": "banner",
974
+ get ["data-part"]() {
975
+ return name.toLowerCase();
976
+ }
977
+ }));
582
978
  }
583
979
  return Component;
584
980
  }
585
- const Icon = part$8("Icon", "span");
586
- const Body$1 = part$8("Body", "div");
587
- const Title$3 = part$8("Title", "p");
588
- const Description$4 = part$8("Description", "p");
589
- const Actions$2 = part$8("Actions", "div");
981
+ const Icon$1 = part$10("Icon", "span");
982
+ const Body$1 = part$10("Body", "div");
983
+ const Title$3 = part$10("Title", "p");
984
+ const Description$4 = part$10("Description", "p");
985
+ const Actions$3 = part$10("Actions", "div");
590
986
  /** The quiet close: a plain square-cut button; dismissal stays the
591
987
  * consumer's state. */
592
988
  function Close(props) {
593
- const [own, rest] = splitProps$1(props, ["type"]);
989
+ const [own, rest] = splitProps(props, ["type"]);
594
990
  return (() => {
595
- var _el$3 = _tmpl$3$3();
596
- spread(_el$3, mergeProps(rest, {
991
+ var _el$2 = _tmpl$2$21();
992
+ spread(_el$2, mergeProps(rest, {
597
993
  get type() {
598
994
  return own.type ?? "button";
599
995
  },
@@ -603,26 +999,26 @@ function Close(props) {
603
999
  "data-scope": "banner",
604
1000
  "data-part": "close"
605
1001
  }), false, true);
606
- return _el$3;
1002
+ return _el$2;
607
1003
  })();
608
1004
  }
609
- const Banner = Object.assign(Root$7, {
610
- Root: Root$7,
611
- Icon,
1005
+ const Banner = Object.assign(Root$9, {
1006
+ Root: Root$9,
1007
+ Icon: Icon$1,
612
1008
  Body: Body$1,
613
1009
  Title: Title$3,
614
1010
  Description: Description$4,
615
- Actions: Actions$2,
1011
+ Actions: Actions$3,
616
1012
  Close
617
1013
  });
618
1014
  injectComponentStyle("banner");
619
1015
  //#endregion
620
1016
  //#region src/components/breadcrumb/index.tsx
621
- var _tmpl$$12 = /*#__PURE__*/ template(`<span>`);
1017
+ var _tmpl$$41 = /*#__PURE__*/ template(`<span>`);
622
1018
  /** A trail of waymarks: Root wraps the nav, List the ordered trail, and
623
1019
  * each Item carries a Link — or the Current page — parted by a quiet
624
1020
  * Separator. Links take href and the rest through attributes. */
625
- function part$7(name, tag, extra = {}) {
1021
+ function part$9(name, tag, extra = {}) {
626
1022
  return ((props) => {
627
1023
  return createComponent(tag, mergeProps(extra, props, {
628
1024
  "data-scope": "breadcrumb",
@@ -632,13 +1028,13 @@ function part$7(name, tag, extra = {}) {
632
1028
  }));
633
1029
  });
634
1030
  }
635
- const Root$6 = part$7("Root", "nav", { "aria-label": "Breadcrumb" });
636
- const List = part$7("List", "ol");
637
- const Item$1 = part$7("Item", "li");
638
- const Link$1 = part$7("Link", "a");
639
- const Current = part$7("Current", "span", { "aria-current": "page" });
1031
+ const Root$8 = part$9("Root", "nav", { "aria-label": "Breadcrumb" });
1032
+ const List$1 = part$9("List", "ol");
1033
+ const Item$3 = part$9("Item", "li");
1034
+ const Link$1 = part$9("Link", "a");
1035
+ const Current = part$9("Current", "span", { "aria-current": "page" });
640
1036
  const Separator$1 = (props) => (() => {
641
- var _el$ = _tmpl$$12();
1037
+ var _el$ = _tmpl$$41();
642
1038
  spread(_el$, mergeProps(() => mergeProps$1({ children: "/" }, props), {
643
1039
  "aria-hidden": "true",
644
1040
  "data-scope": "breadcrumb",
@@ -646,23 +1042,59 @@ const Separator$1 = (props) => (() => {
646
1042
  }), false, false);
647
1043
  return _el$;
648
1044
  })();
649
- const Breadcrumb = Object.assign(Root$6, {
650
- Root: Root$6,
651
- List,
652
- Item: Item$1,
1045
+ const Breadcrumb = Object.assign(Root$8, {
1046
+ Root: Root$8,
1047
+ List: List$1,
1048
+ Item: Item$3,
653
1049
  Link: Link$1,
654
1050
  Current,
655
1051
  Separator: Separator$1
656
1052
  });
657
1053
  injectComponentStyle("breadcrumb");
658
1054
  //#endregion
1055
+ //#region src/components/button-group/index.tsx
1056
+ var _tmpl$$40 = /*#__PURE__*/ template(`<div>`);
1057
+ /**
1058
+ * Buttons fused into one control: the group owns only the joinery, so
1059
+ * members keep every variant they were given — a solid action can sit
1060
+ * beside an outline one and the seam still reads. Selection belongs to
1061
+ * the toggle group; this is layout alone.
1062
+ */
1063
+ function ButtonGroupRoot(props) {
1064
+ const [own, rest] = splitProps(props, [
1065
+ "orientation",
1066
+ "size",
1067
+ "radius"
1068
+ ]);
1069
+ return (() => {
1070
+ var _el$ = _tmpl$$40();
1071
+ spread(_el$, mergeProps(rest, {
1072
+ "role": "group",
1073
+ "data-scope": "button-group",
1074
+ "data-part": "root",
1075
+ get ["data-orientation"]() {
1076
+ return own.orientation ?? "horizontal";
1077
+ },
1078
+ get ["data-size"]() {
1079
+ return own.size;
1080
+ },
1081
+ get ["data-radius"]() {
1082
+ return own.radius;
1083
+ }
1084
+ }), false, false);
1085
+ return _el$;
1086
+ })();
1087
+ }
1088
+ const ButtonGroup = Object.assign(ButtonGroupRoot, { Root: ButtonGroupRoot });
1089
+ injectComponentStyle("button-group");
1090
+ //#endregion
659
1091
  //#region src/components/calendar/index.tsx
660
- var _tmpl$$11 = /*#__PURE__*/ template(`<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 aria-hidden=true><path d="m9 5 7 7-7 7">`);
661
- var _tmpl$2$3 = /*#__PURE__*/ template(`<div data-scope=calendar data-part=header>`);
662
- var _tmpl$3$2 = /*#__PURE__*/ template(`<div>`);
663
- function chevron(dir) {
1092
+ var _tmpl$$39 = /*#__PURE__*/ template(`<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 aria-hidden=true><path d="m9 5 7 7-7 7">`);
1093
+ var _tmpl$2$20 = /*#__PURE__*/ template(`<div data-scope=calendar data-part=header>`);
1094
+ var _tmpl$3$14 = /*#__PURE__*/ template(`<div>`);
1095
+ function chevron$1(dir) {
664
1096
  return (() => {
665
- var _el$ = _tmpl$$11();
1097
+ var _el$ = _tmpl$$39();
666
1098
  effect((_$p) => style(_el$, dir === "left" ? { transform: "rotate(180deg)" } : void 0, _$p));
667
1099
  return _el$;
668
1100
  })();
@@ -680,35 +1112,36 @@ function Calendar(props) {
680
1112
  "onValueChange"
681
1113
  ]);
682
1114
  const title = (dp) => {
683
- const d = dp.focusedValue;
1115
+ const api = dp();
1116
+ const d = api.focusedValue;
684
1117
  if (!d) return "";
685
- if (dp.view === "day") return dp.format(d, {
1118
+ if (api.view === "day") return api.format(d, {
686
1119
  month: "long",
687
1120
  year: "numeric"
688
1121
  });
689
- if (dp.view === "month") return dp.format(d, { year: "numeric" });
1122
+ if (api.view === "month") return api.format(d, { year: "numeric" });
690
1123
  const decade = Math.floor(d.year / 10) * 10;
691
1124
  return `${decade} - ${decade + 9}`;
692
1125
  };
693
1126
  const header = () => (() => {
694
- var _el$2 = _tmpl$2$3();
1127
+ var _el$2 = _tmpl$2$20();
695
1128
  insert(_el$2, createComponent(DatePicker$1.ViewControl, { get children() {
696
1129
  return [
697
1130
  createComponent(DatePicker$1.PrevTrigger, { get children() {
698
- return chevron("left");
1131
+ return chevron$1("left");
699
1132
  } }),
700
1133
  createComponent(DatePicker$1.Context, { children: (dp) => createComponent(DatePicker$1.ViewTrigger, { get children() {
701
1134
  return title(dp);
702
1135
  } }) }),
703
1136
  createComponent(DatePicker$1.NextTrigger, { get children() {
704
- return chevron("right");
1137
+ return chevron$1("right");
705
1138
  } })
706
1139
  ];
707
1140
  } }));
708
1141
  return _el$2;
709
1142
  })();
710
1143
  return (() => {
711
- var _el$3 = _tmpl$3$2();
1144
+ var _el$3 = _tmpl$3$14();
712
1145
  spread(_el$3, mergeProps(rest, {
713
1146
  "data-scope": "calendar",
714
1147
  "data-part": "root"
@@ -729,9 +1162,9 @@ function Calendar(props) {
729
1162
  return createComponent(DatePicker$1.TableRow, { get children() {
730
1163
  return createComponent(DatePicker$1.Context, { children: (dp) => createComponent(For, {
731
1164
  get each() {
732
- return dp.weekDays;
1165
+ return dp().weekDays;
733
1166
  },
734
- children: (day, id) => createComponent(DatePicker$1.TableHeader, {
1167
+ children: (day) => createComponent(DatePicker$1.TableHeader, {
735
1168
  get ["aria-label"]() {
736
1169
  return day.long;
737
1170
  },
@@ -744,12 +1177,12 @@ function Calendar(props) {
744
1177
  } }), createComponent(DatePicker$1.TableBody, { get children() {
745
1178
  return createComponent(DatePicker$1.Context, { children: (dp) => createComponent(For, {
746
1179
  get each() {
747
- return dp.weeks;
1180
+ return dp().weeks;
748
1181
  },
749
- children: (week, id) => createComponent(DatePicker$1.TableRow, { get children() {
1182
+ children: (week) => createComponent(DatePicker$1.TableRow, { get children() {
750
1183
  return createComponent(For, {
751
1184
  each: week,
752
- children: (day, id2) => createComponent(DatePicker$1.TableCell, {
1185
+ children: (day) => createComponent(DatePicker$1.TableCell, {
753
1186
  value: day,
754
1187
  get children() {
755
1188
  return createComponent(DatePicker$1.TableCellTrigger, { get children() {
@@ -773,12 +1206,12 @@ function Calendar(props) {
773
1206
  return createComponent(DatePicker$1.TableBody, { get children() {
774
1207
  return createComponent(DatePicker$1.Context, { children: (dp) => createComponent(For, {
775
1208
  get each() {
776
- return dp.getMonthsGrid({ columns: 3 });
1209
+ return dp().getMonthsGrid({ columns: 3 });
777
1210
  },
778
- children: (months, id) => createComponent(DatePicker$1.TableRow, { get children() {
1211
+ children: (months) => createComponent(DatePicker$1.TableRow, { get children() {
779
1212
  return createComponent(For, {
780
1213
  each: months,
781
- children: (month, id2) => createComponent(DatePicker$1.TableCell, {
1214
+ children: (month) => createComponent(DatePicker$1.TableCell, {
782
1215
  get value() {
783
1216
  return month.value;
784
1217
  },
@@ -806,12 +1239,12 @@ function Calendar(props) {
806
1239
  return createComponent(DatePicker$1.TableBody, { get children() {
807
1240
  return createComponent(DatePicker$1.Context, { children: (dp) => createComponent(For, {
808
1241
  get each() {
809
- return dp.getYearsGrid({ columns: 3 });
1242
+ return dp().getYearsGrid({ columns: 3 });
810
1243
  },
811
- children: (years, id) => createComponent(DatePicker$1.TableRow, { get children() {
1244
+ children: (years) => createComponent(DatePicker$1.TableRow, { get children() {
812
1245
  return createComponent(For, {
813
1246
  each: years,
814
- children: (year, id2) => createComponent(DatePicker$1.TableCell, {
1247
+ children: (year) => createComponent(DatePicker$1.TableCell, {
815
1248
  get value() {
816
1249
  return year.value;
817
1250
  },
@@ -845,12 +1278,13 @@ function Calendar(props) {
845
1278
  })();
846
1279
  }
847
1280
  injectComponentStyle("calendar");
1281
+ injectComponentStyle("date-picker");
848
1282
  //#endregion
849
1283
  //#region src/components/card/index.tsx
850
1284
  /** A vessel: round, resting at the first elevation, one hairline for its
851
1285
  * edge. Root, Header, Title, Description, Content, Footer — sections
852
1286
  * carry their own whitespace, so any subset composes. */
853
- function part$6(name, tag) {
1287
+ function part$8(name, tag) {
854
1288
  return ((props) => {
855
1289
  return createComponent(tag, mergeProps(props, {
856
1290
  "data-scope": "card",
@@ -860,18 +1294,18 @@ function part$6(name, tag) {
860
1294
  }));
861
1295
  });
862
1296
  }
863
- const Root$5 = part$6("Root", "section");
864
- const Header = part$6("Header", "header");
865
- const Title$2 = part$6("Title", "h3");
866
- const Description$3 = part$6("Description", "p");
867
- const Content$1 = part$6("Content", "div");
868
- const Footer = part$6("Footer", "footer");
869
- const Card = Object.assign(Root$5, {
870
- Root: Root$5,
1297
+ const Root$7 = part$8("Root", "section");
1298
+ const Header = part$8("Header", "header");
1299
+ const Title$2 = part$8("Title", "h3");
1300
+ const Description$3 = part$8("Description", "p");
1301
+ const Content$2 = part$8("Content", "div");
1302
+ const Footer = part$8("Footer", "footer");
1303
+ const Card = Object.assign(Root$7, {
1304
+ Root: Root$7,
871
1305
  Header,
872
1306
  Title: Title$2,
873
1307
  Description: Description$3,
874
- Content: Content$1,
1308
+ Content: Content$2,
875
1309
  Footer
876
1310
  });
877
1311
  injectComponentStyle("card");
@@ -885,6 +1319,158 @@ injectComponentStyle("card");
885
1319
  const Carousel = Carousel$1;
886
1320
  injectComponentStyle("carousel");
887
1321
  //#endregion
1322
+ //#region src/components/cascade-select/index.tsx
1323
+ var _tmpl$$38 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m6 9 6 6 6-6">`);
1324
+ var _tmpl$2$19 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m9 18 6-6-6-6">`);
1325
+ var _tmpl$3$13 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=3 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m5 12.5 5 5L19 7">`);
1326
+ var _tmpl$4$9 = /*#__PURE__*/ template(`<ul>`);
1327
+ var _tmpl$5$7 = /*#__PURE__*/ template(`<span data-part=branch-indicator aria-hidden=true>`);
1328
+ var _tmpl$6$5 = /*#__PURE__*/ template(`<li><span></span><span>`);
1329
+ var _tmpl$7$2 = /*#__PURE__*/ template(`<div><div>`);
1330
+ var _tmpl$8$2 = /*#__PURE__*/ template(`<div><div><button><span></span><span>`);
1331
+ function chevronDown$1() {
1332
+ return _tmpl$$38();
1333
+ }
1334
+ function chevronRight() {
1335
+ return _tmpl$2$19();
1336
+ }
1337
+ function checkGlyph$2() {
1338
+ return _tmpl$3$13();
1339
+ }
1340
+ /**
1341
+ * A corridor of linked columns: pick a branch and the next column
1342
+ * dissolves open beside it, until a leaf click settles the whole path.
1343
+ * `value` is the selected path (or paths, when `multiple`) — the
1344
+ * joined labels ride the trigger. `highlightTrigger: "hover"` turns the
1345
+ * classic cascading menu: pointing is enough to unfold.
1346
+ */
1347
+ function CascadeSelect(props) {
1348
+ const [own, rest] = splitProps(props, [
1349
+ "value",
1350
+ "data",
1351
+ "placeholder",
1352
+ "highlightTrigger",
1353
+ "multiple",
1354
+ "disabled",
1355
+ "onValueChange"
1356
+ ]);
1357
+ const id = createUniqueId();
1358
+ const locale = useLocaleContext();
1359
+ const env = useEnvironmentContext();
1360
+ const collection = createMemo(() => cascade.collection({
1361
+ nodeToValue: (node) => node.value,
1362
+ nodeToString: (node) => node.label,
1363
+ nodeToChildren: (node) => node.children ?? [],
1364
+ rootNode: {
1365
+ value: "ROOT",
1366
+ label: "",
1367
+ children: own.data
1368
+ }
1369
+ }));
1370
+ const service = useMachine(cascade.machine, () => ({
1371
+ id,
1372
+ collection: collection(),
1373
+ dir: locale().dir,
1374
+ getRootNode: env().getRootNode.bind(env()),
1375
+ disabled: own.disabled || void 0,
1376
+ multiple: own.multiple || void 0,
1377
+ ...own.value !== void 0 ? { value: own.value } : {},
1378
+ ...own.highlightTrigger != null ? { highlightTrigger: own.highlightTrigger } : {},
1379
+ onValueChange(details) {
1380
+ own.onValueChange?.(details.value);
1381
+ }
1382
+ }));
1383
+ const api = createMemo(() => cascade.connect(service, normalizeProps));
1384
+ /** The machine's `valueAsString` only updates through its select
1385
+ * event, so an externally-set `value` would render the
1386
+ * placeholder forever — resolve the labels from the data instead. */
1387
+ function labelsFor(path) {
1388
+ const out = [];
1389
+ let nodes = own.data;
1390
+ for (const value of path) {
1391
+ const node = nodes?.find((n) => n.value === value);
1392
+ if (!node) return null;
1393
+ out.push(node.label);
1394
+ nodes = node.children;
1395
+ }
1396
+ return out;
1397
+ }
1398
+ const display = () => {
1399
+ const parts = (own.value ?? []).map((path) => labelsFor(path)?.join(" / ")).filter((label) => label != null);
1400
+ return parts.length > 0 ? parts.join(", ") : null;
1401
+ };
1402
+ /** One column per walk of the highlighted path — the list binds to
1403
+ * the node, the next column hangs off its highlighted child. */
1404
+ function renderColumn(node, indexPath, valuePath) {
1405
+ const nodeProps = {
1406
+ item: node,
1407
+ indexPath,
1408
+ value: valuePath
1409
+ };
1410
+ const nodeState = () => api().getItemState(nodeProps);
1411
+ const children = collection().getNodeChildren(node);
1412
+ const list = (() => {
1413
+ var _el$4 = _tmpl$4$9();
1414
+ spread(_el$4, mergeProps(() => mergeProps$1(() => api().getListProps(nodeProps))), false, true);
1415
+ insert(_el$4, createComponent(For, {
1416
+ each: children,
1417
+ children: (item, index) => {
1418
+ const itemValue = collection().getNodeValue(item);
1419
+ const itemProps = {
1420
+ item,
1421
+ indexPath: [...indexPath, index()],
1422
+ value: [...valuePath, itemValue]
1423
+ };
1424
+ const itemState = () => api().getItemState(itemProps);
1425
+ return (() => {
1426
+ var _el$5 = _tmpl$6$5(), _el$6 = _el$5.firstChild, _el$8 = _el$6.nextSibling;
1427
+ spread(_el$5, mergeProps(() => mergeProps$1(() => api().getItemProps(itemProps))), false, true);
1428
+ spread(_el$6, mergeProps(() => mergeProps$1(() => api().getItemTextProps(itemProps))), false, true);
1429
+ insert(_el$6, () => item.label);
1430
+ insert(_el$5, createComponent(Show, {
1431
+ get when() {
1432
+ return itemState().hasChildren;
1433
+ },
1434
+ get children() {
1435
+ var _el$7 = _tmpl$5$7();
1436
+ insert(_el$7, chevronRight);
1437
+ return _el$7;
1438
+ }
1439
+ }), _el$8);
1440
+ spread(_el$8, mergeProps(() => mergeProps$1(() => api().getItemIndicatorProps(itemProps))), false, true);
1441
+ insert(_el$8, checkGlyph$2);
1442
+ return _el$5;
1443
+ })();
1444
+ }
1445
+ }));
1446
+ return _el$4;
1447
+ })();
1448
+ const next = nodeState().highlightedChild;
1449
+ return [list, next != null && collection().isBranchNode(next) ? renderColumn(next, [...indexPath, nodeState().highlightedIndex], [...valuePath, collection().getNodeValue(next)]) : null];
1450
+ }
1451
+ return (() => {
1452
+ var _el$9 = _tmpl$8$2(), _el$0 = _el$9.firstChild, _el$1 = _el$0.firstChild, _el$10 = _el$1.firstChild, _el$11 = _el$10.nextSibling;
1453
+ spread(_el$9, mergeProps(rest, () => mergeProps$1(() => api().getRootProps())), false, true);
1454
+ spread(_el$0, mergeProps(() => mergeProps$1(() => api().getControlProps())), false, true);
1455
+ spread(_el$1, mergeProps(() => mergeProps$1(() => api().getTriggerProps(), { get disabled() {
1456
+ return own.disabled || void 0;
1457
+ } })), false, true);
1458
+ spread(_el$10, mergeProps(() => mergeProps$1(() => api().getValueTextProps())), false, true);
1459
+ insert(_el$10, () => display() ?? own.placeholder ?? "Select…");
1460
+ spread(_el$11, mergeProps(() => mergeProps$1(() => api().getIndicatorProps())), false, true);
1461
+ insert(_el$11, chevronDown$1);
1462
+ insert(_el$9, createComponent(Portal, { get children() {
1463
+ var _el$12 = _tmpl$7$2(), _el$13 = _el$12.firstChild;
1464
+ spread(_el$12, mergeProps(() => mergeProps$1(() => api().getPositionerProps())), false, true);
1465
+ spread(_el$13, mergeProps(() => mergeProps$1(() => api().getContentProps())), false, true);
1466
+ insert(_el$13, () => renderColumn(collection().rootNode, [], []));
1467
+ return _el$12;
1468
+ } }), null);
1469
+ return _el$9;
1470
+ })();
1471
+ }
1472
+ injectComponentStyle("cascade-select");
1473
+ //#endregion
888
1474
  //#region src/components/checkbox/index.ts
889
1475
  /** Ark's Checkbox, dressed in the paper-and-ink system: a square-cut seal
890
1476
  * that fills flat with primary ink when ticked, the mark springing into
@@ -893,17 +1479,87 @@ injectComponentStyle("carousel");
893
1479
  const Checkbox = Checkbox$1;
894
1480
  injectComponentStyle("checkbox");
895
1481
  //#endregion
1482
+ //#region src/components/checkbox-group/index.tsx
1483
+ var _tmpl$$37 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=3 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m5 12.5 5 5L19 7">`);
1484
+ var _tmpl$2$18 = /*#__PURE__*/ template(`<div>`);
1485
+ function checkGlyph$1() {
1486
+ return _tmpl$$37();
1487
+ }
1488
+ /**
1489
+ * One question, many answers: a labelled stack (or row) of the seal-cut
1490
+ * checkboxes bound to a single array. Toggling a box adds or removes its
1491
+ * value; the group itself is semantics (`role="group"`), the boxes stay
1492
+ * the machine-driven originals.
1493
+ */
1494
+ function CheckboxGroup(props) {
1495
+ const [own, rest] = splitProps(props, [
1496
+ "value",
1497
+ "options",
1498
+ "layout",
1499
+ "disabled",
1500
+ "onValueChange"
1501
+ ]);
1502
+ const selected = () => new Set(own.value ?? []);
1503
+ function toggle(value) {
1504
+ const next = new Set(selected());
1505
+ if (next.has(value)) next.delete(value);
1506
+ else next.add(value);
1507
+ own.onValueChange?.([...next]);
1508
+ }
1509
+ return (() => {
1510
+ var _el$2 = _tmpl$2$18();
1511
+ spread(_el$2, mergeProps(rest, {
1512
+ "role": "group",
1513
+ "data-scope": "checkbox-group",
1514
+ "data-part": "root",
1515
+ get ["data-layout"]() {
1516
+ return own.layout ?? "vertical";
1517
+ }
1518
+ }), false, true);
1519
+ insert(_el$2, createComponent(For, {
1520
+ get each() {
1521
+ return own.options;
1522
+ },
1523
+ children: (option) => createComponent(Checkbox$1.Root, {
1524
+ get checked() {
1525
+ return selected().has(option.value);
1526
+ },
1527
+ get disabled() {
1528
+ return own.disabled || option.disabled === true;
1529
+ },
1530
+ onCheckedChange: () => toggle(option.value),
1531
+ get children() {
1532
+ return [
1533
+ createComponent(Checkbox$1.Control, { get children() {
1534
+ return createComponent(Checkbox$1.Indicator, { get children() {
1535
+ return checkGlyph$1();
1536
+ } });
1537
+ } }),
1538
+ createComponent(Checkbox$1.Label, { get children() {
1539
+ return option.label;
1540
+ } }),
1541
+ createComponent(Checkbox$1.HiddenInput, {})
1542
+ ];
1543
+ }
1544
+ })
1545
+ }));
1546
+ return _el$2;
1547
+ })();
1548
+ }
1549
+ injectComponentStyle("checkbox-group");
1550
+ injectComponentStyle("checkbox");
1551
+ //#endregion
896
1552
  //#region src/components/chip/index.tsx
897
- var _tmpl$$10 = /*#__PURE__*/ template(`<span>`);
1553
+ var _tmpl$$36 = /*#__PURE__*/ template(`<span>`);
898
1554
  function Chip(props) {
899
- const [own, rest] = splitProps$1(props, [
1555
+ const [own, rest] = splitProps(props, [
900
1556
  "value",
901
1557
  "max",
902
1558
  "tone",
903
1559
  "variant"
904
1560
  ]);
905
1561
  return (() => {
906
- var _el$ = _tmpl$$10();
1562
+ var _el$ = _tmpl$$36();
907
1563
  spread(_el$, mergeProps(rest, {
908
1564
  "data-scope": "chip",
909
1565
  "data-part": "root",
@@ -952,6 +1608,396 @@ injectComponentStyle("color-picker");
952
1608
  const Combobox = Combobox$1;
953
1609
  injectComponentStyle("combobox");
954
1610
  //#endregion
1611
+ //#region src/components/command/index.tsx
1612
+ var _tmpl$$35 = /*#__PURE__*/ template(`<span data-scope=command data-part=item-hint>`);
1613
+ var _tmpl$2$17 = /*#__PURE__*/ template(`<div>`);
1614
+ var _tmpl$3$12 = /*#__PURE__*/ template(`<span>`);
1615
+ var _tmpl$4$8 = /*#__PURE__*/ template(`<input>`);
1616
+ var _tmpl$5$6 = /*#__PURE__*/ template(`<div data-scope=command data-part=empty>`);
1617
+ /** A command row: the machine's item grafted onto a vessel of our own,
1618
+ * the label riding the machine's item text. */
1619
+ function Row(props) {
1620
+ return createComponent(Combobox$1.Item, {
1621
+ get item() {
1622
+ return props.entry.value;
1623
+ },
1624
+ asChild: (itemProps) => (() => {
1625
+ var _el$ = _tmpl$2$17();
1626
+ spread(_el$, mergeProps(itemProps, {
1627
+ "data-scope": "command",
1628
+ "data-part": "item"
1629
+ }), false, true);
1630
+ insert(_el$, createComponent(Combobox$1.ItemText, { asChild: (textProps) => (() => {
1631
+ var _el$3 = _tmpl$3$12();
1632
+ spread(_el$3, mergeProps(textProps, {
1633
+ "data-scope": "command",
1634
+ "data-part": "item-label"
1635
+ }), false, true);
1636
+ insert(_el$3, () => props.entry.label);
1637
+ return _el$3;
1638
+ })() }), null);
1639
+ insert(_el$, createComponent(Show, {
1640
+ get when() {
1641
+ return props.entry.hint;
1642
+ },
1643
+ get children() {
1644
+ var _el$2 = _tmpl$$35();
1645
+ insert(_el$2, () => props.entry.hint);
1646
+ return _el$2;
1647
+ }
1648
+ }), null);
1649
+ return _el$;
1650
+ })()
1651
+ });
1652
+ }
1653
+ /**
1654
+ * The command palette: a modal sheet at the top of the page carrying a
1655
+ * search field over the caller's commands, grouped as a ledger with a
1656
+ * keycap hint at each row. The shell is the dialog machinery — scrim,
1657
+ * focus trap, Escape — and the searching is the combobox machinery
1658
+ * driving our own list: the vessel and the list live inside the sheet,
1659
+ * so the combobox renders no separate popup and the machine's content
1660
+ * grafts onto the sheet's list.
1661
+ */
1662
+ function Command(props) {
1663
+ const [own, rest] = splitProps(props, [
1664
+ "items",
1665
+ "placeholder",
1666
+ "open",
1667
+ "autoFilter",
1668
+ "inputValue",
1669
+ "emptyText",
1670
+ "onSelect",
1671
+ "onOpenChange",
1672
+ "onInputValueChange"
1673
+ ]);
1674
+ const [internalOpen, setInternalOpen] = createSignal(false);
1675
+ const [listOpen, setListOpen] = createSignal(true);
1676
+ let fieldText = "";
1677
+ const { collection, set, filter } = useListCollection$1({
1678
+ initialItems: (own.items ?? []).map((entry) => entry.value),
1679
+ filter: (value, input) => {
1680
+ const entry = (own.items ?? []).find((candidate) => candidate.value === value);
1681
+ if (!entry) return false;
1682
+ const query = input.toLowerCase();
1683
+ return entry.label.toLowerCase().includes(query) || value.toLowerCase().includes(query);
1684
+ }
1685
+ });
1686
+ createEffect(() => {
1687
+ set((own.items ?? []).map((entry) => entry.value));
1688
+ if (own.autoFilter ?? true) filter(fieldText);
1689
+ });
1690
+ const open = () => own.open ?? internalOpen();
1691
+ const setOpen = (value) => {
1692
+ if (own.open === void 0) setInternalOpen(value);
1693
+ own.onOpenChange?.(value);
1694
+ };
1695
+ createEffect(() => {
1696
+ if (open()) setListOpen(true);
1697
+ });
1698
+ const sections = () => {
1699
+ const available = new Set(collection().items);
1700
+ const groups = /* @__PURE__ */ new Map();
1701
+ for (const entry of own.items ?? []) {
1702
+ if (!available.has(entry.value)) continue;
1703
+ const key = entry.group ?? "";
1704
+ if (!groups.has(key)) groups.set(key, []);
1705
+ groups.get(key).push(entry);
1706
+ }
1707
+ return Array.from(groups, ([group, entries]) => ({
1708
+ group,
1709
+ entries
1710
+ }));
1711
+ };
1712
+ return createComponent(Dialog$1.Root, mergeProps(rest, {
1713
+ get open() {
1714
+ return open();
1715
+ },
1716
+ onOpenChange: (details) => setOpen(details.open),
1717
+ get children() {
1718
+ return createComponent(Portal, { get children() {
1719
+ return [createComponent(Dialog$1.Backdrop, {}), createComponent(Dialog$1.Positioner, { asChild: (positionerProps) => (() => {
1720
+ var _el$4 = _tmpl$2$17();
1721
+ spread(_el$4, mergeProps(positionerProps, {
1722
+ "data-scope": "command",
1723
+ "data-part": "positioner"
1724
+ }), false, true);
1725
+ insert(_el$4, createComponent(Dialog$1.Content, { asChild: (contentProps) => (() => {
1726
+ var _el$5 = _tmpl$2$17();
1727
+ spread(_el$5, mergeProps(contentProps, {
1728
+ "data-scope": "command",
1729
+ "data-part": "content"
1730
+ }), false, true);
1731
+ insert(_el$5, createComponent(Combobox$1.Root, {
1732
+ get collection() {
1733
+ return collection();
1734
+ },
1735
+ get inputValue() {
1736
+ return own.inputValue;
1737
+ },
1738
+ get open() {
1739
+ return listOpen();
1740
+ },
1741
+ onOpenChange: (details) => setListOpen(details.open),
1742
+ inputBehavior: "autohighlight",
1743
+ loopFocus: true,
1744
+ onInputValueChange: (details) => {
1745
+ fieldText = details.inputValue;
1746
+ if (own.autoFilter ?? true) filter(details.inputValue);
1747
+ own.onInputValueChange?.(details.inputValue);
1748
+ },
1749
+ onValueChange: (details) => {
1750
+ const [first] = details.value;
1751
+ if (first == null) return;
1752
+ own.onSelect?.(first);
1753
+ setOpen(false);
1754
+ },
1755
+ get children() {
1756
+ return [createComponent(Combobox$1.Input, { asChild: (inputProps) => (() => {
1757
+ var _el$6 = _tmpl$4$8();
1758
+ spread(_el$6, mergeProps(inputProps, {
1759
+ "type": "text",
1760
+ get placeholder() {
1761
+ return own.placeholder;
1762
+ },
1763
+ "data-scope": "command",
1764
+ "data-part": "input"
1765
+ }), false, false);
1766
+ return _el$6;
1767
+ })() }), createComponent(Combobox$1.Content, { asChild: (listProps) => (() => {
1768
+ var _el$7 = _tmpl$2$17();
1769
+ spread(_el$7, mergeProps(listProps, {
1770
+ "data-scope": "command",
1771
+ "data-part": "list"
1772
+ }), false, true);
1773
+ insert(_el$7, createComponent(For, {
1774
+ get each() {
1775
+ return sections();
1776
+ },
1777
+ children: (section) => createComponent(Show, {
1778
+ get when() {
1779
+ return section.group !== "";
1780
+ },
1781
+ get fallback() {
1782
+ return createComponent(For, {
1783
+ get each() {
1784
+ return section.entries;
1785
+ },
1786
+ children: (entry) => createComponent(Row, { entry })
1787
+ });
1788
+ },
1789
+ get children() {
1790
+ return createComponent(Combobox$1.ItemGroup, { asChild: (groupProps) => (() => {
1791
+ var _el$9 = _tmpl$2$17();
1792
+ spread(_el$9, mergeProps(groupProps, {
1793
+ "data-scope": "command",
1794
+ "data-part": "group"
1795
+ }), false, true);
1796
+ insert(_el$9, createComponent(Combobox$1.ItemGroupLabel, { asChild: (labelProps) => (() => {
1797
+ var _el$0 = _tmpl$2$17();
1798
+ spread(_el$0, mergeProps(labelProps, {
1799
+ "data-scope": "command",
1800
+ "data-part": "group-label"
1801
+ }), false, true);
1802
+ insert(_el$0, () => section.group);
1803
+ return _el$0;
1804
+ })() }), null);
1805
+ insert(_el$9, createComponent(For, {
1806
+ get each() {
1807
+ return section.entries;
1808
+ },
1809
+ children: (entry) => createComponent(Row, { entry })
1810
+ }), null);
1811
+ return _el$9;
1812
+ })() });
1813
+ }
1814
+ })
1815
+ }), null);
1816
+ insert(_el$7, createComponent(Show, {
1817
+ get when() {
1818
+ return sections().length === 0;
1819
+ },
1820
+ get children() {
1821
+ var _el$8 = _tmpl$5$6();
1822
+ insert(_el$8, () => own.emptyText ?? "No matching commands");
1823
+ return _el$8;
1824
+ }
1825
+ }), null);
1826
+ return _el$7;
1827
+ })() })];
1828
+ }
1829
+ }));
1830
+ return _el$5;
1831
+ })() }));
1832
+ return _el$4;
1833
+ })() })];
1834
+ } });
1835
+ }
1836
+ }));
1837
+ }
1838
+ injectComponentStyle("command");
1839
+ injectComponentStyle("dialog");
1840
+ //#endregion
1841
+ //#region src/components/comment/index.tsx
1842
+ var _tmpl$$34 = /*#__PURE__*/ template(`<div data-scope=comment data-part=avatar>`);
1843
+ var _tmpl$2$16 = /*#__PURE__*/ template(`<span data-scope=comment data-part=author>`);
1844
+ var _tmpl$3$11 = /*#__PURE__*/ template(`<time data-scope=comment data-part=datetime>`);
1845
+ var _tmpl$4$7 = /*#__PURE__*/ template(`<header data-scope=comment data-part=header>`);
1846
+ var _tmpl$5$5 = /*#__PURE__*/ template(`<div data-scope=comment data-part=actions>`);
1847
+ var _tmpl$6$4 = /*#__PURE__*/ template(`<article><div data-scope=comment data-part=body><div data-scope=comment data-part=content>`);
1848
+ /**
1849
+ * A voice on the record: the portrait hangs left (the `avatar` prop),
1850
+ * the body carries the byline from `author` and `datetime`, the ink is
1851
+ * the children, and `actions` is the row of answers.
1852
+ */
1853
+ function Comment(props) {
1854
+ const [own, rest] = splitProps(props, [
1855
+ "author",
1856
+ "datetime",
1857
+ "avatar",
1858
+ "actions",
1859
+ "children"
1860
+ ]);
1861
+ return (() => {
1862
+ var _el$ = _tmpl$6$4(), _el$3 = _el$.firstChild, _el$7 = _el$3.firstChild;
1863
+ spread(_el$, mergeProps(rest, {
1864
+ "data-scope": "comment",
1865
+ "data-part": "root"
1866
+ }), false, true);
1867
+ insert(_el$, createComponent(Show, {
1868
+ get when() {
1869
+ return own.avatar;
1870
+ },
1871
+ get children() {
1872
+ var _el$2 = _tmpl$$34();
1873
+ insert(_el$2, () => own.avatar);
1874
+ return _el$2;
1875
+ }
1876
+ }), _el$3);
1877
+ insert(_el$3, createComponent(Show, {
1878
+ get when() {
1879
+ return own.author || own.datetime;
1880
+ },
1881
+ get children() {
1882
+ var _el$4 = _tmpl$4$7();
1883
+ insert(_el$4, createComponent(Show, {
1884
+ get when() {
1885
+ return own.author;
1886
+ },
1887
+ get children() {
1888
+ var _el$5 = _tmpl$2$16();
1889
+ insert(_el$5, () => own.author);
1890
+ return _el$5;
1891
+ }
1892
+ }), null);
1893
+ insert(_el$4, createComponent(Show, {
1894
+ get when() {
1895
+ return own.datetime;
1896
+ },
1897
+ get children() {
1898
+ var _el$6 = _tmpl$3$11();
1899
+ insert(_el$6, () => own.datetime);
1900
+ effect(() => setAttribute(_el$6, "datetime", own.datetime));
1901
+ return _el$6;
1902
+ }
1903
+ }), null);
1904
+ return _el$4;
1905
+ }
1906
+ }), _el$7);
1907
+ insert(_el$7, () => own.children);
1908
+ insert(_el$3, createComponent(Show, {
1909
+ get when() {
1910
+ return own.actions;
1911
+ },
1912
+ get children() {
1913
+ var _el$8 = _tmpl$5$5();
1914
+ insert(_el$8, () => own.actions);
1915
+ return _el$8;
1916
+ }
1917
+ }), null);
1918
+ return _el$;
1919
+ })();
1920
+ }
1921
+ injectComponentStyle("comment");
1922
+ //#endregion
1923
+ //#region src/components/config-provider/index.tsx
1924
+ var _tmpl$$33 = /*#__PURE__*/ template(`<div>`);
1925
+ /** Solid context for the provider's snapshot — a custom part reads it
1926
+ * with `useContext(ConfigContextKey)`. */
1927
+ const ConfigContextKey = createContext(() => ({}));
1928
+ /** The nearest provider's snapshot, or an empty one when no provider
1929
+ * wraps the caller — the hook the date and format families will consume
1930
+ * to localize their output. */
1931
+ function useConfig() {
1932
+ return useContext(ConfigContextKey);
1933
+ }
1934
+ /**
1935
+ * The declarative host for global configuration: one element that both
1936
+ * carries the token layer's attributes — `[data-density]` and
1937
+ * `[data-accent]` fire on any element — and provides the same values to
1938
+ * descendants through `useConfig`, so interactive behavior (formatting,
1939
+ * messages) and visual theming stay one decision.
1940
+ */
1941
+ function ConfigProvider(props) {
1942
+ const [own, rest] = splitProps(props, [
1943
+ "density",
1944
+ "accent",
1945
+ "dir",
1946
+ "locale",
1947
+ "children"
1948
+ ]);
1949
+ return createComponent(ConfigContextKey.Provider, {
1950
+ value: () => ({
1951
+ density: own.density,
1952
+ accent: own.accent,
1953
+ dir: own.dir,
1954
+ locale: own.locale
1955
+ }),
1956
+ get children() {
1957
+ var _el$ = _tmpl$$33();
1958
+ spread(_el$, mergeProps(rest, {
1959
+ "data-scope": "config-provider",
1960
+ "data-part": "root",
1961
+ get ["data-density"]() {
1962
+ return own.density;
1963
+ },
1964
+ get ["data-accent"]() {
1965
+ return own.accent;
1966
+ },
1967
+ get dir() {
1968
+ return own.dir;
1969
+ },
1970
+ get lang() {
1971
+ return own.locale;
1972
+ }
1973
+ }), false, true);
1974
+ insert(_el$, () => own.children);
1975
+ return _el$;
1976
+ }
1977
+ });
1978
+ }
1979
+ //#endregion
1980
+ //#region src/components/container/index.tsx
1981
+ var _tmpl$$32 = /*#__PURE__*/ template(`<div>`);
1982
+ function Container(props) {
1983
+ const [own, rest] = splitProps(props, ["size", "padding"]);
1984
+ return (() => {
1985
+ var _el$ = _tmpl$$32();
1986
+ spread(_el$, mergeProps(rest, {
1987
+ "data-scope": "container",
1988
+ "data-part": "root",
1989
+ get ["data-size"]() {
1990
+ return own.size ?? "readable";
1991
+ },
1992
+ get ["data-padding"]() {
1993
+ return own.padding === false ? void 0 : "";
1994
+ }
1995
+ }), false, false);
1996
+ return _el$;
1997
+ })();
1998
+ }
1999
+ injectComponentStyle("container");
2000
+ //#endregion
955
2001
  //#region src/components/date-input/index.ts
956
2002
  /** Ark's DateInput, dressed in the paper-and-ink system: a segmented
957
2003
  * field where the focused segment takes the flat ink fill. The API is
@@ -970,6 +2016,44 @@ injectComponentStyle("date-input");
970
2016
  const DatePicker = DatePicker$1;
971
2017
  injectComponentStyle("date-picker");
972
2018
  //#endregion
2019
+ //#region src/components/descriptions/index.tsx
2020
+ var _tmpl$$31 = /*#__PURE__*/ template(`<dl>`);
2021
+ function Root$6(props) {
2022
+ const [own, rest] = splitProps(props, ["layout"]);
2023
+ return (() => {
2024
+ var _el$ = _tmpl$$31();
2025
+ spread(_el$, mergeProps(rest, {
2026
+ "data-scope": "descriptions",
2027
+ "data-part": "root",
2028
+ get ["data-layout"]() {
2029
+ return own.layout ?? "horizontal";
2030
+ }
2031
+ }), false, false);
2032
+ return _el$;
2033
+ })();
2034
+ }
2035
+ function part$7(name, tag) {
2036
+ function Component(props) {
2037
+ return createComponent(tag, mergeProps(props, {
2038
+ "data-scope": "descriptions",
2039
+ get ["data-part"]() {
2040
+ return name.toLowerCase();
2041
+ }
2042
+ }));
2043
+ }
2044
+ return Component;
2045
+ }
2046
+ const Item$2 = part$7("Item", "div");
2047
+ const Term = part$7("Term", "dt");
2048
+ const Detail = part$7("Detail", "dd");
2049
+ const Descriptions = Object.assign(Root$6, {
2050
+ Root: Root$6,
2051
+ Item: Item$2,
2052
+ Term,
2053
+ Detail
2054
+ });
2055
+ injectComponentStyle("descriptions");
2056
+ //#endregion
973
2057
  //#region src/components/dialog/index.ts
974
2058
  /** Ark's Dialog, dressed in the paper-and-ink system: the sheet dissolves
975
2059
  * in on elevation, the backdrop fades, and nested overlays stack through
@@ -987,43 +2071,205 @@ injectComponentStyle("dialog");
987
2071
  const Drawer = Drawer$1;
988
2072
  injectComponentStyle("drawer");
989
2073
  //#endregion
990
- //#region src/components/editable/index.ts
991
- /** Ark's Editable, dressed in the paper-and-ink system: bare ink while
992
- * reading, the full field recipe while editing. The API is Ark's own —
993
- * Root, Area, Label, Preview, Input, EditTrigger, SubmitTrigger,
994
- * CancelTrigger, Control. */
995
- const Editable = Editable$1;
996
- injectComponentStyle("editable");
997
- //#endregion
998
- //#region src/components/empty/index.tsx
999
- /** An empty state: the page holds its breath. Root centers the column,
1000
- * Visual carries the mark, Title and Description carry the ink, Actions
1001
- * the way out. Any subset composes. */
1002
- function part$5(name, tag) {
1003
- return ((props) => {
1004
- return createComponent(tag, mergeProps(props, {
1005
- "data-scope": "empty",
1006
- get ["data-part"]() {
1007
- return name.toLowerCase();
1008
- }
1009
- }));
1010
- });
2074
+ //#region src/components/input/index.tsx
2075
+ var _tmpl$$30 = /*#__PURE__*/ template(`<input>`);
2076
+ /** The bare text input: the field recipe — border, surface, focus halo —
2077
+ * on a native control. Standing alone it styles itself from the `invalid`
2078
+ * prop; inside a `Field.Root` it consumes the field context, picking up
2079
+ * the label id, the described-by wiring and the invalid state for free,
2080
+ * which is also the seam the Form validation layer will drive. Disabled
2081
+ * rides the native attribute. */
2082
+ function Input(props) {
2083
+ const field = useFieldContext();
2084
+ const [own, rest] = splitProps(props, [
2085
+ "value",
2086
+ "size",
2087
+ "invalid",
2088
+ "onValueChange"
2089
+ ]);
2090
+ return (() => {
2091
+ var _el$ = _tmpl$$30();
2092
+ spread(_el$, mergeProps(() => mergeProps$1(() => field?.().getInputProps() ?? {}, rest, {
2093
+ get value() {
2094
+ return own.value;
2095
+ },
2096
+ "data-scope": "input",
2097
+ "data-part": "root",
2098
+ get "data-size"() {
2099
+ return own.size ?? "md";
2100
+ },
2101
+ get "data-invalid"() {
2102
+ return own.invalid || field?.().getInputProps()["data-invalid"] != null ? "" : void 0;
2103
+ },
2104
+ onInput: (event) => own.onValueChange?.(event.currentTarget.value)
2105
+ })), false, false);
2106
+ return _el$;
2107
+ })();
1011
2108
  }
1012
- const Root$4 = part$5("Root", "div");
1013
- const Visual = part$5("Visual", "div");
1014
- const Title$1 = part$5("Title", "h3");
1015
- const Description$2 = part$5("Description", "p");
1016
- const Actions$1 = part$5("Actions", "div");
1017
- const Empty = Object.assign(Root$4, {
1018
- Root: Root$4,
1019
- Visual,
1020
- Title: Title$1,
1021
- Description: Description$2,
1022
- Actions: Actions$1
1023
- });
1024
- injectComponentStyle("empty");
2109
+ injectComponentStyle("input");
1025
2110
  //#endregion
1026
- //#region src/components/fieldset/index.ts
2111
+ //#region src/components/dynamic-input/index.tsx
2112
+ var _tmpl$$29 = /*#__PURE__*/ template(`<div><div data-scope=dynamic-input data-part=add>`);
2113
+ var _tmpl$2$15 = /*#__PURE__*/ template(`<div data-scope=dynamic-input data-part=row>`);
2114
+ var _tmpl$3$10 = /*#__PURE__*/ template(`<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M18 6 6 18M6 6l12 12">`);
2115
+ /**
2116
+ * A column of entry rows: one Input per line, each with a quiet remove
2117
+ * seal, and an add row at the tail. The list is controlled — every edit
2118
+ * calls `onValueChange` with a fresh array and the caller's array stays
2119
+ * the only truth. Deleting never drops below `min`, adding never grows
2120
+ * past `max`, and the group always keeps one row: an entry list that
2121
+ * emptied itself would leave the reader no place to type.
2122
+ */
2123
+ function DynamicInput(props) {
2124
+ const [own, rest] = splitProps(props, [
2125
+ "value",
2126
+ "min",
2127
+ "max",
2128
+ "placeholder",
2129
+ "addLabel",
2130
+ "disabled",
2131
+ "invalid",
2132
+ "onValueChange",
2133
+ "children"
2134
+ ]);
2135
+ const values = () => own.value ?? [""];
2136
+ const update = (index, value) => {
2137
+ const next = values().slice();
2138
+ next[index] = value;
2139
+ own.onValueChange?.(next);
2140
+ };
2141
+ const remove = (index) => {
2142
+ const next = values().filter((_, i) => i !== index);
2143
+ own.onValueChange?.(next.length > 0 ? next : [""]);
2144
+ };
2145
+ const add = () => {
2146
+ own.onValueChange?.([...values(), ""]);
2147
+ };
2148
+ const canRemove = () => values().length > Math.max(own.min ?? 0, 1);
2149
+ const canAdd = () => own.max === void 0 || values().length < own.max;
2150
+ return (() => {
2151
+ var _el$ = _tmpl$$29(), _el$2 = _el$.firstChild;
2152
+ spread(_el$, mergeProps(rest, {
2153
+ "data-scope": "dynamic-input",
2154
+ "data-part": "root"
2155
+ }), false, true);
2156
+ insert(_el$, createComponent(Index, {
2157
+ get each() {
2158
+ return values();
2159
+ },
2160
+ children: (value, index) => (() => {
2161
+ var _el$3 = _tmpl$2$15();
2162
+ insert(_el$3, createComponent(Input, {
2163
+ get value() {
2164
+ return value();
2165
+ },
2166
+ get placeholder() {
2167
+ return own.placeholder;
2168
+ },
2169
+ get disabled() {
2170
+ return own.disabled;
2171
+ },
2172
+ get invalid() {
2173
+ return own.invalid;
2174
+ },
2175
+ onValueChange: (next) => update(index, next)
2176
+ }), null);
2177
+ insert(_el$3, createComponent(Button, {
2178
+ variant: "ghost",
2179
+ square: true,
2180
+ get disabled() {
2181
+ return own.disabled || !canRemove();
2182
+ },
2183
+ "aria-label": `Remove entry ${index + 1}`,
2184
+ onClick: () => remove(index),
2185
+ get children() {
2186
+ return crossIcon();
2187
+ }
2188
+ }), null);
2189
+ return _el$3;
2190
+ })()
2191
+ }), _el$2);
2192
+ insert(_el$2, createComponent(Button, {
2193
+ variant: "ghost",
2194
+ get disabled() {
2195
+ return own.disabled || !canAdd();
2196
+ },
2197
+ onClick: () => add(),
2198
+ get children() {
2199
+ return ["+", memo(() => own.addLabel ?? "Add entry")];
2200
+ }
2201
+ }));
2202
+ return _el$;
2203
+ })();
2204
+ }
2205
+ /** The one glyph a remove seal needs: a single crossing stroke. */
2206
+ function crossIcon() {
2207
+ return _tmpl$3$10();
2208
+ }
2209
+ injectComponentStyle("dynamic-input");
2210
+ //#endregion
2211
+ //#region src/components/editable/index.ts
2212
+ /** Ark's Editable, dressed in the paper-and-ink system: bare ink while
2213
+ * reading, the full field recipe while editing. The API is Ark's own —
2214
+ * Root, Area, Label, Preview, Input, EditTrigger, SubmitTrigger,
2215
+ * CancelTrigger, Control. */
2216
+ const Editable = Editable$1;
2217
+ injectComponentStyle("editable");
2218
+ //#endregion
2219
+ //#region src/components/ellipsis/index.tsx
2220
+ var _tmpl$$28 = /*#__PURE__*/ template(`<span>`);
2221
+ function Ellipsis(props) {
2222
+ const [own, rest] = splitProps(props, ["lines"]);
2223
+ const multiline = () => (own.lines ?? 1) > 1;
2224
+ return (() => {
2225
+ var _el$ = _tmpl$$28();
2226
+ spread(_el$, mergeProps(rest, {
2227
+ get style() {
2228
+ return {
2229
+ ...rest.style,
2230
+ ...multiline() ? { "--bs-ellipsis-lines": String(own.lines) } : {}
2231
+ };
2232
+ },
2233
+ "data-scope": "ellipsis",
2234
+ "data-part": "root",
2235
+ get ["data-multiline"]() {
2236
+ return multiline() ? "" : void 0;
2237
+ }
2238
+ }), false, false);
2239
+ return _el$;
2240
+ })();
2241
+ }
2242
+ injectComponentStyle("ellipsis");
2243
+ //#endregion
2244
+ //#region src/components/empty/index.tsx
2245
+ /** An empty state: the page holds its breath. Root centers the column,
2246
+ * Visual carries the mark, Title and Description carry the ink, Actions
2247
+ * the way out. Any subset composes. */
2248
+ function part$6(name, tag) {
2249
+ return ((props) => {
2250
+ return createComponent(tag, mergeProps(props, {
2251
+ "data-scope": "empty",
2252
+ get ["data-part"]() {
2253
+ return name.toLowerCase();
2254
+ }
2255
+ }));
2256
+ });
2257
+ }
2258
+ const Root$5 = part$6("Root", "div");
2259
+ const Visual = part$6("Visual", "div");
2260
+ const Title$1 = part$6("Title", "h3");
2261
+ const Description$2 = part$6("Description", "p");
2262
+ const Actions$2 = part$6("Actions", "div");
2263
+ const Empty = Object.assign(Root$5, {
2264
+ Root: Root$5,
2265
+ Visual,
2266
+ Title: Title$1,
2267
+ Description: Description$2,
2268
+ Actions: Actions$2
2269
+ });
2270
+ injectComponentStyle("empty");
2271
+ //#endregion
2272
+ //#region src/components/fieldset/index.ts
1027
2273
  /** Ark's Fieldset, dressed in the paper-and-ink system: a song-serif
1028
2274
  * legend heading a column of fields. The API is Ark's own — Root, Legend,
1029
2275
  * HelperText, ErrorText. */
@@ -1040,6 +2286,118 @@ injectComponentStyle("fieldset");
1040
2286
  const FileUpload = FileUpload$1;
1041
2287
  injectComponentStyle("file-upload");
1042
2288
  //#endregion
2289
+ //#region src/components/float-button/index.tsx
2290
+ var _tmpl$$27 = /*#__PURE__*/ template(`<div>`);
2291
+ var _tmpl$2$14 = /*#__PURE__*/ template(`<div><span data-scope=float-button data-part=item-label aria-hidden=true>`);
2292
+ /** Solid context for {@link FloatButtonContext}, exported so a custom
2293
+ * part can read the group's state with `useContext`. */
2294
+ const FloatButtonContextKey = createContext();
2295
+ /**
2296
+ * A floating action and its fanned-out alternatives — FAB and speed
2297
+ * dial in one family. The Root moors the group at a page corner and
2298
+ * holds the openness (mirrored from `open` when controlled); the
2299
+ * Trigger flips it; each Item is a round action with its name surfacing
2300
+ * beside it while the group is open. The buttons are the shared recipe
2301
+ * (vessels here: round); this family owns only the mooring, the fan
2302
+ * and the fold.
2303
+ */
2304
+ function FloatButtonRoot(props) {
2305
+ const [own, rest] = splitProps(props, [
2306
+ "open",
2307
+ "placement",
2308
+ "onOpenChange"
2309
+ ]);
2310
+ const [inner, setInner] = createSignal(false);
2311
+ const open = () => own.open ?? inner();
2312
+ const setOpen = (value) => {
2313
+ setInner(value);
2314
+ own.onOpenChange?.(value);
2315
+ };
2316
+ const context = {
2317
+ open,
2318
+ toggle: () => setOpen(!open()),
2319
+ close: () => setOpen(false)
2320
+ };
2321
+ return createComponent(FloatButtonContextKey.Provider, {
2322
+ value: context,
2323
+ get children() {
2324
+ var _el$ = _tmpl$$27();
2325
+ spread(_el$, mergeProps(rest, {
2326
+ "data-scope": "float-button",
2327
+ "data-part": "root",
2328
+ get ["data-placement"]() {
2329
+ return own.placement ?? "bottom-end";
2330
+ },
2331
+ get ["data-state"]() {
2332
+ return open() ? "open" : "closed";
2333
+ }
2334
+ }), false, false);
2335
+ return _el$;
2336
+ }
2337
+ });
2338
+ }
2339
+ function FloatButtonTrigger(props) {
2340
+ const [own, rest] = splitProps(props, ["label", "children"]);
2341
+ const context = useContext(FloatButtonContextKey);
2342
+ return createComponent(Button, mergeProps(rest, {
2343
+ variant: "solid",
2344
+ square: true,
2345
+ size: "lg",
2346
+ onClick: () => context?.toggle(),
2347
+ get ["aria-label"]() {
2348
+ return own.label || "Actions";
2349
+ },
2350
+ get ["aria-expanded"]() {
2351
+ return context?.open() ?? false;
2352
+ },
2353
+ get children() {
2354
+ return own.children;
2355
+ }
2356
+ }));
2357
+ }
2358
+ function FloatButtonItem(props) {
2359
+ const [own, rest] = splitProps(props, [
2360
+ "label",
2361
+ "disabled",
2362
+ "onClick",
2363
+ "children"
2364
+ ]);
2365
+ const context = useContext(FloatButtonContextKey);
2366
+ return (() => {
2367
+ var _el$2 = _tmpl$2$14(), _el$3 = _el$2.firstChild;
2368
+ spread(_el$2, mergeProps(rest, {
2369
+ "data-scope": "float-button",
2370
+ "data-part": "item"
2371
+ }), false, true);
2372
+ insert(_el$2, createComponent(Button, {
2373
+ variant: "outline",
2374
+ square: true,
2375
+ size: "md",
2376
+ get disabled() {
2377
+ return own.disabled;
2378
+ },
2379
+ get ["aria-label"]() {
2380
+ return own.label;
2381
+ },
2382
+ onClick: (event) => {
2383
+ own.onClick?.(event);
2384
+ context?.close();
2385
+ },
2386
+ get children() {
2387
+ return own.children;
2388
+ }
2389
+ }), _el$3);
2390
+ insert(_el$3, () => own.label);
2391
+ return _el$2;
2392
+ })();
2393
+ }
2394
+ const FloatButton = Object.assign(FloatButtonRoot, {
2395
+ Root: FloatButtonRoot,
2396
+ Trigger: FloatButtonTrigger,
2397
+ Item: FloatButtonItem
2398
+ });
2399
+ injectComponentStyle("float-button");
2400
+ //#endregion
1043
2401
  //#region src/components/floating-panel/index.ts
1044
2402
  /** Ark's FloatingPanel, dressed in the paper-and-ink system: the shared
1045
2403
  * popup vessel let loose — a draggable, resizable sheet whose header is the
@@ -1057,6 +2415,187 @@ injectComponentStyle("floating-panel");
1057
2415
  * Byte, Time, RelativeTime. */
1058
2416
  const Format = Format$1;
1059
2417
  //#endregion
2418
+ //#region src/components/form/index.tsx
2419
+ var _tmpl$$26 = /*#__PURE__*/ template(`<form>`);
2420
+ var _tmpl$2$13 = /*#__PURE__*/ template(`<div>`);
2421
+ const FormContext = createContext();
2422
+ /** Walk a Standard Schema issue's path back to the dotted name the
2423
+ * matching FormField declared. */
2424
+ function issueName(issue) {
2425
+ return (issue.path ?? []).map((segment) => typeof segment === "object" ? segment.key : segment).join(".");
2426
+ }
2427
+ /**
2428
+ * The validation scheduler: one reactive error map, a submit that
2429
+ * validates before it emits, live re-validation on the events the
2430
+ * `validateOn` prop names, and the imperative handle. The schema is any
2431
+ * Standard Schema (valibot, zod, arktype, …) — none are bundled; a
2432
+ * `validate` function composes with it for the cases schemas can't
2433
+ * express. Errors reach their field by name, through FormField.
2434
+ */
2435
+ function Form(props) {
2436
+ const [own, rest] = splitProps(props, [
2437
+ "state",
2438
+ "schema",
2439
+ "validate",
2440
+ "validateOn",
2441
+ "disabled",
2442
+ "onSubmit",
2443
+ "onError",
2444
+ "ref"
2445
+ ]);
2446
+ const [errors, setErrorsMap] = createSignal(/* @__PURE__ */ new Map());
2447
+ const provide = {
2448
+ errors,
2449
+ disabled: own.disabled ?? false
2450
+ };
2451
+ let run = 0;
2452
+ async function runValidate() {
2453
+ const seq = ++run;
2454
+ const next = /* @__PURE__ */ new Map();
2455
+ if (own.validate) for (const error of await own.validate(own.state)) next.set(error.name, error.message);
2456
+ if (own.schema) {
2457
+ const result = await own.schema["~standard"].validate(own.state);
2458
+ for (const issue of result.issues ?? []) {
2459
+ const name = issueName(issue);
2460
+ if (!next.has(name)) next.set(name, issue.message);
2461
+ }
2462
+ }
2463
+ if (seq === run) setErrorsMap(next);
2464
+ return next;
2465
+ }
2466
+ function clear(name) {
2467
+ if (!name) {
2468
+ setErrorsMap(/* @__PURE__ */ new Map());
2469
+ return;
2470
+ }
2471
+ const next = new Map(errors());
2472
+ for (const key of next.keys()) if (typeof name === "string" ? key === name : name.test(key)) next.delete(key);
2473
+ setErrorsMap(next);
2474
+ }
2475
+ function setErrors(list) {
2476
+ setErrorsMap(new Map(list.map((error) => [error.name, error.message])));
2477
+ }
2478
+ function getErrors(name) {
2479
+ const all = [...errors()].map(([entry, message]) => ({
2480
+ name: entry,
2481
+ message
2482
+ }));
2483
+ if (!name) return all;
2484
+ return all.filter((error) => typeof name === "string" ? error.name === name : name.test(error.name));
2485
+ }
2486
+ const api = {
2487
+ validate: runValidate,
2488
+ clear,
2489
+ setErrors,
2490
+ getErrors,
2491
+ errors
2492
+ };
2493
+ onMount(() => own.ref?.(api));
2494
+ function handleSubmit(event) {
2495
+ event.preventDefault();
2496
+ runValidate().then((map) => {
2497
+ if (map.size === 0) {
2498
+ own.onSubmit?.(own.state);
2499
+ return;
2500
+ }
2501
+ own.onError?.([...map].map(([name, message]) => ({
2502
+ name,
2503
+ message
2504
+ })));
2505
+ });
2506
+ }
2507
+ let timer;
2508
+ function onDelegated(event) {
2509
+ if (!(own.validateOn ?? [
2510
+ "input",
2511
+ "change",
2512
+ "blur"
2513
+ ]).includes(event.type)) return;
2514
+ const target = event.target;
2515
+ if (!target || !("value" in target)) return;
2516
+ clearTimeout(timer);
2517
+ timer = setTimeout(() => void runValidate(), event.type === "input" ? 300 : 0);
2518
+ }
2519
+ const [formEl, setFormEl] = createSignal(null);
2520
+ onMount(() => {
2521
+ formEl()?.addEventListener("blur", onDelegated, true);
2522
+ onCleanup(() => formEl()?.removeEventListener("blur", onDelegated, true));
2523
+ });
2524
+ return createComponent(FormContext.Provider, {
2525
+ value: provide,
2526
+ get children() {
2527
+ var _el$ = _tmpl$$26();
2528
+ use(setFormEl, _el$);
2529
+ spread(_el$, mergeProps(rest, {
2530
+ "data-scope": "form",
2531
+ "data-part": "root",
2532
+ "novalidate": true,
2533
+ "onSubmit": handleSubmit,
2534
+ "onInput": onDelegated,
2535
+ "onChange": onDelegated
2536
+ }), false, false);
2537
+ return _el$;
2538
+ }
2539
+ });
2540
+ }
2541
+ /**
2542
+ * The named slot in the grid: label, control, hint — and the error the
2543
+ * Form routed to this name, shown through the same parts the standalone
2544
+ * Field family styles. The Ark field context runs underneath, so our
2545
+ * Input and Textarea pick up the label wiring and the invalid state
2546
+ * without knowing the Form exists. Without a Form above it degrades to
2547
+ * a plain labelled field.
2548
+ */
2549
+ function FormField(props) {
2550
+ const [own, rest] = splitProps(props, [
2551
+ "name",
2552
+ "label",
2553
+ "hint",
2554
+ "required",
2555
+ "invalid",
2556
+ "disabled",
2557
+ "children"
2558
+ ]);
2559
+ const form = useContext(FormContext);
2560
+ const error = () => own.name ? form?.errors().get(own.name) : void 0;
2561
+ const invalid = () => own.invalid || error() != null;
2562
+ const disabled = () => own.disabled || (form?.disabled ?? false);
2563
+ return (() => {
2564
+ var _el$2 = _tmpl$2$13();
2565
+ spread(_el$2, mergeProps(rest, { get ["data-form-field"]() {
2566
+ return own.name;
2567
+ } }), false, true);
2568
+ insert(_el$2, createComponent(Field$1.Root, {
2569
+ get invalid() {
2570
+ return invalid();
2571
+ },
2572
+ get required() {
2573
+ return own.required;
2574
+ },
2575
+ get disabled() {
2576
+ return disabled();
2577
+ },
2578
+ get children() {
2579
+ return [
2580
+ memo(() => memo(() => !!own.label)() ? createComponent(Field$1.Label, { get children() {
2581
+ return own.label;
2582
+ } }) : null),
2583
+ memo(() => own.children),
2584
+ memo(() => memo(() => !!(own.hint && error() == null))() ? createComponent(Field$1.HelperText, { get children() {
2585
+ return own.hint;
2586
+ } }) : null),
2587
+ memo(() => memo(() => error() != null)() ? createComponent(Field$1.ErrorText, { get children() {
2588
+ return error();
2589
+ } }) : null)
2590
+ ];
2591
+ }
2592
+ }));
2593
+ return _el$2;
2594
+ })();
2595
+ }
2596
+ injectComponentStyle("form");
2597
+ injectComponentStyle("field");
2598
+ //#endregion
1060
2599
  //#region src/components/frame/index.ts
1061
2600
  /** Ark's Frame, dressed in the paper-and-ink system: a sandboxed
1062
2601
  * iframe whose body mounts the children and whose `head` prop
@@ -1067,6 +2606,46 @@ const Format = Format$1;
1067
2606
  * core stylesheet to hook. The API is Ark's own. */
1068
2607
  const Frame = Frame$1;
1069
2608
  //#endregion
2609
+ //#region src/components/grid/index.tsx
2610
+ var _tmpl$$25 = /*#__PURE__*/ template(`<div>`);
2611
+ /** The same named steps of the space ramp the stack uses — one
2612
+ * vocabulary of distance across the layout primitives. */
2613
+ const gapVars$2 = {
2614
+ none: "0",
2615
+ xs: "var(--bs-gap-xs)",
2616
+ sm: "var(--bs-gap-sm)",
2617
+ md: "var(--bs-gap-md)",
2618
+ lg: "var(--bs-gap-lg)",
2619
+ xl: "var(--bs-gap-xl)"
2620
+ };
2621
+ function Grid(props) {
2622
+ const [own, rest] = splitProps(props, [
2623
+ "columns",
2624
+ "gap",
2625
+ "minChildWidth"
2626
+ ]);
2627
+ return (() => {
2628
+ var _el$ = _tmpl$$25();
2629
+ spread(_el$, mergeProps(rest, {
2630
+ get style() {
2631
+ return {
2632
+ ...rest.style,
2633
+ "--bs-grid-columns": String(own.columns ?? 12),
2634
+ "--bs-grid-gap": gapVars$2[own.gap ?? "md"] ?? gapVars$2.md,
2635
+ ...own.minChildWidth != null ? { "--bs-grid-min-child-width": own.minChildWidth } : {}
2636
+ };
2637
+ },
2638
+ "data-scope": "grid",
2639
+ "data-part": "root",
2640
+ get ["data-autofill"]() {
2641
+ return own.minChildWidth != null ? "" : void 0;
2642
+ }
2643
+ }), false, false);
2644
+ return _el$;
2645
+ })();
2646
+ }
2647
+ injectComponentStyle("grid");
2648
+ //#endregion
1070
2649
  //#region src/components/highlight/index.ts
1071
2650
  /** Ark's Highlight, dressed in the paper-and-ink system: query hits are
1072
2651
  * strokes of pigment on the page — a quiet tint of the accent behind the
@@ -1082,6 +2661,98 @@ injectComponentStyle("highlight");
1082
2661
  const HoverCard = HoverCard$1;
1083
2662
  injectComponentStyle("hover-card");
1084
2663
  //#endregion
2664
+ //#region src/components/icon/index.tsx
2665
+ var _tmpl$$24 = /*#__PURE__*/ template(`<span>`);
2666
+ function Icon(props) {
2667
+ const [own, rest] = splitProps(props, ["size", "label"]);
2668
+ return (() => {
2669
+ var _el$ = _tmpl$$24();
2670
+ spread(_el$, mergeProps(rest, {
2671
+ get role() {
2672
+ return own.label != null ? "img" : void 0;
2673
+ },
2674
+ get ["aria-label"]() {
2675
+ return own.label;
2676
+ },
2677
+ get ["aria-hidden"]() {
2678
+ return own.label != null ? void 0 : "true";
2679
+ },
2680
+ "data-scope": "icon",
2681
+ "data-part": "root",
2682
+ get ["data-size"]() {
2683
+ return own.size ?? "inherit";
2684
+ }
2685
+ }), false, false);
2686
+ return _el$;
2687
+ })();
2688
+ }
2689
+ injectComponentStyle("icon");
2690
+ //#endregion
2691
+ //#region src/components/image/index.tsx
2692
+ var _tmpl$$23 = /*#__PURE__*/ template(`<svg><rect x=3 y=4 width=18 height=16 rx=1.5></svg>`, false, true, false);
2693
+ var _tmpl$2$12 = /*#__PURE__*/ template(`<svg><circle cx=9 cy=10 r=1.5></svg>`, false, true, false);
2694
+ var _tmpl$3$9 = /*#__PURE__*/ template(`<svg><path d="m5.5 17.5 4.5-5 3 3.5 2.5-3 3 4.5"></svg>`, false, true, false);
2695
+ var _tmpl$4$6 = /*#__PURE__*/ template(`<div data-scope=image data-part=fallback>`);
2696
+ var _tmpl$5$4 = /*#__PURE__*/ template(`<figure><img data-scope=image data-part=img decoding=async>`, true, false, false);
2697
+ /** The mark for a source that never arrived: a quiet mountain-and-sun,
2698
+ * drawn in the stylesheet's stroke and hidden from the reader. */
2699
+ function placeholderGlyph() {
2700
+ return [
2701
+ _tmpl$$23(),
2702
+ _tmpl$2$12(),
2703
+ _tmpl$3$9()
2704
+ ];
2705
+ }
2706
+ function Image(props) {
2707
+ const [own, rest] = splitProps(props, [
2708
+ "src",
2709
+ "alt",
2710
+ "fit",
2711
+ "loading",
2712
+ "fallback"
2713
+ ]);
2714
+ const [state, setState] = createSignal("loading");
2715
+ createEffect(on(() => own.src, () => setState("loading")));
2716
+ return (() => {
2717
+ var _el$4 = _tmpl$5$4(), _el$5 = _el$4.firstChild;
2718
+ spread(_el$4, mergeProps(rest, {
2719
+ "data-scope": "image",
2720
+ "data-part": "root",
2721
+ get ["data-state"]() {
2722
+ return state();
2723
+ },
2724
+ get ["data-fit"]() {
2725
+ return own.fit ?? "cover";
2726
+ }
2727
+ }), false, true);
2728
+ _el$5.addEventListener("error", () => setState("error"));
2729
+ _el$5.addEventListener("load", () => setState("loaded"));
2730
+ insert(_el$4, createComponent(Show, {
2731
+ get when() {
2732
+ return state() === "error";
2733
+ },
2734
+ get children() {
2735
+ var _el$6 = _tmpl$4$6();
2736
+ insert(_el$6, () => own.fallback ?? placeholderGlyph());
2737
+ return _el$6;
2738
+ }
2739
+ }), null);
2740
+ effect((_p$) => {
2741
+ var _v$ = own.src, _v$2 = own.alt ?? "", _v$3 = own.loading ?? "lazy";
2742
+ _v$ !== _p$.e && setAttribute(_el$5, "src", _p$.e = _v$);
2743
+ _v$2 !== _p$.t && setAttribute(_el$5, "alt", _p$.t = _v$2);
2744
+ _v$3 !== _p$.a && setAttribute(_el$5, "loading", _p$.a = _v$3);
2745
+ return _p$;
2746
+ }, {
2747
+ e: void 0,
2748
+ t: void 0,
2749
+ a: void 0
2750
+ });
2751
+ return _el$4;
2752
+ })();
2753
+ }
2754
+ injectComponentStyle("image");
2755
+ //#endregion
1085
2756
  //#region src/components/image-cropper/index.ts
1086
2757
  /** Ark's ImageCropper, dressed in the paper-and-ink system: a rounded vessel
1087
2758
  * holding the photograph, one lit selection window framed by light hairlines.
@@ -1090,6 +2761,179 @@ injectComponentStyle("hover-card");
1090
2761
  const ImageCropper = ImageCropper$1;
1091
2762
  injectComponentStyle("image-cropper");
1092
2763
  //#endregion
2764
+ //#region src/components/image-viewer/index.tsx
2765
+ var _tmpl$$22 = /*#__PURE__*/ template(`<svg><circle cx=11 cy=11 r=7></svg>`, false, true, false);
2766
+ var _tmpl$2$11 = /*#__PURE__*/ template(`<svg><path d="m16.2 16.2 4.8 4.8"></svg>`, false, true, false);
2767
+ var _tmpl$3$8 = /*#__PURE__*/ template(`<svg><path d="M8 11h6"></svg>`, false, true, false);
2768
+ var _tmpl$4$5 = /*#__PURE__*/ template(`<svg><path d="M11 8v6"></svg>`, false, true, false);
2769
+ var _tmpl$5$3 = /*#__PURE__*/ template(`<svg><path d="M20.49 12A8.5 8.5 0 1 1 18 6.06"></svg>`, false, true, false);
2770
+ var _tmpl$6$3 = /*#__PURE__*/ template(`<svg><path d="M20.5 3.5v4h-4"></svg>`, false, true, false);
2771
+ var _tmpl$7$1 = /*#__PURE__*/ template(`<svg><path d="m6 6 12 12"></svg>`, false, true, false);
2772
+ var _tmpl$8$1 = /*#__PURE__*/ template(`<svg><path d="M18 6 6 18"></svg>`, false, true, false);
2773
+ var _tmpl$9$1 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round aria-hidden=true>`);
2774
+ var _tmpl$0$1 = /*#__PURE__*/ template(`<img data-scope=image-viewer data-part=viewport>`);
2775
+ var _tmpl$1$1 = /*#__PURE__*/ template(`<div data-scope=image-viewer data-part=toolbar>`);
2776
+ const MIN_SCALE = .5;
2777
+ const MAX_SCALE = 3;
2778
+ const SCALE_STEP = .25;
2779
+ /** The toolbar's line-drawn glyphs, fresh per render. */
2780
+ const TOOL_GLYPHS = {
2781
+ zoomIn: () => [
2782
+ _tmpl$$22(),
2783
+ _tmpl$2$11(),
2784
+ _tmpl$3$8(),
2785
+ _tmpl$4$5()
2786
+ ],
2787
+ zoomOut: () => [
2788
+ _tmpl$$22(),
2789
+ _tmpl$2$11(),
2790
+ _tmpl$3$8()
2791
+ ],
2792
+ rotate: () => [_tmpl$5$3(), _tmpl$6$3()],
2793
+ close: () => [_tmpl$7$1(), _tmpl$8$1()]
2794
+ };
2795
+ function ImageViewer(props) {
2796
+ const [own] = splitProps(props, [
2797
+ "src",
2798
+ "alt",
2799
+ "open",
2800
+ "zoomable",
2801
+ "onOpenChange"
2802
+ ]);
2803
+ const [localOpen, setLocalOpen] = createSignal(false);
2804
+ const [scale, setScale] = createSignal(1);
2805
+ const [rotation, setRotation] = createSignal(0);
2806
+ const isOpen = () => own.open ?? localOpen();
2807
+ const setOpen = (value) => {
2808
+ if (own.open === void 0) setLocalOpen(value);
2809
+ own.onOpenChange?.(value);
2810
+ };
2811
+ createEffect(() => {
2812
+ if (isOpen()) {
2813
+ setScale(1);
2814
+ setRotation(0);
2815
+ }
2816
+ });
2817
+ function zoom(step) {
2818
+ setScale(Math.min(MAX_SCALE, Math.max(MIN_SCALE, scale() + step)));
2819
+ }
2820
+ function rotate() {
2821
+ setRotation((rotation() + 90) % 360);
2822
+ }
2823
+ function toolButton(label, glyph, onClick) {
2824
+ return createComponent(Button, {
2825
+ variant: "ghost",
2826
+ square: true,
2827
+ size: "lg",
2828
+ "aria-label": label,
2829
+ onClick,
2830
+ get children() {
2831
+ var _el$10 = _tmpl$9$1();
2832
+ insert(_el$10, glyph);
2833
+ return _el$10;
2834
+ }
2835
+ });
2836
+ }
2837
+ return createComponent(Dialog$1.Root, {
2838
+ get open() {
2839
+ return isOpen();
2840
+ },
2841
+ onOpenChange: (details) => setOpen(details.open),
2842
+ lazyMount: true,
2843
+ unmountOnExit: true,
2844
+ get children() {
2845
+ return createComponent(Portal, { get children() {
2846
+ return [createComponent(Dialog$1.Backdrop, { "class": "bs-image-viewer-backdrop" }), createComponent(Dialog$1.Positioner, {
2847
+ "class": "bs-image-viewer-positioner",
2848
+ get children() {
2849
+ return createComponent(Dialog$1.Content, {
2850
+ "class": "bs-image-viewer-content",
2851
+ get ["aria-label"]() {
2852
+ return own.alt || "Image preview";
2853
+ },
2854
+ onClick: (event) => {
2855
+ if (event.target === event.currentTarget) setOpen(false);
2856
+ },
2857
+ get children() {
2858
+ return [(() => {
2859
+ var _el$11 = _tmpl$0$1();
2860
+ effect((_p$) => {
2861
+ var _v$ = own.src, _v$2 = own.alt ?? "", _v$3 = `scale(${scale()}) rotate(${rotation()}deg)`;
2862
+ _v$ !== _p$.e && setAttribute(_el$11, "src", _p$.e = _v$);
2863
+ _v$2 !== _p$.t && setAttribute(_el$11, "alt", _p$.t = _v$2);
2864
+ _v$3 !== _p$.a && setStyleProperty(_el$11, "transform", _p$.a = _v$3);
2865
+ return _p$;
2866
+ }, {
2867
+ e: void 0,
2868
+ t: void 0,
2869
+ a: void 0
2870
+ });
2871
+ return _el$11;
2872
+ })(), (() => {
2873
+ var _el$12 = _tmpl$1$1();
2874
+ insert(_el$12, createComponent(ButtonGroup, { get children() {
2875
+ return [
2876
+ createComponent(Show, {
2877
+ get when() {
2878
+ return own.zoomable ?? true;
2879
+ },
2880
+ get children() {
2881
+ return [memo(() => toolButton("Zoom in", TOOL_GLYPHS.zoomIn, () => zoom(SCALE_STEP))), memo(() => toolButton("Zoom out", TOOL_GLYPHS.zoomOut, () => zoom(-.25)))];
2882
+ }
2883
+ }),
2884
+ memo(() => toolButton("Rotate 90 degrees", TOOL_GLYPHS.rotate, rotate)),
2885
+ memo(() => toolButton("Close", TOOL_GLYPHS.close, () => setOpen(false)))
2886
+ ];
2887
+ } }));
2888
+ return _el$12;
2889
+ })()];
2890
+ }
2891
+ });
2892
+ }
2893
+ })];
2894
+ } });
2895
+ }
2896
+ });
2897
+ }
2898
+ injectComponentStyle("image-viewer");
2899
+ //#endregion
2900
+ //#region src/components/input-group/index.tsx
2901
+ var _tmpl$$21 = /*#__PURE__*/ template(`<div>`);
2902
+ /**
2903
+ * Merged controls: attachments and the entry fused into one seal. The
2904
+ * Root draws the single hairline and carries the group's focus halo;
2905
+ * the Addon is a recessed cell for the reader's fixed words — a scheme,
2906
+ * a unit, a quiet button — placed before or after the entry. Put our
2907
+ * Input (or Textarea) inside and its own border and halo step aside in
2908
+ * favor of the group's; the stylesheet does the merging, the wrapper
2909
+ * adds no visuals of its own.
2910
+ */
2911
+ function InputGroupRoot(props) {
2912
+ return (() => {
2913
+ var _el$ = _tmpl$$21();
2914
+ spread(_el$, mergeProps(props, {
2915
+ "data-scope": "input-group",
2916
+ "data-part": "root"
2917
+ }), false, false);
2918
+ return _el$;
2919
+ })();
2920
+ }
2921
+ function InputGroupAddon(props) {
2922
+ return (() => {
2923
+ var _el$2 = _tmpl$$21();
2924
+ spread(_el$2, mergeProps(props, {
2925
+ "data-scope": "input-group",
2926
+ "data-part": "addon"
2927
+ }), false, false);
2928
+ return _el$2;
2929
+ })();
2930
+ }
2931
+ const InputGroup = Object.assign(InputGroupRoot, {
2932
+ Root: InputGroupRoot,
2933
+ Addon: InputGroupAddon
2934
+ });
2935
+ injectComponentStyle("input-group");
2936
+ //#endregion
1093
2937
  //#region src/components/json-tree-view/index.ts
1094
2938
  /** Ark's JsonTreeView, dressed in the paper-and-ink system: the tree-view
1095
2939
  * recipes re-scoped, with value nodes reading as tabular data. The API is
@@ -1098,10 +2942,10 @@ const JsonTreeView = JsonTreeView$1;
1098
2942
  injectComponentStyle("json-tree-view");
1099
2943
  //#endregion
1100
2944
  //#region src/components/kbd/index.tsx
1101
- var _tmpl$$9 = /*#__PURE__*/ template(`<kbd>`);
2945
+ var _tmpl$$20 = /*#__PURE__*/ template(`<kbd>`);
1102
2946
  function Kbd(props) {
1103
2947
  return (() => {
1104
- var _el$ = _tmpl$$9();
2948
+ var _el$ = _tmpl$$20();
1105
2949
  spread(_el$, mergeProps(props, {
1106
2950
  "data-scope": "kbd",
1107
2951
  "data-part": "root"
@@ -1111,15 +2955,204 @@ function Kbd(props) {
1111
2955
  }
1112
2956
  injectComponentStyle("kbd");
1113
2957
  //#endregion
2958
+ //#region src/components/layout/index.tsx
2959
+ var _tmpl$$19 = /*#__PURE__*/ template(`<div>`);
2960
+ var _tmpl$2$10 = /*#__PURE__*/ template(`<header>`);
2961
+ var _tmpl$3$7 = /*#__PURE__*/ template(`<main>`);
2962
+ var _tmpl$4$4 = /*#__PURE__*/ template(`<footer>`);
2963
+ var _tmpl$5$2 = /*#__PURE__*/ template(`<div data-scope=layout data-part=sider-resize role=separator aria-orientation=vertical tabindex=0 aria-label="Resize sidebar">`);
2964
+ var _tmpl$6$2 = /*#__PURE__*/ template(`<aside>`);
2965
+ const LayoutContext = createContext();
2966
+ /**
2967
+ * The application skeleton: Root, Header, Sider, Content, Footer —
2968
+ * the admin arrangement (Element Plus / AntD keep the same anatomy)
2969
+ * dressed in the paper-and-ink surfaces. The root is a full-height
2970
+ * grid; a declared `sider` turns the columns around to meet whichever
2971
+ * edge the rail stands on.
2972
+ */
2973
+ function LayoutRoot(props) {
2974
+ const [own, rest] = splitProps(props, ["sider"]);
2975
+ return createComponent(LayoutContext.Provider, {
2976
+ value: { siderPlacement: () => own.sider },
2977
+ get children() {
2978
+ var _el$ = _tmpl$$19();
2979
+ spread(_el$, mergeProps(rest, {
2980
+ "data-scope": "layout",
2981
+ "data-part": "root",
2982
+ get ["data-sider"]() {
2983
+ return own.sider;
2984
+ }
2985
+ }), false, false);
2986
+ return _el$;
2987
+ }
2988
+ });
2989
+ }
2990
+ function LayoutHeader(props) {
2991
+ return (() => {
2992
+ var _el$2 = _tmpl$2$10();
2993
+ spread(_el$2, mergeProps(props, {
2994
+ "data-scope": "layout",
2995
+ "data-part": "header"
2996
+ }), false, false);
2997
+ return _el$2;
2998
+ })();
2999
+ }
3000
+ function LayoutContent(props) {
3001
+ return (() => {
3002
+ var _el$3 = _tmpl$3$7();
3003
+ spread(_el$3, mergeProps(props, {
3004
+ "data-scope": "layout",
3005
+ "data-part": "content"
3006
+ }), false, false);
3007
+ return _el$3;
3008
+ })();
3009
+ }
3010
+ function LayoutFooter(props) {
3011
+ return (() => {
3012
+ var _el$4 = _tmpl$4$4();
3013
+ spread(_el$4, mergeProps(props, {
3014
+ "data-scope": "layout",
3015
+ "data-part": "footer"
3016
+ }), false, false);
3017
+ return _el$4;
3018
+ })();
3019
+ }
3020
+ /** One step of the arrow-key resize, in px. */
3021
+ const RESIZE_STEP = 16;
3022
+ function LayoutSider(props) {
3023
+ const [own, rest] = splitProps(props, [
3024
+ "collapsed",
3025
+ "width",
3026
+ "collapsedWidth",
3027
+ "resizable",
3028
+ "minWidth",
3029
+ "maxWidth",
3030
+ "onCollapsedChange",
3031
+ "onWidthChange",
3032
+ "style",
3033
+ "children"
3034
+ ]);
3035
+ const collapsed = () => own.collapsed ?? false;
3036
+ const [innerWidth, setInnerWidth] = createSignal(own.width ?? "16rem");
3037
+ const width = () => own.width ?? innerWidth();
3038
+ createEffect(() => {
3039
+ const next = own.width;
3040
+ if (next === void 0 || next === innerWidth()) return;
3041
+ setInnerWidth(next);
3042
+ own.onWidthChange?.(next);
3043
+ });
3044
+ let prevCollapsed = collapsed();
3045
+ createEffect(() => {
3046
+ const next = collapsed();
3047
+ if (next === prevCollapsed) return;
3048
+ prevCollapsed = next;
3049
+ own.onCollapsedChange?.(next);
3050
+ });
3051
+ const layout = useContext(LayoutContext);
3052
+ const [dragging, setDragging] = createSignal(false);
3053
+ let rail;
3054
+ let startPointerX = 0;
3055
+ let startWidth = 0;
3056
+ const railWidth = () => rail ? Math.round(rail.getBoundingClientRect().width) : 0;
3057
+ const onPointerDown = (event) => {
3058
+ setDragging(true);
3059
+ startPointerX = event.clientX;
3060
+ startWidth = railWidth();
3061
+ event.currentTarget.setPointerCapture(event.pointerId);
3062
+ };
3063
+ const onPointerMove = (event) => {
3064
+ if (!dragging()) return;
3065
+ const towardFlow = (layout?.siderPlacement() ?? "start") === "end" ? -1 : 1;
3066
+ const next = Math.round(startWidth + towardFlow * (event.clientX - startPointerX));
3067
+ setInnerWidth(`${next}px`);
3068
+ own.onWidthChange?.(`${next}px`);
3069
+ };
3070
+ const onPointerUp = (event) => {
3071
+ setDragging(false);
3072
+ event.currentTarget.releasePointerCapture(event.pointerId);
3073
+ };
3074
+ const onKeyDown = (event) => {
3075
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
3076
+ event.preventDefault();
3077
+ const widen = (layout?.siderPlacement() ?? "start") === "end" ? event.key === "ArrowLeft" : event.key === "ArrowRight";
3078
+ const next = railWidth() + (widen ? RESIZE_STEP : -16);
3079
+ setInnerWidth(`${next}px`);
3080
+ own.onWidthChange?.(`${next}px`);
3081
+ };
3082
+ const handle = () => own.resizable && !collapsed() ? (() => {
3083
+ var _el$5 = _tmpl$5$2();
3084
+ _el$5.$$keydown = onKeyDown;
3085
+ _el$5.$$pointerup = onPointerUp;
3086
+ _el$5.$$pointermove = onPointerMove;
3087
+ _el$5.$$pointerdown = onPointerDown;
3088
+ effect((_p$) => {
3089
+ var _v$ = dragging() ? "" : void 0, _v$2 = railWidth();
3090
+ _v$ !== _p$.e && setAttribute(_el$5, "data-dragging", _p$.e = _v$);
3091
+ _v$2 !== _p$.t && setAttribute(_el$5, "aria-valuenow", _p$.t = _v$2);
3092
+ return _p$;
3093
+ }, {
3094
+ e: void 0,
3095
+ t: void 0
3096
+ });
3097
+ return _el$5;
3098
+ })() : null;
3099
+ const foldedWidth = () => own.collapsedWidth ?? "3.5rem";
3100
+ return (() => {
3101
+ var _el$6 = _tmpl$6$2();
3102
+ use((el) => rail = el, _el$6);
3103
+ spread(_el$6, mergeProps(rest, {
3104
+ get style() {
3105
+ return {
3106
+ ...typeof own.style === "object" ? own.style : {},
3107
+ "--bs-layout-sider-width": collapsed() ? foldedWidth() : width(),
3108
+ "--bs-layout-sider-min": collapsed() ? foldedWidth() : own.minWidth ?? "12rem",
3109
+ "--bs-layout-sider-max": collapsed() ? foldedWidth() : own.maxWidth ?? "24rem"
3110
+ };
3111
+ },
3112
+ "data-scope": "layout",
3113
+ "data-part": "sider",
3114
+ get ["data-collapsed"]() {
3115
+ return collapsed() ? "" : void 0;
3116
+ },
3117
+ get ["data-dragging"]() {
3118
+ return dragging() ? "" : void 0;
3119
+ },
3120
+ get ["data-resizable"]() {
3121
+ return own.resizable ? "" : void 0;
3122
+ }
3123
+ }), false, true);
3124
+ insert(_el$6, (() => {
3125
+ var _c$ = memo(() => typeof own.children === "function");
3126
+ return () => _c$() ? own.children({ collapsed: collapsed() }) : own.children;
3127
+ })(), null);
3128
+ insert(_el$6, handle, null);
3129
+ return _el$6;
3130
+ })();
3131
+ }
3132
+ const Layout = Object.assign(LayoutRoot, {
3133
+ Root: LayoutRoot,
3134
+ Header: LayoutHeader,
3135
+ Sider: LayoutSider,
3136
+ Content: LayoutContent,
3137
+ Footer: LayoutFooter
3138
+ });
3139
+ injectComponentStyle("layout");
3140
+ delegateEvents([
3141
+ "pointerdown",
3142
+ "pointermove",
3143
+ "pointerup",
3144
+ "keydown"
3145
+ ]);
3146
+ //#endregion
1114
3147
  //#region src/components/link/index.tsx
1115
- var _tmpl$$8 = /*#__PURE__*/ template(`<a>`);
3148
+ var _tmpl$$18 = /*#__PURE__*/ template(`<a>`);
1116
3149
  /** A link is ink in the accent's voice: quiet at rest, deepening under
1117
3150
  * the hand, the halo at focus. The underline follows the prose —
1118
3151
  * always, on hover, or never. */
1119
3152
  function Link(props) {
1120
- const [own, rest] = splitProps$1(props, ["underline"]);
3153
+ const [own, rest] = splitProps(props, ["underline"]);
1121
3154
  return (() => {
1122
- var _el$ = _tmpl$$8();
3155
+ var _el$ = _tmpl$$18();
1123
3156
  spread(_el$, mergeProps(rest, {
1124
3157
  "data-scope": "link",
1125
3158
  "data-part": "root",
@@ -1132,6 +3165,94 @@ function Link(props) {
1132
3165
  }
1133
3166
  injectComponentStyle("link");
1134
3167
  //#endregion
3168
+ //#region src/components/list/index.tsx
3169
+ var _tmpl$$17 = /*#__PURE__*/ template(`<ul>`);
3170
+ var _tmpl$2$9 = /*#__PURE__*/ template(`<div data-scope=list data-part=title>`);
3171
+ var _tmpl$3$6 = /*#__PURE__*/ template(`<div data-scope=list data-part=description>`);
3172
+ var _tmpl$4$3 = /*#__PURE__*/ template(`<div>`);
3173
+ /** A ledger of rows: Root is the list, Item one row, Leading the mark
3174
+ * before the words, Content the title and its quiet echo, Actions the
3175
+ * way out. The bordered variant draws the hairlines; the hoverable
3176
+ * variant gives every row the wash — and any row the caller makes
3177
+ * clickable (role="button") answers the pointer on its own. */
3178
+ function part$5(name, tag) {
3179
+ function Component(props) {
3180
+ return createComponent(tag, mergeProps(props, {
3181
+ "data-scope": "list",
3182
+ get ["data-part"]() {
3183
+ return name.toLowerCase();
3184
+ }
3185
+ }));
3186
+ }
3187
+ return Component;
3188
+ }
3189
+ const Item$1 = part$5("Item", "li");
3190
+ const Leading = part$5("Leading", "div");
3191
+ const Actions$1 = part$5("Actions", "div");
3192
+ function Root$4(props) {
3193
+ const [own, rest] = splitProps(props, ["bordered", "hoverable"]);
3194
+ return (() => {
3195
+ var _el$ = _tmpl$$17();
3196
+ spread(_el$, mergeProps(rest, {
3197
+ "data-scope": "list",
3198
+ "data-part": "root",
3199
+ get ["data-bordered"]() {
3200
+ return own.bordered || void 0;
3201
+ },
3202
+ get ["data-hoverable"]() {
3203
+ return own.hoverable || void 0;
3204
+ }
3205
+ }), false, false);
3206
+ return _el$;
3207
+ })();
3208
+ }
3209
+ /** The row's words: `title` and `description` ride their own named
3210
+ * parts, the children follow them for anything else. */
3211
+ function Content$1(props) {
3212
+ const [own, rest] = splitProps(props, [
3213
+ "title",
3214
+ "description",
3215
+ "children"
3216
+ ]);
3217
+ return (() => {
3218
+ var _el$2 = _tmpl$4$3();
3219
+ spread(_el$2, mergeProps(rest, {
3220
+ "data-scope": "list",
3221
+ "data-part": "content"
3222
+ }), false, true);
3223
+ insert(_el$2, createComponent(Show, {
3224
+ get when() {
3225
+ return own.title;
3226
+ },
3227
+ get children() {
3228
+ var _el$3 = _tmpl$2$9();
3229
+ insert(_el$3, () => own.title);
3230
+ return _el$3;
3231
+ }
3232
+ }), null);
3233
+ insert(_el$2, createComponent(Show, {
3234
+ get when() {
3235
+ return own.description;
3236
+ },
3237
+ get children() {
3238
+ var _el$4 = _tmpl$3$6();
3239
+ insert(_el$4, () => own.description);
3240
+ return _el$4;
3241
+ }
3242
+ }), null);
3243
+ insert(_el$2, () => own.children, null);
3244
+ return _el$2;
3245
+ })();
3246
+ }
3247
+ const List = Object.assign(Root$4, {
3248
+ Root: Root$4,
3249
+ Item: Item$1,
3250
+ Leading,
3251
+ Content: Content$1,
3252
+ Actions: Actions$1
3253
+ });
3254
+ injectComponentStyle("list");
3255
+ //#endregion
1135
3256
  //#region src/components/listbox/index.ts
1136
3257
  /** Ark's Listbox, dressed in the paper-and-ink system: quiet rows of ink
1137
3258
  * where the checked row alone takes the flat primary fill. The API is
@@ -1148,6 +3269,38 @@ injectComponentStyle("listbox");
1148
3269
  const Marquee = Marquee$1;
1149
3270
  injectComponentStyle("marquee");
1150
3271
  //#endregion
3272
+ //#region src/components/masonry/index.tsx
3273
+ var _tmpl$$16 = /*#__PURE__*/ template(`<div>`);
3274
+ /** The same named steps of the space ramp the stack uses — one
3275
+ * vocabulary of distance across the layout primitives. */
3276
+ const gapVars$1 = {
3277
+ none: "0",
3278
+ xs: "var(--bs-gap-xs)",
3279
+ sm: "var(--bs-gap-sm)",
3280
+ md: "var(--bs-gap-md)",
3281
+ lg: "var(--bs-gap-lg)",
3282
+ xl: "var(--bs-gap-xl)"
3283
+ };
3284
+ function Masonry(props) {
3285
+ const [own, rest] = splitProps(props, ["columns", "gap"]);
3286
+ return (() => {
3287
+ var _el$ = _tmpl$$16();
3288
+ spread(_el$, mergeProps(rest, {
3289
+ get style() {
3290
+ return {
3291
+ ...rest.style,
3292
+ "--bs-masonry-columns": String(own.columns ?? 3),
3293
+ "--bs-masonry-gap": gapVars$1[own.gap ?? "md"] ?? gapVars$1.md
3294
+ };
3295
+ },
3296
+ "data-scope": "masonry",
3297
+ "data-part": "root"
3298
+ }), false, false);
3299
+ return _el$;
3300
+ })();
3301
+ }
3302
+ injectComponentStyle("masonry");
3303
+ //#endregion
1151
3304
  //#region src/components/menu/index.ts
1152
3305
  /** Ark's Menu, dressed in the paper-and-ink system: a quiet paper vessel on
1153
3306
  * elevation, hover as light on the row, checked items as the flat ink fill.
@@ -1157,37 +3310,382 @@ injectComponentStyle("marquee");
1157
3310
  const Menu = Menu$1;
1158
3311
  injectComponentStyle("menu");
1159
3312
  //#endregion
3313
+ //#region src/components/menubar/index.tsx
3314
+ var _tmpl$$15 = /*#__PURE__*/ template(`<div>`);
3315
+ var _tmpl$2$8 = /*#__PURE__*/ template(`<button>`);
3316
+ /**
3317
+ * A desktop-style menu bar: a row of quiet ghost triggers, each opening
3318
+ * the same paper vessel as the menu family. The triggers are our own
3319
+ * buttons grafted onto the menu machine's trigger via `asChild` — the
3320
+ * machine keeps the trigger element (positioning, focus restore,
3321
+ * `data-state`) while the element wears the menubar scope. The popups
3322
+ * keep the menu parts untouched, so the menu stylesheet dresses them.
3323
+ *
3324
+ * Keyboard note: the triggers move between each other with Tab, not
3325
+ * arrow keys — cross-menu arrow traversal is out of scope for this
3326
+ * version. Inside an open menu the machine handles arrows and Escape.
3327
+ */
3328
+ function Menubar(props) {
3329
+ const [own, rest] = splitProps(props, ["items", "onSelect"]);
3330
+ return (() => {
3331
+ var _el$ = _tmpl$$15();
3332
+ spread(_el$, mergeProps(rest, {
3333
+ "data-scope": "menubar",
3334
+ "data-part": "root",
3335
+ "role": "menubar"
3336
+ }), false, true);
3337
+ insert(_el$, createComponent(For, {
3338
+ get each() {
3339
+ return own.items ?? [];
3340
+ },
3341
+ children: (group) => createComponent(Menu$1.Root, {
3342
+ positioning: { placement: "bottom-start" },
3343
+ get children() {
3344
+ return [createComponent(Menu$1.Trigger, { asChild: (triggerProps) => (() => {
3345
+ var _el$2 = _tmpl$2$8();
3346
+ spread(_el$2, mergeProps(triggerProps, {
3347
+ "type": "button",
3348
+ "data-scope": "menubar",
3349
+ "data-part": "trigger"
3350
+ }), false, true);
3351
+ insert(_el$2, () => group.label);
3352
+ return _el$2;
3353
+ })() }), createComponent(Portal, { get children() {
3354
+ return createComponent(Menu$1.Positioner, { get children() {
3355
+ return createComponent(Menu$1.Content, { get children() {
3356
+ return createComponent(For, {
3357
+ get each() {
3358
+ return group.items;
3359
+ },
3360
+ children: (entry) => createComponent(Menu$1.Item, {
3361
+ get value() {
3362
+ return entry.value;
3363
+ },
3364
+ get disabled() {
3365
+ return entry.disabled;
3366
+ },
3367
+ get ["data-danger"]() {
3368
+ return entry.danger ? "" : void 0;
3369
+ },
3370
+ onSelect: () => own.onSelect?.(entry.value),
3371
+ get children() {
3372
+ return createComponent(Menu$1.ItemText, { get children() {
3373
+ return entry.label;
3374
+ } });
3375
+ }
3376
+ })
3377
+ });
3378
+ } });
3379
+ } });
3380
+ } })];
3381
+ }
3382
+ })
3383
+ }));
3384
+ return _el$;
3385
+ })();
3386
+ }
3387
+ injectComponentStyle("menubar");
3388
+ injectComponentStyle("menu");
3389
+ //#endregion
3390
+ //#region src/components/textarea/index.tsx
3391
+ var _tmpl$$14 = /*#__PURE__*/ template(`<textarea>`);
3392
+ /** The bare multi-line input: the field recipe on a `<textarea>`, sized
3393
+ * by rows and resizable in the block direction. Standing alone it styles
3394
+ * itself from the `invalid` prop; inside a `Field.Root` it consumes the
3395
+ * field context, picking up the label id, the described-by wiring and
3396
+ * the invalid state for free. Disabled rides the native attribute. */
3397
+ function Textarea(props) {
3398
+ const field = useFieldContext();
3399
+ const [own, rest] = splitProps(props, [
3400
+ "value",
3401
+ "invalid",
3402
+ "onValueChange"
3403
+ ]);
3404
+ return (() => {
3405
+ var _el$ = _tmpl$$14();
3406
+ spread(_el$, mergeProps(() => mergeProps$1(() => field?.().getTextareaProps() ?? {}, rest, {
3407
+ get value() {
3408
+ return own.value;
3409
+ },
3410
+ "data-scope": "textarea",
3411
+ "data-part": "root",
3412
+ get "data-invalid"() {
3413
+ return own.invalid || field?.().getTextareaProps()["data-invalid"] != null ? "" : void 0;
3414
+ },
3415
+ onInput: (event) => own.onValueChange?.(event.currentTarget.value)
3416
+ })), false, false);
3417
+ return _el$;
3418
+ })();
3419
+ }
3420
+ injectComponentStyle("textarea");
3421
+ //#endregion
3422
+ //#region src/components/mentions/use-mentions.ts
3423
+ /** The @-detection machinery behind a mention field: watch the caret,
3424
+ * offer the matching candidates, and answer for the keys that drive
3425
+ * them. The field element arrives as an accessor because hosts wrap it
3426
+ * differently (a bare textarea, a field's own part).
3427
+ *
3428
+ * `onKeydown` answers whether the vessel consumed the key, so a host
3429
+ * with its own Enter semantics — a composer that sends — can yield to
3430
+ * the candidates first and act only when the vessel stands down. */
3431
+ function useMentions(options, textarea, handlers) {
3432
+ const [popupOpen, setPopupOpen] = createSignal(false);
3433
+ const [matches, setMatches] = createSignal([]);
3434
+ const [active, setActive] = createSignal(0);
3435
+ const [anchorIndex, setAnchorIndex] = createSignal(0);
3436
+ const [caretIndex, setCaretIndex] = createSignal(0);
3437
+ const closePopup = () => {
3438
+ setPopupOpen(false);
3439
+ setMatches([]);
3440
+ };
3441
+ const detect = () => {
3442
+ const text = handlers.getText();
3443
+ const caret = textarea()?.selectionStart ?? text.length;
3444
+ setCaretIndex(caret);
3445
+ const head = text.slice(0, caret);
3446
+ const char = options().trigger ?? "@";
3447
+ const anchor = head.lastIndexOf(char);
3448
+ const token = anchor === -1 ? "" : head.slice(anchor + char.length);
3449
+ if (anchor === -1 || /\s/.test(token)) {
3450
+ closePopup();
3451
+ return;
3452
+ }
3453
+ const found = options().items.filter((entry) => entry.label.toLowerCase().startsWith(token.toLowerCase()));
3454
+ setMatches(found);
3455
+ setActive(0);
3456
+ setAnchorIndex(anchor);
3457
+ setPopupOpen(found.length > 0);
3458
+ };
3459
+ const insert = (entry) => {
3460
+ const text = handlers.getText();
3461
+ const char = options().trigger ?? "@";
3462
+ const next = text.slice(0, anchorIndex()) + char + entry.label + " " + text.slice(caretIndex());
3463
+ handlers.setText(next);
3464
+ closePopup();
3465
+ queueMicrotask(() => {
3466
+ const el = textarea();
3467
+ if (!el) return;
3468
+ const caret = anchorIndex() + char.length + entry.label.length + 1;
3469
+ el.focus();
3470
+ el.setSelectionRange(caret, caret);
3471
+ });
3472
+ };
3473
+ /** Feed the field's input events through here — the vessel watches
3474
+ * the text as it lands, from the element itself. */
3475
+ const onInput = () => detect();
3476
+ /** Arrows move, Enter inserts, Escape dismisses. Answers `true` when
3477
+ * the vessel consumed the key. */
3478
+ const onKeydown = (event) => {
3479
+ if (!popupOpen() || matches().length === 0) return false;
3480
+ if (event.key === "ArrowDown") {
3481
+ event.preventDefault();
3482
+ setActive((active() + 1) % matches().length);
3483
+ } else if (event.key === "ArrowUp") {
3484
+ event.preventDefault();
3485
+ setActive((active() - 1 + matches().length) % matches().length);
3486
+ } else if (event.key === "Enter") {
3487
+ event.preventDefault();
3488
+ insert(matches()[active()]);
3489
+ } else if (event.key === "Escape") closePopup();
3490
+ else return false;
3491
+ return true;
3492
+ };
3493
+ return {
3494
+ open: popupOpen,
3495
+ matches,
3496
+ active,
3497
+ setActive,
3498
+ insert,
3499
+ close: closePopup,
3500
+ onInput,
3501
+ onKeydown
3502
+ };
3503
+ }
3504
+ //#endregion
3505
+ //#region src/components/mentions/index.tsx
3506
+ var _tmpl$$13 = /*#__PURE__*/ template(`<div>`);
3507
+ var _tmpl$2$7 = /*#__PURE__*/ template(`<div data-scope=mentions data-part=option>`);
3508
+ /** The vessel: the candidates themselves as a floating card. The anchor
3509
+ * is virtual — a live rectangle off the host's field — so a host keeps
3510
+ * its own anatomy (the textarea rides where the host puts it) and the
3511
+ * vessel still points at the right place. Shares the detection state
3512
+ * with the host through `useMentions`. */
3513
+ function MentionsVessel(props) {
3514
+ return createComponent(Popover$1.Root, {
3515
+ get open() {
3516
+ return props.open ?? false;
3517
+ },
3518
+ onOpenChange: (details) => props.onOpenChange?.(details.open),
3519
+ positioning: {
3520
+ placement: "bottom-start",
3521
+ getAnchorRect: () => props.anchor?.getBoundingClientRect() ?? null
3522
+ },
3523
+ get children() {
3524
+ return createComponent(Portal, { get children() {
3525
+ return createComponent(Popover$1.Positioner, { get children() {
3526
+ return createComponent(Popover$1.Content, { asChild: (contentProps) => (() => {
3527
+ var _el$ = _tmpl$$13();
3528
+ spread(_el$, mergeProps(contentProps, {
3529
+ "data-scope": "mentions",
3530
+ "data-part": "popup"
3531
+ }), false, true);
3532
+ insert(_el$, createComponent(For, {
3533
+ get each() {
3534
+ return props.matches ?? [];
3535
+ },
3536
+ children: (entry, index) => (() => {
3537
+ var _el$2 = _tmpl$2$7();
3538
+ _el$2.$$click = () => props.onInsert?.(entry);
3539
+ _el$2.$$mousedown = (event) => event.preventDefault();
3540
+ _el$2.addEventListener("mouseenter", () => props.onActiveChange?.(index()));
3541
+ insert(_el$2, () => entry.label);
3542
+ effect(() => setAttribute(_el$2, "data-active", index() === (props.active ?? 0) ? "" : void 0));
3543
+ return _el$2;
3544
+ })()
3545
+ }));
3546
+ return _el$;
3547
+ })() });
3548
+ } });
3549
+ } });
3550
+ }
3551
+ });
3552
+ }
3553
+ /**
3554
+ * @-mentions: a plain textarea that, when the text before the caret ends
3555
+ * with the trigger character followed by a token, offers the matching
3556
+ * candidates in a small anchored vessel; choosing one replaces the token
3557
+ * with `trigger + label` and hands the whole text back through
3558
+ * `onValueChange`. Arrows move, Enter inserts, Escape dismisses.
3559
+ *
3560
+ * The field is the shared `Textarea` — field wiring (label ids, the
3561
+ * invalid state) rides on it for free — and the vessel anchors to the
3562
+ * field as a whole (popover machinery), not to the caret coordinates;
3563
+ * caret-precise positioning would need a second positioning system for
3564
+ * no practical gain at typical field sizes. Composers that keep their
3565
+ * own field anatomy (the AI prompt input) skip this shell and wire
3566
+ * `useMentions` plus `MentionsVessel` themselves.
3567
+ */
3568
+ function Mentions(props) {
3569
+ const [own, rest] = splitProps(props, [
3570
+ "items",
3571
+ "value",
3572
+ "trigger",
3573
+ "placeholder",
3574
+ "autoresize",
3575
+ "invalid",
3576
+ "onValueChange"
3577
+ ]);
3578
+ const [internal, setInternal] = createSignal("");
3579
+ const [fieldEl, setFieldEl] = createSignal(null);
3580
+ const value = () => own.value ?? internal();
3581
+ const mentions = useMentions(() => ({
3582
+ items: own.items ?? [],
3583
+ trigger: own.trigger
3584
+ }), fieldEl, {
3585
+ getText: () => fieldEl()?.value ?? value(),
3586
+ setText: (next) => {
3587
+ setInternal(next);
3588
+ own.onValueChange?.(next);
3589
+ }
3590
+ });
3591
+ createEffect(() => {
3592
+ value();
3593
+ const node = fieldEl();
3594
+ if (!node || !(own.autoresize ?? false)) return;
3595
+ node.style.height = "auto";
3596
+ node.style.height = `${node.scrollHeight}px`;
3597
+ });
3598
+ const onInput = () => {
3599
+ const node = fieldEl();
3600
+ if (!node) return;
3601
+ setInternal(node.value);
3602
+ own.onValueChange?.(node.value);
3603
+ mentions.onInput();
3604
+ };
3605
+ return (() => {
3606
+ var _el$3 = _tmpl$$13();
3607
+ spread(_el$3, mergeProps(rest, {
3608
+ "data-scope": "mentions",
3609
+ "data-part": "root"
3610
+ }), false, true);
3611
+ insert(_el$3, createComponent(Textarea, {
3612
+ ref: (node) => setFieldEl(node),
3613
+ get invalid() {
3614
+ return own.invalid;
3615
+ },
3616
+ rows: 3,
3617
+ get placeholder() {
3618
+ return own.placeholder;
3619
+ },
3620
+ get value() {
3621
+ return value();
3622
+ },
3623
+ onValueChange: (next) => {
3624
+ setInternal(next);
3625
+ own.onValueChange?.(next);
3626
+ },
3627
+ onInput,
3628
+ onKeyDown: (event) => {
3629
+ mentions.onKeydown(event);
3630
+ },
3631
+ "data-scope": "mentions",
3632
+ "data-part": "textarea"
3633
+ }), null);
3634
+ insert(_el$3, createComponent(MentionsVessel, {
3635
+ get open() {
3636
+ return mentions.open();
3637
+ },
3638
+ get matches() {
3639
+ return mentions.matches();
3640
+ },
3641
+ get active() {
3642
+ return mentions.active();
3643
+ },
3644
+ get anchor() {
3645
+ return fieldEl();
3646
+ },
3647
+ get onInsert() {
3648
+ return mentions.insert;
3649
+ },
3650
+ get onActiveChange() {
3651
+ return mentions.setActive;
3652
+ },
3653
+ onOpenChange: (open) => {
3654
+ if (!open) mentions.close();
3655
+ }
3656
+ }), null);
3657
+ return _el$3;
3658
+ })();
3659
+ }
3660
+ injectComponentStyle("mentions");
3661
+ delegateEvents(["mousedown", "click"]);
3662
+ //#endregion
1160
3663
  //#region src/components/meter/index.tsx
1161
- var _tmpl$$7 = /*#__PURE__*/ template(`<tag>`);
1162
- var _tmpl$2$2 = /*#__PURE__*/ template(`<span><span data-scope=meter data-part=range>`);
1163
- var _tmpl$3$1 = /*#__PURE__*/ template(`<div>`);
3664
+ var _tmpl$$12 = /*#__PURE__*/ template(`<span><span data-scope=meter data-part=range>`);
3665
+ var _tmpl$2$6 = /*#__PURE__*/ template(`<div>`);
1164
3666
  function part$4(name, tag) {
1165
3667
  function Component(props) {
1166
- return (() => {
1167
- var _el$ = _tmpl$$7();
1168
- spread(_el$, mergeProps(props, {
1169
- "data-scope": "meter",
1170
- get ["data-part"]() {
1171
- return name.toLowerCase();
1172
- }
1173
- }), false, false);
1174
- return _el$;
1175
- })();
3668
+ return createComponent(tag, mergeProps(props, {
3669
+ "data-scope": "meter",
3670
+ get ["data-part"]() {
3671
+ return name.toLowerCase();
3672
+ }
3673
+ }));
1176
3674
  }
1177
3675
  return Component;
1178
3676
  }
1179
3677
  const Label$2 = part$4("Label", "span");
1180
3678
  const ValueText = part$4("ValueText", "span");
1181
3679
  const Track = (props) => (() => {
1182
- var _el$2 = _tmpl$2$2();
1183
- spread(_el$2, mergeProps(props, {
3680
+ var _el$ = _tmpl$$12();
3681
+ spread(_el$, mergeProps(props, {
1184
3682
  "data-scope": "meter",
1185
3683
  "data-part": "track"
1186
3684
  }), false, true);
1187
- return _el$2;
3685
+ return _el$;
1188
3686
  })();
1189
3687
  function Root$3(props) {
1190
- const [own, rest] = splitProps$1(props, [
3688
+ const [own, rest] = splitProps(props, [
1191
3689
  "value",
1192
3690
  "min",
1193
3691
  "max",
@@ -1202,8 +3700,8 @@ function Root$3(props) {
1202
3700
  };
1203
3701
  const level = () => own.level ?? "normal";
1204
3702
  return (() => {
1205
- var _el$3 = _tmpl$3$1();
1206
- spread(_el$3, mergeProps(rest, {
3703
+ var _el$2 = _tmpl$2$6();
3704
+ spread(_el$2, mergeProps(rest, {
1207
3705
  "role": "meter",
1208
3706
  get ["aria-valuemin"]() {
1209
3707
  return min();
@@ -1229,7 +3727,7 @@ function Root$3(props) {
1229
3727
  };
1230
3728
  }
1231
3729
  }), false, true);
1232
- insert(_el$3, () => rest.children ?? [
3730
+ insert(_el$2, () => rest.children ?? [
1233
3731
  createComponent(Label$2, { get children() {
1234
3732
  return own.label;
1235
3733
  } }),
@@ -1238,7 +3736,7 @@ function Root$3(props) {
1238
3736
  } }),
1239
3737
  createComponent(Track, {})
1240
3738
  ]);
1241
- return _el$3;
3739
+ return _el$2;
1242
3740
  })();
1243
3741
  }
1244
3742
  const Meter = Object.assign(Root$3, {
@@ -1266,22 +3764,17 @@ const NumberInput = NumberInput$1;
1266
3764
  injectComponentStyle("number-input");
1267
3765
  //#endregion
1268
3766
  //#region src/components/page-header/index.tsx
1269
- var _tmpl$$6 = /*#__PURE__*/ template(`<tag>`);
1270
3767
  /** The page's face: an eyebrow whisper, a serif title, one line of
1271
3768
  * description, and the actions resting beside the title on the same
1272
3769
  * baseline. Heading groups title and actions; the rest compose below. */
1273
3770
  function part$3(name, tag, extra = {}) {
1274
3771
  function Component(props) {
1275
- return (() => {
1276
- var _el$ = _tmpl$$6();
1277
- spread(_el$, mergeProps(extra, props, {
1278
- "data-scope": "page-header",
1279
- get ["data-part"]() {
1280
- return name.toLowerCase();
1281
- }
1282
- }), false, false);
1283
- return _el$;
1284
- })();
3772
+ return createComponent(tag, mergeProps(extra, props, {
3773
+ "data-scope": "page-header",
3774
+ get ["data-part"]() {
3775
+ return name.toLowerCase();
3776
+ }
3777
+ }));
1285
3778
  }
1286
3779
  return Component;
1287
3780
  }
@@ -1326,6 +3819,78 @@ injectComponentStyle("password-input");
1326
3819
  const PinInput = PinInput$1;
1327
3820
  injectComponentStyle("pin-input");
1328
3821
  //#endregion
3822
+ //#region src/components/popconfirm/index.tsx
3823
+ var _tmpl$$11 = /*#__PURE__*/ template(`<p data-part=message>`);
3824
+ var _tmpl$2$5 = /*#__PURE__*/ template(`<div data-part=actions>`);
3825
+ var _tmpl$3$5 = /*#__PURE__*/ template(`<button>`);
3826
+ /** A question at the point of no return: the trigger opens a small
3827
+ * anchored vessel carrying the message and two answers. Confirmation
3828
+ * and cancellation are the caller's to act on — the panel closes
3829
+ * either way. The children are the trigger's content, riding the
3830
+ * machine-driven trigger button. */
3831
+ function Popconfirm(props) {
3832
+ const [own, rest] = splitProps(props, [
3833
+ "message",
3834
+ "confirmText",
3835
+ "cancelText",
3836
+ "onConfirm",
3837
+ "onCancel",
3838
+ "children"
3839
+ ]);
3840
+ const [open, setOpen] = createSignal(false);
3841
+ function settle(confirmed) {
3842
+ setOpen(false);
3843
+ (confirmed ? own.onConfirm : own.onCancel)?.();
3844
+ }
3845
+ return createComponent(Popover$1.Root, {
3846
+ get open() {
3847
+ return open();
3848
+ },
3849
+ onOpenChange: (details) => setOpen(details.open),
3850
+ positioning: { placement: "top" },
3851
+ get children() {
3852
+ return [createComponent(Popover$1.Trigger, { asChild: (propsFn) => (() => {
3853
+ var _el$3 = _tmpl$3$5();
3854
+ spread(_el$3, mergeProps(propsFn, rest), false, true);
3855
+ insert(_el$3, () => own.children);
3856
+ return _el$3;
3857
+ })() }), createComponent(Portal, { get children() {
3858
+ return createComponent(Popover$1.Positioner, { get children() {
3859
+ return createComponent(Popover$1.Content, {
3860
+ "class": "bs-popconfirm",
3861
+ get children() {
3862
+ return [(() => {
3863
+ var _el$ = _tmpl$$11();
3864
+ insert(_el$, () => own.message);
3865
+ return _el$;
3866
+ })(), (() => {
3867
+ var _el$2 = _tmpl$2$5();
3868
+ insert(_el$2, createComponent(Button, {
3869
+ variant: "ghost",
3870
+ size: "sm",
3871
+ onClick: () => settle(false),
3872
+ get children() {
3873
+ return own.cancelText ?? "Cancel";
3874
+ }
3875
+ }), null);
3876
+ insert(_el$2, createComponent(Button, {
3877
+ size: "sm",
3878
+ onClick: () => settle(true),
3879
+ get children() {
3880
+ return own.confirmText ?? "Confirm";
3881
+ }
3882
+ }), null);
3883
+ return _el$2;
3884
+ })()];
3885
+ }
3886
+ });
3887
+ } });
3888
+ } })];
3889
+ }
3890
+ });
3891
+ }
3892
+ injectComponentStyle("popconfirm");
3893
+ //#endregion
1329
3894
  //#region src/components/popover/index.ts
1330
3895
  /** Ark's Popover, dressed in the paper-and-ink system: a paper vessel that
1331
3896
  * dissolves in on elevation, anchored to its trigger by a whisker arrow. The
@@ -1342,6 +3907,79 @@ injectComponentStyle("popover");
1342
3907
  const Progress = Progress$1;
1343
3908
  injectComponentStyle("progress");
1344
3909
  //#endregion
3910
+ //#region src/components/progress-group/index.tsx
3911
+ var _tmpl$$10 = /*#__PURE__*/ template(`<div data-scope=progress-group data-part=legend>`);
3912
+ var _tmpl$2$4 = /*#__PURE__*/ template(`<div><div data-scope=progress-group data-part=track>`);
3913
+ var _tmpl$3$4 = /*#__PURE__*/ template(`<div data-scope=progress-group data-part=segment role=progressbar aria-valuemin=0>`);
3914
+ var _tmpl$4$2 = /*#__PURE__*/ template(`<div data-scope=progress-group data-part=legend-item><span data-scope=progress-group data-part=swatch aria-hidden=true></span><span data-scope=progress-group data-part=legend-label></span><span data-scope=progress-group data-part=legend-value>`);
3915
+ function ProgressGroup(props) {
3916
+ const [own, rest] = splitProps(props, [
3917
+ "segments",
3918
+ "max",
3919
+ "showLegend"
3920
+ ]);
3921
+ const total = () => own.max ?? own.segments.reduce((sum, segment) => sum + segment.value, 0);
3922
+ const share = (value) => {
3923
+ const whole = total();
3924
+ return whole > 0 ? `${value / whole * 100}%` : "0%";
3925
+ };
3926
+ const nameOf = (segment, index) => segment.label ?? segment.pigment ?? `Segment ${index + 1}`;
3927
+ return (() => {
3928
+ var _el$ = _tmpl$2$4(), _el$2 = _el$.firstChild;
3929
+ spread(_el$, mergeProps(rest, {
3930
+ "data-scope": "progress-group",
3931
+ "data-part": "root"
3932
+ }), false, true);
3933
+ insert(_el$2, createComponent(For, {
3934
+ get each() {
3935
+ return own.segments;
3936
+ },
3937
+ children: (segment, index) => (() => {
3938
+ var _el$4 = _tmpl$3$4();
3939
+ effect((_p$) => {
3940
+ var _v$ = segment.pigment, _v$2 = segment.value, _v$3 = total(), _v$4 = nameOf(segment, index()), _v$5 = share(segment.value);
3941
+ _v$ !== _p$.e && setAttribute(_el$4, "data-pigment", _p$.e = _v$);
3942
+ _v$2 !== _p$.t && setAttribute(_el$4, "aria-valuenow", _p$.t = _v$2);
3943
+ _v$3 !== _p$.a && setAttribute(_el$4, "aria-valuemax", _p$.a = _v$3);
3944
+ _v$4 !== _p$.o && setAttribute(_el$4, "aria-label", _p$.o = _v$4);
3945
+ _v$5 !== _p$.i && setStyleProperty(_el$4, "inline-size", _p$.i = _v$5);
3946
+ return _p$;
3947
+ }, {
3948
+ e: void 0,
3949
+ t: void 0,
3950
+ a: void 0,
3951
+ o: void 0,
3952
+ i: void 0
3953
+ });
3954
+ return _el$4;
3955
+ })()
3956
+ }));
3957
+ insert(_el$, createComponent(Show, {
3958
+ get when() {
3959
+ return own.showLegend ?? true;
3960
+ },
3961
+ get children() {
3962
+ var _el$3 = _tmpl$$10();
3963
+ insert(_el$3, createComponent(For, {
3964
+ get each() {
3965
+ return own.segments;
3966
+ },
3967
+ children: (segment, index) => (() => {
3968
+ var _el$5 = _tmpl$4$2(), _el$7 = _el$5.firstChild.nextSibling, _el$8 = _el$7.nextSibling;
3969
+ insert(_el$7, () => nameOf(segment, index()));
3970
+ insert(_el$8, () => String(segment.value));
3971
+ effect(() => setAttribute(_el$5, "data-pigment", segment.pigment));
3972
+ return _el$5;
3973
+ })()
3974
+ }));
3975
+ return _el$3;
3976
+ }
3977
+ }), null);
3978
+ return _el$;
3979
+ })();
3980
+ }
3981
+ injectComponentStyle("progress-group");
3982
+ //#endregion
1345
3983
  //#region src/components/qr-code/index.ts
1346
3984
  /** Ark's QrCode, dressed in the paper-and-ink system: the pattern prints in
1347
3985
  * ink on the page, with an optional paper badge and a seal-cut download
@@ -1391,12 +4029,12 @@ const Select = Select$1;
1391
4029
  injectComponentStyle("select");
1392
4030
  //#endregion
1393
4031
  //#region src/components/separator/index.tsx
1394
- var _tmpl$$5 = /*#__PURE__*/ template(`<div>`);
4032
+ var _tmpl$$9 = /*#__PURE__*/ template(`<div>`);
1395
4033
  function Separator(props) {
1396
- const [own, rest] = splitProps$1(props, ["orientation", "decorative"]);
4034
+ const [own, rest] = splitProps(props, ["orientation", "decorative"]);
1397
4035
  const orientation = () => own.orientation ?? "horizontal";
1398
4036
  return (() => {
1399
- var _el$ = _tmpl$$5();
4037
+ var _el$ = _tmpl$$9();
1400
4038
  spread(_el$, mergeProps(rest, {
1401
4039
  get role() {
1402
4040
  return own.decorative ? "none" : "separator";
@@ -1424,10 +4062,10 @@ const SignaturePad = SignaturePad$1;
1424
4062
  injectComponentStyle("signature-pad");
1425
4063
  //#endregion
1426
4064
  //#region src/components/skeleton/index.tsx
1427
- var _tmpl$$4 = /*#__PURE__*/ template(`<div>`);
4065
+ var _tmpl$$8 = /*#__PURE__*/ template(`<div>`);
1428
4066
  function Skeleton(props) {
1429
4067
  return (() => {
1430
- var _el$ = _tmpl$$4();
4068
+ var _el$ = _tmpl$$8();
1431
4069
  spread(_el$, mergeProps(props, {
1432
4070
  "data-scope": "skeleton",
1433
4071
  "data-part": "root"
@@ -1446,13 +4084,13 @@ const Slider = Slider$1;
1446
4084
  injectComponentStyle("slider");
1447
4085
  //#endregion
1448
4086
  //#region src/components/spinner/index.tsx
1449
- var _tmpl$$3 = /*#__PURE__*/ template(`<span><svg viewBox="0 0 24 24"fill=none aria-hidden=true><circle cx=12 cy=12 r=9 stroke=currentColor stroke-opacity=0.2 stroke-width=2.5></circle><path d="M21 12a9 9 0 0 0-9-9"stroke=currentColor stroke-width=2.5 stroke-linecap=round>`);
4087
+ var _tmpl$$7 = /*#__PURE__*/ template(`<span><svg viewBox="0 0 24 24"fill=none aria-hidden=true><circle cx=12 cy=12 r=9 stroke=currentColor stroke-opacity=0.2 stroke-width=2.5></circle><path d="M21 12a9 9 0 0 0-9-9"stroke=currentColor stroke-width=2.5 stroke-linecap=round>`);
1450
4088
  /** A wheel of waiting: one arc of ink turning about its center. Quiet by
1451
4089
  * default — it reports progress without claiming attention. */
1452
4090
  function Spinner(props) {
1453
- const [own, rest] = splitProps$1(props, ["size"]);
4091
+ const [own, rest] = splitProps(props, ["size"]);
1454
4092
  return (() => {
1455
- var _el$ = _tmpl$$3();
4093
+ var _el$ = _tmpl$$7();
1456
4094
  spread(_el$, mergeProps(rest, {
1457
4095
  "role": "status",
1458
4096
  get ["aria-label"]() {
@@ -1469,6 +4107,123 @@ function Spinner(props) {
1469
4107
  }
1470
4108
  injectComponentStyle("spinner");
1471
4109
  //#endregion
4110
+ //#region src/components/split-button/index.tsx
4111
+ var _tmpl$$6 = /*#__PURE__*/ template(`<div>`);
4112
+ var _tmpl$2$3 = /*#__PURE__*/ template(`<button>`);
4113
+ var _tmpl$3$3 = /*#__PURE__*/ template(`<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m6 9 6 6 6-6">`);
4114
+ /**
4115
+ * A primary action with its alternatives one seam away: the main button
4116
+ * fires `onClick`, the fitted arrow opens a paper vessel of the same
4117
+ * register whose entries call `onSelect` with their value. The arrow is
4118
+ * the menu machine's trigger with the button recipe riding over it —
4119
+ * the machine keeps the element (positioning, focus, `data-state`), the
4120
+ * button stylesheet's trigger register dresses it. The popup keeps the
4121
+ * menu parts untouched.
4122
+ */
4123
+ function SplitButton(props) {
4124
+ const [own, rest] = splitProps(props, [
4125
+ "label",
4126
+ "items",
4127
+ "variant",
4128
+ "tone",
4129
+ "size",
4130
+ "disabled",
4131
+ "onClick",
4132
+ "onSelect",
4133
+ "children"
4134
+ ]);
4135
+ const variant = () => own.variant ?? "solid";
4136
+ const tone = () => own.tone ?? "ink";
4137
+ const size = () => own.size ?? "md";
4138
+ return (() => {
4139
+ var _el$ = _tmpl$$6();
4140
+ spread(_el$, mergeProps(rest, {
4141
+ "data-scope": "split-button",
4142
+ "data-part": "root"
4143
+ }), false, true);
4144
+ insert(_el$, createComponent(Button, {
4145
+ get variant() {
4146
+ return variant();
4147
+ },
4148
+ get tone() {
4149
+ return tone();
4150
+ },
4151
+ get size() {
4152
+ return size();
4153
+ },
4154
+ get disabled() {
4155
+ return own.disabled;
4156
+ },
4157
+ onClick: (event) => own.onClick?.(event),
4158
+ get children() {
4159
+ return own.label;
4160
+ }
4161
+ }), null);
4162
+ insert(_el$, createComponent(Menu$1.Root, {
4163
+ positioning: { placement: "bottom-end" },
4164
+ get children() {
4165
+ return [createComponent(Menu$1.Trigger, { asChild: (propsFn) => (() => {
4166
+ var _el$2 = _tmpl$2$3();
4167
+ spread(_el$2, mergeProps(propsFn, {
4168
+ "type": "button",
4169
+ get disabled() {
4170
+ return own.disabled;
4171
+ },
4172
+ "aria-label": "More actions",
4173
+ get ["data-variant"]() {
4174
+ return variant();
4175
+ },
4176
+ get ["data-tone"]() {
4177
+ return tone();
4178
+ },
4179
+ get ["data-size"]() {
4180
+ return size();
4181
+ },
4182
+ "data-square": "true",
4183
+ "data-motion": "ink-ripple lit"
4184
+ }), false, true);
4185
+ insert(_el$2, chevronDown);
4186
+ return _el$2;
4187
+ })() }), createComponent(Portal, { get children() {
4188
+ return createComponent(Menu$1.Positioner, { get children() {
4189
+ return createComponent(Menu$1.Content, { get children() {
4190
+ return createComponent(For, {
4191
+ get each() {
4192
+ return own.items ?? [];
4193
+ },
4194
+ children: (entry) => createComponent(Menu$1.Item, {
4195
+ get value() {
4196
+ return entry.value;
4197
+ },
4198
+ get disabled() {
4199
+ return entry.disabled;
4200
+ },
4201
+ get ["data-danger"]() {
4202
+ return entry.danger ? "" : void 0;
4203
+ },
4204
+ onSelect: () => own.onSelect?.(entry.value),
4205
+ get children() {
4206
+ return createComponent(Menu$1.ItemText, { get children() {
4207
+ return entry.label;
4208
+ } });
4209
+ }
4210
+ })
4211
+ });
4212
+ } });
4213
+ } });
4214
+ } })];
4215
+ }
4216
+ }), null);
4217
+ return _el$;
4218
+ })();
4219
+ }
4220
+ /** One stroke pointing down: all a fitted dropdown arrow needs. */
4221
+ function chevronDown() {
4222
+ return _tmpl$3$3();
4223
+ }
4224
+ injectComponentStyle("split-button");
4225
+ injectComponentStyle("menu");
4226
+ //#endregion
1472
4227
  //#region src/components/splitter/index.ts
1473
4228
  /** Ark's Splitter, dressed in the paper-and-ink system: panels divide on
1474
4229
  * a hairline and a small paper-seal thumb answers the hand. The API is
@@ -1476,21 +4231,59 @@ injectComponentStyle("spinner");
1476
4231
  const Splitter = Splitter$1;
1477
4232
  injectComponentStyle("splitter");
1478
4233
  //#endregion
4234
+ //#region src/components/stack/index.tsx
4235
+ var _tmpl$$5 = /*#__PURE__*/ template(`<div>`);
4236
+ /** Whitespace chosen by name: the named steps point at the space ramp so
4237
+ * siblings are held apart by one token, never by ad-hoc margins. */
4238
+ const gapVars = {
4239
+ none: "0",
4240
+ xs: "var(--bs-gap-xs)",
4241
+ sm: "var(--bs-gap-sm)",
4242
+ md: "var(--bs-gap-md)",
4243
+ lg: "var(--bs-gap-lg)",
4244
+ xl: "var(--bs-gap-xl)"
4245
+ };
4246
+ function Stack(props) {
4247
+ const [own, rest] = splitProps(props, [
4248
+ "direction",
4249
+ "gap",
4250
+ "wrap",
4251
+ "align",
4252
+ "justify"
4253
+ ]);
4254
+ return (() => {
4255
+ var _el$ = _tmpl$$5();
4256
+ spread(_el$, mergeProps(rest, {
4257
+ get style() {
4258
+ return {
4259
+ ...rest.style,
4260
+ "--bs-stack-gap": gapVars[own.gap ?? "md"] ?? gapVars.md,
4261
+ "align-items": own.align,
4262
+ "justify-content": own.justify,
4263
+ "flex-wrap": own.wrap ? "wrap" : void 0
4264
+ };
4265
+ },
4266
+ "data-scope": "stack",
4267
+ "data-part": "root",
4268
+ get ["data-direction"]() {
4269
+ return own.direction ?? "column";
4270
+ }
4271
+ }), false, false);
4272
+ return _el$;
4273
+ })();
4274
+ }
4275
+ injectComponentStyle("stack");
4276
+ //#endregion
1479
4277
  //#region src/components/stat/index.tsx
1480
- var _tmpl$$2 = /*#__PURE__*/ template(`<tag>`);
1481
- var _tmpl$2$1 = /*#__PURE__*/ template(`<span>`);
4278
+ var _tmpl$$4 = /*#__PURE__*/ template(`<span>`);
1482
4279
  function part$2(name, tag) {
1483
4280
  function Component(props) {
1484
- return (() => {
1485
- var _el$ = _tmpl$$2();
1486
- spread(_el$, mergeProps(props, {
1487
- "data-scope": "stat",
1488
- get ["data-part"]() {
1489
- return name.toLowerCase();
1490
- }
1491
- }), false, false);
1492
- return _el$;
1493
- })();
4281
+ return createComponent(tag, mergeProps(props, {
4282
+ "data-scope": "stat",
4283
+ get ["data-part"]() {
4284
+ return name.toLowerCase();
4285
+ }
4286
+ }));
1494
4287
  }
1495
4288
  return Component;
1496
4289
  }
@@ -1501,17 +4294,17 @@ const Description = part$2("Description", "p");
1501
4294
  /** The delta reads the direction in the fixed semantic pigments; an
1502
4295
  * explicit `data-direction` attribute on the consumer side still wins. */
1503
4296
  function Delta(props) {
1504
- const [own, rest] = splitProps$1(props, ["direction"]);
4297
+ const [own, rest] = splitProps(props, ["direction"]);
1505
4298
  return (() => {
1506
- var _el$2 = _tmpl$2$1();
1507
- spread(_el$2, mergeProps(rest, {
4299
+ var _el$ = _tmpl$$4();
4300
+ spread(_el$, mergeProps(rest, {
1508
4301
  "data-scope": "stat",
1509
4302
  "data-part": "delta",
1510
4303
  get ["data-direction"]() {
1511
4304
  return rest["data-direction"] ?? own.direction ?? "flat";
1512
4305
  }
1513
4306
  }), false, false);
1514
- return _el$2;
4307
+ return _el$;
1515
4308
  })();
1516
4309
  }
1517
4310
  const Stat = Object.assign(Root$1, {
@@ -1551,16 +4344,16 @@ const Switch = Switch$1;
1551
4344
  injectComponentStyle("switch");
1552
4345
  //#endregion
1553
4346
  //#region src/components/table/index.tsx
1554
- var _tmpl$$1 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m9 6 6 6-6 6">`);
1555
- var _tmpl$2 = /*#__PURE__*/ template(`<input type=checkbox aria-label="Select row">`);
1556
- var _tmpl$3 = /*#__PURE__*/ template(`<div data-scope=table data-part=cell-main><button type=button data-scope=table data-part=expander>`);
1557
- var _tmpl$4 = /*#__PURE__*/ template(`<div role=cell data-scope=table data-part=cell>`);
1558
- var _tmpl$5 = /*#__PURE__*/ template(`<div role=row data-scope=table data-part=row>`);
1559
- var _tmpl$6 = /*#__PURE__*/ template(`<div role=columnheader data-scope=table data-part=header-cell>`);
4347
+ var _tmpl$$3 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m9 6 6 6-6 6">`);
4348
+ var _tmpl$2$2 = /*#__PURE__*/ template(`<input type=checkbox>`);
4349
+ var _tmpl$3$2 = /*#__PURE__*/ template(`<div data-scope=table data-part=cell-main><button type=button data-scope=table data-part=expander>`);
4350
+ var _tmpl$4$1 = /*#__PURE__*/ template(`<div role=cell data-scope=table data-part=cell>`);
4351
+ var _tmpl$5$1 = /*#__PURE__*/ template(`<div role=row data-scope=table data-part=row>`);
4352
+ var _tmpl$6$1 = /*#__PURE__*/ template(`<div role=columnheader data-scope=table data-part=header-cell>`);
1560
4353
  var _tmpl$7 = /*#__PURE__*/ template(`<input type=text data-scope=table data-part=header-filter placeholder=Filter>`);
1561
4354
  var _tmpl$8 = /*#__PURE__*/ template(`<div data-scope=table data-part=root><div data-scope=table data-part=viewport><div role=table data-scope=table data-part=table><div role=rowgroup data-scope=table data-part=header></div><div role=rowgroup data-scope=table data-part=body>`);
1562
4355
  var _tmpl$9 = /*#__PURE__*/ template(`<div data-scope=table data-part=toolbar><input type=search data-scope=table data-part=global-filter aria-label="Filter all columns">`);
1563
- var _tmpl$0 = /*#__PURE__*/ template(`<div role=columnheader data-scope=table data-part=header-cell><input type=checkbox aria-label="Select all rows">`);
4356
+ var _tmpl$0 = /*#__PURE__*/ template(`<div role=columnheader data-scope=table data-part=header-cell><input type=checkbox>`);
1564
4357
  var _tmpl$1 = /*#__PURE__*/ template(`<div data-scope=table data-part=empty>`);
1565
4358
  var _tmpl$10 = /*#__PURE__*/ template(`<div role=rowgroup data-scope=table data-part=footer>`);
1566
4359
  var _tmpl$11 = /*#__PURE__*/ template(`<div role=columnheader data-scope=table data-part=footer-cell>`);
@@ -1616,7 +4409,7 @@ function mark(el, attr, on) {
1616
4409
  if (on) el.setAttribute(attr, "");
1617
4410
  else el.removeAttribute(attr);
1618
4411
  }
1619
- const chevronGlyph = _tmpl$$1();
4412
+ const chevronGlyph = _tmpl$$3();
1620
4413
  function DataTable(props) {
1621
4414
  if (props.virtual && props.merge) console.warn("[DataTable] `virtual` and `merge` are mutually exclusive; merge wins.");
1622
4415
  /** Features follow the construction-time switches: sorting, selection,
@@ -1741,17 +4534,18 @@ function DataTable(props) {
1741
4534
  * stylesheet reads. */
1742
4535
  function pinAttrs(column) {
1743
4536
  const pinned = column.getIsPinned();
1744
- const attrs = { "data-pinned": pinned || void 0 };
1745
- if (!pinned) return attrs;
4537
+ if (!pinned) return { "data-pinned": void 0 };
1746
4538
  const offset = pinned === "start" ? column.getStart("start") : column.getAfter("end");
1747
4539
  const siblings = leafIds();
1748
4540
  const index = siblings.indexOf(column.id);
1749
4541
  const prev = index > 0 ? table.getColumn(siblings[index - 1]) : void 0;
1750
4542
  const next = index < siblings.length - 1 ? table.getColumn(siblings[index + 1]) : void 0;
1751
- attrs["data-last-pinned"] = pinned === "start" && next?.getIsPinned() !== "start" ? "" : void 0;
1752
- attrs["data-first-pinned"] = pinned === "end" && prev?.getIsPinned() !== "end" ? "" : void 0;
1753
- attrs.style = { "--pin-offset": `${offset}px` };
1754
- return attrs;
4543
+ return {
4544
+ "data-pinned": pinned,
4545
+ "data-last-pinned": pinned === "start" && next?.getIsPinned() !== "start" ? "" : void 0,
4546
+ "data-first-pinned": pinned === "end" && prev?.getIsPinned() !== "end" ? "" : void 0,
4547
+ style: { "--pin-offset": `${offset}px` }
4548
+ };
1755
4549
  }
1756
4550
  let dragColId = null;
1757
4551
  let dragRowId = null;
@@ -1923,14 +4717,17 @@ function DataTable(props) {
1923
4717
  };
1924
4718
  let content;
1925
4719
  if (column.id === SELECT_COL_ID) content = (() => {
1926
- var _el$2 = _tmpl$2();
1927
- _el$2.addEventListener("change", () => row.toggleSelected(!row.getIsSelected()));
1928
- _el$2.indeterminate = false;
1929
- effect(() => _el$2.checked = row.getIsSelected());
4720
+ var _el$2 = _tmpl$2$2();
4721
+ spread(_el$2, mergeProps({ get checked() {
4722
+ return row.getIsSelected();
4723
+ } }, { indeterminate: false }, {
4724
+ "aria-label": "Select row",
4725
+ "onchange": () => row.toggleSelected(!row.getIsSelected())
4726
+ }), false, false);
1930
4727
  return _el$2;
1931
4728
  })();
1932
4729
  else if (isExpandHost) content = (() => {
1933
- var _el$3 = _tmpl$3(), _el$4 = _el$3.firstChild;
4730
+ var _el$3 = _tmpl$3$2(), _el$4 = _el$3.firstChild;
1934
4731
  _el$4.$$click = () => row.toggleExpanded();
1935
4732
  insert(_el$4, chevronGlyph);
1936
4733
  insert(_el$3, createComponent(FlexRender, { cell }), null);
@@ -1951,7 +4748,7 @@ function DataTable(props) {
1951
4748
  })();
1952
4749
  else content = createComponent(FlexRender, { cell });
1953
4750
  return (() => {
1954
- var _el$5 = _tmpl$4();
4751
+ var _el$5 = _tmpl$4$1();
1955
4752
  setAttribute(_el$5, "data-spanned", rowSpan > 1 ? "" : void 0);
1956
4753
  spread(_el$5, mergeProps({ get ["data-numeric"]() {
1957
4754
  return column.columnDef.meta?.numeric ? "" : void 0;
@@ -1970,7 +4767,7 @@ function DataTable(props) {
1970
4767
  } : {};
1971
4768
  const draggable = rowDraggable();
1972
4769
  return (() => {
1973
- var _el$6 = _tmpl$5();
4770
+ var _el$6 = _tmpl$5$1();
1974
4771
  addEventListener(_el$6, "dragend", draggable ? onRowDragEnd : void 0);
1975
4772
  addEventListener(_el$6, "drop", draggable ? (e) => onRowDrop(row, e) : void 0);
1976
4773
  addEventListener(_el$6, "dragleave", draggable ? onRowDragLeave : void 0);
@@ -2002,7 +4799,7 @@ function DataTable(props) {
2002
4799
  const canFilter = props.filterable && column.getCanFilter();
2003
4800
  const canDrag = !!props.reorderable && column.id !== SELECT_COL_ID && !column.getIsPinned();
2004
4801
  return (() => {
2005
- var _el$7 = _tmpl$6();
4802
+ var _el$7 = _tmpl$6$1();
2006
4803
  setAttribute(_el$7, "data-sortable", canSort || void 0);
2007
4804
  setAttribute(_el$7, "data-sort", sorted || void 0);
2008
4805
  setAttribute(_el$7, "data-draggable", canDrag || void 0);
@@ -2058,7 +4855,7 @@ function DataTable(props) {
2058
4855
  return table.getHeaderGroups();
2059
4856
  },
2060
4857
  children: (group) => (() => {
2061
- var _el$14 = _tmpl$5();
4858
+ var _el$14 = _tmpl$5$1();
2062
4859
  insert(_el$14, createComponent(For, {
2063
4860
  get each() {
2064
4861
  return group.headers;
@@ -2070,9 +4867,11 @@ function DataTable(props) {
2070
4867
  return (() => {
2071
4868
  var _el$15 = _tmpl$0(), _el$16 = _el$15.firstChild;
2072
4869
  spread(_el$15, mergeProps(() => pinAttrs(column)), false, true);
2073
- _el$16.addEventListener("change", () => table.toggleAllRowsSelected(!all));
2074
4870
  _el$16.checked = all;
2075
- effect(() => _el$16.indeterminate = table.getIsSomeRowsSelected() && !all);
4871
+ spread(_el$16, mergeProps(() => ({ indeterminate: table.getIsSomeRowsSelected() && !all }), {
4872
+ "aria-label": "Select all rows",
4873
+ "onchange": () => table.toggleAllRowsSelected(!all)
4874
+ }), false, false);
2076
4875
  return _el$15;
2077
4876
  })();
2078
4877
  }
@@ -2111,7 +4910,7 @@ function DataTable(props) {
2111
4910
  return table.getFooterGroups();
2112
4911
  },
2113
4912
  children: (group) => (() => {
2114
- var _el$19 = _tmpl$5();
4913
+ var _el$19 = _tmpl$5$1();
2115
4914
  insert(_el$19, createComponent(For, {
2116
4915
  get each() {
2117
4916
  return group.headers;
@@ -2272,22 +5071,17 @@ const Toggle = Toggle$1;
2272
5071
  injectComponentStyle("toggle");
2273
5072
  //#endregion
2274
5073
  //#region src/components/typography/index.tsx
2275
- var _tmpl$ = /*#__PURE__*/ template(`<tag>`);
2276
5074
  /** The typographic voices, named so prose can ask for one: display and
2277
5075
  * heading ride the song-serif, the rest ride the hei. Nothing here is
2278
5076
  * decorative — hierarchy is size, weight, and space. */
2279
5077
  function part(name, tag) {
2280
5078
  function Component(props) {
2281
- return (() => {
2282
- var _el$ = _tmpl$();
2283
- spread(_el$, mergeProps(props, {
2284
- "data-scope": "typography",
2285
- get ["data-part"]() {
2286
- return name.toLowerCase();
2287
- }
2288
- }), false, false);
2289
- return _el$;
2290
- })();
5079
+ return createComponent(tag, mergeProps(props, {
5080
+ "data-scope": "typography",
5081
+ get ["data-part"]() {
5082
+ return name.toLowerCase();
5083
+ }
5084
+ }));
2291
5085
  }
2292
5086
  return Component;
2293
5087
  }
@@ -2314,6 +5108,165 @@ injectComponentStyle("typography");
2314
5108
  const ToggleGroup = ToggleGroup$1;
2315
5109
  injectComponentStyle("toggle-group");
2316
5110
  //#endregion
5111
+ //#region src/components/transfer/index.tsx
5112
+ var _tmpl$$2 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=3 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m5 12.5 5 5L19 7">`);
5113
+ var _tmpl$2$1 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.75 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path>`);
5114
+ var _tmpl$3$1 = /*#__PURE__*/ template(`<div data-scope=transfer data-part=search>`);
5115
+ var _tmpl$4 = /*#__PURE__*/ template(`<div data-scope=transfer data-part=panel><div data-scope=transfer data-part=head><span data-scope=transfer data-part=title></span><span data-scope=transfer data-part=count></span></div><div data-scope=transfer data-part=list>`);
5116
+ var _tmpl$5 = /*#__PURE__*/ template(`<p data-scope=transfer data-part=empty>Nothing here`);
5117
+ var _tmpl$6 = /*#__PURE__*/ template(`<div><div data-scope=transfer data-part=operations>`);
5118
+ function checkGlyph() {
5119
+ return _tmpl$$2();
5120
+ }
5121
+ function arrowGlyph(direction) {
5122
+ return (() => {
5123
+ var _el$2 = _tmpl$2$1(), _el$3 = _el$2.firstChild;
5124
+ setAttribute(_el$3, "d", direction === "right" ? "M5 12h14m-6-6 6 6-6 6" : "M19 12H5m6-6-6 6 6 6");
5125
+ return _el$2;
5126
+ })();
5127
+ }
5128
+ /**
5129
+ * Two ledgers and a crossing: items sit in the source column until the
5130
+ * reader checks them and walks them across — and back, the same way.
5131
+ * `value` is the target column's value list; everything else in
5132
+ * `data` stays on the left. `searchable` adds a filter line to each
5133
+ * panel.
5134
+ */
5135
+ function Transfer(props) {
5136
+ const [own, rest] = splitProps(props, [
5137
+ "value",
5138
+ "data",
5139
+ "titles",
5140
+ "searchable",
5141
+ "disabled",
5142
+ "onValueChange"
5143
+ ]);
5144
+ const [checkedSource, setCheckedSource] = createSignal(/* @__PURE__ */ new Set());
5145
+ const [checkedTarget, setCheckedTarget] = createSignal(/* @__PURE__ */ new Set());
5146
+ const [sourceQuery, setSourceQuery] = createSignal("");
5147
+ const [targetQuery, setTargetQuery] = createSignal("");
5148
+ const target = () => new Set(own.value ?? []);
5149
+ function panelItems(values, inTarget, query) {
5150
+ return values.filter((item) => item.label.toLowerCase().includes(query.toLowerCase()) && target().has(item.value) === inTarget);
5151
+ }
5152
+ function toggle(set, value, setChecked) {
5153
+ const next = new Set(set);
5154
+ if (next.has(value)) next.delete(value);
5155
+ else next.add(value);
5156
+ setChecked(next);
5157
+ }
5158
+ function move(toTarget) {
5159
+ const moving = toTarget ? checkedSource() : checkedTarget();
5160
+ if (moving.size === 0) return;
5161
+ const next = toTarget ? [...own.value ?? [], ...moving].filter((value, index, all) => all.indexOf(value) === index) : (own.value ?? []).filter((value) => !moving.has(value));
5162
+ (toTarget ? setCheckedSource : setCheckedTarget)(/* @__PURE__ */ new Set());
5163
+ own.onValueChange?.(next);
5164
+ }
5165
+ function panel(side, title, query, setQuery, checked, setChecked, items) {
5166
+ return (() => {
5167
+ var _el$4 = _tmpl$4(), _el$5 = _el$4.firstChild, _el$6 = _el$5.firstChild, _el$7 = _el$6.nextSibling, _el$9 = _el$5.nextSibling;
5168
+ setAttribute(_el$4, "data-side", side);
5169
+ insert(_el$6, title);
5170
+ insert(_el$7, () => String(items.length));
5171
+ insert(_el$4, createComponent(Show, {
5172
+ get when() {
5173
+ return own.searchable;
5174
+ },
5175
+ get children() {
5176
+ var _el$8 = _tmpl$3$1();
5177
+ insert(_el$8, createComponent(Input, {
5178
+ size: "sm",
5179
+ get value() {
5180
+ return query();
5181
+ },
5182
+ onValueChange: setQuery,
5183
+ placeholder: "Filter…",
5184
+ "aria-label": `Filter ${title}`
5185
+ }));
5186
+ return _el$8;
5187
+ }
5188
+ }), _el$9);
5189
+ insert(_el$9, createComponent(Show, {
5190
+ get when() {
5191
+ return items.length > 0;
5192
+ },
5193
+ get fallback() {
5194
+ return _tmpl$5();
5195
+ },
5196
+ get children() {
5197
+ return createComponent(For, {
5198
+ each: items,
5199
+ children: (item) => createComponent(Checkbox$1.Root, {
5200
+ get checked() {
5201
+ return checked().has(item.value);
5202
+ },
5203
+ get disabled() {
5204
+ return own.disabled || item.disabled === true;
5205
+ },
5206
+ onCheckedChange: () => toggle(checked(), item.value, setChecked),
5207
+ get children() {
5208
+ return [
5209
+ createComponent(Checkbox$1.Control, { get children() {
5210
+ return createComponent(Checkbox$1.Indicator, { get children() {
5211
+ return checkGlyph();
5212
+ } });
5213
+ } }),
5214
+ createComponent(Checkbox$1.Label, {
5215
+ "data-part": "label",
5216
+ get children() {
5217
+ return item.label;
5218
+ }
5219
+ }),
5220
+ createComponent(Checkbox$1.HiddenInput, {})
5221
+ ];
5222
+ }
5223
+ })
5224
+ });
5225
+ }
5226
+ }));
5227
+ return _el$4;
5228
+ })();
5229
+ }
5230
+ return (() => {
5231
+ var _el$1 = _tmpl$6(), _el$10 = _el$1.firstChild;
5232
+ spread(_el$1, mergeProps(rest, {
5233
+ "data-scope": "transfer",
5234
+ "data-part": "root"
5235
+ }), false, true);
5236
+ insert(_el$1, () => panel("source", own.titles?.[0] ?? "Source", sourceQuery, setSourceQuery, checkedSource, setCheckedSource, panelItems(own.data, false, sourceQuery())), _el$10);
5237
+ insert(_el$10, createComponent(Button, {
5238
+ variant: "outline",
5239
+ size: "sm",
5240
+ square: true,
5241
+ get disabled() {
5242
+ return checkedSource().size === 0 || own.disabled;
5243
+ },
5244
+ "aria-label": "Move right",
5245
+ onClick: () => move(true),
5246
+ get children() {
5247
+ return arrowGlyph("right");
5248
+ }
5249
+ }), null);
5250
+ insert(_el$10, createComponent(Button, {
5251
+ variant: "outline",
5252
+ size: "sm",
5253
+ square: true,
5254
+ get disabled() {
5255
+ return checkedTarget().size === 0 || own.disabled;
5256
+ },
5257
+ "aria-label": "Move left",
5258
+ onClick: () => move(false),
5259
+ get children() {
5260
+ return arrowGlyph("left");
5261
+ }
5262
+ }), null);
5263
+ insert(_el$1, () => panel("target", own.titles?.[1] ?? "Target", targetQuery, setTargetQuery, checkedTarget, setCheckedTarget, panelItems(own.data, true, targetQuery())), null);
5264
+ return _el$1;
5265
+ })();
5266
+ }
5267
+ injectComponentStyle("transfer");
5268
+ injectComponentStyle("checkbox");
5269
+ //#endregion
2317
5270
  //#region src/components/tooltip/index.ts
2318
5271
  /** Ark's Tooltip, dressed in the paper-and-ink system: the smallest
2319
5272
  * vessel — a tight chip of ink that dissolves in over its anchor. The
@@ -2331,6 +5284,181 @@ injectComponentStyle("tooltip");
2331
5284
  const Tour = Tour$1;
2332
5285
  injectComponentStyle("tour");
2333
5286
  //#endregion
5287
+ //#region src/components/tree-select/index.tsx
5288
+ var _tmpl$$1 = /*#__PURE__*/ template(`<svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="m9 18 6-6-6-6">`);
5289
+ var _tmpl$2 = /*#__PURE__*/ template(`<span>`);
5290
+ var _tmpl$3 = /*#__PURE__*/ template(`<button><span data-part=chevron aria-hidden=true>`);
5291
+ function chevron() {
5292
+ return _tmpl$$1();
5293
+ }
5294
+ /**
5295
+ * A tree behind a field: the control reads like an input, the vessel
5296
+ * below walks the hierarchy, and one leaf click closes the deal. Single
5297
+ * selection — the chosen label rides on the control, its value rides in
5298
+ * `value`.
5299
+ */
5300
+ function TreeSelect(props) {
5301
+ const [own, rest] = splitProps(props, [
5302
+ "value",
5303
+ "data",
5304
+ "placeholder",
5305
+ "disabled",
5306
+ "onValueChange"
5307
+ ]);
5308
+ const [open, setOpen] = createSignal(false);
5309
+ const collection = createMemo(() => createTreeCollection$1({
5310
+ nodeToValue: (node) => node.value,
5311
+ nodeToString: (node) => node.label,
5312
+ rootNode: {
5313
+ value: "ROOT",
5314
+ label: "",
5315
+ children: own.data
5316
+ }
5317
+ }));
5318
+ const firstLevel = () => (own.data ?? []).map((node) => node.value);
5319
+ const label = () => {
5320
+ let found;
5321
+ const walk = (nodes) => {
5322
+ for (const node of nodes ?? []) {
5323
+ if (node.value === own.value) found = node.label;
5324
+ walk(node.children);
5325
+ }
5326
+ };
5327
+ walk(own.data);
5328
+ return found;
5329
+ };
5330
+ function pick(details) {
5331
+ const [value] = details.selectedValue;
5332
+ if (value == null) return;
5333
+ own.onValueChange?.(value);
5334
+ setOpen(false);
5335
+ }
5336
+ function Row(rowProps) {
5337
+ return createComponent(TreeView$1.NodeProvider, {
5338
+ get node() {
5339
+ return rowProps.node;
5340
+ },
5341
+ get indexPath() {
5342
+ return rowProps.indexPath;
5343
+ },
5344
+ get children() {
5345
+ return createComponent(Show, {
5346
+ get when() {
5347
+ return rowProps.node.children;
5348
+ },
5349
+ get fallback() {
5350
+ return createComponent(TreeView$1.Item, { asChild: (propsFn) => (() => {
5351
+ var _el$2 = _tmpl$2();
5352
+ spread(_el$2, mergeProps(propsFn, { "style": {
5353
+ display: "flex",
5354
+ "inline-size": "100%"
5355
+ } }), false, true);
5356
+ insert(_el$2, createComponent(TreeView$1.ItemText, { get children() {
5357
+ return rowProps.node.label;
5358
+ } }));
5359
+ return _el$2;
5360
+ })() });
5361
+ },
5362
+ get children() {
5363
+ return createComponent(TreeView$1.Branch, { get children() {
5364
+ return [createComponent(TreeView$1.BranchControl, { get children() {
5365
+ return [createComponent(TreeView$1.BranchIndicator, { get children() {
5366
+ return chevron();
5367
+ } }), createComponent(TreeView$1.BranchText, { get children() {
5368
+ return rowProps.node.label;
5369
+ } })];
5370
+ } }), createComponent(TreeView$1.BranchContent, { get children() {
5371
+ return [createComponent(TreeView$1.BranchIndentGuide, {}), createComponent(For, {
5372
+ get each() {
5373
+ return rowProps.node.children;
5374
+ },
5375
+ children: (child, index) => createComponent(Row, {
5376
+ node: child,
5377
+ get indexPath() {
5378
+ return [...rowProps.indexPath, index()];
5379
+ }
5380
+ })
5381
+ })];
5382
+ } })];
5383
+ } });
5384
+ }
5385
+ });
5386
+ }
5387
+ });
5388
+ }
5389
+ return createComponent(Popover$1.Root, mergeProps(rest, {
5390
+ get open() {
5391
+ return open();
5392
+ },
5393
+ onOpenChange: (details) => setOpen(details.open),
5394
+ positioning: {
5395
+ sameWidth: true,
5396
+ placement: "bottom-start"
5397
+ },
5398
+ get children() {
5399
+ return [createComponent(Popover$1.Trigger, { asChild: (propsFn) => (() => {
5400
+ var _el$3 = _tmpl$3(), _el$4 = _el$3.firstChild;
5401
+ spread(_el$3, mergeProps(propsFn, {
5402
+ "type": "button",
5403
+ "data-scope": "tree-select",
5404
+ "data-part": "control",
5405
+ get ["data-open"]() {
5406
+ return open() ? "" : void 0;
5407
+ },
5408
+ get ["data-placeholder"]() {
5409
+ return label() == null ? "" : void 0;
5410
+ },
5411
+ get disabled() {
5412
+ return own.disabled;
5413
+ }
5414
+ }), false, true);
5415
+ insert(_el$3, () => label() ?? own.placeholder ?? "Select…", _el$4);
5416
+ insert(_el$4, chevron);
5417
+ return _el$3;
5418
+ })() }), createComponent(Portal, { get children() {
5419
+ return createComponent(Popover$1.Positioner, { get children() {
5420
+ return createComponent(Popover$1.Content, {
5421
+ "data-scope": "tree-select",
5422
+ "data-part": "content",
5423
+ get children() {
5424
+ return createComponent(TreeView$1.Root, {
5425
+ get collection() {
5426
+ return collection();
5427
+ },
5428
+ selectionMode: "single",
5429
+ get selectedValue() {
5430
+ return memo(() => !!own.value)() ? [own.value] : [];
5431
+ },
5432
+ get defaultExpandedValue() {
5433
+ return firstLevel();
5434
+ },
5435
+ onSelectionChange: pick,
5436
+ get children() {
5437
+ return createComponent(TreeView$1.Tree, { get children() {
5438
+ return createComponent(For, {
5439
+ get each() {
5440
+ return collection().rootNode.children;
5441
+ },
5442
+ children: (node, index) => createComponent(Row, {
5443
+ node,
5444
+ get indexPath() {
5445
+ return [index()];
5446
+ }
5447
+ })
5448
+ });
5449
+ } });
5450
+ }
5451
+ });
5452
+ }
5453
+ });
5454
+ } });
5455
+ } })];
5456
+ }
5457
+ }));
5458
+ }
5459
+ injectComponentStyle("tree-select");
5460
+ injectComponentStyle("tree-view");
5461
+ //#endregion
2334
5462
  //#region src/components/tree-view/index.ts
2335
5463
  /** Ark's TreeView, dressed in the paper-and-ink system: quiet rows where
2336
5464
  * selection is pure light on the paper, one hairline plumb line per depth,
@@ -2342,4 +5470,71 @@ injectComponentStyle("tour");
2342
5470
  const TreeView = TreeView$1;
2343
5471
  injectComponentStyle("tree-view");
2344
5472
  //#endregion
2345
- export { Accordion, Action, Ai, Alert, AngleSlider, Avatar, AvatarGroup, Badge, Banner, Breadcrumb, Button, Calendar, Card, Carousel, Checkbox, Chip, Clipboard, Collapsible, ColorPicker, Combobox, DataTable, DateInput, DatePicker, Dialog, Drawer, Editable, Empty, Field, Fieldset, FileUpload, FlexRender, FloatingPanel, Format, Frame, Highlight, HoverCard, ImageCropper, JsonTreeView, Kbd, Link, Listbox, Marquee, Menu, Message, Meter, NavigationMenu, NumberInput, PageHeader, Pagination, PasswordInput, PinInput, Popover, Progress, PromptInput, QrCode, RadioGroup, RatingGroup, Reasoning, Response, ScrollArea, SegmentGroup, Select, Separator, SignaturePad, Skeleton, Slider, Source, Spinner, Splitter, Stat, Steps, Suggestion, Swap, Switch, Tabs, TagsInput, Timeline, Timer, Toast, Toaster, Toc, Toggle, ToggleGroup, Tool, Tooltip, Tour, TreeView, Typography, createColumnHelper, createListCollection, createToaster, useTour };
5473
+ //#region src/components/watermark/index.tsx
5474
+ var _tmpl$ = /*#__PURE__*/ template(`<div><div data-scope=watermark data-part=content></div><div data-scope=watermark data-part=marks aria-hidden=true>`);
5475
+ /** Font-relative measures ride the root's own measure; absolute units
5476
+ * pass through untouched — the canvas needs a number, the prop may
5477
+ * speak in CSS. */
5478
+ function toPx(size) {
5479
+ const root = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
5480
+ const value = Number.parseFloat(size) || 0;
5481
+ if (size.includes("em")) return value * root;
5482
+ return value;
5483
+ }
5484
+ function Watermark(props) {
5485
+ const [own, rest] = splitProps(props, [
5486
+ "content",
5487
+ "opacity",
5488
+ "rotate",
5489
+ "fontSize"
5490
+ ]);
5491
+ const [host, setHost] = createSignal();
5492
+ const [tile, setTile] = createSignal("");
5493
+ createEffect(() => {
5494
+ const el = host();
5495
+ if (!el) return;
5496
+ const canvas = document.createElement("canvas");
5497
+ const paint = canvas.getContext("2d");
5498
+ if (!paint) return;
5499
+ const styles = getComputedStyle(el);
5500
+ const fontSizePx = toPx(own.fontSize ?? "0.875rem");
5501
+ const font = `${styles.fontWeight} ${fontSizePx}px ${styles.fontFamily}`;
5502
+ paint.font = font;
5503
+ const textWidth = paint.measureText(own.content).width;
5504
+ const margin = fontSizePx;
5505
+ const boxWidth = Math.ceil(textWidth + margin * 2);
5506
+ const boxHeight = Math.ceil(fontSizePx + margin * 2);
5507
+ const radian = (own.rotate ?? -20) * Math.PI / 180;
5508
+ const cos = Math.cos(radian);
5509
+ const sin = Math.sin(radian);
5510
+ const width = Math.ceil(Math.abs(boxWidth * cos) + Math.abs(boxHeight * sin));
5511
+ const height = Math.ceil(Math.abs(boxWidth * sin) + Math.abs(boxHeight * cos));
5512
+ const dpr = window.devicePixelRatio || 1;
5513
+ canvas.width = width * dpr;
5514
+ canvas.height = height * dpr;
5515
+ paint.scale(dpr, dpr);
5516
+ paint.translate(width / 2, height / 2);
5517
+ paint.rotate(radian);
5518
+ paint.globalAlpha = own.opacity ?? .06;
5519
+ paint.font = font;
5520
+ paint.textAlign = "center";
5521
+ paint.textBaseline = "middle";
5522
+ paint.fillStyle = styles.getPropertyValue("--bs-color-text-tertiary").trim() || styles.color;
5523
+ paint.fillText(own.content, 0, 0);
5524
+ setTile(`url(${canvas.toDataURL()})`);
5525
+ });
5526
+ return (() => {
5527
+ var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
5528
+ use(setHost, _el$);
5529
+ spread(_el$, mergeProps(rest, {
5530
+ "data-scope": "watermark",
5531
+ "data-part": "root"
5532
+ }), false, true);
5533
+ insert(_el$2, () => rest.children);
5534
+ effect((_$p) => setStyleProperty(_el$3, "background-image", tile()));
5535
+ return _el$;
5536
+ })();
5537
+ }
5538
+ injectComponentStyle("watermark");
5539
+ //#endregion
5540
+ export { Accordion, Action, Action as AiAction, Affix, Ai, AiActions, Attachment as AiAttachment, Attachment, Attachments as AiAttachments, Attachments, AiContent, AiConversation, AiLoader, 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, ButtonGroupRoot, Calendar, Card, Carousel, CascadeSelect, Checkbox, CheckboxGroup, Chip, ClientOnly, Clipboard, Collapsible, ColorPicker, Combobox, Command, Comment, ConfigContextKey, ConfigProvider, Container, DataTable, DateInput, DatePicker, Descriptions, Dialog, DownloadTrigger, Drawer, DynamicInput, Editable, Ellipsis, Empty, Field, Fieldset, FileUpload, FlexRender, FloatButton, FloatButtonContextKey, 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 };