@karakuri-ui/react 0.3.5 → 0.3.7

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 (47) hide show
  1. package/dist/components/ui/checkbox.js +3 -1
  2. package/dist/components/ui/checkbox.js.map +1 -1
  3. package/dist/components/ui/checkbox.mjs +4 -2
  4. package/dist/components/ui/checkbox.mjs.map +1 -1
  5. package/dist/components/ui/field.d.mts +11 -1
  6. package/dist/components/ui/field.d.ts +11 -1
  7. package/dist/components/ui/field.js +37 -4
  8. package/dist/components/ui/field.js.map +1 -1
  9. package/dist/components/ui/field.mjs +35 -3
  10. package/dist/components/ui/field.mjs.map +1 -1
  11. package/dist/components/ui/index.d.mts +1 -1
  12. package/dist/components/ui/index.d.ts +1 -1
  13. package/dist/components/ui/input.js +1 -0
  14. package/dist/components/ui/input.js.map +1 -1
  15. package/dist/components/ui/input.mjs +2 -1
  16. package/dist/components/ui/input.mjs.map +1 -1
  17. package/dist/components/ui/navigation-menu.js +30 -9
  18. package/dist/components/ui/navigation-menu.js.map +1 -1
  19. package/dist/components/ui/navigation-menu.mjs +30 -9
  20. package/dist/components/ui/navigation-menu.mjs.map +1 -1
  21. package/dist/components/ui/pagination.js +2 -2
  22. package/dist/components/ui/pagination.js.map +1 -1
  23. package/dist/components/ui/pagination.mjs +3 -3
  24. package/dist/components/ui/pagination.mjs.map +1 -1
  25. package/dist/components/ui/radio-group.js +3 -0
  26. package/dist/components/ui/radio-group.js.map +1 -1
  27. package/dist/components/ui/radio-group.mjs +4 -1
  28. package/dist/components/ui/radio-group.mjs.map +1 -1
  29. package/dist/components/ui/select.d.mts +1 -1
  30. package/dist/components/ui/select.d.ts +1 -1
  31. package/dist/components/ui/select.js +10 -2
  32. package/dist/components/ui/select.js.map +1 -1
  33. package/dist/components/ui/select.mjs +10 -2
  34. package/dist/components/ui/select.mjs.map +1 -1
  35. package/dist/components/ui/slider.js +7 -1
  36. package/dist/components/ui/slider.js.map +1 -1
  37. package/dist/components/ui/slider.mjs +7 -1
  38. package/dist/components/ui/slider.mjs.map +1 -1
  39. package/dist/components/ui/switch.js +3 -1
  40. package/dist/components/ui/switch.js.map +1 -1
  41. package/dist/components/ui/switch.mjs +4 -2
  42. package/dist/components/ui/switch.mjs.map +1 -1
  43. package/dist/components/ui/textarea.js +1 -0
  44. package/dist/components/ui/textarea.js.map +1 -1
  45. package/dist/components/ui/textarea.mjs +2 -1
  46. package/dist/components/ui/textarea.mjs.map +1 -1
  47. package/package.json +3 -1
@@ -109,7 +109,9 @@ const Checkbox = React.forwardRef(({ className, size, radius, weight, color = "d
109
109
  const resolvedSize = size || "default";
110
110
  const resolvedDisabled = disabled ?? fieldContext?.disabled;
111
111
  const generatedId = React.useId();
112
- const checkboxId = id ?? fieldContext?.id ?? generatedId;
112
+ const hasOwnLabel = Boolean(label);
113
+ const checkboxId = id ?? (hasOwnLabel ? generatedId : fieldContext?.id ?? generatedId);
114
+ (0, import_field.useFieldControl)(hasOwnLabel ? "group" : "single", Boolean(fieldContext) && (hasOwnLabel || !id));
113
115
  const checkbox = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
114
116
  CheckboxPrimitive.Root,
115
117
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext } from './field'\n\n// Color maps for checked/indeterminate state\nconst checkboxColorMap = {\n default: 'data-[state=checked]:bg-foreground data-[state=checked]:border-foreground data-[state=checked]:text-background data-[state=indeterminate]:bg-foreground data-[state=indeterminate]:border-foreground data-[state=indeterminate]:text-background',\n primary: 'data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground',\n} as const\n\nexport type CheckboxColor = keyof typeof checkboxColorMap\n\n// Checkbox box variants\nconst checkboxVariants = cva(\n [\n 'peer relative shrink-0 border-border-form hover:border-border-form-strong transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // Transparent hit area expansion via ::after\n \"after:absolute after:content-['']\",\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'w-3.5 h-3.5 after:-inset-[5px]', // 14px box → 24px click\n default: 'w-4 h-4 after:-inset-2', // 16px box → 32px click\n lg: 'w-5 h-5 after:-inset-2', // 20px box → 36px click\n },\n radius: {\n none: 'rounded-none', // 0px — sharp square\n sm: 'rounded-sm', // 2px — default checkbox style\n md: 'rounded', // 4px — softer corners\n },\n weight: {\n thin: 'border', // 1px\n bold: 'border-2', // 2px\n },\n },\n defaultVariants: {\n size: 'default',\n radius: 'sm',\n weight: 'bold',\n },\n }\n)\n\n// Check icon sizes per checkbox size\nconst checkIconSizes = {\n sm: 'w-2.5 h-2.5', // 10px in 14px box\n default: 'w-3 h-3', // 12px in 16px box\n lg: 'icon-xs', // 14px in 20px box\n}\n\n// Label font sizes per checkbox size\nconst labelSizes = {\n sm: 'text-xs', // 12px\n default: 'text-md', // 14px\n lg: 'text-base', // 16px\n}\n\n// Gap between checkbox and label\nconst gapSizes = {\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-2.5',\n}\n\nexport interface CheckboxProps\n extends Omit<React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, 'children'>,\n VariantProps<typeof checkboxVariants> {\n /** Checked state color */\n color?: CheckboxColor\n label?: string\n radius?: 'none' | 'sm' | 'md'\n}\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, size, radius, weight, color = 'default', label, disabled, id, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedDisabled = disabled ?? fieldContext?.disabled\n const generatedId = React.useId()\n const checkboxId = id ?? fieldContext?.id ?? generatedId\n\n const checkbox = (\n <CheckboxPrimitive.Root\n ref={ref}\n id={checkboxId}\n disabled={resolvedDisabled}\n className={cn(\n checkboxVariants({ size, radius, weight }),\n checkboxColorMap[color],\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center animate-checkbox-enter\">\n <CheckIcon className={checkIconSizes[resolvedSize]} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n\n if (!label) return checkbox\n\n return (\n <div className={cn('group flex items-center', gapSizes[resolvedSize])}>\n <div className=\"flex items-center\">\n {checkbox}\n </div>\n <label\n htmlFor={checkboxId}\n className={cn(\n labelSizes[resolvedSize],\n 'text-text-muted cursor-pointer select-none transition-colors duration-micro',\n 'group-hover:text-foreground',\n resolvedDisabled && 'opacity-50 cursor-not-allowed'\n )}\n >\n {label}\n </label>\n </div>\n )\n})\nCheckbox.displayName = 'Checkbox'\n\n// Check icon — renders ✓ for checked, — for indeterminate\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <>\n {/* Check mark (shown when data-state=checked on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=checked]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {/* Dash (shown when data-state=indeterminate on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=indeterminate]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 12h14\" />\n </svg>\n </>\n )\n}\n\nexport { Checkbox, checkboxVariants }\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ui/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\n// Color maps for checked/indeterminate state\nconst checkboxColorMap = {\n default: 'data-[state=checked]:bg-foreground data-[state=checked]:border-foreground data-[state=checked]:text-background data-[state=indeterminate]:bg-foreground data-[state=indeterminate]:border-foreground data-[state=indeterminate]:text-background',\n primary: 'data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground',\n} as const\n\nexport type CheckboxColor = keyof typeof checkboxColorMap\n\n// Checkbox box variants\nconst checkboxVariants = cva(\n [\n 'peer relative shrink-0 border-border-form hover:border-border-form-strong transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // Transparent hit area expansion via ::after\n \"after:absolute after:content-['']\",\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'w-3.5 h-3.5 after:-inset-[5px]', // 14px box → 24px click\n default: 'w-4 h-4 after:-inset-2', // 16px box → 32px click\n lg: 'w-5 h-5 after:-inset-2', // 20px box → 36px click\n },\n radius: {\n none: 'rounded-none', // 0px — sharp square\n sm: 'rounded-sm', // 2px — default checkbox style\n md: 'rounded', // 4px — softer corners\n },\n weight: {\n thin: 'border', // 1px\n bold: 'border-2', // 2px\n },\n },\n defaultVariants: {\n size: 'default',\n radius: 'sm',\n weight: 'bold',\n },\n }\n)\n\n// Check icon sizes per checkbox size\nconst checkIconSizes = {\n sm: 'w-2.5 h-2.5', // 10px in 14px box\n default: 'w-3 h-3', // 12px in 16px box\n lg: 'icon-xs', // 14px in 20px box\n}\n\n// Label font sizes per checkbox size\nconst labelSizes = {\n sm: 'text-xs', // 12px\n default: 'text-md', // 14px\n lg: 'text-base', // 16px\n}\n\n// Gap between checkbox and label\nconst gapSizes = {\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-2.5',\n}\n\nexport interface CheckboxProps\n extends Omit<React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, 'children'>,\n VariantProps<typeof checkboxVariants> {\n /** Checked state color */\n color?: CheckboxColor\n label?: string\n radius?: 'none' | 'sm' | 'md'\n}\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, size, radius, weight, color = 'default', label, disabled, id, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedDisabled = disabled ?? fieldContext?.disabled\n const generatedId = React.useId()\n // With its own label the checkbox is one item of a group: keep a unique id. Only a\n // bare checkbox labelled by FieldLabel takes the Field id.\n const hasOwnLabel = Boolean(label)\n const checkboxId = id ?? (hasOwnLabel ? generatedId : fieldContext?.id ?? generatedId)\n useFieldControl(hasOwnLabel ? 'group' : 'single', Boolean(fieldContext) && (hasOwnLabel || !id))\n\n const checkbox = (\n <CheckboxPrimitive.Root\n ref={ref}\n id={checkboxId}\n disabled={resolvedDisabled}\n className={cn(\n checkboxVariants({ size, radius, weight }),\n checkboxColorMap[color],\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center animate-checkbox-enter\">\n <CheckIcon className={checkIconSizes[resolvedSize]} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n\n if (!label) return checkbox\n\n return (\n <div className={cn('group flex items-center', gapSizes[resolvedSize])}>\n <div className=\"flex items-center\">\n {checkbox}\n </div>\n <label\n htmlFor={checkboxId}\n className={cn(\n labelSizes[resolvedSize],\n 'text-text-muted cursor-pointer select-none transition-colors duration-micro',\n 'group-hover:text-foreground',\n resolvedDisabled && 'opacity-50 cursor-not-allowed'\n )}\n >\n {label}\n </label>\n </div>\n )\n})\nCheckbox.displayName = 'Checkbox'\n\n// Check icon — renders ✓ for checked, — for indeterminate\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <>\n {/* Check mark (shown when data-state=checked on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=checked]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {/* Dash (shown when data-state=indeterminate on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=indeterminate]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 12h14\" />\n </svg>\n </>\n )\n}\n\nexport { Checkbox, checkboxVariants }\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
5
5
  import { cva } from "class-variance-authority";
6
6
  import { cn } from "../../lib/utils.mjs";
7
- import { useFieldContext } from "./field.mjs";
7
+ import { useFieldContext, useFieldControl } from "./field.mjs";
8
8
  const checkboxColorMap = {
9
9
  default: "data-[state=checked]:bg-foreground data-[state=checked]:border-foreground data-[state=checked]:text-background data-[state=indeterminate]:bg-foreground data-[state=indeterminate]:border-foreground data-[state=indeterminate]:text-background",
10
10
  primary: "data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground"
@@ -75,7 +75,9 @@ const Checkbox = React.forwardRef(({ className, size, radius, weight, color = "d
75
75
  const resolvedSize = size || "default";
76
76
  const resolvedDisabled = disabled ?? fieldContext?.disabled;
77
77
  const generatedId = React.useId();
78
- const checkboxId = id ?? fieldContext?.id ?? generatedId;
78
+ const hasOwnLabel = Boolean(label);
79
+ const checkboxId = id ?? (hasOwnLabel ? generatedId : fieldContext?.id ?? generatedId);
80
+ useFieldControl(hasOwnLabel ? "group" : "single", Boolean(fieldContext) && (hasOwnLabel || !id));
79
81
  const checkbox = /* @__PURE__ */ jsx(
80
82
  CheckboxPrimitive.Root,
81
83
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext } from './field'\n\n// Color maps for checked/indeterminate state\nconst checkboxColorMap = {\n default: 'data-[state=checked]:bg-foreground data-[state=checked]:border-foreground data-[state=checked]:text-background data-[state=indeterminate]:bg-foreground data-[state=indeterminate]:border-foreground data-[state=indeterminate]:text-background',\n primary: 'data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground',\n} as const\n\nexport type CheckboxColor = keyof typeof checkboxColorMap\n\n// Checkbox box variants\nconst checkboxVariants = cva(\n [\n 'peer relative shrink-0 border-border-form hover:border-border-form-strong transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // Transparent hit area expansion via ::after\n \"after:absolute after:content-['']\",\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'w-3.5 h-3.5 after:-inset-[5px]', // 14px box → 24px click\n default: 'w-4 h-4 after:-inset-2', // 16px box → 32px click\n lg: 'w-5 h-5 after:-inset-2', // 20px box → 36px click\n },\n radius: {\n none: 'rounded-none', // 0px — sharp square\n sm: 'rounded-sm', // 2px — default checkbox style\n md: 'rounded', // 4px — softer corners\n },\n weight: {\n thin: 'border', // 1px\n bold: 'border-2', // 2px\n },\n },\n defaultVariants: {\n size: 'default',\n radius: 'sm',\n weight: 'bold',\n },\n }\n)\n\n// Check icon sizes per checkbox size\nconst checkIconSizes = {\n sm: 'w-2.5 h-2.5', // 10px in 14px box\n default: 'w-3 h-3', // 12px in 16px box\n lg: 'icon-xs', // 14px in 20px box\n}\n\n// Label font sizes per checkbox size\nconst labelSizes = {\n sm: 'text-xs', // 12px\n default: 'text-md', // 14px\n lg: 'text-base', // 16px\n}\n\n// Gap between checkbox and label\nconst gapSizes = {\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-2.5',\n}\n\nexport interface CheckboxProps\n extends Omit<React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, 'children'>,\n VariantProps<typeof checkboxVariants> {\n /** Checked state color */\n color?: CheckboxColor\n label?: string\n radius?: 'none' | 'sm' | 'md'\n}\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, size, radius, weight, color = 'default', label, disabled, id, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedDisabled = disabled ?? fieldContext?.disabled\n const generatedId = React.useId()\n const checkboxId = id ?? fieldContext?.id ?? generatedId\n\n const checkbox = (\n <CheckboxPrimitive.Root\n ref={ref}\n id={checkboxId}\n disabled={resolvedDisabled}\n className={cn(\n checkboxVariants({ size, radius, weight }),\n checkboxColorMap[color],\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center animate-checkbox-enter\">\n <CheckIcon className={checkIconSizes[resolvedSize]} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n\n if (!label) return checkbox\n\n return (\n <div className={cn('group flex items-center', gapSizes[resolvedSize])}>\n <div className=\"flex items-center\">\n {checkbox}\n </div>\n <label\n htmlFor={checkboxId}\n className={cn(\n labelSizes[resolvedSize],\n 'text-text-muted cursor-pointer select-none transition-colors duration-micro',\n 'group-hover:text-foreground',\n resolvedDisabled && 'opacity-50 cursor-not-allowed'\n )}\n >\n {label}\n </label>\n </div>\n )\n})\nCheckbox.displayName = 'Checkbox'\n\n// Check icon — renders ✓ for checked, — for indeterminate\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <>\n {/* Check mark (shown when data-state=checked on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=checked]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {/* Dash (shown when data-state=indeterminate on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=indeterminate]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 12h14\" />\n </svg>\n </>\n )\n}\n\nexport { Checkbox, checkboxVariants }\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ui/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\n// Color maps for checked/indeterminate state\nconst checkboxColorMap = {\n default: 'data-[state=checked]:bg-foreground data-[state=checked]:border-foreground data-[state=checked]:text-background data-[state=indeterminate]:bg-foreground data-[state=indeterminate]:border-foreground data-[state=indeterminate]:text-background',\n primary: 'data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground',\n} as const\n\nexport type CheckboxColor = keyof typeof checkboxColorMap\n\n// Checkbox box variants\nconst checkboxVariants = cva(\n [\n 'peer relative shrink-0 border-border-form hover:border-border-form-strong transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // Transparent hit area expansion via ::after\n \"after:absolute after:content-['']\",\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'w-3.5 h-3.5 after:-inset-[5px]', // 14px box → 24px click\n default: 'w-4 h-4 after:-inset-2', // 16px box → 32px click\n lg: 'w-5 h-5 after:-inset-2', // 20px box → 36px click\n },\n radius: {\n none: 'rounded-none', // 0px — sharp square\n sm: 'rounded-sm', // 2px — default checkbox style\n md: 'rounded', // 4px — softer corners\n },\n weight: {\n thin: 'border', // 1px\n bold: 'border-2', // 2px\n },\n },\n defaultVariants: {\n size: 'default',\n radius: 'sm',\n weight: 'bold',\n },\n }\n)\n\n// Check icon sizes per checkbox size\nconst checkIconSizes = {\n sm: 'w-2.5 h-2.5', // 10px in 14px box\n default: 'w-3 h-3', // 12px in 16px box\n lg: 'icon-xs', // 14px in 20px box\n}\n\n// Label font sizes per checkbox size\nconst labelSizes = {\n sm: 'text-xs', // 12px\n default: 'text-md', // 14px\n lg: 'text-base', // 16px\n}\n\n// Gap between checkbox and label\nconst gapSizes = {\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-2.5',\n}\n\nexport interface CheckboxProps\n extends Omit<React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, 'children'>,\n VariantProps<typeof checkboxVariants> {\n /** Checked state color */\n color?: CheckboxColor\n label?: string\n radius?: 'none' | 'sm' | 'md'\n}\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, size, radius, weight, color = 'default', label, disabled, id, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedDisabled = disabled ?? fieldContext?.disabled\n const generatedId = React.useId()\n // With its own label the checkbox is one item of a group: keep a unique id. Only a\n // bare checkbox labelled by FieldLabel takes the Field id.\n const hasOwnLabel = Boolean(label)\n const checkboxId = id ?? (hasOwnLabel ? generatedId : fieldContext?.id ?? generatedId)\n useFieldControl(hasOwnLabel ? 'group' : 'single', Boolean(fieldContext) && (hasOwnLabel || !id))\n\n const checkbox = (\n <CheckboxPrimitive.Root\n ref={ref}\n id={checkboxId}\n disabled={resolvedDisabled}\n className={cn(\n checkboxVariants({ size, radius, weight }),\n checkboxColorMap[color],\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center animate-checkbox-enter\">\n <CheckIcon className={checkIconSizes[resolvedSize]} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n\n if (!label) return checkbox\n\n return (\n <div className={cn('group flex items-center', gapSizes[resolvedSize])}>\n <div className=\"flex items-center\">\n {checkbox}\n </div>\n <label\n htmlFor={checkboxId}\n className={cn(\n labelSizes[resolvedSize],\n 'text-text-muted cursor-pointer select-none transition-colors duration-micro',\n 'group-hover:text-foreground',\n resolvedDisabled && 'opacity-50 cursor-not-allowed'\n )}\n >\n {label}\n </label>\n </div>\n )\n})\nCheckbox.displayName = 'Checkbox'\n\n// Check icon — renders ✓ for checked, — for indeterminate\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <>\n {/* Check mark (shown when data-state=checked on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=checked]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {/* Dash (shown when data-state=indeterminate on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=indeterminate]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 12h14\" />\n </svg>\n </>\n )\n}\n\nexport { Checkbox, checkboxVariants }\n"],"mappings":"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","names":[]}
@@ -4,10 +4,20 @@ import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  interface FieldContextValue {
6
6
  id: string;
7
+ /** id of the FieldLabel, for aria-labelledby on grouped controls */
8
+ labelId: string;
7
9
  error?: boolean;
8
10
  disabled?: boolean;
11
+ /** A FieldLabel is rendered inside this Field */
12
+ hasLabel: boolean;
13
+ /** The Field holds labelled checkboxes / switches / a radio group and no single input */
14
+ isGroup: boolean;
15
+ registerLabel: () => () => void;
16
+ registerControl: (kind: FieldControlKind) => () => void;
9
17
  }
18
+ type FieldControlKind = 'single' | 'group' | 'labelled';
10
19
  declare function useFieldContext(): FieldContextValue | null;
20
+ declare function useFieldControl(kind: FieldControlKind, enabled: boolean): void;
11
21
  declare const fieldVariants: (props?: ({
12
22
  gap?: "default" | "sm" | "lg" | "none" | "xs" | null | undefined;
13
23
  } & class_variance_authority_types.ClassProp) | undefined) => string;
@@ -23,4 +33,4 @@ declare const FieldLabel: React.ForwardRefExoticComponent<FieldLabelProps & Reac
23
33
  declare const FieldError: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
24
34
  declare const FieldCharCount: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
25
35
 
26
- export { Field, FieldCharCount, FieldError, FieldLabel, type FieldLabelProps, type FieldProps, useFieldContext };
36
+ export { Field, FieldCharCount, FieldError, FieldLabel, type FieldLabelProps, type FieldProps, useFieldContext, useFieldControl };
@@ -4,10 +4,20 @@ import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  interface FieldContextValue {
6
6
  id: string;
7
+ /** id of the FieldLabel, for aria-labelledby on grouped controls */
8
+ labelId: string;
7
9
  error?: boolean;
8
10
  disabled?: boolean;
11
+ /** A FieldLabel is rendered inside this Field */
12
+ hasLabel: boolean;
13
+ /** The Field holds labelled checkboxes / switches / a radio group and no single input */
14
+ isGroup: boolean;
15
+ registerLabel: () => () => void;
16
+ registerControl: (kind: FieldControlKind) => () => void;
9
17
  }
18
+ type FieldControlKind = 'single' | 'group' | 'labelled';
10
19
  declare function useFieldContext(): FieldContextValue | null;
20
+ declare function useFieldControl(kind: FieldControlKind, enabled: boolean): void;
11
21
  declare const fieldVariants: (props?: ({
12
22
  gap?: "default" | "sm" | "lg" | "none" | "xs" | null | undefined;
13
23
  } & class_variance_authority_types.ClassProp) | undefined) => string;
@@ -23,4 +33,4 @@ declare const FieldLabel: React.ForwardRefExoticComponent<FieldLabelProps & Reac
23
33
  declare const FieldError: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
24
34
  declare const FieldCharCount: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
25
35
 
26
- export { Field, FieldCharCount, FieldError, FieldLabel, type FieldLabelProps, type FieldProps, useFieldContext };
36
+ export { Field, FieldCharCount, FieldError, FieldLabel, type FieldLabelProps, type FieldProps, useFieldContext, useFieldControl };
@@ -33,7 +33,8 @@ __export(field_exports, {
33
33
  FieldCharCount: () => FieldCharCount,
34
34
  FieldError: () => FieldError,
35
35
  FieldLabel: () => FieldLabel,
36
- useFieldContext: () => useFieldContext
36
+ useFieldContext: () => useFieldContext,
37
+ useFieldControl: () => useFieldControl
37
38
  });
38
39
  module.exports = __toCommonJS(field_exports);
39
40
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -44,6 +45,14 @@ const FieldContext = React.createContext(null);
44
45
  function useFieldContext() {
45
46
  return React.useContext(FieldContext);
46
47
  }
48
+ function useFieldControl(kind, enabled) {
49
+ const context = useFieldContext();
50
+ const register = context?.registerControl;
51
+ React.useEffect(() => {
52
+ if (!enabled || !register) return;
53
+ return register(kind);
54
+ }, [enabled, register, kind]);
55
+ }
47
56
  const fieldVariants = (0, import_class_variance_authority.cva)("flex flex-col", {
48
57
  variants: {
49
58
  gap: {
@@ -61,10 +70,30 @@ const fieldVariants = (0, import_class_variance_authority.cva)("flex flex-col",
61
70
  const Field = React.forwardRef(
62
71
  ({ className, gap, error, disabled, children, ...props }, ref) => {
63
72
  const id = React.useId();
64
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldContext.Provider, { value: { id, error, disabled }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
73
+ const labelId = `${id}-label`;
74
+ const [labelCount, setLabelCount] = React.useState(0);
75
+ const [counts, setCounts] = React.useState({ single: 0, group: 0, labelled: 0 });
76
+ const registerLabel = React.useCallback(() => {
77
+ setLabelCount((n) => n + 1);
78
+ return () => setLabelCount((n) => n - 1);
79
+ }, []);
80
+ const registerControl = React.useCallback((kind) => {
81
+ setCounts((c) => ({ ...c, [kind]: c[kind] + 1 }));
82
+ return () => setCounts((c) => ({ ...c, [kind]: c[kind] - 1 }));
83
+ }, []);
84
+ const hasLabel = labelCount > 0;
85
+ const isGroup = counts.single === 0 && (counts.group > 0 || counts.labelled > 0);
86
+ const asGroup = counts.single === 0 && counts.group > 0;
87
+ const contextValue = React.useMemo(
88
+ () => ({ id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl }),
89
+ [id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl]
90
+ );
91
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
65
92
  "div",
66
93
  {
67
94
  ref,
95
+ role: asGroup ? "group" : void 0,
96
+ "aria-labelledby": asGroup && hasLabel ? labelId : void 0,
68
97
  className: (0, import_utils.cn)(fieldVariants({ gap }), className),
69
98
  "data-error": error || void 0,
70
99
  "data-disabled": disabled || void 0,
@@ -78,11 +107,14 @@ Field.displayName = "Field";
78
107
  const FieldLabel = React.forwardRef(
79
108
  ({ className, required, children, ...props }, ref) => {
80
109
  const context = useFieldContext();
110
+ const registerLabel = context?.registerLabel;
111
+ React.useEffect(() => registerLabel?.(), [registerLabel]);
81
112
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
82
113
  "label",
83
114
  {
84
115
  ref,
85
- htmlFor: context?.id,
116
+ id: context?.labelId,
117
+ htmlFor: context && !context.isGroup ? context.id : void 0,
86
118
  className: (0, import_utils.cn)(
87
119
  "text-md font-semibold text-foreground",
88
120
  // 14px - primary field identifier
@@ -139,6 +171,7 @@ FieldCharCount.displayName = "FieldCharCount";
139
171
  FieldCharCount,
140
172
  FieldError,
141
173
  FieldLabel,
142
- useFieldContext
174
+ useFieldContext,
175
+ useFieldControl
143
176
  });
144
177
  //# sourceMappingURL=field.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/field.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// Field Context for sharing state between components\ninterface FieldContextValue {\n id: string\n error?: boolean\n disabled?: boolean\n}\n\nconst FieldContext = React.createContext<FieldContextValue | null>(null)\n\nfunction useFieldContext() {\n return React.useContext(FieldContext)\n}\n\n// Field wrapper\nconst fieldVariants = cva('flex flex-col', {\n variants: {\n gap: {\n none: 'gap-0',\n xs: 'gap-1',\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-3',\n },\n },\n defaultVariants: {\n gap: 'default',\n },\n})\n\nexport interface FieldProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof fieldVariants> {\n error?: boolean\n disabled?: boolean\n}\n\nconst Field = React.forwardRef<HTMLDivElement, FieldProps>(\n ({ className, gap, error, disabled, children, ...props }, ref) => {\n const id = React.useId()\n\n return (\n <FieldContext.Provider value={{ id, error, disabled }}>\n <div\n ref={ref}\n className={cn(fieldVariants({ gap }), className)}\n data-error={error || undefined}\n data-disabled={disabled || undefined}\n {...props}\n >\n {children}\n </div>\n </FieldContext.Provider>\n )\n }\n)\nField.displayName = 'Field'\n\n// Field Label\nexport interface FieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {\n required?: boolean\n}\n\nconst FieldLabel = React.forwardRef<HTMLLabelElement, FieldLabelProps>(\n ({ className, required, children, ...props }, ref) => {\n const context = useFieldContext()\n\n return (\n <label\n ref={ref}\n htmlFor={context?.id}\n className={cn(\n 'text-md font-semibold text-foreground', // 14px - primary field identifier\n context?.disabled && 'opacity-50 cursor-not-allowed',\n className\n )}\n {...props}\n >\n {children}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </label>\n )\n }\n)\nFieldLabel.displayName = 'FieldLabel'\n\n// Field Error\nconst FieldError = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const context = useFieldContext()\n\n if (!children) return null\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-error` : undefined}\n role=\"alert\"\n className={cn('text-xs text-error pl-1', className)} // 12px - color-distinguished, left-aligned with input text\n {...props}\n >\n {children}\n </p>\n )\n})\nFieldError.displayName = 'FieldError'\n\n// Field Character Count\nconst FieldCharCount = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const context = useFieldContext()\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-charcount` : undefined}\n className={cn(\n 'text-xs text-text-muted text-right pr-1 -mt-1', // 12px - right-aligned, 4px gap from input (gap-2 8px - mt-1 4px)\n context?.disabled && 'opacity-50',\n className\n )}\n {...props}\n />\n )\n})\nFieldCharCount.displayName = 'FieldCharCount'\n\nexport { Field, FieldLabel, FieldError, FieldCharCount, useFieldContext }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgDQ;AA9CR,YAAuB;AACvB,sCAAuC;AACvC,mBAAmB;AASnB,MAAM,eAAe,MAAM,cAAwC,IAAI;AAEvE,SAAS,kBAAkB;AACzB,SAAO,MAAM,WAAW,YAAY;AACtC;AAGA,MAAM,oBAAgB,qCAAI,iBAAiB;AAAA,EACzC,UAAU;AAAA,IACR,KAAK;AAAA,MACH,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,KAAK;AAAA,EACP;AACF,CAAC;AASD,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,WAAW,KAAK,OAAO,UAAU,UAAU,GAAG,MAAM,GAAG,QAAQ;AAChE,UAAM,KAAK,MAAM,MAAM;AAEvB,WACE,4CAAC,aAAa,UAAb,EAAsB,OAAO,EAAE,IAAI,OAAO,SAAS,GAClD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,eAAW,iBAAG,cAAc,EAAE,IAAI,CAAC,GAAG,SAAS;AAAA,QAC/C,cAAY,SAAS;AAAA,QACrB,iBAAe,YAAY;AAAA,QAC1B,GAAG;AAAA,QAEH;AAAA;AAAA,IACH,GACF;AAAA,EAEJ;AACF;AACA,MAAM,cAAc;AAOpB,MAAM,aAAa,MAAM;AAAA,EACvB,CAAC,EAAE,WAAW,UAAU,UAAU,GAAG,MAAM,GAAG,QAAQ;AACpD,UAAM,UAAU,gBAAgB;AAEhC,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,SAAS,SAAS;AAAA,QAClB,eAAW;AAAA,UACT;AAAA;AAAA,UACA,SAAS,YAAY;AAAA,UACrB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,YAAY,4CAAC,UAAK,WAAU,qBAAoB,eAAC;AAAA;AAAA;AAAA,IACpD;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;AAGzB,MAAM,aAAa,MAAM,WAGvB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AAC5C,QAAM,UAAU,gBAAgB;AAEhC,MAAI,CAAC,SAAU,QAAO;AAEtB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI,UAAU,GAAG,QAAQ,EAAE,WAAW;AAAA,MACtC,MAAK;AAAA,MACL,eAAW,iBAAG,2BAA2B,SAAS;AAAA,MACjD,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ,CAAC;AACD,WAAW,cAAc;AAGzB,MAAM,iBAAiB,MAAM,WAG3B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,UAAU,gBAAgB;AAEhC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI,UAAU,GAAG,QAAQ,EAAE,eAAe;AAAA,MAC1C,eAAW;AAAA,QACT;AAAA;AAAA,QACA,SAAS,YAAY;AAAA,QACrB;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,eAAe,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ui/field.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// Field Context for sharing state between components\ninterface FieldContextValue {\n id: string\n /** id of the FieldLabel, for aria-labelledby on grouped controls */\n labelId: string\n error?: boolean\n disabled?: boolean\n /** A FieldLabel is rendered inside this Field */\n hasLabel: boolean\n /** The Field holds labelled checkboxes / switches / a radio group and no single input */\n isGroup: boolean\n registerLabel: () => () => void\n registerControl: (kind: FieldControlKind) => () => void\n}\n\ntype FieldControlKind = 'single' | 'group' | 'labelled'\n\nconst FieldContext = React.createContext<FieldContextValue | null>(null)\n\nfunction useFieldContext() {\n return React.useContext(FieldContext)\n}\n\n// Controls tell their Field what they are, so FieldLabel can point at the right thing.\n// 'single': one input that takes the Field id (Input, Textarea, a bare Checkbox / Switch);\n// FieldLabel targets it with htmlFor.\n// 'group': a Checkbox / Switch with its own label keeps a unique id; the Field becomes\n// role=\"group\" named by FieldLabel instead of every item sharing one id.\n// 'labelled': a RadioGroup names itself from FieldLabel (aria-labelledby).\n// A single input wins: with one present, FieldLabel keeps pointing at it.\nfunction useFieldControl(kind: FieldControlKind, enabled: boolean) {\n const context = useFieldContext()\n const register = context?.registerControl\n React.useEffect(() => {\n if (!enabled || !register) return\n return register(kind)\n }, [enabled, register, kind])\n}\n\n// Field wrapper\nconst fieldVariants = cva('flex flex-col', {\n variants: {\n gap: {\n none: 'gap-0',\n xs: 'gap-1',\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-3',\n },\n },\n defaultVariants: {\n gap: 'default',\n },\n})\n\nexport interface FieldProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof fieldVariants> {\n error?: boolean\n disabled?: boolean\n}\n\nconst Field = React.forwardRef<HTMLDivElement, FieldProps>(\n ({ className, gap, error, disabled, children, ...props }, ref) => {\n const id = React.useId()\n const labelId = `${id}-label`\n const [labelCount, setLabelCount] = React.useState(0)\n const [counts, setCounts] = React.useState({ single: 0, group: 0, labelled: 0 })\n\n const registerLabel = React.useCallback(() => {\n setLabelCount((n) => n + 1)\n return () => setLabelCount((n) => n - 1)\n }, [])\n const registerControl = React.useCallback((kind: FieldControlKind) => {\n setCounts((c) => ({ ...c, [kind]: c[kind] + 1 }))\n return () => setCounts((c) => ({ ...c, [kind]: c[kind] - 1 }))\n }, [])\n\n const hasLabel = labelCount > 0\n const isGroup = counts.single === 0 && (counts.group > 0 || counts.labelled > 0)\n const asGroup = counts.single === 0 && counts.group > 0\n const contextValue = React.useMemo(\n () => ({ id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl }),\n [id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl]\n )\n\n return (\n <FieldContext.Provider value={contextValue}>\n <div\n ref={ref}\n role={asGroup ? 'group' : undefined}\n aria-labelledby={asGroup && hasLabel ? labelId : undefined}\n className={cn(fieldVariants({ gap }), className)}\n data-error={error || undefined}\n data-disabled={disabled || undefined}\n {...props}\n >\n {children}\n </div>\n </FieldContext.Provider>\n )\n }\n)\nField.displayName = 'Field'\n\n// Field Label\nexport interface FieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {\n required?: boolean\n}\n\nconst FieldLabel = React.forwardRef<HTMLLabelElement, FieldLabelProps>(\n ({ className, required, children, ...props }, ref) => {\n const context = useFieldContext()\n const registerLabel = context?.registerLabel\n React.useEffect(() => registerLabel?.(), [registerLabel])\n\n return (\n <label\n ref={ref}\n id={context?.labelId}\n // Grouped controls have their own labels; the group title targets no input\n htmlFor={context && !context.isGroup ? context.id : undefined}\n className={cn(\n 'text-md font-semibold text-foreground', // 14px - primary field identifier\n context?.disabled && 'opacity-50 cursor-not-allowed',\n className\n )}\n {...props}\n >\n {children}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </label>\n )\n }\n)\nFieldLabel.displayName = 'FieldLabel'\n\n// Field Error\nconst FieldError = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const context = useFieldContext()\n\n if (!children) return null\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-error` : undefined}\n role=\"alert\"\n className={cn('text-xs text-error pl-1', className)} // 12px - color-distinguished, left-aligned with input text\n {...props}\n >\n {children}\n </p>\n )\n})\nFieldError.displayName = 'FieldError'\n\n// Field Character Count\nconst FieldCharCount = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const context = useFieldContext()\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-charcount` : undefined}\n className={cn(\n 'text-xs text-text-muted text-right pr-1 -mt-1', // 12px - right-aligned, 4px gap from input (gap-2 8px - mt-1 4px)\n context?.disabled && 'opacity-50',\n className\n )}\n {...props}\n />\n )\n})\nFieldCharCount.displayName = 'FieldCharCount'\n\nexport { Field, FieldLabel, FieldError, FieldCharCount, useFieldContext, useFieldControl }\n"],"mappings":"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","names":[]}
@@ -7,6 +7,14 @@ const FieldContext = React.createContext(null);
7
7
  function useFieldContext() {
8
8
  return React.useContext(FieldContext);
9
9
  }
10
+ function useFieldControl(kind, enabled) {
11
+ const context = useFieldContext();
12
+ const register = context?.registerControl;
13
+ React.useEffect(() => {
14
+ if (!enabled || !register) return;
15
+ return register(kind);
16
+ }, [enabled, register, kind]);
17
+ }
10
18
  const fieldVariants = cva("flex flex-col", {
11
19
  variants: {
12
20
  gap: {
@@ -24,10 +32,30 @@ const fieldVariants = cva("flex flex-col", {
24
32
  const Field = React.forwardRef(
25
33
  ({ className, gap, error, disabled, children, ...props }, ref) => {
26
34
  const id = React.useId();
27
- return /* @__PURE__ */ jsx(FieldContext.Provider, { value: { id, error, disabled }, children: /* @__PURE__ */ jsx(
35
+ const labelId = `${id}-label`;
36
+ const [labelCount, setLabelCount] = React.useState(0);
37
+ const [counts, setCounts] = React.useState({ single: 0, group: 0, labelled: 0 });
38
+ const registerLabel = React.useCallback(() => {
39
+ setLabelCount((n) => n + 1);
40
+ return () => setLabelCount((n) => n - 1);
41
+ }, []);
42
+ const registerControl = React.useCallback((kind) => {
43
+ setCounts((c) => ({ ...c, [kind]: c[kind] + 1 }));
44
+ return () => setCounts((c) => ({ ...c, [kind]: c[kind] - 1 }));
45
+ }, []);
46
+ const hasLabel = labelCount > 0;
47
+ const isGroup = counts.single === 0 && (counts.group > 0 || counts.labelled > 0);
48
+ const asGroup = counts.single === 0 && counts.group > 0;
49
+ const contextValue = React.useMemo(
50
+ () => ({ id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl }),
51
+ [id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl]
52
+ );
53
+ return /* @__PURE__ */ jsx(FieldContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
28
54
  "div",
29
55
  {
30
56
  ref,
57
+ role: asGroup ? "group" : void 0,
58
+ "aria-labelledby": asGroup && hasLabel ? labelId : void 0,
31
59
  className: cn(fieldVariants({ gap }), className),
32
60
  "data-error": error || void 0,
33
61
  "data-disabled": disabled || void 0,
@@ -41,11 +69,14 @@ Field.displayName = "Field";
41
69
  const FieldLabel = React.forwardRef(
42
70
  ({ className, required, children, ...props }, ref) => {
43
71
  const context = useFieldContext();
72
+ const registerLabel = context?.registerLabel;
73
+ React.useEffect(() => registerLabel?.(), [registerLabel]);
44
74
  return /* @__PURE__ */ jsxs(
45
75
  "label",
46
76
  {
47
77
  ref,
48
- htmlFor: context?.id,
78
+ id: context?.labelId,
79
+ htmlFor: context && !context.isGroup ? context.id : void 0,
49
80
  className: cn(
50
81
  "text-md font-semibold text-foreground",
51
82
  // 14px - primary field identifier
@@ -101,6 +132,7 @@ export {
101
132
  FieldCharCount,
102
133
  FieldError,
103
134
  FieldLabel,
104
- useFieldContext
135
+ useFieldContext,
136
+ useFieldControl
105
137
  };
106
138
  //# sourceMappingURL=field.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/field.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// Field Context for sharing state between components\ninterface FieldContextValue {\n id: string\n error?: boolean\n disabled?: boolean\n}\n\nconst FieldContext = React.createContext<FieldContextValue | null>(null)\n\nfunction useFieldContext() {\n return React.useContext(FieldContext)\n}\n\n// Field wrapper\nconst fieldVariants = cva('flex flex-col', {\n variants: {\n gap: {\n none: 'gap-0',\n xs: 'gap-1',\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-3',\n },\n },\n defaultVariants: {\n gap: 'default',\n },\n})\n\nexport interface FieldProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof fieldVariants> {\n error?: boolean\n disabled?: boolean\n}\n\nconst Field = React.forwardRef<HTMLDivElement, FieldProps>(\n ({ className, gap, error, disabled, children, ...props }, ref) => {\n const id = React.useId()\n\n return (\n <FieldContext.Provider value={{ id, error, disabled }}>\n <div\n ref={ref}\n className={cn(fieldVariants({ gap }), className)}\n data-error={error || undefined}\n data-disabled={disabled || undefined}\n {...props}\n >\n {children}\n </div>\n </FieldContext.Provider>\n )\n }\n)\nField.displayName = 'Field'\n\n// Field Label\nexport interface FieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {\n required?: boolean\n}\n\nconst FieldLabel = React.forwardRef<HTMLLabelElement, FieldLabelProps>(\n ({ className, required, children, ...props }, ref) => {\n const context = useFieldContext()\n\n return (\n <label\n ref={ref}\n htmlFor={context?.id}\n className={cn(\n 'text-md font-semibold text-foreground', // 14px - primary field identifier\n context?.disabled && 'opacity-50 cursor-not-allowed',\n className\n )}\n {...props}\n >\n {children}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </label>\n )\n }\n)\nFieldLabel.displayName = 'FieldLabel'\n\n// Field Error\nconst FieldError = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const context = useFieldContext()\n\n if (!children) return null\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-error` : undefined}\n role=\"alert\"\n className={cn('text-xs text-error pl-1', className)} // 12px - color-distinguished, left-aligned with input text\n {...props}\n >\n {children}\n </p>\n )\n})\nFieldError.displayName = 'FieldError'\n\n// Field Character Count\nconst FieldCharCount = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const context = useFieldContext()\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-charcount` : undefined}\n className={cn(\n 'text-xs text-text-muted text-right pr-1 -mt-1', // 12px - right-aligned, 4px gap from input (gap-2 8px - mt-1 4px)\n context?.disabled && 'opacity-50',\n className\n )}\n {...props}\n />\n )\n})\nFieldCharCount.displayName = 'FieldCharCount'\n\nexport { Field, FieldLabel, FieldError, FieldCharCount, useFieldContext }\n"],"mappings":";AAgDQ,cAyBF,YAzBE;AA9CR,YAAY,WAAW;AACvB,SAAS,WAA8B;AACvC,SAAS,UAAU;AASnB,MAAM,eAAe,MAAM,cAAwC,IAAI;AAEvE,SAAS,kBAAkB;AACzB,SAAO,MAAM,WAAW,YAAY;AACtC;AAGA,MAAM,gBAAgB,IAAI,iBAAiB;AAAA,EACzC,UAAU;AAAA,IACR,KAAK;AAAA,MACH,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,KAAK;AAAA,EACP;AACF,CAAC;AASD,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,WAAW,KAAK,OAAO,UAAU,UAAU,GAAG,MAAM,GAAG,QAAQ;AAChE,UAAM,KAAK,MAAM,MAAM;AAEvB,WACE,oBAAC,aAAa,UAAb,EAAsB,OAAO,EAAE,IAAI,OAAO,SAAS,GAClD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,cAAc,EAAE,IAAI,CAAC,GAAG,SAAS;AAAA,QAC/C,cAAY,SAAS;AAAA,QACrB,iBAAe,YAAY;AAAA,QAC1B,GAAG;AAAA,QAEH;AAAA;AAAA,IACH,GACF;AAAA,EAEJ;AACF;AACA,MAAM,cAAc;AAOpB,MAAM,aAAa,MAAM;AAAA,EACvB,CAAC,EAAE,WAAW,UAAU,UAAU,GAAG,MAAM,GAAG,QAAQ;AACpD,UAAM,UAAU,gBAAgB;AAEhC,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,SAAS,SAAS;AAAA,QAClB,WAAW;AAAA,UACT;AAAA;AAAA,UACA,SAAS,YAAY;AAAA,UACrB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,YAAY,oBAAC,UAAK,WAAU,qBAAoB,eAAC;AAAA;AAAA;AAAA,IACpD;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;AAGzB,MAAM,aAAa,MAAM,WAGvB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AAC5C,QAAM,UAAU,gBAAgB;AAEhC,MAAI,CAAC,SAAU,QAAO;AAEtB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI,UAAU,GAAG,QAAQ,EAAE,WAAW;AAAA,MACtC,MAAK;AAAA,MACL,WAAW,GAAG,2BAA2B,SAAS;AAAA,MACjD,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ,CAAC;AACD,WAAW,cAAc;AAGzB,MAAM,iBAAiB,MAAM,WAG3B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,UAAU,gBAAgB;AAEhC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI,UAAU,GAAG,QAAQ,EAAE,eAAe;AAAA,MAC1C,WAAW;AAAA,QACT;AAAA;AAAA,QACA,SAAS,YAAY;AAAA,QACrB;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,eAAe,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ui/field.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// Field Context for sharing state between components\ninterface FieldContextValue {\n id: string\n /** id of the FieldLabel, for aria-labelledby on grouped controls */\n labelId: string\n error?: boolean\n disabled?: boolean\n /** A FieldLabel is rendered inside this Field */\n hasLabel: boolean\n /** The Field holds labelled checkboxes / switches / a radio group and no single input */\n isGroup: boolean\n registerLabel: () => () => void\n registerControl: (kind: FieldControlKind) => () => void\n}\n\ntype FieldControlKind = 'single' | 'group' | 'labelled'\n\nconst FieldContext = React.createContext<FieldContextValue | null>(null)\n\nfunction useFieldContext() {\n return React.useContext(FieldContext)\n}\n\n// Controls tell their Field what they are, so FieldLabel can point at the right thing.\n// 'single': one input that takes the Field id (Input, Textarea, a bare Checkbox / Switch);\n// FieldLabel targets it with htmlFor.\n// 'group': a Checkbox / Switch with its own label keeps a unique id; the Field becomes\n// role=\"group\" named by FieldLabel instead of every item sharing one id.\n// 'labelled': a RadioGroup names itself from FieldLabel (aria-labelledby).\n// A single input wins: with one present, FieldLabel keeps pointing at it.\nfunction useFieldControl(kind: FieldControlKind, enabled: boolean) {\n const context = useFieldContext()\n const register = context?.registerControl\n React.useEffect(() => {\n if (!enabled || !register) return\n return register(kind)\n }, [enabled, register, kind])\n}\n\n// Field wrapper\nconst fieldVariants = cva('flex flex-col', {\n variants: {\n gap: {\n none: 'gap-0',\n xs: 'gap-1',\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-3',\n },\n },\n defaultVariants: {\n gap: 'default',\n },\n})\n\nexport interface FieldProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof fieldVariants> {\n error?: boolean\n disabled?: boolean\n}\n\nconst Field = React.forwardRef<HTMLDivElement, FieldProps>(\n ({ className, gap, error, disabled, children, ...props }, ref) => {\n const id = React.useId()\n const labelId = `${id}-label`\n const [labelCount, setLabelCount] = React.useState(0)\n const [counts, setCounts] = React.useState({ single: 0, group: 0, labelled: 0 })\n\n const registerLabel = React.useCallback(() => {\n setLabelCount((n) => n + 1)\n return () => setLabelCount((n) => n - 1)\n }, [])\n const registerControl = React.useCallback((kind: FieldControlKind) => {\n setCounts((c) => ({ ...c, [kind]: c[kind] + 1 }))\n return () => setCounts((c) => ({ ...c, [kind]: c[kind] - 1 }))\n }, [])\n\n const hasLabel = labelCount > 0\n const isGroup = counts.single === 0 && (counts.group > 0 || counts.labelled > 0)\n const asGroup = counts.single === 0 && counts.group > 0\n const contextValue = React.useMemo(\n () => ({ id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl }),\n [id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl]\n )\n\n return (\n <FieldContext.Provider value={contextValue}>\n <div\n ref={ref}\n role={asGroup ? 'group' : undefined}\n aria-labelledby={asGroup && hasLabel ? labelId : undefined}\n className={cn(fieldVariants({ gap }), className)}\n data-error={error || undefined}\n data-disabled={disabled || undefined}\n {...props}\n >\n {children}\n </div>\n </FieldContext.Provider>\n )\n }\n)\nField.displayName = 'Field'\n\n// Field Label\nexport interface FieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {\n required?: boolean\n}\n\nconst FieldLabel = React.forwardRef<HTMLLabelElement, FieldLabelProps>(\n ({ className, required, children, ...props }, ref) => {\n const context = useFieldContext()\n const registerLabel = context?.registerLabel\n React.useEffect(() => registerLabel?.(), [registerLabel])\n\n return (\n <label\n ref={ref}\n id={context?.labelId}\n // Grouped controls have their own labels; the group title targets no input\n htmlFor={context && !context.isGroup ? context.id : undefined}\n className={cn(\n 'text-md font-semibold text-foreground', // 14px - primary field identifier\n context?.disabled && 'opacity-50 cursor-not-allowed',\n className\n )}\n {...props}\n >\n {children}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </label>\n )\n }\n)\nFieldLabel.displayName = 'FieldLabel'\n\n// Field Error\nconst FieldError = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const context = useFieldContext()\n\n if (!children) return null\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-error` : undefined}\n role=\"alert\"\n className={cn('text-xs text-error pl-1', className)} // 12px - color-distinguished, left-aligned with input text\n {...props}\n >\n {children}\n </p>\n )\n})\nFieldError.displayName = 'FieldError'\n\n// Field Character Count\nconst FieldCharCount = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const context = useFieldContext()\n\n return (\n <p\n ref={ref}\n id={context ? `${context.id}-charcount` : undefined}\n className={cn(\n 'text-xs text-text-muted text-right pr-1 -mt-1', // 12px - right-aligned, 4px gap from input (gap-2 8px - mt-1 4px)\n context?.disabled && 'opacity-50',\n className\n )}\n {...props}\n />\n )\n})\nFieldCharCount.displayName = 'FieldCharCount'\n\nexport { Field, FieldLabel, FieldError, FieldCharCount, useFieldContext, useFieldControl }\n"],"mappings":";AA8FQ,cA6BF,YA7BE;AA5FR,YAAY,WAAW;AACvB,SAAS,WAA8B;AACvC,SAAS,UAAU;AAmBnB,MAAM,eAAe,MAAM,cAAwC,IAAI;AAEvE,SAAS,kBAAkB;AACzB,SAAO,MAAM,WAAW,YAAY;AACtC;AASA,SAAS,gBAAgB,MAAwB,SAAkB;AACjE,QAAM,UAAU,gBAAgB;AAChC,QAAM,WAAW,SAAS;AAC1B,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,WAAW,CAAC,SAAU;AAC3B,WAAO,SAAS,IAAI;AAAA,EACtB,GAAG,CAAC,SAAS,UAAU,IAAI,CAAC;AAC9B;AAGA,MAAM,gBAAgB,IAAI,iBAAiB;AAAA,EACzC,UAAU;AAAA,IACR,KAAK;AAAA,MACH,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,KAAK;AAAA,EACP;AACF,CAAC;AASD,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,WAAW,KAAK,OAAO,UAAU,UAAU,GAAG,MAAM,GAAG,QAAQ;AAChE,UAAM,KAAK,MAAM,MAAM;AACvB,UAAM,UAAU,GAAG,EAAE;AACrB,UAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,UAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,EAAE,CAAC;AAE/E,UAAM,gBAAgB,MAAM,YAAY,MAAM;AAC5C,oBAAc,CAAC,MAAM,IAAI,CAAC;AAC1B,aAAO,MAAM,cAAc,CAAC,MAAM,IAAI,CAAC;AAAA,IACzC,GAAG,CAAC,CAAC;AACL,UAAM,kBAAkB,MAAM,YAAY,CAAC,SAA2B;AACpE,gBAAU,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE,EAAE;AAChD,aAAO,MAAM,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE,EAAE;AAAA,IAC/D,GAAG,CAAC,CAAC;AAEL,UAAM,WAAW,aAAa;AAC9B,UAAM,UAAU,OAAO,WAAW,MAAM,OAAO,QAAQ,KAAK,OAAO,WAAW;AAC9E,UAAM,UAAU,OAAO,WAAW,KAAK,OAAO,QAAQ;AACtD,UAAM,eAAe,MAAM;AAAA,MACzB,OAAO,EAAE,IAAI,SAAS,OAAO,UAAU,UAAU,SAAS,eAAe,gBAAgB;AAAA,MACzF,CAAC,IAAI,SAAS,OAAO,UAAU,UAAU,SAAS,eAAe,eAAe;AAAA,IAClF;AAEA,WACE,oBAAC,aAAa,UAAb,EAAsB,OAAO,cAC5B;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM,UAAU,UAAU;AAAA,QAC1B,mBAAiB,WAAW,WAAW,UAAU;AAAA,QACjD,WAAW,GAAG,cAAc,EAAE,IAAI,CAAC,GAAG,SAAS;AAAA,QAC/C,cAAY,SAAS;AAAA,QACrB,iBAAe,YAAY;AAAA,QAC1B,GAAG;AAAA,QAEH;AAAA;AAAA,IACH,GACF;AAAA,EAEJ;AACF;AACA,MAAM,cAAc;AAOpB,MAAM,aAAa,MAAM;AAAA,EACvB,CAAC,EAAE,WAAW,UAAU,UAAU,GAAG,MAAM,GAAG,QAAQ;AACpD,UAAM,UAAU,gBAAgB;AAChC,UAAM,gBAAgB,SAAS;AAC/B,UAAM,UAAU,MAAM,gBAAgB,GAAG,CAAC,aAAa,CAAC;AAExD,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,IAAI,SAAS;AAAA,QAEb,SAAS,WAAW,CAAC,QAAQ,UAAU,QAAQ,KAAK;AAAA,QACpD,WAAW;AAAA,UACT;AAAA;AAAA,UACA,SAAS,YAAY;AAAA,UACrB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,YAAY,oBAAC,UAAK,WAAU,qBAAoB,eAAC;AAAA;AAAA;AAAA,IACpD;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;AAGzB,MAAM,aAAa,MAAM,WAGvB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AAC5C,QAAM,UAAU,gBAAgB;AAEhC,MAAI,CAAC,SAAU,QAAO;AAEtB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI,UAAU,GAAG,QAAQ,EAAE,WAAW;AAAA,MACtC,MAAK;AAAA,MACL,WAAW,GAAG,2BAA2B,SAAS;AAAA,MACjD,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ,CAAC;AACD,WAAW,cAAc;AAGzB,MAAM,iBAAiB,MAAM,WAG3B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,UAAU,gBAAgB;AAEhC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI,UAAU,GAAG,QAAQ,EAAE,eAAe;AAAA,MAC1C,WAAW;AAAA,QACT;AAAA;AAAA,QACA,SAAS,YAAY;AAAA,QACrB;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,eAAe,cAAc;","names":[]}
@@ -9,7 +9,7 @@ export { ToggleGroup, ToggleGroupItem, ToggleGroupItemProps, ToggleGroupProps, t
9
9
  export { Segmented, SegmentedItem, SegmentedItemProps, SegmentedProps, segmentedItemVariants, segmentedVariants } from './segmented.mjs';
10
10
  export { Input, InputProps, inputVariants } from './input.mjs';
11
11
  export { Textarea, TextareaProps, textareaVariants } from './textarea.mjs';
12
- export { Field, FieldCharCount, FieldError, FieldLabel, FieldLabelProps, FieldProps, useFieldContext } from './field.mjs';
12
+ export { Field, FieldCharCount, FieldError, FieldLabel, FieldLabelProps, FieldProps, useFieldContext, useFieldControl } from './field.mjs';
13
13
  export { Checkbox, CheckboxColor, CheckboxProps, checkboxVariants } from './checkbox.mjs';
14
14
  export { RadioColor, RadioGroup, RadioGroupItem, RadioGroupItemProps, RadioGroupProps, radioGroupVariants, radioItemVariants } from './radio-group.mjs';
15
15
  export { Switch, SwitchColor, SwitchLabelPosition, SwitchProps, switchVariants } from './switch.mjs';
@@ -9,7 +9,7 @@ export { ToggleGroup, ToggleGroupItem, ToggleGroupItemProps, ToggleGroupProps, t
9
9
  export { Segmented, SegmentedItem, SegmentedItemProps, SegmentedProps, segmentedItemVariants, segmentedVariants } from './segmented.js';
10
10
  export { Input, InputProps, inputVariants } from './input.js';
11
11
  export { Textarea, TextareaProps, textareaVariants } from './textarea.js';
12
- export { Field, FieldCharCount, FieldError, FieldLabel, FieldLabelProps, FieldProps, useFieldContext } from './field.js';
12
+ export { Field, FieldCharCount, FieldError, FieldLabel, FieldLabelProps, FieldProps, useFieldContext, useFieldControl } from './field.js';
13
13
  export { Checkbox, CheckboxColor, CheckboxProps, checkboxVariants } from './checkbox.js';
14
14
  export { RadioColor, RadioGroup, RadioGroupItem, RadioGroupItemProps, RadioGroupProps, radioGroupVariants, radioItemVariants } from './radio-group.js';
15
15
  export { Switch, SwitchColor, SwitchLabelPosition, SwitchProps, switchVariants } from './switch.js';
@@ -148,6 +148,7 @@ const Input = React.forwardRef(
148
148
  const resolvedError = error ?? fieldContext?.error;
149
149
  const resolvedState = resolvedError ? "error" : state;
150
150
  const inputId = id ?? fieldContext?.id;
151
+ (0, import_field.useFieldControl)("single", Boolean(fieldContext) && !id);
151
152
  const isDisabled = props.disabled ?? fieldContext?.disabled;
152
153
  const pointerRef = React.useRef(false);
153
154
  const windowBlurredRef = React.useRef(false);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext } from './field'\n\nconst inputVariants = cva(\n [\n 'flex w-full bg-background text-foreground placeholder:text-foreground/30',\n 'border transition-colors duration-micro outline-transparent',\n 'focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-background-muted',\n 'file:border-0 file:bg-transparent file:text-sm file:font-semibold',\n ].join(' '),\n {\n variants: {\n variant: {\n default: 'border-border-form hover:border-border-form-strong',\n filled: 'border-transparent bg-background-muted',\n },\n focusRing: {\n true: '',\n false: '',\n },\n size: {\n xs: 'h-9 px-3 text-sm', // 36px / 12px padding / 13px font (3.0:1)\n sm: 'h-10 px-3 text-md', // 40px / 12px padding / 14px font (3.3:1)\n default: 'h-11 px-4 text-base', // 44px / 16px padding / 16px font (2.75:1)\n lg: 'h-12 px-4 text-base', // 48px / 16px padding / 16px font (3.0:1)\n xl: 'h-14 px-4 text-base', // 56px / 16px padding / 16px font (3.5:1)\n },\n radius: {\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 state: {\n default: '',\n error: 'border-error hover:border-error focus:border-error shadow-[0_0_0_2px_var(--color-focus-ring-error)]',\n },\n },\n compoundVariants: [\n // focusRing: true → show custom focus ring\n { focusRing: true, className: 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)]' },\n // focusRing: false → keep same state as hover\n { variant: 'default', focusRing: false, className: 'focus:border-border-form-strong' },\n // filled + error\n {\n variant: 'filled',\n state: 'error',\n className: 'border-transparent hover:border-transparent focus:border-transparent bg-[var(--color-error-bg)] hover:bg-[var(--color-error-bg)] focus:bg-[var(--color-error-bg)] shadow-none',\n },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n state: 'default',\n focusRing: false,\n },\n }\n)\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>,\n VariantProps<typeof inputVariants> {\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n error?: boolean\n focusRing?: boolean\n}\n\n// Icon size for input (2-step scale)\n// xs~sm: 14px, default~xl: 16px\nconst iconSizeClasses = {\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// Icon padding (padding + icon + gap)\nconst iconPaddingClasses = {\n xs: { left: 'pl-8', right: 'pr-8' }, // 12px + 14px icon + 6px gap = 32px\n sm: { left: 'pl-9', right: 'pr-9' }, // 12px + 14px icon + 8px gap = 34px → 36px\n default: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n lg: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n xl: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n}\n\n// Icon position (matches horizontal padding)\nconst iconPositionClasses = {\n xs: { left: 'left-3', right: 'right-3' }, // 12px\n sm: { left: 'left-3', right: 'right-3' }, // 12px\n default: { left: 'left-4', right: 'right-4' }, // 16px\n lg: { left: 'left-4', right: 'right-4' }, // 16px\n xl: { left: 'left-4', right: 'right-4' }, // 16px\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, variant, size, radius, state, type, leftIcon, rightIcon, error, focusRing, id, onPointerDown, onFocus, onBlur, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedError = error ?? fieldContext?.error\n const resolvedState = resolvedError ? 'error' : state\n const inputId = id ?? fieldContext?.id\n const isDisabled = props.disabled ?? fieldContext?.disabled\n\n // Keyboard focus detection (when focusRing: false, auto-show ring on Tab navigation)\n const pointerRef = React.useRef(false)\n const windowBlurredRef = React.useRef(false)\n const [keyboardFocus, setKeyboardFocus] = React.useState(false)\n\n // Track window blur/focus to distinguish Tab navigation from window re-activation\n React.useEffect(() => {\n const onBlur = () => { windowBlurredRef.current = true }\n const onFocus = () => { requestAnimationFrame(() => { windowBlurredRef.current = false }) }\n window.addEventListener('blur', onBlur)\n window.addEventListener('focus', onFocus)\n return () => { window.removeEventListener('blur', onBlur); window.removeEventListener('focus', onFocus) }\n }, [])\n\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLInputElement>) => {\n pointerRef.current = true\n onPointerDown?.(e)\n }, [onPointerDown])\n\n const handleFocus = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n if (!pointerRef.current && !focusRing && !windowBlurredRef.current) {\n setKeyboardFocus(true)\n }\n pointerRef.current = false\n onFocus?.(e)\n }, [focusRing, onFocus])\n\n const handleBlur = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n setKeyboardFocus(false)\n pointerRef.current = false\n onBlur?.(e)\n }, [onBlur])\n\n // Build aria-describedby from context\n const ariaDescribedBy = fieldContext\n ? [\n resolvedError ? `${fieldContext.id}-error` : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n : undefined\n\n const focusHandlers = {\n onPointerDown: handlePointerDown,\n onFocus: handleFocus,\n onBlur: handleBlur,\n }\n\n // If icons are present, wrap input in a container\n if (leftIcon || rightIcon) {\n return (\n <div className=\"relative w-full\">\n {leftIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].left,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {leftIcon}\n </div>\n )}\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n leftIcon && iconPaddingClasses[resolvedSize].left,\n rightIcon && iconPaddingClasses[resolvedSize].right,\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n {rightIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].right,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {rightIcon}\n </div>\n )}\n </div>\n )\n }\n\n return (\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input, inputVariants }\n"],"mappings":"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","names":["onBlur","onFocus"]}
1
+ {"version":3,"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\nconst inputVariants = cva(\n [\n 'flex w-full bg-background text-foreground placeholder:text-foreground/30',\n 'border transition-colors duration-micro outline-transparent',\n 'focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-background-muted',\n 'file:border-0 file:bg-transparent file:text-sm file:font-semibold',\n ].join(' '),\n {\n variants: {\n variant: {\n default: 'border-border-form hover:border-border-form-strong',\n filled: 'border-transparent bg-background-muted',\n },\n focusRing: {\n true: '',\n false: '',\n },\n size: {\n xs: 'h-9 px-3 text-sm', // 36px / 12px padding / 13px font (3.0:1)\n sm: 'h-10 px-3 text-md', // 40px / 12px padding / 14px font (3.3:1)\n default: 'h-11 px-4 text-base', // 44px / 16px padding / 16px font (2.75:1)\n lg: 'h-12 px-4 text-base', // 48px / 16px padding / 16px font (3.0:1)\n xl: 'h-14 px-4 text-base', // 56px / 16px padding / 16px font (3.5:1)\n },\n radius: {\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 state: {\n default: '',\n error: 'border-error hover:border-error focus:border-error shadow-[0_0_0_2px_var(--color-focus-ring-error)]',\n },\n },\n compoundVariants: [\n // focusRing: true → show custom focus ring\n { focusRing: true, className: 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)]' },\n // focusRing: false → keep same state as hover\n { variant: 'default', focusRing: false, className: 'focus:border-border-form-strong' },\n // filled + error\n {\n variant: 'filled',\n state: 'error',\n className: 'border-transparent hover:border-transparent focus:border-transparent bg-[var(--color-error-bg)] hover:bg-[var(--color-error-bg)] focus:bg-[var(--color-error-bg)] shadow-none',\n },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n state: 'default',\n focusRing: false,\n },\n }\n)\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>,\n VariantProps<typeof inputVariants> {\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n error?: boolean\n focusRing?: boolean\n}\n\n// Icon size for input (2-step scale)\n// xs~sm: 14px, default~xl: 16px\nconst iconSizeClasses = {\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// Icon padding (padding + icon + gap)\nconst iconPaddingClasses = {\n xs: { left: 'pl-8', right: 'pr-8' }, // 12px + 14px icon + 6px gap = 32px\n sm: { left: 'pl-9', right: 'pr-9' }, // 12px + 14px icon + 8px gap = 34px → 36px\n default: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n lg: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n xl: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n}\n\n// Icon position (matches horizontal padding)\nconst iconPositionClasses = {\n xs: { left: 'left-3', right: 'right-3' }, // 12px\n sm: { left: 'left-3', right: 'right-3' }, // 12px\n default: { left: 'left-4', right: 'right-4' }, // 16px\n lg: { left: 'left-4', right: 'right-4' }, // 16px\n xl: { left: 'left-4', right: 'right-4' }, // 16px\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, variant, size, radius, state, type, leftIcon, rightIcon, error, focusRing, id, onPointerDown, onFocus, onBlur, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedError = error ?? fieldContext?.error\n const resolvedState = resolvedError ? 'error' : state\n const inputId = id ?? fieldContext?.id\n useFieldControl('single', Boolean(fieldContext) && !id)\n const isDisabled = props.disabled ?? fieldContext?.disabled\n\n // Keyboard focus detection (when focusRing: false, auto-show ring on Tab navigation)\n const pointerRef = React.useRef(false)\n const windowBlurredRef = React.useRef(false)\n const [keyboardFocus, setKeyboardFocus] = React.useState(false)\n\n // Track window blur/focus to distinguish Tab navigation from window re-activation\n React.useEffect(() => {\n const onBlur = () => { windowBlurredRef.current = true }\n const onFocus = () => { requestAnimationFrame(() => { windowBlurredRef.current = false }) }\n window.addEventListener('blur', onBlur)\n window.addEventListener('focus', onFocus)\n return () => { window.removeEventListener('blur', onBlur); window.removeEventListener('focus', onFocus) }\n }, [])\n\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLInputElement>) => {\n pointerRef.current = true\n onPointerDown?.(e)\n }, [onPointerDown])\n\n const handleFocus = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n if (!pointerRef.current && !focusRing && !windowBlurredRef.current) {\n setKeyboardFocus(true)\n }\n pointerRef.current = false\n onFocus?.(e)\n }, [focusRing, onFocus])\n\n const handleBlur = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n setKeyboardFocus(false)\n pointerRef.current = false\n onBlur?.(e)\n }, [onBlur])\n\n // Build aria-describedby from context\n const ariaDescribedBy = fieldContext\n ? [\n resolvedError ? `${fieldContext.id}-error` : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n : undefined\n\n const focusHandlers = {\n onPointerDown: handlePointerDown,\n onFocus: handleFocus,\n onBlur: handleBlur,\n }\n\n // If icons are present, wrap input in a container\n if (leftIcon || rightIcon) {\n return (\n <div className=\"relative w-full\">\n {leftIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].left,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {leftIcon}\n </div>\n )}\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n leftIcon && iconPaddingClasses[resolvedSize].left,\n rightIcon && iconPaddingClasses[resolvedSize].right,\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n {rightIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].right,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {rightIcon}\n </div>\n )}\n </div>\n )\n }\n\n return (\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input, inputVariants }\n"],"mappings":"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","names":["onBlur","onFocus"]}
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cva } from "class-variance-authority";
5
5
  import { cn } from "../../lib/utils.mjs";
6
- import { useFieldContext } from "./field.mjs";
6
+ import { useFieldContext, useFieldControl } from "./field.mjs";
7
7
  const inputVariants = cva(
8
8
  [
9
9
  "flex w-full bg-background text-foreground placeholder:text-foreground/30",
@@ -114,6 +114,7 @@ const Input = React.forwardRef(
114
114
  const resolvedError = error ?? fieldContext?.error;
115
115
  const resolvedState = resolvedError ? "error" : state;
116
116
  const inputId = id ?? fieldContext?.id;
117
+ useFieldControl("single", Boolean(fieldContext) && !id);
117
118
  const isDisabled = props.disabled ?? fieldContext?.disabled;
118
119
  const pointerRef = React.useRef(false);
119
120
  const windowBlurredRef = React.useRef(false);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext } from './field'\n\nconst inputVariants = cva(\n [\n 'flex w-full bg-background text-foreground placeholder:text-foreground/30',\n 'border transition-colors duration-micro outline-transparent',\n 'focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-background-muted',\n 'file:border-0 file:bg-transparent file:text-sm file:font-semibold',\n ].join(' '),\n {\n variants: {\n variant: {\n default: 'border-border-form hover:border-border-form-strong',\n filled: 'border-transparent bg-background-muted',\n },\n focusRing: {\n true: '',\n false: '',\n },\n size: {\n xs: 'h-9 px-3 text-sm', // 36px / 12px padding / 13px font (3.0:1)\n sm: 'h-10 px-3 text-md', // 40px / 12px padding / 14px font (3.3:1)\n default: 'h-11 px-4 text-base', // 44px / 16px padding / 16px font (2.75:1)\n lg: 'h-12 px-4 text-base', // 48px / 16px padding / 16px font (3.0:1)\n xl: 'h-14 px-4 text-base', // 56px / 16px padding / 16px font (3.5:1)\n },\n radius: {\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 state: {\n default: '',\n error: 'border-error hover:border-error focus:border-error shadow-[0_0_0_2px_var(--color-focus-ring-error)]',\n },\n },\n compoundVariants: [\n // focusRing: true → show custom focus ring\n { focusRing: true, className: 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)]' },\n // focusRing: false → keep same state as hover\n { variant: 'default', focusRing: false, className: 'focus:border-border-form-strong' },\n // filled + error\n {\n variant: 'filled',\n state: 'error',\n className: 'border-transparent hover:border-transparent focus:border-transparent bg-[var(--color-error-bg)] hover:bg-[var(--color-error-bg)] focus:bg-[var(--color-error-bg)] shadow-none',\n },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n state: 'default',\n focusRing: false,\n },\n }\n)\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>,\n VariantProps<typeof inputVariants> {\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n error?: boolean\n focusRing?: boolean\n}\n\n// Icon size for input (2-step scale)\n// xs~sm: 14px, default~xl: 16px\nconst iconSizeClasses = {\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// Icon padding (padding + icon + gap)\nconst iconPaddingClasses = {\n xs: { left: 'pl-8', right: 'pr-8' }, // 12px + 14px icon + 6px gap = 32px\n sm: { left: 'pl-9', right: 'pr-9' }, // 12px + 14px icon + 8px gap = 34px → 36px\n default: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n lg: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n xl: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n}\n\n// Icon position (matches horizontal padding)\nconst iconPositionClasses = {\n xs: { left: 'left-3', right: 'right-3' }, // 12px\n sm: { left: 'left-3', right: 'right-3' }, // 12px\n default: { left: 'left-4', right: 'right-4' }, // 16px\n lg: { left: 'left-4', right: 'right-4' }, // 16px\n xl: { left: 'left-4', right: 'right-4' }, // 16px\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, variant, size, radius, state, type, leftIcon, rightIcon, error, focusRing, id, onPointerDown, onFocus, onBlur, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedError = error ?? fieldContext?.error\n const resolvedState = resolvedError ? 'error' : state\n const inputId = id ?? fieldContext?.id\n const isDisabled = props.disabled ?? fieldContext?.disabled\n\n // Keyboard focus detection (when focusRing: false, auto-show ring on Tab navigation)\n const pointerRef = React.useRef(false)\n const windowBlurredRef = React.useRef(false)\n const [keyboardFocus, setKeyboardFocus] = React.useState(false)\n\n // Track window blur/focus to distinguish Tab navigation from window re-activation\n React.useEffect(() => {\n const onBlur = () => { windowBlurredRef.current = true }\n const onFocus = () => { requestAnimationFrame(() => { windowBlurredRef.current = false }) }\n window.addEventListener('blur', onBlur)\n window.addEventListener('focus', onFocus)\n return () => { window.removeEventListener('blur', onBlur); window.removeEventListener('focus', onFocus) }\n }, [])\n\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLInputElement>) => {\n pointerRef.current = true\n onPointerDown?.(e)\n }, [onPointerDown])\n\n const handleFocus = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n if (!pointerRef.current && !focusRing && !windowBlurredRef.current) {\n setKeyboardFocus(true)\n }\n pointerRef.current = false\n onFocus?.(e)\n }, [focusRing, onFocus])\n\n const handleBlur = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n setKeyboardFocus(false)\n pointerRef.current = false\n onBlur?.(e)\n }, [onBlur])\n\n // Build aria-describedby from context\n const ariaDescribedBy = fieldContext\n ? [\n resolvedError ? `${fieldContext.id}-error` : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n : undefined\n\n const focusHandlers = {\n onPointerDown: handlePointerDown,\n onFocus: handleFocus,\n onBlur: handleBlur,\n }\n\n // If icons are present, wrap input in a container\n if (leftIcon || rightIcon) {\n return (\n <div className=\"relative w-full\">\n {leftIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].left,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {leftIcon}\n </div>\n )}\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n leftIcon && iconPaddingClasses[resolvedSize].left,\n rightIcon && iconPaddingClasses[resolvedSize].right,\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n {rightIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].right,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {rightIcon}\n </div>\n )}\n </div>\n )\n }\n\n return (\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input, inputVariants }\n"],"mappings":";AAuKQ,SAEI,KAFJ;AArKR,YAAY,WAAW;AACvB,SAAS,WAA8B;AACvC,SAAS,UAAU;AACnB,SAAS,uBAAuB;AAEhC,MAAM,gBAAgB;AAAA,EACpB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,MACA,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA,MAAM;AAAA,QACJ,IAAI;AAAA;AAAA,QACJ,IAAI;AAAA;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,IAAI;AAAA;AAAA,QACJ,IAAI;AAAA;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB,EAAE,WAAW,MAAM,WAAW,2DAA2D;AAAA;AAAA,MAEzF,EAAE,SAAS,WAAW,WAAW,OAAO,WAAW,kCAAkC;AAAA;AAAA,MAErF;AAAA,QACE,SAAS;AAAA,QACT,OAAO;AAAA,QACP,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,WAAW;AAAA,IACb;AAAA,EACF;AACF;AAaA,MAAM,kBAAkB;AAAA,EACtB,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAGA,MAAM,qBAAqB;AAAA,EACzB,IAAI,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA;AAAA,EAClC,IAAI,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA;AAAA,EAClC,SAAS,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA;AAAA,EACzC,IAAI,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA;AAAA,EACpC,IAAI,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA;AACtC;AAGA,MAAM,sBAAsB;AAAA,EAC1B,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EACvC,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EACvC,SAAS,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EAC5C,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EACvC,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AACzC;AAEA,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,WAAW,SAAS,MAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,OAAO,WAAW,IAAI,eAAe,SAAS,QAAQ,GAAG,MAAM,GAAG,QAAQ;AAC/I,UAAM,eAAe,gBAAgB;AACrC,UAAM,eAAe,QAAQ;AAC7B,UAAM,gBAAgB,SAAS,cAAc;AAC7C,UAAM,gBAAgB,gBAAgB,UAAU;AAChD,UAAM,UAAU,MAAM,cAAc;AACpC,UAAM,aAAa,MAAM,YAAY,cAAc;AAGnD,UAAM,aAAa,MAAM,OAAO,KAAK;AACrC,UAAM,mBAAmB,MAAM,OAAO,KAAK;AAC3C,UAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAS,KAAK;AAG9D,UAAM,UAAU,MAAM;AACpB,YAAMA,UAAS,MAAM;AAAE,yBAAiB,UAAU;AAAA,MAAK;AACvD,YAAMC,WAAU,MAAM;AAAE,8BAAsB,MAAM;AAAE,2BAAiB,UAAU;AAAA,QAAM,CAAC;AAAA,MAAE;AAC1F,aAAO,iBAAiB,QAAQD,OAAM;AACtC,aAAO,iBAAiB,SAASC,QAAO;AACxC,aAAO,MAAM;AAAE,eAAO,oBAAoB,QAAQD,OAAM;AAAG,eAAO,oBAAoB,SAASC,QAAO;AAAA,MAAE;AAAA,IAC1G,GAAG,CAAC,CAAC;AAEL,UAAM,oBAAoB,MAAM,YAAY,CAAC,MAA4C;AACvF,iBAAW,UAAU;AACrB,sBAAgB,CAAC;AAAA,IACnB,GAAG,CAAC,aAAa,CAAC;AAElB,UAAM,cAAc,MAAM,YAAY,CAAC,MAA0C;AAC/E,UAAI,CAAC,WAAW,WAAW,CAAC,aAAa,CAAC,iBAAiB,SAAS;AAClE,yBAAiB,IAAI;AAAA,MACvB;AACA,iBAAW,UAAU;AACrB,gBAAU,CAAC;AAAA,IACb,GAAG,CAAC,WAAW,OAAO,CAAC;AAEvB,UAAM,aAAa,MAAM,YAAY,CAAC,MAA0C;AAC9E,uBAAiB,KAAK;AACtB,iBAAW,UAAU;AACrB,eAAS,CAAC;AAAA,IACZ,GAAG,CAAC,MAAM,CAAC;AAGX,UAAM,kBAAkB,eACpB;AAAA,MACE,gBAAgB,GAAG,aAAa,EAAE,WAAW;AAAA,IAC/C,EACG,OAAO,OAAO,EACd,KAAK,GAAG,KAAK,SAChB;AAEJ,UAAM,gBAAgB;AAAA,MACpB,eAAe;AAAA,MACf,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAGA,QAAI,YAAY,WAAW;AACzB,aACE,qBAAC,SAAI,WAAU,mBACZ;AAAA,oBACC,oBAAC,SAAI,WAAW;AAAA,UACd;AAAA,UACA,oBAAoB,YAAY,EAAE;AAAA,UAClC,WAAW,gBAAgB,YAAY,CAAC;AAAA,QAC1C,GACG,oBACH;AAAA,QAEF;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,IAAI;AAAA,YACJ,WAAW;AAAA,cACT,cAAc,EAAE,SAAS,MAAM,QAAQ,OAAO,eAAe,UAAU,CAAC;AAAA,cACxE,iBAAiB;AAAA,cACjB,YAAY,mBAAmB,YAAY,EAAE;AAAA,cAC7C,aAAa,mBAAmB,YAAY,EAAE;AAAA,cAC9C;AAAA,YACF;AAAA,YACA,gBAAc,iBAAiB;AAAA,YAC/B,oBAAkB;AAAA,YAClB,UAAU;AAAA,YACV;AAAA,YACC,GAAG;AAAA,YACH,GAAG;AAAA;AAAA,QACN;AAAA,QACC,aACC,oBAAC,SAAI,WAAW;AAAA,UACd;AAAA,UACA,oBAAoB,YAAY,EAAE;AAAA,UAClC,WAAW,gBAAgB,YAAY,CAAC;AAAA,QAC1C,GACG,qBACH;AAAA,SAEJ;AAAA,IAEJ;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,IAAI;AAAA,QACJ,WAAW;AAAA,UACT,cAAc,EAAE,SAAS,MAAM,QAAQ,OAAO,eAAe,UAAU,CAAC;AAAA,UACxE,iBAAiB;AAAA,UACjB;AAAA,QACF;AAAA,QACA,gBAAc,iBAAiB;AAAA,QAC/B,oBAAkB;AAAA,QAClB,UAAU;AAAA,QACV;AAAA,QACC,GAAG;AAAA,QACH,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AACA,MAAM,cAAc;","names":["onBlur","onFocus"]}
1
+ {"version":3,"sources":["../../../src/components/ui/input.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\nconst inputVariants = cva(\n [\n 'flex w-full bg-background text-foreground placeholder:text-foreground/30',\n 'border transition-colors duration-micro outline-transparent',\n 'focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-background-muted',\n 'file:border-0 file:bg-transparent file:text-sm file:font-semibold',\n ].join(' '),\n {\n variants: {\n variant: {\n default: 'border-border-form hover:border-border-form-strong',\n filled: 'border-transparent bg-background-muted',\n },\n focusRing: {\n true: '',\n false: '',\n },\n size: {\n xs: 'h-9 px-3 text-sm', // 36px / 12px padding / 13px font (3.0:1)\n sm: 'h-10 px-3 text-md', // 40px / 12px padding / 14px font (3.3:1)\n default: 'h-11 px-4 text-base', // 44px / 16px padding / 16px font (2.75:1)\n lg: 'h-12 px-4 text-base', // 48px / 16px padding / 16px font (3.0:1)\n xl: 'h-14 px-4 text-base', // 56px / 16px padding / 16px font (3.5:1)\n },\n radius: {\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 state: {\n default: '',\n error: 'border-error hover:border-error focus:border-error shadow-[0_0_0_2px_var(--color-focus-ring-error)]',\n },\n },\n compoundVariants: [\n // focusRing: true → show custom focus ring\n { focusRing: true, className: 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)]' },\n // focusRing: false → keep same state as hover\n { variant: 'default', focusRing: false, className: 'focus:border-border-form-strong' },\n // filled + error\n {\n variant: 'filled',\n state: 'error',\n className: 'border-transparent hover:border-transparent focus:border-transparent bg-[var(--color-error-bg)] hover:bg-[var(--color-error-bg)] focus:bg-[var(--color-error-bg)] shadow-none',\n },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n state: 'default',\n focusRing: false,\n },\n }\n)\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>,\n VariantProps<typeof inputVariants> {\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n error?: boolean\n focusRing?: boolean\n}\n\n// Icon size for input (2-step scale)\n// xs~sm: 14px, default~xl: 16px\nconst iconSizeClasses = {\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// Icon padding (padding + icon + gap)\nconst iconPaddingClasses = {\n xs: { left: 'pl-8', right: 'pr-8' }, // 12px + 14px icon + 6px gap = 32px\n sm: { left: 'pl-9', right: 'pr-9' }, // 12px + 14px icon + 8px gap = 34px → 36px\n default: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n lg: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n xl: { left: 'pl-10', right: 'pr-10' }, // 16px + 16px icon + 8px gap = 40px\n}\n\n// Icon position (matches horizontal padding)\nconst iconPositionClasses = {\n xs: { left: 'left-3', right: 'right-3' }, // 12px\n sm: { left: 'left-3', right: 'right-3' }, // 12px\n default: { left: 'left-4', right: 'right-4' }, // 16px\n lg: { left: 'left-4', right: 'right-4' }, // 16px\n xl: { left: 'left-4', right: 'right-4' }, // 16px\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, variant, size, radius, state, type, leftIcon, rightIcon, error, focusRing, id, onPointerDown, onFocus, onBlur, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedError = error ?? fieldContext?.error\n const resolvedState = resolvedError ? 'error' : state\n const inputId = id ?? fieldContext?.id\n useFieldControl('single', Boolean(fieldContext) && !id)\n const isDisabled = props.disabled ?? fieldContext?.disabled\n\n // Keyboard focus detection (when focusRing: false, auto-show ring on Tab navigation)\n const pointerRef = React.useRef(false)\n const windowBlurredRef = React.useRef(false)\n const [keyboardFocus, setKeyboardFocus] = React.useState(false)\n\n // Track window blur/focus to distinguish Tab navigation from window re-activation\n React.useEffect(() => {\n const onBlur = () => { windowBlurredRef.current = true }\n const onFocus = () => { requestAnimationFrame(() => { windowBlurredRef.current = false }) }\n window.addEventListener('blur', onBlur)\n window.addEventListener('focus', onFocus)\n return () => { window.removeEventListener('blur', onBlur); window.removeEventListener('focus', onFocus) }\n }, [])\n\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLInputElement>) => {\n pointerRef.current = true\n onPointerDown?.(e)\n }, [onPointerDown])\n\n const handleFocus = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n if (!pointerRef.current && !focusRing && !windowBlurredRef.current) {\n setKeyboardFocus(true)\n }\n pointerRef.current = false\n onFocus?.(e)\n }, [focusRing, onFocus])\n\n const handleBlur = React.useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n setKeyboardFocus(false)\n pointerRef.current = false\n onBlur?.(e)\n }, [onBlur])\n\n // Build aria-describedby from context\n const ariaDescribedBy = fieldContext\n ? [\n resolvedError ? `${fieldContext.id}-error` : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n : undefined\n\n const focusHandlers = {\n onPointerDown: handlePointerDown,\n onFocus: handleFocus,\n onBlur: handleBlur,\n }\n\n // If icons are present, wrap input in a container\n if (leftIcon || rightIcon) {\n return (\n <div className=\"relative w-full\">\n {leftIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].left,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {leftIcon}\n </div>\n )}\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n leftIcon && iconPaddingClasses[resolvedSize].left,\n rightIcon && iconPaddingClasses[resolvedSize].right,\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n {rightIcon && (\n <div className={cn(\n 'absolute top-1/2 -translate-y-1/2 pointer-events-none text-text-muted z-10',\n iconPositionClasses[resolvedSize].right,\n `[&>svg]:${iconSizeClasses[resolvedSize]}`\n )}>\n {rightIcon}\n </div>\n )}\n </div>\n )\n }\n\n return (\n <input\n type={type}\n id={inputId}\n className={cn(\n inputVariants({ variant, size, radius, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n {...focusHandlers}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input, inputVariants }\n"],"mappings":";AAwKQ,SAEI,KAFJ;AAtKR,YAAY,WAAW;AACvB,SAAS,WAA8B;AACvC,SAAS,UAAU;AACnB,SAAS,iBAAiB,uBAAuB;AAEjD,MAAM,gBAAgB;AAAA,EACpB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,MACA,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA,MAAM;AAAA,QACJ,IAAI;AAAA;AAAA,QACJ,IAAI;AAAA;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,IAAI;AAAA;AAAA,QACJ,IAAI;AAAA;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB,EAAE,WAAW,MAAM,WAAW,2DAA2D;AAAA;AAAA,MAEzF,EAAE,SAAS,WAAW,WAAW,OAAO,WAAW,kCAAkC;AAAA;AAAA,MAErF;AAAA,QACE,SAAS;AAAA,QACT,OAAO;AAAA,QACP,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,WAAW;AAAA,IACb;AAAA,EACF;AACF;AAaA,MAAM,kBAAkB;AAAA,EACtB,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAGA,MAAM,qBAAqB;AAAA,EACzB,IAAI,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA;AAAA,EAClC,IAAI,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA;AAAA,EAClC,SAAS,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA;AAAA,EACzC,IAAI,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA;AAAA,EACpC,IAAI,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA;AACtC;AAGA,MAAM,sBAAsB;AAAA,EAC1B,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EACvC,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EACvC,SAAS,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EAC5C,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AAAA,EACvC,IAAI,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA;AACzC;AAEA,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,WAAW,SAAS,MAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,OAAO,WAAW,IAAI,eAAe,SAAS,QAAQ,GAAG,MAAM,GAAG,QAAQ;AAC/I,UAAM,eAAe,gBAAgB;AACrC,UAAM,eAAe,QAAQ;AAC7B,UAAM,gBAAgB,SAAS,cAAc;AAC7C,UAAM,gBAAgB,gBAAgB,UAAU;AAChD,UAAM,UAAU,MAAM,cAAc;AACpC,oBAAgB,UAAU,QAAQ,YAAY,KAAK,CAAC,EAAE;AACtD,UAAM,aAAa,MAAM,YAAY,cAAc;AAGnD,UAAM,aAAa,MAAM,OAAO,KAAK;AACrC,UAAM,mBAAmB,MAAM,OAAO,KAAK;AAC3C,UAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAS,KAAK;AAG9D,UAAM,UAAU,MAAM;AACpB,YAAMA,UAAS,MAAM;AAAE,yBAAiB,UAAU;AAAA,MAAK;AACvD,YAAMC,WAAU,MAAM;AAAE,8BAAsB,MAAM;AAAE,2BAAiB,UAAU;AAAA,QAAM,CAAC;AAAA,MAAE;AAC1F,aAAO,iBAAiB,QAAQD,OAAM;AACtC,aAAO,iBAAiB,SAASC,QAAO;AACxC,aAAO,MAAM;AAAE,eAAO,oBAAoB,QAAQD,OAAM;AAAG,eAAO,oBAAoB,SAASC,QAAO;AAAA,MAAE;AAAA,IAC1G,GAAG,CAAC,CAAC;AAEL,UAAM,oBAAoB,MAAM,YAAY,CAAC,MAA4C;AACvF,iBAAW,UAAU;AACrB,sBAAgB,CAAC;AAAA,IACnB,GAAG,CAAC,aAAa,CAAC;AAElB,UAAM,cAAc,MAAM,YAAY,CAAC,MAA0C;AAC/E,UAAI,CAAC,WAAW,WAAW,CAAC,aAAa,CAAC,iBAAiB,SAAS;AAClE,yBAAiB,IAAI;AAAA,MACvB;AACA,iBAAW,UAAU;AACrB,gBAAU,CAAC;AAAA,IACb,GAAG,CAAC,WAAW,OAAO,CAAC;AAEvB,UAAM,aAAa,MAAM,YAAY,CAAC,MAA0C;AAC9E,uBAAiB,KAAK;AACtB,iBAAW,UAAU;AACrB,eAAS,CAAC;AAAA,IACZ,GAAG,CAAC,MAAM,CAAC;AAGX,UAAM,kBAAkB,eACpB;AAAA,MACE,gBAAgB,GAAG,aAAa,EAAE,WAAW;AAAA,IAC/C,EACG,OAAO,OAAO,EACd,KAAK,GAAG,KAAK,SAChB;AAEJ,UAAM,gBAAgB;AAAA,MACpB,eAAe;AAAA,MACf,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAGA,QAAI,YAAY,WAAW;AACzB,aACE,qBAAC,SAAI,WAAU,mBACZ;AAAA,oBACC,oBAAC,SAAI,WAAW;AAAA,UACd;AAAA,UACA,oBAAoB,YAAY,EAAE;AAAA,UAClC,WAAW,gBAAgB,YAAY,CAAC;AAAA,QAC1C,GACG,oBACH;AAAA,QAEF;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,IAAI;AAAA,YACJ,WAAW;AAAA,cACT,cAAc,EAAE,SAAS,MAAM,QAAQ,OAAO,eAAe,UAAU,CAAC;AAAA,cACxE,iBAAiB;AAAA,cACjB,YAAY,mBAAmB,YAAY,EAAE;AAAA,cAC7C,aAAa,mBAAmB,YAAY,EAAE;AAAA,cAC9C;AAAA,YACF;AAAA,YACA,gBAAc,iBAAiB;AAAA,YAC/B,oBAAkB;AAAA,YAClB,UAAU;AAAA,YACV;AAAA,YACC,GAAG;AAAA,YACH,GAAG;AAAA;AAAA,QACN;AAAA,QACC,aACC,oBAAC,SAAI,WAAW;AAAA,UACd;AAAA,UACA,oBAAoB,YAAY,EAAE;AAAA,UAClC,WAAW,gBAAgB,YAAY,CAAC;AAAA,QAC1C,GACG,qBACH;AAAA,SAEJ;AAAA,IAEJ;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,IAAI;AAAA,QACJ,WAAW;AAAA,UACT,cAAc,EAAE,SAAS,MAAM,QAAQ,OAAO,eAAe,UAAU,CAAC;AAAA,UACxE,iBAAiB;AAAA,UACjB;AAAA,QACF;AAAA,QACA,gBAAc,iBAAiB;AAAA,QAC/B,oBAAkB;AAAA,QAClB,UAAU;AAAA,QACV;AAAA,QACC,GAAG;AAAA,QACH,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AACA,MAAM,cAAc;","names":["onBlur","onFocus"]}