@spear-ai/spectral 1.15.0 → 1.15.1

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 (272) hide show
  1. package/dist/Accordion.d.ts.map +1 -1
  2. package/dist/Accordion.js.map +1 -1
  3. package/dist/Alert/AlertBase.d.ts.map +1 -1
  4. package/dist/Alert/AlertBase.js.map +1 -1
  5. package/dist/Alert.js.map +1 -1
  6. package/dist/Avatar.js.map +1 -1
  7. package/dist/Badge.d.ts.map +1 -1
  8. package/dist/Badge.js +3 -3
  9. package/dist/Badge.js.map +1 -1
  10. package/dist/Button.js.map +1 -1
  11. package/dist/ButtonGroup/ButtonGroupButton.js.map +1 -1
  12. package/dist/ButtonGroup.d.ts.map +1 -1
  13. package/dist/ButtonGroup.js.map +1 -1
  14. package/dist/ButtonIcon.js.map +1 -1
  15. package/dist/Checkbox/CheckboxBase.js.map +1 -1
  16. package/dist/Checkbox.js.map +1 -1
  17. package/dist/Combobox.js +0 -1
  18. package/dist/Combobox.js.map +1 -1
  19. package/dist/ControlGroup/ControlGroupSelect.js.map +1 -1
  20. package/dist/ControlGroup.d.ts.map +1 -1
  21. package/dist/ControlGroup.js.map +1 -1
  22. package/dist/DataCard/Card.d.ts.map +1 -1
  23. package/dist/DataCard/Card.js.map +1 -1
  24. package/dist/DataCard.js.map +1 -1
  25. package/dist/DateTimePicker/Calendar.js.map +1 -1
  26. package/dist/DateTimePicker/DateTimeDisplayInput.js.map +1 -1
  27. package/dist/DateTimePicker/TimePeriodSelect.js.map +1 -1
  28. package/dist/DateTimePicker/TimePicker.js.map +1 -1
  29. package/dist/DateTimePicker.js.map +1 -1
  30. package/dist/Dialog.d.ts.map +1 -1
  31. package/dist/Dialog.js.map +1 -1
  32. package/dist/Drawer.js.map +1 -1
  33. package/dist/DropdownMenu.js.map +1 -1
  34. package/dist/FormFieldMessage.d.ts.map +1 -1
  35. package/dist/FormFieldMessage.js +2 -2
  36. package/dist/FormFieldMessage.js.map +1 -1
  37. package/dist/HoverCard.d.ts.map +1 -1
  38. package/dist/HoverCard.js.map +1 -1
  39. package/dist/Icons/AdjustmentsIcon.d.ts.map +1 -1
  40. package/dist/Icons/AdjustmentsIcon.js.map +1 -1
  41. package/dist/Icons/AnalyzeIcon.d.ts.map +1 -1
  42. package/dist/Icons/AnalyzeIcon.js.map +1 -1
  43. package/dist/Icons/AnnotationsIcon.d.ts.map +1 -1
  44. package/dist/Icons/AnnotationsIcon.js.map +1 -1
  45. package/dist/Icons/ApprovedIcon.d.ts.map +1 -1
  46. package/dist/Icons/ApprovedIcon.js.map +1 -1
  47. package/dist/Icons/ArrowDownIcon.d.ts.map +1 -1
  48. package/dist/Icons/ArrowDownIcon.js.map +1 -1
  49. package/dist/Icons/ArrowUpIcon.d.ts.map +1 -1
  50. package/dist/Icons/ArrowUpIcon.js.map +1 -1
  51. package/dist/Icons/BoxToolIcon.d.ts.map +1 -1
  52. package/dist/Icons/BoxToolIcon.js.map +1 -1
  53. package/dist/Icons/CalendarIcon.d.ts.map +1 -1
  54. package/dist/Icons/CalendarIcon.js.map +1 -1
  55. package/dist/Icons/CheckCircleIcon.d.ts.map +1 -1
  56. package/dist/Icons/CheckCircleIcon.js.map +1 -1
  57. package/dist/Icons/CheckSquareIcon.d.ts.map +1 -1
  58. package/dist/Icons/CheckSquareIcon.js.map +1 -1
  59. package/dist/Icons/CheckmarkIcon.d.ts.map +1 -1
  60. package/dist/Icons/CheckmarkIcon.js.map +1 -1
  61. package/dist/Icons/ChevronDownIcon.d.ts.map +1 -1
  62. package/dist/Icons/ChevronDownIcon.js.map +1 -1
  63. package/dist/Icons/ChevronUpIcon.d.ts.map +1 -1
  64. package/dist/Icons/ChevronUpIcon.js.map +1 -1
  65. package/dist/Icons/ClockIcon.d.ts.map +1 -1
  66. package/dist/Icons/ClockIcon.js.map +1 -1
  67. package/dist/Icons/CloseCircleIcon.d.ts.map +1 -1
  68. package/dist/Icons/CloseCircleIcon.js.map +1 -1
  69. package/dist/Icons/CloseIcon.d.ts.map +1 -1
  70. package/dist/Icons/CloseIcon.js.map +1 -1
  71. package/dist/Icons/Crosshairs2Icon.d.ts.map +1 -1
  72. package/dist/Icons/Crosshairs2Icon.js.map +1 -1
  73. package/dist/Icons/CrosshairsIcon.d.ts.map +1 -1
  74. package/dist/Icons/CrosshairsIcon.js.map +1 -1
  75. package/dist/Icons/DashboardIcon.d.ts.map +1 -1
  76. package/dist/Icons/DashboardIcon.js.map +1 -1
  77. package/dist/Icons/DatabaseIcon.d.ts.map +1 -1
  78. package/dist/Icons/DatabaseIcon.js.map +1 -1
  79. package/dist/Icons/DeleteIcon.d.ts.map +1 -1
  80. package/dist/Icons/DeleteIcon.js.map +1 -1
  81. package/dist/Icons/DurationIcon.d.ts.map +1 -1
  82. package/dist/Icons/DurationIcon.js.map +1 -1
  83. package/dist/Icons/EditIcon.d.ts.map +1 -1
  84. package/dist/Icons/EditIcon.js.map +1 -1
  85. package/dist/Icons/EmailIcon.d.ts.map +1 -1
  86. package/dist/Icons/EmailIcon.js.map +1 -1
  87. package/dist/Icons/EraserIcon.d.ts.map +1 -1
  88. package/dist/Icons/EraserIcon.js.map +1 -1
  89. package/dist/Icons/ErrorIcon.d.ts.map +1 -1
  90. package/dist/Icons/ErrorIcon.js.map +1 -1
  91. package/dist/Icons/EyeClosedIcon.d.ts.map +1 -1
  92. package/dist/Icons/EyeClosedIcon.js.map +1 -1
  93. package/dist/Icons/EyeClosedIcon2.d.ts.map +1 -1
  94. package/dist/Icons/EyeClosedIcon2.js.map +1 -1
  95. package/dist/Icons/EyeOpenIcon.d.ts.map +1 -1
  96. package/dist/Icons/EyeOpenIcon.js.map +1 -1
  97. package/dist/Icons/FileDownloadIcon.d.ts.map +1 -1
  98. package/dist/Icons/FileDownloadIcon.js.map +1 -1
  99. package/dist/Icons/GoToFirstIcon.d.ts.map +1 -1
  100. package/dist/Icons/GoToFirstIcon.js.map +1 -1
  101. package/dist/Icons/GoToLastIcon.d.ts.map +1 -1
  102. package/dist/Icons/GoToLastIcon.js.map +1 -1
  103. package/dist/Icons/HarmonicCursorsIcon.d.ts.map +1 -1
  104. package/dist/Icons/HarmonicCursorsIcon.js.map +1 -1
  105. package/dist/Icons/InfoIcon.d.ts.map +1 -1
  106. package/dist/Icons/InfoIcon.js.map +1 -1
  107. package/dist/Icons/KeyboardIcon.d.ts.map +1 -1
  108. package/dist/Icons/KeyboardIcon.js.map +1 -1
  109. package/dist/Icons/LabelIcon.d.ts.map +1 -1
  110. package/dist/Icons/LabelIcon.js.map +1 -1
  111. package/dist/Icons/LassoIcon.d.ts.map +1 -1
  112. package/dist/Icons/LassoIcon.js.map +1 -1
  113. package/dist/Icons/LineToolIcon.d.ts.map +1 -1
  114. package/dist/Icons/LineToolIcon.js.map +1 -1
  115. package/dist/Icons/LiveViewIcon.d.ts.map +1 -1
  116. package/dist/Icons/LiveViewIcon.js.map +1 -1
  117. package/dist/Icons/LoaderIcon.d.ts.map +1 -1
  118. package/dist/Icons/LoaderIcon.js.map +1 -1
  119. package/dist/Icons/LocationIcon.d.ts.map +1 -1
  120. package/dist/Icons/LocationIcon.js.map +1 -1
  121. package/dist/Icons/LogoutIcon.d.ts.map +1 -1
  122. package/dist/Icons/LogoutIcon.js.map +1 -1
  123. package/dist/Icons/MaximizeIcon.d.ts.map +1 -1
  124. package/dist/Icons/MaximizeIcon.js.map +1 -1
  125. package/dist/Icons/MeasureIcon.d.ts.map +1 -1
  126. package/dist/Icons/MeasureIcon.js.map +1 -1
  127. package/dist/Icons/MenuDotsIcon.d.ts.map +1 -1
  128. package/dist/Icons/MenuDotsIcon.js.map +1 -1
  129. package/dist/Icons/MenuIcon.d.ts.map +1 -1
  130. package/dist/Icons/MenuIcon.js.map +1 -1
  131. package/dist/Icons/MessagesIcon.d.ts.map +1 -1
  132. package/dist/Icons/MessagesIcon.js.map +1 -1
  133. package/dist/Icons/MetadataIcon.d.ts.map +1 -1
  134. package/dist/Icons/MetadataIcon.js.map +1 -1
  135. package/dist/Icons/MinimizeIcon.d.ts.map +1 -1
  136. package/dist/Icons/MinimizeIcon.js.map +1 -1
  137. package/dist/Icons/MinusIcon.d.ts.map +1 -1
  138. package/dist/Icons/MinusIcon.js.map +1 -1
  139. package/dist/Icons/OntologyIcon.d.ts.map +1 -1
  140. package/dist/Icons/OntologyIcon.js.map +1 -1
  141. package/dist/Icons/PanelIconClose.d.ts.map +1 -1
  142. package/dist/Icons/PanelIconClose.js.map +1 -1
  143. package/dist/Icons/PanelIconOpen.d.ts.map +1 -1
  144. package/dist/Icons/PanelIconOpen.js.map +1 -1
  145. package/dist/Icons/PauseIcon.d.ts.map +1 -1
  146. package/dist/Icons/PauseIcon.js.map +1 -1
  147. package/dist/Icons/PlayIcon.d.ts.map +1 -1
  148. package/dist/Icons/PlayIcon.js.map +1 -1
  149. package/dist/Icons/PlusIcon.d.ts.map +1 -1
  150. package/dist/Icons/PlusIcon.js.map +1 -1
  151. package/dist/Icons/PolygonIcon.d.ts.map +1 -1
  152. package/dist/Icons/PolygonIcon.js.map +1 -1
  153. package/dist/Icons/PrinterIcon.d.ts.map +1 -1
  154. package/dist/Icons/PrinterIcon.js.map +1 -1
  155. package/dist/Icons/ProgressCheckIcon.d.ts.map +1 -1
  156. package/dist/Icons/ProgressCheckIcon.js.map +1 -1
  157. package/dist/Icons/ResetIcon.d.ts.map +1 -1
  158. package/dist/Icons/ResetIcon.js.map +1 -1
  159. package/dist/Icons/ReviewedIcon.d.ts.map +1 -1
  160. package/dist/Icons/ReviewedIcon.js.map +1 -1
  161. package/dist/Icons/ScissorsIcon.d.ts.map +1 -1
  162. package/dist/Icons/ScissorsIcon.js.map +1 -1
  163. package/dist/Icons/SearchIcon.d.ts.map +1 -1
  164. package/dist/Icons/SearchIcon.js.map +1 -1
  165. package/dist/Icons/SettingsIcon.d.ts.map +1 -1
  166. package/dist/Icons/SettingsIcon.js.map +1 -1
  167. package/dist/Icons/SortAscendingIcon.d.ts.map +1 -1
  168. package/dist/Icons/SortAscendingIcon.js.map +1 -1
  169. package/dist/Icons/SortAtoZIcon.d.ts.map +1 -1
  170. package/dist/Icons/SortAtoZIcon.js.map +1 -1
  171. package/dist/Icons/SortDescendingIcon.d.ts.map +1 -1
  172. package/dist/Icons/SortDescendingIcon.js.map +1 -1
  173. package/dist/Icons/SortZtoAIcon.d.ts.map +1 -1
  174. package/dist/Icons/SortZtoAIcon.js.map +1 -1
  175. package/dist/Icons/SparklesIcon.d.ts.map +1 -1
  176. package/dist/Icons/SparklesIcon.js.map +1 -1
  177. package/dist/Icons/StackIcon.d.ts.map +1 -1
  178. package/dist/Icons/StackIcon.js.map +1 -1
  179. package/dist/Icons/StarIcon.d.ts.map +1 -1
  180. package/dist/Icons/StarIcon.js.map +1 -1
  181. package/dist/Icons/TrashIcon.d.ts.map +1 -1
  182. package/dist/Icons/TrashIcon.js.map +1 -1
  183. package/dist/Icons/UndoIcon.d.ts.map +1 -1
  184. package/dist/Icons/UndoIcon.js.map +1 -1
  185. package/dist/Icons/UploadIcon.d.ts.map +1 -1
  186. package/dist/Icons/UploadIcon.js.map +1 -1
  187. package/dist/Icons/User2Icon.d.ts.map +1 -1
  188. package/dist/Icons/User2Icon.js.map +1 -1
  189. package/dist/Icons/UserIcon.d.ts.map +1 -1
  190. package/dist/Icons/UserIcon.js.map +1 -1
  191. package/dist/Icons/WarningIcon.d.ts.map +1 -1
  192. package/dist/Icons/WarningIcon.js.map +1 -1
  193. package/dist/Icons/ZoomAllIcon.d.ts.map +1 -1
  194. package/dist/Icons/ZoomAllIcon.js.map +1 -1
  195. package/dist/Icons/ZoomXIcon.d.ts.map +1 -1
  196. package/dist/Icons/ZoomXIcon.js.map +1 -1
  197. package/dist/Icons/ZoomYIcon.d.ts.map +1 -1
  198. package/dist/Icons/ZoomYIcon.js.map +1 -1
  199. package/dist/IconsAnimated/PanelLeftCloseIcon.js.map +1 -1
  200. package/dist/IconsAnimated/PanelLeftOpenIcon.js.map +1 -1
  201. package/dist/Input.js.map +1 -1
  202. package/dist/InputNumeric.js +0 -6
  203. package/dist/InputNumeric.js.map +1 -1
  204. package/dist/InputOTP.d.ts.map +1 -1
  205. package/dist/InputOTP.js +0 -1
  206. package/dist/InputOTP.js.map +1 -1
  207. package/dist/Kbd.d.ts.map +1 -1
  208. package/dist/Kbd.js.map +1 -1
  209. package/dist/Label.js.map +1 -1
  210. package/dist/MultiSelect/MultiSelectBase.js +1 -1
  211. package/dist/MultiSelect/MultiSelectBase.js.map +1 -1
  212. package/dist/MultiSelect.js.map +1 -1
  213. package/dist/Popover.d.ts.map +1 -1
  214. package/dist/Popover.js.map +1 -1
  215. package/dist/RadioButton.d.ts +6 -0
  216. package/dist/RadioButton.d.ts.map +1 -1
  217. package/dist/RadioButton.js +7 -2
  218. package/dist/RadioButton.js.map +1 -1
  219. package/dist/RadioButtonGroup/RadioButtonGroupBase.d.ts +15 -1
  220. package/dist/RadioButtonGroup/RadioButtonGroupBase.d.ts.map +1 -1
  221. package/dist/RadioButtonGroup/RadioButtonGroupBase.js +166 -15
  222. package/dist/RadioButtonGroup/RadioButtonGroupBase.js.map +1 -1
  223. package/dist/RadioButtonGroup.d.ts +4 -1
  224. package/dist/RadioButtonGroup.d.ts.map +1 -1
  225. package/dist/RadioButtonGroup.js.map +1 -1
  226. package/dist/RadioGroup.d.ts.map +1 -1
  227. package/dist/RadioGroup.js.map +1 -1
  228. package/dist/Select.js +1 -2
  229. package/dist/Select.js.map +1 -1
  230. package/dist/Skeleton.js.map +1 -1
  231. package/dist/Slider.js.map +1 -1
  232. package/dist/Switch/SwitchBase.d.ts.map +1 -1
  233. package/dist/Switch/SwitchBase.js.map +1 -1
  234. package/dist/Switch.js.map +1 -1
  235. package/dist/Tabs/TabsBase.d.ts.map +1 -1
  236. package/dist/Tabs/TabsBase.js +1 -0
  237. package/dist/Tabs/TabsBase.js.map +1 -1
  238. package/dist/Tabs.d.ts.map +1 -1
  239. package/dist/Tabs.js.map +1 -1
  240. package/dist/Textarea.js.map +1 -1
  241. package/dist/Toast.d.ts.map +1 -1
  242. package/dist/Toast.js.map +1 -1
  243. package/dist/Toggle/ToggleBase.js.map +1 -1
  244. package/dist/Toggle.d.ts +5 -6
  245. package/dist/Toggle.d.ts.map +1 -1
  246. package/dist/Toggle.js +4 -19
  247. package/dist/Toggle.js.map +1 -1
  248. package/dist/ToggleGroup/ToggleGroupBase.d.ts.map +1 -1
  249. package/dist/ToggleGroup/ToggleGroupBase.js.map +1 -1
  250. package/dist/ToggleGroup/ToggleGroupItem.d.ts +3 -2
  251. package/dist/ToggleGroup/ToggleGroupItem.d.ts.map +1 -1
  252. package/dist/ToggleGroup/ToggleGroupItem.js +3 -2
  253. package/dist/ToggleGroup/ToggleGroupItem.js.map +1 -1
  254. package/dist/ToggleGroup/ToggleGroupSplitMenuItem.d.ts.map +1 -1
  255. package/dist/ToggleGroup/ToggleGroupSplitMenuItem.js +3 -2
  256. package/dist/ToggleGroup/ToggleGroupSplitMenuItem.js.map +1 -1
  257. package/dist/ToggleGroup.d.ts +3 -2
  258. package/dist/ToggleGroup.d.ts.map +1 -1
  259. package/dist/ToggleGroup.js +1 -1
  260. package/dist/ToggleGroup.js.map +1 -1
  261. package/dist/Tooltip.d.ts.map +1 -1
  262. package/dist/Tooltip.js.map +1 -1
  263. package/dist/Tray.d.ts.map +1 -1
  264. package/dist/Tray.js.map +1 -1
  265. package/dist/components/ToggleGroup/ToggleGroup.context.js.map +1 -1
  266. package/dist/styles/horizon/colors.css +9 -16
  267. package/dist/styles/spectral.css +2 -2
  268. package/dist/utils/activeColorStyle.d.ts +11 -0
  269. package/dist/utils/activeColorStyle.d.ts.map +1 -0
  270. package/dist/utils/activeColorStyle.js +41 -0
  271. package/dist/utils/activeColorStyle.js.map +1 -0
  272. package/package.json +25 -20
@@ -1 +1 @@
1
- {"version":3,"file":"RadioButtonGroupBase.js","names":[],"sources":["../../src/components/RadioButtonGroup/RadioButtonGroupBase.tsx"],"sourcesContent":["import { Slot, type AsChildProp } from '@primitives/slot'\nimport { cn } from '@utils/twUtils'\nimport { createContext, useContext, type ButtonHTMLAttributes, type MouseEvent, type ReactNode, type Ref } from 'react'\n\ninterface RadioButtonGroupContextValue {\n value?: string\n onValueChange?: (value: string) => void\n isKeptActive?: boolean\n expanded?: boolean\n variant?: 'default' | 'outline'\n}\n\nconst RadioButtonGroupContext = createContext<RadioButtonGroupContextValue | null>(null)\n\nexport interface RadioButtonGroupProps {\n asChild?: boolean\n children: ReactNode\n className?: string\n expanded?: boolean\n isKeptActive?: boolean\n onValueChange?: (value: string) => void\n value?: string\n variant?: 'default' | 'outline'\n 'aria-label'?: string\n 'aria-labelledby'?: string\n}\n\nexport interface RadioButtonGroupItemProps extends AsChildProp, Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'value' | 'onSelect' | 'type'> {\n children: ReactNode\n onSelect?: (value: string) => void\n value: string\n}\n\nexport const RadioButtonGroupBase = ({ 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, children, className, expanded = false, isKeptActive = false, onValueChange, value, variant = 'default' }: RadioButtonGroupProps) => {\n return (\n <RadioButtonGroupContext.Provider value={{ value, onValueChange, isKeptActive, expanded, variant }}>\n <div\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n className={cn(\n 'rounded-md [&_button:first-of-type]:rounded-l-md [&_button:last-of-type]:rounded-r-md flex h-fit w-fit items-center',\n 'data-[expanded=true]:w-full',\n `data-[variant=outline]:gap-0 data-[variant=outline]:[--color-toggle-border:var(--color-toggle-outline-border)] data-[variant=outline]:[&_button:not(:last-of-type)]:[border-right-color:var(--color-toggle-outline-divider)]`,\n className,\n )}\n data-expanded={expanded}\n data-testid='spectral-radio-button-group'\n data-variant={variant}\n role='radiogroup'\n >\n {children}\n </div>\n </RadioButtonGroupContext.Provider>\n )\n}\n\nexport const RadioButtonGroupItem = ({\n asChild = false,\n children,\n className,\n disabled = false,\n onClick,\n onSelect,\n ref,\n value,\n ...rest\n}: RadioButtonGroupItemProps & {\n ref?: Ref<HTMLButtonElement>\n}) => {\n const context = useContext(RadioButtonGroupContext)\n\n if (!context) {\n throw new Error('RadioButtonGroupItem must be used within a RadioButtonGroup')\n }\n\n const { value: selectedValue, onValueChange, isKeptActive, expanded, variant } = context\n const isSelected = selectedValue === value\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (onClick) onClick(event)\n if (event.defaultPrevented) return\n if (!disabled) {\n if (onValueChange) {\n onValueChange(value)\n }\n if (onSelect) {\n onSelect(value)\n }\n }\n }\n\n const baseProps = {\n ...rest,\n className: cn(\n `gap-2 text-sm font-medium focus-visible:border-ring focus-visible:ring-ring/50 h-9 px-3 min-w-9 [&_svg:not([class*='size-']):not([width]):not([height])]:size-4 inline-flex items-center justify-center rounded-none border border-toggle-border bg-toggle-bg text-toggle-text shadow-none transition-[colors] outline-none hover:cursor-pointer hover:border-toggle-border--hover hover:bg-toggle-bg--hover hover:text-toggle-text--hover focus:z-10 focus:outline-none focus-visible:z-10 focus-visible:ring-[3px] active:border-toggle-border--active active:bg-toggle-bg--active active:text-toggle-text--active disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&:not(:first-child)]:border-l-0`,\n expanded && 'w-full',\n isKeptActive && 'data-[state=on]:border-toggle-border--active data-[state=on]:bg-toggle-bg--active data-[state=on]:text-toggle-text--active',\n className,\n ),\n disabled,\n onClick: handleClick,\n role: 'radio',\n 'aria-checked': isSelected,\n 'data-state': isSelected ? 'on' : 'off',\n 'data-testid': 'spectral-radio-button-group-item',\n 'data-variant': variant,\n }\n\n if (asChild) {\n return (\n <Slot ref={ref as Ref<HTMLElement>} {...baseProps}>\n {children}\n </Slot>\n )\n }\n\n return (\n <button ref={ref} {...baseProps} type='button'>\n {children}\n </button>\n )\n}\n\nRadioButtonGroupItem.displayName = 'RadioButtonGroupItem'\n"],"mappings":";;;;;;;AAYA,MAAM,0BAA0B,cAAmD,KAAK;AAqBxF,MAAa,wBAAwB,EAAE,cAAc,WAAW,mBAAmB,gBAAgB,UAAU,WAAW,WAAW,OAAO,eAAe,OAAO,eAAe,OAAO,UAAU,gBAAuC;AACrO,QACE,oBAAC,wBAAwB,UAAzB;EAAkC,OAAO;GAAE;GAAO;GAAe;GAAc;GAAU;GAAS;YAChG,oBAAC,OAAD;GACE,cAAY;GACZ,mBAAiB;GACjB,WAAW,GACT,uHACA,+BACA,gOACA,UACD;GACD,iBAAe;GACf,eAAY;GACZ,gBAAc;GACd,MAAK;GAEJ;GACG;EAC2B;;AAIvC,MAAa,wBAAwB,EACnC,UAAU,OACV,UACA,WACA,WAAW,OACX,SACA,UACA,KACA,OACA,GAAG,WAGC;CACJ,MAAM,UAAU,WAAW,wBAAwB;AAEnD,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,8DAA8D;CAGhF,MAAM,EAAE,OAAO,eAAe,eAAe,cAAc,UAAU,YAAY;CACjF,MAAM,aAAa,kBAAkB;CAErC,MAAM,eAAe,UAAyC;AAC5D,MAAI,QAAS,SAAQ,MAAM;AAC3B,MAAI,MAAM,iBAAkB;AAC5B,MAAI,CAAC,UAAU;AACb,OAAI,cACF,eAAc,MAAM;AAEtB,OAAI,SACF,UAAS,MAAM;;;CAKrB,MAAM,YAAY;EAChB,GAAG;EACH,WAAW,GACT,mvBACA,YAAY,UACZ,gBAAgB,8HAChB,UACD;EACD;EACA,SAAS;EACT,MAAM;EACN,gBAAgB;EAChB,cAAc,aAAa,OAAO;EAClC,eAAe;EACf,gBAAgB;EACjB;AAED,KAAI,QACF,QACE,oBAAC,MAAD;EAAW;EAAyB,GAAI;EACrC;EACI;AAIX,QACE,oBAAC,UAAD;EAAa;EAAK,GAAI;EAAW,MAAK;EACnC;EACM;;AAIb,qBAAqB,cAAc"}
1
+ {"version":3,"file":"RadioButtonGroupBase.js","names":[],"sources":["../../src/components/RadioButtonGroup/RadioButtonGroupBase.tsx"],"sourcesContent":["import { Slot, type AsChildProp } from '@primitives/slot'\nimport { getActiveColorStyle, type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\nimport { cn } from '@utils/twUtils'\nimport { createContext, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState, type ButtonHTMLAttributes, type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react'\n\ninterface RadioButtonGroupContextValue {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n focusItemByIndex: (index: number) => void\n getIndexByValue: (value: string) => number\n isDisabledAtIndex: (index: number) => boolean\n itemCount: () => number\n loop: boolean\n orientation: 'horizontal' | 'vertical'\n selectByIndex: (index: number) => void\n onValueChange?: (value: string) => void\n value?: string\n isKeptActive?: boolean\n expanded?: boolean\n variant?: 'default' | 'outline'\n register: (value: string, element: HTMLButtonElement | null, disabled: boolean) => () => void\n}\n\nconst RadioButtonGroupContext = createContext<RadioButtonGroupContextValue | null>(null)\n\nexport interface RadioButtonGroupProps {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n asChild?: boolean\n children: ReactNode\n className?: string\n expanded?: boolean\n isKeptActive?: boolean\n loop?: boolean\n onValueChange?: (value: string) => void\n orientation?: 'horizontal' | 'vertical'\n value?: string\n variant?: 'default' | 'outline'\n 'aria-label'?: string\n 'aria-labelledby'?: string\n}\n\nexport interface RadioButtonGroupItemProps extends AsChildProp, Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'value' | 'onSelect' | 'type'> {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n children: ReactNode\n onSelect?: (value: string) => void\n value: string\n}\n\ninterface RadioButtonRegistryItem {\n value: string\n element: HTMLButtonElement | null\n disabled: boolean\n}\n\nexport const RadioButtonGroupBase = ({\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n activeColor = 'default',\n activeTextColor,\n children,\n className,\n expanded = false,\n isKeptActive = false,\n loop = true,\n onValueChange,\n orientation = 'horizontal',\n value,\n variant = 'default',\n}: RadioButtonGroupProps) => {\n const [registry, setRegistry] = useState<RadioButtonRegistryItem[]>([])\n\n const register = useCallback((nextValue: string, element: HTMLButtonElement | null, disabled: boolean) => {\n setRegistry((previousRegistry) => {\n const existingIndex = previousRegistry.findIndex((item) => item.value === nextValue)\n\n if (existingIndex !== -1) {\n const existingItem = previousRegistry[existingIndex]\n if (existingItem?.element === element && existingItem.disabled === disabled) return previousRegistry\n\n return previousRegistry.map((item, index) => (index === existingIndex ? { value: nextValue, element, disabled } : item))\n }\n\n return [...previousRegistry, { value: nextValue, element, disabled }]\n })\n\n return () => {\n setRegistry((previousRegistry) => previousRegistry.filter((item) => item.value !== nextValue))\n }\n }, [])\n\n const getIndexByValue = useCallback((itemValue: string) => registry.findIndex((item) => item.value === itemValue), [registry])\n const itemCount = useCallback(() => registry.length, [registry])\n const isDisabledAtIndex = useCallback((index: number) => registry[index]?.disabled ?? false, [registry])\n\n const getNextEnabledIndex = useCallback(\n (startIndex: number, direction: 1 | -1) => {\n const items = registry\n if (items.length === 0) return -1\n\n let currentIndex = startIndex\n for (let attempt = 0; attempt < items.length; attempt += 1) {\n if (!loop && (currentIndex < 0 || currentIndex >= items.length)) return -1\n const boundedIndex = loop ? (currentIndex + items.length) % items.length : currentIndex\n if (!items[boundedIndex]?.disabled) return boundedIndex\n currentIndex += direction\n }\n\n return -1\n },\n [loop, registry],\n )\n\n const focusItemByIndex = useCallback(\n (index: number) => {\n const targetIndex = getNextEnabledIndex(index, 1)\n if (targetIndex === -1) return\n registry[targetIndex]?.element?.focus()\n },\n [getNextEnabledIndex, registry],\n )\n\n const selectByIndex = useCallback(\n (index: number) => {\n const target = registry[index]\n if (!target || target.disabled) return\n onValueChange?.(target.value)\n },\n [onValueChange, registry],\n )\n\n const contextValue = useMemo(\n () => ({\n activeColor,\n activeTextColor,\n focusItemByIndex,\n getIndexByValue,\n isDisabledAtIndex,\n itemCount,\n loop,\n onValueChange,\n orientation,\n selectByIndex,\n value,\n isKeptActive,\n expanded,\n variant,\n register,\n }),\n [activeColor, activeTextColor, expanded, focusItemByIndex, getIndexByValue, isDisabledAtIndex, isKeptActive, itemCount, loop, onValueChange, orientation, register, selectByIndex, value, variant],\n )\n\n return (\n <RadioButtonGroupContext.Provider value={contextValue}>\n <div\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n className={cn(\n 'rounded-md [&_button:first-of-type]:rounded-l-md [&_button:last-of-type]:rounded-r-md flex h-fit w-fit items-center',\n 'data-[expanded=true]:w-full',\n `data-[variant=outline]:gap-0 data-[variant=outline]:[--color-toggle-border:var(--color-toggle-outline-border)] data-[variant=outline]:[&_button:not(:last-of-type)]:[border-right-color:var(--color-toggle-outline-divider)]`,\n className,\n )}\n data-expanded={expanded}\n data-orientation={orientation}\n data-testid='spectral-radio-button-group'\n data-variant={variant}\n aria-orientation={orientation}\n role='radiogroup'\n >\n {children}\n </div>\n </RadioButtonGroupContext.Provider>\n )\n}\n\nexport const RadioButtonGroupItem = ({\n asChild = false,\n activeColor,\n activeTextColor,\n children,\n className,\n disabled = false,\n onClick,\n onSelect,\n ref,\n style,\n value,\n ...rest\n}: RadioButtonGroupItemProps & {\n ref?: Ref<HTMLButtonElement | null>\n}) => {\n const context = useContext(RadioButtonGroupContext)\n\n if (!context) {\n throw new Error('RadioButtonGroupItem must be used within a RadioButtonGroup')\n }\n\n const { activeColor: contextActiveColor, activeTextColor: contextActiveTextColor, value: selectedValue, onValueChange, isKeptActive, expanded, variant, orientation, register, getIndexByValue, isDisabledAtIndex, focusItemByIndex, itemCount, loop, selectByIndex } = context\n const isSelected = selectedValue === value\n const resolvedActiveColor = activeColor ?? contextActiveColor\n const resolvedActiveTextColor = activeTextColor ?? contextActiveTextColor\n const itemRef = useRef<HTMLButtonElement | null>(null)\n\n useImperativeHandle<HTMLButtonElement | null, HTMLButtonElement | null>(ref, () => itemRef.current)\n\n useEffect(() => register(value, itemRef.current, disabled), [disabled, register, value])\n\n const setItemRef = (node: HTMLButtonElement | null) => {\n itemRef.current = node\n if (!ref) return\n if (typeof ref === 'function') {\n ref(node)\n return\n }\n ref.current = node\n }\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (onClick) onClick(event)\n if (event.defaultPrevented) return\n if (!disabled) {\n if (onValueChange) {\n onValueChange(value)\n }\n if (onSelect) {\n onSelect(value)\n }\n }\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (rest.onKeyDown) rest.onKeyDown(event)\n if (event.defaultPrevented) return\n\n const currentIndex = getIndexByValue(value)\n if (currentIndex === -1) return\n\n const key = event.key\n const isHorizontal = orientation === 'horizontal'\n const moveNext = (isHorizontal && key === 'ArrowRight') || (!isHorizontal && key === 'ArrowDown')\n const movePrev = (isHorizontal && key === 'ArrowLeft') || (!isHorizontal && key === 'ArrowUp')\n\n if (key === 'Home') {\n event.preventDefault()\n for (let index = 0; index < itemCount(); index += 1) {\n if (!isDisabledAtIndex(index)) {\n selectByIndex(index)\n focusItemByIndex(index)\n return\n }\n }\n return\n }\n\n if (key === 'End') {\n event.preventDefault()\n for (let index = itemCount() - 1; index >= 0; index -= 1) {\n if (!isDisabledAtIndex(index)) {\n selectByIndex(index)\n focusItemByIndex(index)\n return\n }\n }\n return\n }\n\n if (!moveNext && !movePrev) return\n event.preventDefault()\n\n const direction = moveNext ? 1 : -1\n let nextIndex = currentIndex + direction\n for (let attempt = 0; attempt < itemCount(); attempt += 1) {\n if (!loop && (nextIndex < 0 || nextIndex >= itemCount())) return\n const boundedIndex = loop ? (nextIndex + itemCount()) % itemCount() : nextIndex\n if (!isDisabledAtIndex(boundedIndex)) {\n selectByIndex(boundedIndex)\n focusItemByIndex(boundedIndex)\n return\n }\n nextIndex += direction\n }\n }\n\n const selectedIndex = selectedValue ? getIndexByValue(selectedValue) : -1\n const firstEnabledIndex = (() => {\n for (let index = 0; index < itemCount(); index += 1) {\n if (!isDisabledAtIndex(index)) return index\n }\n return -1\n })()\n const currentIndex = getIndexByValue(value)\n const tabIndex = isSelected || (selectedIndex === -1 && firstEnabledIndex !== -1 && currentIndex === firstEnabledIndex) ? 0 : -1\n\n const baseProps = {\n ...rest,\n className: cn(\n `gap-2 text-sm font-medium h-9 px-3 min-w-9 [&_svg:not([class*='size-']):not([width]):not([height])]:size-4 inline-flex items-center justify-center rounded-none border border-toggle-border bg-toggle-bg text-toggle-text shadow-none transition-colors hover:cursor-pointer hover:border-toggle-border--hover hover:bg-toggle-bg--hover hover:text-toggle-text--hover focus-visible:z-10 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent active:border-toggle-border--active active:bg-toggle-bg--active active:text-toggle-text--active disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&:not(:first-child)]:border-l-0`,\n expanded && 'w-full',\n isKeptActive && 'data-[state=on]:border-toggle-border--active data-[state=on]:bg-toggle-bg--active data-[state=on]:text-toggle-text--active',\n className,\n ),\n style: { ...getActiveColorStyle(resolvedActiveColor, resolvedActiveTextColor), ...style },\n disabled,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n role: 'radio',\n 'aria-checked': isSelected,\n 'data-state': isSelected ? 'on' : 'off',\n 'data-testid': 'spectral-radio-button-group-item',\n 'data-variant': variant,\n tabIndex: disabled ? -1 : tabIndex,\n }\n\n if (asChild) {\n return (\n <Slot\n ref={setItemRef as Ref<HTMLElement>}\n {...baseProps}\n >\n {children}\n </Slot>\n )\n }\n\n return (\n <button\n ref={setItemRef}\n {...baseProps}\n type='button'\n >\n {children}\n </button>\n )\n}\n\nRadioButtonGroupItem.displayName = 'RadioButtonGroupItem'\n"],"mappings":"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"}
@@ -15,16 +15,19 @@ declare const RadioButtonGroup: ({
15
15
  declare const RadioButtonGroupItem: {
16
16
  ({
17
17
  asChild,
18
+ activeColor,
19
+ activeTextColor,
18
20
  children,
19
21
  className,
20
22
  disabled,
21
23
  onClick,
22
24
  onSelect,
23
25
  ref,
26
+ style,
24
27
  value,
25
28
  ...rest
26
29
  }: RadioButtonGroupItemProps$1 & {
27
- ref?: _$react.Ref<HTMLButtonElement>;
30
+ ref?: _$react.Ref<HTMLButtonElement | null>;
28
31
  }): _$react_jsx_runtime0.JSX.Element;
29
32
  displayName: string;
30
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"RadioButtonGroup.d.ts","names":[],"sources":["../src/components/RadioButtonGroup/RadioButtonGroup.tsx"],"mappings":";;;;;;;KAIY,qBAAA,GAAwB,cAAA,QAAsB,oBAAA;AAAA,KAC9C,yBAAA,GAA4B,2BAAA;AAAA,cAE3B,gBAAA;EAAgB,SAAA;EAAA,QAAA;EAAA,GAAA;AAAA,GAAuC,qBAAA,KAAqB,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAO5E,oBAAA;EAAA"}
1
+ {"version":3,"file":"RadioButtonGroup.d.ts","names":[],"sources":["../src/components/RadioButtonGroup/RadioButtonGroup.tsx"],"mappings":";;;;;;;KAIY,qBAAA,GAAwB,cAAA,QAAsB,oBAAA;AAAA,KAC9C,yBAAA,GAA4B,2BAAA;AAAA,cAE3B,gBAAA;EAAgB,SAAA;EAAA,QAAA;EAAA,GAAA;AAAA,GAAuC,qBAAA,KAAqB,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAU5E,oBAAA;EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RadioButtonGroup.js","names":["RadioButtonGroupItemBase"],"sources":["../src/components/RadioButtonGroup/RadioButtonGroup.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentProps } from 'react'\nimport { RadioButtonGroupBase, RadioButtonGroupItem as RadioButtonGroupItemBase, type RadioButtonGroupItemProps as RadioButtonGroupItemPropsBase } from './RadioButtonGroupBase'\n\nexport type RadioButtonGroupProps = ComponentProps<typeof RadioButtonGroupBase>\nexport type RadioButtonGroupItemProps = RadioButtonGroupItemPropsBase\n\nexport const RadioButtonGroup = ({ className, children, ...props }: RadioButtonGroupProps) => {\n return (\n <RadioButtonGroupBase className={cn('rounded-md [&_button:first-of-type]:rounded-l-md [&_button:last-of-type]:rounded-r-md flex h-fit w-fit items-center whitespace-nowrap', className)} {...props}>\n {children}\n </RadioButtonGroupBase>\n )\n}\nexport const RadioButtonGroupItem = RadioButtonGroupItemBase\n"],"mappings":";;;;;;;AAOA,MAAa,oBAAoB,EAAE,WAAW,UAAU,GAAG,YAAmC;AAC5F,QACE,oBAAC,sBAAD;EAAsB,WAAW,GAAG,yIAAyI,UAAU;EAAE,GAAI;EAC1L;EACoB;;AAG3B,MAAa,uBAAuBA"}
1
+ {"version":3,"file":"RadioButtonGroup.js","names":["RadioButtonGroupItemBase"],"sources":["../src/components/RadioButtonGroup/RadioButtonGroup.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentProps } from 'react'\nimport { RadioButtonGroupBase, RadioButtonGroupItem as RadioButtonGroupItemBase, type RadioButtonGroupItemProps as RadioButtonGroupItemPropsBase } from './RadioButtonGroupBase'\n\nexport type RadioButtonGroupProps = ComponentProps<typeof RadioButtonGroupBase>\nexport type RadioButtonGroupItemProps = RadioButtonGroupItemPropsBase\n\nexport const RadioButtonGroup = ({ className, children, ...props }: RadioButtonGroupProps) => {\n return (\n <RadioButtonGroupBase\n className={cn('rounded-md [&_button:first-of-type]:rounded-l-md [&_button:last-of-type]:rounded-r-md flex h-fit w-fit items-center whitespace-nowrap', className)}\n {...props}\n >\n {children}\n </RadioButtonGroupBase>\n )\n}\nexport const RadioButtonGroupItem = RadioButtonGroupItemBase\n"],"mappings":";;;;;;;AAOA,MAAa,oBAAoB,EAAE,WAAW,UAAU,GAAG,YAAmC;AAC5F,QACE,oBAAC,sBAAD;EACE,WAAW,GAAG,yIAAyI,UAAU;EACjK,GAAI;EAEH;EACoB;;AAG3B,MAAa,uBAAuBA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup.d.ts","names":[],"sources":["../src/components/RadioGroup/RadioGroup.tsx"],"mappings":";;;;;;;KAOK,iBAAA;AAAA,UAEY,eAAA,SAAwB,IAAA,CAAK,cAAA,QAAsB,mBAAA,CAAoB,IAAA;EACtF,kBAAA;EACA,YAAA;EACA,SAAA;EACA,QAAA;EACA,YAAA,GAAe,kBAAA;EACf,aAAA;EACA,mBAAA;EACA,mBAAA;EACA,IAAA;EACA,QAAA,IAAY,QAAA;EACZ,aAAA,GAAgB,QAAA;EAChB,WAAA;EACA,QAAA;EACA,QAAA;EACA,KAAA,GAAQ,cAAA;EACR,OAAA,GAAU,iBAAA;EACV,cAAA,GAAiB,kBAAA;AAAA;AAAA,UAGF,mBAAA,SAA4B,cAAA,QAAsB,mBAAA,CAAoB,IAAA;EACrF,SAAA;EACA,QAAA,GAAW,SAAA;EACX,WAAA,YAAuB,SAAA;EACvB,EAAA;EACA,KAAA;AAAA;AAAA,iBACD,UAAA,CAqBC,QAAA,EAAU,eAAA;EACR,GAAA,GAAM,GAAA,CAAI,YAAA,QAAoB,mBAAA,CAAoB,IAAA;AAAA,IAEnD,YAAA;AAAA,kBAAY,UAAA;EAAA;;;EAyIb,QAAA;EACA,SAAA;EACA,QAAA;EACA,GAAA;EACA,KAAA;EAAA,GACG;AAAA,GACF,mBAAA;EACD,GAAA,GAAM,GAAA,CAAI,YAAA,QAAoB,mBAAA,CAAoB,IAAA;AAAA,IAChD,YAAA;AAAA,kBAAY,cAAA;EAAA;;;EAgCd,GAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,cAAA,QAAsB,KAAA;EACvB,GAAA,GAAM,GAAA,CAAI,YAAA,QAAoB,KAAA;AAAA,IAC5B,YAAA;AAAA,kBAAY,eAAA;EAAA"}
1
+ {"version":3,"file":"RadioGroup.d.ts","names":[],"sources":["../src/components/RadioGroup/RadioGroup.tsx"],"mappings":";;;;;;;KAOK,iBAAA;AAAA,UAEY,eAAA,SAAwB,IAAA,CAAK,cAAA,QAAsB,mBAAA,CAAoB,IAAA;EACtF,kBAAA;EACA,YAAA;EACA,SAAA;EACA,QAAA;EACA,YAAA,GAAe,kBAAA;EACf,aAAA;EACA,mBAAA;EACA,mBAAA;EACA,IAAA;EACA,QAAA,IAAY,QAAA;EACZ,aAAA,GAAgB,QAAA;EAChB,WAAA;EACA,QAAA;EACA,QAAA;EACA,KAAA,GAAQ,cAAA;EACR,OAAA,GAAU,iBAAA;EACV,cAAA,GAAiB,kBAAA;AAAA;AAAA,UAGF,mBAAA,SAA4B,cAAA,QAAsB,mBAAA,CAAoB,IAAA;EACrF,SAAA;EACA,QAAA,GAAW,SAAA;EACX,WAAA,YAAuB,SAAA;EACvB,EAAA;EACA,KAAA;AAAA;AAAA,iBACD,UAAA,CAqBC,QAAA,EAAU,eAAA;EACR,GAAA,GAAM,GAAA,CAAI,YAAA,QAAoB,mBAAA,CAAoB,IAAA;AAAA,IAEnD,YAAA;AAAA,kBAAY,UAAA;EAAA;;;EAqKb,QAAA;EACA,SAAA;EACA,QAAA;EACA,GAAA;EACA,KAAA;EAAA,GACG;AAAA,GACF,mBAAA;EACD,GAAA,GAAM,GAAA,CAAI,YAAA,QAAoB,mBAAA,CAAoB,IAAA;AAAA,IAChD,YAAA;AAAA,kBAAY,cAAA;EAAA;;;EAqDd,GAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,cAAA,QAAsB,KAAA;EACvB,GAAA,GAAM,GAAA,CAAI,YAAA,QAAoB,KAAA;AAAA,IAC5B,YAAA;AAAA,kBAAY,eAAA;EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup.js","names":[],"sources":["../src/components/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import { Label } from '@components/Label/Label'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { ErrorMessage, WarningMessage, useFormFieldId, type BaseFormFieldProps, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { AnimatePresence, motion, useReducedMotion, type Transition } from 'motion/react'\nimport { createContext, memo, useContext, useId, useMemo, type ComponentProps, type ComponentRef, type ReactElement, type ReactNode, type Ref } from 'react'\n\ntype RadioGroupVariant = 'default' | 'unstyled'\n\nexport interface RadioGroupProps extends Omit<ComponentProps<typeof RadioGroupPrimitive.Root>, 'onChange' | 'disabled'> {\n 'aria-describedby'?: string\n 'aria-label'?: string\n className?: string\n disabled?: boolean | string[]\n errorMessage?: BaseFormFieldProps['errorMessage']\n itemClassName?: string\n messageReserveLines?: number\n messageReserveSpace?: boolean\n name: string\n onChange?: (selected: string) => void\n onValueChange: (selected: string) => void\n orientation?: 'horizontal' | 'vertical'\n required?: boolean\n selected?: string\n state?: FormFieldState\n variant?: RadioGroupVariant\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nexport interface RadioGroupItemProps extends ComponentProps<typeof RadioGroupPrimitive.Item> {\n className?: string\n children?: ReactNode\n description?: string | ReactNode\n id?: string\n value: string\n}\n\ninterface RadioGroupContextType {\n disabledValues: string[]\n groupDisabled: boolean\n itemClassName?: string\n orientation: 'horizontal' | 'vertical'\n selected?: string\n variant: RadioGroupVariant\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextType>({\n disabledValues: [],\n groupDisabled: false,\n orientation: 'vertical',\n variant: 'default',\n})\n\nconst DISABLED_STYLES = 'pointer-events-none opacity-60'\n\nconst RadioGroup = (\n allProps: RadioGroupProps & {\n ref?: Ref<ComponentRef<typeof RadioGroupPrimitive.Root>>\n },\n): ReactElement => {\n const isControlled = 'selected' in allProps\n const {\n className,\n disabled,\n errorMessage,\n itemClassName,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n onValueChange,\n orientation = 'vertical',\n ref,\n selected: selectedProp,\n state = 'default',\n variant = 'default',\n warningMessage,\n 'aria-describedby': ariaDescribedBy,\n ...props\n } = allProps\n const selected = isControlled ? (selectedProp ?? '') : selectedProp\n const groupId = useFormFieldId(props.id, name)\n const errorMessageId = `${groupId}-error`\n const warningMessageId = `${groupId}-warning`\n const messageId = state === 'error' && errorMessage ? errorMessageId : state === 'warning' && warningMessage ? warningMessageId : undefined\n const handleValueChange = (nextValue: string) => {\n onValueChange(nextValue)\n onChange?.(nextValue)\n }\n\n const contextValue = useMemo(\n () => ({\n disabledValues: Array.isArray(disabled) ? disabled : [],\n groupDisabled: typeof disabled === 'boolean' ? disabled : false,\n itemClassName,\n orientation,\n selected,\n variant,\n }),\n [orientation, variant, disabled, itemClassName, selected],\n )\n\n return (\n <RadioGroupContext.Provider value={contextValue}>\n <div data-slot='radio-group-field' className='space-y-1.5 w-full'>\n <RadioGroupPrimitive.Root\n className={cn('flex w-full text-text-primary', orientation === 'vertical' ? 'gap-4 flex-col' : 'gap-5 flex-row', variant === 'unstyled' && 'gap-2.5 w-fit', className)}\n data-state={state}\n data-testid='spectral-radio-group'\n id={groupId}\n aria-invalid={state === 'error' ? true : undefined}\n aria-describedby={[messageId, ariaDescribedBy].filter(Boolean).join(' ') || undefined}\n disabled={contextValue.groupDisabled}\n name={name}\n onValueChange={handleValueChange}\n ref={ref}\n value={selected}\n {...props}\n />\n <ErrorMessage dataTestId='spectral-radio-group-error-message' id={errorMessageId} message={state === 'error' ? errorMessage : null} messageReserveLines={messageReserveLines} messageReserveSpace={messageReserveSpace && state === 'error'} />\n <WarningMessage dataTestId='spectral-radio-group-warning-message' id={warningMessageId} message={state === 'warning' ? warningMessage : null} messageReserveLines={messageReserveLines} messageReserveSpace={messageReserveSpace && state === 'warning'} />\n </div>\n </RadioGroupContext.Provider>\n )\n}\nRadioGroup.displayName = 'RadioGroup'\n\nconst DEFAULT_TRANSITION: Transition = { type: 'spring', stiffness: 200, damping: 16 }\n\nconst RadioButton = memo(\n ({\n className,\n id,\n isDisabled,\n ref,\n transition = DEFAULT_TRANSITION,\n value,\n ...props\n }: Omit<ComponentProps<typeof RadioGroupPrimitive.Item>, 'asChild'> & {\n isDisabled?: boolean\n ref?: Ref<HTMLButtonElement>\n transition?: Transition\n }) => {\n const prefersReducedMotion = useReducedMotion()\n\n // When reduced motion is preferred, fall back to original non-animated behavior\n if (prefersReducedMotion) {\n return (\n <RadioGroupPrimitive.Item\n className={cn(\n 'h-4.5 w-4.5 border-border-subtle ring-black relative aspect-square cursor-pointer rounded-full border-2 bg-radio-bg transition-colors',\n 'hover:border-radio-border--hover focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'data-[state=checked]:border-radio-border--selected data-[state=checked]:bg-radio-bg',\n isDisabled && DISABLED_STYLES,\n className,\n )}\n data-testid='spectral-radio-group-item'\n disabled={isDisabled}\n id={id}\n ref={ref as Ref<ComponentRef<typeof RadioGroupPrimitive.Item>>}\n value={value}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className={cn(`after:inset-0 after:h-2.5 after:w-2.5 after:absolute after:m-auto after:rounded-full after:bg-radio-bg--selected after:content-['']`, isDisabled && DISABLED_STYLES)} />\n </RadioGroupPrimitive.Item>\n )\n }\n\n return (\n <RadioGroupPrimitive.Item value={value} id={id} disabled={isDisabled} asChild {...props}>\n <motion.button\n className={cn(\n 'h-4.5 w-4.5 border-border-subtle ring-black relative aspect-square cursor-pointer rounded-full border-2 bg-radio-bg transition-colors',\n 'hover:border-radio-border--hover focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'data-[state=checked]:border-radio-border--selected data-[state=checked]:bg-radio-bg',\n isDisabled && DISABLED_STYLES,\n className,\n )}\n data-testid='spectral-radio-group-item'\n ref={ref}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n >\n <RadioGroupPrimitive.Indicator className='relative flex items-center justify-center'>\n <AnimatePresence>\n <motion.div animate={{ opacity: 1, scale: 1 }} className='h-2.5 w-2.5 absolute rounded-full bg-radio-bg--selected' exit={{ opacity: 0, scale: 0 }} initial={{ opacity: 0, scale: 0 }} key='radio-indicator' transition={transition} />\n </AnimatePresence>\n </RadioGroupPrimitive.Indicator>\n </motion.button>\n </RadioGroupPrimitive.Item>\n )\n },\n)\nRadioButton.displayName = 'RadioButton'\n\nconst RadioGroupItem = ({\n children,\n className,\n disabled,\n ref,\n value,\n ...props\n}: RadioGroupItemProps & {\n ref?: Ref<ComponentRef<typeof RadioGroupPrimitive.Item>>\n}): ReactElement => {\n const { disabledValues, groupDisabled, itemClassName, variant, orientation } = useContext(RadioGroupContext)\n const generatedId = useId()\n\n const stringValue = value.toString()\n const id = props.id?.toString() ?? `${stringValue}-${generatedId}`\n const isDisabled = groupDisabled || disabledValues.includes(stringValue) || Boolean(disabled)\n\n if (variant === 'unstyled') {\n return (\n <RadioGroupPrimitive.Item asChild data-testid='spectral-radio-group-item' disabled={isDisabled} id={id} ref={ref} value={stringValue} {...props}>\n <Label className={cn('rounded flex h-fit w-fit border-2 border-transparent data-[state=checked]:border-radio-border--selected', isDisabled && DISABLED_STYLES, itemClassName, className)} data-testid='spectral-radio-group-item-label' htmlFor={id}>\n {children}\n </Label>\n </RadioGroupPrimitive.Item>\n )\n }\n\n return (\n <div className={cn('flex items-center', isDisabled && DISABLED_STYLES, itemClassName, className, orientation)}>\n <RadioButton ref={ref} value={stringValue} id={id} isDisabled={isDisabled} {...props} />\n {children && (\n <Label className={cn('text-md font-normal cursor-pointer', orientation === 'vertical' ? 'ml-2' : 'ml-1')} htmlFor={id}>\n {children}\n </Label>\n )}\n </div>\n )\n}\nRadioGroupItem.displayName = 'RadioGroup.Item'\n\nconst RadioGroupLabel = ({\n ref,\n className,\n ...props\n}: ComponentProps<typeof Label> & {\n ref?: Ref<ComponentRef<typeof Label>>\n}): ReactElement => {\n return <Label ref={ref} data-testid='spectral-radio-group-label' className={cn('text-md font-medium block', className)} {...props} />\n}\nRadioGroupLabel.displayName = 'RadioGroup.Label'\n\nexport { RadioGroup, RadioGroupItem, RadioGroupLabel }\n"],"mappings":"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"}
1
+ {"version":3,"file":"RadioGroup.js","names":[],"sources":["../src/components/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import { Label } from '@components/Label/Label'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { ErrorMessage, WarningMessage, useFormFieldId, type BaseFormFieldProps, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { AnimatePresence, motion, useReducedMotion, type Transition } from 'motion/react'\nimport { createContext, memo, useContext, useId, useMemo, type ComponentProps, type ComponentRef, type ReactElement, type ReactNode, type Ref } from 'react'\n\ntype RadioGroupVariant = 'default' | 'unstyled'\n\nexport interface RadioGroupProps extends Omit<ComponentProps<typeof RadioGroupPrimitive.Root>, 'onChange' | 'disabled'> {\n 'aria-describedby'?: string\n 'aria-label'?: string\n className?: string\n disabled?: boolean | string[]\n errorMessage?: BaseFormFieldProps['errorMessage']\n itemClassName?: string\n messageReserveLines?: number\n messageReserveSpace?: boolean\n name: string\n onChange?: (selected: string) => void\n onValueChange: (selected: string) => void\n orientation?: 'horizontal' | 'vertical'\n required?: boolean\n selected?: string\n state?: FormFieldState\n variant?: RadioGroupVariant\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nexport interface RadioGroupItemProps extends ComponentProps<typeof RadioGroupPrimitive.Item> {\n className?: string\n children?: ReactNode\n description?: string | ReactNode\n id?: string\n value: string\n}\n\ninterface RadioGroupContextType {\n disabledValues: string[]\n groupDisabled: boolean\n itemClassName?: string\n orientation: 'horizontal' | 'vertical'\n selected?: string\n variant: RadioGroupVariant\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextType>({\n disabledValues: [],\n groupDisabled: false,\n orientation: 'vertical',\n variant: 'default',\n})\n\nconst DISABLED_STYLES = 'pointer-events-none opacity-60'\n\nconst RadioGroup = (\n allProps: RadioGroupProps & {\n ref?: Ref<ComponentRef<typeof RadioGroupPrimitive.Root>>\n },\n): ReactElement => {\n const isControlled = 'selected' in allProps\n const {\n className,\n disabled,\n errorMessage,\n itemClassName,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n onValueChange,\n orientation = 'vertical',\n ref,\n selected: selectedProp,\n state = 'default',\n variant = 'default',\n warningMessage,\n 'aria-describedby': ariaDescribedBy,\n ...props\n } = allProps\n const selected = isControlled ? (selectedProp ?? '') : selectedProp\n const groupId = useFormFieldId(props.id, name)\n const errorMessageId = `${groupId}-error`\n const warningMessageId = `${groupId}-warning`\n const messageId = state === 'error' && errorMessage ? errorMessageId : state === 'warning' && warningMessage ? warningMessageId : undefined\n const handleValueChange = (nextValue: string) => {\n onValueChange(nextValue)\n onChange?.(nextValue)\n }\n\n const contextValue = useMemo(\n () => ({\n disabledValues: Array.isArray(disabled) ? disabled : [],\n groupDisabled: typeof disabled === 'boolean' ? disabled : false,\n itemClassName,\n orientation,\n selected,\n variant,\n }),\n [orientation, variant, disabled, itemClassName, selected],\n )\n\n return (\n <RadioGroupContext.Provider value={contextValue}>\n <div\n data-slot='radio-group-field'\n className='space-y-1.5 w-full'\n >\n <RadioGroupPrimitive.Root\n className={cn('flex w-full text-text-primary', orientation === 'vertical' ? 'gap-4 flex-col' : 'gap-5 flex-row', variant === 'unstyled' && 'gap-2.5 w-fit', className)}\n data-state={state}\n data-testid='spectral-radio-group'\n id={groupId}\n aria-invalid={state === 'error' ? true : undefined}\n aria-describedby={[messageId, ariaDescribedBy].filter(Boolean).join(' ') || undefined}\n disabled={contextValue.groupDisabled}\n name={name}\n onValueChange={handleValueChange}\n ref={ref}\n value={selected}\n {...props}\n />\n <ErrorMessage\n dataTestId='spectral-radio-group-error-message'\n id={errorMessageId}\n message={state === 'error' ? errorMessage : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'error'}\n />\n <WarningMessage\n dataTestId='spectral-radio-group-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? warningMessage : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'warning'}\n />\n </div>\n </RadioGroupContext.Provider>\n )\n}\nRadioGroup.displayName = 'RadioGroup'\n\nconst DEFAULT_TRANSITION: Transition = { type: 'spring', stiffness: 200, damping: 16 }\n\nconst RadioButton = memo(\n ({\n className,\n id,\n isDisabled,\n ref,\n transition = DEFAULT_TRANSITION,\n value,\n ...props\n }: Omit<ComponentProps<typeof RadioGroupPrimitive.Item>, 'asChild'> & {\n isDisabled?: boolean\n ref?: Ref<HTMLButtonElement>\n transition?: Transition\n }) => {\n const prefersReducedMotion = useReducedMotion()\n\n // When reduced motion is preferred, fall back to original non-animated behavior\n if (prefersReducedMotion) {\n return (\n <RadioGroupPrimitive.Item\n className={cn(\n 'h-4.5 w-4.5 border-border-subtle ring-black relative aspect-square cursor-pointer rounded-full border-2 bg-radio-bg transition-colors',\n 'hover:border-radio-border--hover focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'data-[state=checked]:border-radio-border--selected data-[state=checked]:bg-radio-bg',\n isDisabled && DISABLED_STYLES,\n className,\n )}\n data-testid='spectral-radio-group-item'\n disabled={isDisabled}\n id={id}\n ref={ref as Ref<ComponentRef<typeof RadioGroupPrimitive.Item>>}\n value={value}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className={cn(`after:inset-0 after:h-2.5 after:w-2.5 after:absolute after:m-auto after:rounded-full after:bg-radio-bg--selected after:content-['']`, isDisabled && DISABLED_STYLES)} />\n </RadioGroupPrimitive.Item>\n )\n }\n\n return (\n <RadioGroupPrimitive.Item\n value={value}\n id={id}\n disabled={isDisabled}\n asChild\n {...props}\n >\n <motion.button\n className={cn(\n 'h-4.5 w-4.5 border-border-subtle ring-black relative aspect-square cursor-pointer rounded-full border-2 bg-radio-bg transition-colors',\n 'hover:border-radio-border--hover focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'data-[state=checked]:border-radio-border--selected data-[state=checked]:bg-radio-bg',\n isDisabled && DISABLED_STYLES,\n className,\n )}\n data-testid='spectral-radio-group-item'\n ref={ref}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n >\n <RadioGroupPrimitive.Indicator className='relative flex items-center justify-center'>\n <AnimatePresence>\n <motion.div\n animate={{ opacity: 1, scale: 1 }}\n className='h-2.5 w-2.5 absolute rounded-full bg-radio-bg--selected'\n exit={{ opacity: 0, scale: 0 }}\n initial={{ opacity: 0, scale: 0 }}\n key='radio-indicator'\n transition={transition}\n />\n </AnimatePresence>\n </RadioGroupPrimitive.Indicator>\n </motion.button>\n </RadioGroupPrimitive.Item>\n )\n },\n)\nRadioButton.displayName = 'RadioButton'\n\nconst RadioGroupItem = ({\n children,\n className,\n disabled,\n ref,\n value,\n ...props\n}: RadioGroupItemProps & {\n ref?: Ref<ComponentRef<typeof RadioGroupPrimitive.Item>>\n}): ReactElement => {\n const { disabledValues, groupDisabled, itemClassName, variant, orientation } = useContext(RadioGroupContext)\n const generatedId = useId()\n\n const stringValue = value.toString()\n const id = props.id?.toString() ?? `${stringValue}-${generatedId}`\n const isDisabled = groupDisabled || disabledValues.includes(stringValue) || Boolean(disabled)\n\n if (variant === 'unstyled') {\n return (\n <RadioGroupPrimitive.Item\n asChild\n data-testid='spectral-radio-group-item'\n disabled={isDisabled}\n id={id}\n ref={ref}\n value={stringValue}\n {...props}\n >\n <Label\n className={cn('rounded flex h-fit w-fit border-2 border-transparent data-[state=checked]:border-radio-border--selected', isDisabled && DISABLED_STYLES, itemClassName, className)}\n data-testid='spectral-radio-group-item-label'\n htmlFor={id}\n >\n {children}\n </Label>\n </RadioGroupPrimitive.Item>\n )\n }\n\n return (\n <div className={cn('flex items-center', isDisabled && DISABLED_STYLES, itemClassName, className, orientation)}>\n <RadioButton\n ref={ref}\n value={stringValue}\n id={id}\n isDisabled={isDisabled}\n {...props}\n />\n {children && (\n <Label\n className={cn('text-md font-normal cursor-pointer', orientation === 'vertical' ? 'ml-2' : 'ml-1')}\n htmlFor={id}\n >\n {children}\n </Label>\n )}\n </div>\n )\n}\nRadioGroupItem.displayName = 'RadioGroup.Item'\n\nconst RadioGroupLabel = ({\n ref,\n className,\n ...props\n}: ComponentProps<typeof Label> & {\n ref?: Ref<ComponentRef<typeof Label>>\n}): ReactElement => {\n return (\n <Label\n ref={ref}\n data-testid='spectral-radio-group-label'\n className={cn('text-md font-medium block', className)}\n {...props}\n />\n )\n}\nRadioGroupLabel.displayName = 'RadioGroup.Label'\n\nexport { RadioGroup, RadioGroupItem, RadioGroupLabel }\n"],"mappings":"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"}
package/dist/Select.js CHANGED
@@ -15,7 +15,7 @@ import * as SelectPrimitive from "@radix-ui/react-select";
15
15
  //#region src/components/Select/Select.tsx
16
16
  const Select = (allProps) => {
17
17
  const isControlled = "value" in allProps;
18
- const { align = "start", alignOffset = 0, avoidCollisions = true, className, collisionBoundary, collisionPadding = 10, defaultValue, dropdownWidth = "trigger", emptyMessage = "No options found", errorMessage, disabled, id, label, labelClassName, loadingMessage = "Loading…", messageReserveLines = 1, messageReserveSpace = false, name, onChange, onValueChange, options = [], placeholder = "Select an option", position = "popper", ref, required, side = "bottom", sideOffset = 4, state = "default", value: valueProp, warningMessage, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, ...props } = allProps;
18
+ const { align = "start", alignOffset = 0, avoidCollisions = true, className, collisionBoundary, collisionPadding = 10, defaultValue, dropdownWidth = "trigger", emptyMessage = "No options found", errorMessage, disabled, id, label, labelClassName, loadingMessage = "Loading…", messageReserveLines = 1, messageReserveSpace = false, name, onChange, onValueChange, options, placeholder = "Select an option", position = "popper", ref, required, side = "bottom", sideOffset = 4, state = "default", value: valueProp, warningMessage, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, ...props } = allProps;
19
19
  const value = isControlled ? valueProp ?? "" : valueProp;
20
20
  const [open, setOpen] = useState(false);
21
21
  const { dropdownShiftStyle, setDropdownElement } = useAutoDropdownHorizontalShift(open);
@@ -122,7 +122,6 @@ const Select = (allProps) => {
122
122
  "data-testid": "spectral-select-trigger",
123
123
  id: selectId,
124
124
  ref,
125
- role: "combobox",
126
125
  style: getFormFieldCSSProperties(),
127
126
  ...ariaProps,
128
127
  ...props,
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","names":[],"sources":["../src/components/Select/Select.tsx"],"sourcesContent":["import { CheckmarkIcon, ChevronDownIcon, LoaderIcon } from '@components/Icons'\nimport { Label } from '@components/Label/Label'\nimport { SelectValue } from '@primitives/select'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { useAutoDropdownHorizontalShift } from '@utils/dropdownPositioning'\nimport {\n EmptyState,\n ErrorMessage,\n getAriaProps,\n getDropdownWidthStyles,\n getDropdownSurfaceClasses,\n getErrorMessageId,\n getFormFieldCSSProperties,\n getOptionClasses,\n getTriggerClasses,\n groupOptions,\n LoadingState,\n WarningMessage,\n useFormFieldId,\n type BaseFormFieldProps,\n type BaseOption,\n type DropdownWidth,\n type FormFieldState,\n} from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { useState, type ComponentPropsWithoutRef, type CSSProperties, type ReactNode, type Ref } from 'react'\n\ntype SelectOption = BaseOption\ntype Align = 'start' | 'center' | 'end'\ntype Side = 'top' | 'bottom' | 'left' | 'right'\n\nexport interface SelectProps extends Omit<ComponentPropsWithoutRef<'button'>, 'value' | 'onChange' | 'aria-disabled' | 'aria-invalid' | 'aria-required' | 'aria-describedby' | 'aria-label'>, Omit<BaseFormFieldProps, 'state'> {\n defaultValue?: string\n dropdownWidth?: DropdownWidth\n emptyMessage?: ReactNode\n id?: string\n label?: string\n labelClassName?: string\n loadingMessage?: string\n onChange?: (value: string) => void\n onValueChange?: (value: string) => void\n options: SelectOption[]\n placeholder?: string\n state?: Exclude<FormFieldState, 'disabled'>\n value?: string\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nexport interface SelectExtendedProps extends SelectProps {\n align?: Align\n alignOffset?: number\n avoidCollisions?: boolean\n collisionBoundary?: Element | Element[] | null\n collisionPadding?: number | Partial<Record<Side, number>>\n position?: 'popper' | 'item-aligned'\n side?: Side\n sideOffset?: number\n}\n\nexport const Select = (\n allProps: SelectExtendedProps & {\n ref?: Ref<HTMLButtonElement>\n },\n) => {\n const isControlled = 'value' in allProps\n const {\n align = 'start',\n alignOffset = 0,\n avoidCollisions = true,\n className,\n collisionBoundary,\n collisionPadding = 10,\n defaultValue,\n dropdownWidth = 'trigger',\n emptyMessage = 'No options found',\n errorMessage,\n disabled,\n id,\n label,\n labelClassName,\n loadingMessage = 'Loading…',\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n onValueChange,\n options = [],\n placeholder = 'Select an option',\n position = 'popper',\n ref,\n required,\n side = 'bottom',\n sideOffset = 4,\n state = 'default',\n value: valueProp,\n warningMessage,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedBy,\n ...props\n } = allProps\n const value = isControlled ? (valueProp ?? '') : valueProp\n const [open, setOpen] = useState(false)\n const { dropdownShiftStyle, setDropdownElement } = useAutoDropdownHorizontalShift(open)\n const selectId = useFormFieldId(id, name)\n const listboxId = `${selectId}-listbox`\n const errorMessageId = getErrorMessageId(selectId)\n const warningMessageId = `${selectId}-warning`\n const messageId = state === 'error' && errorMessage ? errorMessageId : state === 'warning' && warningMessage ? warningMessageId : undefined\n const { dropdownWidthMode, dropdownWidthStyle, resolvedDropdownWidth } = getDropdownWidthStyles({\n dropdownWidth,\n triggerWidth: 'var(--radix-select-trigger-width)',\n })\n const selectContentStyle = {\n '--spectral-select-content-width': resolvedDropdownWidth,\n ...(position === 'item-aligned' ? { width: resolvedDropdownWidth } : {}),\n ...dropdownWidthStyle,\n ...dropdownShiftStyle,\n } as CSSProperties\n const isDisabled = Boolean(disabled)\n const isLoading = state === 'loading'\n const isInvalid = state === 'error'\n const ariaProps = getAriaProps(state, ariaDescribedBy, required, messageId)\n const { groups, ungrouped } = groupOptions(options)\n const handleValueChange = (nextValue: string) => {\n onChange?.(nextValue)\n onValueChange?.(nextValue)\n }\n\n const renderOptions = () => {\n if (isLoading) {\n return <LoadingState data-testid='spectral-select-loading' message={loadingMessage} />\n }\n\n if (options.length === 0) {\n return <EmptyState data-testid='spectral-select-empty' message={emptyMessage} />\n }\n\n const renderOption = (option: SelectOption) => {\n const isSelected = value === option.value\n\n return (\n <SelectPrimitive.Item className={cn(getOptionClasses(!!option.disabled, false, isSelected), 'relative flex w-full cursor-pointer items-center')} data-testid='spectral-select-item' disabled={option.disabled} key={option.value} value={option.value}>\n <SelectPrimitive.ItemText data-testid='spectral-select-item-text' className='block truncate'>\n {option.label}\n </SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator data-testid='spectral-select-item-selected-indicator' asChild>\n <span className='right-2 h-4 w-4 absolute flex items-center justify-center'>\n <CheckmarkIcon size={16} />\n </span>\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n )\n }\n\n return (\n <>\n {ungrouped.length > 0 && (\n <>\n {ungrouped.map(renderOption)}\n {Object.keys(groups).length > 0 && <SelectPrimitive.Separator className='-mx-1 my-1 h-px bg-border-secondary' data-testid='spectral-select-separator' />}\n </>\n )}\n\n {Object.entries(groups).map(([groupName, groupOptions], groupIndex) => (\n <SelectPrimitive.Group key={groupName} data-testid='spectral-select-group'>\n {groupIndex > 0 && <SelectPrimitive.Separator className='-mx-1 my-1 h-px bg-border-secondary' data-testid='spectral-select-group-separator' />}\n <Label className={cn('px-2 py-1.5 text-base font-semibold text-text-primary', labelClassName)} data-testid='spectral-select-group-label'>\n {groupName}\n </Label>\n {groupOptions.map((option: BaseOption) => renderOption(option))}\n </SelectPrimitive.Group>\n ))}\n </>\n )\n }\n\n return (\n <div className='w-full'>\n {label && (\n <Label className={cn('mb-2 block text-text-primary', labelClassName, isDisabled && 'text-text-secondary')} data-testid='spectral-select-label' htmlFor={selectId}>\n {label}\n </Label>\n )}\n <SelectPrimitive.Root data-testid='spectral-select' defaultValue={defaultValue} disabled={isDisabled} name={name} onOpenChange={setOpen} onValueChange={handleValueChange} open={open} required={required} value={value}>\n <SelectPrimitive.Trigger\n aria-controls={listboxId}\n aria-expanded={open}\n aria-label={ariaLabel ?? label}\n asChild\n className={cn(getTriggerClasses(open, state), 'text-input-text data-placeholder:text-input-text-placeholder!', className)}\n data-slot='select-trigger'\n data-state={state}\n data-testid='spectral-select-trigger'\n id={selectId}\n ref={ref}\n role='combobox'\n style={getFormFieldCSSProperties() as CSSProperties}\n {...ariaProps}\n {...props}\n >\n <button\n className='min-w-0 gap-2 [&>span]:min-w-0 grid w-full cursor-pointer grid-cols-[minmax(0,1fr)_auto] items-center overflow-hidden text-left whitespace-nowrap text-input-text! data-placeholder:text-input-text-placeholder! [&>span]:block [&>span]:overflow-hidden [&>span]:text-ellipsis [&>span]:whitespace-nowrap [&>span[data-placeholder]]:text-input-text-placeholder!'\n type='button'\n disabled={isDisabled}\n >\n <SelectValue data-testid='spectral-select-value' placeholder={placeholder} />\n <SelectPrimitive.Icon asChild>\n <div className='flex shrink-0 cursor-pointer items-center'>{isLoading ? <LoaderIcon size={20} /> : <ChevronDownIcon className={cn('transition-transform duration-200', open && 'rotate-180')} size={20} />}</div>\n </SelectPrimitive.Icon>\n </button>\n </SelectPrimitive.Trigger>\n\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n align={align}\n alignOffset={alignOffset}\n avoidCollisions={avoidCollisions}\n className={cn(\n 'relative z-50 motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=open]:animate-in',\n getDropdownSurfaceClasses(),\n 'motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=closed]:zoom-out-95 motion-safe:data-[state=open]:fade-in-0 motion-safe:data-[state=open]:zoom-in-95',\n 'max-h-[min(var(--radix-select-content-available-height),300px)] motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=top]:slide-in-from-bottom-2',\n 'min-w-32 origin-(--radix-select-content-transform-origin) overflow-hidden',\n position === 'popper' && 'data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1',\n )}\n collisionBoundary={collisionBoundary}\n collisionPadding={collisionPadding}\n data-dropdown-width-mode={dropdownWidthMode}\n data-dropdown-width-value={dropdownWidthMode === 'custom' ? dropdownWidth : undefined}\n id={listboxId}\n data-slot='select-content'\n data-testid='spectral-select-content'\n position={position}\n ref={setDropdownElement}\n side={side}\n sideOffset={sideOffset}\n style={selectContentStyle}\n >\n <SelectPrimitive.ScrollUpButton className='py-1 flex cursor-default items-center justify-center' data-testid='spectral-select-scroll-up-button'>\n <ChevronDownIcon aria-hidden='true' className='rotate-180' size={18} />\n </SelectPrimitive.ScrollUpButton>\n\n <SelectPrimitive.Viewport asChild>\n <div\n className={cn(\n 'p-1 overflow-x-hidden overflow-y-auto',\n position === 'popper' && (dropdownWidth === 'trigger' ? 'scroll-my-1 h-(--radix-select-trigger-height) w-(--spectral-select-content-width) min-w-(--spectral-select-content-width)' : 'scroll-my-1 h-(--radix-select-trigger-height)'),\n )}\n data-testid='spectral-select-items'\n >\n {renderOptions()}\n </div>\n </SelectPrimitive.Viewport>\n\n <SelectPrimitive.ScrollDownButton className='py-1 flex cursor-default items-center justify-center' data-testid='spectral-select-scroll-down-button'>\n <ChevronDownIcon aria-hidden='true' size={18} />\n </SelectPrimitive.ScrollDownButton>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n\n <ErrorMessage dataTestId='spectral-select-error-message' id={errorMessageId} message={isInvalid ? (errorMessage ?? null) : null} messageReserveLines={messageReserveLines} messageReserveSpace={messageReserveSpace && state === 'error'} />\n <WarningMessage dataTestId='spectral-select-warning-message' id={warningMessageId} message={state === 'warning' ? (warningMessage ?? null) : null} messageReserveLines={messageReserveLines} messageReserveSpace={messageReserveSpace && state === 'warning'} />\n </div>\n )\n}\nSelect.displayName = 'Select'\n"],"mappings":"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"}
1
+ {"version":3,"file":"Select.js","names":[],"sources":["../src/components/Select/Select.tsx"],"sourcesContent":["import { CheckmarkIcon, ChevronDownIcon, LoaderIcon } from '@components/Icons'\nimport { Label } from '@components/Label/Label'\nimport { SelectValue } from '@primitives/select'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { useAutoDropdownHorizontalShift } from '@utils/dropdownPositioning'\nimport {\n EmptyState,\n ErrorMessage,\n getAriaProps,\n getDropdownWidthStyles,\n getDropdownSurfaceClasses,\n getErrorMessageId,\n getFormFieldCSSProperties,\n getOptionClasses,\n getTriggerClasses,\n groupOptions,\n LoadingState,\n WarningMessage,\n useFormFieldId,\n type BaseFormFieldProps,\n type BaseOption,\n type DropdownWidth,\n type FormFieldState,\n} from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { useState, type ComponentPropsWithoutRef, type CSSProperties, type ReactNode, type Ref } from 'react'\n\ntype SelectOption = BaseOption\ntype Align = 'start' | 'center' | 'end'\ntype Side = 'top' | 'bottom' | 'left' | 'right'\n\nexport interface SelectProps extends Omit<ComponentPropsWithoutRef<'button'>, 'value' | 'onChange' | 'aria-disabled' | 'aria-invalid' | 'aria-required' | 'aria-describedby' | 'aria-label'>, Omit<BaseFormFieldProps, 'state'> {\n defaultValue?: string\n dropdownWidth?: DropdownWidth\n emptyMessage?: ReactNode\n id?: string\n label?: string\n labelClassName?: string\n loadingMessage?: string\n onChange?: (value: string) => void\n onValueChange?: (value: string) => void\n options: SelectOption[]\n placeholder?: string\n state?: Exclude<FormFieldState, 'disabled'>\n value?: string\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nexport interface SelectExtendedProps extends SelectProps {\n align?: Align\n alignOffset?: number\n avoidCollisions?: boolean\n collisionBoundary?: Element | Element[] | null\n collisionPadding?: number | Partial<Record<Side, number>>\n position?: 'popper' | 'item-aligned'\n side?: Side\n sideOffset?: number\n}\n\nexport const Select = (\n allProps: SelectExtendedProps & {\n ref?: Ref<HTMLButtonElement>\n },\n) => {\n const isControlled = 'value' in allProps\n const {\n align = 'start',\n alignOffset = 0,\n avoidCollisions = true,\n className,\n collisionBoundary,\n collisionPadding = 10,\n defaultValue,\n dropdownWidth = 'trigger',\n emptyMessage = 'No options found',\n errorMessage,\n disabled,\n id,\n label,\n labelClassName,\n loadingMessage = 'Loading…',\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n onValueChange,\n options,\n placeholder = 'Select an option',\n position = 'popper',\n ref,\n required,\n side = 'bottom',\n sideOffset = 4,\n state = 'default',\n value: valueProp,\n warningMessage,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedBy,\n ...props\n } = allProps\n const value = isControlled ? (valueProp ?? '') : valueProp\n const [open, setOpen] = useState(false)\n const { dropdownShiftStyle, setDropdownElement } = useAutoDropdownHorizontalShift(open)\n const selectId = useFormFieldId(id, name)\n const listboxId = `${selectId}-listbox`\n const errorMessageId = getErrorMessageId(selectId)\n const warningMessageId = `${selectId}-warning`\n const messageId = state === 'error' && errorMessage ? errorMessageId : state === 'warning' && warningMessage ? warningMessageId : undefined\n const { dropdownWidthMode, dropdownWidthStyle, resolvedDropdownWidth } = getDropdownWidthStyles({\n dropdownWidth,\n triggerWidth: 'var(--radix-select-trigger-width)',\n })\n const selectContentStyle = {\n '--spectral-select-content-width': resolvedDropdownWidth,\n ...(position === 'item-aligned' ? { width: resolvedDropdownWidth } : {}),\n ...dropdownWidthStyle,\n ...dropdownShiftStyle,\n } as CSSProperties\n const isDisabled = Boolean(disabled)\n const isLoading = state === 'loading'\n const isInvalid = state === 'error'\n const ariaProps = getAriaProps(state, ariaDescribedBy, required, messageId)\n const { groups, ungrouped } = groupOptions(options)\n const handleValueChange = (nextValue: string) => {\n onChange?.(nextValue)\n onValueChange?.(nextValue)\n }\n\n const renderOptions = () => {\n if (isLoading) {\n return (\n <LoadingState\n data-testid='spectral-select-loading'\n message={loadingMessage}\n />\n )\n }\n\n if (options.length === 0) {\n return (\n <EmptyState\n data-testid='spectral-select-empty'\n message={emptyMessage}\n />\n )\n }\n\n const renderOption = (option: SelectOption) => {\n const isSelected = value === option.value\n\n return (\n <SelectPrimitive.Item\n className={cn(getOptionClasses(!!option.disabled, false, isSelected), 'relative flex w-full cursor-pointer items-center')}\n data-testid='spectral-select-item'\n disabled={option.disabled}\n key={option.value}\n value={option.value}\n >\n <SelectPrimitive.ItemText\n data-testid='spectral-select-item-text'\n className='block truncate'\n >\n {option.label}\n </SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator\n data-testid='spectral-select-item-selected-indicator'\n asChild\n >\n <span className='right-2 h-4 w-4 absolute flex items-center justify-center'>\n <CheckmarkIcon size={16} />\n </span>\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n )\n }\n\n return (\n <>\n {ungrouped.length > 0 && (\n <>\n {ungrouped.map(renderOption)}\n {Object.keys(groups).length > 0 && (\n <SelectPrimitive.Separator\n className='-mx-1 my-1 h-px bg-border-secondary'\n data-testid='spectral-select-separator'\n />\n )}\n </>\n )}\n\n {Object.entries(groups).map(([groupName, groupOptions], groupIndex) => (\n <SelectPrimitive.Group\n key={groupName}\n data-testid='spectral-select-group'\n >\n {groupIndex > 0 && (\n <SelectPrimitive.Separator\n className='-mx-1 my-1 h-px bg-border-secondary'\n data-testid='spectral-select-group-separator'\n />\n )}\n <Label\n className={cn('px-2 py-1.5 text-base font-semibold text-text-primary', labelClassName)}\n data-testid='spectral-select-group-label'\n >\n {groupName}\n </Label>\n {groupOptions.map((option: BaseOption) => renderOption(option))}\n </SelectPrimitive.Group>\n ))}\n </>\n )\n }\n\n return (\n <div className='w-full'>\n {label && (\n <Label\n className={cn('mb-2 block text-text-primary', labelClassName, isDisabled && 'text-text-secondary')}\n data-testid='spectral-select-label'\n htmlFor={selectId}\n >\n {label}\n </Label>\n )}\n <SelectPrimitive.Root\n data-testid='spectral-select'\n defaultValue={defaultValue}\n disabled={isDisabled}\n name={name}\n onOpenChange={setOpen}\n onValueChange={handleValueChange}\n open={open}\n required={required}\n value={value}\n >\n <SelectPrimitive.Trigger\n aria-controls={listboxId}\n aria-expanded={open}\n aria-label={ariaLabel ?? label}\n asChild\n className={cn(getTriggerClasses(open, state), 'text-input-text data-placeholder:text-input-text-placeholder!', className)}\n data-slot='select-trigger'\n data-state={state}\n data-testid='spectral-select-trigger'\n id={selectId}\n ref={ref}\n style={getFormFieldCSSProperties() as CSSProperties}\n {...ariaProps}\n {...props}\n >\n <button\n className='min-w-0 gap-2 [&>span]:min-w-0 grid w-full cursor-pointer grid-cols-[minmax(0,1fr)_auto] items-center overflow-hidden text-left whitespace-nowrap text-input-text! data-placeholder:text-input-text-placeholder! [&>span]:block [&>span]:overflow-hidden [&>span]:text-ellipsis [&>span]:whitespace-nowrap [&>span[data-placeholder]]:text-input-text-placeholder!'\n type='button'\n disabled={isDisabled}\n >\n <SelectValue\n data-testid='spectral-select-value'\n placeholder={placeholder}\n />\n <SelectPrimitive.Icon asChild>\n <div className='flex shrink-0 cursor-pointer items-center'>\n {isLoading ? (\n <LoaderIcon size={20} />\n ) : (\n <ChevronDownIcon\n className={cn('transition-transform duration-200', open && 'rotate-180')}\n size={20}\n />\n )}\n </div>\n </SelectPrimitive.Icon>\n </button>\n </SelectPrimitive.Trigger>\n\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n align={align}\n alignOffset={alignOffset}\n avoidCollisions={avoidCollisions}\n className={cn(\n 'relative z-50 motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=open]:animate-in',\n getDropdownSurfaceClasses(),\n 'motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=closed]:zoom-out-95 motion-safe:data-[state=open]:fade-in-0 motion-safe:data-[state=open]:zoom-in-95',\n 'max-h-[min(var(--radix-select-content-available-height),300px)] motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=top]:slide-in-from-bottom-2',\n 'min-w-32 origin-(--radix-select-content-transform-origin) overflow-hidden',\n position === 'popper' && 'data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1',\n )}\n collisionBoundary={collisionBoundary}\n collisionPadding={collisionPadding}\n data-dropdown-width-mode={dropdownWidthMode}\n data-dropdown-width-value={dropdownWidthMode === 'custom' ? dropdownWidth : undefined}\n id={listboxId}\n data-slot='select-content'\n data-testid='spectral-select-content'\n position={position}\n ref={setDropdownElement}\n side={side}\n sideOffset={sideOffset}\n style={selectContentStyle}\n >\n <SelectPrimitive.ScrollUpButton\n className='py-1 flex cursor-default items-center justify-center'\n data-testid='spectral-select-scroll-up-button'\n >\n <ChevronDownIcon\n aria-hidden='true'\n className='rotate-180'\n size={18}\n />\n </SelectPrimitive.ScrollUpButton>\n\n <SelectPrimitive.Viewport asChild>\n <div\n className={cn(\n 'p-1 overflow-x-hidden overflow-y-auto',\n position === 'popper' && (dropdownWidth === 'trigger' ? 'scroll-my-1 h-(--radix-select-trigger-height) w-(--spectral-select-content-width) min-w-(--spectral-select-content-width)' : 'scroll-my-1 h-(--radix-select-trigger-height)'),\n )}\n data-testid='spectral-select-items'\n >\n {renderOptions()}\n </div>\n </SelectPrimitive.Viewport>\n\n <SelectPrimitive.ScrollDownButton\n className='py-1 flex cursor-default items-center justify-center'\n data-testid='spectral-select-scroll-down-button'\n >\n <ChevronDownIcon\n aria-hidden='true'\n size={18}\n />\n </SelectPrimitive.ScrollDownButton>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n\n <ErrorMessage\n dataTestId='spectral-select-error-message'\n id={errorMessageId}\n message={isInvalid ? (errorMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'error'}\n />\n <WarningMessage\n dataTestId='spectral-select-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? (warningMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'warning'}\n />\n </div>\n )\n}\nSelect.displayName = 'Select'\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Skeleton.js","names":[],"sources":["../src/components/Skeleton/Skeleton.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentProps } from 'react'\n\nexport const Skeleton = ({ className, ...props }: ComponentProps<'div'>) => {\n return <div data-slot='skeleton' className={cn('motion-safe:animate-pulse rounded-md bg-level-three', className)} {...props} />\n}\n"],"mappings":";;;;;;AAGA,MAAa,YAAY,EAAE,WAAW,GAAG,YAAmC;AAC1E,QAAO,oBAAC,OAAD;EAAK,aAAU;EAAW,WAAW,GAAG,uDAAuD,UAAU;EAAE,GAAI;EAAS"}
1
+ {"version":3,"file":"Skeleton.js","names":[],"sources":["../src/components/Skeleton/Skeleton.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentProps } from 'react'\n\nexport const Skeleton = ({ className, ...props }: ComponentProps<'div'>) => {\n return (\n <div\n data-slot='skeleton'\n className={cn('motion-safe:animate-pulse rounded-md bg-level-three', className)}\n {...props}\n />\n )\n}\n"],"mappings":";;;;;;AAGA,MAAa,YAAY,EAAE,WAAW,GAAG,YAAmC;AAC1E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,uDAAuD,UAAU;EAC/E,GAAI;EACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.js","names":[],"sources":["../src/components/Slider/Slider.tsx"],"sourcesContent":["import { Input } from '@primitives/input'\nimport * as SliderBase from '@radix-ui/react-slider'\nimport { cn } from '@utils/twUtils'\nimport { useCallback, useEffect, useMemo, useState, type ChangeEvent, type KeyboardEvent, type ReactNode } from 'react'\n\nexport type SliderLabelPosition = 'end' | 'both'\nexport type SliderInputPosition = 'start' | 'both'\n\nexport interface SliderLabelRenderProps {\n max: number\n min: number\n position: 'start' | 'end'\n values: number[]\n}\n\nexport interface SliderProps {\n accessibleName?: string\n className?: string\n defaultValue?: number[]\n disabled?: boolean\n inputPosition?: SliderInputPosition\n label?: (props: SliderLabelRenderProps) => ReactNode\n labelPosition?: SliderLabelPosition\n max?: number\n min?: number\n minStepsBetweenThumbs?: number\n name?: string\n onValueChange?: (value: number[]) => void\n onValueCommit?: (value: number[]) => void\n orientation?: 'horizontal' | 'vertical'\n step?: number\n value?: number[]\n}\n\nexport const Slider = ({ accessibleName, className, defaultValue, disabled, inputPosition, label, labelPosition, max = 100, min = 0, minStepsBetweenThumbs = 1, name, onValueChange, onValueCommit, orientation = 'horizontal', step = 1, value }: SliderProps) => {\n const isControlled = value !== undefined\n const initialValues = useMemo(\n () => (Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min]),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n )\n const [internalValues, setInternalValues] = useState(initialValues)\n const _values = isControlled ? value : internalValues\n\n // Local state for input text to allow intermediate typing states\n const [inputTexts, setInputTexts] = useState<string[]>(() => _values.map(String))\n\n // Sync input text when slider values change externally\n useEffect(() => {\n setInputTexts(_values.map(String))\n }, [_values])\n\n const handleValueChange = useCallback(\n (newValues: number[]) => {\n if (!isControlled) {\n setInternalValues(newValues)\n }\n onValueChange?.(newValues)\n },\n [isControlled, onValueChange],\n )\n\n const handleInputTextChange = useCallback(\n (index: number, e: ChangeEvent<HTMLInputElement>) => {\n const newTexts = [...inputTexts]\n newTexts[index] = e.target.value\n setInputTexts(newTexts)\n },\n [inputTexts],\n )\n\n const commitInputValue = useCallback(\n (index: number) => {\n const inputValue = inputTexts[index]\n if (inputValue === '') {\n // Reset to current slider value if empty\n setInputTexts(_values.map(String))\n return\n }\n\n let newValue = parseFloat(inputValue)\n if (isNaN(newValue)) {\n // Reset to current slider value if invalid\n setInputTexts(_values.map(String))\n return\n }\n\n // Clamp to min/max\n newValue = Math.max(min, Math.min(max, newValue))\n\n // Respect minStepsBetweenThumbs for range sliders\n const newValues = [..._values]\n if (index === 0 && _values.length > 1) {\n // Start input: ensure it doesn't exceed end value minus gap\n const maxAllowed = _values[1] - minStepsBetweenThumbs * step\n newValue = Math.min(newValue, maxAllowed)\n } else if (index === 1) {\n // End input: ensure it doesn't go below start value plus gap\n const minAllowed = _values[0] + minStepsBetweenThumbs * step\n newValue = Math.max(newValue, minAllowed)\n }\n\n newValues[index] = newValue\n handleValueChange(newValues)\n onValueCommit?.(newValues)\n },\n [inputTexts, _values, min, max, step, minStepsBetweenThumbs, handleValueChange, onValueCommit],\n )\n\n const handleInputKeyDown = useCallback(\n (index: number, e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n commitInputValue(index)\n e.currentTarget.blur()\n }\n },\n [commitInputValue],\n )\n\n const isVertical = orientation === 'vertical'\n const showStartLabel = labelPosition === 'both'\n const showEndLabel = label && (labelPosition === 'end' || labelPosition === 'both')\n const showStartInput = inputPosition === 'start' || inputPosition === 'both'\n const showEndInput = inputPosition === 'both' && _values.length > 1\n\n const labelClasses = cn('text-slider-label text-sm shrink-0 tabular-nums', isVertical ? 'text-center' : '')\n\n const inputClasses = 'w-10 h-fit px-1 shrink-0 text-center text-sm tabular-nums [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none'\n\n return (\n <div className={cn('gap-3 flex items-center', isVertical ? 'flex-col' : 'w-full', className)} data-testid='spectral-slider-container'>\n {showStartLabel && (\n <span className={labelClasses} data-slot='slider-label' data-testid='spectral-slider-label-start'>\n {label?.({ values: _values, min, max, position: 'start' })}\n </span>\n )}\n\n {showStartInput && (\n <Input\n aria-label={accessibleName ? `${accessibleName} start value` : 'Slider start value'}\n className={inputClasses}\n data-slot='slider-input'\n data-testid='spectral-slider-input-start'\n disabled={disabled}\n max={_values.length > 1 ? _values[1] - minStepsBetweenThumbs * step : max}\n min={min}\n onBlur={() => commitInputValue(0)}\n onChange={(e) => handleInputTextChange(0, e)}\n onKeyDown={(e) => handleInputKeyDown(0, e)}\n step={step}\n type='number'\n value={inputTexts[0] ?? ''}\n />\n )}\n\n <SliderBase.Root\n aria-label={accessibleName}\n aria-valuemax={max}\n aria-valuemin={min}\n aria-valuenow={_values[0]}\n className='data-[orientation=vertical]:min-h-44 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col'\n data-slot='slider'\n data-testid='spectral-slider'\n disabled={disabled}\n max={max}\n min={min}\n minStepsBetweenThumbs={minStepsBetweenThumbs}\n name={name}\n onValueChange={handleValueChange}\n onValueCommit={onValueCommit}\n orientation={orientation}\n step={step}\n value={_values}\n >\n <SliderBase.Track\n className='data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:w-1.5 relative grow overflow-hidden rounded-full bg-slider-track data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full'\n data-slot='slider-track'\n data-testid='spectral-slider-track'\n >\n <SliderBase.Range className='absolute bg-slider-range data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full' data-slot='slider-range' data-testid='spectral-slider-range' />\n </SliderBase.Track>\n {Array.from({ length: _values.length }, (_, index) => (\n <SliderBase.Thumb\n className='size-5 shadow-sm block shrink-0 rounded-full border border-slider-thumb-border bg-slider-thumb-bg ring-slider-thumb-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50'\n data-slot='slider-thumb'\n data-testid='spectral-slider-thumb'\n key={index}\n />\n ))}\n </SliderBase.Root>\n\n {showEndInput && (\n <Input\n aria-label={accessibleName ? `${accessibleName} end value` : 'Slider end value'}\n className={inputClasses}\n data-slot='slider-input'\n data-testid='spectral-slider-input-end'\n disabled={disabled}\n max={max}\n min={_values[0] + minStepsBetweenThumbs * step}\n onBlur={() => commitInputValue(1)}\n onChange={(e) => handleInputTextChange(1, e)}\n onKeyDown={(e) => handleInputKeyDown(1, e)}\n step={step}\n type='number'\n value={inputTexts[1] ?? ''}\n />\n )}\n\n {showEndLabel && (\n <span className={labelClasses} data-slot='slider-label' data-testid='spectral-slider-label-end'>\n {label({ values: _values, min, max, position: 'end' })}\n </span>\n )}\n </div>\n )\n}\n"],"mappings":";;;;;;;;AAkCA,MAAa,UAAU,EAAE,gBAAgB,WAAW,cAAc,UAAU,eAAe,OAAO,eAAe,MAAM,KAAK,MAAM,GAAG,wBAAwB,GAAG,MAAM,eAAe,eAAe,cAAc,cAAc,OAAO,GAAG,YAAyB;CACjQ,MAAM,eAAe,UAAU;CAM/B,MAAM,CAAC,gBAAgB,qBAAqB,SALtB,cACb,MAAM,QAAQ,MAAM,GAAG,QAAQ,MAAM,QAAQ,aAAa,GAAG,eAAe,CAAC,IAAI,EAExF,EAAE,CAE8D,CAAC;CACnE,MAAM,UAAU,eAAe,QAAQ;CAGvC,MAAM,CAAC,YAAY,iBAAiB,eAAyB,QAAQ,IAAI,OAAO,CAAC;AAGjF,iBAAgB;AACd,gBAAc,QAAQ,IAAI,OAAO,CAAC;IACjC,CAAC,QAAQ,CAAC;CAEb,MAAM,oBAAoB,aACvB,cAAwB;AACvB,MAAI,CAAC,aACH,mBAAkB,UAAU;AAE9B,kBAAgB,UAAU;IAE5B,CAAC,cAAc,cAAc,CAC9B;CAED,MAAM,wBAAwB,aAC3B,OAAe,MAAqC;EACnD,MAAM,WAAW,CAAC,GAAG,WAAW;AAChC,WAAS,SAAS,EAAE,OAAO;AAC3B,gBAAc,SAAS;IAEzB,CAAC,WAAW,CACb;CAED,MAAM,mBAAmB,aACtB,UAAkB;EACjB,MAAM,aAAa,WAAW;AAC9B,MAAI,eAAe,IAAI;AAErB,iBAAc,QAAQ,IAAI,OAAO,CAAC;AAClC;;EAGF,IAAI,WAAW,WAAW,WAAW;AACrC,MAAI,MAAM,SAAS,EAAE;AAEnB,iBAAc,QAAQ,IAAI,OAAO,CAAC;AAClC;;AAIF,aAAW,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,SAAS,CAAC;EAGjD,MAAM,YAAY,CAAC,GAAG,QAAQ;AAC9B,MAAI,UAAU,KAAK,QAAQ,SAAS,GAAG;GAErC,MAAM,aAAa,QAAQ,KAAK,wBAAwB;AACxD,cAAW,KAAK,IAAI,UAAU,WAAW;aAChC,UAAU,GAAG;GAEtB,MAAM,aAAa,QAAQ,KAAK,wBAAwB;AACxD,cAAW,KAAK,IAAI,UAAU,WAAW;;AAG3C,YAAU,SAAS;AACnB,oBAAkB,UAAU;AAC5B,kBAAgB,UAAU;IAE5B;EAAC;EAAY;EAAS;EAAK;EAAK;EAAM;EAAuB;EAAmB;EAAc,CAC/F;CAED,MAAM,qBAAqB,aACxB,OAAe,MAAuC;AACrD,MAAI,EAAE,QAAQ,SAAS;AACrB,oBAAiB,MAAM;AACvB,KAAE,cAAc,MAAM;;IAG1B,CAAC,iBAAiB,CACnB;CAED,MAAM,aAAa,gBAAgB;CACnC,MAAM,iBAAiB,kBAAkB;CACzC,MAAM,eAAe,UAAU,kBAAkB,SAAS,kBAAkB;CAC5E,MAAM,iBAAiB,kBAAkB,WAAW,kBAAkB;CACtE,MAAM,eAAe,kBAAkB,UAAU,QAAQ,SAAS;CAElE,MAAM,eAAe,GAAG,mDAAmD,aAAa,gBAAgB,GAAG;CAE3G,MAAM,eAAe;AAErB,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,2BAA2B,aAAa,aAAa,UAAU,UAAU;EAAE,eAAY;YAA1G;GACG,kBACC,oBAAC,QAAD;IAAM,WAAW;IAAc,aAAU;IAAe,eAAY;cACjE,QAAQ;KAAE,QAAQ;KAAS;KAAK;KAAK,UAAU;KAAS,CAAC;IACrD;GAGR,kBACC,oBAAC,OAAD;IACE,cAAY,iBAAiB,GAAG,eAAe,gBAAgB;IAC/D,WAAW;IACX,aAAU;IACV,eAAY;IACF;IACV,KAAK,QAAQ,SAAS,IAAI,QAAQ,KAAK,wBAAwB,OAAO;IACjE;IACL,cAAc,iBAAiB,EAAE;IACjC,WAAW,MAAM,sBAAsB,GAAG,EAAE;IAC5C,YAAY,MAAM,mBAAmB,GAAG,EAAE;IACpC;IACN,MAAK;IACL,OAAO,WAAW,MAAM;IACxB;GAGJ,qBAAC,WAAW,MAAZ;IACE,cAAY;IACZ,iBAAe;IACf,iBAAe;IACf,iBAAe,QAAQ;IACvB,WAAU;IACV,aAAU;IACV,eAAY;IACF;IACL;IACA;IACkB;IACjB;IACN,eAAe;IACA;IACF;IACP;IACN,OAAO;cAjBT,CAmBE,oBAAC,WAAW,OAAZ;KACE,WAAU;KACV,aAAU;KACV,eAAY;eAEZ,oBAAC,WAAW,OAAZ;MAAkB,WAAU;MAAmG,aAAU;MAAe,eAAY;MAA0B;KAC7K,GAClB,MAAM,KAAK,EAAE,QAAQ,QAAQ,QAAQ,GAAG,GAAG,UAC1C,oBAAC,WAAW,OAAZ;KACE,WAAU;KACV,aAAU;KACV,eAAY;KAEZ,EADK,MACL,CACF,CACc;;GAEjB,gBACC,oBAAC,OAAD;IACE,cAAY,iBAAiB,GAAG,eAAe,cAAc;IAC7D,WAAW;IACX,aAAU;IACV,eAAY;IACF;IACL;IACL,KAAK,QAAQ,KAAK,wBAAwB;IAC1C,cAAc,iBAAiB,EAAE;IACjC,WAAW,MAAM,sBAAsB,GAAG,EAAE;IAC5C,YAAY,MAAM,mBAAmB,GAAG,EAAE;IACpC;IACN,MAAK;IACL,OAAO,WAAW,MAAM;IACxB;GAGH,gBACC,oBAAC,QAAD;IAAM,WAAW;IAAc,aAAU;IAAe,eAAY;cACjE,MAAM;KAAE,QAAQ;KAAS;KAAK;KAAK,UAAU;KAAO,CAAC;IACjD;GAEL"}
1
+ {"version":3,"file":"Slider.js","names":[],"sources":["../src/components/Slider/Slider.tsx"],"sourcesContent":["import { Input } from '@primitives/input'\nimport * as SliderBase from '@radix-ui/react-slider'\nimport { cn } from '@utils/twUtils'\nimport { useCallback, useEffect, useMemo, useState, type ChangeEvent, type KeyboardEvent, type ReactNode } from 'react'\n\nexport type SliderLabelPosition = 'end' | 'both'\nexport type SliderInputPosition = 'start' | 'both'\n\nexport interface SliderLabelRenderProps {\n max: number\n min: number\n position: 'start' | 'end'\n values: number[]\n}\n\nexport interface SliderProps {\n accessibleName?: string\n className?: string\n defaultValue?: number[]\n disabled?: boolean\n inputPosition?: SliderInputPosition\n label?: (props: SliderLabelRenderProps) => ReactNode\n labelPosition?: SliderLabelPosition\n max?: number\n min?: number\n minStepsBetweenThumbs?: number\n name?: string\n onValueChange?: (value: number[]) => void\n onValueCommit?: (value: number[]) => void\n orientation?: 'horizontal' | 'vertical'\n step?: number\n value?: number[]\n}\n\nexport const Slider = ({ accessibleName, className, defaultValue, disabled, inputPosition, label, labelPosition, max = 100, min = 0, minStepsBetweenThumbs = 1, name, onValueChange, onValueCommit, orientation = 'horizontal', step = 1, value }: SliderProps) => {\n const isControlled = value !== undefined\n const initialValues = useMemo(\n () => (Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min]),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n )\n const [internalValues, setInternalValues] = useState(initialValues)\n const _values = isControlled ? value : internalValues\n\n // Local state for input text to allow intermediate typing states\n const [inputTexts, setInputTexts] = useState<string[]>(() => _values.map(String))\n\n // Sync input text when slider values change externally\n useEffect(() => {\n setInputTexts(_values.map(String))\n }, [_values])\n\n const handleValueChange = useCallback(\n (newValues: number[]) => {\n if (!isControlled) {\n setInternalValues(newValues)\n }\n onValueChange?.(newValues)\n },\n [isControlled, onValueChange],\n )\n\n const handleInputTextChange = useCallback(\n (index: number, e: ChangeEvent<HTMLInputElement>) => {\n const newTexts = [...inputTexts]\n newTexts[index] = e.target.value\n setInputTexts(newTexts)\n },\n [inputTexts],\n )\n\n const commitInputValue = useCallback(\n (index: number) => {\n const inputValue = inputTexts[index]\n if (inputValue === '') {\n // Reset to current slider value if empty\n setInputTexts(_values.map(String))\n return\n }\n\n let newValue = parseFloat(inputValue)\n if (isNaN(newValue)) {\n // Reset to current slider value if invalid\n setInputTexts(_values.map(String))\n return\n }\n\n // Clamp to min/max\n newValue = Math.max(min, Math.min(max, newValue))\n\n // Respect minStepsBetweenThumbs for range sliders\n const newValues = [..._values]\n if (index === 0 && _values.length > 1) {\n // Start input: ensure it doesn't exceed end value minus gap\n const maxAllowed = _values[1] - minStepsBetweenThumbs * step\n newValue = Math.min(newValue, maxAllowed)\n } else if (index === 1) {\n // End input: ensure it doesn't go below start value plus gap\n const minAllowed = _values[0] + minStepsBetweenThumbs * step\n newValue = Math.max(newValue, minAllowed)\n }\n\n newValues[index] = newValue\n handleValueChange(newValues)\n onValueCommit?.(newValues)\n },\n [inputTexts, _values, min, max, step, minStepsBetweenThumbs, handleValueChange, onValueCommit],\n )\n\n const handleInputKeyDown = useCallback(\n (index: number, e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n commitInputValue(index)\n e.currentTarget.blur()\n }\n },\n [commitInputValue],\n )\n\n const isVertical = orientation === 'vertical'\n const showStartLabel = labelPosition === 'both'\n const showEndLabel = label && (labelPosition === 'end' || labelPosition === 'both')\n const showStartInput = inputPosition === 'start' || inputPosition === 'both'\n const showEndInput = inputPosition === 'both' && _values.length > 1\n\n const labelClasses = cn('text-slider-label text-sm shrink-0 tabular-nums', isVertical ? 'text-center' : '')\n\n const inputClasses = 'w-10 h-fit px-1 shrink-0 text-center text-sm tabular-nums [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none'\n\n return (\n <div\n className={cn('gap-3 flex items-center', isVertical ? 'flex-col' : 'w-full', className)}\n data-testid='spectral-slider-container'\n >\n {showStartLabel && (\n <span\n className={labelClasses}\n data-slot='slider-label'\n data-testid='spectral-slider-label-start'\n >\n {label?.({ values: _values, min, max, position: 'start' })}\n </span>\n )}\n\n {showStartInput && (\n <Input\n aria-label={accessibleName ? `${accessibleName} start value` : 'Slider start value'}\n className={inputClasses}\n data-slot='slider-input'\n data-testid='spectral-slider-input-start'\n disabled={disabled}\n max={_values.length > 1 ? _values[1] - minStepsBetweenThumbs * step : max}\n min={min}\n onBlur={() => commitInputValue(0)}\n onChange={(e) => handleInputTextChange(0, e)}\n onKeyDown={(e) => handleInputKeyDown(0, e)}\n step={step}\n type='number'\n value={inputTexts[0] ?? ''}\n />\n )}\n\n <SliderBase.Root\n aria-label={accessibleName}\n aria-valuemax={max}\n aria-valuemin={min}\n aria-valuenow={_values[0]}\n className='data-[orientation=vertical]:min-h-44 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col'\n data-slot='slider'\n data-testid='spectral-slider'\n disabled={disabled}\n max={max}\n min={min}\n minStepsBetweenThumbs={minStepsBetweenThumbs}\n name={name}\n onValueChange={handleValueChange}\n onValueCommit={onValueCommit}\n orientation={orientation}\n step={step}\n value={_values}\n >\n <SliderBase.Track\n className='data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:w-1.5 relative grow overflow-hidden rounded-full bg-slider-track data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full'\n data-slot='slider-track'\n data-testid='spectral-slider-track'\n >\n <SliderBase.Range\n className='absolute bg-slider-range data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full'\n data-slot='slider-range'\n data-testid='spectral-slider-range'\n />\n </SliderBase.Track>\n {Array.from({ length: _values.length }, (_, index) => (\n <SliderBase.Thumb\n className='size-5 shadow-sm block shrink-0 rounded-full border border-slider-thumb-border bg-slider-thumb-bg ring-slider-thumb-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50'\n data-slot='slider-thumb'\n data-testid='spectral-slider-thumb'\n key={index}\n />\n ))}\n </SliderBase.Root>\n\n {showEndInput && (\n <Input\n aria-label={accessibleName ? `${accessibleName} end value` : 'Slider end value'}\n className={inputClasses}\n data-slot='slider-input'\n data-testid='spectral-slider-input-end'\n disabled={disabled}\n max={max}\n min={_values[0] + minStepsBetweenThumbs * step}\n onBlur={() => commitInputValue(1)}\n onChange={(e) => handleInputTextChange(1, e)}\n onKeyDown={(e) => handleInputKeyDown(1, e)}\n step={step}\n type='number'\n value={inputTexts[1] ?? ''}\n />\n )}\n\n {showEndLabel && (\n <span\n className={labelClasses}\n data-slot='slider-label'\n data-testid='spectral-slider-label-end'\n >\n {label({ values: _values, min, max, position: 'end' })}\n </span>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SwitchBase.d.ts","names":[],"sources":["../../src/components/Switch/SwitchBase.tsx"],"mappings":";;;;;;KAWK,eAAA,GAAkB,IAAA,CAAK,oBAAA,CAAqB,iBAAA;AAAA,UAEhC,WAAA,SAAoB,eAAA,EAAiB,WAAA;EACpD,OAAA;EACA,cAAA;EACA,IAAA;EACA,IAAA;EACA,eAAA,IAAmB,OAAA;EACnB,QAAA;EACA,KAAA;AAAA;AAAA;EAIA,OAAA;EACA,OAAA;EACA,QAAA;EACA,SAAA;EACA,cAAA;EACA,QAAA;EACA,IAAA;EACA,EAAA;EACA,IAAA;EACA,eAAA;EACA,OAAA;EACA,SAAA;EACA,GAAA;EACA,QAAA;EACA,KAAA;EAAA,GACG;AAAA,GACF,WAAA;EACD,GAAA,GAAM,GAAA,CAAI,iBAAA;AAAA,IACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA;;;KA4FW,gBAAA,GAAmB,cAAA,CAAe,eAAA,IAAmB,WAAA;AAAA;EAG/D,OAAA;EACA,SAAA;EACA,GAAA;EAAA,GACG;AAAA,GACF,gBAAA;EACD,GAAA,GAAM,GAAA,CAAI,eAAA;AAAA,IACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
1
+ {"version":3,"file":"SwitchBase.d.ts","names":[],"sources":["../../src/components/Switch/SwitchBase.tsx"],"mappings":";;;;;;KAWK,eAAA,GAAkB,IAAA,CAAK,oBAAA,CAAqB,iBAAA;AAAA,UAEhC,WAAA,SAAoB,eAAA,EAAiB,WAAA;EACpD,OAAA;EACA,cAAA;EACA,IAAA;EACA,IAAA;EACA,eAAA,IAAmB,OAAA;EACnB,QAAA;EACA,KAAA;AAAA;AAAA;EAIA,OAAA;EACA,OAAA;EACA,QAAA;EACA,SAAA;EACA,cAAA;EACA,QAAA;EACA,IAAA;EACA,EAAA;EACA,IAAA;EACA,eAAA;EACA,OAAA;EACA,SAAA;EACA,GAAA;EACA,QAAA;EACA,KAAA;EAAA,GACG;AAAA,GACF,WAAA;EACD,GAAA,GAAM,GAAA,CAAI,iBAAA;AAAA,IACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA;;;KAyGW,gBAAA,GAAmB,cAAA,CAAe,eAAA,IAAmB,WAAA;AAAA;EAG/D,OAAA;EACA,SAAA;EACA,GAAA;EAAA,GACG;AAAA,GACF,gBAAA;EACD,GAAA,GAAM,GAAA,CAAI,eAAA;AAAA,IACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SwitchBase.js","names":[],"sources":["../../src/components/Switch/SwitchBase.tsx"],"sourcesContent":["import { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { Slot, type AsChildProp } from '@primitives/slot'\nimport { createContext, useCallback, useContext, useEffect, useId, useRef, type ButtonHTMLAttributes, type ElementType, type HTMLAttributes, type KeyboardEvent, type MouseEvent, type Ref } from 'react'\n\ninterface Ctx {\n checked: boolean\n disabled: boolean | undefined\n}\n\nconst SwitchCtx = createContext<Ctx | null>(null)\n\ntype BaseButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'value'>\n\nexport interface SwitchProps extends BaseButtonProps, AsChildProp {\n checked?: boolean\n defaultChecked?: boolean\n form?: string\n name?: string\n onCheckedChange?: (checked: boolean) => void\n required?: boolean\n value?: string\n}\n\nexport const Switch = ({\n asChild,\n checked,\n children,\n className,\n defaultChecked = false,\n disabled,\n form,\n id,\n name,\n onCheckedChange,\n onClick,\n onKeyDown,\n ref,\n required,\n value = 'on',\n ...rest\n}: SwitchProps & {\n ref?: Ref<HTMLButtonElement>\n}) => {\n const inputRef = useRef<HTMLInputElement | null>(null)\n const autoId = useId()\n const resolvedId = id ?? `swt-${autoId}`\n\n const [isChecked, setIsChecked] = useUncontrolledState<boolean>({\n value: checked,\n defaultValue: defaultChecked,\n onChange: onCheckedChange,\n })\n\n // form reset -> restore default\n useEffect(() => {\n const formEl = inputRef.current?.form ?? null\n if (!formEl) return\n const handleReset = () => setIsChecked(defaultChecked)\n formEl.addEventListener('reset', handleReset)\n return () => formEl.removeEventListener('reset', handleReset)\n }, [defaultChecked, setIsChecked])\n\n const emitFormChange = useCallback((checkedValue: boolean) => {\n const el = inputRef.current\n if (!el) return\n el.checked = checkedValue\n const ev = new Event('change', { bubbles: true })\n el.dispatchEvent(ev)\n }, [])\n\n const toggle = useCallback(() => {\n if (disabled) return\n const newChecked = !isChecked\n setIsChecked(newChecked)\n queueMicrotask(() => emitFormChange(newChecked))\n }, [disabled, emitFormChange, isChecked, setIsChecked])\n\n const handleClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (e.defaultPrevented) return\n toggle()\n },\n [onClick, toggle],\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented) return\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault()\n toggle()\n }\n },\n [onKeyDown, toggle],\n )\n\n const Comp: ElementType = asChild ? Slot : 'button'\n\n return (\n <SwitchCtx.Provider value={{ checked: isChecked, disabled }}>\n <>\n <Comp aria-checked={isChecked} className={className} data-disabled={disabled ?? undefined} data-state={isChecked ? 'checked' : 'unchecked'} disabled={disabled} id={resolvedId} onClick={handleClick} onKeyDown={handleKeyDown} ref={ref} role='switch' type='button' {...rest}>\n {children}\n </Comp>\n {/* hidden input outside <button> — <input> inside <button> is invalid HTML.\n The form attribute handles cross-form association without nesting. */}\n <input\n aria-hidden='true'\n checked={isChecked}\n disabled={disabled}\n form={form}\n name={name}\n readOnly\n ref={inputRef}\n required={required}\n tabIndex={-1}\n type='checkbox'\n value={value}\n style={{\n height: 0,\n opacity: 0,\n pointerEvents: 'none',\n position: 'absolute',\n width: 0,\n }}\n />\n </>\n </SwitchCtx.Provider>\n )\n}\nSwitch.displayName = 'Switch'\n\nexport type SwitchThumbProps = HTMLAttributes<HTMLSpanElement> & AsChildProp\n\nexport const SwitchThumb = ({\n asChild,\n className,\n ref,\n ...props\n}: SwitchThumbProps & {\n ref?: Ref<HTMLSpanElement>\n}) => {\n const ctx = useContext(SwitchCtx)\n if (!ctx) throw new Error('SwitchThumb must be used within Switch')\n\n const Comp: ElementType = asChild ? Slot : 'span'\n\n return <Comp className={className} data-disabled={ctx.disabled ?? undefined} data-state={ctx.checked ? 'checked' : 'unchecked'} ref={ref} {...props} />\n}\nSwitchThumb.displayName = 'SwitchThumb'\n"],"mappings":";;;;;;;AASA,MAAM,YAAY,cAA0B,KAAK;AAcjD,MAAa,UAAU,EACrB,SACA,SACA,UACA,WACA,iBAAiB,OACjB,UACA,MACA,IACA,MACA,iBACA,SACA,WACA,KACA,UACA,QAAQ,MACR,GAAG,WAGC;CACJ,MAAM,WAAW,OAAgC,KAAK;CACtD,MAAM,SAAS,OAAO;CACtB,MAAM,aAAa,MAAM,OAAO;CAEhC,MAAM,CAAC,WAAW,gBAAgB,qBAA8B;EAC9D,OAAO;EACP,cAAc;EACd,UAAU;EACX,CAAC;AAGF,iBAAgB;EACd,MAAM,SAAS,SAAS,SAAS,QAAQ;AACzC,MAAI,CAAC,OAAQ;EACb,MAAM,oBAAoB,aAAa,eAAe;AACtD,SAAO,iBAAiB,SAAS,YAAY;AAC7C,eAAa,OAAO,oBAAoB,SAAS,YAAY;IAC5D,CAAC,gBAAgB,aAAa,CAAC;CAElC,MAAM,iBAAiB,aAAa,iBAA0B;EAC5D,MAAM,KAAK,SAAS;AACpB,MAAI,CAAC,GAAI;AACT,KAAG,UAAU;EACb,MAAM,KAAK,IAAI,MAAM,UAAU,EAAE,SAAS,MAAM,CAAC;AACjD,KAAG,cAAc,GAAG;IACnB,EAAE,CAAC;CAEN,MAAM,SAAS,kBAAkB;AAC/B,MAAI,SAAU;EACd,MAAM,aAAa,CAAC;AACpB,eAAa,WAAW;AACxB,uBAAqB,eAAe,WAAW,CAAC;IAC/C;EAAC;EAAU;EAAgB;EAAW;EAAa,CAAC;CAEvD,MAAM,cAAc,aACjB,MAAqC;AACpC,YAAU,EAAE;AACZ,MAAI,EAAE,iBAAkB;AACxB,UAAQ;IAEV,CAAC,SAAS,OAAO,CAClB;CAED,MAAM,gBAAgB,aACnB,MAAwC;AACvC,cAAY,EAAE;AACd,MAAI,EAAE,iBAAkB;AACxB,MAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,SAAS;AACtC,KAAE,gBAAgB;AAClB,WAAQ;;IAGZ,CAAC,WAAW,OAAO,CACpB;CAED,MAAM,OAAoB,UAAU,OAAO;AAE3C,QACE,oBAAC,UAAU,UAAX;EAAoB,OAAO;GAAE,SAAS;GAAW;GAAU;YACzD,4CACE,oBAAC,MAAD;GAAM,gBAAc;GAAsB;GAAW,iBAAe,YAAY;GAAW,cAAY,YAAY,YAAY;GAAuB;GAAU,IAAI;GAAY,SAAS;GAAa,WAAW;GAAoB;GAAK,MAAK;GAAS,MAAK;GAAS,GAAI;GACvQ;GACI,GAGP,oBAAC,SAAD;GACE,eAAY;GACZ,SAAS;GACC;GACJ;GACA;GACN;GACA,KAAK;GACK;GACV,UAAU;GACV,MAAK;GACE;GACP,OAAO;IACL,QAAQ;IACR,SAAS;IACT,eAAe;IACf,UAAU;IACV,OAAO;IACR;GACD,EACD;EACgB;;AAGzB,OAAO,cAAc;AAIrB,MAAa,eAAe,EAC1B,SACA,WACA,KACA,GAAG,YAGC;CACJ,MAAM,MAAM,WAAW,UAAU;AACjC,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,yCAAyC;AAInE,QAAO,oBAFmB,UAAU,OAAO,QAEpC;EAAiB;EAAW,iBAAe,IAAI,YAAY;EAAW,cAAY,IAAI,UAAU,YAAY;EAAkB;EAAK,GAAI;EAAS;;AAEzJ,YAAY,cAAc"}
1
+ {"version":3,"file":"SwitchBase.js","names":[],"sources":["../../src/components/Switch/SwitchBase.tsx"],"sourcesContent":["import { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { Slot, type AsChildProp } from '@primitives/slot'\nimport { createContext, useCallback, useContext, useEffect, useId, useRef, type ButtonHTMLAttributes, type ElementType, type HTMLAttributes, type KeyboardEvent, type MouseEvent, type Ref } from 'react'\n\ninterface Ctx {\n checked: boolean\n disabled: boolean | undefined\n}\n\nconst SwitchCtx = createContext<Ctx | null>(null)\n\ntype BaseButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'value'>\n\nexport interface SwitchProps extends BaseButtonProps, AsChildProp {\n checked?: boolean\n defaultChecked?: boolean\n form?: string\n name?: string\n onCheckedChange?: (checked: boolean) => void\n required?: boolean\n value?: string\n}\n\nexport const Switch = ({\n asChild,\n checked,\n children,\n className,\n defaultChecked = false,\n disabled,\n form,\n id,\n name,\n onCheckedChange,\n onClick,\n onKeyDown,\n ref,\n required,\n value = 'on',\n ...rest\n}: SwitchProps & {\n ref?: Ref<HTMLButtonElement>\n}) => {\n const inputRef = useRef<HTMLInputElement | null>(null)\n const autoId = useId()\n const resolvedId = id ?? `swt-${autoId}`\n\n const [isChecked, setIsChecked] = useUncontrolledState<boolean>({\n value: checked,\n defaultValue: defaultChecked,\n onChange: onCheckedChange,\n })\n\n // form reset -> restore default\n useEffect(() => {\n const formEl = inputRef.current?.form ?? null\n if (!formEl) return\n const handleReset = () => setIsChecked(defaultChecked)\n formEl.addEventListener('reset', handleReset)\n return () => formEl.removeEventListener('reset', handleReset)\n }, [defaultChecked, setIsChecked])\n\n const emitFormChange = useCallback((checkedValue: boolean) => {\n const el = inputRef.current\n if (!el) return\n el.checked = checkedValue\n const ev = new Event('change', { bubbles: true })\n el.dispatchEvent(ev)\n }, [])\n\n const toggle = useCallback(() => {\n if (disabled) return\n const newChecked = !isChecked\n setIsChecked(newChecked)\n queueMicrotask(() => emitFormChange(newChecked))\n }, [disabled, emitFormChange, isChecked, setIsChecked])\n\n const handleClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n onClick?.(e)\n if (e.defaultPrevented) return\n toggle()\n },\n [onClick, toggle],\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented) return\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault()\n toggle()\n }\n },\n [onKeyDown, toggle],\n )\n\n const Comp: ElementType = asChild ? Slot : 'button'\n\n return (\n <SwitchCtx.Provider value={{ checked: isChecked, disabled }}>\n <>\n <Comp\n aria-checked={isChecked}\n className={className}\n data-disabled={disabled ?? undefined}\n data-state={isChecked ? 'checked' : 'unchecked'}\n disabled={disabled}\n id={resolvedId}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n ref={ref}\n role='switch'\n type='button'\n {...rest}\n >\n {children}\n </Comp>\n {/* hidden input outside <button> — <input> inside <button> is invalid HTML.\n The form attribute handles cross-form association without nesting. */}\n <input\n aria-hidden='true'\n checked={isChecked}\n disabled={disabled}\n form={form}\n name={name}\n readOnly\n ref={inputRef}\n required={required}\n tabIndex={-1}\n type='checkbox'\n value={value}\n style={{\n height: 0,\n opacity: 0,\n pointerEvents: 'none',\n position: 'absolute',\n width: 0,\n }}\n />\n </>\n </SwitchCtx.Provider>\n )\n}\nSwitch.displayName = 'Switch'\n\nexport type SwitchThumbProps = HTMLAttributes<HTMLSpanElement> & AsChildProp\n\nexport const SwitchThumb = ({\n asChild,\n className,\n ref,\n ...props\n}: SwitchThumbProps & {\n ref?: Ref<HTMLSpanElement>\n}) => {\n const ctx = useContext(SwitchCtx)\n if (!ctx) throw new Error('SwitchThumb must be used within Switch')\n\n const Comp: ElementType = asChild ? Slot : 'span'\n\n return (\n <Comp\n className={className}\n data-disabled={ctx.disabled ?? undefined}\n data-state={ctx.checked ? 'checked' : 'unchecked'}\n ref={ref}\n {...props}\n />\n )\n}\nSwitchThumb.displayName = 'SwitchThumb'\n"],"mappings":";;;;;;;AASA,MAAM,YAAY,cAA0B,KAAK;AAcjD,MAAa,UAAU,EACrB,SACA,SACA,UACA,WACA,iBAAiB,OACjB,UACA,MACA,IACA,MACA,iBACA,SACA,WACA,KACA,UACA,QAAQ,MACR,GAAG,WAGC;CACJ,MAAM,WAAW,OAAgC,KAAK;CACtD,MAAM,SAAS,OAAO;CACtB,MAAM,aAAa,MAAM,OAAO;CAEhC,MAAM,CAAC,WAAW,gBAAgB,qBAA8B;EAC9D,OAAO;EACP,cAAc;EACd,UAAU;EACX,CAAC;AAGF,iBAAgB;EACd,MAAM,SAAS,SAAS,SAAS,QAAQ;AACzC,MAAI,CAAC,OAAQ;EACb,MAAM,oBAAoB,aAAa,eAAe;AACtD,SAAO,iBAAiB,SAAS,YAAY;AAC7C,eAAa,OAAO,oBAAoB,SAAS,YAAY;IAC5D,CAAC,gBAAgB,aAAa,CAAC;CAElC,MAAM,iBAAiB,aAAa,iBAA0B;EAC5D,MAAM,KAAK,SAAS;AACpB,MAAI,CAAC,GAAI;AACT,KAAG,UAAU;EACb,MAAM,KAAK,IAAI,MAAM,UAAU,EAAE,SAAS,MAAM,CAAC;AACjD,KAAG,cAAc,GAAG;IACnB,EAAE,CAAC;CAEN,MAAM,SAAS,kBAAkB;AAC/B,MAAI,SAAU;EACd,MAAM,aAAa,CAAC;AACpB,eAAa,WAAW;AACxB,uBAAqB,eAAe,WAAW,CAAC;IAC/C;EAAC;EAAU;EAAgB;EAAW;EAAa,CAAC;CAEvD,MAAM,cAAc,aACjB,MAAqC;AACpC,YAAU,EAAE;AACZ,MAAI,EAAE,iBAAkB;AACxB,UAAQ;IAEV,CAAC,SAAS,OAAO,CAClB;CAED,MAAM,gBAAgB,aACnB,MAAwC;AACvC,cAAY,EAAE;AACd,MAAI,EAAE,iBAAkB;AACxB,MAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,SAAS;AACtC,KAAE,gBAAgB;AAClB,WAAQ;;IAGZ,CAAC,WAAW,OAAO,CACpB;CAED,MAAM,OAAoB,UAAU,OAAO;AAE3C,QACE,oBAAC,UAAU,UAAX;EAAoB,OAAO;GAAE,SAAS;GAAW;GAAU;YACzD,4CACE,oBAAC,MAAD;GACE,gBAAc;GACH;GACX,iBAAe,YAAY;GAC3B,cAAY,YAAY,YAAY;GAC1B;GACV,IAAI;GACJ,SAAS;GACT,WAAW;GACN;GACL,MAAK;GACL,MAAK;GACL,GAAI;GAEH;GACI,GAGP,oBAAC,SAAD;GACE,eAAY;GACZ,SAAS;GACC;GACJ;GACA;GACN;GACA,KAAK;GACK;GACV,UAAU;GACV,MAAK;GACE;GACP,OAAO;IACL,QAAQ;IACR,SAAS;IACT,eAAe;IACf,UAAU;IACV,OAAO;IACR;GACD,EACD;EACgB;;AAGzB,OAAO,cAAc;AAIrB,MAAa,eAAe,EAC1B,SACA,WACA,KACA,GAAG,YAGC;CACJ,MAAM,MAAM,WAAW,UAAU;AACjC,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,yCAAyC;AAInE,QACE,oBAHwB,UAAU,OAAO,QAGzC;EACa;EACX,iBAAe,IAAI,YAAY;EAC/B,cAAY,IAAI,UAAU,YAAY;EACjC;EACL,GAAI;EACJ;;AAGN,YAAY,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","names":["SwitchBase"],"sources":["../src/components/Switch/Switch.tsx"],"sourcesContent":["import { Label } from '@components/Label/Label'\nimport { ErrorMessage, WarningMessage, useFormFieldId, type BaseFormFieldProps, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { CheckIcon, XIcon } from 'lucide-react'\nimport { type Ref } from 'react'\nimport { Switch as SwitchBase, SwitchThumb, type SwitchProps as SwitchBaseProps } from './SwitchBase'\n\ntype SwitchVisualState = Exclude<FormFieldState, 'disabled'>\n\nexport type SwitchProps = Omit<SwitchBaseProps, 'onCheckedChange'> & {\n 'aria-describedby'?: string\n 'aria-label'?: string\n errorMessage?: BaseFormFieldProps['errorMessage']\n hideLabel?: boolean\n id?: string\n label?: string\n labelPosition?: 'left' | 'right'\n labelText?: string\n messageReserveLines?: number\n messageReserveSpace?: boolean\n onChange?: (checked: boolean) => void\n ref?: Ref<HTMLButtonElement>\n required?: boolean\n state?: SwitchVisualState\n value?: string\n variant?: 'default' | 'squared' | 'permanent-indicator'\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nconst thumbBase = 'bg-switch-thumb--checked data-[state=checked]:bg-switch-thumb pointer-events-none block rounded-full ring-0 transition-transform motion-reduce:transition-none'\n\nexport const Switch = ({\n className,\n disabled,\n errorMessage,\n hideLabel = false,\n id,\n label,\n labelPosition = 'right',\n labelText,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n ref,\n required,\n state = 'default',\n value,\n variant,\n warningMessage,\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n ...props\n}: SwitchProps) => {\n const switchId = useFormFieldId(id, name)\n const isDisabled = Boolean(disabled)\n const resolvedLabelText = labelText ?? label\n const errorMessageId = `${switchId}-error`\n const warningMessageId = `${switchId}-warning`\n const messageId = state === 'error' && errorMessage && errorMessageId ? errorMessageId : state === 'warning' && warningMessage && warningMessageId ? warningMessageId : undefined\n const isSquared = variant === 'squared'\n const isPermanentIndicator = variant === 'permanent-indicator'\n\n return (\n <div className='flex items-center' data-testid='spectral-switch-container' data-state={state}>\n {labelPosition === 'left' && !hideLabel && resolvedLabelText && (\n <Label className='mr-2' data-testid='spectral-switch-label-left' htmlFor={switchId}>\n {resolvedLabelText}\n </Label>\n )}\n\n {isPermanentIndicator ? (\n <div className='h-7 text-sm font-medium relative inline-grid grid-cols-[1fr_1fr] items-center'>\n <SwitchBase\n aria-required={required}\n aria-describedby={[messageId, ariaDescribedBy].filter(Boolean).join(' ') || undefined}\n aria-invalid={state === 'error' ? true : undefined}\n aria-label={ariaLabel ?? (hideLabel ? resolvedLabelText : undefined)}\n className={cn(\n 'peer inset-0 w-14 focus-visible:ring-ring absolute inline-flex h-[inherit] items-center focus-visible:ring-offset-background data-[state=checked]:bg-switch-bg--checked data-[state=unchecked]:bg-switch-bg/50',\n 'shadow-2xs cursor-pointer rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n data-testid='spectral-switch'\n disabled={isDisabled}\n id={switchId}\n name={name}\n onCheckedChange={onChange}\n ref={ref}\n required={required}\n value={value}\n {...props}\n >\n <SwitchThumb className={cn(thumbBase, 'size-6.5 shadow-xs relative z-10 duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] data-[state=checked]:translate-x-[26px] motion-reduce:duration-0 data-[state=checked]:rtl:translate-x-[-26px]')} />\n </SwitchBase>\n <span className='ml-0.5 min-w-8 peer-data-[state=unchecked]:translate-x-6 peer-data-[state=unchecked]:rtl:-translate-x-6 motion-reduce:translate-x-0 pointer-events-none relative flex items-center justify-center text-center transition-transform duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] peer-data-[state=checked]:invisible motion-reduce:transition-none motion-reduce:duration-0'>\n <XIcon aria-hidden='true' className='size-4' />\n </span>\n <span className='min-w-8 motion-reduce:translate-x-0 pointer-events-none relative flex items-center justify-center text-center transition-transform duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] peer-data-[state=checked]:-translate-x-full peer-data-[state=checked]:text-background peer-data-[state=unchecked]:invisible motion-reduce:transition-none motion-reduce:duration-0 peer-data-[state=checked]:rtl:translate-x-full'>\n <CheckIcon aria-hidden='true' className='size-4' />\n </span>\n </div>\n ) : (\n <SwitchBase\n aria-required={required}\n aria-describedby={[messageId, ariaDescribedBy].filter(Boolean).join(' ') || undefined}\n aria-invalid={state === 'error' ? true : undefined}\n aria-label={ariaLabel ?? (hideLabel ? resolvedLabelText : undefined)}\n className={cn(\n isSquared\n ? 'peer h-6 w-10 rounded-sm focus-visible:ring-black inline-flex shrink-0 items-center border-2 border-transparent transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-switch-bg--checked data-[state=unchecked]:bg-switch-bg [&_span]:rounded-[4px]'\n : 'focus-visible:ring-ring peer h-6 w-10 shadow-2xs inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-switch-bg--checked data-[state=unchecked]:bg-switch-bg',\n className,\n )}\n data-testid='spectral-switch'\n disabled={isDisabled}\n id={switchId}\n name={name}\n onCheckedChange={onChange}\n ref={ref}\n required={required}\n value={value}\n {...props}\n >\n <SwitchThumb className={cn(thumbBase, isSquared ? 'size-5 shadow-xs data-[state=checked]:translate-x-4 data-[state=checked]:rtl:-translate-x-4' : 'h-5 w-5 shadow-lg data-[state=checked]:translate-x-4')} />\n </SwitchBase>\n )}\n\n {labelPosition === 'right' && !hideLabel && resolvedLabelText && (\n <Label className='ml-2' data-testid='spectral-switch-label-right' htmlFor={switchId} id={`${switchId}-label`}>\n {resolvedLabelText}\n </Label>\n )}\n\n {hideLabel && resolvedLabelText && (\n <Label className='sr-only' data-testid='spectral-switch-label-hidden' htmlFor={switchId}>\n {resolvedLabelText}\n </Label>\n )}\n <ErrorMessage dataTestId='spectral-switch-error-message' id={errorMessageId} message={state === 'error' ? (errorMessage ?? null) : null} messageReserveLines={messageReserveLines} messageReserveSpace={messageReserveSpace && state === 'error'} />\n <WarningMessage dataTestId='spectral-switch-warning-message' id={warningMessageId} message={state === 'warning' ? (warningMessage ?? null) : null} messageReserveLines={messageReserveLines} messageReserveSpace={messageReserveSpace && state === 'warning'} />\n </div>\n )\n}\nSwitch.displayName = 'Switch'\n"],"mappings":";;;;;;;;;;;AA6BA,MAAM,YAAY;AAElB,MAAa,UAAU,EACrB,WACA,UACA,cACA,YAAY,OACZ,IACA,OACA,gBAAgB,SAChB,WACA,sBAAsB,GACtB,sBAAsB,OACtB,MACA,UACA,KACA,UACA,QAAQ,WACR,OACA,SACA,gBACA,oBAAoB,iBACpB,cAAc,WACd,GAAG,YACc;CACjB,MAAM,WAAW,eAAe,IAAI,KAAK;CACzC,MAAM,aAAa,QAAQ,SAAS;CACpC,MAAM,oBAAoB,aAAa;CACvC,MAAM,iBAAiB,GAAG,SAAS;CACnC,MAAM,mBAAmB,GAAG,SAAS;CACrC,MAAM,YAAY,UAAU,WAAW,gBAAgB,iBAAiB,iBAAiB,UAAU,aAAa,kBAAkB,mBAAmB,mBAAmB;CACxK,MAAM,YAAY,YAAY;AAG9B,QACE,qBAAC,OAAD;EAAK,WAAU;EAAoB,eAAY;EAA4B,cAAY;YAAvF;GACG,kBAAkB,UAAU,CAAC,aAAa,qBACzC,oBAAC,OAAD;IAAO,WAAU;IAAO,eAAY;IAA6B,SAAS;cACvE;IACK;GAPe,YAAY,wBAWnC,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAACA,UAAD;MACE,iBAAe;MACf,oBAAkB,CAAC,WAAW,gBAAgB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,IAAI;MAC5E,gBAAc,UAAU,UAAU,OAAO;MACzC,cAAY,cAAc,YAAY,oBAAoB;MAC1D,WAAW,GACT,kNACA,oKACA,mDACA,UACD;MACD,eAAY;MACZ,UAAU;MACV,IAAI;MACE;MACN,iBAAiB;MACZ;MACK;MACH;MACP,GAAI;gBAEJ,oBAAC,aAAD,EAAa,WAAW,GAAG,WAAW,gMAAgM,EAAI;MAC/N;KACb,oBAAC,QAAD;MAAM,WAAU;gBACd,oBAAC,OAAD;OAAO,eAAY;OAAO,WAAU;OAAW;MAC1C;KACP,oBAAC,QAAD;MAAM,WAAU;gBACd,oBAAC,WAAD;OAAW,eAAY;OAAO,WAAU;OAAW;MAC9C;KACH;QAEN,oBAACA,UAAD;IACE,iBAAe;IACf,oBAAkB,CAAC,WAAW,gBAAgB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,IAAI;IAC5E,gBAAc,UAAU,UAAU,OAAO;IACzC,cAAY,cAAc,YAAY,oBAAoB;IAC1D,WAAW,GACT,YACI,+TACA,gZACJ,UACD;IACD,eAAY;IACZ,UAAU;IACV,IAAI;IACE;IACN,iBAAiB;IACZ;IACK;IACH;IACP,GAAI;cAEJ,oBAAC,aAAD,EAAa,WAAW,GAAG,WAAW,YAAY,gGAAgG,uDAAuD,EAAI;IAClM;GAGd,kBAAkB,WAAW,CAAC,aAAa,qBAC1C,oBAAC,OAAD;IAAO,WAAU;IAAO,eAAY;IAA8B,SAAS;IAAU,IAAI,GAAG,SAAS;cAClG;IACK;GAGT,aAAa,qBACZ,oBAAC,OAAD;IAAO,WAAU;IAAU,eAAY;IAA+B,SAAS;cAC5E;IACK;GAEV,oBAAC,cAAD;IAAc,YAAW;IAAgC,IAAI;IAAgB,SAAS,UAAU,UAAW,gBAAgB,OAAQ;IAA2B;IAAqB,qBAAqB,uBAAuB,UAAU;IAAW;GACpP,oBAAC,gBAAD;IAAgB,YAAW;IAAkC,IAAI;IAAkB,SAAS,UAAU,YAAa,kBAAkB,OAAQ;IAA2B;IAAqB,qBAAqB,uBAAuB,UAAU;IAAa;GAC5P;;;AAGV,OAAO,cAAc"}
1
+ {"version":3,"file":"Switch.js","names":["SwitchBase"],"sources":["../src/components/Switch/Switch.tsx"],"sourcesContent":["import { Label } from '@components/Label/Label'\nimport { ErrorMessage, WarningMessage, useFormFieldId, type BaseFormFieldProps, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { CheckIcon, XIcon } from 'lucide-react'\nimport { type Ref } from 'react'\nimport { Switch as SwitchBase, SwitchThumb, type SwitchProps as SwitchBaseProps } from './SwitchBase'\n\ntype SwitchVisualState = Exclude<FormFieldState, 'disabled'>\n\nexport type SwitchProps = Omit<SwitchBaseProps, 'onCheckedChange'> & {\n 'aria-describedby'?: string\n 'aria-label'?: string\n errorMessage?: BaseFormFieldProps['errorMessage']\n hideLabel?: boolean\n id?: string\n label?: string\n labelPosition?: 'left' | 'right'\n labelText?: string\n messageReserveLines?: number\n messageReserveSpace?: boolean\n onChange?: (checked: boolean) => void\n ref?: Ref<HTMLButtonElement>\n required?: boolean\n state?: SwitchVisualState\n value?: string\n variant?: 'default' | 'squared' | 'permanent-indicator'\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nconst thumbBase = 'bg-switch-thumb--checked data-[state=checked]:bg-switch-thumb pointer-events-none block rounded-full ring-0 transition-transform motion-reduce:transition-none'\n\nexport const Switch = ({\n className,\n disabled,\n errorMessage,\n hideLabel = false,\n id,\n label,\n labelPosition = 'right',\n labelText,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n ref,\n required,\n state = 'default',\n value,\n variant,\n warningMessage,\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n ...props\n}: SwitchProps) => {\n const switchId = useFormFieldId(id, name)\n const isDisabled = Boolean(disabled)\n const resolvedLabelText = labelText ?? label\n const errorMessageId = `${switchId}-error`\n const warningMessageId = `${switchId}-warning`\n const messageId = state === 'error' && errorMessage && errorMessageId ? errorMessageId : state === 'warning' && warningMessage && warningMessageId ? warningMessageId : undefined\n const isSquared = variant === 'squared'\n const isPermanentIndicator = variant === 'permanent-indicator'\n\n return (\n <div\n className='flex items-center'\n data-testid='spectral-switch-container'\n data-state={state}\n >\n {labelPosition === 'left' && !hideLabel && resolvedLabelText && (\n <Label\n className='mr-2'\n data-testid='spectral-switch-label-left'\n htmlFor={switchId}\n >\n {resolvedLabelText}\n </Label>\n )}\n\n {isPermanentIndicator ? (\n <div className='h-7 text-sm font-medium relative inline-grid grid-cols-[1fr_1fr] items-center'>\n <SwitchBase\n aria-required={required}\n aria-describedby={[messageId, ariaDescribedBy].filter(Boolean).join(' ') || undefined}\n aria-invalid={state === 'error' ? true : undefined}\n aria-label={ariaLabel ?? (hideLabel ? resolvedLabelText : undefined)}\n className={cn(\n 'peer inset-0 w-14 focus-visible:ring-ring absolute inline-flex h-[inherit] items-center focus-visible:ring-offset-background data-[state=checked]:bg-switch-bg--checked data-[state=unchecked]:bg-switch-bg/50',\n 'shadow-2xs cursor-pointer rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n data-testid='spectral-switch'\n disabled={isDisabled}\n id={switchId}\n name={name}\n onCheckedChange={onChange}\n ref={ref}\n required={required}\n value={value}\n {...props}\n >\n <SwitchThumb className={cn(thumbBase, 'size-6.5 shadow-xs relative z-10 duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] data-[state=checked]:translate-x-[26px] motion-reduce:duration-0 data-[state=checked]:rtl:translate-x-[-26px]')} />\n </SwitchBase>\n <span className='ml-0.5 min-w-8 peer-data-[state=unchecked]:translate-x-6 peer-data-[state=unchecked]:rtl:-translate-x-6 motion-reduce:translate-x-0 pointer-events-none relative flex items-center justify-center text-center transition-transform duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] peer-data-[state=checked]:invisible motion-reduce:transition-none motion-reduce:duration-0'>\n <XIcon\n aria-hidden='true'\n className='size-4'\n />\n </span>\n <span className='min-w-8 motion-reduce:translate-x-0 pointer-events-none relative flex items-center justify-center text-center transition-transform duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] peer-data-[state=checked]:-translate-x-full peer-data-[state=checked]:text-background peer-data-[state=unchecked]:invisible motion-reduce:transition-none motion-reduce:duration-0 peer-data-[state=checked]:rtl:translate-x-full'>\n <CheckIcon\n aria-hidden='true'\n className='size-4'\n />\n </span>\n </div>\n ) : (\n <SwitchBase\n aria-required={required}\n aria-describedby={[messageId, ariaDescribedBy].filter(Boolean).join(' ') || undefined}\n aria-invalid={state === 'error' ? true : undefined}\n aria-label={ariaLabel ?? (hideLabel ? resolvedLabelText : undefined)}\n className={cn(\n isSquared\n ? 'peer h-6 w-10 rounded-sm focus-visible:ring-black inline-flex shrink-0 items-center border-2 border-transparent transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-switch-bg--checked data-[state=unchecked]:bg-switch-bg [&_span]:rounded-[4px]'\n : 'focus-visible:ring-ring peer h-6 w-10 shadow-2xs inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-switch-bg--checked data-[state=unchecked]:bg-switch-bg',\n className,\n )}\n data-testid='spectral-switch'\n disabled={isDisabled}\n id={switchId}\n name={name}\n onCheckedChange={onChange}\n ref={ref}\n required={required}\n value={value}\n {...props}\n >\n <SwitchThumb className={cn(thumbBase, isSquared ? 'size-5 shadow-xs data-[state=checked]:translate-x-4 data-[state=checked]:rtl:-translate-x-4' : 'h-5 w-5 shadow-lg data-[state=checked]:translate-x-4')} />\n </SwitchBase>\n )}\n\n {labelPosition === 'right' && !hideLabel && resolvedLabelText && (\n <Label\n className='ml-2'\n data-testid='spectral-switch-label-right'\n htmlFor={switchId}\n id={`${switchId}-label`}\n >\n {resolvedLabelText}\n </Label>\n )}\n\n {hideLabel && resolvedLabelText && (\n <Label\n className='sr-only'\n data-testid='spectral-switch-label-hidden'\n htmlFor={switchId}\n >\n {resolvedLabelText}\n </Label>\n )}\n <ErrorMessage\n dataTestId='spectral-switch-error-message'\n id={errorMessageId}\n message={state === 'error' ? (errorMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'error'}\n />\n <WarningMessage\n dataTestId='spectral-switch-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? (warningMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'warning'}\n />\n </div>\n )\n}\nSwitch.displayName = 'Switch'\n"],"mappings":";;;;;;;;;;;AA6BA,MAAM,YAAY;AAElB,MAAa,UAAU,EACrB,WACA,UACA,cACA,YAAY,OACZ,IACA,OACA,gBAAgB,SAChB,WACA,sBAAsB,GACtB,sBAAsB,OACtB,MACA,UACA,KACA,UACA,QAAQ,WACR,OACA,SACA,gBACA,oBAAoB,iBACpB,cAAc,WACd,GAAG,YACc;CACjB,MAAM,WAAW,eAAe,IAAI,KAAK;CACzC,MAAM,aAAa,QAAQ,SAAS;CACpC,MAAM,oBAAoB,aAAa;CACvC,MAAM,iBAAiB,GAAG,SAAS;CACnC,MAAM,mBAAmB,GAAG,SAAS;CACrC,MAAM,YAAY,UAAU,WAAW,gBAAgB,iBAAiB,iBAAiB,UAAU,aAAa,kBAAkB,mBAAmB,mBAAmB;CACxK,MAAM,YAAY,YAAY;AAG9B,QACE,qBAAC,OAAD;EACE,WAAU;EACV,eAAY;EACZ,cAAY;YAHd;GAKG,kBAAkB,UAAU,CAAC,aAAa,qBACzC,oBAAC,OAAD;IACE,WAAU;IACV,eAAY;IACZ,SAAS;cAER;IACK;GAfe,YAAY,wBAmBnC,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAACA,UAAD;MACE,iBAAe;MACf,oBAAkB,CAAC,WAAW,gBAAgB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,IAAI;MAC5E,gBAAc,UAAU,UAAU,OAAO;MACzC,cAAY,cAAc,YAAY,oBAAoB;MAC1D,WAAW,GACT,kNACA,oKACA,mDACA,UACD;MACD,eAAY;MACZ,UAAU;MACV,IAAI;MACE;MACN,iBAAiB;MACZ;MACK;MACH;MACP,GAAI;gBAEJ,oBAAC,aAAD,EAAa,WAAW,GAAG,WAAW,gMAAgM,EAAI;MAC/N;KACb,oBAAC,QAAD;MAAM,WAAU;gBACd,oBAAC,OAAD;OACE,eAAY;OACZ,WAAU;OACV;MACG;KACP,oBAAC,QAAD;MAAM,WAAU;gBACd,oBAAC,WAAD;OACE,eAAY;OACZ,WAAU;OACV;MACG;KACH;QAEN,oBAACA,UAAD;IACE,iBAAe;IACf,oBAAkB,CAAC,WAAW,gBAAgB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,IAAI;IAC5E,gBAAc,UAAU,UAAU,OAAO;IACzC,cAAY,cAAc,YAAY,oBAAoB;IAC1D,WAAW,GACT,YACI,+TACA,gZACJ,UACD;IACD,eAAY;IACZ,UAAU;IACV,IAAI;IACE;IACN,iBAAiB;IACZ;IACK;IACH;IACP,GAAI;cAEJ,oBAAC,aAAD,EAAa,WAAW,GAAG,WAAW,YAAY,gGAAgG,uDAAuD,EAAI;IAClM;GAGd,kBAAkB,WAAW,CAAC,aAAa,qBAC1C,oBAAC,OAAD;IACE,WAAU;IACV,eAAY;IACZ,SAAS;IACT,IAAI,GAAG,SAAS;cAEf;IACK;GAGT,aAAa,qBACZ,oBAAC,OAAD;IACE,WAAU;IACV,eAAY;IACZ,SAAS;cAER;IACK;GAEV,oBAAC,cAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,UAAW,gBAAgB,OAAQ;IACjC;IACrB,qBAAqB,uBAAuB,UAAU;IACtD;GACF,oBAAC,gBAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,YAAa,kBAAkB,OAAQ;IACrC;IACrB,qBAAqB,uBAAuB,UAAU;IACtD;GACE;;;AAGV,OAAO,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"TabsBase.d.ts","names":[],"sources":["../../src/components/Tabs/TabsBase.tsx"],"mappings":";;;;;;UAMiB,gBAAA;EACf,cAAA;EACA,MAAA;EACA,GAAA;EACA,QAAA;EACA,aAAA,GAAgB,KAAA;EAChB,WAAA;EACA,SAAA,GAAY,SAAA;EACZ,KAAA;AAAA;AAAA,cAGW,WAAA,EAAW,OAAA,CAAA,OAAA,CAAA,gBAAA;AAAA,cAEX,cAAA,GAAc,aAAA,cAAqC,gBAAA;AAAA,UAQ/C,aAAA,SAAsB,IAAA,CAAK,wBAAA;EAC1C,aAAA,IAAiB,KAAA;EACjB,cAAA;EACA,YAAA;EACA,QAAA,EAAU,SAAA;EACV,GAAA;EACA,QAAA;EACA,WAAA;EACA,SAAA,GAAY,SAAA;EACZ,KAAA;AAAA;AAAA,cAGW,QAAA;EAAQ,GAAA;EAAA,cAAA;EAAA,QAAA;EAAA,YAAA;EAAA,GAAA;EAAA,QAAA;EAAA,aAAA;EAAA,WAAA;EAAA,SAAA;EAAA,KAAA,EAAA,eAAA;EAAA,GAAA;AAAA,GAYlB,aAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAsCgB,aAAA,SAAsB,IAAA,CAAK,wBAAA;EAC1C,QAAA,GAAW,SAAA;EACX,IAAA;EACA,SAAA,GAAY,SAAA;AAAA;AAAA,cAGD,QAAA;EAAQ,GAAA;EAAA,QAAA;EAAA,SAAA;EAAA,IAAA;EAAA,SAAA;EAAA,GAAA;AAAA,GAOlB,aAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAwJgB,gBAAA,SAAyB,wBAAA;EACxC,KAAA;EACA,QAAA;AAAA;AAAA,cAGW,WAAA;EAAW,GAAA;EAAA,SAAA;EAAA,KAAA,EAAA,YAAA;EAAA,OAAA;EAAA,SAAA;EAAA,QAAA,EAAA,eAAA;EAAA,GAAA;AAAA,GAQrB,gBAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAsEgB,yBAAA;EACf,QAAA,EAAU,SAAA;EACV,SAAA;AAAA;AAAA,cAGW,oBAAA;EAAoB,GAAA;EAAA,QAAA;EAAA;AAAA,GAI9B,yBAAA;EACD,GAAA,GAAM,GAAA,CAAI,cAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UA6CgB,gBAAA,SAAyB,wBAAA;EACxC,KAAA;EACA,UAAA;AAAA;AAAA,cAGW,WAAA;EAAW,GAAA;EAAA,SAAA;EAAA,KAAA,EAAA,YAAA;EAAA,UAAA;EAAA,GAAA;AAAA,GAMrB,gBAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"TabsBase.d.ts","names":[],"sources":["../../src/components/Tabs/TabsBase.tsx"],"mappings":";;;;;;UAMiB,gBAAA;EACf,cAAA;EACA,MAAA;EACA,GAAA;EACA,QAAA;EACA,aAAA,GAAgB,KAAA;EAChB,WAAA;EACA,SAAA,GAAY,SAAA;EACZ,KAAA;AAAA;AAAA,cAGW,WAAA,EAAW,OAAA,CAAA,OAAA,CAAA,gBAAA;AAAA,cAEX,cAAA,GAAc,aAAA,cAAqC,gBAAA;AAAA,UAQ/C,aAAA,SAAsB,IAAA,CAAK,wBAAA;EAC1C,aAAA,IAAiB,KAAA;EACjB,cAAA;EACA,YAAA;EACA,QAAA,EAAU,SAAA;EACV,GAAA;EACA,QAAA;EACA,WAAA;EACA,SAAA,GAAY,SAAA;EACZ,KAAA;AAAA;AAAA,cAGW,QAAA;EAAQ,GAAA;EAAA,cAAA;EAAA,QAAA;EAAA,YAAA;EAAA,GAAA;EAAA,QAAA;EAAA,aAAA;EAAA,WAAA;EAAA,SAAA;EAAA,KAAA,EAAA,eAAA;EAAA,GAAA;AAAA,GAYlB,aAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UA6CgB,aAAA,SAAsB,IAAA,CAAK,wBAAA;EAC1C,QAAA,GAAW,SAAA;EACX,IAAA;EACA,SAAA,GAAY,SAAA;AAAA;AAAA,cAGD,QAAA;EAAQ,GAAA;EAAA,QAAA;EAAA,SAAA;EAAA,IAAA;EAAA,SAAA;EAAA,GAAA;AAAA,GAOlB,aAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UA4JgB,gBAAA,SAAyB,wBAAA;EACxC,KAAA;EACA,QAAA;AAAA;AAAA,cAGW,WAAA;EAAW,GAAA;EAAA,SAAA;EAAA,KAAA,EAAA,YAAA;EAAA,OAAA;EAAA,SAAA;EAAA,QAAA,EAAA,eAAA;EAAA,GAAA;AAAA,GAQrB,gBAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAsEgB,yBAAA;EACf,QAAA,EAAU,SAAA;EACV,SAAA;AAAA;AAAA,cAGW,oBAAA;EAAoB,GAAA;EAAA,QAAA;EAAA;AAAA,GAI9B,yBAAA;EACD,GAAA,GAAM,GAAA,CAAI,cAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAgDgB,gBAAA,SAAyB,wBAAA;EACxC,KAAA;EACA,UAAA;AAAA;AAAA,cAGW,WAAA;EAAW,GAAA;EAAA,SAAA;EAAA,KAAA,EAAA,YAAA;EAAA,UAAA;EAAA,GAAA;AAAA,GAMrB,gBAAA;EACD,GAAA,GAAM,GAAA,CAAI,WAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -114,6 +114,7 @@ const TabsList = function TabsList({ ref, children, className, loop = true, righ
114
114
  children: [/* @__PURE__ */ jsxs("div", {
115
115
  ref,
116
116
  role: "tablist",
117
+ tabIndex: -1,
117
118
  "data-testid": "spectral-tabs-list",
118
119
  "aria-orientation": orientation,
119
120
  "aria-disabled": disabled,
@@ -1 +1 @@
1
- {"version":3,"file":"TabsBase.js","names":[],"sources":["../../src/components/Tabs/TabsBase.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, type ComponentPropsWithoutRef, type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react'\nimport useMeasure from 'react-use-measure'\nimport { calculateIndicatorStyle, debounce, generateId, prefersReducedMotion, type IndicatorStyle } from './tabsUtils'\n\nexport interface TabsContextValue {\n activationMode: 'automatic' | 'manual'\n baseId: string\n dir: 'ltr' | 'rtl'\n disabled: boolean\n onValueChange: (value: string) => void\n orientation: 'horizontal' | 'vertical'\n rightSlot?: ReactNode | undefined\n value: string\n}\n\nexport const TabsContext = createContext<TabsContextValue | null>(null)\n\nexport const useTabsContext = (componentName: string = 'Tabs'): TabsContextValue => {\n const context = useContext(TabsContext)\n if (context === null) {\n throw new Error(`${componentName} components must be used within a Tabs.Root`)\n }\n return context\n}\n\nexport interface TabsBaseProps extends Omit<ComponentPropsWithoutRef<'div'>, 'dir' | 'defaultValue'> {\n onValueChange?: (value: string) => void\n activationMode?: 'automatic' | 'manual'\n defaultValue?: string\n children: ReactNode\n dir?: 'ltr' | 'rtl'\n disabled?: boolean\n orientation?: 'horizontal' | 'vertical'\n rightSlot?: ReactNode | undefined\n value?: string\n}\n\nexport const TabsBase = function Tabs({\n ref,\n activationMode = 'automatic',\n children,\n defaultValue,\n dir = 'ltr',\n disabled = false,\n onValueChange,\n orientation = 'horizontal',\n rightSlot,\n value: controlledValue,\n ...props\n}: TabsBaseProps & {\n ref?: Ref<HTMLElement>\n}) {\n const [uncontrolledValue, setUncontrolledValue] = useState<string>(defaultValue ?? '')\n const baseId = useId() ?? generateId('tabs')\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = useCallback(\n (newValue: string): void => {\n if (disabled) return\n\n if (!isControlled) {\n setUncontrolledValue(newValue)\n }\n onValueChange?.(newValue)\n },\n [isControlled, onValueChange, disabled],\n )\n\n const contextValue = {\n activationMode,\n baseId,\n dir,\n disabled,\n onValueChange: handleValueChange,\n orientation,\n rightSlot,\n value,\n } as const satisfies TabsContextValue\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div ref={ref as Ref<HTMLDivElement>} data-testid='spectral-tabs' data-orientation={orientation} data-disabled={disabled ? '' : undefined} dir={dir} {...props}>\n {children}\n </div>\n </TabsContext.Provider>\n )\n}\n\nexport interface TabsListProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: ReactNode\n loop?: boolean\n rightSlot?: ReactNode | undefined\n}\n\nexport const TabsList = function TabsList({\n ref,\n children,\n className,\n loop = true,\n rightSlot,\n ...props\n}: TabsListProps & {\n ref?: Ref<HTMLElement>\n}) {\n const { orientation, disabled, value } = useTabsContext('TabsList')\n const [indicatorStyle, setIndicatorStyle] = useState<IndicatorStyle | null>(null)\n const tabsListRef = useRef<HTMLDivElement>(null)\n const reducedMotion = prefersReducedMotion()\n\n // Calculate indicator position\n const calculatePosition = useCallback(() => {\n const newStyle = calculateIndicatorStyle(tabsListRef)\n // Only update if we have a valid position (width/height > 0)\n if (newStyle.width > 0 || newStyle.height > 0) {\n setIndicatorStyle(newStyle)\n }\n }, [])\n\n // Debounced version for resize/mutation observers\n const debouncedCalculatePosition = useMemo(() => debounce(calculatePosition, 16), [calculatePosition])\n\n // Initial calculation and observer setup\n useEffect(() => {\n // Immediate calculation on mount\n calculatePosition()\n\n // Only set up observers if browser APIs are available\n if (typeof ResizeObserver === 'undefined' || typeof MutationObserver === 'undefined') {\n return\n }\n\n const resizeObserver = new ResizeObserver(debouncedCalculatePosition)\n const mutationObserver = new MutationObserver(debouncedCalculatePosition)\n\n const currentRef = tabsListRef.current\n if (currentRef) {\n resizeObserver.observe(currentRef)\n mutationObserver.observe(currentRef, {\n attributes: true,\n childList: true,\n subtree: true,\n })\n }\n\n return () => {\n resizeObserver.disconnect()\n mutationObserver.disconnect()\n debouncedCalculatePosition.cancel()\n }\n }, [calculatePosition, debouncedCalculatePosition])\n\n // Recalculate when value changes\n useEffect(() => {\n calculatePosition()\n }, [value, calculatePosition])\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>): void => {\n if (disabled) return\n\n const triggers = Array.from(tabsListRef.current?.querySelectorAll<HTMLElement>(`[role='tab']:not([disabled]):not([aria-disabled='true'])`) ?? [])\n\n if (triggers.length === 0) return\n\n const currentIndex = triggers.findIndex((trigger) => trigger === document.activeElement)\n if (currentIndex === -1) return\n\n let nextIndex: number | null = null\n\n const { key, ctrlKey, metaKey } = event\n const isModified = ctrlKey || metaKey\n\n if (orientation === 'horizontal') {\n if (key === 'ArrowLeft' || (key === 'ArrowUp' && isModified)) {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : loop ? triggers.length - 1 : currentIndex\n } else if (key === 'ArrowRight' || (key === 'ArrowDown' && isModified)) {\n nextIndex = currentIndex < triggers.length - 1 ? currentIndex + 1 : loop ? 0 : currentIndex\n }\n } else {\n if (key === 'ArrowUp' || (key === 'ArrowLeft' && isModified)) {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : loop ? triggers.length - 1 : currentIndex\n } else if (key === 'ArrowDown' || (key === 'ArrowRight' && isModified)) {\n nextIndex = currentIndex < triggers.length - 1 ? currentIndex + 1 : loop ? 0 : currentIndex\n }\n }\n\n if (key === 'Home') {\n nextIndex = 0\n } else if (key === 'End') {\n nextIndex = triggers.length - 1\n }\n\n if (nextIndex !== null && nextIndex !== currentIndex) {\n event.preventDefault()\n event.stopPropagation()\n ;(triggers[nextIndex] as HTMLButtonElement)?.focus()\n }\n },\n [disabled, orientation, loop],\n )\n\n return (\n <div className='relative' ref={tabsListRef}>\n <div\n ref={ref as Ref<HTMLDivElement>}\n role='tablist'\n data-testid='spectral-tabs-list'\n aria-orientation={orientation}\n aria-disabled={disabled}\n className={cn('tabs-list flex', orientation === 'horizontal' && 'items-center justify-between', orientation === 'vertical' && 'flex-col', className)}\n onKeyDown={handleKeyDown}\n {...props}\n >\n <div className={cn('flex', orientation === 'horizontal' && 'items-center', orientation === 'vertical' && 'flex-col')}>{children}</div>\n {rightSlot && <div className='z-10 flex items-center'>{rightSlot}</div>}\n </div>\n {/* Animated indicator - only rendered after first measurement */}\n {indicatorStyle && (\n <motion.div\n className={cn(\n 'top-0 left-0 pointer-events-none absolute will-change-transform select-none',\n indicatorStyle.orientation === 'horizontal' && !indicatorStyle.isEnclosed && `after:bottom-0 after:left-0 bottom-px z-10 after:absolute after:w-full after:rounded-t-[0.3rem] after:border-b-[0.3rem] after:border-tabs-indicator after:content-['']`,\n indicatorStyle.orientation === 'vertical' && !indicatorStyle.isEnclosed && `after:right-0 after:top-0 after:w-1 right-px z-10 after:absolute after:h-full after:rounded-l-[0.3rem] after:border-r-[0.3rem] after:border-tabs-indicator after:content-['']`,\n indicatorStyle.orientation === 'horizontal' && indicatorStyle.isEnclosed && 'rounded-lg shadow-lg z-0 bg-tabs-enclosed-indicator',\n indicatorStyle.orientation === 'vertical' && indicatorStyle.isEnclosed && 'rounded-lg shadow-lg z-0 bg-tabs-enclosed-indicator',\n )}\n // Don't animate on initial mount - prevents sliding from (0,0)\n initial={false}\n animate={{\n // Use x/y (translateX/translateY) for position - compositor-friendly, no reflows\n x: indicatorStyle.left,\n y: indicatorStyle.isEnclosed ? indicatorStyle.top + indicatorStyle.height * 0.1 : indicatorStyle.top,\n // Width/height required for correct rendering: scaleX/Y would distort\n // border-radius on enclosed variant and border widths on default variant\n width: indicatorStyle.width,\n height: indicatorStyle.isEnclosed ? (indicatorStyle.orientation === 'vertical' ? 40 : indicatorStyle.height * 0.8) : indicatorStyle.height,\n }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : {\n // Separate transition configs: spring for transforms, tween for layout\n x: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n y: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n width: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n height: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n }\n }\n aria-hidden='true'\n />\n )}\n </div>\n )\n}\n\nexport interface TabsTriggerProps extends ComponentPropsWithoutRef<'button'> {\n value: string\n disabled?: boolean\n}\n\nexport const TabsTrigger = function TabsTrigger({\n ref,\n className,\n value: triggerValue,\n onClick,\n onKeyDown,\n disabled: triggerDisabled = false,\n ...props\n}: TabsTriggerProps & {\n ref?: Ref<HTMLElement>\n}) {\n const { value, onValueChange, activationMode, disabled: contextDisabled, baseId } = useTabsContext('TabsTrigger')\n\n const triggerId = `${baseId}-trigger-${triggerValue}`\n const contentId = `${baseId}-content-${triggerValue}`\n const isActive = value === triggerValue\n const isDisabled = contextDisabled || triggerDisabled\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>): void => {\n if (isDisabled) {\n event.preventDefault()\n return\n }\n onValueChange(triggerValue)\n onClick?.(event)\n },\n [triggerValue, onValueChange, onClick, isDisabled],\n )\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLButtonElement>): void => {\n if (isDisabled) {\n event.preventDefault()\n return\n }\n\n const { key } = event\n\n if (key === 'Enter' || key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n onValueChange(triggerValue)\n }\n\n onKeyDown?.(event)\n },\n [triggerValue, onValueChange, onKeyDown, isDisabled],\n )\n\n const handleFocus = useCallback((): void => {\n if (isDisabled) return\n if (activationMode === 'automatic') {\n onValueChange(triggerValue)\n }\n }, [activationMode, onValueChange, triggerValue, isDisabled])\n\n return (\n <button\n aria-controls={contentId}\n aria-disabled={isDisabled}\n aria-selected={isActive}\n className={cn('tabs-trigger z-10 hover:cursor-pointer focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent', className)}\n data-disabled={isDisabled ? '' : undefined}\n data-state={isActive ? 'active' : 'inactive'}\n data-testid='spectral-tabs-trigger'\n disabled={isDisabled}\n id={triggerId}\n onClick={handleClick}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n ref={ref as Ref<HTMLButtonElement>}\n role='tab'\n tabIndex={isActive ? 0 : -1}\n type='button'\n {...props}\n />\n )\n}\n\nexport interface TabsContentContainerProps {\n children: ReactNode\n className?: string\n}\n\nexport const TabsContentContainer = function TabsContentContainer({\n ref,\n children,\n className,\n}: TabsContentContainerProps & {\n ref?: Ref<HTMLDivElement>\n}) {\n const { value } = useTabsContext('TabsContentContainer')\n const [measureRef, bounds] = useMeasure()\n const reducedMotion = prefersReducedMotion()\n\n return (\n <motion.div\n ref={ref}\n className={cn('overflow-hidden', className)}\n data-testid='spectral-tabs-content-container'\n animate={{\n height: bounds.height || 'auto',\n }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : {\n duration: 0.3,\n ease: [0.25, 1, 0.5, 1],\n }\n }\n >\n <AnimatePresence mode='wait' initial={false}>\n <motion.div\n key={value}\n ref={measureRef}\n initial={reducedMotion ? false : { opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={reducedMotion ? undefined : { opacity: 0, y: -8 }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : {\n duration: 0.2,\n ease: [0.25, 1, 0.5, 1],\n }\n }\n >\n {children}\n </motion.div>\n </AnimatePresence>\n </motion.div>\n )\n}\n\nexport interface TabsContentProps extends ComponentPropsWithoutRef<'div'> {\n value: string\n forceMount?: boolean\n}\n\nexport const TabsContent = function TabsContent({\n ref,\n className,\n value: contentValue,\n forceMount = false,\n ...props\n}: TabsContentProps & {\n ref?: Ref<HTMLElement>\n}) {\n const { value, baseId } = useTabsContext('TabsContent')\n const contentId = `${baseId}-content-${contentValue}`\n const triggerId = `${baseId}-trigger-${contentValue}`\n const isActive = value === contentValue\n\n if (!forceMount && !isActive) {\n return null\n }\n\n return (\n <div\n aria-labelledby={triggerId}\n className={cn('tabs-content focus:outline-none focus-visible:outline-none', className)}\n data-state={isActive ? 'active' : 'inactive'}\n data-testid='spectral-tabs-content'\n hidden={!isActive}\n id={contentId}\n ref={ref as Ref<HTMLDivElement>}\n role='tabpanel'\n tabIndex={0}\n {...props}\n />\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TabsBase.js","names":[],"sources":["../../src/components/Tabs/TabsBase.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, type ComponentPropsWithoutRef, type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react'\nimport useMeasure from 'react-use-measure'\nimport { calculateIndicatorStyle, debounce, generateId, prefersReducedMotion, type IndicatorStyle } from './tabsUtils'\n\nexport interface TabsContextValue {\n activationMode: 'automatic' | 'manual'\n baseId: string\n dir: 'ltr' | 'rtl'\n disabled: boolean\n onValueChange: (value: string) => void\n orientation: 'horizontal' | 'vertical'\n rightSlot?: ReactNode | undefined\n value: string\n}\n\nexport const TabsContext = createContext<TabsContextValue | null>(null)\n\nexport const useTabsContext = (componentName: string = 'Tabs'): TabsContextValue => {\n const context = useContext(TabsContext)\n if (context === null) {\n throw new Error(`${componentName} components must be used within a Tabs.Root`)\n }\n return context\n}\n\nexport interface TabsBaseProps extends Omit<ComponentPropsWithoutRef<'div'>, 'dir' | 'defaultValue'> {\n onValueChange?: (value: string) => void\n activationMode?: 'automatic' | 'manual'\n defaultValue?: string\n children: ReactNode\n dir?: 'ltr' | 'rtl'\n disabled?: boolean\n orientation?: 'horizontal' | 'vertical'\n rightSlot?: ReactNode | undefined\n value?: string\n}\n\nexport const TabsBase = function Tabs({\n ref,\n activationMode = 'automatic',\n children,\n defaultValue,\n dir = 'ltr',\n disabled = false,\n onValueChange,\n orientation = 'horizontal',\n rightSlot,\n value: controlledValue,\n ...props\n}: TabsBaseProps & {\n ref?: Ref<HTMLElement>\n}) {\n const [uncontrolledValue, setUncontrolledValue] = useState<string>(defaultValue ?? '')\n const baseId = useId() ?? generateId('tabs')\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = useCallback(\n (newValue: string): void => {\n if (disabled) return\n\n if (!isControlled) {\n setUncontrolledValue(newValue)\n }\n onValueChange?.(newValue)\n },\n [isControlled, onValueChange, disabled],\n )\n\n const contextValue = {\n activationMode,\n baseId,\n dir,\n disabled,\n onValueChange: handleValueChange,\n orientation,\n rightSlot,\n value,\n } as const satisfies TabsContextValue\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div\n ref={ref as Ref<HTMLDivElement>}\n data-testid='spectral-tabs'\n data-orientation={orientation}\n data-disabled={disabled ? '' : undefined}\n dir={dir}\n {...props}\n >\n {children}\n </div>\n </TabsContext.Provider>\n )\n}\n\nexport interface TabsListProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: ReactNode\n loop?: boolean\n rightSlot?: ReactNode | undefined\n}\n\nexport const TabsList = function TabsList({\n ref,\n children,\n className,\n loop = true,\n rightSlot,\n ...props\n}: TabsListProps & {\n ref?: Ref<HTMLElement>\n}) {\n const { orientation, disabled, value } = useTabsContext('TabsList')\n const [indicatorStyle, setIndicatorStyle] = useState<IndicatorStyle | null>(null)\n const tabsListRef = useRef<HTMLDivElement>(null)\n const reducedMotion = prefersReducedMotion()\n\n // Calculate indicator position\n const calculatePosition = useCallback(() => {\n const newStyle = calculateIndicatorStyle(tabsListRef)\n // Only update if we have a valid position (width/height > 0)\n if (newStyle.width > 0 || newStyle.height > 0) {\n setIndicatorStyle(newStyle)\n }\n }, [])\n\n // Debounced version for resize/mutation observers\n const debouncedCalculatePosition = useMemo(() => debounce(calculatePosition, 16), [calculatePosition])\n\n // Initial calculation and observer setup\n useEffect(() => {\n // Immediate calculation on mount\n calculatePosition()\n\n // Only set up observers if browser APIs are available\n if (typeof ResizeObserver === 'undefined' || typeof MutationObserver === 'undefined') {\n return\n }\n\n const resizeObserver = new ResizeObserver(debouncedCalculatePosition)\n const mutationObserver = new MutationObserver(debouncedCalculatePosition)\n\n const currentRef = tabsListRef.current\n if (currentRef) {\n resizeObserver.observe(currentRef)\n mutationObserver.observe(currentRef, {\n attributes: true,\n childList: true,\n subtree: true,\n })\n }\n\n return () => {\n resizeObserver.disconnect()\n mutationObserver.disconnect()\n debouncedCalculatePosition.cancel()\n }\n }, [calculatePosition, debouncedCalculatePosition])\n\n // Recalculate when value changes\n useEffect(() => {\n calculatePosition()\n }, [value, calculatePosition])\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>): void => {\n if (disabled) return\n\n const triggers = Array.from(tabsListRef.current?.querySelectorAll<HTMLElement>(`[role='tab']:not([disabled]):not([aria-disabled='true'])`) ?? [])\n\n if (triggers.length === 0) return\n\n const currentIndex = triggers.findIndex((trigger) => trigger === document.activeElement)\n if (currentIndex === -1) return\n\n let nextIndex: number | null = null\n\n const { key, ctrlKey, metaKey } = event\n const isModified = ctrlKey || metaKey\n\n if (orientation === 'horizontal') {\n if (key === 'ArrowLeft' || (key === 'ArrowUp' && isModified)) {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : loop ? triggers.length - 1 : currentIndex\n } else if (key === 'ArrowRight' || (key === 'ArrowDown' && isModified)) {\n nextIndex = currentIndex < triggers.length - 1 ? currentIndex + 1 : loop ? 0 : currentIndex\n }\n } else {\n if (key === 'ArrowUp' || (key === 'ArrowLeft' && isModified)) {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : loop ? triggers.length - 1 : currentIndex\n } else if (key === 'ArrowDown' || (key === 'ArrowRight' && isModified)) {\n nextIndex = currentIndex < triggers.length - 1 ? currentIndex + 1 : loop ? 0 : currentIndex\n }\n }\n\n if (key === 'Home') {\n nextIndex = 0\n } else if (key === 'End') {\n nextIndex = triggers.length - 1\n }\n\n if (nextIndex !== null && nextIndex !== currentIndex) {\n event.preventDefault()\n event.stopPropagation()\n ;(triggers[nextIndex] as HTMLButtonElement)?.focus()\n }\n },\n [disabled, orientation, loop],\n )\n\n return (\n <div\n className='relative'\n ref={tabsListRef}\n >\n <div\n ref={ref as Ref<HTMLDivElement>}\n role='tablist'\n tabIndex={-1}\n data-testid='spectral-tabs-list'\n aria-orientation={orientation}\n aria-disabled={disabled}\n className={cn('tabs-list flex', orientation === 'horizontal' && 'items-center justify-between', orientation === 'vertical' && 'flex-col', className)}\n onKeyDown={handleKeyDown}\n {...props}\n >\n <div className={cn('flex', orientation === 'horizontal' && 'items-center', orientation === 'vertical' && 'flex-col')}>{children}</div>\n {rightSlot && <div className='z-10 flex items-center'>{rightSlot}</div>}\n </div>\n {/* Animated indicator - only rendered after first measurement */}\n {indicatorStyle && (\n <motion.div\n className={cn(\n 'top-0 left-0 pointer-events-none absolute will-change-transform select-none',\n indicatorStyle.orientation === 'horizontal' && !indicatorStyle.isEnclosed && `after:bottom-0 after:left-0 bottom-px z-10 after:absolute after:w-full after:rounded-t-[0.3rem] after:border-b-[0.3rem] after:border-tabs-indicator after:content-['']`,\n indicatorStyle.orientation === 'vertical' && !indicatorStyle.isEnclosed && `after:right-0 after:top-0 after:w-1 right-px z-10 after:absolute after:h-full after:rounded-l-[0.3rem] after:border-r-[0.3rem] after:border-tabs-indicator after:content-['']`,\n indicatorStyle.orientation === 'horizontal' && indicatorStyle.isEnclosed && 'rounded-lg shadow-lg z-0 bg-tabs-enclosed-indicator',\n indicatorStyle.orientation === 'vertical' && indicatorStyle.isEnclosed && 'rounded-lg shadow-lg z-0 bg-tabs-enclosed-indicator',\n )}\n // Don't animate on initial mount - prevents sliding from (0,0)\n initial={false}\n animate={{\n // Use x/y (translateX/translateY) for position - compositor-friendly, no reflows\n x: indicatorStyle.left,\n y: indicatorStyle.isEnclosed ? indicatorStyle.top + indicatorStyle.height * 0.1 : indicatorStyle.top,\n // Width/height required for correct rendering: scaleX/Y would distort\n // border-radius on enclosed variant and border widths on default variant\n width: indicatorStyle.width,\n height: indicatorStyle.isEnclosed ? (indicatorStyle.orientation === 'vertical' ? 40 : indicatorStyle.height * 0.8) : indicatorStyle.height,\n }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : {\n // Separate transition configs: spring for transforms, tween for layout\n x: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n y: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n width: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n height: { type: 'spring', stiffness: 500, damping: 40, mass: 1 },\n }\n }\n aria-hidden='true'\n />\n )}\n </div>\n )\n}\n\nexport interface TabsTriggerProps extends ComponentPropsWithoutRef<'button'> {\n value: string\n disabled?: boolean\n}\n\nexport const TabsTrigger = function TabsTrigger({\n ref,\n className,\n value: triggerValue,\n onClick,\n onKeyDown,\n disabled: triggerDisabled = false,\n ...props\n}: TabsTriggerProps & {\n ref?: Ref<HTMLElement>\n}) {\n const { value, onValueChange, activationMode, disabled: contextDisabled, baseId } = useTabsContext('TabsTrigger')\n\n const triggerId = `${baseId}-trigger-${triggerValue}`\n const contentId = `${baseId}-content-${triggerValue}`\n const isActive = value === triggerValue\n const isDisabled = contextDisabled || triggerDisabled\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>): void => {\n if (isDisabled) {\n event.preventDefault()\n return\n }\n onValueChange(triggerValue)\n onClick?.(event)\n },\n [triggerValue, onValueChange, onClick, isDisabled],\n )\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLButtonElement>): void => {\n if (isDisabled) {\n event.preventDefault()\n return\n }\n\n const { key } = event\n\n if (key === 'Enter' || key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n onValueChange(triggerValue)\n }\n\n onKeyDown?.(event)\n },\n [triggerValue, onValueChange, onKeyDown, isDisabled],\n )\n\n const handleFocus = useCallback((): void => {\n if (isDisabled) return\n if (activationMode === 'automatic') {\n onValueChange(triggerValue)\n }\n }, [activationMode, onValueChange, triggerValue, isDisabled])\n\n return (\n <button\n aria-controls={contentId}\n aria-disabled={isDisabled}\n aria-selected={isActive}\n className={cn('tabs-trigger z-10 hover:cursor-pointer focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent', className)}\n data-disabled={isDisabled ? '' : undefined}\n data-state={isActive ? 'active' : 'inactive'}\n data-testid='spectral-tabs-trigger'\n disabled={isDisabled}\n id={triggerId}\n onClick={handleClick}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n ref={ref as Ref<HTMLButtonElement>}\n role='tab'\n tabIndex={isActive ? 0 : -1}\n type='button'\n {...props}\n />\n )\n}\n\nexport interface TabsContentContainerProps {\n children: ReactNode\n className?: string\n}\n\nexport const TabsContentContainer = function TabsContentContainer({\n ref,\n children,\n className,\n}: TabsContentContainerProps & {\n ref?: Ref<HTMLDivElement>\n}) {\n const { value } = useTabsContext('TabsContentContainer')\n const [measureRef, bounds] = useMeasure()\n const reducedMotion = prefersReducedMotion()\n\n return (\n <motion.div\n ref={ref}\n className={cn('overflow-hidden', className)}\n data-testid='spectral-tabs-content-container'\n animate={{\n height: bounds.height || 'auto',\n }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : {\n duration: 0.3,\n ease: [0.25, 1, 0.5, 1],\n }\n }\n >\n <AnimatePresence\n mode='wait'\n initial={false}\n >\n <motion.div\n key={value}\n ref={measureRef}\n initial={reducedMotion ? false : { opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={reducedMotion ? undefined : { opacity: 0, y: -8 }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : {\n duration: 0.2,\n ease: [0.25, 1, 0.5, 1],\n }\n }\n >\n {children}\n </motion.div>\n </AnimatePresence>\n </motion.div>\n )\n}\n\nexport interface TabsContentProps extends ComponentPropsWithoutRef<'div'> {\n value: string\n forceMount?: boolean\n}\n\nexport const TabsContent = function TabsContent({\n ref,\n className,\n value: contentValue,\n forceMount = false,\n ...props\n}: TabsContentProps & {\n ref?: Ref<HTMLElement>\n}) {\n const { value, baseId } = useTabsContext('TabsContent')\n const contentId = `${baseId}-content-${contentValue}`\n const triggerId = `${baseId}-trigger-${contentValue}`\n const isActive = value === contentValue\n\n if (!forceMount && !isActive) {\n return null\n }\n\n return (\n <div\n aria-labelledby={triggerId}\n className={cn('tabs-content focus:outline-none focus-visible:outline-none', className)}\n data-state={isActive ? 'active' : 'inactive'}\n data-testid='spectral-tabs-content'\n hidden={!isActive}\n id={contentId}\n ref={ref as Ref<HTMLDivElement>}\n role='tabpanel'\n tabIndex={0}\n {...props}\n />\n )\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","names":[],"sources":["../src/components/Tabs/Tabs.tsx"],"mappings":";;;;;;UAKiB,QAAA;EACf,QAAA,EAAU,SAAA;EACV,QAAA;EACA,GAAA;EACA,KAAA,EAAO,SAAA;EACP,YAAA;EACA,kBAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,IAAA,CAAK,aAAA;EACtC,cAAA;EACA,SAAA;EACA,SAAA;EARO;EAUP,WAAA;EACA,cAAA,IAAkB,QAAA,UAAkB,QAAA,uBAA+B,OAAA;EACnE,OAAA,KAAY,KAAA,EAAO,KAAA;EACnB,OAAA;EACA,UAAA;EACA,SAAA,GAAY,SAAA;EACZ,SAAA,EAAW,QAAA;EAX2B;;;;;;EAkBtC,KAAA;EACA,OAAA;AAAA;AAAA,cAGW,IAAA;EAAI,cAAA;EAAA,SAAA;EAAA,SAAA;EAAA,WAAA;EAAA,OAAA;EAAA,cAAA;EAAA,OAAA;EAAA,aAAA;EAAA,UAAA;EAAA,WAAA;EAAA,SAAA;EAAA,SAAA;EAAA,KAAA,EAAA,eAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAgBd,SAAA,KAAS,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,KAmIA,OAAA,WAAkB,QAAA,MAAc,CAAA;AAAA,KAChC,eAAA,wBAAuC,QAAA;EAAa,GAAA,EAAK,IAAA;AAAA"}
1
+ {"version":3,"file":"Tabs.d.ts","names":[],"sources":["../src/components/Tabs/Tabs.tsx"],"mappings":";;;;;;UAKiB,QAAA;EACf,QAAA,EAAU,SAAA;EACV,QAAA;EACA,GAAA;EACA,KAAA,EAAO,SAAA;EACP,YAAA;EACA,kBAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,IAAA,CAAK,aAAA;EACtC,cAAA;EACA,SAAA;EACA,SAAA;EARO;EAUP,WAAA;EACA,cAAA,IAAkB,QAAA,UAAkB,QAAA,uBAA+B,OAAA;EACnE,OAAA,KAAY,KAAA,EAAO,KAAA;EACnB,OAAA;EACA,UAAA;EACA,SAAA,GAAY,SAAA;EACZ,SAAA,EAAW,QAAA;EAX2B;;;;;;EAkBtC,KAAA;EACA,OAAA;AAAA;AAAA,cAGW,IAAA;EAAI,cAAA;EAAA,SAAA;EAAA,SAAA;EAAA,WAAA;EAAA,OAAA;EAAA,cAAA;EAAA,OAAA;EAAA,aAAA;EAAA,UAAA;EAAA,WAAA;EAAA,SAAA;EAAA,SAAA;EAAA,KAAA,EAAA,eAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAgBd,SAAA,KAAS,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,KAmJA,OAAA,WAAkB,QAAA,MAAc,CAAA;AAAA,KAChC,eAAA,wBAAuC,QAAA;EAAa,GAAA,EAAK,IAAA;AAAA"}