@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.
- package/dist/components/ui/checkbox.js +3 -1
- package/dist/components/ui/checkbox.js.map +1 -1
- package/dist/components/ui/checkbox.mjs +4 -2
- package/dist/components/ui/checkbox.mjs.map +1 -1
- package/dist/components/ui/field.d.mts +11 -1
- package/dist/components/ui/field.d.ts +11 -1
- package/dist/components/ui/field.js +37 -4
- package/dist/components/ui/field.js.map +1 -1
- package/dist/components/ui/field.mjs +35 -3
- package/dist/components/ui/field.mjs.map +1 -1
- package/dist/components/ui/index.d.mts +1 -1
- package/dist/components/ui/index.d.ts +1 -1
- package/dist/components/ui/input.js +1 -0
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/input.mjs +2 -1
- package/dist/components/ui/input.mjs.map +1 -1
- package/dist/components/ui/navigation-menu.js +30 -9
- package/dist/components/ui/navigation-menu.js.map +1 -1
- package/dist/components/ui/navigation-menu.mjs +30 -9
- package/dist/components/ui/navigation-menu.mjs.map +1 -1
- package/dist/components/ui/pagination.js +2 -2
- package/dist/components/ui/pagination.js.map +1 -1
- package/dist/components/ui/pagination.mjs +3 -3
- package/dist/components/ui/pagination.mjs.map +1 -1
- package/dist/components/ui/radio-group.js +3 -0
- package/dist/components/ui/radio-group.js.map +1 -1
- package/dist/components/ui/radio-group.mjs +4 -1
- package/dist/components/ui/radio-group.mjs.map +1 -1
- package/dist/components/ui/select.d.mts +1 -1
- package/dist/components/ui/select.d.ts +1 -1
- package/dist/components/ui/select.js +10 -2
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/select.mjs +10 -2
- package/dist/components/ui/select.mjs.map +1 -1
- package/dist/components/ui/slider.js +7 -1
- package/dist/components/ui/slider.js.map +1 -1
- package/dist/components/ui/slider.mjs +7 -1
- package/dist/components/ui/slider.mjs.map +1 -1
- package/dist/components/ui/switch.js +3 -1
- package/dist/components/ui/switch.js.map +1 -1
- package/dist/components/ui/switch.mjs +4 -2
- package/dist/components/ui/switch.mjs.map +1 -1
- package/dist/components/ui/textarea.js +1 -0
- package/dist/components/ui/textarea.js.map +1 -1
- package/dist/components/ui/textarea.mjs +2 -1
- package/dist/components/ui/textarea.mjs.map +1 -1
- 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
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
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
|
|
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":";
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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":[]}
|
|
@@ -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":"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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"]}
|