@spear-ai/spectral 1.14.3 → 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.
- package/dist/Accordion.d.ts.map +1 -1
- package/dist/Accordion.js.map +1 -1
- package/dist/Alert/AlertBase.d.ts.map +1 -1
- package/dist/Alert/AlertBase.js.map +1 -1
- package/dist/Alert.js.map +1 -1
- package/dist/Avatar.js.map +1 -1
- package/dist/Badge.d.ts.map +1 -1
- package/dist/Badge.js +3 -3
- package/dist/Badge.js.map +1 -1
- package/dist/Button.d.ts +0 -6
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +36 -51
- package/dist/Button.js.map +1 -1
- package/dist/ButtonGroup/ButtonGroupButton.js.map +1 -1
- package/dist/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup.js.map +1 -1
- package/dist/ButtonIcon.js.map +1 -1
- package/dist/Checkbox/CheckboxBase.js.map +1 -1
- package/dist/Checkbox.js +1 -1
- package/dist/Checkbox.js.map +1 -1
- package/dist/Combobox.js +1 -2
- package/dist/Combobox.js.map +1 -1
- package/dist/ControlGroup/ControlGroupSelect.d.ts +1 -1
- package/dist/ControlGroup/ControlGroupSelect.js +1 -1
- package/dist/ControlGroup/ControlGroupSelect.js.map +1 -1
- package/dist/ControlGroup.d.ts.map +1 -1
- package/dist/ControlGroup.js +1 -1
- package/dist/ControlGroup.js.map +1 -1
- package/dist/DataCard/Card.d.ts.map +1 -1
- package/dist/DataCard/Card.js.map +1 -1
- package/dist/DataCard.js.map +1 -1
- package/dist/DateTimePicker/Calendar.js.map +1 -1
- package/dist/DateTimePicker/DateTimeDisplayInput.js.map +1 -1
- package/dist/DateTimePicker/TimePeriodSelect.js.map +1 -1
- package/dist/DateTimePicker/TimePicker.js.map +1 -1
- package/dist/DateTimePicker.js +1 -1
- package/dist/DateTimePicker.js.map +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js.map +1 -1
- package/dist/Drawer.js.map +1 -1
- package/dist/DropdownMenu.js.map +1 -1
- package/dist/FormFieldMessage.d.ts.map +1 -1
- package/dist/FormFieldMessage.js +3 -3
- package/dist/FormFieldMessage.js.map +1 -1
- package/dist/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard.js.map +1 -1
- package/dist/Icons/AdjustmentsIcon.d.ts.map +1 -1
- package/dist/Icons/AdjustmentsIcon.js.map +1 -1
- package/dist/Icons/AnalyzeIcon.d.ts.map +1 -1
- package/dist/Icons/AnalyzeIcon.js.map +1 -1
- package/dist/Icons/AnnotationsIcon.d.ts.map +1 -1
- package/dist/Icons/AnnotationsIcon.js.map +1 -1
- package/dist/Icons/ApprovedIcon.d.ts.map +1 -1
- package/dist/Icons/ApprovedIcon.js.map +1 -1
- package/dist/Icons/ArrowDownIcon.d.ts.map +1 -1
- package/dist/Icons/ArrowDownIcon.js.map +1 -1
- package/dist/Icons/ArrowUpIcon.d.ts.map +1 -1
- package/dist/Icons/ArrowUpIcon.js.map +1 -1
- package/dist/Icons/BoxToolIcon.d.ts.map +1 -1
- package/dist/Icons/BoxToolIcon.js.map +1 -1
- package/dist/Icons/CalendarIcon.d.ts.map +1 -1
- package/dist/Icons/CalendarIcon.js.map +1 -1
- package/dist/Icons/CheckCircleIcon.d.ts.map +1 -1
- package/dist/Icons/CheckCircleIcon.js.map +1 -1
- package/dist/Icons/CheckSquareIcon.d.ts.map +1 -1
- package/dist/Icons/CheckSquareIcon.js.map +1 -1
- package/dist/Icons/CheckmarkIcon.d.ts.map +1 -1
- package/dist/Icons/CheckmarkIcon.js.map +1 -1
- package/dist/Icons/ChevronDownIcon.d.ts.map +1 -1
- package/dist/Icons/ChevronDownIcon.js.map +1 -1
- package/dist/Icons/ChevronUpIcon.d.ts.map +1 -1
- package/dist/Icons/ChevronUpIcon.js.map +1 -1
- package/dist/Icons/ClockIcon.d.ts.map +1 -1
- package/dist/Icons/ClockIcon.js.map +1 -1
- package/dist/Icons/CloseCircleIcon.d.ts.map +1 -1
- package/dist/Icons/CloseCircleIcon.js.map +1 -1
- package/dist/Icons/CloseIcon.d.ts.map +1 -1
- package/dist/Icons/CloseIcon.js.map +1 -1
- package/dist/Icons/Crosshairs2Icon.d.ts.map +1 -1
- package/dist/Icons/Crosshairs2Icon.js.map +1 -1
- package/dist/Icons/CrosshairsIcon.d.ts.map +1 -1
- package/dist/Icons/CrosshairsIcon.js.map +1 -1
- package/dist/Icons/DashboardIcon.d.ts.map +1 -1
- package/dist/Icons/DashboardIcon.js.map +1 -1
- package/dist/Icons/DatabaseIcon.d.ts.map +1 -1
- package/dist/Icons/DatabaseIcon.js.map +1 -1
- package/dist/Icons/DeleteIcon.d.ts.map +1 -1
- package/dist/Icons/DeleteIcon.js.map +1 -1
- package/dist/Icons/DurationIcon.d.ts.map +1 -1
- package/dist/Icons/DurationIcon.js.map +1 -1
- package/dist/Icons/EditIcon.d.ts.map +1 -1
- package/dist/Icons/EditIcon.js.map +1 -1
- package/dist/Icons/EmailIcon.d.ts.map +1 -1
- package/dist/Icons/EmailIcon.js.map +1 -1
- package/dist/Icons/EraserIcon.d.ts.map +1 -1
- package/dist/Icons/EraserIcon.js.map +1 -1
- package/dist/Icons/ErrorIcon.d.ts.map +1 -1
- package/dist/Icons/ErrorIcon.js.map +1 -1
- package/dist/Icons/EyeClosedIcon.d.ts.map +1 -1
- package/dist/Icons/EyeClosedIcon.js.map +1 -1
- package/dist/Icons/EyeClosedIcon2.d.ts.map +1 -1
- package/dist/Icons/EyeClosedIcon2.js.map +1 -1
- package/dist/Icons/EyeOpenIcon.d.ts.map +1 -1
- package/dist/Icons/EyeOpenIcon.js.map +1 -1
- package/dist/Icons/FileDownloadIcon.d.ts.map +1 -1
- package/dist/Icons/FileDownloadIcon.js.map +1 -1
- package/dist/Icons/GoToFirstIcon.d.ts.map +1 -1
- package/dist/Icons/GoToFirstIcon.js.map +1 -1
- package/dist/Icons/GoToLastIcon.d.ts.map +1 -1
- package/dist/Icons/GoToLastIcon.js.map +1 -1
- package/dist/Icons/HarmonicCursorsIcon.d.ts.map +1 -1
- package/dist/Icons/HarmonicCursorsIcon.js.map +1 -1
- package/dist/Icons/InfoIcon.d.ts.map +1 -1
- package/dist/Icons/InfoIcon.js.map +1 -1
- package/dist/Icons/KeyboardIcon.d.ts.map +1 -1
- package/dist/Icons/KeyboardIcon.js.map +1 -1
- package/dist/Icons/LabelIcon.d.ts.map +1 -1
- package/dist/Icons/LabelIcon.js.map +1 -1
- package/dist/Icons/LassoIcon.d.ts.map +1 -1
- package/dist/Icons/LassoIcon.js.map +1 -1
- package/dist/Icons/LineToolIcon.d.ts.map +1 -1
- package/dist/Icons/LineToolIcon.js.map +1 -1
- package/dist/Icons/LiveViewIcon.d.ts.map +1 -1
- package/dist/Icons/LiveViewIcon.js.map +1 -1
- package/dist/Icons/LoaderIcon.d.ts.map +1 -1
- package/dist/Icons/LoaderIcon.js.map +1 -1
- package/dist/Icons/LocationIcon.d.ts.map +1 -1
- package/dist/Icons/LocationIcon.js.map +1 -1
- package/dist/Icons/LogoutIcon.d.ts.map +1 -1
- package/dist/Icons/LogoutIcon.js.map +1 -1
- package/dist/Icons/MaximizeIcon.d.ts.map +1 -1
- package/dist/Icons/MaximizeIcon.js.map +1 -1
- package/dist/Icons/MeasureIcon.d.ts.map +1 -1
- package/dist/Icons/MeasureIcon.js.map +1 -1
- package/dist/Icons/MenuDotsIcon.d.ts.map +1 -1
- package/dist/Icons/MenuDotsIcon.js.map +1 -1
- package/dist/Icons/MenuIcon.d.ts.map +1 -1
- package/dist/Icons/MenuIcon.js.map +1 -1
- package/dist/Icons/MessagesIcon.d.ts.map +1 -1
- package/dist/Icons/MessagesIcon.js.map +1 -1
- package/dist/Icons/MetadataIcon.d.ts.map +1 -1
- package/dist/Icons/MetadataIcon.js.map +1 -1
- package/dist/Icons/MinimizeIcon.d.ts.map +1 -1
- package/dist/Icons/MinimizeIcon.js.map +1 -1
- package/dist/Icons/MinusIcon.d.ts.map +1 -1
- package/dist/Icons/MinusIcon.js.map +1 -1
- package/dist/Icons/OntologyIcon.d.ts.map +1 -1
- package/dist/Icons/OntologyIcon.js.map +1 -1
- package/dist/Icons/PanelIconClose.d.ts.map +1 -1
- package/dist/Icons/PanelIconClose.js.map +1 -1
- package/dist/Icons/PanelIconOpen.d.ts.map +1 -1
- package/dist/Icons/PanelIconOpen.js.map +1 -1
- package/dist/Icons/PauseIcon.d.ts.map +1 -1
- package/dist/Icons/PauseIcon.js.map +1 -1
- package/dist/Icons/PlayIcon.d.ts.map +1 -1
- package/dist/Icons/PlayIcon.js.map +1 -1
- package/dist/Icons/PlusIcon.d.ts.map +1 -1
- package/dist/Icons/PlusIcon.js.map +1 -1
- package/dist/Icons/PolygonIcon.d.ts.map +1 -1
- package/dist/Icons/PolygonIcon.js.map +1 -1
- package/dist/Icons/PrinterIcon.d.ts.map +1 -1
- package/dist/Icons/PrinterIcon.js.map +1 -1
- package/dist/Icons/ProgressCheckIcon.d.ts.map +1 -1
- package/dist/Icons/ProgressCheckIcon.js.map +1 -1
- package/dist/Icons/ResetIcon.d.ts.map +1 -1
- package/dist/Icons/ResetIcon.js.map +1 -1
- package/dist/Icons/ReviewedIcon.d.ts.map +1 -1
- package/dist/Icons/ReviewedIcon.js.map +1 -1
- package/dist/Icons/ScissorsIcon.d.ts.map +1 -1
- package/dist/Icons/ScissorsIcon.js.map +1 -1
- package/dist/Icons/SearchIcon.d.ts.map +1 -1
- package/dist/Icons/SearchIcon.js.map +1 -1
- package/dist/Icons/SettingsIcon.d.ts.map +1 -1
- package/dist/Icons/SettingsIcon.js.map +1 -1
- package/dist/Icons/SortAscendingIcon.d.ts.map +1 -1
- package/dist/Icons/SortAscendingIcon.js.map +1 -1
- package/dist/Icons/SortAtoZIcon.d.ts.map +1 -1
- package/dist/Icons/SortAtoZIcon.js.map +1 -1
- package/dist/Icons/SortDescendingIcon.d.ts.map +1 -1
- package/dist/Icons/SortDescendingIcon.js.map +1 -1
- package/dist/Icons/SortZtoAIcon.d.ts.map +1 -1
- package/dist/Icons/SortZtoAIcon.js.map +1 -1
- package/dist/Icons/SparklesIcon.d.ts.map +1 -1
- package/dist/Icons/SparklesIcon.js.map +1 -1
- package/dist/Icons/StackIcon.d.ts.map +1 -1
- package/dist/Icons/StackIcon.js.map +1 -1
- package/dist/Icons/StarIcon.d.ts.map +1 -1
- package/dist/Icons/StarIcon.js.map +1 -1
- package/dist/Icons/TrashIcon.d.ts.map +1 -1
- package/dist/Icons/TrashIcon.js.map +1 -1
- package/dist/Icons/UndoIcon.d.ts.map +1 -1
- package/dist/Icons/UndoIcon.js.map +1 -1
- package/dist/Icons/UploadIcon.d.ts.map +1 -1
- package/dist/Icons/UploadIcon.js.map +1 -1
- package/dist/Icons/User2Icon.d.ts.map +1 -1
- package/dist/Icons/User2Icon.js.map +1 -1
- package/dist/Icons/UserIcon.d.ts.map +1 -1
- package/dist/Icons/UserIcon.js.map +1 -1
- package/dist/Icons/WarningIcon.d.ts.map +1 -1
- package/dist/Icons/WarningIcon.js.map +1 -1
- package/dist/Icons/ZoomAllIcon.d.ts.map +1 -1
- package/dist/Icons/ZoomAllIcon.js.map +1 -1
- package/dist/Icons/ZoomXIcon.d.ts.map +1 -1
- package/dist/Icons/ZoomXIcon.js.map +1 -1
- package/dist/Icons/ZoomYIcon.d.ts.map +1 -1
- package/dist/Icons/ZoomYIcon.js.map +1 -1
- package/dist/IconsAnimated/PanelLeftCloseIcon.js.map +1 -1
- package/dist/IconsAnimated/PanelLeftOpenIcon.js.map +1 -1
- package/dist/Input.js +1 -1
- package/dist/Input.js.map +1 -1
- package/dist/InputNumeric.d.ts +4 -2
- package/dist/InputNumeric.d.ts.map +1 -1
- package/dist/InputNumeric.js +3 -7
- package/dist/InputNumeric.js.map +1 -1
- package/dist/InputOTP.d.ts.map +1 -1
- package/dist/InputOTP.js +1 -2
- package/dist/InputOTP.js.map +1 -1
- package/dist/Kbd.d.ts.map +1 -1
- package/dist/Kbd.js.map +1 -1
- package/dist/Label.js.map +1 -1
- package/dist/MultiSelect/MultiSelectBase.js +2 -2
- package/dist/MultiSelect/MultiSelectBase.js.map +1 -1
- package/dist/MultiSelect.js.map +1 -1
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js.map +1 -1
- package/dist/RadioButton.d.ts +6 -0
- package/dist/RadioButton.d.ts.map +1 -1
- package/dist/RadioButton.js +7 -2
- package/dist/RadioButton.js.map +1 -1
- package/dist/RadioButtonGroup/RadioButtonGroupBase.d.ts +15 -1
- package/dist/RadioButtonGroup/RadioButtonGroupBase.d.ts.map +1 -1
- package/dist/RadioButtonGroup/RadioButtonGroupBase.js +166 -15
- package/dist/RadioButtonGroup/RadioButtonGroupBase.js.map +1 -1
- package/dist/RadioButtonGroup.d.ts +4 -1
- package/dist/RadioButtonGroup.d.ts.map +1 -1
- package/dist/RadioButtonGroup.js.map +1 -1
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +1 -1
- package/dist/RadioGroup.js.map +1 -1
- package/dist/Select.js +1 -2
- package/dist/Select.js.map +1 -1
- package/dist/Skeleton.js.map +1 -1
- package/dist/Slider.js.map +1 -1
- package/dist/Switch/SwitchBase.d.ts.map +1 -1
- package/dist/Switch/SwitchBase.js.map +1 -1
- package/dist/Switch.js +1 -1
- package/dist/Switch.js.map +1 -1
- package/dist/Tabs/TabsBase.d.ts.map +1 -1
- package/dist/Tabs/TabsBase.js +1 -0
- package/dist/Tabs/TabsBase.js.map +1 -1
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js.map +1 -1
- package/dist/Textarea.d.ts +1 -1
- package/dist/Textarea.js +1 -1
- package/dist/Textarea.js.map +1 -1
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js.map +1 -1
- package/dist/Toggle/ToggleBase.js.map +1 -1
- package/dist/Toggle.d.ts +5 -6
- package/dist/Toggle.d.ts.map +1 -1
- package/dist/Toggle.js +4 -19
- package/dist/Toggle.js.map +1 -1
- package/dist/ToggleGroup/ToggleGroupBase.d.ts.map +1 -1
- package/dist/ToggleGroup/ToggleGroupBase.js.map +1 -1
- package/dist/ToggleGroup/ToggleGroupItem.d.ts +3 -2
- package/dist/ToggleGroup/ToggleGroupItem.d.ts.map +1 -1
- package/dist/ToggleGroup/ToggleGroupItem.js +3 -2
- package/dist/ToggleGroup/ToggleGroupItem.js.map +1 -1
- package/dist/ToggleGroup/ToggleGroupSplitMenuItem.d.ts.map +1 -1
- package/dist/ToggleGroup/ToggleGroupSplitMenuItem.js +3 -2
- package/dist/ToggleGroup/ToggleGroupSplitMenuItem.js.map +1 -1
- package/dist/ToggleGroup.d.ts +3 -2
- package/dist/ToggleGroup.d.ts.map +1 -1
- package/dist/ToggleGroup.js +1 -1
- package/dist/ToggleGroup.js.map +1 -1
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js.map +1 -1
- package/dist/Tray.d.ts.map +1 -1
- package/dist/Tray.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.context.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/styles/horizon/colors.css +9 -16
- package/dist/styles/spectral.css +2 -2
- package/dist/utils/activeColorStyle.d.ts +11 -0
- package/dist/utils/activeColorStyle.d.ts.map +1 -0
- package/dist/utils/activeColorStyle.js +41 -0
- package/dist/utils/activeColorStyle.js.map +1 -0
- package/package.json +25 -20
|
@@ -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
|
|
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"}
|
package/dist/Switch.js
CHANGED
|
@@ -10,7 +10,7 @@ import { CheckIcon, XIcon } from "lucide-react";
|
|
|
10
10
|
|
|
11
11
|
//#region src/components/Switch/Switch.tsx
|
|
12
12
|
const 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";
|
|
13
|
-
const Switch = ({ className, disabled, errorMessage, hideLabel = false, id, label, labelPosition = "right", labelText, messageReserveLines = 1, messageReserveSpace =
|
|
13
|
+
const Switch = ({ className, disabled, errorMessage, hideLabel = false, id, label, labelPosition = "right", labelText, messageReserveLines = 1, messageReserveSpace = false, name, onChange, ref, required, state = "default", value, variant, warningMessage, "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel, ...props }) => {
|
|
14
14
|
const switchId = useFormFieldId(id, name);
|
|
15
15
|
const isDisabled = Boolean(disabled);
|
|
16
16
|
const resolvedLabelText = labelText ?? label;
|
package/dist/Switch.js.map
CHANGED
|
@@ -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 = true,\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,MACtB,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,
|
|
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"}
|
package/dist/Tabs/TabsBase.js
CHANGED
|
@@ -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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"}
|
package/dist/Tabs.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/Tabs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.js","names":[],"sources":["../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ReactNode } from 'react'\nimport { TabsBase, TabsContent, TabsContentContainer, TabsList, TabsTrigger, type TabsBaseProps } from './TabsBase'\nimport { getTabKeys, validateTabValues } from './tabsUtils'\n\nexport interface TabValue {\n children: ReactNode\n disabled?: boolean | undefined\n key: string | undefined\n label: ReactNode\n 'aria-label'?: string | undefined\n 'aria-describedby'?: string | undefined\n}\n\nexport interface TabsProps extends Omit<TabsBaseProps, 'children' | 'defaultValue' | 'onError' | 'disabled' | 'value'> {\n activationMode?: 'automatic' | 'manual' | undefined\n ariaLabel?: string | undefined\n className?: string | undefined\n /** Hide the content panel, useful when managing content display externally */\n hideContent?: boolean | undefined\n onBeforeChange?: (newValue: string, oldValue: string) => boolean | Promise<boolean> | undefined\n onError?: ((error: Error) => void) | undefined\n loading?: boolean | undefined\n openOnLoad?: string | undefined\n rightSlot?: ReactNode | undefined\n tabValues: TabValue[] | undefined\n /**\n * Controlled value - the currently active tab key.\n * When provided, the component operates in controlled mode and the parent\n * must manage the active tab state via `onValueChange`.\n * Mutually exclusive with `openOnLoad` - use one or the other.\n */\n value?: string | undefined\n variant?: 'enclosed' | 'default'\n}\n\nexport const Tabs = ({\n activationMode = 'automatic',\n ariaLabel,\n className,\n hideContent = false,\n loading = false,\n onBeforeChange,\n onError,\n onValueChange,\n openOnLoad,\n orientation = 'horizontal',\n rightSlot,\n tabValues = [],\n value: controlledValue,\n variant = 'default',\n ...props\n}: TabsProps) => {\n if (loading) {\n return (\n <div className='p-4 relative flex w-full flex-col text-center text-text-secondary' role='status' aria-live='polite'>\n <p>Loading tabs…</p>\n </div>\n )\n }\n\n const validTabs = tabValues.filter((tab): tab is TabValue & { key: string } => tab.key !== undefined)\n const isControlled = controlledValue !== undefined\n\n if (!validateTabValues(validTabs as { key: string; label: unknown; children: unknown; [K: string]: unknown }[])) {\n const error = new Error('Invalid tabValues provided to Tabs component')\n onError?.(error)\n\n return (\n <div className='p-4 text-gray-500 relative flex w-full flex-col text-center' role='alert' aria-live='polite'>\n <p>No valid tabs provided</p>\n </div>\n )\n }\n\n const validKeys = getTabKeys(validTabs)\n\n // Compute effective value for controlled mode (fallback if invalid)\n let effectiveValue: string | undefined\n if (isControlled) {\n if (validKeys.includes(controlledValue)) {\n effectiveValue = controlledValue\n } else {\n console.warn(`Tabs: value '${controlledValue}' is not a valid tab key, falling back to first tab`)\n effectiveValue = validKeys[0]\n }\n }\n\n // For uncontrolled mode, determine the default value\n let defaultValue: string | undefined\n if (!isControlled) {\n defaultValue = openOnLoad ?? validKeys[0]\n\n if (openOnLoad && !validKeys.includes(openOnLoad)) {\n console.warn(`Tabs: openOnLoad value '${openOnLoad}' is not a valid tab key`)\n defaultValue = validKeys[0]\n }\n\n if (!defaultValue) {\n const error = new Error('No valid default tab available')\n onError?.(error)\n return (\n <div className='p-4 relative flex w-full flex-col text-center text-text-secondary' role='alert' aria-live='polite'>\n <p>Unable to render tabs</p>\n </div>\n )\n }\n }\n\n const handleValueChange = async (newValue: string) => {\n if (onBeforeChange && onValueChange) {\n const currentValue = isControlled ? (effectiveValue ?? '') : (defaultValue ?? '')\n try {\n const canChange = await onBeforeChange(newValue, currentValue)\n if (canChange === false) return\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error('Before change callback failed'))\n return\n }\n }\n\n onValueChange?.(newValue)\n }\n\n return (\n <div className='relative flex w-full flex-col'>\n <TabsBase\n aria-label={ariaLabel}\n className={cn('relative w-full data-[orientation=vertical]:flex', variant, className)}\n {...(isControlled ? { value: effectiveValue } : { defaultValue })}\n orientation={orientation}\n activationMode={activationMode}\n onValueChange={handleValueChange}\n {...props}\n >\n <TabsList\n className={cn(\n 'inline-flex w-full items-center justify-between',\n orientation === 'horizontal' && variant === 'default' && 'border-b border-tabs-border',\n orientation === 'vertical' && variant === 'default' && 'm-0 py-1 relative h-auto w-auto flex-col items-stretch border-r border-tabs-border',\n orientation === 'horizontal' && variant === 'enclosed' && 'rounded-lg p-1 relative border-0 bg-tabs-group-bg',\n orientation === 'vertical' && variant === 'enclosed' && 'rounded-lg p-1 w-auto flex-col border-0 bg-tabs-group-bg',\n )}\n rightSlot={rightSlot}\n >\n {validTabs.map((tab) => (\n <TabsTrigger\n key={tab.key}\n value={tab.key}\n disabled={tab.disabled}\n aria-label={tab['aria-label']}\n aria-describedby={tab['aria-describedby']}\n className={cn(\n 'font-semibold relative whitespace-nowrap transition-all duration-500 ease-in-out focus:outline-none focus-visible:outline-none',\n orientation === 'horizontal' && variant === 'default' && 'py-2 px-4 hover:bg-tabs-bg--hover text-text-primary hover:text-accent',\n orientation === 'vertical' && variant === 'default' && 'h-10 px-4 py-2 hover:bg-tabs-bg--hover flex items-center text-text-primary hover:text-accent data-[state=active]:text-accent',\n orientation === 'horizontal' && variant === 'enclosed' && 'px-4 py-2 hover:bg-tabs-bg--hover z-[1] inline-flex items-center justify-center text-text-primary hover:text-accent data-[state=active]:text-accent',\n orientation === 'vertical' && variant === 'enclosed' && 'px-4 py-2 hover:bg-tabs-bg--hover z-1 text-text-primary hover:text-accent data-[state=active]:text-accent',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent disabled:hover:text-text-primary',\n )}\n >\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {!hideContent && (\n <TabsContentContainer className={cn(orientation === 'vertical' && 'flex-1')}>\n {validTabs.map((tab) => (\n <TabsContent key={tab.key} value={tab.key} className={cn('text-text-primary focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent', orientation === 'horizontal' && 'pb-4', orientation === 'vertical' && 'py-2 px-4')}>\n {tab.children}\n </TabsContent>\n ))}\n </TabsContentContainer>\n )}\n </TabsBase>\n </div>\n )\n}\n\nexport { TabsContent, TabsContentContainer, TabsList, TabsBase as TabsRoot, TabsTrigger }\n\nexport type { TabsBaseProps, TabsContentContainerProps, TabsContentProps, TabsListProps, TabsTriggerProps } from './TabsBase'\n\nexport type TabKeys<T extends TabValue[]> = T[number]['key']\nexport type TabValueWithKey<TKey extends string> = TabValue & { key: TKey }\n"],"mappings":";;;;;;;;AAoCA,MAAa,QAAQ,EACnB,iBAAiB,aACjB,WACA,WACA,cAAc,OACd,UAAU,OACV,gBACA,SACA,eACA,YACA,cAAc,cACd,WACA,YAAY,EAAE,EACd,OAAO,iBACP,UAAU,WACV,GAAG,YACY;AACf,KAAI,QACF,QACE,oBAAC,OAAD;EAAK,WAAU;EAAoE,MAAK;EAAS,aAAU;YACzG,oBAAC,KAAD,YAAG,iBAAiB;EAChB;CAIV,MAAM,YAAY,UAAU,QAAQ,QAA2C,IAAI,QAAQ,OAAU;CACrG,MAAM,eAAe,oBAAoB;AAEzC,KAAI,CAAC,kBAAkB,UAAwF,EAAE;AAE/G,4BAAU,IADQ,MAAM,+CACT,CAAC;AAEhB,SACE,oBAAC,OAAD;GAAK,WAAU;GAA8D,MAAK;GAAQ,aAAU;aAClG,oBAAC,KAAD,YAAG,0BAA0B;GACzB;;CAIV,MAAM,YAAY,WAAW,UAAU;CAGvC,IAAI;AACJ,KAAI,aACF,KAAI,UAAU,SAAS,gBAAgB,CACrC,kBAAiB;MACZ;AACL,UAAQ,KAAK,gBAAgB,gBAAgB,qDAAqD;AAClG,mBAAiB,UAAU;;CAK/B,IAAI;AACJ,KAAI,CAAC,cAAc;AACjB,iBAAe,cAAc,UAAU;AAEvC,MAAI,cAAc,CAAC,UAAU,SAAS,WAAW,EAAE;AACjD,WAAQ,KAAK,2BAA2B,WAAW,0BAA0B;AAC7E,kBAAe,UAAU;;AAG3B,MAAI,CAAC,cAAc;AAEjB,6BAAU,IADQ,MAAM,iCACT,CAAC;AAChB,UACE,oBAAC,OAAD;IAAK,WAAU;IAAoE,MAAK;IAAQ,aAAU;cACxG,oBAAC,KAAD,YAAG,yBAAyB;IACxB;;;CAKZ,MAAM,oBAAoB,OAAO,aAAqB;AACpD,MAAI,kBAAkB,eAAe;GACnC,MAAM,eAAe,eAAgB,kBAAkB,KAAO,gBAAgB;AAC9E,OAAI;AAEF,QAAI,MADoB,eAAe,UAAU,aAAa,KAC5C,MAAO;YAClB,OAAO;AACd,cAAU,iBAAiB,QAAQ,wBAAQ,IAAI,MAAM,gCAAgC,CAAC;AACtF;;;AAIJ,kBAAgB,SAAS;;AAG3B,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,qBAAC,UAAD;GACE,cAAY;GACZ,WAAW,GAAG,oDAAoD,SAAS,UAAU;GACrF,GAAK,eAAe,EAAE,OAAO,gBAAgB,GAAG,EAAE,cAAc;GACnD;GACG;GAChB,eAAe;GACf,GAAI;aAPN,CASE,oBAAC,UAAD;IACE,WAAW,GACT,mDACA,gBAAgB,gBAAgB,YAAY,aAAa,+BACzD,gBAAgB,cAAc,YAAY,aAAa,sFACvD,gBAAgB,gBAAgB,YAAY,cAAc,qDAC1D,gBAAgB,cAAc,YAAY,cAAc,2DACzD;IACU;cAEV,UAAU,KAAK,QACd,oBAAC,aAAD;KAEE,OAAO,IAAI;KACX,UAAU,IAAI;KACd,cAAY,IAAI;KAChB,oBAAkB,IAAI;KACtB,WAAW,GACT,kIACA,gBAAgB,gBAAgB,YAAY,aAAa,yEACzD,gBAAgB,cAAc,YAAY,aAAa,gIACvD,gBAAgB,gBAAgB,YAAY,cAAc,uJAC1D,gBAAgB,cAAc,YAAY,cAAc,6GACxD,iHACD;eAEA,IAAI;KACO,EAfP,IAAI,IAeG,CACd;IACO,GACV,CAAC,eACA,oBAAC,sBAAD;IAAsB,WAAW,GAAG,gBAAgB,cAAc,SAAS;cACxE,UAAU,KAAK,QACd,oBAAC,aAAD;KAA2B,OAAO,IAAI;KAAK,WAAW,GAAG,4HAA4H,gBAAgB,gBAAgB,QAAQ,gBAAgB,cAAc,YAAY;eACpQ,IAAI;KACO,EAFI,IAAI,IAER,CACd;IACmB,EAEhB;;EACP"}
|
|
1
|
+
{"version":3,"file":"Tabs.js","names":[],"sources":["../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ReactNode } from 'react'\nimport { TabsBase, TabsContent, TabsContentContainer, TabsList, TabsTrigger, type TabsBaseProps } from './TabsBase'\nimport { getTabKeys, validateTabValues } from './tabsUtils'\n\nexport interface TabValue {\n children: ReactNode\n disabled?: boolean | undefined\n key: string | undefined\n label: ReactNode\n 'aria-label'?: string | undefined\n 'aria-describedby'?: string | undefined\n}\n\nexport interface TabsProps extends Omit<TabsBaseProps, 'children' | 'defaultValue' | 'onError' | 'disabled' | 'value'> {\n activationMode?: 'automatic' | 'manual' | undefined\n ariaLabel?: string | undefined\n className?: string | undefined\n /** Hide the content panel, useful when managing content display externally */\n hideContent?: boolean | undefined\n onBeforeChange?: (newValue: string, oldValue: string) => boolean | Promise<boolean> | undefined\n onError?: ((error: Error) => void) | undefined\n loading?: boolean | undefined\n openOnLoad?: string | undefined\n rightSlot?: ReactNode | undefined\n tabValues: TabValue[] | undefined\n /**\n * Controlled value - the currently active tab key.\n * When provided, the component operates in controlled mode and the parent\n * must manage the active tab state via `onValueChange`.\n * Mutually exclusive with `openOnLoad` - use one or the other.\n */\n value?: string | undefined\n variant?: 'enclosed' | 'default'\n}\n\nexport const Tabs = ({\n activationMode = 'automatic',\n ariaLabel,\n className,\n hideContent = false,\n loading = false,\n onBeforeChange,\n onError,\n onValueChange,\n openOnLoad,\n orientation = 'horizontal',\n rightSlot,\n tabValues = [],\n value: controlledValue,\n variant = 'default',\n ...props\n}: TabsProps) => {\n if (loading) {\n return (\n <div\n className='p-4 relative flex w-full flex-col text-center text-text-secondary'\n role='status'\n aria-live='polite'\n >\n <p>Loading tabs…</p>\n </div>\n )\n }\n\n const validTabs = tabValues.filter((tab): tab is TabValue & { key: string } => tab.key !== undefined)\n const isControlled = controlledValue !== undefined\n\n if (!validateTabValues(validTabs as { key: string; label: unknown; children: unknown; [K: string]: unknown }[])) {\n const error = new Error('Invalid tabValues provided to Tabs component')\n onError?.(error)\n\n return (\n <div\n className='p-4 text-gray-500 relative flex w-full flex-col text-center'\n role='alert'\n aria-live='polite'\n >\n <p>No valid tabs provided</p>\n </div>\n )\n }\n\n const validKeys = getTabKeys(validTabs)\n\n // Compute effective value for controlled mode (fallback if invalid)\n let effectiveValue: string | undefined\n if (isControlled) {\n if (validKeys.includes(controlledValue)) {\n effectiveValue = controlledValue\n } else {\n console.warn(`Tabs: value '${controlledValue}' is not a valid tab key, falling back to first tab`)\n effectiveValue = validKeys[0]\n }\n }\n\n // For uncontrolled mode, determine the default value\n let defaultValue: string | undefined\n if (!isControlled) {\n defaultValue = openOnLoad ?? validKeys[0]\n\n if (openOnLoad && !validKeys.includes(openOnLoad)) {\n console.warn(`Tabs: openOnLoad value '${openOnLoad}' is not a valid tab key`)\n defaultValue = validKeys[0]\n }\n\n if (!defaultValue) {\n const error = new Error('No valid default tab available')\n onError?.(error)\n return (\n <div\n className='p-4 relative flex w-full flex-col text-center text-text-secondary'\n role='alert'\n aria-live='polite'\n >\n <p>Unable to render tabs</p>\n </div>\n )\n }\n }\n\n const handleValueChange = async (newValue: string) => {\n if (onBeforeChange && onValueChange) {\n const currentValue = isControlled ? (effectiveValue ?? '') : (defaultValue ?? '')\n try {\n const canChange = await onBeforeChange(newValue, currentValue)\n if (canChange === false) return\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error('Before change callback failed'))\n return\n }\n }\n\n onValueChange?.(newValue)\n }\n\n return (\n <div className='relative flex w-full flex-col'>\n <TabsBase\n aria-label={ariaLabel}\n className={cn('relative w-full data-[orientation=vertical]:flex', variant, className)}\n {...(isControlled ? { value: effectiveValue } : { defaultValue })}\n orientation={orientation}\n activationMode={activationMode}\n onValueChange={handleValueChange}\n {...props}\n >\n <TabsList\n className={cn(\n 'inline-flex w-full items-center justify-between',\n orientation === 'horizontal' && variant === 'default' && 'border-b border-tabs-border',\n orientation === 'vertical' && variant === 'default' && 'm-0 py-1 relative h-auto w-auto flex-col items-stretch border-r border-tabs-border',\n orientation === 'horizontal' && variant === 'enclosed' && 'rounded-lg p-1 relative border-0 bg-tabs-group-bg',\n orientation === 'vertical' && variant === 'enclosed' && 'rounded-lg p-1 w-auto flex-col border-0 bg-tabs-group-bg',\n )}\n rightSlot={rightSlot}\n >\n {validTabs.map((tab) => (\n <TabsTrigger\n key={tab.key}\n value={tab.key}\n disabled={tab.disabled}\n aria-label={tab['aria-label']}\n aria-describedby={tab['aria-describedby']}\n className={cn(\n 'font-semibold relative whitespace-nowrap transition-all duration-500 ease-in-out focus:outline-none focus-visible:outline-none',\n orientation === 'horizontal' && variant === 'default' && 'py-2 px-4 hover:bg-tabs-bg--hover text-text-primary hover:text-accent',\n orientation === 'vertical' && variant === 'default' && 'h-10 px-4 py-2 hover:bg-tabs-bg--hover flex items-center text-text-primary hover:text-accent data-[state=active]:text-accent',\n orientation === 'horizontal' && variant === 'enclosed' && 'px-4 py-2 hover:bg-tabs-bg--hover z-[1] inline-flex items-center justify-center text-text-primary hover:text-accent data-[state=active]:text-accent',\n orientation === 'vertical' && variant === 'enclosed' && 'px-4 py-2 hover:bg-tabs-bg--hover z-1 text-text-primary hover:text-accent data-[state=active]:text-accent',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent disabled:hover:text-text-primary',\n )}\n >\n {tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {!hideContent && (\n <TabsContentContainer className={cn(orientation === 'vertical' && 'flex-1')}>\n {validTabs.map((tab) => (\n <TabsContent\n key={tab.key}\n value={tab.key}\n className={cn('text-text-primary focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent', orientation === 'horizontal' && 'pb-4', orientation === 'vertical' && 'py-2 px-4')}\n >\n {tab.children}\n </TabsContent>\n ))}\n </TabsContentContainer>\n )}\n </TabsBase>\n </div>\n )\n}\n\nexport { TabsContent, TabsContentContainer, TabsList, TabsBase as TabsRoot, TabsTrigger }\n\nexport type { TabsBaseProps, TabsContentContainerProps, TabsContentProps, TabsListProps, TabsTriggerProps } from './TabsBase'\n\nexport type TabKeys<T extends TabValue[]> = T[number]['key']\nexport type TabValueWithKey<TKey extends string> = TabValue & { key: TKey }\n"],"mappings":";;;;;;;;AAoCA,MAAa,QAAQ,EACnB,iBAAiB,aACjB,WACA,WACA,cAAc,OACd,UAAU,OACV,gBACA,SACA,eACA,YACA,cAAc,cACd,WACA,YAAY,EAAE,EACd,OAAO,iBACP,UAAU,WACV,GAAG,YACY;AACf,KAAI,QACF,QACE,oBAAC,OAAD;EACE,WAAU;EACV,MAAK;EACL,aAAU;YAEV,oBAAC,KAAD,YAAG,iBAAiB;EAChB;CAIV,MAAM,YAAY,UAAU,QAAQ,QAA2C,IAAI,QAAQ,OAAU;CACrG,MAAM,eAAe,oBAAoB;AAEzC,KAAI,CAAC,kBAAkB,UAAwF,EAAE;AAE/G,4BAAU,IADQ,MAAM,+CACT,CAAC;AAEhB,SACE,oBAAC,OAAD;GACE,WAAU;GACV,MAAK;GACL,aAAU;aAEV,oBAAC,KAAD,YAAG,0BAA0B;GACzB;;CAIV,MAAM,YAAY,WAAW,UAAU;CAGvC,IAAI;AACJ,KAAI,aACF,KAAI,UAAU,SAAS,gBAAgB,CACrC,kBAAiB;MACZ;AACL,UAAQ,KAAK,gBAAgB,gBAAgB,qDAAqD;AAClG,mBAAiB,UAAU;;CAK/B,IAAI;AACJ,KAAI,CAAC,cAAc;AACjB,iBAAe,cAAc,UAAU;AAEvC,MAAI,cAAc,CAAC,UAAU,SAAS,WAAW,EAAE;AACjD,WAAQ,KAAK,2BAA2B,WAAW,0BAA0B;AAC7E,kBAAe,UAAU;;AAG3B,MAAI,CAAC,cAAc;AAEjB,6BAAU,IADQ,MAAM,iCACT,CAAC;AAChB,UACE,oBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,aAAU;cAEV,oBAAC,KAAD,YAAG,yBAAyB;IACxB;;;CAKZ,MAAM,oBAAoB,OAAO,aAAqB;AACpD,MAAI,kBAAkB,eAAe;GACnC,MAAM,eAAe,eAAgB,kBAAkB,KAAO,gBAAgB;AAC9E,OAAI;AAEF,QAAI,MADoB,eAAe,UAAU,aAAa,KAC5C,MAAO;YAClB,OAAO;AACd,cAAU,iBAAiB,QAAQ,wBAAQ,IAAI,MAAM,gCAAgC,CAAC;AACtF;;;AAIJ,kBAAgB,SAAS;;AAG3B,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,qBAAC,UAAD;GACE,cAAY;GACZ,WAAW,GAAG,oDAAoD,SAAS,UAAU;GACrF,GAAK,eAAe,EAAE,OAAO,gBAAgB,GAAG,EAAE,cAAc;GACnD;GACG;GAChB,eAAe;GACf,GAAI;aAPN,CASE,oBAAC,UAAD;IACE,WAAW,GACT,mDACA,gBAAgB,gBAAgB,YAAY,aAAa,+BACzD,gBAAgB,cAAc,YAAY,aAAa,sFACvD,gBAAgB,gBAAgB,YAAY,cAAc,qDAC1D,gBAAgB,cAAc,YAAY,cAAc,2DACzD;IACU;cAEV,UAAU,KAAK,QACd,oBAAC,aAAD;KAEE,OAAO,IAAI;KACX,UAAU,IAAI;KACd,cAAY,IAAI;KAChB,oBAAkB,IAAI;KACtB,WAAW,GACT,kIACA,gBAAgB,gBAAgB,YAAY,aAAa,yEACzD,gBAAgB,cAAc,YAAY,aAAa,gIACvD,gBAAgB,gBAAgB,YAAY,cAAc,uJAC1D,gBAAgB,cAAc,YAAY,cAAc,6GACxD,iHACD;eAEA,IAAI;KACO,EAfP,IAAI,IAeG,CACd;IACO,GACV,CAAC,eACA,oBAAC,sBAAD;IAAsB,WAAW,GAAG,gBAAgB,cAAc,SAAS;cACxE,UAAU,KAAK,QACd,oBAAC,aAAD;KAEE,OAAO,IAAI;KACX,WAAW,GAAG,4HAA4H,gBAAgB,gBAAgB,QAAQ,gBAAgB,cAAc,YAAY;eAE3N,IAAI;KACO,EALP,IAAI,IAKG,CACd;IACmB,EAEhB;;EACP"}
|
package/dist/Textarea.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ type TextareaProps = Omit<ComponentProps<'textarea'>, 'onChange'> & {
|
|
|
12
12
|
label: string;
|
|
13
13
|
labelClassName?: string;
|
|
14
14
|
maxLength?: number | undefined; /** Number of message lines to reserve (default: 1). */
|
|
15
|
-
messageReserveLines?: number; /** Whether to keep message space reserved when hidden (default:
|
|
15
|
+
messageReserveLines?: number; /** Whether to keep message space reserved when hidden (default: false). */
|
|
16
16
|
messageReserveSpace?: boolean;
|
|
17
17
|
name: string;
|
|
18
18
|
onBlur?: (e: FocusEvent<HTMLTextAreaElement>) => void;
|
package/dist/Textarea.js
CHANGED
|
@@ -19,7 +19,7 @@ const getCounterClasses = (currentLength, maxLength) => {
|
|
|
19
19
|
return cn("absolute bottom-2 right-3 text-xs pointer-events-none z-10 tabular-nums", currentLength >= maxLength ? "text-danger-400" : "text-text-secondary");
|
|
20
20
|
};
|
|
21
21
|
const Textarea = (allProps) => {
|
|
22
|
-
const { ref, autoComplete, className, defaultValue, disabled, errorMessage, id, label, labelClassName, maxLength = 280, messageReserveLines = 1, messageReserveSpace =
|
|
22
|
+
const { ref, autoComplete, className, defaultValue, disabled, errorMessage, id, label, labelClassName, maxLength = 280, messageReserveLines = 1, messageReserveSpace = false, name, onBlur, onChange, onFocus, placeholder, required, state = "default", value: valueProp, warningMessage, ...props } = allProps;
|
|
23
23
|
const textareaId = useFormFieldId(id, name);
|
|
24
24
|
const errorMessageId = getErrorMessageId(textareaId);
|
|
25
25
|
const warningMessageId = `${textareaId}-warning`;
|
package/dist/Textarea.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Textarea.js","names":[],"sources":["../src/components/Textarea/Textarea.tsx"],"sourcesContent":["import { LoaderIcon } from '@components/Icons'\nimport { Label } from '@components/Label/Label'\nimport { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { ErrorMessage, getAriaProps, getErrorMessageId, getTextareaClasses, useFormFieldId, useFormFieldState, WarningMessage, type BaseFormFieldProps, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { useRef, type ComponentProps, type CSSProperties, type FocusEvent, type Ref } from 'react'\nimport { useTextarea } from './TextareaUtils'\n\nexport type TextareaState = FormFieldState\n\ntype AutoCompleteValue = 'on' | 'off' | 'name' | 'email' | 'username' | 'street-address' | (string & {})\n\nexport type TextareaProps = Omit<ComponentProps<'textarea'>, 'onChange'> & {\n className?: string | undefined\n errorMessage?: BaseFormFieldProps['errorMessage']\n id?: string | undefined\n label: string\n labelClassName?: string\n maxLength?: number | undefined\n /** Number of message lines to reserve (default: 1). */\n messageReserveLines?: number\n /** Whether to keep message space reserved when hidden (default:
|
|
1
|
+
{"version":3,"file":"Textarea.js","names":[],"sources":["../src/components/Textarea/Textarea.tsx"],"sourcesContent":["import { LoaderIcon } from '@components/Icons'\nimport { Label } from '@components/Label/Label'\nimport { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { ErrorMessage, getAriaProps, getErrorMessageId, getTextareaClasses, useFormFieldId, useFormFieldState, WarningMessage, type BaseFormFieldProps, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { useRef, type ComponentProps, type CSSProperties, type FocusEvent, type Ref } from 'react'\nimport { useTextarea } from './TextareaUtils'\n\nexport type TextareaState = FormFieldState\n\ntype AutoCompleteValue = 'on' | 'off' | 'name' | 'email' | 'username' | 'street-address' | (string & {})\n\nexport type TextareaProps = Omit<ComponentProps<'textarea'>, 'onChange'> & {\n className?: string | undefined\n errorMessage?: BaseFormFieldProps['errorMessage']\n id?: string | undefined\n label: string\n labelClassName?: string\n maxLength?: number | undefined\n /** Number of message lines to reserve (default: 1). */\n messageReserveLines?: number\n /** Whether to keep message space reserved when hidden (default: false). */\n messageReserveSpace?: boolean\n name: string\n onBlur?: (e: FocusEvent<HTMLTextAreaElement>) => void\n onChange?: (value: string) => void\n onFocus?: (e: FocusEvent<HTMLTextAreaElement>) => void\n placeholder?: string | undefined\n required?: boolean\n state?: TextareaState\n value?: string | undefined\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nconst LOADING_ICON_CLASSES = 'absolute right-4 top-4'\n\nconst getAutoCompleteValue = (autoComplete?: string): AutoCompleteValue => {\n if (autoComplete) return autoComplete\n return 'off'\n}\n\nconst getCounterClasses = (currentLength: number, maxLength: number): string => {\n const baseClasses = 'absolute bottom-2 right-3 text-xs pointer-events-none z-10 tabular-nums'\n const colorClass = currentLength >= maxLength ? 'text-danger-400' : 'text-text-secondary'\n return cn(baseClasses, colorClass)\n}\n\nexport const Textarea = (\n allProps: TextareaProps & {\n ref?: Ref<HTMLTextAreaElement>\n },\n) => {\n const {\n ref,\n autoComplete,\n className,\n defaultValue,\n disabled,\n errorMessage,\n id,\n label,\n labelClassName,\n maxLength = 280,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onBlur,\n onChange,\n onFocus,\n placeholder,\n required,\n state = 'default',\n value: valueProp,\n warningMessage,\n ...props\n } = allProps\n const textareaId = useFormFieldId(id, name)\n const errorMessageId = getErrorMessageId(textareaId)\n const warningMessageId = `${textareaId}-warning`\n const messageId = state === 'error' ? errorMessageId : state === 'warning' && warningMessage ? warningMessageId : undefined\n const internalRef = useRef<HTMLTextAreaElement>(null)\n const textareaRef = ref ?? internalRef\n const normalizedDefaultValue = typeof defaultValue === 'string' ? defaultValue : defaultValue !== undefined && defaultValue !== null ? String(defaultValue) : ''\n const [value, setValue] = useUncontrolledState<string>({\n value: valueProp,\n defaultValue: normalizedDefaultValue,\n onChange,\n })\n\n const { handleFocus, handleBlur, handleChange, handlePaste } = useTextarea({\n maxLength,\n value,\n onChange: setValue,\n onFocus,\n onBlur,\n })\n\n const { isDisabled, isLoading } = useFormFieldState(disabled, state)\n const ariaProps = getAriaProps(state, props['aria-describedby'], required, messageId)\n const currentLength = value?.length || 0\n const textareaClasses = getTextareaClasses(state, className)\n\n const getCSSCustomProperties = () => ({\n '--textarea-min-height': '6rem',\n '--textarea-max-height': '12rem',\n '--textarea-border-radius': '0.5rem',\n })\n\n return (\n <div className='w-full'>\n {label && (\n <Label\n data-testid='spectral-textarea-label'\n htmlFor={textareaId}\n className={cn('mb-2 block', isDisabled && 'cursor-not-allowed opacity-50', labelClassName)}\n >\n {label}\n </Label>\n )}\n <div className='relative'>\n <textarea\n aria-multiline='true'\n autoComplete={getAutoCompleteValue(autoComplete)}\n className={textareaClasses}\n data-state={state}\n data-testid='spectral-textarea'\n disabled={isDisabled}\n id={textareaId}\n name={name}\n onBlur={handleBlur}\n onChange={handleChange}\n onFocus={handleFocus}\n onPaste={handlePaste}\n placeholder={placeholder}\n ref={textareaRef}\n required={required}\n spellCheck='true'\n style={getCSSCustomProperties() as CSSProperties}\n value={value}\n {...ariaProps}\n {...props}\n />\n\n {isLoading && (\n <div\n className={LOADING_ICON_CLASSES}\n data-testid='spectral-textarea-loading-icon'\n >\n <LoaderIcon size={24} />\n </div>\n )}\n\n <div\n // oxlint will throw an error when passing ternaries in for aria-label\n aria-label={currentLength + ' of ' + maxLength + ' characters used'}\n aria-live='polite'\n className={getCounterClasses(currentLength, maxLength)}\n data-testid='spectral-textarea-counter'\n role='status'\n >\n {currentLength}/{maxLength}\n </div>\n </div>\n\n <ErrorMessage\n dataTestId='spectral-textarea-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-textarea-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? warningMessage : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'warning'}\n />\n </div>\n )\n}\nTextarea.displayName = 'Textarea'\n"],"mappings":";;;;;;;;;;;;AAkCA,MAAM,uBAAuB;AAE7B,MAAM,wBAAwB,iBAA6C;AACzE,KAAI,aAAc,QAAO;AACzB,QAAO;;AAGT,MAAM,qBAAqB,eAAuB,cAA8B;AAG9E,QAAO,GAAG,2EADS,iBAAiB,YAAY,oBAAoB,sBAClC;;AAGpC,MAAa,YACX,aAGG;CACH,MAAM,EACJ,KACA,cACA,WACA,cACA,UACA,cACA,IACA,OACA,gBACA,YAAY,KACZ,sBAAsB,GACtB,sBAAsB,OACtB,MACA,QACA,UACA,SACA,aACA,UACA,QAAQ,WACR,OAAO,WACP,gBACA,GAAG,UACD;CACJ,MAAM,aAAa,eAAe,IAAI,KAAK;CAC3C,MAAM,iBAAiB,kBAAkB,WAAW;CACpD,MAAM,mBAAmB,GAAG,WAAW;CACvC,MAAM,YAAY,UAAU,UAAU,iBAAiB,UAAU,aAAa,iBAAiB,mBAAmB;CAClH,MAAM,cAAc,OAA4B,KAAK;CACrD,MAAM,cAAc,OAAO;CAE3B,MAAM,CAAC,OAAO,YAAY,qBAA6B;EACrD,OAAO;EACP,cAH6B,OAAO,iBAAiB,WAAW,eAAe,iBAAiB,UAAa,iBAAiB,OAAO,OAAO,aAAa,GAAG;EAI5J;EACD,CAAC;CAEF,MAAM,EAAE,aAAa,YAAY,cAAc,gBAAgB,YAAY;EACzE;EACA;EACA,UAAU;EACV;EACA;EACD,CAAC;CAEF,MAAM,EAAE,YAAY,cAAc,kBAAkB,UAAU,MAAM;CACpE,MAAM,YAAY,aAAa,OAAO,MAAM,qBAAqB,UAAU,UAAU;CACrF,MAAM,gBAAgB,OAAO,UAAU;CACvC,MAAM,kBAAkB,mBAAmB,OAAO,UAAU;CAE5D,MAAM,gCAAgC;EACpC,yBAAyB;EACzB,yBAAyB;EACzB,4BAA4B;EAC7B;AAED,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACG,SACC,oBAAC,OAAD;IACE,eAAY;IACZ,SAAS;IACT,WAAW,GAAG,cAAc,cAAc,iCAAiC,eAAe;cAEzF;IACK;GAEV,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAAC,YAAD;MACE,kBAAe;MACf,cAAc,qBAAqB,aAAa;MAChD,WAAW;MACX,cAAY;MACZ,eAAY;MACZ,UAAU;MACV,IAAI;MACE;MACN,QAAQ;MACR,UAAU;MACV,SAAS;MACT,SAAS;MACI;MACb,KAAK;MACK;MACV,YAAW;MACX,OAAO,wBAAwB;MACxB;MACP,GAAI;MACJ,GAAI;MACJ;KAED,aACC,oBAAC,OAAD;MACE,WAAW;MACX,eAAY;gBAEZ,oBAAC,YAAD,EAAY,MAAM,IAAM;MACpB;KAGR,qBAAC,OAAD;MAEE,cAAY,gBAAgB,SAAS,YAAY;MACjD,aAAU;MACV,WAAW,kBAAkB,eAAe,UAAU;MACtD,eAAY;MACZ,MAAK;gBANP;OAQG;OAAc;OAAE;OACb;;KACF;;GAEN,oBAAC,cAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,UAAU,eAAe;IACvB;IACrB,qBAAqB,uBAAuB,UAAU;IACtD;GACF,oBAAC,gBAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,YAAY,iBAAiB;IAC3B;IACrB,qBAAqB,uBAAuB,UAAU;IACtD;GACE;;;AAGV,SAAS,cAAc"}
|
package/dist/Toast.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.d.ts","names":[],"sources":["../src/components/Toast/Toast.tsx"],"mappings":";;;;;;;;KAMK,YAAA;AAAA,KACA,aAAA;AAAA,UAEY,UAAA,SAAmB,YAAA,QAAoB,aAAA;EACtD,SAAA;EACA,kBAAA;EACA,UAAA;EACA,OAAA,YAAmB,SAAA;EACnB,QAAA;EACA,IAAA,GAAO,SAAA;EACP,EAAA;EACA,WAAA;EACA,QAAA,GAAW,aAAA;EACX,OAAA,GAAU,YAAA;AAAA;AAAA,UAGK,YAAA,SAAqB,IAAA,CAAK,cAAA;EACzC,GAAA;EACA,MAAA;EACA,QAAA,GAAW,aAAA;EACX,aAAA;AAAA;AAAA,cAGI,aAAA,GAAa,KAAA;;IAajB,iCAAA,CAAA,SAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","names":[],"sources":["../src/components/Toast/Toast.tsx"],"mappings":";;;;;;;;KAMK,YAAA;AAAA,KACA,aAAA;AAAA,UAEY,UAAA,SAAmB,YAAA,QAAoB,aAAA;EACtD,SAAA;EACA,kBAAA;EACA,UAAA;EACA,OAAA,YAAmB,SAAA;EACnB,QAAA;EACA,IAAA,GAAO,SAAA;EACP,EAAA;EACA,WAAA;EACA,QAAA,GAAW,aAAA;EACX,OAAA,GAAU,YAAA;AAAA;AAAA,UAGK,YAAA,SAAqB,IAAA,CAAK,cAAA;EACzC,GAAA;EACA,MAAA;EACA,QAAA,GAAW,aAAA;EACX,aAAA;AAAA;AAAA,cAGI,aAAA,GAAa,KAAA;;IAajB,iCAAA,CAAA,SAAA;AAAA,cA8FW,KAAA;EAAA;;;;;;;KAlD+G,UAAA,GAAU,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;;;;OAnB5B,YAAA,GAAY,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;cAyEzG,KAAA;EAAK,SAAA;EAAA,kBAAA;EAAA,UAAA;EAAA,QAAA;EAAA,IAAA;EAAA,OAAA;EAAA,WAAA;EAAA,QAAA;EAAA;AAAA,GAzB4H,UAAA;qBA0BzH,IAAA,CAAK,UAAA;mBACP,IAAA,CAAK,UAAA;kBACN,IAAA,CAAK,UAAA;qBACF,IAAA,CAAK,UAAA;AAAA"}
|
package/dist/Toast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.js","names":["SonnerToaster","sonnerToast"],"sources":["../src/components/Toast/Toast.tsx"],"sourcesContent":["import { CheckSquareIcon, CloseCircleIcon, InfoIcon, WarningIcon } from '@components/Icons'\nimport { cn } from '@utils/twUtils'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type ReactNode } from 'react'\nimport { toast as sonnerToast, Toaster as SonnerToaster, type ToasterProps as SonnerToasterProps } from 'sonner'\n\ntype ToastVariant = 'default' | 'success' | 'error' | 'info' | 'warning'\ntype ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\n\nexport interface ToastProps extends VariantProps<typeof toastVariants> {\n className?: string\n containerAriaLabel?: string\n dataTestId?: string\n message?: string | ReactNode\n duration?: number\n icon?: ReactNode\n id?: string | number\n onAutoClose?: () => void\n position?: ToastPosition\n variant?: ToastVariant\n}\n\nexport interface ToasterProps extends Omit<SonnerToasterProps, 'toastOptions'> {\n gap?: number\n offset?: number | string\n position?: ToastPosition\n visibleToasts?: number\n}\n\nconst toastVariants = cva('rounded-md px-4 py-3 text-sm gap-3 shadow-lg flex max-w-[420px] min-w-[300px] items-start border', {\n variants: {\n variant: {\n default: 'border-toast-border bg-toast-bg text-toast-text',\n success: 'border-toast-success-border bg-toast-success-bg text-toast-success-text',\n error: 'border-toast-danger-border bg-toast-danger-bg text-toast-danger-text',\n info: 'border-toast-info-border bg-toast-info-bg text-toast-info-text',\n warning: 'border-toast-warning-border bg-toast-warning-bg text-toast-warning-text',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n})\n\nconst messageVariants = cva('mt-1 text-sm opacity-90', {\n variants: {\n variant: {\n default: 'text-toast-text',\n success: 'text-toast-success-text',\n error: 'text-toast-danger-text',\n info: 'text-toast-info-text',\n warning: 'text-toast-warning-text',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n})\n\nconst variantIcons: Record<ToastVariant, ReactNode> = {\n default: null,\n success: <CheckSquareIcon className='size-5 shrink-0 text-toast-success-icon' />,\n info: <InfoIcon className='size-5 shrink-0 text-toast-info-icon' />,\n warning: <WarningIcon className='size-5 shrink-0 text-toast-warning-icon' />,\n error: <CloseCircleIcon className='size-5 shrink-0 text-toast-danger-icon' />,\n}\n\nconst ToastProvider = ({ gap = 14, offset = 32, position = 'bottom-right', visibleToasts = 3, ...props }: ToasterProps) => {\n return (\n <SonnerToaster\n position={position}\n visibleToasts={visibleToasts}\n offset={offset}\n gap={gap}\n toastOptions={{\n unstyled: true,\n classNames: {\n toast: 'spectral-toast',\n },\n }}\n {...props}\n />\n )\n}\nToastProvider.displayName = 'Toast.Provider'\n\nconst ToastComponent = ({ className, containerAriaLabel = 'Notification', dataTestId, icon, message, variant = 'default' }: ToastProps) => {\n const resolvedVariant = variant ?? 'default'\n const displayIcon = icon ?? variantIcons[resolvedVariant]\n\n return (\n <div
|
|
1
|
+
{"version":3,"file":"Toast.js","names":["SonnerToaster","sonnerToast"],"sources":["../src/components/Toast/Toast.tsx"],"sourcesContent":["import { CheckSquareIcon, CloseCircleIcon, InfoIcon, WarningIcon } from '@components/Icons'\nimport { cn } from '@utils/twUtils'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type ReactNode } from 'react'\nimport { toast as sonnerToast, Toaster as SonnerToaster, type ToasterProps as SonnerToasterProps } from 'sonner'\n\ntype ToastVariant = 'default' | 'success' | 'error' | 'info' | 'warning'\ntype ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\n\nexport interface ToastProps extends VariantProps<typeof toastVariants> {\n className?: string\n containerAriaLabel?: string\n dataTestId?: string\n message?: string | ReactNode\n duration?: number\n icon?: ReactNode\n id?: string | number\n onAutoClose?: () => void\n position?: ToastPosition\n variant?: ToastVariant\n}\n\nexport interface ToasterProps extends Omit<SonnerToasterProps, 'toastOptions'> {\n gap?: number\n offset?: number | string\n position?: ToastPosition\n visibleToasts?: number\n}\n\nconst toastVariants = cva('rounded-md px-4 py-3 text-sm gap-3 shadow-lg flex max-w-[420px] min-w-[300px] items-start border', {\n variants: {\n variant: {\n default: 'border-toast-border bg-toast-bg text-toast-text',\n success: 'border-toast-success-border bg-toast-success-bg text-toast-success-text',\n error: 'border-toast-danger-border bg-toast-danger-bg text-toast-danger-text',\n info: 'border-toast-info-border bg-toast-info-bg text-toast-info-text',\n warning: 'border-toast-warning-border bg-toast-warning-bg text-toast-warning-text',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n})\n\nconst messageVariants = cva('mt-1 text-sm opacity-90', {\n variants: {\n variant: {\n default: 'text-toast-text',\n success: 'text-toast-success-text',\n error: 'text-toast-danger-text',\n info: 'text-toast-info-text',\n warning: 'text-toast-warning-text',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n})\n\nconst variantIcons: Record<ToastVariant, ReactNode> = {\n default: null,\n success: <CheckSquareIcon className='size-5 shrink-0 text-toast-success-icon' />,\n info: <InfoIcon className='size-5 shrink-0 text-toast-info-icon' />,\n warning: <WarningIcon className='size-5 shrink-0 text-toast-warning-icon' />,\n error: <CloseCircleIcon className='size-5 shrink-0 text-toast-danger-icon' />,\n}\n\nconst ToastProvider = ({ gap = 14, offset = 32, position = 'bottom-right', visibleToasts = 3, ...props }: ToasterProps) => {\n return (\n <SonnerToaster\n position={position}\n visibleToasts={visibleToasts}\n offset={offset}\n gap={gap}\n toastOptions={{\n unstyled: true,\n classNames: {\n toast: 'spectral-toast',\n },\n }}\n {...props}\n />\n )\n}\nToastProvider.displayName = 'Toast.Provider'\n\nconst ToastComponent = ({ className, containerAriaLabel = 'Notification', dataTestId, icon, message, variant = 'default' }: ToastProps) => {\n const resolvedVariant = variant ?? 'default'\n const displayIcon = icon ?? variantIcons[resolvedVariant]\n\n return (\n <div\n aria-label={containerAriaLabel}\n className={cn(toastVariants({ variant: resolvedVariant }), className)}\n data-variant={resolvedVariant}\n data-testid={dataTestId ?? `spectral-toast-${resolvedVariant}`}\n role='status'\n aria-live='polite'\n >\n {displayIcon && (\n <div\n className='mt-0.5'\n aria-hidden='true'\n >\n {displayIcon}\n </div>\n )}\n <div className='flex flex-col'>\n <p className={messageVariants({ variant: resolvedVariant })}>{message}</p>\n </div>\n </div>\n )\n}\nToastComponent.displayName = 'Toast'\n\nconst showToast = ({ className, containerAriaLabel, dataTestId, duration = 4000, icon, message, onAutoClose, position, variant = 'default' }: ToastProps) => {\n return sonnerToast.custom(\n (id) => (\n <ToastComponent\n className={className}\n containerAriaLabel={containerAriaLabel}\n dataTestId={dataTestId}\n icon={icon}\n id={id}\n message={message}\n variant={variant}\n />\n ),\n {\n duration,\n onAutoClose,\n position,\n },\n )\n}\n\nexport const Toast = Object.assign(ToastComponent, {\n Provider: ToastProvider,\n})\n\nexport const toast = Object.assign(showToast, {\n success: (options: Omit<ToastProps, 'variant'>) => showToast({ ...options, variant: 'success' }),\n error: (options: Omit<ToastProps, 'variant'>) => showToast({ ...options, variant: 'error' }),\n info: (options: Omit<ToastProps, 'variant'>) => showToast({ ...options, variant: 'info' }),\n warning: (options: Omit<ToastProps, 'variant'>) => showToast({ ...options, variant: 'warning' }),\n})\n"],"mappings":";;;;;;;;;;;;AA6BA,MAAM,gBAAgB,IAAI,oGAAoG;CAC5H,UAAU,EACR,SAAS;EACP,SAAS;EACT,SAAS;EACT,OAAO;EACP,MAAM;EACN,SAAS;EACV,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CAAC;AAEF,MAAM,kBAAkB,IAAI,2BAA2B;CACrD,UAAU,EACR,SAAS;EACP,SAAS;EACT,SAAS;EACT,OAAO;EACP,MAAM;EACN,SAAS;EACV,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CAAC;AAEF,MAAM,eAAgD;CACpD,SAAS;CACT,SAAS,oBAAC,iBAAD,EAAiB,WAAU,2CAA4C;CAChF,MAAM,oBAAC,UAAD,EAAU,WAAU,wCAAyC;CACnE,SAAS,oBAAC,aAAD,EAAa,WAAU,2CAA4C;CAC5E,OAAO,oBAAC,iBAAD,EAAiB,WAAU,0CAA2C;CAC9E;AAED,MAAM,iBAAiB,EAAE,MAAM,IAAI,SAAS,IAAI,WAAW,gBAAgB,gBAAgB,GAAG,GAAG,YAA0B;AACzH,QACE,oBAACA,SAAD;EACY;EACK;EACP;EACH;EACL,cAAc;GACZ,UAAU;GACV,YAAY,EACV,OAAO,kBACR;GACF;EACD,GAAI;EACJ;;AAGN,cAAc,cAAc;AAE5B,MAAM,kBAAkB,EAAE,WAAW,qBAAqB,gBAAgB,YAAY,MAAM,SAAS,UAAU,gBAA4B;CACzI,MAAM,kBAAkB,WAAW;CACnC,MAAM,cAAc,QAAQ,aAAa;AAEzC,QACE,qBAAC,OAAD;EACE,cAAY;EACZ,WAAW,GAAG,cAAc,EAAE,SAAS,iBAAiB,CAAC,EAAE,UAAU;EACrE,gBAAc;EACd,eAAa,cAAc,kBAAkB;EAC7C,MAAK;EACL,aAAU;YANZ,CAQG,eACC,oBAAC,OAAD;GACE,WAAU;GACV,eAAY;aAEX;GACG,GAER,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,KAAD;IAAG,WAAW,gBAAgB,EAAE,SAAS,iBAAiB,CAAC;cAAG;IAAY;GACtE,EACF;;;AAGV,eAAe,cAAc;AAE7B,MAAM,aAAa,EAAE,WAAW,oBAAoB,YAAY,WAAW,KAAM,MAAM,SAAS,aAAa,UAAU,UAAU,gBAA4B;AAC3J,QAAOC,QAAY,QAChB,OACC,oBAAC,gBAAD;EACa;EACS;EACR;EACN;EACF;EACK;EACA;EACT,GAEJ;EACE;EACA;EACA;EACD,CACF;;AAGH,MAAa,QAAQ,OAAO,OAAO,gBAAgB,EACjD,UAAU,eACX,CAAC;AAEF,MAAa,QAAQ,OAAO,OAAO,WAAW;CAC5C,UAAU,YAAyC,UAAU;EAAE,GAAG;EAAS,SAAS;EAAW,CAAC;CAChG,QAAQ,YAAyC,UAAU;EAAE,GAAG;EAAS,SAAS;EAAS,CAAC;CAC5F,OAAO,YAAyC,UAAU;EAAE,GAAG;EAAS,SAAS;EAAQ,CAAC;CAC1F,UAAU,YAAyC,UAAU;EAAE,GAAG;EAAS,SAAS;EAAW,CAAC;CACjG,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleBase.js","names":[],"sources":["../../src/components/Toggle/ToggleBase.tsx"],"sourcesContent":["import { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { Slot, type AsChildProp } from '@primitives/slot'\nimport { useCallback, type ButtonHTMLAttributes, type HTMLAttributes, type KeyboardEvent, type MouseEvent, type Ref } from 'react'\n\nexport type ToggleProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange'> &\n Omit<AsChildProp, 'asChild'> & {\n asChild?: boolean\n defaultPressed?: boolean\n disabled?: boolean\n onPressedChange?: (pressed: boolean) => void\n pressed?: boolean\n }\n\nexport const ToggleBase = function Toggle({\n asChild = false,\n children,\n className,\n defaultPressed = false,\n disabled,\n onClick,\n onKeyDown,\n onPressedChange,\n pressed: pressedProp,\n ref,\n ...rest\n}: ToggleProps & {\n ref?: Ref<HTMLButtonElement>\n}) {\n const [pressed, setPressed] = useUncontrolledState<boolean>({\n defaultValue: defaultPressed,\n onChange: onPressedChange,\n value: pressedProp,\n })\n\n const handleToggle = useCallback(() => {\n if (disabled) return\n setPressed(!pressed)\n }, [disabled, pressed, setPressed])\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement | HTMLDivElement>) => {\n if (onKeyDown) onKeyDown(e as KeyboardEvent<HTMLButtonElement>)\n if (e.defaultPrevented) return\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault()\n handleToggle()\n }\n },\n [handleToggle, onKeyDown],\n )\n\n const handleClick = useCallback(\n (e: MouseEvent<HTMLButtonElement | HTMLDivElement>) => {\n if (onClick) onClick(e as MouseEvent<HTMLButtonElement>)\n if (e.defaultPrevented) return\n handleToggle()\n },\n [handleToggle, onClick],\n )\n\n const sharedProps = {\n className,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n 'aria-disabled': disabled ? true : undefined,\n 'aria-pressed': pressed,\n 'data-state': pressed ? 'on' : 'off',\n 'data-disabled': disabled ? true : undefined,\n }\n\n if (asChild) {\n return (\n <div\n ref={ref as Ref<HTMLDivElement>}\n // eslint-disable-next-line jsx-a11y/prefer-tag-over-role -- div wrapper required for Slot primitive to merge props with child\n role='button'\n tabIndex={disabled ? -1 : 0}\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...sharedProps}\n >\n <Slot>{children}</Slot>\n </div>\n )\n }\n\n return (\n <button
|
|
1
|
+
{"version":3,"file":"ToggleBase.js","names":[],"sources":["../../src/components/Toggle/ToggleBase.tsx"],"sourcesContent":["import { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { Slot, type AsChildProp } from '@primitives/slot'\nimport { useCallback, type ButtonHTMLAttributes, type HTMLAttributes, type KeyboardEvent, type MouseEvent, type Ref } from 'react'\n\nexport type ToggleProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange'> &\n Omit<AsChildProp, 'asChild'> & {\n asChild?: boolean\n defaultPressed?: boolean\n disabled?: boolean\n onPressedChange?: (pressed: boolean) => void\n pressed?: boolean\n }\n\nexport const ToggleBase = function Toggle({\n asChild = false,\n children,\n className,\n defaultPressed = false,\n disabled,\n onClick,\n onKeyDown,\n onPressedChange,\n pressed: pressedProp,\n ref,\n ...rest\n}: ToggleProps & {\n ref?: Ref<HTMLButtonElement>\n}) {\n const [pressed, setPressed] = useUncontrolledState<boolean>({\n defaultValue: defaultPressed,\n onChange: onPressedChange,\n value: pressedProp,\n })\n\n const handleToggle = useCallback(() => {\n if (disabled) return\n setPressed(!pressed)\n }, [disabled, pressed, setPressed])\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement | HTMLDivElement>) => {\n if (onKeyDown) onKeyDown(e as KeyboardEvent<HTMLButtonElement>)\n if (e.defaultPrevented) return\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault()\n handleToggle()\n }\n },\n [handleToggle, onKeyDown],\n )\n\n const handleClick = useCallback(\n (e: MouseEvent<HTMLButtonElement | HTMLDivElement>) => {\n if (onClick) onClick(e as MouseEvent<HTMLButtonElement>)\n if (e.defaultPrevented) return\n handleToggle()\n },\n [handleToggle, onClick],\n )\n\n const sharedProps = {\n className,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n 'aria-disabled': disabled ? true : undefined,\n 'aria-pressed': pressed,\n 'data-state': pressed ? 'on' : 'off',\n 'data-disabled': disabled ? true : undefined,\n }\n\n if (asChild) {\n return (\n <div\n ref={ref as Ref<HTMLDivElement>}\n // eslint-disable-next-line jsx-a11y/prefer-tag-over-role -- div wrapper required for Slot primitive to merge props with child\n role='button'\n tabIndex={disabled ? -1 : 0}\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...sharedProps}\n >\n <Slot>{children}</Slot>\n </div>\n )\n }\n\n return (\n <button\n {...rest}\n {...sharedProps}\n disabled={disabled}\n ref={ref as Ref<HTMLButtonElement>}\n type='button'\n >\n {children}\n </button>\n )\n}\n"],"mappings":";;;;;;;AAaA,MAAa,aAAa,SAAS,OAAO,EACxC,UAAU,OACV,UACA,WACA,iBAAiB,OACjB,UACA,SACA,WACA,iBACA,SAAS,aACT,KACA,GAAG,QAGF;CACD,MAAM,CAAC,SAAS,cAAc,qBAA8B;EAC1D,cAAc;EACd,UAAU;EACV,OAAO;EACR,CAAC;CAEF,MAAM,eAAe,kBAAkB;AACrC,MAAI,SAAU;AACd,aAAW,CAAC,QAAQ;IACnB;EAAC;EAAU;EAAS;EAAW,CAAC;CAEnC,MAAM,gBAAgB,aACnB,MAAyD;AACxD,MAAI,UAAW,WAAU,EAAsC;AAC/D,MAAI,EAAE,iBAAkB;AACxB,MAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,SAAS;AACtC,KAAE,gBAAgB;AAClB,iBAAc;;IAGlB,CAAC,cAAc,UAAU,CAC1B;CAWD,MAAM,cAAc;EAClB;EACA,SAXkB,aACjB,MAAsD;AACrD,OAAI,QAAS,SAAQ,EAAmC;AACxD,OAAI,EAAE,iBAAkB;AACxB,iBAAc;KAEhB,CAAC,cAAc,QAAQ,CAKH;EACpB,WAAW;EACX,iBAAiB,WAAW,OAAO;EACnC,gBAAgB;EAChB,cAAc,UAAU,OAAO;EAC/B,iBAAiB,WAAW,OAAO;EACpC;AAED,KAAI,QACF,QACE,oBAAC,OAAD;EACO;EAEL,MAAK;EACL,UAAU,WAAW,KAAK;EAC1B,GAAK;EACL,GAAI;YAEJ,oBAAC,MAAD,EAAO,UAAgB;EACnB;AAIV,QACE,oBAAC,UAAD;EACE,GAAI;EACJ,GAAI;EACM;EACL;EACL,MAAK;EAEJ;EACM"}
|
package/dist/Toggle.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import { ActiveColor, ActiveTextColor, getActiveColorStyle } from "./utils/activeColorStyle.js";
|
|
2
3
|
import { ToggleBase } from "./Toggle/ToggleBase.js";
|
|
3
|
-
import {
|
|
4
|
+
import { ComponentProps, Ref } from "react";
|
|
4
5
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
6
|
import { VariantProps } from "class-variance-authority";
|
|
6
7
|
import * as _$class_variance_authority_types0 from "class-variance-authority/types";
|
|
7
8
|
|
|
8
9
|
//#region src/components/Toggle/Toggle.d.ts
|
|
9
|
-
type ActiveColor = string;
|
|
10
|
-
declare const getActiveColorStyle: (activeColor: ActiveColor | undefined, activeTextColor?: ActiveColor) => CSSProperties | undefined;
|
|
11
10
|
type ToggleProps = ComponentProps<typeof ToggleBase> & VariantProps<typeof toggleVariants> & {
|
|
12
11
|
activeColor?: ActiveColor;
|
|
13
|
-
activeTextColor?:
|
|
12
|
+
activeTextColor?: ActiveTextColor;
|
|
14
13
|
};
|
|
15
14
|
declare const toggleVariants: (props?: ({
|
|
16
|
-
variant?: "default" | "outline" | null | undefined;
|
|
15
|
+
variant?: "default" | "outline" | "separated" | null | undefined;
|
|
17
16
|
size?: "default" | "lg" | "sm" | null | undefined;
|
|
18
17
|
layout?: "default" | "expanded" | null | undefined;
|
|
19
18
|
} & _$class_variance_authority_types0.ClassProp) | undefined) => string;
|
|
@@ -32,5 +31,5 @@ declare const Toggle: ({
|
|
|
32
31
|
ref?: Ref<HTMLButtonElement>;
|
|
33
32
|
}) => _$react_jsx_runtime0.JSX.Element;
|
|
34
33
|
//#endregion
|
|
35
|
-
export { ActiveColor, Toggle, ToggleProps, getActiveColorStyle, toggleVariants };
|
|
34
|
+
export { type ActiveColor, type ActiveTextColor, Toggle, ToggleProps, getActiveColorStyle, toggleVariants };
|
|
36
35
|
//# sourceMappingURL=Toggle.d.ts.map
|
package/dist/Toggle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toggle.d.ts","names":[],"sources":["../src/components/Toggle/Toggle.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Toggle.d.ts","names":[],"sources":["../src/components/Toggle/Toggle.tsx"],"mappings":";;;;;;;;;KASY,WAAA,GAAc,cAAA,QAAsB,UAAA,IAC9C,YAAA,QAAoB,cAAA;EAClB,WAAA,GAAc,WAAA;EACd,eAAA,GAAkB,eAAA;AAAA;AAAA,cAGT,cAAA,GAAc,KAAA;;;;IAyB1B,iCAAA,CAAA,SAAA;AAAA,cAEY,MAAA;EAAM,GAAA;EAAA,SAAA;EAAA,OAAA;EAAA,IAAA;EAAA,MAAA;EAAA,QAAA;EAAA,WAAA;EAAA,eAAA;EAAA,KAAA;EAAA,GAAA;AAAA,GAWhB,WAAA;EACD,GAAA,GAAM,GAAA,CAAI,iBAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA"}
|
package/dist/Toggle.js
CHANGED
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { cn } from "./utils/twUtils.js";
|
|
3
|
+
import { getActiveColorStyle } from "./utils/activeColorStyle.js";
|
|
3
4
|
import { ToggleBase } from "./Toggle/ToggleBase.js";
|
|
4
5
|
import "react";
|
|
5
6
|
import { jsx } from "react/jsx-runtime";
|
|
6
7
|
import { cva } from "class-variance-authority";
|
|
7
8
|
|
|
8
9
|
//#region src/components/Toggle/Toggle.tsx
|
|
9
|
-
const RAW_COLOR_PATTERN = /^(#|rgb|hsl|oklch|oklab|lab|lch|color|var\(|transparent|currentcolor)/i;
|
|
10
|
-
const BASE_COLOR_PATTERN = /^(success|warning|danger|primary|neutral|secondary)-\d+$/;
|
|
11
|
-
const resolveColor = (color) => {
|
|
12
|
-
if (RAW_COLOR_PATTERN.test(color)) return color;
|
|
13
|
-
if (BASE_COLOR_PATTERN.test(color)) return `var(--horizon-color-${color})`;
|
|
14
|
-
return `var(--color-${color})`;
|
|
15
|
-
};
|
|
16
|
-
const getActiveColorStyle = (activeColor, activeTextColor) => {
|
|
17
|
-
if (!activeColor && !activeTextColor) return void 0;
|
|
18
|
-
return {
|
|
19
|
-
...activeColor && {
|
|
20
|
-
"--color-toggle-bg--active": resolveColor(activeColor),
|
|
21
|
-
"--color-toggle-border--active": resolveColor(activeColor)
|
|
22
|
-
},
|
|
23
|
-
...activeTextColor && { "--color-toggle-text--active": resolveColor(activeTextColor) }
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
10
|
const toggleVariants = cva(`gap-2 rounded-md text-sm shadow-sm font-medium inline-flex w-fit items-center justify-center border bg-toggle-bg whitespace-nowrap text-toggle-text transition-colors hover:cursor-pointer hover:border-toggle-border--hover hover:bg-toggle-bg--hover hover:text-toggle-text--hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent active:bg-toggle-bg--active aria-invalid:border-danger-200 aria-invalid:outline-danger-200/20 aria-pressed:border-toggle-border--active aria-pressed:bg-toggle-bg--active aria-pressed:text-toggle-text--active data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[state=on]:border-toggle-border--active data-[state=on]:bg-toggle-bg--active data-[state=on]:text-toggle-text--active [&_svg]:pointer-events-none [&_svg]:shrink-0`, {
|
|
27
11
|
variants: {
|
|
28
12
|
variant: {
|
|
29
13
|
default: "border-toggle-border hover:border-toggle-border--hover",
|
|
30
|
-
outline: "border-toggle-outline-border hover:border-toggle-outline-border--hover hover:bg-toggle-bg--hover"
|
|
14
|
+
outline: "border-toggle-outline-border hover:border-toggle-outline-border--hover hover:bg-toggle-bg--hover",
|
|
15
|
+
separated: "border-toggle-border hover:border-toggle-border--hover aria-pressed:border-toggle-border--active aria-pressed:bg-toggle-bg--active data-[state=on]:border-toggle-border--active data-[state=on]:bg-toggle-bg--active"
|
|
31
16
|
},
|
|
32
17
|
size: {
|
|
33
18
|
default: `h-9 px-3 min-w-9 [&_svg:not([class*='size-']):not([width]):not([height])]:size-4`,
|
|
@@ -45,7 +30,7 @@ const toggleVariants = cva(`gap-2 rounded-md text-sm shadow-sm font-medium inlin
|
|
|
45
30
|
layout: "default"
|
|
46
31
|
}
|
|
47
32
|
});
|
|
48
|
-
const Toggle = ({ ref, className, variant, size, layout, disabled, activeColor, activeTextColor, style, ...props }) => {
|
|
33
|
+
const Toggle = ({ ref, className, variant, size, layout, disabled, activeColor = "default", activeTextColor, style, ...props }) => {
|
|
49
34
|
return /* @__PURE__ */ jsx(ToggleBase, {
|
|
50
35
|
ref,
|
|
51
36
|
disabled,
|
package/dist/Toggle.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toggle.js","names":[],"sources":["../src/components/Toggle/Toggle.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type ComponentProps, type
|
|
1
|
+
{"version":3,"file":"Toggle.js","names":[],"sources":["../src/components/Toggle/Toggle.tsx"],"sourcesContent":["import { getActiveColorStyle, type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\nimport { cn } from '@utils/twUtils'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type ComponentProps, type Ref } from 'react'\nimport { ToggleBase } from './ToggleBase'\n\nexport { getActiveColorStyle }\nexport type { ActiveColor, ActiveTextColor }\n\nexport type ToggleProps = ComponentProps<typeof ToggleBase> &\n VariantProps<typeof toggleVariants> & {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n }\n\nexport const toggleVariants = cva(\n `gap-2 rounded-md text-sm shadow-sm font-medium inline-flex w-fit items-center justify-center border bg-toggle-bg whitespace-nowrap text-toggle-text transition-colors hover:cursor-pointer hover:border-toggle-border--hover hover:bg-toggle-bg--hover hover:text-toggle-text--hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent active:bg-toggle-bg--active aria-invalid:border-danger-200 aria-invalid:outline-danger-200/20 aria-pressed:border-toggle-border--active aria-pressed:bg-toggle-bg--active aria-pressed:text-toggle-text--active data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[state=on]:border-toggle-border--active data-[state=on]:bg-toggle-bg--active data-[state=on]:text-toggle-text--active [&_svg]:pointer-events-none [&_svg]:shrink-0`,\n {\n variants: {\n variant: {\n default: 'border-toggle-border hover:border-toggle-border--hover',\n outline: 'border-toggle-outline-border hover:border-toggle-outline-border--hover hover:bg-toggle-bg--hover',\n separated: 'border-toggle-border hover:border-toggle-border--hover aria-pressed:border-toggle-border--active aria-pressed:bg-toggle-bg--active data-[state=on]:border-toggle-border--active data-[state=on]:bg-toggle-bg--active',\n },\n size: {\n default: `h-9 px-3 min-w-9 [&_svg:not([class*='size-']):not([width]):not([height])]:size-4`,\n sm: `h-8 px-1.5 min-w-8 [&_svg:not([class*='size-']):not([width]):not([height])]:size-3`,\n lg: `h-10 px-2.5 min-w-10 [&_svg:not([class*='size-']):not([width]):not([height])]:size-5`,\n },\n layout: {\n default: 'w-fit',\n expanded: 'w-full',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n layout: 'default',\n },\n },\n)\n\nexport const Toggle = ({\n ref,\n className,\n variant,\n size,\n layout,\n disabled,\n activeColor = 'default',\n activeTextColor,\n style,\n ...props\n}: ToggleProps & {\n ref?: Ref<HTMLButtonElement>\n}) => {\n return (\n <ToggleBase\n ref={ref}\n disabled={disabled}\n data-slot='toggle'\n data-testid='spectral-toggle'\n className={cn(toggleVariants({ variant, size, layout }), className)}\n style={{ ...getActiveColorStyle(activeColor, activeTextColor), ...style }}\n {...props}\n />\n )\n}\n"],"mappings":";;;;;;;;;AAeA,MAAa,iBAAiB,IAC5B,s0BACA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,SAAS;GACT,WAAW;GACZ;EACD,MAAM;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACL;EACD,QAAQ;GACN,SAAS;GACT,UAAU;GACX;EACF;CACD,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,QAAQ;EACT;CACF,CACF;AAED,MAAa,UAAU,EACrB,KACA,WACA,SACA,MACA,QACA,UACA,cAAc,WACd,iBACA,OACA,GAAG,YAGC;AACJ,QACE,oBAAC,YAAD;EACO;EACK;EACV,aAAU;EACV,eAAY;EACZ,WAAW,GAAG,eAAe;GAAE;GAAS;GAAM;GAAQ,CAAC,EAAE,UAAU;EACnE,OAAO;GAAE,GAAG,oBAAoB,aAAa,gBAAgB;GAAE,GAAG;GAAO;EACzE,GAAI;EACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleGroupBase.d.ts","names":[],"sources":["../../src/components/ToggleGroup/ToggleGroupBase.tsx"],"mappings":";;;;;KAKK,WAAA;AAAA,UAEY,gBAAA;EACf,SAAA;EACA,QAAA;EACA,IAAA;EACA,IAAA;EACA,WAAA,GAAc,WAAA;AAAA;AAAA,KAGJ,WAAA,GAAc,gBAAA;EACxB,YAAA;EACA,aAAA,IAAiB,CAAA;EACjB,IAAA;EACA,KAAA;AAAA;AAAA,KAGU,aAAA,GAAgB,gBAAA;EAC1B,YAAA;EACA,aAAA,IAAiB,CAAA;EACjB,IAAA;EACA,KAAA;AAAA;AAAA,KAGU,gBAAA,IAAoB,WAAA,GAAc,aAAA,IAAiB,IAAA,CAAK,cAAA,CAAe,cAAA;AAAA,UAElE,eAAA;EACf,QAAA,GAAW,SAAA;EACX,SAAA;EACA,QAAA;EACA,KAAA;AAAA;AAAA,cAiBW,eAAA,GAAe,KAAA,EAAW,gBAAA,GAAmB,MAAA,gCAAiC,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"ToggleGroupBase.d.ts","names":[],"sources":["../../src/components/ToggleGroup/ToggleGroupBase.tsx"],"mappings":";;;;;KAKK,WAAA;AAAA,UAEY,gBAAA;EACf,SAAA;EACA,QAAA;EACA,IAAA;EACA,IAAA;EACA,WAAA,GAAc,WAAA;AAAA;AAAA,KAGJ,WAAA,GAAc,gBAAA;EACxB,YAAA;EACA,aAAA,IAAiB,CAAA;EACjB,IAAA;EACA,KAAA;AAAA;AAAA,KAGU,aAAA,GAAgB,gBAAA;EAC1B,YAAA;EACA,aAAA,IAAiB,CAAA;EACjB,IAAA;EACA,KAAA;AAAA;AAAA,KAGU,gBAAA,IAAoB,WAAA,GAAc,aAAA,IAAiB,IAAA,CAAK,cAAA,CAAe,cAAA;AAAA,UAElE,eAAA;EACf,QAAA,GAAW,SAAA;EACX,SAAA;EACA,QAAA;EACA,KAAA;AAAA;AAAA,cAiBW,eAAA,GAAe,KAAA,EAAW,gBAAA,GAAmB,MAAA,gCAAiC,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,KAiI/E,oBAAA,GAAuB,IAAA,CAAK,oBAAA,CAAqB,iBAAA,oEAC3D,eAAA;EAnKA,iFAqKE,OAAA,YArKG;EAuKH,cAAA;AAAA;AAAA,cAGS,mBAAA;EAAmB,GAAA;EAAA,KAAA;EAAA,QAAA;EAAA,SAAA;EAAA,QAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAS7B,oBAAA;EACD,GAAA,GAAM,GAAA,CAAI,iBAAA;AAAA,MACX,oBAAA,CAAA,GAAA,CAAA,OAAA"}
|