@dillingerstaffing/strand-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1364 -0
  2. package/package.json +58 -0
package/dist/index.js ADDED
@@ -0,0 +1,1364 @@
1
+ import { jsxs as _, jsx as s } from "preact/jsx-runtime";
2
+ import { forwardRef as p } from "preact/compat";
3
+ import { useRef as k, useCallback as b, useEffect as x, useState as B, useContext as R } from "preact/hooks";
4
+ import { createContext as I } from "preact";
5
+ const E = p(
6
+ ({
7
+ variant: a = "primary",
8
+ size: t = "md",
9
+ loading: e = !1,
10
+ iconOnly: n = !1,
11
+ fullWidth: i = !1,
12
+ disabled: o = !1,
13
+ className: r = "",
14
+ children: l,
15
+ onClick: c,
16
+ type: u = "button",
17
+ ...d
18
+ }, h) => {
19
+ const m = o || e, f = [
20
+ "strand-btn",
21
+ `strand-btn--${a}`,
22
+ `strand-btn--${t}`,
23
+ n && "strand-btn--icon-only",
24
+ i && "strand-btn--full-width",
25
+ e && "strand-btn--loading",
26
+ r
27
+ ].filter(Boolean).join(" ");
28
+ return /* @__PURE__ */ _(
29
+ "button",
30
+ {
31
+ ref: h,
32
+ type: u,
33
+ className: f,
34
+ disabled: m,
35
+ "aria-disabled": m ? "true" : void 0,
36
+ "aria-busy": e ? "true" : void 0,
37
+ onClick: m ? void 0 : c,
38
+ ...d,
39
+ children: [
40
+ e && /* @__PURE__ */ s("span", { className: "strand-btn__spinner", "aria-hidden": "true" }),
41
+ /* @__PURE__ */ s(
42
+ "span",
43
+ {
44
+ className: "strand-btn__content",
45
+ style: e ? { visibility: "hidden" } : void 0,
46
+ children: l
47
+ }
48
+ )
49
+ ]
50
+ }
51
+ );
52
+ }
53
+ );
54
+ E.displayName = "Button";
55
+ const K = p(
56
+ ({
57
+ type: a = "text",
58
+ error: t = !1,
59
+ leadingAddon: e,
60
+ trailingAddon: n,
61
+ className: i = "",
62
+ disabled: o,
63
+ ...r
64
+ }, l) => {
65
+ const c = [
66
+ "strand-input",
67
+ t && "strand-input--error",
68
+ o && "strand-input--disabled",
69
+ e && "strand-input--has-leading",
70
+ n && "strand-input--has-trailing",
71
+ i
72
+ ].filter(Boolean).join(" ");
73
+ return /* @__PURE__ */ _("div", { className: c, children: [
74
+ e && /* @__PURE__ */ s("span", { className: "strand-input__leading", "aria-hidden": "true", children: e }),
75
+ /* @__PURE__ */ s(
76
+ "input",
77
+ {
78
+ ref: l,
79
+ type: a,
80
+ className: "strand-input__field",
81
+ disabled: o,
82
+ "aria-invalid": t ? "true" : void 0,
83
+ ...r
84
+ }
85
+ ),
86
+ n && /* @__PURE__ */ s("span", { className: "strand-input__trailing", "aria-hidden": "true", children: n })
87
+ ] });
88
+ }
89
+ );
90
+ K.displayName = "Input";
91
+ const A = p(
92
+ ({
93
+ autoResize: a = !1,
94
+ showCount: t = !1,
95
+ error: e = !1,
96
+ maxLength: n,
97
+ disabled: i,
98
+ className: o = "",
99
+ value: r,
100
+ onInput: l,
101
+ ...c
102
+ }, u) => {
103
+ const d = k(null), h = b(
104
+ (g) => {
105
+ d.current = g, typeof u == "function" ? u(g) : u && (u.current = g);
106
+ },
107
+ [u]
108
+ ), m = b(
109
+ (g) => {
110
+ a && d.current && (d.current.style.height = "auto", d.current.style.height = `${d.current.scrollHeight}px`), l && l(g);
111
+ },
112
+ [a, l]
113
+ ), f = [
114
+ "strand-textarea",
115
+ e && "strand-textarea--error",
116
+ i && "strand-textarea--disabled",
117
+ a && "strand-textarea--auto-resize",
118
+ o
119
+ ].filter(Boolean).join(" "), N = typeof r == "string" ? r.length : 0;
120
+ return /* @__PURE__ */ _("div", { className: f, children: [
121
+ /* @__PURE__ */ s(
122
+ "textarea",
123
+ {
124
+ ref: h,
125
+ className: "strand-textarea__field",
126
+ disabled: i,
127
+ "aria-invalid": e ? "true" : void 0,
128
+ maxLength: n,
129
+ value: r,
130
+ onInput: m,
131
+ ...c
132
+ }
133
+ ),
134
+ t && n != null && /* @__PURE__ */ _("span", { className: "strand-textarea__count", "aria-live": "polite", children: [
135
+ N,
136
+ "/",
137
+ n
138
+ ] })
139
+ ] });
140
+ }
141
+ );
142
+ A.displayName = "Textarea";
143
+ const L = p(
144
+ ({
145
+ options: a,
146
+ value: t,
147
+ onChange: e,
148
+ disabled: n,
149
+ error: i = !1,
150
+ placeholder: o,
151
+ className: r = "",
152
+ ...l
153
+ }, c) => {
154
+ const u = [
155
+ "strand-select",
156
+ i && "strand-select--error",
157
+ n && "strand-select--disabled",
158
+ r
159
+ ].filter(Boolean).join(" ");
160
+ return /* @__PURE__ */ _("div", { className: u, children: [
161
+ /* @__PURE__ */ _(
162
+ "select",
163
+ {
164
+ ref: c,
165
+ className: "strand-select__field",
166
+ value: t,
167
+ onChange: e,
168
+ disabled: n,
169
+ "aria-invalid": i ? "true" : void 0,
170
+ ...l,
171
+ children: [
172
+ o && /* @__PURE__ */ s("option", { value: "", disabled: !0, children: o }),
173
+ a.map((d) => /* @__PURE__ */ s("option", { value: d.value, children: d.label }, d.value))
174
+ ]
175
+ }
176
+ ),
177
+ /* @__PURE__ */ s("span", { className: "strand-select__arrow", "aria-hidden": "true" })
178
+ ] });
179
+ }
180
+ );
181
+ L.displayName = "Select";
182
+ const M = p(
183
+ ({
184
+ checked: a = !1,
185
+ indeterminate: t = !1,
186
+ onChange: e,
187
+ disabled: n = !1,
188
+ label: i,
189
+ className: o = "",
190
+ ...r
191
+ }, l) => {
192
+ const c = k(null);
193
+ x(() => {
194
+ const f = typeof l == "function" ? c.current : (l == null ? void 0 : l.current) ?? c.current;
195
+ f && (f.indeterminate = t);
196
+ }, [t, l]);
197
+ const u = [
198
+ "strand-checkbox",
199
+ a && "strand-checkbox--checked",
200
+ t && "strand-checkbox--indeterminate",
201
+ n && "strand-checkbox--disabled",
202
+ o
203
+ ].filter(Boolean).join(" ");
204
+ return /* @__PURE__ */ _(
205
+ "label",
206
+ {
207
+ className: u,
208
+ onKeyDown: (f) => {
209
+ if (f.key === " " && !n) {
210
+ f.preventDefault();
211
+ const N = c.current;
212
+ N && N.click();
213
+ }
214
+ },
215
+ children: [
216
+ /* @__PURE__ */ s(
217
+ "input",
218
+ {
219
+ ref: (f) => {
220
+ c.current = f, typeof l == "function" ? l(f) : l && (l.current = f);
221
+ },
222
+ type: "checkbox",
223
+ className: "strand-checkbox__native",
224
+ checked: a,
225
+ disabled: n,
226
+ onChange: n ? void 0 : e,
227
+ "aria-checked": t ? "mixed" : a ? "true" : "false",
228
+ role: "checkbox",
229
+ ...r
230
+ }
231
+ ),
232
+ /* @__PURE__ */ s("span", { className: "strand-checkbox__control", "aria-hidden": "true", children: t ? /* @__PURE__ */ s(
233
+ "svg",
234
+ {
235
+ className: "strand-checkbox__icon",
236
+ viewBox: "0 0 16 16",
237
+ fill: "none",
238
+ children: /* @__PURE__ */ s(
239
+ "line",
240
+ {
241
+ x1: "4",
242
+ y1: "8",
243
+ x2: "12",
244
+ y2: "8",
245
+ stroke: "currentColor",
246
+ "stroke-width": "2",
247
+ "stroke-linecap": "round"
248
+ }
249
+ )
250
+ }
251
+ ) : a ? /* @__PURE__ */ s(
252
+ "svg",
253
+ {
254
+ className: "strand-checkbox__icon",
255
+ viewBox: "0 0 16 16",
256
+ fill: "none",
257
+ children: /* @__PURE__ */ s(
258
+ "path",
259
+ {
260
+ d: "M3.5 8L6.5 11L12.5 5",
261
+ stroke: "currentColor",
262
+ "stroke-width": "2",
263
+ "stroke-linecap": "round",
264
+ "stroke-linejoin": "round"
265
+ }
266
+ )
267
+ }
268
+ ) : null }),
269
+ i && /* @__PURE__ */ s("span", { className: "strand-checkbox__label", children: i })
270
+ ]
271
+ }
272
+ );
273
+ }
274
+ );
275
+ M.displayName = "Checkbox";
276
+ const P = p(
277
+ ({
278
+ checked: a = !1,
279
+ onChange: t,
280
+ disabled: e = !1,
281
+ label: n,
282
+ name: i,
283
+ value: o,
284
+ className: r = "",
285
+ ...l
286
+ }, c) => {
287
+ const u = [
288
+ "strand-radio",
289
+ a && "strand-radio--checked",
290
+ e && "strand-radio--disabled",
291
+ r
292
+ ].filter(Boolean).join(" ");
293
+ return /* @__PURE__ */ _("label", { className: u, children: [
294
+ /* @__PURE__ */ s(
295
+ "input",
296
+ {
297
+ ref: c,
298
+ type: "radio",
299
+ className: "strand-radio__native",
300
+ checked: a,
301
+ disabled: e,
302
+ onChange: e ? void 0 : t,
303
+ name: i,
304
+ value: o,
305
+ ...l
306
+ }
307
+ ),
308
+ /* @__PURE__ */ s("span", { className: "strand-radio__control", "aria-hidden": "true", children: /* @__PURE__ */ s("span", { className: "strand-radio__dot" }) }),
309
+ n && /* @__PURE__ */ s("span", { className: "strand-radio__label", children: n })
310
+ ] });
311
+ }
312
+ );
313
+ P.displayName = "Radio";
314
+ const F = p(
315
+ ({
316
+ checked: a = !1,
317
+ onChange: t,
318
+ disabled: e = !1,
319
+ label: n,
320
+ className: i = "",
321
+ ...o
322
+ }, r) => {
323
+ const l = [
324
+ "strand-switch",
325
+ a && "strand-switch--checked",
326
+ e && "strand-switch--disabled",
327
+ i
328
+ ].filter(Boolean).join(" ");
329
+ return /* @__PURE__ */ _("label", { className: l, children: [
330
+ /* @__PURE__ */ s(
331
+ "button",
332
+ {
333
+ ref: r,
334
+ type: "button",
335
+ role: "switch",
336
+ className: "strand-switch__track",
337
+ "aria-checked": a ? "true" : "false",
338
+ disabled: e,
339
+ onClick: () => {
340
+ !e && t && t(!a);
341
+ },
342
+ onKeyDown: (d) => {
343
+ (d.key === " " || d.key === "Enter") && !e && (d.preventDefault(), t && t(!a));
344
+ },
345
+ ...o,
346
+ children: /* @__PURE__ */ s("span", { className: "strand-switch__thumb", "aria-hidden": "true" })
347
+ }
348
+ ),
349
+ n && /* @__PURE__ */ s("span", { className: "strand-switch__label", children: n })
350
+ ] });
351
+ }
352
+ );
353
+ F.displayName = "Switch";
354
+ const q = p(
355
+ ({
356
+ min: a = 0,
357
+ max: t = 100,
358
+ step: e = 1,
359
+ value: n,
360
+ onChange: i,
361
+ disabled: o,
362
+ className: r = "",
363
+ ...l
364
+ }, c) => {
365
+ const u = [
366
+ "strand-slider",
367
+ o && "strand-slider--disabled",
368
+ r
369
+ ].filter(Boolean).join(" ");
370
+ return /* @__PURE__ */ s("div", { className: u, children: /* @__PURE__ */ s(
371
+ "input",
372
+ {
373
+ ref: c,
374
+ type: "range",
375
+ className: "strand-slider__field",
376
+ min: a,
377
+ max: t,
378
+ step: e,
379
+ value: n,
380
+ onChange: i,
381
+ disabled: o,
382
+ "aria-valuemin": a,
383
+ "aria-valuemax": t,
384
+ "aria-valuenow": n,
385
+ ...l
386
+ }
387
+ ) });
388
+ }
389
+ );
390
+ q.displayName = "Slider";
391
+ const G = p(
392
+ ({
393
+ label: a,
394
+ htmlFor: t,
395
+ hint: e,
396
+ error: n,
397
+ required: i = !1,
398
+ className: o = "",
399
+ children: r
400
+ }, l) => {
401
+ const c = [
402
+ "strand-form-field",
403
+ n && "strand-form-field--error",
404
+ o
405
+ ].filter(Boolean).join(" ");
406
+ return /* @__PURE__ */ _("div", { ref: l, className: c, children: [
407
+ /* @__PURE__ */ _("label", { className: "strand-form-field__label", htmlFor: t, children: [
408
+ a,
409
+ i && /* @__PURE__ */ s("span", { className: "strand-form-field__required", "aria-hidden": "true", children: "*" })
410
+ ] }),
411
+ /* @__PURE__ */ s("div", { className: "strand-form-field__control", children: r }),
412
+ n ? /* @__PURE__ */ s(
413
+ "p",
414
+ {
415
+ className: "strand-form-field__error",
416
+ id: `${t}-error`,
417
+ role: "alert",
418
+ children: n
419
+ }
420
+ ) : e ? /* @__PURE__ */ s("p", { className: "strand-form-field__hint", id: `${t}-hint`, children: e }) : null
421
+ ] });
422
+ }
423
+ );
424
+ G.displayName = "FormField";
425
+ const H = p(
426
+ ({
427
+ variant: a = "elevated",
428
+ padding: t = "md",
429
+ className: e = "",
430
+ children: n,
431
+ ...i
432
+ }, o) => {
433
+ const r = [
434
+ "strand-card",
435
+ `strand-card--${a}`,
436
+ `strand-card--pad-${t}`,
437
+ e
438
+ ].filter(Boolean).join(" ");
439
+ return /* @__PURE__ */ s("div", { ref: o, className: r, ...i, children: n });
440
+ }
441
+ );
442
+ H.displayName = "Card";
443
+ const U = p(
444
+ ({
445
+ variant: a = "count",
446
+ status: t = "default",
447
+ count: e,
448
+ maxCount: n = 99,
449
+ className: i = "",
450
+ children: o,
451
+ ...r
452
+ }, l) => {
453
+ const c = o != null && o !== !1, u = a === "count" ? e != null && e > n ? `${n}+` : e : null, d = a === "dot" ? "Status indicator" : e != null ? `${e} notifications` : void 0, h = [
454
+ "strand-badge__indicator",
455
+ `strand-badge--${a}`,
456
+ `strand-badge--${t}`
457
+ ].filter(Boolean).join(" "), m = /* @__PURE__ */ s("span", { className: h, "aria-label": d, role: "status", children: u });
458
+ if (!c) {
459
+ const N = [
460
+ "strand-badge",
461
+ "strand-badge--inline",
462
+ i
463
+ ].filter(Boolean).join(" ");
464
+ return /* @__PURE__ */ s("span", { ref: l, className: N, ...r, children: m });
465
+ }
466
+ const f = ["strand-badge", i].filter(Boolean).join(" ");
467
+ return /* @__PURE__ */ _("span", { ref: l, className: f, ...r, children: [
468
+ o,
469
+ m
470
+ ] });
471
+ }
472
+ );
473
+ U.displayName = "Badge";
474
+ const V = p(
475
+ ({
476
+ src: a,
477
+ alt: t = "",
478
+ initials: e = "",
479
+ size: n = "md",
480
+ className: i = "",
481
+ ...o
482
+ }, r) => {
483
+ const [l, c] = B(!1), u = b(() => {
484
+ c(!0);
485
+ }, []), d = a && !l, h = e.slice(0, 2).toUpperCase(), m = [
486
+ "strand-avatar",
487
+ `strand-avatar--${n}`,
488
+ i
489
+ ].filter(Boolean).join(" ");
490
+ return /* @__PURE__ */ s("div", { ref: r, className: m, role: "img", "aria-label": t || h, ...o, children: d ? /* @__PURE__ */ s(
491
+ "img",
492
+ {
493
+ className: "strand-avatar__img",
494
+ src: a,
495
+ alt: t,
496
+ onError: u
497
+ }
498
+ ) : /* @__PURE__ */ s("span", { className: "strand-avatar__initials", "aria-hidden": "true", children: h }) });
499
+ }
500
+ );
501
+ V.displayName = "Avatar";
502
+ const z = p(
503
+ ({
504
+ variant: a = "solid",
505
+ status: t = "default",
506
+ removable: e = !1,
507
+ onRemove: n,
508
+ className: i = "",
509
+ children: o,
510
+ ...r
511
+ }, l) => {
512
+ const c = [
513
+ "strand-tag",
514
+ `strand-tag--${a}`,
515
+ `strand-tag--${t}`,
516
+ i
517
+ ].filter(Boolean).join(" ");
518
+ return /* @__PURE__ */ _("span", { ref: l, className: c, ...r, children: [
519
+ /* @__PURE__ */ s("span", { className: "strand-tag__text", children: o }),
520
+ e && /* @__PURE__ */ s(
521
+ "button",
522
+ {
523
+ type: "button",
524
+ className: "strand-tag__remove",
525
+ "aria-label": "Remove",
526
+ onClick: n,
527
+ children: /* @__PURE__ */ s(
528
+ "svg",
529
+ {
530
+ width: "12",
531
+ height: "12",
532
+ viewBox: "0 0 12 12",
533
+ fill: "none",
534
+ "aria-hidden": "true",
535
+ children: /* @__PURE__ */ s(
536
+ "path",
537
+ {
538
+ d: "M3 3l6 6M9 3l-6 6",
539
+ stroke: "currentColor",
540
+ "stroke-width": "1.5",
541
+ "stroke-linecap": "round"
542
+ }
543
+ )
544
+ }
545
+ )
546
+ }
547
+ )
548
+ ] });
549
+ }
550
+ );
551
+ z.displayName = "Tag";
552
+ const O = p(
553
+ ({ columns: a, data: t, onSort: e, className: n = "", ...i }, o) => {
554
+ const [r, l] = B(null), [c, u] = B("asc"), d = b(
555
+ (m) => {
556
+ const f = r === m && c === "asc" ? "desc" : "asc";
557
+ l(m), u(f), e == null || e(m, f);
558
+ },
559
+ [r, c, e]
560
+ ), h = ["strand-table-wrapper", n].filter(Boolean).join(" ");
561
+ return /* @__PURE__ */ s("div", { ref: o, className: h, ...i, children: /* @__PURE__ */ _("table", { className: "strand-table", children: [
562
+ /* @__PURE__ */ s("thead", { className: "strand-table__head", children: /* @__PURE__ */ s("tr", { children: a.map((m) => /* @__PURE__ */ s(
563
+ "th",
564
+ {
565
+ className: "strand-table__th",
566
+ style: m.width ? { width: m.width } : void 0,
567
+ children: m.sortable ? /* @__PURE__ */ _(
568
+ "button",
569
+ {
570
+ type: "button",
571
+ className: "strand-table__sort-btn",
572
+ onClick: () => d(m.key),
573
+ "aria-label": `Sort by ${m.header}`,
574
+ children: [
575
+ m.header,
576
+ /* @__PURE__ */ s(
577
+ "span",
578
+ {
579
+ className: "strand-table__sort-indicator",
580
+ "aria-hidden": "true",
581
+ children: r === m.key ? c === "asc" ? "↑" : "↓" : "↕"
582
+ }
583
+ )
584
+ ]
585
+ }
586
+ ) : m.header
587
+ },
588
+ m.key
589
+ )) }) }),
590
+ /* @__PURE__ */ s("tbody", { className: "strand-table__body", children: t.map((m, f) => /* @__PURE__ */ s("tr", { className: "strand-table__row", children: a.map((N) => /* @__PURE__ */ s("td", { className: "strand-table__td", children: m[N.key] }, N.key)) }, f)) })
591
+ ] }) });
592
+ }
593
+ );
594
+ O.displayName = "Table";
595
+ const W = p(
596
+ ({ label: a, value: t, className: e = "", ...n }, i) => {
597
+ const o = ["strand-data-readout", e].filter(Boolean).join(" ");
598
+ return /* @__PURE__ */ _("div", { ref: i, className: o, ...n, children: [
599
+ /* @__PURE__ */ s("span", { className: "strand-data-readout__label", children: a }),
600
+ /* @__PURE__ */ s("span", { className: "strand-data-readout__value", children: t })
601
+ ] });
602
+ }
603
+ );
604
+ W.displayName = "DataReadout";
605
+ const Z = p(
606
+ ({
607
+ direction: a = "vertical",
608
+ gap: t = 4,
609
+ align: e = "stretch",
610
+ wrap: n = !1,
611
+ justify: i,
612
+ className: o = "",
613
+ style: r,
614
+ children: l,
615
+ ...c
616
+ }, u) => {
617
+ const d = [
618
+ "strand-stack",
619
+ `strand-stack--${a}`,
620
+ e !== "stretch" && `strand-stack--align-${e}`,
621
+ i && `strand-stack--justify-${i}`,
622
+ n && "strand-stack--wrap",
623
+ o
624
+ ].filter(Boolean).join(" "), h = {
625
+ gap: `var(--strand-space-${t})`
626
+ };
627
+ return /* @__PURE__ */ s(
628
+ "div",
629
+ {
630
+ ref: u,
631
+ className: d,
632
+ style: { ...h, ...r },
633
+ ...c,
634
+ children: l
635
+ }
636
+ );
637
+ }
638
+ );
639
+ Z.displayName = "Stack";
640
+ const J = p(
641
+ ({
642
+ columns: a = 1,
643
+ gap: t = 4,
644
+ className: e = "",
645
+ style: n,
646
+ children: i,
647
+ ...o
648
+ }, r) => {
649
+ const l = ["strand-grid", e].filter(Boolean).join(" "), c = {
650
+ gridTemplateColumns: `repeat(${a}, 1fr)`,
651
+ gap: `var(--strand-space-${t})`
652
+ };
653
+ return /* @__PURE__ */ s(
654
+ "div",
655
+ {
656
+ ref: r,
657
+ className: l,
658
+ style: { ...c, ...n },
659
+ ...o,
660
+ children: i
661
+ }
662
+ );
663
+ }
664
+ );
665
+ J.displayName = "Grid";
666
+ const Q = p(
667
+ ({
668
+ size: a = "default",
669
+ className: t = "",
670
+ children: e,
671
+ ...n
672
+ }, i) => {
673
+ const o = [
674
+ "strand-container",
675
+ `strand-container--${a}`,
676
+ t
677
+ ].filter(Boolean).join(" ");
678
+ return /* @__PURE__ */ s("div", { ref: i, className: o, ...n, children: e });
679
+ }
680
+ );
681
+ Q.displayName = "Container";
682
+ const X = p(
683
+ ({ direction: a = "horizontal", label: t, className: e = "" }, n) => {
684
+ if (a === "vertical") {
685
+ const r = [
686
+ "strand-divider",
687
+ "strand-divider--vertical",
688
+ e
689
+ ].filter(Boolean).join(" ");
690
+ return /* @__PURE__ */ s(
691
+ "div",
692
+ {
693
+ ref: n,
694
+ role: "separator",
695
+ "aria-orientation": "vertical",
696
+ className: r
697
+ }
698
+ );
699
+ }
700
+ if (t) {
701
+ const r = [
702
+ "strand-divider",
703
+ "strand-divider--horizontal",
704
+ "strand-divider--labeled",
705
+ e
706
+ ].filter(Boolean).join(" ");
707
+ return /* @__PURE__ */ _(
708
+ "div",
709
+ {
710
+ ref: n,
711
+ role: "separator",
712
+ "aria-orientation": "horizontal",
713
+ className: r,
714
+ children: [
715
+ /* @__PURE__ */ s("span", { className: "strand-divider__line" }),
716
+ /* @__PURE__ */ s("span", { className: "strand-divider__label", children: t }),
717
+ /* @__PURE__ */ s("span", { className: "strand-divider__line" })
718
+ ]
719
+ }
720
+ );
721
+ }
722
+ const o = [
723
+ "strand-divider",
724
+ "strand-divider--horizontal",
725
+ e
726
+ ].filter(Boolean).join(" ");
727
+ return /* @__PURE__ */ s(
728
+ "hr",
729
+ {
730
+ ref: n,
731
+ role: "separator",
732
+ "aria-orientation": "horizontal",
733
+ className: o
734
+ }
735
+ );
736
+ }
737
+ );
738
+ X.displayName = "Divider";
739
+ const Y = p(
740
+ ({
741
+ variant: a = "standard",
742
+ background: t = "primary",
743
+ className: e = "",
744
+ children: n,
745
+ ...i
746
+ }, o) => {
747
+ const r = [
748
+ "strand-section",
749
+ `strand-section--${a}`,
750
+ `strand-section--bg-${t}`,
751
+ e
752
+ ].filter(Boolean).join(" ");
753
+ return /* @__PURE__ */ s("section", { ref: o, className: r, ...i, children: n });
754
+ }
755
+ );
756
+ Y.displayName = "Section";
757
+ const aa = p(
758
+ ({ href: a, external: t = !1, className: e = "", children: n, ...i }, o) => {
759
+ const r = ["strand-link", e].filter(Boolean).join(" ");
760
+ return /* @__PURE__ */ s(
761
+ "a",
762
+ {
763
+ ref: o,
764
+ href: a,
765
+ className: r,
766
+ ...t && { target: "_blank", rel: "noopener noreferrer" },
767
+ ...i,
768
+ children: n
769
+ }
770
+ );
771
+ }
772
+ );
773
+ aa.displayName = "Link";
774
+ const ea = p(
775
+ ({ tabs: a, activeTab: t, onChange: e, className: n = "", ...i }, o) => {
776
+ const r = k(null), l = ["strand-tabs", n].filter(Boolean).join(" "), c = b(
777
+ (d) => {
778
+ var m, f;
779
+ const h = a[d];
780
+ if (h) {
781
+ e(h.id);
782
+ const N = (m = r.current) == null ? void 0 : m.querySelectorAll(
783
+ '[role="tab"]'
784
+ );
785
+ (f = N == null ? void 0 : N[d]) == null || f.focus();
786
+ }
787
+ },
788
+ [a, e]
789
+ ), u = b(
790
+ (d) => {
791
+ const h = a.findIndex((f) => f.id === t);
792
+ let m = null;
793
+ switch (d.key) {
794
+ case "ArrowRight":
795
+ m = (h + 1) % a.length;
796
+ break;
797
+ case "ArrowLeft":
798
+ m = (h - 1 + a.length) % a.length;
799
+ break;
800
+ case "Home":
801
+ m = 0;
802
+ break;
803
+ case "End":
804
+ m = a.length - 1;
805
+ break;
806
+ default:
807
+ return;
808
+ }
809
+ d.preventDefault(), c(m);
810
+ },
811
+ [a, t, c]
812
+ );
813
+ return /* @__PURE__ */ _("div", { ref: o, className: l, ...i, children: [
814
+ /* @__PURE__ */ s(
815
+ "div",
816
+ {
817
+ ref: r,
818
+ role: "tablist",
819
+ onKeyDown: u,
820
+ children: a.map((d) => {
821
+ const h = d.id === t, m = [
822
+ "strand-tabs__tab",
823
+ h && "strand-tabs__tab--active"
824
+ ].filter(Boolean).join(" ");
825
+ return /* @__PURE__ */ s(
826
+ "button",
827
+ {
828
+ id: `tab-${d.id}`,
829
+ role: "tab",
830
+ type: "button",
831
+ className: m,
832
+ "aria-selected": h ? "true" : "false",
833
+ "aria-controls": `panel-${d.id}`,
834
+ tabIndex: h ? 0 : -1,
835
+ onClick: () => e(d.id),
836
+ children: d.label
837
+ },
838
+ d.id
839
+ );
840
+ })
841
+ }
842
+ ),
843
+ a.map((d) => {
844
+ const h = d.id === t;
845
+ return /* @__PURE__ */ s(
846
+ "div",
847
+ {
848
+ id: `panel-${d.id}`,
849
+ role: "tabpanel",
850
+ "aria-labelledby": `tab-${d.id}`,
851
+ hidden: !h,
852
+ tabIndex: 0,
853
+ children: d.content
854
+ },
855
+ d.id
856
+ );
857
+ })
858
+ ] });
859
+ }
860
+ );
861
+ ea.displayName = "Tabs";
862
+ const sa = p(
863
+ ({ items: a, separator: t = "/", className: e = "", ...n }, i) => {
864
+ const o = ["strand-breadcrumb", e].filter(Boolean).join(" ");
865
+ return /* @__PURE__ */ s("nav", { ref: i, "aria-label": "Breadcrumb", className: o, ...n, children: /* @__PURE__ */ s("ol", { className: "strand-breadcrumb__list", children: a.map((r, l) => {
866
+ const c = l === a.length - 1;
867
+ return /* @__PURE__ */ _("li", { className: "strand-breadcrumb__item", children: [
868
+ l > 0 && /* @__PURE__ */ s("span", { className: "strand-breadcrumb__separator", "aria-hidden": "true", children: t }),
869
+ c ? /* @__PURE__ */ s(
870
+ "span",
871
+ {
872
+ className: "strand-breadcrumb__current",
873
+ "aria-current": "page",
874
+ children: r.label
875
+ }
876
+ ) : /* @__PURE__ */ s("a", { href: r.href, className: "strand-breadcrumb__link", children: r.label })
877
+ ] }, `${r.label}-${l}`);
878
+ }) }) });
879
+ }
880
+ );
881
+ sa.displayName = "Breadcrumb";
882
+ const ta = p(
883
+ ({ logo: a, items: t = [], actions: e, className: n = "", ...i }, o) => {
884
+ const [r, l] = B(!1), c = b(() => {
885
+ l((d) => !d);
886
+ }, []), u = ["strand-nav", n].filter(Boolean).join(" ");
887
+ return /* @__PURE__ */ _("nav", { ref: o, className: u, "aria-label": "Main navigation", ...i, children: [
888
+ /* @__PURE__ */ _("div", { className: "strand-nav__inner", children: [
889
+ a && /* @__PURE__ */ s("div", { className: "strand-nav__logo", children: a }),
890
+ /* @__PURE__ */ s("div", { className: "strand-nav__items", children: t.map((d) => {
891
+ const h = [
892
+ "strand-nav__link",
893
+ d.active && "strand-nav__link--active"
894
+ ].filter(Boolean).join(" ");
895
+ return /* @__PURE__ */ s(
896
+ "a",
897
+ {
898
+ href: d.href,
899
+ className: h,
900
+ "aria-current": d.active ? "page" : void 0,
901
+ children: d.label
902
+ },
903
+ d.href
904
+ );
905
+ }) }),
906
+ e && /* @__PURE__ */ s("div", { className: "strand-nav__actions", children: e }),
907
+ /* @__PURE__ */ s(
908
+ "button",
909
+ {
910
+ type: "button",
911
+ className: "strand-nav__hamburger",
912
+ "aria-expanded": r ? "true" : "false",
913
+ "aria-label": r ? "Close menu" : "Menu",
914
+ onClick: c,
915
+ children: /* @__PURE__ */ s("span", { className: "strand-nav__hamburger-icon", "aria-hidden": "true" })
916
+ }
917
+ )
918
+ ] }),
919
+ r && /* @__PURE__ */ s("div", { className: "strand-nav__mobile-menu", children: t.map((d) => {
920
+ const h = [
921
+ "strand-nav__mobile-link",
922
+ d.active && "strand-nav__mobile-link--active"
923
+ ].filter(Boolean).join(" ");
924
+ return /* @__PURE__ */ s(
925
+ "a",
926
+ {
927
+ href: d.href,
928
+ className: h,
929
+ "aria-current": d.active ? "page" : void 0,
930
+ children: d.label
931
+ },
932
+ d.href
933
+ );
934
+ }) })
935
+ ] });
936
+ }
937
+ );
938
+ ta.displayName = "Nav";
939
+ const S = I(null);
940
+ function ya() {
941
+ const a = R(S);
942
+ if (!a)
943
+ throw new Error("useToast must be used within a ToastProvider");
944
+ return a;
945
+ }
946
+ let na = 0;
947
+ const ra = ({ children: a, className: t = "" }) => {
948
+ const [e, n] = B([]), i = b((l) => {
949
+ n((c) => c.filter((u) => u.id !== l));
950
+ }, []), o = b((l) => {
951
+ const c = {
952
+ id: ++na,
953
+ message: l.message,
954
+ status: l.status ?? "info",
955
+ duration: l.duration ?? 5e3
956
+ };
957
+ n((u) => [...u, c]);
958
+ }, []), r = ["strand-toast__container", t].filter(Boolean).join(" ");
959
+ return /* @__PURE__ */ _(S.Provider, { value: { toast: o }, children: [
960
+ a,
961
+ e.length > 0 && /* @__PURE__ */ s("div", { className: r, children: e.map((l) => /* @__PURE__ */ s(
962
+ la,
963
+ {
964
+ entry: l,
965
+ onDismiss: () => i(l.id)
966
+ },
967
+ l.id
968
+ )) })
969
+ ] });
970
+ };
971
+ ra.displayName = "ToastProvider";
972
+ function la({ entry: a, onDismiss: t }) {
973
+ const e = k(null);
974
+ x(() => (a.duration > 0 && (e.current = setTimeout(t, a.duration)), () => {
975
+ e.current !== null && clearTimeout(e.current);
976
+ }), [a.duration, t]);
977
+ const n = a.status === "error" || a.status === "warning", i = ["strand-toast", `strand-toast--${a.status}`].filter(Boolean).join(" ");
978
+ return /* @__PURE__ */ _(
979
+ "div",
980
+ {
981
+ className: i,
982
+ role: "status",
983
+ "aria-live": n ? "assertive" : "polite",
984
+ children: [
985
+ /* @__PURE__ */ s("span", { className: "strand-toast__message", children: a.message }),
986
+ /* @__PURE__ */ s(
987
+ "button",
988
+ {
989
+ type: "button",
990
+ className: "strand-toast__dismiss",
991
+ "aria-label": "Dismiss",
992
+ onClick: t,
993
+ children: "×"
994
+ }
995
+ )
996
+ ]
997
+ }
998
+ );
999
+ }
1000
+ const ia = p(
1001
+ ({ status: a = "info", message: t, onDismiss: e, className: n = "", ...i }, o) => {
1002
+ const r = a === "error" || a === "warning", l = [
1003
+ "strand-toast",
1004
+ `strand-toast--${a}`,
1005
+ n
1006
+ ].filter(Boolean).join(" ");
1007
+ return /* @__PURE__ */ _(
1008
+ "div",
1009
+ {
1010
+ ref: o,
1011
+ className: l,
1012
+ role: "status",
1013
+ "aria-live": r ? "assertive" : "polite",
1014
+ ...i,
1015
+ children: [
1016
+ /* @__PURE__ */ s("span", { className: "strand-toast__message", children: t }),
1017
+ e && /* @__PURE__ */ s(
1018
+ "button",
1019
+ {
1020
+ type: "button",
1021
+ className: "strand-toast__dismiss",
1022
+ "aria-label": "Dismiss",
1023
+ onClick: e,
1024
+ children: "×"
1025
+ }
1026
+ )
1027
+ ]
1028
+ }
1029
+ );
1030
+ }
1031
+ );
1032
+ ia.displayName = "Toast";
1033
+ const oa = p(
1034
+ ({
1035
+ status: a = "info",
1036
+ dismissible: t = !1,
1037
+ onDismiss: e,
1038
+ className: n = "",
1039
+ children: i,
1040
+ ...o
1041
+ }, r) => {
1042
+ const l = a === "error" || a === "warning" ? "alert" : "status", c = [
1043
+ "strand-alert",
1044
+ `strand-alert--${a}`,
1045
+ n
1046
+ ].filter(Boolean).join(" ");
1047
+ return /* @__PURE__ */ _("div", { ref: r, className: c, role: l, ...o, children: [
1048
+ /* @__PURE__ */ s("div", { className: "strand-alert__content", children: i }),
1049
+ t && /* @__PURE__ */ s(
1050
+ "button",
1051
+ {
1052
+ type: "button",
1053
+ className: "strand-alert__dismiss",
1054
+ "aria-label": "Dismiss",
1055
+ onClick: e,
1056
+ children: "×"
1057
+ }
1058
+ )
1059
+ ] });
1060
+ }
1061
+ );
1062
+ oa.displayName = "Alert";
1063
+ const T = 'a[href], button:not(:disabled), textarea:not(:disabled), input:not(:disabled), select:not(:disabled), [tabindex]:not([tabindex="-1"])';
1064
+ let da = 0;
1065
+ const ca = p(
1066
+ ({
1067
+ open: a,
1068
+ onClose: t,
1069
+ title: e,
1070
+ closeOnOutsideClick: n = !0,
1071
+ closeOnEscape: i = !0,
1072
+ className: o = "",
1073
+ children: r,
1074
+ ...l
1075
+ }, c) => {
1076
+ const u = k(null), d = k(null), m = k(`strand-dialog-title-${++da}`).current;
1077
+ x(() => {
1078
+ if (!a) return;
1079
+ d.current = document.activeElement;
1080
+ const v = requestAnimationFrame(() => {
1081
+ const y = u.current;
1082
+ if (!y) return;
1083
+ const w = y.querySelectorAll(T);
1084
+ w.length > 0 ? w[0].focus() : y.focus();
1085
+ });
1086
+ return () => {
1087
+ cancelAnimationFrame(v);
1088
+ const y = d.current;
1089
+ y && y instanceof HTMLElement && y.focus();
1090
+ };
1091
+ }, [a]), x(() => {
1092
+ if (!a) return;
1093
+ const v = document.body.style.overflow;
1094
+ return document.body.style.overflow = "hidden", () => {
1095
+ document.body.style.overflow = v;
1096
+ };
1097
+ }, [a]);
1098
+ const f = b(
1099
+ (v) => {
1100
+ if (v.key === "Escape" && i) {
1101
+ v.stopPropagation(), t();
1102
+ return;
1103
+ }
1104
+ if (v.key === "Tab") {
1105
+ const y = u.current;
1106
+ if (!y) return;
1107
+ const w = Array.from(
1108
+ y.querySelectorAll(T)
1109
+ );
1110
+ if (w.length === 0) return;
1111
+ const j = w[0], C = w[w.length - 1];
1112
+ v.shiftKey ? document.activeElement === j && (v.preventDefault(), C.focus()) : document.activeElement === C && (v.preventDefault(), j.focus());
1113
+ }
1114
+ },
1115
+ [i, t]
1116
+ ), N = b(
1117
+ (v) => {
1118
+ n && v.target === v.currentTarget && t();
1119
+ },
1120
+ [n, t]
1121
+ );
1122
+ if (!a) return null;
1123
+ const g = ["strand-dialog__panel", o].filter(Boolean).join(" ");
1124
+ return /* @__PURE__ */ s(
1125
+ "div",
1126
+ {
1127
+ className: "strand-dialog__backdrop",
1128
+ onClick: N,
1129
+ onKeyDown: f,
1130
+ children: /* @__PURE__ */ _(
1131
+ "div",
1132
+ {
1133
+ ref: (v) => {
1134
+ u.current = v, typeof c == "function" ? c(v) : c && (c.current = v);
1135
+ },
1136
+ className: g,
1137
+ role: "dialog",
1138
+ "aria-modal": "true",
1139
+ "aria-labelledby": e ? m : void 0,
1140
+ tabIndex: -1,
1141
+ ...l,
1142
+ children: [
1143
+ e && /* @__PURE__ */ s("div", { className: "strand-dialog__header", children: /* @__PURE__ */ s("h2", { id: m, className: "strand-dialog__title", children: e }) }),
1144
+ /* @__PURE__ */ s(
1145
+ "button",
1146
+ {
1147
+ type: "button",
1148
+ className: "strand-dialog__close",
1149
+ "aria-label": "Close",
1150
+ onClick: t,
1151
+ children: "×"
1152
+ }
1153
+ ),
1154
+ /* @__PURE__ */ s("div", { className: "strand-dialog__body", children: r })
1155
+ ]
1156
+ }
1157
+ )
1158
+ }
1159
+ );
1160
+ }
1161
+ );
1162
+ ca.displayName = "Dialog";
1163
+ let ua = 0;
1164
+ const ma = p(
1165
+ ({
1166
+ content: a,
1167
+ position: t = "top",
1168
+ delay: e = 200,
1169
+ className: n = "",
1170
+ children: i,
1171
+ ...o
1172
+ }, r) => {
1173
+ const [l, c] = B(!1), u = k(null), h = k(`strand-tooltip-${++ua}`).current, m = b(() => {
1174
+ u.current = setTimeout(() => {
1175
+ c(!0);
1176
+ }, e);
1177
+ }, [e]), f = b(() => {
1178
+ u.current !== null && (clearTimeout(u.current), u.current = null), c(!1);
1179
+ }, []), N = ["strand-tooltip__wrapper", n].filter(Boolean).join(" "), g = [
1180
+ "strand-tooltip",
1181
+ `strand-tooltip--${t}`,
1182
+ l && "strand-tooltip--visible"
1183
+ ].filter(Boolean).join(" ");
1184
+ return /* @__PURE__ */ _(
1185
+ "span",
1186
+ {
1187
+ ref: r,
1188
+ className: N,
1189
+ onMouseEnter: m,
1190
+ onMouseLeave: f,
1191
+ onFocus: m,
1192
+ onBlur: f,
1193
+ "aria-describedby": h,
1194
+ ...o,
1195
+ children: [
1196
+ i,
1197
+ /* @__PURE__ */ s(
1198
+ "span",
1199
+ {
1200
+ id: h,
1201
+ className: g,
1202
+ role: "tooltip",
1203
+ "aria-hidden": !l,
1204
+ children: a
1205
+ }
1206
+ )
1207
+ ]
1208
+ }
1209
+ );
1210
+ }
1211
+ );
1212
+ ma.displayName = "Tooltip";
1213
+ const D = { sm: 24, md: 40, lg: 56 }, $ = 3, ha = p(
1214
+ ({
1215
+ variant: a = "bar",
1216
+ value: t,
1217
+ size: e = "md",
1218
+ className: n = "",
1219
+ ...i
1220
+ }, o) => {
1221
+ const r = t != null, l = [
1222
+ "strand-progress",
1223
+ `strand-progress--${a}`,
1224
+ `strand-progress--${e}`,
1225
+ !r && "strand-progress--indeterminate",
1226
+ n
1227
+ ].filter(Boolean).join(" "), c = {
1228
+ role: "progressbar",
1229
+ "aria-valuemin": 0,
1230
+ "aria-valuemax": 100
1231
+ };
1232
+ if (r && (c["aria-valuenow"] = t), a === "ring") {
1233
+ const u = D[e] ?? D.md, d = (u - $) / 2, h = 2 * Math.PI * d, m = r ? h - h * t / 100 : 0;
1234
+ return /* @__PURE__ */ s("div", { ref: o, className: l, ...c, ...i, children: /* @__PURE__ */ _(
1235
+ "svg",
1236
+ {
1237
+ width: u,
1238
+ height: u,
1239
+ viewBox: `0 0 ${u} ${u}`,
1240
+ className: "strand-progress__ring",
1241
+ children: [
1242
+ /* @__PURE__ */ s(
1243
+ "circle",
1244
+ {
1245
+ cx: u / 2,
1246
+ cy: u / 2,
1247
+ r: d,
1248
+ fill: "none",
1249
+ "stroke-width": $,
1250
+ className: "strand-progress__track"
1251
+ }
1252
+ ),
1253
+ /* @__PURE__ */ s(
1254
+ "circle",
1255
+ {
1256
+ cx: u / 2,
1257
+ cy: u / 2,
1258
+ r: d,
1259
+ fill: "none",
1260
+ "stroke-width": $,
1261
+ "stroke-dasharray": h,
1262
+ "stroke-dashoffset": r ? m : void 0,
1263
+ "stroke-linecap": "round",
1264
+ className: "strand-progress__fill",
1265
+ transform: `rotate(-90 ${u / 2} ${u / 2})`
1266
+ }
1267
+ )
1268
+ ]
1269
+ }
1270
+ ) });
1271
+ }
1272
+ return /* @__PURE__ */ s("div", { ref: o, className: l, ...c, ...i, children: /* @__PURE__ */ s(
1273
+ "div",
1274
+ {
1275
+ className: "strand-progress__fill",
1276
+ style: r ? { width: `${t}%` } : void 0
1277
+ }
1278
+ ) });
1279
+ }
1280
+ );
1281
+ ha.displayName = "Progress";
1282
+ const pa = p(
1283
+ ({
1284
+ size: a = "md",
1285
+ className: t = "",
1286
+ ...e
1287
+ }, n) => {
1288
+ const i = [
1289
+ "strand-spinner",
1290
+ `strand-spinner--${a}`,
1291
+ t
1292
+ ].filter(Boolean).join(" ");
1293
+ return /* @__PURE__ */ _("span", { ref: n, className: i, role: "status", ...e, children: [
1294
+ /* @__PURE__ */ s("span", { className: "strand-spinner__ring", "aria-hidden": "true" }),
1295
+ /* @__PURE__ */ s("span", { className: "strand-spinner__sr-only", children: "Loading" })
1296
+ ] });
1297
+ }
1298
+ );
1299
+ pa.displayName = "Spinner";
1300
+ const fa = p(
1301
+ ({
1302
+ variant: a = "text",
1303
+ width: t,
1304
+ height: e,
1305
+ className: n = "",
1306
+ ...i
1307
+ }, o) => {
1308
+ const r = t ?? (a === "text" ? "100%" : void 0), l = a === "circle" ? r : e, c = [
1309
+ "strand-skeleton",
1310
+ `strand-skeleton--${a}`,
1311
+ "strand-skeleton--shimmer",
1312
+ n
1313
+ ].filter(Boolean).join(" ");
1314
+ return /* @__PURE__ */ s(
1315
+ "div",
1316
+ {
1317
+ ref: o,
1318
+ className: c,
1319
+ "aria-hidden": "true",
1320
+ style: {
1321
+ width: r,
1322
+ height: l
1323
+ },
1324
+ ...i
1325
+ }
1326
+ );
1327
+ }
1328
+ );
1329
+ fa.displayName = "Skeleton";
1330
+ export {
1331
+ oa as Alert,
1332
+ V as Avatar,
1333
+ U as Badge,
1334
+ sa as Breadcrumb,
1335
+ E as Button,
1336
+ H as Card,
1337
+ M as Checkbox,
1338
+ Q as Container,
1339
+ W as DataReadout,
1340
+ ca as Dialog,
1341
+ X as Divider,
1342
+ G as FormField,
1343
+ J as Grid,
1344
+ K as Input,
1345
+ aa as Link,
1346
+ ta as Nav,
1347
+ ha as Progress,
1348
+ P as Radio,
1349
+ Y as Section,
1350
+ L as Select,
1351
+ fa as Skeleton,
1352
+ q as Slider,
1353
+ pa as Spinner,
1354
+ Z as Stack,
1355
+ F as Switch,
1356
+ O as Table,
1357
+ ea as Tabs,
1358
+ z as Tag,
1359
+ A as Textarea,
1360
+ ia as Toast,
1361
+ ra as ToastProvider,
1362
+ ma as Tooltip,
1363
+ ya as useToast
1364
+ };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@dillingerstaffing/strand-ui",
3
+ "version": "0.1.0",
4
+ "description": "Strand UI - Preact/React component library built on the Strand Design Language",
5
+ "author": "Dillinger Staffing <engineering@dillingerstaffing.com> (https://dillingerstaffing.com)",
6
+ "license": "MIT",
7
+ "homepage": "https://dillingerstaffing.com/labs/strand",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/dillingerstaffing/strand",
11
+ "directory": "packages/strand-ui"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/dillingerstaffing/strand/issues"
15
+ },
16
+ "type": "module",
17
+ "main": "./dist/index.js",
18
+ "module": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ },
25
+ "./css/*": "./dist/css/*"
26
+ },
27
+ "files": [
28
+ "dist/"
29
+ ],
30
+ "sideEffects": [
31
+ "dist/css/*.css"
32
+ ],
33
+ "scripts": {
34
+ "build": "vite build",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest",
37
+ "test:coverage": "vitest run --coverage"
38
+ },
39
+ "peerDependencies": {
40
+ "preact": "^10.0.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "preact": {
44
+ "optional": false
45
+ }
46
+ },
47
+ "dependencies": {
48
+ "@dillingerstaffing/strand": "workspace:*"
49
+ },
50
+ "devDependencies": {
51
+ "@testing-library/preact": "^3.2.0",
52
+ "@testing-library/jest-dom": "^6.6.0",
53
+ "jsdom": "^26.0.0",
54
+ "preact": "^10.25.0",
55
+ "vite": "^6.0.0",
56
+ "vitest": "^3.0.0"
57
+ }
58
+ }