@karakuri-ui/react 0.3.4 → 0.3.6

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 (74) hide show
  1. package/dist/components/ui/accordion.mjs +1 -1
  2. package/dist/components/ui/alert.mjs +1 -1
  3. package/dist/components/ui/avatar.mjs +1 -1
  4. package/dist/components/ui/badge.mjs +1 -1
  5. package/dist/components/ui/breadcrumb.mjs +1 -1
  6. package/dist/components/ui/button-group.mjs +1 -1
  7. package/dist/components/ui/button.mjs +2 -2
  8. package/dist/components/ui/card.mjs +1 -1
  9. package/dist/components/ui/chart.mjs +1 -1
  10. package/dist/components/ui/checkbox.js +3 -1
  11. package/dist/components/ui/checkbox.js.map +1 -1
  12. package/dist/components/ui/checkbox.mjs +5 -3
  13. package/dist/components/ui/checkbox.mjs.map +1 -1
  14. package/dist/components/ui/divider.mjs +1 -1
  15. package/dist/components/ui/drawer.mjs +1 -1
  16. package/dist/components/ui/dropdown.mjs +1 -1
  17. package/dist/components/ui/field.d.mts +11 -1
  18. package/dist/components/ui/field.d.ts +11 -1
  19. package/dist/components/ui/field.js +37 -4
  20. package/dist/components/ui/field.js.map +1 -1
  21. package/dist/components/ui/field.mjs +36 -4
  22. package/dist/components/ui/field.mjs.map +1 -1
  23. package/dist/components/ui/icon-button.mjs +2 -2
  24. package/dist/components/ui/index.d.mts +1 -1
  25. package/dist/components/ui/index.d.ts +1 -1
  26. package/dist/components/ui/index.mjs +35 -35
  27. package/dist/components/ui/input.js +1 -0
  28. package/dist/components/ui/input.js.map +1 -1
  29. package/dist/components/ui/input.mjs +3 -2
  30. package/dist/components/ui/input.mjs.map +1 -1
  31. package/dist/components/ui/metric-card.mjs +1 -1
  32. package/dist/components/ui/modal.mjs +1 -1
  33. package/dist/components/ui/navigation-menu.js +30 -9
  34. package/dist/components/ui/navigation-menu.js.map +1 -1
  35. package/dist/components/ui/navigation-menu.mjs +31 -10
  36. package/dist/components/ui/navigation-menu.mjs.map +1 -1
  37. package/dist/components/ui/pagination.js +2 -2
  38. package/dist/components/ui/pagination.js.map +1 -1
  39. package/dist/components/ui/pagination.mjs +4 -4
  40. package/dist/components/ui/pagination.mjs.map +1 -1
  41. package/dist/components/ui/popover.mjs +1 -1
  42. package/dist/components/ui/progress.mjs +1 -1
  43. package/dist/components/ui/radio-group.js +3 -0
  44. package/dist/components/ui/radio-group.js.map +1 -1
  45. package/dist/components/ui/radio-group.mjs +5 -2
  46. package/dist/components/ui/radio-group.mjs.map +1 -1
  47. package/dist/components/ui/segmented.mjs +1 -1
  48. package/dist/components/ui/select.d.mts +1 -1
  49. package/dist/components/ui/select.d.ts +1 -1
  50. package/dist/components/ui/select.js +10 -2
  51. package/dist/components/ui/select.js.map +1 -1
  52. package/dist/components/ui/select.mjs +11 -3
  53. package/dist/components/ui/select.mjs.map +1 -1
  54. package/dist/components/ui/skeleton.mjs +1 -1
  55. package/dist/components/ui/slider.js +7 -1
  56. package/dist/components/ui/slider.js.map +1 -1
  57. package/dist/components/ui/slider.mjs +8 -2
  58. package/dist/components/ui/slider.mjs.map +1 -1
  59. package/dist/components/ui/spinner.mjs +1 -1
  60. package/dist/components/ui/switch.js +3 -1
  61. package/dist/components/ui/switch.js.map +1 -1
  62. package/dist/components/ui/switch.mjs +5 -3
  63. package/dist/components/ui/switch.mjs.map +1 -1
  64. package/dist/components/ui/table.mjs +1 -1
  65. package/dist/components/ui/tabs.mjs +1 -1
  66. package/dist/components/ui/textarea.js +1 -0
  67. package/dist/components/ui/textarea.js.map +1 -1
  68. package/dist/components/ui/textarea.mjs +3 -2
  69. package/dist/components/ui/textarea.mjs.map +1 -1
  70. package/dist/components/ui/toast.mjs +1 -1
  71. package/dist/components/ui/toggle-group.mjs +1 -1
  72. package/dist/components/ui/toggle.mjs +1 -1
  73. package/dist/components/ui/tooltip.mjs +1 -1
  74. package/package.json +1 -1
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
6
+ import { cn } from "../../lib/utils.mjs";
7
7
  const DefaultChevronIcon = ({ className }) => /* @__PURE__ */ jsx(
8
8
  "svg",
9
9
  {
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cva } from "class-variance-authority";
5
- import { cn } from "../../lib/utils";
5
+ import { cn } from "../../lib/utils.mjs";
6
6
  const InfoIcon = ({ className }) => /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
7
7
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
8
8
  /* @__PURE__ */ jsx("path", { d: "M12 16v-4" }),
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
6
+ import { cn } from "../../lib/utils.mjs";
7
7
  const avatarVariants = cva(
8
8
  "relative inline-flex items-center justify-center overflow-hidden bg-background-muted select-none",
9
9
  {
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Slot } from "@radix-ui/react-slot";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
6
+ import { cn } from "../../lib/utils.mjs";
7
7
  const colorMap = {
8
8
  default: {
9
9
  solid: "bg-foreground text-background",
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Slot } from "@radix-ui/react-slot";
5
- import { cn } from "../../lib/utils";
5
+ import { cn } from "../../lib/utils.mjs";
6
6
  const BreadcrumbContext = React.createContext({});
7
7
  const useBreadcrumbContext = () => React.useContext(BreadcrumbContext);
8
8
  function ChevronRightIcon({ className }) {
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { cn } from "../../lib/utils";
4
+ import { cn } from "../../lib/utils.mjs";
5
5
  const ButtonGroupContext = React.createContext(null);
6
6
  function useButtonGroup() {
7
7
  return React.useContext(ButtonGroupContext);
@@ -3,8 +3,8 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Slot } from "@radix-ui/react-slot";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
7
- import { useButtonGroup } from "./button-group";
6
+ import { cn } from "../../lib/utils.mjs";
7
+ import { useButtonGroup } from "./button-group.mjs";
8
8
  const solidColorMap = {
9
9
  default: "bg-foreground text-background hover:bg-foreground/90 active:bg-foreground/80",
10
10
  primary: "bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active",
@@ -3,7 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Slot } from "@radix-ui/react-slot";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
6
+ import { cn } from "../../lib/utils.mjs";
7
7
  const CardContext = React.createContext({
8
8
  size: "default",
9
9
  direction: "vertical"
@@ -2,7 +2,7 @@
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as RechartsPrimitive from "recharts";
5
- import { cn } from "../../lib/utils";
5
+ import { cn } from "../../lib/utils.mjs";
6
6
  const THEMES = { light: "", dark: ".dark" };
7
7
  const ChartContext = React.createContext(null);
8
8
  function useChart() {
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2GQ;AAzGR,YAAuB;AACvB,wBAAmC;AACnC,sCAAuC;AACvC,mBAAmB;AACnB,mBAAiD;AAGjD,MAAM,mBAAmB;AAAA,EACvB,SAAS;AAAA,EACT,SAAS;AACX;AAKA,MAAM,uBAAmB;AAAA,EACvB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,EACF,EAAE,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,IAAI;AAAA;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA;AAAA,QACN,IAAI;AAAA;AAAA,QACJ,IAAI;AAAA;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA;AAAA,QACN,MAAM;AAAA;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAGA,MAAM,iBAAiB;AAAA,EACrB,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AACN;AAGA,MAAM,aAAa;AAAA,EACjB,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AACN;AAGA,MAAM,WAAW;AAAA,EACf,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,IAAI;AACN;AAWA,MAAM,WAAW,MAAM,WAGrB,CAAC,EAAE,WAAW,MAAM,QAAQ,QAAQ,QAAQ,WAAW,OAAO,UAAU,IAAI,GAAG,MAAM,GAAG,QAAQ;AAChG,QAAM,mBAAe,8BAAgB;AACrC,QAAM,eAAe,QAAQ;AAC7B,QAAM,mBAAmB,YAAY,cAAc;AACnD,QAAM,cAAc,MAAM,MAAM;AAGhC,QAAM,cAAc,QAAQ,KAAK;AACjC,QAAM,aAAa,OAAO,cAAc,cAAc,cAAc,MAAM;AAC1E,oCAAgB,cAAc,UAAU,UAAU,QAAQ,YAAY,MAAM,eAAe,CAAC,GAAG;AAE/F,QAAM,WACJ;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC;AAAA,MACA,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,eAAW;AAAA,QACT,iBAAiB,EAAE,MAAM,QAAQ,OAAO,CAAC;AAAA,QACzC,iBAAiB,KAAK;AAAA,QACtB;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ,sDAAC,kBAAkB,WAAlB,EAA4B,WAAU,2DACrC,sDAAC,aAAU,WAAW,eAAe,YAAY,GAAG,GACtD;AAAA;AAAA,EACF;AAGF,MAAI,CAAC,MAAO,QAAO;AAEnB,SACE,6CAAC,SAAI,eAAW,iBAAG,2BAA2B,SAAS,YAAY,CAAC,GAClE;AAAA,gDAAC,SAAI,WAAU,qBACZ,oBACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,eAAW;AAAA,UACT,WAAW,YAAY;AAAA,UACvB;AAAA,UACA;AAAA,UACA,oBAAoB;AAAA,QACtB;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,KACF;AAEJ,CAAC;AACD,SAAS,cAAc;AAGvB,SAAS,UAAU,EAAE,UAAU,GAA2B;AACxD,SACE,4EAEE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,eAAW,iBAAG,WAAW,uCAAuC;AAAA,QAChE,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,QAAO;AAAA,QACP,aAAa;AAAA,QACb,eAAY;AAAA,QAEZ,sDAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kBAAiB;AAAA;AAAA,IACxE;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,eAAW,iBAAG,WAAW,6CAA6C;AAAA,QACtE,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,QAAO;AAAA,QACP,aAAa;AAAA,QACb,eAAY;AAAA,QAEZ,sDAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,YAAW;AAAA;AAAA,IAClE;AAAA,KACF;AAEJ;","names":[]}
@@ -3,8 +3,8 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
7
- import { useFieldContext } from "./field";
6
+ import { cn } from "../../lib/utils.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":[]}
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as SeparatorPrimitive from "@radix-ui/react-separator";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
6
+ import { cn } from "../../lib/utils.mjs";
7
7
  const dividerVariants = cva("shrink-0", {
8
8
  variants: {
9
9
  orientation: {
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as DialogPrimitive from "@radix-ui/react-dialog";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
6
+ import { cn } from "../../lib/utils.mjs";
7
7
  const DefaultCloseIcon = ({ className }) => /* @__PURE__ */ jsx(
8
8
  "svg",
9
9
  {
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
- import { cn } from "../../lib/utils";
5
+ import { cn } from "../../lib/utils.mjs";
6
6
  const contentRadiusMap = {
7
7
  md: "rounded-md",
8
8
  // 6px
@@ -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":[]}
@@ -2,11 +2,19 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cva } from "class-variance-authority";
5
- import { cn } from "../../lib/utils";
5
+ import { cn } from "../../lib/utils.mjs";
6
6
  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":"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","names":[]}
@@ -3,8 +3,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Slot } from "@radix-ui/react-slot";
5
5
  import { cva } from "class-variance-authority";
6
- import { cn } from "../../lib/utils";
7
- import { useButtonGroup } from "./button-group";
6
+ import { cn } from "../../lib/utils.mjs";
7
+ import { useButtonGroup } from "./button-group.mjs";
8
8
  const solidColorMap = {
9
9
  default: "bg-foreground text-background hover:bg-foreground/90 active:bg-foreground/80",
10
10
  primary: "bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active",
@@ -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';