@karakuri-ui/react 0.3.10 → 0.3.12
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/components/ui/accordion.d.mts +1 -1
- package/dist/components/ui/accordion.d.ts +1 -1
- package/dist/components/ui/alert.d.mts +2 -0
- package/dist/components/ui/alert.d.ts +2 -0
- package/dist/components/ui/alert.js +2 -1
- package/dist/components/ui/alert.js.map +1 -1
- package/dist/components/ui/alert.mjs +2 -1
- package/dist/components/ui/alert.mjs.map +1 -1
- package/dist/components/ui/badge.d.mts +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.js +54 -43
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/badge.mjs +55 -44
- package/dist/components/ui/badge.mjs.map +1 -1
- package/dist/components/ui/button.js +31 -20
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/button.mjs +31 -20
- package/dist/components/ui/button.mjs.map +1 -1
- package/dist/components/ui/chart.d.mts +1 -1
- package/dist/components/ui/chart.d.ts +1 -1
- package/dist/components/ui/drawer.d.mts +2 -0
- package/dist/components/ui/drawer.d.ts +2 -0
- package/dist/components/ui/drawer.js +2 -2
- package/dist/components/ui/drawer.js.map +1 -1
- package/dist/components/ui/drawer.mjs +2 -2
- package/dist/components/ui/drawer.mjs.map +1 -1
- package/dist/components/ui/dropdown.js +35 -18
- package/dist/components/ui/dropdown.js.map +1 -1
- package/dist/components/ui/dropdown.mjs +35 -18
- package/dist/components/ui/dropdown.mjs.map +1 -1
- package/dist/components/ui/icon-button.js +24 -13
- package/dist/components/ui/icon-button.js.map +1 -1
- package/dist/components/ui/icon-button.mjs +24 -13
- package/dist/components/ui/icon-button.mjs.map +1 -1
- package/dist/components/ui/modal.d.mts +2 -0
- package/dist/components/ui/modal.d.ts +2 -0
- package/dist/components/ui/modal.js +2 -2
- package/dist/components/ui/modal.js.map +1 -1
- package/dist/components/ui/modal.mjs +2 -2
- package/dist/components/ui/modal.mjs.map +1 -1
- package/dist/components/ui/navigation-menu.js +25 -11
- package/dist/components/ui/navigation-menu.js.map +1 -1
- package/dist/components/ui/navigation-menu.mjs +25 -11
- package/dist/components/ui/navigation-menu.mjs.map +1 -1
- package/dist/components/ui/popover.d.mts +2 -0
- package/dist/components/ui/popover.d.ts +2 -0
- package/dist/components/ui/popover.js +2 -2
- package/dist/components/ui/popover.js.map +1 -1
- package/dist/components/ui/popover.mjs +2 -2
- package/dist/components/ui/popover.mjs.map +1 -1
- package/dist/components/ui/segmented.js +3 -1
- package/dist/components/ui/segmented.js.map +1 -1
- package/dist/components/ui/segmented.mjs +3 -1
- package/dist/components/ui/segmented.mjs.map +1 -1
- package/dist/components/ui/select.js +16 -1
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/select.mjs +16 -1
- package/dist/components/ui/select.mjs.map +1 -1
- package/dist/components/ui/toast.d.mts +3 -1
- package/dist/components/ui/toast.d.ts +3 -1
- package/dist/components/ui/toast.js +4 -1
- package/dist/components/ui/toast.js.map +1 -1
- package/dist/components/ui/toast.mjs +4 -1
- package/dist/components/ui/toast.mjs.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/select.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\n// Radius (matches Input — set at Root, propagates to Trigger and Content)\ntype SelectRadius = 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n\nconst triggerRadiusMap: Record<SelectRadius, string> = {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n '3xl': 'rounded-3xl',\n full: 'rounded-full',\n}\n\n// Auto-mapping: root radius → content radius (3 levels)\ntype SelectContentRadius = 'md' | 'lg' | 'xl'\n\nconst contentRadiusFromRoot: Record<SelectRadius, SelectContentRadius> = {\n none: 'md',\n sm: 'md',\n base: 'md',\n default: 'md',\n lg: 'lg',\n xl: 'xl',\n '2xl': 'xl',\n '3xl': 'xl',\n full: 'xl',\n}\n\nconst contentRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded-md', // 6px\n lg: 'rounded-lg', // 8px\n xl: 'rounded-xl', // 12px\n}\n\nconst itemRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded', // 4px — perceptual balance (67%)\n lg: 'rounded-md', // 6px — perceptual balance (75%)\n xl: 'rounded-lg', // 8px — perceptual balance (67%)\n}\n\n// Size variants (matches Input component)\ntype SelectSize = 'xs' | 'sm' | 'default' | 'lg' | 'xl'\n\n// Trigger sizes (identical to Input)\nconst triggerSizeMap: Record<SelectSize, string> = {\n xs: 'h-9 px-3 text-sm', // 36px\n sm: 'h-10 px-3 text-md', // 40px\n default: 'h-11 px-4 text-base', // 44px\n lg: 'h-12 px-4 text-base', // 48px\n xl: 'h-14 px-4 text-base', // 56px\n}\n\n// Trigger icon sizes (matches Input icon pattern)\nconst triggerIconSizeMap: Record<SelectSize, string> = {\n xs: 'icon-xs', // 14px\n sm: 'icon-xs', // 14px\n default: 'icon-sm', // 16px\n lg: 'icon-sm', // 16px\n xl: 'icon-sm', // 16px\n}\n\n// Auto-mapping: trigger size → content item size (3 levels)\ntype SelectItemSize = 'sm' | 'md' | 'lg'\n\nconst itemSizeFromTrigger: Record<SelectSize, SelectItemSize> = {\n xs: 'sm',\n sm: 'sm',\n default: 'md',\n lg: 'md',\n xl: 'lg',\n}\n\n// Item sizes (font matches Trigger for seamless selection, padding controls density)\nconst itemSizeMap: Record<SelectItemSize, string> = {\n sm: 'pl-2 pr-6 py-1.5 text-sm',\n md: 'pl-3 pr-8 py-1.5 text-base',\n lg: 'pl-3 pr-10 py-2.5 text-base',\n}\n\n// Item indicator (check mark) — right-aligned\nconst indicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-2 h-3 w-3',\n md: 'right-2 h-3.5 w-3.5',\n lg: 'right-3 h-4 w-4',\n}\n\n// Label sizes\nconst labelSizeMap: Record<SelectItemSize, string> = {\n sm: 'px-2 py-1.5 text-xs',\n md: 'px-2 py-1.5 text-xs',\n lg: 'px-3 py-2.5 text-xs',\n}\n\n// Flush mode — items span full width, no inner radius\nconst flushItemPaddingMap: Record<SelectItemSize, string> = {\n sm: 'pl-3 pr-7',\n md: 'pl-4 pr-9',\n lg: 'pl-4 pr-11',\n}\n\nconst flushIndicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-3 h-3 w-3',\n md: 'right-3 h-3.5 w-3.5',\n lg: 'right-4 h-4 w-4',\n}\n\nconst flushLabelPaddingMap: Record<SelectItemSize, string> = {\n sm: 'px-3',\n md: 'px-3',\n lg: 'px-4',\n}\n\n// Root context — set at Root, consumed by Trigger and Content\nconst SelectContext = React.createContext<{\n size: SelectSize\n radius: SelectRadius\n}>({ size: 'default', radius: 'default' })\n\n// Style context — set at Content, consumed by Item/Label\nconst SelectStyleContext = React.createContext<{\n contentRadius: SelectContentRadius\n itemSize: SelectItemSize\n flush: boolean\n}>({ contentRadius: 'xl', itemSize: 'md', flush: false })\n\n// Root — state management + size/radius context. Inside a Field it inherits the\n// Field's disabled state, like Input and Textarea.\nconst Select = ({\n size = 'default',\n radius = 'default',\n disabled,\n ...props\n}: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {\n size?: SelectSize\n radius?: SelectRadius\n}) => {\n const fieldContext = useFieldContext()\n return (\n <SelectContext.Provider value={{ size, radius }}>\n <SelectPrimitive.Root disabled={disabled ?? fieldContext?.disabled} {...props} />\n </SelectContext.Provider>\n )\n}\n\n// Value — displays selected value or placeholder\nconst SelectValue = SelectPrimitive.Value\n\n// Group — groups related items\nconst SelectGroup = SelectPrimitive.Group\n\n// Trigger — the element that opens the select (reads size + radius from context)\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, id, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectContext)\n // Inside a Field the trigger takes the Field id, so FieldLabel names it\n const fieldContext = useFieldContext()\n useFieldControl('single', Boolean(fieldContext) && !id)\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n id={id ?? fieldContext?.id}\n aria-required={(!id && fieldContext?.required) || undefined}\n className={cn(\n 'flex w-full items-center justify-between bg-background text-foreground hover:bg-background-muted',\n 'border border-border-form',\n triggerRadiusMap[radius],\n 'transition-colors duration-micro outline-transparent',\n 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)] focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'data-[placeholder]:text-foreground/30',\n triggerSizeMap[size],\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <svg\n className={cn('ml-2 shrink-0 text-text-muted', triggerIconSizeMap[size])}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n})\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\n// ScrollUpButton — scroll indicator at top\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 15l7-7 7 7\" />\n </svg>\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\n// ScrollDownButton — scroll indicator at bottom\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\n// Content — the floating panel (reads size + radius from context, auto-maps both)\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n flush?: boolean\n }\n>(({ className, children, position = 'popper', sideOffset = 1, flush = false, onCloseAutoFocus, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectContext)\n const itemSize = itemSizeFromTrigger[size]\n const contentRadius = contentRadiusFromRoot[radius]\n return (\n <SelectPrimitive.Portal>\n <SelectStyleContext.Provider value={{ contentRadius, itemSize, flush }}>\n <SelectPrimitive.Content\n ref={ref}\n onCloseAutoFocus={(e) => {\n e.preventDefault()\n onCloseAutoFocus?.(e)\n }}\n className={cn(\n 'relative z-popover min-w-[var(--radix-select-trigger-width)] overflow-hidden border border-border bg-background text-foreground shadow-lg',\n flush ? 'py-1' : 'p-1',\n contentRadiusMap[contentRadius],\n position === 'popper' &&\n 'max-h-[var(--radix-select-content-available-height)]',\n className\n )}\n position={position}\n sideOffset={sideOffset}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n position === 'popper' &&\n 'h-[var(--radix-select-content-available-height)] w-full'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectStyleContext.Provider>\n </SelectPrimitive.Portal>\n )\n})\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\n// Item — a single selectable item (with right-aligned check indicator)\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => {\n const { contentRadius, itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center outline-none',\n itemSizeMap[itemSize],\n !flush && itemRadiusMap[contentRadius],\n flush && flushItemPaddingMap[itemSize],\n 'transition-colors duration-fast',\n 'focus:bg-background-muted',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"truncate\">{children}</SelectPrimitive.ItemText>\n <span className={cn('absolute flex items-center justify-center', flush ? flushIndicatorSizeMap[itemSize] : indicatorSizeMap[itemSize])}>\n <SelectPrimitive.ItemIndicator>\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </SelectPrimitive.ItemIndicator>\n </span>\n </SelectPrimitive.Item>\n )\n})\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\n// Label — non-interactive group heading\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => {\n const { itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\n 'font-semibold text-text-muted',\n labelSizeMap[itemSize],\n flush && flushLabelPaddingMap[itemSize],\n className\n )}\n {...props}\n />\n )\n})\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\n// Separator — visual divider between groups\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => {\n const { flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('h-px bg-border my-1', !flush && '-mx-1', className)}\n {...props}\n />\n )\n})\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport type { SelectRadius, SelectSize }\n\nexport {\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n SelectGroup,\n SelectLabel,\n SelectSeparator,\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoJM;AAlJN,YAAuB;AACvB,sBAAiC;AACjC,mBAAmB;AACnB,mBAAiD;AAKjD,MAAM,mBAAiD;AAAA,EACrD,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AACR;AAKA,MAAM,wBAAmE;AAAA,EACvE,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AACR;AAEA,MAAM,mBAAwD;AAAA,EAC5D,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAEA,MAAM,gBAAqD;AAAA,EACzD,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAMA,MAAM,iBAA6C;AAAA,EACjD,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAGA,MAAM,qBAAiD;AAAA,EACrD,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAKA,MAAM,sBAA0D;AAAA,EAC9D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,MAAM,cAA8C;AAAA,EAClD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,MAAM,mBAAmD;AAAA,EACvD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,MAAM,eAA+C;AAAA,EACnD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,MAAM,sBAAsD;AAAA,EAC1D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,MAAM,wBAAwD;AAAA,EAC5D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,MAAM,uBAAuD;AAAA,EAC3D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,MAAM,gBAAgB,MAAM,cAGzB,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AAGzC,MAAM,qBAAqB,MAAM,cAI9B,EAAE,eAAe,MAAM,UAAU,MAAM,OAAO,MAAM,CAAC;AAIxD,MAAM,SAAS,CAAC;AAAA,EACd,OAAO;AAAA,EACP,SAAS;AAAA,EACT;AAAA,EACA,GAAG;AACL,MAGM;AACJ,QAAM,mBAAe,8BAAgB;AACrC,SACE,4CAAC,cAAc,UAAd,EAAuB,OAAO,EAAE,MAAM,OAAO,GAC5C,sDAAC,gBAAgB,MAAhB,EAAqB,UAAU,YAAY,cAAc,UAAW,GAAG,OAAO,GACjF;AAEJ;AAGA,MAAM,cAAc,gBAAgB;AAGpC,MAAM,cAAc,gBAAgB;AAGpC,MAAM,gBAAgB,MAAM,WAG1B,CAAC,EAAE,WAAW,UAAU,IAAI,GAAG,MAAM,GAAG,QAAQ;AAChD,QAAM,EAAE,MAAM,OAAO,IAAI,MAAM,WAAW,aAAa;AAEvD,QAAM,mBAAe,8BAAgB;AACrC,oCAAgB,UAAU,QAAQ,YAAY,KAAK,CAAC,EAAE;AACtD,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,IAAI,MAAM,cAAc;AAAA,MACxB,iBAAgB,CAAC,MAAM,cAAc,YAAa;AAAA,MAClD,eAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA,iBAAiB,MAAM;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,IAAI;AAAA,QACnB;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,QACD,4CAAC,gBAAgB,MAAhB,EAAqB,SAAO,MAC3B;AAAA,UAAC;AAAA;AAAA,YACC,eAAW,iBAAG,iCAAiC,mBAAmB,IAAI,CAAC;AAAA,YACvE,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,QAAO;AAAA,YACP,aAAa;AAAA,YACb,eAAY;AAAA,YAEZ,sDAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kBAAiB;AAAA;AAAA,QACxE,GACF;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;AACD,cAAc,cAAc,gBAAgB,QAAQ;AAGpD,MAAM,uBAAuB,MAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,eAAW,iBAAG,wDAAwD,SAAS;AAAA,IAC9E,GAAG;AAAA,IAEJ,sDAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,aAAa,GAAG,eAAY,QACzG,sDAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,iBAAgB,GACvE;AAAA;AACF,CACD;AACD,qBAAqB,cAAc,gBAAgB,eAAe;AAGlE,MAAM,yBAAyB,MAAM,WAGnC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,eAAW,iBAAG,wDAAwD,SAAS;AAAA,IAC9E,GAAG;AAAA,IAEJ,sDAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,aAAa,GAAG,eAAY,QACzG,sDAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kBAAiB,GACxE;AAAA;AACF,CACD;AACD,uBAAuB,cAAc,gBAAgB,iBAAiB;AAGtE,MAAM,gBAAgB,MAAM,WAK1B,CAAC,EAAE,WAAW,UAAU,WAAW,UAAU,aAAa,GAAG,QAAQ,OAAO,kBAAkB,GAAG,MAAM,GAAG,QAAQ;AAClH,QAAM,EAAE,MAAM,OAAO,IAAI,MAAM,WAAW,aAAa;AACvD,QAAM,WAAW,oBAAoB,IAAI;AACzC,QAAM,gBAAgB,sBAAsB,MAAM;AAClD,SACE,4CAAC,gBAAgB,QAAhB,EACC,sDAAC,mBAAmB,UAAnB,EAA4B,OAAO,EAAE,eAAe,UAAU,MAAM,GACnE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,kBAAkB,CAAC,MAAM;AACvB,UAAE,eAAe;AACjB,2BAAmB,CAAC;AAAA,MACtB;AAAA,MACA,eAAW;AAAA,QACT;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB,iBAAiB,aAAa;AAAA,QAC9B,aAAa,YACX;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,oDAAC,wBAAqB;AAAA,QACtB;AAAA,UAAC,gBAAgB;AAAA,UAAhB;AAAA,YACC,eAAW;AAAA,cACT,aAAa,YACX;AAAA,YACJ;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QACA,4CAAC,0BAAuB;AAAA;AAAA;AAAA,EAC1B,GACF,GACF;AAEJ,CAAC;AACD,cAAc,cAAc,gBAAgB,QAAQ;AAGpD,MAAM,aAAa,MAAM,WAGvB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AAC5C,QAAM,EAAE,eAAe,UAAU,MAAM,IAAI,MAAM,WAAW,kBAAkB;AAC9E,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,eAAW;AAAA,QACT;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB,CAAC,SAAS,cAAc,aAAa;AAAA,QACrC,SAAS,oBAAoB,QAAQ;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,oDAAC,gBAAgB,UAAhB,EAAyB,WAAU,YAAY,UAAS;AAAA,QACzD,4CAAC,UAAK,eAAW,iBAAG,6CAA6C,QAAQ,sBAAsB,QAAQ,IAAI,iBAAiB,QAAQ,CAAC,GACnI,sDAAC,gBAAgB,eAAhB,EACC,sDAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,aAAa,GAAG,eAAY,QACzG,sDAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kBAAiB,GACxE,GACF,GACF;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;AACD,WAAW,cAAc,gBAAgB,KAAK;AAG9C,MAAM,cAAc,MAAM,WAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,EAAE,UAAU,MAAM,IAAI,MAAM,WAAW,kBAAkB;AAC/D,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,eAAW;AAAA,QACT;AAAA,QACA,aAAa,QAAQ;AAAA,QACrB,SAAS,qBAAqB,QAAQ;AAAA,QACtC;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,YAAY,cAAc,gBAAgB,MAAM;AAGhD,MAAM,kBAAkB,MAAM,WAG5B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,EAAE,MAAM,IAAI,MAAM,WAAW,kBAAkB;AACrD,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,eAAW,iBAAG,uBAAuB,CAAC,SAAS,SAAS,SAAS;AAAA,MAChE,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,gBAAgB,cAAc,gBAAgB,UAAU;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/select.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\n// Radius (matches Input — set at Root, propagates to Trigger and Content)\ntype SelectRadius = 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n\nconst triggerRadiusMap: Record<SelectRadius, string> = {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n '3xl': 'rounded-3xl',\n full: 'rounded-full',\n}\n\n// Auto-mapping: root radius → content radius (3 levels)\ntype SelectContentRadius = 'md' | 'lg' | 'xl'\n\nconst contentRadiusFromRoot: Record<SelectRadius, SelectContentRadius> = {\n none: 'md',\n sm: 'md',\n base: 'md',\n default: 'md',\n lg: 'lg',\n xl: 'xl',\n '2xl': 'xl',\n '3xl': 'xl',\n full: 'xl',\n}\n\nconst contentRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded-md', // 6px\n lg: 'rounded-lg', // 8px\n xl: 'rounded-xl', // 12px\n}\n\nconst itemRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded', // 4px — perceptual balance (67%)\n lg: 'rounded-md', // 6px — perceptual balance (75%)\n xl: 'rounded-lg', // 8px — perceptual balance (67%)\n}\n\n// Size variants (matches Input component)\ntype SelectSize = 'xs' | 'sm' | 'default' | 'lg' | 'xl'\n\n// Trigger sizes (identical to Input)\nconst triggerSizeMap: Record<SelectSize, string> = {\n xs: 'h-9 px-3 text-sm', // 36px\n sm: 'h-10 px-3 text-md', // 40px\n default: 'h-11 px-4 text-base', // 44px\n lg: 'h-12 px-4 text-base', // 48px\n xl: 'h-14 px-4 text-base', // 56px\n}\n\n// Trigger icon sizes (matches Input icon pattern)\nconst triggerIconSizeMap: Record<SelectSize, string> = {\n xs: 'icon-xs', // 14px\n sm: 'icon-xs', // 14px\n default: 'icon-sm', // 16px\n lg: 'icon-sm', // 16px\n xl: 'icon-sm', // 16px\n}\n\n// Auto-mapping: trigger size → content item size (3 levels)\ntype SelectItemSize = 'sm' | 'md' | 'lg'\n\nconst itemSizeFromTrigger: Record<SelectSize, SelectItemSize> = {\n xs: 'sm',\n sm: 'sm',\n default: 'md',\n lg: 'md',\n xl: 'lg',\n}\n\n// Item sizes (font matches Trigger for seamless selection, padding controls density)\nconst itemSizeMap: Record<SelectItemSize, string> = {\n sm: 'pl-2 pr-6 py-1.5 text-sm',\n md: 'pl-3 pr-8 py-1.5 text-base',\n lg: 'pl-3 pr-10 py-2.5 text-base',\n}\n\n// Item indicator (check mark) — right-aligned\nconst indicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-2 h-3 w-3',\n md: 'right-2 h-3.5 w-3.5',\n lg: 'right-3 h-4 w-4',\n}\n\n// Label sizes\nconst labelSizeMap: Record<SelectItemSize, string> = {\n sm: 'px-2 py-1.5 text-xs',\n md: 'px-2 py-1.5 text-xs',\n lg: 'px-3 py-2.5 text-xs',\n}\n\n// Flush mode — items span full width, no inner radius\nconst flushItemPaddingMap: Record<SelectItemSize, string> = {\n sm: 'pl-3 pr-7',\n md: 'pl-4 pr-9',\n lg: 'pl-4 pr-11',\n}\n\nconst flushIndicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-3 h-3 w-3',\n md: 'right-3 h-3.5 w-3.5',\n lg: 'right-4 h-4 w-4',\n}\n\nconst flushLabelPaddingMap: Record<SelectItemSize, string> = {\n sm: 'px-3',\n md: 'px-3',\n lg: 'px-4',\n}\n\n// Root context — set at Root, consumed by Trigger and Content\nconst SelectContext = React.createContext<{\n size: SelectSize\n radius: SelectRadius\n}>({ size: 'default', radius: 'default' })\n\n// Style context — set at Content, consumed by Item/Label\nconst SelectStyleContext = React.createContext<{\n contentRadius: SelectContentRadius\n itemSize: SelectItemSize\n flush: boolean\n}>({ contentRadius: 'xl', itemSize: 'md', flush: false })\n\n// Root — state management + size/radius context. Inside a Field it inherits the\n// Field's disabled state, like Input and Textarea.\nconst Select = ({\n size = 'default',\n radius = 'default',\n disabled,\n ...props\n}: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {\n size?: SelectSize\n radius?: SelectRadius\n}) => {\n const fieldContext = useFieldContext()\n return (\n <SelectContext.Provider value={{ size, radius }}>\n <SelectPrimitive.Root disabled={disabled ?? fieldContext?.disabled} {...props} />\n </SelectContext.Provider>\n )\n}\n\n// Value — displays selected value or placeholder\nconst SelectValue = SelectPrimitive.Value\n\n// Group — groups related items\nconst SelectGroup = SelectPrimitive.Group\n\n// Trigger — the element that opens the select (reads size + radius from context)\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, id, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectContext)\n // Inside a Field the trigger takes the Field id, so FieldLabel names it\n const fieldContext = useFieldContext()\n useFieldControl('single', Boolean(fieldContext) && !id)\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n id={id ?? fieldContext?.id}\n aria-required={(!id && fieldContext?.required) || undefined}\n className={cn(\n 'flex w-full items-center justify-between bg-background text-foreground hover:bg-background-muted',\n 'border border-border-form',\n triggerRadiusMap[radius],\n 'transition-colors duration-micro outline-transparent',\n 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)] focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'data-[placeholder]:text-foreground/30',\n triggerSizeMap[size],\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <svg\n className={cn('ml-2 shrink-0 text-text-muted', triggerIconSizeMap[size])}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n})\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\n// ScrollUpButton — scroll indicator at top\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 15l7-7 7 7\" />\n </svg>\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\n// ScrollDownButton — scroll indicator at bottom\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\n// Close focus: Radix returns focus to the trigger on close. Return it only when the menu was closed\n// from the keyboard — after a pointer close the programmatic focus would show a stray focus ring.\n// Tracks the last input type once per page.\nlet lastInputWasKeyboard = false\nlet inputTypeTrackerInstalled = false\nfunction useLastInputTypeTracker() {\n React.useEffect(() => {\n if (inputTypeTrackerInstalled) return\n inputTypeTrackerInstalled = true\n document.addEventListener('keydown', () => { lastInputWasKeyboard = true }, true)\n document.addEventListener('pointerdown', () => { lastInputWasKeyboard = false }, true)\n }, [])\n}\n\n// Content — the floating panel (reads size + radius from context, auto-maps both)\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n flush?: boolean\n }\n>(({ className, children, position = 'popper', sideOffset = 1, flush = false, onCloseAutoFocus, ...props }, ref) => {\n useLastInputTypeTracker()\n const { size, radius } = React.useContext(SelectContext)\n const itemSize = itemSizeFromTrigger[size]\n const contentRadius = contentRadiusFromRoot[radius]\n return (\n <SelectPrimitive.Portal>\n <SelectStyleContext.Provider value={{ contentRadius, itemSize, flush }}>\n <SelectPrimitive.Content\n ref={ref}\n onCloseAutoFocus={(e) => {\n if (!lastInputWasKeyboard) e.preventDefault()\n onCloseAutoFocus?.(e)\n }}\n className={cn(\n 'relative z-popover min-w-[var(--radix-select-trigger-width)] overflow-hidden border border-border bg-background text-foreground shadow-lg',\n flush ? 'py-1' : 'p-1',\n contentRadiusMap[contentRadius],\n position === 'popper' &&\n 'max-h-[var(--radix-select-content-available-height)]',\n className\n )}\n position={position}\n sideOffset={sideOffset}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n position === 'popper' &&\n 'h-[var(--radix-select-content-available-height)] w-full'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectStyleContext.Provider>\n </SelectPrimitive.Portal>\n )\n})\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\n// Item — a single selectable item (with right-aligned check indicator)\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => {\n const { contentRadius, itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center outline-none',\n itemSizeMap[itemSize],\n !flush && itemRadiusMap[contentRadius],\n flush && flushItemPaddingMap[itemSize],\n 'transition-colors duration-fast',\n 'focus:bg-background-muted',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"truncate\">{children}</SelectPrimitive.ItemText>\n <span className={cn('absolute flex items-center justify-center', flush ? flushIndicatorSizeMap[itemSize] : indicatorSizeMap[itemSize])}>\n <SelectPrimitive.ItemIndicator>\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </SelectPrimitive.ItemIndicator>\n </span>\n </SelectPrimitive.Item>\n )\n})\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\n// Label — non-interactive group heading\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => {\n const { itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\n 'font-semibold text-text-muted',\n labelSizeMap[itemSize],\n flush && flushLabelPaddingMap[itemSize],\n className\n )}\n {...props}\n />\n )\n})\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\n// Separator — visual divider between groups\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => {\n const { flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('h-px bg-border my-1', !flush && '-mx-1', className)}\n {...props}\n />\n )\n})\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport type { SelectRadius, SelectSize }\n\nexport {\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n SelectGroup,\n SelectLabel,\n SelectSeparator,\n}\n"],"mappings":"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","names":[]}
|
|
@@ -177,7 +177,22 @@ const SelectScrollDownButton = React.forwardRef(({ className, ...props }, ref) =
|
|
|
177
177
|
}
|
|
178
178
|
));
|
|
179
179
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
180
|
+
let lastInputWasKeyboard = false;
|
|
181
|
+
let inputTypeTrackerInstalled = false;
|
|
182
|
+
function useLastInputTypeTracker() {
|
|
183
|
+
React.useEffect(() => {
|
|
184
|
+
if (inputTypeTrackerInstalled) return;
|
|
185
|
+
inputTypeTrackerInstalled = true;
|
|
186
|
+
document.addEventListener("keydown", () => {
|
|
187
|
+
lastInputWasKeyboard = true;
|
|
188
|
+
}, true);
|
|
189
|
+
document.addEventListener("pointerdown", () => {
|
|
190
|
+
lastInputWasKeyboard = false;
|
|
191
|
+
}, true);
|
|
192
|
+
}, []);
|
|
193
|
+
}
|
|
180
194
|
const SelectContent = React.forwardRef(({ className, children, position = "popper", sideOffset = 1, flush = false, onCloseAutoFocus, ...props }, ref) => {
|
|
195
|
+
useLastInputTypeTracker();
|
|
181
196
|
const { size, radius } = React.useContext(SelectContext);
|
|
182
197
|
const itemSize = itemSizeFromTrigger[size];
|
|
183
198
|
const contentRadius = contentRadiusFromRoot[radius];
|
|
@@ -186,7 +201,7 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
|
|
|
186
201
|
{
|
|
187
202
|
ref,
|
|
188
203
|
onCloseAutoFocus: (e) => {
|
|
189
|
-
e.preventDefault();
|
|
204
|
+
if (!lastInputWasKeyboard) e.preventDefault();
|
|
190
205
|
onCloseAutoFocus?.(e);
|
|
191
206
|
},
|
|
192
207
|
className: cn(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/select.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\n// Radius (matches Input — set at Root, propagates to Trigger and Content)\ntype SelectRadius = 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n\nconst triggerRadiusMap: Record<SelectRadius, string> = {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n '3xl': 'rounded-3xl',\n full: 'rounded-full',\n}\n\n// Auto-mapping: root radius → content radius (3 levels)\ntype SelectContentRadius = 'md' | 'lg' | 'xl'\n\nconst contentRadiusFromRoot: Record<SelectRadius, SelectContentRadius> = {\n none: 'md',\n sm: 'md',\n base: 'md',\n default: 'md',\n lg: 'lg',\n xl: 'xl',\n '2xl': 'xl',\n '3xl': 'xl',\n full: 'xl',\n}\n\nconst contentRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded-md', // 6px\n lg: 'rounded-lg', // 8px\n xl: 'rounded-xl', // 12px\n}\n\nconst itemRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded', // 4px — perceptual balance (67%)\n lg: 'rounded-md', // 6px — perceptual balance (75%)\n xl: 'rounded-lg', // 8px — perceptual balance (67%)\n}\n\n// Size variants (matches Input component)\ntype SelectSize = 'xs' | 'sm' | 'default' | 'lg' | 'xl'\n\n// Trigger sizes (identical to Input)\nconst triggerSizeMap: Record<SelectSize, string> = {\n xs: 'h-9 px-3 text-sm', // 36px\n sm: 'h-10 px-3 text-md', // 40px\n default: 'h-11 px-4 text-base', // 44px\n lg: 'h-12 px-4 text-base', // 48px\n xl: 'h-14 px-4 text-base', // 56px\n}\n\n// Trigger icon sizes (matches Input icon pattern)\nconst triggerIconSizeMap: Record<SelectSize, string> = {\n xs: 'icon-xs', // 14px\n sm: 'icon-xs', // 14px\n default: 'icon-sm', // 16px\n lg: 'icon-sm', // 16px\n xl: 'icon-sm', // 16px\n}\n\n// Auto-mapping: trigger size → content item size (3 levels)\ntype SelectItemSize = 'sm' | 'md' | 'lg'\n\nconst itemSizeFromTrigger: Record<SelectSize, SelectItemSize> = {\n xs: 'sm',\n sm: 'sm',\n default: 'md',\n lg: 'md',\n xl: 'lg',\n}\n\n// Item sizes (font matches Trigger for seamless selection, padding controls density)\nconst itemSizeMap: Record<SelectItemSize, string> = {\n sm: 'pl-2 pr-6 py-1.5 text-sm',\n md: 'pl-3 pr-8 py-1.5 text-base',\n lg: 'pl-3 pr-10 py-2.5 text-base',\n}\n\n// Item indicator (check mark) — right-aligned\nconst indicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-2 h-3 w-3',\n md: 'right-2 h-3.5 w-3.5',\n lg: 'right-3 h-4 w-4',\n}\n\n// Label sizes\nconst labelSizeMap: Record<SelectItemSize, string> = {\n sm: 'px-2 py-1.5 text-xs',\n md: 'px-2 py-1.5 text-xs',\n lg: 'px-3 py-2.5 text-xs',\n}\n\n// Flush mode — items span full width, no inner radius\nconst flushItemPaddingMap: Record<SelectItemSize, string> = {\n sm: 'pl-3 pr-7',\n md: 'pl-4 pr-9',\n lg: 'pl-4 pr-11',\n}\n\nconst flushIndicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-3 h-3 w-3',\n md: 'right-3 h-3.5 w-3.5',\n lg: 'right-4 h-4 w-4',\n}\n\nconst flushLabelPaddingMap: Record<SelectItemSize, string> = {\n sm: 'px-3',\n md: 'px-3',\n lg: 'px-4',\n}\n\n// Root context — set at Root, consumed by Trigger and Content\nconst SelectContext = React.createContext<{\n size: SelectSize\n radius: SelectRadius\n}>({ size: 'default', radius: 'default' })\n\n// Style context — set at Content, consumed by Item/Label\nconst SelectStyleContext = React.createContext<{\n contentRadius: SelectContentRadius\n itemSize: SelectItemSize\n flush: boolean\n}>({ contentRadius: 'xl', itemSize: 'md', flush: false })\n\n// Root — state management + size/radius context. Inside a Field it inherits the\n// Field's disabled state, like Input and Textarea.\nconst Select = ({\n size = 'default',\n radius = 'default',\n disabled,\n ...props\n}: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {\n size?: SelectSize\n radius?: SelectRadius\n}) => {\n const fieldContext = useFieldContext()\n return (\n <SelectContext.Provider value={{ size, radius }}>\n <SelectPrimitive.Root disabled={disabled ?? fieldContext?.disabled} {...props} />\n </SelectContext.Provider>\n )\n}\n\n// Value — displays selected value or placeholder\nconst SelectValue = SelectPrimitive.Value\n\n// Group — groups related items\nconst SelectGroup = SelectPrimitive.Group\n\n// Trigger — the element that opens the select (reads size + radius from context)\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, id, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectContext)\n // Inside a Field the trigger takes the Field id, so FieldLabel names it\n const fieldContext = useFieldContext()\n useFieldControl('single', Boolean(fieldContext) && !id)\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n id={id ?? fieldContext?.id}\n aria-required={(!id && fieldContext?.required) || undefined}\n className={cn(\n 'flex w-full items-center justify-between bg-background text-foreground hover:bg-background-muted',\n 'border border-border-form',\n triggerRadiusMap[radius],\n 'transition-colors duration-micro outline-transparent',\n 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)] focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'data-[placeholder]:text-foreground/30',\n triggerSizeMap[size],\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <svg\n className={cn('ml-2 shrink-0 text-text-muted', triggerIconSizeMap[size])}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n})\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\n// ScrollUpButton — scroll indicator at top\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 15l7-7 7 7\" />\n </svg>\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\n// ScrollDownButton — scroll indicator at bottom\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\n// Content — the floating panel (reads size + radius from context, auto-maps both)\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n flush?: boolean\n }\n>(({ className, children, position = 'popper', sideOffset = 1, flush = false, onCloseAutoFocus, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectContext)\n const itemSize = itemSizeFromTrigger[size]\n const contentRadius = contentRadiusFromRoot[radius]\n return (\n <SelectPrimitive.Portal>\n <SelectStyleContext.Provider value={{ contentRadius, itemSize, flush }}>\n <SelectPrimitive.Content\n ref={ref}\n onCloseAutoFocus={(e) => {\n e.preventDefault()\n onCloseAutoFocus?.(e)\n }}\n className={cn(\n 'relative z-popover min-w-[var(--radix-select-trigger-width)] overflow-hidden border border-border bg-background text-foreground shadow-lg',\n flush ? 'py-1' : 'p-1',\n contentRadiusMap[contentRadius],\n position === 'popper' &&\n 'max-h-[var(--radix-select-content-available-height)]',\n className\n )}\n position={position}\n sideOffset={sideOffset}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n position === 'popper' &&\n 'h-[var(--radix-select-content-available-height)] w-full'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectStyleContext.Provider>\n </SelectPrimitive.Portal>\n )\n})\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\n// Item — a single selectable item (with right-aligned check indicator)\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => {\n const { contentRadius, itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center outline-none',\n itemSizeMap[itemSize],\n !flush && itemRadiusMap[contentRadius],\n flush && flushItemPaddingMap[itemSize],\n 'transition-colors duration-fast',\n 'focus:bg-background-muted',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"truncate\">{children}</SelectPrimitive.ItemText>\n <span className={cn('absolute flex items-center justify-center', flush ? flushIndicatorSizeMap[itemSize] : indicatorSizeMap[itemSize])}>\n <SelectPrimitive.ItemIndicator>\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </SelectPrimitive.ItemIndicator>\n </span>\n </SelectPrimitive.Item>\n )\n})\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\n// Label — non-interactive group heading\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => {\n const { itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\n 'font-semibold text-text-muted',\n labelSizeMap[itemSize],\n flush && flushLabelPaddingMap[itemSize],\n className\n )}\n {...props}\n />\n )\n})\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\n// Separator — visual divider between groups\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => {\n const { flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('h-px bg-border my-1', !flush && '-mx-1', className)}\n {...props}\n />\n )\n})\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport type { SelectRadius, SelectSize }\n\nexport {\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n SelectGroup,\n SelectLabel,\n SelectSeparator,\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/select.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\n// Radius (matches Input — set at Root, propagates to Trigger and Content)\ntype SelectRadius = 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n\nconst triggerRadiusMap: Record<SelectRadius, string> = {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n '3xl': 'rounded-3xl',\n full: 'rounded-full',\n}\n\n// Auto-mapping: root radius → content radius (3 levels)\ntype SelectContentRadius = 'md' | 'lg' | 'xl'\n\nconst contentRadiusFromRoot: Record<SelectRadius, SelectContentRadius> = {\n none: 'md',\n sm: 'md',\n base: 'md',\n default: 'md',\n lg: 'lg',\n xl: 'xl',\n '2xl': 'xl',\n '3xl': 'xl',\n full: 'xl',\n}\n\nconst contentRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded-md', // 6px\n lg: 'rounded-lg', // 8px\n xl: 'rounded-xl', // 12px\n}\n\nconst itemRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded', // 4px — perceptual balance (67%)\n lg: 'rounded-md', // 6px — perceptual balance (75%)\n xl: 'rounded-lg', // 8px — perceptual balance (67%)\n}\n\n// Size variants (matches Input component)\ntype SelectSize = 'xs' | 'sm' | 'default' | 'lg' | 'xl'\n\n// Trigger sizes (identical to Input)\nconst triggerSizeMap: Record<SelectSize, string> = {\n xs: 'h-9 px-3 text-sm', // 36px\n sm: 'h-10 px-3 text-md', // 40px\n default: 'h-11 px-4 text-base', // 44px\n lg: 'h-12 px-4 text-base', // 48px\n xl: 'h-14 px-4 text-base', // 56px\n}\n\n// Trigger icon sizes (matches Input icon pattern)\nconst triggerIconSizeMap: Record<SelectSize, string> = {\n xs: 'icon-xs', // 14px\n sm: 'icon-xs', // 14px\n default: 'icon-sm', // 16px\n lg: 'icon-sm', // 16px\n xl: 'icon-sm', // 16px\n}\n\n// Auto-mapping: trigger size → content item size (3 levels)\ntype SelectItemSize = 'sm' | 'md' | 'lg'\n\nconst itemSizeFromTrigger: Record<SelectSize, SelectItemSize> = {\n xs: 'sm',\n sm: 'sm',\n default: 'md',\n lg: 'md',\n xl: 'lg',\n}\n\n// Item sizes (font matches Trigger for seamless selection, padding controls density)\nconst itemSizeMap: Record<SelectItemSize, string> = {\n sm: 'pl-2 pr-6 py-1.5 text-sm',\n md: 'pl-3 pr-8 py-1.5 text-base',\n lg: 'pl-3 pr-10 py-2.5 text-base',\n}\n\n// Item indicator (check mark) — right-aligned\nconst indicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-2 h-3 w-3',\n md: 'right-2 h-3.5 w-3.5',\n lg: 'right-3 h-4 w-4',\n}\n\n// Label sizes\nconst labelSizeMap: Record<SelectItemSize, string> = {\n sm: 'px-2 py-1.5 text-xs',\n md: 'px-2 py-1.5 text-xs',\n lg: 'px-3 py-2.5 text-xs',\n}\n\n// Flush mode — items span full width, no inner radius\nconst flushItemPaddingMap: Record<SelectItemSize, string> = {\n sm: 'pl-3 pr-7',\n md: 'pl-4 pr-9',\n lg: 'pl-4 pr-11',\n}\n\nconst flushIndicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-3 h-3 w-3',\n md: 'right-3 h-3.5 w-3.5',\n lg: 'right-4 h-4 w-4',\n}\n\nconst flushLabelPaddingMap: Record<SelectItemSize, string> = {\n sm: 'px-3',\n md: 'px-3',\n lg: 'px-4',\n}\n\n// Root context — set at Root, consumed by Trigger and Content\nconst SelectContext = React.createContext<{\n size: SelectSize\n radius: SelectRadius\n}>({ size: 'default', radius: 'default' })\n\n// Style context — set at Content, consumed by Item/Label\nconst SelectStyleContext = React.createContext<{\n contentRadius: SelectContentRadius\n itemSize: SelectItemSize\n flush: boolean\n}>({ contentRadius: 'xl', itemSize: 'md', flush: false })\n\n// Root — state management + size/radius context. Inside a Field it inherits the\n// Field's disabled state, like Input and Textarea.\nconst Select = ({\n size = 'default',\n radius = 'default',\n disabled,\n ...props\n}: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {\n size?: SelectSize\n radius?: SelectRadius\n}) => {\n const fieldContext = useFieldContext()\n return (\n <SelectContext.Provider value={{ size, radius }}>\n <SelectPrimitive.Root disabled={disabled ?? fieldContext?.disabled} {...props} />\n </SelectContext.Provider>\n )\n}\n\n// Value — displays selected value or placeholder\nconst SelectValue = SelectPrimitive.Value\n\n// Group — groups related items\nconst SelectGroup = SelectPrimitive.Group\n\n// Trigger — the element that opens the select (reads size + radius from context)\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, id, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectContext)\n // Inside a Field the trigger takes the Field id, so FieldLabel names it\n const fieldContext = useFieldContext()\n useFieldControl('single', Boolean(fieldContext) && !id)\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n id={id ?? fieldContext?.id}\n aria-required={(!id && fieldContext?.required) || undefined}\n className={cn(\n 'flex w-full items-center justify-between bg-background text-foreground hover:bg-background-muted',\n 'border border-border-form',\n triggerRadiusMap[radius],\n 'transition-colors duration-micro outline-transparent',\n 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)] focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'data-[placeholder]:text-foreground/30',\n triggerSizeMap[size],\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <svg\n className={cn('ml-2 shrink-0 text-text-muted', triggerIconSizeMap[size])}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n})\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\n// ScrollUpButton — scroll indicator at top\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 15l7-7 7 7\" />\n </svg>\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\n// ScrollDownButton — scroll indicator at bottom\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\n// Close focus: Radix returns focus to the trigger on close. Return it only when the menu was closed\n// from the keyboard — after a pointer close the programmatic focus would show a stray focus ring.\n// Tracks the last input type once per page.\nlet lastInputWasKeyboard = false\nlet inputTypeTrackerInstalled = false\nfunction useLastInputTypeTracker() {\n React.useEffect(() => {\n if (inputTypeTrackerInstalled) return\n inputTypeTrackerInstalled = true\n document.addEventListener('keydown', () => { lastInputWasKeyboard = true }, true)\n document.addEventListener('pointerdown', () => { lastInputWasKeyboard = false }, true)\n }, [])\n}\n\n// Content — the floating panel (reads size + radius from context, auto-maps both)\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n flush?: boolean\n }\n>(({ className, children, position = 'popper', sideOffset = 1, flush = false, onCloseAutoFocus, ...props }, ref) => {\n useLastInputTypeTracker()\n const { size, radius } = React.useContext(SelectContext)\n const itemSize = itemSizeFromTrigger[size]\n const contentRadius = contentRadiusFromRoot[radius]\n return (\n <SelectPrimitive.Portal>\n <SelectStyleContext.Provider value={{ contentRadius, itemSize, flush }}>\n <SelectPrimitive.Content\n ref={ref}\n onCloseAutoFocus={(e) => {\n if (!lastInputWasKeyboard) e.preventDefault()\n onCloseAutoFocus?.(e)\n }}\n className={cn(\n 'relative z-popover min-w-[var(--radix-select-trigger-width)] overflow-hidden border border-border bg-background text-foreground shadow-lg',\n flush ? 'py-1' : 'p-1',\n contentRadiusMap[contentRadius],\n position === 'popper' &&\n 'max-h-[var(--radix-select-content-available-height)]',\n className\n )}\n position={position}\n sideOffset={sideOffset}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n position === 'popper' &&\n 'h-[var(--radix-select-content-available-height)] w-full'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectStyleContext.Provider>\n </SelectPrimitive.Portal>\n )\n})\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\n// Item — a single selectable item (with right-aligned check indicator)\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => {\n const { contentRadius, itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center outline-none',\n itemSizeMap[itemSize],\n !flush && itemRadiusMap[contentRadius],\n flush && flushItemPaddingMap[itemSize],\n 'transition-colors duration-fast',\n 'focus:bg-background-muted',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"truncate\">{children}</SelectPrimitive.ItemText>\n <span className={cn('absolute flex items-center justify-center', flush ? flushIndicatorSizeMap[itemSize] : indicatorSizeMap[itemSize])}>\n <SelectPrimitive.ItemIndicator>\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </SelectPrimitive.ItemIndicator>\n </span>\n </SelectPrimitive.Item>\n )\n})\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\n// Label — non-interactive group heading\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => {\n const { itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\n 'font-semibold text-text-muted',\n labelSizeMap[itemSize],\n flush && flushLabelPaddingMap[itemSize],\n className\n )}\n {...props}\n />\n )\n})\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\n// Separator — visual divider between groups\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => {\n const { flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('h-px bg-border my-1', !flush && '-mx-1', className)}\n {...props}\n />\n )\n})\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport type { SelectRadius, SelectSize }\n\nexport {\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n SelectGroup,\n SelectLabel,\n SelectSeparator,\n}\n"],"mappings":"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","names":[]}
|
|
@@ -72,6 +72,8 @@ interface ToasterProps {
|
|
|
72
72
|
visibleToasts?: number;
|
|
73
73
|
/** Show close button on all toasts */
|
|
74
74
|
closeButton?: boolean;
|
|
75
|
+
/** Accessible label for the close button (screen readers) — localize per page */
|
|
76
|
+
closeLabel?: string;
|
|
75
77
|
/** Use rich (filled) colors for status toasts — default: true */
|
|
76
78
|
richColors?: boolean;
|
|
77
79
|
/** Expand all toasts (no stacking) */
|
|
@@ -85,7 +87,7 @@ interface ToasterProps {
|
|
|
85
87
|
/** Additional className for container */
|
|
86
88
|
className?: string;
|
|
87
89
|
}
|
|
88
|
-
declare function Toaster({ position, duration, visibleToasts, closeButton, richColors, expand, offset, gap, size, className, }: ToasterProps): React.JSX.Element;
|
|
90
|
+
declare function Toaster({ position, duration, visibleToasts, closeButton, closeLabel, richColors, expand, offset, gap, size, className, }: ToasterProps): React.JSX.Element;
|
|
89
91
|
declare namespace Toaster {
|
|
90
92
|
var displayName: string;
|
|
91
93
|
}
|
|
@@ -72,6 +72,8 @@ interface ToasterProps {
|
|
|
72
72
|
visibleToasts?: number;
|
|
73
73
|
/** Show close button on all toasts */
|
|
74
74
|
closeButton?: boolean;
|
|
75
|
+
/** Accessible label for the close button (screen readers) — localize per page */
|
|
76
|
+
closeLabel?: string;
|
|
75
77
|
/** Use rich (filled) colors for status toasts — default: true */
|
|
76
78
|
richColors?: boolean;
|
|
77
79
|
/** Expand all toasts (no stacking) */
|
|
@@ -85,7 +87,7 @@ interface ToasterProps {
|
|
|
85
87
|
/** Additional className for container */
|
|
86
88
|
className?: string;
|
|
87
89
|
}
|
|
88
|
-
declare function Toaster({ position, duration, visibleToasts, closeButton, richColors, expand, offset, gap, size, className, }: ToasterProps): React.JSX.Element;
|
|
90
|
+
declare function Toaster({ position, duration, visibleToasts, closeButton, closeLabel, richColors, expand, offset, gap, size, className, }: ToasterProps): React.JSX.Element;
|
|
89
91
|
declare namespace Toaster {
|
|
90
92
|
var displayName: string;
|
|
91
93
|
}
|
|
@@ -237,6 +237,7 @@ const ToastItem = React.memo(function ToastItem2({
|
|
|
237
237
|
position,
|
|
238
238
|
size,
|
|
239
239
|
closeButton: globalCloseButton,
|
|
240
|
+
closeLabel,
|
|
240
241
|
richColors,
|
|
241
242
|
defaultDuration,
|
|
242
243
|
onRemove
|
|
@@ -358,7 +359,7 @@ const ToastItem = React.memo(function ToastItem2({
|
|
|
358
359
|
type: "button",
|
|
359
360
|
className: "shrink-0 rounded-md p-1 opacity-70 hover:opacity-100 transition-opacity focus-visible:focus-ring",
|
|
360
361
|
onClick: handleDismiss,
|
|
361
|
-
"aria-label":
|
|
362
|
+
"aria-label": closeLabel,
|
|
362
363
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultCloseIcon, { className: "icon-sm" })
|
|
363
364
|
}
|
|
364
365
|
)
|
|
@@ -371,6 +372,7 @@ function Toaster({
|
|
|
371
372
|
duration = 4e3,
|
|
372
373
|
visibleToasts = 5,
|
|
373
374
|
closeButton = false,
|
|
375
|
+
closeLabel = "Close",
|
|
374
376
|
richColors = true,
|
|
375
377
|
expand = false,
|
|
376
378
|
offset = 24,
|
|
@@ -431,6 +433,7 @@ function Toaster({
|
|
|
431
433
|
position,
|
|
432
434
|
size,
|
|
433
435
|
closeButton,
|
|
436
|
+
closeLabel,
|
|
434
437
|
richColors,
|
|
435
438
|
defaultDuration: duration,
|
|
436
439
|
onRemove: handleRemove
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/toast.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\n\n// ─── Built-in status icons (shared with Alert — no external dependency) ──────\n// All icons: Lucide-compatible 24×24 viewBox, strokeWidth=2, rounded caps/joins\nconst InfoIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n)\n\nconst SuccessIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n)\n\nconst WarningIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n)\n\nconst ErrorIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 8v5\" />\n <path d=\"M12 16h.01\" />\n </svg>\n)\n\nconst DefaultCloseIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n)\n\nconst LoadingIcon = ({ className }: { className?: string }) => (\n <svg className={cn('animate-spin', className)} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" strokeLinecap=\"round\" />\n </svg>\n)\n\n// ─── Status icon mapping ─────────────────────────────────────────\nconst STATUS_ICONS: Record<ToastType, React.FC<{ className?: string }>> = {\n default: InfoIcon,\n success: SuccessIcon,\n warning: WarningIcon,\n error: ErrorIcon,\n info: InfoIcon,\n loading: LoadingIcon,\n}\n\n// ─── Color × Type class mapping ─────────────────────────────────\nconst colorMap: Record<ToastType, string> = {\n default: 'bg-background-paper text-foreground border-border shadow-lg',\n success: 'bg-success-tint text-text-success border-success/20 shadow-lg',\n error: 'bg-error-tint text-text-error border-error/20 shadow-lg',\n warning: 'bg-warning-tint text-text-warning border-warning/20 shadow-lg',\n info: 'bg-info-tint text-text-info border-info/20 shadow-lg',\n loading: 'bg-background-paper text-foreground border-border shadow-lg',\n}\n\nconst richColorMap: Record<ToastType, string> = {\n default: 'bg-foreground text-background border-transparent shadow-lg',\n success: 'bg-success text-success-foreground border-transparent shadow-lg',\n error: 'bg-error text-error-foreground border-transparent shadow-lg',\n warning: 'bg-warning text-warning-foreground border-transparent shadow-lg',\n info: 'bg-info text-info-foreground border-transparent shadow-lg',\n loading: 'bg-foreground text-background border-transparent shadow-lg',\n}\n\n// ─── Constants (JS cannot read CSS variables at runtime) ─────────\nconst TOAST_EXIT_DURATION = 200 // --duration-normal (200ms)\nconst TOAST_MIN_RESUME_MS = 500 // --duration-slowest (500ms) — minimum time after hover resume\nconst TOAST_WIDTH = 360 // fixed toast width — smallest mobile viewport baseline\nconst TOAST_VIEWPORT_MARGIN = 48 // 2 × offset default (24px) — viewport safe area\nconst TOAST_STACK_OFFSET = 8 // --spacing-2 (8px) — vertical gap between stacked toasts\nconst TOAST_STACK_SCALE_STEP = 0.05 // scale reduction per stack level (0.95, 0.90, ...)\nconst TOAST_STACK_OPACITY_STEP = 0.15 // opacity reduction per stack level (0.85, 0.70, ...)\nconst TOAST_STACK_VISIBLE_LAYERS = 3 // max visible stacked layers before hidden\n\n// ─── Toast variants (CVA) ────────────────────────────────────────\nconst toastVariants = cva(\n 'group pointer-events-auto relative flex items-center gap-2.5 border w-full overflow-hidden transition-all',\n {\n variants: {\n size: {\n sm: 'p-3 text-sm rounded-md',\n default: 'p-4 text-md rounded-lg',\n lg: 'p-5 text-md rounded-lg',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\n// ─── Types ───────────────────────────────────────────────────────\nexport type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info' | 'loading'\nexport type ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\nexport type ToastSize = 'sm' | 'default' | 'lg'\n\nexport interface ToastAction {\n label: string\n onClick: () => void\n}\n\nexport interface ToastData {\n id: string\n type: ToastType\n message: React.ReactNode\n description?: React.ReactNode\n duration?: number\n dismissible?: boolean\n closeButton?: boolean\n icon?: React.ReactNode\n action?: ToastAction\n cancel?: ToastAction\n onDismiss?: (toast: ToastData) => void\n onAutoClose?: (toast: ToastData) => void\n className?: string\n /** Promise state — managed internally */\n _promiseState?: 'loading' | 'success' | 'error'\n}\n\n// ─── Global toast store ──────────────────────────────────────────\ntype ToastListener = () => void\n\ninterface ToastStore {\n toasts: ToastData[]\n listeners: Set<ToastListener>\n addToast: (toast: ToastData) => void\n removeToast: (id: string) => void\n updateToast: (id: string, updates: Partial<ToastData>) => void\n removeAll: () => void\n subscribe: (listener: ToastListener) => () => void\n}\n\nfunction createToastStore(): ToastStore {\n const store: ToastStore = {\n toasts: [],\n listeners: new Set(),\n addToast(toast) {\n store.toasts = [toast, ...store.toasts]\n store.listeners.forEach((l) => l())\n },\n removeToast(id) {\n store.toasts = store.toasts.filter((t) => t.id !== id)\n store.listeners.forEach((l) => l())\n },\n updateToast(id, updates) {\n store.toasts = store.toasts.map((t) => (t.id === id ? { ...t, ...updates } : t))\n store.listeners.forEach((l) => l())\n },\n removeAll() {\n store.toasts = []\n store.listeners.forEach((l) => l())\n },\n subscribe(listener) {\n store.listeners.add(listener)\n return () => { store.listeners.delete(listener) }\n },\n }\n return store\n}\n\nconst globalStore = createToastStore()\n\nfunction useToastStore() {\n const [, forceUpdate] = React.useState(0)\n React.useEffect(() => {\n return globalStore.subscribe(() => forceUpdate((n) => n + 1))\n }, [])\n return globalStore.toasts\n}\n\n// ─── Toast ID generator ─────────────────────────────────────────\nlet toastCounter = 0\nfunction genId() {\n toastCounter += 1\n return `toast-${toastCounter}-${Date.now()}`\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// Imperative API: toast()\n// ═══════════════════════════════════════════════════════════════════\n\ninterface ToastOptions {\n id?: string\n description?: React.ReactNode\n duration?: number\n dismissible?: boolean\n closeButton?: boolean\n icon?: React.ReactNode\n action?: ToastAction\n cancel?: ToastAction\n onDismiss?: (toast: ToastData) => void\n onAutoClose?: (toast: ToastData) => void\n className?: string\n}\n\ninterface PromiseOptions<T> {\n loading: React.ReactNode\n success: React.ReactNode | ((data: T) => React.ReactNode)\n error: React.ReactNode | ((err: unknown) => React.ReactNode)\n finally?: () => void\n description?: {\n loading?: React.ReactNode\n success?: React.ReactNode | ((data: T) => React.ReactNode)\n error?: React.ReactNode | ((err: unknown) => React.ReactNode)\n }\n}\n\nfunction createToast(message: React.ReactNode, type: ToastType, opts?: ToastOptions): string {\n const id = opts?.id ?? genId()\n\n // If updating existing toast, just update\n const existing = globalStore.toasts.find((t) => t.id === id)\n if (existing) {\n globalStore.updateToast(id, { message, type, ...opts })\n return id\n }\n\n globalStore.addToast({\n id,\n type,\n message,\n description: opts?.description,\n duration: opts?.duration,\n dismissible: opts?.dismissible,\n closeButton: opts?.closeButton,\n icon: opts?.icon,\n action: opts?.action,\n cancel: opts?.cancel,\n onDismiss: opts?.onDismiss,\n onAutoClose: opts?.onAutoClose,\n className: opts?.className,\n })\n return id\n}\n\nfunction toast(message: React.ReactNode, opts?: ToastOptions): string {\n return createToast(message, 'default', opts)\n}\n\ntoast.success = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'success', opts)\n\ntoast.error = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'error', opts)\n\ntoast.warning = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'warning', opts)\n\ntoast.info = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'info', opts)\n\ntoast.loading = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'loading', { ...opts, duration: 0 })\n\ntoast.promise = <T,>(\n promise: Promise<T>,\n opts: PromiseOptions<T>,\n toastOpts?: ToastOptions\n): Promise<T> => {\n const id = createToast(opts.loading, 'loading', {\n ...toastOpts,\n duration: 0,\n })\n\n promise\n .then((data) => {\n const msg = typeof opts.success === 'function' ? opts.success(data) : opts.success\n const desc = typeof opts.description?.success === 'function'\n ? opts.description.success(data)\n : opts.description?.success\n globalStore.updateToast(id, {\n type: 'success',\n message: msg,\n description: desc,\n duration: toastOpts?.duration,\n _promiseState: 'success',\n })\n })\n .catch((err) => {\n const msg = typeof opts.error === 'function' ? opts.error(err) : opts.error\n const desc = typeof opts.description?.error === 'function'\n ? opts.description.error(err)\n : opts.description?.error\n globalStore.updateToast(id, {\n type: 'error',\n message: msg,\n description: desc,\n duration: toastOpts?.duration,\n _promiseState: 'error',\n })\n })\n .finally(() => {\n opts.finally?.()\n })\n\n return promise\n}\n\ntoast.dismiss = (id?: string) => {\n if (id) {\n globalStore.removeToast(id)\n } else {\n globalStore.removeAll()\n }\n}\n\ntoast.custom = (render: (t: ToastData) => React.ReactNode, opts?: ToastOptions): string => {\n const id = opts?.id ?? genId()\n globalStore.addToast({\n id,\n type: 'default',\n message: render as unknown as React.ReactNode,\n duration: opts?.duration,\n dismissible: opts?.dismissible,\n className: opts?.className,\n onDismiss: opts?.onDismiss,\n onAutoClose: opts?.onAutoClose,\n _promiseState: undefined,\n })\n return id\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// ToastItem — individual toast renderer\n// ═══════════════════════════════════════════════════════════════════\n\ninterface ToastItemProps {\n data: ToastData\n position: ToastPosition\n size: ToastSize\n closeButton: boolean\n richColors: boolean\n defaultDuration: number\n onRemove: (id: string) => void\n}\n\nconst ToastItem = React.memo(function ToastItem({\n data,\n position,\n size,\n closeButton: globalCloseButton,\n richColors,\n defaultDuration,\n onRemove,\n}: ToastItemProps) {\n const [isExiting, setIsExiting] = React.useState(false)\n const [isEntered, setIsEntered] = React.useState(false)\n const [isPaused, setIsPaused] = React.useState(false)\n const timerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n const remainingRef = React.useRef<number>(0)\n const startTimeRef = React.useRef<number>(0)\n\n // Enter animation — play once on mount, then remove class\n React.useEffect(() => {\n const timer = setTimeout(() => setIsEntered(true), TOAST_EXIT_DURATION)\n return () => clearTimeout(timer)\n }, [])\n\n const showClose = data.closeButton ?? globalCloseButton\n const dismissible = data.dismissible !== false\n const duration = data.type === 'loading' ? 0 : (data.duration ?? defaultDuration)\n\n // ARIA — error/warning use assertive, others polite\n const role = data.type === 'error' || data.type === 'warning' ? 'alert' : 'status'\n const ariaLive = data.type === 'error' || data.type === 'warning' ? 'assertive' : 'polite'\n\n const colors = richColors ? richColorMap[data.type] : colorMap[data.type]\n const StatusIcon = STATUS_ICONS[data.type]\n\n // Animation classes based on position\n const enterAnim = position.includes('right')\n ? 'animate-toast-slide-in-right'\n : position.includes('left')\n ? 'animate-toast-slide-in-left'\n : position.includes('top')\n ? 'animate-toast-slide-in-top'\n : 'animate-toast-slide-in-bottom'\n\n const exitAnim = position.includes('right')\n ? 'animate-toast-slide-out-right'\n : position.includes('left')\n ? 'animate-toast-slide-out-left'\n : position.includes('top')\n ? 'animate-toast-slide-out-top'\n : 'animate-toast-slide-out-bottom'\n\n const handleDismiss = React.useCallback(() => {\n if (!dismissible) return\n setIsExiting(true)\n data.onDismiss?.(data)\n // Wait for exit animation then remove\n setTimeout(() => onRemove(data.id), TOAST_EXIT_DURATION)\n }, [data, dismissible, onRemove])\n\n const handleAutoClose = React.useCallback(() => {\n setIsExiting(true)\n data.onAutoClose?.(data)\n setTimeout(() => onRemove(data.id), TOAST_EXIT_DURATION)\n }, [data, onRemove])\n\n // Auto-dismiss timer with pause support\n React.useEffect(() => {\n if (duration <= 0) return\n\n remainingRef.current = duration\n startTimeRef.current = Date.now()\n\n timerRef.current = setTimeout(handleAutoClose, duration)\n\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current)\n }\n }, [duration, handleAutoClose])\n\n // Pause/resume on hover\n const handleMouseEnter = React.useCallback(() => {\n if (duration <= 0) return\n setIsPaused(true)\n if (timerRef.current) {\n clearTimeout(timerRef.current)\n remainingRef.current -= Date.now() - startTimeRef.current\n }\n }, [duration])\n\n const handleMouseLeave = React.useCallback(() => {\n if (duration <= 0) return\n setIsPaused(false)\n startTimeRef.current = Date.now()\n timerRef.current = setTimeout(handleAutoClose, Math.max(remainingRef.current, TOAST_MIN_RESUME_MS))\n }, [duration, handleAutoClose])\n\n // Reset timer when toast updates (promise resolve)\n React.useEffect(() => {\n if (data._promiseState === 'success' || data._promiseState === 'error') {\n const newDuration = data.duration ?? defaultDuration\n if (newDuration > 0) {\n if (timerRef.current) clearTimeout(timerRef.current)\n remainingRef.current = newDuration\n startTimeRef.current = Date.now()\n timerRef.current = setTimeout(handleAutoClose, newDuration)\n }\n }\n }, [data._promiseState, data.duration, defaultDuration, handleAutoClose])\n\n return (\n <div\n role={role}\n aria-live={ariaLive}\n aria-atomic=\"true\"\n className={cn(\n toastVariants({ size }),\n colors,\n isExiting ? exitAnim : !isEntered ? enterAnim : undefined,\n isExiting && 'pointer-events-none',\n data.className,\n )}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {/* Icon */}\n {data.icon !== undefined ? (\n data.icon && <span className=\"shrink-0\">{data.icon}</span>\n ) : (\n data.type !== 'default' && (\n <span className=\"shrink-0\">\n <StatusIcon className=\"icon-sm\" />\n </span>\n )\n )}\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-semibold\">{data.message}</div>\n {data.description && (\n <div className={cn('mt-1 opacity-80', size === 'sm' ? 'text-xs' : 'text-sm')}>\n {data.description}\n </div>\n )}\n </div>\n\n {/* Actions */}\n {(data.action || data.cancel) && (\n <div className=\"flex items-center gap-1.5 shrink-0\">\n {data.cancel && (\n <button\n type=\"button\"\n className=\"px-2.5 py-1.5 text-xs font-semibold rounded-md opacity-70 hover:opacity-100 transition-opacity\"\n onClick={() => {\n data.cancel!.onClick()\n handleDismiss()\n }}\n >\n {data.cancel.label}\n </button>\n )}\n {data.action && (\n <button\n type=\"button\"\n className=\"px-2.5 py-1.5 text-xs font-semibold rounded-md bg-foreground/5 hover:bg-foreground/15 transition-colors\"\n onClick={() => {\n data.action!.onClick()\n handleDismiss()\n }}\n >\n {data.action.label}\n </button>\n )}\n </div>\n )}\n\n {/* Close button */}\n {showClose && dismissible && (\n <button\n type=\"button\"\n className=\"shrink-0 rounded-md p-1 opacity-70 hover:opacity-100 transition-opacity focus-visible:focus-ring\"\n onClick={handleDismiss}\n aria-label=\"Close\"\n >\n <DefaultCloseIcon className=\"icon-sm\" />\n </button>\n )}\n\n </div>\n )\n})\n\n// ═══════════════════════════════════════════════════════════════════\n// Toaster — renders all toasts\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface ToasterProps {\n /** Position on screen */\n position?: ToastPosition\n /** Default auto-dismiss duration in ms (0 = persistent) */\n duration?: number\n /** Max visible toasts */\n visibleToasts?: number\n /** Show close button on all toasts */\n closeButton?: boolean\n /** Use rich (filled) colors for status toasts — default: true */\n richColors?: boolean\n /** Expand all toasts (no stacking) */\n expand?: boolean\n /** Offset from screen edge in px */\n offset?: number\n /** Gap between toasts in px */\n gap?: number\n /** Toast size */\n size?: ToastSize\n /** Additional className for container */\n className?: string\n}\n\nfunction Toaster({\n position = 'bottom-right',\n duration = 4000,\n visibleToasts = 5,\n closeButton = false,\n richColors = true,\n expand = false,\n offset = 24,\n gap = 8,\n size = 'default',\n className,\n}: ToasterProps) {\n const toasts = useToastStore()\n const [expanded, setExpanded] = React.useState(false)\n\n const handleRemove = React.useCallback((id: string) => {\n globalStore.removeToast(id)\n }, [])\n\n const visible = toasts.slice(0, visibleToasts)\n\n const isTop = position.startsWith('top')\n const isCenter = position.includes('center')\n const isRight = position.includes('right')\n const isLeft = position.includes('left')\n\n // Position styles\n const positionClasses = cn(\n 'fixed z-toast flex flex-col pointer-events-none',\n isTop ? 'top-0' : 'bottom-0',\n isCenter ? 'left-1/2 -translate-x-1/2' : isRight ? 'right-0' : 'left-0',\n )\n\n return (\n <section\n aria-label=\"Notifications\"\n className={cn(positionClasses, className)}\n style={{\n padding: offset,\n gap,\n width: isCenter ? 'auto' : undefined,\n maxWidth: isCenter ? `calc(100vw - ${TOAST_VIEWPORT_MARGIN}px)` : undefined,\n }}\n onMouseEnter={() => setExpanded(true)}\n onMouseLeave={() => setExpanded(false)}\n >\n {visible.map((t, index) => {\n const isStacked = !expand && !expanded && index > 0\n return (\n <div\n key={t.id}\n className=\"transition-[transform,opacity] duration-normal ease-out\"\n style={{\n width: TOAST_WIDTH,\n maxWidth: `calc(100vw - ${TOAST_VIEWPORT_MARGIN}px)`,\n ...(isStacked\n ? {\n position: 'absolute' as const,\n ...(isTop ? { top: offset + index * TOAST_STACK_OFFSET } : { bottom: offset + index * TOAST_STACK_OFFSET }),\n ...(isCenter\n ? { left: '50%', transform: `translateX(-50%) scale(${1 - index * TOAST_STACK_SCALE_STEP})` }\n : isRight\n ? { right: offset, transform: `scale(${1 - index * TOAST_STACK_SCALE_STEP})` }\n : { left: offset, transform: `scale(${1 - index * TOAST_STACK_SCALE_STEP})` }),\n opacity: index < TOAST_STACK_VISIBLE_LAYERS ? 1 - index * TOAST_STACK_OPACITY_STEP : 0,\n zIndex: visibleToasts - index,\n pointerEvents: 'none' as const,\n }\n : { zIndex: visibleToasts - index }),\n }}\n >\n <ToastItem\n data={t}\n position={position}\n size={size}\n closeButton={closeButton}\n richColors={richColors}\n defaultDuration={duration}\n onRemove={handleRemove}\n />\n </div>\n )\n })}\n </section>\n )\n}\nToaster.displayName = 'Toaster'\n\n// ─── Exports ─────────────────────────────────────────────────────\nexport {\n toast,\n Toaster,\n toastVariants,\n}\n\nexport type {\n ToastOptions,\n PromiseOptions,\n}\n"],"mappings":"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","names":["toast","ToastItem"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/toast.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\n\n// ─── Built-in status icons (shared with Alert — no external dependency) ──────\n// All icons: Lucide-compatible 24×24 viewBox, strokeWidth=2, rounded caps/joins\nconst InfoIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n)\n\nconst SuccessIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n)\n\nconst WarningIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n)\n\nconst ErrorIcon = ({ className }: { className?: string }) => (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 8v5\" />\n <path d=\"M12 16h.01\" />\n </svg>\n)\n\nconst DefaultCloseIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n)\n\nconst LoadingIcon = ({ className }: { className?: string }) => (\n <svg className={cn('animate-spin', className)} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" strokeLinecap=\"round\" />\n </svg>\n)\n\n// ─── Status icon mapping ─────────────────────────────────────────\nconst STATUS_ICONS: Record<ToastType, React.FC<{ className?: string }>> = {\n default: InfoIcon,\n success: SuccessIcon,\n warning: WarningIcon,\n error: ErrorIcon,\n info: InfoIcon,\n loading: LoadingIcon,\n}\n\n// ─── Color × Type class mapping ─────────────────────────────────\nconst colorMap: Record<ToastType, string> = {\n default: 'bg-background-paper text-foreground border-border shadow-lg',\n success: 'bg-success-tint text-text-success border-success/20 shadow-lg',\n error: 'bg-error-tint text-text-error border-error/20 shadow-lg',\n warning: 'bg-warning-tint text-text-warning border-warning/20 shadow-lg',\n info: 'bg-info-tint text-text-info border-info/20 shadow-lg',\n loading: 'bg-background-paper text-foreground border-border shadow-lg',\n}\n\nconst richColorMap: Record<ToastType, string> = {\n default: 'bg-foreground text-background border-transparent shadow-lg',\n success: 'bg-success text-success-foreground border-transparent shadow-lg',\n error: 'bg-error text-error-foreground border-transparent shadow-lg',\n warning: 'bg-warning text-warning-foreground border-transparent shadow-lg',\n info: 'bg-info text-info-foreground border-transparent shadow-lg',\n loading: 'bg-foreground text-background border-transparent shadow-lg',\n}\n\n// ─── Constants (JS cannot read CSS variables at runtime) ─────────\nconst TOAST_EXIT_DURATION = 200 // --duration-normal (200ms)\nconst TOAST_MIN_RESUME_MS = 500 // --duration-slowest (500ms) — minimum time after hover resume\nconst TOAST_WIDTH = 360 // fixed toast width — smallest mobile viewport baseline\nconst TOAST_VIEWPORT_MARGIN = 48 // 2 × offset default (24px) — viewport safe area\nconst TOAST_STACK_OFFSET = 8 // --spacing-2 (8px) — vertical gap between stacked toasts\nconst TOAST_STACK_SCALE_STEP = 0.05 // scale reduction per stack level (0.95, 0.90, ...)\nconst TOAST_STACK_OPACITY_STEP = 0.15 // opacity reduction per stack level (0.85, 0.70, ...)\nconst TOAST_STACK_VISIBLE_LAYERS = 3 // max visible stacked layers before hidden\n\n// ─── Toast variants (CVA) ────────────────────────────────────────\nconst toastVariants = cva(\n 'group pointer-events-auto relative flex items-center gap-2.5 border w-full overflow-hidden transition-all',\n {\n variants: {\n size: {\n sm: 'p-3 text-sm rounded-md',\n default: 'p-4 text-md rounded-lg',\n lg: 'p-5 text-md rounded-lg',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\n// ─── Types ───────────────────────────────────────────────────────\nexport type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info' | 'loading'\nexport type ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\nexport type ToastSize = 'sm' | 'default' | 'lg'\n\nexport interface ToastAction {\n label: string\n onClick: () => void\n}\n\nexport interface ToastData {\n id: string\n type: ToastType\n message: React.ReactNode\n description?: React.ReactNode\n duration?: number\n dismissible?: boolean\n closeButton?: boolean\n icon?: React.ReactNode\n action?: ToastAction\n cancel?: ToastAction\n onDismiss?: (toast: ToastData) => void\n onAutoClose?: (toast: ToastData) => void\n className?: string\n /** Promise state — managed internally */\n _promiseState?: 'loading' | 'success' | 'error'\n}\n\n// ─── Global toast store ──────────────────────────────────────────\ntype ToastListener = () => void\n\ninterface ToastStore {\n toasts: ToastData[]\n listeners: Set<ToastListener>\n addToast: (toast: ToastData) => void\n removeToast: (id: string) => void\n updateToast: (id: string, updates: Partial<ToastData>) => void\n removeAll: () => void\n subscribe: (listener: ToastListener) => () => void\n}\n\nfunction createToastStore(): ToastStore {\n const store: ToastStore = {\n toasts: [],\n listeners: new Set(),\n addToast(toast) {\n store.toasts = [toast, ...store.toasts]\n store.listeners.forEach((l) => l())\n },\n removeToast(id) {\n store.toasts = store.toasts.filter((t) => t.id !== id)\n store.listeners.forEach((l) => l())\n },\n updateToast(id, updates) {\n store.toasts = store.toasts.map((t) => (t.id === id ? { ...t, ...updates } : t))\n store.listeners.forEach((l) => l())\n },\n removeAll() {\n store.toasts = []\n store.listeners.forEach((l) => l())\n },\n subscribe(listener) {\n store.listeners.add(listener)\n return () => { store.listeners.delete(listener) }\n },\n }\n return store\n}\n\nconst globalStore = createToastStore()\n\nfunction useToastStore() {\n const [, forceUpdate] = React.useState(0)\n React.useEffect(() => {\n return globalStore.subscribe(() => forceUpdate((n) => n + 1))\n }, [])\n return globalStore.toasts\n}\n\n// ─── Toast ID generator ─────────────────────────────────────────\nlet toastCounter = 0\nfunction genId() {\n toastCounter += 1\n return `toast-${toastCounter}-${Date.now()}`\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// Imperative API: toast()\n// ═══════════════════════════════════════════════════════════════════\n\ninterface ToastOptions {\n id?: string\n description?: React.ReactNode\n duration?: number\n dismissible?: boolean\n closeButton?: boolean\n icon?: React.ReactNode\n action?: ToastAction\n cancel?: ToastAction\n onDismiss?: (toast: ToastData) => void\n onAutoClose?: (toast: ToastData) => void\n className?: string\n}\n\ninterface PromiseOptions<T> {\n loading: React.ReactNode\n success: React.ReactNode | ((data: T) => React.ReactNode)\n error: React.ReactNode | ((err: unknown) => React.ReactNode)\n finally?: () => void\n description?: {\n loading?: React.ReactNode\n success?: React.ReactNode | ((data: T) => React.ReactNode)\n error?: React.ReactNode | ((err: unknown) => React.ReactNode)\n }\n}\n\nfunction createToast(message: React.ReactNode, type: ToastType, opts?: ToastOptions): string {\n const id = opts?.id ?? genId()\n\n // If updating existing toast, just update\n const existing = globalStore.toasts.find((t) => t.id === id)\n if (existing) {\n globalStore.updateToast(id, { message, type, ...opts })\n return id\n }\n\n globalStore.addToast({\n id,\n type,\n message,\n description: opts?.description,\n duration: opts?.duration,\n dismissible: opts?.dismissible,\n closeButton: opts?.closeButton,\n icon: opts?.icon,\n action: opts?.action,\n cancel: opts?.cancel,\n onDismiss: opts?.onDismiss,\n onAutoClose: opts?.onAutoClose,\n className: opts?.className,\n })\n return id\n}\n\nfunction toast(message: React.ReactNode, opts?: ToastOptions): string {\n return createToast(message, 'default', opts)\n}\n\ntoast.success = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'success', opts)\n\ntoast.error = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'error', opts)\n\ntoast.warning = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'warning', opts)\n\ntoast.info = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'info', opts)\n\ntoast.loading = (message: React.ReactNode, opts?: ToastOptions) =>\n createToast(message, 'loading', { ...opts, duration: 0 })\n\ntoast.promise = <T,>(\n promise: Promise<T>,\n opts: PromiseOptions<T>,\n toastOpts?: ToastOptions\n): Promise<T> => {\n const id = createToast(opts.loading, 'loading', {\n ...toastOpts,\n duration: 0,\n })\n\n promise\n .then((data) => {\n const msg = typeof opts.success === 'function' ? opts.success(data) : opts.success\n const desc = typeof opts.description?.success === 'function'\n ? opts.description.success(data)\n : opts.description?.success\n globalStore.updateToast(id, {\n type: 'success',\n message: msg,\n description: desc,\n duration: toastOpts?.duration,\n _promiseState: 'success',\n })\n })\n .catch((err) => {\n const msg = typeof opts.error === 'function' ? opts.error(err) : opts.error\n const desc = typeof opts.description?.error === 'function'\n ? opts.description.error(err)\n : opts.description?.error\n globalStore.updateToast(id, {\n type: 'error',\n message: msg,\n description: desc,\n duration: toastOpts?.duration,\n _promiseState: 'error',\n })\n })\n .finally(() => {\n opts.finally?.()\n })\n\n return promise\n}\n\ntoast.dismiss = (id?: string) => {\n if (id) {\n globalStore.removeToast(id)\n } else {\n globalStore.removeAll()\n }\n}\n\ntoast.custom = (render: (t: ToastData) => React.ReactNode, opts?: ToastOptions): string => {\n const id = opts?.id ?? genId()\n globalStore.addToast({\n id,\n type: 'default',\n message: render as unknown as React.ReactNode,\n duration: opts?.duration,\n dismissible: opts?.dismissible,\n className: opts?.className,\n onDismiss: opts?.onDismiss,\n onAutoClose: opts?.onAutoClose,\n _promiseState: undefined,\n })\n return id\n}\n\n// ═══════════════════════════════════════════════════════════════════\n// ToastItem — individual toast renderer\n// ═══════════════════════════════════════════════════════════════════\n\ninterface ToastItemProps {\n data: ToastData\n position: ToastPosition\n size: ToastSize\n closeButton: boolean\n closeLabel: string\n richColors: boolean\n defaultDuration: number\n onRemove: (id: string) => void\n}\n\nconst ToastItem = React.memo(function ToastItem({\n data,\n position,\n size,\n closeButton: globalCloseButton,\n closeLabel,\n richColors,\n defaultDuration,\n onRemove,\n}: ToastItemProps) {\n const [isExiting, setIsExiting] = React.useState(false)\n const [isEntered, setIsEntered] = React.useState(false)\n const [isPaused, setIsPaused] = React.useState(false)\n const timerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n const remainingRef = React.useRef<number>(0)\n const startTimeRef = React.useRef<number>(0)\n\n // Enter animation — play once on mount, then remove class\n React.useEffect(() => {\n const timer = setTimeout(() => setIsEntered(true), TOAST_EXIT_DURATION)\n return () => clearTimeout(timer)\n }, [])\n\n const showClose = data.closeButton ?? globalCloseButton\n const dismissible = data.dismissible !== false\n const duration = data.type === 'loading' ? 0 : (data.duration ?? defaultDuration)\n\n // ARIA — error/warning use assertive, others polite\n const role = data.type === 'error' || data.type === 'warning' ? 'alert' : 'status'\n const ariaLive = data.type === 'error' || data.type === 'warning' ? 'assertive' : 'polite'\n\n const colors = richColors ? richColorMap[data.type] : colorMap[data.type]\n const StatusIcon = STATUS_ICONS[data.type]\n\n // Animation classes based on position\n const enterAnim = position.includes('right')\n ? 'animate-toast-slide-in-right'\n : position.includes('left')\n ? 'animate-toast-slide-in-left'\n : position.includes('top')\n ? 'animate-toast-slide-in-top'\n : 'animate-toast-slide-in-bottom'\n\n const exitAnim = position.includes('right')\n ? 'animate-toast-slide-out-right'\n : position.includes('left')\n ? 'animate-toast-slide-out-left'\n : position.includes('top')\n ? 'animate-toast-slide-out-top'\n : 'animate-toast-slide-out-bottom'\n\n const handleDismiss = React.useCallback(() => {\n if (!dismissible) return\n setIsExiting(true)\n data.onDismiss?.(data)\n // Wait for exit animation then remove\n setTimeout(() => onRemove(data.id), TOAST_EXIT_DURATION)\n }, [data, dismissible, onRemove])\n\n const handleAutoClose = React.useCallback(() => {\n setIsExiting(true)\n data.onAutoClose?.(data)\n setTimeout(() => onRemove(data.id), TOAST_EXIT_DURATION)\n }, [data, onRemove])\n\n // Auto-dismiss timer with pause support\n React.useEffect(() => {\n if (duration <= 0) return\n\n remainingRef.current = duration\n startTimeRef.current = Date.now()\n\n timerRef.current = setTimeout(handleAutoClose, duration)\n\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current)\n }\n }, [duration, handleAutoClose])\n\n // Pause/resume on hover\n const handleMouseEnter = React.useCallback(() => {\n if (duration <= 0) return\n setIsPaused(true)\n if (timerRef.current) {\n clearTimeout(timerRef.current)\n remainingRef.current -= Date.now() - startTimeRef.current\n }\n }, [duration])\n\n const handleMouseLeave = React.useCallback(() => {\n if (duration <= 0) return\n setIsPaused(false)\n startTimeRef.current = Date.now()\n timerRef.current = setTimeout(handleAutoClose, Math.max(remainingRef.current, TOAST_MIN_RESUME_MS))\n }, [duration, handleAutoClose])\n\n // Reset timer when toast updates (promise resolve)\n React.useEffect(() => {\n if (data._promiseState === 'success' || data._promiseState === 'error') {\n const newDuration = data.duration ?? defaultDuration\n if (newDuration > 0) {\n if (timerRef.current) clearTimeout(timerRef.current)\n remainingRef.current = newDuration\n startTimeRef.current = Date.now()\n timerRef.current = setTimeout(handleAutoClose, newDuration)\n }\n }\n }, [data._promiseState, data.duration, defaultDuration, handleAutoClose])\n\n return (\n <div\n role={role}\n aria-live={ariaLive}\n aria-atomic=\"true\"\n className={cn(\n toastVariants({ size }),\n colors,\n isExiting ? exitAnim : !isEntered ? enterAnim : undefined,\n isExiting && 'pointer-events-none',\n data.className,\n )}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {/* Icon */}\n {data.icon !== undefined ? (\n data.icon && <span className=\"shrink-0\">{data.icon}</span>\n ) : (\n data.type !== 'default' && (\n <span className=\"shrink-0\">\n <StatusIcon className=\"icon-sm\" />\n </span>\n )\n )}\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-semibold\">{data.message}</div>\n {data.description && (\n <div className={cn('mt-1 opacity-80', size === 'sm' ? 'text-xs' : 'text-sm')}>\n {data.description}\n </div>\n )}\n </div>\n\n {/* Actions */}\n {(data.action || data.cancel) && (\n <div className=\"flex items-center gap-1.5 shrink-0\">\n {data.cancel && (\n <button\n type=\"button\"\n className=\"px-2.5 py-1.5 text-xs font-semibold rounded-md opacity-70 hover:opacity-100 transition-opacity\"\n onClick={() => {\n data.cancel!.onClick()\n handleDismiss()\n }}\n >\n {data.cancel.label}\n </button>\n )}\n {data.action && (\n <button\n type=\"button\"\n className=\"px-2.5 py-1.5 text-xs font-semibold rounded-md bg-foreground/5 hover:bg-foreground/15 transition-colors\"\n onClick={() => {\n data.action!.onClick()\n handleDismiss()\n }}\n >\n {data.action.label}\n </button>\n )}\n </div>\n )}\n\n {/* Close button */}\n {showClose && dismissible && (\n <button\n type=\"button\"\n className=\"shrink-0 rounded-md p-1 opacity-70 hover:opacity-100 transition-opacity focus-visible:focus-ring\"\n onClick={handleDismiss}\n aria-label={closeLabel}\n >\n <DefaultCloseIcon className=\"icon-sm\" />\n </button>\n )}\n\n </div>\n )\n})\n\n// ═══════════════════════════════════════════════════════════════════\n// Toaster — renders all toasts\n// ═══════════════════════════════════════════════════════════════════\n\nexport interface ToasterProps {\n /** Position on screen */\n position?: ToastPosition\n /** Default auto-dismiss duration in ms (0 = persistent) */\n duration?: number\n /** Max visible toasts */\n visibleToasts?: number\n /** Show close button on all toasts */\n closeButton?: boolean\n /** Accessible label for the close button (screen readers) — localize per page */\n closeLabel?: string\n /** Use rich (filled) colors for status toasts — default: true */\n richColors?: boolean\n /** Expand all toasts (no stacking) */\n expand?: boolean\n /** Offset from screen edge in px */\n offset?: number\n /** Gap between toasts in px */\n gap?: number\n /** Toast size */\n size?: ToastSize\n /** Additional className for container */\n className?: string\n}\n\nfunction Toaster({\n position = 'bottom-right',\n duration = 4000,\n visibleToasts = 5,\n closeButton = false,\n closeLabel = 'Close',\n richColors = true,\n expand = false,\n offset = 24,\n gap = 8,\n size = 'default',\n className,\n}: ToasterProps) {\n const toasts = useToastStore()\n const [expanded, setExpanded] = React.useState(false)\n\n const handleRemove = React.useCallback((id: string) => {\n globalStore.removeToast(id)\n }, [])\n\n const visible = toasts.slice(0, visibleToasts)\n\n const isTop = position.startsWith('top')\n const isCenter = position.includes('center')\n const isRight = position.includes('right')\n const isLeft = position.includes('left')\n\n // Position styles\n const positionClasses = cn(\n 'fixed z-toast flex flex-col pointer-events-none',\n isTop ? 'top-0' : 'bottom-0',\n isCenter ? 'left-1/2 -translate-x-1/2' : isRight ? 'right-0' : 'left-0',\n )\n\n return (\n <section\n aria-label=\"Notifications\"\n className={cn(positionClasses, className)}\n style={{\n padding: offset,\n gap,\n width: isCenter ? 'auto' : undefined,\n maxWidth: isCenter ? `calc(100vw - ${TOAST_VIEWPORT_MARGIN}px)` : undefined,\n }}\n onMouseEnter={() => setExpanded(true)}\n onMouseLeave={() => setExpanded(false)}\n >\n {visible.map((t, index) => {\n const isStacked = !expand && !expanded && index > 0\n return (\n <div\n key={t.id}\n className=\"transition-[transform,opacity] duration-normal ease-out\"\n style={{\n width: TOAST_WIDTH,\n maxWidth: `calc(100vw - ${TOAST_VIEWPORT_MARGIN}px)`,\n ...(isStacked\n ? {\n position: 'absolute' as const,\n ...(isTop ? { top: offset + index * TOAST_STACK_OFFSET } : { bottom: offset + index * TOAST_STACK_OFFSET }),\n ...(isCenter\n ? { left: '50%', transform: `translateX(-50%) scale(${1 - index * TOAST_STACK_SCALE_STEP})` }\n : isRight\n ? { right: offset, transform: `scale(${1 - index * TOAST_STACK_SCALE_STEP})` }\n : { left: offset, transform: `scale(${1 - index * TOAST_STACK_SCALE_STEP})` }),\n opacity: index < TOAST_STACK_VISIBLE_LAYERS ? 1 - index * TOAST_STACK_OPACITY_STEP : 0,\n zIndex: visibleToasts - index,\n pointerEvents: 'none' as const,\n }\n : { zIndex: visibleToasts - index }),\n }}\n >\n <ToastItem\n data={t}\n position={position}\n size={size}\n closeButton={closeButton}\n closeLabel={closeLabel}\n richColors={richColors}\n defaultDuration={duration}\n onRemove={handleRemove}\n />\n </div>\n )\n })}\n </section>\n )\n}\nToaster.displayName = 'Toaster'\n\n// ─── Exports ─────────────────────────────────────────────────────\nexport {\n toast,\n Toaster,\n toastVariants,\n}\n\nexport type {\n ToastOptions,\n PromiseOptions,\n}\n"],"mappings":"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","names":["toast","ToastItem"]}
|
|
@@ -202,6 +202,7 @@ const ToastItem = React.memo(function ToastItem2({
|
|
|
202
202
|
position,
|
|
203
203
|
size,
|
|
204
204
|
closeButton: globalCloseButton,
|
|
205
|
+
closeLabel,
|
|
205
206
|
richColors,
|
|
206
207
|
defaultDuration,
|
|
207
208
|
onRemove
|
|
@@ -323,7 +324,7 @@ const ToastItem = React.memo(function ToastItem2({
|
|
|
323
324
|
type: "button",
|
|
324
325
|
className: "shrink-0 rounded-md p-1 opacity-70 hover:opacity-100 transition-opacity focus-visible:focus-ring",
|
|
325
326
|
onClick: handleDismiss,
|
|
326
|
-
"aria-label":
|
|
327
|
+
"aria-label": closeLabel,
|
|
327
328
|
children: /* @__PURE__ */ jsx(DefaultCloseIcon, { className: "icon-sm" })
|
|
328
329
|
}
|
|
329
330
|
)
|
|
@@ -336,6 +337,7 @@ function Toaster({
|
|
|
336
337
|
duration = 4e3,
|
|
337
338
|
visibleToasts = 5,
|
|
338
339
|
closeButton = false,
|
|
340
|
+
closeLabel = "Close",
|
|
339
341
|
richColors = true,
|
|
340
342
|
expand = false,
|
|
341
343
|
offset = 24,
|
|
@@ -396,6 +398,7 @@ function Toaster({
|
|
|
396
398
|
position,
|
|
397
399
|
size,
|
|
398
400
|
closeButton,
|
|
401
|
+
closeLabel,
|
|
399
402
|
richColors,
|
|
400
403
|
defaultDuration: duration,
|
|
401
404
|
onRemove: handleRemove
|