@stealthscale/component-actions 0.2.2 → 0.2.3

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.
@@ -0,0 +1,997 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { n as recipe$1, r as recipe, t as recipe$2 } from "./recipes-BhcK7PNL.js";
3
+ import { createElement, useId } from "react";
4
+ import { createRecipeContext, createSlotRecipeContext } from "@stealthscale/theme";
5
+ import { c } from "react/compiler-runtime";
6
+ import * as clipboard from "@zag-js/clipboard";
7
+ import { mergeProps, normalizeProps, useMachine } from "@zag-js/react";
8
+ import { createSplitProps } from "@zag-js/utils";
9
+ import { createRequiredContext, omitUndefined, splitEnumerable, usePresence } from "@stealthscale/hooks";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { useColorMode } from "@stealthscale/provider-color-mode";
12
+ import { downloadFile } from "@zag-js/file-utils";
13
+ import * as toggle from "@zag-js/toggle-group";
14
+ import { Group } from "@stealthscale/component-layout";
15
+ //#region src/button/context.ts
16
+ /**
17
+ * Binds the button recipe to the elements that render it.
18
+ *
19
+ * @remarks
20
+ * The binding is kept out of `recipe.ts` because an application's style compiler imports the
21
+ * recipe at build time, and a binding there would pull the React runtime into that import.
22
+ */
23
+ /**
24
+ * Supplies the element factory `Button` and `IconButton` are built from, and the provider an
25
+ * ancestor sets their variants through.
26
+ */
27
+ const { PropsProvider, withContext: withContext$2 } = createRecipeContext(recipe);
28
+ //#endregion
29
+ //#region src/button/button.ts
30
+ /**
31
+ * Renders a `button` element styled by the button recipe.
32
+ *
33
+ * @remarks
34
+ * The native element provides focus, activation with Space and Enter, and an accessible name from
35
+ * its content. The recipe supplies every style, so a theme that extends the recipe restyles every
36
+ * button. Pass `as` to render another element, such as an anchor.
37
+ */
38
+ /**
39
+ * Renders an element with the button recipe's classes.
40
+ */
41
+ const Bound$1 = withContext$2("button");
42
+ /**
43
+ * Renders a `button` element with `type` defaulting to `button`, so a button inside a form does not
44
+ * submit it.
45
+ *
46
+ * @remarks
47
+ * An element that `as` names takes a `type` only from the caller, because an `a` reads `type` as
48
+ * the media type of the page it opens.
49
+ * @param props - The recipe's variants and the props of the element.
50
+ * @returns The element with the button's classes.
51
+ */
52
+ function Button(props) {
53
+ return createElement(Bound$1, {
54
+ type: props.as === void 0 ? "button" : void 0,
55
+ ...props
56
+ });
57
+ }
58
+ //#endregion
59
+ //#region src/button/icon-button.ts
60
+ /**
61
+ * Renders a square button that contains one icon and requires an accessible name.
62
+ *
63
+ * @remarks
64
+ * It binds the button recipe with `shape` defaulting to `square`, so a theme that restyles the
65
+ * button restyles it too. An icon provides no text, so the props type requires `aria-label` or
66
+ * `aria-labelledby`. The union makes an unnamed icon button a type error, where a lint rule would
67
+ * only warn.
68
+ */
69
+ /**
70
+ * Renders an element with the button recipe's classes and `shape` defaulting to `square`.
71
+ */
72
+ const Bound = withContext$2("button", { defaultProps: { shape: "square" } });
73
+ /**
74
+ * Renders a square `button` element with `type` defaulting to `button`.
75
+ *
76
+ * @remarks
77
+ * An element that `as` names takes a `type` only from the caller, because an `a` reads `type` as
78
+ * the media type of the page it opens.
79
+ * @param props - The recipe's variants and the props of the element.
80
+ * @returns The element with the button's classes.
81
+ */
82
+ function Square(props) {
83
+ return createElement(Bound, {
84
+ type: props.as === void 0 ? "button" : void 0,
85
+ ...props
86
+ });
87
+ }
88
+ /**
89
+ * Renders a square button around one icon, named by `aria-label` or `aria-labelledby`.
90
+ */
91
+ const IconButton = Square;
92
+ //#endregion
93
+ //#region src/clipboard/machine.ts
94
+ /**
95
+ * Connects the Zag clipboard machine and provides its API to the parts.
96
+ *
97
+ * @remarks
98
+ * The root starts one machine, and every part reads the API from context, so the input, the
99
+ * trigger and the indicator report the same state. The machine derives the label and input IDs
100
+ * from `id`, so a caller's ID appears in the label's `for` attribute.
101
+ */
102
+ /**
103
+ * Context through which the root provides the connected API to its parts.
104
+ *
105
+ * @remarks
106
+ * `useClipboard` throws when no `Clipboard.Root` is mounted above the calling part.
107
+ */
108
+ const [ApiProvider$1, useClipboard] = createRequiredContext("Clipboard");
109
+ /**
110
+ * Starts the clipboard machine and returns its connected API.
111
+ *
112
+ * @param options - Machine settings split from the root's props. A generated ID is used when `id`
113
+ * is absent.
114
+ */
115
+ function useClipboardMachine(options) {
116
+ const $ = c(5);
117
+ const generated = useId();
118
+ let t0;
119
+ if ($[0] !== options) {
120
+ t0 = omitUndefined(options);
121
+ $[0] = options;
122
+ $[1] = t0;
123
+ } else t0 = $[1];
124
+ const t1 = options.id ?? generated;
125
+ let t2;
126
+ if ($[2] !== t0 || $[3] !== t1) {
127
+ t2 = {
128
+ ...t0,
129
+ id: t1
130
+ };
131
+ $[2] = t0;
132
+ $[3] = t1;
133
+ $[4] = t2;
134
+ } else t2 = $[4];
135
+ return clipboard.connect(useMachine(clipboard.machine, t2), normalizeProps);
136
+ }
137
+ /**
138
+ * Splits the root's props into machine settings and element props.
139
+ *
140
+ * @remarks
141
+ * The key list is `clipboard.props` without `translations`, so it follows the installed machine
142
+ * version. The machine's own splitter types `id` as required, and the root generates the ID after
143
+ * splitting, so the splitter is rebuilt over `ClipboardOptions` with `createSplitProps`.
144
+ */
145
+ const splitClipboardProps = splitEnumerable(createSplitProps(clipboard.props.filter((key) => key !== "translations")));
146
+ //#endregion
147
+ //#region src/clipboard/consumer.ts
148
+ /**
149
+ * Calls the render function with the API of the nearest root.
150
+ *
151
+ * @param props - The render function, as `children`.
152
+ * @returns The tree the render function returns.
153
+ */
154
+ function Consumer(t0) {
155
+ const $ = c(3);
156
+ const { children } = t0;
157
+ const t1 = useClipboard();
158
+ let t2;
159
+ if ($[0] !== children || $[1] !== t1) {
160
+ t2 = children(t1);
161
+ $[0] = children;
162
+ $[1] = t1;
163
+ $[2] = t2;
164
+ } else t2 = $[2];
165
+ return t2;
166
+ }
167
+ //#endregion
168
+ //#region src/clipboard/context.ts
169
+ /**
170
+ * Binds the clipboard slot recipe to the React context its parts share.
171
+ *
172
+ * @remarks
173
+ * The binding lives outside `recipe.ts`, because the style compiler of an application imports
174
+ * the recipe at build time and must not load React. It lives outside `machine.ts`, because the
175
+ * styles and the behaviour change independently.
176
+ */
177
+ /**
178
+ * Factories that bind an element to a slot: `withProvider` for the root, which provides the
179
+ * variants, and `withContext` for every other part, which reads them.
180
+ */
181
+ const { withContext: withContext$1, withProvider: withProvider$1 } = createSlotRecipeContext(recipe$1);
182
+ //#endregion
183
+ //#region src/clipboard/control.tsx
184
+ /**
185
+ * `div` bound to the control slot.
186
+ */
187
+ const Styled$6 = withContext$1("div", "control");
188
+ /**
189
+ * Renders the row with the caller's props merged over the machine's.
190
+ *
191
+ * @param props - Props of the styled `div`.
192
+ * @returns The row, with the `data-copied` attribute the machine sets after a copy.
193
+ */
194
+ function Control(props) {
195
+ const $ = c(5);
196
+ const api = useClipboard();
197
+ let t0;
198
+ if ($[0] !== api || $[1] !== props) {
199
+ t0 = mergeProps(api.getControlProps(), props);
200
+ $[0] = api;
201
+ $[1] = props;
202
+ $[2] = t0;
203
+ } else t0 = $[2];
204
+ let t1;
205
+ if ($[3] !== t0) {
206
+ t1 = /* @__PURE__ */ jsx(Styled$6, { ...t0 });
207
+ $[3] = t0;
208
+ $[4] = t1;
209
+ } else t1 = $[4];
210
+ return t1;
211
+ }
212
+ //#endregion
213
+ //#region src/clipboard/indicator.tsx
214
+ /**
215
+ * `span` bound to the indicator slot.
216
+ */
217
+ const Styled$5 = withContext$1("span", "indicator");
218
+ /**
219
+ * Renders `children` in the idle state and `copied` in the copied state.
220
+ *
221
+ * @param props - The two marks and the props of the styled `span`.
222
+ * @returns The span, hidden from assistive technology unless the caller overrides `aria-hidden`.
223
+ */
224
+ function Indicator$1(t0) {
225
+ const $ = c(4);
226
+ const { children, copied, ...rest } = t0;
227
+ const api = useClipboard();
228
+ const T0 = Styled$5;
229
+ const t1 = mergeProps({ "aria-hidden": true }, api.getIndicatorProps({ copied: api.copied }), rest);
230
+ const t2 = api.copied ? copied : children;
231
+ let t3;
232
+ if ($[0] !== T0 || $[1] !== t1 || $[2] !== t2) {
233
+ t3 = /* @__PURE__ */ jsx(T0, {
234
+ ...t1,
235
+ children: t2
236
+ });
237
+ $[0] = T0;
238
+ $[1] = t1;
239
+ $[2] = t2;
240
+ $[3] = t3;
241
+ } else t3 = $[3];
242
+ return t3;
243
+ }
244
+ //#endregion
245
+ //#region src/clipboard/input.tsx
246
+ /**
247
+ * `input` bound to the input slot.
248
+ */
249
+ const Styled$4 = withContext$1("input", "input");
250
+ /**
251
+ * Renders the field with the caller's props merged over the machine's.
252
+ *
253
+ * @param props - Props of the styled `input`.
254
+ * @returns The read-only field that holds the machine's value.
255
+ */
256
+ function Input(props) {
257
+ const $ = c(5);
258
+ const api = useClipboard();
259
+ let t0;
260
+ if ($[0] !== api || $[1] !== props) {
261
+ t0 = mergeProps(api.getInputProps(), props);
262
+ $[0] = api;
263
+ $[1] = props;
264
+ $[2] = t0;
265
+ } else t0 = $[2];
266
+ let t1;
267
+ if ($[3] !== t0) {
268
+ t1 = /* @__PURE__ */ jsx(Styled$4, { ...t0 });
269
+ $[3] = t0;
270
+ $[4] = t1;
271
+ } else t1 = $[4];
272
+ return t1;
273
+ }
274
+ //#endregion
275
+ //#region src/clipboard/label.tsx
276
+ /**
277
+ * `label` bound to the label slot.
278
+ */
279
+ const Styled$3 = withContext$1("label", "label");
280
+ /**
281
+ * Renders the label with the caller's props merged over the machine's.
282
+ *
283
+ * @param props - Props of the styled `label`.
284
+ * @returns The label, whose `for` attribute points at the field.
285
+ */
286
+ function Label(props) {
287
+ const $ = c(5);
288
+ const api = useClipboard();
289
+ let t0;
290
+ if ($[0] !== api || $[1] !== props) {
291
+ t0 = mergeProps(api.getLabelProps(), props);
292
+ $[0] = api;
293
+ $[1] = props;
294
+ $[2] = t0;
295
+ } else t0 = $[2];
296
+ let t1;
297
+ if ($[3] !== t0) {
298
+ t1 = /* @__PURE__ */ jsx(Styled$3, { ...t0 });
299
+ $[3] = t0;
300
+ $[4] = t1;
301
+ } else t1 = $[4];
302
+ return t1;
303
+ }
304
+ //#endregion
305
+ //#region src/clipboard/root.tsx
306
+ /**
307
+ * `div` bound to the root slot, which provides the recipe's variants to the parts.
308
+ */
309
+ const Styled$2 = withProvider$1("div", "root");
310
+ /**
311
+ * Starts a clipboard machine and renders the container its parts read from.
312
+ *
313
+ * @param props - Machine settings, recipe variants and `div` props.
314
+ * @returns The container, with the connected API in context.
315
+ */
316
+ function Root$2(props) {
317
+ const $ = c(10);
318
+ let t0;
319
+ if ($[0] !== props) {
320
+ t0 = splitClipboardProps(props);
321
+ $[0] = props;
322
+ $[1] = t0;
323
+ } else t0 = $[1];
324
+ const [options, rest] = t0;
325
+ const api = useClipboardMachine(options);
326
+ let t1;
327
+ if ($[2] !== api) {
328
+ t1 = api.getRootProps();
329
+ $[2] = api;
330
+ $[3] = t1;
331
+ } else t1 = $[3];
332
+ let t2;
333
+ if ($[4] !== rest || $[5] !== t1) {
334
+ t2 = /* @__PURE__ */ jsx(Styled$2, {
335
+ ...rest,
336
+ ...t1
337
+ });
338
+ $[4] = rest;
339
+ $[5] = t1;
340
+ $[6] = t2;
341
+ } else t2 = $[6];
342
+ let t3;
343
+ if ($[7] !== api || $[8] !== t2) {
344
+ t3 = /* @__PURE__ */ jsx(ApiProvider$1, {
345
+ value: api,
346
+ children: t2
347
+ });
348
+ $[7] = api;
349
+ $[8] = t2;
350
+ $[9] = t3;
351
+ } else t3 = $[9];
352
+ return t3;
353
+ }
354
+ //#endregion
355
+ //#region src/clipboard/trigger.tsx
356
+ /**
357
+ * `button` bound to the trigger slot.
358
+ */
359
+ const Styled$1 = withContext$1("button", "trigger");
360
+ /**
361
+ * Default accessible name in the idle state.
362
+ */
363
+ const LABEL = "Copy to clipboard";
364
+ /**
365
+ * Default accessible name in the copied state.
366
+ */
367
+ const COPIED_LABEL = "Copied to clipboard";
368
+ /**
369
+ * Renders the button with the caller's props merged over the machine's.
370
+ *
371
+ * @remarks
372
+ * An `aria-label` the caller passes takes precedence over both names.
373
+ * @param props - The two accessible names and the props of the styled `button`.
374
+ * @returns The button, wired to the machine's copy handler.
375
+ */
376
+ function Trigger(t0) {
377
+ const $ = c(3);
378
+ const { copiedLabel: t1, label: t2, ...rest } = t0;
379
+ const copiedLabel = t1 === void 0 ? COPIED_LABEL : t1;
380
+ const label = t2 === void 0 ? LABEL : t2;
381
+ const api = useClipboard();
382
+ const named = { "aria-label": api.copied ? copiedLabel : label };
383
+ const T0 = Styled$1;
384
+ const t3 = mergeProps(api.getTriggerProps(), named, rest);
385
+ let t4;
386
+ if ($[0] !== T0 || $[1] !== t3) {
387
+ t4 = /* @__PURE__ */ jsx(T0, { ...t3 });
388
+ $[0] = T0;
389
+ $[1] = t3;
390
+ $[2] = t4;
391
+ } else t4 = $[2];
392
+ return t4;
393
+ }
394
+ //#endregion
395
+ //#region src/clipboard/value-text.tsx
396
+ /**
397
+ * `span` bound to the valueText slot.
398
+ */
399
+ const Styled = withContext$1("span", "valueText");
400
+ /**
401
+ * Renders the caller's children, or the machine's value when there are none.
402
+ *
403
+ * @param props - Props of the styled `span`.
404
+ * @returns The span with the children or the value.
405
+ */
406
+ function ValueText(t0) {
407
+ const $ = c(6);
408
+ let children;
409
+ let rest;
410
+ if ($[0] !== t0) {
411
+ ({children, ...rest} = t0);
412
+ $[0] = t0;
413
+ $[1] = children;
414
+ $[2] = rest;
415
+ } else {
416
+ children = $[1];
417
+ rest = $[2];
418
+ }
419
+ const api = useClipboard();
420
+ const t1 = children ?? api.value;
421
+ let t2;
422
+ if ($[3] !== rest || $[4] !== t1) {
423
+ t2 = /* @__PURE__ */ jsx(Styled, {
424
+ ...rest,
425
+ children: t1
426
+ });
427
+ $[3] = rest;
428
+ $[4] = t1;
429
+ $[5] = t2;
430
+ } else t2 = $[5];
431
+ return t2;
432
+ }
433
+ //#endregion
434
+ //#region src/clipboard/index.ts
435
+ var clipboard_exports = /* @__PURE__ */ __exportAll({
436
+ Consumer: () => Consumer,
437
+ Control: () => Control,
438
+ Indicator: () => Indicator$1,
439
+ Input: () => Input,
440
+ Label: () => Label,
441
+ Root: () => Root$2,
442
+ Trigger: () => Trigger,
443
+ ValueText: () => ValueText
444
+ });
445
+ //#endregion
446
+ //#region src/swap/context.ts
447
+ /**
448
+ * Binds the swap's recipe to its parts.
449
+ *
450
+ * @remarks
451
+ * The binding is apart from the recipe, because a compiler reads the recipe at build time and the
452
+ * binding imports the runtime.
453
+ */
454
+ /**
455
+ * Binds the recipe once. The root provides the variants and each indicator reads them.
456
+ */
457
+ const { withContext, withProvider } = createSlotRecipeContext(recipe$2);
458
+ //#endregion
459
+ //#region src/swap/state.ts
460
+ /**
461
+ * Provides the swap's state from the root to its indicators.
462
+ */
463
+ /**
464
+ * Creates the context through which the root provides the state to its indicators.
465
+ *
466
+ * @remarks
467
+ * `useSwapState` throws when no `Swap.Root` is mounted above the calling indicator.
468
+ */
469
+ const [StateProvider, useSwapState] = createRequiredContext("Swap");
470
+ //#endregion
471
+ //#region src/swap/indicator.tsx
472
+ /**
473
+ * Renders the `span` with the swap's indicator class.
474
+ */
475
+ const Drawn = withContext("span", "indicator");
476
+ /**
477
+ * Renders the mark with its presence's `data-state` and `inert`, and `data-hidden` in place of
478
+ * `hidden`, under the caller's props.
479
+ *
480
+ * @param props - Which mark this is and the props of a `span`.
481
+ * @returns The `span` element, or nothing while the presence renders nothing.
482
+ */
483
+ function Indicator(t0) {
484
+ const $ = c(16);
485
+ let props;
486
+ let type;
487
+ if ($[0] !== t0) {
488
+ ({type, ...props} = t0);
489
+ $[0] = t0;
490
+ $[1] = props;
491
+ $[2] = type;
492
+ } else {
493
+ props = $[1];
494
+ type = $[2];
495
+ }
496
+ const { lazyMount, swap, unmountOnExit } = useSwapState();
497
+ const t1 = type === "on" ? swap : !swap;
498
+ let t2;
499
+ if ($[3] !== lazyMount || $[4] !== t1 || $[5] !== unmountOnExit) {
500
+ t2 = {
501
+ lazyMount,
502
+ present: t1,
503
+ skipAnimationOnMount: true,
504
+ unmountOnExit
505
+ };
506
+ $[3] = lazyMount;
507
+ $[4] = t1;
508
+ $[5] = unmountOnExit;
509
+ $[6] = t2;
510
+ } else t2 = $[6];
511
+ const { props: t3, setNode, unmounted } = usePresence(t2);
512
+ let hidden;
513
+ let presented;
514
+ if ($[7] !== t3) {
515
+ ({hidden, ...presented} = t3);
516
+ $[7] = t3;
517
+ $[8] = hidden;
518
+ $[9] = presented;
519
+ } else {
520
+ hidden = $[8];
521
+ presented = $[9];
522
+ }
523
+ if (unmounted) return null;
524
+ const t4 = hidden ? "" : void 0;
525
+ let t5;
526
+ if ($[10] !== presented || $[11] !== props || $[12] !== setNode || $[13] !== t4 || $[14] !== type) {
527
+ t5 = /* @__PURE__ */ jsx(Drawn, {
528
+ ...presented,
529
+ "data-hidden": t4,
530
+ ...props,
531
+ "data-type": type,
532
+ ref: setNode
533
+ });
534
+ $[10] = presented;
535
+ $[11] = props;
536
+ $[12] = setNode;
537
+ $[13] = t4;
538
+ $[14] = type;
539
+ $[15] = t5;
540
+ } else t5 = $[15];
541
+ return t5;
542
+ }
543
+ //#endregion
544
+ //#region src/swap/root.tsx
545
+ /**
546
+ * Renders the `span` with the swap's root class.
547
+ */
548
+ const Framed = withProvider("span", "root");
549
+ /**
550
+ * Renders the root and provides which mark shows to the indicators.
551
+ *
552
+ * @param props - Which mark shows, how the marks render while hidden, the motion and the props of a
553
+ * `span`.
554
+ * @returns The `span` element inside the state's provider.
555
+ */
556
+ function Root$1(t0) {
557
+ const $ = c(15);
558
+ let props;
559
+ let t1;
560
+ let t2;
561
+ let t3;
562
+ if ($[0] !== t0) {
563
+ ({lazyMount: t1, swap: t2, unmountOnExit: t3, ...props} = t0);
564
+ $[0] = t0;
565
+ $[1] = props;
566
+ $[2] = t1;
567
+ $[3] = t2;
568
+ $[4] = t3;
569
+ } else {
570
+ props = $[1];
571
+ t1 = $[2];
572
+ t2 = $[3];
573
+ t3 = $[4];
574
+ }
575
+ const lazyMount = t1 === void 0 ? false : t1;
576
+ const swap = t2 === void 0 ? false : t2;
577
+ const unmountOnExit = t3 === void 0 ? false : t3;
578
+ let t4;
579
+ if ($[5] !== lazyMount || $[6] !== swap || $[7] !== unmountOnExit) {
580
+ t4 = {
581
+ lazyMount,
582
+ swap,
583
+ unmountOnExit
584
+ };
585
+ $[5] = lazyMount;
586
+ $[6] = swap;
587
+ $[7] = unmountOnExit;
588
+ $[8] = t4;
589
+ } else t4 = $[8];
590
+ const t5 = swap ? "on" : "off";
591
+ let t6;
592
+ if ($[9] !== props || $[10] !== t5) {
593
+ t6 = /* @__PURE__ */ jsx(Framed, {
594
+ "data-swap": t5,
595
+ ...props
596
+ });
597
+ $[9] = props;
598
+ $[10] = t5;
599
+ $[11] = t6;
600
+ } else t6 = $[11];
601
+ let t7;
602
+ if ($[12] !== t4 || $[13] !== t6) {
603
+ t7 = /* @__PURE__ */ jsx(StateProvider, {
604
+ value: t4,
605
+ children: t6
606
+ });
607
+ $[12] = t4;
608
+ $[13] = t6;
609
+ $[14] = t7;
610
+ } else t7 = $[14];
611
+ return t7;
612
+ }
613
+ //#endregion
614
+ //#region src/swap/index.ts
615
+ var swap_exports = /* @__PURE__ */ __exportAll({
616
+ Indicator: () => Indicator,
617
+ Root: () => Root$1
618
+ });
619
+ //#endregion
620
+ //#region src/color-mode-toggle/color-mode-toggle.tsx
621
+ /**
622
+ * Renders the actions `Button` as a ghost, neutral square that sets the other color mode on a press
623
+ * the caller did not cancel.
624
+ *
625
+ * @param props - The two glyphs, the name and the props of a `Button`.
626
+ * @returns The `button` element.
627
+ */
628
+ function ColorModeToggle(t0) {
629
+ const $ = c(24);
630
+ let dark;
631
+ let light;
632
+ let onClick;
633
+ let props;
634
+ let t1;
635
+ if ($[0] !== t0) {
636
+ ({dark, label: t1, light, onClick, ...props} = t0);
637
+ $[0] = t0;
638
+ $[1] = dark;
639
+ $[2] = light;
640
+ $[3] = onClick;
641
+ $[4] = props;
642
+ $[5] = t1;
643
+ } else {
644
+ dark = $[1];
645
+ light = $[2];
646
+ onClick = $[3];
647
+ props = $[4];
648
+ t1 = $[5];
649
+ }
650
+ const label = t1 === void 0 ? "Dark mode" : t1;
651
+ const { colorMode, setColorMode } = useColorMode();
652
+ const darkened = colorMode === "dark";
653
+ let t2;
654
+ if ($[6] !== darkened || $[7] !== onClick || $[8] !== setColorMode) {
655
+ t2 = (event) => {
656
+ onClick?.(event);
657
+ if (!event.defaultPrevented) setColorMode(darkened ? "light" : "dark");
658
+ };
659
+ $[6] = darkened;
660
+ $[7] = onClick;
661
+ $[8] = setColorMode;
662
+ $[9] = t2;
663
+ } else t2 = $[9];
664
+ let t3;
665
+ if ($[10] !== dark) {
666
+ t3 = /* @__PURE__ */ jsx(Indicator, {
667
+ type: "on",
668
+ children: dark
669
+ });
670
+ $[10] = dark;
671
+ $[11] = t3;
672
+ } else t3 = $[11];
673
+ let t4;
674
+ if ($[12] !== light) {
675
+ t4 = /* @__PURE__ */ jsx(Indicator, {
676
+ type: "off",
677
+ children: light
678
+ });
679
+ $[12] = light;
680
+ $[13] = t4;
681
+ } else t4 = $[13];
682
+ let t5;
683
+ if ($[14] !== darkened || $[15] !== t3 || $[16] !== t4) {
684
+ t5 = /* @__PURE__ */ jsxs(Root$1, {
685
+ swap: darkened,
686
+ children: [t3, t4]
687
+ });
688
+ $[14] = darkened;
689
+ $[15] = t3;
690
+ $[16] = t4;
691
+ $[17] = t5;
692
+ } else t5 = $[17];
693
+ let t6;
694
+ if ($[18] !== darkened || $[19] !== label || $[20] !== props || $[21] !== t2 || $[22] !== t5) {
695
+ t6 = /* @__PURE__ */ jsx(Button, {
696
+ palette: "neutral",
697
+ shape: "square",
698
+ variant: "ghost",
699
+ ...props,
700
+ "aria-label": label,
701
+ "aria-pressed": darkened,
702
+ onClick: t2,
703
+ children: t5
704
+ });
705
+ $[18] = darkened;
706
+ $[19] = label;
707
+ $[20] = props;
708
+ $[21] = t2;
709
+ $[22] = t5;
710
+ $[23] = t6;
711
+ } else t6 = $[23];
712
+ return t6;
713
+ }
714
+ //#endregion
715
+ //#region src/download-trigger/download.ts
716
+ /**
717
+ * Saves data built in the page to a file on the reader's device.
718
+ *
719
+ * @remarks
720
+ * Zag's `downloadFile` hands the browser an object URL through an anchor with a `download`
721
+ * attribute and revokes the URL once the anchor is pressed. Nothing is fetched and no server is
722
+ * involved. A menu row, or any control other than `DownloadTrigger`, calls `download` from its
723
+ * own handler.
724
+ */
725
+ /**
726
+ * Resolves the data and hands it to the browser as a file.
727
+ *
728
+ * @returns A promise that settles once the browser has the file, and rejects when the data
729
+ * function throws or its promise rejects.
730
+ */
731
+ async function download({ data, fileName, mimeType = "" }) {
732
+ const file = typeof data === "function" ? await data() : data;
733
+ downloadFile({
734
+ file,
735
+ name: fileName,
736
+ type: mimeType
737
+ });
738
+ }
739
+ //#endregion
740
+ //#region src/download-trigger/download-trigger.tsx
741
+ /**
742
+ * Renders a button that downloads `data` as `fileName` when pressed.
743
+ *
744
+ * @remarks
745
+ * `onClick` runs first. A handler that calls `preventDefault` cancels the download.
746
+ */
747
+ function DownloadTrigger(t0) {
748
+ const $ = c(14);
749
+ let data;
750
+ let fileName;
751
+ let mimeType;
752
+ let onClick;
753
+ let rest;
754
+ if ($[0] !== t0) {
755
+ ({data, fileName, mimeType, onClick, ...rest} = t0);
756
+ $[0] = t0;
757
+ $[1] = data;
758
+ $[2] = fileName;
759
+ $[3] = mimeType;
760
+ $[4] = onClick;
761
+ $[5] = rest;
762
+ } else {
763
+ data = $[1];
764
+ fileName = $[2];
765
+ mimeType = $[3];
766
+ onClick = $[4];
767
+ rest = $[5];
768
+ }
769
+ let t1;
770
+ if ($[6] !== data || $[7] !== fileName || $[8] !== mimeType || $[9] !== onClick) {
771
+ t1 = function pressed(event) {
772
+ onClick?.(event);
773
+ if (!event.defaultPrevented) download({
774
+ data,
775
+ fileName,
776
+ mimeType
777
+ });
778
+ };
779
+ $[6] = data;
780
+ $[7] = fileName;
781
+ $[8] = mimeType;
782
+ $[9] = onClick;
783
+ $[10] = t1;
784
+ } else t1 = $[10];
785
+ const pressed = t1;
786
+ let t2;
787
+ if ($[11] !== pressed || $[12] !== rest) {
788
+ t2 = /* @__PURE__ */ jsx(Button, {
789
+ ...rest,
790
+ onClick: pressed
791
+ });
792
+ $[11] = pressed;
793
+ $[12] = rest;
794
+ $[13] = t2;
795
+ } else t2 = $[13];
796
+ return t2;
797
+ }
798
+ //#endregion
799
+ //#region src/toggle-group/machine.ts
800
+ /**
801
+ * Runs the toggle group machine and provides its api to the items.
802
+ *
803
+ * @remarks
804
+ * The root starts one machine and every item reads the api from context, so the items report one
805
+ * value. A single-select group is a `radiogroup` of radios, and a multiple-select group is a
806
+ * `group` of buttons that report `aria-pressed`. The machine moves focus between the items with
807
+ * the arrow keys, Home and End, and the browser's own button toggles an item on Space and Enter.
808
+ */
809
+ /**
810
+ * Provides the connected api to the items, and reads it back.
811
+ *
812
+ * @remarks
813
+ * `useToggleGroup` throws for an item rendered outside `ToggleGroup.Root`.
814
+ */
815
+ const [ApiProvider, useToggleGroup] = createRequiredContext("ToggleGroup");
816
+ /**
817
+ * Starts the toggle group machine and returns its connected api.
818
+ *
819
+ * @remarks
820
+ * The ID of an item percent-encodes its value, so an ID never contains a space. An ID the caller
821
+ * passes in `ids` replaces it.
822
+ * @param options - The machine options split from the root's props. React generates `id` when the
823
+ * caller states none.
824
+ * @returns The connected api.
825
+ */
826
+ function useToggleGroupMachine(options) {
827
+ const $ = c(11);
828
+ const generated = useId();
829
+ const id = options.id ?? generated;
830
+ let t0;
831
+ if ($[0] !== options) {
832
+ t0 = omitUndefined(options);
833
+ $[0] = options;
834
+ $[1] = t0;
835
+ } else t0 = $[1];
836
+ let t1;
837
+ if ($[2] !== id) {
838
+ t1 = (value) => `toggle-group-${id}-item-${encodeURIComponent(value)}`;
839
+ $[2] = id;
840
+ $[3] = t1;
841
+ } else t1 = $[3];
842
+ let t2;
843
+ if ($[4] !== options.ids || $[5] !== t1) {
844
+ t2 = {
845
+ item: t1,
846
+ ...options.ids
847
+ };
848
+ $[4] = options.ids;
849
+ $[5] = t1;
850
+ $[6] = t2;
851
+ } else t2 = $[6];
852
+ let t3;
853
+ if ($[7] !== id || $[8] !== t0 || $[9] !== t2) {
854
+ t3 = {
855
+ ...t0,
856
+ id,
857
+ ids: t2
858
+ };
859
+ $[7] = id;
860
+ $[8] = t0;
861
+ $[9] = t2;
862
+ $[10] = t3;
863
+ } else t3 = $[10];
864
+ return toggle.connect(useMachine(toggle.machine, t3), normalizeProps);
865
+ }
866
+ /**
867
+ * Splits the root's props into the machine's options and the element's props.
868
+ *
869
+ * @remarks
870
+ * The key list comes from the machine's own `splitProps`, so it follows the installed machine.
871
+ */
872
+ const splitToggleGroupProps = splitEnumerable(toggle.splitProps);
873
+ /**
874
+ * Splits an item's props into its options and the element's props.
875
+ */
876
+ const splitItemProps = splitEnumerable(toggle.splitItemProps);
877
+ //#endregion
878
+ //#region src/toggle-group/item.tsx
879
+ /**
880
+ * Scrolls the item that took focus into view by the least distance.
881
+ */
882
+ function revealed(event) {
883
+ event.currentTarget.scrollIntoView({
884
+ block: "nearest",
885
+ inline: "nearest"
886
+ });
887
+ }
888
+ /**
889
+ * Renders the item as a button with the machine's item props.
890
+ *
891
+ * @param props - The item's options and the props of the button.
892
+ * @returns The `button` element.
893
+ */
894
+ function Item(props) {
895
+ const $ = c(9);
896
+ const api = useToggleGroup();
897
+ let T0;
898
+ let pressed;
899
+ let t0;
900
+ if ($[0] !== api || $[1] !== props) {
901
+ const [options, rest] = splitItemProps(props);
902
+ ({pressed} = api.getItemState(options));
903
+ T0 = Button;
904
+ t0 = mergeProps(api.getItemProps(options), { onFocus: revealed }, rest);
905
+ $[0] = api;
906
+ $[1] = props;
907
+ $[2] = T0;
908
+ $[3] = pressed;
909
+ $[4] = t0;
910
+ } else {
911
+ T0 = $[2];
912
+ pressed = $[3];
913
+ t0 = $[4];
914
+ }
915
+ const t1 = pressed ? "" : void 0;
916
+ let t2;
917
+ if ($[5] !== T0 || $[6] !== t0 || $[7] !== t1) {
918
+ t2 = /* @__PURE__ */ jsx(T0, {
919
+ ...t0,
920
+ "data-pressed": t1
921
+ });
922
+ $[5] = T0;
923
+ $[6] = t0;
924
+ $[7] = t1;
925
+ $[8] = t2;
926
+ } else t2 = $[8];
927
+ return t2;
928
+ }
929
+ //#endregion
930
+ //#region src/toggle-group/root.tsx
931
+ /**
932
+ * Renders the group and provides the machine's api and the items' variants.
933
+ *
934
+ * @param props - The machine's options, the group's props and the items' variants.
935
+ * @returns The `div` element that contains the items.
936
+ */
937
+ function Root(props) {
938
+ const $ = c(13);
939
+ const [options, rest] = splitToggleGroupProps(props);
940
+ const { attached: t0, palette, size, variant, ...attributes } = rest;
941
+ const attached = t0 === void 0 ? true : t0;
942
+ const api = useToggleGroupMachine(options);
943
+ const T0 = ApiProvider;
944
+ const T1 = PropsProvider;
945
+ const t1 = omitUndefined({
946
+ palette,
947
+ size,
948
+ variant
949
+ });
950
+ const T2 = Group;
951
+ const t2 = options.orientation ?? "horizontal";
952
+ const t3 = mergeProps(api.getRootProps(), attributes);
953
+ let t4;
954
+ if ($[0] !== T2 || $[1] !== attached || $[2] !== t2 || $[3] !== t3) {
955
+ t4 = /* @__PURE__ */ jsx(T2, {
956
+ attached,
957
+ orientation: t2,
958
+ ...t3
959
+ });
960
+ $[0] = T2;
961
+ $[1] = attached;
962
+ $[2] = t2;
963
+ $[3] = t3;
964
+ $[4] = t4;
965
+ } else t4 = $[4];
966
+ let t5;
967
+ if ($[5] !== T1 || $[6] !== t1 || $[7] !== t4) {
968
+ t5 = /* @__PURE__ */ jsx(T1, {
969
+ value: t1,
970
+ children: t4
971
+ });
972
+ $[5] = T1;
973
+ $[6] = t1;
974
+ $[7] = t4;
975
+ $[8] = t5;
976
+ } else t5 = $[8];
977
+ let t6;
978
+ if ($[9] !== T0 || $[10] !== api || $[11] !== t5) {
979
+ t6 = /* @__PURE__ */ jsx(T0, {
980
+ value: api,
981
+ children: t5
982
+ });
983
+ $[9] = T0;
984
+ $[10] = api;
985
+ $[11] = t5;
986
+ $[12] = t6;
987
+ } else t6 = $[12];
988
+ return t6;
989
+ }
990
+ //#endregion
991
+ //#region src/toggle-group/index.ts
992
+ var toggle_group_exports = /* @__PURE__ */ __exportAll({
993
+ Item: () => Item,
994
+ Root: () => Root
995
+ });
996
+ //#endregion
997
+ export { Control as _, download as a, Button as b, Root$1 as c, ValueText as d, Trigger as f, Indicator$1 as g, Input as h, DownloadTrigger as i, Indicator as l, Label as m, Root as n, ColorModeToggle as o, Root$2 as p, Item as r, swap_exports as s, toggle_group_exports as t, clipboard_exports as u, Consumer as v, PropsProvider as x, IconButton as y };