@takeoff-ui/react-spar 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,12 +1,14 @@
1
- import { createContext, Children, isValidElement, useMemo, useRef, useState, useCallback, useEffect, createElement, useContext, Fragment as Fragment$1 } from 'react';
1
+ import { createContext, Children, isValidElement, useMemo, useRef, useState, useCallback, useEffect, useId, createElement, useContext, Fragment as Fragment$1 } from 'react';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
- import { Accordion as Accordion$1, AccordionContent as AccordionContent$1, useAccordionItemContext, AccordionTrigger as AccordionTrigger$1, AccordionHeader as AccordionHeader$1, AccordionItem as AccordionItem$1, Breadcrumb as Breadcrumb$1, BreadcrumbSeparator as BreadcrumbSeparator$1, BreadcrumbPage as BreadcrumbPage$1, BreadcrumbLink as BreadcrumbLink$1, BreadcrumbItem as BreadcrumbItem$1, BreadcrumbList as BreadcrumbList$1, Checkbox as Checkbox$1, Dialog as Dialog$1, DialogClose as DialogClose$1, DialogDescription as DialogDescription$1, DialogTitle as DialogTitle$1, DialogContent, DialogOverlay as DialogOverlay$1, DialogTrigger as DialogTrigger$1, Field as Field$1, FieldErrorMessage as FieldErrorMessage$1, FieldDescription as FieldDescription$1, useFieldContext, FieldLabel as FieldLabel$1, Input as Input$1, useInputContext, InputField as InputField$1, Radio as Radio$1, RadioItem as RadioItem$1, Popover as Popover$1, PopoverClose as PopoverClose$1, PopoverArrow as PopoverArrow$1, PopoverContent as PopoverContent$1, PopoverTrigger as PopoverTrigger$1, Select as Select$1, SelectSeparator as SelectSeparator$1, SelectLabel as SelectLabel$1, SelectGroup as SelectGroup$1, SelectItem as SelectItem$1, useSelectContext, SelectContent as SelectContent$1, SelectTrigger as SelectTrigger$1, Switch as Switch$1, Tabs as Tabs$1, TabsContent as TabsContent$1, TabsTrigger as TabsTrigger$1, TabsList as TabsList$1, Tooltip as Tooltip$1, TooltipArrow as TooltipArrow$1, TooltipContent as TooltipContent$1, TooltipTrigger as TooltipTrigger$1, TooltipProvider as TooltipProvider$1, Button as Button$1, Label as Label$1, Toast as Toast$1, Toaster as Toaster$1 } from '@turkish-technology/spar';
3
+ import { Accordion as Accordion$1, AccordionContent as AccordionContent$1, useAccordionItemContext, AccordionTrigger as AccordionTrigger$1, AccordionHeader as AccordionHeader$1, AccordionItem as AccordionItem$1, Breadcrumb as Breadcrumb$1, BreadcrumbSeparator as BreadcrumbSeparator$1, BreadcrumbPage as BreadcrumbPage$1, BreadcrumbLink as BreadcrumbLink$1, BreadcrumbItem as BreadcrumbItem$1, BreadcrumbList as BreadcrumbList$1, Checkbox as Checkbox$1, Dialog as Dialog$1, DialogClose as DialogClose$1, DialogDescription as DialogDescription$1, DialogTitle as DialogTitle$1, DialogContent, DialogOverlay as DialogOverlay$1, DialogTrigger as DialogTrigger$1, DropdownMenu, DropdownMenuArrow, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuGroup, DropdownMenuItem, DropdownMenuViewport, useDropdownMenuContext, DropdownMenuContent, DropdownMenuTrigger, Field as Field$1, FieldErrorMessage as FieldErrorMessage$1, FieldDescription as FieldDescription$1, useFieldContext, FieldLabel as FieldLabel$1, Input as Input$1, useInputContext, InputField as InputField$1, Radio as Radio$1, RadioItem as RadioItem$1, Popover as Popover$1, PopoverClose as PopoverClose$1, PopoverArrow as PopoverArrow$1, PopoverContent as PopoverContent$1, PopoverTrigger as PopoverTrigger$1, useOptionalFieldContext, Select as Select$1, SelectArrow as SelectArrow$1, SelectSeparator as SelectSeparator$1, SelectLabel as SelectLabel$1, SelectGroup as SelectGroup$1, SelectItem as SelectItem$1, SelectViewport as SelectViewport$1, useSelectContext, SelectContent as SelectContent$1, SelectTrigger as SelectTrigger$1, Switch as Switch$1, Tabs as Tabs$1, TabsContent as TabsContent$1, TabsTrigger as TabsTrigger$1, TabsList as TabsList$1, Tooltip as Tooltip$1, TooltipArrow as TooltipArrow$1, TooltipContent as TooltipContent$1, TooltipTrigger as TooltipTrigger$1, TooltipProvider as TooltipProvider$1, Button as Button$1, Label as Label$1, Toast as Toast$1, Toaster as Toaster$1 } from '@turkish-technology/spar';
4
4
  export { createToaster } from '@turkish-technology/spar';
5
5
  import { clsx } from 'clsx';
6
6
  import { ChevronBottomIconOutlinedRounded } from '@takeoff-icons/react/chevron-bottom';
7
7
  import { ChevronTopIconOutlinedRounded } from '@takeoff-icons/react/chevron-top';
8
- import { useReactTable, getPaginationRowModel, getExpandedRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel, functionalUpdate, flexRender } from '@tanstack/react-table';
9
8
  import { ChevronRightIconOutlinedRounded } from '@takeoff-icons/react/chevron-right';
9
+ import { CheckIconOutlinedRounded } from '@takeoff-icons/react/check';
10
+ import { CloseIconOutlinedRounded } from '@takeoff-icons/react/close';
11
+ import { useReactTable, getPaginationRowModel, getExpandedRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel, functionalUpdate, flexRender } from '@tanstack/react-table';
10
12
  import { SwapIconOutlinedRounded } from '@takeoff-icons/react/swap';
11
13
  import { SearchIconOutlinedRounded } from '@takeoff-icons/react/search';
12
14
  import { ArrowLeftIconOutlinedRounded } from '@takeoff-icons/react/arrow-left';
@@ -145,6 +147,10 @@ var resolveDisclosureIndicator = (children, isOpen) => {
145
147
  if (typeof children === "function") return children({ isOpen });
146
148
  return children ?? (isOpen ? DEFAULT_DISCLOSURE_COLLAPSE_ICON : DEFAULT_DISCLOSURE_EXPAND_ICON);
147
149
  };
150
+ var renderPointerArrow = () => /* @__PURE__ */ jsxs(Fragment, { children: [
151
+ /* @__PURE__ */ jsx("polygon", { className: "tk-arrow-border", points: "0,0 5,5 10,0" }),
152
+ /* @__PURE__ */ jsx("polygon", { className: "tk-arrow-fill", points: "-0.086,-1.5 5,3.586 10.086,-1.5" })
153
+ ] });
148
154
 
149
155
  // src/components/accordion/base.ts
150
156
  var AccordionBase = createComponentBase({
@@ -195,6 +201,37 @@ function createSafeContext(displayName) {
195
201
  };
196
202
  return [Provider, useSafeContext];
197
203
  }
204
+ var resolveStaticWidth = (mode) => {
205
+ if (mode === "trigger" || mode === "content") return void 0;
206
+ return typeof mode === "number" ? `${mode}px` : mode;
207
+ };
208
+ var useContentWidthStyle = (mode, triggerRef) => {
209
+ const [triggerWidth, setTriggerWidth] = useState(null);
210
+ useEffect(() => {
211
+ if (mode !== "trigger") return;
212
+ const node = triggerRef.current;
213
+ if (!node) return;
214
+ const measure = () => setTriggerWidth(Math.round(node.getBoundingClientRect().width));
215
+ measure();
216
+ let frame = 0;
217
+ const observer = new ResizeObserver(() => {
218
+ cancelAnimationFrame(frame);
219
+ frame = requestAnimationFrame(measure);
220
+ });
221
+ observer.observe(node);
222
+ return () => {
223
+ cancelAnimationFrame(frame);
224
+ observer.disconnect();
225
+ };
226
+ }, [mode, triggerRef]);
227
+ return useMemo(() => {
228
+ if (mode === "trigger") {
229
+ return triggerWidth != null ? { width: triggerWidth } : void 0;
230
+ }
231
+ const staticWidth = resolveStaticWidth(mode);
232
+ return staticWidth != null ? { width: staticWidth } : void 0;
233
+ }, [mode, triggerWidth]);
234
+ };
198
235
  function useControllableState(controlledValue, defaultValue, onChange) {
199
236
  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
200
237
  const { current: isControlled } = useRef(controlledValue !== void 0);
@@ -568,7 +605,6 @@ var [BreadcrumbProvider] = createSafeContext("BreadcrumbProvider");
568
605
  // src/components/breadcrumb/defaults.ts
569
606
  var DEFAULT_SIZE3 = "base";
570
607
  var DEFAULT_TYPE2 = "basic";
571
- var DEFAULT_SEPARATOR_VARIANT = "chevron";
572
608
  var Breadcrumb = (props) => {
573
609
  const theme = useComponentTheme("Breadcrumb");
574
610
  const { rootAttrs, rest } = composeRootAttrs(BreadcrumbBase, props, theme, {
@@ -610,17 +646,11 @@ var BreadcrumbPage = (props) => {
610
646
  return /* @__PURE__ */ jsx(BreadcrumbPage$1, { ...spar, ref, ...rootAttrs, children });
611
647
  };
612
648
  BreadcrumbPage.displayName = "Breadcrumb.Page";
613
- var DEFAULT_SEPARATOR_ICON = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M6 4L10 8L6 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
614
649
  var BreadcrumbSeparator = (props) => {
615
650
  const theme = useComponentTheme("BreadcrumbSeparator");
616
- const { rootAttrs, rest } = composeRootAttrs(BreadcrumbSeparatorBase, props, theme, {
617
- stateAttrs: ({ variant: variant2 = DEFAULT_SEPARATOR_VARIANT }) => ({
618
- "data-variant": variant2
619
- })
620
- });
621
- const { variant = DEFAULT_SEPARATOR_VARIANT, children, ref, ...spar } = rest;
622
- const fallback = variant === "chevron" ? DEFAULT_SEPARATOR_ICON : null;
623
- return /* @__PURE__ */ jsx(BreadcrumbSeparator$1, { ...spar, ref, ...rootAttrs, children: children ?? fallback });
651
+ const { rootAttrs, rest } = composeRootAttrs(BreadcrumbSeparatorBase, props, theme);
652
+ const { children, ref, ...spar } = rest;
653
+ return /* @__PURE__ */ jsx(BreadcrumbSeparator$1, { ...spar, ref, ...rootAttrs, children: children ?? /* @__PURE__ */ jsx(ChevronRightIconOutlinedRounded, { "aria-hidden": "true", focusable: "false" }) });
624
654
  };
625
655
  BreadcrumbSeparator.displayName = "Breadcrumb.Separator";
626
656
 
@@ -849,56 +879,47 @@ var Checkbox = (props) => {
849
879
  // Visual props are consumed via `stateAttrs`; destructured to keep them
850
880
  // off the rendered DOM where they would leak as raw HTML attributes.
851
881
  size: _size,
852
- // `invalid` is forwarded to Spar as `invalid` (same name).
853
- invalid = false,
854
882
  // takeoff-spar tri-state vocabulary; mapped to Spar's `CheckedState` below.
855
883
  checked,
856
884
  defaultChecked,
857
885
  indeterminate = false,
858
886
  onChange,
859
- // Behavior props owned by Spar — defaults are restated here so they also
860
- // flow into the context for compound sub-components (asterisk on Label).
861
- disabled = false,
862
- readOnly = false,
863
- required = false,
864
887
  children,
865
888
  ref,
889
+ // `invalid`, `disabled`, `readOnly` and `required` are intentionally NOT
890
+ // destructured (so no eager `= false` default is applied) — they flow to
891
+ // Spar via `...sparProps` untouched. Defaulting them here would turn an
892
+ // omitted prop into an explicit `false`, defeating Spar's
893
+ // `prop ?? fieldCtx?.x` inheritance and silently overriding a wrapping
894
+ // `<Field disabled>`. Their resolved values are read back off Spar's
895
+ // render-prop `state` below for the compound context. See Radio/Input/
896
+ // Select wrappers for the same pass-through pattern.
866
897
  ...sparProps
867
898
  } = rest;
868
899
  const sparChecked = indeterminate ? "indeterminate" : checked;
869
900
  const sparDefaultChecked = indeterminate ? "indeterminate" : defaultChecked;
870
901
  const handleSparChange = onChange ? (next) => onChange(next === true) : void 0;
871
- return /* @__PURE__ */ jsx(
872
- Checkbox$1,
902
+ return /* @__PURE__ */ jsx(Checkbox$1, { ...sparProps, checked: sparChecked, defaultChecked: sparDefaultChecked, onChange: handleSparChange, ref, ...rootAttrs, children: (state) => /* @__PURE__ */ jsx(
903
+ CheckboxProvider,
873
904
  {
874
- ...sparProps,
875
- checked: sparChecked,
876
- defaultChecked: sparDefaultChecked,
877
- onChange: handleSparChange,
878
- disabled,
879
- readOnly,
880
- required,
881
- invalid,
882
- ref,
883
- ...rootAttrs,
884
- children: (state) => /* @__PURE__ */ jsx(
885
- CheckboxProvider,
886
- {
887
- value: {
888
- classNames,
889
- slotProps,
890
- required,
891
- invalid,
892
- disabled: state.disabled,
893
- readOnly: state.readOnly,
894
- checked: state.checked === true,
895
- indeterminate: state.checked === "indeterminate"
896
- },
897
- children: typeof children === "function" ? children(state) : children
898
- }
899
- )
905
+ value: {
906
+ classNames,
907
+ slotProps,
908
+ // Read the *resolved* behavior state off Spar's render-prop so the
909
+ // compound context reflects Field-inherited values, not the raw
910
+ // props. `state.required` / `state.invalid` already fold in
911
+ // `fieldCtx`, so `<Field disabled>` / `<Field invalid>` reach the
912
+ // Label asterisk and slotted styling correctly.
913
+ required: state.required,
914
+ invalid: state.invalid,
915
+ disabled: state.disabled,
916
+ readOnly: state.readOnly,
917
+ checked: state.checked === true,
918
+ indeterminate: state.checked === "indeterminate"
919
+ },
920
+ children: typeof children === "function" ? children(state) : children
900
921
  }
901
- );
922
+ ) });
902
923
  };
903
924
  Checkbox.displayName = "Checkbox";
904
925
  var CheckboxIndicator = (props) => {
@@ -1399,6 +1420,182 @@ var Dialog2 = Object.assign(Dialog, {
1399
1420
  Close: DialogClose
1400
1421
  });
1401
1422
 
1423
+ // src/components/divider/base.ts
1424
+ var DividerBase = createComponentBase({
1425
+ name: "Divider",
1426
+ slots: ["root", "label"],
1427
+ classes: {
1428
+ root: "tk-divider",
1429
+ label: "tk-divider-label"
1430
+ }
1431
+ });
1432
+
1433
+ // src/components/divider/defaults.ts
1434
+ var DEFAULT_ORIENTATION = "horizontal";
1435
+ var DEFAULT_APPEARANCE5 = "solid";
1436
+ var DEFAULT_ALIGN = "center";
1437
+ var hasRenderableDividerLabel = (node) => Array.isArray(node) ? node.some(hasRenderableDividerLabel) : isRenderableNode(node);
1438
+ var Divider = (props) => {
1439
+ const theme = useComponentTheme("Divider");
1440
+ const { rootAttrs, rest } = composeRootAttrs(DividerBase, props, theme, {
1441
+ // role/aria-orientation live here alongside the data-* hooks so consumer
1442
+ // slotProps cannot silently strip the separator semantics.
1443
+ stateAttrs: ({ orientation: orientation2 = DEFAULT_ORIENTATION, appearance = DEFAULT_APPEARANCE5, align = DEFAULT_ALIGN, decorative: decorative2 = false }) => ({
1444
+ "role": decorative2 ? "none" : "separator",
1445
+ "data-orientation": orientation2,
1446
+ "data-type": appearance,
1447
+ "data-align": align
1448
+ })
1449
+ });
1450
+ const { orientation = DEFAULT_ORIENTATION, appearance: _appearance, align: _align, decorative = false, children, ref, ...nativeProps } = rest;
1451
+ const labelSlotAttrs = buildSlotAttrs(DividerBase.getSlotProps("label"), "label", {
1452
+ themeSlotProps: theme?.slotProps,
1453
+ themeClassNames: theme?.classNames,
1454
+ instanceSlotProps: props.slotProps,
1455
+ instanceClassNames: props.classNames
1456
+ });
1457
+ return /* @__PURE__ */ jsx("div", { ...nativeProps, ...rootAttrs, "aria-orientation": decorative ? void 0 : orientation, ref, children: hasRenderableDividerLabel(children) && /* @__PURE__ */ jsx("span", { ...labelSlotAttrs, children }) });
1458
+ };
1459
+ Divider.displayName = "Divider";
1460
+
1461
+ // src/components/dropdown/context.ts
1462
+ var [DropdownProvider, useDropdownOwnContext] = createSafeContext("DropdownProvider");
1463
+
1464
+ // src/components/dropdown/defaults.ts
1465
+ var DEFAULT_SIZE7 = "base";
1466
+ var DEFAULT_CONTENT_WIDTH = "content";
1467
+ var Dropdown = (props) => {
1468
+ const theme = useComponentTheme("Dropdown");
1469
+ const merged = { ...theme?.defaultProps, ...props };
1470
+ const { size = DEFAULT_SIZE7, contentWidth = DEFAULT_CONTENT_WIDTH, children, ...sparProps } = merged;
1471
+ return /* @__PURE__ */ jsx(DropdownProvider, { value: { size, contentWidth }, children: /* @__PURE__ */ jsx(DropdownMenu, { ...sparProps, children }) });
1472
+ };
1473
+ Dropdown.displayName = "Dropdown";
1474
+
1475
+ // src/components/dropdown/base.ts
1476
+ var DropdownTriggerBase = createComponentBase({
1477
+ name: "DropdownTrigger",
1478
+ slots: ["root"],
1479
+ classes: { root: "tk-dropdown-trigger" }
1480
+ });
1481
+ var DropdownContentBase = createComponentBase({
1482
+ name: "DropdownContent",
1483
+ slots: ["root"],
1484
+ classes: { root: "tk-dropdown-content" }
1485
+ });
1486
+ var DropdownViewportBase = createComponentBase({
1487
+ name: "DropdownViewport",
1488
+ slots: ["root"],
1489
+ classes: { root: "tk-dropdown-viewport" }
1490
+ });
1491
+ var DropdownItemBase = createComponentBase({
1492
+ name: "DropdownItem",
1493
+ slots: ["root"],
1494
+ classes: { root: "tk-dropdown-item" }
1495
+ });
1496
+ var DropdownGroupBase = createComponentBase({
1497
+ name: "DropdownGroup",
1498
+ slots: ["root"],
1499
+ classes: { root: "tk-dropdown-group" }
1500
+ });
1501
+ var DropdownLabelBase = createComponentBase({
1502
+ name: "DropdownLabel",
1503
+ slots: ["root"],
1504
+ classes: { root: "tk-dropdown-label" }
1505
+ });
1506
+ var DropdownSeparatorBase = createComponentBase({
1507
+ name: "DropdownSeparator",
1508
+ slots: ["root"],
1509
+ classes: { root: "tk-dropdown-separator" }
1510
+ });
1511
+ var DropdownArrowBase = createComponentBase({
1512
+ name: "DropdownArrow",
1513
+ slots: ["root"],
1514
+ classes: { root: "tk-dropdown-arrow" }
1515
+ });
1516
+ var DropdownArrow = (props) => {
1517
+ const theme = useComponentTheme("DropdownArrow");
1518
+ const { rootAttrs, rest } = composeRootAttrs(DropdownArrowBase, props, theme);
1519
+ const { children, ref, ...sparProps } = rest;
1520
+ return /* @__PURE__ */ jsx(DropdownMenuArrow, { ...sparProps, ...rootAttrs, ref, children: children ?? renderPointerArrow() });
1521
+ };
1522
+ DropdownArrow.displayName = "Dropdown.Arrow";
1523
+ var DropdownContent = (props) => {
1524
+ const theme = useComponentTheme("DropdownContent");
1525
+ const { size, contentWidth } = useDropdownOwnContext("Dropdown.Content");
1526
+ const { triggerRef } = useDropdownMenuContext();
1527
+ const widthStyle = useContentWidthStyle(contentWidth, triggerRef);
1528
+ const { rootAttrs, rest } = composeRootAttrs(DropdownContentBase, props, theme, {
1529
+ stateAttrs: () => ({
1530
+ "data-size": size
1531
+ })
1532
+ });
1533
+ const { children, ref, style: userStyle, ...sparProps } = rest;
1534
+ const { style: rootStyle, ...rootRest } = rootAttrs;
1535
+ const mergedStyle = widthStyle || rootStyle || userStyle ? { ...widthStyle, ...rootStyle, ...userStyle } : void 0;
1536
+ return /* @__PURE__ */ jsx(DropdownMenuContent, { ...sparProps, ...rootRest, ref, style: mergedStyle, children });
1537
+ };
1538
+ DropdownContent.displayName = "Dropdown.Content";
1539
+ var DropdownGroup = (props) => {
1540
+ const theme = useComponentTheme("DropdownGroup");
1541
+ const { rootAttrs, rest } = composeRootAttrs(DropdownGroupBase, props, theme);
1542
+ const { children, ref, ...sparProps } = rest;
1543
+ return /* @__PURE__ */ jsx(DropdownMenuGroup, { ...sparProps, ...rootAttrs, ref, children });
1544
+ };
1545
+ DropdownGroup.displayName = "Dropdown.Group";
1546
+ var DropdownItem = (props) => {
1547
+ const theme = useComponentTheme("DropdownItem");
1548
+ const { rootAttrs, rest } = composeRootAttrs(DropdownItemBase, props, theme);
1549
+ const { children, ref, ...sparProps } = rest;
1550
+ return /* @__PURE__ */ jsx(DropdownMenuItem, { ...sparProps, ...rootAttrs, ref, children });
1551
+ };
1552
+ DropdownItem.displayName = "Dropdown.Item";
1553
+ var DropdownLabel = (props) => {
1554
+ const theme = useComponentTheme("DropdownLabel");
1555
+ const { rootAttrs, rest } = composeRootAttrs(DropdownLabelBase, props, theme);
1556
+ const { children, ref, ...sparProps } = rest;
1557
+ return /* @__PURE__ */ jsx(DropdownMenuLabel, { ...sparProps, ...rootAttrs, ref, children });
1558
+ };
1559
+ DropdownLabel.displayName = "Dropdown.Label";
1560
+ var DropdownSeparator = (props) => {
1561
+ const theme = useComponentTheme("DropdownSeparator");
1562
+ const { rootAttrs, rest } = composeRootAttrs(DropdownSeparatorBase, props, theme);
1563
+ const { children, ref, ...sparProps } = rest;
1564
+ return /* @__PURE__ */ jsx(DropdownMenuSeparator, { ...sparProps, ...rootAttrs, ref, children });
1565
+ };
1566
+ DropdownSeparator.displayName = "Dropdown.Separator";
1567
+ var DropdownTrigger = (props) => {
1568
+ const theme = useComponentTheme("DropdownTrigger");
1569
+ const { size } = useDropdownOwnContext("Dropdown.Trigger");
1570
+ const { rootAttrs, rest } = composeRootAttrs(DropdownTriggerBase, props, theme, {
1571
+ stateAttrs: () => ({
1572
+ "data-size": size
1573
+ })
1574
+ });
1575
+ const { children, ref, ...sparProps } = rest;
1576
+ return /* @__PURE__ */ jsx(DropdownMenuTrigger, { ...sparProps, ...rootAttrs, ref, children });
1577
+ };
1578
+ DropdownTrigger.displayName = "Dropdown.Trigger";
1579
+ var DropdownViewport = (props) => {
1580
+ const theme = useComponentTheme("DropdownViewport");
1581
+ const { rootAttrs, rest } = composeRootAttrs(DropdownViewportBase, props, theme);
1582
+ const { children, ref, ...sparProps } = rest;
1583
+ return /* @__PURE__ */ jsx(DropdownMenuViewport, { ...sparProps, ...rootAttrs, ref, children });
1584
+ };
1585
+ DropdownViewport.displayName = "Dropdown.Viewport";
1586
+
1587
+ // src/components/dropdown/index.ts
1588
+ var Dropdown2 = Object.assign(Dropdown, {
1589
+ Trigger: DropdownTrigger,
1590
+ Content: DropdownContent,
1591
+ Viewport: DropdownViewport,
1592
+ Item: DropdownItem,
1593
+ Group: DropdownGroup,
1594
+ Label: DropdownLabel,
1595
+ Separator: DropdownSeparator,
1596
+ Arrow: DropdownArrow
1597
+ });
1598
+
1402
1599
  // src/components/field/base.ts
1403
1600
  var FieldBase = createComponentBase({
1404
1601
  name: "Field",
@@ -1562,7 +1759,7 @@ var InputChipsBase = createComponentBase({
1562
1759
  var [InputProvider, useInputOwnContext] = createSafeContext("InputProvider");
1563
1760
 
1564
1761
  // src/components/input/defaults.ts
1565
- var DEFAULT_SIZE7 = "base";
1762
+ var DEFAULT_SIZE8 = "base";
1566
1763
  var SEGMENT_COUNT = 4;
1567
1764
  var computeStrength = (value) => {
1568
1765
  let strength = 0;
@@ -1614,11 +1811,11 @@ var Input = (props) => {
1614
1811
  for (const value of clearablesRef.current.values()) value.clear();
1615
1812
  }, []);
1616
1813
  const { rootAttrs, rest } = composeRootAttrs(InputBase, props, theme, {
1617
- stateAttrs: ({ size: size2 = DEFAULT_SIZE7 }) => ({
1814
+ stateAttrs: ({ size: size2 = DEFAULT_SIZE8 }) => ({
1618
1815
  "data-size": size2
1619
1816
  })
1620
1817
  });
1621
- const { size = DEFAULT_SIZE7, children, ref, ...sparProps } = rest;
1818
+ const { size = DEFAULT_SIZE8, children, ref, ...sparProps } = rest;
1622
1819
  const contextValue = useMemo(
1623
1820
  () => ({
1624
1821
  size,
@@ -2074,19 +2271,19 @@ var RADIO_ITEM_CONTEXT_VALUE = { inside: true };
2074
2271
  var [RadioItemProvider, useRadioItemOwnContext] = createSafeContext("RadioItemProvider");
2075
2272
 
2076
2273
  // src/components/radio/defaults.ts
2077
- var DEFAULT_SIZE8 = "base";
2274
+ var DEFAULT_SIZE9 = "base";
2078
2275
  var DEFAULT_POSITION = "left";
2079
2276
  var Radio = (props) => {
2080
2277
  const theme = useComponentTheme("Radio");
2081
2278
  const { rootAttrs, rest } = composeRootAttrs(RadioBase, props, theme, {
2082
- stateAttrs: ({ size: size2 = DEFAULT_SIZE8, position: position2 = DEFAULT_POSITION, spread }) => ({
2279
+ stateAttrs: ({ size: size2 = DEFAULT_SIZE9, position: position2 = DEFAULT_POSITION, spread }) => ({
2083
2280
  "data-size": size2,
2084
2281
  "data-position": position2,
2085
2282
  "data-spread": spread ? "" : void 0
2086
2283
  })
2087
2284
  });
2088
2285
  const {
2089
- size = DEFAULT_SIZE8,
2286
+ size = DEFAULT_SIZE9,
2090
2287
  position = DEFAULT_POSITION,
2091
2288
  invalid,
2092
2289
  // `spread` is consumed only as a data-attr above; destructure to keep it
@@ -2233,8 +2430,8 @@ PopoverDescription.displayName = "Popover.Description";
2233
2430
  var PopoverArrow = (props) => {
2234
2431
  const theme = useComponentTheme("PopoverArrow");
2235
2432
  const { rootAttrs, rest } = composeRootAttrs(PopoverArrowBase, props, theme);
2236
- const { ref, ...sparProps } = rest;
2237
- return /* @__PURE__ */ jsx(PopoverArrow$1, { ...sparProps, ...rootAttrs, ref });
2433
+ const { ref, children, ...sparProps } = rest;
2434
+ return /* @__PURE__ */ jsx(PopoverArrow$1, { ...sparProps, ...rootAttrs, ref, children: children ?? renderPointerArrow() });
2238
2435
  };
2239
2436
  PopoverArrow.displayName = "Popover.Arrow";
2240
2437
  var PopoverClose = (props) => {
@@ -2255,6 +2452,193 @@ var Popover2 = Object.assign(Popover, {
2255
2452
  Close: PopoverClose
2256
2453
  });
2257
2454
 
2455
+ // src/components/progress/base.ts
2456
+ var ProgressBase = createComponentBase({
2457
+ name: "Progress",
2458
+ slots: ["root"],
2459
+ classes: { root: "tk-progress" }
2460
+ });
2461
+ var ProgressTrackBase = createComponentBase({
2462
+ name: "ProgressTrack",
2463
+ slots: ["root", "rail"],
2464
+ classes: { root: "tk-progress-track", rail: "tk-progress-rail" }
2465
+ });
2466
+ var ProgressIndicatorBase = createComponentBase({
2467
+ name: "ProgressIndicator",
2468
+ slots: ["root"],
2469
+ classes: { root: "tk-progress-indicator" }
2470
+ });
2471
+ var ProgressValueBase = createComponentBase({
2472
+ name: "ProgressValue",
2473
+ slots: ["root"],
2474
+ classes: { root: "tk-progress-value" }
2475
+ });
2476
+
2477
+ // src/components/progress/context.ts
2478
+ var [ProgressProvider, useProgressContext] = createSafeContext("ProgressProvider");
2479
+
2480
+ // src/components/progress/defaults.ts
2481
+ var DEFAULT_APPEARANCE6 = "linear";
2482
+ var DEFAULT_SIZE10 = "base";
2483
+ var DEFAULT_VARIANT6 = "primary";
2484
+ var DEFAULT_MIN = 0;
2485
+ var DEFAULT_MAX = 100;
2486
+ var DEFAULT_RANGE = 100;
2487
+ var DEFAULT_ARIA_LABEL = "Progress";
2488
+ var RING_VIEWBOX = "0 0 40 40";
2489
+ var RING_CENTER = 20;
2490
+ var RING_RADIUS = 18;
2491
+ var ProgressIndicator = (props) => {
2492
+ const theme = useComponentTheme("ProgressIndicator");
2493
+ const { value, min, max, appearance, indeterminate } = useProgressContext("Progress.Indicator");
2494
+ const percent = Math.min(100, Math.max(0, (value - min) * 100 / (max - min)));
2495
+ const { rootAttrs, rest } = composeRootAttrs(ProgressIndicatorBase, props, theme, {
2496
+ stateAttrs: () => ({
2497
+ "data-type": appearance,
2498
+ "data-indeterminate": indeterminate ? "" : void 0
2499
+ })
2500
+ });
2501
+ const { ref, style, ...nativeProps } = rest;
2502
+ const { style: slotStyle, ...slotAttrs } = rootAttrs;
2503
+ if (appearance === "circular") {
2504
+ return /* @__PURE__ */ jsx(
2505
+ "circle",
2506
+ {
2507
+ cx: RING_CENTER,
2508
+ cy: RING_CENTER,
2509
+ r: RING_RADIUS,
2510
+ ...nativeProps,
2511
+ ...slotAttrs,
2512
+ pathLength: "100",
2513
+ style: { ...style, ...slotStyle, strokeDasharray: 100, strokeDashoffset: indeterminate ? void 0 : 100 - percent },
2514
+ ref
2515
+ }
2516
+ );
2517
+ }
2518
+ return /* @__PURE__ */ jsx("span", { ...nativeProps, ...slotAttrs, "aria-hidden": "true", style: { ...style, ...slotStyle, width: indeterminate ? void 0 : `${percent}%` }, ref });
2519
+ };
2520
+ ProgressIndicator.displayName = "Progress.Indicator";
2521
+ var ProgressTrack = (props) => {
2522
+ const theme = useComponentTheme("ProgressTrack");
2523
+ const { appearance } = useProgressContext("Progress.Track");
2524
+ const { rootAttrs, rest } = composeRootAttrs(ProgressTrackBase, props, theme, {
2525
+ stateAttrs: () => ({ "data-type": appearance })
2526
+ });
2527
+ const { children, ref, ...nativeProps } = rest;
2528
+ const content = children ?? /* @__PURE__ */ jsx(ProgressIndicator, {});
2529
+ if (appearance === "circular") {
2530
+ const railAttrs = buildSlotAttrs(ProgressTrackBase.getSlotProps("rail"), "rail", {
2531
+ themeSlotProps: theme?.slotProps,
2532
+ themeClassNames: theme?.classNames,
2533
+ instanceSlotProps: props.slotProps,
2534
+ instanceClassNames: props.classNames
2535
+ });
2536
+ return (
2537
+ // The decorative role and the ring geometry are design-system
2538
+ // invariants (the value is announced by the root; the viewBox must
2539
+ // agree with the rail/arc circles) — layered after the spreads so
2540
+ // neither instance nor slot props can override them.
2541
+ /* @__PURE__ */ jsxs("svg", { ...nativeProps, ...rootAttrs, "aria-hidden": "true", focusable: "false", viewBox: RING_VIEWBOX, ref, children: [
2542
+ /* @__PURE__ */ jsx("circle", { ...railAttrs, cx: RING_CENTER, cy: RING_CENTER, r: RING_RADIUS }),
2543
+ content
2544
+ ] })
2545
+ );
2546
+ }
2547
+ return /* @__PURE__ */ jsx("div", { ...nativeProps, ...rootAttrs, ref, children: content });
2548
+ };
2549
+ ProgressTrack.displayName = "Progress.Track";
2550
+ var resolveRange = ({ value: rawValue, min: rawMin = DEFAULT_MIN, max: rawMax = DEFAULT_MAX }) => {
2551
+ const min = Number.isFinite(rawMin) ? rawMin : DEFAULT_MIN;
2552
+ const max = Number.isFinite(rawMax) && rawMax > min ? rawMax : min + DEFAULT_RANGE;
2553
+ const value = typeof rawValue === "number" && Number.isFinite(rawValue) ? Math.min(Math.max(rawValue, min), max) : min;
2554
+ return { min, max, value };
2555
+ };
2556
+ var warnedRanges = /* @__PURE__ */ new Set();
2557
+ var Progress = (props) => {
2558
+ const theme = useComponentTheme("Progress");
2559
+ const field = useOptionalFieldContext();
2560
+ const resolveState = ({
2561
+ indeterminate: indeterminate2 = false,
2562
+ appearance: appearance2 = DEFAULT_APPEARANCE6,
2563
+ size: size2 = DEFAULT_SIZE10,
2564
+ variant: variant2 = DEFAULT_VARIANT6,
2565
+ disabled: disabled2 = field?.disabled ?? false
2566
+ }) => ({ indeterminate: indeterminate2, appearance: appearance2, size: size2, variant: variant2, disabled: disabled2 });
2567
+ const { rootAttrs, rest } = composeRootAttrs(ProgressBase, props, theme);
2568
+ const {
2569
+ // Consumed through resolveState/resolveRange (and as the root data-* hooks
2570
+ // below); destructured so the <div> doesn't receive unknown DOM
2571
+ // attributes.
2572
+ value: _value,
2573
+ min: _min,
2574
+ max: rawMax,
2575
+ indeterminate: _indeterminate,
2576
+ appearance: _appearance,
2577
+ disabled: _disabled,
2578
+ size: _size,
2579
+ variant: _variant,
2580
+ as,
2581
+ children,
2582
+ ref,
2583
+ ...nativeProps
2584
+ } = rest;
2585
+ const { indeterminate, appearance, size, variant, disabled } = resolveState(rest);
2586
+ const { min, max, value } = resolveRange(rest);
2587
+ const dataAttrs = {
2588
+ "data-type": appearance,
2589
+ "data-size": size,
2590
+ "data-variant": variant,
2591
+ "data-disabled": disabled ? "" : void 0,
2592
+ "data-indeterminate": indeterminate ? "" : void 0,
2593
+ // Styling hook for the finished state (e.g. a success fill at 100%);
2594
+ // meaningless while indeterminate, so dropped alongside the value.
2595
+ "data-complete": !indeterminate && value === max ? "" : void 0
2596
+ };
2597
+ if (isDevelopment() && typeof rawMax === "number" && Number.isFinite(rawMax) && rawMax <= min) {
2598
+ const message = `[Progress] \`max\` (${rawMax}) must be greater than \`min\` (${min}); falling back to ${max}.`;
2599
+ if (!warnedRanges.has(message)) {
2600
+ warnedRanges.add(message);
2601
+ console.warn(message);
2602
+ }
2603
+ }
2604
+ const consumerLabelledBy = nativeProps["aria-labelledby"];
2605
+ const accessibilityAttrs = {
2606
+ "role": nativeProps.role ?? "progressbar",
2607
+ "aria-valuemin": min,
2608
+ "aria-valuemax": max,
2609
+ // Per the progressbar pattern, an indeterminate bar exposes no
2610
+ // aria-valuenow — assistive tech then announces it as busy rather than
2611
+ // stuck at a bogus percentage.
2612
+ "aria-valuenow": indeterminate ? void 0 : value,
2613
+ // aria-valuetext accompanies aria-valuenow; drop it while indeterminate so
2614
+ // a consumer-formatted value can't linger next to a busy bar.
2615
+ "aria-valuetext": indeterminate ? void 0 : nativeProps["aria-valuetext"],
2616
+ "aria-labelledby": consumerLabelledBy ?? field?.labelId,
2617
+ "aria-label": nativeProps["aria-label"] ?? (consumerLabelledBy ? void 0 : DEFAULT_ARIA_LABEL),
2618
+ "aria-disabled": disabled || void 0
2619
+ };
2620
+ const Component = as ?? "div";
2621
+ return /* @__PURE__ */ jsx(ProgressProvider, { value: { value, min, max, appearance, indeterminate }, children: /* @__PURE__ */ jsx(Component, { ...nativeProps, ...accessibilityAttrs, ...rootAttrs, ...dataAttrs, ref, children: children ?? /* @__PURE__ */ jsx(ProgressTrack, {}) }) });
2622
+ };
2623
+ Progress.displayName = "Progress";
2624
+ var ProgressValue = (props) => {
2625
+ const theme = useComponentTheme("ProgressValue");
2626
+ const { appearance } = useProgressContext("Progress.Value");
2627
+ const { rootAttrs, rest } = composeRootAttrs(ProgressValueBase, props, theme, {
2628
+ stateAttrs: () => ({ "data-type": appearance })
2629
+ });
2630
+ const { children, ref, ...nativeProps } = rest;
2631
+ return /* @__PURE__ */ jsx("span", { ...nativeProps, ...rootAttrs, "aria-hidden": "true", ref, children });
2632
+ };
2633
+ ProgressValue.displayName = "Progress.Value";
2634
+
2635
+ // src/components/progress/index.ts
2636
+ var Progress2 = Object.assign(Progress, {
2637
+ Track: ProgressTrack,
2638
+ Indicator: ProgressIndicator,
2639
+ Value: ProgressValue
2640
+ });
2641
+
2258
2642
  // src/components/select/base.ts
2259
2643
  var SelectBase = createComponentBase({
2260
2644
  name: "Select",
@@ -2285,6 +2669,11 @@ var SelectContentBase = createComponentBase({
2285
2669
  slots: ["root"],
2286
2670
  classes: { root: "tk-select-content" }
2287
2671
  });
2672
+ var SelectViewportBase = createComponentBase({
2673
+ name: "SelectViewport",
2674
+ slots: ["root"],
2675
+ classes: { root: "tk-select-viewport" }
2676
+ });
2288
2677
  var SelectItemBase = createComponentBase({
2289
2678
  name: "SelectItem",
2290
2679
  slots: ["root"],
@@ -2305,22 +2694,27 @@ var SelectSeparatorBase = createComponentBase({
2305
2694
  slots: ["root"],
2306
2695
  classes: { root: "tk-select-separator" }
2307
2696
  });
2697
+ var SelectArrowBase = createComponentBase({
2698
+ name: "SelectArrow",
2699
+ slots: ["root"],
2700
+ classes: { root: "tk-select-arrow" }
2701
+ });
2308
2702
 
2309
2703
  // src/components/select/context.ts
2310
2704
  var [SelectProvider, useSelectOwnContext] = createSafeContext("SelectProvider");
2311
2705
 
2312
2706
  // src/components/select/defaults.ts
2313
- var DEFAULT_SIZE9 = "base";
2314
- var DEFAULT_CONTENT_WIDTH = "trigger";
2707
+ var DEFAULT_SIZE11 = "base";
2708
+ var DEFAULT_CONTENT_WIDTH2 = "trigger";
2315
2709
  var Select = (props) => {
2316
2710
  const theme = useComponentTheme("Select");
2317
2711
  const { rootAttrs, rest } = composeRootAttrs(SelectBase, props, theme, {
2318
- stateAttrs: ({ size: size2 = DEFAULT_SIZE9, invalid: invalid2 }) => ({
2712
+ stateAttrs: ({ size: size2 = DEFAULT_SIZE11, invalid: invalid2 }) => ({
2319
2713
  "data-size": size2,
2320
2714
  "data-invalid": invalid2 ? "" : void 0
2321
2715
  })
2322
2716
  });
2323
- const { size = DEFAULT_SIZE9, invalid = false, contentWidth = DEFAULT_CONTENT_WIDTH, children, ref, ...sparProps } = rest;
2717
+ const { size = DEFAULT_SIZE11, invalid = false, contentWidth = DEFAULT_CONTENT_WIDTH2, children, ref, ...sparProps } = rest;
2324
2718
  return /* @__PURE__ */ jsx(SelectProvider, { value: { size, invalid, contentWidth }, children: /* @__PURE__ */ jsx(Select$1, { ...sparProps, ref, ...rootAttrs, children }) });
2325
2719
  };
2326
2720
  Select.displayName = "Select";
@@ -2371,44 +2765,29 @@ var SelectIndicator = (props) => {
2371
2765
  return /* @__PURE__ */ jsx(Component, { ...rendered, ref, "aria-hidden": "true", ...rootAttrs, children: resolved });
2372
2766
  };
2373
2767
  SelectIndicator.displayName = "Select.Indicator";
2374
- var resolveStaticWidth = (mode) => {
2375
- if (mode === "trigger" || mode === "content") return void 0;
2376
- return typeof mode === "number" ? `${mode}px` : mode;
2377
- };
2378
2768
  var SelectContent = (props) => {
2379
2769
  const theme = useComponentTheme("SelectContent");
2380
2770
  const { size, contentWidth } = useSelectOwnContext("Select.Content");
2381
2771
  const { triggerRef } = useSelectContext();
2382
- const [triggerWidth, setTriggerWidth] = useState(null);
2383
- useEffect(() => {
2384
- if (contentWidth !== "trigger") return;
2385
- const node = triggerRef.current;
2386
- if (!node) return;
2387
- setTriggerWidth(node.offsetWidth);
2388
- const observer = new ResizeObserver((entries) => {
2389
- const entry = entries[0];
2390
- if (entry) setTriggerWidth(Math.round(entry.contentRect.width + 2));
2391
- });
2392
- observer.observe(node);
2393
- return () => observer.disconnect();
2394
- }, [contentWidth, triggerRef]);
2772
+ const widthStyle = useContentWidthStyle(contentWidth, triggerRef);
2395
2773
  const { rootAttrs, rest } = composeRootAttrs(SelectContentBase, props, theme, {
2396
2774
  stateAttrs: () => ({
2397
2775
  "data-size": size
2398
2776
  })
2399
2777
  });
2400
2778
  const { children, ref, style: userStyle, ...spar } = rest;
2401
- const widthStyle = useMemo(() => {
2402
- if (contentWidth === "trigger") {
2403
- return triggerWidth != null ? { width: triggerWidth } : void 0;
2404
- }
2405
- const staticWidth = resolveStaticWidth(contentWidth);
2406
- return staticWidth != null ? { width: staticWidth } : void 0;
2407
- }, [contentWidth, triggerWidth]);
2408
- const mergedStyle = widthStyle || userStyle ? { ...widthStyle, ...userStyle } : void 0;
2409
- return /* @__PURE__ */ jsx(SelectContent$1, { ...spar, ref, style: mergedStyle, ...rootAttrs, children });
2779
+ const { style: rootStyle, ...rootRest } = rootAttrs;
2780
+ const mergedStyle = widthStyle || rootStyle || userStyle ? { ...widthStyle, ...rootStyle, ...userStyle } : void 0;
2781
+ return /* @__PURE__ */ jsx(SelectContent$1, { ...spar, ...rootRest, ref, style: mergedStyle, children });
2410
2782
  };
2411
2783
  SelectContent.displayName = "Select.Content";
2784
+ var SelectViewport = (props) => {
2785
+ const theme = useComponentTheme("SelectViewport");
2786
+ const { rootAttrs, rest } = composeRootAttrs(SelectViewportBase, props, theme);
2787
+ const { children, ref, ...spar } = rest;
2788
+ return /* @__PURE__ */ jsx(SelectViewport$1, { ...spar, ref, ...rootAttrs, children });
2789
+ };
2790
+ SelectViewport.displayName = "Select.Viewport";
2412
2791
  var SelectItem = (props) => {
2413
2792
  const theme = useComponentTheme("SelectItem");
2414
2793
  const { rootAttrs, rest } = composeRootAttrs(SelectItemBase, props, theme);
@@ -2437,16 +2816,638 @@ var SelectSeparator = (props) => {
2437
2816
  return /* @__PURE__ */ jsx(SelectSeparator$1, { ...spar, ref, ...rootAttrs, children });
2438
2817
  };
2439
2818
  SelectSeparator.displayName = "Select.Separator";
2819
+ var SelectArrow = (props) => {
2820
+ const theme = useComponentTheme("SelectArrow");
2821
+ const { rootAttrs, rest } = composeRootAttrs(SelectArrowBase, props, theme);
2822
+ const { children, ref, ...sparProps } = rest;
2823
+ return /* @__PURE__ */ jsx(SelectArrow$1, { ...sparProps, ...rootAttrs, ref, children: children ?? renderPointerArrow() });
2824
+ };
2825
+ SelectArrow.displayName = "Select.Arrow";
2440
2826
 
2441
2827
  // src/components/select/index.ts
2442
2828
  var Select2 = Object.assign(Select, {
2443
2829
  Trigger: SelectTrigger,
2444
2830
  Indicator: SelectIndicator,
2445
2831
  Content: SelectContent,
2832
+ Viewport: SelectViewport,
2446
2833
  Item: SelectItem,
2447
2834
  Group: SelectGroup,
2448
2835
  Label: SelectLabel,
2449
- Separator: SelectSeparator
2836
+ Separator: SelectSeparator,
2837
+ Arrow: SelectArrow
2838
+ });
2839
+
2840
+ // src/components/slider/base.ts
2841
+ var SliderBase = createComponentBase({
2842
+ name: "Slider",
2843
+ slots: ["root"],
2844
+ classes: { root: "tk-slider" }
2845
+ });
2846
+ var SliderTrackBase = createComponentBase({
2847
+ name: "SliderTrack",
2848
+ slots: ["root"],
2849
+ classes: { root: "tk-slider-track" }
2850
+ });
2851
+ var SliderRangeBase = createComponentBase({
2852
+ name: "SliderRange",
2853
+ slots: ["root"],
2854
+ classes: { root: "tk-slider-range" }
2855
+ });
2856
+ var SliderThumbBase = createComponentBase({
2857
+ name: "SliderThumb",
2858
+ slots: ["root", "tooltip", "arrow"],
2859
+ classes: { root: "tk-slider-thumb", tooltip: "tk-slider-tooltip", arrow: "tk-slider-arrow" }
2860
+ });
2861
+ var SliderTicksBase = createComponentBase({
2862
+ name: "SliderTicks",
2863
+ slots: ["root", "tick"],
2864
+ classes: { root: "tk-slider-ticks", tick: "tk-slider-tick" }
2865
+ });
2866
+ var SliderValueBase = createComponentBase({
2867
+ name: "SliderValue",
2868
+ slots: ["root"],
2869
+ classes: { root: "tk-slider-value" }
2870
+ });
2871
+
2872
+ // src/components/slider/context.ts
2873
+ var [SliderProvider, useSliderContext] = createSafeContext("SliderProvider");
2874
+
2875
+ // src/components/slider/defaults.ts
2876
+ var DEFAULT_ORIENTATION2 = "horizontal";
2877
+ var DEFAULT_SIZE12 = "base";
2878
+ var DEFAULT_VARIANT7 = "primary";
2879
+ var DEFAULT_TOOLTIP = "auto";
2880
+ var DEFAULT_TRACK = "normal";
2881
+ var DEFAULT_MIN_DISTANCE = 0;
2882
+ var DEFAULT_MIN2 = 0;
2883
+ var DEFAULT_MAX2 = 100;
2884
+ var DEFAULT_STEP = 1;
2885
+ var DEFAULT_SPAN = 100;
2886
+ var PAGE_STEP_MULTIPLIER = 10;
2887
+ var MAX_TICKS = 100;
2888
+ var RANGE_VALUE_SEPARATOR = " \u2013 ";
2889
+ var RANGE_THUMB_LABELS = ["Minimum", "Maximum"];
2890
+
2891
+ // src/components/slider/helpers.ts
2892
+ var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
2893
+ var decimalsOf = (value) => {
2894
+ if (!Number.isFinite(value)) return 0;
2895
+ const text = String(value);
2896
+ const exponent = text.indexOf("e-");
2897
+ if (exponent !== -1) {
2898
+ const fraction = text.slice(0, exponent).split(".")[1]?.length ?? 0;
2899
+ return fraction + Number(text.slice(exponent + 2));
2900
+ }
2901
+ const dot = text.indexOf(".");
2902
+ return dot === -1 ? 0 : text.length - dot - 1;
2903
+ };
2904
+ var roundTo = (value, decimals) => decimals > 0 ? Number(value.toFixed(Math.min(decimals, 15))) : Math.round(value);
2905
+ var resolveBounds = (rawMin = DEFAULT_MIN2, rawMax = DEFAULT_MAX2, rawStep = DEFAULT_STEP) => {
2906
+ const min = Number.isFinite(rawMin) ? rawMin : DEFAULT_MIN2;
2907
+ const max = Number.isFinite(rawMax) && rawMax > min ? rawMax : min + DEFAULT_SPAN;
2908
+ const step = Number.isFinite(rawStep) && rawStep > 0 ? rawStep : DEFAULT_STEP;
2909
+ return { min, max, step };
2910
+ };
2911
+ var snap = (value, { min, max, step }) => {
2912
+ if (!Number.isFinite(value)) return min;
2913
+ const steps = Math.round((value - min) / step);
2914
+ const snapped = min + steps * step;
2915
+ return clamp(roundTo(snapped, Math.max(decimalsOf(step), decimalsOf(min))), min, max);
2916
+ };
2917
+ var toPercent = (value, { min, max }) => clamp((value - min) * 100 / (max - min), 0, 100);
2918
+ var fromRatio = (ratio, { min, max }) => min + ratio * (max - min);
2919
+ var pointerCoord = (event, orientation) => orientation === "vertical" ? event.clientY : event.clientX;
2920
+ var valueFromPointer = (rect, point, bounds, orientation) => {
2921
+ const ratio = orientation === "vertical" ? rect.height === 0 ? 0 : (rect.bottom - point) / rect.height : rect.width === 0 ? 0 : (point - rect.left) / rect.width;
2922
+ return snap(fromRatio(clamp(ratio, 0, 1), bounds), bounds);
2923
+ };
2924
+ var offsetStyle = (percent, orientation) => orientation === "vertical" ? { insetBlockEnd: `${percent}%` } : { insetInlineStart: `${percent}%` };
2925
+ var bandStyle = (start, end, orientation) => orientation === "vertical" ? { insetBlockEnd: `${start}%`, height: `${end - start}%` } : { insetInlineStart: `${start}%`, width: `${end - start}%` };
2926
+ var normalizeValues = (value, range, bounds) => {
2927
+ if (range) {
2928
+ const seeded = Array.isArray(value) && value.length >= 2 ? value : [bounds.min, bounds.max];
2929
+ return seeded.map((entry) => snap(entry, bounds)).sort((a, b) => a - b);
2930
+ }
2931
+ return [snap(Array.isArray(value) ? value[0] : value ?? bounds.min, bounds)];
2932
+ };
2933
+ var toCommittedValue = (values, range) => range ? [...values] : values[0];
2934
+ var rangeInputName = (name, index, count) => count === 2 ? index === 0 ? `${name}-min` : `${name}-max` : `${name}-${index + 1}`;
2935
+ var valuesEqual = (a, b) => a.length === b.length && a.every((entry, index) => entry === b[index]);
2936
+ var thumbLabel = (index, count) => {
2937
+ if (count < 2) return void 0;
2938
+ if (count === 2) return RANGE_THUMB_LABELS[index];
2939
+ return `Value ${index + 1}`;
2940
+ };
2941
+ var closestThumbIndex = (values, target, disabled = []) => {
2942
+ let index = 0;
2943
+ let best = Infinity;
2944
+ let found = false;
2945
+ values.forEach((entry, current) => {
2946
+ if (disabled[current]) return;
2947
+ const distance = Math.abs(entry - target);
2948
+ if (distance <= best) {
2949
+ best = distance;
2950
+ index = current;
2951
+ found = true;
2952
+ }
2953
+ });
2954
+ if (found) return index;
2955
+ values.forEach((entry, current) => {
2956
+ const distance = Math.abs(entry - target);
2957
+ if (distance <= best) {
2958
+ best = distance;
2959
+ index = current;
2960
+ }
2961
+ });
2962
+ return index;
2963
+ };
2964
+ var thumbBounds = (values, index, bounds, minDistance = 0) => {
2965
+ const hardLower = index > 0 ? values[index - 1] : bounds.min;
2966
+ const hardUpper = index < values.length - 1 ? values[index + 1] : bounds.max;
2967
+ const lower = index > 0 ? hardLower + minDistance : bounds.min;
2968
+ const upper = index < values.length - 1 ? hardUpper - minDistance : bounds.max;
2969
+ return lower <= upper ? { min: lower, max: upper } : { min: hardLower, max: hardUpper };
2970
+ };
2971
+ var withThumbClamped = (values, index, next, bounds, minDistance = 0) => {
2972
+ const { min: lower, max: upper } = thumbBounds(values, index, bounds, minDistance);
2973
+ const updated = [...values];
2974
+ updated[index] = clamp(snap(next, bounds), lower, upper);
2975
+ return updated;
2976
+ };
2977
+ var withThumbSwapped = (values, index, next, bounds, minDistance = 0, disabled = []) => {
2978
+ const lowerBlocked = index > 0 && disabled[index - 1];
2979
+ const upperBlocked = index < values.length - 1 && disabled[index + 1];
2980
+ if (minDistance > 0 || lowerBlocked || upperBlocked) {
2981
+ const { min: lower, max: upper } = thumbBounds(values, index, bounds, minDistance);
2982
+ const updated2 = [...values];
2983
+ updated2[index] = clamp(snap(next, bounds), lower, upper);
2984
+ return { values: updated2, index };
2985
+ }
2986
+ const updated = [...values];
2987
+ updated[index] = snap(next, bounds);
2988
+ let active = index;
2989
+ while (active > 0 && updated[active] < updated[active - 1]) {
2990
+ [updated[active], updated[active - 1]] = [updated[active - 1], updated[active]];
2991
+ active -= 1;
2992
+ }
2993
+ while (active < updated.length - 1 && updated[active] > updated[active + 1]) {
2994
+ [updated[active], updated[active + 1]] = [updated[active + 1], updated[active]];
2995
+ active += 1;
2996
+ }
2997
+ return { values: updated, index: active };
2998
+ };
2999
+ var formatValueText = (value, formatValue) => formatValue?.(value) ?? String(value);
3000
+ var tickPercents = ({ min, max, step }, limit) => {
3001
+ const raw = (max - min) / step;
3002
+ const steps = Math.abs(raw - Math.round(raw)) < 1e-9 ? Math.round(raw) : Math.floor(raw);
3003
+ const count = steps + 1;
3004
+ if (count > limit) return null;
3005
+ return Array.from({ length: count }, (_, index) => toPercent(min + index * step, { min, max}));
3006
+ };
3007
+ var SliderRange = (props) => {
3008
+ const theme = useComponentTheme("SliderRange");
3009
+ const { values, bounds, range, orientation } = useSliderContext("Slider.Range");
3010
+ const start = range ? toPercent(values[0], bounds) : 0;
3011
+ const end = toPercent(range ? values[values.length - 1] : values[0], bounds);
3012
+ const { rootAttrs, rest } = composeRootAttrs(SliderRangeBase, props, theme);
3013
+ const { ref, style, ...nativeProps } = rest;
3014
+ const { style: slotStyle, ...slotAttrs } = rootAttrs;
3015
+ return /* @__PURE__ */ jsx("span", { ...nativeProps, ...slotAttrs, "aria-hidden": "true", style: { ...style, ...slotStyle, ...bandStyle(start, end, orientation) }, ref });
3016
+ };
3017
+ SliderRange.displayName = "Slider.Range";
3018
+ var SliderThumb = (props) => {
3019
+ const theme = useComponentTheme("SliderThumb");
3020
+ const {
3021
+ values,
3022
+ bounds,
3023
+ range,
3024
+ minDistance,
3025
+ orientation,
3026
+ disabled,
3027
+ readOnly,
3028
+ invalid,
3029
+ required,
3030
+ draggingIndex,
3031
+ formatValue,
3032
+ setThumbValue,
3033
+ startDrag,
3034
+ thumbRefs,
3035
+ thumbDisabledRef,
3036
+ fieldId,
3037
+ labelId,
3038
+ describedBy,
3039
+ rootAriaLabel,
3040
+ rootAriaLabelledby
3041
+ } = useSliderContext("Slider.Thumb");
3042
+ const [isFocused, setIsFocused] = useState(false);
3043
+ const { rootAttrs, rest } = composeRootAttrs(SliderThumbBase, props, theme);
3044
+ const { index = 0, disabled: ownDisabled, children, ref, style, onKeyDown, onPointerDown, onFocus, onBlur, ...nativeProps } = rest;
3045
+ const value = values[index] ?? bounds.min;
3046
+ const isDragging = draggingIndex === index;
3047
+ const isDisabled = disabled || Boolean(ownDisabled);
3048
+ thumbDisabledRef.current[index] = isDisabled;
3049
+ const { min: lowerBound, max: upperBound } = thumbBounds(values, index, bounds, minDistance);
3050
+ const handleKeyDown = (event) => {
3051
+ onKeyDown?.(event);
3052
+ if (isDisabled || readOnly || event.defaultPrevented) return;
3053
+ const page = bounds.step * PAGE_STEP_MULTIPLIER;
3054
+ const next = {
3055
+ ArrowRight: value + bounds.step,
3056
+ ArrowUp: value + bounds.step,
3057
+ ArrowLeft: value - bounds.step,
3058
+ ArrowDown: value - bounds.step,
3059
+ PageUp: value + page,
3060
+ PageDown: value - page,
3061
+ Home: bounds.min,
3062
+ End: bounds.max
3063
+ }[event.key];
3064
+ if (next === void 0) return;
3065
+ event.preventDefault();
3066
+ setThumbValue(index, next);
3067
+ };
3068
+ const handlePointerDown = (event) => {
3069
+ onPointerDown?.(event);
3070
+ if (isDisabled || readOnly || event.defaultPrevented || event.button !== 0) return;
3071
+ event.preventDefault();
3072
+ event.stopPropagation();
3073
+ startDrag(index, pointerCoord(event, orientation), false, event.pointerId);
3074
+ };
3075
+ const tooltipAttrs = buildSlotAttrs(SliderThumbBase.getSlotProps("tooltip"), "tooltip", {
3076
+ themeSlotProps: theme?.slotProps,
3077
+ themeClassNames: theme?.classNames,
3078
+ instanceSlotProps: props.slotProps,
3079
+ instanceClassNames: props.classNames
3080
+ });
3081
+ const arrowAttrs = buildSlotAttrs(SliderThumbBase.getSlotProps("arrow"), "arrow", {
3082
+ themeSlotProps: theme?.slotProps,
3083
+ themeClassNames: theme?.classNames,
3084
+ instanceSlotProps: props.slotProps,
3085
+ instanceClassNames: props.classNames
3086
+ });
3087
+ const formattedText = formatValueText(value, formatValue);
3088
+ const formatted = formatValue ? formattedText : void 0;
3089
+ const { style: slotStyle, ...slotAttrs } = rootAttrs;
3090
+ const bubbleContent = children === void 0 ? formattedText : typeof children === "function" ? children({ value, formatted: formattedText, index, isDragging, isFocused }) : children;
3091
+ return /* @__PURE__ */ jsx(
3092
+ "span",
3093
+ {
3094
+ ...nativeProps,
3095
+ ...slotAttrs,
3096
+ role: "slider",
3097
+ tabIndex: isDisabled ? -1 : 0,
3098
+ "aria-valuemin": lowerBound,
3099
+ "aria-valuemax": upperBound,
3100
+ "aria-valuenow": value,
3101
+ "aria-valuetext": formatted,
3102
+ "aria-orientation": orientation,
3103
+ "aria-disabled": isDisabled || void 0,
3104
+ "aria-readonly": readOnly || void 0,
3105
+ "aria-invalid": invalid || void 0,
3106
+ "aria-required": required || void 0,
3107
+ "aria-label": nativeProps["aria-label"] ?? thumbLabel(index, values.length) ?? rootAriaLabel,
3108
+ "aria-labelledby": nativeProps["aria-labelledby"] ?? (range ? void 0 : rootAriaLabelledby ?? labelId),
3109
+ "aria-describedby": nativeProps["aria-describedby"] ?? describedBy,
3110
+ id: nativeProps.id ?? (index === 0 ? fieldId : void 0),
3111
+ "data-thumb": range ? index === 0 ? "min" : index === values.length - 1 ? "max" : void 0 : void 0,
3112
+ "data-dragging": isDragging ? "" : void 0,
3113
+ "data-focus": isFocused ? "" : void 0,
3114
+ "data-disabled": isDisabled ? "" : void 0,
3115
+ onKeyDown: handleKeyDown,
3116
+ onPointerDown: handlePointerDown,
3117
+ onFocus: (event) => {
3118
+ onFocus?.(event);
3119
+ setIsFocused(true);
3120
+ },
3121
+ onBlur: (event) => {
3122
+ onBlur?.(event);
3123
+ setIsFocused(false);
3124
+ },
3125
+ style: { ...style, ...slotStyle, ...offsetStyle(toPercent(value, bounds), orientation) },
3126
+ ref: (node) => {
3127
+ thumbRefs.current[index] = node;
3128
+ if (typeof ref === "function") ref(node);
3129
+ else if (ref) ref.current = node;
3130
+ },
3131
+ children: /* @__PURE__ */ jsxs("span", { ...tooltipAttrs, "aria-hidden": "true", children: [
3132
+ bubbleContent,
3133
+ /* @__PURE__ */ jsx("span", { ...arrowAttrs, "aria-hidden": "true" })
3134
+ ] })
3135
+ }
3136
+ );
3137
+ };
3138
+ SliderThumb.displayName = "Slider.Thumb";
3139
+ var SliderTrack = (props) => {
3140
+ const theme = useComponentTheme("SliderTrack");
3141
+ const { values, disabled, readOnly, orientation, valueFromPoint, startDrag, trackRef, thumbDisabledRef } = useSliderContext("Slider.Track");
3142
+ const { rootAttrs, rest } = composeRootAttrs(SliderTrackBase, props, theme);
3143
+ const { children, ref, onPointerDown, ...nativeProps } = rest;
3144
+ const handlePointerDown = (event) => {
3145
+ onPointerDown?.(event);
3146
+ if (disabled || readOnly || event.defaultPrevented || event.button !== 0) return;
3147
+ event.preventDefault();
3148
+ const point = pointerCoord(event, orientation);
3149
+ startDrag(closestThumbIndex(values, valueFromPoint(point), thumbDisabledRef.current), point, true, event.pointerId);
3150
+ };
3151
+ return /* @__PURE__ */ jsx(
3152
+ "div",
3153
+ {
3154
+ ...nativeProps,
3155
+ ...rootAttrs,
3156
+ onPointerDown: handlePointerDown,
3157
+ ref: (node) => {
3158
+ trackRef.current = node;
3159
+ if (typeof ref === "function") ref(node);
3160
+ else if (ref) ref.current = node;
3161
+ },
3162
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
3163
+ /* @__PURE__ */ jsx(SliderRange, {}),
3164
+ values.map((_, index) => /* @__PURE__ */ jsx(SliderThumb, { index }, index))
3165
+ ] })
3166
+ }
3167
+ );
3168
+ };
3169
+ SliderTrack.displayName = "Slider.Track";
3170
+ var warnedRanges2 = /* @__PURE__ */ new Set();
3171
+ var Slider = (props) => {
3172
+ const theme = useComponentTheme("Slider");
3173
+ const field = useOptionalFieldContext();
3174
+ const { rootAttrs, rest } = composeRootAttrs(SliderBase, props, theme, {
3175
+ stateAttrs: (merged) => {
3176
+ const {
3177
+ size = DEFAULT_SIZE12,
3178
+ variant = DEFAULT_VARIANT7,
3179
+ orientation: orientation2 = DEFAULT_ORIENTATION2,
3180
+ tooltip = DEFAULT_TOOLTIP,
3181
+ track = DEFAULT_TRACK,
3182
+ range: range2,
3183
+ disabled: disabled2,
3184
+ readOnly: readOnly2,
3185
+ invalid: invalid2,
3186
+ required: required2
3187
+ } = merged;
3188
+ return {
3189
+ "data-size": size,
3190
+ "data-variant": variant,
3191
+ "data-orientation": orientation2,
3192
+ "data-tooltip": tooltip,
3193
+ "data-track": track,
3194
+ "data-range": range2 ? "" : void 0,
3195
+ "data-disabled": disabled2 ?? field?.disabled ? "" : void 0,
3196
+ "data-readonly": readOnly2 ?? field?.readOnly ? "" : void 0,
3197
+ "data-invalid": invalid2 ?? field?.invalid ? "" : void 0,
3198
+ "data-required": required2 ?? field?.required ? "" : void 0
3199
+ };
3200
+ }
3201
+ });
3202
+ const {
3203
+ // Consumed through the resolved state below (and as the root data-* hooks);
3204
+ // destructured so the <div> doesn't receive unknown DOM attributes.
3205
+ min: rawMin,
3206
+ max: rawMax,
3207
+ step: rawStep,
3208
+ range = false,
3209
+ value,
3210
+ defaultValue,
3211
+ onValueChange,
3212
+ onValueChangeEnd,
3213
+ disabled: ownDisabled,
3214
+ readOnly: ownReadOnly,
3215
+ invalid: ownInvalid,
3216
+ required: ownRequired,
3217
+ minDistance = DEFAULT_MIN_DISTANCE,
3218
+ orientation = DEFAULT_ORIENTATION2,
3219
+ size: _size,
3220
+ variant: _variant,
3221
+ // Consumed as the `data-tooltip` / `data-track` root hooks above (the recipe
3222
+ // drives the value bubble and the inverted/none fill off them); pulled out
3223
+ // so they never land on the <div> as unknown attributes.
3224
+ tooltip: _tooltip,
3225
+ track: _track,
3226
+ formatValue,
3227
+ name,
3228
+ form,
3229
+ as,
3230
+ children,
3231
+ ref,
3232
+ ...nativeProps
3233
+ } = rest;
3234
+ const disabled = ownDisabled ?? field?.disabled ?? false;
3235
+ const readOnly = ownReadOnly ?? field?.readOnly ?? false;
3236
+ const invalid = ownInvalid ?? field?.invalid ?? false;
3237
+ const required = ownRequired ?? field?.required ?? false;
3238
+ const bounds = resolveBounds(rawMin, rawMax, rawStep);
3239
+ if (isDevelopment() && typeof rawMax === "number" && Number.isFinite(rawMax) && rawMax <= bounds.min) {
3240
+ const message = `[Slider] \`max\` (${rawMax}) must be greater than \`min\` (${bounds.min}); falling back to ${bounds.max}.`;
3241
+ if (!warnedRanges2.has("inverted-range")) {
3242
+ warnedRanges2.add("inverted-range");
3243
+ console.warn(message);
3244
+ }
3245
+ }
3246
+ const controlledValues = value === void 0 ? void 0 : normalizeValues(value, range, bounds);
3247
+ const initialValues = normalizeValues(defaultValue, range, bounds);
3248
+ const onValueChangeRef = useRef(onValueChange);
3249
+ onValueChangeRef.current = onValueChange;
3250
+ const handleCommit = useCallback((next) => onValueChangeRef.current?.(toCommittedValue(next, range)), [range]);
3251
+ const [rawValues = initialValues, setValues] = useControllableState(controlledValues, initialValues, handleCommit);
3252
+ const values = useMemo(() => normalizeValues(toCommittedValue(rawValues, range), range, bounds), [rawValues, range, bounds.min, bounds.max, bounds.step]);
3253
+ const onValueChangeEndRef = useRef(onValueChangeEnd);
3254
+ onValueChangeEndRef.current = onValueChangeEnd;
3255
+ const emitChangeEnd = useCallback((vals) => onValueChangeEndRef.current?.(toCommittedValue(vals, range)), [range]);
3256
+ const emitChangeEndRef = useRef(emitChangeEnd);
3257
+ emitChangeEndRef.current = emitChangeEnd;
3258
+ const [draggingIndex, setDraggingIndex] = useState(null);
3259
+ const trackRef = useRef(null);
3260
+ const thumbRefs = useRef([]);
3261
+ const thumbDisabledRef = useRef([]);
3262
+ const gestureStartRef = useRef(null);
3263
+ const dragPointerRef = useRef(null);
3264
+ const valuesRef = useRef(values);
3265
+ valuesRef.current = values;
3266
+ thumbDisabledRef.current.length = values.length;
3267
+ const valueFromPoint = useCallback(
3268
+ (point) => {
3269
+ const track = trackRef.current;
3270
+ if (!track) return bounds.min;
3271
+ return valueFromPointer(track.getBoundingClientRect(), point, bounds, orientation);
3272
+ },
3273
+ [bounds.min, bounds.max, bounds.step, orientation]
3274
+ );
3275
+ const commit = useCallback(
3276
+ (next) => {
3277
+ if (!valuesEqual(next, valuesRef.current)) setValues(next);
3278
+ },
3279
+ [setValues]
3280
+ );
3281
+ const setThumbValue = useCallback(
3282
+ (index, next) => {
3283
+ if (disabled || readOnly || thumbDisabledRef.current[index]) return;
3284
+ const before = valuesRef.current;
3285
+ const updated = withThumbClamped(before, index, next, bounds, minDistance);
3286
+ commit(updated);
3287
+ if (!valuesEqual(updated, before)) emitChangeEnd(updated);
3288
+ },
3289
+ [disabled, readOnly, commit, emitChangeEnd, minDistance, bounds.min, bounds.max, bounds.step]
3290
+ );
3291
+ const startDrag = useCallback(
3292
+ (index, point, seek, pointerId) => {
3293
+ if (disabled || readOnly || thumbDisabledRef.current[index]) return;
3294
+ gestureStartRef.current = valuesRef.current;
3295
+ dragPointerRef.current = pointerId;
3296
+ if (!seek) {
3297
+ setDraggingIndex(index);
3298
+ thumbRefs.current[index]?.focus();
3299
+ return;
3300
+ }
3301
+ const { values: next, index: active } = withThumbSwapped(valuesRef.current, index, valueFromPoint(point), bounds, minDistance, thumbDisabledRef.current);
3302
+ setDraggingIndex(active);
3303
+ thumbRefs.current[active]?.focus();
3304
+ commit(next);
3305
+ },
3306
+ [disabled, readOnly, commit, valueFromPoint, minDistance, bounds.min, bounds.max, bounds.step]
3307
+ );
3308
+ useEffect(() => {
3309
+ if (draggingIndex === null) return;
3310
+ const ownerId = dragPointerRef.current;
3311
+ const isOwner = (event) => ownerId === null || event.pointerId === ownerId;
3312
+ const settle = () => {
3313
+ setDraggingIndex(null);
3314
+ if (gestureStartRef.current && !valuesEqual(valuesRef.current, gestureStartRef.current)) emitChangeEnd(valuesRef.current);
3315
+ gestureStartRef.current = null;
3316
+ dragPointerRef.current = null;
3317
+ };
3318
+ const handleMove = (event) => {
3319
+ if (!isOwner(event)) return;
3320
+ if (event.buttons === 0) {
3321
+ settle();
3322
+ return;
3323
+ }
3324
+ const { values: next, index: active } = withThumbSwapped(
3325
+ valuesRef.current,
3326
+ draggingIndex,
3327
+ valueFromPoint(pointerCoord(event, orientation)),
3328
+ bounds,
3329
+ minDistance,
3330
+ thumbDisabledRef.current
3331
+ );
3332
+ if (active !== draggingIndex) {
3333
+ setDraggingIndex(active);
3334
+ thumbRefs.current[active]?.focus();
3335
+ }
3336
+ commit(next);
3337
+ };
3338
+ const handleEnd = (event) => {
3339
+ if (!isOwner(event)) return;
3340
+ settle();
3341
+ };
3342
+ document.addEventListener("pointermove", handleMove);
3343
+ document.addEventListener("pointerup", handleEnd);
3344
+ document.addEventListener("pointercancel", handleEnd);
3345
+ return () => {
3346
+ document.removeEventListener("pointermove", handleMove);
3347
+ document.removeEventListener("pointerup", handleEnd);
3348
+ document.removeEventListener("pointercancel", handleEnd);
3349
+ };
3350
+ }, [draggingIndex, valueFromPoint, commit, emitChangeEnd, minDistance, orientation, bounds.min, bounds.max, bounds.step]);
3351
+ useEffect(
3352
+ () => () => {
3353
+ if (gestureStartRef.current && !valuesEqual(valuesRef.current, gestureStartRef.current)) emitChangeEndRef.current(valuesRef.current);
3354
+ gestureStartRef.current = null;
3355
+ },
3356
+ []
3357
+ );
3358
+ const Component = as ?? "div";
3359
+ const htmlProps = nativeProps;
3360
+ const groupAttrs = range ? {
3361
+ "role": htmlProps.role ?? "group",
3362
+ "aria-labelledby": htmlProps["aria-labelledby"] ?? field?.labelId
3363
+ } : {};
3364
+ const { "aria-label": rootAriaLabel, "aria-labelledby": rootAriaLabelledby, ...singleWrapperProps } = htmlProps;
3365
+ const wrapperProps = range ? nativeProps : singleWrapperProps;
3366
+ return /* @__PURE__ */ jsx(
3367
+ SliderProvider,
3368
+ {
3369
+ value: {
3370
+ values,
3371
+ bounds,
3372
+ range,
3373
+ minDistance,
3374
+ orientation,
3375
+ disabled,
3376
+ readOnly,
3377
+ invalid,
3378
+ required,
3379
+ draggingIndex,
3380
+ trackRef,
3381
+ thumbRefs,
3382
+ thumbDisabledRef,
3383
+ formatValue,
3384
+ setThumbValue,
3385
+ startDrag,
3386
+ valueFromPoint,
3387
+ fieldId: field?.fieldId,
3388
+ labelId: field?.labelId,
3389
+ describedBy: invalid ? field?.errorId : field?.descriptionId,
3390
+ // Only a single slider forwards the root name to its thumb; a range
3391
+ // carries it on the group wrapper above.
3392
+ rootAriaLabel: range ? void 0 : rootAriaLabel,
3393
+ rootAriaLabelledby: range ? void 0 : rootAriaLabelledby
3394
+ },
3395
+ children: /* @__PURE__ */ jsxs(Component, { ...wrapperProps, ...groupAttrs, ...rootAttrs, ref, children: [
3396
+ children ?? /* @__PURE__ */ jsx(SliderTrack, {}),
3397
+ name && !disabled && (range ? (
3398
+ // One input per handle so a 3+ thumb range submits every value; a
3399
+ // two-handle range keeps the conventional `-min` / `-max` pair.
3400
+ values.map((entry, index) => /* @__PURE__ */ jsx("input", { type: "hidden", name: rangeInputName(name, index, values.length), value: entry, form }, index))
3401
+ ) : /* @__PURE__ */ jsx("input", { type: "hidden", name, value: values[0], form }))
3402
+ ] })
3403
+ }
3404
+ );
3405
+ };
3406
+ Slider.displayName = "Slider";
3407
+ var warnedGrids = /* @__PURE__ */ new Set();
3408
+ var SliderTicks = (props) => {
3409
+ const theme = useComponentTheme("SliderTicks");
3410
+ const { bounds, orientation } = useSliderContext("Slider.Ticks");
3411
+ const { rootAttrs, rest } = composeRootAttrs(SliderTicksBase, props, theme);
3412
+ const { ref, ...nativeProps } = rest;
3413
+ const percents = tickPercents(bounds, MAX_TICKS);
3414
+ if (percents === null) {
3415
+ if (isDevelopment()) {
3416
+ const message = `[Slider.Ticks] needs at most ${MAX_TICKS} marks, but min ${bounds.min} / max ${bounds.max} / step ${bounds.step} produces more; the ticks are not rendered.`;
3417
+ if (!warnedGrids.has("ticks-too-dense")) {
3418
+ warnedGrids.add("ticks-too-dense");
3419
+ console.warn(message);
3420
+ }
3421
+ }
3422
+ return null;
3423
+ }
3424
+ const tickAttrs = buildSlotAttrs(SliderTicksBase.getSlotProps("tick"), "tick", {
3425
+ themeSlotProps: theme?.slotProps,
3426
+ themeClassNames: theme?.classNames,
3427
+ instanceSlotProps: props.slotProps,
3428
+ instanceClassNames: props.classNames
3429
+ });
3430
+ return /* @__PURE__ */ jsx("div", { ...nativeProps, ...rootAttrs, "aria-hidden": "true", ref, children: percents.map((percent, index) => /* @__PURE__ */ jsx("span", { ...tickAttrs, style: offsetStyle(percent, orientation) }, index)) });
3431
+ };
3432
+ SliderTicks.displayName = "Slider.Ticks";
3433
+ var SliderValue = (props) => {
3434
+ const theme = useComponentTheme("SliderValue");
3435
+ const { values, range, formatValue } = useSliderContext("Slider.Value");
3436
+ const { rootAttrs, rest } = composeRootAttrs(SliderValueBase, props, theme);
3437
+ const { children, ref, ...nativeProps } = rest;
3438
+ const formatted = values.map((value) => formatValueText(value, formatValue));
3439
+ const state = { values, formatted, range };
3440
+ return /* @__PURE__ */ jsx("span", { ...nativeProps, ...rootAttrs, "aria-hidden": "true", ref, children: typeof children === "function" ? children(state) : children ?? formatted.join(RANGE_VALUE_SEPARATOR) });
3441
+ };
3442
+ SliderValue.displayName = "Slider.Value";
3443
+
3444
+ // src/components/slider/index.ts
3445
+ var Slider2 = Object.assign(Slider, {
3446
+ Track: SliderTrack,
3447
+ Range: SliderRange,
3448
+ Thumb: SliderThumb,
3449
+ Ticks: SliderTicks,
3450
+ Value: SliderValue
2450
3451
  });
2451
3452
 
2452
3453
  // src/components/spinner/base.ts
@@ -2460,10 +3461,10 @@ var SpinnerBase = createComponentBase({
2460
3461
  });
2461
3462
 
2462
3463
  // src/components/spinner/defaults.ts
2463
- var DEFAULT_APPEARANCE5 = "rounded";
2464
- var DEFAULT_SIZE10 = "base";
2465
- var DEFAULT_VARIANT6 = "neutral";
2466
- var DEFAULT_ARIA_LABEL = "Loading";
3464
+ var DEFAULT_APPEARANCE7 = "rounded";
3465
+ var DEFAULT_SIZE13 = "base";
3466
+ var DEFAULT_VARIANT8 = "neutral";
3467
+ var DEFAULT_ARIA_LABEL2 = "Loading";
2467
3468
  var SPINNER_RADIAL_PARTS = 8;
2468
3469
  var SPINNER_THREE_DOT_PARTS = 3;
2469
3470
  var renderIndicatorContent = (appearance) => {
@@ -2500,13 +3501,13 @@ var renderIndicatorContent = (appearance) => {
2500
3501
  var Spinner = (props) => {
2501
3502
  const theme = useComponentTheme("Spinner");
2502
3503
  const { rootAttrs, rest } = composeRootAttrs(SpinnerBase, props, theme, {
2503
- stateAttrs: ({ variant = DEFAULT_VARIANT6, size = DEFAULT_SIZE10, appearance: appearance2 = DEFAULT_APPEARANCE5 }) => ({
3504
+ stateAttrs: ({ variant = DEFAULT_VARIANT8, size = DEFAULT_SIZE13, appearance: appearance2 = DEFAULT_APPEARANCE7 }) => ({
2504
3505
  "data-variant": variant,
2505
3506
  "data-size": size,
2506
3507
  "data-type": appearance2
2507
3508
  })
2508
3509
  });
2509
- const { variant: _variant, size: _size, appearance = DEFAULT_APPEARANCE5, ref, ...nativeProps } = rest;
3510
+ const { variant: _variant, size: _size, appearance = DEFAULT_APPEARANCE7, ref, ...nativeProps } = rest;
2510
3511
  const indicatorSlotAttrs = buildSlotAttrs(SpinnerBase.getSlotProps("indicator"), "indicator", {
2511
3512
  themeSlotProps: theme?.slotProps,
2512
3513
  themeClassNames: theme?.classNames,
@@ -2516,12 +3517,307 @@ var Spinner = (props) => {
2516
3517
  const isDecorative = nativeProps["aria-hidden"] === true || nativeProps["aria-hidden"] === "true";
2517
3518
  const accessibilityAttrs = isDecorative ? {} : {
2518
3519
  "role": nativeProps.role ?? "status",
2519
- "aria-label": nativeProps["aria-label"] ?? (nativeProps["aria-labelledby"] ? void 0 : DEFAULT_ARIA_LABEL)
3520
+ "aria-label": nativeProps["aria-label"] ?? (nativeProps["aria-labelledby"] ? void 0 : DEFAULT_ARIA_LABEL2)
2520
3521
  };
2521
3522
  return /* @__PURE__ */ jsx("span", { ...accessibilityAttrs, ...nativeProps, ...rootAttrs, ref, children: /* @__PURE__ */ jsx("span", { ...indicatorSlotAttrs, "aria-hidden": "true", children: renderIndicatorContent(appearance) }) });
2522
3523
  };
2523
3524
  Spinner.displayName = "Spinner";
2524
3525
 
3526
+ // src/components/stepper/base.ts
3527
+ var StepperBase = createComponentBase({
3528
+ name: "Stepper",
3529
+ slots: ["root"],
3530
+ classes: { root: "tk-stepper" }
3531
+ });
3532
+ var StepperItemBase = createComponentBase({
3533
+ name: "StepperItem",
3534
+ slots: ["root", "trigger", "rail", "indicator", "content"],
3535
+ classes: {
3536
+ root: "tk-stepper-item",
3537
+ trigger: "tk-stepper-trigger",
3538
+ rail: "tk-stepper-rail",
3539
+ indicator: "tk-stepper-indicator",
3540
+ content: "tk-stepper-content"
3541
+ }
3542
+ });
3543
+ var StepperTitleBase = createComponentBase({
3544
+ name: "StepperTitle",
3545
+ slots: ["root"],
3546
+ classes: { root: "tk-stepper-title" }
3547
+ });
3548
+ var StepperDescriptionBase = createComponentBase({
3549
+ name: "StepperDescription",
3550
+ slots: ["root"],
3551
+ classes: { root: "tk-stepper-description" }
3552
+ });
3553
+
3554
+ // src/components/stepper/context.ts
3555
+ var [StepperProvider, useStepperContext] = createSafeContext("StepperProvider");
3556
+ var [StepperItemIndexProvider, useStepperItemIndex] = createSafeContext("StepperItemIndexProvider");
3557
+ var [StepperItemProvider, useStepperItem] = createSafeContext("Stepper.Item");
3558
+
3559
+ // src/components/stepper/defaults.ts
3560
+ var DEFAULT_ORIENTATION3 = "horizontal";
3561
+ var DEFAULT_MODE2 = "default";
3562
+ var DEFAULT_SIZE14 = "base";
3563
+ var DEFAULT_ACTIVE = 0;
3564
+ var DEFAULT_COMPLETED_LABEL = "completed";
3565
+ var DEFAULT_ERROR_LABEL = "error";
3566
+ var FOCUSABLE_TRIGGER_SELECTOR = '.tk-stepper-trigger:not(:disabled):not([tabindex="-1"])';
3567
+ var Stepper = (props) => {
3568
+ const theme = useComponentTheme("Stepper");
3569
+ const { rootAttrs, rest } = composeRootAttrs(StepperBase, props, theme, {
3570
+ stateAttrs: ({ orientation: orientation2 = DEFAULT_ORIENTATION3, mode: mode2 = DEFAULT_MODE2, size = DEFAULT_SIZE14, linear: linear2 = false, reverse = false }) => ({
3571
+ "data-orientation": orientation2,
3572
+ "data-mode": mode2,
3573
+ "data-size": size,
3574
+ "data-linear": linear2 ? "" : void 0,
3575
+ "data-reverse": reverse ? "" : void 0
3576
+ })
3577
+ });
3578
+ const {
3579
+ active: controlledActive,
3580
+ defaultActive = DEFAULT_ACTIVE,
3581
+ onActiveChange,
3582
+ onStepClick,
3583
+ orientation = DEFAULT_ORIENTATION3,
3584
+ mode = DEFAULT_MODE2,
3585
+ // Consumed only as root data-* hooks above; destructured so the <ol>
3586
+ // doesn't receive unknown DOM attributes.
3587
+ size: _size,
3588
+ linear = false,
3589
+ reverse: _reverse,
3590
+ completedLabel = DEFAULT_COMPLETED_LABEL,
3591
+ errorLabel = DEFAULT_ERROR_LABEL,
3592
+ onKeyDown: nativeOnKeyDown,
3593
+ as,
3594
+ children,
3595
+ ref,
3596
+ ...nativeProps
3597
+ } = rest;
3598
+ const onActiveChangeRef = useRef(onActiveChange);
3599
+ onActiveChangeRef.current = onActiveChange;
3600
+ const stableOnActiveChange = useCallback((index) => {
3601
+ onActiveChangeRef.current?.(index);
3602
+ }, []);
3603
+ const onStepClickRef = useRef(onStepClick);
3604
+ onStepClickRef.current = onStepClick;
3605
+ const stableOnStepClick = useCallback((detail) => {
3606
+ onStepClickRef.current?.(detail);
3607
+ }, []);
3608
+ const [activeValue, setActive] = useControllableState(controlledActive, defaultActive, stableOnActiveChange);
3609
+ const active = activeValue ?? DEFAULT_ACTIVE;
3610
+ const [stepsMeta, setStepsMeta] = useState(/* @__PURE__ */ new Map());
3611
+ const { items, renderStepsMeta } = useMemo(() => {
3612
+ const meta = /* @__PURE__ */ new Map();
3613
+ let stepIndex = 0;
3614
+ const items2 = Children.toArray(children).map((child) => {
3615
+ if (!isValidElement(child)) return child;
3616
+ const index = stepIndex++;
3617
+ const { error = false, disabled = false, isClickable = true } = child.props;
3618
+ meta.set(index, { error, disabled, isClickable });
3619
+ return /* @__PURE__ */ jsx(StepperItemIndexProvider, { value: { index }, children: child }, child.key ?? index);
3620
+ });
3621
+ return { items: items2, renderStepsMeta: meta };
3622
+ }, [children]);
3623
+ const registerStep = useCallback((index, meta) => {
3624
+ setStepsMeta((previous) => new Map(previous).set(index, meta));
3625
+ return () => {
3626
+ setStepsMeta((previous) => {
3627
+ const next = new Map(previous);
3628
+ next.delete(index);
3629
+ return next;
3630
+ });
3631
+ };
3632
+ }, []);
3633
+ const contextValue = useMemo(() => {
3634
+ const canSelectStep = (index, selfMeta) => {
3635
+ const target = stepsMeta.get(index) ?? selfMeta ?? renderStepsMeta.get(index);
3636
+ if (!target || target.disabled || !target.isClickable) return false;
3637
+ if (!linear) return true;
3638
+ if (index < active) return true;
3639
+ if (index === active + 1) {
3640
+ const current = stepsMeta.get(active) ?? renderStepsMeta.get(active);
3641
+ return !current?.error && !current?.disabled;
3642
+ }
3643
+ return false;
3644
+ };
3645
+ const getStepStatus = (options) => {
3646
+ const { index } = options;
3647
+ if (index < active) return "completed";
3648
+ if (index === active) return "active";
3649
+ return "inactive";
3650
+ };
3651
+ return {
3652
+ active,
3653
+ mode,
3654
+ completedLabel,
3655
+ errorLabel,
3656
+ getStepStatus,
3657
+ registerStep,
3658
+ canSelectStep,
3659
+ selectStep: (index) => {
3660
+ if (index !== active && canSelectStep(index)) {
3661
+ setActive(index);
3662
+ }
3663
+ },
3664
+ emitStepClick: (detail) => {
3665
+ stableOnStepClick(detail);
3666
+ }
3667
+ };
3668
+ }, [active, mode, completedLabel, errorLabel, linear, stepsMeta, renderStepsMeta, registerStep, setActive, stableOnStepClick]);
3669
+ const { onKeyDown: slotOnKeyDown, ...restRootAttrs } = rootAttrs;
3670
+ const userOnKeyDown = slotOnKeyDown ?? nativeOnKeyDown;
3671
+ const handleKeyDown = (event) => {
3672
+ userOnKeyDown?.(event);
3673
+ if (event.defaultPrevented) return;
3674
+ const forwardKey = orientation === "horizontal" ? "ArrowRight" : "ArrowDown";
3675
+ const backwardKey = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
3676
+ if (event.key !== forwardKey && event.key !== backwardKey && event.key !== "Home" && event.key !== "End") return;
3677
+ const pressedTrigger = event.target instanceof HTMLElement ? event.target.closest(".tk-stepper-trigger") : null;
3678
+ if (!pressedTrigger || pressedTrigger.closest(".tk-stepper") !== event.currentTarget) return;
3679
+ event.preventDefault();
3680
+ const triggers = Array.from(event.currentTarget.querySelectorAll(FOCUSABLE_TRIGGER_SELECTOR)).filter(
3681
+ (trigger) => trigger.closest(".tk-stepper") === event.currentTarget
3682
+ );
3683
+ const currentIndex = triggers.indexOf(pressedTrigger);
3684
+ if (triggers.length === 0 || currentIndex === -1 && event.key !== "Home" && event.key !== "End") return;
3685
+ const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? triggers.length - 1 : event.key === forwardKey ? currentIndex + 1 : currentIndex - 1;
3686
+ triggers[nextIndex]?.focus();
3687
+ };
3688
+ const Component = as ?? "ol";
3689
+ return /* @__PURE__ */ jsx(StepperProvider, { value: contextValue, children: /* @__PURE__ */ jsx(Component, { ...nativeProps, ...restRootAttrs, ref, onKeyDown: handleKeyDown, children: items }) });
3690
+ };
3691
+ Stepper.displayName = "Stepper";
3692
+ var StepperTitle = (props) => {
3693
+ const theme = useComponentTheme("StepperTitle");
3694
+ useStepperContext("Stepper.Title");
3695
+ const { rootAttrs, rest } = composeRootAttrs(StepperTitleBase, props, theme);
3696
+ const { as, children, ref, ...nativeProps } = rest;
3697
+ const Component = as ?? "span";
3698
+ return /* @__PURE__ */ jsx(Component, { ...nativeProps, ...rootAttrs, ref, children });
3699
+ };
3700
+ StepperTitle.displayName = "Stepper.Title";
3701
+ var visuallyHidden = {
3702
+ position: "absolute",
3703
+ width: 1,
3704
+ height: 1,
3705
+ margin: -1,
3706
+ padding: 0,
3707
+ overflow: "hidden",
3708
+ clip: "rect(0 0 0 0)",
3709
+ whiteSpace: "nowrap",
3710
+ border: 0
3711
+ };
3712
+ var StepperItem = (props) => {
3713
+ const theme = useComponentTheme("StepperItem");
3714
+ const { active, mode, completedLabel, errorLabel, getStepStatus, registerStep, canSelectStep, selectStep, emitStepClick } = useStepperContext("Stepper.Item");
3715
+ const { index } = useStepperItemIndex("Stepper.Item");
3716
+ const { rootAttrs, rest } = composeRootAttrs(StepperItemBase, props, theme, {
3717
+ stateAttrs: ({ error: error2 = false, disabled: disabled2 = false, isClickable: isClickable2 = true }) => ({
3718
+ "data-state": getStepStatus({ index }),
3719
+ "data-error": error2 ? "" : void 0,
3720
+ "data-disabled": disabled2 ? "" : void 0,
3721
+ // The active step is excluded: pressing it re-emits `onStepClick` but
3722
+ // can never change the selection, which is what this hook advertises.
3723
+ "data-clickable": index !== active && canSelectStep(index, { error: error2, disabled: disabled2, isClickable: isClickable2 }) ? "" : void 0
3724
+ })
3725
+ });
3726
+ const { error = false, disabled = false, isClickable = true, indicator, as, children, ref, ...nativeProps } = rest;
3727
+ useEffect(() => registerStep(index, { error, disabled, isClickable }), [registerStep, index, error, disabled, isClickable]);
3728
+ const status = getStepStatus({ index });
3729
+ const selectable = canSelectStep(index, { error, disabled, isClickable });
3730
+ const isActive = index === active;
3731
+ const ariaDisabled = selectable || isActive ? void 0 : true;
3732
+ const statusLabel = error ? errorLabel : status === "completed" ? completedLabel : void 0;
3733
+ const [descriptionId, setDescriptionId] = useState();
3734
+ const registerDescription = useCallback((id) => {
3735
+ setDescriptionId(id);
3736
+ return () => {
3737
+ setDescriptionId((current) => current === id ? void 0 : current);
3738
+ };
3739
+ }, []);
3740
+ const itemContextValue = useMemo(() => ({ registerDescription }), [registerDescription]);
3741
+ const slotLayering = {
3742
+ themeSlotProps: theme?.slotProps,
3743
+ themeClassNames: theme?.classNames,
3744
+ instanceSlotProps: props.slotProps,
3745
+ instanceClassNames: props.classNames
3746
+ };
3747
+ const triggerSlotAttrs = buildSlotAttrs(StepperItemBase.getSlotProps("trigger"), "trigger", slotLayering);
3748
+ const { onClick: triggerSlotOnClick, ...triggerAttrs } = triggerSlotAttrs;
3749
+ const railAttrs = buildSlotAttrs(StepperItemBase.getSlotProps("rail"), "rail", slotLayering);
3750
+ const indicatorAttrs = buildSlotAttrs(StepperItemBase.getSlotProps("indicator"), "indicator", slotLayering);
3751
+ const contentAttrs = buildSlotAttrs(StepperItemBase.getSlotProps("content"), "content", slotLayering);
3752
+ const resolvedIndicator = typeof indicator === "function" ? indicator({ status, index }) : indicator;
3753
+ let indicatorContent = null;
3754
+ if (!disabled) {
3755
+ if (resolvedIndicator != null) {
3756
+ indicatorContent = resolvedIndicator;
3757
+ } else if (error) {
3758
+ indicatorContent = /* @__PURE__ */ jsx(CloseIconOutlinedRounded, {});
3759
+ } else if (status === "completed") {
3760
+ indicatorContent = /* @__PURE__ */ jsx(CheckIconOutlinedRounded, {});
3761
+ }
3762
+ }
3763
+ const handleTriggerClick = (event) => {
3764
+ triggerSlotOnClick?.(event);
3765
+ if (event.defaultPrevented) return;
3766
+ if (!selectable && !(isActive && isClickable)) return;
3767
+ emitStepClick({ index, status });
3768
+ selectStep(index);
3769
+ };
3770
+ const Component = as ?? "li";
3771
+ return /* @__PURE__ */ jsx(StepperItemProvider, { value: itemContextValue, children: /* @__PURE__ */ jsxs(Component, { ...nativeProps, ...rootAttrs, ref, children: [
3772
+ mode !== "compact" && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", ...railAttrs }),
3773
+ /* @__PURE__ */ jsxs(
3774
+ "button",
3775
+ {
3776
+ ...triggerAttrs,
3777
+ type: "button",
3778
+ disabled,
3779
+ onClick: handleTriggerClick,
3780
+ "aria-current": isActive ? "step" : void 0,
3781
+ "aria-disabled": ariaDisabled,
3782
+ "aria-describedby": descriptionId,
3783
+ tabIndex: isClickable ? void 0 : -1,
3784
+ children: [
3785
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", ...indicatorAttrs, children: indicatorContent }),
3786
+ /* @__PURE__ */ jsx("span", { ...contentAttrs, children }),
3787
+ statusLabel ? /* @__PURE__ */ jsx("span", { style: visuallyHidden, children: `, ${statusLabel}` }) : null
3788
+ ]
3789
+ }
3790
+ )
3791
+ ] }) });
3792
+ };
3793
+ StepperItem.displayName = "Stepper.Item";
3794
+ var StepperDescription = (props) => {
3795
+ const theme = useComponentTheme("StepperDescription");
3796
+ const { registerDescription } = useStepperItem("Stepper.Description");
3797
+ const { rootAttrs, rest } = composeRootAttrs(StepperDescriptionBase, props, theme);
3798
+ const { as, children, ref, id: idProp, ...nativeProps } = rest;
3799
+ const autoId = useId();
3800
+ const id = idProp ?? autoId;
3801
+ useEffect(() => registerDescription(id), [registerDescription, id]);
3802
+ const Component = as ?? "span";
3803
+ return (
3804
+ // Locked after the spread: the id must match the trigger's
3805
+ // `aria-describedby` registration, and `aria-hidden` keeps the description
3806
+ // out of the trigger's accessible NAME — it still reaches assistive
3807
+ // technology as the trigger's description, since `aria-describedby` may
3808
+ // reference hidden elements.
3809
+ /* @__PURE__ */ jsx(Component, { ...nativeProps, ...rootAttrs, ref, id, "aria-hidden": "true", children })
3810
+ );
3811
+ };
3812
+ StepperDescription.displayName = "Stepper.Description";
3813
+
3814
+ // src/components/stepper/index.ts
3815
+ var Stepper2 = Object.assign(Stepper, {
3816
+ Item: StepperItem,
3817
+ Title: StepperTitle,
3818
+ Description: StepperDescription
3819
+ });
3820
+
2525
3821
  // src/components/switch/base.ts
2526
3822
  var SwitchBase = createComponentBase({
2527
3823
  name: "Switch",
@@ -2539,12 +3835,12 @@ var SwitchBase = createComponentBase({
2539
3835
  var [SwitchProvider, useSwitchOwnContext] = createSafeContext("SwitchProvider");
2540
3836
 
2541
3837
  // src/components/switch/defaults.ts
2542
- var DEFAULT_SIZE11 = "base";
2543
- var DEFAULT_VARIANT7 = "info";
3838
+ var DEFAULT_SIZE15 = "base";
3839
+ var DEFAULT_VARIANT9 = "info";
2544
3840
  var Switch = (props) => {
2545
3841
  const theme = useComponentTheme("Switch");
2546
3842
  const { rootAttrs, rest } = composeRootAttrs(SwitchBase, props, theme, {
2547
- stateAttrs: ({ size = DEFAULT_SIZE11, variant = DEFAULT_VARIANT7 }) => ({
3843
+ stateAttrs: ({ size = DEFAULT_SIZE15, variant = DEFAULT_VARIANT9 }) => ({
2548
3844
  "data-size": size,
2549
3845
  "data-variant": variant
2550
3846
  })
@@ -2555,13 +3851,17 @@ var Switch = (props) => {
2555
3851
  // off the rendered DOM where they would leak as raw HTML attributes.
2556
3852
  size: _size,
2557
3853
  variant: _variant,
2558
- // `invalid` is forwarded to Spar as `invalid` (same name).
2559
- invalid = false,
2560
3854
  children,
2561
3855
  ref,
3856
+ // `invalid`, `disabled`, `readOnly` and `required` are intentionally NOT
3857
+ // destructured (so no eager `= false` default is applied) — they flow to
3858
+ // Spar via `...sparProps` untouched. Defaulting `invalid` here would turn
3859
+ // an omitted prop into an explicit `false`, defeating Spar's
3860
+ // `invalid ?? fieldCtx?.invalid` inheritance and silently overriding a
3861
+ // wrapping `<Field invalid>`. Mirrors the Radio/Input/Select pass-through.
2562
3862
  ...sparProps
2563
3863
  } = rest;
2564
- return /* @__PURE__ */ jsx(Switch$1, { ...sparProps, invalid, ref, ...rootAttrs, children: (state) => /* @__PURE__ */ jsx(
3864
+ return /* @__PURE__ */ jsx(Switch$1, { ...sparProps, ref, ...rootAttrs, children: (state) => /* @__PURE__ */ jsx(
2565
3865
  SwitchProvider,
2566
3866
  {
2567
3867
  value: {
@@ -2667,7 +3967,7 @@ var TableBase = createComponentBase({
2667
3967
  var [TableProvider, useTableContext] = createSafeContext("Table");
2668
3968
 
2669
3969
  // src/components/table/defaults.ts
2670
- var DEFAULT_SIZE12 = "base";
3970
+ var DEFAULT_SIZE16 = "base";
2671
3971
  var DEFAULT_PAGE_SIZE = 10;
2672
3972
  var DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
2673
3973
  var DEFAULT_COLUMN_WIDTH = 150;
@@ -3193,7 +4493,7 @@ var Table = (props) => {
3193
4493
  // Visual vocabulary lives on the root so recipes cascade
3194
4494
  // to the portal-free table descendants. `data-loading` mirrors the
3195
4495
  // boolean-presence convention (rule 5).
3196
- stateAttrs: ({ size: size2 = DEFAULT_SIZE12, striped: striped2, bordered: bordered2, stickyHeader: stickyHeader2, loading: loading2 }) => ({
4496
+ stateAttrs: ({ size: size2 = DEFAULT_SIZE16, striped: striped2, bordered: bordered2, stickyHeader: stickyHeader2, loading: loading2 }) => ({
3197
4497
  "data-size": size2,
3198
4498
  "data-striped": striped2 ? "" : void 0,
3199
4499
  "data-bordered": bordered2 ? "" : void 0,
@@ -3207,7 +4507,7 @@ var Table = (props) => {
3207
4507
  getRowId,
3208
4508
  manual = false,
3209
4509
  loading = false,
3210
- size = DEFAULT_SIZE12,
4510
+ size = DEFAULT_SIZE16,
3211
4511
  striped = false,
3212
4512
  bordered = false,
3213
4513
  stickyHeader = false,
@@ -3407,19 +4707,19 @@ var TabsContentBase = createComponentBase({
3407
4707
  var [TabsOwnProvider, useTabsOwnContext] = createSafeContext("Tabs");
3408
4708
 
3409
4709
  // src/components/tabs/defaults.ts
3410
- var DEFAULT_SIZE13 = "base";
3411
- var DEFAULT_VARIANT8 = "primary";
3412
- var DEFAULT_APPEARANCE6 = "basic";
4710
+ var DEFAULT_SIZE17 = "base";
4711
+ var DEFAULT_VARIANT10 = "primary";
4712
+ var DEFAULT_APPEARANCE8 = "basic";
3413
4713
  var Tabs = (props) => {
3414
4714
  const theme = useComponentTheme("Tabs");
3415
4715
  const { rootAttrs, rest } = composeRootAttrs(TabsBase, props, theme, {
3416
- stateAttrs: ({ size: size2 = DEFAULT_SIZE13, variant: variant2 = DEFAULT_VARIANT8, appearance: appearance2 = DEFAULT_APPEARANCE6 }) => ({
4716
+ stateAttrs: ({ size: size2 = DEFAULT_SIZE17, variant: variant2 = DEFAULT_VARIANT10, appearance: appearance2 = DEFAULT_APPEARANCE8 }) => ({
3417
4717
  "data-size": size2,
3418
4718
  "data-variant": variant2,
3419
4719
  "data-type": appearance2
3420
4720
  })
3421
4721
  });
3422
- const { size = DEFAULT_SIZE13, variant = DEFAULT_VARIANT8, appearance = DEFAULT_APPEARANCE6, children, ref, ...sparProps } = rest;
4722
+ const { size = DEFAULT_SIZE17, variant = DEFAULT_VARIANT10, appearance = DEFAULT_APPEARANCE8, children, ref, ...sparProps } = rest;
3423
4723
  return /* @__PURE__ */ jsx(TabsOwnProvider, { value: { size, variant, appearance }, children: /* @__PURE__ */ jsx(Tabs$1, { ...sparProps, ...rootAttrs, ref, children }) });
3424
4724
  };
3425
4725
  Tabs.displayName = "Tabs";
@@ -3519,11 +4819,11 @@ var TooltipTrigger = (props) => {
3519
4819
  TooltipTrigger.displayName = "Tooltip.Trigger";
3520
4820
 
3521
4821
  // src/components/tooltip/defaults.ts
3522
- var DEFAULT_VARIANT9 = "white";
4822
+ var DEFAULT_VARIANT11 = "white";
3523
4823
  var TooltipContent = (props) => {
3524
4824
  const theme = useComponentTheme("TooltipContent");
3525
4825
  const { rootAttrs, rest } = composeRootAttrs(TooltipContentBase, props, theme, {
3526
- stateAttrs: ({ variant = DEFAULT_VARIANT9 }) => ({
4826
+ stateAttrs: ({ variant = DEFAULT_VARIANT11 }) => ({
3527
4827
  "data-variant": variant
3528
4828
  })
3529
4829
  });
@@ -3548,8 +4848,8 @@ TooltipDescription.displayName = "Tooltip.Description";
3548
4848
  var TooltipArrow = (props) => {
3549
4849
  const theme = useComponentTheme("TooltipArrow");
3550
4850
  const { rootAttrs, rest } = composeRootAttrs(TooltipArrowBase, props, theme);
3551
- const { ref, ...sparProps } = rest;
3552
- return /* @__PURE__ */ jsx(TooltipArrow$1, { ...sparProps, ...rootAttrs, ref });
4851
+ const { ref, children, ...sparProps } = rest;
4852
+ return /* @__PURE__ */ jsx(TooltipArrow$1, { ...sparProps, ...rootAttrs, ref, children: children ?? renderPointerArrow() });
3553
4853
  };
3554
4854
  TooltipArrow.displayName = "Tooltip.Arrow";
3555
4855
 
@@ -3633,4 +4933,42 @@ var Toaster = (props) => {
3633
4933
  };
3634
4934
  Toaster.displayName = "Toaster";
3635
4935
 
3636
- export { Accordion2 as Accordion, Alert2 as Alert, Badge, Breadcrumb2 as Breadcrumb, Button, Card2 as Card, Checkbox2 as Checkbox, Chip, Dialog2 as Dialog, Drawer2 as Drawer, Field2 as Field, Input2 as Input, Label, Popover2 as Popover, Radio2 as Radio, Select2 as Select, Spinner, Switch2 as Switch, Table, Tabs2 as Tabs, TakeoffSparProvider, Toast, Toaster, Tooltip2 as Tooltip, getExportRows, useComponentTheme, useTheme };
4936
+ // src/components/skeleton/base.ts
4937
+ var SkeletonBase = createComponentBase({
4938
+ name: "Skeleton",
4939
+ slots: ["root", "shimmer"],
4940
+ classes: {
4941
+ root: "tk-skeleton",
4942
+ shimmer: "tk-skeleton-shimmer"
4943
+ }
4944
+ });
4945
+
4946
+ // src/components/skeleton/defaults.ts
4947
+ var DEFAULT_SHAPE = "rectangle";
4948
+ var DEFAULT_ANIMATION = "shimmer";
4949
+ var toCssSize = (value) => typeof value === "number" ? `${value}px` : value;
4950
+ var Skeleton = (props) => {
4951
+ const theme = useComponentTheme("Skeleton");
4952
+ const { rootAttrs, rest } = composeRootAttrs(SkeletonBase, props, theme, {
4953
+ stateAttrs: ({ shape = DEFAULT_SHAPE, animation = DEFAULT_ANIMATION }) => ({
4954
+ "data-type": shape,
4955
+ "data-animation": animation
4956
+ })
4957
+ });
4958
+ const { shape: _shape, animation: _animation, width, height, ref, style, ...nativeProps } = rest;
4959
+ const { style: slotStyle, ...slotAttrs } = rootAttrs;
4960
+ const shimmerSlotAttrs = buildSlotAttrs(SkeletonBase.getSlotProps("shimmer"), "shimmer", {
4961
+ themeSlotProps: theme?.slotProps,
4962
+ themeClassNames: theme?.classNames,
4963
+ instanceSlotProps: props.slotProps,
4964
+ instanceClassNames: props.classNames
4965
+ });
4966
+ const sizeVars = {
4967
+ ...width !== void 0 && { "--tk-skeleton-width": toCssSize(width) },
4968
+ ...height !== void 0 && { "--tk-skeleton-height": toCssSize(height) }
4969
+ };
4970
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", ...nativeProps, ...slotAttrs, style: { ...style, ...slotStyle, ...sizeVars }, ref, children: /* @__PURE__ */ jsx("span", { ...shimmerSlotAttrs, "aria-hidden": "true" }) });
4971
+ };
4972
+ Skeleton.displayName = "Skeleton";
4973
+
4974
+ export { Accordion2 as Accordion, Alert2 as Alert, Badge, Breadcrumb2 as Breadcrumb, Button, Card2 as Card, Checkbox2 as Checkbox, Chip, Dialog2 as Dialog, Divider, Drawer2 as Drawer, Dropdown2 as Dropdown, Field2 as Field, Input2 as Input, Label, Popover2 as Popover, Progress2 as Progress, Radio2 as Radio, Select2 as Select, Skeleton, Slider2 as Slider, Spinner, Stepper2 as Stepper, Switch2 as Switch, Table, Tabs2 as Tabs, TakeoffSparProvider, Toast, Toaster, Tooltip2 as Tooltip, getExportRows, useComponentTheme, useTheme };