glasswind 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,1979 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var reactDom = require('react-dom');
6
+
7
+ // src/components/Accordion/Accordion.tsx
8
+
9
+ // src/utils/cn.ts
10
+ function cn(...inputs) {
11
+ const out = [];
12
+ for (const input of inputs) {
13
+ if (!input) continue;
14
+ if (Array.isArray(input)) {
15
+ const nested = cn(...input);
16
+ if (nested) out.push(nested);
17
+ } else if (typeof input === "string" || typeof input === "number") {
18
+ out.push(String(input));
19
+ }
20
+ }
21
+ return out.join(" ");
22
+ }
23
+ function useDisclosure(defaultOpen = false) {
24
+ const [isOpen, setOpen] = react.useState(defaultOpen);
25
+ const open = react.useCallback(() => setOpen(true), []);
26
+ const close = react.useCallback(() => setOpen(false), []);
27
+ const toggle = react.useCallback(() => setOpen((v) => !v), []);
28
+ return { isOpen, open, close, toggle, setOpen };
29
+ }
30
+ function useClickOutside(ref, handler, enabled = true) {
31
+ react.useEffect(() => {
32
+ if (!enabled) return;
33
+ const listener = (event) => {
34
+ const el = ref.current;
35
+ if (!el || el.contains(event.target)) return;
36
+ handler(event);
37
+ };
38
+ document.addEventListener("mousedown", listener);
39
+ document.addEventListener("touchstart", listener);
40
+ return () => {
41
+ document.removeEventListener("mousedown", listener);
42
+ document.removeEventListener("touchstart", listener);
43
+ };
44
+ }, [ref, handler, enabled]);
45
+ }
46
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
47
+
48
+ // src/hooks/useScrollLock.ts
49
+ function useScrollLock(locked) {
50
+ useIsomorphicLayoutEffect(() => {
51
+ if (!locked || typeof document === "undefined") return;
52
+ const { body } = document;
53
+ const prevOverflow = body.style.overflow;
54
+ const prevPaddingRight = body.style.paddingRight;
55
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
56
+ body.style.overflow = "hidden";
57
+ if (scrollbarWidth > 0) {
58
+ body.style.paddingRight = `${scrollbarWidth}px`;
59
+ }
60
+ return () => {
61
+ body.style.overflow = prevOverflow;
62
+ body.style.paddingRight = prevPaddingRight;
63
+ };
64
+ }, [locked]);
65
+ }
66
+ function useControllableState(params) {
67
+ const { value, defaultValue, onChange } = params;
68
+ const isControlled = value !== void 0;
69
+ const [internal, setInternal] = react.useState(defaultValue);
70
+ const onChangeRef = react.useRef(onChange);
71
+ onChangeRef.current = onChange;
72
+ const current = isControlled ? value : internal;
73
+ const setValue = react.useCallback(
74
+ (next) => {
75
+ if (!isControlled) setInternal(next);
76
+ onChangeRef.current?.(next);
77
+ },
78
+ [isControlled]
79
+ );
80
+ return [current, setValue];
81
+ }
82
+ var AccordionContext = react.createContext(null);
83
+ function useAccordionContext() {
84
+ const ctx = react.useContext(AccordionContext);
85
+ if (ctx === null) {
86
+ throw new Error(
87
+ "Glasswind: <AccordionItem> must be rendered inside an <Accordion>."
88
+ );
89
+ }
90
+ return ctx;
91
+ }
92
+ function toOpenList(value) {
93
+ if (Array.isArray(value)) return value;
94
+ return value === "" ? [] : [value];
95
+ }
96
+ var NAV_KEYS = ["ArrowDown", "ArrowUp", "Home", "End"];
97
+ var Accordion = react.forwardRef(
98
+ function Accordion2({
99
+ type = "single",
100
+ value: valueProp,
101
+ defaultValue,
102
+ onChange,
103
+ collapsible = true,
104
+ className,
105
+ children,
106
+ ...rest
107
+ }, ref) {
108
+ const [value, setValue] = useControllableState({
109
+ value: valueProp,
110
+ defaultValue: defaultValue ?? (type === "multiple" ? [] : ""),
111
+ onChange
112
+ });
113
+ const toggle = react.useCallback(
114
+ (itemValue) => {
115
+ if (type === "multiple") {
116
+ const open = toOpenList(value);
117
+ const next = open.includes(itemValue) ? open.filter((v) => v !== itemValue) : [...open, itemValue];
118
+ setValue(next);
119
+ return;
120
+ }
121
+ const current = toOpenList(value)[0] ?? "";
122
+ if (current === itemValue) {
123
+ if (collapsible) setValue("");
124
+ } else {
125
+ setValue(itemValue);
126
+ }
127
+ },
128
+ [type, collapsible, value, setValue]
129
+ );
130
+ const ctx = react.useMemo(
131
+ () => ({
132
+ type,
133
+ isOpen: (itemValue) => toOpenList(value).includes(itemValue),
134
+ toggle
135
+ }),
136
+ [type, value, toggle]
137
+ );
138
+ return /* @__PURE__ */ jsxRuntime.jsx(
139
+ "div",
140
+ {
141
+ ref,
142
+ "data-gl-accordion": "",
143
+ className: cn("gl-accordion", className),
144
+ ...rest,
145
+ children: /* @__PURE__ */ jsxRuntime.jsx(AccordionContext.Provider, { value: ctx, children })
146
+ }
147
+ );
148
+ }
149
+ );
150
+ var AccordionItem = react.forwardRef(
151
+ function AccordionItem2({ value, title, disabled = false, className, children, ...rest }, ref) {
152
+ const { isOpen, toggle } = useAccordionContext();
153
+ const open = isOpen(value);
154
+ const baseId = react.useId();
155
+ const triggerId = `${baseId}-trigger`;
156
+ const panelId = `${baseId}-panel`;
157
+ const handleKeyDown = react.useCallback(
158
+ (event) => {
159
+ if (!NAV_KEYS.includes(event.key)) return;
160
+ const trigger = event.currentTarget;
161
+ const root = trigger.closest("[data-gl-accordion]");
162
+ if (root === null) return;
163
+ const triggers = Array.from(
164
+ root.querySelectorAll(
165
+ ".gl-accordion__trigger:not([disabled])"
166
+ )
167
+ ).filter((el) => el.closest("[data-gl-accordion]") === root);
168
+ if (triggers.length === 0) return;
169
+ const currentIndex = triggers.indexOf(trigger);
170
+ let nextIndex = currentIndex;
171
+ switch (event.key) {
172
+ case "ArrowDown":
173
+ nextIndex = (currentIndex + 1) % triggers.length;
174
+ break;
175
+ case "ArrowUp":
176
+ nextIndex = (currentIndex - 1 + triggers.length) % triggers.length;
177
+ break;
178
+ case "Home":
179
+ nextIndex = 0;
180
+ break;
181
+ case "End":
182
+ nextIndex = triggers.length - 1;
183
+ break;
184
+ default:
185
+ return;
186
+ }
187
+ event.preventDefault();
188
+ triggers[nextIndex]?.focus();
189
+ },
190
+ []
191
+ );
192
+ return /* @__PURE__ */ jsxRuntime.jsxs(
193
+ "div",
194
+ {
195
+ ref,
196
+ "data-state": open ? "open" : "closed",
197
+ className: cn(
198
+ "gl-accordion__item",
199
+ disabled && "gl-accordion__item--disabled",
200
+ className
201
+ ),
202
+ ...rest,
203
+ children: [
204
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "gl-accordion__header", children: /* @__PURE__ */ jsxRuntime.jsxs(
205
+ "button",
206
+ {
207
+ type: "button",
208
+ id: triggerId,
209
+ className: "gl-accordion__trigger",
210
+ "aria-expanded": open,
211
+ "aria-controls": panelId,
212
+ disabled,
213
+ onClick: () => toggle(value),
214
+ onKeyDown: handleKeyDown,
215
+ children: [
216
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-accordion__title", children: title }),
217
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-accordion__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
218
+ "svg",
219
+ {
220
+ viewBox: "0 0 24 24",
221
+ width: "1em",
222
+ height: "1em",
223
+ fill: "none",
224
+ stroke: "currentColor",
225
+ strokeWidth: "2",
226
+ strokeLinecap: "round",
227
+ strokeLinejoin: "round",
228
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
229
+ }
230
+ ) })
231
+ ]
232
+ }
233
+ ) }),
234
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gl-accordion__panel", "data-state": open ? "open" : "closed", children: /* @__PURE__ */ jsxRuntime.jsx(
235
+ "div",
236
+ {
237
+ id: panelId,
238
+ role: "region",
239
+ "aria-labelledby": triggerId,
240
+ className: "gl-accordion__content",
241
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gl-accordion__body", children })
242
+ }
243
+ ) })
244
+ ]
245
+ }
246
+ );
247
+ }
248
+ );
249
+ var STATUS_LABELS = {
250
+ online: "Online",
251
+ offline: "Offline",
252
+ busy: "Busy",
253
+ away: "Away"
254
+ };
255
+ function getInitials(name) {
256
+ const words = name.trim().split(/\s+/).filter(Boolean);
257
+ if (words.length === 0) return "";
258
+ return words.slice(0, 2).map((word) => word.charAt(0)).join("").toUpperCase();
259
+ }
260
+ function FallbackIcon() {
261
+ return /* @__PURE__ */ jsxRuntime.jsx(
262
+ "svg",
263
+ {
264
+ className: "gl-avatar__icon",
265
+ viewBox: "0 0 24 24",
266
+ fill: "none",
267
+ "aria-hidden": "true",
268
+ focusable: "false",
269
+ children: /* @__PURE__ */ jsxRuntime.jsx(
270
+ "path",
271
+ {
272
+ d: "M12 12.5a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 1.75c-3.6 0-6.5 2-6.5 4.5 0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25 0-2.5-2.9-4.5-6.5-4.5Z",
273
+ fill: "currentColor"
274
+ }
275
+ )
276
+ }
277
+ );
278
+ }
279
+ var Avatar = react.forwardRef(function Avatar2({
280
+ src,
281
+ alt,
282
+ name,
283
+ size = "md",
284
+ shape = "circle",
285
+ status,
286
+ className,
287
+ children,
288
+ ...rest
289
+ }, ref) {
290
+ const [imgFailed, setImgFailed] = react.useState(false);
291
+ react.useEffect(() => {
292
+ setImgFailed(false);
293
+ }, [src]);
294
+ const showImage = Boolean(src) && !imgFailed;
295
+ const initials = name ? getInitials(name) : "";
296
+ const a11yLabel = alt ?? name;
297
+ return /* @__PURE__ */ jsxRuntime.jsxs(
298
+ "span",
299
+ {
300
+ ref,
301
+ className: cn(
302
+ "gl-avatar",
303
+ `gl-avatar--${size}`,
304
+ `gl-avatar--${shape}`,
305
+ "gl-focusable",
306
+ className
307
+ ),
308
+ ...showImage ? {} : { role: "img", "aria-label": a11yLabel || "Avatar" },
309
+ ...rest,
310
+ children: [
311
+ showImage ? /* @__PURE__ */ jsxRuntime.jsx(
312
+ "img",
313
+ {
314
+ className: "gl-avatar__img",
315
+ src,
316
+ alt: alt ?? name ?? "",
317
+ draggable: false,
318
+ onError: () => setImgFailed(true)
319
+ }
320
+ ) : initials ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-avatar__initials", "aria-hidden": "true", children: initials }) : /* @__PURE__ */ jsxRuntime.jsx(FallbackIcon, {}),
321
+ children,
322
+ status ? /* @__PURE__ */ jsxRuntime.jsx(
323
+ "span",
324
+ {
325
+ className: cn("gl-avatar__status", `gl-avatar__status--${status}`),
326
+ role: "img",
327
+ "aria-label": STATUS_LABELS[status]
328
+ }
329
+ ) : null
330
+ ]
331
+ }
332
+ );
333
+ });
334
+ var Badge = react.forwardRef(function Badge2({
335
+ variant = "glass",
336
+ size = "md",
337
+ dot = false,
338
+ pill = true,
339
+ className,
340
+ children,
341
+ ...rest
342
+ }, ref) {
343
+ return /* @__PURE__ */ jsxRuntime.jsxs(
344
+ "span",
345
+ {
346
+ ref,
347
+ className: cn(
348
+ "gl-badge",
349
+ `gl-badge--${variant}`,
350
+ `gl-badge--${size}`,
351
+ pill && "gl-badge--pill",
352
+ className
353
+ ),
354
+ ...rest,
355
+ children: [
356
+ dot ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-badge__dot", "aria-hidden": "true" }) : null,
357
+ children != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-badge__label", children }) : null
358
+ ]
359
+ }
360
+ );
361
+ });
362
+ var Button = react.forwardRef(function Button2({
363
+ variant = "glass",
364
+ size = "md",
365
+ loading = false,
366
+ leftIcon,
367
+ rightIcon,
368
+ fullWidth = false,
369
+ className,
370
+ children,
371
+ disabled,
372
+ type = "button",
373
+ ...rest
374
+ }, ref) {
375
+ return /* @__PURE__ */ jsxRuntime.jsxs(
376
+ "button",
377
+ {
378
+ ref,
379
+ type,
380
+ className: cn(
381
+ "gl-btn",
382
+ `gl-btn--${variant}`,
383
+ `gl-btn--${size}`,
384
+ fullWidth && "gl-btn--block",
385
+ loading && "gl-btn--loading",
386
+ "gl-focusable",
387
+ className
388
+ ),
389
+ disabled: disabled || loading,
390
+ "aria-busy": loading || void 0,
391
+ ...rest,
392
+ children: [
393
+ loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-btn__spinner", "aria-hidden": "true" }),
394
+ !loading && leftIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-btn__icon", "aria-hidden": "true", children: leftIcon }) : null,
395
+ children != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-btn__label", children }) : null,
396
+ !loading && rightIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-btn__icon", "aria-hidden": "true", children: rightIcon }) : null
397
+ ]
398
+ }
399
+ );
400
+ });
401
+ var Card = react.forwardRef(function Card2({
402
+ variant = "glass",
403
+ padding = "md",
404
+ hoverable = false,
405
+ className,
406
+ children,
407
+ ...rest
408
+ }, ref) {
409
+ return /* @__PURE__ */ jsxRuntime.jsx(
410
+ "div",
411
+ {
412
+ ref,
413
+ className: cn(
414
+ "gl-card",
415
+ `gl-card--${variant}`,
416
+ `gl-card--pad-${padding}`,
417
+ hoverable && "gl-card--hoverable",
418
+ className
419
+ ),
420
+ ...rest,
421
+ children
422
+ }
423
+ );
424
+ });
425
+ var CardHeader = react.forwardRef(
426
+ function CardHeader2({ className, children, ...rest }, ref) {
427
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-card__header", className), ...rest, children });
428
+ }
429
+ );
430
+ var CardBody = react.forwardRef(
431
+ function CardBody2({ className, children, ...rest }, ref) {
432
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-card__body", className), ...rest, children });
433
+ }
434
+ );
435
+ var CardFooter = react.forwardRef(
436
+ function CardFooter2({ className, children, ...rest }, ref) {
437
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-card__footer", className), ...rest, children });
438
+ }
439
+ );
440
+ var Checkbox = react.forwardRef(
441
+ function Checkbox2({
442
+ label,
443
+ indeterminate = false,
444
+ error = false,
445
+ boxSize = "md",
446
+ className,
447
+ disabled,
448
+ ...rest
449
+ }, ref) {
450
+ const innerRef = react.useRef(null);
451
+ const setRef = react.useCallback(
452
+ (node) => {
453
+ innerRef.current = node;
454
+ if (typeof ref === "function") {
455
+ ref(node);
456
+ } else if (ref) {
457
+ ref.current = node;
458
+ }
459
+ },
460
+ [ref]
461
+ );
462
+ useIsomorphicLayoutEffect(() => {
463
+ if (innerRef.current) {
464
+ innerRef.current.indeterminate = indeterminate;
465
+ }
466
+ }, [indeterminate]);
467
+ return /* @__PURE__ */ jsxRuntime.jsxs(
468
+ "label",
469
+ {
470
+ className: cn(
471
+ "gl-checkbox",
472
+ `gl-checkbox--${boxSize}`,
473
+ error && "gl-checkbox--error",
474
+ disabled && "gl-checkbox--disabled",
475
+ className
476
+ ),
477
+ children: [
478
+ /* @__PURE__ */ jsxRuntime.jsx(
479
+ "input",
480
+ {
481
+ ref: setRef,
482
+ type: "checkbox",
483
+ className: "gl-sr-only gl-checkbox__input",
484
+ disabled,
485
+ "aria-invalid": error || void 0,
486
+ ...rest
487
+ }
488
+ ),
489
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "gl-checkbox__box", "aria-hidden": "true", children: [
490
+ /* @__PURE__ */ jsxRuntime.jsx(
491
+ "svg",
492
+ {
493
+ className: "gl-checkbox__check",
494
+ viewBox: "0 0 16 16",
495
+ fill: "none",
496
+ xmlns: "http://www.w3.org/2000/svg",
497
+ children: /* @__PURE__ */ jsxRuntime.jsx(
498
+ "path",
499
+ {
500
+ d: "M3.5 8.5L6.5 11.5L12.5 4.5",
501
+ stroke: "currentColor",
502
+ strokeWidth: "2",
503
+ strokeLinecap: "round",
504
+ strokeLinejoin: "round"
505
+ }
506
+ )
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-checkbox__dash" })
510
+ ] }),
511
+ label != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-checkbox__label", children: label }) : null
512
+ ]
513
+ }
514
+ );
515
+ }
516
+ );
517
+ function Portal({ children, container }) {
518
+ const [mounted, setMounted] = react.useState(false);
519
+ useIsomorphicLayoutEffect(() => {
520
+ setMounted(true);
521
+ return () => setMounted(false);
522
+ }, []);
523
+ if (!mounted || typeof document === "undefined") return null;
524
+ return reactDom.createPortal(children, container ?? document.body);
525
+ }
526
+ function assignRef(ref, node) {
527
+ if (typeof ref === "function") {
528
+ ref(node);
529
+ } else if (ref) {
530
+ ref.current = node;
531
+ }
532
+ }
533
+ var Drawer = react.forwardRef(function Drawer2({
534
+ isOpen,
535
+ onClose,
536
+ children,
537
+ side = "right",
538
+ size = "340px",
539
+ title,
540
+ closeOnBackdrop = true,
541
+ closeOnEsc = true,
542
+ showClose = true,
543
+ className,
544
+ style,
545
+ ...rest
546
+ }, ref) {
547
+ const panelRef = react.useRef(null);
548
+ const previousFocusRef = react.useRef(null);
549
+ const reactId = react.useId();
550
+ const titleId = `${reactId}-title`;
551
+ useScrollLock(isOpen);
552
+ const setPanelRef = react.useCallback(
553
+ (node) => {
554
+ panelRef.current = node;
555
+ assignRef(ref, node);
556
+ },
557
+ [ref]
558
+ );
559
+ react.useEffect(() => {
560
+ if (!isOpen || !closeOnEsc) return;
561
+ const onKeyDown = (event) => {
562
+ if (event.key === "Escape") {
563
+ event.stopPropagation();
564
+ onClose();
565
+ }
566
+ };
567
+ document.addEventListener("keydown", onKeyDown);
568
+ return () => document.removeEventListener("keydown", onKeyDown);
569
+ }, [isOpen, closeOnEsc, onClose]);
570
+ react.useEffect(() => {
571
+ if (!isOpen) return;
572
+ previousFocusRef.current = document.activeElement;
573
+ panelRef.current?.focus();
574
+ return () => {
575
+ previousFocusRef.current?.focus?.();
576
+ };
577
+ }, [isOpen]);
578
+ if (!isOpen) return null;
579
+ const isHorizontal = side === "left" || side === "right";
580
+ const sizeValue = typeof size === "number" ? `${size}px` : size;
581
+ const panelStyle = {
582
+ ...style,
583
+ ...isHorizontal ? { width: sizeValue } : { height: sizeValue }
584
+ };
585
+ const hasHeader = title != null || showClose;
586
+ return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gl-drawer", children: [
587
+ /* @__PURE__ */ jsxRuntime.jsx(
588
+ "div",
589
+ {
590
+ className: "gl-drawer__backdrop",
591
+ "aria-hidden": "true",
592
+ onClick: closeOnBackdrop ? onClose : void 0
593
+ }
594
+ ),
595
+ /* @__PURE__ */ jsxRuntime.jsxs(
596
+ "div",
597
+ {
598
+ ref: setPanelRef,
599
+ role: "dialog",
600
+ "aria-modal": "true",
601
+ "aria-labelledby": title != null ? titleId : void 0,
602
+ tabIndex: -1,
603
+ style: panelStyle,
604
+ className: cn(
605
+ "gl-drawer__panel",
606
+ `gl-drawer__panel--${side}`,
607
+ "gl-focusable",
608
+ className
609
+ ),
610
+ ...rest,
611
+ children: [
612
+ hasHeader ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gl-drawer__header", children: [
613
+ title != null ? /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: "gl-drawer__title", children: title }) : null,
614
+ showClose ? /* @__PURE__ */ jsxRuntime.jsx(
615
+ "button",
616
+ {
617
+ type: "button",
618
+ className: "gl-drawer__close gl-focusable",
619
+ "aria-label": "Close",
620
+ onClick: onClose,
621
+ children: /* @__PURE__ */ jsxRuntime.jsx(
622
+ "svg",
623
+ {
624
+ viewBox: "0 0 24 24",
625
+ width: "18",
626
+ height: "18",
627
+ fill: "none",
628
+ stroke: "currentColor",
629
+ strokeWidth: "2",
630
+ strokeLinecap: "round",
631
+ "aria-hidden": "true",
632
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M18 6L6 18" })
633
+ }
634
+ )
635
+ }
636
+ ) : null
637
+ ] }) : null,
638
+ children
639
+ ]
640
+ }
641
+ )
642
+ ] }) });
643
+ });
644
+ var DrawerHeader = react.forwardRef(
645
+ function DrawerHeader2({ className, children, ...rest }, ref) {
646
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-drawer__header", className), ...rest, children });
647
+ }
648
+ );
649
+ var DrawerBody = react.forwardRef(
650
+ function DrawerBody2({ className, children, ...rest }, ref) {
651
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-drawer__body", className), ...rest, children });
652
+ }
653
+ );
654
+ var DrawerFooter = react.forwardRef(
655
+ function DrawerFooter2({ className, children, ...rest }, ref) {
656
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-drawer__footer", className), ...rest, children });
657
+ }
658
+ );
659
+ var DropdownContext = react.createContext(null);
660
+ function useDropdownContext(part) {
661
+ const ctx = react.useContext(DropdownContext);
662
+ if (!ctx) {
663
+ throw new Error(`${part} must be rendered inside a <Dropdown>.`);
664
+ }
665
+ return ctx;
666
+ }
667
+ var ITEM_SELECTOR = '[role="menuitem"]:not([disabled]):not([aria-disabled="true"])';
668
+ function getMenuItems(menu) {
669
+ if (!menu) return [];
670
+ return Array.from(menu.querySelectorAll(ITEM_SELECTOR));
671
+ }
672
+ function assignRef2(ref, value) {
673
+ if (typeof ref === "function") {
674
+ ref(value);
675
+ } else if (ref) {
676
+ ref.current = value;
677
+ }
678
+ }
679
+ function Dropdown({
680
+ open: openProp,
681
+ defaultOpen = false,
682
+ onOpenChange,
683
+ placement = "bottom-start",
684
+ children
685
+ }) {
686
+ const [open, setOpen] = useControllableState({
687
+ value: openProp,
688
+ defaultValue: defaultOpen,
689
+ onChange: onOpenChange
690
+ });
691
+ const rootRef = react.useRef(null);
692
+ const triggerRef = react.useRef(null);
693
+ const menuRef = react.useRef(null);
694
+ const reactId = react.useId();
695
+ const triggerId = `${reactId}-trigger`;
696
+ const menuId = `${reactId}-menu`;
697
+ const close = react.useCallback(() => setOpen(false), [setOpen]);
698
+ const closeAndFocusTrigger = react.useCallback(() => {
699
+ setOpen(false);
700
+ triggerRef.current?.focus();
701
+ }, [setOpen]);
702
+ useClickOutside(rootRef, close, open);
703
+ react.useEffect(() => {
704
+ if (!open) return;
705
+ const onKeyDown = (event) => {
706
+ if (event.key === "Escape") {
707
+ event.preventDefault();
708
+ setOpen(false);
709
+ triggerRef.current?.focus();
710
+ }
711
+ };
712
+ document.addEventListener("keydown", onKeyDown);
713
+ return () => document.removeEventListener("keydown", onKeyDown);
714
+ }, [open, setOpen]);
715
+ const value = {
716
+ open,
717
+ setOpen,
718
+ placement,
719
+ triggerId,
720
+ menuId,
721
+ triggerRef,
722
+ menuRef,
723
+ closeAndFocusTrigger
724
+ };
725
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx("span", { ref: rootRef, className: "gl-dropdown", children }) });
726
+ }
727
+ var DropdownTrigger = react.forwardRef(function DropdownTrigger2({ className, children, onClick, onKeyDown, type = "button", ...rest }, ref) {
728
+ const ctx = useDropdownContext("DropdownTrigger");
729
+ const setRef = react.useCallback(
730
+ (node) => {
731
+ ctx.triggerRef.current = node;
732
+ assignRef2(ref, node);
733
+ },
734
+ [ctx.triggerRef, ref]
735
+ );
736
+ const handleClick = react.useCallback(
737
+ (event) => {
738
+ ctx.setOpen(!ctx.open);
739
+ onClick?.(event);
740
+ },
741
+ [ctx, onClick]
742
+ );
743
+ const handleKeyDown = react.useCallback(
744
+ (event) => {
745
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
746
+ event.preventDefault();
747
+ if (!ctx.open) {
748
+ ctx.setOpen(true);
749
+ } else {
750
+ getMenuItems(ctx.menuRef.current)[0]?.focus();
751
+ }
752
+ }
753
+ onKeyDown?.(event);
754
+ },
755
+ [ctx, onKeyDown]
756
+ );
757
+ return /* @__PURE__ */ jsxRuntime.jsx(
758
+ "button",
759
+ {
760
+ ref: setRef,
761
+ type,
762
+ id: ctx.triggerId,
763
+ className: cn("gl-dropdown__trigger", "gl-focusable", className),
764
+ "aria-haspopup": "menu",
765
+ "aria-expanded": ctx.open,
766
+ "aria-controls": ctx.open ? ctx.menuId : void 0,
767
+ onClick: handleClick,
768
+ onKeyDown: handleKeyDown,
769
+ ...rest,
770
+ children
771
+ }
772
+ );
773
+ });
774
+ var DropdownMenu = react.forwardRef(
775
+ function DropdownMenu2({ className, children, onKeyDown, ...rest }, ref) {
776
+ const ctx = useDropdownContext("DropdownMenu");
777
+ const { open, menuRef } = ctx;
778
+ const setRef = react.useCallback(
779
+ (node) => {
780
+ menuRef.current = node;
781
+ assignRef2(ref, node);
782
+ },
783
+ [menuRef, ref]
784
+ );
785
+ react.useEffect(() => {
786
+ if (!open) return;
787
+ getMenuItems(menuRef.current)[0]?.focus();
788
+ }, [open, menuRef]);
789
+ const handleKeyDown = react.useCallback(
790
+ (event) => {
791
+ const items = getMenuItems(menuRef.current);
792
+ if (items.length > 0) {
793
+ const active = document.activeElement;
794
+ const currentIndex = active ? items.indexOf(active) : -1;
795
+ switch (event.key) {
796
+ case "ArrowDown": {
797
+ event.preventDefault();
798
+ const next = currentIndex < 0 ? 0 : (currentIndex + 1) % items.length;
799
+ items[next]?.focus();
800
+ break;
801
+ }
802
+ case "ArrowUp": {
803
+ event.preventDefault();
804
+ const prev = currentIndex < 0 ? items.length - 1 : (currentIndex - 1 + items.length) % items.length;
805
+ items[prev]?.focus();
806
+ break;
807
+ }
808
+ case "Home": {
809
+ event.preventDefault();
810
+ items[0]?.focus();
811
+ break;
812
+ }
813
+ case "End": {
814
+ event.preventDefault();
815
+ items[items.length - 1]?.focus();
816
+ break;
817
+ }
818
+ }
819
+ }
820
+ onKeyDown?.(event);
821
+ },
822
+ [menuRef, onKeyDown]
823
+ );
824
+ if (!open) return null;
825
+ return /* @__PURE__ */ jsxRuntime.jsx(
826
+ "div",
827
+ {
828
+ ref: setRef,
829
+ id: ctx.menuId,
830
+ role: "menu",
831
+ "aria-orientation": "vertical",
832
+ "aria-labelledby": ctx.triggerId,
833
+ tabIndex: -1,
834
+ className: cn(
835
+ "gl-dropdown__menu",
836
+ `gl-dropdown__menu--${ctx.placement}`,
837
+ className
838
+ ),
839
+ onKeyDown: handleKeyDown,
840
+ ...rest,
841
+ children
842
+ }
843
+ );
844
+ }
845
+ );
846
+ var DropdownItem = react.forwardRef(
847
+ function DropdownItem2({ className, children, onSelect, disabled = false, leftIcon, onClick, type = "button", ...rest }, ref) {
848
+ const ctx = useDropdownContext("DropdownItem");
849
+ const handleClick = react.useCallback(
850
+ (event) => {
851
+ if (disabled) return;
852
+ onClick?.(event);
853
+ onSelect?.();
854
+ ctx.closeAndFocusTrigger();
855
+ },
856
+ [ctx, disabled, onClick, onSelect]
857
+ );
858
+ return /* @__PURE__ */ jsxRuntime.jsxs(
859
+ "button",
860
+ {
861
+ ref,
862
+ type,
863
+ role: "menuitem",
864
+ tabIndex: -1,
865
+ disabled,
866
+ className: cn("gl-dropdown__item", "gl-focusable", className),
867
+ onClick: handleClick,
868
+ ...rest,
869
+ children: [
870
+ leftIcon != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-dropdown__item-icon", "aria-hidden": "true", children: leftIcon }) : null,
871
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-dropdown__item-label", children })
872
+ ]
873
+ }
874
+ );
875
+ }
876
+ );
877
+ var DropdownSeparator = react.forwardRef(function DropdownSeparator2({ className, ...rest }, ref) {
878
+ return /* @__PURE__ */ jsxRuntime.jsx(
879
+ "div",
880
+ {
881
+ ref,
882
+ role: "separator",
883
+ "aria-orientation": "horizontal",
884
+ className: cn("gl-dropdown__separator", className),
885
+ ...rest
886
+ }
887
+ );
888
+ });
889
+ var DropdownLabel = react.forwardRef(
890
+ function DropdownLabel2({ className, children, ...rest }, ref) {
891
+ return /* @__PURE__ */ jsxRuntime.jsx(
892
+ "div",
893
+ {
894
+ ref,
895
+ role: "presentation",
896
+ className: cn("gl-dropdown__label", className),
897
+ ...rest,
898
+ children
899
+ }
900
+ );
901
+ }
902
+ );
903
+ var Input = react.forwardRef(function Input2({
904
+ variant = "subtle",
905
+ inputSize = "md",
906
+ error = false,
907
+ leftIcon,
908
+ rightIcon,
909
+ fullWidth = false,
910
+ className,
911
+ disabled,
912
+ "aria-invalid": ariaInvalid,
913
+ ...rest
914
+ }, ref) {
915
+ return /* @__PURE__ */ jsxRuntime.jsxs(
916
+ "span",
917
+ {
918
+ className: cn(
919
+ "gl-input",
920
+ `gl-input--${variant}`,
921
+ `gl-input--${inputSize}`,
922
+ error && "gl-input--error",
923
+ fullWidth && "gl-input--block",
924
+ disabled && "gl-input--disabled",
925
+ className
926
+ ),
927
+ children: [
928
+ leftIcon != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-input__icon gl-input__icon--left", "aria-hidden": "true", children: leftIcon }) : null,
929
+ /* @__PURE__ */ jsxRuntime.jsx(
930
+ "input",
931
+ {
932
+ ref,
933
+ className: "gl-input__field",
934
+ disabled,
935
+ "aria-invalid": ariaInvalid ?? (error || void 0),
936
+ ...rest
937
+ }
938
+ ),
939
+ rightIcon != null ? /* @__PURE__ */ jsxRuntime.jsx(
940
+ "span",
941
+ {
942
+ className: "gl-input__icon gl-input__icon--right",
943
+ "aria-hidden": "true",
944
+ children: rightIcon
945
+ }
946
+ ) : null
947
+ ]
948
+ }
949
+ );
950
+ });
951
+ var Modal = react.forwardRef(function Modal2({
952
+ isOpen,
953
+ onClose,
954
+ children,
955
+ title,
956
+ size = "md",
957
+ closeOnBackdrop = true,
958
+ closeOnEsc = true,
959
+ showClose = true,
960
+ className,
961
+ ...rest
962
+ }, ref) {
963
+ const titleId = react.useId();
964
+ const panelRef = react.useRef(null);
965
+ const setPanelRef = react.useCallback(
966
+ (node) => {
967
+ panelRef.current = node;
968
+ if (typeof ref === "function") {
969
+ ref(node);
970
+ } else if (ref) {
971
+ ref.current = node;
972
+ }
973
+ },
974
+ [ref]
975
+ );
976
+ useScrollLock(isOpen);
977
+ react.useEffect(() => {
978
+ if (!isOpen || !closeOnEsc) return;
979
+ const handleKeyDown = (event) => {
980
+ if (event.key === "Escape") {
981
+ event.stopPropagation();
982
+ onClose();
983
+ }
984
+ };
985
+ document.addEventListener("keydown", handleKeyDown);
986
+ return () => document.removeEventListener("keydown", handleKeyDown);
987
+ }, [isOpen, closeOnEsc, onClose]);
988
+ react.useEffect(() => {
989
+ if (!isOpen) return;
990
+ const previouslyFocused = typeof document !== "undefined" ? document.activeElement : null;
991
+ panelRef.current?.focus();
992
+ return () => {
993
+ previouslyFocused?.focus?.();
994
+ };
995
+ }, [isOpen]);
996
+ if (!isOpen) return null;
997
+ const handleBackdropClick = (event) => {
998
+ if (closeOnBackdrop && event.target === event.currentTarget) {
999
+ onClose();
1000
+ }
1001
+ };
1002
+ const hasHeader = title != null || showClose;
1003
+ return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gl-modal__backdrop", onClick: handleBackdropClick, children: /* @__PURE__ */ jsxRuntime.jsxs(
1004
+ "div",
1005
+ {
1006
+ ref: setPanelRef,
1007
+ role: "dialog",
1008
+ "aria-modal": "true",
1009
+ "aria-labelledby": title != null ? titleId : void 0,
1010
+ tabIndex: -1,
1011
+ className: cn(
1012
+ "gl-modal__panel",
1013
+ `gl-modal__panel--${size}`,
1014
+ "gl-focusable",
1015
+ className
1016
+ ),
1017
+ ...rest,
1018
+ children: [
1019
+ hasHeader ? /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "gl-modal__header", children: [
1020
+ title != null ? /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: "gl-modal__title", children: title }) : null,
1021
+ showClose ? /* @__PURE__ */ jsxRuntime.jsx(
1022
+ "button",
1023
+ {
1024
+ type: "button",
1025
+ className: "gl-modal__close gl-focusable",
1026
+ "aria-label": "Close",
1027
+ onClick: onClose,
1028
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1029
+ "svg",
1030
+ {
1031
+ viewBox: "0 0 24 24",
1032
+ width: "1em",
1033
+ height: "1em",
1034
+ fill: "none",
1035
+ stroke: "currentColor",
1036
+ strokeWidth: 2,
1037
+ strokeLinecap: "round",
1038
+ "aria-hidden": "true",
1039
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M18 6L6 18" })
1040
+ }
1041
+ )
1042
+ }
1043
+ ) : null
1044
+ ] }) : null,
1045
+ children
1046
+ ]
1047
+ }
1048
+ ) }) });
1049
+ });
1050
+ var ModalHeader = react.forwardRef(
1051
+ function ModalHeader2({ className, children, ...rest }, ref) {
1052
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-modal__header", className), ...rest, children });
1053
+ }
1054
+ );
1055
+ var ModalBody = react.forwardRef(
1056
+ function ModalBody2({ className, children, ...rest }, ref) {
1057
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-modal__body", className), ...rest, children });
1058
+ }
1059
+ );
1060
+ var ModalFooter = react.forwardRef(
1061
+ function ModalFooter2({ className, children, ...rest }, ref) {
1062
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-modal__footer", className), ...rest, children });
1063
+ }
1064
+ );
1065
+ var Progress = react.forwardRef(function Progress2({
1066
+ value = 0,
1067
+ max = 100,
1068
+ indeterminate = false,
1069
+ barSize = "md",
1070
+ color = "primary",
1071
+ showLabel = false,
1072
+ className,
1073
+ ...rest
1074
+ }, ref) {
1075
+ const safeMax = max > 0 ? max : 100;
1076
+ const clamped = Math.min(Math.max(value, 0), safeMax);
1077
+ const ratio = clamped / safeMax;
1078
+ const percent = Math.round(ratio * 100);
1079
+ const barStyle = indeterminate ? void 0 : { "--gl-progress-value": ratio };
1080
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1081
+ "div",
1082
+ {
1083
+ ref,
1084
+ role: "progressbar",
1085
+ "aria-valuemin": 0,
1086
+ "aria-valuemax": safeMax,
1087
+ "aria-valuenow": indeterminate ? void 0 : clamped,
1088
+ "aria-valuetext": indeterminate ? void 0 : `${percent}%`,
1089
+ className: cn(
1090
+ "gl-progress",
1091
+ `gl-progress--${barSize}`,
1092
+ `gl-progress--${color}`,
1093
+ className
1094
+ ),
1095
+ ...rest,
1096
+ children: [
1097
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gl-progress__track", children: /* @__PURE__ */ jsxRuntime.jsx(
1098
+ "div",
1099
+ {
1100
+ className: cn(
1101
+ "gl-progress__bar",
1102
+ indeterminate && "gl-progress__bar--indeterminate"
1103
+ ),
1104
+ style: barStyle
1105
+ }
1106
+ ) }),
1107
+ showLabel && !indeterminate ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "gl-progress__label", children: [
1108
+ percent,
1109
+ "%"
1110
+ ] }) : null
1111
+ ]
1112
+ }
1113
+ );
1114
+ });
1115
+ var RadioGroupContext = react.createContext(
1116
+ null
1117
+ );
1118
+ function useRadioGroupContext(component) {
1119
+ const ctx = react.useContext(RadioGroupContext);
1120
+ if (ctx === null) {
1121
+ throw new Error(
1122
+ `Glasswind: <${component}> must be rendered inside a <RadioGroup>.`
1123
+ );
1124
+ }
1125
+ return ctx;
1126
+ }
1127
+ var RadioGroup = react.forwardRef(
1128
+ function RadioGroup2({
1129
+ value,
1130
+ defaultValue,
1131
+ onChange,
1132
+ name,
1133
+ orientation = "vertical",
1134
+ className,
1135
+ children,
1136
+ ...rest
1137
+ }, ref) {
1138
+ const fallbackName = react.useId();
1139
+ const [selected, setSelected] = useControllableState({
1140
+ value,
1141
+ defaultValue: defaultValue ?? "",
1142
+ onChange
1143
+ });
1144
+ const ctx = react.useMemo(
1145
+ () => ({
1146
+ name: name ?? fallbackName,
1147
+ value: selected,
1148
+ setValue: setSelected
1149
+ }),
1150
+ [name, fallbackName, selected, setSelected]
1151
+ );
1152
+ return /* @__PURE__ */ jsxRuntime.jsx(
1153
+ "div",
1154
+ {
1155
+ ref,
1156
+ role: "radiogroup",
1157
+ "aria-orientation": orientation,
1158
+ className: cn(
1159
+ "gl-radio-group",
1160
+ `gl-radio-group--${orientation}`,
1161
+ className
1162
+ ),
1163
+ ...rest,
1164
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadioGroupContext.Provider, { value: ctx, children })
1165
+ }
1166
+ );
1167
+ }
1168
+ );
1169
+ var Radio = react.forwardRef(function Radio2({ value, label, disabled = false, className, ...rest }, ref) {
1170
+ const ctx = useRadioGroupContext("Radio");
1171
+ const checked = ctx.value === value;
1172
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1173
+ "label",
1174
+ {
1175
+ className: cn(
1176
+ "gl-radio",
1177
+ checked && "gl-radio--checked",
1178
+ disabled && "gl-radio--disabled",
1179
+ className
1180
+ ),
1181
+ children: [
1182
+ /* @__PURE__ */ jsxRuntime.jsx(
1183
+ "input",
1184
+ {
1185
+ ref,
1186
+ type: "radio",
1187
+ className: "gl-sr-only gl-radio__input",
1188
+ name: ctx.name,
1189
+ value,
1190
+ checked,
1191
+ disabled,
1192
+ onChange: () => ctx.setValue(value),
1193
+ ...rest
1194
+ }
1195
+ ),
1196
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-radio__dot", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-radio__mark" }) }),
1197
+ label != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-radio__label", children: label }) : null
1198
+ ]
1199
+ }
1200
+ );
1201
+ });
1202
+ var Select = react.forwardRef(function Select2({
1203
+ options,
1204
+ placeholder,
1205
+ selectSize = "md",
1206
+ error = false,
1207
+ fullWidth = false,
1208
+ className,
1209
+ children,
1210
+ disabled,
1211
+ value,
1212
+ defaultValue,
1213
+ "aria-invalid": ariaInvalid,
1214
+ ...rest
1215
+ }, ref) {
1216
+ const isControlled = value !== void 0;
1217
+ const resolvedDefaultValue = !isControlled && defaultValue === void 0 && placeholder != null ? "" : defaultValue;
1218
+ const selectionProps = isControlled ? { value } : { defaultValue: resolvedDefaultValue };
1219
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1220
+ "span",
1221
+ {
1222
+ className: cn(
1223
+ "gl-select",
1224
+ `gl-select--${selectSize}`,
1225
+ error && "gl-select--error",
1226
+ fullWidth && "gl-select--block",
1227
+ disabled && "gl-select--disabled",
1228
+ className
1229
+ ),
1230
+ children: [
1231
+ /* @__PURE__ */ jsxRuntime.jsxs(
1232
+ "select",
1233
+ {
1234
+ ref,
1235
+ className: "gl-select__field",
1236
+ disabled,
1237
+ "aria-invalid": ariaInvalid ?? (error || void 0),
1238
+ ...selectionProps,
1239
+ ...rest,
1240
+ children: [
1241
+ placeholder != null ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, hidden: true, children: placeholder }) : null,
1242
+ options ? options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
1243
+ "option",
1244
+ {
1245
+ value: opt.value,
1246
+ disabled: opt.disabled,
1247
+ children: opt.label
1248
+ },
1249
+ String(opt.value)
1250
+ )) : children
1251
+ ]
1252
+ }
1253
+ ),
1254
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-select__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
1255
+ "svg",
1256
+ {
1257
+ viewBox: "0 0 24 24",
1258
+ width: "1em",
1259
+ height: "1em",
1260
+ fill: "none",
1261
+ stroke: "currentColor",
1262
+ strokeWidth: "2",
1263
+ strokeLinecap: "round",
1264
+ strokeLinejoin: "round",
1265
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
1266
+ }
1267
+ ) })
1268
+ ]
1269
+ }
1270
+ );
1271
+ });
1272
+ var Slider = react.forwardRef(function Slider2({
1273
+ min = 0,
1274
+ max = 100,
1275
+ step = 1,
1276
+ value,
1277
+ defaultValue,
1278
+ onChange,
1279
+ showValue = false,
1280
+ className,
1281
+ style,
1282
+ disabled,
1283
+ ...rest
1284
+ }, ref) {
1285
+ const [current, setValue] = useControllableState({
1286
+ value,
1287
+ defaultValue: defaultValue ?? min,
1288
+ onChange
1289
+ });
1290
+ const range = max - min;
1291
+ const clamped = Math.min(max, Math.max(min, current));
1292
+ const fillPct = range > 0 ? (clamped - min) / range * 100 : 0;
1293
+ const handleChange = (event) => {
1294
+ const next = event.target.valueAsNumber;
1295
+ setValue(Number.isNaN(next) ? min : next);
1296
+ };
1297
+ const wrapperStyle = {
1298
+ ...style,
1299
+ "--gl-slider-fill": `${fillPct}%`
1300
+ };
1301
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1302
+ "span",
1303
+ {
1304
+ className: cn(
1305
+ "gl-slider",
1306
+ showValue && "gl-slider--show-value",
1307
+ disabled && "gl-slider--disabled",
1308
+ className
1309
+ ),
1310
+ style: wrapperStyle,
1311
+ children: [
1312
+ /* @__PURE__ */ jsxRuntime.jsx(
1313
+ "input",
1314
+ {
1315
+ ref,
1316
+ type: "range",
1317
+ className: "gl-slider__input",
1318
+ min,
1319
+ max,
1320
+ step,
1321
+ value: clamped,
1322
+ disabled,
1323
+ onChange: handleChange,
1324
+ ...rest
1325
+ }
1326
+ ),
1327
+ showValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-slider__value", "aria-hidden": "true", children: current }) : null
1328
+ ]
1329
+ }
1330
+ );
1331
+ });
1332
+ var Spinner = react.forwardRef(function Spinner2({ size = "md", label = "Loading", thickness, className, style, ...rest }, ref) {
1333
+ const styleWithThickness = thickness != null ? { ...style, "--gl-spinner-bw": `${thickness}px` } : style;
1334
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1335
+ "span",
1336
+ {
1337
+ ref,
1338
+ role: "status",
1339
+ "aria-live": "polite",
1340
+ className: cn("gl-spinner", `gl-spinner--${size}`, className),
1341
+ style: styleWithThickness,
1342
+ ...rest,
1343
+ children: [
1344
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-spinner__ring", "aria-hidden": "true" }),
1345
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-sr-only", children: label })
1346
+ ]
1347
+ }
1348
+ );
1349
+ });
1350
+ var Switch = react.forwardRef(function Switch2({
1351
+ checked,
1352
+ defaultChecked = false,
1353
+ onChange,
1354
+ label,
1355
+ switchSize = "md",
1356
+ disabled = false,
1357
+ className,
1358
+ id,
1359
+ ...rest
1360
+ }, ref) {
1361
+ const reactId = react.useId();
1362
+ const inputId = id ?? reactId;
1363
+ const [isChecked, setChecked] = useControllableState({
1364
+ value: checked,
1365
+ defaultValue: defaultChecked,
1366
+ onChange
1367
+ });
1368
+ const handleChange = (event) => {
1369
+ setChecked(event.target.checked);
1370
+ };
1371
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1372
+ "label",
1373
+ {
1374
+ className: cn(
1375
+ "gl-switch",
1376
+ `gl-switch--${switchSize}`,
1377
+ isChecked && "gl-switch--checked",
1378
+ disabled && "gl-switch--disabled",
1379
+ className
1380
+ ),
1381
+ htmlFor: inputId,
1382
+ children: [
1383
+ /* @__PURE__ */ jsxRuntime.jsx(
1384
+ "input",
1385
+ {
1386
+ ref,
1387
+ id: inputId,
1388
+ type: "checkbox",
1389
+ role: "switch",
1390
+ className: "gl-switch__input gl-sr-only",
1391
+ checked: isChecked,
1392
+ disabled,
1393
+ onChange: handleChange,
1394
+ ...rest
1395
+ }
1396
+ ),
1397
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-switch__track", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-switch__thumb" }) }),
1398
+ label != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-switch__label", children: label }) : null
1399
+ ]
1400
+ }
1401
+ );
1402
+ });
1403
+ var TabsContext = react.createContext(null);
1404
+ function useTabsContext(component) {
1405
+ const ctx = react.useContext(TabsContext);
1406
+ if (!ctx) {
1407
+ throw new Error(`<${component}> must be rendered inside <Tabs>.`);
1408
+ }
1409
+ return ctx;
1410
+ }
1411
+ var idSafe = (value) => value.replace(/\s+/g, "-");
1412
+ var Tabs = react.forwardRef(function Tabs2({ value, defaultValue, onChange, className, children, ...rest }, ref) {
1413
+ const baseId = react.useId();
1414
+ const [activeValue, setControllableValue] = useControllableState({
1415
+ value,
1416
+ defaultValue,
1417
+ onChange: onChange ? (next) => {
1418
+ if (next !== void 0) onChange(next);
1419
+ } : void 0
1420
+ });
1421
+ const orderRef = react.useRef([]);
1422
+ const disabledRef = react.useRef(/* @__PURE__ */ new Map());
1423
+ const [, bump] = react.useReducer((n) => n + 1, 0);
1424
+ const registerTab = react.useCallback((v) => {
1425
+ if (orderRef.current.includes(v)) return;
1426
+ orderRef.current = [...orderRef.current, v];
1427
+ if (!disabledRef.current.has(v)) disabledRef.current.set(v, false);
1428
+ bump();
1429
+ }, []);
1430
+ const unregisterTab = react.useCallback((v) => {
1431
+ if (!orderRef.current.includes(v)) return;
1432
+ orderRef.current = orderRef.current.filter((x) => x !== v);
1433
+ disabledRef.current.delete(v);
1434
+ bump();
1435
+ }, []);
1436
+ const setTabDisabled = react.useCallback((v, disabled) => {
1437
+ if (disabledRef.current.get(v) === disabled) return;
1438
+ disabledRef.current.set(v, disabled);
1439
+ bump();
1440
+ }, []);
1441
+ const activeValueRef = react.useRef(activeValue);
1442
+ activeValueRef.current = activeValue;
1443
+ const setActiveValue = react.useCallback(
1444
+ (v) => {
1445
+ if (activeValueRef.current === v) return;
1446
+ setControllableValue(v);
1447
+ },
1448
+ [setControllableValue]
1449
+ );
1450
+ const getTabId = react.useCallback(
1451
+ (v) => `${baseId}-tab-${idSafe(v)}`,
1452
+ [baseId]
1453
+ );
1454
+ const getPanelId = react.useCallback(
1455
+ (v) => `${baseId}-panel-${idSafe(v)}`,
1456
+ [baseId]
1457
+ );
1458
+ const order = orderRef.current;
1459
+ const disabledMap = disabledRef.current;
1460
+ const activeIsFocusable = activeValue !== void 0 && order.includes(activeValue) && !disabledMap.get(activeValue);
1461
+ const focusableValue = activeIsFocusable ? activeValue : order.find((v) => !disabledMap.get(v));
1462
+ const ctx = react.useMemo(
1463
+ () => ({
1464
+ baseId,
1465
+ activeValue,
1466
+ setActiveValue,
1467
+ focusableValue,
1468
+ registerTab,
1469
+ unregisterTab,
1470
+ setTabDisabled,
1471
+ getTabId,
1472
+ getPanelId
1473
+ }),
1474
+ [
1475
+ baseId,
1476
+ activeValue,
1477
+ setActiveValue,
1478
+ focusableValue,
1479
+ registerTab,
1480
+ unregisterTab,
1481
+ setTabDisabled,
1482
+ getTabId,
1483
+ getPanelId
1484
+ ]
1485
+ );
1486
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: ctx, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("gl-tabs", className), ...rest, children }) });
1487
+ });
1488
+ var TabList = react.forwardRef(function TabList2({ className, children, onKeyDown, ...rest }, ref) {
1489
+ const { setActiveValue } = useTabsContext("TabList");
1490
+ const listRef = react.useRef(null);
1491
+ const setRefs = react.useCallback(
1492
+ (node) => {
1493
+ listRef.current = node;
1494
+ if (typeof ref === "function") ref(node);
1495
+ else if (ref) ref.current = node;
1496
+ },
1497
+ [ref]
1498
+ );
1499
+ const handleKeyDown = (event) => {
1500
+ onKeyDown?.(event);
1501
+ if (event.defaultPrevented) return;
1502
+ const nav = ["ArrowRight", "ArrowLeft", "Home", "End"];
1503
+ if (!nav.includes(event.key)) return;
1504
+ const list = listRef.current;
1505
+ if (!list) return;
1506
+ const tabs = Array.from(
1507
+ list.querySelectorAll('[role="tab"]:not([disabled])')
1508
+ );
1509
+ if (tabs.length === 0) return;
1510
+ const currentIndex = tabs.findIndex((t) => t === document.activeElement);
1511
+ let nextIndex;
1512
+ switch (event.key) {
1513
+ case "Home":
1514
+ nextIndex = 0;
1515
+ break;
1516
+ case "End":
1517
+ nextIndex = tabs.length - 1;
1518
+ break;
1519
+ case "ArrowRight":
1520
+ nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % tabs.length;
1521
+ break;
1522
+ default:
1523
+ nextIndex = currentIndex < 0 ? tabs.length - 1 : (currentIndex - 1 + tabs.length) % tabs.length;
1524
+ }
1525
+ const next = tabs[nextIndex];
1526
+ event.preventDefault();
1527
+ next.focus();
1528
+ const nextValue = next.getAttribute("data-value");
1529
+ if (nextValue !== null) setActiveValue(nextValue);
1530
+ };
1531
+ return /* @__PURE__ */ jsxRuntime.jsx(
1532
+ "div",
1533
+ {
1534
+ ref: setRefs,
1535
+ role: "tablist",
1536
+ "aria-orientation": "horizontal",
1537
+ className: cn("gl-tabs__list", className),
1538
+ onKeyDown: handleKeyDown,
1539
+ ...rest,
1540
+ children
1541
+ }
1542
+ );
1543
+ });
1544
+ var Tab = react.forwardRef(function Tab2({ value, disabled = false, className, children, onClick, type = "button", ...rest }, ref) {
1545
+ const ctx = useTabsContext("Tab");
1546
+ const { registerTab, unregisterTab, setTabDisabled, setActiveValue } = ctx;
1547
+ const selected = ctx.activeValue === value;
1548
+ const focusable = ctx.focusableValue === value;
1549
+ useIsomorphicLayoutEffect(() => {
1550
+ registerTab(value);
1551
+ return () => unregisterTab(value);
1552
+ }, [registerTab, unregisterTab, value]);
1553
+ useIsomorphicLayoutEffect(() => {
1554
+ setTabDisabled(value, disabled);
1555
+ }, [setTabDisabled, value, disabled]);
1556
+ const handleClick = (event) => {
1557
+ onClick?.(event);
1558
+ if (event.defaultPrevented) return;
1559
+ setActiveValue(value);
1560
+ };
1561
+ return /* @__PURE__ */ jsxRuntime.jsx(
1562
+ "button",
1563
+ {
1564
+ ref,
1565
+ type,
1566
+ role: "tab",
1567
+ id: ctx.getTabId(value),
1568
+ "data-value": value,
1569
+ "aria-selected": selected,
1570
+ "aria-controls": ctx.getPanelId(value),
1571
+ tabIndex: focusable ? 0 : -1,
1572
+ disabled,
1573
+ className: cn(
1574
+ "gl-tabs__tab",
1575
+ selected && "gl-tabs__tab--active",
1576
+ "gl-focusable",
1577
+ className
1578
+ ),
1579
+ onClick: handleClick,
1580
+ ...rest,
1581
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-tabs__tab-label", children })
1582
+ }
1583
+ );
1584
+ });
1585
+ var TabPanel = react.forwardRef(function TabPanel2({ value, className, children, ...rest }, ref) {
1586
+ const ctx = useTabsContext("TabPanel");
1587
+ const selected = ctx.activeValue === value;
1588
+ return /* @__PURE__ */ jsxRuntime.jsx(
1589
+ "div",
1590
+ {
1591
+ ref,
1592
+ role: "tabpanel",
1593
+ id: ctx.getPanelId(value),
1594
+ "aria-labelledby": ctx.getTabId(value),
1595
+ hidden: !selected,
1596
+ tabIndex: 0,
1597
+ className: cn("gl-tabs__panel", className),
1598
+ ...rest,
1599
+ children
1600
+ }
1601
+ );
1602
+ });
1603
+ var Textarea = react.forwardRef(
1604
+ function Textarea2({
1605
+ variant = "subtle",
1606
+ error = false,
1607
+ fullWidth = false,
1608
+ autoResize = false,
1609
+ className,
1610
+ onChange,
1611
+ value,
1612
+ defaultValue,
1613
+ rows,
1614
+ disabled,
1615
+ ...rest
1616
+ }, ref) {
1617
+ const innerRef = react.useRef(null);
1618
+ const setRef = react.useCallback(
1619
+ (node) => {
1620
+ innerRef.current = node;
1621
+ if (typeof ref === "function") {
1622
+ ref(node);
1623
+ } else if (ref) {
1624
+ ref.current = node;
1625
+ }
1626
+ },
1627
+ [ref]
1628
+ );
1629
+ const resize = react.useCallback(() => {
1630
+ const el = innerRef.current;
1631
+ if (!el) return;
1632
+ if (!autoResize) {
1633
+ el.style.height = "";
1634
+ return;
1635
+ }
1636
+ el.style.height = "auto";
1637
+ el.style.height = `${el.scrollHeight}px`;
1638
+ }, [autoResize]);
1639
+ useIsomorphicLayoutEffect(() => {
1640
+ resize();
1641
+ }, [resize, value, defaultValue, rows]);
1642
+ const handleChange = react.useCallback(
1643
+ (event) => {
1644
+ if (autoResize) resize();
1645
+ onChange?.(event);
1646
+ },
1647
+ [autoResize, resize, onChange]
1648
+ );
1649
+ return /* @__PURE__ */ jsxRuntime.jsx(
1650
+ "div",
1651
+ {
1652
+ className: cn(
1653
+ "gl-textarea",
1654
+ `gl-textarea--${variant}`,
1655
+ fullWidth && "gl-textarea--full",
1656
+ error && "gl-textarea--error",
1657
+ autoResize && "gl-textarea--auto",
1658
+ disabled && "gl-textarea--disabled",
1659
+ className
1660
+ ),
1661
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1662
+ "textarea",
1663
+ {
1664
+ ref: setRef,
1665
+ className: "gl-textarea__field",
1666
+ value,
1667
+ defaultValue,
1668
+ rows,
1669
+ disabled,
1670
+ "aria-invalid": error || void 0,
1671
+ onChange: handleChange,
1672
+ ...rest
1673
+ }
1674
+ )
1675
+ }
1676
+ );
1677
+ }
1678
+ );
1679
+ var DEFAULT_DURATION = 4e3;
1680
+ var ToastContext = react.createContext(null);
1681
+ function ToastItem({ toast, onDismiss }) {
1682
+ const { id, title, description, variant, duration } = toast;
1683
+ const autoDismiss = duration > 0 && Number.isFinite(duration);
1684
+ const timerRef = react.useRef(null);
1685
+ const remainingRef = react.useRef(duration);
1686
+ const startedRef = react.useRef(0);
1687
+ const clearTimer = react.useCallback(() => {
1688
+ if (timerRef.current !== null) {
1689
+ window.clearTimeout(timerRef.current);
1690
+ timerRef.current = null;
1691
+ }
1692
+ }, []);
1693
+ const resumeTimer = react.useCallback(() => {
1694
+ if (!autoDismiss || timerRef.current !== null) return;
1695
+ startedRef.current = performance.now();
1696
+ timerRef.current = window.setTimeout(() => {
1697
+ timerRef.current = null;
1698
+ onDismiss(id);
1699
+ }, remainingRef.current);
1700
+ }, [autoDismiss, id, onDismiss]);
1701
+ const pauseTimer = react.useCallback(() => {
1702
+ if (timerRef.current === null) return;
1703
+ clearTimer();
1704
+ remainingRef.current = Math.max(
1705
+ 0,
1706
+ remainingRef.current - (performance.now() - startedRef.current)
1707
+ );
1708
+ }, [clearTimer]);
1709
+ react.useEffect(() => {
1710
+ remainingRef.current = duration;
1711
+ resumeTimer();
1712
+ return clearTimer;
1713
+ }, [duration, resumeTimer, clearTimer]);
1714
+ const handleKeyDown = (event) => {
1715
+ if (event.key === "Escape") {
1716
+ event.stopPropagation();
1717
+ onDismiss(id);
1718
+ }
1719
+ };
1720
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1721
+ "div",
1722
+ {
1723
+ className: cn("gl-toast", `gl-toast--${variant}`),
1724
+ role: "status",
1725
+ "aria-atomic": "true",
1726
+ onMouseEnter: pauseTimer,
1727
+ onMouseLeave: resumeTimer,
1728
+ onFocus: pauseTimer,
1729
+ onBlur: resumeTimer,
1730
+ onKeyDown: handleKeyDown,
1731
+ children: [
1732
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gl-toast__accent", "aria-hidden": "true" }),
1733
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gl-toast__body", children: [
1734
+ title != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gl-toast__title", children: title }) : null,
1735
+ description != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gl-toast__description", children: description }) : null
1736
+ ] }),
1737
+ /* @__PURE__ */ jsxRuntime.jsx(
1738
+ "button",
1739
+ {
1740
+ type: "button",
1741
+ className: "gl-toast__close gl-focusable",
1742
+ "aria-label": "Dismiss notification",
1743
+ onClick: () => onDismiss(id),
1744
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1745
+ "svg",
1746
+ {
1747
+ className: "gl-toast__close-icon",
1748
+ viewBox: "0 0 24 24",
1749
+ fill: "none",
1750
+ "aria-hidden": "true",
1751
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1752
+ "path",
1753
+ {
1754
+ d: "M6 6l12 12M18 6L6 18",
1755
+ stroke: "currentColor",
1756
+ strokeWidth: "2",
1757
+ strokeLinecap: "round"
1758
+ }
1759
+ )
1760
+ }
1761
+ )
1762
+ }
1763
+ )
1764
+ ]
1765
+ }
1766
+ );
1767
+ }
1768
+ function ToastProvider({
1769
+ children,
1770
+ position = "bottom-right"
1771
+ }) {
1772
+ const [toasts, setToasts] = react.useState([]);
1773
+ const baseId = react.useId();
1774
+ const counterRef = react.useRef(0);
1775
+ const dismiss = react.useCallback((id) => {
1776
+ setToasts((prev) => prev.filter((item) => item.id !== id));
1777
+ }, []);
1778
+ const toast = react.useCallback(
1779
+ (options) => {
1780
+ const id = `${baseId}${counterRef.current++}`;
1781
+ setToasts((prev) => [
1782
+ ...prev,
1783
+ {
1784
+ id,
1785
+ title: options.title,
1786
+ description: options.description,
1787
+ variant: options.variant ?? "glass",
1788
+ duration: options.duration ?? DEFAULT_DURATION
1789
+ }
1790
+ ]);
1791
+ return id;
1792
+ },
1793
+ [baseId]
1794
+ );
1795
+ const success = react.useCallback(
1796
+ (title, options) => toast({ ...options, title, variant: "success" }),
1797
+ [toast]
1798
+ );
1799
+ const error = react.useCallback(
1800
+ (title, options) => toast({ ...options, title, variant: "danger" }),
1801
+ [toast]
1802
+ );
1803
+ const info = react.useCallback(
1804
+ (title, options) => toast({ ...options, title, variant: "info" }),
1805
+ [toast]
1806
+ );
1807
+ const warning = react.useCallback(
1808
+ (title, options) => toast({ ...options, title, variant: "warning" }),
1809
+ [toast]
1810
+ );
1811
+ const value = react.useMemo(
1812
+ () => ({ toast, dismiss, success, error, info, warning }),
1813
+ [toast, dismiss, success, error, info, warning]
1814
+ );
1815
+ return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value, children: [
1816
+ children,
1817
+ /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1818
+ "div",
1819
+ {
1820
+ className: cn("gl-toast-viewport", `gl-toast-viewport--${position}`),
1821
+ role: "region",
1822
+ "aria-label": "Notifications",
1823
+ children: toasts.map((item) => /* @__PURE__ */ jsxRuntime.jsx(ToastItem, { toast: item, onDismiss: dismiss }, item.id))
1824
+ }
1825
+ ) })
1826
+ ] });
1827
+ }
1828
+ function useToast() {
1829
+ const ctx = react.useContext(ToastContext);
1830
+ if (ctx === null) {
1831
+ throw new Error(
1832
+ "useToast must be used within a <ToastProvider>. Wrap your app (or the subtree that shows toasts) in <ToastProvider>."
1833
+ );
1834
+ }
1835
+ return ctx;
1836
+ }
1837
+ var Tooltip = react.forwardRef(function Tooltip2({
1838
+ content,
1839
+ children,
1840
+ placement = "top",
1841
+ delay = 200,
1842
+ disabled = false,
1843
+ className,
1844
+ onMouseEnter,
1845
+ onMouseLeave,
1846
+ onFocus,
1847
+ onBlur,
1848
+ onKeyDown,
1849
+ ...rest
1850
+ }, ref) {
1851
+ const [visible, setVisible] = react.useState(false);
1852
+ const timeoutRef = react.useRef(null);
1853
+ const tooltipId = react.useId();
1854
+ const clearTimer = react.useCallback(() => {
1855
+ if (timeoutRef.current !== null) {
1856
+ clearTimeout(timeoutRef.current);
1857
+ timeoutRef.current = null;
1858
+ }
1859
+ }, []);
1860
+ const show = react.useCallback(() => {
1861
+ if (disabled) return;
1862
+ clearTimer();
1863
+ timeoutRef.current = setTimeout(() => {
1864
+ timeoutRef.current = null;
1865
+ setVisible(true);
1866
+ }, delay);
1867
+ }, [disabled, delay, clearTimer]);
1868
+ const hide = react.useCallback(() => {
1869
+ clearTimer();
1870
+ setVisible(false);
1871
+ }, [clearTimer]);
1872
+ react.useEffect(() => {
1873
+ if (disabled) {
1874
+ clearTimer();
1875
+ setVisible(false);
1876
+ }
1877
+ }, [disabled, clearTimer]);
1878
+ react.useEffect(() => clearTimer, [clearTimer]);
1879
+ const handleMouseEnter = (event) => {
1880
+ show();
1881
+ onMouseEnter?.(event);
1882
+ };
1883
+ const handleMouseLeave = (event) => {
1884
+ hide();
1885
+ onMouseLeave?.(event);
1886
+ };
1887
+ const handleFocus = (event) => {
1888
+ show();
1889
+ onFocus?.(event);
1890
+ };
1891
+ const handleBlur = (event) => {
1892
+ hide();
1893
+ onBlur?.(event);
1894
+ };
1895
+ const handleKeyDown = (event) => {
1896
+ if (event.key === "Escape") {
1897
+ hide();
1898
+ }
1899
+ onKeyDown?.(event);
1900
+ };
1901
+ const open = visible && !disabled;
1902
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1903
+ "span",
1904
+ {
1905
+ ref,
1906
+ className: cn("gl-tooltip-wrap", className),
1907
+ onMouseEnter: handleMouseEnter,
1908
+ onMouseLeave: handleMouseLeave,
1909
+ onFocus: handleFocus,
1910
+ onBlur: handleBlur,
1911
+ onKeyDown: handleKeyDown,
1912
+ "aria-describedby": open ? tooltipId : void 0,
1913
+ ...rest,
1914
+ children: [
1915
+ children,
1916
+ open ? /* @__PURE__ */ jsxRuntime.jsx(
1917
+ "span",
1918
+ {
1919
+ id: tooltipId,
1920
+ role: "tooltip",
1921
+ className: cn("gl-tooltip", `gl-tooltip--${placement}`),
1922
+ children: content
1923
+ }
1924
+ ) : null
1925
+ ]
1926
+ }
1927
+ );
1928
+ });
1929
+
1930
+ exports.Accordion = Accordion;
1931
+ exports.AccordionItem = AccordionItem;
1932
+ exports.Avatar = Avatar;
1933
+ exports.Badge = Badge;
1934
+ exports.Button = Button;
1935
+ exports.Card = Card;
1936
+ exports.CardBody = CardBody;
1937
+ exports.CardFooter = CardFooter;
1938
+ exports.CardHeader = CardHeader;
1939
+ exports.Checkbox = Checkbox;
1940
+ exports.Drawer = Drawer;
1941
+ exports.DrawerBody = DrawerBody;
1942
+ exports.DrawerFooter = DrawerFooter;
1943
+ exports.DrawerHeader = DrawerHeader;
1944
+ exports.Dropdown = Dropdown;
1945
+ exports.DropdownItem = DropdownItem;
1946
+ exports.DropdownLabel = DropdownLabel;
1947
+ exports.DropdownMenu = DropdownMenu;
1948
+ exports.DropdownSeparator = DropdownSeparator;
1949
+ exports.DropdownTrigger = DropdownTrigger;
1950
+ exports.Input = Input;
1951
+ exports.Modal = Modal;
1952
+ exports.ModalBody = ModalBody;
1953
+ exports.ModalFooter = ModalFooter;
1954
+ exports.ModalHeader = ModalHeader;
1955
+ exports.Portal = Portal;
1956
+ exports.Progress = Progress;
1957
+ exports.Radio = Radio;
1958
+ exports.RadioGroup = RadioGroup;
1959
+ exports.RadioGroupContext = RadioGroupContext;
1960
+ exports.Select = Select;
1961
+ exports.Slider = Slider;
1962
+ exports.Spinner = Spinner;
1963
+ exports.Switch = Switch;
1964
+ exports.Tab = Tab;
1965
+ exports.TabList = TabList;
1966
+ exports.TabPanel = TabPanel;
1967
+ exports.Tabs = Tabs;
1968
+ exports.Textarea = Textarea;
1969
+ exports.ToastProvider = ToastProvider;
1970
+ exports.Tooltip = Tooltip;
1971
+ exports.cn = cn;
1972
+ exports.useClickOutside = useClickOutside;
1973
+ exports.useControllableState = useControllableState;
1974
+ exports.useDisclosure = useDisclosure;
1975
+ exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
1976
+ exports.useScrollLock = useScrollLock;
1977
+ exports.useToast = useToast;
1978
+ //# sourceMappingURL=index.cjs.map
1979
+ //# sourceMappingURL=index.cjs.map