@staqforce.studio/staqui 0.0.0-stage → 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.
package/dist/index.cjs ADDED
@@ -0,0 +1,1538 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // src/index.ts
33
+ var index_exports = {};
34
+ __export(index_exports, {
35
+ Avatar: () => Avatar,
36
+ Badge: () => Badge,
37
+ Banner: () => Banner,
38
+ Box: () => Box,
39
+ Button: () => Button,
40
+ ButtonGroup: () => ButtonGroup,
41
+ Checkbox: () => Checkbox,
42
+ Chip: () => Chip,
43
+ ChoiceList: () => ChoiceList,
44
+ Clickable: () => Clickable,
45
+ ClickableChip: () => ClickableChip,
46
+ ColorField: () => ColorField,
47
+ ColorPicker: () => ColorPicker,
48
+ DateField: () => DateField,
49
+ DatePicker: () => DatePicker,
50
+ Divider: () => Divider,
51
+ DropZone: () => DropZone,
52
+ EmailField: () => EmailField,
53
+ EmptyState: () => EmptyState,
54
+ Grid: () => Grid,
55
+ Heading: () => Heading,
56
+ Icon: () => Icon,
57
+ Image: () => Image,
58
+ Link: () => Link,
59
+ ListItem: () => ListItem,
60
+ Menu: () => Menu,
61
+ Modal: () => Modal,
62
+ MoneyField: () => MoneyField,
63
+ Number: () => Number,
64
+ NumberField: () => NumberField,
65
+ OrderedList: () => OrderedList,
66
+ Page: () => Page,
67
+ Paragraph: () => Paragraph,
68
+ PasswordField: () => PasswordField,
69
+ Popover: () => Popover,
70
+ Progress: () => Progress,
71
+ QueryContainer: () => QueryContainer,
72
+ SearchField: () => SearchField,
73
+ Section: () => Section,
74
+ Select: () => Select,
75
+ Spinner: () => Spinner,
76
+ Stack: () => Stack,
77
+ StaqContext: () => StaqContext,
78
+ StaqProvider: () => StaqProvider,
79
+ Switch: () => Switch,
80
+ Table: () => Table,
81
+ Text: () => Text,
82
+ TextArea: () => TextArea,
83
+ TextField: () => TextField,
84
+ Thumbnail: () => Thumbnail,
85
+ Tooltip: () => Tooltip,
86
+ URLField: () => URLField,
87
+ UnorderedList: () => UnorderedList,
88
+ cx: () => cx,
89
+ icons: () => icons,
90
+ useControllable: () => useControllable,
91
+ useStaq: () => useStaq
92
+ });
93
+ module.exports = __toCommonJS(index_exports);
94
+
95
+ // src/shared.ts
96
+ var import_react = require("react");
97
+ var cx = (...values) => values.filter(Boolean).join(" ");
98
+ function useControllable(value, defaultValue, onChange, controlled = value !== void 0) {
99
+ const [internal, setInternal] = (0, import_react.useState)(defaultValue);
100
+ return [
101
+ controlled ? value : internal,
102
+ (next) => {
103
+ if (!controlled) setInternal(next);
104
+ onChange?.(next);
105
+ }
106
+ ];
107
+ }
108
+
109
+ // src/foundations.tsx
110
+ var import_react2 = require("react");
111
+ var import_lucide_react = require("lucide-react");
112
+ var import_jsx_runtime = require("react/jsx-runtime");
113
+ var StaqContext = (0, import_react2.createContext)({ theme: "light", density: "compact" });
114
+ var useStaq = () => (0, import_react2.useContext)(StaqContext);
115
+ function StaqProvider({
116
+ theme = "light",
117
+ density = "compact",
118
+ className,
119
+ ...props
120
+ }) {
121
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StaqContext.Provider, { value: { theme, density }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
+ "div",
123
+ {
124
+ "data-staq-theme": theme,
125
+ "data-staq-density": density,
126
+ className: cx("sq-root", className),
127
+ ...props
128
+ }
129
+ ) });
130
+ }
131
+ var icons = {
132
+ check: import_lucide_react.Check,
133
+ close: import_lucide_react.X,
134
+ search: import_lucide_react.Search,
135
+ plus: import_lucide_react.Plus,
136
+ chevronDown: import_lucide_react.ChevronDown,
137
+ chevronLeft: import_lucide_react.ChevronLeft,
138
+ chevronRight: import_lucide_react.ChevronRight,
139
+ info: import_lucide_react.Info,
140
+ warning: import_lucide_react.CircleAlert,
141
+ settings: import_lucide_react.Settings,
142
+ copy: import_lucide_react.Copy,
143
+ arrowUpRight: import_lucide_react.ArrowUpRight,
144
+ package: import_lucide_react.Package,
145
+ upload: import_lucide_react.Upload,
146
+ moon: import_lucide_react.Moon,
147
+ sun: import_lucide_react.Sun,
148
+ sliders: import_lucide_react.SlidersHorizontal,
149
+ code: import_lucide_react.Code,
150
+ layers: import_lucide_react.Layers,
151
+ complete: import_lucide_react.CheckCheck
152
+ };
153
+ function Icon({
154
+ name = "info",
155
+ source,
156
+ size = 18,
157
+ label,
158
+ className
159
+ }) {
160
+ const Component = source ?? icons[name];
161
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
162
+ Component,
163
+ {
164
+ size,
165
+ strokeWidth: 1.7,
166
+ role: label ? "img" : void 0,
167
+ "aria-label": label,
168
+ "aria-hidden": label ? void 0 : true,
169
+ className
170
+ }
171
+ );
172
+ }
173
+ function Box({
174
+ padding = "4",
175
+ background = "transparent",
176
+ border = false,
177
+ radius = "medium",
178
+ className,
179
+ style,
180
+ ...props
181
+ }) {
182
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
183
+ "div",
184
+ {
185
+ className: cx("sq-box", className),
186
+ "data-background": background,
187
+ "data-border": border,
188
+ "data-radius": radius,
189
+ style: { padding: `var(--sq-space-${padding})`, ...style },
190
+ ...props
191
+ }
192
+ );
193
+ }
194
+ function Stack({
195
+ direction = "column",
196
+ gap = "4",
197
+ align,
198
+ justify,
199
+ wrap = true,
200
+ className,
201
+ style,
202
+ ...props
203
+ }) {
204
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
205
+ "div",
206
+ {
207
+ className: cx("sq-stack", className),
208
+ style: {
209
+ flexDirection: direction,
210
+ gap: `var(--sq-space-${gap})`,
211
+ alignItems: align,
212
+ justifyContent: justify,
213
+ flexWrap: wrap ? "wrap" : "nowrap",
214
+ ...style
215
+ },
216
+ ...props
217
+ }
218
+ );
219
+ }
220
+ function Grid({
221
+ columns = 2,
222
+ minColumnWidth = "14rem",
223
+ gap = "4",
224
+ style,
225
+ className,
226
+ ...props
227
+ }) {
228
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
229
+ "div",
230
+ {
231
+ className: cx("sq-grid", className),
232
+ style: {
233
+ "--sq-columns": columns,
234
+ "--sq-grid-min": minColumnWidth,
235
+ gap: `var(--sq-space-${gap})`,
236
+ ...style
237
+ },
238
+ ...props
239
+ }
240
+ );
241
+ }
242
+ function QueryContainer({
243
+ name = "staq",
244
+ style,
245
+ ...props
246
+ }) {
247
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
248
+ "div",
249
+ {
250
+ style: { containerType: "inline-size", containerName: name, ...style },
251
+ ...props
252
+ }
253
+ );
254
+ }
255
+ function Divider({
256
+ vertical = false,
257
+ className,
258
+ ...props
259
+ }) {
260
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
261
+ "hr",
262
+ {
263
+ className: cx("sq-divider", className),
264
+ "data-vertical": vertical,
265
+ "aria-orientation": vertical ? "vertical" : "horizontal",
266
+ ...props
267
+ }
268
+ );
269
+ }
270
+ function Heading({
271
+ level = 2,
272
+ size = "medium",
273
+ className,
274
+ ...props
275
+ }) {
276
+ return (0, import_react2.createElement)(`h${level}`, {
277
+ className: cx("sq-heading", `sq-heading-${size}`, className),
278
+ ...props
279
+ });
280
+ }
281
+ function Text({
282
+ tone = "neutral",
283
+ weight = "regular",
284
+ size = "medium",
285
+ className,
286
+ ...props
287
+ }) {
288
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
289
+ "span",
290
+ {
291
+ className: cx("sq-text", className),
292
+ "data-tone": tone,
293
+ "data-weight": weight,
294
+ "data-size": size,
295
+ ...props
296
+ }
297
+ );
298
+ }
299
+ function Paragraph({
300
+ tone = "neutral",
301
+ className,
302
+ ...props
303
+ }) {
304
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: cx("sq-paragraph", className), "data-tone": tone, ...props });
305
+ }
306
+ function Number({
307
+ value,
308
+ locale = "en-US",
309
+ format,
310
+ className,
311
+ ...props
312
+ }) {
313
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { className: cx("sq-number", className), ...props, children: new Intl.NumberFormat(locale, format).format(value) });
314
+ }
315
+ function OrderedList(props) {
316
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "sq-list", ...props });
317
+ }
318
+ function UnorderedList(props) {
319
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "sq-list", ...props });
320
+ }
321
+ function ListItem(props) {
322
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { ...props });
323
+ }
324
+ function Section({
325
+ heading,
326
+ description,
327
+ action,
328
+ children,
329
+ className,
330
+ ...props
331
+ }) {
332
+ const id = (0, import_react2.useId)();
333
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
334
+ "section",
335
+ {
336
+ "aria-labelledby": heading ? id : void 0,
337
+ className: cx("sq-section", className),
338
+ ...props,
339
+ children: [
340
+ (heading || action) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "sq-section-header", children: [
341
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
342
+ heading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { id, children: heading }),
343
+ description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Paragraph, { tone: "muted", children: description })
344
+ ] }),
345
+ action
346
+ ] }),
347
+ children
348
+ ]
349
+ }
350
+ );
351
+ }
352
+ function Page({
353
+ heading,
354
+ description,
355
+ action,
356
+ aside,
357
+ breadcrumbs,
358
+ width = "default",
359
+ className,
360
+ children,
361
+ ...props
362
+ }) {
363
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cx("sq-page", className), "data-width": width, ...props, children: [
364
+ breadcrumbs,
365
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "sq-section-header", children: [
366
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
367
+ heading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { level: 1, size: "large", children: heading }),
368
+ description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Paragraph, { tone: "muted", children: description })
369
+ ] }),
370
+ action
371
+ ] }),
372
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: aside ? "sq-page-layout" : void 0, children: [
373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children }),
374
+ aside && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("aside", { children: aside })
375
+ ] })
376
+ ] });
377
+ }
378
+ function Image({
379
+ alt,
380
+ fit = "cover",
381
+ aspectRatio,
382
+ style,
383
+ className,
384
+ ...props
385
+ }) {
386
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
387
+ "img",
388
+ {
389
+ alt,
390
+ className: cx("sq-image", className),
391
+ style: { objectFit: fit, aspectRatio, ...style },
392
+ ...props
393
+ }
394
+ );
395
+ }
396
+ function Thumbnail({
397
+ size = "medium",
398
+ className,
399
+ ...props
400
+ }) {
401
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
402
+ Image,
403
+ {
404
+ className: cx("sq-thumbnail", className),
405
+ "data-size": size,
406
+ ...props
407
+ }
408
+ );
409
+ }
410
+ function Avatar({ name, src, size = "medium", className }) {
411
+ const [failed, setFailed] = (0, import_react2.useState)(false);
412
+ const initials = name.trim().split(/\s+/).slice(0, 2).map((x) => x[0]).join("");
413
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
414
+ "span",
415
+ {
416
+ className: cx("sq-avatar", className),
417
+ "data-size": size,
418
+ role: "img",
419
+ "aria-label": name,
420
+ children: src && !failed ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src, alt: "", onError: () => setFailed(true) }) : initials
421
+ }
422
+ );
423
+ }
424
+
425
+ // src/actions.tsx
426
+ var import_react3 = require("react");
427
+ var import_react_slot = require("@radix-ui/react-slot");
428
+ var import_jsx_runtime2 = require("react/jsx-runtime");
429
+ var Button = (0, import_react3.forwardRef)(
430
+ function Button2({
431
+ variant = "secondary",
432
+ tone = "neutral",
433
+ size = "medium",
434
+ loading,
435
+ disabled,
436
+ icon,
437
+ fullWidth,
438
+ asChild,
439
+ children,
440
+ className,
441
+ type = "button",
442
+ ...props
443
+ }, ref) {
444
+ const Comp = asChild ? import_react_slot.Slot : "button";
445
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
446
+ Comp,
447
+ {
448
+ ref,
449
+ type: asChild ? void 0 : type,
450
+ className: cx("sq-button", className),
451
+ "data-variant": variant,
452
+ "data-tone": tone,
453
+ "data-size": size,
454
+ "data-full-width": fullWidth,
455
+ disabled: asChild ? void 0 : disabled || loading,
456
+ "aria-busy": loading || void 0,
457
+ ...props,
458
+ children: asChild ? children : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
459
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "sq-spinner", "aria-hidden": "true" }) : icon,
460
+ children,
461
+ loading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "sq-sr-only", children: "Loading" })
462
+ ] })
463
+ }
464
+ );
465
+ }
466
+ );
467
+ function ButtonGroup({
468
+ label,
469
+ className,
470
+ ...props
471
+ }) {
472
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
473
+ "div",
474
+ {
475
+ role: "group",
476
+ "aria-label": label,
477
+ className: cx("sq-button-group", className),
478
+ ...props
479
+ }
480
+ );
481
+ }
482
+ var Clickable = (0, import_react3.forwardRef)(function Clickable2({ className, type = "button", ...props }, ref) {
483
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
484
+ "button",
485
+ {
486
+ ref,
487
+ type,
488
+ className: cx("sq-clickable", className),
489
+ ...props
490
+ }
491
+ );
492
+ });
493
+ var Link = (0, import_react3.forwardRef)(function Link2({ tone = "neutral", variant = "text", className, target, rel, ...props }, ref) {
494
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
495
+ "a",
496
+ {
497
+ ref,
498
+ className: cx(variant === "button" ? "sq-button" : "sq-link", className),
499
+ "data-tone": tone,
500
+ target,
501
+ rel: rel ?? (target === "_blank" ? "noopener noreferrer" : void 0),
502
+ ...props
503
+ }
504
+ );
505
+ });
506
+ function Chip({
507
+ onRemove,
508
+ removeLabel = "Remove tag",
509
+ tone = "neutral",
510
+ className,
511
+ children,
512
+ ...props
513
+ }) {
514
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: cx("sq-chip", className), "data-tone": tone, ...props, children: [
515
+ children,
516
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
517
+ "button",
518
+ {
519
+ className: "sq-chip-remove",
520
+ type: "button",
521
+ "aria-label": removeLabel,
522
+ onClick: onRemove,
523
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: "close", size: 12 })
524
+ }
525
+ )
526
+ ] });
527
+ }
528
+ function ClickableChip({
529
+ selected = false,
530
+ onRemove,
531
+ removeLabel = "Remove filter",
532
+ className,
533
+ children,
534
+ ...props
535
+ }) {
536
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "sq-chip-wrapper", children: [
537
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
538
+ "button",
539
+ {
540
+ type: "button",
541
+ className: cx("sq-chip", "sq-clickable-chip", className),
542
+ "aria-pressed": selected,
543
+ ...props,
544
+ children: [
545
+ selected && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: "check", size: 14 }),
546
+ " ",
547
+ children
548
+ ]
549
+ }
550
+ ),
551
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
552
+ "button",
553
+ {
554
+ type: "button",
555
+ className: "sq-chip-remove",
556
+ disabled: props.disabled,
557
+ "aria-label": removeLabel,
558
+ onClick: onRemove,
559
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: "close", size: 12 })
560
+ }
561
+ )
562
+ ] });
563
+ }
564
+ function Badge({
565
+ tone = "neutral",
566
+ size = "medium",
567
+ icon,
568
+ className,
569
+ children,
570
+ ...props
571
+ }) {
572
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
573
+ "span",
574
+ {
575
+ className: cx("sq-badge", className),
576
+ "data-tone": tone,
577
+ "data-size": size,
578
+ ...props,
579
+ children: [
580
+ icon,
581
+ children
582
+ ]
583
+ }
584
+ );
585
+ }
586
+ function Banner({
587
+ title,
588
+ tone = "info",
589
+ dismissible,
590
+ onDismiss,
591
+ action,
592
+ className,
593
+ children,
594
+ ...props
595
+ }) {
596
+ const [dismissed, setDismissed] = (0, import_react3.useState)(false);
597
+ if (dismissed) return null;
598
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
599
+ "div",
600
+ {
601
+ role: tone === "critical" ? "alert" : "status",
602
+ className: cx("sq-banner", className),
603
+ "data-tone": tone,
604
+ ...props,
605
+ children: [
606
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
607
+ Icon,
608
+ {
609
+ name: tone === "critical" || tone === "warning" ? "warning" : "info"
610
+ }
611
+ ),
612
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "sq-grow", children: [
613
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: title }),
614
+ children && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children }),
615
+ action
616
+ ] }),
617
+ dismissible && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
618
+ Button,
619
+ {
620
+ variant: "tertiary",
621
+ size: "small",
622
+ "aria-label": "Dismiss notification",
623
+ onClick: () => {
624
+ setDismissed(true);
625
+ onDismiss?.();
626
+ },
627
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: "close" })
628
+ }
629
+ )
630
+ ]
631
+ }
632
+ );
633
+ }
634
+ function EmptyState({
635
+ title,
636
+ children,
637
+ action,
638
+ graphic
639
+ }) {
640
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "sq-empty", children: [
641
+ graphic ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: "package", size: 36 }),
642
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: title }),
643
+ children && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sq-muted", children }),
644
+ action
645
+ ] });
646
+ }
647
+ function Progress({
648
+ value,
649
+ max = 100,
650
+ label,
651
+ showValue = true
652
+ }) {
653
+ const safeMax = Math.max(1, max);
654
+ const safeValue = value === void 0 ? void 0 : Math.min(safeMax, Math.max(0, value));
655
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "sq-progress", children: [
656
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
657
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: label }),
658
+ showValue && safeValue !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
659
+ Math.round(safeValue / safeMax * 100),
660
+ "%"
661
+ ] })
662
+ ] }),
663
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("progress", { "aria-label": label, max: safeMax, value: safeValue })
664
+ ] });
665
+ }
666
+ function Spinner({
667
+ label = "Loading",
668
+ size = "medium"
669
+ }) {
670
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { role: "status", className: "sq-spinner-wrap", children: [
671
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "sq-spinner", "data-size": size, "aria-hidden": "true" }),
672
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "sq-sr-only", children: label })
673
+ ] });
674
+ }
675
+
676
+ // src/forms.tsx
677
+ var import_react4 = require("react");
678
+ var import_jsx_runtime3 = require("react/jsx-runtime");
679
+ function FieldShell({
680
+ id,
681
+ label,
682
+ description,
683
+ error,
684
+ hideLabel,
685
+ required,
686
+ children
687
+ }) {
688
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "sq-field", children: [
689
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { htmlFor: id, className: hideLabel ? "sq-sr-only" : "sq-label", children: [
690
+ label,
691
+ required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "aria-hidden": "true", children: " *" })
692
+ ] }),
693
+ children,
694
+ description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: `${id}-help`, className: "sq-field-help", children: description }),
695
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { id: `${id}-error`, className: "sq-field-error", children: [
696
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { name: "warning", size: 14 }),
697
+ error
698
+ ] })
699
+ ] });
700
+ }
701
+ var TextField = (0, import_react4.forwardRef)(
702
+ function TextField2({
703
+ label,
704
+ description,
705
+ error,
706
+ hideLabel,
707
+ id: givenId,
708
+ prefix,
709
+ suffix,
710
+ className,
711
+ onValueChange,
712
+ onChange,
713
+ required,
714
+ ...props
715
+ }, ref) {
716
+ const uid = (0, import_react4.useId)();
717
+ const id = givenId ?? uid;
718
+ const describedBy = [
719
+ description && `${id}-help`,
720
+ error && `${id}-error`,
721
+ props["aria-describedby"]
722
+ ].filter(Boolean).join(" ") || void 0;
723
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FieldShell, { ...{ id, label, description, error, hideLabel, required }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
724
+ "div",
725
+ {
726
+ className: "sq-input-wrap",
727
+ "data-error": !!error,
728
+ "data-disabled": !!props.disabled,
729
+ children: [
730
+ prefix && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "sq-input-affix", children: prefix }),
731
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
732
+ "input",
733
+ {
734
+ ref,
735
+ id,
736
+ className: cx("sq-input", className),
737
+ required,
738
+ ...props,
739
+ "aria-invalid": error ? true : props["aria-invalid"],
740
+ "aria-describedby": describedBy,
741
+ onChange: (e) => {
742
+ onChange?.(e);
743
+ onValueChange?.(e.target.value);
744
+ }
745
+ }
746
+ ),
747
+ suffix && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "sq-input-affix", children: suffix })
748
+ ]
749
+ }
750
+ ) });
751
+ }
752
+ );
753
+ function EmailField(props) {
754
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextField, { autoComplete: "email", ...props, type: "email" });
755
+ }
756
+ function URLField(props) {
757
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextField, { autoComplete: "url", ...props, type: "url" });
758
+ }
759
+ function SearchField(props) {
760
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextField, { prefix: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { name: "search" }), ...props, type: "search" });
761
+ }
762
+ function NumberField(props) {
763
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextField, { inputMode: "decimal", ...props, type: "number" });
764
+ }
765
+ function MoneyField({
766
+ currency = "USD",
767
+ locale = "en-US",
768
+ ...props
769
+ }) {
770
+ const symbol = new Intl.NumberFormat(locale, { style: "currency", currency }).formatToParts(0).find((p) => p.type === "currency")?.value ?? currency;
771
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NumberField, { step: "0.01", prefix: symbol, suffix: currency, ...props });
772
+ }
773
+ function PasswordField(props) {
774
+ const [visible, setVisible] = (0, import_react4.useState)(false);
775
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
776
+ TextField,
777
+ {
778
+ autoComplete: "current-password",
779
+ ...props,
780
+ type: visible ? "text" : "password",
781
+ suffix: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
782
+ Button,
783
+ {
784
+ variant: "tertiary",
785
+ size: "small",
786
+ disabled: props.disabled,
787
+ "aria-label": visible ? "Hide password" : "Show password",
788
+ "aria-pressed": visible,
789
+ onClick: () => setVisible(!visible),
790
+ children: visible ? "Hide" : "Show"
791
+ }
792
+ )
793
+ }
794
+ );
795
+ }
796
+ function DateField(props) {
797
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextField, { ...props, className: cx("sq-date-field", props.className), type: "date" });
798
+ }
799
+ var TextArea = (0, import_react4.forwardRef)(
800
+ function TextArea2({
801
+ label,
802
+ description,
803
+ error,
804
+ hideLabel,
805
+ id: givenId,
806
+ onValueChange,
807
+ onChange,
808
+ className,
809
+ required,
810
+ ...props
811
+ }, ref) {
812
+ const uid = (0, import_react4.useId)();
813
+ const id = givenId ?? uid;
814
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FieldShell, { ...{ id, label, description, error, hideLabel, required }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
815
+ "textarea",
816
+ {
817
+ ref,
818
+ id,
819
+ rows: 4,
820
+ className: cx("sq-input", "sq-textarea", className),
821
+ required,
822
+ ...props,
823
+ "aria-invalid": error ? true : props["aria-invalid"],
824
+ "aria-describedby": [
825
+ description && `${id}-help`,
826
+ error && `${id}-error`,
827
+ props["aria-describedby"]
828
+ ].filter(Boolean).join(" ") || void 0,
829
+ onChange: (e) => {
830
+ onChange?.(e);
831
+ onValueChange?.(e.target.value);
832
+ }
833
+ }
834
+ ) });
835
+ }
836
+ );
837
+ var Select = (0, import_react4.forwardRef)(
838
+ function Select2({
839
+ label,
840
+ description,
841
+ error,
842
+ hideLabel,
843
+ id: givenId,
844
+ options,
845
+ placeholder,
846
+ onValueChange,
847
+ onChange,
848
+ className,
849
+ required,
850
+ ...props
851
+ }, ref) {
852
+ const uid = (0, import_react4.useId)();
853
+ const id = givenId ?? uid;
854
+ const groups = [...new Set(options.map((o) => o.group))];
855
+ const option = (o) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: o.value, disabled: o.disabled, children: o.label }, o.value);
856
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FieldShell, { ...{ id, label, description, error, hideLabel, required }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
857
+ "select",
858
+ {
859
+ ref,
860
+ id,
861
+ className: cx("sq-input", "sq-select", className),
862
+ required,
863
+ defaultValue: placeholder && props.value === void 0 ? props.defaultValue ?? "" : void 0,
864
+ ...props,
865
+ "aria-invalid": error ? true : props["aria-invalid"],
866
+ "aria-describedby": [
867
+ description && `${id}-help`,
868
+ error && `${id}-error`,
869
+ props["aria-describedby"]
870
+ ].filter(Boolean).join(" ") || void 0,
871
+ onChange: (e) => {
872
+ onChange?.(e);
873
+ onValueChange?.(e.target.value);
874
+ },
875
+ children: [
876
+ placeholder && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", disabled: true, children: placeholder }),
877
+ groups.map(
878
+ (group) => group ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("optgroup", { label: group, children: options.filter((o) => o.group === group).map(option) }, group) : options.filter((o) => !o.group).map(option)
879
+ )
880
+ ]
881
+ }
882
+ ) });
883
+ }
884
+ );
885
+ function Checkbox({
886
+ label,
887
+ description,
888
+ error,
889
+ hideLabel,
890
+ id: givenId,
891
+ indeterminate,
892
+ onCheckedChange,
893
+ onChange,
894
+ className,
895
+ ...props
896
+ }) {
897
+ const uid = (0, import_react4.useId)();
898
+ const id = givenId ?? uid;
899
+ const ref = (0, import_react4.useRef)(null);
900
+ (0, import_react4.useEffect)(() => {
901
+ if (ref.current) ref.current.indeterminate = !!indeterminate;
902
+ }, [indeterminate]);
903
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "sq-check-field", children: [
904
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { htmlFor: id, className: cx("sq-check-label", className), children: [
905
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
906
+ "input",
907
+ {
908
+ ref,
909
+ id,
910
+ type: "checkbox",
911
+ className: "sq-checkbox",
912
+ ...props,
913
+ "aria-invalid": error ? true : props["aria-invalid"],
914
+ "aria-describedby": [
915
+ description && `${id}-help`,
916
+ error && `${id}-error`,
917
+ props["aria-describedby"]
918
+ ].filter(Boolean).join(" ") || void 0,
919
+ onChange: (e) => {
920
+ onChange?.(e);
921
+ onCheckedChange?.(e.target.checked);
922
+ }
923
+ }
924
+ ),
925
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: hideLabel ? "sq-sr-only" : void 0, children: label })
926
+ ] }),
927
+ description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: `${id}-help`, className: "sq-field-help", children: description }),
928
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: `${id}-error`, className: "sq-field-error", children: error })
929
+ ] });
930
+ }
931
+ function Switch(props) {
932
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
933
+ Checkbox,
934
+ {
935
+ ...props,
936
+ role: "switch",
937
+ className: cx("sq-switch", props.className)
938
+ }
939
+ );
940
+ }
941
+ function ChoiceList({
942
+ label,
943
+ options,
944
+ value,
945
+ defaultValue = [],
946
+ onValueChange,
947
+ multiple,
948
+ disabled,
949
+ name,
950
+ required,
951
+ description,
952
+ error,
953
+ hideLabel
954
+ }) {
955
+ const id = (0, import_react4.useId)();
956
+ const [selected, setSelected] = useControllable(
957
+ value,
958
+ defaultValue,
959
+ onValueChange
960
+ );
961
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
962
+ "fieldset",
963
+ {
964
+ className: "sq-choice-list",
965
+ disabled,
966
+ "aria-invalid": !!error,
967
+ "aria-describedby": [description && `${id}-help`, error && `${id}-error`].filter(Boolean).join(" ") || void 0,
968
+ children: [
969
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("legend", { className: hideLabel ? "sq-sr-only" : "sq-label", children: label }),
970
+ options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "sq-check-label", children: [
971
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
972
+ "input",
973
+ {
974
+ className: "sq-checkbox",
975
+ type: multiple ? "checkbox" : "radio",
976
+ name: name ?? id,
977
+ value: o.value,
978
+ required: required && (!multiple || selected.length === 0),
979
+ disabled: o.disabled,
980
+ checked: selected.includes(o.value),
981
+ onChange: (e) => setSelected(
982
+ multiple ? e.target.checked ? [...selected, o.value] : selected.filter((v) => v !== o.value) : [o.value]
983
+ )
984
+ }
985
+ ),
986
+ o.label
987
+ ] }, o.value)),
988
+ description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: `${id}-help`, className: "sq-field-help", children: description }),
989
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: `${id}-error`, className: "sq-field-error", children: error })
990
+ ]
991
+ }
992
+ );
993
+ }
994
+ function ColorPicker({
995
+ label = "Color",
996
+ value,
997
+ defaultValue = "#0a2eb5",
998
+ onValueChange,
999
+ ...props
1000
+ }) {
1001
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "sq-color-picker", children: [
1002
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: label }),
1003
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1004
+ "input",
1005
+ {
1006
+ type: "color",
1007
+ value,
1008
+ defaultValue: value === void 0 ? defaultValue : void 0,
1009
+ onChange: (e) => onValueChange?.(e.target.value),
1010
+ ...props
1011
+ }
1012
+ )
1013
+ ] });
1014
+ }
1015
+ function ColorField({
1016
+ value,
1017
+ defaultValue = "#0a2eb5",
1018
+ onValueChange,
1019
+ onChange,
1020
+ ...props
1021
+ }) {
1022
+ const [color, setColor] = useControllable(
1023
+ value === void 0 ? void 0 : String(value),
1024
+ String(defaultValue),
1025
+ onValueChange
1026
+ );
1027
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1028
+ TextField,
1029
+ {
1030
+ ...props,
1031
+ value: color,
1032
+ pattern: "#[0-9a-fA-F]{6}",
1033
+ onChange,
1034
+ onValueChange: setColor,
1035
+ prefix: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1036
+ "input",
1037
+ {
1038
+ "aria-label": `${props.label} picker`,
1039
+ className: "sq-color-input",
1040
+ type: "color",
1041
+ disabled: props.disabled || props.readOnly,
1042
+ value: /^#[0-9a-f]{6}$/i.test(color) ? color : "#000000",
1043
+ onChange: (e) => setColor(e.target.value)
1044
+ }
1045
+ )
1046
+ }
1047
+ );
1048
+ }
1049
+ function DropZone({
1050
+ label,
1051
+ description,
1052
+ error,
1053
+ accept,
1054
+ multiple,
1055
+ disabled,
1056
+ maxSize = 10 * 1024 * 1024,
1057
+ name,
1058
+ required,
1059
+ onFilesChange,
1060
+ onReject
1061
+ }) {
1062
+ const id = (0, import_react4.useId)();
1063
+ const ref = (0, import_react4.useRef)(null);
1064
+ const [files, setFiles] = (0, import_react4.useState)([]);
1065
+ const [rejection, setRejection] = (0, import_react4.useState)("");
1066
+ const [dragging, setDragging] = (0, import_react4.useState)(false);
1067
+ function receive(incoming) {
1068
+ if (disabled) return false;
1069
+ const patterns = accept?.split(",").map((x) => x.trim().toLowerCase()).filter(Boolean) ?? [];
1070
+ const invalid = !multiple && incoming.length > 1 || incoming.some(
1071
+ (f) => f.size > maxSize || patterns.length > 0 && !patterns.some(
1072
+ (p) => p.startsWith(".") ? f.name.toLowerCase().endsWith(p) : p.endsWith("/*") ? f.type.startsWith(p.slice(0, -1)) : f.type === p
1073
+ )
1074
+ );
1075
+ if (invalid) {
1076
+ const message = "File rejected. Check the file type, size, and number of files.";
1077
+ setRejection(message);
1078
+ onReject?.(message);
1079
+ if (ref.current) ref.current.value = "";
1080
+ return false;
1081
+ }
1082
+ setRejection("");
1083
+ setFiles(incoming);
1084
+ onFilesChange?.(incoming);
1085
+ return true;
1086
+ }
1087
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "sq-field", children: [
1088
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { htmlFor: id, className: "sq-label", children: label }),
1089
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1090
+ "div",
1091
+ {
1092
+ className: "sq-drop-zone",
1093
+ "data-dragging": dragging,
1094
+ "data-disabled": disabled,
1095
+ onDragOver: (e) => {
1096
+ e.preventDefault();
1097
+ if (!disabled) setDragging(true);
1098
+ },
1099
+ onDragLeave: () => setDragging(false),
1100
+ onDrop: (e) => {
1101
+ e.preventDefault();
1102
+ setDragging(false);
1103
+ const dropped = Array.from(e.dataTransfer.files);
1104
+ if (receive(dropped) && ref.current) {
1105
+ try {
1106
+ const transfer = new DataTransfer();
1107
+ dropped.forEach((f) => transfer.items.add(f));
1108
+ ref.current.files = transfer.files;
1109
+ } catch {
1110
+ }
1111
+ }
1112
+ },
1113
+ children: [
1114
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { name: "upload", size: 24 }),
1115
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Drop files here or choose files" }),
1116
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1117
+ "input",
1118
+ {
1119
+ ref,
1120
+ id,
1121
+ type: "file",
1122
+ name,
1123
+ required,
1124
+ accept,
1125
+ multiple,
1126
+ disabled,
1127
+ "aria-invalid": !!(error || rejection),
1128
+ "aria-describedby": `${id}-help ${id}-status`,
1129
+ onChange: (e) => receive(Array.from(e.target.files ?? []))
1130
+ }
1131
+ )
1132
+ ]
1133
+ }
1134
+ ),
1135
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: `${id}-help`, className: "sq-field-help", children: description ?? `Maximum ${Math.round(maxSize / 1024 / 1024)} MB per file` }),
1136
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1137
+ "div",
1138
+ {
1139
+ id: `${id}-status`,
1140
+ "aria-live": "polite",
1141
+ className: error || rejection ? "sq-field-error" : "sq-field-help",
1142
+ children: error || rejection || files.map((f) => f.name).join(", ")
1143
+ }
1144
+ )
1145
+ ] });
1146
+ }
1147
+
1148
+ // src/overlays.tsx
1149
+ var Dialog = __toESM(require("@radix-ui/react-dialog"), 1);
1150
+ var Pop = __toESM(require("@radix-ui/react-popover"), 1);
1151
+ var Dropdown = __toESM(require("@radix-ui/react-dropdown-menu"), 1);
1152
+ var Tip = __toESM(require("@radix-ui/react-tooltip"), 1);
1153
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1154
+ function Modal({
1155
+ title,
1156
+ description,
1157
+ trigger,
1158
+ children,
1159
+ footer,
1160
+ size = "medium",
1161
+ ...props
1162
+ }) {
1163
+ const { theme, density } = useStaq();
1164
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Dialog.Root, { ...props, children: [
1165
+ trigger && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dialog.Trigger, { asChild: true, children: trigger }),
1166
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Dialog.Portal, { children: [
1167
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dialog.Overlay, { className: "sq-overlay" }),
1168
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1169
+ Dialog.Content,
1170
+ {
1171
+ "data-staq-theme": theme,
1172
+ "data-staq-density": density,
1173
+ className: "sq-modal",
1174
+ "data-size": size,
1175
+ children: [
1176
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "sq-section-header", children: [
1177
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dialog.Title, { className: "sq-heading", children: title }),
1178
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dialog.Close, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { variant: "tertiary", size: "small", "aria-label": "Close dialog", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { name: "close" }) }) })
1179
+ ] }),
1180
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dialog.Description, { className: "sq-muted", children: description }),
1181
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "sq-modal-body", children }),
1182
+ footer && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("footer", { className: "sq-modal-footer", children: footer })
1183
+ ]
1184
+ }
1185
+ )
1186
+ ] })
1187
+ ] });
1188
+ }
1189
+ function Popover({
1190
+ trigger,
1191
+ label,
1192
+ children,
1193
+ align = "start",
1194
+ side = "bottom",
1195
+ ...props
1196
+ }) {
1197
+ const { theme, density } = useStaq();
1198
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Pop.Root, { ...props, children: [
1199
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pop.Trigger, { asChild: true, children: trigger }),
1200
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pop.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1201
+ Pop.Content,
1202
+ {
1203
+ "aria-label": label,
1204
+ "data-staq-theme": theme,
1205
+ "data-staq-density": density,
1206
+ className: "sq-popover",
1207
+ align,
1208
+ side,
1209
+ sideOffset: 8,
1210
+ collisionPadding: 16,
1211
+ children: [
1212
+ children,
1213
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pop.Close, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { variant: "tertiary", size: "small", "aria-label": "Close popover", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { name: "close" }) }) })
1214
+ ]
1215
+ }
1216
+ ) })
1217
+ ] });
1218
+ }
1219
+ function Menu({
1220
+ trigger,
1221
+ label,
1222
+ items,
1223
+ align = "end",
1224
+ onOpenChange
1225
+ }) {
1226
+ const { theme, density } = useStaq();
1227
+ const groups = [...new Set(items.map((x) => x.group))];
1228
+ const item = (i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1229
+ Dropdown.Item,
1230
+ {
1231
+ className: "sq-menu-item",
1232
+ disabled: i.disabled,
1233
+ onSelect: i.onSelect,
1234
+ "data-tone": i.tone,
1235
+ asChild: !!i.href && !i.disabled,
1236
+ children: i.href && !i.disabled ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("a", { href: i.href, children: [
1237
+ i.icon,
1238
+ i.label
1239
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1240
+ i.icon,
1241
+ i.label
1242
+ ] })
1243
+ },
1244
+ i.id
1245
+ );
1246
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Dropdown.Root, { onOpenChange, children: [
1247
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dropdown.Trigger, { asChild: true, children: trigger }),
1248
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dropdown.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1249
+ Dropdown.Content,
1250
+ {
1251
+ "aria-label": label,
1252
+ "data-staq-theme": theme,
1253
+ "data-staq-density": density,
1254
+ className: "sq-menu",
1255
+ sideOffset: 6,
1256
+ align,
1257
+ collisionPadding: 12,
1258
+ children: groups.map((group, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Dropdown.Group, { children: [
1259
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dropdown.Separator, { className: "sq-divider" }),
1260
+ group && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dropdown.Label, { className: "sq-menu-label", children: group }),
1261
+ items.filter((i) => i.group === group).map(item)
1262
+ ] }, group ?? "default"))
1263
+ }
1264
+ ) })
1265
+ ] });
1266
+ }
1267
+ function Tooltip({ content, children, side = "top" }) {
1268
+ const { theme, density } = useStaq();
1269
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tip.Provider, { delayDuration: 800, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Tip.Root, { children: [
1270
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tip.Trigger, { asChild: true, children }),
1271
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1272
+ Tip.Content,
1273
+ {
1274
+ "data-staq-theme": theme,
1275
+ "data-staq-density": density,
1276
+ className: "sq-tooltip",
1277
+ side,
1278
+ sideOffset: 8,
1279
+ collisionPadding: 12,
1280
+ children: [
1281
+ content,
1282
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tip.Arrow, { className: "sq-tooltip-arrow" })
1283
+ ]
1284
+ }
1285
+ ) })
1286
+ ] }) });
1287
+ }
1288
+
1289
+ // src/complex.tsx
1290
+ var import_react5 = require("react");
1291
+ var import_react_day_picker = require("react-day-picker");
1292
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1293
+ var iso = (d) => d ? `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}` : "";
1294
+ function DatePicker(props) {
1295
+ const { label = "Choose a date", name, ...calendar } = props;
1296
+ const [selected, setSelected] = useControllable(
1297
+ props.value,
1298
+ props.defaultValue,
1299
+ (next) => {
1300
+ if (props.mode === "range")
1301
+ props.onValueChange?.(next);
1302
+ else props.onValueChange?.(next);
1303
+ },
1304
+ "value" in props
1305
+ );
1306
+ const common = {
1307
+ month: calendar.month,
1308
+ defaultMonth: calendar.defaultMonth,
1309
+ onMonthChange: calendar.onMonthChange,
1310
+ disabled: calendar.disabled,
1311
+ numberOfMonths: calendar.numberOfMonths,
1312
+ locale: calendar.locale,
1313
+ startMonth: calendar.startMonth,
1314
+ endMonth: calendar.endMonth,
1315
+ showOutsideDays: true,
1316
+ labels: {
1317
+ labelDayButton: ((date, modifiers, options, dateLib) => `${(0, import_react_day_picker.formatDay)(date, options, dateLib)}: ${(0, import_react_day_picker.labelDayButton)(date, modifiers, options, dateLib)}`)
1318
+ }
1319
+ };
1320
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "sq-calendar", role: "group", "aria-label": label, children: [
1321
+ props.mode === "range" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1322
+ import_react_day_picker.DayPicker,
1323
+ {
1324
+ ...common,
1325
+ mode: "range",
1326
+ selected,
1327
+ onSelect: setSelected,
1328
+ excludeDisabled: true
1329
+ }
1330
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1331
+ import_react_day_picker.DayPicker,
1332
+ {
1333
+ ...common,
1334
+ mode: "single",
1335
+ selected,
1336
+ onSelect: setSelected
1337
+ }
1338
+ ),
1339
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "sq-sr-only", "aria-live": "polite", children: selected instanceof Date ? iso(selected) : selected?.from ? `${iso(selected.from)} to ${iso(selected.to) || "select end date"}` : "No date selected" }),
1340
+ name && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1341
+ "input",
1342
+ {
1343
+ type: "hidden",
1344
+ name,
1345
+ value: selected instanceof Date ? iso(selected) : selected ? `${iso(selected.from)}/${iso(selected.to)}` : ""
1346
+ }
1347
+ )
1348
+ ] });
1349
+ }
1350
+ function Table({
1351
+ label,
1352
+ columns,
1353
+ rows,
1354
+ rowKey,
1355
+ loading,
1356
+ emptyMessage = "No results found.",
1357
+ sort,
1358
+ onSortChange,
1359
+ selected = [],
1360
+ onSelectionChange,
1361
+ pagination,
1362
+ filters
1363
+ }) {
1364
+ const id = (0, import_react5.useId)();
1365
+ const [sorting, setSorting] = useControllable(
1366
+ sort,
1367
+ void 0,
1368
+ (next) => {
1369
+ if (next) onSortChange?.(next);
1370
+ }
1371
+ );
1372
+ const column = columns.find((c) => c.id === sorting?.column);
1373
+ const displayed = column?.sortValue ? [...rows].sort((a, b) => {
1374
+ const av = column.sortValue(a);
1375
+ const bv = column.sortValue(b);
1376
+ return (typeof av === "number" && typeof bv === "number" ? av - bv : String(av).localeCompare(String(bv))) * (sorting?.direction === "descending" ? -1 : 1);
1377
+ }) : rows;
1378
+ const all = rows.length > 0 && rows.every((r) => selected.includes(rowKey(r)));
1379
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "sq-table-container", "aria-busy": loading, children: [
1380
+ filters && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "sq-table-filters", children: filters }),
1381
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1382
+ "div",
1383
+ {
1384
+ className: "sq-table-scroll",
1385
+ role: "region",
1386
+ "aria-label": `${label} table`,
1387
+ tabIndex: 0,
1388
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "sq-table", children: [
1389
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("caption", { id, children: label }),
1390
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
1391
+ onSelectionChange && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { scope: "col", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1392
+ "input",
1393
+ {
1394
+ "aria-label": "Select all visible rows",
1395
+ type: "checkbox",
1396
+ className: "sq-checkbox",
1397
+ checked: all,
1398
+ onChange: (e) => {
1399
+ const keys = rows.map(rowKey);
1400
+ onSelectionChange(
1401
+ e.target.checked ? [.../* @__PURE__ */ new Set([...selected, ...keys])] : selected.filter((k) => !keys.includes(k))
1402
+ );
1403
+ }
1404
+ }
1405
+ ) }),
1406
+ columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1407
+ "th",
1408
+ {
1409
+ scope: "col",
1410
+ "data-align": c.align,
1411
+ "aria-sort": sorting?.column === c.id ? sorting.direction : void 0,
1412
+ children: c.sortValue ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1413
+ "button",
1414
+ {
1415
+ className: "sq-table-sort",
1416
+ type: "button",
1417
+ onClick: () => setSorting({
1418
+ column: c.id,
1419
+ direction: sorting?.column === c.id && sorting.direction === "ascending" ? "descending" : "ascending"
1420
+ }),
1421
+ children: [
1422
+ c.header,
1423
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { name: "chevronDown", size: 14 })
1424
+ ]
1425
+ }
1426
+ ) : c.header
1427
+ },
1428
+ c.id
1429
+ ))
1430
+ ] }) }),
1431
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tbody", { children: [
1432
+ displayed.map((r) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { "data-selected": selected.includes(rowKey(r)), children: [
1433
+ onSelectionChange && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1434
+ "input",
1435
+ {
1436
+ type: "checkbox",
1437
+ className: "sq-checkbox",
1438
+ "aria-label": `Select row ${rowKey(r)}`,
1439
+ checked: selected.includes(rowKey(r)),
1440
+ onChange: (e) => onSelectionChange(
1441
+ e.target.checked ? [.../* @__PURE__ */ new Set([...selected, rowKey(r)])] : selected.filter((k) => k !== rowKey(r))
1442
+ )
1443
+ }
1444
+ ) }),
1445
+ columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { "data-align": c.align, children: c.cell(r) }, c.id))
1446
+ ] }, rowKey(r))),
1447
+ !rows.length && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { colSpan: columns.length + (onSelectionChange ? 1 : 0), children: loading ? "Loading\u2026" : emptyMessage }) })
1448
+ ] })
1449
+ ] })
1450
+ }
1451
+ ),
1452
+ pagination && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "sq-pagination", children: [
1453
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: pagination.label }),
1454
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1455
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1456
+ Button,
1457
+ {
1458
+ size: "small",
1459
+ disabled: !pagination.hasPrevious || loading,
1460
+ "aria-label": "Previous page",
1461
+ onClick: pagination.onPrevious,
1462
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { name: "chevronLeft" })
1463
+ }
1464
+ ),
1465
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1466
+ Button,
1467
+ {
1468
+ size: "small",
1469
+ disabled: !pagination.hasNext || loading,
1470
+ "aria-label": "Next page",
1471
+ onClick: pagination.onNext,
1472
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { name: "chevronRight" })
1473
+ }
1474
+ )
1475
+ ] })
1476
+ ] })
1477
+ ] });
1478
+ }
1479
+ // Annotate the CommonJS export names for ESM import in node:
1480
+ 0 && (module.exports = {
1481
+ Avatar,
1482
+ Badge,
1483
+ Banner,
1484
+ Box,
1485
+ Button,
1486
+ ButtonGroup,
1487
+ Checkbox,
1488
+ Chip,
1489
+ ChoiceList,
1490
+ Clickable,
1491
+ ClickableChip,
1492
+ ColorField,
1493
+ ColorPicker,
1494
+ DateField,
1495
+ DatePicker,
1496
+ Divider,
1497
+ DropZone,
1498
+ EmailField,
1499
+ EmptyState,
1500
+ Grid,
1501
+ Heading,
1502
+ Icon,
1503
+ Image,
1504
+ Link,
1505
+ ListItem,
1506
+ Menu,
1507
+ Modal,
1508
+ MoneyField,
1509
+ Number,
1510
+ NumberField,
1511
+ OrderedList,
1512
+ Page,
1513
+ Paragraph,
1514
+ PasswordField,
1515
+ Popover,
1516
+ Progress,
1517
+ QueryContainer,
1518
+ SearchField,
1519
+ Section,
1520
+ Select,
1521
+ Spinner,
1522
+ Stack,
1523
+ StaqContext,
1524
+ StaqProvider,
1525
+ Switch,
1526
+ Table,
1527
+ Text,
1528
+ TextArea,
1529
+ TextField,
1530
+ Thumbnail,
1531
+ Tooltip,
1532
+ URLField,
1533
+ UnorderedList,
1534
+ cx,
1535
+ icons,
1536
+ useControllable,
1537
+ useStaq
1538
+ });