@spear-ai/spectral 1.20.1 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Accordion.js +0 -4
- package/dist/Accordion.js.map +1 -1
- package/dist/Alert/AlertBase.d.ts +0 -1
- package/dist/Alert/AlertBase.d.ts.map +1 -1
- package/dist/Alert/AlertBase.js +14 -17
- package/dist/Alert/AlertBase.js.map +1 -1
- package/dist/Alert.js +16 -4
- package/dist/Alert.js.map +1 -1
- package/dist/AlertDialog.js +3 -3
- package/dist/AlertDialog.js.map +1 -1
- package/dist/Avatar.js +1 -9
- package/dist/Avatar.js.map +1 -1
- package/dist/Badge.js +0 -1
- package/dist/Badge.js.map +1 -1
- package/dist/Button.js +0 -3
- package/dist/Button.js.map +1 -1
- package/dist/ButtonGroup.js +0 -4
- package/dist/ButtonGroup.js.map +1 -1
- package/dist/ButtonIcon.js +0 -1
- package/dist/ButtonIcon.js.map +1 -1
- package/dist/ButtonIconSlideout.js +0 -3
- package/dist/ButtonIconSlideout.js.map +1 -1
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +5 -8
- package/dist/Checkbox.js.map +1 -1
- package/dist/Combobox.d.ts +1 -0
- package/dist/Combobox.d.ts.map +1 -1
- package/dist/Combobox.js +0 -4
- package/dist/Combobox.js.map +1 -1
- package/dist/ControlGroup/ControlGroupSelect.js +0 -5
- package/dist/ControlGroup/ControlGroupSelect.js.map +1 -1
- package/dist/DataCard/Card.js +0 -6
- package/dist/DataCard/Card.js.map +1 -1
- package/dist/DataCard.js +1 -7
- package/dist/DataCard.js.map +1 -1
- package/dist/DateTimePicker/Calendar.js +0 -1
- package/dist/DateTimePicker/Calendar.js.map +1 -1
- package/dist/DateTimePicker/DateTimeInput.js +0 -1
- package/dist/DateTimePicker/DateTimeInput.js.map +1 -1
- package/dist/DateTimePicker/TimePeriodSelect.js +0 -4
- package/dist/DateTimePicker/TimePeriodSelect.js.map +1 -1
- package/dist/DateTimePicker/TimePicker.js +0 -3
- package/dist/DateTimePicker/TimePicker.js.map +1 -1
- package/dist/DateTimePicker.js +0 -4
- package/dist/DateTimePicker.js.map +1 -1
- package/dist/Dialog.js +0 -16
- package/dist/Dialog.js.map +1 -1
- package/dist/DirectionalColorWheel/DirectionalColorWheelDisclosure.js +0 -2
- package/dist/DirectionalColorWheel/DirectionalColorWheelDisclosure.js.map +1 -1
- package/dist/DirectionalColorWheel/DirectionalColorWheelGlyph.js +0 -1
- package/dist/DirectionalColorWheel/DirectionalColorWheelGlyph.js.map +1 -1
- package/dist/DirectionalColorWheel.js +9 -21
- package/dist/DirectionalColorWheel.js.map +1 -1
- package/dist/Drawer.js +6 -29
- package/dist/Drawer.js.map +1 -1
- package/dist/DropdownMenu.js +1 -9
- package/dist/DropdownMenu.js.map +1 -1
- package/dist/FormFieldMessage.js +0 -1
- package/dist/FormFieldMessage.js.map +1 -1
- package/dist/HoverCard.js +0 -3
- package/dist/HoverCard.js.map +1 -1
- package/dist/Input.js +0 -10
- package/dist/Input.js.map +1 -1
- package/dist/InputOTP.js +0 -4
- package/dist/InputOTP.js.map +1 -1
- package/dist/InputSearch.js +3 -15
- package/dist/InputSearch.js.map +1 -1
- package/dist/Kbd.js +0 -2
- package/dist/Kbd.js.map +1 -1
- package/dist/Meter.d.ts +23 -0
- package/dist/Meter.d.ts.map +1 -0
- package/dist/Meter.js +45 -0
- package/dist/Meter.js.map +1 -0
- package/dist/MultiSelect/MultiSelectBase.js +1 -16
- package/dist/MultiSelect/MultiSelectBase.js.map +1 -1
- package/dist/Popover.js +0 -3
- package/dist/Popover.js.map +1 -1
- package/dist/RadialMenu.js +1 -7
- package/dist/RadialMenu.js.map +1 -1
- package/dist/RadioButtonGroup/RadioButtonGroupBase.d.ts.map +1 -1
- package/dist/RadioButtonGroup/RadioButtonGroupBase.js +1 -4
- package/dist/RadioButtonGroup/RadioButtonGroupBase.js.map +1 -1
- package/dist/RadioButtonGroup.js +1 -1
- package/dist/RadioButtonGroup.js.map +1 -1
- package/dist/RadioGroup.js +0 -6
- package/dist/RadioGroup.js.map +1 -1
- package/dist/Select.js +12 -41
- package/dist/Select.js.map +1 -1
- package/dist/Slider.js +2 -11
- package/dist/Slider.js.map +1 -1
- package/dist/Switch.js +0 -6
- package/dist/Switch.js.map +1 -1
- package/dist/Tabs/TabsBase.js +0 -5
- package/dist/Tabs/TabsBase.js.map +1 -1
- package/dist/Textarea.js +0 -4
- package/dist/Textarea.js.map +1 -1
- package/dist/Toast.d.ts +2 -0
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js +9 -8
- package/dist/Toast.js.map +1 -1
- package/dist/Toggle.js +0 -1
- package/dist/Toggle.js.map +1 -1
- package/dist/ToggleGroup/ToggleGroupItem.js +0 -1
- package/dist/ToggleGroup/ToggleGroupItem.js.map +1 -1
- package/dist/ToggleGroup.js +0 -1
- package/dist/ToggleGroup.js.map +1 -1
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js +4 -5
- package/dist/Tooltip.js.map +1 -1
- package/dist/Tray.js +1 -9
- package/dist/Tray.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/styles/horizon/base.css +31 -16
- package/dist/styles/horizon/colors.css +37 -21
- package/dist/styles/horizon/theme.css +15 -7
- package/dist/styles/horizon/utilities.css +19 -45
- package/dist/styles/spectral.css +1 -1
- package/package.json +4 -1
package/dist/Switch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.js","names":[
|
|
1
|
+
{"version":3,"file":"Switch.js","names":[],"sources":["../src/components/Switch/Switch.tsx"],"sourcesContent":["import { Label } from '@components/Label/Label'\nimport { ErrorMessage, WarningMessage, useFormFieldId, type BaseFormFieldProps, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { CheckIcon, XIcon } from 'lucide-react'\nimport { type Ref } from 'react'\nimport { Switch as SwitchBase, SwitchThumb, type SwitchProps as SwitchBaseProps } from './SwitchBase'\n\ntype SwitchVisualState = Exclude<FormFieldState, 'disabled'>\n\nexport type SwitchProps = Omit<SwitchBaseProps, 'onCheckedChange'> & {\n 'aria-describedby'?: string\n 'aria-label'?: string\n errorMessage?: BaseFormFieldProps['errorMessage']\n hideLabel?: boolean\n id?: string\n label?: string\n labelPosition?: 'left' | 'right'\n labelText?: string\n messageReserveLines?: number\n messageReserveSpace?: boolean\n onChange?: (checked: boolean) => void\n ref?: Ref<HTMLButtonElement>\n required?: boolean\n state?: SwitchVisualState\n value?: string\n variant?: 'default' | 'squared' | 'permanent-indicator'\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nconst thumbBase = 'bg-switch-thumb--checked data-[state=checked]:bg-switch-thumb pointer-events-none block rounded-full ring-0 transition-transform motion-reduce:transition-none'\n\nexport const Switch = ({\n className,\n disabled,\n errorMessage,\n hideLabel = false,\n id,\n label,\n labelPosition = 'right',\n labelText,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n ref,\n required,\n state = 'default',\n value,\n variant,\n warningMessage,\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n ...props\n}: SwitchProps) => {\n const switchId = useFormFieldId(id, name)\n const isDisabled = Boolean(disabled)\n const resolvedLabelText = labelText ?? label\n const errorMessageId = `${switchId}-error`\n const warningMessageId = `${switchId}-warning`\n const messageId = state === 'error' && errorMessage && errorMessageId ? errorMessageId : state === 'warning' && warningMessage && warningMessageId ? warningMessageId : undefined\n const isSquared = variant === 'squared'\n const isPermanentIndicator = variant === 'permanent-indicator'\n\n return (\n <div className='flex items-center' data-testid='spectral-switch-container' data-state={state}>\n {labelPosition === 'left' && !hideLabel && resolvedLabelText && (\n <Label className='mr-2' data-testid='spectral-switch-label-left' htmlFor={switchId}>\n {resolvedLabelText}\n </Label>\n )}\n\n {isPermanentIndicator ? (\n <div className='h-7 text-sm font-medium relative inline-grid grid-cols-[1fr_1fr] items-center'>\n <SwitchBase\n aria-required={required}\n aria-describedby={[messageId, ariaDescribedBy].filter(Boolean).join(' ') || undefined}\n aria-invalid={state === 'error' ? true : undefined}\n aria-label={ariaLabel ?? (hideLabel ? resolvedLabelText : undefined)}\n className={cn(\n 'peer inset-0 w-14 focus-visible:ring-ring absolute inline-flex h-[inherit] items-center focus-visible:ring-offset-background data-[state=checked]:bg-switch-bg--checked data-[state=unchecked]:bg-switch-bg/50',\n 'shadow-2xs cursor-pointer rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n data-testid='spectral-switch'\n disabled={isDisabled}\n id={switchId}\n name={name}\n onCheckedChange={onChange}\n ref={ref}\n required={required}\n value={value}\n {...props}\n >\n <SwitchThumb className={cn(thumbBase, 'size-6.5 shadow-xs relative z-10 duration-200 ease-out 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-200 ease-out 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-200 ease-out 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-colors 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\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,KAAI;CACxC,MAAM,aAAa,QAAQ,SAAQ;CACnC,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;EAA4D,cAAY;YAAvF;GACG,kBAAkB,UAAU,CAAC,aAAa,qBACzC,oBAAC,OAAD;IAAO,WAAU;IAAgD,SAAS;cACvE;IACI;GAPgB,YAAY,wBAWnC,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAAC,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;MAED,UAAU;MACV,IAAI;MACE;MACN,iBAAiB;MACZ;MACK;MACH;MACP,GAAI;gBAEJ,oBAAC,aAAD,EAAa,WAAW,GAAG,WAAW,uKAAuK,EAAG;MACtM;KACZ,oBAAC,QAAD;MAAM,WAAU;gBACd,oBAAC,OAAD;OAAO,eAAY;OAAO,WAAU;OAAU;MAC1C;KACN,oBAAC,QAAD;MAAM,WAAU;gBACd,oBAAC,WAAD;OAAW,eAAY;OAAO,WAAU;OAAU;MAC9C;KACH;QAEL,oBAAC,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,kUACA,gZACJ,UACD;IAED,UAAU;IACV,IAAI;IACE;IACN,iBAAiB;IACZ;IACK;IACH;IACP,GAAI;cAEJ,oBAAC,aAAD,EAAa,WAAW,GAAG,WAAW,YAAY,gGAAgG,uDAAuD,EAAG;IAClM;GAGb,kBAAkB,WAAW,CAAC,aAAa,qBAC1C,oBAAC,OAAD;IAAO,WAAU;IAAiD,SAAS;IAAU,IAAI,GAAG,SAAS;cAClG;IACI;GAGR,aAAa,qBACZ,oBAAC,OAAD;IAAO,WAAU;IAAqD,SAAS;cAC5E;IACI;GAET,oBAAC,cAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,UAAW,gBAAgB,OAAQ;IACjC;IACrB,qBAAqB,uBAAuB,UAAU;IACvD;GACD,oBAAC,gBAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,YAAa,kBAAkB,OAAQ;IACrC;IACrB,qBAAqB,uBAAuB,UAAU;IACvD;GACE;;;AAGT,OAAO,cAAc"}
|
package/dist/Tabs/TabsBase.js
CHANGED
|
@@ -39,7 +39,6 @@ const TabsBase = function Tabs({ ref, activationMode = "automatic", children, de
|
|
|
39
39
|
value: contextValue,
|
|
40
40
|
children: /* @__PURE__ */ jsx("div", {
|
|
41
41
|
ref,
|
|
42
|
-
"data-testid": "spectral-tabs",
|
|
43
42
|
"data-orientation": orientation,
|
|
44
43
|
"data-disabled": disabled ? "" : void 0,
|
|
45
44
|
dir,
|
|
@@ -113,7 +112,6 @@ const TabsList = function TabsList({ ref, children, className, loop = true, righ
|
|
|
113
112
|
ref,
|
|
114
113
|
role: "tablist",
|
|
115
114
|
tabIndex: -1,
|
|
116
|
-
"data-testid": "spectral-tabs-list",
|
|
117
115
|
"aria-orientation": orientation,
|
|
118
116
|
"aria-disabled": disabled,
|
|
119
117
|
className: cn("tabs-list flex", orientation === "horizontal" && "items-center justify-between", orientation === "vertical" && "flex-col", className),
|
|
@@ -191,7 +189,6 @@ const TabsTrigger = function TabsTrigger({ ref, className, value: triggerValue,
|
|
|
191
189
|
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),
|
|
192
190
|
"data-disabled": isDisabled ? "" : void 0,
|
|
193
191
|
"data-state": isActive ? "active" : "inactive",
|
|
194
|
-
"data-testid": "spectral-tabs-trigger",
|
|
195
192
|
disabled: isDisabled,
|
|
196
193
|
id: triggerId,
|
|
197
194
|
onClick: handleClick,
|
|
@@ -210,7 +207,6 @@ const TabsContentContainer = function TabsContentContainer({ ref, children, clas
|
|
|
210
207
|
return /* @__PURE__ */ jsx("div", {
|
|
211
208
|
ref,
|
|
212
209
|
className: cn("overflow-hidden", className),
|
|
213
|
-
"data-testid": "spectral-tabs-content-container",
|
|
214
210
|
children: /* @__PURE__ */ jsx(AnimatePresence, {
|
|
215
211
|
mode: "wait",
|
|
216
212
|
initial: false,
|
|
@@ -246,7 +242,6 @@ const TabsContent = function TabsContent({ ref, className, value: contentValue,
|
|
|
246
242
|
"aria-labelledby": triggerId,
|
|
247
243
|
className: cn("tabs-content focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent", className),
|
|
248
244
|
"data-state": isActive ? "active" : "inactive",
|
|
249
|
-
"data-testid": "spectral-tabs-content",
|
|
250
245
|
hidden: !isActive,
|
|
251
246
|
id: contentId,
|
|
252
247
|
ref,
|
|
@@ -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 { 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\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 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 <div\n className={cn(\n 'top-0 left-0 pointer-events-none absolute 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 aria-hidden='true'\n style={{\n left: indicatorStyle.left,\n top: indicatorStyle.isEnclosed ? indicatorStyle.top + indicatorStyle.height * 0.1 : indicatorStyle.top,\n width: indicatorStyle.width,\n height: indicatorStyle.isEnclosed ? (indicatorStyle.orientation === 'vertical' ? 40 : indicatorStyle.height * 0.8) : indicatorStyle.height,\n }}\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 reducedMotion = prefersReducedMotion()\n\n return (\n <div\n ref={ref}\n className={cn('overflow-hidden', className)}\n data-testid='spectral-tabs-content-container'\n >\n <AnimatePresence mode='wait' initial={false}>\n <motion.div\n key={value}\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: 'easeOut',\n }\n }\n >\n {children}\n </motion.div>\n </AnimatePresence>\n </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-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent', 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 { 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\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 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 <div\n className={cn(\n 'top-0 left-0 pointer-events-none absolute 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 aria-hidden='true'\n style={{\n left: indicatorStyle.left,\n top: indicatorStyle.isEnclosed ? indicatorStyle.top + indicatorStyle.height * 0.1 : indicatorStyle.top,\n width: indicatorStyle.width,\n height: indicatorStyle.isEnclosed ? (indicatorStyle.orientation === 'vertical' ? 40 : indicatorStyle.height * 0.8) : indicatorStyle.height,\n }}\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 reducedMotion = prefersReducedMotion()\n\n return (\n <div\n ref={ref}\n className={cn('overflow-hidden', className)}\n data-testid='spectral-tabs-content-container'\n >\n <AnimatePresence mode='wait' initial={false}>\n <motion.div\n key={value}\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: 'easeOut',\n }\n }\n >\n {children}\n </motion.div>\n </AnimatePresence>\n </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-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent', 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/Textarea.js
CHANGED
|
@@ -51,7 +51,6 @@ const Textarea = (allProps) => {
|
|
|
51
51
|
className: "w-full",
|
|
52
52
|
children: [
|
|
53
53
|
label && /* @__PURE__ */ jsx(Label, {
|
|
54
|
-
"data-testid": "spectral-textarea-label",
|
|
55
54
|
htmlFor: textareaId,
|
|
56
55
|
className: cn("mb-2 block", isDisabled && "cursor-not-allowed opacity-50", labelClassName),
|
|
57
56
|
children: label
|
|
@@ -64,7 +63,6 @@ const Textarea = (allProps) => {
|
|
|
64
63
|
autoComplete: getAutoCompleteValue(autoComplete),
|
|
65
64
|
className: textareaClasses,
|
|
66
65
|
"data-state": state,
|
|
67
|
-
"data-testid": "spectral-textarea",
|
|
68
66
|
disabled: isDisabled,
|
|
69
67
|
id: textareaId,
|
|
70
68
|
name,
|
|
@@ -83,14 +81,12 @@ const Textarea = (allProps) => {
|
|
|
83
81
|
}),
|
|
84
82
|
isLoading && /* @__PURE__ */ jsx("div", {
|
|
85
83
|
className: LOADING_ICON_CLASSES,
|
|
86
|
-
"data-testid": "spectral-textarea-loading-icon",
|
|
87
84
|
children: /* @__PURE__ */ jsx(LoaderIcon, { size: 24 })
|
|
88
85
|
}),
|
|
89
86
|
showCounter && /* @__PURE__ */ jsxs("div", {
|
|
90
87
|
"aria-label": currentLength + " of " + maxLength + " characters used",
|
|
91
88
|
"aria-live": "polite",
|
|
92
89
|
className: getCounterClasses(currentLength, maxLength),
|
|
93
|
-
"data-testid": "spectral-textarea-counter",
|
|
94
90
|
role: "status",
|
|
95
91
|
children: [
|
|
96
92
|
currentLength,
|
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 /** Controls visibility of the bottom-right character counter (default: true). */\n showCounter?: boolean\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 showCounter = true,\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 className={LOADING_ICON_CLASSES} data-testid='spectral-textarea-loading-icon'>\n <LoaderIcon size={24} />\n </div>\n )}\n\n {showCounter && (\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 )}\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":";;;;;;;;;;;;AAoCA,MAAM,uBAAuB;AAE7B,MAAM,wBAAwB,iBAA6C;AACzE,KAAI,aAAc,QAAO;AACzB,QAAO;;AAGT,MAAM,qBAAqB,eAAuB,cAA8B;AAG9E,QAAO,GAAG,2EADS,iBAAiB,YAAY,oBAAoB,
|
|
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 /** Controls visibility of the bottom-right character counter (default: true). */\n showCounter?: boolean\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 showCounter = true,\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 className={LOADING_ICON_CLASSES} data-testid='spectral-textarea-loading-icon'>\n <LoaderIcon size={24} />\n </div>\n )}\n\n {showCounter && (\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 )}\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":";;;;;;;;;;;;AAoCA,MAAM,uBAAuB;AAE7B,MAAM,wBAAwB,iBAA6C;AACzE,KAAI,aAAc,QAAO;AACzB,QAAO;;AAGT,MAAM,qBAAqB,eAAuB,cAA8B;AAG9E,QAAO,GAAG,2EADS,iBAAiB,YAAY,oBAAoB,sBACnC;;AAGnC,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,cAAc,MACd,QAAQ,WACR,OAAO,WACP,gBACA,GAAG,UACD;CACJ,MAAM,aAAa,eAAe,IAAI,KAAI;CAC1C,MAAM,iBAAiB,kBAAkB,WAAU;CACnD,MAAM,mBAAmB,GAAG,WAAW;CACvC,MAAM,YAAY,UAAU,UAAU,iBAAiB,UAAU,aAAa,iBAAiB,mBAAmB;CAClH,MAAM,cAAc,OAA4B,KAAI;CACpD,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,CAAA;CAED,MAAM,EAAE,aAAa,YAAY,cAAc,gBAAgB,YAAY;EACzE;EACA;EACA,UAAU;EACV;EACA;EACD,CAAA;CAED,MAAM,EAAE,YAAY,cAAc,kBAAkB,UAAU,MAAK;CACnE,MAAM,YAAY,aAAa,OAAO,MAAM,qBAAqB,UAAU,UAAS;CACpF,MAAM,gBAAgB,OAAO,UAAU;CACvC,MAAM,kBAAkB,mBAAmB,OAAO,UAAS;CAE3D,MAAM,gCAAgC;EACpC,yBAAyB;EACzB,yBAAyB;EACzB,4BAA4B;EAC7B;AAED,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACG,SACC,oBAAC,OAAD;IAEE,SAAS;IACT,WAAW,GAAG,cAAc,cAAc,iCAAiC,eAAe;cAEzF;IACI;GAET,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAAC,YAAD;MACE,kBAAe;MACf,cAAc,qBAAqB,aAAa;MAChD,WAAW;MACX,cAAY;MAEZ,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;MACL;KAEA,aACC,oBAAC,OAAD;MAAK,WAAW;gBACd,oBAAC,YAAD,EAAY,MAAM,IAAK;MACpB;KAGN,eACC,qBAAC,OAAD;MAEE,cAAY,gBAAgB,SAAS,YAAY;MACjD,aAAU;MACV,WAAW,kBAAkB,eAAe,UAAU;MAEtD,MAAK;gBANP;OAQG;OAAc;OAAE;OACd;;KAEJ;;GAEL,oBAAC,cAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,UAAU,eAAe;IACvB;IACrB,qBAAqB,uBAAuB,UAAU;IACvD;GACD,oBAAC,gBAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,YAAY,iBAAiB;IAC3B;IACrB,qBAAqB,uBAAuB,UAAU;IACvD;GACE;;;AAGT,SAAS,cAAc"}
|
package/dist/Toast.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ interface ToastProps extends VariantProps<typeof toastVariants> {
|
|
|
18
18
|
icon?: ReactNode;
|
|
19
19
|
id?: string | number;
|
|
20
20
|
onAutoClose?: () => void;
|
|
21
|
+
onDismiss?: () => void;
|
|
21
22
|
position?: ToastPosition;
|
|
22
23
|
variant?: ToastVariant;
|
|
23
24
|
}
|
|
@@ -60,6 +61,7 @@ declare const toast: ((messageOrOptions: string | ToastProps, options?: ToastDef
|
|
|
60
61
|
error: (messageOrOptions: string | Omit<ToastProps, 'variant'>, options?: ToastVariantOptions) => string | number;
|
|
61
62
|
info: (messageOrOptions: string | Omit<ToastProps, 'variant'>, options?: ToastVariantOptions) => string | number;
|
|
62
63
|
warning: (messageOrOptions: string | Omit<ToastProps, 'variant'>, options?: ToastVariantOptions) => string | number;
|
|
64
|
+
dismiss: (id?: number | string) => string | number;
|
|
63
65
|
};
|
|
64
66
|
//#endregion
|
|
65
67
|
export { Toast, ToastProps, ToasterProps, toast };
|
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,iBAAA,YAA6B,SAAA;EAC7B,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,KAGG,mBAAA,GAAsB,IAAA,CAAK,UAAA;AAAA,KAC3B,mBAAA,GAAsB,IAAA,CAAK,UAAA;AAAA,cAG1B,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,iBAAA,YAA6B,SAAA;EAC7B,SAAA;EACA,kBAAA;EACA,UAAA;EACA,OAAA,YAAmB,SAAA;EACnB,QAAA;EACA,IAAA,GAAO,SAAA;EACP,EAAA;EACA,WAAA;EACA,SAAA;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,KAGG,mBAAA,GAAsB,IAAA,CAAK,UAAA;AAAA,KAC3B,mBAAA,GAAsB,IAAA,CAAK,UAAA;AAAA,cAG1B,aAAA,GAAa,KAAA;;IAajB,iCAAA,CAAA,SAAA;AAAA,cA4GW,KAAA;EAAA;;;;;;;;KAxDV,UAAA,GAAU,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;;;;OA3B6F,YAAA,GAAY,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;cAuFzG,KAAA,IAAK,gBAAA,WAtB4B,UAAA,EAAU,OAAA,GAAW,mBAAA;uCAS9B,IAAA,CAAK,UAAA,cAAsB,OAAA,GAAW,mBAAA"}
|
package/dist/Toast.js
CHANGED
|
@@ -10,7 +10,7 @@ import { cva } from "class-variance-authority";
|
|
|
10
10
|
import { Toaster, toast as toast$1 } from "sonner";
|
|
11
11
|
|
|
12
12
|
//#region src/components/Toast/Toast.tsx
|
|
13
|
-
const toastVariants = cva("rounded-md px-4 py-3 text-sm gap-3 shadow-
|
|
13
|
+
const toastVariants = cva("rounded-md px-4 py-3 text-sm gap-3 shadow-elevation-2 flex max-w-[420px] min-w-[300px] items-start border", {
|
|
14
14
|
variants: { variant: {
|
|
15
15
|
default: "border-toast-border bg-toast-bg text-toast-text",
|
|
16
16
|
success: "border-toast-success-border bg-toast-success-bg text-toast-success-text",
|
|
@@ -59,7 +59,6 @@ const ToastComponent = ({ additionalMessage, className, containerAriaLabel = "No
|
|
|
59
59
|
"aria-label": containerAriaLabel,
|
|
60
60
|
className: cn(toastVariants({ variant: resolvedVariant }), className),
|
|
61
61
|
"data-variant": resolvedVariant,
|
|
62
|
-
"data-testid": dataTestId ?? `spectral-toast-${resolvedVariant}`,
|
|
63
62
|
role: "status",
|
|
64
63
|
"aria-live": "polite",
|
|
65
64
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -75,27 +74,28 @@ const ToastComponent = ({ additionalMessage, className, containerAriaLabel = "No
|
|
|
75
74
|
})]
|
|
76
75
|
}), additionalMessage && /* @__PURE__ */ jsx("div", {
|
|
77
76
|
className: cn("mt-1 text-text-primary", hasIcon && "pl-8"),
|
|
78
|
-
"data-testid": "spectral-toast-additional-content",
|
|
79
77
|
children: typeof additionalMessage === "string" ? /* @__PURE__ */ jsx("p", { children: additionalMessage }) : /* @__PURE__ */ jsx(Fragment$1, { children: additionalMessage })
|
|
80
78
|
})]
|
|
81
79
|
})
|
|
82
80
|
});
|
|
83
81
|
};
|
|
84
82
|
ToastComponent.displayName = "Toast";
|
|
85
|
-
const showToast = ({ additionalMessage, className, containerAriaLabel, dataTestId, duration = 4e3, icon, message, onAutoClose, position, variant = "default" }) => {
|
|
86
|
-
return toast$1.custom((
|
|
83
|
+
const showToast = ({ additionalMessage, className, containerAriaLabel, dataTestId, duration = 4e3, icon, id, message, onAutoClose, onDismiss, position, variant = "default" }) => {
|
|
84
|
+
return toast$1.custom((toastId) => /* @__PURE__ */ jsx(ToastComponent, {
|
|
87
85
|
additionalMessage,
|
|
88
86
|
className,
|
|
89
87
|
containerAriaLabel,
|
|
90
88
|
dataTestId,
|
|
91
89
|
icon,
|
|
92
|
-
id,
|
|
90
|
+
id: toastId,
|
|
93
91
|
message,
|
|
94
92
|
variant
|
|
95
93
|
}), {
|
|
96
94
|
duration,
|
|
97
95
|
onAutoClose,
|
|
98
|
-
|
|
96
|
+
onDismiss,
|
|
97
|
+
position,
|
|
98
|
+
...id !== void 0 && { id }
|
|
99
99
|
});
|
|
100
100
|
};
|
|
101
101
|
const toastBase = (messageOrOptions, options = {}) => {
|
|
@@ -123,7 +123,8 @@ const toast = Object.assign(toastBase, {
|
|
|
123
123
|
success: createVariantToast("success"),
|
|
124
124
|
error: createVariantToast("error"),
|
|
125
125
|
info: createVariantToast("info"),
|
|
126
|
-
warning: createVariantToast("warning")
|
|
126
|
+
warning: createVariantToast("warning"),
|
|
127
|
+
dismiss: toast$1.dismiss
|
|
127
128
|
});
|
|
128
129
|
|
|
129
130
|
//#endregion
|
package/dist/Toast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.js","names":[
|
|
1
|
+
{"version":3,"file":"Toast.js","names":[],"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 additionalMessage?: string | ReactNode\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 onDismiss?: () => 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\ntype ToastDefaultOptions = Omit<ToastProps, 'message'>\ntype ToastVariantOptions = Omit<ToastProps, 'message' | 'variant'>\ntype ToastVariantShorthand = Exclude<ToastVariant, 'default'>\n\nconst toastVariants = cva('rounded-md px-4 py-3 text-sm gap-3 shadow-elevation-2 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('font-semibold', {\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 gap={gap}\n offset={offset}\n position={position}\n visibleToasts={visibleToasts}\n toastOptions={{\n unstyled: true,\n classNames: {\n toast: 'bg-black rounded-lg',\n },\n }}\n {...props}\n />\n )\n}\nToastProvider.displayName = 'Toast.Provider'\n\nconst ToastComponent = ({\n additionalMessage,\n className,\n containerAriaLabel = 'Notification',\n dataTestId,\n icon,\n message,\n variant = 'default',\n}: ToastProps) => {\n const resolvedVariant = variant ?? 'default'\n const displayIcon = icon ?? variantIcons[resolvedVariant]\n const hasIcon = Boolean(displayIcon)\n\n return (\n <div aria-label={containerAriaLabel} className={cn(toastVariants({ variant: resolvedVariant }), className)} data-variant={resolvedVariant} data-testid={dataTestId ?? `spectral-toast-${resolvedVariant}`} role='status' aria-live='polite'>\n <div className='flex flex-col'>\n <div className='flex items-center gap-3'>\n {displayIcon && (\n <div aria-hidden='true'>\n {displayIcon}\n </div>\n )}\n <p className={messageVariants({ variant: resolvedVariant })}>{message}</p>\n </div>\n {additionalMessage && (\n <div className={cn('mt-1 text-text-primary', hasIcon && 'pl-8')} data-testid='spectral-toast-additional-content'>\n {typeof additionalMessage === 'string' ? <p>{additionalMessage}</p> : <>{additionalMessage}</>}\n </div>\n )}\n </div>\n </div>\n )\n}\nToastComponent.displayName = 'Toast'\n\nconst showToast = ({ additionalMessage, className, containerAriaLabel, dataTestId, duration = 4000, icon, id, message, onAutoClose, onDismiss, position, variant = 'default' }: ToastProps) => {\n return sonnerToast.custom((toastId) => <ToastComponent additionalMessage={additionalMessage} className={className} containerAriaLabel={containerAriaLabel} dataTestId={dataTestId} icon={icon} id={toastId} message={message} variant={variant} />, {\n duration,\n onAutoClose,\n onDismiss,\n position,\n // Spreading an explicit `id: undefined` would clobber Sonner's generated id\n ...(id !== undefined && { id }),\n })\n}\n\nconst toastBase = (messageOrOptions: string | ToastProps, options: ToastDefaultOptions = {}) => {\n if (typeof messageOrOptions === 'string') {\n return showToast({ ...options, message: messageOrOptions })\n }\n\n return showToast(messageOrOptions)\n}\n\nconst createVariantToast = (variant: ToastVariantShorthand) => {\n return (messageOrOptions: string | Omit<ToastProps, 'variant'>, options: ToastVariantOptions = {}) => {\n if (typeof messageOrOptions === 'string') {\n return showToast({ ...options, message: messageOrOptions, variant })\n }\n\n return showToast({ ...messageOrOptions, variant })\n }\n}\n\nexport const Toast = Object.assign(ToastComponent, {\n Provider: ToastProvider,\n})\n\nexport const toast = Object.assign(toastBase, {\n success: createVariantToast('success'),\n error: createVariantToast('error'),\n info: createVariantToast('info'),\n warning: createVariantToast('warning'),\n dismiss: sonnerToast.dismiss,\n})\n"],"mappings":"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"}
|
package/dist/Toggle.js
CHANGED
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 Ref } from 'react'\nimport { getActiveColorStyle, type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\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\n 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\n 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\n 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\n 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 divided: '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 data-[state=on]:border-toggle-border--active aria-pressed:bg-toggle-bg--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 <ToggleBase ref={ref} disabled={disabled} data-slot='toggle' data-testid='spectral-toggle' className={cn(toggleVariants({ variant, size, layout }), className)} style={{ ...getActiveColorStyle(activeColor, activeTextColor), ...style }} {...props} />\n}\n"],"mappings":";;;;;;;;;AAeA,MAAa,iBAAiB,IAC5B;;;;+HAKA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,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,
|
|
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 Ref } from 'react'\nimport { getActiveColorStyle, type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\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\n 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\n 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\n 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\n 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 divided: '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 data-[state=on]:border-toggle-border--active aria-pressed:bg-toggle-bg--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 <ToggleBase ref={ref} disabled={disabled} data-slot='toggle' data-testid='spectral-toggle' className={cn(toggleVariants({ variant, size, layout }), className)} style={{ ...getActiveColorStyle(activeColor, activeTextColor), ...style }} {...props} />\n}\n"],"mappings":";;;;;;;;;AAeA,MAAa,iBAAiB,IAC5B;;;;+HAKA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,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,CACH;AAEA,MAAa,UAAU,EACrB,KACA,WACA,SACA,MACA,QACA,UACA,cAAc,WACd,iBACA,OACA,GAAG,YAGC;AACJ,QAAO,oBAAC,YAAD;EAAiB;EAAe;EAAU,aAAU;EAAuC,WAAW,GAAG,eAAe;GAAE;GAAS;GAAM;GAAQ,CAAC,EAAE,UAAU;EAAE,OAAO;GAAE,GAAG,oBAAoB,aAAa,gBAAgB;GAAE,GAAG;GAAO;EAAE,GAAI;EAAQ"}
|
|
@@ -25,7 +25,6 @@ const ToggleGroupItem = ({ activeColor, activeTextColor, children, className, la
|
|
|
25
25
|
"data-layout": resolvedLayout,
|
|
26
26
|
"data-size": resolvedSize,
|
|
27
27
|
"data-slot": "toggle-group-item",
|
|
28
|
-
"data-testid": "spectral-toggle-group-item",
|
|
29
28
|
"data-variant": resolvedVariant,
|
|
30
29
|
ref,
|
|
31
30
|
style: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleGroupItem.js","names":[],"sources":["../../src/components/ToggleGroup/ToggleGroupItem.tsx"],"sourcesContent":["import { toggleVariants } from '@components/Toggle/Toggle'\nimport { getActiveColorStyle, type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\nimport { cn } from '@utils/twUtils'\nimport { type VariantProps } from 'class-variance-authority'\nimport { useContext, type ComponentProps, type Ref } from 'react'\nimport { ToggleGroupContext } from './ToggleGroup.context'\nimport { ToggleGroupItemBase } from './ToggleGroupBase'\n\nexport type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupItemBase> &\n VariantProps<typeof toggleVariants> & {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n }\n\nexport const ToggleGroupItem = ({\n activeColor,\n activeTextColor,\n children,\n className,\n layout,\n ref,\n size,\n style,\n value,\n variant,\n ...props\n}: ToggleGroupItemProps & {\n ref?: Ref<HTMLButtonElement>\n}) => {\n const context = useContext(ToggleGroupContext)\n const resolvedVariant = variant ?? context.variant\n const resolvedSize = size ?? context.size\n const resolvedLayout = layout ?? context.layout\n const resolvedActiveColor = activeColor ?? context.activeColor\n const resolvedActiveTextColor = activeTextColor ?? context.activeTextColor\n\n return (\n <ToggleGroupItemBase\n className={cn(\n toggleVariants({\n variant: resolvedVariant,\n size: resolvedSize,\n layout: resolvedLayout,\n }),\n 'group data-[variant=separated]:rounded-md rounded-none shadow-none focus:z-10 focus-visible:z-10 data-[variant=outline]:border-toggle-border data-[variant=outline]:hover:border-toggle-border',\n 'data-[variant=divided]:border-toggle-border data-[variant=divided]:hover:border-toggle-border data-[variant=outline]:data-[state=on]:border-toggle-border--active',\n 'data-[variant=outline]:data-[state=on]:hover:border-toggle-border--active data-[variant=divided]:data-[state=on]:border-toggle-border--active data-[variant=divided]:data-[state=on]:hover:border-toggle-border--active data-[variant=separated]:border-toggle-border',\n 'data-[variant=separated]:hover:border-toggle-border--hover data-[variant=separated]:data-[state=on]:border-toggle-border--active data-[variant=separated]:data-[state=on]:bg-toggle-bg--active',\n 'data-[variant=separated]:data-[state=on]:hover:border-toggle-border--active data-[variant=separated]:data-[state=on]:hover:bg-toggle-bg--active',\n className,\n )}\n data-layout={resolvedLayout}\n data-size={resolvedSize}\n data-slot='toggle-group-item'\n data-testid='spectral-toggle-group-item'\n data-variant={resolvedVariant}\n ref={ref}\n style={{ ...getActiveColorStyle(resolvedActiveColor, resolvedActiveTextColor), ...style }}\n value={value}\n {...props}\n >\n {children}\n </ToggleGroupItemBase>\n )\n}\n\nToggleGroupItem.displayName = 'ToggleGroupItem'\n"],"mappings":";;;;;;;;;;;AAcA,MAAa,mBAAmB,EAC9B,aACA,iBACA,UACA,WACA,QACA,KACA,MACA,OACA,OACA,SACA,GAAG,YAGC;CACJ,MAAM,UAAU,WAAW,
|
|
1
|
+
{"version":3,"file":"ToggleGroupItem.js","names":[],"sources":["../../src/components/ToggleGroup/ToggleGroupItem.tsx"],"sourcesContent":["import { toggleVariants } from '@components/Toggle/Toggle'\nimport { getActiveColorStyle, type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\nimport { cn } from '@utils/twUtils'\nimport { type VariantProps } from 'class-variance-authority'\nimport { useContext, type ComponentProps, type Ref } from 'react'\nimport { ToggleGroupContext } from './ToggleGroup.context'\nimport { ToggleGroupItemBase } from './ToggleGroupBase'\n\nexport type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupItemBase> &\n VariantProps<typeof toggleVariants> & {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n }\n\nexport const ToggleGroupItem = ({\n activeColor,\n activeTextColor,\n children,\n className,\n layout,\n ref,\n size,\n style,\n value,\n variant,\n ...props\n}: ToggleGroupItemProps & {\n ref?: Ref<HTMLButtonElement>\n}) => {\n const context = useContext(ToggleGroupContext)\n const resolvedVariant = variant ?? context.variant\n const resolvedSize = size ?? context.size\n const resolvedLayout = layout ?? context.layout\n const resolvedActiveColor = activeColor ?? context.activeColor\n const resolvedActiveTextColor = activeTextColor ?? context.activeTextColor\n\n return (\n <ToggleGroupItemBase\n className={cn(\n toggleVariants({\n variant: resolvedVariant,\n size: resolvedSize,\n layout: resolvedLayout,\n }),\n 'group data-[variant=separated]:rounded-md rounded-none shadow-none focus:z-10 focus-visible:z-10 data-[variant=outline]:border-toggle-border data-[variant=outline]:hover:border-toggle-border',\n 'data-[variant=divided]:border-toggle-border data-[variant=divided]:hover:border-toggle-border data-[variant=outline]:data-[state=on]:border-toggle-border--active',\n 'data-[variant=outline]:data-[state=on]:hover:border-toggle-border--active data-[variant=divided]:data-[state=on]:border-toggle-border--active data-[variant=divided]:data-[state=on]:hover:border-toggle-border--active data-[variant=separated]:border-toggle-border',\n 'data-[variant=separated]:hover:border-toggle-border--hover data-[variant=separated]:data-[state=on]:border-toggle-border--active data-[variant=separated]:data-[state=on]:bg-toggle-bg--active',\n 'data-[variant=separated]:data-[state=on]:hover:border-toggle-border--active data-[variant=separated]:data-[state=on]:hover:bg-toggle-bg--active',\n className,\n )}\n data-layout={resolvedLayout}\n data-size={resolvedSize}\n data-slot='toggle-group-item'\n data-testid='spectral-toggle-group-item'\n data-variant={resolvedVariant}\n ref={ref}\n style={{ ...getActiveColorStyle(resolvedActiveColor, resolvedActiveTextColor), ...style }}\n value={value}\n {...props}\n >\n {children}\n </ToggleGroupItemBase>\n )\n}\n\nToggleGroupItem.displayName = 'ToggleGroupItem'\n"],"mappings":";;;;;;;;;;;AAcA,MAAa,mBAAmB,EAC9B,aACA,iBACA,UACA,WACA,QACA,KACA,MACA,OACA,OACA,SACA,GAAG,YAGC;CACJ,MAAM,UAAU,WAAW,mBAAkB;CAC7C,MAAM,kBAAkB,WAAW,QAAQ;CAC3C,MAAM,eAAe,QAAQ,QAAQ;CACrC,MAAM,iBAAiB,UAAU,QAAQ;CACzC,MAAM,sBAAsB,eAAe,QAAQ;CACnD,MAAM,0BAA0B,mBAAmB,QAAQ;AAE3D,QACE,oBAAC,qBAAD;EACE,WAAW,GACT,eAAe;GACb,SAAS;GACT,MAAM;GACN,QAAQ;GACT,CAAC,EACF,kMACA,qKACA,yQACA,kMACA,mJACA,UACD;EACD,eAAa;EACb,aAAW;EACX,aAAU;EAEV,gBAAc;EACT;EACL,OAAO;GAAE,GAAG,oBAAoB,qBAAqB,wBAAwB;GAAE,GAAG;GAAO;EAClF;EACP,GAAI;EAEH;EACkB;;AAIzB,gBAAgB,cAAc"}
|
package/dist/ToggleGroup.js
CHANGED
package/dist/ToggleGroup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleGroup.js","names":[],"sources":["../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["import { type toggleVariants } from '@components/Toggle/Toggle'\nimport { type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\nimport { cn } from '@utils/twUtils'\nimport { type VariantProps } from 'class-variance-authority'\nimport { type ComponentProps } from 'react'\nimport { ToggleGroupContext } from './ToggleGroup.context'\nimport { ToggleGroupBase } from './ToggleGroupBase'\nexport { ToggleGroupItem, type ToggleGroupItemProps } from './ToggleGroupItem'\nexport { ToggleGroupSplitMenuItem, type ToggleGroupSplitMenuItemProps } from './ToggleGroupSplitMenuItem'\n\nexport type ToggleGroupProps = ComponentProps<typeof ToggleGroupBase> &\n VariantProps<typeof toggleVariants> & {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n }\n\nexport const ToggleGroup = ({ className, variant, size, layout, activeColor, activeTextColor, orientation, children, ...props }: ToggleGroupProps) => {\n return (\n <ToggleGroupBase\n className={cn(\n `group/toggle-group rounded-md [&_button:first-of-type]:rounded-l-md [&_button:last-of-type]:rounded-r-md data-[variant='outline']:gap-0 data-[variant='divided']:gap-0 data-[variant='separated']:gap-1.5\n data-[size='sm']:data-[variant='separated']:gap-1 data-[size='lg']:data-[variant='separated']:gap-2 flex h-fit w-fit items-center data-[layout='expanded']:w-full\n data-[variant='outline']:[--color-toggle-border:var(--color-toggle-outline-border)] data-[variant='outline']:[&_button:not(:first-of-type)]:border-l-0\n data-[variant='outline']:[&_button:not(:last-of-type)]:[border-right-color:var(--color-toggle-outline-divider)]\n data-[variant='outline']:[&_button[data-state='on']:not(:last-of-type)]:[border-right-color:var(--color-toggle-border--active)]\n data-[variant='divided']:[--color-toggle-border:var(--color-toggle-outline-border)] data-[variant='divided']:[&_button:not(:first-of-type)]:border-l-0\n data-[variant='divided']:[&_button:not(:last-of-type)]:[border-right-color:var(--color-toggle-outline-divider)] data-[variant='divided']:[&_button]:border-y-0\n data-[variant='divided']:[&_button:first-of-type]:border-l-0 data-[variant='divided']:[&_button:last-of-type]:border-r-0\n data-[variant='divided']:[&_button[data-state='on']:not(:last-of-type)]:[border-right-color:var(--color-toggle-border--active)]`,\n className,\n )}\n data-layout={layout}\n data-size={size}\n data-slot='toggle-group'\n data-testid='spectral-toggle-group'\n data-variant={variant}\n orientation={orientation}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size, layout, activeColor, activeTextColor, orientation }}>{children}</ToggleGroupContext.Provider>\n </ToggleGroupBase>\n )\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,eAAe,EAAE,WAAW,SAAS,MAAM,QAAQ,aAAa,iBAAiB,aAAa,UAAU,GAAG,YAA8B;AACpJ,QACE,oBAAC,iBAAD;EACE,WAAW,GACT;;;;;;;;0IASA,UACD;EACD,eAAa;EACb,aAAW;EACX,aAAU;
|
|
1
|
+
{"version":3,"file":"ToggleGroup.js","names":[],"sources":["../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["import { type toggleVariants } from '@components/Toggle/Toggle'\nimport { type ActiveColor, type ActiveTextColor } from '@utils/activeColorStyle'\nimport { cn } from '@utils/twUtils'\nimport { type VariantProps } from 'class-variance-authority'\nimport { type ComponentProps } from 'react'\nimport { ToggleGroupContext } from './ToggleGroup.context'\nimport { ToggleGroupBase } from './ToggleGroupBase'\nexport { ToggleGroupItem, type ToggleGroupItemProps } from './ToggleGroupItem'\nexport { ToggleGroupSplitMenuItem, type ToggleGroupSplitMenuItemProps } from './ToggleGroupSplitMenuItem'\n\nexport type ToggleGroupProps = ComponentProps<typeof ToggleGroupBase> &\n VariantProps<typeof toggleVariants> & {\n activeColor?: ActiveColor\n activeTextColor?: ActiveTextColor\n }\n\nexport const ToggleGroup = ({ className, variant, size, layout, activeColor, activeTextColor, orientation, children, ...props }: ToggleGroupProps) => {\n return (\n <ToggleGroupBase\n className={cn(\n `group/toggle-group rounded-md [&_button:first-of-type]:rounded-l-md [&_button:last-of-type]:rounded-r-md data-[variant='outline']:gap-0 data-[variant='divided']:gap-0 data-[variant='separated']:gap-1.5\n data-[size='sm']:data-[variant='separated']:gap-1 data-[size='lg']:data-[variant='separated']:gap-2 flex h-fit w-fit items-center data-[layout='expanded']:w-full\n data-[variant='outline']:[--color-toggle-border:var(--color-toggle-outline-border)] data-[variant='outline']:[&_button:not(:first-of-type)]:border-l-0\n data-[variant='outline']:[&_button:not(:last-of-type)]:[border-right-color:var(--color-toggle-outline-divider)]\n data-[variant='outline']:[&_button[data-state='on']:not(:last-of-type)]:[border-right-color:var(--color-toggle-border--active)]\n data-[variant='divided']:[--color-toggle-border:var(--color-toggle-outline-border)] data-[variant='divided']:[&_button:not(:first-of-type)]:border-l-0\n data-[variant='divided']:[&_button:not(:last-of-type)]:[border-right-color:var(--color-toggle-outline-divider)] data-[variant='divided']:[&_button]:border-y-0\n data-[variant='divided']:[&_button:first-of-type]:border-l-0 data-[variant='divided']:[&_button:last-of-type]:border-r-0\n data-[variant='divided']:[&_button[data-state='on']:not(:last-of-type)]:[border-right-color:var(--color-toggle-border--active)]`,\n className,\n )}\n data-layout={layout}\n data-size={size}\n data-slot='toggle-group'\n data-testid='spectral-toggle-group'\n data-variant={variant}\n orientation={orientation}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size, layout, activeColor, activeTextColor, orientation }}>{children}</ToggleGroupContext.Provider>\n </ToggleGroupBase>\n )\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,eAAe,EAAE,WAAW,SAAS,MAAM,QAAQ,aAAa,iBAAiB,aAAa,UAAU,GAAG,YAA8B;AACpJ,QACE,oBAAC,iBAAD;EACE,WAAW,GACT;;;;;;;;0IASA,UACD;EACD,eAAa;EACb,aAAW;EACX,aAAU;EAEV,gBAAc;EACD;EACb,GAAI;YAEJ,oBAAC,mBAAmB,UAApB;GAA6B,OAAO;IAAE;IAAS;IAAM;IAAQ;IAAa;IAAiB;IAAa;GAAG;GAAsC;EAClI"}
|
package/dist/Tooltip.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.d.ts","names":[],"sources":["../src/components/Tooltip/Tooltip.tsx"],"mappings":";;;;;;;;cAKa,eAAA;EAAe,aAAA;EAAA,GAAA;AAAA,GAAqC,cAAA,QAAsB,gBAAA,CAAiB,QAAA,MAAS,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAIpG,OAAA;EAAA,GAAO;AAAA,GAAkB,cAAA,QAAsB,gBAAA,CAAiB,IAAA,MAAK,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAQrE,cAAA;EAAc,OAAA;EAAA,QAAA;EAAA,SAAA;EAAA,GAAA;AAAA,GAAgD,cAAA,QAAsB,gBAAA,CAAiB,OAAA,MAAQ,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAQpH,eAAA,GAAe,KAAA;;
|
|
1
|
+
{"version":3,"file":"Tooltip.d.ts","names":[],"sources":["../src/components/Tooltip/Tooltip.tsx"],"mappings":";;;;;;;;cAKa,eAAA;EAAe,aAAA;EAAA,GAAA;AAAA,GAAqC,cAAA,QAAsB,gBAAA,CAAiB,QAAA,MAAS,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAIpG,OAAA;EAAA,GAAO;AAAA,GAAkB,cAAA,QAAsB,gBAAA,CAAiB,IAAA,MAAK,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAQrE,cAAA;EAAc,OAAA;EAAA,QAAA;EAAA,SAAA;EAAA,GAAA;AAAA,GAAgD,cAAA,QAAsB,gBAAA,CAAiB,OAAA,MAAQ,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,cAQpH,eAAA,GAAe,KAAA;;IAgBpB,iCAAA,CAAA,SAAA;AAAA,cAcY,cAAA;EAAc,QAAA;EAAA,SAAA;EAAA,SAAA;EAAA,IAAA;EAAA,UAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAQxB,cAAA,QAAsB,gBAAA,CAAiB,OAAA,IACxC,YAAA,QAAoB,eAAA;EAClB,SAAA;AAAA,MACD,oBAAA,CAAA,GAAA,CAAA,OAAA"}
|
package/dist/Tooltip.js
CHANGED
|
@@ -16,7 +16,6 @@ const TooltipProvider = ({ delayDuration = 0, ...props }) => {
|
|
|
16
16
|
const Tooltip = ({ ...props }) => {
|
|
17
17
|
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Root, {
|
|
18
18
|
"data-slot": "tooltip",
|
|
19
|
-
"data-testid": "spectral-tooltip",
|
|
20
19
|
...props
|
|
21
20
|
}) });
|
|
22
21
|
};
|
|
@@ -25,12 +24,14 @@ const TooltipTrigger = ({ asChild, children, className, ...props }) => {
|
|
|
25
24
|
asChild,
|
|
26
25
|
className: cn(!asChild && "w-fit", className),
|
|
27
26
|
"data-slot": "tooltip-trigger",
|
|
28
|
-
"data-testid": "spectral-tooltip-trigger",
|
|
29
27
|
...props,
|
|
30
28
|
children
|
|
31
29
|
});
|
|
32
30
|
};
|
|
33
|
-
const tooltipVariants = cva(`tooltip-effects rounded-md px-3 py-1.5 text-xs pointer-events-auto z-50 w-fit bg-tooltip-bg text-text-primary outline-none select-none
|
|
31
|
+
const tooltipVariants = cva(`tooltip-effects rounded-md px-3 py-1.5 text-xs pointer-events-auto z-50 w-fit bg-tooltip-bg text-text-primary focus:outline-none select-none focus-visible:outline-2 focus-visible:outline-offset-2
|
|
32
|
+
focus-visible:outline-accent motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=left]:slide-in-from-right-2 motion-safe:data-[side=right]:slide-in-from-left-2
|
|
33
|
+
motion-safe:data-[side=top]:slide-in-from-bottom-2 motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=closed]:zoom-out-95
|
|
34
|
+
motion-safe:data-[state=open]:animate-in motion-safe:data-[state=open]:fade-in-0 motion-safe:data-[state=open]:zoom-in-95`, {
|
|
34
35
|
variants: { variant: {
|
|
35
36
|
default: "",
|
|
36
37
|
outline: "border-2 border-tooltip-outline-border"
|
|
@@ -46,12 +47,10 @@ const tooltipArrowVariants = cva("size-2.5 z-[-1] rotate-45 rounded-[2px] bg-too
|
|
|
46
47
|
});
|
|
47
48
|
const TooltipContent = ({ children, className, showArrow = false, side, sideOffset = 0, variant = "default", ...props }) => {
|
|
48
49
|
return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, {
|
|
49
|
-
"data-testid": "spectral-tooltip-portal",
|
|
50
50
|
"data-slot": "tooltip-portal",
|
|
51
51
|
children: /* @__PURE__ */ jsxs(TooltipPrimitive.Content, {
|
|
52
52
|
className: cn(tooltipVariants({ variant }), className),
|
|
53
53
|
"data-slot": "tooltip-content",
|
|
54
|
-
"data-testid": "spectral-tooltip-content",
|
|
55
54
|
side,
|
|
56
55
|
sideOffset,
|
|
57
56
|
...props,
|
package/dist/Tooltip.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","names":[],"sources":["../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from '@radix-ui/react-tooltip'\nimport { cn } from '@utils/twUtils'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type ComponentProps } from 'react'\n\nexport const TooltipProvider = ({ delayDuration = 0, ...props }: ComponentProps<typeof TooltipPrimitive.Provider>) => {\n return <TooltipPrimitive.Provider data-slot='tooltip-provider' delayDuration={delayDuration} {...props} />\n}\n\nexport const Tooltip = ({ ...props }: ComponentProps<typeof TooltipPrimitive.Root>) => {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot='tooltip' data-testid='spectral-tooltip' {...props} />\n </TooltipProvider>\n )\n}\n\nexport const TooltipTrigger = ({ asChild, children, className, ...props }: ComponentProps<typeof TooltipPrimitive.Trigger>) => {\n return (\n <TooltipPrimitive.Trigger asChild={asChild} className={cn(!asChild && 'w-fit', className)} data-slot='tooltip-trigger' data-testid='spectral-tooltip-trigger' {...props}>\n {children}\n </TooltipPrimitive.Trigger>\n )\n}\n\nconst tooltipVariants = cva(\n `tooltip-effects rounded-md px-3 py-1.5 text-xs pointer-events-auto z-50 w-fit bg-tooltip-bg text-text-primary outline-none select-none motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=left]:slide-in-from-right-2 motion-safe:data-[side=right]:slide-in-from-left-2
|
|
1
|
+
{"version":3,"file":"Tooltip.js","names":[],"sources":["../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from '@radix-ui/react-tooltip'\nimport { cn } from '@utils/twUtils'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { type ComponentProps } from 'react'\n\nexport const TooltipProvider = ({ delayDuration = 0, ...props }: ComponentProps<typeof TooltipPrimitive.Provider>) => {\n return <TooltipPrimitive.Provider data-slot='tooltip-provider' delayDuration={delayDuration} {...props} />\n}\n\nexport const Tooltip = ({ ...props }: ComponentProps<typeof TooltipPrimitive.Root>) => {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot='tooltip' data-testid='spectral-tooltip' {...props} />\n </TooltipProvider>\n )\n}\n\nexport const TooltipTrigger = ({ asChild, children, className, ...props }: ComponentProps<typeof TooltipPrimitive.Trigger>) => {\n return (\n <TooltipPrimitive.Trigger asChild={asChild} className={cn(!asChild && 'w-fit', className)} data-slot='tooltip-trigger' data-testid='spectral-tooltip-trigger' {...props}>\n {children}\n </TooltipPrimitive.Trigger>\n )\n}\n\nconst tooltipVariants = cva(\n `tooltip-effects rounded-md px-3 py-1.5 text-xs pointer-events-auto z-50 w-fit bg-tooltip-bg text-text-primary focus:outline-none select-none focus-visible:outline-2 focus-visible:outline-offset-2\n focus-visible:outline-accent motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=left]:slide-in-from-right-2 motion-safe:data-[side=right]:slide-in-from-left-2\n motion-safe:data-[side=top]:slide-in-from-bottom-2 motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=closed]:zoom-out-95\n motion-safe:data-[state=open]:animate-in motion-safe:data-[state=open]:fade-in-0 motion-safe:data-[state=open]:zoom-in-95`,\n {\n variants: {\n variant: {\n default: '',\n outline: 'border-2 border-tooltip-outline-border',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n)\n\nconst tooltipArrowVariants = cva('size-2.5 z-[-1] rotate-45 rounded-[2px] bg-tooltip-arrow fill-tooltip-arrow', {\n variants: {\n variant: {\n default: '-translate-y-[calc(50%+1px)]',\n outline: '-translate-y-[calc(50%-1.5px)] border-2 border-t-0 border-l-0 border-tooltip-outline-arrow',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n})\n\nexport const TooltipContent = ({\n children,\n className,\n showArrow = false,\n side,\n sideOffset = 0,\n variant = 'default',\n ...props\n}: ComponentProps<typeof TooltipPrimitive.Content> &\n VariantProps<typeof tooltipVariants> & {\n showArrow?: boolean\n }) => {\n return (\n <TooltipPrimitive.Portal data-testid='spectral-tooltip-portal' data-slot='tooltip-portal'>\n <TooltipPrimitive.Content className={cn(tooltipVariants({ variant }), className)} data-slot='tooltip-content' data-testid='spectral-tooltip-content' side={side} sideOffset={sideOffset} {...props}>\n {children}\n {showArrow && <TooltipPrimitive.Arrow className={cn(tooltipArrowVariants({ variant }))} height={8} />}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )\n}\n"],"mappings":";;;;;;;;AAKA,MAAa,mBAAmB,EAAE,gBAAgB,GAAG,GAAG,YAA8D;AACpH,QAAO,oBAAC,iBAAiB,UAAlB;EAA2B,aAAU;EAAkC;EAAe,GAAI;EAAQ;;AAG3G,MAAa,WAAW,EAAE,GAAG,YAA0D;AACrF,QACE,oBAAC,iBAAD,YACE,oBAAC,iBAAiB,MAAlB;EAAuB,aAAU;EAAyC,GAAI;EAAQ,GACvE;;AAIrB,MAAa,kBAAkB,EAAE,SAAS,UAAU,WAAW,GAAG,YAA6D;AAC7H,QACE,oBAAC,iBAAiB,SAAlB;EAAmC;EAAS,WAAW,GAAG,CAAC,WAAW,SAAS,UAAU;EAAE,aAAU;EAAyD,GAAI;EAC/J;EACuB;;AAI9B,MAAM,kBAAkB,IACtB;;;8HAIA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,SAAS;EACV,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACH;AAEA,MAAM,uBAAuB,IAAI,+EAA+E;CAC9G,UAAU,EACR,SAAS;EACP,SAAS;EACT,SAAS;EACV,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CAAA;AAED,MAAa,kBAAkB,EAC7B,UACA,WACA,YAAY,OACZ,MACA,aAAa,GACb,UAAU,WACV,GAAG,YAIG;AACN,QACE,oBAAC,iBAAiB,QAAlB;EAA+D,aAAU;YACvE,qBAAC,iBAAiB,SAAlB;GAA0B,WAAW,GAAG,gBAAgB,EAAE,SAAS,CAAC,EAAE,UAAU;GAAE,aAAU;GAA+D;GAAkB;GAAY,GAAI;aAA7L,CACG,UACA,aAAa,oBAAC,iBAAiB,OAAlB;IAAwB,WAAW,GAAG,qBAAqB,EAAE,SAAS,CAAC,CAAC;IAAE,QAAQ;IAAK,EAC7E;;EACH"}
|