@mortenbrudvik/waveui 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/README.md +231 -85
  2. package/dist/components/data-display/InfoButton.cjs +2 -0
  3. package/dist/components/data-display/InfoButton.cjs.map +1 -0
  4. package/dist/components/data-display/InfoButton.mjs +173 -0
  5. package/dist/components/data-display/InfoButton.mjs.map +1 -0
  6. package/dist/components/data-display/InfoLabel.cjs +1 -1
  7. package/dist/components/data-display/InfoLabel.cjs.map +1 -1
  8. package/dist/components/data-display/InfoLabel.mjs +39 -96
  9. package/dist/components/data-display/InfoLabel.mjs.map +1 -1
  10. package/dist/components/input/Checkbox.cjs +1 -1
  11. package/dist/components/input/Checkbox.cjs.map +1 -1
  12. package/dist/components/input/Checkbox.mjs +91 -75
  13. package/dist/components/input/Checkbox.mjs.map +1 -1
  14. package/dist/components/input/ColorPicker.parts.cjs +1 -1
  15. package/dist/components/input/ColorPicker.parts.cjs.map +1 -1
  16. package/dist/components/input/ColorPicker.parts.mjs +1 -1
  17. package/dist/components/input/ColorPicker.parts.mjs.map +1 -1
  18. package/dist/components/input/Combobox.cjs +1 -1
  19. package/dist/components/input/Combobox.cjs.map +1 -1
  20. package/dist/components/input/Combobox.expand.cjs +1 -1
  21. package/dist/components/input/Combobox.expand.cjs.map +1 -1
  22. package/dist/components/input/Combobox.expand.mjs +20 -20
  23. package/dist/components/input/Combobox.expand.mjs.map +1 -1
  24. package/dist/components/input/Combobox.mjs +143 -138
  25. package/dist/components/input/Combobox.mjs.map +1 -1
  26. package/dist/components/input/DatePicker.cjs +1 -1
  27. package/dist/components/input/DatePicker.cjs.map +1 -1
  28. package/dist/components/input/DatePicker.mjs +213 -209
  29. package/dist/components/input/DatePicker.mjs.map +1 -1
  30. package/dist/components/input/Dropdown.cjs +1 -1
  31. package/dist/components/input/Dropdown.cjs.map +1 -1
  32. package/dist/components/input/Dropdown.mjs +80 -74
  33. package/dist/components/input/Dropdown.mjs.map +1 -1
  34. package/dist/components/input/Field.cjs +1 -1
  35. package/dist/components/input/Field.cjs.map +1 -1
  36. package/dist/components/input/Field.mjs +99 -66
  37. package/dist/components/input/Field.mjs.map +1 -1
  38. package/dist/components/input/Input.cjs +1 -1
  39. package/dist/components/input/Input.cjs.map +1 -1
  40. package/dist/components/input/Input.mjs +79 -55
  41. package/dist/components/input/Input.mjs.map +1 -1
  42. package/dist/components/input/Label.cjs +1 -1
  43. package/dist/components/input/Label.cjs.map +1 -1
  44. package/dist/components/input/Label.mjs +19 -13
  45. package/dist/components/input/Label.mjs.map +1 -1
  46. package/dist/components/input/Rating.cjs +1 -1
  47. package/dist/components/input/Rating.cjs.map +1 -1
  48. package/dist/components/input/Rating.item.cjs +2 -0
  49. package/dist/components/input/Rating.item.cjs.map +1 -0
  50. package/dist/components/input/Rating.item.mjs +255 -0
  51. package/dist/components/input/Rating.item.mjs.map +1 -0
  52. package/dist/components/input/Rating.mjs +150 -151
  53. package/dist/components/input/Rating.mjs.map +1 -1
  54. package/dist/components/input/SearchBox.cjs +1 -1
  55. package/dist/components/input/SearchBox.cjs.map +1 -1
  56. package/dist/components/input/SearchBox.mjs +146 -115
  57. package/dist/components/input/SearchBox.mjs.map +1 -1
  58. package/dist/components/input/Select.cjs +1 -1
  59. package/dist/components/input/Select.cjs.map +1 -1
  60. package/dist/components/input/Select.mjs +34 -25
  61. package/dist/components/input/Select.mjs.map +1 -1
  62. package/dist/components/input/Slider.cjs +1 -1
  63. package/dist/components/input/Slider.cjs.map +1 -1
  64. package/dist/components/input/Slider.mjs +77 -54
  65. package/dist/components/input/Slider.mjs.map +1 -1
  66. package/dist/components/input/SpinButton.cjs +1 -1
  67. package/dist/components/input/SpinButton.cjs.map +1 -1
  68. package/dist/components/input/SpinButton.mjs +198 -96
  69. package/dist/components/input/SpinButton.mjs.map +1 -1
  70. package/dist/components/input/Switch.cjs +1 -1
  71. package/dist/components/input/Switch.cjs.map +1 -1
  72. package/dist/components/input/Switch.mjs +71 -55
  73. package/dist/components/input/Switch.mjs.map +1 -1
  74. package/dist/components/input/TagPicker.cjs +1 -1
  75. package/dist/components/input/TagPicker.cjs.map +1 -1
  76. package/dist/components/input/TagPicker.mjs +142 -116
  77. package/dist/components/input/TagPicker.mjs.map +1 -1
  78. package/dist/components/input/Textarea.cjs +1 -1
  79. package/dist/components/input/Textarea.cjs.map +1 -1
  80. package/dist/components/input/Textarea.mjs +28 -21
  81. package/dist/components/input/Textarea.mjs.map +1 -1
  82. package/dist/components/input/TimePicker.cjs +1 -1
  83. package/dist/components/input/TimePicker.cjs.map +1 -1
  84. package/dist/components/input/TimePicker.mjs +189 -184
  85. package/dist/components/input/TimePicker.mjs.map +1 -1
  86. package/dist/components/input/fieldLabel.cjs +2 -0
  87. package/dist/components/input/fieldLabel.cjs.map +1 -0
  88. package/dist/components/input/fieldLabel.mjs +17 -0
  89. package/dist/components/input/fieldLabel.mjs.map +1 -0
  90. package/dist/components/input/inputLook.cjs +2 -0
  91. package/dist/components/input/inputLook.cjs.map +1 -0
  92. package/dist/components/input/inputLook.mjs +28 -0
  93. package/dist/components/input/inputLook.mjs.map +1 -0
  94. package/dist/components/input/pickerStyles.cjs +1 -1
  95. package/dist/components/input/pickerStyles.cjs.map +1 -1
  96. package/dist/components/input/pickerStyles.mjs +42 -4
  97. package/dist/components/input/pickerStyles.mjs.map +1 -1
  98. package/dist/components/navigation/Menu.popover.cjs +1 -1
  99. package/dist/components/navigation/Menu.popover.cjs.map +1 -1
  100. package/dist/components/navigation/Menu.popover.mjs +10 -10
  101. package/dist/components/navigation/Menu.root.cjs +1 -1
  102. package/dist/components/navigation/Menu.root.cjs.map +1 -1
  103. package/dist/components/navigation/Menu.root.mjs +10 -10
  104. package/dist/components/overlays/Popover.cjs +1 -1
  105. package/dist/components/overlays/Popover.cjs.map +1 -1
  106. package/dist/components/overlays/Popover.mjs +203 -208
  107. package/dist/components/overlays/Popover.mjs.map +1 -1
  108. package/dist/components/overlays/Popover.shared.cjs +1 -1
  109. package/dist/components/overlays/Popover.shared.cjs.map +1 -1
  110. package/dist/components/overlays/Popover.shared.mjs +82 -77
  111. package/dist/components/overlays/Popover.shared.mjs.map +1 -1
  112. package/dist/components/provider/WaveProvider.cjs +1 -1
  113. package/dist/components/provider/WaveProvider.cjs.map +1 -1
  114. package/dist/components/provider/WaveProvider.mjs +25 -19
  115. package/dist/components/provider/WaveProvider.mjs.map +1 -1
  116. package/dist/hooks/useFieldControl.cjs.map +1 -1
  117. package/dist/hooks/useFieldControl.mjs.map +1 -1
  118. package/dist/index.cjs +1 -1
  119. package/dist/index.d.cts +805 -99
  120. package/dist/index.d.ts +805 -99
  121. package/dist/index.mjs +101 -99
  122. package/dist/lib/classNames.cjs +1 -1
  123. package/dist/lib/classNames.cjs.map +1 -1
  124. package/dist/lib/classNames.mjs +74 -66
  125. package/dist/lib/classNames.mjs.map +1 -1
  126. package/dist/lib/styles.cjs +1 -1
  127. package/dist/lib/styles.cjs.map +1 -1
  128. package/dist/lib/styles.mjs +21 -4
  129. package/dist/lib/styles.mjs.map +1 -1
  130. package/dist/styles.css +1 -1
  131. package/package.json +1 -1
  132. package/src/styles/tokens.css +13 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.cjs","names":["slotRendersContent","useControllable","useId","useFieldContext","useFieldControl","joinIds","React","useMergedRefs","cn","switchClassNames","materialiseSlotContent","focusableDisabledProps","composeEventHandlers","focusRing","forcedColors","HiddenInput","require_runtime","require_cn","require_dev","require_slot","require_composeEventHandlers","require_classNames","require_useControllable","require_useId","require_useMergedRefs","require_aria","require_useFieldControl","require_styles","require_useFormReset","require_HiddenInput","react","react_jsx_runtime","onTrack","disabledOnTrack","Switch","checkedProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaDisabled","rest","onChange","hasChildren","children","checked","setChecked","defaultChecked","onCheckedChange","next","generatedId","labelTextId","field","fieldProps","required","isRequired","hasLabel","label","labelledBy","buttonRef","mergedControlRef","controlRef","form","labelText","labelFirst","labelPosition","unavailable","disabled","disabledFocusable","className","event","onClick","prev"],"sources":["../../../src/components/input/Switch.tsx"],"sourcesContent":["import * as React from 'react';\nimport { focusableDisabledProps, joinIds } from '../../lib/aria';\nimport { switchClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { materialiseSlotContent, slotRendersContent } from '../../lib/slot';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport type { LabelPosition } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\n\n/*\n * Forced colors: the focusable track keeps system-color utilities, so the browser still forces its\n * focus outline; only the thumb (the leaf indicator) opts out of forced colors. A disabled switch\n * draws a GrayText thumb and border on Canvas, without the Highlight fill.\n */\nconst onTrack = 'forced-colors:border-[Highlight] forced-colors:bg-[Highlight]';\nconst disabledOnTrack = 'forced-colors:border-[GrayText] forced-colors:bg-[Canvas]';\n\n/** Handlers that run on the `role=\"switch\"` button instead of the root label (C-ROUTING). */\ntype SwitchControlHandlers = 'onClick' | 'onFocus' | 'onBlur' | 'onKeyDown' | 'onKeyUp';\n\n/** Where a Switch renders its label: after the track (default), before it or above it. */\nexport type SwitchLabelPosition = Extract<LabelPosition, 'before' | 'after' | 'above'>;\n\n/** Properties for the Switch component. */\nexport interface SwitchProps extends Omit<\n React.HTMLAttributes<HTMLLabelElement>,\n 'onChange' | 'defaultChecked' | SwitchControlHandlers\n> {\n /** Controlled checked (on/off) state. */\n checked?: boolean;\n /** Initial checked state for uncontrolled usage (also the value a form reset restores).\n * @default false\n */\n defaultChecked?: boolean;\n /** Called with the new checked state when the switch is toggled (not for no-op updates). */\n onCheckedChange?: (checked: boolean) => void;\n /**\n * Called with the new checked state when the switch is toggled.\n * @deprecated Use `onCheckedChange`.\n */\n onChange?: (checked: boolean) => void;\n /** Whether the switch is disabled and non-interactive. */\n disabled?: boolean;\n /**\n * Marks the switch unavailable but keeps it focusable and in the tab order: for a disabled\n * switch that needs a Tooltip, or one in a toolbar. Renders `aria-disabled=\"true\"`,\n * `data-disabled` and `data-disabled-focusable` on the switch instead of the native `disabled`\n * attribute. The switch cannot be toggled and is not submitted with its form; your `onClick` is\n * not called, and a click on the switch (or Space and Enter) does not reach ancestor click\n * handlers, as for a natively disabled control. Wins over `disabled` when both are set. In a\n * roving container (a `Toolbar`) it stays in the arrow-key order.\n * @default false\n */\n disabledFocusable?: boolean;\n /**\n * Label next to the control (any phrasing content, links included, but no other form\n * controls). It names the control through `aria-labelledby`, after a consumer or Field\n * `aria-labelledby`; a consumer `aria-label` names it instead. Clicking its text toggles the\n * control; clicking a link inside it follows the link. `children` are not rendered: pass the\n * label here.\n */\n label?: React.ReactNode;\n /**\n * Where the label renders: after the control (default), before it, or above it. The DOM order\n * follows the visual order.\n * @default 'after'\n */\n labelPosition?: SwitchLabelPosition;\n /**\n * Form field name. With a name, the switch takes part in native form submission: it submits\n * `name=value` while on.\n */\n name?: string;\n /** Value submitted while on.\n * @default 'on'\n */\n value?: string;\n /** The form must not be submitted while the switch is off (native validation). */\n required?: boolean;\n /** Id of the form the switch belongs to, when it is rendered outside that form. */\n form?: string;\n /** Click handler of the switch control (the `role=\"switch\"` button). */\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n /** Focus handler of the switch control. */\n onFocus?: React.FocusEventHandler<HTMLButtonElement>;\n /** Blur handler of the switch control. */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /** Keydown handler of the switch control. */\n onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Keyup handler of the switch control. */\n onKeyUp?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Ref to the focusable `role=\"switch\"` button. */\n controlRef?: React.Ref<HTMLButtonElement>;\n /** Ref to the root `<label>` element. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * An on/off toggle drawn as a `role=\"switch\"` button inside a `<label>`.\n *\n * - The root `<label>` receives `ref`, `className`, `style` and `data-*`; the control receives\n * `id`, `aria-label`/`-labelledby`/`-describedby`/`-invalid`/`-required`/`-errormessage`/\n * `-details`/`-disabled`, `tabIndex`, `autoFocus` and the click, focus and key handlers\n * (`controlRef` exposes it). A consumer `onClick` runs once per activation, before the toggle;\n * `preventDefault()` in it cancels the toggle.\n * - Inside a `Field` it is named by the Field label (followed by its own `label` text) and described\n * by the Field message and hint.\n * - With `name` (or `required`) it takes part in native forms like `<input type=\"checkbox\">`, and\n * a form reset restores `defaultChecked`.\n * - The thumb position mirrors when the switch itself is right-to-left (its nearest `dir`), so a\n * switch in an LTR subtree of an RTL page keeps the LTR layout.\n * - `label` takes rich content (a link) and renders after the switch, or before or above it with\n * `labelPosition` (the root carries `data-label-position`). Beside the label, the switch lines\n * up with the first line of a label that wraps or has a second line. `children` are not\n * rendered (a development warning says so).\n */\nexport const Switch = ({\n checked: checkedProp,\n defaultChecked = false,\n onCheckedChange,\n onChange,\n disabled = false,\n disabledFocusable = false,\n label,\n labelPosition = 'after',\n name,\n value,\n required,\n form,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-disabled': ariaDisabled,\n autoFocus,\n tabIndex,\n onClick,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n controlRef,\n className,\n children,\n ref,\n ...rest\n}: SwitchProps) => {\n if (onChange !== undefined) warnDeprecated('Switch', 'onChange', 'onCheckedChange');\n const hasChildren = slotRendersContent(children);\n React.useEffect(() => {\n if (hasChildren) {\n warnOnce('Switch:children', 'Switch: children are not rendered. Pass the label in `label`.');\n }\n }, [hasChildren]);\n const [checked, setChecked] = useControllable(checkedProp, defaultChecked, (next: boolean) => {\n onCheckedChange?.(next);\n onChange?.(next);\n });\n\n const generatedId = useId('switch');\n const labelTextId = useId('switch-label');\n const field = useFieldContext();\n const fieldProps = useFieldControl({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n // An explicit `required={false}` wins over a required Field, so aria-required always matches\n // the native validation below (`isRequired`).\n 'aria-required': ariaRequired ?? required,\n });\n const isRequired = required ?? field?.required ?? false;\n // `0` is a label; `null`, `false`, `''` and empty collections are not (C-SLOTS).\n const hasLabel = slotRendersContent(label);\n // The label text names the control through aria-labelledby, disabled or not: axe exempts the\n // dimmed text of a disabled control only when the control references it this way (its <label>\n // exemption covers native inputs only). A consumer aria-label still names the control alone.\n // The ids already there (the consumer's, the Field label from useFieldControl) come first, then\n // the Field label whose <label htmlFor> targets this control (aria-labelledby would hide it), so\n // the name keeps every label.\n const labelledBy =\n hasLabel && fieldProps['aria-label'] === undefined\n ? joinIds(\n fieldProps['aria-labelledby'],\n field && fieldProps.id === field.controlId ? field.labelId : undefined,\n labelTextId,\n )\n : fieldProps['aria-labelledby'];\n\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const mergedControlRef = useMergedRefs(buttonRef, controlRef);\n useFormReset(buttonRef, () => setChecked(defaultChecked), form);\n\n const labelText = hasLabel ? (\n <span id={labelTextId} className={cn(switchClassNames.label, 'text-body-1 text-foreground')}>\n {materialiseSlotContent(label)}\n </span>\n ) : null;\n const labelFirst = labelPosition === 'before' || labelPosition === 'above';\n // Focusable-disabled wins over `disabled`: the switch stays focusable but looks and acts disabled.\n const unavailable = disabled || disabledFocusable;\n\n return (\n <label\n ref={ref}\n data-label-position={labelPosition}\n className={cn(\n switchClassNames.root,\n // items-start: the 20px track lines up with the 20px first line of a label that wraps or\n // has a second line, not with its middle.\n 'relative inline-flex items-start gap-2 select-none',\n labelPosition === 'above' && 'flex-col gap-1',\n // The dimmed look lifts while a focus ring shows inside the root (the control's, under\n // disabledFocusable, or a link's in the label): opacity would dim the ring below 3:1.\n unavailable\n ? 'cursor-not-allowed opacity-50 has-focus-visible:opacity-100'\n : 'cursor-pointer',\n className,\n )}\n {...rest}\n >\n {labelFirst && labelText}\n <button\n id={generatedId}\n type=\"button\"\n {...fieldProps}\n aria-labelledby={labelledBy}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-disabled={ariaDisabled}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n onFocus={onFocus}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n ref={mergedControlRef}\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled && !disabledFocusable}\n {...focusableDisabledProps(disabledFocusable, { reachable: true })}\n onClick={\n disabledFocusable\n ? // Clicks, Space and Enter (which click a button) neither toggle nor reach `onClick`,\n // and, as a natively disabled control dispatches no click, no ancestor sees them.\n (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : composeEventHandlers(onClick, () => setChecked((prev) => !prev))\n }\n className={cn(\n switchClassNames.track,\n // The whole control is sized in px, like the Checkbox box and the radio circle: the thumb\n // and its offsets are px, so a track in rem would stop fitting them at any root font size\n // other than 16px. The 40x20 track (1px border) leaves a 2px inset around the 14px thumb.\n // p-0 is set here, not left to the native reset, which any app button style overrides\n // (C-NATIVE): the thumb offsets assume no padding.\n 'relative inline-flex h-[20px] w-[40px] shrink-0 items-center rounded-full border p-0 transition-colors duration-200 motion-reduce:transition-none',\n focusRing,\n checked\n ? cn('border-primary bg-primary', unavailable ? disabledOnTrack : onTrack)\n : cn(\n 'border-stroke-accessible bg-transparent',\n unavailable ? forcedColors.disabled : forcedColors.control,\n ),\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n switchClassNames.thumb,\n 'block h-[14px] w-[14px] rounded-full transition-transform duration-200 motion-reduce:transition-none forced-colors:forced-color-adjust-none',\n checked\n ? 'translate-x-[22px] wave-rtl:-translate-x-[22px] bg-primary-foreground'\n : 'translate-x-[2px] wave-rtl:-translate-x-[2px] bg-stroke-accessible',\n unavailable\n ? 'forced-colors:bg-[GrayText]'\n : checked\n ? 'forced-colors:bg-[HighlightText]'\n : 'forced-colors:bg-[ButtonText]',\n )}\n />\n </button>\n {!labelFirst && labelText}\n <HiddenInput\n type=\"checkbox\"\n name={name}\n form={form}\n disabled={unavailable}\n value={value}\n checked={checked}\n required={isRequired}\n onInvalid={() => buttonRef.current?.focus()}\n />\n </label>\n );\n};\n\nSwitch.displayName = 'Switch';\n"],"mappings":"ooBAqBA,IAAMgC,EAAU,gEACVC,EAAkB,4DAqGXC,GAAU,CACrB,QAASC,EACT,iBAAiB,GACjB,kBACA,WACA,WAAW,GACX,oBAAoB,GACpB,QACA,gBAAgB,QAChB,OACA,QACA,WACA,OACA,MACA,aAAcC,GACd,kBAAmBC,GACnB,mBAAoBC,EACpB,eAAgBC,EAChB,gBAAiBC,EACjB,oBAAqBC,EACrB,eAAgBC,EAChB,gBAAiBC,EACjB,YACA,WACA,UACA,UACA,SACA,YACA,UACA,aACA,YACA,YACA,MACA,GAAGC,KACc,CACbC,IAAa,IAAA,IAAW3B,EAAA,eAAe,SAAU,WAAY,iBAAiB,EAClF,IAAM4B,EAAc9C,EAAAA,mBAAmB+C,EAAQ,EAC/CjB,EAAM,cAAgB,CAChBgB,GACF5B,EAAA,SAAS,kBAAmB,+DAA+D,CAE/F,EAAG,CAAC4B,CAAW,CAAC,EAChB,GAAM,CAACE,EAASC,GAAchD,GAAAA,gBAAgBkC,EAAae,EAAiB,GAAkB,CAC5FC,IAAkBC,CAAI,EACtBP,IAAWO,CAAI,CACjB,CAAC,EAEKC,EAAcnD,EAAAA,MAAM,QAAQ,EAC5BoD,EAAcpD,EAAAA,MAAM,cAAc,EAClCqD,EAAQpD,EAAAA,gBAAgB,EACxBqD,EAAapD,EAAAA,gBAAgB,CACjC,MACA,aAAcgC,GACd,kBAAmBC,GACnB,mBAAoBC,EACpB,eAAgBC,EAGhB,gBAAiBC,GAAgBiB,CACnC,CAAC,EACKC,GAAaD,GAAYF,GAAO,UAAY,GAE5CI,EAAW3D,EAAAA,mBAAmB4D,CAAK,EAOnCC,GACJF,GAAYH,EAAW,gBAAkB,IAAA,GACrCnD,EAAAA,QACEmD,EAAW,mBACXD,GAASC,EAAW,KAAOD,EAAM,UAAYA,EAAM,QAAU,IAAA,GAC7DD,CACF,EACAE,EAAW,mBAEXM,EAAYxD,EAAM,OAA0B,IAAI,EAChDyD,GAAmBxD,EAAAA,cAAcuD,EAAWE,CAAU,EAC5DpC,GAAA,aAAakC,MAAiBb,EAAWC,CAAc,EAAGe,CAAI,EAE9D,IAAMC,EAAYP,GAChB,EAAA5B,EAAA,IAAA,CAAC,OAAD,CAAM,GAAIuB,EAAa,UAAW9C,EAAAA,GAAGC,EAAAA,iBAAiB,MAAO,6BAA6B,EACvF,SAAAC,EAAAA,uBAAuBkD,CAAK,CACzB,CAAA,EACJ,KACEO,EAAaC,IAAkB,UAAYA,IAAkB,QAE7DC,EAAcC,GAAYC,EAEhC,OACE,EAAAxC,EAAA,KAAA,CAAC,QAAD,CACO,MACL,sBAAqBqC,EACrB,UAAW5D,EAAAA,GACTC,EAAAA,iBAAiB,KAGjB,qDACA2D,IAAkB,SAAW,iBAG7BC,EACI,8DACA,iBACJG,CACF,EACA,GAAI5B,EAhBN,SAAA,CAkBGuB,GAAcD,GACf,EAAAnC,EAAA,IAAA,CAAC,SAAD,CACE,GAAIsB,EACJ,KAAK,SACL,GAAIG,EACJ,kBAAiBK,GACjB,oBAAmBpB,EACnB,eAAcC,EACd,gBAAeC,EACJ,YACD,WACD,UACD,SACG,YACF,UACT,IAAKoB,GACL,KAAK,SACL,eAAcf,EACd,SAAUsB,GAAY,CAACC,EACvB,GAAI5D,EAAAA,uBAAuB4D,EAAmB,CAAE,UAAW,EAAK,CAAC,EACjE,QACEA,EAGK,GAA+C,CAC9CE,EAAM,eAAe,EACrBA,EAAM,gBAAgB,CACxB,EACA7D,GAAAA,qBAAqB8D,MAAezB,EAAY,GAAS,CAAC0B,CAAI,CAAC,EAErE,UAAWnE,EAAAA,GACTC,EAAAA,iBAAiB,MAMjB,oJACAI,EAAAA,UACAmC,EACIxC,EAAAA,GAAG,4BAA6B6D,EAAcpC,EAAkBD,CAAO,EACvExB,EAAAA,GACE,0CACA6D,EAAcvD,EAAAA,aAAa,SAAWA,EAAAA,aAAa,OACrD,CACN,EAEA,UAAA,EAAAiB,EAAA,IAAA,CAAC,OAAD,CACE,cAAY,OACZ,UAAWvB,EAAAA,GACTC,EAAAA,iBAAiB,MACjB,8IACAuC,EACI,wEACA,qEACJqB,EACI,8BACArB,EACE,mCACA,+BACR,CACD,CAAA,CACK,CAAA,EACP,CAACmB,GAAcD,GAChB,EAAAnC,EAAA,IAAA,CAAChB,GAAAA,YAAD,CACE,KAAK,WACC,OACA,OACN,SAAUsD,EACH,QACE,UACT,SAAUX,GACV,cAAiBI,EAAU,SAAS,MAAM,CAC3C,CAAA,CACI,GAEX,EAEA,EAAO,YAAc"}
1
+ {"version":3,"file":"Switch.cjs","names":["slotRendersContent","useControllable","useId","useFieldContext","useFieldControl","joinIds","React","useMergedRefs","cn","switchClassNames","materialiseSlotContent","focusableDisabledProps","composeEventHandlers","focusRing","forcedColors","HiddenInput","require_runtime","require_cn","require_dev","require_slot","require_composeEventHandlers","require_classNames","require_useControllable","require_useId","require_useMergedRefs","require_aria","require_useFieldControl","require_styles","require_useFormReset","require_HiddenInput","react","react_jsx_runtime","onTrack","disabledOnTrack","SWITCH_SIZE","Switch","checkedProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaDisabled","rest","onChange","hasChildren","children","checked","setChecked","defaultChecked","onCheckedChange","next","generatedId","labelTextId","field","fieldProps","required","isRequired","hasLabel","label","labelledBy","buttonRef","mergedControlRef","controlRef","form","resolvedSize","size","sizeMetrics","labelText","labelFirst","labelPosition","unavailable","disabled","disabledFocusable","className","event","onClick","prev"],"sources":["../../../src/components/input/Switch.tsx"],"sourcesContent":["import * as React from 'react';\nimport { focusableDisabledProps, joinIds } from '../../lib/aria';\nimport { switchClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { materialiseSlotContent, slotRendersContent } from '../../lib/slot';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport type { LabelPosition, Size } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\n\n/*\n * Forced colors: the focusable track keeps system-color utilities, so the browser still forces its\n * focus outline; only the thumb (the leaf indicator) opts out of forced colors. A disabled switch\n * draws a GrayText thumb and border on Canvas, without the Highlight fill.\n */\nconst onTrack = 'forced-colors:border-[Highlight] forced-colors:bg-[Highlight]';\nconst disabledOnTrack = 'forced-colors:border-[GrayText] forced-colors:bg-[Canvas]';\n\n/** Handlers that run on the `role=\"switch\"` button instead of the root label (C-ROUTING). */\ntype SwitchControlHandlers = 'onClick' | 'onFocus' | 'onBlur' | 'onKeyDown' | 'onKeyUp';\n\n/** Where a Switch renders its label: after the track (default), before it or above it. */\nexport type SwitchLabelPosition = Extract<LabelPosition, 'before' | 'after' | 'above'>;\n\n/** Size of the track: a 32x16 track with a 10px thumb, or the 0.7 40x20 track with a 14px thumb. */\nexport type SwitchSize = Extract<Size, 'small' | 'medium'>;\n\n/** Per-size track, thumb and label-offset classes. */\nconst SWITCH_SIZE: Readonly<\n Record<SwitchSize, { track: string; thumb: string; on: string; off: string; offset: string }>\n> = {\n small: {\n // The target layer is placed against the padding box inside the 1px border: 14 + 2 × 5 = 24px.\n track: 'h-[16px] w-[32px] before:absolute before:inset-x-0 before:-inset-y-[5px]',\n thumb: 'h-[10px] w-[10px]',\n on: 'translate-x-[18px] wave-rtl:-translate-x-[18px]',\n off: 'translate-x-[2px] wave-rtl:-translate-x-[2px]',\n offset: 'mt-0.5',\n },\n medium: {\n track: 'h-[20px] w-[40px]',\n thumb: 'h-[14px] w-[14px]',\n on: 'translate-x-[22px] wave-rtl:-translate-x-[22px]',\n off: 'translate-x-[2px] wave-rtl:-translate-x-[2px]',\n offset: '',\n },\n};\n\n/** Properties for the Switch component. */\nexport interface SwitchProps extends Omit<\n React.HTMLAttributes<HTMLLabelElement>,\n 'onChange' | 'defaultChecked' | SwitchControlHandlers\n> {\n /** Controlled checked (on/off) state. */\n checked?: boolean;\n /** Initial checked state for uncontrolled usage (also the value a form reset restores).\n * @default false\n */\n defaultChecked?: boolean;\n /** Called with the new checked state when the switch is toggled (not for no-op updates). */\n onCheckedChange?: (checked: boolean) => void;\n /**\n * Called with the new checked state when the switch is toggled.\n * @deprecated Use `onCheckedChange`.\n */\n onChange?: (checked: boolean) => void;\n /** Whether the switch is disabled and non-interactive. */\n disabled?: boolean;\n /**\n * Marks the switch unavailable but keeps it focusable and in the tab order: for a disabled\n * switch that needs a Tooltip, or one in a toolbar. Renders `aria-disabled=\"true\"`,\n * `data-disabled` and `data-disabled-focusable` on the switch instead of the native `disabled`\n * attribute. The switch cannot be toggled and is not submitted with its form; your `onClick` is\n * not called, and a click on the switch (or Space and Enter) does not reach ancestor click\n * handlers, as for a natively disabled control. Wins over `disabled` when both are set. In a\n * roving container (a `Toolbar`) it stays in the arrow-key order.\n * @default false\n */\n disabledFocusable?: boolean;\n /**\n * Label next to the control (any phrasing content, links included, but no other form\n * controls). It names the control through `aria-labelledby`, after a consumer or Field\n * `aria-labelledby`; a consumer `aria-label` names it instead. Clicking its text toggles the\n * control; clicking a link inside it follows the link. `children` are not rendered: pass the\n * label here.\n */\n label?: React.ReactNode;\n /**\n * Where the label renders: after the control (default), before it, or above it. The DOM order\n * follows the visual order.\n * @default 'after'\n */\n labelPosition?: SwitchLabelPosition;\n /**\n * Size of the track: the 0.7 40x20 track with a 14px thumb, or a small 32x16 track with a 10px\n * thumb and a 24px-tall pointer target. Unlike the text controls and pickers, Switch does not\n * read a surrounding Field's size or a WaveProvider's input defaults: this prop is the only\n * source of its size.\n * @default 'medium'\n */\n size?: SwitchSize;\n /**\n * Form field name. With a name, the switch takes part in native form submission: it submits\n * `name=value` while on.\n */\n name?: string;\n /** Value submitted while on.\n * @default 'on'\n */\n value?: string;\n /** The form must not be submitted while the switch is off (native validation). */\n required?: boolean;\n /** Id of the form the switch belongs to, when it is rendered outside that form. */\n form?: string;\n /** Click handler of the switch control (the `role=\"switch\"` button). */\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n /** Focus handler of the switch control. */\n onFocus?: React.FocusEventHandler<HTMLButtonElement>;\n /** Blur handler of the switch control. */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /** Keydown handler of the switch control. */\n onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Keyup handler of the switch control. */\n onKeyUp?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Ref to the focusable `role=\"switch\"` button. */\n controlRef?: React.Ref<HTMLButtonElement>;\n /** Ref to the root `<label>` element. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * An on/off toggle drawn as a `role=\"switch\"` button inside a `<label>`.\n *\n * - The root `<label>` receives `ref`, `className`, `style` and `data-*`; the control receives\n * `id`, `aria-label`/`-labelledby`/`-describedby`/`-invalid`/`-required`/`-errormessage`/\n * `-details`/`-disabled`, `tabIndex`, `autoFocus` and the click, focus and key handlers\n * (`controlRef` exposes it). A consumer `onClick` runs once per activation, before the toggle;\n * `preventDefault()` in it cancels the toggle.\n * - Inside a `Field` it is named by the Field label (followed by its own `label` text) and described\n * by the Field message and hint.\n * - With `name` (or `required`) it takes part in native forms like `<input type=\"checkbox\">`, and\n * a form reset restores `defaultChecked`.\n * - The thumb position mirrors when the switch itself is right-to-left (its nearest `dir`), so a\n * switch in an LTR subtree of an RTL page keeps the LTR layout.\n * - `label` takes rich content (a link) and renders after the switch, or before or above it with\n * `labelPosition` (the root carries `data-label-position`). Beside the label, the switch lines\n * up with the first line of a label that wraps or has a second line. `children` are not\n * rendered (a development warning says so).\n * - `size` (`small`, `medium`) sets the track and thumb dimensions; the root carries `data-size`.\n * Switch does not read a surrounding `Field`'s size or a `WaveProvider`'s input defaults.\n */\nexport const Switch = ({\n checked: checkedProp,\n defaultChecked = false,\n onCheckedChange,\n onChange,\n disabled = false,\n disabledFocusable = false,\n label,\n labelPosition = 'after',\n size = 'medium',\n name,\n value,\n required,\n form,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-disabled': ariaDisabled,\n autoFocus,\n tabIndex,\n onClick,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n controlRef,\n className,\n children,\n ref,\n ...rest\n}: SwitchProps) => {\n if (onChange !== undefined) warnDeprecated('Switch', 'onChange', 'onCheckedChange');\n const hasChildren = slotRendersContent(children);\n React.useEffect(() => {\n if (hasChildren) {\n warnOnce('Switch:children', 'Switch: children are not rendered. Pass the label in `label`.');\n }\n }, [hasChildren]);\n const [checked, setChecked] = useControllable(checkedProp, defaultChecked, (next: boolean) => {\n onCheckedChange?.(next);\n onChange?.(next);\n });\n\n const generatedId = useId('switch');\n const labelTextId = useId('switch-label');\n const field = useFieldContext();\n const fieldProps = useFieldControl({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n // An explicit `required={false}` wins over a required Field, so aria-required always matches\n // the native validation below (`isRequired`).\n 'aria-required': ariaRequired ?? required,\n });\n const isRequired = required ?? field?.required ?? false;\n // `0` is a label; `null`, `false`, `''` and empty collections are not (C-SLOTS).\n const hasLabel = slotRendersContent(label);\n // The label text names the control through aria-labelledby, disabled or not: axe exempts the\n // dimmed text of a disabled control only when the control references it this way (its <label>\n // exemption covers native inputs only). A consumer aria-label still names the control alone.\n // The ids already there (the consumer's, the Field label from useFieldControl) come first, then\n // the Field label whose <label htmlFor> targets this control (aria-labelledby would hide it), so\n // the name keeps every label.\n const labelledBy =\n hasLabel && fieldProps['aria-label'] === undefined\n ? joinIds(\n fieldProps['aria-labelledby'],\n field && fieldProps.id === field.controlId ? field.labelId : undefined,\n labelTextId,\n )\n : fieldProps['aria-labelledby'];\n\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const mergedControlRef = useMergedRefs(buttonRef, controlRef);\n useFormReset(buttonRef, () => setChecked(defaultChecked), form);\n\n // A size outside the union (from untyped code) renders, and is reported in the data attribute,\n // as the default: TypeScript rejects one, but the value still reaches this render.\n const resolvedSize: SwitchSize = Object.hasOwn(SWITCH_SIZE, size) ? size : 'medium';\n const sizeMetrics = SWITCH_SIZE[resolvedSize];\n const labelText = hasLabel ? (\n <span id={labelTextId} className={cn(switchClassNames.label, 'text-body-1 text-foreground')}>\n {materialiseSlotContent(label)}\n </span>\n ) : null;\n const labelFirst = labelPosition === 'before' || labelPosition === 'above';\n // Focusable-disabled wins over `disabled`: the switch stays focusable but looks and acts disabled.\n const unavailable = disabled || disabledFocusable;\n\n return (\n <label\n ref={ref}\n data-label-position={labelPosition}\n data-size={resolvedSize}\n className={cn(\n switchClassNames.root,\n // items-start: the track lines up with the top of the label's first line, not its\n // middle, when the label wraps or has a second line; medium's 20px track matches that\n // 20px line exactly, small's 16px track gets an offset below to stay centred on it.\n 'relative inline-flex items-start gap-2 select-none',\n labelPosition === 'above' && 'flex-col gap-1',\n // The dimmed look lifts while a focus ring shows inside the root (the control's, under\n // disabledFocusable, or a link's in the label): opacity would dim the ring below 3:1.\n unavailable\n ? 'cursor-not-allowed opacity-50 has-focus-visible:opacity-100'\n : 'cursor-pointer',\n className,\n )}\n {...rest}\n >\n {labelFirst && labelText}\n <button\n id={generatedId}\n type=\"button\"\n {...fieldProps}\n aria-labelledby={labelledBy}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-disabled={ariaDisabled}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n onFocus={onFocus}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n ref={mergedControlRef}\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled && !disabledFocusable}\n {...focusableDisabledProps(disabledFocusable, { reachable: true })}\n onClick={\n disabledFocusable\n ? // Clicks, Space and Enter (which click a button) neither toggle nor reach `onClick`,\n // and, as a natively disabled control dispatches no click, no ancestor sees them.\n (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : composeEventHandlers(onClick, () => setChecked((prev) => !prev))\n }\n className={cn(\n switchClassNames.track,\n // The whole control is sized in px, like the Checkbox box and the radio circle: the\n // thumb and its offsets are px, so a track in rem would stop fitting them at any root\n // font size other than 16px. Medium keeps the 0.7 look, a 40x20 track around a 14px\n // thumb, a 2px gap on every side. Small is a 32x16 track around a 10px thumb, the same\n // 2px gap, and a transparent strip behind the track that grows the pointer target to\n // 24px tall. No padding is assumed here, unlike the native reset that any app button\n // style overrides (C-NATIVE): the thumb offsets rely on it staying at zero.\n 'relative inline-flex shrink-0 items-center rounded-full border p-0 transition-colors duration-200 motion-reduce:transition-none',\n sizeMetrics.track,\n // The offset centres the track on the label line beside it; above the label, the\n // column gap alone separates them.\n hasLabel && labelPosition !== 'above' && sizeMetrics.offset,\n focusRing,\n checked\n ? cn('border-primary bg-primary', unavailable ? disabledOnTrack : onTrack)\n : cn(\n 'border-stroke-accessible bg-transparent',\n unavailable ? forcedColors.disabled : forcedColors.control,\n ),\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n switchClassNames.thumb,\n 'block rounded-full transition-transform duration-200 motion-reduce:transition-none forced-colors:forced-color-adjust-none',\n sizeMetrics.thumb,\n checked\n ? cn(sizeMetrics.on, 'bg-primary-foreground')\n : cn(sizeMetrics.off, 'bg-stroke-accessible'),\n unavailable\n ? 'forced-colors:bg-[GrayText]'\n : checked\n ? 'forced-colors:bg-[HighlightText]'\n : 'forced-colors:bg-[ButtonText]',\n )}\n />\n </button>\n {!labelFirst && labelText}\n <HiddenInput\n type=\"checkbox\"\n name={name}\n form={form}\n disabled={unavailable}\n value={value}\n checked={checked}\n required={isRequired}\n onInvalid={() => buttonRef.current?.focus()}\n />\n </label>\n );\n};\n\nSwitch.displayName = 'Switch';\n"],"mappings":"moBAqBA,IAAMgC,GAAU,gEACVC,GAAkB,4DAYlBC,EAEF,CACF,MAAO,CAEL,MAAO,2EACP,MAAO,oBACP,GAAI,kDACJ,IAAK,gDACL,OAAQ,QACV,EACA,OAAQ,CACN,MAAO,oBACP,MAAO,oBACP,GAAI,kDACJ,IAAK,gDACL,OAAQ,EACV,CACF,EAyGaC,GAAU,CACrB,QAASC,EACT,iBAAiB,GACjB,kBACA,WACA,WAAW,GACX,oBAAoB,GACpB,QACA,gBAAgB,QAChB,OAAO,SACP,OACA,QACA,WACA,OACA,MACA,aAAcC,GACd,kBAAmBC,GACnB,mBAAoBC,GACpB,eAAgBC,GAChB,gBAAiBC,EACjB,oBAAqBC,EACrB,eAAgBC,EAChB,gBAAiBC,EACjB,YACA,WACA,UACA,UACA,SACA,YACA,UACA,aACA,YACA,WACA,MACA,GAAGC,MACc,CACbC,IAAa,IAAA,IAAW5B,EAAA,eAAe,SAAU,WAAY,iBAAiB,EAClF,IAAM6B,EAAc/C,EAAAA,mBAAmBgD,CAAQ,EAC/ClB,EAAM,cAAgB,CAChBiB,GACF7B,EAAA,SAAS,kBAAmB,+DAA+D,CAE/F,EAAG,CAAC6B,CAAW,CAAC,EAChB,GAAM,CAACE,EAASC,GAAcjD,EAAAA,gBAAgBmC,EAAae,EAAiB,GAAkB,CAC5FC,IAAkBC,CAAI,EACtBP,IAAWO,CAAI,CACjB,CAAC,EAEKC,GAAcpD,EAAAA,MAAM,QAAQ,EAC5BqD,EAAcrD,EAAAA,MAAM,cAAc,EAClCsD,EAAQrD,EAAAA,gBAAgB,EACxBsD,EAAarD,EAAAA,gBAAgB,CACjC,MACA,aAAciC,GACd,kBAAmBC,GACnB,mBAAoBC,GACpB,eAAgBC,GAGhB,gBAAiBC,GAAgBiB,CACnC,CAAC,EACKC,GAAaD,GAAYF,GAAO,UAAY,GAE5CI,EAAW5D,EAAAA,mBAAmB6D,CAAK,EAOnCC,GACJF,GAAYH,EAAW,gBAAkB,IAAA,GACrCpD,EAAAA,QACEoD,EAAW,mBACXD,GAASC,EAAW,KAAOD,EAAM,UAAYA,EAAM,QAAU,IAAA,GAC7DD,CACF,EACAE,EAAW,mBAEXM,EAAYzD,EAAM,OAA0B,IAAI,EAChD0D,GAAmBzD,EAAAA,cAAcwD,EAAWE,CAAU,EAC5DrC,GAAA,aAAamC,MAAiBb,EAAWC,CAAc,EAAGe,CAAI,EAI9D,IAAMC,EAA2B,OAAO,OAAOjC,EAAakC,CAAI,EAAIA,EAAO,SACrEC,EAAcnC,EAAYiC,GAC1BG,EAAYV,GAChB,EAAA7B,EAAA,IAAA,CAAC,OAAD,CAAM,GAAIwB,EAAa,UAAW/C,EAAAA,GAAGC,EAAAA,iBAAiB,MAAO,6BAA6B,EACvF,SAAAC,EAAAA,uBAAuBmD,CAAK,CACzB,CAAA,EACJ,KACEU,EAAaC,IAAkB,UAAYA,IAAkB,QAE7DC,EAAcC,GAAYC,EAEhC,OACE,EAAA5C,EAAA,KAAA,CAAC,QAAD,CACO,MACL,sBAAqByC,EACrB,YAAWL,EACX,UAAW3D,EAAAA,GACTC,EAAAA,iBAAiB,KAIjB,qDACA+D,IAAkB,SAAW,iBAG7BC,EACI,8DACA,iBACJG,CACF,EACA,GAAI/B,GAlBN,SAAA,CAoBG0B,GAAcD,GACf,EAAAvC,EAAA,IAAA,CAAC,SAAD,CACE,GAAIuB,GACJ,KAAK,SACL,GAAIG,EACJ,kBAAiBK,GACjB,oBAAmBpB,EACnB,eAAcC,EACd,gBAAeC,EACJ,YACD,WACD,UACD,SACG,YACF,UACT,IAAKoB,GACL,KAAK,SACL,eAAcf,EACd,SAAUyB,GAAY,CAACC,EACvB,GAAIhE,EAAAA,uBAAuBgE,EAAmB,CAAE,UAAW,EAAK,CAAC,EACjE,QACEA,EAGK,GAA+C,CAC9CE,EAAM,eAAe,EACrBA,EAAM,gBAAgB,CACxB,EACAjE,GAAAA,qBAAqBkE,MAAe5B,EAAY,GAAS,CAAC6B,CAAI,CAAC,EAErE,UAAWvE,EAAAA,GACTC,EAAAA,iBAAiB,MAQjB,kIACA4D,EAAY,MAGZT,GAAYY,IAAkB,SAAWH,EAAY,OACrDxD,EAAAA,UACAoC,EACIzC,EAAAA,GAAG,4BAA6BiE,EAAcxC,GAAkBD,EAAO,EACvExB,EAAAA,GACE,0CACAiE,EAAc3D,EAAAA,aAAa,SAAWA,EAAAA,aAAa,OACrD,CACN,EAEA,UAAA,EAAAiB,EAAA,IAAA,CAAC,OAAD,CACE,cAAY,OACZ,UAAWvB,EAAAA,GACTC,EAAAA,iBAAiB,MACjB,4HACA4D,EAAY,MACZpB,EACIzC,EAAAA,GAAG6D,EAAY,GAAI,uBAAuB,EAC1C7D,EAAAA,GAAG6D,EAAY,IAAK,sBAAsB,EAC9CI,EACI,8BACAxB,EACE,mCACA,+BACR,CACD,CAAA,CACK,CAAA,EACP,CAACsB,GAAcD,GAChB,EAAAvC,EAAA,IAAA,CAAChB,GAAAA,YAAD,CACE,KAAK,WACC,OACA,OACN,SAAU0D,EACH,QACE,UACT,SAAUd,GACV,cAAiBI,EAAU,SAAS,MAAM,CAC3C,CAAA,CACI,GAEX,EAEA,EAAO,YAAc"}
@@ -1,93 +1,109 @@
1
1
  "use client";
2
2
  import { cn as e } from "../../lib/cn.mjs";
3
- import { warnDeprecated as t, warnOnce as n } from "../../lib/dev.mjs";
4
- import { materialiseSlotContent as ee, slotRendersContent as r } from "../../lib/slot.mjs";
5
- import { composeEventHandlers as te } from "../../lib/composeEventHandlers.mjs";
3
+ import { warnDeprecated as t, warnOnce as ee } from "../../lib/dev.mjs";
4
+ import { materialiseSlotContent as te, slotRendersContent as n } from "../../lib/slot.mjs";
5
+ import { composeEventHandlers as r } from "../../lib/composeEventHandlers.mjs";
6
6
  import { switchClassNames as i } from "../../lib/classNames.mjs";
7
- import { useControllable as a } from "../../hooks/useControllable.mjs";
8
- import { useId as o } from "../../hooks/useId.mjs";
9
- import { useMergedRefs as ne } from "../../hooks/useMergedRefs.mjs";
10
- import { focusableDisabledProps as re, joinIds as ie } from "../../lib/aria.mjs";
11
- import { useFieldContext as ae, useFieldControl as s } from "../../hooks/useFieldControl.mjs";
12
- import { focusRing as oe, forcedColors as c } from "../../lib/styles.mjs";
13
- import { useFormReset as se } from "../../hooks/useFormReset.mjs";
14
- import { HiddenInput as ce } from "../internal/HiddenInput.mjs";
15
- import * as l from "react";
16
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
7
+ import { useControllable as ne } from "../../hooks/useControllable.mjs";
8
+ import { useId as a } from "../../hooks/useId.mjs";
9
+ import { useMergedRefs as re } from "../../hooks/useMergedRefs.mjs";
10
+ import { focusableDisabledProps as ie, joinIds as ae } from "../../lib/aria.mjs";
11
+ import { useFieldContext as oe, useFieldControl as se } from "../../hooks/useFieldControl.mjs";
12
+ import { focusRing as ce, forcedColors as o } from "../../lib/styles.mjs";
13
+ import { useFormReset as le } from "../../hooks/useFormReset.mjs";
14
+ import { HiddenInput as s } from "../internal/HiddenInput.mjs";
15
+ import * as c from "react";
16
+ import { jsx as l, jsxs as ue } from "react/jsx-runtime";
17
17
  //#region src/components/input/Switch.tsx
18
- var f = "forced-colors:border-[Highlight] forced-colors:bg-[Highlight]", le = "forced-colors:border-[GrayText] forced-colors:bg-[Canvas]", p = ({ checked: p, defaultChecked: m = !1, onCheckedChange: ue, onChange: h, disabled: g = !1, disabledFocusable: _ = !1, label: v, labelPosition: y = "after", name: b, value: x, required: S, form: C, id: w, "aria-label": T, "aria-labelledby": E, "aria-describedby": D, "aria-invalid": O, "aria-required": k, "aria-errormessage": A, "aria-details": j, "aria-disabled": M, autoFocus: N, tabIndex: P, onClick: F, onFocus: I, onBlur: de, onKeyDown: L, onKeyUp: R, controlRef: z, className: B, children: V, ref: H, ...fe }) => {
19
- h !== void 0 && t("Switch", "onChange", "onCheckedChange");
20
- let U = r(V);
21
- l.useEffect(() => {
22
- U && n("Switch:children", "Switch: children are not rendered. Pass the label in `label`.");
23
- }, [U]);
24
- let [W, G] = a(p, m, (e) => {
25
- ue?.(e), h?.(e);
26
- }), pe = o("switch"), K = o("switch-label"), q = ae(), J = s({
18
+ var de = "forced-colors:border-[Highlight] forced-colors:bg-[Highlight]", u = "forced-colors:border-[GrayText] forced-colors:bg-[Canvas]", d = {
19
+ small: {
20
+ track: "h-[16px] w-[32px] before:absolute before:inset-x-0 before:-inset-y-[5px]",
21
+ thumb: "h-[10px] w-[10px]",
22
+ on: "translate-x-[18px] wave-rtl:-translate-x-[18px]",
23
+ off: "translate-x-[2px] wave-rtl:-translate-x-[2px]",
24
+ offset: "mt-0.5"
25
+ },
26
+ medium: {
27
+ track: "h-[20px] w-[40px]",
28
+ thumb: "h-[14px] w-[14px]",
29
+ on: "translate-x-[22px] wave-rtl:-translate-x-[22px]",
30
+ off: "translate-x-[2px] wave-rtl:-translate-x-[2px]",
31
+ offset: ""
32
+ }
33
+ }, f = ({ checked: f, defaultChecked: p = !1, onCheckedChange: fe, onChange: m, disabled: h = !1, disabledFocusable: g = !1, label: _, labelPosition: v = "after", size: y = "medium", name: b, value: x, required: S, form: C, id: w, "aria-label": T, "aria-labelledby": E, "aria-describedby": D, "aria-invalid": O, "aria-required": k, "aria-errormessage": A, "aria-details": j, "aria-disabled": M, autoFocus: N, tabIndex: P, onClick: F, onFocus: I, onBlur: L, onKeyDown: R, onKeyUp: pe, controlRef: z, className: B, children: me, ref: he, ...ge }) => {
34
+ m !== void 0 && t("Switch", "onChange", "onCheckedChange");
35
+ let V = n(me);
36
+ c.useEffect(() => {
37
+ V && ee("Switch:children", "Switch: children are not rendered. Pass the label in `label`.");
38
+ }, [V]);
39
+ let [H, U] = ne(f, p, (e) => {
40
+ fe?.(e), m?.(e);
41
+ }), _e = a("switch"), W = a("switch-label"), G = oe(), K = se({
27
42
  id: w,
28
43
  "aria-label": T,
29
44
  "aria-labelledby": E,
30
45
  "aria-describedby": D,
31
46
  "aria-invalid": O,
32
47
  "aria-required": k ?? S
33
- }), me = S ?? q?.required ?? !1, Y = r(v), he = Y && J["aria-label"] === void 0 ? ie(J["aria-labelledby"], q && J.id === q.controlId ? q.labelId : void 0, K) : J["aria-labelledby"], X = l.useRef(null), ge = ne(X, z);
34
- se(X, () => G(m), C);
35
- let Z = Y ? /* @__PURE__ */ u("span", {
36
- id: K,
48
+ }), ve = S ?? G?.required ?? !1, q = n(_), ye = q && K["aria-label"] === void 0 ? ae(K["aria-labelledby"], G && K.id === G.controlId ? G.labelId : void 0, W) : K["aria-labelledby"], J = c.useRef(null), be = re(J, z);
49
+ le(J, () => U(p), C);
50
+ let Y = Object.hasOwn(d, y) ? y : "medium", X = d[Y], Z = q ? /* @__PURE__ */ l("span", {
51
+ id: W,
37
52
  className: e(i.label, "text-body-1 text-foreground"),
38
- children: ee(v)
39
- }) : null, Q = y === "before" || y === "above", $ = g || _;
40
- return /* @__PURE__ */ d("label", {
41
- ref: H,
42
- "data-label-position": y,
43
- className: e(i.root, "relative inline-flex items-start gap-2 select-none", y === "above" && "flex-col gap-1", $ ? "cursor-not-allowed opacity-50 has-focus-visible:opacity-100" : "cursor-pointer", B),
44
- ...fe,
53
+ children: te(_)
54
+ }) : null, Q = v === "before" || v === "above", $ = h || g;
55
+ return /* @__PURE__ */ ue("label", {
56
+ ref: he,
57
+ "data-label-position": v,
58
+ "data-size": Y,
59
+ className: e(i.root, "relative inline-flex items-start gap-2 select-none", v === "above" && "flex-col gap-1", $ ? "cursor-not-allowed opacity-50 has-focus-visible:opacity-100" : "cursor-pointer", B),
60
+ ...ge,
45
61
  children: [
46
62
  Q && Z,
47
- /* @__PURE__ */ u("button", {
48
- id: pe,
63
+ /* @__PURE__ */ l("button", {
64
+ id: _e,
49
65
  type: "button",
50
- ...J,
51
- "aria-labelledby": he,
66
+ ...K,
67
+ "aria-labelledby": ye,
52
68
  "aria-errormessage": A,
53
69
  "aria-details": j,
54
70
  "aria-disabled": M,
55
71
  autoFocus: N,
56
72
  tabIndex: P,
57
73
  onFocus: I,
58
- onBlur: de,
59
- onKeyDown: L,
60
- onKeyUp: R,
61
- ref: ge,
74
+ onBlur: L,
75
+ onKeyDown: R,
76
+ onKeyUp: pe,
77
+ ref: be,
62
78
  role: "switch",
63
- "aria-checked": W,
64
- disabled: g && !_,
65
- ...re(_, { reachable: !0 }),
66
- onClick: _ ? (e) => {
79
+ "aria-checked": H,
80
+ disabled: h && !g,
81
+ ...ie(g, { reachable: !0 }),
82
+ onClick: g ? (e) => {
67
83
  e.preventDefault(), e.stopPropagation();
68
- } : te(F, () => G((e) => !e)),
69
- className: e(i.track, "relative inline-flex h-[20px] w-[40px] shrink-0 items-center rounded-full border p-0 transition-colors duration-200 motion-reduce:transition-none", oe, W ? e("border-primary bg-primary", $ ? le : f) : e("border-stroke-accessible bg-transparent", $ ? c.disabled : c.control)),
70
- children: /* @__PURE__ */ u("span", {
84
+ } : r(F, () => U((e) => !e)),
85
+ className: e(i.track, "relative inline-flex shrink-0 items-center rounded-full border p-0 transition-colors duration-200 motion-reduce:transition-none", X.track, q && v !== "above" && X.offset, ce, H ? e("border-primary bg-primary", $ ? u : de) : e("border-stroke-accessible bg-transparent", $ ? o.disabled : o.control)),
86
+ children: /* @__PURE__ */ l("span", {
71
87
  "aria-hidden": "true",
72
- className: e(i.thumb, "block h-[14px] w-[14px] rounded-full transition-transform duration-200 motion-reduce:transition-none forced-colors:forced-color-adjust-none", W ? "translate-x-[22px] wave-rtl:-translate-x-[22px] bg-primary-foreground" : "translate-x-[2px] wave-rtl:-translate-x-[2px] bg-stroke-accessible", $ ? "forced-colors:bg-[GrayText]" : W ? "forced-colors:bg-[HighlightText]" : "forced-colors:bg-[ButtonText]")
88
+ className: e(i.thumb, "block rounded-full transition-transform duration-200 motion-reduce:transition-none forced-colors:forced-color-adjust-none", X.thumb, H ? e(X.on, "bg-primary-foreground") : e(X.off, "bg-stroke-accessible"), $ ? "forced-colors:bg-[GrayText]" : H ? "forced-colors:bg-[HighlightText]" : "forced-colors:bg-[ButtonText]")
73
89
  })
74
90
  }),
75
91
  !Q && Z,
76
- /* @__PURE__ */ u(ce, {
92
+ /* @__PURE__ */ l(s, {
77
93
  type: "checkbox",
78
94
  name: b,
79
95
  form: C,
80
96
  disabled: $,
81
97
  value: x,
82
- checked: W,
83
- required: me,
84
- onInvalid: () => X.current?.focus()
98
+ checked: H,
99
+ required: ve,
100
+ onInvalid: () => J.current?.focus()
85
101
  })
86
102
  ]
87
103
  });
88
104
  };
89
- p.displayName = "Switch";
105
+ f.displayName = "Switch";
90
106
  //#endregion
91
- export { p as Switch };
107
+ export { f as Switch };
92
108
 
93
109
  //# sourceMappingURL=Switch.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.mjs","names":["useId","useId$1","React","onTrack","disabledOnTrack","Switch","checkedProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaDisabled","rest","onChange","warnDeprecated","hasChildren","slotRendersContent","children","warnOnce","checked","setChecked","useControllable","defaultChecked","onCheckedChange","next","generatedId","labelTextId","field","useFieldContext","fieldProps","useFieldControl","required","isRequired","hasLabel","label","labelledBy","joinIds","buttonRef","mergedControlRef","useMergedRefs","controlRef","form","labelText","cn","switchClassNames","materialiseSlotContent","labelFirst","labelPosition","unavailable","disabled","disabledFocusable","className","focusableDisabledProps","event","composeEventHandlers","onClick","prev","focusRing","forcedColors","HiddenInput"],"sources":["../../../src/components/input/Switch.tsx"],"sourcesContent":["import * as React from 'react';\nimport { focusableDisabledProps, joinIds } from '../../lib/aria';\nimport { switchClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { materialiseSlotContent, slotRendersContent } from '../../lib/slot';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport type { LabelPosition } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\n\n/*\n * Forced colors: the focusable track keeps system-color utilities, so the browser still forces its\n * focus outline; only the thumb (the leaf indicator) opts out of forced colors. A disabled switch\n * draws a GrayText thumb and border on Canvas, without the Highlight fill.\n */\nconst onTrack = 'forced-colors:border-[Highlight] forced-colors:bg-[Highlight]';\nconst disabledOnTrack = 'forced-colors:border-[GrayText] forced-colors:bg-[Canvas]';\n\n/** Handlers that run on the `role=\"switch\"` button instead of the root label (C-ROUTING). */\ntype SwitchControlHandlers = 'onClick' | 'onFocus' | 'onBlur' | 'onKeyDown' | 'onKeyUp';\n\n/** Where a Switch renders its label: after the track (default), before it or above it. */\nexport type SwitchLabelPosition = Extract<LabelPosition, 'before' | 'after' | 'above'>;\n\n/** Properties for the Switch component. */\nexport interface SwitchProps extends Omit<\n React.HTMLAttributes<HTMLLabelElement>,\n 'onChange' | 'defaultChecked' | SwitchControlHandlers\n> {\n /** Controlled checked (on/off) state. */\n checked?: boolean;\n /** Initial checked state for uncontrolled usage (also the value a form reset restores).\n * @default false\n */\n defaultChecked?: boolean;\n /** Called with the new checked state when the switch is toggled (not for no-op updates). */\n onCheckedChange?: (checked: boolean) => void;\n /**\n * Called with the new checked state when the switch is toggled.\n * @deprecated Use `onCheckedChange`.\n */\n onChange?: (checked: boolean) => void;\n /** Whether the switch is disabled and non-interactive. */\n disabled?: boolean;\n /**\n * Marks the switch unavailable but keeps it focusable and in the tab order: for a disabled\n * switch that needs a Tooltip, or one in a toolbar. Renders `aria-disabled=\"true\"`,\n * `data-disabled` and `data-disabled-focusable` on the switch instead of the native `disabled`\n * attribute. The switch cannot be toggled and is not submitted with its form; your `onClick` is\n * not called, and a click on the switch (or Space and Enter) does not reach ancestor click\n * handlers, as for a natively disabled control. Wins over `disabled` when both are set. In a\n * roving container (a `Toolbar`) it stays in the arrow-key order.\n * @default false\n */\n disabledFocusable?: boolean;\n /**\n * Label next to the control (any phrasing content, links included, but no other form\n * controls). It names the control through `aria-labelledby`, after a consumer or Field\n * `aria-labelledby`; a consumer `aria-label` names it instead. Clicking its text toggles the\n * control; clicking a link inside it follows the link. `children` are not rendered: pass the\n * label here.\n */\n label?: React.ReactNode;\n /**\n * Where the label renders: after the control (default), before it, or above it. The DOM order\n * follows the visual order.\n * @default 'after'\n */\n labelPosition?: SwitchLabelPosition;\n /**\n * Form field name. With a name, the switch takes part in native form submission: it submits\n * `name=value` while on.\n */\n name?: string;\n /** Value submitted while on.\n * @default 'on'\n */\n value?: string;\n /** The form must not be submitted while the switch is off (native validation). */\n required?: boolean;\n /** Id of the form the switch belongs to, when it is rendered outside that form. */\n form?: string;\n /** Click handler of the switch control (the `role=\"switch\"` button). */\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n /** Focus handler of the switch control. */\n onFocus?: React.FocusEventHandler<HTMLButtonElement>;\n /** Blur handler of the switch control. */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /** Keydown handler of the switch control. */\n onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Keyup handler of the switch control. */\n onKeyUp?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Ref to the focusable `role=\"switch\"` button. */\n controlRef?: React.Ref<HTMLButtonElement>;\n /** Ref to the root `<label>` element. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * An on/off toggle drawn as a `role=\"switch\"` button inside a `<label>`.\n *\n * - The root `<label>` receives `ref`, `className`, `style` and `data-*`; the control receives\n * `id`, `aria-label`/`-labelledby`/`-describedby`/`-invalid`/`-required`/`-errormessage`/\n * `-details`/`-disabled`, `tabIndex`, `autoFocus` and the click, focus and key handlers\n * (`controlRef` exposes it). A consumer `onClick` runs once per activation, before the toggle;\n * `preventDefault()` in it cancels the toggle.\n * - Inside a `Field` it is named by the Field label (followed by its own `label` text) and described\n * by the Field message and hint.\n * - With `name` (or `required`) it takes part in native forms like `<input type=\"checkbox\">`, and\n * a form reset restores `defaultChecked`.\n * - The thumb position mirrors when the switch itself is right-to-left (its nearest `dir`), so a\n * switch in an LTR subtree of an RTL page keeps the LTR layout.\n * - `label` takes rich content (a link) and renders after the switch, or before or above it with\n * `labelPosition` (the root carries `data-label-position`). Beside the label, the switch lines\n * up with the first line of a label that wraps or has a second line. `children` are not\n * rendered (a development warning says so).\n */\nexport const Switch = ({\n checked: checkedProp,\n defaultChecked = false,\n onCheckedChange,\n onChange,\n disabled = false,\n disabledFocusable = false,\n label,\n labelPosition = 'after',\n name,\n value,\n required,\n form,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-disabled': ariaDisabled,\n autoFocus,\n tabIndex,\n onClick,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n controlRef,\n className,\n children,\n ref,\n ...rest\n}: SwitchProps) => {\n if (onChange !== undefined) warnDeprecated('Switch', 'onChange', 'onCheckedChange');\n const hasChildren = slotRendersContent(children);\n React.useEffect(() => {\n if (hasChildren) {\n warnOnce('Switch:children', 'Switch: children are not rendered. Pass the label in `label`.');\n }\n }, [hasChildren]);\n const [checked, setChecked] = useControllable(checkedProp, defaultChecked, (next: boolean) => {\n onCheckedChange?.(next);\n onChange?.(next);\n });\n\n const generatedId = useId('switch');\n const labelTextId = useId('switch-label');\n const field = useFieldContext();\n const fieldProps = useFieldControl({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n // An explicit `required={false}` wins over a required Field, so aria-required always matches\n // the native validation below (`isRequired`).\n 'aria-required': ariaRequired ?? required,\n });\n const isRequired = required ?? field?.required ?? false;\n // `0` is a label; `null`, `false`, `''` and empty collections are not (C-SLOTS).\n const hasLabel = slotRendersContent(label);\n // The label text names the control through aria-labelledby, disabled or not: axe exempts the\n // dimmed text of a disabled control only when the control references it this way (its <label>\n // exemption covers native inputs only). A consumer aria-label still names the control alone.\n // The ids already there (the consumer's, the Field label from useFieldControl) come first, then\n // the Field label whose <label htmlFor> targets this control (aria-labelledby would hide it), so\n // the name keeps every label.\n const labelledBy =\n hasLabel && fieldProps['aria-label'] === undefined\n ? joinIds(\n fieldProps['aria-labelledby'],\n field && fieldProps.id === field.controlId ? field.labelId : undefined,\n labelTextId,\n )\n : fieldProps['aria-labelledby'];\n\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const mergedControlRef = useMergedRefs(buttonRef, controlRef);\n useFormReset(buttonRef, () => setChecked(defaultChecked), form);\n\n const labelText = hasLabel ? (\n <span id={labelTextId} className={cn(switchClassNames.label, 'text-body-1 text-foreground')}>\n {materialiseSlotContent(label)}\n </span>\n ) : null;\n const labelFirst = labelPosition === 'before' || labelPosition === 'above';\n // Focusable-disabled wins over `disabled`: the switch stays focusable but looks and acts disabled.\n const unavailable = disabled || disabledFocusable;\n\n return (\n <label\n ref={ref}\n data-label-position={labelPosition}\n className={cn(\n switchClassNames.root,\n // items-start: the 20px track lines up with the 20px first line of a label that wraps or\n // has a second line, not with its middle.\n 'relative inline-flex items-start gap-2 select-none',\n labelPosition === 'above' && 'flex-col gap-1',\n // The dimmed look lifts while a focus ring shows inside the root (the control's, under\n // disabledFocusable, or a link's in the label): opacity would dim the ring below 3:1.\n unavailable\n ? 'cursor-not-allowed opacity-50 has-focus-visible:opacity-100'\n : 'cursor-pointer',\n className,\n )}\n {...rest}\n >\n {labelFirst && labelText}\n <button\n id={generatedId}\n type=\"button\"\n {...fieldProps}\n aria-labelledby={labelledBy}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-disabled={ariaDisabled}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n onFocus={onFocus}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n ref={mergedControlRef}\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled && !disabledFocusable}\n {...focusableDisabledProps(disabledFocusable, { reachable: true })}\n onClick={\n disabledFocusable\n ? // Clicks, Space and Enter (which click a button) neither toggle nor reach `onClick`,\n // and, as a natively disabled control dispatches no click, no ancestor sees them.\n (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : composeEventHandlers(onClick, () => setChecked((prev) => !prev))\n }\n className={cn(\n switchClassNames.track,\n // The whole control is sized in px, like the Checkbox box and the radio circle: the thumb\n // and its offsets are px, so a track in rem would stop fitting them at any root font size\n // other than 16px. The 40x20 track (1px border) leaves a 2px inset around the 14px thumb.\n // p-0 is set here, not left to the native reset, which any app button style overrides\n // (C-NATIVE): the thumb offsets assume no padding.\n 'relative inline-flex h-[20px] w-[40px] shrink-0 items-center rounded-full border p-0 transition-colors duration-200 motion-reduce:transition-none',\n focusRing,\n checked\n ? cn('border-primary bg-primary', unavailable ? disabledOnTrack : onTrack)\n : cn(\n 'border-stroke-accessible bg-transparent',\n unavailable ? forcedColors.disabled : forcedColors.control,\n ),\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n switchClassNames.thumb,\n 'block h-[14px] w-[14px] rounded-full transition-transform duration-200 motion-reduce:transition-none forced-colors:forced-color-adjust-none',\n checked\n ? 'translate-x-[22px] wave-rtl:-translate-x-[22px] bg-primary-foreground'\n : 'translate-x-[2px] wave-rtl:-translate-x-[2px] bg-stroke-accessible',\n unavailable\n ? 'forced-colors:bg-[GrayText]'\n : checked\n ? 'forced-colors:bg-[HighlightText]'\n : 'forced-colors:bg-[ButtonText]',\n )}\n />\n </button>\n {!labelFirst && labelText}\n <HiddenInput\n type=\"checkbox\"\n name={name}\n form={form}\n disabled={unavailable}\n value={value}\n checked={checked}\n required={isRequired}\n onInvalid={() => buttonRef.current?.focus()}\n />\n </label>\n );\n};\n\nSwitch.displayName = 'Switch';\n"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,IAAMG,IAAU,iEACVC,KAAkB,6DAqGXC,KAAU,EACrB,SAASC,GACT,oBAAiB,IACjB,qBACA,aACA,cAAW,IACX,uBAAoB,IACpB,UACA,mBAAgB,SAChB,SACA,UACA,aACA,SACA,OACA,cAAcC,GACd,mBAAmBC,GACnB,oBAAoBC,GACpB,gBAAgBC,GAChB,iBAAiBC,GACjB,qBAAqBC,GACrB,gBAAgBC,GAChB,iBAAiBC,GACjB,cACA,aACA,YACA,YACA,YACA,cACA,YACA,eACA,cACA,aACA,QACA,GAAGC,SACc;CACjB,AAAIC,MAAa,KAAA,KAAWC,EAAe,UAAU,YAAY,iBAAiB;CAClF,IAAMC,IAAcC,EAAmBC,CAAQ;CAC/C,EAAM,gBAAgB;EACpB,AAAIF,KACFG,EAAS,mBAAmB,+DAA+D;CAE/F,GAAG,CAACH,CAAW,CAAC;CAChB,IAAM,CAACI,GAASC,KAAcC,EAAgBlB,GAAamB,IAAiB,MAAkB;EAE5F,AADAC,KAAkBC,CAAI,GACtBX,IAAWW,CAAI;CACjB,CAAC,GAEKC,KAAc5B,EAAM,QAAQ,GAC5B6B,IAAc7B,EAAM,cAAc,GAClC8B,IAAQC,GAAgB,GACxBC,IAAaC,EAAgB;EACjC;EACA,cAAc1B;EACd,mBAAmBC;EACnB,oBAAoBC;EACpB,gBAAgBC;EAGhB,iBAAiBC,KAAgBuB;CACnC,CAAC,GACKC,KAAaD,KAAYJ,GAAO,YAAY,IAE5CM,IAAWjB,EAAmBkB,CAAK,GAOnCC,KACJF,KAAYJ,EAAW,kBAAkB,KAAA,IACrCO,GACEP,EAAW,oBACXF,KAASE,EAAW,OAAOF,EAAM,YAAYA,EAAM,UAAU,KAAA,GAC7DD,CACF,IACAG,EAAW,oBAEXQ,IAAYtC,EAAM,OAA0B,IAAI,GAChDuC,KAAmBC,GAAcF,GAAWG,CAAU;CAC5D,GAAaH,SAAiBjB,EAAWE,CAAc,GAAGmB,CAAI;CAE9D,IAAMC,IAAYT,IAChB,kBAAC,QAAD;EAAM,IAAIP;EAAa,WAAWiB,EAAGC,EAAiB,OAAO,6BAA6B;EACvF,UAAAC,GAAuBX,CAAK;CACzB,CAAA,IACJ,MACEY,IAAaC,MAAkB,YAAYA,MAAkB,SAE7DC,IAAcC,KAAYC;CAEhC,OACE,kBAAC,SAAD;EACO;EACL,uBAAqBH;EACrB,WAAWJ,EACTC,EAAiB,MAGjB,sDACAG,MAAkB,WAAW,kBAG7BC,IACI,gEACA,kBACJG,CACF;EACA,GAAIvC;EAhBN,UAAA;GAkBGkC,KAAcJ;GACf,kBAAC,UAAD;IACE,IAAIjB;IACJ,MAAK;IACL,GAAII;IACJ,mBAAiBM;IACjB,qBAAmB1B;IACnB,gBAAcC;IACd,iBAAeC;IACJ;IACD;IACD;IACD;IACG;IACF;IACT,KAAK2B;IACL,MAAK;IACL,gBAAcnB;IACd,UAAU8B,KAAY,CAACC;IACvB,GAAIE,GAAuBF,GAAmB,EAAE,WAAW,GAAK,CAAC;IACjE,SACEA,KAGK,MAA+C;KAE9C,AADAG,EAAM,eAAe,GACrBA,EAAM,gBAAgB;IACxB,IACAC,GAAqBC,SAAenC,GAAY,MAAS,CAACoC,CAAI,CAAC;IAErE,WAAWb,EACTC,EAAiB,OAMjB,qJACAa,IACAtC,IACIwB,EAAG,6BAA6BK,IAAc/C,KAAkBD,CAAO,IACvE2C,EACE,2CACAK,IAAcU,EAAa,WAAWA,EAAa,OACrD,CACN;IAEA,UAAA,kBAAC,QAAD;KACE,eAAY;KACZ,WAAWf,EACTC,EAAiB,OACjB,+IACAzB,IACI,0EACA,sEACJ6B,IACI,gCACA7B,IACE,qCACA,+BACR;IACD,CAAA;GACK,CAAA;GACP,CAAC2B,KAAcJ;GAChB,kBAACiB,IAAD;IACE,MAAK;IACC;IACA;IACN,UAAUX;IACH;IACE;IACT,UAAUhB;IACV,iBAAiBK,EAAU,SAAS,MAAM;GAC3C,CAAA;EACI;;AAEX;AAEA,EAAO,cAAc"}
1
+ {"version":3,"file":"Switch.mjs","names":["useId","useId$1","React","onTrack","disabledOnTrack","SWITCH_SIZE","Switch","checkedProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaDisabled","rest","onChange","warnDeprecated","hasChildren","slotRendersContent","children","warnOnce","checked","setChecked","useControllable","defaultChecked","onCheckedChange","next","generatedId","labelTextId","field","useFieldContext","fieldProps","useFieldControl","required","isRequired","hasLabel","label","labelledBy","joinIds","buttonRef","mergedControlRef","useMergedRefs","controlRef","form","resolvedSize","size","sizeMetrics","labelText","cn","switchClassNames","materialiseSlotContent","labelFirst","labelPosition","unavailable","disabled","disabledFocusable","className","focusableDisabledProps","event","composeEventHandlers","onClick","prev","focusRing","forcedColors","HiddenInput"],"sources":["../../../src/components/input/Switch.tsx"],"sourcesContent":["import * as React from 'react';\nimport { focusableDisabledProps, joinIds } from '../../lib/aria';\nimport { switchClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { materialiseSlotContent, slotRendersContent } from '../../lib/slot';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport type { LabelPosition, Size } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\n\n/*\n * Forced colors: the focusable track keeps system-color utilities, so the browser still forces its\n * focus outline; only the thumb (the leaf indicator) opts out of forced colors. A disabled switch\n * draws a GrayText thumb and border on Canvas, without the Highlight fill.\n */\nconst onTrack = 'forced-colors:border-[Highlight] forced-colors:bg-[Highlight]';\nconst disabledOnTrack = 'forced-colors:border-[GrayText] forced-colors:bg-[Canvas]';\n\n/** Handlers that run on the `role=\"switch\"` button instead of the root label (C-ROUTING). */\ntype SwitchControlHandlers = 'onClick' | 'onFocus' | 'onBlur' | 'onKeyDown' | 'onKeyUp';\n\n/** Where a Switch renders its label: after the track (default), before it or above it. */\nexport type SwitchLabelPosition = Extract<LabelPosition, 'before' | 'after' | 'above'>;\n\n/** Size of the track: a 32x16 track with a 10px thumb, or the 0.7 40x20 track with a 14px thumb. */\nexport type SwitchSize = Extract<Size, 'small' | 'medium'>;\n\n/** Per-size track, thumb and label-offset classes. */\nconst SWITCH_SIZE: Readonly<\n Record<SwitchSize, { track: string; thumb: string; on: string; off: string; offset: string }>\n> = {\n small: {\n // The target layer is placed against the padding box inside the 1px border: 14 + 2 × 5 = 24px.\n track: 'h-[16px] w-[32px] before:absolute before:inset-x-0 before:-inset-y-[5px]',\n thumb: 'h-[10px] w-[10px]',\n on: 'translate-x-[18px] wave-rtl:-translate-x-[18px]',\n off: 'translate-x-[2px] wave-rtl:-translate-x-[2px]',\n offset: 'mt-0.5',\n },\n medium: {\n track: 'h-[20px] w-[40px]',\n thumb: 'h-[14px] w-[14px]',\n on: 'translate-x-[22px] wave-rtl:-translate-x-[22px]',\n off: 'translate-x-[2px] wave-rtl:-translate-x-[2px]',\n offset: '',\n },\n};\n\n/** Properties for the Switch component. */\nexport interface SwitchProps extends Omit<\n React.HTMLAttributes<HTMLLabelElement>,\n 'onChange' | 'defaultChecked' | SwitchControlHandlers\n> {\n /** Controlled checked (on/off) state. */\n checked?: boolean;\n /** Initial checked state for uncontrolled usage (also the value a form reset restores).\n * @default false\n */\n defaultChecked?: boolean;\n /** Called with the new checked state when the switch is toggled (not for no-op updates). */\n onCheckedChange?: (checked: boolean) => void;\n /**\n * Called with the new checked state when the switch is toggled.\n * @deprecated Use `onCheckedChange`.\n */\n onChange?: (checked: boolean) => void;\n /** Whether the switch is disabled and non-interactive. */\n disabled?: boolean;\n /**\n * Marks the switch unavailable but keeps it focusable and in the tab order: for a disabled\n * switch that needs a Tooltip, or one in a toolbar. Renders `aria-disabled=\"true\"`,\n * `data-disabled` and `data-disabled-focusable` on the switch instead of the native `disabled`\n * attribute. The switch cannot be toggled and is not submitted with its form; your `onClick` is\n * not called, and a click on the switch (or Space and Enter) does not reach ancestor click\n * handlers, as for a natively disabled control. Wins over `disabled` when both are set. In a\n * roving container (a `Toolbar`) it stays in the arrow-key order.\n * @default false\n */\n disabledFocusable?: boolean;\n /**\n * Label next to the control (any phrasing content, links included, but no other form\n * controls). It names the control through `aria-labelledby`, after a consumer or Field\n * `aria-labelledby`; a consumer `aria-label` names it instead. Clicking its text toggles the\n * control; clicking a link inside it follows the link. `children` are not rendered: pass the\n * label here.\n */\n label?: React.ReactNode;\n /**\n * Where the label renders: after the control (default), before it, or above it. The DOM order\n * follows the visual order.\n * @default 'after'\n */\n labelPosition?: SwitchLabelPosition;\n /**\n * Size of the track: the 0.7 40x20 track with a 14px thumb, or a small 32x16 track with a 10px\n * thumb and a 24px-tall pointer target. Unlike the text controls and pickers, Switch does not\n * read a surrounding Field's size or a WaveProvider's input defaults: this prop is the only\n * source of its size.\n * @default 'medium'\n */\n size?: SwitchSize;\n /**\n * Form field name. With a name, the switch takes part in native form submission: it submits\n * `name=value` while on.\n */\n name?: string;\n /** Value submitted while on.\n * @default 'on'\n */\n value?: string;\n /** The form must not be submitted while the switch is off (native validation). */\n required?: boolean;\n /** Id of the form the switch belongs to, when it is rendered outside that form. */\n form?: string;\n /** Click handler of the switch control (the `role=\"switch\"` button). */\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n /** Focus handler of the switch control. */\n onFocus?: React.FocusEventHandler<HTMLButtonElement>;\n /** Blur handler of the switch control. */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /** Keydown handler of the switch control. */\n onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Keyup handler of the switch control. */\n onKeyUp?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Ref to the focusable `role=\"switch\"` button. */\n controlRef?: React.Ref<HTMLButtonElement>;\n /** Ref to the root `<label>` element. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * An on/off toggle drawn as a `role=\"switch\"` button inside a `<label>`.\n *\n * - The root `<label>` receives `ref`, `className`, `style` and `data-*`; the control receives\n * `id`, `aria-label`/`-labelledby`/`-describedby`/`-invalid`/`-required`/`-errormessage`/\n * `-details`/`-disabled`, `tabIndex`, `autoFocus` and the click, focus and key handlers\n * (`controlRef` exposes it). A consumer `onClick` runs once per activation, before the toggle;\n * `preventDefault()` in it cancels the toggle.\n * - Inside a `Field` it is named by the Field label (followed by its own `label` text) and described\n * by the Field message and hint.\n * - With `name` (or `required`) it takes part in native forms like `<input type=\"checkbox\">`, and\n * a form reset restores `defaultChecked`.\n * - The thumb position mirrors when the switch itself is right-to-left (its nearest `dir`), so a\n * switch in an LTR subtree of an RTL page keeps the LTR layout.\n * - `label` takes rich content (a link) and renders after the switch, or before or above it with\n * `labelPosition` (the root carries `data-label-position`). Beside the label, the switch lines\n * up with the first line of a label that wraps or has a second line. `children` are not\n * rendered (a development warning says so).\n * - `size` (`small`, `medium`) sets the track and thumb dimensions; the root carries `data-size`.\n * Switch does not read a surrounding `Field`'s size or a `WaveProvider`'s input defaults.\n */\nexport const Switch = ({\n checked: checkedProp,\n defaultChecked = false,\n onCheckedChange,\n onChange,\n disabled = false,\n disabledFocusable = false,\n label,\n labelPosition = 'after',\n size = 'medium',\n name,\n value,\n required,\n form,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-disabled': ariaDisabled,\n autoFocus,\n tabIndex,\n onClick,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n controlRef,\n className,\n children,\n ref,\n ...rest\n}: SwitchProps) => {\n if (onChange !== undefined) warnDeprecated('Switch', 'onChange', 'onCheckedChange');\n const hasChildren = slotRendersContent(children);\n React.useEffect(() => {\n if (hasChildren) {\n warnOnce('Switch:children', 'Switch: children are not rendered. Pass the label in `label`.');\n }\n }, [hasChildren]);\n const [checked, setChecked] = useControllable(checkedProp, defaultChecked, (next: boolean) => {\n onCheckedChange?.(next);\n onChange?.(next);\n });\n\n const generatedId = useId('switch');\n const labelTextId = useId('switch-label');\n const field = useFieldContext();\n const fieldProps = useFieldControl({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n // An explicit `required={false}` wins over a required Field, so aria-required always matches\n // the native validation below (`isRequired`).\n 'aria-required': ariaRequired ?? required,\n });\n const isRequired = required ?? field?.required ?? false;\n // `0` is a label; `null`, `false`, `''` and empty collections are not (C-SLOTS).\n const hasLabel = slotRendersContent(label);\n // The label text names the control through aria-labelledby, disabled or not: axe exempts the\n // dimmed text of a disabled control only when the control references it this way (its <label>\n // exemption covers native inputs only). A consumer aria-label still names the control alone.\n // The ids already there (the consumer's, the Field label from useFieldControl) come first, then\n // the Field label whose <label htmlFor> targets this control (aria-labelledby would hide it), so\n // the name keeps every label.\n const labelledBy =\n hasLabel && fieldProps['aria-label'] === undefined\n ? joinIds(\n fieldProps['aria-labelledby'],\n field && fieldProps.id === field.controlId ? field.labelId : undefined,\n labelTextId,\n )\n : fieldProps['aria-labelledby'];\n\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const mergedControlRef = useMergedRefs(buttonRef, controlRef);\n useFormReset(buttonRef, () => setChecked(defaultChecked), form);\n\n // A size outside the union (from untyped code) renders, and is reported in the data attribute,\n // as the default: TypeScript rejects one, but the value still reaches this render.\n const resolvedSize: SwitchSize = Object.hasOwn(SWITCH_SIZE, size) ? size : 'medium';\n const sizeMetrics = SWITCH_SIZE[resolvedSize];\n const labelText = hasLabel ? (\n <span id={labelTextId} className={cn(switchClassNames.label, 'text-body-1 text-foreground')}>\n {materialiseSlotContent(label)}\n </span>\n ) : null;\n const labelFirst = labelPosition === 'before' || labelPosition === 'above';\n // Focusable-disabled wins over `disabled`: the switch stays focusable but looks and acts disabled.\n const unavailable = disabled || disabledFocusable;\n\n return (\n <label\n ref={ref}\n data-label-position={labelPosition}\n data-size={resolvedSize}\n className={cn(\n switchClassNames.root,\n // items-start: the track lines up with the top of the label's first line, not its\n // middle, when the label wraps or has a second line; medium's 20px track matches that\n // 20px line exactly, small's 16px track gets an offset below to stay centred on it.\n 'relative inline-flex items-start gap-2 select-none',\n labelPosition === 'above' && 'flex-col gap-1',\n // The dimmed look lifts while a focus ring shows inside the root (the control's, under\n // disabledFocusable, or a link's in the label): opacity would dim the ring below 3:1.\n unavailable\n ? 'cursor-not-allowed opacity-50 has-focus-visible:opacity-100'\n : 'cursor-pointer',\n className,\n )}\n {...rest}\n >\n {labelFirst && labelText}\n <button\n id={generatedId}\n type=\"button\"\n {...fieldProps}\n aria-labelledby={labelledBy}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-disabled={ariaDisabled}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n onFocus={onFocus}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n ref={mergedControlRef}\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled && !disabledFocusable}\n {...focusableDisabledProps(disabledFocusable, { reachable: true })}\n onClick={\n disabledFocusable\n ? // Clicks, Space and Enter (which click a button) neither toggle nor reach `onClick`,\n // and, as a natively disabled control dispatches no click, no ancestor sees them.\n (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : composeEventHandlers(onClick, () => setChecked((prev) => !prev))\n }\n className={cn(\n switchClassNames.track,\n // The whole control is sized in px, like the Checkbox box and the radio circle: the\n // thumb and its offsets are px, so a track in rem would stop fitting them at any root\n // font size other than 16px. Medium keeps the 0.7 look, a 40x20 track around a 14px\n // thumb, a 2px gap on every side. Small is a 32x16 track around a 10px thumb, the same\n // 2px gap, and a transparent strip behind the track that grows the pointer target to\n // 24px tall. No padding is assumed here, unlike the native reset that any app button\n // style overrides (C-NATIVE): the thumb offsets rely on it staying at zero.\n 'relative inline-flex shrink-0 items-center rounded-full border p-0 transition-colors duration-200 motion-reduce:transition-none',\n sizeMetrics.track,\n // The offset centres the track on the label line beside it; above the label, the\n // column gap alone separates them.\n hasLabel && labelPosition !== 'above' && sizeMetrics.offset,\n focusRing,\n checked\n ? cn('border-primary bg-primary', unavailable ? disabledOnTrack : onTrack)\n : cn(\n 'border-stroke-accessible bg-transparent',\n unavailable ? forcedColors.disabled : forcedColors.control,\n ),\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n switchClassNames.thumb,\n 'block rounded-full transition-transform duration-200 motion-reduce:transition-none forced-colors:forced-color-adjust-none',\n sizeMetrics.thumb,\n checked\n ? cn(sizeMetrics.on, 'bg-primary-foreground')\n : cn(sizeMetrics.off, 'bg-stroke-accessible'),\n unavailable\n ? 'forced-colors:bg-[GrayText]'\n : checked\n ? 'forced-colors:bg-[HighlightText]'\n : 'forced-colors:bg-[ButtonText]',\n )}\n />\n </button>\n {!labelFirst && labelText}\n <HiddenInput\n type=\"checkbox\"\n name={name}\n form={form}\n disabled={unavailable}\n value={value}\n checked={checked}\n required={isRequired}\n onInvalid={() => buttonRef.current?.focus()}\n />\n </label>\n );\n};\n\nSwitch.displayName = 'Switch';\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useControllable.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../lib/direction.cjs"),c=require("../../hooks/useMergedRefs.cjs"),ee=require("../../hooks/useIsClient.cjs"),te=require("../../lib/aria.cjs"),l=require("../../hooks/useFieldControl.cjs"),ne=require("../../hooks/useAnnounce.cjs"),u=require("../../lib/styles.cjs"),d=require("../../lib/icons.cjs"),re=require("./Input.cjs"),ie=require("../../hooks/useFormReset.cjs"),ae=require("../internal/HiddenInput.cjs"),oe=require("../../hooks/useListbox.cjs"),f=require("./Option.cjs"),p=require("../../hooks/usePreserveFocus.cjs");let m=require("react");m=e.__toESM(m,1);let h=require("react/jsx-runtime");var se=e=>`Remove ${e}`,ce=e=>`Selected: ${e.join(`, `)}`,le=(e,t)=>`${e} added, ${t} selected`,ue=(e,t)=>`${e} removed, ${t} selected`,g=[];function de(e,t){return e.length===t.length&&e.every((e,n)=>e===t[n])}function fe({label:e,disabled:n,onClick:r,onKeyDown:a,getFallback:o}){let s=m.useRef(null);return p.usePreserveFocus(s,o),(0,h.jsx)(`button`,{ref:s,type:`button`,"data-wave-tagpicker-remove":``,disabled:n,"aria-label":e,className:t.cn(i.tagPickerClassNames.removeButton,`ms-0.5 inline-flex rounded-sm bg-transparent p-0 text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground disabled:cursor-not-allowed`,u.focusRing),onClick:r,onKeyDown:a,children:(0,h.jsx)(d.DismissIcon,{size:12})})}var _=e=>{let{options:d,value:p,defaultValue:_,onValueChange:pe,onChange:v,open:me,defaultOpen:he,onOpenChange:ge,placeholder:_e=`Select...`,disabled:y=!1,name:ve,form:b,required:x,autoComplete:ye=`off`,autoCapitalize:be,autoCorrect:xe,maxLength:Se,readOnly:S,labels:C,inputMode:Ce,spellCheck:we,enterKeyHint:Te,autoFocus:Ee,tabIndex:w,id:T,"aria-label":E,"aria-labelledby":D,"aria-describedby":De,"aria-invalid":Oe,"aria-required":ke,"aria-errormessage":Ae,"aria-details":je,onFocus:Me,onBlur:Ne,onKeyDown:Pe,onKeyUp:Fe,controlRef:Ie,className:Le,ref:Re,...ze}=e;v!==void 0&&n.warnDeprecated(`TagPicker`,`onChange`,`onValueChange`);let O=l.useFieldContext(),Be=(x??O?.required??!1)&&!S,k=l.useFieldControl({id:T,"aria-label":E,"aria-labelledby":D,"aria-describedby":De,"aria-invalid":Oe,"aria-required":ke??x}),Ve=re.isInvalidLook(!1,k[`aria-invalid`]),[A,j]=a.useControllable(p,_??g,e=>{let t=[...e];pe?.(t),v?.(t)}),M=!y&&!S,[N,P]=a.useControllable(me,(he??!1)&&M,ge),He=ee.useIsClient(),F=N&&M&&He,[I,L]=m.useState(``),[Ue,We]=m.useState(M);Ue!==M&&(We(M),M||L(``));let R=!M&&N;m.useEffect(()=>{R&&P(!1)},[R,P]);let z=ne.useAnnounce(),B=m.useRef(null),V=m.useRef(null),H=o.useId(`tagpicker-summary`),U=m.useMemo(()=>{let e=new Map;for(let t of d)e.has(t.value)||e.set(t.value,t.label);return e},[d]),W=e=>U.get(e)??e,Ge=m.useMemo(()=>{let e=new Set(A);return d.filter(t=>!e.has(t.value)).map(e=>({value:e.value,label:e.label}))},[d,A]),Ke=m.useMemo(()=>I?e=>e.label.toLowerCase().includes(I.toLowerCase()):void 0,[I]),G=A.filter(e=>!U.has(e)).join(`\0`);m.useEffect(()=>{G&&n.warnOnce(`TagPicker:unknown-value`,`TagPicker: the selected value(s) ${G.split(`\0`).map(e=>`"${e}"`).join(`, `)} match no option; the raw value is shown as the tag label.`)},[G]);let qe=()=>V.current,K=()=>V.current?.focus(),Je=e=>{if(!M||A.includes(e))return;let t=[...A,e];j(t),L(``),z((C?.added??le)(W(e),t.length))},q=e=>{if(!M)return;let t=A.filter(t=>t!==e);j(t),z((C?.removed??ue)(W(e),t.length)),K()},J=oe.useListbox({open:F,onOpenChange:e=>P(e),mode:`editable`,multiple:!0,selectedValues:A,onSelect:e=>Je(e),items:Ge,filter:Ke,autoHighlight:I?`first`:!1,idPrefix:`tagpicker-listbox`,onClearDraft:I?()=>L(``):void 0}),Y=F&&J.items.length>0,X=C?.noMatches??`No matches`,Z=F&&(Y||I!==``),Ye=Z&&!Y,{layerId:Xe,setReference:Ze,surfaceRef:Qe,floatingProps:Q}=f.useListboxPopup({open:F,surfaceOpen:Z,onDismiss:()=>P(!1),rootRef:B,anchorRef:V}),$e=c.useMergedRefs(B,Re),et=c.useMergedRefs(V,Ie);ie.useFormReset(V,()=>{let e=_??g;j(t=>de(t,e)?t:[...e]),L(``)},b);let $=e=>Array.from(e.closest(`[data-wave-tagpicker-control]`)?.querySelectorAll(`[data-wave-tagpicker-remove]`)??[]),tt=e=>{if(M){if(e.key===`Escape`&&F&&!Z&&!e.nativeEvent.isComposing){P(!1);return}if(e.key===`Backspace`&&I===``&&A.length>0){e.preventDefault(),$(e.currentTarget).at(-1)?.focus();return}J.onKeyDown(e)}},nt=(e,t)=>{if(!M)return;let n=$(e.currentTarget),r=n.indexOf(e.currentTarget);if(e.key===`Backspace`||e.key===`Delete`){e.preventDefault(),q(t);return}if(e.key===`Escape`){e.preventDefault(),K();return}let i=s.getArrowIntent(e.key,{orientation:`horizontal`,dir:s.getDirection(e.currentTarget)});i===`prev`&&r>0?(e.preventDefault(),n[r-1].focus()):i===`next`&&(e.preventDefault(),r<n.length-1?n[r+1].focus():K())},rt=k[`aria-label`]===void 0?k[`aria-labelledby`]??O?.labelId:k[`aria-labelledby`];return(0,h.jsxs)(`div`,{...ze,ref:$e,className:t.cn(i.tagPickerClassNames.root,`relative`,Le),children:[(0,h.jsxs)(`div`,{ref:Ze,"data-wave-tagpicker-control":``,role:`group`,"aria-disabled":y||void 0,className:t.cn(i.tagPickerClassNames.control,`flex flex-wrap items-center gap-1 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1.5`,u.inputFocusWithin,Ve&&`border-destructive focus-within:border-b-destructive`,y&&`cursor-not-allowed opacity-50`),onClick:e=>{y||e.target.closest(`button`)||(K(),!F&&M&&P(!0))},children:[A.length>0&&(0,h.jsx)(`div`,{role:`list`,"aria-label":C?.selected??`Selected`,className:t.cn(i.tagPickerClassNames.group,`flex flex-wrap items-center gap-1`),children:A.map(e=>{let n=W(e);return(0,h.jsxs)(`div`,{role:`listitem`,className:t.cn(i.tagPickerClassNames.tag,`inline-flex items-center gap-1 rounded bg-muted px-2 py-0.5 text-body-1 text-foreground`),children:[n,!S&&(0,h.jsx)(fe,{label:(C?.remove??se)(n),disabled:y,onClick:()=>q(e),onKeyDown:t=>nt(t,e),getFallback:qe})]},e)})}),A.length>0&&(0,h.jsx)(`span`,{id:H,hidden:!0,children:(C?.summary??ce)(A.map(W))}),(0,h.jsx)(`input`,{type:`text`,autoComplete:ye,...k,...J.getComboboxProps(),"aria-expanded":Y,"aria-describedby":te.joinIds(k[`aria-describedby`],A.length>0?H:void 0),"aria-errormessage":Ae,"aria-details":je,ref:et,disabled:y,readOnly:S,placeholder:A.length===0?_e:``,autoCapitalize:be,autoCorrect:xe,maxLength:Se,inputMode:Ce,spellCheck:we,enterKeyHint:Te,autoFocus:Ee,tabIndex:w,value:I,onChange:e=>{M&&(L(e.target.value),F||P(!0))},onKeyDown:r.composeEventHandlers(Pe,tt),onKeyUp:r.composeEventHandlers(Fe,J.onKeyUp),onFocus:Me,onBlur:Ne,className:t.cn(i.tagPickerClassNames.input,`min-w-15 flex-1 bg-transparent py-0.5 text-body-1 text-foreground placeholder:text-muted-foreground focus:outline-hidden`)})]}),(0,h.jsx)(`span`,{role:`status`,className:`sr-only`,children:Ye&&X}),(0,h.jsx)(f.ListboxSurface,{listbox:J,layerId:Xe,surfaceRef:Qe,floatingProps:Q,open:F,expanded:Y,showCheck:!1,listboxClassName:i.tagPickerClassNames.listbox,surfaceClassName:i.tagPickerClassNames.surface,emptyContent:I===``?void 0:(0,h.jsx)(`div`,{"aria-hidden":`true`,className:t.cn(i.tagPickerClassNames.emptyMessage,`px-3 py-1.5 text-body-1 text-muted-foreground`),children:X}),"aria-label":k[`aria-label`],"aria-labelledby":rt,children:Y&&J.items.map(e=>(0,h.jsx)(f.Option,{value:e.value,label:e.label,className:i.tagPickerClassNames.option,children:e.label},e.value))}),(0,h.jsx)(ae.HiddenInput,{name:ve,form:b,disabled:y,value:A,type:`text`,required:Be,onInvalid:K})]})};_.displayName=`TagPicker`,exports.TagPicker=_;
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useControllable.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../lib/direction.cjs"),c=require("../../hooks/useMergedRefs.cjs"),ee=require("../../hooks/useIsClient.cjs"),te=require("../../lib/aria.cjs"),l=require("../../hooks/useFieldControl.cjs"),ne=require("../../hooks/useAnnounce.cjs"),u=require("../../lib/styles.cjs"),d=require("../../lib/icons.cjs"),re=require("./inputLook.cjs"),ie=require("./Input.cjs"),ae=require("../../hooks/useFormReset.cjs"),oe=require("../internal/HiddenInput.cjs"),se=require("../../hooks/useListbox.cjs"),f=require("./Option.cjs"),p=require("../../hooks/usePreserveFocus.cjs");let m=require("react");m=e.__toESM(m,1);let h=require("react/jsx-runtime");var ce=e=>`Remove ${e}`,le=e=>`Selected: ${e.join(`, `)}`,ue=(e,t)=>`${e} added, ${t} selected`,de=(e,t)=>`${e} removed, ${t} selected`,fe=[`medium`,`large`,`extra-large`],pe={medium:{control:`gap-1 px-2 py-1.5`,tag:`px-2 py-0.5 text-body-1`,input:`py-0.5 text-body-1`},large:{control:`gap-1.5 px-2.5 py-2`,tag:`px-2 py-1 text-body-1`,input:`py-1 text-body-1`},"extra-large":{control:`gap-1.5 px-3 py-2.5`,tag:`px-2.5 py-1 text-body-2`,input:`py-1 text-body-2`}},g=[];function me(e,t){return e.length===t.length&&e.every((e,n)=>e===t[n])}function he({label:e,disabled:n,onClick:r,onKeyDown:a,getFallback:o}){let s=m.useRef(null);return p.usePreserveFocus(s,o),(0,h.jsx)(`button`,{ref:s,type:`button`,"data-wave-tagpicker-remove":``,disabled:n,"aria-label":e,className:t.cn(i.tagPickerClassNames.removeButton,`ms-0.5 inline-flex rounded-sm bg-transparent p-0 text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground disabled:cursor-not-allowed`,u.focusRing),onClick:r,onKeyDown:a,children:(0,h.jsx)(d.DismissIcon,{size:12})})}var _=e=>{let{options:d,value:p,defaultValue:_,onValueChange:ge,onChange:v,open:_e,defaultOpen:ve,onOpenChange:ye,placeholder:be=`Select...`,disabled:y=!1,size:xe,appearance:Se,name:Ce,form:b,required:x,autoComplete:we=`off`,autoCapitalize:Te,autoCorrect:Ee,maxLength:De,readOnly:S,labels:C,inputMode:Oe,spellCheck:ke,enterKeyHint:w,autoFocus:Ae,tabIndex:je,id:Me,"aria-label":Ne,"aria-labelledby":Pe,"aria-describedby":Fe,"aria-invalid":Ie,"aria-required":Le,"aria-errormessage":Re,"aria-details":ze,onFocus:Be,onBlur:Ve,onKeyDown:He,onKeyUp:Ue,controlRef:We,className:Ge,ref:Ke,...qe}=e;v!==void 0&&n.warnDeprecated(`TagPicker`,`onChange`,`onValueChange`);let T=l.useFieldContext(),Je=(x??T?.required??!1)&&!S,E=l.useFieldControl({id:Me,"aria-label":Ne,"aria-labelledby":Pe,"aria-describedby":Fe,"aria-invalid":Ie,"aria-required":Le??x}),Ye=ie.isInvalidLook(!1,E[`aria-invalid`]),{size:D,appearance:O}=re.useInputLook(xe,Se,{sizes:fe,defaultSize:`medium`}),k=pe[D],[A,j]=a.useControllable(p,_??g,e=>{let t=[...e];ge?.(t),v?.(t)}),M=!y&&!S,[N,P]=a.useControllable(_e,(ve??!1)&&M,ye),Xe=ee.useIsClient(),F=N&&M&&Xe,[I,L]=m.useState(``),[Ze,Qe]=m.useState(M);Ze!==M&&(Qe(M),M||L(``));let R=!M&&N;m.useEffect(()=>{R&&P(!1)},[R,P]);let z=ne.useAnnounce(),B=m.useRef(null),V=m.useRef(null),H=o.useId(`tagpicker-summary`),U=m.useMemo(()=>{let e=new Map;for(let t of d)e.has(t.value)||e.set(t.value,t.label);return e},[d]),W=e=>U.get(e)??e,$e=m.useMemo(()=>{let e=new Set(A);return d.filter(t=>!e.has(t.value)).map(e=>({value:e.value,label:e.label}))},[d,A]),et=m.useMemo(()=>I?e=>e.label.toLowerCase().includes(I.toLowerCase()):void 0,[I]),G=A.filter(e=>!U.has(e)).join(`\0`);m.useEffect(()=>{G&&n.warnOnce(`TagPicker:unknown-value`,`TagPicker: the selected value(s) ${G.split(`\0`).map(e=>`"${e}"`).join(`, `)} match no option; the raw value is shown as the tag label.`)},[G]);let tt=()=>V.current,K=()=>V.current?.focus(),nt=e=>{if(!M||A.includes(e))return;let t=[...A,e];j(t),L(``),z((C?.added??ue)(W(e),t.length))},q=e=>{if(!M)return;let t=A.filter(t=>t!==e);j(t),z((C?.removed??de)(W(e),t.length)),K()},J=se.useListbox({open:F,onOpenChange:e=>P(e),mode:`editable`,multiple:!0,selectedValues:A,onSelect:e=>nt(e),items:$e,filter:et,autoHighlight:I?`first`:!1,idPrefix:`tagpicker-listbox`,onClearDraft:I?()=>L(``):void 0}),Y=F&&J.items.length>0,X=C?.noMatches??`No matches`,Z=F&&(Y||I!==``),rt=Z&&!Y,{layerId:it,setReference:at,surfaceRef:Q,floatingProps:ot}=f.useListboxPopup({open:F,surfaceOpen:Z,onDismiss:()=>P(!1),rootRef:B,anchorRef:V}),st=c.useMergedRefs(B,Ke),ct=c.useMergedRefs(V,We);ae.useFormReset(V,()=>{let e=_??g;j(t=>me(t,e)?t:[...e]),L(``)},b);let $=e=>Array.from(e.closest(`[data-wave-tagpicker-control]`)?.querySelectorAll(`[data-wave-tagpicker-remove]`)??[]),lt=e=>{if(M){if(e.key===`Escape`&&F&&!Z&&!e.nativeEvent.isComposing){P(!1);return}if(e.key===`Backspace`&&I===``&&A.length>0){e.preventDefault(),$(e.currentTarget).at(-1)?.focus();return}J.onKeyDown(e)}},ut=(e,t)=>{if(!M)return;let n=$(e.currentTarget),r=n.indexOf(e.currentTarget);if(e.key===`Backspace`||e.key===`Delete`){e.preventDefault(),q(t);return}if(e.key===`Escape`){e.preventDefault(),K();return}let i=s.getArrowIntent(e.key,{orientation:`horizontal`,dir:s.getDirection(e.currentTarget)});i===`prev`&&r>0?(e.preventDefault(),n[r-1].focus()):i===`next`&&(e.preventDefault(),r<n.length-1?n[r+1].focus():K())},dt=E[`aria-label`]===void 0?E[`aria-labelledby`]??T?.labelId:E[`aria-labelledby`];return(0,h.jsxs)(`div`,{"data-size":D,"data-appearance":O,...qe,ref:st,className:t.cn(i.tagPickerClassNames.root,`relative`,Ge),children:[(0,h.jsxs)(`div`,{ref:at,"data-wave-tagpicker-control":``,role:`group`,"aria-disabled":y||void 0,className:t.cn(i.tagPickerClassNames.control,`flex flex-wrap items-center`,k.control,u.inputAppearanceClasses[O],u.inputFocusWithin,Ye&&`border-destructive`,y&&`cursor-not-allowed opacity-50`),onClick:e=>{y||e.target.closest(`button`)||(K(),!F&&M&&P(!0))},children:[A.length>0&&(0,h.jsx)(`div`,{role:`list`,"aria-label":C?.selected??`Selected`,className:t.cn(i.tagPickerClassNames.group,`flex flex-wrap items-center gap-1`),children:A.map(e=>{let n=W(e);return(0,h.jsxs)(`div`,{role:`listitem`,className:t.cn(i.tagPickerClassNames.tag,`inline-flex items-center gap-1 rounded bg-muted text-foreground`,k.tag),children:[n,!S&&(0,h.jsx)(he,{label:(C?.remove??ce)(n),disabled:y,onClick:()=>q(e),onKeyDown:t=>ut(t,e),getFallback:tt})]},e)})}),A.length>0&&(0,h.jsx)(`span`,{id:H,hidden:!0,children:(C?.summary??le)(A.map(W))}),(0,h.jsx)(`input`,{type:`text`,autoComplete:we,...E,...J.getComboboxProps(),"aria-expanded":Y,"aria-describedby":te.joinIds(E[`aria-describedby`],A.length>0?H:void 0),"aria-errormessage":Re,"aria-details":ze,ref:ct,disabled:y,readOnly:S,placeholder:A.length===0?be:``,autoCapitalize:Te,autoCorrect:Ee,maxLength:De,inputMode:Oe,spellCheck:ke,enterKeyHint:w,autoFocus:Ae,tabIndex:je,value:I,onChange:e=>{M&&(L(e.target.value),F||P(!0))},onKeyDown:r.composeEventHandlers(He,lt),onKeyUp:r.composeEventHandlers(Ue,J.onKeyUp),onFocus:Be,onBlur:Ve,className:t.cn(i.tagPickerClassNames.input,`min-w-15 flex-1 bg-transparent text-foreground placeholder:text-muted-foreground focus:outline-hidden`,k.input)})]}),(0,h.jsx)(`span`,{role:`status`,className:`sr-only`,children:rt&&X}),(0,h.jsx)(f.ListboxSurface,{listbox:J,layerId:it,surfaceRef:Q,floatingProps:ot,open:F,expanded:Y,showCheck:!1,listboxClassName:i.tagPickerClassNames.listbox,surfaceClassName:i.tagPickerClassNames.surface,emptyContent:I===``?void 0:(0,h.jsx)(`div`,{"aria-hidden":`true`,className:t.cn(i.tagPickerClassNames.emptyMessage,`px-3 py-1.5 text-body-1 text-muted-foreground`),children:X}),"aria-label":E[`aria-label`],"aria-labelledby":dt,children:Y&&J.items.map(e=>(0,h.jsx)(f.Option,{value:e.value,label:e.label,className:i.tagPickerClassNames.option,children:e.label},e.value))}),(0,h.jsx)(oe.HiddenInput,{name:Ce,form:b,disabled:y,value:A,type:`text`,required:Je,onInvalid:K})]})};_.displayName=`TagPicker`,exports.TagPicker=_;
2
2
  //# sourceMappingURL=TagPicker.cjs.map