acai-ui-library 0.1.13 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/components/alert.cjs +3 -2
  2. package/dist/components/alert.cjs.map +1 -1
  3. package/dist/components/alert.js +3 -2
  4. package/dist/components/alert.js.map +1 -1
  5. package/dist/components/card.cjs +1 -1
  6. package/dist/components/card.cjs.map +1 -1
  7. package/dist/components/card.js +1 -1
  8. package/dist/components/card.js.map +1 -1
  9. package/dist/components/checkbox.cjs +2 -1
  10. package/dist/components/checkbox.cjs.map +1 -1
  11. package/dist/components/checkbox.js +2 -1
  12. package/dist/components/checkbox.js.map +1 -1
  13. package/dist/components/data-table.cjs +2 -1
  14. package/dist/components/data-table.cjs.map +1 -1
  15. package/dist/components/data-table.js +2 -1
  16. package/dist/components/data-table.js.map +1 -1
  17. package/dist/components/date-picker.cjs.map +1 -1
  18. package/dist/components/date-picker.js.map +1 -1
  19. package/dist/components/impersonation-banner.cjs +137 -0
  20. package/dist/components/impersonation-banner.cjs.map +1 -0
  21. package/dist/components/impersonation-banner.d.cts +36 -0
  22. package/dist/components/impersonation-banner.d.ts +36 -0
  23. package/dist/components/impersonation-banner.js +101 -0
  24. package/dist/components/impersonation-banner.js.map +1 -0
  25. package/dist/components/input.cjs +2 -1
  26. package/dist/components/input.cjs.map +1 -1
  27. package/dist/components/input.js +2 -1
  28. package/dist/components/input.js.map +1 -1
  29. package/dist/components/item.cjs +1 -2
  30. package/dist/components/item.cjs.map +1 -1
  31. package/dist/components/item.js +1 -2
  32. package/dist/components/item.js.map +1 -1
  33. package/dist/components/pagination.cjs +3 -1
  34. package/dist/components/pagination.cjs.map +1 -1
  35. package/dist/components/pagination.d.cts +1 -1
  36. package/dist/components/pagination.d.ts +1 -1
  37. package/dist/components/pagination.js +3 -1
  38. package/dist/components/pagination.js.map +1 -1
  39. package/dist/components/read-only-guard.cjs +103 -0
  40. package/dist/components/read-only-guard.cjs.map +1 -0
  41. package/dist/components/read-only-guard.d.cts +40 -0
  42. package/dist/components/read-only-guard.d.ts +40 -0
  43. package/dist/components/read-only-guard.js +64 -0
  44. package/dist/components/read-only-guard.js.map +1 -0
  45. package/dist/components/stepper.cjs.map +1 -1
  46. package/dist/components/stepper.js.map +1 -1
  47. package/dist/components/typography.cjs +4 -4
  48. package/dist/components/typography.cjs.map +1 -1
  49. package/dist/components/typography.js +4 -4
  50. package/dist/components/typography.js.map +1 -1
  51. package/dist/index.cjs +236 -12
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +3 -0
  54. package/dist/index.d.ts +3 -0
  55. package/dist/index.js +224 -12
  56. package/dist/index.js.map +1 -1
  57. package/dist/lib/impersonation.cjs +127 -0
  58. package/dist/lib/impersonation.cjs.map +1 -0
  59. package/dist/lib/impersonation.d.cts +45 -0
  60. package/dist/lib/impersonation.d.ts +45 -0
  61. package/dist/lib/impersonation.js +86 -0
  62. package/dist/lib/impersonation.js.map +1 -0
  63. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/date-picker.tsx","../../src/lib/utils.ts","../../src/components/button.tsx","../../src/components/calendar.tsx","../../src/components/popover.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { CalendarIcon } from \"lucide-react\"\nimport type { DateRange, Matcher } from \"react-day-picker\"\nimport { cn } from \"../lib/utils\"\nimport { Button } from \"./button\"\nimport { Calendar } from \"./calendar\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\"\n\nexport type DatePickerPreset =\n | { label: string; value: Date }\n | { label: string; value: { from: Date; to: Date } }\n\nexport interface DatePickerProps {\n /** Selected value. For `mode=\"single\"` this is a Date, for `mode=\"range\"` this is a range object. */\n date?: Date | DateRange\n /** Called with the new selection. */\n onDateChange?: (date: Date | DateRange | undefined) => void\n /** Selection mode. Defaults to \"single\". */\n mode?: \"single\" | \"range\"\n /** Placeholder for the trigger when no date is picked. */\n placeholder?: string\n /** Classname applied to the trigger button. */\n className?: string\n /** Optional date format string — reserved for future use. */\n formatStr?: string\n /** Optional preset list rendered in a sidebar to the left of the calendar. */\n presets?: DatePickerPreset[]\n /** Passed through to the underlying Calendar. */\n disabled?: Matcher | Matcher[]\n}\n\nfunction formatDate(d: Date): string {\n return d.toLocaleDateString()\n}\n\nfunction DatePicker({\n date,\n onDateChange,\n mode = \"single\",\n placeholder = \"Pick a date\",\n className,\n presets,\n disabled,\n}: DatePickerProps) {\n const label = React.useMemo(() => {\n if (!date) return <span>{placeholder}</span>\n if (mode === \"range\") {\n const range = date as DateRange\n if (range.from && range.to) {\n return `${formatDate(range.from)} – ${formatDate(range.to)}`\n }\n if (range.from) return formatDate(range.from)\n return <span>{placeholder}</span>\n }\n return (date as Date).toLocaleDateString()\n }, [date, mode, placeholder])\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"w-[280px] justify-start text-left font-normal\",\n !date && \"text-muted-foreground\",\n className\n )}\n >\n <CalendarIcon className=\"me-2 h-4 w-4\" />\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"flex\">\n {presets && presets.length > 0 && (\n <div className=\"flex flex-col gap-1 border-e p-2 min-w-[140px]\">\n {presets.map((preset) => (\n <Button\n key={preset.label}\n variant=\"ghost\"\n size=\"sm\"\n className=\"justify-start font-normal\"\n onClick={() => onDateChange?.(preset.value as Date | DateRange)}\n >\n {preset.label}\n </Button>\n ))}\n </div>\n )}\n <div>\n {mode === \"range\" ? (\n <Calendar\n mode=\"range\"\n selected={date as DateRange | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n autoFocus\n />\n ) : (\n <Calendar\n mode=\"single\"\n selected={date as Date | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n autoFocus\n />\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n\nexport { DatePicker }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Loader2 } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground hover:bg-primary-hover\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive-hover\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary-hover\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground\",\n link:\n \"text-primary underline-offset-4 hover:underline\",\n success:\n \"bg-success text-success-foreground hover:bg-success-hover\",\n },\n size: {\n xs: \"h-7 px-2.5 text-xs\",\n sm: \"h-9 px-3\",\n default: \"h-10 px-4 py-2\",\n lg: \"h-11 px-8\",\n icon: \"h-10 w-10\",\n \"icon-sm\": \"h-8 w-8\",\n },\n shape: {\n default: \"rounded-md\",\n rounded: \"rounded-lg\",\n pill: \"rounded-full\",\n square: \"rounded-none\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n shape: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n loading?: boolean\n prefixIcon?: React.ReactNode\n suffixIcon?: React.ReactNode\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n shape,\n asChild = false,\n loading = false,\n prefixIcon,\n suffixIcon,\n children,\n disabled,\n ...props\n },\n ref\n ) => {\n const Comp = asChild ? Slot : \"button\"\n const isDisabled = disabled || loading\n\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, shape, className }))}\n ref={ref}\n disabled={isDisabled}\n {...props}\n >\n {loading && <Loader2 className=\"animate-spin\" />}\n {!loading && prefixIcon}\n {children}\n {suffixIcon}\n </Comp>\n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\nimport { DayPicker } from \"react-day-picker\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker>\n\nfunction Calendar({ className, classNames, showOutsideDays = true, captionLayout = \"dropdown\", ...props }: CalendarProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"w-[260px] rounded-lg p-3\", className)}\n classNames={{\n months: \"flex flex-col\",\n month: \"space-y-3\",\n month_caption: \"relative flex h-8 items-center justify-center\",\n caption_label: \"text-sm font-medium hidden\",\n nav: \"flex items-center\",\n button_previous: cn(\n \"absolute start-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n button_next: cn(\n \"absolute end-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n month_grid: \"w-full border-collapse\",\n weekdays: \"flex w-full\",\n weekday:\n \"flex-1 h-8 flex items-center justify-center text-[11px] font-medium text-muted-foreground uppercase tracking-wider\",\n week: \"flex w-full mt-1\",\n day: \"flex-1 h-8 p-0 relative focus-within:z-20 flex items-center justify-center text-sm\",\n day_button: cn(\n \"inline-flex size-8 items-center justify-center rounded-md bg-transparent text-sm font-normal cursor-pointer border-none hover:bg-[var(--hc-color-border-subtle)] transition-colors\"\n ),\n range_end: \"day-range-end\",\n selected:\n \"[&>button]:bg-[var(--hc-primary-600)] [&>button]:text-white [&>button]:hover:bg-[var(--hc-primary-600)] [&>button]:hover:text-white [&>button]:font-medium\",\n today: \"[&>button]:font-semibold [&>button]:text-[var(--hc-primary-600)]\",\n outside:\n \"day-outside [&>button]:bg-transparent [&>button]:text-[var(--hc-grey-200)]\",\n disabled: \"[&>button]:text-[var(--hc-grey-200)] [&>button]:opacity-50 [&>button]:cursor-default\",\n range_middle:\n \"[&>button]:bg-[var(--hc-primary-100)] [&>button]:text-foreground [&>button]:rounded-none\",\n range_start: \"[&>button]:rounded-e-none\",\n dropdowns: \"flex items-center gap-1.5 justify-center [&>select]:flex-1\",\n dropdown:\n \"h-7 w-[88px] rounded-md border border-[var(--hc-color-border-subtle)] bg-background px-2 text-xs font-medium text-foreground cursor-pointer outline-none accent-[var(--hc-primary-600)] focus:border-[var(--hc-primary-500)] focus:ring-[2px] focus:ring-[var(--hc-primary-500)]/20 [&>option:checked]:bg-[var(--hc-primary-600)] [&>option:checked]:text-white [&>option]:py-1\",\n hidden: \"invisible\",\n ...classNames,\n }}\n captionLayout={captionLayout}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === \"left\" ? ChevronLeft : ChevronRight\n return <Icon className=\"size-4\" />\n },\n }}\n {...props}\n />\n )\n}\nCalendar.displayName = \"Calendar\"\n\nexport { Calendar }\n","import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\nimport { cn } from \"../lib/utils\"\n\nconst Popover = PopoverPrimitive.Root\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent }\n"],"mappings":"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","names":["React","import_lucide_react","import_lucide_react","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/components/date-picker.tsx","../../src/lib/utils.ts","../../src/components/button.tsx","../../src/components/calendar.tsx","../../src/components/popover.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { CalendarIcon } from \"lucide-react\"\nimport type { DateRange, Matcher } from \"react-day-picker\"\nimport { cn } from \"../lib/utils\"\nimport { Button } from \"./button\"\nimport { Calendar } from \"./calendar\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\"\n\nexport type DatePickerPreset =\n | { label: string; value: Date }\n | { label: string; value: { from: Date; to: Date } }\n\nexport interface DatePickerProps {\n /** Selected value. For `mode=\"single\"` this is a Date, for `mode=\"range\"` this is a range object. */\n date?: Date | DateRange\n /** Called with the new selection. */\n onDateChange?: (date: Date | DateRange | undefined) => void\n /** Selection mode. Defaults to \"single\". */\n mode?: \"single\" | \"range\"\n /** Placeholder for the trigger when no date is picked. */\n placeholder?: string\n /** Classname applied to the trigger button. */\n className?: string\n /** Optional date format string — reserved for future use. */\n formatStr?: string\n /** Optional preset list rendered in a sidebar to the left of the calendar. */\n presets?: DatePickerPreset[]\n /** Passed through to the underlying Calendar. */\n disabled?: Matcher | Matcher[]\n}\n\nfunction formatDate(d: Date): string {\n return d.toLocaleDateString()\n}\n\nfunction DatePicker({\n date,\n onDateChange,\n mode = \"single\",\n placeholder = \"Pick a date\",\n className,\n presets,\n disabled,\n}: DatePickerProps) {\n const label = React.useMemo(() => {\n if (!date) return <span>{placeholder}</span>\n if (mode === \"range\") {\n const range = date as DateRange\n if (range.from && range.to) {\n return `${formatDate(range.from)} – ${formatDate(range.to)}`\n }\n if (range.from) return formatDate(range.from)\n return <span>{placeholder}</span>\n }\n return (date as Date).toLocaleDateString()\n }, [date, mode, placeholder])\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"w-[280px] justify-start text-left font-normal\",\n !date && \"text-muted-foreground\",\n className\n )}\n >\n <CalendarIcon className=\"me-2 h-4 w-4\" />\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"flex\">\n {presets && presets.length > 0 && (\n <div className=\"flex flex-col gap-1 border-e p-2 min-w-[140px]\">\n {presets.map((preset) => (\n <Button\n key={preset.label}\n variant=\"ghost\"\n size=\"sm\"\n className=\"justify-start font-normal\"\n onClick={() => onDateChange?.(preset.value as Date | DateRange)}\n >\n {preset.label}\n </Button>\n ))}\n </div>\n )}\n <div>\n {mode === \"range\" ? (\n <Calendar\n mode=\"range\"\n selected={date as DateRange | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n // Focus moves into the calendar the user just opened (keyboard navigation).\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n />\n ) : (\n <Calendar\n mode=\"single\"\n selected={date as Date | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n // Focus moves into the calendar the user just opened (keyboard navigation).\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n />\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n\nexport { DatePicker }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Loader2 } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground hover:bg-primary-hover\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive-hover\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary-hover\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground\",\n link:\n \"text-primary underline-offset-4 hover:underline\",\n success:\n \"bg-success text-success-foreground hover:bg-success-hover\",\n },\n size: {\n xs: \"h-7 px-2.5 text-xs\",\n sm: \"h-9 px-3\",\n default: \"h-10 px-4 py-2\",\n lg: \"h-11 px-8\",\n icon: \"h-10 w-10\",\n \"icon-sm\": \"h-8 w-8\",\n },\n shape: {\n default: \"rounded-md\",\n rounded: \"rounded-lg\",\n pill: \"rounded-full\",\n square: \"rounded-none\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n shape: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n loading?: boolean\n prefixIcon?: React.ReactNode\n suffixIcon?: React.ReactNode\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n shape,\n asChild = false,\n loading = false,\n prefixIcon,\n suffixIcon,\n children,\n disabled,\n ...props\n },\n ref\n ) => {\n const Comp = asChild ? Slot : \"button\"\n const isDisabled = disabled || loading\n\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, shape, className }))}\n ref={ref}\n disabled={isDisabled}\n {...props}\n >\n {loading && <Loader2 className=\"animate-spin\" />}\n {!loading && prefixIcon}\n {children}\n {suffixIcon}\n </Comp>\n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\nimport { DayPicker } from \"react-day-picker\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker>\n\nfunction Calendar({ className, classNames, showOutsideDays = true, captionLayout = \"dropdown\", ...props }: CalendarProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"w-[260px] rounded-lg p-3\", className)}\n classNames={{\n months: \"flex flex-col\",\n month: \"space-y-3\",\n month_caption: \"relative flex h-8 items-center justify-center\",\n caption_label: \"text-sm font-medium hidden\",\n nav: \"flex items-center\",\n button_previous: cn(\n \"absolute start-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n button_next: cn(\n \"absolute end-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n month_grid: \"w-full border-collapse\",\n weekdays: \"flex w-full\",\n weekday:\n \"flex-1 h-8 flex items-center justify-center text-[11px] font-medium text-muted-foreground uppercase tracking-wider\",\n week: \"flex w-full mt-1\",\n day: \"flex-1 h-8 p-0 relative focus-within:z-20 flex items-center justify-center text-sm\",\n day_button: cn(\n \"inline-flex size-8 items-center justify-center rounded-md bg-transparent text-sm font-normal cursor-pointer border-none hover:bg-[var(--hc-color-border-subtle)] transition-colors\"\n ),\n range_end: \"day-range-end\",\n selected:\n \"[&>button]:bg-[var(--hc-primary-600)] [&>button]:text-white [&>button]:hover:bg-[var(--hc-primary-600)] [&>button]:hover:text-white [&>button]:font-medium\",\n today: \"[&>button]:font-semibold [&>button]:text-[var(--hc-primary-600)]\",\n outside:\n \"day-outside [&>button]:bg-transparent [&>button]:text-[var(--hc-grey-200)]\",\n disabled: \"[&>button]:text-[var(--hc-grey-200)] [&>button]:opacity-50 [&>button]:cursor-default\",\n range_middle:\n \"[&>button]:bg-[var(--hc-primary-100)] [&>button]:text-foreground [&>button]:rounded-none\",\n range_start: \"[&>button]:rounded-e-none\",\n dropdowns: \"flex items-center gap-1.5 justify-center [&>select]:flex-1\",\n dropdown:\n \"h-7 w-[88px] rounded-md border border-[var(--hc-color-border-subtle)] bg-background px-2 text-xs font-medium text-foreground cursor-pointer outline-none accent-[var(--hc-primary-600)] focus:border-[var(--hc-primary-500)] focus:ring-[2px] focus:ring-[var(--hc-primary-500)]/20 [&>option:checked]:bg-[var(--hc-primary-600)] [&>option:checked]:text-white [&>option]:py-1\",\n hidden: \"invisible\",\n ...classNames,\n }}\n captionLayout={captionLayout}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === \"left\" ? ChevronLeft : ChevronRight\n return <Icon className=\"size-4\" />\n },\n }}\n {...props}\n />\n )\n}\nCalendar.displayName = \"Calendar\"\n\nexport { Calendar }\n","import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\nimport { cn } from \"../lib/utils\"\n\nconst Popover = PopoverPrimitive.Root\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent }\n"],"mappings":"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","names":["React","import_lucide_react","import_lucide_react","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/date-picker.tsx","../../src/lib/utils.ts","../../src/components/button.tsx","../../src/components/calendar.tsx","../../src/components/popover.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { CalendarIcon } from \"lucide-react\"\nimport type { DateRange, Matcher } from \"react-day-picker\"\nimport { cn } from \"../lib/utils\"\nimport { Button } from \"./button\"\nimport { Calendar } from \"./calendar\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\"\n\nexport type DatePickerPreset =\n | { label: string; value: Date }\n | { label: string; value: { from: Date; to: Date } }\n\nexport interface DatePickerProps {\n /** Selected value. For `mode=\"single\"` this is a Date, for `mode=\"range\"` this is a range object. */\n date?: Date | DateRange\n /** Called with the new selection. */\n onDateChange?: (date: Date | DateRange | undefined) => void\n /** Selection mode. Defaults to \"single\". */\n mode?: \"single\" | \"range\"\n /** Placeholder for the trigger when no date is picked. */\n placeholder?: string\n /** Classname applied to the trigger button. */\n className?: string\n /** Optional date format string — reserved for future use. */\n formatStr?: string\n /** Optional preset list rendered in a sidebar to the left of the calendar. */\n presets?: DatePickerPreset[]\n /** Passed through to the underlying Calendar. */\n disabled?: Matcher | Matcher[]\n}\n\nfunction formatDate(d: Date): string {\n return d.toLocaleDateString()\n}\n\nfunction DatePicker({\n date,\n onDateChange,\n mode = \"single\",\n placeholder = \"Pick a date\",\n className,\n presets,\n disabled,\n}: DatePickerProps) {\n const label = React.useMemo(() => {\n if (!date) return <span>{placeholder}</span>\n if (mode === \"range\") {\n const range = date as DateRange\n if (range.from && range.to) {\n return `${formatDate(range.from)} – ${formatDate(range.to)}`\n }\n if (range.from) return formatDate(range.from)\n return <span>{placeholder}</span>\n }\n return (date as Date).toLocaleDateString()\n }, [date, mode, placeholder])\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"w-[280px] justify-start text-left font-normal\",\n !date && \"text-muted-foreground\",\n className\n )}\n >\n <CalendarIcon className=\"me-2 h-4 w-4\" />\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"flex\">\n {presets && presets.length > 0 && (\n <div className=\"flex flex-col gap-1 border-e p-2 min-w-[140px]\">\n {presets.map((preset) => (\n <Button\n key={preset.label}\n variant=\"ghost\"\n size=\"sm\"\n className=\"justify-start font-normal\"\n onClick={() => onDateChange?.(preset.value as Date | DateRange)}\n >\n {preset.label}\n </Button>\n ))}\n </div>\n )}\n <div>\n {mode === \"range\" ? (\n <Calendar\n mode=\"range\"\n selected={date as DateRange | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n autoFocus\n />\n ) : (\n <Calendar\n mode=\"single\"\n selected={date as Date | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n autoFocus\n />\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n\nexport { DatePicker }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Loader2 } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground hover:bg-primary-hover\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive-hover\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary-hover\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground\",\n link:\n \"text-primary underline-offset-4 hover:underline\",\n success:\n \"bg-success text-success-foreground hover:bg-success-hover\",\n },\n size: {\n xs: \"h-7 px-2.5 text-xs\",\n sm: \"h-9 px-3\",\n default: \"h-10 px-4 py-2\",\n lg: \"h-11 px-8\",\n icon: \"h-10 w-10\",\n \"icon-sm\": \"h-8 w-8\",\n },\n shape: {\n default: \"rounded-md\",\n rounded: \"rounded-lg\",\n pill: \"rounded-full\",\n square: \"rounded-none\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n shape: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n loading?: boolean\n prefixIcon?: React.ReactNode\n suffixIcon?: React.ReactNode\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n shape,\n asChild = false,\n loading = false,\n prefixIcon,\n suffixIcon,\n children,\n disabled,\n ...props\n },\n ref\n ) => {\n const Comp = asChild ? Slot : \"button\"\n const isDisabled = disabled || loading\n\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, shape, className }))}\n ref={ref}\n disabled={isDisabled}\n {...props}\n >\n {loading && <Loader2 className=\"animate-spin\" />}\n {!loading && prefixIcon}\n {children}\n {suffixIcon}\n </Comp>\n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\nimport { DayPicker } from \"react-day-picker\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker>\n\nfunction Calendar({ className, classNames, showOutsideDays = true, captionLayout = \"dropdown\", ...props }: CalendarProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"w-[260px] rounded-lg p-3\", className)}\n classNames={{\n months: \"flex flex-col\",\n month: \"space-y-3\",\n month_caption: \"relative flex h-8 items-center justify-center\",\n caption_label: \"text-sm font-medium hidden\",\n nav: \"flex items-center\",\n button_previous: cn(\n \"absolute start-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n button_next: cn(\n \"absolute end-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n month_grid: \"w-full border-collapse\",\n weekdays: \"flex w-full\",\n weekday:\n \"flex-1 h-8 flex items-center justify-center text-[11px] font-medium text-muted-foreground uppercase tracking-wider\",\n week: \"flex w-full mt-1\",\n day: \"flex-1 h-8 p-0 relative focus-within:z-20 flex items-center justify-center text-sm\",\n day_button: cn(\n \"inline-flex size-8 items-center justify-center rounded-md bg-transparent text-sm font-normal cursor-pointer border-none hover:bg-[var(--hc-color-border-subtle)] transition-colors\"\n ),\n range_end: \"day-range-end\",\n selected:\n \"[&>button]:bg-[var(--hc-primary-600)] [&>button]:text-white [&>button]:hover:bg-[var(--hc-primary-600)] [&>button]:hover:text-white [&>button]:font-medium\",\n today: \"[&>button]:font-semibold [&>button]:text-[var(--hc-primary-600)]\",\n outside:\n \"day-outside [&>button]:bg-transparent [&>button]:text-[var(--hc-grey-200)]\",\n disabled: \"[&>button]:text-[var(--hc-grey-200)] [&>button]:opacity-50 [&>button]:cursor-default\",\n range_middle:\n \"[&>button]:bg-[var(--hc-primary-100)] [&>button]:text-foreground [&>button]:rounded-none\",\n range_start: \"[&>button]:rounded-e-none\",\n dropdowns: \"flex items-center gap-1.5 justify-center [&>select]:flex-1\",\n dropdown:\n \"h-7 w-[88px] rounded-md border border-[var(--hc-color-border-subtle)] bg-background px-2 text-xs font-medium text-foreground cursor-pointer outline-none accent-[var(--hc-primary-600)] focus:border-[var(--hc-primary-500)] focus:ring-[2px] focus:ring-[var(--hc-primary-500)]/20 [&>option:checked]:bg-[var(--hc-primary-600)] [&>option:checked]:text-white [&>option]:py-1\",\n hidden: \"invisible\",\n ...classNames,\n }}\n captionLayout={captionLayout}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === \"left\" ? ChevronLeft : ChevronRight\n return <Icon className=\"size-4\" />\n },\n }}\n {...props}\n />\n )\n}\nCalendar.displayName = \"Calendar\"\n\nexport { Calendar }\n","import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\nimport { cn } from \"../lib/utils\"\n\nconst Popover = PopoverPrimitive.Root\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent }\n"],"mappings":"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","names":["React","jsx","React","jsx","jsx","jsxs"]}
1
+ {"version":3,"sources":["../../src/components/date-picker.tsx","../../src/lib/utils.ts","../../src/components/button.tsx","../../src/components/calendar.tsx","../../src/components/popover.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { CalendarIcon } from \"lucide-react\"\nimport type { DateRange, Matcher } from \"react-day-picker\"\nimport { cn } from \"../lib/utils\"\nimport { Button } from \"./button\"\nimport { Calendar } from \"./calendar\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\"\n\nexport type DatePickerPreset =\n | { label: string; value: Date }\n | { label: string; value: { from: Date; to: Date } }\n\nexport interface DatePickerProps {\n /** Selected value. For `mode=\"single\"` this is a Date, for `mode=\"range\"` this is a range object. */\n date?: Date | DateRange\n /** Called with the new selection. */\n onDateChange?: (date: Date | DateRange | undefined) => void\n /** Selection mode. Defaults to \"single\". */\n mode?: \"single\" | \"range\"\n /** Placeholder for the trigger when no date is picked. */\n placeholder?: string\n /** Classname applied to the trigger button. */\n className?: string\n /** Optional date format string — reserved for future use. */\n formatStr?: string\n /** Optional preset list rendered in a sidebar to the left of the calendar. */\n presets?: DatePickerPreset[]\n /** Passed through to the underlying Calendar. */\n disabled?: Matcher | Matcher[]\n}\n\nfunction formatDate(d: Date): string {\n return d.toLocaleDateString()\n}\n\nfunction DatePicker({\n date,\n onDateChange,\n mode = \"single\",\n placeholder = \"Pick a date\",\n className,\n presets,\n disabled,\n}: DatePickerProps) {\n const label = React.useMemo(() => {\n if (!date) return <span>{placeholder}</span>\n if (mode === \"range\") {\n const range = date as DateRange\n if (range.from && range.to) {\n return `${formatDate(range.from)} – ${formatDate(range.to)}`\n }\n if (range.from) return formatDate(range.from)\n return <span>{placeholder}</span>\n }\n return (date as Date).toLocaleDateString()\n }, [date, mode, placeholder])\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"w-[280px] justify-start text-left font-normal\",\n !date && \"text-muted-foreground\",\n className\n )}\n >\n <CalendarIcon className=\"me-2 h-4 w-4\" />\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"flex\">\n {presets && presets.length > 0 && (\n <div className=\"flex flex-col gap-1 border-e p-2 min-w-[140px]\">\n {presets.map((preset) => (\n <Button\n key={preset.label}\n variant=\"ghost\"\n size=\"sm\"\n className=\"justify-start font-normal\"\n onClick={() => onDateChange?.(preset.value as Date | DateRange)}\n >\n {preset.label}\n </Button>\n ))}\n </div>\n )}\n <div>\n {mode === \"range\" ? (\n <Calendar\n mode=\"range\"\n selected={date as DateRange | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n // Focus moves into the calendar the user just opened (keyboard navigation).\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n />\n ) : (\n <Calendar\n mode=\"single\"\n selected={date as Date | undefined}\n onSelect={(value) => onDateChange?.(value)}\n disabled={disabled}\n // Focus moves into the calendar the user just opened (keyboard navigation).\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n />\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n\nexport { DatePicker }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Loader2 } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground hover:bg-primary-hover\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive-hover\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary-hover\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground\",\n link:\n \"text-primary underline-offset-4 hover:underline\",\n success:\n \"bg-success text-success-foreground hover:bg-success-hover\",\n },\n size: {\n xs: \"h-7 px-2.5 text-xs\",\n sm: \"h-9 px-3\",\n default: \"h-10 px-4 py-2\",\n lg: \"h-11 px-8\",\n icon: \"h-10 w-10\",\n \"icon-sm\": \"h-8 w-8\",\n },\n shape: {\n default: \"rounded-md\",\n rounded: \"rounded-lg\",\n pill: \"rounded-full\",\n square: \"rounded-none\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n shape: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n loading?: boolean\n prefixIcon?: React.ReactNode\n suffixIcon?: React.ReactNode\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n shape,\n asChild = false,\n loading = false,\n prefixIcon,\n suffixIcon,\n children,\n disabled,\n ...props\n },\n ref\n ) => {\n const Comp = asChild ? Slot : \"button\"\n const isDisabled = disabled || loading\n\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, shape, className }))}\n ref={ref}\n disabled={isDisabled}\n {...props}\n >\n {loading && <Loader2 className=\"animate-spin\" />}\n {!loading && prefixIcon}\n {children}\n {suffixIcon}\n </Comp>\n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\nimport { DayPicker } from \"react-day-picker\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker>\n\nfunction Calendar({ className, classNames, showOutsideDays = true, captionLayout = \"dropdown\", ...props }: CalendarProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"w-[260px] rounded-lg p-3\", className)}\n classNames={{\n months: \"flex flex-col\",\n month: \"space-y-3\",\n month_caption: \"relative flex h-8 items-center justify-center\",\n caption_label: \"text-sm font-medium hidden\",\n nav: \"flex items-center\",\n button_previous: cn(\n \"absolute start-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n button_next: cn(\n \"absolute end-0 inline-flex size-7 items-center justify-center rounded-md bg-transparent p-0 text-muted-foreground hover:bg-[var(--hc-color-border-subtle)] hover:text-foreground transition-colors cursor-pointer border-none\"\n ),\n month_grid: \"w-full border-collapse\",\n weekdays: \"flex w-full\",\n weekday:\n \"flex-1 h-8 flex items-center justify-center text-[11px] font-medium text-muted-foreground uppercase tracking-wider\",\n week: \"flex w-full mt-1\",\n day: \"flex-1 h-8 p-0 relative focus-within:z-20 flex items-center justify-center text-sm\",\n day_button: cn(\n \"inline-flex size-8 items-center justify-center rounded-md bg-transparent text-sm font-normal cursor-pointer border-none hover:bg-[var(--hc-color-border-subtle)] transition-colors\"\n ),\n range_end: \"day-range-end\",\n selected:\n \"[&>button]:bg-[var(--hc-primary-600)] [&>button]:text-white [&>button]:hover:bg-[var(--hc-primary-600)] [&>button]:hover:text-white [&>button]:font-medium\",\n today: \"[&>button]:font-semibold [&>button]:text-[var(--hc-primary-600)]\",\n outside:\n \"day-outside [&>button]:bg-transparent [&>button]:text-[var(--hc-grey-200)]\",\n disabled: \"[&>button]:text-[var(--hc-grey-200)] [&>button]:opacity-50 [&>button]:cursor-default\",\n range_middle:\n \"[&>button]:bg-[var(--hc-primary-100)] [&>button]:text-foreground [&>button]:rounded-none\",\n range_start: \"[&>button]:rounded-e-none\",\n dropdowns: \"flex items-center gap-1.5 justify-center [&>select]:flex-1\",\n dropdown:\n \"h-7 w-[88px] rounded-md border border-[var(--hc-color-border-subtle)] bg-background px-2 text-xs font-medium text-foreground cursor-pointer outline-none accent-[var(--hc-primary-600)] focus:border-[var(--hc-primary-500)] focus:ring-[2px] focus:ring-[var(--hc-primary-500)]/20 [&>option:checked]:bg-[var(--hc-primary-600)] [&>option:checked]:text-white [&>option]:py-1\",\n hidden: \"invisible\",\n ...classNames,\n }}\n captionLayout={captionLayout}\n components={{\n Chevron: ({ orientation }) => {\n const Icon = orientation === \"left\" ? ChevronLeft : ChevronRight\n return <Icon className=\"size-4\" />\n },\n }}\n {...props}\n />\n )\n}\nCalendar.displayName = \"Calendar\"\n\nexport { Calendar }\n","import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\nimport { cn } from \"../lib/utils\"\n\nconst Popover = PopoverPrimitive.Root\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent }\n"],"mappings":"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","names":["React","jsx","React","jsx","jsx","jsxs"]}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/components/impersonation-banner.tsx
31
+ var impersonation_banner_exports = {};
32
+ __export(impersonation_banner_exports, {
33
+ ImpersonationBanner: () => ImpersonationBanner,
34
+ formatRemaining: () => formatRemaining
35
+ });
36
+ module.exports = __toCommonJS(impersonation_banner_exports);
37
+ var React = __toESM(require("react"), 1);
38
+
39
+ // src/lib/utils.ts
40
+ var import_clsx = require("clsx");
41
+ var import_tailwind_merge = require("tailwind-merge");
42
+ function cn(...inputs) {
43
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
44
+ }
45
+
46
+ // src/components/impersonation-banner.tsx
47
+ var import_jsx_runtime = require("react/jsx-runtime");
48
+ function toMs(value) {
49
+ if (value instanceof Date) return value.getTime();
50
+ if (typeof value === "number") return value;
51
+ const parsed = Date.parse(value);
52
+ return Number.isNaN(parsed) ? 0 : parsed;
53
+ }
54
+ function formatRemaining(ms) {
55
+ const total = Math.max(0, Math.floor(ms / 1e3));
56
+ const h = Math.floor(total / 3600);
57
+ const m = Math.floor(total % 3600 / 60);
58
+ const s = total % 60;
59
+ const pad = (n) => String(n).padStart(2, "0");
60
+ return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${m}:${pad(s)}`;
61
+ }
62
+ var ImpersonationBanner = React.forwardRef(
63
+ ({ actorLabel, mode, expiresAt, onExit, targetLabel, ops, inline = false, onExpire, className }, ref) => {
64
+ const endMs = toMs(expiresAt);
65
+ const [now, setNow] = React.useState(() => Date.now());
66
+ const remaining = endMs - now;
67
+ const expired = remaining <= 0;
68
+ const onExpireRef = React.useRef(onExpire);
69
+ onExpireRef.current = onExpire;
70
+ React.useEffect(() => {
71
+ if (expired) return void 0;
72
+ const timer = setInterval(() => setNow(Date.now()), 1e3);
73
+ return () => clearInterval(timer);
74
+ }, [expired]);
75
+ const firedFor = React.useRef(null);
76
+ React.useEffect(() => {
77
+ if (expired && firedFor.current !== endMs) {
78
+ firedFor.current = endMs;
79
+ onExpireRef.current?.();
80
+ }
81
+ }, [expired, endMs]);
82
+ const isRead = mode === "READ";
83
+ const modeText = isRead ? "Read-only" : "Changes allowed";
84
+ const opsText = ops && ops.length > 0 ? ops.join(", ") : null;
85
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
86
+ inline ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "aria-hidden": "true", className: "h-12", "data-impersonation-spacer": "" }),
87
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
88
+ "div",
89
+ {
90
+ ref,
91
+ role: "alert",
92
+ "data-impersonation-banner": "",
93
+ "data-mode": mode,
94
+ className: cn(
95
+ inline ? "relative" : "fixed inset-x-0 top-0 z-[2147483000]",
96
+ "flex h-12 items-center gap-3 border-b-2 px-4 text-sm font-medium shadow-md",
97
+ isRead ? "border-black bg-[#FDE047] text-black" : "border-white bg-[#991B1B] text-white",
98
+ className
99
+ ),
100
+ children: [
101
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "shrink-0 rounded px-2 py-0.5 text-xs font-bold uppercase tracking-wide ring-1 ring-current", children: "Support session" }),
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "min-w-0 flex-1 truncate", children: [
103
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold", children: actorLabel }),
104
+ targetLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
105
+ " is acting as ",
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold", children: targetLabel })
107
+ ] }) : " is acting as this user",
108
+ " \xB7 ",
109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "data-testid": "impersonation-mode", children: modeText }),
110
+ opsText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hidden sm:inline", children: ` (${opsText})` }) : null
111
+ ] }),
112
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "shrink-0 tabular-nums", "aria-live": "off", title: "Time left in this support session", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", { "data-testid": "impersonation-countdown", dateTime: new Date(endMs).toISOString(), children: expired ? "Expired" : formatRemaining(remaining) }) }),
113
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
114
+ "button",
115
+ {
116
+ type: "button",
117
+ onClick: onExit,
118
+ className: cn(
119
+ "shrink-0 rounded-md px-3 py-1 text-sm font-semibold focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
120
+ isRead ? "bg-black text-[#FDE047] hover:bg-black/85 focus-visible:ring-black focus-visible:ring-offset-[#FDE047]" : "bg-white text-[#991B1B] hover:bg-white/90 focus-visible:ring-white focus-visible:ring-offset-[#991B1B]"
121
+ ),
122
+ children: "Exit"
123
+ }
124
+ )
125
+ ]
126
+ }
127
+ )
128
+ ] });
129
+ }
130
+ );
131
+ ImpersonationBanner.displayName = "ImpersonationBanner";
132
+ // Annotate the CommonJS export names for ESM import in node:
133
+ 0 && (module.exports = {
134
+ ImpersonationBanner,
135
+ formatRemaining
136
+ });
137
+ //# sourceMappingURL=impersonation-banner.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/impersonation-banner.tsx","../../src/lib/utils.ts"],"sourcesContent":["import * as React from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { ImpersonationMode, OperationClass } from \"../lib/impersonation\"\n\nexport interface ImpersonationBannerProps {\n /** Who is acting, e.g. the support person's email. */\n actorLabel: string\n /** READ or WRITE (from the token's imp_mode). */\n mode: ImpersonationMode\n /** When the session ends (Date, ISO string or epoch milliseconds). */\n expiresAt: Date | string | number\n /** Ends the session: the app clears the token. The banner itself never hides. */\n onExit: () => void\n /** Whose account is being used, e.g. the user's name. */\n targetLabel?: string\n /** Approved operation classes (imp_ops), shown next to the mode. */\n ops?: readonly OperationClass[]\n /** Render in the page flow instead of fixed to the top (docs and stories only). Default false. */\n inline?: boolean\n /** Called once when the countdown reaches zero. */\n onExpire?: () => void\n className?: string\n}\n\nfunction toMs(value: Date | string | number): number {\n if (value instanceof Date) return value.getTime()\n if (typeof value === \"number\") return value\n const parsed = Date.parse(value)\n return Number.isNaN(parsed) ? 0 : parsed\n}\n\n/** 29:59, or 1:02:03 past an hour. */\nexport function formatRemaining(ms: number): string {\n const total = Math.max(0, Math.floor(ms / 1000))\n const h = Math.floor(total / 3600)\n const m = Math.floor((total % 3600) / 60)\n const s = total % 60\n const pad = (n: number) => String(n).padStart(2, \"0\")\n return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${m}:${pad(s)}`\n}\n\n/**\n * Fixed, non-dismissible top bar shown on every page while a support person acts as a user (acai-ai-platform#1274).\n *\n * - role=\"alert\" so screen readers announce it once (the countdown is aria-live off); there is no close control and Escape does nothing.\n * - Fixed colours that do not change with the theme: black on yellow for READ, white on dark red for WRITE. Both are\n * above 7:1 contrast in light and dark mode.\n * - A live countdown to the end of the session. \"Exit\" calls onExit; the app ends the session and unmounts the banner.\n * - Renders a spacer of the same height so page content is not hidden under the bar.\n */\nconst ImpersonationBanner = React.forwardRef<HTMLDivElement, ImpersonationBannerProps>(\n ({ actorLabel, mode, expiresAt, onExit, targetLabel, ops, inline = false, onExpire, className }, ref) => {\n const endMs = toMs(expiresAt)\n const [now, setNow] = React.useState(() => Date.now())\n const remaining = endMs - now\n const expired = remaining <= 0\n const onExpireRef = React.useRef(onExpire)\n onExpireRef.current = onExpire\n\n React.useEffect(() => {\n if (expired) return undefined\n const timer = setInterval(() => setNow(Date.now()), 1000)\n return () => clearInterval(timer)\n }, [expired])\n\n const firedFor = React.useRef<number | null>(null)\n React.useEffect(() => {\n if (expired && firedFor.current !== endMs) {\n firedFor.current = endMs\n onExpireRef.current?.()\n }\n }, [expired, endMs])\n\n const isRead = mode === \"READ\"\n const modeText = isRead ? \"Read-only\" : \"Changes allowed\"\n const opsText = ops && ops.length > 0 ? ops.join(\", \") : null\n\n return (\n <>\n {inline ? null : <div aria-hidden=\"true\" className=\"h-12\" data-impersonation-spacer=\"\" />}\n <div\n ref={ref}\n role=\"alert\"\n data-impersonation-banner=\"\"\n data-mode={mode}\n className={cn(\n inline ? \"relative\" : \"fixed inset-x-0 top-0 z-[2147483000]\",\n \"flex h-12 items-center gap-3 border-b-2 px-4 text-sm font-medium shadow-md\",\n isRead\n ? \"border-black bg-[#FDE047] text-black\"\n : \"border-white bg-[#991B1B] text-white\",\n className\n )}\n >\n <span className=\"shrink-0 rounded px-2 py-0.5 text-xs font-bold uppercase tracking-wide ring-1 ring-current\">\n Support session\n </span>\n <p className=\"min-w-0 flex-1 truncate\">\n <span className=\"font-semibold\">{actorLabel}</span>\n {targetLabel ? (\n <>\n {\" is acting as \"}\n <span className=\"font-semibold\">{targetLabel}</span>\n </>\n ) : (\n \" is acting as this user\"\n )}\n {\" · \"}\n <span data-testid=\"impersonation-mode\">{modeText}</span>\n {opsText ? <span className=\"hidden sm:inline\">{` (${opsText})`}</span> : null}\n </p>\n {/* aria-live off: the ticking countdown must not be re-announced every second. */}\n <span className=\"shrink-0 tabular-nums\" aria-live=\"off\" title=\"Time left in this support session\">\n <time data-testid=\"impersonation-countdown\" dateTime={new Date(endMs).toISOString()}>\n {expired ? \"Expired\" : formatRemaining(remaining)}\n </time>\n </span>\n <button\n type=\"button\"\n onClick={onExit}\n className={cn(\n \"shrink-0 rounded-md px-3 py-1 text-sm font-semibold focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2\",\n isRead\n ? \"bg-black text-[#FDE047] hover:bg-black/85 focus-visible:ring-black focus-visible:ring-offset-[#FDE047]\"\n : \"bg-white text-[#991B1B] hover:bg-white/90 focus-visible:ring-white focus-visible:ring-offset-[#991B1B]\"\n )}\n >\n Exit\n </button>\n </div>\n </>\n )\n }\n)\nImpersonationBanner.displayName = \"ImpersonationBanner\"\n\nexport { ImpersonationBanner }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import { ImpersonationMode, OperationClass } from '../lib/impersonation.cjs';
3
+
4
+ interface ImpersonationBannerProps {
5
+ /** Who is acting, e.g. the support person's email. */
6
+ actorLabel: string;
7
+ /** READ or WRITE (from the token's imp_mode). */
8
+ mode: ImpersonationMode;
9
+ /** When the session ends (Date, ISO string or epoch milliseconds). */
10
+ expiresAt: Date | string | number;
11
+ /** Ends the session: the app clears the token. The banner itself never hides. */
12
+ onExit: () => void;
13
+ /** Whose account is being used, e.g. the user's name. */
14
+ targetLabel?: string;
15
+ /** Approved operation classes (imp_ops), shown next to the mode. */
16
+ ops?: readonly OperationClass[];
17
+ /** Render in the page flow instead of fixed to the top (docs and stories only). Default false. */
18
+ inline?: boolean;
19
+ /** Called once when the countdown reaches zero. */
20
+ onExpire?: () => void;
21
+ className?: string;
22
+ }
23
+ /** 29:59, or 1:02:03 past an hour. */
24
+ declare function formatRemaining(ms: number): string;
25
+ /**
26
+ * Fixed, non-dismissible top bar shown on every page while a support person acts as a user (acai-ai-platform#1274).
27
+ *
28
+ * - role="alert" so screen readers announce it once (the countdown is aria-live off); there is no close control and Escape does nothing.
29
+ * - Fixed colours that do not change with the theme: black on yellow for READ, white on dark red for WRITE. Both are
30
+ * above 7:1 contrast in light and dark mode.
31
+ * - A live countdown to the end of the session. "Exit" calls onExit; the app ends the session and unmounts the banner.
32
+ * - Renders a spacer of the same height so page content is not hidden under the bar.
33
+ */
34
+ declare const ImpersonationBanner: React.ForwardRefExoticComponent<ImpersonationBannerProps & React.RefAttributes<HTMLDivElement>>;
35
+
36
+ export { ImpersonationBanner, type ImpersonationBannerProps, formatRemaining };
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import { ImpersonationMode, OperationClass } from '../lib/impersonation.js';
3
+
4
+ interface ImpersonationBannerProps {
5
+ /** Who is acting, e.g. the support person's email. */
6
+ actorLabel: string;
7
+ /** READ or WRITE (from the token's imp_mode). */
8
+ mode: ImpersonationMode;
9
+ /** When the session ends (Date, ISO string or epoch milliseconds). */
10
+ expiresAt: Date | string | number;
11
+ /** Ends the session: the app clears the token. The banner itself never hides. */
12
+ onExit: () => void;
13
+ /** Whose account is being used, e.g. the user's name. */
14
+ targetLabel?: string;
15
+ /** Approved operation classes (imp_ops), shown next to the mode. */
16
+ ops?: readonly OperationClass[];
17
+ /** Render in the page flow instead of fixed to the top (docs and stories only). Default false. */
18
+ inline?: boolean;
19
+ /** Called once when the countdown reaches zero. */
20
+ onExpire?: () => void;
21
+ className?: string;
22
+ }
23
+ /** 29:59, or 1:02:03 past an hour. */
24
+ declare function formatRemaining(ms: number): string;
25
+ /**
26
+ * Fixed, non-dismissible top bar shown on every page while a support person acts as a user (acai-ai-platform#1274).
27
+ *
28
+ * - role="alert" so screen readers announce it once (the countdown is aria-live off); there is no close control and Escape does nothing.
29
+ * - Fixed colours that do not change with the theme: black on yellow for READ, white on dark red for WRITE. Both are
30
+ * above 7:1 contrast in light and dark mode.
31
+ * - A live countdown to the end of the session. "Exit" calls onExit; the app ends the session and unmounts the banner.
32
+ * - Renders a spacer of the same height so page content is not hidden under the bar.
33
+ */
34
+ declare const ImpersonationBanner: React.ForwardRefExoticComponent<ImpersonationBannerProps & React.RefAttributes<HTMLDivElement>>;
35
+
36
+ export { ImpersonationBanner, type ImpersonationBannerProps, formatRemaining };
@@ -0,0 +1,101 @@
1
+ // src/components/impersonation-banner.tsx
2
+ import * as React from "react";
3
+
4
+ // src/lib/utils.ts
5
+ import { clsx } from "clsx";
6
+ import { twMerge } from "tailwind-merge";
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ // src/components/impersonation-banner.tsx
12
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
+ function toMs(value) {
14
+ if (value instanceof Date) return value.getTime();
15
+ if (typeof value === "number") return value;
16
+ const parsed = Date.parse(value);
17
+ return Number.isNaN(parsed) ? 0 : parsed;
18
+ }
19
+ function formatRemaining(ms) {
20
+ const total = Math.max(0, Math.floor(ms / 1e3));
21
+ const h = Math.floor(total / 3600);
22
+ const m = Math.floor(total % 3600 / 60);
23
+ const s = total % 60;
24
+ const pad = (n) => String(n).padStart(2, "0");
25
+ return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${m}:${pad(s)}`;
26
+ }
27
+ var ImpersonationBanner = React.forwardRef(
28
+ ({ actorLabel, mode, expiresAt, onExit, targetLabel, ops, inline = false, onExpire, className }, ref) => {
29
+ const endMs = toMs(expiresAt);
30
+ const [now, setNow] = React.useState(() => Date.now());
31
+ const remaining = endMs - now;
32
+ const expired = remaining <= 0;
33
+ const onExpireRef = React.useRef(onExpire);
34
+ onExpireRef.current = onExpire;
35
+ React.useEffect(() => {
36
+ if (expired) return void 0;
37
+ const timer = setInterval(() => setNow(Date.now()), 1e3);
38
+ return () => clearInterval(timer);
39
+ }, [expired]);
40
+ const firedFor = React.useRef(null);
41
+ React.useEffect(() => {
42
+ if (expired && firedFor.current !== endMs) {
43
+ firedFor.current = endMs;
44
+ onExpireRef.current?.();
45
+ }
46
+ }, [expired, endMs]);
47
+ const isRead = mode === "READ";
48
+ const modeText = isRead ? "Read-only" : "Changes allowed";
49
+ const opsText = ops && ops.length > 0 ? ops.join(", ") : null;
50
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
51
+ inline ? null : /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "h-12", "data-impersonation-spacer": "" }),
52
+ /* @__PURE__ */ jsxs(
53
+ "div",
54
+ {
55
+ ref,
56
+ role: "alert",
57
+ "data-impersonation-banner": "",
58
+ "data-mode": mode,
59
+ className: cn(
60
+ inline ? "relative" : "fixed inset-x-0 top-0 z-[2147483000]",
61
+ "flex h-12 items-center gap-3 border-b-2 px-4 text-sm font-medium shadow-md",
62
+ isRead ? "border-black bg-[#FDE047] text-black" : "border-white bg-[#991B1B] text-white",
63
+ className
64
+ ),
65
+ children: [
66
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded px-2 py-0.5 text-xs font-bold uppercase tracking-wide ring-1 ring-current", children: "Support session" }),
67
+ /* @__PURE__ */ jsxs("p", { className: "min-w-0 flex-1 truncate", children: [
68
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: actorLabel }),
69
+ targetLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
70
+ " is acting as ",
71
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: targetLabel })
72
+ ] }) : " is acting as this user",
73
+ " \xB7 ",
74
+ /* @__PURE__ */ jsx("span", { "data-testid": "impersonation-mode", children: modeText }),
75
+ opsText ? /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: ` (${opsText})` }) : null
76
+ ] }),
77
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums", "aria-live": "off", title: "Time left in this support session", children: /* @__PURE__ */ jsx("time", { "data-testid": "impersonation-countdown", dateTime: new Date(endMs).toISOString(), children: expired ? "Expired" : formatRemaining(remaining) }) }),
78
+ /* @__PURE__ */ jsx(
79
+ "button",
80
+ {
81
+ type: "button",
82
+ onClick: onExit,
83
+ className: cn(
84
+ "shrink-0 rounded-md px-3 py-1 text-sm font-semibold focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
85
+ isRead ? "bg-black text-[#FDE047] hover:bg-black/85 focus-visible:ring-black focus-visible:ring-offset-[#FDE047]" : "bg-white text-[#991B1B] hover:bg-white/90 focus-visible:ring-white focus-visible:ring-offset-[#991B1B]"
86
+ ),
87
+ children: "Exit"
88
+ }
89
+ )
90
+ ]
91
+ }
92
+ )
93
+ ] });
94
+ }
95
+ );
96
+ ImpersonationBanner.displayName = "ImpersonationBanner";
97
+ export {
98
+ ImpersonationBanner,
99
+ formatRemaining
100
+ };
101
+ //# sourceMappingURL=impersonation-banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/impersonation-banner.tsx","../../src/lib/utils.ts"],"sourcesContent":["import * as React from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { ImpersonationMode, OperationClass } from \"../lib/impersonation\"\n\nexport interface ImpersonationBannerProps {\n /** Who is acting, e.g. the support person's email. */\n actorLabel: string\n /** READ or WRITE (from the token's imp_mode). */\n mode: ImpersonationMode\n /** When the session ends (Date, ISO string or epoch milliseconds). */\n expiresAt: Date | string | number\n /** Ends the session: the app clears the token. The banner itself never hides. */\n onExit: () => void\n /** Whose account is being used, e.g. the user's name. */\n targetLabel?: string\n /** Approved operation classes (imp_ops), shown next to the mode. */\n ops?: readonly OperationClass[]\n /** Render in the page flow instead of fixed to the top (docs and stories only). Default false. */\n inline?: boolean\n /** Called once when the countdown reaches zero. */\n onExpire?: () => void\n className?: string\n}\n\nfunction toMs(value: Date | string | number): number {\n if (value instanceof Date) return value.getTime()\n if (typeof value === \"number\") return value\n const parsed = Date.parse(value)\n return Number.isNaN(parsed) ? 0 : parsed\n}\n\n/** 29:59, or 1:02:03 past an hour. */\nexport function formatRemaining(ms: number): string {\n const total = Math.max(0, Math.floor(ms / 1000))\n const h = Math.floor(total / 3600)\n const m = Math.floor((total % 3600) / 60)\n const s = total % 60\n const pad = (n: number) => String(n).padStart(2, \"0\")\n return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${m}:${pad(s)}`\n}\n\n/**\n * Fixed, non-dismissible top bar shown on every page while a support person acts as a user (acai-ai-platform#1274).\n *\n * - role=\"alert\" so screen readers announce it once (the countdown is aria-live off); there is no close control and Escape does nothing.\n * - Fixed colours that do not change with the theme: black on yellow for READ, white on dark red for WRITE. Both are\n * above 7:1 contrast in light and dark mode.\n * - A live countdown to the end of the session. \"Exit\" calls onExit; the app ends the session and unmounts the banner.\n * - Renders a spacer of the same height so page content is not hidden under the bar.\n */\nconst ImpersonationBanner = React.forwardRef<HTMLDivElement, ImpersonationBannerProps>(\n ({ actorLabel, mode, expiresAt, onExit, targetLabel, ops, inline = false, onExpire, className }, ref) => {\n const endMs = toMs(expiresAt)\n const [now, setNow] = React.useState(() => Date.now())\n const remaining = endMs - now\n const expired = remaining <= 0\n const onExpireRef = React.useRef(onExpire)\n onExpireRef.current = onExpire\n\n React.useEffect(() => {\n if (expired) return undefined\n const timer = setInterval(() => setNow(Date.now()), 1000)\n return () => clearInterval(timer)\n }, [expired])\n\n const firedFor = React.useRef<number | null>(null)\n React.useEffect(() => {\n if (expired && firedFor.current !== endMs) {\n firedFor.current = endMs\n onExpireRef.current?.()\n }\n }, [expired, endMs])\n\n const isRead = mode === \"READ\"\n const modeText = isRead ? \"Read-only\" : \"Changes allowed\"\n const opsText = ops && ops.length > 0 ? ops.join(\", \") : null\n\n return (\n <>\n {inline ? null : <div aria-hidden=\"true\" className=\"h-12\" data-impersonation-spacer=\"\" />}\n <div\n ref={ref}\n role=\"alert\"\n data-impersonation-banner=\"\"\n data-mode={mode}\n className={cn(\n inline ? \"relative\" : \"fixed inset-x-0 top-0 z-[2147483000]\",\n \"flex h-12 items-center gap-3 border-b-2 px-4 text-sm font-medium shadow-md\",\n isRead\n ? \"border-black bg-[#FDE047] text-black\"\n : \"border-white bg-[#991B1B] text-white\",\n className\n )}\n >\n <span className=\"shrink-0 rounded px-2 py-0.5 text-xs font-bold uppercase tracking-wide ring-1 ring-current\">\n Support session\n </span>\n <p className=\"min-w-0 flex-1 truncate\">\n <span className=\"font-semibold\">{actorLabel}</span>\n {targetLabel ? (\n <>\n {\" is acting as \"}\n <span className=\"font-semibold\">{targetLabel}</span>\n </>\n ) : (\n \" is acting as this user\"\n )}\n {\" · \"}\n <span data-testid=\"impersonation-mode\">{modeText}</span>\n {opsText ? <span className=\"hidden sm:inline\">{` (${opsText})`}</span> : null}\n </p>\n {/* aria-live off: the ticking countdown must not be re-announced every second. */}\n <span className=\"shrink-0 tabular-nums\" aria-live=\"off\" title=\"Time left in this support session\">\n <time data-testid=\"impersonation-countdown\" dateTime={new Date(endMs).toISOString()}>\n {expired ? \"Expired\" : formatRemaining(remaining)}\n </time>\n </span>\n <button\n type=\"button\"\n onClick={onExit}\n className={cn(\n \"shrink-0 rounded-md px-3 py-1 text-sm font-semibold focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2\",\n isRead\n ? \"bg-black text-[#FDE047] hover:bg-black/85 focus-visible:ring-black focus-visible:ring-offset-[#FDE047]\"\n : \"bg-white text-[#991B1B] hover:bg-white/90 focus-visible:ring-white focus-visible:ring-offset-[#991B1B]\"\n )}\n >\n Exit\n </button>\n </div>\n </>\n )\n }\n)\nImpersonationBanner.displayName = \"ImpersonationBanner\"\n\nexport { ImpersonationBanner }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":[]}
@@ -87,7 +87,8 @@ var Input = React.forwardRef(
87
87
  onChange,
88
88
  ...props
89
89
  }, ref) => {
90
- const inputId = id || React.useId();
90
+ const generatedId = React.useId();
91
+ const inputId = id || generatedId;
91
92
  const isControlled = value !== void 0;
92
93
  const [internalValue, setInternalValue] = React.useState(defaultValue);
93
94
  const innerRef = React.useRef(null);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/input.tsx","../../src/lib/utils.ts"],"sourcesContent":["import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Eye, EyeOff, X } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nconst inputVariants = cva(\n \"flex w-full rounded-md border bg-background transition-[color,border-color,box-shadow] duration-150 file:border-0 file:bg-transparent file:font-medium file:text-foreground placeholder:text-muted-foreground focus-within:outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n {\n variants: {\n variant: {\n default:\n \"border-input hover:border-muted-foreground focus-within:border-[var(--hc-primary-500)] focus-within:ring-[3px] focus-within:ring-[color-mix(in_srgb,var(--hc-primary-500)_22%,transparent)]\",\n error:\n \"border-[var(--hc-color-destructive)] focus-within:border-[var(--hc-color-destructive)] focus-within:ring-[3px] focus-within:ring-[color-mix(in_srgb,var(--hc-color-destructive)_22%,transparent)]\",\n success:\n \"border-[var(--hc-color-success)] focus-within:border-[var(--hc-color-success)] focus-within:ring-[3px] focus-within:ring-[color-mix(in_srgb,var(--hc-color-success)_22%,transparent)]\",\n },\n inputSize: {\n default: \"h-10 px-3 py-2 text-sm\",\n sm: \"h-8 px-2.5 py-1.5 text-xs\",\n lg: \"h-12 px-4 py-3 text-base\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n inputSize: \"default\",\n },\n }\n)\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">,\n VariantProps<typeof inputVariants> {\n label?: string\n hint?: string\n leadingIcon?: React.ReactNode\n trailingIcon?: React.ReactNode\n clearable?: boolean\n onClear?: () => void\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n type,\n label,\n hint,\n variant = \"default\",\n inputSize = \"default\",\n leadingIcon,\n trailingIcon,\n clearable,\n onClear,\n disabled,\n id,\n value,\n defaultValue,\n onChange,\n ...props\n },\n ref\n ) => {\n const inputId = id || React.useId()\n const isControlled = value !== undefined\n const [internalValue, setInternalValue] = React.useState<\n string | number | readonly string[] | undefined\n >(defaultValue)\n const innerRef = React.useRef<HTMLInputElement | null>(null)\n\n React.useImperativeHandle(\n ref,\n () => innerRef.current as HTMLInputElement,\n []\n )\n\n const currentValue = isControlled ? value : internalValue\n const hasValue =\n currentValue !== undefined &&\n currentValue !== null &&\n String(currentValue).length > 0\n\n const isPassword = type === \"password\"\n const [showPassword, setShowPassword] = React.useState(false)\n const resolvedType = isPassword ? (showPassword ? \"text\" : \"password\") : type\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalValue(e.target.value)\n }\n onChange?.(e)\n }\n\n const handleClear = () => {\n if (!isControlled) {\n setInternalValue(\"\")\n }\n // Fire a synthetic input event so consumers relying on onChange receive it.\n const input = innerRef.current\n if (input) {\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n window.HTMLInputElement.prototype,\n \"value\"\n )?.set\n nativeInputValueSetter?.call(input, \"\")\n const event = new Event(\"input\", { bubbles: true })\n input.dispatchEvent(event)\n input.focus()\n }\n onClear?.()\n }\n\n const showClearButton = clearable && hasValue && !isPassword && !disabled\n const showPasswordToggle = isPassword && !disabled\n\n const trailingSlots = [\n showClearButton ? 1 : 0,\n showPasswordToggle ? 1 : 0,\n trailingIcon ? 1 : 0,\n ].reduce((a, b) => a + b, 0)\n\n const inputPaddingEnd =\n trailingSlots >= 2 ? \"pe-14\" : trailingSlots === 1 ? \"pe-8\" : undefined\n\n return (\n <div className=\"flex flex-col gap-1.5\" data-slot=\"input-root\">\n {label && (\n <label\n htmlFor={inputId}\n className={cn(\n \"text-sm font-medium text-foreground\",\n disabled && \"text-muted-foreground\"\n )}\n >\n {label}\n </label>\n )}\n <div\n data-slot=\"input-wrapper\"\n className={cn(\n inputVariants({ variant, inputSize }),\n \"relative flex items-center gap-2\",\n disabled && \"cursor-not-allowed opacity-50\",\n className\n )}\n >\n {leadingIcon && (\n <span className=\"shrink-0 text-muted-foreground\">\n {leadingIcon}\n </span>\n )}\n <input\n id={inputId}\n type={resolvedType}\n disabled={disabled}\n className={cn(\n \"flex-1 min-w-0 bg-transparent outline-none text-inherit placeholder:text-muted-foreground disabled:cursor-not-allowed\",\n inputPaddingEnd\n )}\n ref={innerRef}\n value={isControlled ? value : internalValue}\n defaultValue={isControlled ? undefined : undefined}\n onChange={handleChange}\n {...props}\n />\n {(showClearButton || showPasswordToggle) && (\n <span\n className=\"pointer-events-none absolute end-2 top-1/2 -translate-y-1/2 flex items-center gap-1\"\n >\n {showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Clear\"\n onClick={handleClear}\n tabIndex={-1}\n className=\"pointer-events-auto inline-flex size-4 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--hc-primary-500)] focus-visible:ring-offset-1 focus-visible:ring-offset-background\"\n >\n <X className=\"size-4\" aria-hidden=\"true\" />\n </button>\n )}\n {showPasswordToggle && (\n <button\n type=\"button\"\n aria-label={showPassword ? \"Hide password\" : \"Show password\"}\n onClick={() => setShowPassword((s) => !s)}\n tabIndex={-1}\n className=\"pointer-events-auto inline-flex size-4 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--hc-primary-500)] focus-visible:ring-offset-1 focus-visible:ring-offset-background\"\n >\n {showPassword ? (\n <EyeOff className=\"size-4\" aria-hidden=\"true\" />\n ) : (\n <Eye className=\"size-4\" aria-hidden=\"true\" />\n )}\n </button>\n )}\n </span>\n )}\n {trailingIcon && !showClearButton && !showPasswordToggle && (\n <span className=\"shrink-0 text-muted-foreground\">\n {trailingIcon}\n </span>\n )}\n </div>\n {hint && (\n <p\n className={cn(\n \"text-xs\",\n variant === \"default\" && \"text-muted-foreground\",\n variant === \"error\" && \"text-destructive\",\n variant === \"success\" && \"text-success\"\n )}\n >\n {hint}\n </p>\n )}\n </div>\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input, inputVariants }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/input.tsx","../../src/lib/utils.ts"],"sourcesContent":["import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Eye, EyeOff, X } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nconst inputVariants = cva(\n \"flex w-full rounded-md border bg-background transition-[color,border-color,box-shadow] duration-150 file:border-0 file:bg-transparent file:font-medium file:text-foreground placeholder:text-muted-foreground focus-within:outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n {\n variants: {\n variant: {\n default:\n \"border-input hover:border-muted-foreground focus-within:border-[var(--hc-primary-500)] focus-within:ring-[3px] focus-within:ring-[color-mix(in_srgb,var(--hc-primary-500)_22%,transparent)]\",\n error:\n \"border-[var(--hc-color-destructive)] focus-within:border-[var(--hc-color-destructive)] focus-within:ring-[3px] focus-within:ring-[color-mix(in_srgb,var(--hc-color-destructive)_22%,transparent)]\",\n success:\n \"border-[var(--hc-color-success)] focus-within:border-[var(--hc-color-success)] focus-within:ring-[3px] focus-within:ring-[color-mix(in_srgb,var(--hc-color-success)_22%,transparent)]\",\n },\n inputSize: {\n default: \"h-10 px-3 py-2 text-sm\",\n sm: \"h-8 px-2.5 py-1.5 text-xs\",\n lg: \"h-12 px-4 py-3 text-base\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n inputSize: \"default\",\n },\n }\n)\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">,\n VariantProps<typeof inputVariants> {\n label?: string\n hint?: string\n leadingIcon?: React.ReactNode\n trailingIcon?: React.ReactNode\n clearable?: boolean\n onClear?: () => void\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n type,\n label,\n hint,\n variant = \"default\",\n inputSize = \"default\",\n leadingIcon,\n trailingIcon,\n clearable,\n onClear,\n disabled,\n id,\n value,\n defaultValue,\n onChange,\n ...props\n },\n ref\n ) => {\n const generatedId = React.useId()\n const inputId = id || generatedId\n const isControlled = value !== undefined\n const [internalValue, setInternalValue] = React.useState<\n string | number | readonly string[] | undefined\n >(defaultValue)\n const innerRef = React.useRef<HTMLInputElement | null>(null)\n\n React.useImperativeHandle(\n ref,\n () => innerRef.current as HTMLInputElement,\n []\n )\n\n const currentValue = isControlled ? value : internalValue\n const hasValue =\n currentValue !== undefined &&\n currentValue !== null &&\n String(currentValue).length > 0\n\n const isPassword = type === \"password\"\n const [showPassword, setShowPassword] = React.useState(false)\n const resolvedType = isPassword ? (showPassword ? \"text\" : \"password\") : type\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalValue(e.target.value)\n }\n onChange?.(e)\n }\n\n const handleClear = () => {\n if (!isControlled) {\n setInternalValue(\"\")\n }\n // Fire a synthetic input event so consumers relying on onChange receive it.\n const input = innerRef.current\n if (input) {\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n window.HTMLInputElement.prototype,\n \"value\"\n )?.set\n nativeInputValueSetter?.call(input, \"\")\n const event = new Event(\"input\", { bubbles: true })\n input.dispatchEvent(event)\n input.focus()\n }\n onClear?.()\n }\n\n const showClearButton = clearable && hasValue && !isPassword && !disabled\n const showPasswordToggle = isPassword && !disabled\n\n const trailingSlots = [\n showClearButton ? 1 : 0,\n showPasswordToggle ? 1 : 0,\n trailingIcon ? 1 : 0,\n ].reduce((a, b) => a + b, 0)\n\n const inputPaddingEnd =\n trailingSlots >= 2 ? \"pe-14\" : trailingSlots === 1 ? \"pe-8\" : undefined\n\n return (\n <div className=\"flex flex-col gap-1.5\" data-slot=\"input-root\">\n {label && (\n <label\n htmlFor={inputId}\n className={cn(\n \"text-sm font-medium text-foreground\",\n disabled && \"text-muted-foreground\"\n )}\n >\n {label}\n </label>\n )}\n <div\n data-slot=\"input-wrapper\"\n className={cn(\n inputVariants({ variant, inputSize }),\n \"relative flex items-center gap-2\",\n disabled && \"cursor-not-allowed opacity-50\",\n className\n )}\n >\n {leadingIcon && (\n <span className=\"shrink-0 text-muted-foreground\">\n {leadingIcon}\n </span>\n )}\n <input\n id={inputId}\n type={resolvedType}\n disabled={disabled}\n className={cn(\n \"flex-1 min-w-0 bg-transparent outline-none text-inherit placeholder:text-muted-foreground disabled:cursor-not-allowed\",\n inputPaddingEnd\n )}\n ref={innerRef}\n value={isControlled ? value : internalValue}\n defaultValue={isControlled ? undefined : undefined}\n onChange={handleChange}\n {...props}\n />\n {(showClearButton || showPasswordToggle) && (\n <span\n className=\"pointer-events-none absolute end-2 top-1/2 -translate-y-1/2 flex items-center gap-1\"\n >\n {showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Clear\"\n onClick={handleClear}\n tabIndex={-1}\n className=\"pointer-events-auto inline-flex size-4 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--hc-primary-500)] focus-visible:ring-offset-1 focus-visible:ring-offset-background\"\n >\n <X className=\"size-4\" aria-hidden=\"true\" />\n </button>\n )}\n {showPasswordToggle && (\n <button\n type=\"button\"\n aria-label={showPassword ? \"Hide password\" : \"Show password\"}\n onClick={() => setShowPassword((s) => !s)}\n tabIndex={-1}\n className=\"pointer-events-auto inline-flex size-4 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--hc-primary-500)] focus-visible:ring-offset-1 focus-visible:ring-offset-background\"\n >\n {showPassword ? (\n <EyeOff className=\"size-4\" aria-hidden=\"true\" />\n ) : (\n <Eye className=\"size-4\" aria-hidden=\"true\" />\n )}\n </button>\n )}\n </span>\n )}\n {trailingIcon && !showClearButton && !showPasswordToggle && (\n <span className=\"shrink-0 text-muted-foreground\">\n {trailingIcon}\n </span>\n )}\n </div>\n {hint && (\n <p\n className={cn(\n \"text-xs\",\n variant === \"default\" && \"text-muted-foreground\",\n variant === \"error\" && \"text-destructive\",\n variant === \"success\" && \"text-success\"\n )}\n >\n {hint}\n </p>\n )}\n </div>\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input, inputVariants }\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":[]}
@@ -52,7 +52,8 @@ var Input = React.forwardRef(
52
52
  onChange,
53
53
  ...props
54
54
  }, ref) => {
55
- const inputId = id || React.useId();
55
+ const generatedId = React.useId();
56
+ const inputId = id || generatedId;
56
57
  const isControlled = value !== void 0;
57
58
  const [internalValue, setInternalValue] = React.useState(defaultValue);
58
59
  const innerRef = React.useRef(null);