@fictjs/ui-primitives 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +181 -0
  3. package/dist/index.cjs +5091 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +1123 -0
  6. package/dist/index.d.ts +1123 -0
  7. package/dist/index.js +4907 -0
  8. package/dist/index.js.map +1 -0
  9. package/docs/README.md +39 -0
  10. package/docs/accessibility.md +50 -0
  11. package/docs/api-reference.md +200 -0
  12. package/docs/architecture.md +113 -0
  13. package/docs/components/core/accessible-icon.md +23 -0
  14. package/docs/components/core/id.md +26 -0
  15. package/docs/components/core/portal.md +30 -0
  16. package/docs/components/core/presence.md +27 -0
  17. package/docs/components/core/primitive.md +22 -0
  18. package/docs/components/core/separator.md +25 -0
  19. package/docs/components/core/slot.md +25 -0
  20. package/docs/components/core/visually-hidden.md +21 -0
  21. package/docs/components/disclosure/accordion.md +33 -0
  22. package/docs/components/disclosure/collapsible.md +29 -0
  23. package/docs/components/disclosure/navigation-menu.md +43 -0
  24. package/docs/components/disclosure/tabs.md +35 -0
  25. package/docs/components/feedback/toast.md +60 -0
  26. package/docs/components/form/calendar.md +35 -0
  27. package/docs/components/form/controls.md +52 -0
  28. package/docs/components/form/date-picker.md +44 -0
  29. package/docs/components/form/form-field.md +39 -0
  30. package/docs/components/form/inputs.md +99 -0
  31. package/docs/components/interaction/dismissable-layer.md +28 -0
  32. package/docs/components/interaction/focus-scope.md +27 -0
  33. package/docs/components/interaction/live-region.md +26 -0
  34. package/docs/components/interaction/popper.md +30 -0
  35. package/docs/components/interaction/roving-focus.md +27 -0
  36. package/docs/components/interaction/scroll-lock.md +22 -0
  37. package/docs/components/layout/layout.md +61 -0
  38. package/docs/components/menu/context-menu.md +44 -0
  39. package/docs/components/menu/dropdown-menu.md +62 -0
  40. package/docs/components/menu/menubar.md +38 -0
  41. package/docs/components/overlay/alert-dialog.md +46 -0
  42. package/docs/components/overlay/command-palette.md +54 -0
  43. package/docs/components/overlay/dialog.md +69 -0
  44. package/docs/components/overlay/hover-card.md +25 -0
  45. package/docs/components/overlay/popover.md +36 -0
  46. package/docs/components/overlay/tooltip.md +28 -0
  47. package/docs/examples.md +155 -0
  48. package/docs/release.md +60 -0
  49. package/docs/testing.md +36 -0
  50. package/package.json +89 -0
package/dist/index.js ADDED
@@ -0,0 +1,4907 @@
1
+ // src/internal/event.ts
2
+ function composeEventHandlers(original, extra, options = { checkDefaultPrevented: true }) {
3
+ return (event) => {
4
+ original?.(event);
5
+ if (!options.checkDefaultPrevented || !event.defaultPrevented) {
6
+ extra?.(event);
7
+ }
8
+ };
9
+ }
10
+
11
+ // src/internal/ref.ts
12
+ function assignRef(ref, value) {
13
+ if (!ref) return;
14
+ if (typeof ref === "function") {
15
+ ref(value);
16
+ return;
17
+ }
18
+ ref.current = value;
19
+ }
20
+ function composeRefs(...refs) {
21
+ return (node) => {
22
+ for (const ref of refs) {
23
+ assignRef(ref, node);
24
+ }
25
+ };
26
+ }
27
+
28
+ // src/internal/vnode.ts
29
+ function isEventKey(key) {
30
+ return key.startsWith("on") && key.length > 2;
31
+ }
32
+ function mergeClassName(a, b) {
33
+ if (!a) return b;
34
+ if (!b) return a;
35
+ return `${String(a)} ${String(b)}`;
36
+ }
37
+ function mergeStyle(a, b) {
38
+ if (!a) return b;
39
+ if (!b) return a;
40
+ if (typeof a === "string" || typeof b === "string") {
41
+ return `${String(a)}; ${String(b)}`;
42
+ }
43
+ if (typeof a === "object" && typeof b === "object") {
44
+ return { ...a, ...b };
45
+ }
46
+ return b;
47
+ }
48
+ function mergePropValue(key, targetValue, sourceValue) {
49
+ if (key === "class" || key === "className") {
50
+ return mergeClassName(targetValue, sourceValue);
51
+ }
52
+ if (key === "style") {
53
+ return mergeStyle(targetValue, sourceValue);
54
+ }
55
+ if (key === "ref") {
56
+ return composeRefs(
57
+ targetValue,
58
+ sourceValue
59
+ );
60
+ }
61
+ if (isEventKey(key)) {
62
+ if (typeof targetValue === "function" || typeof sourceValue === "function") {
63
+ return composeEventHandlers(
64
+ targetValue,
65
+ sourceValue
66
+ );
67
+ }
68
+ }
69
+ return sourceValue;
70
+ }
71
+ function isVNodeLike(value) {
72
+ return typeof value === "object" && value !== null && "type" in value && "props" in value && !(value instanceof Node);
73
+ }
74
+ function mergeVNodeProps(target, source) {
75
+ const next = { ...target ?? {} };
76
+ for (const [key, sourceValue] of Object.entries(source)) {
77
+ if (key === "children" && sourceValue === void 0) continue;
78
+ const targetValue = next[key];
79
+ next[key] = mergePropValue(key, targetValue, sourceValue);
80
+ }
81
+ return next;
82
+ }
83
+ function cloneVNodeWithProps(vnode, props, children) {
84
+ const merged = mergeVNodeProps(vnode.props, props);
85
+ if (children !== void 0) {
86
+ merged.children = children;
87
+ }
88
+ return {
89
+ type: vnode.type,
90
+ props: merged,
91
+ key: vnode.key
92
+ };
93
+ }
94
+
95
+ // src/components/core/slot.ts
96
+ function getFirstChild(children) {
97
+ if (Array.isArray(children)) {
98
+ return children.find((child) => child !== null && child !== void 0 && child !== false) ?? null;
99
+ }
100
+ return children ?? null;
101
+ }
102
+ function Slot(props) {
103
+ const { children, ...slotProps } = props;
104
+ if (children === void 0 || children === null) {
105
+ return null;
106
+ }
107
+ const child = getFirstChild(children);
108
+ if (!child) {
109
+ return null;
110
+ }
111
+ if (!isVNodeLike(child)) {
112
+ return child;
113
+ }
114
+ return cloneVNodeWithProps(child, slotProps);
115
+ }
116
+
117
+ // src/components/core/primitive.ts
118
+ function Primitive(props) {
119
+ const { as = "div", asChild = false, children, ...rest } = props;
120
+ if (asChild) {
121
+ return Slot({ ...rest, children });
122
+ }
123
+ return {
124
+ type: as,
125
+ props: {
126
+ ...rest,
127
+ children
128
+ }
129
+ };
130
+ }
131
+ function createPrimitive(tag) {
132
+ return (props) => Primitive({ ...props, as: tag });
133
+ }
134
+ var PrimitiveElements = {
135
+ div: createPrimitive("div"),
136
+ span: createPrimitive("span"),
137
+ button: createPrimitive("button"),
138
+ input: createPrimitive("input"),
139
+ label: createPrimitive("label"),
140
+ form: createPrimitive("form"),
141
+ ul: createPrimitive("ul"),
142
+ li: createPrimitive("li"),
143
+ nav: createPrimitive("nav"),
144
+ section: createPrimitive("section"),
145
+ article: createPrimitive("article")
146
+ };
147
+
148
+ // src/internal/accessor.ts
149
+ function read(value, fallback) {
150
+ if (typeof value === "function") {
151
+ return value();
152
+ }
153
+ if (value === void 0) {
154
+ return fallback;
155
+ }
156
+ return value;
157
+ }
158
+
159
+ // src/components/core/presence.ts
160
+ function Presence(props) {
161
+ return () => {
162
+ const present = read(props.present, true);
163
+ const forceMount = read(props.forceMount, false);
164
+ if (!present && !forceMount) {
165
+ return null;
166
+ }
167
+ if (typeof props.children === "function") {
168
+ return props.children({ present });
169
+ }
170
+ return props.children ?? null;
171
+ };
172
+ }
173
+
174
+ // src/components/core/portal.ts
175
+ import {
176
+ createContext,
177
+ createPortal,
178
+ createElement,
179
+ useContext,
180
+ createMemo,
181
+ onMount
182
+ } from "@fictjs/runtime";
183
+ var PortalContainerContext = createContext(
184
+ () => typeof document !== "undefined" ? document.body : null
185
+ );
186
+ function resolveContainer(container) {
187
+ if (container === void 0) {
188
+ return null;
189
+ }
190
+ return read(container, null) ?? null;
191
+ }
192
+ function PortalHost(props) {
193
+ const container = createMemo(() => resolveContainer(props.container));
194
+ return {
195
+ type: PortalContainerContext.Provider,
196
+ props: {
197
+ value: container,
198
+ children: props.children
199
+ }
200
+ };
201
+ }
202
+ function Portal(props) {
203
+ if (read(props.disabled, false)) {
204
+ return props.children ?? null;
205
+ }
206
+ const hostContainerAccessor = useContext(PortalContainerContext);
207
+ onMount(() => {
208
+ const container = (props.container !== void 0 ? resolveContainer(props.container) : hostContainerAccessor()) ?? (typeof document !== "undefined" ? document.body : null);
209
+ if (!container) return;
210
+ createPortal(
211
+ container,
212
+ () => typeof props.children === "function" ? props.children() : props.children ?? null,
213
+ createElement
214
+ );
215
+ });
216
+ return null;
217
+ }
218
+
219
+ // src/components/core/visually-hidden.ts
220
+ var visuallyHiddenStyle = {
221
+ position: "absolute",
222
+ border: "0",
223
+ width: "1px",
224
+ height: "1px",
225
+ padding: "0",
226
+ margin: "-1px",
227
+ overflow: "hidden",
228
+ clip: "rect(0, 0, 0, 0)",
229
+ whiteSpace: "nowrap"
230
+ };
231
+ function VisuallyHidden(props) {
232
+ const { as = "span", children, style, ...rest } = props;
233
+ return {
234
+ type: as,
235
+ props: {
236
+ ...rest,
237
+ style: typeof style === "object" && style !== null ? { ...visuallyHiddenStyle, ...style } : visuallyHiddenStyle,
238
+ children
239
+ }
240
+ };
241
+ }
242
+
243
+ // src/components/core/separator.ts
244
+ function Separator(props) {
245
+ const orientation = read(props.orientation, "horizontal");
246
+ const decorative = read(props.decorative, false);
247
+ const tag = props.as ?? "div";
248
+ return {
249
+ type: tag,
250
+ props: {
251
+ ...props,
252
+ as: void 0,
253
+ role: decorative ? "presentation" : "separator",
254
+ "aria-orientation": orientation,
255
+ "aria-hidden": decorative || void 0,
256
+ "data-orientation": orientation
257
+ }
258
+ };
259
+ }
260
+
261
+ // src/components/core/accessible-icon.ts
262
+ function AccessibleIcon(props) {
263
+ const { label, children, ...rest } = props;
264
+ return {
265
+ type: "span",
266
+ props: {
267
+ ...rest,
268
+ children: [
269
+ {
270
+ type: "span",
271
+ props: {
272
+ "aria-hidden": "true",
273
+ children
274
+ }
275
+ },
276
+ {
277
+ type: VisuallyHidden,
278
+ props: {
279
+ children: label
280
+ }
281
+ }
282
+ ]
283
+ }
284
+ };
285
+ }
286
+
287
+ // src/internal/ids.ts
288
+ import { createContext as createContext2, hasContext, useContext as useContext2 } from "@fictjs/runtime";
289
+ var IdContext = createContext2(null);
290
+ var globalCounters = /* @__PURE__ */ new Map();
291
+ function nextCounter(prefix) {
292
+ const current = globalCounters.get(prefix) ?? 0;
293
+ const next = current + 1;
294
+ globalCounters.set(prefix, next);
295
+ return next;
296
+ }
297
+ function tryReadIdContext() {
298
+ try {
299
+ if (!hasContext(IdContext)) {
300
+ return null;
301
+ }
302
+ return useContext2(IdContext);
303
+ } catch {
304
+ return null;
305
+ }
306
+ }
307
+ function createId(prefix = "fict-ui") {
308
+ return `${prefix}-${nextCounter(prefix)}`;
309
+ }
310
+ function useId(id, prefix = "fict-ui") {
311
+ if (id) return id;
312
+ const context = tryReadIdContext();
313
+ if (context) {
314
+ return `${context.prefix}-${context.next()}`;
315
+ }
316
+ return createId(prefix);
317
+ }
318
+ function IdProvider(props) {
319
+ const parent = tryReadIdContext();
320
+ let localCounter = 0;
321
+ const prefix = props.prefix ?? parent?.prefix ?? "fict-ui";
322
+ const context = {
323
+ prefix,
324
+ next: () => {
325
+ localCounter += 1;
326
+ return localCounter;
327
+ }
328
+ };
329
+ return {
330
+ type: IdContext.Provider,
331
+ props: {
332
+ value: context,
333
+ children: props.children
334
+ }
335
+ };
336
+ }
337
+
338
+ // src/components/disclosure/collapsible.ts
339
+ import { createContext as createContext3, useContext as useContext3 } from "@fictjs/runtime";
340
+
341
+ // src/internal/state.ts
342
+ import { createSignal } from "@fictjs/runtime/advanced";
343
+ function createControllableState(options) {
344
+ const uncontrolled = createSignal(options.defaultValue);
345
+ const isControlled = () => options.value !== void 0;
346
+ const get = () => {
347
+ if (isControlled()) {
348
+ return read(options.value, options.defaultValue);
349
+ }
350
+ return uncontrolled();
351
+ };
352
+ const set = (next) => {
353
+ const prev = get();
354
+ const equals = options.equals ?? Object.is;
355
+ if (equals(prev, next)) return;
356
+ if (!isControlled()) {
357
+ uncontrolled(next);
358
+ }
359
+ options.onChange?.(next);
360
+ };
361
+ return { get, set, isControlled };
362
+ }
363
+
364
+ // src/components/disclosure/collapsible.ts
365
+ var CollapsibleContext = createContext3(null);
366
+ function useCollapsibleContext(component) {
367
+ const context = useContext3(CollapsibleContext);
368
+ if (!context) {
369
+ throw new Error(`${component} must be used inside CollapsibleRoot`);
370
+ }
371
+ return context;
372
+ }
373
+ function CollapsibleRoot(props) {
374
+ const state = createControllableState({
375
+ value: props.open,
376
+ defaultValue: props.defaultOpen ?? false,
377
+ onChange: props.onOpenChange
378
+ });
379
+ const context = {
380
+ open: () => state.get(),
381
+ setOpen: (open) => state.set(open),
382
+ disabled: () => props.disabled ?? false
383
+ };
384
+ return {
385
+ type: CollapsibleContext.Provider,
386
+ props: {
387
+ value: context,
388
+ children: props.children
389
+ }
390
+ };
391
+ }
392
+ function CollapsibleTrigger(props) {
393
+ const context = useCollapsibleContext("CollapsibleTrigger");
394
+ const tag = props.as ?? "button";
395
+ return Primitive({
396
+ ...props,
397
+ as: tag,
398
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
399
+ disabled: () => context.disabled(),
400
+ "aria-expanded": () => context.open(),
401
+ "data-state": () => context.open() ? "open" : "closed",
402
+ onClick: (event) => {
403
+ ;
404
+ props.onClick?.(event);
405
+ if (event.defaultPrevented) return;
406
+ if (context.disabled()) return;
407
+ context.setOpen(!context.open());
408
+ },
409
+ children: props.children
410
+ });
411
+ }
412
+ function CollapsibleContent(props) {
413
+ const context = useCollapsibleContext("CollapsibleContent");
414
+ return {
415
+ type: "div",
416
+ props: {
417
+ "data-collapsible-content-wrapper": "",
418
+ children: () => context.open() || props.forceMount ? {
419
+ type: "div",
420
+ props: {
421
+ ...props,
422
+ forceMount: void 0,
423
+ "data-state": () => context.open() ? "open" : "closed",
424
+ "data-collapsible-content": "",
425
+ children: props.children
426
+ }
427
+ } : null
428
+ }
429
+ };
430
+ }
431
+
432
+ // src/components/disclosure/accordion.ts
433
+ import { createContext as createContext4, useContext as useContext4 } from "@fictjs/runtime";
434
+ var AccordionContext = createContext4(null);
435
+ var AccordionItemContext = createContext4(null);
436
+ function useAccordionContext(component) {
437
+ const context = useContext4(AccordionContext);
438
+ if (!context) {
439
+ throw new Error(`${component} must be used inside AccordionRoot`);
440
+ }
441
+ return context;
442
+ }
443
+ function useAccordionItemContext(component) {
444
+ const context = useContext4(AccordionItemContext);
445
+ if (!context) {
446
+ throw new Error(`${component} must be used inside AccordionItem`);
447
+ }
448
+ return context;
449
+ }
450
+ function normalize(value) {
451
+ if (value === void 0) return [];
452
+ return Array.isArray(value) ? value : [value];
453
+ }
454
+ function AccordionRoot(props) {
455
+ const type = props.type ?? "single";
456
+ const initialValues = normalize(props.defaultValue);
457
+ const valuesState = createControllableState({
458
+ value: props.value === void 0 ? void 0 : typeof props.value === "function" ? (() => normalize(props.value())) : normalize(props.value),
459
+ defaultValue: initialValues,
460
+ onChange: (next) => {
461
+ props.onValueChange?.(type === "single" ? next[0] ?? "" : next);
462
+ }
463
+ });
464
+ const context = {
465
+ type: () => type,
466
+ values: () => valuesState.get(),
467
+ toggle: (value) => {
468
+ const current = valuesState.get();
469
+ const exists = current.includes(value);
470
+ if (type === "single") {
471
+ if (exists) {
472
+ if (props.collapsible ?? false) {
473
+ valuesState.set([]);
474
+ }
475
+ return;
476
+ }
477
+ valuesState.set([value]);
478
+ return;
479
+ }
480
+ if (exists) {
481
+ valuesState.set(current.filter((item) => item !== value));
482
+ } else {
483
+ valuesState.set([...current, value]);
484
+ }
485
+ }
486
+ };
487
+ return {
488
+ type: AccordionContext.Provider,
489
+ props: {
490
+ value: context,
491
+ children: props.children
492
+ }
493
+ };
494
+ }
495
+ function AccordionItem(props) {
496
+ const accordion = useAccordionContext("AccordionItem");
497
+ const tag = props.as ?? "div";
498
+ const itemContext = {
499
+ value: props.value,
500
+ open: () => accordion.values().includes(props.value)
501
+ };
502
+ return {
503
+ type: AccordionItemContext.Provider,
504
+ props: {
505
+ value: itemContext,
506
+ children: {
507
+ type: CollapsibleRoot,
508
+ props: {
509
+ open: () => itemContext.open(),
510
+ onOpenChange: (open) => {
511
+ const shouldOpen = open;
512
+ if (shouldOpen !== itemContext.open()) {
513
+ accordion.toggle(props.value);
514
+ }
515
+ },
516
+ children: Primitive({
517
+ ...props,
518
+ value: void 0,
519
+ as: tag,
520
+ "data-accordion-item": props.value,
521
+ "data-state": () => itemContext.open() ? "open" : "closed",
522
+ children: props.children
523
+ })
524
+ }
525
+ }
526
+ }
527
+ };
528
+ }
529
+ function AccordionTrigger(props) {
530
+ useAccordionContext("AccordionTrigger");
531
+ useAccordionItemContext("AccordionTrigger");
532
+ return {
533
+ type: CollapsibleTrigger,
534
+ props
535
+ };
536
+ }
537
+ function AccordionContent(props) {
538
+ return {
539
+ type: CollapsibleContent,
540
+ props
541
+ };
542
+ }
543
+
544
+ // src/components/disclosure/tabs.ts
545
+ import { createContext as createContext6, useContext as useContext6 } from "@fictjs/runtime";
546
+
547
+ // src/components/interaction/roving-focus.ts
548
+ import { createContext as createContext5, createEffect, onCleanup, useContext as useContext5 } from "@fictjs/runtime";
549
+ import { createSignal as createSignal2 } from "@fictjs/runtime/advanced";
550
+ import { useEventListener } from "@fictjs/hooks";
551
+ var RovingContext = createContext5(null);
552
+ function RovingFocusGroup(props) {
553
+ const currentIdSignal = createSignal2(null);
554
+ const items = [];
555
+ const groupNode = createSignal2(null);
556
+ const syncDomState = (activeId) => {
557
+ for (const item of items) {
558
+ const isActive = item.id === activeId && !item.disabled;
559
+ item.element.tabIndex = isActive ? 0 : -1;
560
+ if (isActive) {
561
+ item.element.setAttribute("data-active", "");
562
+ } else {
563
+ item.element.removeAttribute("data-active");
564
+ }
565
+ }
566
+ };
567
+ const moveFocus = (direction) => {
568
+ const activeItems = context.getItems().filter((item) => !item.disabled);
569
+ if (activeItems.length === 0) return;
570
+ const currentId = context.currentId();
571
+ const currentIndex = activeItems.findIndex((item) => item.id === currentId);
572
+ const baseIndex = currentIndex >= 0 ? currentIndex : 0;
573
+ let nextIndex = baseIndex + direction;
574
+ if (nextIndex < 0) {
575
+ nextIndex = context.loop() ? activeItems.length - 1 : 0;
576
+ } else if (nextIndex >= activeItems.length) {
577
+ nextIndex = context.loop() ? 0 : activeItems.length - 1;
578
+ }
579
+ const nextItem = activeItems[nextIndex];
580
+ if (!nextItem) return;
581
+ context.setCurrentId(nextItem.id);
582
+ nextItem.element.focus();
583
+ };
584
+ const focusFirst2 = () => {
585
+ const first = context.getItems().find((item) => !item.disabled);
586
+ if (!first) return;
587
+ context.setCurrentId(first.id);
588
+ first.element.focus();
589
+ };
590
+ const focusLast = () => {
591
+ const reversed = context.getItems().slice().reverse();
592
+ const last = reversed.find((item) => !item.disabled);
593
+ if (!last) return;
594
+ context.setCurrentId(last.id);
595
+ last.element.focus();
596
+ };
597
+ const context = {
598
+ orientation: () => read(props.orientation, "horizontal"),
599
+ loop: () => read(props.loop, true),
600
+ currentId: () => currentIdSignal(),
601
+ setCurrentId: (id) => {
602
+ currentIdSignal(id);
603
+ syncDomState(id);
604
+ },
605
+ register: (item) => {
606
+ items.push(item);
607
+ if (!currentIdSignal() && !item.disabled) {
608
+ context.setCurrentId(item.id);
609
+ } else {
610
+ syncDomState(currentIdSignal());
611
+ }
612
+ return () => {
613
+ const index = items.findIndex((entry) => entry.id === item.id);
614
+ if (index >= 0) {
615
+ items.splice(index, 1);
616
+ }
617
+ if (currentIdSignal() === item.id) {
618
+ context.setCurrentId(items.find((entry) => !entry.disabled)?.id ?? null);
619
+ } else {
620
+ syncDomState(currentIdSignal());
621
+ }
622
+ };
623
+ },
624
+ getItems: () => items.slice(),
625
+ moveFocus,
626
+ focusFirst: focusFirst2,
627
+ focusLast
628
+ };
629
+ const onKeyDown = (event) => {
630
+ const orientation = context.orientation();
631
+ const key = event.key;
632
+ if (orientation === "horizontal") {
633
+ if (key === "ArrowRight") {
634
+ event.preventDefault();
635
+ moveFocus(1);
636
+ } else if (key === "ArrowLeft") {
637
+ event.preventDefault();
638
+ moveFocus(-1);
639
+ }
640
+ }
641
+ if (orientation === "vertical") {
642
+ if (key === "ArrowDown") {
643
+ event.preventDefault();
644
+ moveFocus(1);
645
+ } else if (key === "ArrowUp") {
646
+ event.preventDefault();
647
+ moveFocus(-1);
648
+ }
649
+ }
650
+ if (key === "Home") {
651
+ event.preventDefault();
652
+ context.focusFirst();
653
+ }
654
+ if (key === "End") {
655
+ event.preventDefault();
656
+ context.focusLast();
657
+ }
658
+ };
659
+ const onDocumentKeyDown = (event) => {
660
+ const target = event.target;
661
+ const group = groupNode();
662
+ if (!group || !(target instanceof Node)) return;
663
+ if (!group.contains(target)) return;
664
+ onKeyDown(event);
665
+ };
666
+ const targetDocument = () => groupNode()?.ownerDocument ?? (typeof document !== "undefined" ? document : null);
667
+ useEventListener(targetDocument, "keydown", onDocumentKeyDown, { capture: true });
668
+ return {
669
+ type: RovingContext.Provider,
670
+ props: {
671
+ value: context,
672
+ children: {
673
+ type: "div",
674
+ props: {
675
+ ...props,
676
+ orientation: void 0,
677
+ loop: void 0,
678
+ role: "group",
679
+ "data-roving-focus-group": "",
680
+ ref: (node) => {
681
+ groupNode(node);
682
+ const refProp = props.ref;
683
+ if (typeof refProp === "function") {
684
+ refProp(node);
685
+ } else if (refProp) {
686
+ refProp.current = node;
687
+ }
688
+ },
689
+ onKeyDown,
690
+ children: props.children
691
+ }
692
+ }
693
+ }
694
+ };
695
+ }
696
+ function RovingFocusItem(props) {
697
+ const context = useContext5(RovingContext);
698
+ if (!context) {
699
+ throw new Error("RovingFocusItem must be used inside RovingFocusGroup");
700
+ }
701
+ const id = useId(props.id, "rf-item");
702
+ const tag = props.as ?? "button";
703
+ const itemNode = createSignal2(null);
704
+ let cleanup = null;
705
+ const onFocus = (event) => {
706
+ props.onFocus?.(event);
707
+ context.setCurrentId(id);
708
+ };
709
+ const onKeyDown = (event) => {
710
+ props.onKeyDown?.(event);
711
+ if (event.defaultPrevented) return;
712
+ const orientation = context.orientation();
713
+ if (orientation === "horizontal") {
714
+ if (event.key === "ArrowRight") {
715
+ event.preventDefault();
716
+ context.moveFocus(1);
717
+ } else if (event.key === "ArrowLeft") {
718
+ event.preventDefault();
719
+ context.moveFocus(-1);
720
+ }
721
+ } else if (orientation === "vertical") {
722
+ if (event.key === "ArrowDown") {
723
+ event.preventDefault();
724
+ context.moveFocus(1);
725
+ } else if (event.key === "ArrowUp") {
726
+ event.preventDefault();
727
+ context.moveFocus(-1);
728
+ }
729
+ }
730
+ if (event.key === "Home") {
731
+ event.preventDefault();
732
+ context.focusFirst();
733
+ }
734
+ if (event.key === "End") {
735
+ event.preventDefault();
736
+ context.focusLast();
737
+ }
738
+ };
739
+ useEventListener(() => itemNode(), "keydown", onKeyDown);
740
+ createEffect(() => {
741
+ const node = itemNode();
742
+ cleanup?.();
743
+ cleanup = null;
744
+ if (!node) return;
745
+ cleanup = context.register({
746
+ id,
747
+ element: node,
748
+ disabled: read(props.disabled, false)
749
+ });
750
+ onCleanup(() => {
751
+ cleanup?.();
752
+ cleanup = null;
753
+ });
754
+ });
755
+ const register = (node) => {
756
+ itemNode(node);
757
+ };
758
+ return Primitive({
759
+ ...props,
760
+ as: tag,
761
+ disabled: read(props.disabled, false),
762
+ ref: composeRefs(props.ref, register),
763
+ tabIndex: -1,
764
+ "data-roving-focus-item": "",
765
+ onFocus,
766
+ children: props.children
767
+ });
768
+ }
769
+
770
+ // src/components/disclosure/tabs.ts
771
+ var TabsContext = createContext6(null);
772
+ function useTabsContext(component) {
773
+ const context = useContext6(TabsContext);
774
+ if (!context) {
775
+ throw new Error(`${component} must be used inside TabsRoot`);
776
+ }
777
+ return context;
778
+ }
779
+ function TabsRoot(props) {
780
+ const valueState = createControllableState({
781
+ value: props.value,
782
+ defaultValue: props.defaultValue ?? "",
783
+ onChange: props.onValueChange
784
+ });
785
+ const baseId = useId(props.id, "tabs");
786
+ const context = {
787
+ value: () => valueState.get(),
788
+ setValue: (value) => valueState.set(value),
789
+ orientation: () => props.orientation ?? "horizontal",
790
+ baseId
791
+ };
792
+ return {
793
+ type: TabsContext.Provider,
794
+ props: {
795
+ value: context,
796
+ children: props.children
797
+ }
798
+ };
799
+ }
800
+ function TabsList(props) {
801
+ const context = useTabsContext("TabsList");
802
+ return {
803
+ type: "div",
804
+ props: {
805
+ ...props,
806
+ role: "tablist",
807
+ "aria-orientation": () => context.orientation(),
808
+ "data-tabs-list": "",
809
+ children: {
810
+ type: RovingFocusGroup,
811
+ props: {
812
+ orientation: () => context.orientation(),
813
+ loop: true,
814
+ children: props.children
815
+ }
816
+ }
817
+ }
818
+ };
819
+ }
820
+ function TabsTrigger(props) {
821
+ const context = useTabsContext("TabsTrigger");
822
+ const tag = props.as ?? "button";
823
+ const selected = () => context.value() === props.value;
824
+ return Primitive({
825
+ ...props,
826
+ as: tag,
827
+ value: void 0,
828
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
829
+ role: "tab",
830
+ id: `${context.baseId}-trigger-${props.value}`,
831
+ "aria-controls": `${context.baseId}-content-${props.value}`,
832
+ "aria-selected": selected,
833
+ "data-state": () => selected() ? "active" : "inactive",
834
+ onClick: (event) => {
835
+ ;
836
+ props.onClick?.(event);
837
+ if (!event.defaultPrevented) {
838
+ context.setValue(props.value);
839
+ }
840
+ },
841
+ children: props.children
842
+ });
843
+ }
844
+ function TabsContent(props) {
845
+ const context = useTabsContext("TabsContent");
846
+ return {
847
+ type: "div",
848
+ props: {
849
+ "data-tabs-content-wrapper": props.value,
850
+ children: () => context.value() === props.value || props.forceMount ? {
851
+ type: "div",
852
+ props: {
853
+ ...props,
854
+ value: void 0,
855
+ forceMount: void 0,
856
+ role: "tabpanel",
857
+ id: `${context.baseId}-content-${props.value}`,
858
+ "aria-labelledby": `${context.baseId}-trigger-${props.value}`,
859
+ "data-state": () => context.value() === props.value ? "active" : "inactive",
860
+ "data-tabs-content": props.value,
861
+ children: props.children
862
+ }
863
+ } : null
864
+ }
865
+ };
866
+ }
867
+
868
+ // src/components/disclosure/navigation-menu.ts
869
+ import { createContext as createContext7, useContext as useContext7 } from "@fictjs/runtime";
870
+ import { createSignal as createSignal3 } from "@fictjs/runtime/advanced";
871
+ var NavigationMenuRootContext = createContext7(null);
872
+ var NavigationMenuItemContext = createContext7(null);
873
+ function useNavigationRootContext(component) {
874
+ const context = useContext7(NavigationMenuRootContext);
875
+ if (!context) {
876
+ throw new Error(`${component} must be used inside NavigationMenuRoot`);
877
+ }
878
+ return context;
879
+ }
880
+ function useNavigationItemContext(component) {
881
+ const context = useContext7(NavigationMenuItemContext);
882
+ if (!context) {
883
+ throw new Error(`${component} must be used inside NavigationMenuItem`);
884
+ }
885
+ return context;
886
+ }
887
+ function NavigationMenuRoot(props) {
888
+ const activeItemSignal = createSignal3(null);
889
+ const context = {
890
+ activeItem: () => activeItemSignal(),
891
+ setActiveItem: (value) => activeItemSignal(value)
892
+ };
893
+ return {
894
+ type: NavigationMenuRootContext.Provider,
895
+ props: {
896
+ value: context,
897
+ children: {
898
+ type: "nav",
899
+ props: {
900
+ ...props,
901
+ "data-navigation-menu-root": "",
902
+ children: props.children
903
+ }
904
+ }
905
+ }
906
+ };
907
+ }
908
+ function NavigationMenuList(props) {
909
+ return {
910
+ type: "ul",
911
+ props: {
912
+ ...props,
913
+ "data-navigation-menu-list": "",
914
+ children: props.children
915
+ }
916
+ };
917
+ }
918
+ function NavigationMenuItem(props) {
919
+ const value = useId(props.value, "navigation-menu-item");
920
+ const tag = props.as ?? "li";
921
+ return {
922
+ type: NavigationMenuItemContext.Provider,
923
+ props: {
924
+ value: { value },
925
+ children: Primitive({
926
+ ...props,
927
+ value: void 0,
928
+ as: tag,
929
+ "data-navigation-menu-item": value,
930
+ children: props.children
931
+ })
932
+ }
933
+ };
934
+ }
935
+ function NavigationMenuTrigger(props) {
936
+ const root = useNavigationRootContext("NavigationMenuTrigger");
937
+ const item = useNavigationItemContext("NavigationMenuTrigger");
938
+ const tag = props.as ?? "button";
939
+ const open = () => root.activeItem() === item.value;
940
+ return Primitive({
941
+ ...props,
942
+ as: tag,
943
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
944
+ "aria-expanded": open,
945
+ "aria-haspopup": "menu",
946
+ "data-state": () => open() ? "open" : "closed",
947
+ onClick: (event) => {
948
+ ;
949
+ props.onClick?.(event);
950
+ if (event.defaultPrevented) return;
951
+ root.setActiveItem(open() ? null : item.value);
952
+ },
953
+ children: props.children
954
+ });
955
+ }
956
+ function NavigationMenuContent(props) {
957
+ const root = useNavigationRootContext("NavigationMenuContent");
958
+ const item = useNavigationItemContext("NavigationMenuContent");
959
+ const open = () => root.activeItem() === item.value;
960
+ return {
961
+ type: "div",
962
+ props: {
963
+ "data-navigation-menu-content-wrapper": item.value,
964
+ children: () => open() || props.forceMount ? {
965
+ type: "div",
966
+ props: {
967
+ ...props,
968
+ forceMount: void 0,
969
+ role: "menu",
970
+ "data-state": () => open() ? "open" : "closed",
971
+ "data-navigation-menu-content": item.value,
972
+ children: props.children
973
+ }
974
+ } : null
975
+ }
976
+ };
977
+ }
978
+ function NavigationMenuLink(props) {
979
+ const tag = props.as ?? "a";
980
+ return Primitive({
981
+ ...props,
982
+ as: tag,
983
+ "data-navigation-menu-link": "",
984
+ children: props.children
985
+ });
986
+ }
987
+ function NavigationMenuIndicator(props) {
988
+ return {
989
+ type: "div",
990
+ props: {
991
+ ...props,
992
+ "data-navigation-menu-indicator": "",
993
+ children: props.children
994
+ }
995
+ };
996
+ }
997
+ function NavigationMenuViewport(props) {
998
+ return {
999
+ type: "div",
1000
+ props: {
1001
+ ...props,
1002
+ "data-navigation-menu-viewport": "",
1003
+ children: props.children
1004
+ }
1005
+ };
1006
+ }
1007
+
1008
+ // src/components/form/label.ts
1009
+ function Label(props) {
1010
+ return {
1011
+ type: "label",
1012
+ props: {
1013
+ ...props,
1014
+ "data-label": "",
1015
+ children: props.children
1016
+ }
1017
+ };
1018
+ }
1019
+
1020
+ // src/components/form/checkbox.ts
1021
+ function Checkbox(props) {
1022
+ const checkedState = createControllableState({
1023
+ value: props.checked,
1024
+ defaultValue: props.defaultChecked ?? false,
1025
+ onChange: props.onCheckedChange
1026
+ });
1027
+ return {
1028
+ type: "button",
1029
+ props: {
1030
+ ...props,
1031
+ type: "button",
1032
+ role: "checkbox",
1033
+ disabled: props.disabled,
1034
+ "aria-checked": () => checkedState.get(),
1035
+ "data-state": () => checkedState.get() ? "checked" : "unchecked",
1036
+ "data-checkbox": "",
1037
+ onClick: (event) => {
1038
+ ;
1039
+ props.onClick?.(event);
1040
+ if (event.defaultPrevented || props.disabled) return;
1041
+ checkedState.set(!checkedState.get());
1042
+ },
1043
+ children: [
1044
+ props.children,
1045
+ props.name ? {
1046
+ type: "input",
1047
+ props: {
1048
+ type: "checkbox",
1049
+ hidden: true,
1050
+ tabIndex: -1,
1051
+ name: props.name,
1052
+ value: props.value,
1053
+ checked: () => checkedState.get(),
1054
+ required: props.required,
1055
+ readOnly: true
1056
+ }
1057
+ } : null
1058
+ ]
1059
+ }
1060
+ };
1061
+ }
1062
+
1063
+ // src/components/form/radio-group.ts
1064
+ import { createContext as createContext8, useContext as useContext8 } from "@fictjs/runtime";
1065
+ var RadioGroupContext = createContext8(null);
1066
+ function useRadioGroupContext(component) {
1067
+ const context = useContext8(RadioGroupContext);
1068
+ if (!context) {
1069
+ throw new Error(`${component} must be used inside RadioGroup`);
1070
+ }
1071
+ return context;
1072
+ }
1073
+ function RadioGroup(props) {
1074
+ const valueState = createControllableState({
1075
+ value: props.value,
1076
+ defaultValue: props.defaultValue ?? "",
1077
+ onChange: props.onValueChange
1078
+ });
1079
+ const context = {
1080
+ value: () => valueState.get(),
1081
+ setValue: (value) => valueState.set(value),
1082
+ name: props.name
1083
+ };
1084
+ return {
1085
+ type: RadioGroupContext.Provider,
1086
+ props: {
1087
+ value: context,
1088
+ children: {
1089
+ type: "div",
1090
+ props: {
1091
+ ...props,
1092
+ role: "radiogroup",
1093
+ "data-radio-group": "",
1094
+ children: props.children
1095
+ }
1096
+ }
1097
+ }
1098
+ };
1099
+ }
1100
+ function RadioItem(props) {
1101
+ const group = useRadioGroupContext("RadioItem");
1102
+ const checked = () => group.value() === props.value;
1103
+ const tag = props.as ?? "button";
1104
+ const hiddenInput = group.name ? {
1105
+ type: "input",
1106
+ props: {
1107
+ type: "radio",
1108
+ hidden: true,
1109
+ tabIndex: -1,
1110
+ name: group.name,
1111
+ checked,
1112
+ value: props.value,
1113
+ readOnly: true
1114
+ }
1115
+ } : null;
1116
+ if (props.asChild) {
1117
+ return [
1118
+ Primitive({
1119
+ ...props,
1120
+ as: tag,
1121
+ type: props.type,
1122
+ role: "radio",
1123
+ disabled: props.disabled,
1124
+ "aria-checked": checked,
1125
+ "data-state": () => checked() ? "checked" : "unchecked",
1126
+ "data-radio-item": "",
1127
+ onClick: (event) => {
1128
+ ;
1129
+ props.onClick?.(event);
1130
+ if (event.defaultPrevented || props.disabled) return;
1131
+ group.setValue(props.value);
1132
+ },
1133
+ children: props.children
1134
+ }),
1135
+ hiddenInput
1136
+ ];
1137
+ }
1138
+ return Primitive({
1139
+ ...props,
1140
+ as: tag,
1141
+ type: tag === "button" ? "button" : props.type,
1142
+ role: "radio",
1143
+ disabled: props.disabled,
1144
+ "aria-checked": checked,
1145
+ "data-state": () => checked() ? "checked" : "unchecked",
1146
+ "data-radio-item": "",
1147
+ onClick: (event) => {
1148
+ ;
1149
+ props.onClick?.(event);
1150
+ if (event.defaultPrevented || props.disabled) return;
1151
+ group.setValue(props.value);
1152
+ },
1153
+ children: [props.children, hiddenInput]
1154
+ });
1155
+ }
1156
+
1157
+ // src/components/form/switch.ts
1158
+ function Switch(props) {
1159
+ const checkedState = createControllableState({
1160
+ value: props.checked,
1161
+ defaultValue: props.defaultChecked ?? false,
1162
+ onChange: props.onCheckedChange
1163
+ });
1164
+ return {
1165
+ type: "button",
1166
+ props: {
1167
+ ...props,
1168
+ type: "button",
1169
+ role: "switch",
1170
+ disabled: props.disabled,
1171
+ "aria-checked": () => checkedState.get(),
1172
+ "data-state": () => checkedState.get() ? "checked" : "unchecked",
1173
+ "data-switch": "",
1174
+ onClick: (event) => {
1175
+ ;
1176
+ props.onClick?.(event);
1177
+ if (event.defaultPrevented || props.disabled) return;
1178
+ checkedState.set(!checkedState.get());
1179
+ },
1180
+ children: [
1181
+ props.children,
1182
+ props.name ? {
1183
+ type: "input",
1184
+ props: {
1185
+ type: "checkbox",
1186
+ hidden: true,
1187
+ tabIndex: -1,
1188
+ name: props.name,
1189
+ value: props.value,
1190
+ checked: () => checkedState.get(),
1191
+ readOnly: true
1192
+ }
1193
+ } : null
1194
+ ]
1195
+ }
1196
+ };
1197
+ }
1198
+ function SwitchThumb(props) {
1199
+ return {
1200
+ type: "span",
1201
+ props: {
1202
+ ...props,
1203
+ "data-switch-thumb": "",
1204
+ children: props.children
1205
+ }
1206
+ };
1207
+ }
1208
+
1209
+ // src/components/form/toggle.ts
1210
+ import { createContext as createContext9, useContext as useContext9 } from "@fictjs/runtime";
1211
+ var ToggleGroupContext = createContext9(null);
1212
+ function normalize2(value) {
1213
+ if (value === void 0) return [];
1214
+ return Array.isArray(value) ? value : [value];
1215
+ }
1216
+ function Toggle(props) {
1217
+ const pressedState = createControllableState({
1218
+ value: props.pressed,
1219
+ defaultValue: props.defaultPressed ?? false,
1220
+ onChange: props.onPressedChange
1221
+ });
1222
+ return {
1223
+ type: "button",
1224
+ props: {
1225
+ ...props,
1226
+ type: "button",
1227
+ disabled: props.disabled,
1228
+ "aria-pressed": () => pressedState.get(),
1229
+ "data-state": () => pressedState.get() ? "on" : "off",
1230
+ "data-toggle": "",
1231
+ onClick: (event) => {
1232
+ ;
1233
+ props.onClick?.(event);
1234
+ if (event.defaultPrevented || props.disabled) return;
1235
+ pressedState.set(!pressedState.get());
1236
+ },
1237
+ children: props.children
1238
+ }
1239
+ };
1240
+ }
1241
+ function ToggleGroup(props) {
1242
+ const type = props.type ?? "single";
1243
+ const valuesState = createControllableState({
1244
+ value: props.value === void 0 ? void 0 : typeof props.value === "function" ? (() => normalize2(props.value())) : normalize2(props.value),
1245
+ defaultValue: normalize2(props.defaultValue),
1246
+ onChange: (next) => {
1247
+ props.onValueChange?.(type === "single" ? next[0] ?? "" : next);
1248
+ }
1249
+ });
1250
+ const context = {
1251
+ type: () => type,
1252
+ values: () => valuesState.get(),
1253
+ toggle: (value) => {
1254
+ const current = valuesState.get();
1255
+ const exists = current.includes(value);
1256
+ if (type === "single") {
1257
+ valuesState.set(exists ? [] : [value]);
1258
+ return;
1259
+ }
1260
+ if (exists) {
1261
+ valuesState.set(current.filter((item) => item !== value));
1262
+ } else {
1263
+ valuesState.set([...current, value]);
1264
+ }
1265
+ }
1266
+ };
1267
+ return {
1268
+ type: ToggleGroupContext.Provider,
1269
+ props: {
1270
+ value: context,
1271
+ children: {
1272
+ type: "div",
1273
+ props: {
1274
+ ...props,
1275
+ role: "group",
1276
+ "data-toggle-group": "",
1277
+ children: props.children
1278
+ }
1279
+ }
1280
+ }
1281
+ };
1282
+ }
1283
+ function ToggleGroupItem(props) {
1284
+ const group = useContext9(ToggleGroupContext);
1285
+ if (!group) {
1286
+ throw new Error("ToggleGroupItem must be used inside ToggleGroup");
1287
+ }
1288
+ const pressed = () => group.values().includes(props.value);
1289
+ const tag = props.as ?? "button";
1290
+ return Primitive({
1291
+ ...props,
1292
+ as: tag,
1293
+ type: !props.asChild && tag === "button" ? "button" : props.type,
1294
+ disabled: props.disabled,
1295
+ "aria-pressed": pressed,
1296
+ "data-state": () => pressed() ? "on" : "off",
1297
+ "data-toggle-group-item": "",
1298
+ onClick: (event) => {
1299
+ ;
1300
+ props.onClick?.(event);
1301
+ if (event.defaultPrevented || props.disabled) return;
1302
+ group.toggle(props.value);
1303
+ },
1304
+ children: props.children
1305
+ });
1306
+ }
1307
+
1308
+ // src/components/form/slider.ts
1309
+ function Slider(props) {
1310
+ const valueState = createControllableState({
1311
+ value: props.value,
1312
+ defaultValue: props.defaultValue ?? 0,
1313
+ onChange: props.onValueChange
1314
+ });
1315
+ return {
1316
+ type: "input",
1317
+ props: {
1318
+ ...props,
1319
+ type: "range",
1320
+ min: props.min ?? 0,
1321
+ max: props.max ?? 100,
1322
+ step: props.step ?? 1,
1323
+ value: () => valueState.get(),
1324
+ disabled: props.disabled,
1325
+ "data-slider": "",
1326
+ onInput: (event) => {
1327
+ ;
1328
+ props.onInput?.(event);
1329
+ const target = event.target;
1330
+ if (!target) return;
1331
+ valueState.set(Number(target.value));
1332
+ }
1333
+ }
1334
+ };
1335
+ }
1336
+ function RangeSlider(props) {
1337
+ const valueState = createControllableState({
1338
+ value: props.value,
1339
+ defaultValue: props.defaultValue ?? [0, 100],
1340
+ onChange: props.onValueChange
1341
+ });
1342
+ const min = props.min ?? 0;
1343
+ const max = props.max ?? 100;
1344
+ const step = props.step ?? 1;
1345
+ const setStart = (nextStart) => {
1346
+ const [, end] = valueState.get();
1347
+ valueState.set([Math.min(nextStart, end), end]);
1348
+ };
1349
+ const setEnd = (nextEnd) => {
1350
+ const [start] = valueState.get();
1351
+ valueState.set([start, Math.max(start, nextEnd)]);
1352
+ };
1353
+ return {
1354
+ type: "div",
1355
+ props: {
1356
+ ...props,
1357
+ "data-range-slider": "",
1358
+ children: [
1359
+ {
1360
+ type: "input",
1361
+ props: {
1362
+ type: "range",
1363
+ min,
1364
+ max,
1365
+ step,
1366
+ value: () => valueState.get()[0],
1367
+ disabled: props.disabled,
1368
+ "data-range-slider-start": "",
1369
+ onInput: (event) => {
1370
+ ;
1371
+ props.onInput?.(event);
1372
+ const target = event.target;
1373
+ if (!target) return;
1374
+ setStart(Number(target.value));
1375
+ }
1376
+ }
1377
+ },
1378
+ {
1379
+ type: "input",
1380
+ props: {
1381
+ type: "range",
1382
+ min,
1383
+ max,
1384
+ step,
1385
+ value: () => valueState.get()[1],
1386
+ disabled: props.disabled,
1387
+ "data-range-slider-end": "",
1388
+ onInput: (event) => {
1389
+ ;
1390
+ props.onInput?.(event);
1391
+ const target = event.target;
1392
+ if (!target) return;
1393
+ setEnd(Number(target.value));
1394
+ }
1395
+ }
1396
+ }
1397
+ ]
1398
+ }
1399
+ };
1400
+ }
1401
+
1402
+ // src/components/form/calendar.ts
1403
+ import { createContext as createContext10, useContext as useContext10 } from "@fictjs/runtime";
1404
+ function toDate(value) {
1405
+ if (value === null || value === void 0) return null;
1406
+ const next = value instanceof Date ? new Date(value.getTime()) : new Date(value);
1407
+ return Number.isNaN(next.getTime()) ? null : next;
1408
+ }
1409
+ function normalizeDate(date) {
1410
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
1411
+ }
1412
+ function normalizeMonth(date) {
1413
+ return new Date(date.getFullYear(), date.getMonth(), 1);
1414
+ }
1415
+ function clampWeekday(value) {
1416
+ if (!Number.isFinite(value)) return 0;
1417
+ const next = Math.floor(value);
1418
+ if (next < 0) return 0;
1419
+ if (next > 6) return 6;
1420
+ return next;
1421
+ }
1422
+ function isSameDay(a, b) {
1423
+ if (!a || !b) return a === b;
1424
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
1425
+ }
1426
+ function isSameMonth(a, b) {
1427
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
1428
+ }
1429
+ function addMonths(month, offset) {
1430
+ return normalizeMonth(new Date(month.getFullYear(), month.getMonth() + offset, 1));
1431
+ }
1432
+ function formatDateKey(date) {
1433
+ const y = date.getFullYear();
1434
+ const m = String(date.getMonth() + 1).padStart(2, "0");
1435
+ const d = String(date.getDate()).padStart(2, "0");
1436
+ return `${y}-${m}-${d}`;
1437
+ }
1438
+ function resolveDate(value) {
1439
+ const next = toDate(read(value, void 0));
1440
+ return next ? normalizeDate(next) : null;
1441
+ }
1442
+ function buildVisibleDays(month, weekStartsOn) {
1443
+ const firstOfMonth = normalizeMonth(month);
1444
+ const firstWeekday = firstOfMonth.getDay();
1445
+ const offset = (firstWeekday - weekStartsOn + 7) % 7;
1446
+ const start = new Date(firstOfMonth.getFullYear(), firstOfMonth.getMonth(), 1 - offset);
1447
+ return Array.from({ length: 42 }, (_, index) => normalizeDate(new Date(start.getFullYear(), start.getMonth(), start.getDate() + index)));
1448
+ }
1449
+ function weekdayLabels(locale, format, weekStartsOn) {
1450
+ const formatter = new Intl.DateTimeFormat(locale, { weekday: format });
1451
+ const start = new Date(2026, 0, 4);
1452
+ return Array.from({ length: 7 }, (_, index) => {
1453
+ const day = new Date(start.getFullYear(), start.getMonth(), start.getDate() + (weekStartsOn + index) % 7);
1454
+ return formatter.format(day);
1455
+ });
1456
+ }
1457
+ var CalendarContext = createContext10(null);
1458
+ function useCalendarContext(component) {
1459
+ const context = useContext10(CalendarContext);
1460
+ if (!context) {
1461
+ throw new Error(`${component} must be used inside CalendarRoot`);
1462
+ }
1463
+ return context;
1464
+ }
1465
+ function CalendarRoot(props) {
1466
+ const initialValue = toDate(props.defaultValue);
1467
+ const initialMonth = normalizeMonth(toDate(props.defaultMonth) ?? initialValue ?? /* @__PURE__ */ new Date());
1468
+ const baseId = useId(props.id, "calendar");
1469
+ const valueState = createControllableState({
1470
+ value: props.value === void 0 ? void 0 : (() => resolveDate(props.value)),
1471
+ defaultValue: initialValue ? normalizeDate(initialValue) : null,
1472
+ onChange: props.onValueChange,
1473
+ equals: (a, b) => isSameDay(a, b)
1474
+ });
1475
+ const monthState = createControllableState({
1476
+ value: props.month === void 0 ? void 0 : (() => {
1477
+ const next = toDate(read(props.month, void 0));
1478
+ return normalizeMonth(next ?? initialMonth);
1479
+ }),
1480
+ defaultValue: initialMonth,
1481
+ onChange: props.onMonthChange,
1482
+ equals: (a, b) => isSameMonth(a, b)
1483
+ });
1484
+ const context = {
1485
+ baseId,
1486
+ gridId: `${baseId}-grid`,
1487
+ value: () => valueState.get(),
1488
+ setValue: (value) => valueState.set(value ? normalizeDate(value) : null),
1489
+ month: () => normalizeMonth(monthState.get()),
1490
+ setMonth: (month) => monthState.set(normalizeMonth(month)),
1491
+ locale: () => read(props.locale, "en-US"),
1492
+ weekStartsOn: () => clampWeekday(read(props.weekStartsOn, 0)),
1493
+ weekdayFormat: () => read(props.weekdayFormat, "short"),
1494
+ showOutsideDays: () => read(props.showOutsideDays, true),
1495
+ disabled: (date) => props.disabled?.(normalizeDate(date)) ?? false
1496
+ };
1497
+ const defaultChildren = [
1498
+ {
1499
+ type: CalendarHeader,
1500
+ props: {
1501
+ children: [
1502
+ { type: CalendarPrevButton, props: { "data-calendar-prev-button": "", children: "Prev" } },
1503
+ { type: CalendarTitle, props: {} },
1504
+ { type: CalendarNextButton, props: { "data-calendar-next-button": "", children: "Next" } }
1505
+ ]
1506
+ }
1507
+ },
1508
+ { type: CalendarGrid, props: {} }
1509
+ ];
1510
+ return {
1511
+ type: CalendarContext.Provider,
1512
+ props: {
1513
+ value: context,
1514
+ children: {
1515
+ type: "div",
1516
+ props: {
1517
+ ...props,
1518
+ id: baseId,
1519
+ value: void 0,
1520
+ defaultValue: void 0,
1521
+ onValueChange: void 0,
1522
+ month: void 0,
1523
+ defaultMonth: void 0,
1524
+ onMonthChange: void 0,
1525
+ locale: void 0,
1526
+ weekStartsOn: void 0,
1527
+ weekdayFormat: void 0,
1528
+ showOutsideDays: void 0,
1529
+ disabled: void 0,
1530
+ "data-calendar-root": "",
1531
+ children: props.children ?? defaultChildren
1532
+ }
1533
+ }
1534
+ }
1535
+ };
1536
+ }
1537
+ var Calendar = CalendarRoot;
1538
+ function CalendarHeader(props) {
1539
+ return {
1540
+ type: "div",
1541
+ props: {
1542
+ ...props,
1543
+ "data-calendar-header": "",
1544
+ children: props.children
1545
+ }
1546
+ };
1547
+ }
1548
+ function CalendarTitle(props) {
1549
+ const context = useCalendarContext("CalendarTitle");
1550
+ return {
1551
+ type: "span",
1552
+ props: {
1553
+ ...props,
1554
+ "data-calendar-title": "",
1555
+ children: props.children ?? (() => new Intl.DateTimeFormat(context.locale(), {
1556
+ month: "long",
1557
+ year: "numeric"
1558
+ }).format(context.month()))
1559
+ }
1560
+ };
1561
+ }
1562
+ function CalendarPrevButton(props) {
1563
+ const context = useCalendarContext("CalendarPrevButton");
1564
+ const tag = props.as ?? "button";
1565
+ return Primitive({
1566
+ ...props,
1567
+ as: tag,
1568
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
1569
+ "aria-controls": context.gridId,
1570
+ "data-calendar-prev": "",
1571
+ onClick: (event) => {
1572
+ ;
1573
+ props.onClick?.(event);
1574
+ if (event.defaultPrevented) return;
1575
+ context.setMonth(addMonths(context.month(), -1));
1576
+ },
1577
+ children: props.children ?? "Prev"
1578
+ });
1579
+ }
1580
+ function CalendarNextButton(props) {
1581
+ const context = useCalendarContext("CalendarNextButton");
1582
+ const tag = props.as ?? "button";
1583
+ return Primitive({
1584
+ ...props,
1585
+ as: tag,
1586
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
1587
+ "aria-controls": context.gridId,
1588
+ "data-calendar-next": "",
1589
+ onClick: (event) => {
1590
+ ;
1591
+ props.onClick?.(event);
1592
+ if (event.defaultPrevented) return;
1593
+ context.setMonth(addMonths(context.month(), 1));
1594
+ },
1595
+ children: props.children ?? "Next"
1596
+ });
1597
+ }
1598
+ function CalendarGrid(props) {
1599
+ const context = useCalendarContext("CalendarGrid");
1600
+ return {
1601
+ type: "div",
1602
+ props: {
1603
+ ...props,
1604
+ showOutsideDays: void 0,
1605
+ onDaySelect: void 0,
1606
+ id: props.id ?? context.gridId,
1607
+ role: "grid",
1608
+ "data-calendar-grid": "",
1609
+ children: () => {
1610
+ const month = context.month();
1611
+ const weekStartsOn = context.weekStartsOn();
1612
+ const showOutside = read(props.showOutsideDays, context.showOutsideDays());
1613
+ const labels = weekdayLabels(context.locale(), context.weekdayFormat(), weekStartsOn);
1614
+ const days = buildVisibleDays(month, weekStartsOn);
1615
+ const header = {
1616
+ type: "div",
1617
+ props: {
1618
+ role: "row",
1619
+ "data-calendar-weekdays": "",
1620
+ children: labels.map((label, index) => ({
1621
+ type: "span",
1622
+ props: {
1623
+ role: "columnheader",
1624
+ "data-calendar-weekday": index,
1625
+ children: label
1626
+ }
1627
+ }))
1628
+ }
1629
+ };
1630
+ const rows = Array.from({ length: 6 }, (_, weekIndex) => {
1631
+ const start = weekIndex * 7;
1632
+ const weekDays = days.slice(start, start + 7);
1633
+ return {
1634
+ type: "div",
1635
+ props: {
1636
+ role: "row",
1637
+ "data-calendar-week": weekIndex,
1638
+ children: weekDays.map((day) => {
1639
+ const key = formatDateKey(day);
1640
+ const outsideMonth = !isSameMonth(day, month);
1641
+ const selected = isSameDay(context.value(), day);
1642
+ const disabled = context.disabled(day);
1643
+ if (!showOutside && outsideMonth) {
1644
+ return {
1645
+ type: "span",
1646
+ props: {
1647
+ role: "gridcell",
1648
+ "data-calendar-day-placeholder": key,
1649
+ "aria-hidden": "true",
1650
+ children: ""
1651
+ }
1652
+ };
1653
+ }
1654
+ return {
1655
+ type: "button",
1656
+ props: {
1657
+ type: "button",
1658
+ role: "gridcell",
1659
+ "aria-selected": selected,
1660
+ disabled,
1661
+ "data-calendar-day": key,
1662
+ "data-state": selected ? "selected" : "idle",
1663
+ "data-outside-month": outsideMonth ? "true" : void 0,
1664
+ onClick: (event) => {
1665
+ ;
1666
+ props.onDaySelect?.(day, event);
1667
+ if (event.defaultPrevented || disabled) return;
1668
+ context.setValue(day);
1669
+ context.setMonth(day);
1670
+ },
1671
+ children: String(day.getDate())
1672
+ }
1673
+ };
1674
+ })
1675
+ }
1676
+ };
1677
+ });
1678
+ return [header, ...rows];
1679
+ }
1680
+ }
1681
+ };
1682
+ }
1683
+
1684
+ // src/components/form/date-picker.ts
1685
+ import { createContext as createContext13, useContext as useContext13 } from "@fictjs/runtime";
1686
+
1687
+ // src/components/overlay/popover.ts
1688
+ import { createContext as createContext12, useContext as useContext12 } from "@fictjs/runtime";
1689
+ import { createRef } from "@fictjs/runtime";
1690
+
1691
+ // src/components/interaction/dismissable-layer.ts
1692
+ import { onDestroy, onMount as onMount2 } from "@fictjs/runtime";
1693
+ import { createSignal as createSignal4 } from "@fictjs/runtime/advanced";
1694
+ import { useEventListener as useEventListener2 } from "@fictjs/hooks";
1695
+ var activeLayers = [];
1696
+ function isTopLayer(node) {
1697
+ if (!node) return false;
1698
+ return activeLayers[activeLayers.length - 1] === node;
1699
+ }
1700
+ function DismissableLayer(props) {
1701
+ const node = createSignal4(null);
1702
+ const dismiss = () => {
1703
+ if (read(props.disabled, false)) return;
1704
+ props.onDismiss?.();
1705
+ };
1706
+ const onKeyDown = (event) => {
1707
+ if (!isTopLayer(node())) return;
1708
+ if (event.key !== "Escape") return;
1709
+ props.onEscapeKeyDown?.(event);
1710
+ if (!event.defaultPrevented) {
1711
+ dismiss();
1712
+ }
1713
+ };
1714
+ const onPointerDown = (event) => {
1715
+ const layer = node();
1716
+ if (!layer || !isTopLayer(layer)) return;
1717
+ const target = event.target;
1718
+ const isOutside = !target || !layer.contains(target);
1719
+ if (!isOutside) return;
1720
+ props.onInteractOutside?.(event);
1721
+ props.onPointerDownOutside?.(event);
1722
+ if (!event.defaultPrevented) {
1723
+ dismiss();
1724
+ }
1725
+ };
1726
+ const onFocusIn = (event) => {
1727
+ const layer = node();
1728
+ if (!layer || !isTopLayer(layer)) return;
1729
+ const target = event.target;
1730
+ const isOutside = !target || !layer.contains(target);
1731
+ if (!isOutside) return;
1732
+ props.onInteractOutside?.(event);
1733
+ props.onFocusOutside?.(event);
1734
+ if (!event.defaultPrevented) {
1735
+ dismiss();
1736
+ }
1737
+ };
1738
+ const targetDocument = () => node()?.ownerDocument ?? (typeof document !== "undefined" ? document : null);
1739
+ const keydownListener = useEventListener2(targetDocument, "keydown", onKeyDown, {
1740
+ capture: true,
1741
+ immediate: false
1742
+ });
1743
+ const pointerDownListener = useEventListener2(targetDocument, "pointerdown", onPointerDown, {
1744
+ capture: true,
1745
+ immediate: false
1746
+ });
1747
+ const focusInListener = useEventListener2(targetDocument, "focusin", onFocusIn, {
1748
+ capture: true,
1749
+ immediate: false
1750
+ });
1751
+ onMount2(() => {
1752
+ const layer = node();
1753
+ if (!layer) return;
1754
+ activeLayers.push(layer);
1755
+ keydownListener.start();
1756
+ pointerDownListener.start();
1757
+ focusInListener.start();
1758
+ });
1759
+ onDestroy(() => {
1760
+ keydownListener.stop();
1761
+ pointerDownListener.stop();
1762
+ focusInListener.stop();
1763
+ const layer = node();
1764
+ if (!layer) return;
1765
+ const index = activeLayers.indexOf(layer);
1766
+ if (index >= 0) {
1767
+ activeLayers.splice(index, 1);
1768
+ }
1769
+ });
1770
+ return {
1771
+ type: "div",
1772
+ props: {
1773
+ ...props,
1774
+ disabled: void 0,
1775
+ onDismiss: void 0,
1776
+ onEscapeKeyDown: void 0,
1777
+ onInteractOutside: void 0,
1778
+ onPointerDownOutside: void 0,
1779
+ onFocusOutside: void 0,
1780
+ ref: (el) => {
1781
+ node(el);
1782
+ },
1783
+ "data-dismissable-layer": "",
1784
+ children: props.children
1785
+ }
1786
+ };
1787
+ }
1788
+
1789
+ // src/components/interaction/popper.ts
1790
+ import { createContext as createContext11, createEffect as createEffect2, useContext as useContext11 } from "@fictjs/runtime";
1791
+ import { createSignal as createSignal5 } from "@fictjs/runtime/advanced";
1792
+ import { useEventListener as useEventListener3 } from "@fictjs/hooks";
1793
+ var PopperContext = createContext11(null);
1794
+ function computePosition(anchorRect, contentRect, side, align, sideOffset, alignOffset) {
1795
+ let x;
1796
+ let y;
1797
+ if (side === "bottom") {
1798
+ y = anchorRect.bottom + sideOffset;
1799
+ } else if (side === "top") {
1800
+ y = anchorRect.top - contentRect.height - sideOffset;
1801
+ } else {
1802
+ y = anchorRect.top;
1803
+ }
1804
+ if (side === "right") {
1805
+ x = anchorRect.right + sideOffset;
1806
+ } else if (side === "left") {
1807
+ x = anchorRect.left - contentRect.width - sideOffset;
1808
+ } else {
1809
+ x = anchorRect.left;
1810
+ }
1811
+ if (side === "top" || side === "bottom") {
1812
+ if (align === "center") {
1813
+ x = anchorRect.left + (anchorRect.width - contentRect.width) / 2;
1814
+ } else if (align === "end") {
1815
+ x = anchorRect.right - contentRect.width;
1816
+ }
1817
+ x += alignOffset;
1818
+ } else {
1819
+ if (align === "center") {
1820
+ y = anchorRect.top + (anchorRect.height - contentRect.height) / 2;
1821
+ } else if (align === "end") {
1822
+ y = anchorRect.bottom - contentRect.height;
1823
+ }
1824
+ y += alignOffset;
1825
+ }
1826
+ const placement = align === "center" ? side : `${side}-${align}`;
1827
+ return { x, y, placement };
1828
+ }
1829
+ function PopperRoot(props) {
1830
+ const anchorNode = createSignal5(null);
1831
+ const contentNode = createSignal5(null);
1832
+ const currentPlacement = createSignal5("bottom");
1833
+ const context = {
1834
+ anchor: () => anchorNode(),
1835
+ setAnchor: (node) => {
1836
+ anchorNode(node);
1837
+ },
1838
+ content: () => contentNode(),
1839
+ setContent: (node) => {
1840
+ contentNode(node);
1841
+ },
1842
+ placement: () => currentPlacement(),
1843
+ setPlacement: (placement) => {
1844
+ currentPlacement(placement);
1845
+ }
1846
+ };
1847
+ return {
1848
+ type: PopperContext.Provider,
1849
+ props: {
1850
+ value: context,
1851
+ children: props.children
1852
+ }
1853
+ };
1854
+ }
1855
+ function PopperAnchor(props) {
1856
+ const context = useContext11(PopperContext);
1857
+ if (!context) {
1858
+ throw new Error("PopperAnchor must be used inside PopperRoot");
1859
+ }
1860
+ return {
1861
+ type: "div",
1862
+ props: {
1863
+ ...props,
1864
+ ref: (node) => {
1865
+ context.setAnchor(node);
1866
+ if (typeof props.ref === "function") {
1867
+ props.ref(node);
1868
+ }
1869
+ },
1870
+ "data-popper-anchor": "",
1871
+ children: props.children
1872
+ }
1873
+ };
1874
+ }
1875
+ function PopperContent(props) {
1876
+ const context = useContext11(PopperContext);
1877
+ if (!context) {
1878
+ throw new Error("PopperContent must be used inside PopperRoot");
1879
+ }
1880
+ const side = props.side ?? "bottom";
1881
+ const align = props.align ?? "center";
1882
+ const sideOffset = props.sideOffset ?? 8;
1883
+ const alignOffset = props.alignOffset ?? 0;
1884
+ const strategy = props.strategy ?? "absolute";
1885
+ const contentId = useId(props.id, "popper-content");
1886
+ const update = () => {
1887
+ const anchor = context.anchor();
1888
+ const content = context.content();
1889
+ if (!anchor || !content) return;
1890
+ const anchorRect = anchor.getBoundingClientRect();
1891
+ const contentRect = content.getBoundingClientRect();
1892
+ const { x, y, placement } = computePosition(
1893
+ anchorRect,
1894
+ contentRect,
1895
+ side,
1896
+ align,
1897
+ sideOffset,
1898
+ alignOffset
1899
+ );
1900
+ content.style.position = strategy;
1901
+ content.style.left = `${Math.round(x)}px`;
1902
+ content.style.top = `${Math.round(y)}px`;
1903
+ content.dataset.placement = placement;
1904
+ context.setPlacement(placement);
1905
+ };
1906
+ createEffect2(() => {
1907
+ context.anchor();
1908
+ context.content();
1909
+ update();
1910
+ });
1911
+ const onWindowUpdate = () => update();
1912
+ const targetDocument = () => context.anchor()?.ownerDocument ?? (typeof document !== "undefined" ? document : null);
1913
+ const targetWindow = () => targetDocument()?.defaultView ?? null;
1914
+ useEventListener3(targetWindow, "resize", onWindowUpdate);
1915
+ useEventListener3(targetDocument, "scroll", onWindowUpdate, { capture: true });
1916
+ return {
1917
+ type: "div",
1918
+ props: {
1919
+ ...props,
1920
+ side: void 0,
1921
+ align: void 0,
1922
+ sideOffset: void 0,
1923
+ alignOffset: void 0,
1924
+ strategy: void 0,
1925
+ id: contentId,
1926
+ ref: (node) => {
1927
+ context.setContent(node);
1928
+ if (typeof props.ref === "function") {
1929
+ props.ref(node);
1930
+ }
1931
+ },
1932
+ role: props.role ?? "dialog",
1933
+ "data-popper-content": "",
1934
+ "data-placement": () => context.placement(),
1935
+ children: props.children
1936
+ }
1937
+ };
1938
+ }
1939
+ function PopperArrow(props) {
1940
+ const size = props.size ?? 8;
1941
+ return {
1942
+ type: "span",
1943
+ props: {
1944
+ ...props,
1945
+ size: void 0,
1946
+ "data-popper-arrow": "",
1947
+ style: {
1948
+ width: `${size}px`,
1949
+ height: `${size}px`,
1950
+ display: "inline-block",
1951
+ transform: "rotate(45deg)",
1952
+ ...typeof props.style === "object" && props.style !== null ? props.style : {}
1953
+ }
1954
+ }
1955
+ };
1956
+ }
1957
+
1958
+ // src/components/overlay/popover.ts
1959
+ var PopoverContext = createContext12(null);
1960
+ function usePopoverContext(component) {
1961
+ const context = useContext12(PopoverContext);
1962
+ if (!context) {
1963
+ throw new Error(`${component} must be used inside PopoverRoot`);
1964
+ }
1965
+ return context;
1966
+ }
1967
+ function PopoverRoot(props) {
1968
+ const openState = createControllableState({
1969
+ value: props.open,
1970
+ defaultValue: props.defaultOpen ?? false,
1971
+ onChange: props.onOpenChange
1972
+ });
1973
+ const baseId = useId(props.id, "popover");
1974
+ const context = {
1975
+ open: () => openState.get(),
1976
+ setOpen: (value) => openState.set(value),
1977
+ contentId: `${baseId}-content`,
1978
+ triggerRef: createRef()
1979
+ };
1980
+ return {
1981
+ type: PopoverContext.Provider,
1982
+ props: {
1983
+ value: context,
1984
+ children: {
1985
+ type: PopperRoot,
1986
+ props: {
1987
+ children: props.children
1988
+ }
1989
+ }
1990
+ }
1991
+ };
1992
+ }
1993
+ function PopoverTrigger(props) {
1994
+ const context = usePopoverContext("PopoverTrigger");
1995
+ const tag = props.as ?? "button";
1996
+ const refProp = props.ref;
1997
+ return {
1998
+ type: PopperAnchor,
1999
+ props: {
2000
+ children: Primitive({
2001
+ ...props,
2002
+ as: tag,
2003
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
2004
+ ref: composeRefs(context.triggerRef, refProp),
2005
+ "aria-haspopup": props["aria-haspopup"] ?? "dialog",
2006
+ "aria-expanded": () => context.open(),
2007
+ "aria-controls": context.contentId,
2008
+ "data-state": () => context.open() ? "open" : "closed",
2009
+ onClick: (event) => {
2010
+ props.onClick?.(event);
2011
+ if (event.defaultPrevented) return;
2012
+ context.setOpen(!context.open());
2013
+ },
2014
+ children: props.children
2015
+ })
2016
+ }
2017
+ };
2018
+ }
2019
+ function buildPopoverContent(context, props) {
2020
+ return {
2021
+ type: DismissableLayer,
2022
+ props: {
2023
+ onEscapeKeyDown: props.onEscapeKeyDown,
2024
+ onInteractOutside: props.onInteractOutside,
2025
+ onPointerDownOutside: props.onPointerDownOutside,
2026
+ onFocusOutside: props.onFocusOutside,
2027
+ onDismiss: () => {
2028
+ props.onDismiss?.();
2029
+ context.setOpen(false);
2030
+ },
2031
+ children: {
2032
+ type: PopperContent,
2033
+ props: {
2034
+ ...props,
2035
+ portal: void 0,
2036
+ forceMount: void 0,
2037
+ onDismiss: void 0,
2038
+ onEscapeKeyDown: void 0,
2039
+ onInteractOutside: void 0,
2040
+ onPointerDownOutside: void 0,
2041
+ onFocusOutside: void 0,
2042
+ id: props.id ?? context.contentId,
2043
+ role: props.role ?? "dialog",
2044
+ "data-popover-content": "",
2045
+ "data-state": () => context.open() ? "open" : "closed",
2046
+ children: props.children
2047
+ }
2048
+ }
2049
+ }
2050
+ };
2051
+ }
2052
+ function PopoverContent(props) {
2053
+ const context = usePopoverContext("PopoverContent");
2054
+ const content = buildPopoverContent(context, props);
2055
+ const child = () => context.open() || props.forceMount ? content : null;
2056
+ if (props.portal ?? true) {
2057
+ return {
2058
+ type: Portal,
2059
+ props: {
2060
+ children: child
2061
+ }
2062
+ };
2063
+ }
2064
+ return {
2065
+ type: "div",
2066
+ props: {
2067
+ "data-popover-inline-container": "",
2068
+ children: child
2069
+ }
2070
+ };
2071
+ }
2072
+ function PopoverClose(props) {
2073
+ const context = usePopoverContext("PopoverClose");
2074
+ const tag = props.as ?? "button";
2075
+ return Primitive({
2076
+ ...props,
2077
+ as: tag,
2078
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
2079
+ onClick: (event) => {
2080
+ props.onClick?.(event);
2081
+ if (event.defaultPrevented) return;
2082
+ context.setOpen(false);
2083
+ },
2084
+ children: props.children
2085
+ });
2086
+ }
2087
+
2088
+ // src/components/form/date-picker.ts
2089
+ function toDate2(value) {
2090
+ if (value === null || value === void 0) return null;
2091
+ const next = value instanceof Date ? new Date(value.getTime()) : new Date(value);
2092
+ return Number.isNaN(next.getTime()) ? null : next;
2093
+ }
2094
+ function sameDay(a, b) {
2095
+ if (!a || !b) return a === b;
2096
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
2097
+ }
2098
+ var DatePickerContext = createContext13(null);
2099
+ function useDatePickerContext(component) {
2100
+ const context = useContext13(DatePickerContext);
2101
+ if (!context) {
2102
+ throw new Error(`${component} must be used inside DatePickerRoot`);
2103
+ }
2104
+ return context;
2105
+ }
2106
+ function DatePickerRoot(props) {
2107
+ const baseId = useId(props.id, "date-picker");
2108
+ const valueState = createControllableState({
2109
+ value: props.value === void 0 ? void 0 : (() => {
2110
+ const next = toDate2(read(props.value, void 0));
2111
+ return next ? new Date(next.getFullYear(), next.getMonth(), next.getDate()) : null;
2112
+ }),
2113
+ defaultValue: toDate2(props.defaultValue),
2114
+ onChange: props.onValueChange,
2115
+ equals: (a, b) => sameDay(a, b)
2116
+ });
2117
+ const openState = createControllableState({
2118
+ value: props.open,
2119
+ defaultValue: props.defaultOpen ?? false,
2120
+ onChange: props.onOpenChange
2121
+ });
2122
+ const context = {
2123
+ baseId,
2124
+ value: () => valueState.get(),
2125
+ setValue: (value) => valueState.set(value),
2126
+ open: () => openState.get(),
2127
+ setOpen: (open) => openState.set(open),
2128
+ locale: () => read(props.locale, "en-US")
2129
+ };
2130
+ return {
2131
+ type: DatePickerContext.Provider,
2132
+ props: {
2133
+ value: context,
2134
+ children: {
2135
+ type: PopoverRoot,
2136
+ props: {
2137
+ id: baseId,
2138
+ open: () => context.open(),
2139
+ onOpenChange: (open) => context.setOpen(open),
2140
+ children: props.children
2141
+ }
2142
+ }
2143
+ }
2144
+ };
2145
+ }
2146
+ function DatePickerTrigger(props) {
2147
+ return {
2148
+ type: PopoverTrigger,
2149
+ props: {
2150
+ ...props,
2151
+ "data-date-picker-trigger": "",
2152
+ children: props.children ?? { type: DatePickerValue, props: {} }
2153
+ }
2154
+ };
2155
+ }
2156
+ function DatePickerValue(props) {
2157
+ const context = useDatePickerContext("DatePickerValue");
2158
+ return {
2159
+ type: "span",
2160
+ props: {
2161
+ ...props,
2162
+ locale: void 0,
2163
+ formatOptions: void 0,
2164
+ placeholder: void 0,
2165
+ "data-date-picker-value": "",
2166
+ children: props.children ?? (() => {
2167
+ const value = context.value();
2168
+ if (!value) {
2169
+ return props.placeholder ?? "";
2170
+ }
2171
+ return new Intl.DateTimeFormat(props.locale ?? context.locale(), props.formatOptions ?? { dateStyle: "medium" }).format(value);
2172
+ })
2173
+ }
2174
+ };
2175
+ }
2176
+ function DatePickerContent(props) {
2177
+ const context = useDatePickerContext("DatePickerContent");
2178
+ return {
2179
+ type: PopoverContent,
2180
+ props: {
2181
+ ...props,
2182
+ closeOnSelect: void 0,
2183
+ id: props.id ?? `${context.baseId}-content`,
2184
+ role: props.role ?? "dialog",
2185
+ "data-date-picker-content": "",
2186
+ children: props.children ?? {
2187
+ type: DatePickerCalendar,
2188
+ props: {
2189
+ closeOnSelect: props.closeOnSelect
2190
+ }
2191
+ }
2192
+ }
2193
+ };
2194
+ }
2195
+ function DatePickerCalendar(props) {
2196
+ const context = useDatePickerContext("DatePickerCalendar");
2197
+ return {
2198
+ type: CalendarRoot,
2199
+ props: {
2200
+ ...props,
2201
+ closeOnSelect: void 0,
2202
+ locale: props.locale ?? context.locale,
2203
+ value: () => context.value(),
2204
+ onValueChange: (value) => {
2205
+ props.onValueChange?.(value);
2206
+ context.setValue(value);
2207
+ if ((props.closeOnSelect ?? true) && value) {
2208
+ context.setOpen(false);
2209
+ }
2210
+ },
2211
+ "data-date-picker-calendar": "",
2212
+ children: props.children
2213
+ }
2214
+ };
2215
+ }
2216
+
2217
+ // src/components/form/select.ts
2218
+ import { createContext as createContext14, useContext as useContext14 } from "@fictjs/runtime";
2219
+ var SelectContext = createContext14(null);
2220
+ function useSelectContext(component) {
2221
+ const context = useContext14(SelectContext);
2222
+ if (!context) {
2223
+ throw new Error(`${component} must be used inside SelectRoot`);
2224
+ }
2225
+ return context;
2226
+ }
2227
+ function SelectRoot(props) {
2228
+ const valueState = createControllableState({
2229
+ value: props.value,
2230
+ defaultValue: props.defaultValue ?? "",
2231
+ onChange: props.onValueChange
2232
+ });
2233
+ const openState = createControllableState({
2234
+ value: props.open,
2235
+ defaultValue: props.defaultOpen ?? false,
2236
+ onChange: props.onOpenChange
2237
+ });
2238
+ const context = {
2239
+ value: () => valueState.get(),
2240
+ setValue: (value) => valueState.set(value),
2241
+ open: () => openState.get(),
2242
+ setOpen: (open) => openState.set(open),
2243
+ disabled: () => props.disabled ?? false
2244
+ };
2245
+ return {
2246
+ type: SelectContext.Provider,
2247
+ props: {
2248
+ value: context,
2249
+ children: props.children
2250
+ }
2251
+ };
2252
+ }
2253
+ function SelectTrigger(props) {
2254
+ const context = useSelectContext("SelectTrigger");
2255
+ const tag = props.as ?? "button";
2256
+ return Primitive({
2257
+ ...props,
2258
+ as: tag,
2259
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
2260
+ disabled: () => context.disabled(),
2261
+ "aria-haspopup": "listbox",
2262
+ "aria-expanded": () => context.open(),
2263
+ "data-state": () => context.open() ? "open" : "closed",
2264
+ "data-select-trigger": "",
2265
+ onClick: (event) => {
2266
+ ;
2267
+ props.onClick?.(event);
2268
+ if (event.defaultPrevented || context.disabled()) return;
2269
+ context.setOpen(!context.open());
2270
+ },
2271
+ children: props.children
2272
+ });
2273
+ }
2274
+ function SelectValue(props) {
2275
+ const context = useSelectContext("SelectValue");
2276
+ return {
2277
+ type: "span",
2278
+ props: {
2279
+ ...props,
2280
+ "data-select-value": "",
2281
+ children: () => context.value() || props.placeholder || ""
2282
+ }
2283
+ };
2284
+ }
2285
+ function SelectContent(props) {
2286
+ const context = useSelectContext("SelectContent");
2287
+ return {
2288
+ type: "div",
2289
+ props: {
2290
+ "data-select-content-wrapper": "",
2291
+ children: () => context.open() || props.forceMount ? {
2292
+ type: "div",
2293
+ props: {
2294
+ ...props,
2295
+ forceMount: void 0,
2296
+ role: "listbox",
2297
+ "data-select-content": "",
2298
+ children: props.children
2299
+ }
2300
+ } : null
2301
+ }
2302
+ };
2303
+ }
2304
+ function SelectItem(props) {
2305
+ const context = useSelectContext("SelectItem");
2306
+ const selected = () => context.value() === props.value;
2307
+ const tag = props.as ?? "button";
2308
+ return Primitive({
2309
+ ...props,
2310
+ as: tag,
2311
+ type: !props.asChild && tag === "button" ? "button" : props.type,
2312
+ role: "option",
2313
+ "aria-selected": selected,
2314
+ "data-state": () => selected() ? "checked" : "unchecked",
2315
+ "data-select-item": props.value,
2316
+ onClick: (event) => {
2317
+ ;
2318
+ props.onClick?.(event);
2319
+ if (event.defaultPrevented) return;
2320
+ context.setValue(props.value);
2321
+ context.setOpen(false);
2322
+ },
2323
+ children: props.children
2324
+ });
2325
+ }
2326
+
2327
+ // src/components/form/combobox.ts
2328
+ import { createContext as createContext15, useContext as useContext15 } from "@fictjs/runtime";
2329
+ import { createSignal as createSignal6 } from "@fictjs/runtime/advanced";
2330
+ var ComboboxContext = createContext15(null);
2331
+ function useComboboxContext(component) {
2332
+ const context = useContext15(ComboboxContext);
2333
+ if (!context) {
2334
+ throw new Error(`${component} must be used inside ComboboxRoot`);
2335
+ }
2336
+ return context;
2337
+ }
2338
+ function ComboboxRoot(props) {
2339
+ const valueState = createControllableState({
2340
+ value: props.value,
2341
+ defaultValue: props.defaultValue ?? "",
2342
+ onChange: props.onValueChange
2343
+ });
2344
+ const openState = createControllableState({
2345
+ value: props.open,
2346
+ defaultValue: props.defaultOpen ?? false,
2347
+ onChange: props.onOpenChange
2348
+ });
2349
+ const querySignal = createSignal6("");
2350
+ const context = {
2351
+ value: () => valueState.get(),
2352
+ setValue: (value) => valueState.set(value),
2353
+ open: () => openState.get(),
2354
+ setOpen: (open) => openState.set(open),
2355
+ query: () => querySignal(),
2356
+ setQuery: (query) => querySignal(query)
2357
+ };
2358
+ return {
2359
+ type: ComboboxContext.Provider,
2360
+ props: {
2361
+ value: context,
2362
+ children: props.children
2363
+ }
2364
+ };
2365
+ }
2366
+ function ComboboxInput(props) {
2367
+ const context = useComboboxContext("ComboboxInput");
2368
+ return {
2369
+ type: "input",
2370
+ props: {
2371
+ ...props,
2372
+ type: "text",
2373
+ role: "combobox",
2374
+ "aria-expanded": () => context.open(),
2375
+ "aria-autocomplete": "list",
2376
+ value: () => context.query() || context.value(),
2377
+ "data-combobox-input": "",
2378
+ onFocus: (event) => {
2379
+ ;
2380
+ props.onFocus?.(event);
2381
+ context.setOpen(true);
2382
+ },
2383
+ onInput: (event) => {
2384
+ ;
2385
+ props.onInput?.(event);
2386
+ const target = event.target;
2387
+ if (!target) return;
2388
+ context.setQuery(target.value);
2389
+ context.setOpen(true);
2390
+ }
2391
+ }
2392
+ };
2393
+ }
2394
+ function ComboboxList(props) {
2395
+ const context = useComboboxContext("ComboboxList");
2396
+ return {
2397
+ type: "div",
2398
+ props: {
2399
+ "data-combobox-list-wrapper": "",
2400
+ children: () => context.open() || props.forceMount ? {
2401
+ type: "div",
2402
+ props: {
2403
+ ...props,
2404
+ forceMount: void 0,
2405
+ role: "listbox",
2406
+ "data-combobox-list": "",
2407
+ children: props.children
2408
+ }
2409
+ } : null
2410
+ }
2411
+ };
2412
+ }
2413
+ function ComboboxItem(props) {
2414
+ const context = useComboboxContext("ComboboxItem");
2415
+ const tag = props.as ?? "button";
2416
+ const matches = () => {
2417
+ const query = context.query().trim().toLowerCase();
2418
+ if (!query) return true;
2419
+ const text = typeof props.children === "string" ? props.children : Array.isArray(props.children) ? props.children.join(" ") : props.value;
2420
+ return String(text).toLowerCase().includes(query);
2421
+ };
2422
+ return {
2423
+ type: "div",
2424
+ props: {
2425
+ "data-combobox-item-wrapper": props.value,
2426
+ children: () => matches() ? Primitive({
2427
+ ...props,
2428
+ as: tag,
2429
+ type: !props.asChild && tag === "button" ? "button" : props.type,
2430
+ role: "option",
2431
+ "data-combobox-item": props.value,
2432
+ onClick: (event) => {
2433
+ ;
2434
+ props.onClick?.(event);
2435
+ if (event.defaultPrevented) return;
2436
+ context.setValue(props.value);
2437
+ context.setQuery(props.value);
2438
+ context.setOpen(false);
2439
+ },
2440
+ children: props.children
2441
+ }) : null
2442
+ }
2443
+ };
2444
+ }
2445
+
2446
+ // src/components/form/form-field.ts
2447
+ import { createContext as createContext16, useContext as useContext16 } from "@fictjs/runtime";
2448
+ var FieldContext = createContext16(null);
2449
+ function useFieldContext(component) {
2450
+ const context = useContext16(FieldContext);
2451
+ if (!context) {
2452
+ throw new Error(`${component} must be used inside FormField`);
2453
+ }
2454
+ return context;
2455
+ }
2456
+ function Form(props) {
2457
+ return {
2458
+ type: "form",
2459
+ props: {
2460
+ ...props,
2461
+ "data-form": "",
2462
+ children: props.children
2463
+ }
2464
+ };
2465
+ }
2466
+ function FormField(props) {
2467
+ const fieldId = useId(props.id ?? (props.name ? `field-${props.name}` : void 0), "field");
2468
+ const context = {
2469
+ controlId: fieldId,
2470
+ descriptionId: `${fieldId}-description`,
2471
+ messageId: `${fieldId}-message`
2472
+ };
2473
+ return {
2474
+ type: FieldContext.Provider,
2475
+ props: {
2476
+ value: context,
2477
+ children: props.children
2478
+ }
2479
+ };
2480
+ }
2481
+ function FormLabel(props) {
2482
+ const field = useFieldContext("FormLabel");
2483
+ return {
2484
+ type: Label,
2485
+ props: {
2486
+ ...props,
2487
+ htmlFor: props.htmlFor ?? field.controlId,
2488
+ "data-form-label": "",
2489
+ children: props.children
2490
+ }
2491
+ };
2492
+ }
2493
+ function FormControl(props) {
2494
+ const field = useFieldContext("FormControl");
2495
+ const tag = props.as ?? "input";
2496
+ return {
2497
+ type: tag,
2498
+ props: {
2499
+ ...props,
2500
+ as: void 0,
2501
+ id: props.id ?? field.controlId,
2502
+ "aria-describedby": `${field.descriptionId} ${field.messageId}`,
2503
+ "data-form-control": "",
2504
+ children: props.children
2505
+ }
2506
+ };
2507
+ }
2508
+ function FormDescription(props) {
2509
+ const field = useFieldContext("FormDescription");
2510
+ return {
2511
+ type: "p",
2512
+ props: {
2513
+ ...props,
2514
+ id: props.id ?? field.descriptionId,
2515
+ "data-form-description": "",
2516
+ children: props.children
2517
+ }
2518
+ };
2519
+ }
2520
+ function FormMessage(props) {
2521
+ const field = useFieldContext("FormMessage");
2522
+ return {
2523
+ type: "p",
2524
+ props: {
2525
+ ...props,
2526
+ id: props.id ?? field.messageId,
2527
+ role: props.role ?? "alert",
2528
+ "data-form-message": "",
2529
+ children: props.children
2530
+ }
2531
+ };
2532
+ }
2533
+
2534
+ // src/components/interaction/focus-scope.ts
2535
+ import { onDestroy as onDestroy2, onMount as onMount3 } from "@fictjs/runtime";
2536
+ import { createSignal as createSignal7 } from "@fictjs/runtime/advanced";
2537
+ import { useEventListener as useEventListener4 } from "@fictjs/hooks";
2538
+
2539
+ // src/internal/dom.ts
2540
+ function getFocusableCandidates(container) {
2541
+ const selectors = [
2542
+ "a[href]",
2543
+ "button:not([disabled])",
2544
+ "input:not([disabled])",
2545
+ "select:not([disabled])",
2546
+ "textarea:not([disabled])",
2547
+ '[tabindex]:not([tabindex="-1"])',
2548
+ '[contenteditable="true"]'
2549
+ ];
2550
+ return Array.from(container.querySelectorAll(selectors.join(","))).filter((element) => {
2551
+ if (element.hasAttribute("disabled")) return false;
2552
+ if (element.getAttribute("aria-hidden") === "true") return false;
2553
+ if (element.tabIndex < 0) return false;
2554
+ const style = window.getComputedStyle(element);
2555
+ return style.display !== "none" && style.visibility !== "hidden";
2556
+ });
2557
+ }
2558
+ function focusFirst(container) {
2559
+ const [first] = getFocusableCandidates(container);
2560
+ first?.focus();
2561
+ }
2562
+
2563
+ // src/components/interaction/focus-scope.ts
2564
+ function FocusScope(props) {
2565
+ const node = createSignal7(null);
2566
+ let previousFocused = null;
2567
+ const onKeyDown = (event) => {
2568
+ if (event.key !== "Tab") return;
2569
+ const scope = node();
2570
+ if (!scope) return;
2571
+ const trapped = read(props.trapped, true);
2572
+ if (!trapped) return;
2573
+ const candidates = getFocusableCandidates(scope);
2574
+ if (candidates.length === 0) {
2575
+ event.preventDefault();
2576
+ return;
2577
+ }
2578
+ const first = candidates[0];
2579
+ const last = candidates[candidates.length - 1];
2580
+ const active = (scope.ownerDocument ?? document).activeElement;
2581
+ if (event.shiftKey) {
2582
+ if (active === first || !scope.contains(active)) {
2583
+ if (read(props.loop, true)) {
2584
+ event.preventDefault();
2585
+ last.focus();
2586
+ }
2587
+ }
2588
+ return;
2589
+ }
2590
+ if (active === last) {
2591
+ if (read(props.loop, true)) {
2592
+ event.preventDefault();
2593
+ first.focus();
2594
+ }
2595
+ }
2596
+ };
2597
+ const targetDocument = () => node()?.ownerDocument ?? (typeof document !== "undefined" ? document : null);
2598
+ useEventListener4(targetDocument, "keydown", onKeyDown, { capture: true });
2599
+ onMount3(() => {
2600
+ const scope = node();
2601
+ if (!scope) return;
2602
+ const doc = targetDocument();
2603
+ if (!doc) return;
2604
+ previousFocused = doc.activeElement;
2605
+ if (read(props.autoFocus, true)) {
2606
+ const mountEvent = new CustomEvent("fict-focus-scope.mount");
2607
+ props.onMountAutoFocus?.(mountEvent);
2608
+ if (!mountEvent.defaultPrevented) {
2609
+ focusFirst(scope);
2610
+ }
2611
+ }
2612
+ });
2613
+ onDestroy2(() => {
2614
+ if (read(props.restoreFocus, true) && previousFocused instanceof HTMLElement) {
2615
+ const unmountEvent = new CustomEvent("fict-focus-scope.unmount");
2616
+ props.onUnmountAutoFocus?.(unmountEvent);
2617
+ if (!unmountEvent.defaultPrevented) {
2618
+ previousFocused.focus();
2619
+ }
2620
+ }
2621
+ });
2622
+ return {
2623
+ type: "div",
2624
+ props: {
2625
+ ...props,
2626
+ trapped: void 0,
2627
+ loop: void 0,
2628
+ autoFocus: void 0,
2629
+ restoreFocus: void 0,
2630
+ onMountAutoFocus: void 0,
2631
+ onUnmountAutoFocus: void 0,
2632
+ ref: (el) => {
2633
+ node(el);
2634
+ },
2635
+ "data-focus-scope": "",
2636
+ children: props.children
2637
+ }
2638
+ };
2639
+ }
2640
+ function FocusTrap(props) {
2641
+ return {
2642
+ type: FocusScope,
2643
+ props: {
2644
+ ...props,
2645
+ trapped: true
2646
+ }
2647
+ };
2648
+ }
2649
+
2650
+ // src/components/interaction/scroll-lock.ts
2651
+ import { createEffect as createEffect3, onDestroy as onDestroy3 } from "@fictjs/runtime";
2652
+ var lockCount = 0;
2653
+ var previousOverflow = "";
2654
+ var previousPaddingRight = "";
2655
+ function lockBodyScroll() {
2656
+ if (typeof document === "undefined") return;
2657
+ if (lockCount === 0) {
2658
+ const body = document.body;
2659
+ previousOverflow = body.style.overflow;
2660
+ previousPaddingRight = body.style.paddingRight;
2661
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
2662
+ body.style.overflow = "hidden";
2663
+ if (scrollbarWidth > 0) {
2664
+ body.style.paddingRight = `${scrollbarWidth}px`;
2665
+ }
2666
+ }
2667
+ lockCount += 1;
2668
+ }
2669
+ function unlockBodyScroll() {
2670
+ if (typeof document === "undefined") return;
2671
+ if (lockCount === 0) return;
2672
+ lockCount -= 1;
2673
+ if (lockCount === 0) {
2674
+ const body = document.body;
2675
+ body.style.overflow = previousOverflow;
2676
+ body.style.paddingRight = previousPaddingRight;
2677
+ }
2678
+ }
2679
+ function ScrollLock(props) {
2680
+ let locked = false;
2681
+ createEffect3(() => {
2682
+ const enabled = read(props.enabled, true);
2683
+ if (enabled && !locked) {
2684
+ lockBodyScroll();
2685
+ locked = true;
2686
+ return;
2687
+ }
2688
+ if (!enabled && locked) {
2689
+ unlockBodyScroll();
2690
+ locked = false;
2691
+ }
2692
+ });
2693
+ onDestroy3(() => {
2694
+ if (locked) {
2695
+ unlockBodyScroll();
2696
+ locked = false;
2697
+ }
2698
+ });
2699
+ return null;
2700
+ }
2701
+
2702
+ // src/components/interaction/live-region.ts
2703
+ import { createContext as createContext17, useContext as useContext17 } from "@fictjs/runtime";
2704
+ var LiveRegionContext = createContext17(null);
2705
+ function LiveRegionProvider(props) {
2706
+ let politeNode = null;
2707
+ let assertiveNode = null;
2708
+ let pendingPolite = null;
2709
+ let pendingAssertive = null;
2710
+ const writeRegion = (node, message) => {
2711
+ if (!node) return;
2712
+ node.textContent = "";
2713
+ queueMicrotask(() => {
2714
+ if (node) {
2715
+ node.textContent = message;
2716
+ }
2717
+ });
2718
+ };
2719
+ const announce = (message, options) => {
2720
+ const politeness = options?.politeness ?? "polite";
2721
+ if (politeness === "assertive") {
2722
+ if (assertiveNode) {
2723
+ writeRegion(assertiveNode, message);
2724
+ } else {
2725
+ pendingAssertive = message;
2726
+ }
2727
+ return;
2728
+ }
2729
+ if (politeNode) {
2730
+ writeRegion(politeNode, message);
2731
+ } else {
2732
+ pendingPolite = message;
2733
+ }
2734
+ };
2735
+ return {
2736
+ type: LiveRegionContext.Provider,
2737
+ props: {
2738
+ value: { announce },
2739
+ children: [
2740
+ props.children,
2741
+ {
2742
+ type: VisuallyHidden,
2743
+ props: {
2744
+ "aria-live": "polite",
2745
+ "aria-atomic": "true",
2746
+ "data-live-region": "polite",
2747
+ ref: (node) => {
2748
+ politeNode = node;
2749
+ if (node && pendingPolite) {
2750
+ writeRegion(node, pendingPolite);
2751
+ pendingPolite = null;
2752
+ }
2753
+ },
2754
+ children: ""
2755
+ }
2756
+ },
2757
+ {
2758
+ type: VisuallyHidden,
2759
+ props: {
2760
+ "aria-live": "assertive",
2761
+ "aria-atomic": "true",
2762
+ "data-live-region": "assertive",
2763
+ ref: (node) => {
2764
+ assertiveNode = node;
2765
+ if (node && pendingAssertive) {
2766
+ writeRegion(node, pendingAssertive);
2767
+ pendingAssertive = null;
2768
+ }
2769
+ },
2770
+ children: ""
2771
+ }
2772
+ }
2773
+ ]
2774
+ }
2775
+ };
2776
+ }
2777
+ function useAnnouncer() {
2778
+ const context = useContext17(LiveRegionContext);
2779
+ if (!context) {
2780
+ throw new Error("useAnnouncer must be used inside LiveRegionProvider");
2781
+ }
2782
+ return context.announce;
2783
+ }
2784
+ function Announce(props) {
2785
+ const announce = useAnnouncer();
2786
+ if (props.message) {
2787
+ announce(props.message, { politeness: props.politeness });
2788
+ }
2789
+ return null;
2790
+ }
2791
+
2792
+ // src/components/layout/scroll-area.ts
2793
+ import { createContext as createContext18, useContext as useContext18 } from "@fictjs/runtime";
2794
+ var ScrollAreaContext = createContext18(null);
2795
+ function useScrollAreaContext(component) {
2796
+ const context = useContext18(ScrollAreaContext);
2797
+ if (!context) {
2798
+ throw new Error(`${component} must be used inside ScrollArea`);
2799
+ }
2800
+ return context;
2801
+ }
2802
+ function ScrollArea(props) {
2803
+ const context = {
2804
+ viewportRef: { current: null }
2805
+ };
2806
+ return {
2807
+ type: ScrollAreaContext.Provider,
2808
+ props: {
2809
+ value: context,
2810
+ children: {
2811
+ type: "div",
2812
+ props: {
2813
+ ...props,
2814
+ "data-scroll-area": "",
2815
+ children: props.children
2816
+ }
2817
+ }
2818
+ }
2819
+ };
2820
+ }
2821
+ function ScrollAreaViewport(props) {
2822
+ const context = useScrollAreaContext("ScrollAreaViewport");
2823
+ return {
2824
+ type: "div",
2825
+ props: {
2826
+ ...props,
2827
+ ref: (node) => {
2828
+ context.viewportRef.current = node;
2829
+ },
2830
+ style: {
2831
+ overflow: "auto",
2832
+ ...typeof props.style === "object" && props.style !== null ? props.style : {}
2833
+ },
2834
+ "data-scroll-area-viewport": "",
2835
+ children: props.children
2836
+ }
2837
+ };
2838
+ }
2839
+ function ScrollAreaScrollbar(props) {
2840
+ const orientation = props.orientation ?? "vertical";
2841
+ return {
2842
+ type: "div",
2843
+ props: {
2844
+ ...props,
2845
+ orientation: void 0,
2846
+ "data-orientation": orientation,
2847
+ "data-scroll-area-scrollbar": "",
2848
+ children: props.children
2849
+ }
2850
+ };
2851
+ }
2852
+ function ScrollAreaThumb(props) {
2853
+ return {
2854
+ type: "div",
2855
+ props: {
2856
+ ...props,
2857
+ "data-scroll-area-thumb": "",
2858
+ children: props.children
2859
+ }
2860
+ };
2861
+ }
2862
+
2863
+ // src/components/layout/resizable.ts
2864
+ import { createSignal as createSignal8 } from "@fictjs/runtime/advanced";
2865
+ import { useEventListener as useEventListener5 } from "@fictjs/hooks";
2866
+ function clamp(value, min, max) {
2867
+ return Math.min(max, Math.max(min, value));
2868
+ }
2869
+ function ResizablePanelGroup(props) {
2870
+ const direction = props.direction ?? "horizontal";
2871
+ return {
2872
+ type: "div",
2873
+ props: {
2874
+ ...props,
2875
+ direction: void 0,
2876
+ "data-resizable-panel-group": "",
2877
+ "data-direction": direction,
2878
+ style: {
2879
+ display: "flex",
2880
+ flexDirection: direction === "horizontal" ? "row" : "column",
2881
+ ...typeof props.style === "object" && props.style !== null ? props.style : {}
2882
+ },
2883
+ children: props.children
2884
+ }
2885
+ };
2886
+ }
2887
+ function ResizablePanel(props) {
2888
+ const defaultSize = props.defaultSize ?? 50;
2889
+ return {
2890
+ type: "div",
2891
+ props: {
2892
+ ...props,
2893
+ defaultSize: void 0,
2894
+ minSize: void 0,
2895
+ maxSize: void 0,
2896
+ "data-resizable-panel": "",
2897
+ style: {
2898
+ flexBasis: `${defaultSize}%`,
2899
+ flexGrow: 0,
2900
+ flexShrink: 0,
2901
+ overflow: "auto",
2902
+ ...typeof props.style === "object" && props.style !== null ? props.style : {}
2903
+ },
2904
+ children: props.children
2905
+ }
2906
+ };
2907
+ }
2908
+ function ResizableHandle(props) {
2909
+ let node = null;
2910
+ const dragState = createSignal8(null);
2911
+ const targetWindow = () => typeof window !== "undefined" ? window : null;
2912
+ const onMove = (moveEvent) => {
2913
+ const state = dragState();
2914
+ if (!state) return;
2915
+ const currentPos = state.direction === "horizontal" ? moveEvent.clientX : moveEvent.clientY;
2916
+ const delta = currentPos - state.startPos;
2917
+ const nextPrevPx = state.prevStart + delta;
2918
+ const nextNextPx = state.nextStart - delta;
2919
+ const nextPrevPercent = clamp(nextPrevPx / state.groupSize * 100, state.minPrev, state.maxPrev);
2920
+ const nextNextPercent = clamp(nextNextPx / state.groupSize * 100, state.minNext, state.maxNext);
2921
+ state.prev.style.flexBasis = `${nextPrevPercent}%`;
2922
+ state.next.style.flexBasis = `${nextNextPercent}%`;
2923
+ };
2924
+ const moveListener = useEventListener5(targetWindow, "pointermove", onMove, {
2925
+ immediate: false
2926
+ });
2927
+ const upListener = useEventListener5(
2928
+ targetWindow,
2929
+ "pointerup",
2930
+ () => {
2931
+ dragState(null);
2932
+ moveListener.stop();
2933
+ upListener.stop();
2934
+ },
2935
+ { immediate: false }
2936
+ );
2937
+ const onPointerDown = (event) => {
2938
+ if (!node) return;
2939
+ const group = node.parentElement;
2940
+ const prev = node.previousElementSibling;
2941
+ const next = node.nextElementSibling;
2942
+ if (!group || !prev || !next) return;
2943
+ const direction = group.getAttribute("data-direction") ?? "horizontal";
2944
+ const groupRect = group.getBoundingClientRect();
2945
+ const prevRect = prev.getBoundingClientRect();
2946
+ const nextRect = next.getBoundingClientRect();
2947
+ const startPos = direction === "horizontal" ? event.clientX : event.clientY;
2948
+ const prevStart = direction === "horizontal" ? prevRect.width : prevRect.height;
2949
+ const nextStart = direction === "horizontal" ? nextRect.width : nextRect.height;
2950
+ const groupSize = direction === "horizontal" ? groupRect.width : groupRect.height;
2951
+ const minPrev = Number(prev.getAttribute("data-min-size") ?? "5");
2952
+ const minNext = Number(next.getAttribute("data-min-size") ?? "5");
2953
+ const maxPrev = Number(prev.getAttribute("data-max-size") ?? "95");
2954
+ const maxNext = Number(next.getAttribute("data-max-size") ?? "95");
2955
+ dragState({
2956
+ direction,
2957
+ startPos,
2958
+ prevStart,
2959
+ nextStart,
2960
+ groupSize,
2961
+ minPrev,
2962
+ minNext,
2963
+ maxPrev,
2964
+ maxNext,
2965
+ prev,
2966
+ next
2967
+ });
2968
+ moveListener.start();
2969
+ upListener.start();
2970
+ };
2971
+ return {
2972
+ type: "div",
2973
+ props: {
2974
+ ...props,
2975
+ withHandle: void 0,
2976
+ ref: (el) => {
2977
+ node = el;
2978
+ },
2979
+ role: "separator",
2980
+ tabIndex: 0,
2981
+ "data-resizable-handle": "",
2982
+ onPointerDown,
2983
+ children: props.withHandle ? {
2984
+ type: "div",
2985
+ props: {
2986
+ "data-resizable-handle-grip": ""
2987
+ }
2988
+ } : null
2989
+ }
2990
+ };
2991
+ }
2992
+
2993
+ // src/components/layout/aspect-ratio.ts
2994
+ function AspectRatio(props) {
2995
+ const ratio = props.ratio ?? 1;
2996
+ const paddingBottom = `${1 / ratio * 100}%`;
2997
+ return {
2998
+ type: "div",
2999
+ props: {
3000
+ ...props,
3001
+ ratio: void 0,
3002
+ "data-aspect-ratio": "",
3003
+ style: {
3004
+ position: "relative",
3005
+ width: "100%",
3006
+ paddingBottom,
3007
+ ...typeof props.style === "object" && props.style !== null ? props.style : {}
3008
+ },
3009
+ children: {
3010
+ type: "div",
3011
+ props: {
3012
+ style: {
3013
+ position: "absolute",
3014
+ inset: 0
3015
+ },
3016
+ "data-aspect-ratio-content": "",
3017
+ children: props.children
3018
+ }
3019
+ }
3020
+ }
3021
+ };
3022
+ }
3023
+
3024
+ // src/components/layout/progress.ts
3025
+ function Progress(props) {
3026
+ const max = props.max ?? 100;
3027
+ const value = Math.min(max, Math.max(0, props.value ?? 0));
3028
+ return {
3029
+ type: "div",
3030
+ props: {
3031
+ ...props,
3032
+ value: void 0,
3033
+ max: void 0,
3034
+ role: "progressbar",
3035
+ "aria-valuemin": 0,
3036
+ "aria-valuemax": max,
3037
+ "aria-valuenow": value,
3038
+ "data-progress": "",
3039
+ children: {
3040
+ type: "div",
3041
+ props: {
3042
+ "data-progress-indicator": "",
3043
+ style: {
3044
+ width: `${value / max * 100}%`
3045
+ }
3046
+ }
3047
+ }
3048
+ }
3049
+ };
3050
+ }
3051
+ function Meter(props) {
3052
+ const min = props.min ?? 0;
3053
+ const max = props.max ?? 100;
3054
+ const value = Math.min(max, Math.max(min, props.value ?? 0));
3055
+ return {
3056
+ type: "meter",
3057
+ props: {
3058
+ ...props,
3059
+ min,
3060
+ max,
3061
+ value,
3062
+ low: props.low,
3063
+ high: props.high,
3064
+ optimum: props.optimum,
3065
+ "data-meter": "",
3066
+ children: props.children
3067
+ }
3068
+ };
3069
+ }
3070
+
3071
+ // src/components/layout/skeleton.ts
3072
+ function Skeleton(props) {
3073
+ const loading = props.loading ?? true;
3074
+ return {
3075
+ type: "div",
3076
+ props: {
3077
+ ...props,
3078
+ loading: void 0,
3079
+ "aria-busy": loading ? "true" : "false",
3080
+ "data-skeleton": "",
3081
+ children: loading ? {
3082
+ type: "span",
3083
+ props: {
3084
+ "data-skeleton-placeholder": "",
3085
+ children: props.children ?? null
3086
+ }
3087
+ } : props.children
3088
+ }
3089
+ };
3090
+ }
3091
+
3092
+ // src/components/layout/focus-visible.ts
3093
+ import { createContext as createContext19, useContext as useContext19 } from "@fictjs/runtime";
3094
+ import { createSignal as createSignal9 } from "@fictjs/runtime/advanced";
3095
+ import { useEventListener as useEventListener6 } from "@fictjs/hooks";
3096
+ var KeyboardModeContext = createContext19({
3097
+ isKeyboardMode: () => false
3098
+ });
3099
+ function KeyboardModeProvider(props) {
3100
+ const keyboardModeSignal = createSignal9(false);
3101
+ const targetDocument = () => typeof document !== "undefined" ? document : null;
3102
+ useEventListener6(targetDocument, "keydown", () => keyboardModeSignal(true), { capture: true });
3103
+ useEventListener6(targetDocument, "pointerdown", () => keyboardModeSignal(false), { capture: true });
3104
+ const context = {
3105
+ isKeyboardMode: () => keyboardModeSignal()
3106
+ };
3107
+ return {
3108
+ type: KeyboardModeContext.Provider,
3109
+ props: {
3110
+ value: context,
3111
+ children: props.children
3112
+ }
3113
+ };
3114
+ }
3115
+ function useKeyboardMode() {
3116
+ const context = useContext19(KeyboardModeContext);
3117
+ return context.isKeyboardMode;
3118
+ }
3119
+ function FocusVisible(props) {
3120
+ const isKeyboardMode = useKeyboardMode();
3121
+ const tag = props.as ?? "div";
3122
+ return {
3123
+ type: tag,
3124
+ props: {
3125
+ ...props,
3126
+ as: void 0,
3127
+ "data-focus-visible": () => isKeyboardMode() ? "true" : "false",
3128
+ children: props.children
3129
+ }
3130
+ };
3131
+ }
3132
+
3133
+ // src/components/overlay/dialog.ts
3134
+ import { createContext as createContext20, useContext as useContext20 } from "@fictjs/runtime";
3135
+ import { createRef as createRef2 } from "@fictjs/runtime";
3136
+ var DialogContext = createContext20(null);
3137
+ function useDialogContext(component) {
3138
+ const context = useContext20(DialogContext);
3139
+ if (!context) {
3140
+ throw new Error(`${component} must be used inside DialogRoot`);
3141
+ }
3142
+ return context;
3143
+ }
3144
+ function shouldRender(open, forceMount) {
3145
+ return open || !!forceMount;
3146
+ }
3147
+ function DialogRoot(props) {
3148
+ const openState = createControllableState({
3149
+ value: props.open,
3150
+ defaultValue: props.defaultOpen ?? false,
3151
+ onChange: props.onOpenChange
3152
+ });
3153
+ const baseId = useId(props.id, "dialog");
3154
+ const context = {
3155
+ open: () => openState.get(),
3156
+ setOpen: (value) => openState.set(value),
3157
+ modal: () => props.modal ?? true,
3158
+ contentId: `${baseId}-content`,
3159
+ titleId: `${baseId}-title`,
3160
+ descriptionId: `${baseId}-description`,
3161
+ triggerRef: createRef2(),
3162
+ contentRef: createRef2()
3163
+ };
3164
+ return {
3165
+ type: DialogContext.Provider,
3166
+ props: {
3167
+ value: context,
3168
+ children: props.children
3169
+ }
3170
+ };
3171
+ }
3172
+ function DialogPortal(props) {
3173
+ const context = useDialogContext("DialogPortal");
3174
+ return {
3175
+ type: Portal,
3176
+ props: {
3177
+ container: props.container,
3178
+ children: () => shouldRender(context.open(), props.forceMount) ? props.children ?? null : null
3179
+ }
3180
+ };
3181
+ }
3182
+ function DialogTrigger(props) {
3183
+ const context = useDialogContext("DialogTrigger");
3184
+ const tag = props.as ?? "button";
3185
+ const refProp = props.ref;
3186
+ const onClick = (event) => {
3187
+ props.onClick?.(event);
3188
+ if (event.defaultPrevented) return;
3189
+ context.setOpen(!context.open());
3190
+ };
3191
+ return Primitive({
3192
+ ...props,
3193
+ as: tag,
3194
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
3195
+ ref: composeRefs(context.triggerRef, refProp),
3196
+ "aria-haspopup": "dialog",
3197
+ "aria-expanded": () => context.open(),
3198
+ "aria-controls": context.contentId,
3199
+ "data-state": () => context.open() ? "open" : "closed",
3200
+ onClick,
3201
+ children: props.children
3202
+ });
3203
+ }
3204
+ function DialogOverlay(props) {
3205
+ const context = useDialogContext("DialogOverlay");
3206
+ const overlayNode = {
3207
+ type: "div",
3208
+ props: {
3209
+ ...props,
3210
+ forceMount: void 0,
3211
+ role: "presentation",
3212
+ "data-state": () => context.open() ? "open" : "closed",
3213
+ "data-dialog-overlay": "",
3214
+ onClick: (event) => {
3215
+ props.onClick?.(event);
3216
+ if (event.defaultPrevented) return;
3217
+ context.setOpen(false);
3218
+ },
3219
+ children: props.children
3220
+ }
3221
+ };
3222
+ return {
3223
+ type: DialogPortal,
3224
+ props: {
3225
+ forceMount: props.forceMount,
3226
+ children: overlayNode
3227
+ }
3228
+ };
3229
+ }
3230
+ function buildDialogContentNode(context, props) {
3231
+ const refProp = props.ref;
3232
+ return {
3233
+ type: DismissableLayer,
3234
+ props: {
3235
+ onEscapeKeyDown: props.onEscapeKeyDown,
3236
+ onInteractOutside: props.onInteractOutside,
3237
+ onPointerDownOutside: props.onPointerDownOutside,
3238
+ onFocusOutside: props.onFocusOutside,
3239
+ onDismiss: () => {
3240
+ props.onDismiss?.();
3241
+ context.setOpen(false);
3242
+ },
3243
+ children: {
3244
+ type: FocusScope,
3245
+ props: {
3246
+ trapped: () => context.modal(),
3247
+ loop: true,
3248
+ autoFocus: true,
3249
+ restoreFocus: true,
3250
+ children: [
3251
+ context.modal() ? { type: ScrollLock, props: { enabled: true } } : null,
3252
+ {
3253
+ type: "div",
3254
+ props: {
3255
+ ...props,
3256
+ portal: void 0,
3257
+ forceMount: void 0,
3258
+ onDismiss: void 0,
3259
+ onEscapeKeyDown: void 0,
3260
+ onInteractOutside: void 0,
3261
+ onPointerDownOutside: void 0,
3262
+ onFocusOutside: void 0,
3263
+ ref: composeRefs(context.contentRef, refProp),
3264
+ id: props.id ?? context.contentId,
3265
+ role: props.role ?? "dialog",
3266
+ "aria-modal": context.modal() ? "true" : void 0,
3267
+ "aria-labelledby": props["aria-labelledby"] ?? context.titleId,
3268
+ "aria-describedby": props["aria-describedby"] ?? context.descriptionId,
3269
+ "data-state": () => context.open() ? "open" : "closed",
3270
+ "data-dialog-content": "",
3271
+ children: props.children
3272
+ }
3273
+ }
3274
+ ]
3275
+ }
3276
+ }
3277
+ }
3278
+ };
3279
+ }
3280
+ function DialogContent(props) {
3281
+ const context = useDialogContext("DialogContent");
3282
+ const node = buildDialogContentNode(context, props);
3283
+ if (props.portal ?? true) {
3284
+ return {
3285
+ type: DialogPortal,
3286
+ props: {
3287
+ forceMount: props.forceMount,
3288
+ children: node
3289
+ }
3290
+ };
3291
+ }
3292
+ return {
3293
+ type: "div",
3294
+ props: {
3295
+ "data-dialog-inline-container": "",
3296
+ children: () => shouldRender(context.open(), props.forceMount) ? node : null
3297
+ }
3298
+ };
3299
+ }
3300
+ function DialogClose(props) {
3301
+ const context = useDialogContext("DialogClose");
3302
+ const tag = props.as ?? "button";
3303
+ return Primitive({
3304
+ ...props,
3305
+ as: tag,
3306
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
3307
+ onClick: (event) => {
3308
+ props.onClick?.(event);
3309
+ if (event.defaultPrevented) return;
3310
+ context.setOpen(false);
3311
+ },
3312
+ children: props.children
3313
+ });
3314
+ }
3315
+ function DialogTitle(props) {
3316
+ const context = useDialogContext("DialogTitle");
3317
+ return {
3318
+ type: "h2",
3319
+ props: {
3320
+ ...props,
3321
+ id: props.id ?? context.titleId,
3322
+ "data-dialog-title": "",
3323
+ children: props.children
3324
+ }
3325
+ };
3326
+ }
3327
+ function DialogDescription(props) {
3328
+ const context = useDialogContext("DialogDescription");
3329
+ return {
3330
+ type: "p",
3331
+ props: {
3332
+ ...props,
3333
+ id: props.id ?? context.descriptionId,
3334
+ "data-dialog-description": "",
3335
+ children: props.children
3336
+ }
3337
+ };
3338
+ }
3339
+
3340
+ // src/components/overlay/alert-dialog.ts
3341
+ function AlertDialogRoot(props) {
3342
+ return {
3343
+ type: DialogRoot,
3344
+ props: {
3345
+ ...props,
3346
+ modal: true
3347
+ }
3348
+ };
3349
+ }
3350
+ var AlertDialogTrigger = DialogTrigger;
3351
+ var AlertDialogPortal = DialogPortal;
3352
+ var AlertDialogOverlay = DialogOverlay;
3353
+ var AlertDialogTitle = DialogTitle;
3354
+ var AlertDialogDescription = DialogDescription;
3355
+ function AlertDialogContent(props) {
3356
+ return {
3357
+ type: DialogContent,
3358
+ props: {
3359
+ ...props,
3360
+ role: props.role ?? "alertdialog"
3361
+ }
3362
+ };
3363
+ }
3364
+ function AlertDialogAction(props) {
3365
+ return {
3366
+ type: DialogClose,
3367
+ props
3368
+ };
3369
+ }
3370
+ function AlertDialogCancel(props) {
3371
+ return {
3372
+ type: DialogClose,
3373
+ props
3374
+ };
3375
+ }
3376
+
3377
+ // src/components/overlay/tooltip.ts
3378
+ import { createContext as createContext21, useContext as useContext21 } from "@fictjs/runtime";
3379
+ import { useDebounceFn } from "@fictjs/hooks";
3380
+ var TooltipProviderContext = createContext21({
3381
+ delayDuration: 700
3382
+ });
3383
+ var TooltipRootContext = createContext21(null);
3384
+ function useTooltipRootContext(component) {
3385
+ const context = useContext21(TooltipRootContext);
3386
+ if (!context) {
3387
+ throw new Error(`${component} must be used inside TooltipRoot`);
3388
+ }
3389
+ return context;
3390
+ }
3391
+ function TooltipProvider(props) {
3392
+ return {
3393
+ type: TooltipProviderContext.Provider,
3394
+ props: {
3395
+ value: {
3396
+ delayDuration: props.delayDuration ?? 700
3397
+ },
3398
+ children: props.children
3399
+ }
3400
+ };
3401
+ }
3402
+ function TooltipRoot(props) {
3403
+ const provider = useContext21(TooltipProviderContext);
3404
+ const openState = createControllableState({
3405
+ value: props.open,
3406
+ defaultValue: props.defaultOpen ?? false,
3407
+ onChange: props.onOpenChange
3408
+ });
3409
+ const baseId = useId(props.id, "tooltip");
3410
+ const openDebounced = useDebounceFn(
3411
+ () => {
3412
+ openState.set(true);
3413
+ },
3414
+ props.delayDuration ?? provider.delayDuration
3415
+ );
3416
+ const clearSchedule = () => openDebounced.cancel();
3417
+ const scheduleOpen = () => openDebounced.run();
3418
+ const context = {
3419
+ open: () => openState.get(),
3420
+ setOpen: (value) => openState.set(value),
3421
+ delayDuration: () => props.delayDuration ?? provider.delayDuration,
3422
+ contentId: `${baseId}-content`,
3423
+ scheduleOpen,
3424
+ clearSchedule
3425
+ };
3426
+ return {
3427
+ type: TooltipRootContext.Provider,
3428
+ props: {
3429
+ value: context,
3430
+ children: {
3431
+ type: PopperRoot,
3432
+ props: {
3433
+ children: props.children
3434
+ }
3435
+ }
3436
+ }
3437
+ };
3438
+ }
3439
+ function TooltipTrigger(props) {
3440
+ const context = useTooltipRootContext("TooltipTrigger");
3441
+ const tag = props.as ?? "button";
3442
+ const refProp = props.ref;
3443
+ let cleanupListeners = null;
3444
+ const open = (event) => {
3445
+ context.scheduleOpen();
3446
+ if (event instanceof PointerEvent) props.onPointerEnter?.(event);
3447
+ if (event instanceof MouseEvent) {
3448
+ props.onMouseEnter?.(event);
3449
+ props.onMouseOver?.(event);
3450
+ }
3451
+ };
3452
+ const close = (event) => {
3453
+ context.clearSchedule();
3454
+ context.setOpen(false);
3455
+ if (event instanceof PointerEvent) props.onPointerLeave?.(event);
3456
+ if (event instanceof MouseEvent) {
3457
+ props.onMouseLeave?.(event);
3458
+ props.onMouseOut?.(event);
3459
+ }
3460
+ };
3461
+ const onFocus = (event) => {
3462
+ props.onFocus?.(event);
3463
+ context.scheduleOpen();
3464
+ };
3465
+ const onBlur = (event) => {
3466
+ props.onBlur?.(event);
3467
+ context.clearSchedule();
3468
+ context.setOpen(false);
3469
+ };
3470
+ const registerRef = (node) => {
3471
+ cleanupListeners?.();
3472
+ cleanupListeners = null;
3473
+ if (typeof refProp === "function") {
3474
+ refProp(node);
3475
+ } else if (refProp) {
3476
+ refProp.current = node;
3477
+ }
3478
+ if (!node) return;
3479
+ node.addEventListener("pointerenter", open);
3480
+ node.addEventListener("pointerleave", close);
3481
+ node.addEventListener("mouseover", open);
3482
+ node.addEventListener("mouseout", close);
3483
+ node.addEventListener("focus", onFocus);
3484
+ node.addEventListener("blur", onBlur);
3485
+ cleanupListeners = () => {
3486
+ node.removeEventListener("pointerenter", open);
3487
+ node.removeEventListener("pointerleave", close);
3488
+ node.removeEventListener("mouseover", open);
3489
+ node.removeEventListener("mouseout", close);
3490
+ node.removeEventListener("focus", onFocus);
3491
+ node.removeEventListener("blur", onBlur);
3492
+ };
3493
+ };
3494
+ return {
3495
+ type: PopperAnchor,
3496
+ props: {
3497
+ children: Primitive({
3498
+ ...props,
3499
+ as: tag,
3500
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
3501
+ ref: registerRef,
3502
+ "aria-describedby": () => context.open() ? context.contentId : void 0,
3503
+ "data-state": () => context.open() ? "open" : "closed",
3504
+ children: props.children
3505
+ })
3506
+ }
3507
+ };
3508
+ }
3509
+ function TooltipContent(props) {
3510
+ const context = useTooltipRootContext("TooltipContent");
3511
+ const contentNode = {
3512
+ type: PopperContent,
3513
+ props: {
3514
+ ...props,
3515
+ forceMount: void 0,
3516
+ portal: void 0,
3517
+ id: props.id ?? context.contentId,
3518
+ role: props.role ?? "tooltip",
3519
+ "data-tooltip-content": "",
3520
+ "data-state": () => context.open() ? "open" : "closed",
3521
+ onPointerEnter: (event) => {
3522
+ props.onPointerEnter?.(event);
3523
+ context.clearSchedule();
3524
+ },
3525
+ onPointerLeave: (event) => {
3526
+ props.onPointerLeave?.(event);
3527
+ context.setOpen(false);
3528
+ },
3529
+ onMouseEnter: (event) => {
3530
+ props.onMouseEnter?.(event);
3531
+ context.clearSchedule();
3532
+ },
3533
+ onMouseLeave: (event) => {
3534
+ props.onMouseLeave?.(event);
3535
+ context.setOpen(false);
3536
+ },
3537
+ onMouseOver: (event) => {
3538
+ props.onMouseOver?.(event);
3539
+ context.clearSchedule();
3540
+ },
3541
+ onMouseOut: (event) => {
3542
+ props.onMouseOut?.(event);
3543
+ context.setOpen(false);
3544
+ },
3545
+ children: props.children
3546
+ }
3547
+ };
3548
+ const child = () => context.open() || props.forceMount ? contentNode : null;
3549
+ if (props.portal ?? true) {
3550
+ return {
3551
+ type: Portal,
3552
+ props: {
3553
+ children: child
3554
+ }
3555
+ };
3556
+ }
3557
+ return {
3558
+ type: "div",
3559
+ props: {
3560
+ "data-tooltip-inline-container": "",
3561
+ children: child
3562
+ }
3563
+ };
3564
+ }
3565
+
3566
+ // src/components/overlay/hover-card.ts
3567
+ import { createContext as createContext22, useContext as useContext22 } from "@fictjs/runtime";
3568
+ import { useDebounceFn as useDebounceFn2 } from "@fictjs/hooks";
3569
+ var HoverCardContext = createContext22(null);
3570
+ function useHoverCardContext(component) {
3571
+ const context = useContext22(HoverCardContext);
3572
+ if (!context) {
3573
+ throw new Error(`${component} must be used inside HoverCardRoot`);
3574
+ }
3575
+ return context;
3576
+ }
3577
+ function HoverCardRoot(props) {
3578
+ const openState = createControllableState({
3579
+ value: props.open,
3580
+ defaultValue: props.defaultOpen ?? false,
3581
+ onChange: props.onOpenChange
3582
+ });
3583
+ const baseId = useId(props.id, "hover-card");
3584
+ const openDebounced = useDebounceFn2(
3585
+ () => {
3586
+ openState.set(true);
3587
+ },
3588
+ props.openDelay ?? 200
3589
+ );
3590
+ const closeDebounced = useDebounceFn2(
3591
+ () => {
3592
+ openState.set(false);
3593
+ },
3594
+ props.closeDelay ?? 200
3595
+ );
3596
+ const clearTimers = () => {
3597
+ openDebounced.cancel();
3598
+ closeDebounced.cancel();
3599
+ };
3600
+ const scheduleOpen = () => {
3601
+ closeDebounced.cancel();
3602
+ openDebounced.run();
3603
+ };
3604
+ const scheduleClose = () => {
3605
+ openDebounced.cancel();
3606
+ closeDebounced.run();
3607
+ };
3608
+ const context = {
3609
+ open: () => openState.get(),
3610
+ setOpen: (value) => openState.set(value),
3611
+ contentId: `${baseId}-content`,
3612
+ scheduleOpen,
3613
+ scheduleClose,
3614
+ clearTimers
3615
+ };
3616
+ return {
3617
+ type: HoverCardContext.Provider,
3618
+ props: {
3619
+ value: context,
3620
+ children: {
3621
+ type: PopperRoot,
3622
+ props: {
3623
+ children: props.children
3624
+ }
3625
+ }
3626
+ }
3627
+ };
3628
+ }
3629
+ function HoverCardTrigger(props) {
3630
+ const context = useHoverCardContext("HoverCardTrigger");
3631
+ const tag = props.as ?? "button";
3632
+ const refProp = props.ref;
3633
+ let cleanupListeners = null;
3634
+ const open = (event) => {
3635
+ context.scheduleOpen();
3636
+ if (event instanceof PointerEvent) props.onPointerEnter?.(event);
3637
+ if (event instanceof MouseEvent) {
3638
+ props.onMouseEnter?.(event);
3639
+ props.onMouseOver?.(event);
3640
+ }
3641
+ };
3642
+ const close = (event) => {
3643
+ context.scheduleClose();
3644
+ if (event instanceof PointerEvent) props.onPointerLeave?.(event);
3645
+ if (event instanceof MouseEvent) {
3646
+ props.onMouseLeave?.(event);
3647
+ props.onMouseOut?.(event);
3648
+ }
3649
+ };
3650
+ const onFocus = (event) => {
3651
+ props.onFocus?.(event);
3652
+ context.scheduleOpen();
3653
+ };
3654
+ const onBlur = (event) => {
3655
+ props.onBlur?.(event);
3656
+ context.scheduleClose();
3657
+ };
3658
+ const registerRef = (node) => {
3659
+ cleanupListeners?.();
3660
+ cleanupListeners = null;
3661
+ if (typeof refProp === "function") {
3662
+ refProp(node);
3663
+ } else if (refProp) {
3664
+ refProp.current = node;
3665
+ }
3666
+ if (!node) return;
3667
+ node.addEventListener("pointerenter", open);
3668
+ node.addEventListener("pointerleave", close);
3669
+ node.addEventListener("mouseover", open);
3670
+ node.addEventListener("mouseout", close);
3671
+ node.addEventListener("focus", onFocus);
3672
+ node.addEventListener("blur", onBlur);
3673
+ cleanupListeners = () => {
3674
+ node.removeEventListener("pointerenter", open);
3675
+ node.removeEventListener("pointerleave", close);
3676
+ node.removeEventListener("mouseover", open);
3677
+ node.removeEventListener("mouseout", close);
3678
+ node.removeEventListener("focus", onFocus);
3679
+ node.removeEventListener("blur", onBlur);
3680
+ };
3681
+ };
3682
+ return {
3683
+ type: PopperAnchor,
3684
+ props: {
3685
+ children: Primitive({
3686
+ ...props,
3687
+ as: tag,
3688
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
3689
+ ref: registerRef,
3690
+ "aria-describedby": () => context.open() ? context.contentId : void 0,
3691
+ "data-state": () => context.open() ? "open" : "closed",
3692
+ children: props.children
3693
+ })
3694
+ }
3695
+ };
3696
+ }
3697
+ function HoverCardContent(props) {
3698
+ const context = useHoverCardContext("HoverCardContent");
3699
+ const contentNode = {
3700
+ type: PopperContent,
3701
+ props: {
3702
+ ...props,
3703
+ forceMount: void 0,
3704
+ portal: void 0,
3705
+ id: props.id ?? context.contentId,
3706
+ role: props.role ?? "dialog",
3707
+ "data-hover-card-content": "",
3708
+ "data-state": () => context.open() ? "open" : "closed",
3709
+ onPointerEnter: (event) => {
3710
+ props.onPointerEnter?.(event);
3711
+ context.clearTimers();
3712
+ },
3713
+ onPointerLeave: (event) => {
3714
+ props.onPointerLeave?.(event);
3715
+ context.scheduleClose();
3716
+ },
3717
+ onMouseEnter: (event) => {
3718
+ props.onMouseEnter?.(event);
3719
+ context.clearTimers();
3720
+ },
3721
+ onMouseLeave: (event) => {
3722
+ props.onMouseLeave?.(event);
3723
+ context.scheduleClose();
3724
+ },
3725
+ onMouseOver: (event) => {
3726
+ props.onMouseOver?.(event);
3727
+ context.clearTimers();
3728
+ },
3729
+ onMouseOut: (event) => {
3730
+ props.onMouseOut?.(event);
3731
+ context.scheduleClose();
3732
+ },
3733
+ children: props.children
3734
+ }
3735
+ };
3736
+ const child = () => context.open() || props.forceMount ? contentNode : null;
3737
+ if (props.portal ?? true) {
3738
+ return {
3739
+ type: Portal,
3740
+ props: {
3741
+ children: child
3742
+ }
3743
+ };
3744
+ }
3745
+ return {
3746
+ type: "div",
3747
+ props: {
3748
+ "data-hover-card-inline-container": "",
3749
+ children: child
3750
+ }
3751
+ };
3752
+ }
3753
+
3754
+ // src/components/overlay/command-palette.ts
3755
+ import { createContext as createContext23, onDestroy as onDestroy4, onMount as onMount4, useContext as useContext23 } from "@fictjs/runtime";
3756
+ import { createSignal as createSignal10 } from "@fictjs/runtime/advanced";
3757
+ function normalizeText(node) {
3758
+ if (node === null || node === void 0 || node === false) return "";
3759
+ if (typeof node === "string" || typeof node === "number") return String(node);
3760
+ if (Array.isArray(node)) {
3761
+ return node.map((item) => normalizeText(item)).join(" ").trim();
3762
+ }
3763
+ return "";
3764
+ }
3765
+ function matchCommand(query, item) {
3766
+ const normalized = query.trim().toLowerCase();
3767
+ if (!normalized) return true;
3768
+ const searchable = [item.value, item.text, ...item.keywords].map((value) => value.toLowerCase()).join(" ");
3769
+ return searchable.includes(normalized);
3770
+ }
3771
+ var CommandPaletteContext = createContext23(null);
3772
+ function useCommandPaletteContext(component) {
3773
+ const context = useContext23(CommandPaletteContext);
3774
+ if (!context) {
3775
+ throw new Error(`${component} must be used inside CommandPaletteRoot`);
3776
+ }
3777
+ return context;
3778
+ }
3779
+ function CommandPaletteRoot(props) {
3780
+ const baseId = useId(props.id, "command-palette");
3781
+ const openState = createControllableState({
3782
+ value: props.open,
3783
+ defaultValue: props.defaultOpen ?? false,
3784
+ onChange: props.onOpenChange
3785
+ });
3786
+ const valueState = createControllableState({
3787
+ value: props.value,
3788
+ defaultValue: props.defaultValue ?? "",
3789
+ onChange: props.onValueChange
3790
+ });
3791
+ const queryState = createControllableState({
3792
+ value: props.query,
3793
+ defaultValue: props.defaultQuery ?? "",
3794
+ onChange: props.onQueryChange
3795
+ });
3796
+ const itemsSignal = createSignal10([]);
3797
+ const context = {
3798
+ listId: `${baseId}-list`,
3799
+ open: () => openState.get(),
3800
+ setOpen: (open) => {
3801
+ openState.set(open);
3802
+ if (!open && (props.resetQueryOnClose ?? true)) {
3803
+ queryState.set("");
3804
+ }
3805
+ },
3806
+ value: () => valueState.get(),
3807
+ setValue: (value) => valueState.set(value),
3808
+ query: () => queryState.get(),
3809
+ setQuery: (query) => queryState.set(query),
3810
+ registerItem: (item) => {
3811
+ itemsSignal([...itemsSignal(), item]);
3812
+ return () => {
3813
+ itemsSignal(itemsSignal().filter((entry) => entry !== item));
3814
+ };
3815
+ },
3816
+ hasMatches: () => {
3817
+ const items = itemsSignal();
3818
+ if (items.length === 0) return false;
3819
+ return items.some((item) => matchCommand(queryState.get(), item));
3820
+ }
3821
+ };
3822
+ return {
3823
+ type: CommandPaletteContext.Provider,
3824
+ props: {
3825
+ value: context,
3826
+ children: {
3827
+ type: DialogRoot,
3828
+ props: {
3829
+ id: baseId,
3830
+ modal: true,
3831
+ open: () => context.open(),
3832
+ onOpenChange: (open) => context.setOpen(open),
3833
+ children: props.children
3834
+ }
3835
+ }
3836
+ }
3837
+ };
3838
+ }
3839
+ function CommandPaletteTrigger(props) {
3840
+ return {
3841
+ type: DialogTrigger,
3842
+ props: {
3843
+ ...props,
3844
+ "data-command-trigger": "",
3845
+ children: props.children
3846
+ }
3847
+ };
3848
+ }
3849
+ function CommandPaletteContent(props) {
3850
+ return {
3851
+ type: DialogContent,
3852
+ props: {
3853
+ ...props,
3854
+ role: props.role ?? "dialog",
3855
+ "data-command-content": "",
3856
+ children: props.children
3857
+ }
3858
+ };
3859
+ }
3860
+ function CommandPaletteInput(props) {
3861
+ const context = useCommandPaletteContext("CommandPaletteInput");
3862
+ return {
3863
+ type: "input",
3864
+ props: {
3865
+ ...props,
3866
+ type: "text",
3867
+ role: "combobox",
3868
+ "aria-expanded": () => context.open(),
3869
+ "aria-controls": context.listId,
3870
+ value: () => context.query(),
3871
+ "data-command-input": "",
3872
+ onFocus: (event) => {
3873
+ ;
3874
+ props.onFocus?.(event);
3875
+ if (!event.defaultPrevented) {
3876
+ context.setOpen(true);
3877
+ }
3878
+ },
3879
+ onInput: (event) => {
3880
+ ;
3881
+ props.onInput?.(event);
3882
+ const target = event.target;
3883
+ if (!target) return;
3884
+ context.setQuery(target.value);
3885
+ },
3886
+ onKeyDown: (event) => {
3887
+ ;
3888
+ props.onKeyDown?.(event);
3889
+ if (event.defaultPrevented) return;
3890
+ if (event.key === "ArrowDown") {
3891
+ const list = document.getElementById(context.listId);
3892
+ const firstItem = list?.querySelector("[data-command-item]");
3893
+ firstItem?.focus();
3894
+ event.preventDefault();
3895
+ }
3896
+ }
3897
+ }
3898
+ };
3899
+ }
3900
+ function CommandPaletteList(props) {
3901
+ const context = useCommandPaletteContext("CommandPaletteList");
3902
+ return {
3903
+ type: "div",
3904
+ props: {
3905
+ ...props,
3906
+ id: props.id ?? context.listId,
3907
+ role: "listbox",
3908
+ "data-command-list": "",
3909
+ children: {
3910
+ type: RovingFocusGroup,
3911
+ props: {
3912
+ orientation: "vertical",
3913
+ loop: true,
3914
+ children: props.children
3915
+ }
3916
+ }
3917
+ }
3918
+ };
3919
+ }
3920
+ function CommandPaletteItem(props) {
3921
+ const context = useCommandPaletteContext("CommandPaletteItem");
3922
+ const tag = props.as ?? "button";
3923
+ const text = normalizeText(props.children) || props.value;
3924
+ let cleanup = null;
3925
+ onMount4(() => {
3926
+ cleanup = context.registerItem({
3927
+ value: props.value,
3928
+ text,
3929
+ keywords: props.keywords ?? []
3930
+ });
3931
+ });
3932
+ onDestroy4(() => {
3933
+ cleanup?.();
3934
+ cleanup = null;
3935
+ });
3936
+ const matches = () => matchCommand(context.query(), {
3937
+ value: props.value,
3938
+ text,
3939
+ keywords: props.keywords ?? []
3940
+ });
3941
+ return {
3942
+ type: "div",
3943
+ props: {
3944
+ "data-command-item-wrapper": props.value,
3945
+ children: () => matches() ? Primitive({
3946
+ ...props,
3947
+ as: tag,
3948
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
3949
+ role: props.role ?? "option",
3950
+ "aria-selected": () => context.value() === props.value,
3951
+ "data-state": () => context.value() === props.value ? "selected" : "idle",
3952
+ "data-command-item": props.value,
3953
+ onClick: (event) => {
3954
+ ;
3955
+ props.onClick?.(event);
3956
+ props.onSelect?.(props.value, event);
3957
+ if (event.defaultPrevented) return;
3958
+ context.setValue(props.value);
3959
+ if (!props.keepOpen) {
3960
+ context.setOpen(false);
3961
+ }
3962
+ },
3963
+ children: props.children
3964
+ }) : null
3965
+ }
3966
+ };
3967
+ }
3968
+ function CommandPaletteEmpty(props) {
3969
+ const context = useCommandPaletteContext("CommandPaletteEmpty");
3970
+ return {
3971
+ type: "div",
3972
+ props: {
3973
+ ...props,
3974
+ "data-command-empty": "",
3975
+ children: () => !context.hasMatches() ? props.children ?? "No results found." : null
3976
+ }
3977
+ };
3978
+ }
3979
+ function CommandPaletteGroup(props) {
3980
+ return {
3981
+ type: "div",
3982
+ props: {
3983
+ ...props,
3984
+ heading: void 0,
3985
+ role: props.role ?? "group",
3986
+ "data-command-group": "",
3987
+ children: [
3988
+ props.heading ? {
3989
+ type: "div",
3990
+ props: {
3991
+ "data-command-group-heading": "",
3992
+ children: props.heading
3993
+ }
3994
+ } : null,
3995
+ props.children
3996
+ ]
3997
+ }
3998
+ };
3999
+ }
4000
+ var CommandPaletteSeparator = Separator;
4001
+ var CommandPaletteClose = DialogClose;
4002
+
4003
+ // src/components/menu/dropdown-menu.ts
4004
+ import { createContext as createContext24, useContext as useContext24 } from "@fictjs/runtime";
4005
+ var DropdownMenuContext = createContext24(null);
4006
+ var DropdownRadioContext = createContext24(null);
4007
+ function useDropdownMenuContext(component) {
4008
+ const context = useContext24(DropdownMenuContext);
4009
+ if (!context) {
4010
+ throw new Error(`${component} must be used inside DropdownMenuRoot`);
4011
+ }
4012
+ return context;
4013
+ }
4014
+ function DropdownMenuRoot(props) {
4015
+ const state = createControllableState({
4016
+ value: props.open,
4017
+ defaultValue: props.defaultOpen ?? false,
4018
+ onChange: props.onOpenChange
4019
+ });
4020
+ const context = {
4021
+ open: () => state.get(),
4022
+ setOpen: (open) => state.set(open)
4023
+ };
4024
+ return {
4025
+ type: DropdownMenuContext.Provider,
4026
+ props: {
4027
+ value: context,
4028
+ children: {
4029
+ type: PopoverRoot,
4030
+ props: {
4031
+ open: () => context.open(),
4032
+ onOpenChange: (open) => context.setOpen(open),
4033
+ children: props.children
4034
+ }
4035
+ }
4036
+ }
4037
+ };
4038
+ }
4039
+ function DropdownMenuTrigger(props) {
4040
+ return {
4041
+ type: PopoverTrigger,
4042
+ props
4043
+ };
4044
+ }
4045
+ function DropdownMenuContent(props) {
4046
+ return {
4047
+ type: PopoverContent,
4048
+ props: {
4049
+ ...props,
4050
+ role: "menu",
4051
+ "aria-orientation": "vertical",
4052
+ "data-dropdown-menu-content": "",
4053
+ children: {
4054
+ type: RovingFocusGroup,
4055
+ props: {
4056
+ orientation: "vertical",
4057
+ loop: true,
4058
+ children: props.children
4059
+ }
4060
+ }
4061
+ }
4062
+ };
4063
+ }
4064
+ function DropdownMenuItem(props) {
4065
+ const context = useDropdownMenuContext("DropdownMenuItem");
4066
+ const tag = props.as ?? "button";
4067
+ return Primitive({
4068
+ ...props,
4069
+ as: tag,
4070
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
4071
+ role: props.role ?? "menuitem",
4072
+ "data-dropdown-menu-item": "",
4073
+ onClick: (event) => {
4074
+ ;
4075
+ props.onClick?.(event);
4076
+ props.onSelect?.(event);
4077
+ if (event.defaultPrevented) return;
4078
+ if (!props.keepOpen) {
4079
+ context.setOpen(false);
4080
+ }
4081
+ },
4082
+ children: props.children
4083
+ });
4084
+ }
4085
+ function DropdownMenuCheckboxItem(props) {
4086
+ const checkedState = createControllableState({
4087
+ value: props.checked,
4088
+ defaultValue: props.defaultChecked ?? false,
4089
+ onChange: props.onCheckedChange
4090
+ });
4091
+ return {
4092
+ type: DropdownMenuItem,
4093
+ props: {
4094
+ ...props,
4095
+ keepOpen: props.keepOpen ?? true,
4096
+ role: "menuitemcheckbox",
4097
+ "aria-checked": () => checkedState.get(),
4098
+ "data-checked": () => checkedState.get() ? "true" : "false",
4099
+ onSelect: (event) => {
4100
+ props.onSelect?.(event);
4101
+ if (event.defaultPrevented) return;
4102
+ checkedState.set(!checkedState.get());
4103
+ },
4104
+ children: props.children
4105
+ }
4106
+ };
4107
+ }
4108
+ function DropdownMenuRadioGroup(props) {
4109
+ const valueState = createControllableState({
4110
+ value: props.value,
4111
+ defaultValue: props.defaultValue ?? "",
4112
+ onChange: props.onValueChange
4113
+ });
4114
+ const context = {
4115
+ value: () => valueState.get(),
4116
+ setValue: (value) => valueState.set(value)
4117
+ };
4118
+ return {
4119
+ type: DropdownRadioContext.Provider,
4120
+ props: {
4121
+ value: context,
4122
+ children: props.children
4123
+ }
4124
+ };
4125
+ }
4126
+ function DropdownMenuRadioItem(props) {
4127
+ const radio = useContext24(DropdownRadioContext);
4128
+ if (!radio) {
4129
+ throw new Error("DropdownMenuRadioItem must be used inside DropdownMenuRadioGroup");
4130
+ }
4131
+ return {
4132
+ type: DropdownMenuItem,
4133
+ props: {
4134
+ ...props,
4135
+ keepOpen: props.keepOpen ?? true,
4136
+ role: "menuitemradio",
4137
+ "aria-checked": () => radio.value() === props.value,
4138
+ "data-checked": () => radio.value() === props.value ? "true" : "false",
4139
+ onSelect: (event) => {
4140
+ props.onSelect?.(event);
4141
+ if (event.defaultPrevented) return;
4142
+ radio.setValue(props.value);
4143
+ },
4144
+ children: props.children
4145
+ }
4146
+ };
4147
+ }
4148
+ function DropdownMenuSub(props) {
4149
+ const state = createControllableState({
4150
+ value: props.open,
4151
+ defaultValue: props.defaultOpen ?? false,
4152
+ onChange: props.onOpenChange
4153
+ });
4154
+ return {
4155
+ type: PopoverRoot,
4156
+ props: {
4157
+ open: () => state.get(),
4158
+ onOpenChange: (open) => state.set(open),
4159
+ children: props.children
4160
+ }
4161
+ };
4162
+ }
4163
+ function DropdownMenuSubTrigger(props) {
4164
+ return {
4165
+ type: PopoverTrigger,
4166
+ props: {
4167
+ asChild: true,
4168
+ "aria-haspopup": "menu",
4169
+ children: {
4170
+ type: DropdownMenuItem,
4171
+ props: {
4172
+ ...props,
4173
+ keepOpen: true,
4174
+ "aria-haspopup": props["aria-haspopup"] ?? "menu",
4175
+ "aria-expanded": props["aria-expanded"],
4176
+ "data-dropdown-menu-sub-trigger": "",
4177
+ children: props.children
4178
+ }
4179
+ }
4180
+ }
4181
+ };
4182
+ }
4183
+ function DropdownMenuSubContent(props) {
4184
+ return {
4185
+ type: PopoverContent,
4186
+ props: {
4187
+ ...props,
4188
+ role: "menu",
4189
+ side: props.side ?? "right",
4190
+ align: props.align ?? "start",
4191
+ "aria-orientation": "vertical",
4192
+ "data-dropdown-menu-sub-content": "",
4193
+ children: {
4194
+ type: RovingFocusGroup,
4195
+ props: {
4196
+ orientation: "vertical",
4197
+ loop: true,
4198
+ children: props.children
4199
+ }
4200
+ }
4201
+ }
4202
+ };
4203
+ }
4204
+ function DropdownMenuLabel(props) {
4205
+ return {
4206
+ type: "div",
4207
+ props: {
4208
+ ...props,
4209
+ role: props.role ?? "presentation",
4210
+ "data-dropdown-menu-label": "",
4211
+ children: props.children
4212
+ }
4213
+ };
4214
+ }
4215
+ var DropdownMenuSeparator = Separator;
4216
+
4217
+ // src/components/menu/context-menu.ts
4218
+ import { createContext as createContext25, useContext as useContext25 } from "@fictjs/runtime";
4219
+ import { createSignal as createSignal11 } from "@fictjs/runtime/advanced";
4220
+ import { useEventListener as useEventListener7 } from "@fictjs/hooks";
4221
+ var ContextMenuContext = createContext25(null);
4222
+ function useContextMenuContext(component) {
4223
+ const context = useContext25(ContextMenuContext);
4224
+ if (!context) {
4225
+ throw new Error(`${component} must be used inside ContextMenuRoot`);
4226
+ }
4227
+ return context;
4228
+ }
4229
+ function ContextMenuRoot(props) {
4230
+ const state = createControllableState({
4231
+ value: props.open,
4232
+ defaultValue: props.defaultOpen ?? false,
4233
+ onChange: props.onOpenChange
4234
+ });
4235
+ const position = createSignal11({ x: 0, y: 0 });
4236
+ const context = {
4237
+ open: () => state.get(),
4238
+ setOpen: (open) => state.set(open),
4239
+ x: () => position().x,
4240
+ y: () => position().y,
4241
+ setPosition: (x, y) => position({ x, y })
4242
+ };
4243
+ return {
4244
+ type: ContextMenuContext.Provider,
4245
+ props: {
4246
+ value: context,
4247
+ children: props.children
4248
+ }
4249
+ };
4250
+ }
4251
+ function ContextMenuTrigger(props) {
4252
+ const context = useContextMenuContext("ContextMenuTrigger");
4253
+ const tag = props.as ?? "div";
4254
+ const refProp = props.ref;
4255
+ const triggerNode = createSignal11(null);
4256
+ const handleContextMenu = (event) => {
4257
+ ;
4258
+ props.onContextMenu?.(event);
4259
+ if (event.defaultPrevented) return;
4260
+ event.preventDefault();
4261
+ context.setPosition(event.clientX, event.clientY);
4262
+ context.setOpen(true);
4263
+ };
4264
+ const contextMenuListener = useEventListener7(
4265
+ () => triggerNode(),
4266
+ "contextmenu",
4267
+ handleContextMenu,
4268
+ { immediate: false }
4269
+ );
4270
+ const registerRef = (node) => {
4271
+ contextMenuListener.stop();
4272
+ if (typeof refProp === "function") {
4273
+ refProp(node);
4274
+ } else if (refProp) {
4275
+ refProp.current = node;
4276
+ }
4277
+ triggerNode(node);
4278
+ if (node) {
4279
+ contextMenuListener.start();
4280
+ }
4281
+ };
4282
+ return Primitive({
4283
+ ...props,
4284
+ as: tag,
4285
+ ref: registerRef,
4286
+ onContextMenu: handleContextMenu,
4287
+ children: props.children
4288
+ });
4289
+ }
4290
+ function ContextMenuContent(props) {
4291
+ const context = useContextMenuContext("ContextMenuContent");
4292
+ const content = {
4293
+ type: DismissableLayer,
4294
+ props: {
4295
+ onEscapeKeyDown: props.onEscapeKeyDown,
4296
+ onInteractOutside: props.onInteractOutside,
4297
+ onPointerDownOutside: props.onPointerDownOutside,
4298
+ onFocusOutside: props.onFocusOutside,
4299
+ onDismiss: () => {
4300
+ props.onDismiss?.();
4301
+ context.setOpen(false);
4302
+ },
4303
+ children: {
4304
+ type: "div",
4305
+ props: {
4306
+ ...props,
4307
+ forceMount: void 0,
4308
+ portal: void 0,
4309
+ onDismiss: void 0,
4310
+ onEscapeKeyDown: void 0,
4311
+ onInteractOutside: void 0,
4312
+ onPointerDownOutside: void 0,
4313
+ onFocusOutside: void 0,
4314
+ role: "menu",
4315
+ "data-context-menu-content": "",
4316
+ style: {
4317
+ position: "fixed",
4318
+ left: `${context.x()}px`,
4319
+ top: `${context.y()}px`
4320
+ },
4321
+ children: {
4322
+ type: RovingFocusGroup,
4323
+ props: {
4324
+ orientation: "vertical",
4325
+ loop: true,
4326
+ children: props.children
4327
+ }
4328
+ }
4329
+ }
4330
+ }
4331
+ }
4332
+ };
4333
+ const child = () => context.open() || props.forceMount ? content : null;
4334
+ if (props.portal ?? true) {
4335
+ return {
4336
+ type: Portal,
4337
+ props: {
4338
+ children: child
4339
+ }
4340
+ };
4341
+ }
4342
+ return {
4343
+ type: "div",
4344
+ props: {
4345
+ "data-context-menu-inline-container": "",
4346
+ children: child
4347
+ }
4348
+ };
4349
+ }
4350
+ function ContextMenuItem(props) {
4351
+ const context = useContextMenuContext("ContextMenuItem");
4352
+ const tag = props.as ?? "button";
4353
+ return Primitive({
4354
+ ...props,
4355
+ as: tag,
4356
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
4357
+ role: props.role ?? "menuitem",
4358
+ "data-context-menu-item": "",
4359
+ onClick: (event) => {
4360
+ ;
4361
+ props.onClick?.(event);
4362
+ props.onSelect?.(event);
4363
+ if (event.defaultPrevented) return;
4364
+ if (!props.keepOpen) {
4365
+ context.setOpen(false);
4366
+ }
4367
+ },
4368
+ children: props.children
4369
+ });
4370
+ }
4371
+ function ContextMenuSub(props) {
4372
+ const state = createControllableState({
4373
+ value: props.open,
4374
+ defaultValue: props.defaultOpen ?? false,
4375
+ onChange: props.onOpenChange
4376
+ });
4377
+ return {
4378
+ type: PopoverRoot,
4379
+ props: {
4380
+ open: () => state.get(),
4381
+ onOpenChange: (open) => state.set(open),
4382
+ children: props.children
4383
+ }
4384
+ };
4385
+ }
4386
+ function ContextMenuSubTrigger(props) {
4387
+ return {
4388
+ type: PopoverTrigger,
4389
+ props: {
4390
+ asChild: true,
4391
+ "aria-haspopup": "menu",
4392
+ children: {
4393
+ type: ContextMenuItem,
4394
+ props: {
4395
+ ...props,
4396
+ keepOpen: true,
4397
+ "aria-haspopup": props["aria-haspopup"] ?? "menu",
4398
+ "aria-expanded": props["aria-expanded"],
4399
+ "data-context-menu-sub-trigger": "",
4400
+ children: props.children
4401
+ }
4402
+ }
4403
+ }
4404
+ };
4405
+ }
4406
+ function ContextMenuSubContent(props) {
4407
+ return {
4408
+ type: PopoverContent,
4409
+ props: {
4410
+ ...props,
4411
+ role: "menu",
4412
+ side: props.side ?? "right",
4413
+ align: props.align ?? "start",
4414
+ "aria-orientation": "vertical",
4415
+ "data-context-menu-sub-content": "",
4416
+ children: {
4417
+ type: RovingFocusGroup,
4418
+ props: {
4419
+ orientation: "vertical",
4420
+ loop: true,
4421
+ children: props.children
4422
+ }
4423
+ }
4424
+ }
4425
+ };
4426
+ }
4427
+
4428
+ // src/components/menu/menubar.ts
4429
+ import { createContext as createContext26, useContext as useContext26 } from "@fictjs/runtime";
4430
+ import { createSignal as createSignal12 } from "@fictjs/runtime/advanced";
4431
+ var MenubarRootContext = createContext26(null);
4432
+ var MenubarMenuContext = createContext26(null);
4433
+ function useMenubarRootContext(component) {
4434
+ const context = useContext26(MenubarRootContext);
4435
+ if (!context) {
4436
+ throw new Error(`${component} must be used inside MenubarRoot`);
4437
+ }
4438
+ return context;
4439
+ }
4440
+ function useMenubarMenuContext(component) {
4441
+ const context = useContext26(MenubarMenuContext);
4442
+ if (!context) {
4443
+ throw new Error(`${component} must be used inside MenubarMenu`);
4444
+ }
4445
+ return context;
4446
+ }
4447
+ function MenubarRoot(props) {
4448
+ const activeMenuSignal = createSignal12(null);
4449
+ const context = {
4450
+ activeMenu: () => activeMenuSignal(),
4451
+ setActiveMenu: (id) => activeMenuSignal(id)
4452
+ };
4453
+ return {
4454
+ type: MenubarRootContext.Provider,
4455
+ props: {
4456
+ value: context,
4457
+ children: {
4458
+ type: "div",
4459
+ props: {
4460
+ ...props,
4461
+ role: "menubar",
4462
+ "data-menubar-root": "",
4463
+ children: {
4464
+ type: RovingFocusGroup,
4465
+ props: {
4466
+ orientation: "horizontal",
4467
+ loop: true,
4468
+ children: props.children
4469
+ }
4470
+ }
4471
+ }
4472
+ }
4473
+ }
4474
+ };
4475
+ }
4476
+ function MenubarMenu(props) {
4477
+ const id = useId(props.value, "menubar-menu");
4478
+ return {
4479
+ type: MenubarMenuContext.Provider,
4480
+ props: {
4481
+ value: { id },
4482
+ children: {
4483
+ type: "div",
4484
+ props: {
4485
+ "data-menubar-menu": id,
4486
+ children: props.children
4487
+ }
4488
+ }
4489
+ }
4490
+ };
4491
+ }
4492
+ function MenubarTrigger(props) {
4493
+ const root = useMenubarRootContext("MenubarTrigger");
4494
+ const menu = useMenubarMenuContext("MenubarTrigger");
4495
+ const tag = props.as ?? "button";
4496
+ const open = () => root.activeMenu() === menu.id;
4497
+ return Primitive({
4498
+ ...props,
4499
+ as: tag,
4500
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
4501
+ role: "menuitem",
4502
+ "aria-haspopup": "menu",
4503
+ "aria-expanded": open,
4504
+ "data-state": () => open() ? "open" : "closed",
4505
+ "data-menubar-trigger": menu.id,
4506
+ onClick: (event) => {
4507
+ ;
4508
+ props.onClick?.(event);
4509
+ if (event.defaultPrevented) return;
4510
+ root.setActiveMenu(open() ? null : menu.id);
4511
+ },
4512
+ onMouseOver: (event) => {
4513
+ ;
4514
+ props.onMouseOver?.(event);
4515
+ if (event.defaultPrevented) return;
4516
+ root.setActiveMenu(menu.id);
4517
+ },
4518
+ children: props.children
4519
+ });
4520
+ }
4521
+ function MenubarContent(props) {
4522
+ const root = useMenubarRootContext("MenubarContent");
4523
+ const menu = useMenubarMenuContext("MenubarContent");
4524
+ const open = () => root.activeMenu() === menu.id;
4525
+ return {
4526
+ type: "div",
4527
+ props: {
4528
+ "data-menubar-content-wrapper": menu.id,
4529
+ children: () => open() || props.forceMount ? {
4530
+ type: "div",
4531
+ props: {
4532
+ ...props,
4533
+ forceMount: void 0,
4534
+ role: "menu",
4535
+ "data-menubar-content": menu.id,
4536
+ children: props.children
4537
+ }
4538
+ } : null
4539
+ }
4540
+ };
4541
+ }
4542
+ function MenubarItem(props) {
4543
+ const root = useMenubarRootContext("MenubarItem");
4544
+ const tag = props.as ?? "button";
4545
+ return Primitive({
4546
+ ...props,
4547
+ as: tag,
4548
+ type: !props.asChild && tag === "button" ? props.type ?? "button" : props.type,
4549
+ role: props.role ?? "menuitem",
4550
+ "data-menubar-item": "",
4551
+ onClick: (event) => {
4552
+ ;
4553
+ props.onClick?.(event);
4554
+ props.onSelect?.(event);
4555
+ if (!event.defaultPrevented) {
4556
+ root.setActiveMenu(null);
4557
+ }
4558
+ },
4559
+ children: props.children
4560
+ });
4561
+ }
4562
+
4563
+ // src/components/feedback/toast.ts
4564
+ import { createContext as createContext27, onDestroy as onDestroy5, useContext as useContext27 } from "@fictjs/runtime";
4565
+ import { createSignal as createSignal13 } from "@fictjs/runtime/advanced";
4566
+ import { useDebounceFn as useDebounceFn3 } from "@fictjs/hooks";
4567
+ var ToastContext = createContext27(null);
4568
+ function useToastContext(component) {
4569
+ const context = useContext27(ToastContext);
4570
+ if (!context) {
4571
+ throw new Error(`${component} must be used inside ToastProvider`);
4572
+ }
4573
+ return context;
4574
+ }
4575
+ function ToastProvider(props) {
4576
+ const toastsSignal = createSignal13([]);
4577
+ const timers = /* @__PURE__ */ new Map();
4578
+ const dismiss = (id) => {
4579
+ toastsSignal(toastsSignal().filter((toast) => toast.id !== id));
4580
+ const timer = timers.get(id);
4581
+ if (timer) {
4582
+ timer.cancel();
4583
+ timers.delete(id);
4584
+ }
4585
+ };
4586
+ const show = (toast) => {
4587
+ const id = toast.id ?? createId("toast");
4588
+ const existingTimer = timers.get(id);
4589
+ existingTimer?.cancel();
4590
+ timers.delete(id);
4591
+ const nextToast = {
4592
+ id,
4593
+ title: toast.title,
4594
+ description: toast.description,
4595
+ duration: toast.duration
4596
+ };
4597
+ toastsSignal([...toastsSignal(), nextToast]);
4598
+ const timer = useDebounceFn3(
4599
+ () => {
4600
+ dismiss(id);
4601
+ },
4602
+ toast.duration ?? props.duration ?? 5e3
4603
+ );
4604
+ timer.run();
4605
+ timers.set(id, timer);
4606
+ return id;
4607
+ };
4608
+ onDestroy5(() => {
4609
+ for (const timer of timers.values()) {
4610
+ timer.cancel();
4611
+ }
4612
+ timers.clear();
4613
+ });
4614
+ const context = {
4615
+ toasts: () => toastsSignal(),
4616
+ show,
4617
+ dismiss,
4618
+ duration: () => props.duration ?? 5e3
4619
+ };
4620
+ return {
4621
+ type: ToastContext.Provider,
4622
+ props: {
4623
+ value: context,
4624
+ children: props.children
4625
+ }
4626
+ };
4627
+ }
4628
+ function useToast() {
4629
+ const context = useToastContext("useToast");
4630
+ return {
4631
+ show: context.show,
4632
+ dismiss: context.dismiss,
4633
+ toasts: context.toasts
4634
+ };
4635
+ }
4636
+ function ToastViewport(props) {
4637
+ const context = useToastContext("ToastViewport");
4638
+ return {
4639
+ type: "div",
4640
+ props: {
4641
+ ...props,
4642
+ role: "region",
4643
+ "aria-live": "polite",
4644
+ "aria-relevant": "additions text",
4645
+ "data-toast-viewport": "",
4646
+ children: [
4647
+ props.children,
4648
+ {
4649
+ type: "div",
4650
+ props: {
4651
+ children: () => context.toasts().map((toast) => ({
4652
+ type: ToastRoot,
4653
+ props: {
4654
+ id: toast.id,
4655
+ title: toast.title,
4656
+ description: toast.description,
4657
+ duration: toast.duration ?? context.duration()
4658
+ }
4659
+ }))
4660
+ }
4661
+ }
4662
+ ]
4663
+ }
4664
+ };
4665
+ }
4666
+ function ToastRoot(props) {
4667
+ const context = useContext27(ToastContext);
4668
+ const close = () => {
4669
+ if (props.id && context) {
4670
+ context.dismiss(props.id);
4671
+ }
4672
+ props.onOpenChange?.(false);
4673
+ };
4674
+ return {
4675
+ type: "div",
4676
+ props: {
4677
+ ...props,
4678
+ role: props.role ?? "status",
4679
+ "data-toast-root": "",
4680
+ children: [
4681
+ props.title ? { type: ToastTitle, props: { children: props.title } } : null,
4682
+ props.description ? { type: ToastDescription, props: { children: props.description } } : null,
4683
+ props.children,
4684
+ {
4685
+ type: ToastClose,
4686
+ props: {
4687
+ onClick: () => close(),
4688
+ children: props["data-close-label"] ?? "Dismiss"
4689
+ }
4690
+ }
4691
+ ]
4692
+ }
4693
+ };
4694
+ }
4695
+ function ToastTitle(props) {
4696
+ return {
4697
+ type: "div",
4698
+ props: {
4699
+ ...props,
4700
+ "data-toast-title": "",
4701
+ children: props.children
4702
+ }
4703
+ };
4704
+ }
4705
+ function ToastDescription(props) {
4706
+ return {
4707
+ type: "div",
4708
+ props: {
4709
+ ...props,
4710
+ "data-toast-description": "",
4711
+ children: props.children
4712
+ }
4713
+ };
4714
+ }
4715
+ function ToastAction(props) {
4716
+ return {
4717
+ type: "button",
4718
+ props: {
4719
+ ...props,
4720
+ type: "button",
4721
+ "data-toast-action": "",
4722
+ "aria-label": props.altText,
4723
+ children: [props.children, { type: VisuallyHidden, props: { children: props.altText } }]
4724
+ }
4725
+ };
4726
+ }
4727
+ function ToastClose(props) {
4728
+ const tag = props.as ?? "button";
4729
+ return Primitive({
4730
+ ...props,
4731
+ as: tag,
4732
+ type: !props.asChild && tag === "button" ? "button" : props.type,
4733
+ "data-toast-close": "",
4734
+ onClick: (event) => {
4735
+ props.onClick?.(event);
4736
+ },
4737
+ children: props.children ?? "Close"
4738
+ });
4739
+ }
4740
+ export {
4741
+ AccessibleIcon,
4742
+ AccordionContent,
4743
+ AccordionItem,
4744
+ AccordionRoot,
4745
+ AccordionTrigger,
4746
+ AlertDialogAction,
4747
+ AlertDialogCancel,
4748
+ AlertDialogContent,
4749
+ AlertDialogDescription,
4750
+ AlertDialogOverlay,
4751
+ AlertDialogPortal,
4752
+ AlertDialogRoot,
4753
+ AlertDialogTitle,
4754
+ AlertDialogTrigger,
4755
+ Announce,
4756
+ AspectRatio,
4757
+ Calendar,
4758
+ CalendarGrid,
4759
+ CalendarHeader,
4760
+ CalendarNextButton,
4761
+ CalendarPrevButton,
4762
+ CalendarRoot,
4763
+ CalendarTitle,
4764
+ Checkbox,
4765
+ CollapsibleContent,
4766
+ CollapsibleRoot,
4767
+ CollapsibleTrigger,
4768
+ ComboboxInput,
4769
+ ComboboxItem,
4770
+ ComboboxList,
4771
+ ComboboxRoot,
4772
+ CommandPaletteClose,
4773
+ CommandPaletteContent,
4774
+ CommandPaletteEmpty,
4775
+ CommandPaletteGroup,
4776
+ CommandPaletteInput,
4777
+ CommandPaletteItem,
4778
+ CommandPaletteList,
4779
+ CommandPaletteRoot,
4780
+ CommandPaletteSeparator,
4781
+ CommandPaletteTrigger,
4782
+ ContextMenuContent,
4783
+ ContextMenuItem,
4784
+ ContextMenuRoot,
4785
+ ContextMenuSub,
4786
+ ContextMenuSubContent,
4787
+ ContextMenuSubTrigger,
4788
+ ContextMenuTrigger,
4789
+ DatePickerCalendar,
4790
+ DatePickerContent,
4791
+ DatePickerRoot,
4792
+ DatePickerTrigger,
4793
+ DatePickerValue,
4794
+ DialogClose,
4795
+ DialogContent,
4796
+ DialogDescription,
4797
+ DialogOverlay,
4798
+ DialogPortal,
4799
+ DialogRoot,
4800
+ DialogTitle,
4801
+ DialogTrigger,
4802
+ DismissableLayer,
4803
+ DropdownMenuCheckboxItem,
4804
+ DropdownMenuContent,
4805
+ DropdownMenuItem,
4806
+ DropdownMenuLabel,
4807
+ DropdownMenuRadioGroup,
4808
+ DropdownMenuRadioItem,
4809
+ DropdownMenuRoot,
4810
+ DropdownMenuSeparator,
4811
+ DropdownMenuSub,
4812
+ DropdownMenuSubContent,
4813
+ DropdownMenuSubTrigger,
4814
+ DropdownMenuTrigger,
4815
+ FocusScope,
4816
+ FocusTrap,
4817
+ FocusVisible,
4818
+ Form,
4819
+ FormControl,
4820
+ FormDescription,
4821
+ FormField,
4822
+ FormLabel,
4823
+ FormMessage,
4824
+ HoverCardContent,
4825
+ HoverCardRoot,
4826
+ HoverCardTrigger,
4827
+ IdProvider,
4828
+ KeyboardModeProvider,
4829
+ Label,
4830
+ LiveRegionProvider,
4831
+ MenubarContent,
4832
+ MenubarItem,
4833
+ MenubarMenu,
4834
+ MenubarRoot,
4835
+ MenubarTrigger,
4836
+ Meter,
4837
+ NavigationMenuContent,
4838
+ NavigationMenuIndicator,
4839
+ NavigationMenuItem,
4840
+ NavigationMenuLink,
4841
+ NavigationMenuList,
4842
+ NavigationMenuRoot,
4843
+ NavigationMenuTrigger,
4844
+ NavigationMenuViewport,
4845
+ PopoverClose,
4846
+ PopoverContent,
4847
+ PopoverRoot,
4848
+ PopoverTrigger,
4849
+ PopperAnchor,
4850
+ PopperArrow,
4851
+ PopperContent,
4852
+ PopperRoot,
4853
+ Portal,
4854
+ PortalHost,
4855
+ Presence,
4856
+ Primitive,
4857
+ PrimitiveElements,
4858
+ Progress,
4859
+ RadioGroup,
4860
+ RadioItem,
4861
+ RangeSlider,
4862
+ ResizableHandle,
4863
+ ResizablePanel,
4864
+ ResizablePanelGroup,
4865
+ RovingFocusGroup,
4866
+ RovingFocusItem,
4867
+ ScrollArea,
4868
+ ScrollAreaScrollbar,
4869
+ ScrollAreaThumb,
4870
+ ScrollAreaViewport,
4871
+ ScrollLock,
4872
+ SelectContent,
4873
+ SelectItem,
4874
+ SelectRoot,
4875
+ SelectTrigger,
4876
+ SelectValue,
4877
+ Separator,
4878
+ Skeleton,
4879
+ Slider,
4880
+ Slot,
4881
+ Switch,
4882
+ SwitchThumb,
4883
+ TabsContent,
4884
+ TabsList,
4885
+ TabsRoot,
4886
+ TabsTrigger,
4887
+ ToastAction,
4888
+ ToastClose,
4889
+ ToastDescription,
4890
+ ToastProvider,
4891
+ ToastRoot,
4892
+ ToastTitle,
4893
+ ToastViewport,
4894
+ Toggle,
4895
+ ToggleGroup,
4896
+ ToggleGroupItem,
4897
+ TooltipContent,
4898
+ TooltipProvider,
4899
+ TooltipRoot,
4900
+ TooltipTrigger,
4901
+ VisuallyHidden,
4902
+ useAnnouncer,
4903
+ useId,
4904
+ useKeyboardMode,
4905
+ useToast
4906
+ };
4907
+ //# sourceMappingURL=index.js.map