@fabio.caffarello/react-design-system 3.13.0 → 4.1.0

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 (154) hide show
  1. package/dist/granular/ui/components/Autocomplete/Autocomplete.js +116 -88
  2. package/dist/granular/ui/components/Autocomplete/Autocomplete.js.map +1 -1
  3. package/dist/granular/ui/components/Autocomplete/AutocompleteList.js +57 -47
  4. package/dist/granular/ui/components/Autocomplete/AutocompleteList.js.map +1 -1
  5. package/dist/granular/ui/components/Autocomplete/AutocompleteOption.js +21 -20
  6. package/dist/granular/ui/components/Autocomplete/AutocompleteOption.js.map +1 -1
  7. package/dist/granular/ui/components/Breadcrumb/Breadcrumb.js.map +1 -1
  8. package/dist/granular/ui/components/ColorPicker/ColorPicker.js.map +1 -1
  9. package/dist/granular/ui/components/CommandPalette/CommandPalette.js +187 -149
  10. package/dist/granular/ui/components/CommandPalette/CommandPalette.js.map +1 -1
  11. package/dist/granular/ui/components/DataGrid/DataGrid.js +92 -92
  12. package/dist/granular/ui/components/DataGrid/DataGrid.js.map +1 -1
  13. package/dist/granular/ui/components/DatePicker/DatePickerCalendar.js +154 -139
  14. package/dist/granular/ui/components/DatePicker/DatePickerCalendar.js.map +1 -1
  15. package/dist/granular/ui/components/Dialog/AlertDialog.js +73 -40
  16. package/dist/granular/ui/components/Dialog/AlertDialog.js.map +1 -1
  17. package/dist/granular/ui/components/Dialog/DialogContent.js +54 -48
  18. package/dist/granular/ui/components/Dialog/DialogContent.js.map +1 -1
  19. package/dist/granular/ui/components/Dialog/DialogDescription.js +31 -31
  20. package/dist/granular/ui/components/Dialog/DialogDescription.js.map +1 -1
  21. package/dist/granular/ui/components/Dialog/DialogTitle.js +30 -30
  22. package/dist/granular/ui/components/Dialog/DialogTitle.js.map +1 -1
  23. package/dist/granular/ui/components/Drawer/Drawer.js.map +1 -1
  24. package/dist/granular/ui/components/Dropdown/Dropdown.js.map +1 -1
  25. package/dist/granular/ui/components/EmptyState/EmptyState.js.map +1 -1
  26. package/dist/granular/ui/components/FileUpload/FileUpload.js.map +1 -1
  27. package/dist/granular/ui/components/Form/Form.js +38 -37
  28. package/dist/granular/ui/components/Form/Form.js.map +1 -1
  29. package/dist/granular/ui/components/Form/FormField.js +28 -26
  30. package/dist/granular/ui/components/Form/FormField.js.map +1 -1
  31. package/dist/granular/ui/components/Header/Header.js.map +1 -1
  32. package/dist/granular/ui/components/Header/components/HeaderActions.js.map +1 -1
  33. package/dist/granular/ui/components/Header/components/HeaderHamburger.js.map +1 -1
  34. package/dist/granular/ui/components/Header/components/HeaderLogo.js.map +1 -1
  35. package/dist/granular/ui/components/Header/components/HeaderMobileMenu.js.map +1 -1
  36. package/dist/granular/ui/components/Header/components/HeaderNavigation.js.map +1 -1
  37. package/dist/granular/ui/components/Header/contexts/HeaderContext.js.map +1 -1
  38. package/dist/granular/ui/components/Menu/Menu.js.map +1 -1
  39. package/dist/granular/ui/components/Modal/Modal.js +98 -86
  40. package/dist/granular/ui/components/Modal/Modal.js.map +1 -1
  41. package/dist/granular/ui/components/MultiSelect/MultiSelect.js +122 -106
  42. package/dist/granular/ui/components/MultiSelect/MultiSelect.js.map +1 -1
  43. package/dist/granular/ui/components/Navigation/Navigation.js.map +1 -1
  44. package/dist/granular/ui/components/PageHeader/PageHeader.js.map +1 -1
  45. package/dist/granular/ui/components/Pagination/Pagination.js.map +1 -1
  46. package/dist/granular/ui/components/Popover/Popover.js.map +1 -1
  47. package/dist/granular/ui/components/Rating/Rating.js.map +1 -1
  48. package/dist/granular/ui/components/SearchInput/SearchInput.js.map +1 -1
  49. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarGroup.js +82 -64
  50. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarGroup.js.map +1 -1
  51. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarItem.js +30 -29
  52. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarItem.js.map +1 -1
  53. package/dist/granular/ui/components/SideNavbar/components/SideNavbarResizeHandle.js +37 -35
  54. package/dist/granular/ui/components/SideNavbar/components/SideNavbarResizeHandle.js.map +1 -1
  55. package/dist/granular/ui/components/SideNavbar/providers/SideNavbarStateProvider.js +57 -57
  56. package/dist/granular/ui/components/SideNavbar/providers/SideNavbarStateProvider.js.map +1 -1
  57. package/dist/granular/ui/components/Stepper/Stepper.js +102 -94
  58. package/dist/granular/ui/components/Stepper/Stepper.js.map +1 -1
  59. package/dist/granular/ui/components/Table/Table.js +41 -35
  60. package/dist/granular/ui/components/Table/Table.js.map +1 -1
  61. package/dist/granular/ui/components/Table/TableActions/TableActions.js.map +1 -1
  62. package/dist/granular/ui/components/Table/TableFilters/TableFilters.js +49 -46
  63. package/dist/granular/ui/components/Table/TableFilters/TableFilters.js.map +1 -1
  64. package/dist/granular/ui/components/Table/TablePagination/TablePagination.js.map +1 -1
  65. package/dist/granular/ui/components/Table/TableProvider.js +82 -80
  66. package/dist/granular/ui/components/Table/TableProvider.js.map +1 -1
  67. package/dist/granular/ui/components/Table/TableRow.js +57 -53
  68. package/dist/granular/ui/components/Table/TableRow.js.map +1 -1
  69. package/dist/granular/ui/components/Table/useColumnResizing.js +53 -53
  70. package/dist/granular/ui/components/Table/useColumnResizing.js.map +1 -1
  71. package/dist/granular/ui/components/TimePicker/TimePicker.js +149 -103
  72. package/dist/granular/ui/components/TimePicker/TimePicker.js.map +1 -1
  73. package/dist/granular/ui/components/Timeline/Timeline.js.map +1 -1
  74. package/dist/granular/ui/hooks/useFocusRestore.js +14 -15
  75. package/dist/granular/ui/hooks/useFocusRestore.js.map +1 -1
  76. package/dist/granular/ui/primitives/Badge/Badge.js.map +1 -1
  77. package/dist/granular/ui/primitives/Button/Button.js +86 -104
  78. package/dist/granular/ui/primitives/Button/Button.js.map +1 -1
  79. package/dist/granular/ui/primitives/Checkbox/Checkbox.js.map +1 -1
  80. package/dist/granular/ui/primitives/Chip/Chip.js +91 -71
  81. package/dist/granular/ui/primitives/Chip/Chip.js.map +1 -1
  82. package/dist/granular/ui/primitives/ErrorMessage/ErrorMessage.js.map +1 -1
  83. package/dist/granular/ui/primitives/Input/Input.js.map +1 -1
  84. package/dist/granular/ui/primitives/Label/Label.js.map +1 -1
  85. package/dist/granular/ui/primitives/NavLink/NavLink.js.map +1 -1
  86. package/dist/granular/ui/primitives/Radio/Radio.js.map +1 -1
  87. package/dist/granular/ui/primitives/Select/Select.js.map +1 -1
  88. package/dist/granular/ui/primitives/Separator/Separator.js.map +1 -1
  89. package/dist/granular/ui/primitives/Skeleton/Skeleton.js.map +1 -1
  90. package/dist/granular/ui/primitives/Slider/Slider.js.map +1 -1
  91. package/dist/granular/ui/primitives/Spinner/Spinner.js.map +1 -1
  92. package/dist/granular/ui/primitives/Switch/Switch.js.map +1 -1
  93. package/dist/granular/ui/primitives/Tooltip/Tooltip.js.map +1 -1
  94. package/dist/granular/ui/providers/DialogContext.js.map +1 -1
  95. package/dist/granular/ui/providers/DialogProvider.js +24 -20
  96. package/dist/granular/ui/providers/DialogProvider.js.map +1 -1
  97. package/dist/index.cjs +144 -144
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.js +5896 -5609
  100. package/dist/index.js.map +1 -1
  101. package/dist/react-design-system.css +1 -1
  102. package/dist/server/index.cjs +13 -13
  103. package/dist/server/index.cjs.map +1 -1
  104. package/dist/server/index.js +1050 -789
  105. package/dist/server/index.js.map +1 -1
  106. package/dist/ui/components/Autocomplete/Autocomplete.d.ts +21 -0
  107. package/dist/ui/components/Autocomplete/AutocompleteList.d.ts +4 -0
  108. package/dist/ui/components/Autocomplete/AutocompleteOption.d.ts +8 -0
  109. package/dist/ui/components/Breadcrumb/Breadcrumb.d.ts +0 -1
  110. package/dist/ui/components/ColorPicker/ColorPicker.d.ts +0 -1
  111. package/dist/ui/components/CommandPalette/CommandPalette.d.ts +0 -1
  112. package/dist/ui/components/DataGrid/DataGrid.d.ts +0 -1
  113. package/dist/ui/components/Dialog/DialogContent.d.ts +20 -1
  114. package/dist/ui/components/Drawer/Drawer.d.ts +0 -1
  115. package/dist/ui/components/Dropdown/Dropdown.d.ts +0 -1
  116. package/dist/ui/components/EmptyState/EmptyState.d.ts +0 -1
  117. package/dist/ui/components/FileUpload/FileUpload.d.ts +0 -1
  118. package/dist/ui/components/Form/FormField.d.ts +7 -0
  119. package/dist/ui/components/Header/Header.d.ts +1 -1
  120. package/dist/ui/components/Header/components/HeaderActions.d.ts +1 -1
  121. package/dist/ui/components/Header/components/HeaderHamburger.d.ts +1 -1
  122. package/dist/ui/components/Header/components/HeaderLogo.d.ts +1 -1
  123. package/dist/ui/components/Header/components/HeaderMobileMenu.d.ts +1 -1
  124. package/dist/ui/components/Header/components/HeaderNavigation.d.ts +1 -1
  125. package/dist/ui/components/Header/contexts/HeaderContext.d.ts +1 -1
  126. package/dist/ui/components/Menu/Menu.d.ts +0 -1
  127. package/dist/ui/components/Modal/Modal.d.ts +1 -2
  128. package/dist/ui/components/Navigation/Navigation.d.ts +1 -1
  129. package/dist/ui/components/PageHeader/PageHeader.d.ts +1 -1
  130. package/dist/ui/components/Pagination/Pagination.d.ts +0 -1
  131. package/dist/ui/components/Popover/Popover.d.ts +0 -1
  132. package/dist/ui/components/Rating/Rating.d.ts +0 -1
  133. package/dist/ui/components/SearchInput/SearchInput.d.ts +0 -1
  134. package/dist/ui/components/Stepper/Stepper.d.ts +0 -1
  135. package/dist/ui/components/Table/TableActions/TableActions.d.ts +0 -1
  136. package/dist/ui/components/Table/TableFilters/TableFilters.d.ts +0 -1
  137. package/dist/ui/components/Table/TablePagination/TablePagination.d.ts +0 -1
  138. package/dist/ui/components/TimePicker/TimePicker.d.ts +0 -1
  139. package/dist/ui/components/Timeline/Timeline.d.ts +0 -1
  140. package/dist/ui/primitives/Checkbox/Checkbox.d.ts +0 -1
  141. package/dist/ui/primitives/Chip/Chip.d.ts +21 -0
  142. package/dist/ui/primitives/ErrorMessage/ErrorMessage.d.ts +0 -1
  143. package/dist/ui/primitives/Input/Input.d.ts +0 -1
  144. package/dist/ui/primitives/Label/Label.d.ts +0 -1
  145. package/dist/ui/primitives/NavLink/NavLink.d.ts +1 -1
  146. package/dist/ui/primitives/Radio/Radio.d.ts +0 -1
  147. package/dist/ui/primitives/Select/Select.d.ts +0 -1
  148. package/dist/ui/primitives/Skeleton/Skeleton.d.ts +0 -1
  149. package/dist/ui/primitives/Slider/Slider.d.ts +0 -1
  150. package/dist/ui/primitives/Switch/Switch.d.ts +0 -1
  151. package/dist/ui/primitives/Tooltip/Tooltip.d.ts +0 -1
  152. package/dist/ui/providers/DialogContext.d.ts +8 -0
  153. package/dist/ui/server.d.ts +2 -0
  154. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.js","sources":["../../../../../src/ui/primitives/Checkbox/Checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useRef,\n useEffect,\n forwardRef,\n memo,\n useId,\n useMemo,\n useCallback,\n} from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { getTypographyClasses } from \"../../tokens/typography\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn } from \"../../utils\";\n\nexport interface CheckboxProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\"\n> {\n label?: ReactNode;\n error?: boolean;\n /**\n * Validation success state — paints the border and (when\n * `helperText` is also set) the helper-text color green. Matches\n * the Input + Select + Radio + Switch + Textarea convention; the\n * three feedback flags (`error`, `success`, `helperText`) cover\n * every form primitive in the DS. Error takes precedence when\n * both `error` and `success` are set.\n */\n success?: boolean;\n helperText?: string;\n indeterminate?: boolean;\n}\n\n/**\n * Checkbox Component\n *\n * A styled checkbox input component.\n * Follows Atomic Design principles as an Atom component.\n * Uses Composite Pattern when combined with Label and ErrorMessage.\n *\n * @example\n * ```tsx\n * <Checkbox\n * id=\"terms\"\n * label=\"I agree to the terms\"\n * checked={checked}\n * onChange={handleChange}\n * />\n * ```\n */\nconst Checkbox = memo(\n forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n {\n id,\n label,\n error = false,\n success = false,\n helperText,\n className = \"\",\n disabled = false,\n indeterminate = false,\n ...props\n },\n ref,\n ) {\n // Stable fallback id when the consumer doesn't provide one. useId\n // is SSR-safe and stable across renders, replacing the deprecated\n // Math.random().substr() pattern.\n const reactId = useId();\n const checkboxId = id || `checkbox-${reactId}`;\n\n const errorId = useMemo(\n () => (error ? `${checkboxId}-error` : undefined),\n [error, checkboxId],\n );\n\n const helperId = useMemo(\n () => (helperText ? `${checkboxId}-helper` : undefined),\n [helperText, checkboxId],\n );\n\n // Memoize focus ring colors\n const primaryFocusRing = useMemo(() => \"focus:border-line-focus\", []);\n\n const errorFocusRing = useMemo(() => \"focus:border-error\", []);\n\n const focusRingColor = useMemo(\n () =>\n error\n ? errorFocusRing.replace(\"focus:border-\", \"focus:ring-\")\n : primaryFocusRing.replace(\"focus:border-\", \"focus:ring-\"),\n [error, errorFocusRing, primaryFocusRing],\n );\n\n // Memoize classes — error wins over success when both flags are\n // set (a field cannot be valid AND invalid; treat it as invalid).\n const checkboxClasses = useMemo(\n () =>\n cn(\n \"h-4\",\n \"w-4\",\n getRadiusClass(\"sm\"),\n \"border\",\n \"border-line-default\",\n \"text-fg-brand\",\n \"focus:ring-2\",\n focusRingColor,\n \"focus:ring-offset-2\",\n \"disabled:opacity-50\",\n \"disabled:cursor-not-allowed\",\n \"cursor-pointer\",\n error && \"border-error\",\n !error && success && \"border-success\",\n className,\n ),\n [focusRingColor, error, success, className],\n );\n\n const labelClasses = useMemo(\n () =>\n cn(\n getTypographyClasses(\"label\"),\n getSpacingClass(\"sm\", \"ml\"),\n disabled ? \"opacity-50 cursor-not-allowed\" : \"cursor-pointer\",\n ),\n [disabled],\n );\n\n // Set indeterminate state via ref\n const internalRef = useRef<HTMLInputElement>(null);\n\n // Memoize callback ref\n const setRef = useCallback(\n (element: HTMLInputElement | null) => {\n internalRef.current = element;\n\n // Handle forwarded ref (can be function or object)\n if (typeof ref === \"function\") {\n ref(element);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current =\n element;\n }\n\n // Set indeterminate state\n if (element) {\n element.indeterminate = indeterminate;\n }\n },\n [ref, indeterminate],\n );\n\n useEffect(() => {\n if (internalRef.current) {\n internalRef.current.indeterminate = indeterminate;\n }\n }, [indeterminate]);\n\n return (\n <div className={cn(\"flex\", \"flex-col\", getSpacingClass(\"sm\", \"my\"))}>\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n id={checkboxId}\n ref={setRef}\n className={checkboxClasses}\n disabled={disabled}\n aria-invalid={error}\n aria-describedby={errorId || helperId || undefined}\n aria-label={!label ? \"Checkbox\" : undefined}\n {...props}\n />\n {label && (\n <label htmlFor={checkboxId} className={labelClasses}>\n {label}\n </label>\n )}\n </div>\n {(error || success || helperText) && (\n <div\n id={errorId || helperId}\n className={cn(\n getSpacingClass(\"xs\", \"mt\"),\n getTypographyClasses(\"caption\"),\n error\n ? \"text-fg-error\"\n : success\n ? \"text-fg-success\"\n : \"text-fg-secondary\",\n )}\n role={error || success ? \"alert\" : undefined}\n >\n {error ? helperText || \"This field has an error\" : helperText}\n </div>\n )}\n </div>\n );\n }),\n);\n\nCheckbox.displayName = \"Checkbox\";\n\nexport default Checkbox;\n"],"names":["Checkbox","memo","forwardRef","_a","ref","_b","id","label","error","success","helperText","className","disabled","indeterminate","props","__objRest","reactId","useId","checkboxId","errorId","useMemo","helperId","primaryFocusRing","errorFocusRing","focusRingColor","checkboxClasses","cn","getRadiusClass","labelClasses","getTypographyClasses","getSpacingClass","internalRef","useRef","setRef","useCallback","element","useEffect","jsxs","jsx","__spreadValues"],"mappings":"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"}
1
+ {"version":3,"file":"Checkbox.js","sources":["../../../../../src/ui/primitives/Checkbox/Checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useRef,\n useEffect,\n forwardRef,\n memo,\n useId,\n useMemo,\n useCallback,\n} from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { getTypographyClasses } from \"../../tokens/typography\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn } from \"../../utils\";\n\nexport interface CheckboxProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\"\n> {\n label?: ReactNode;\n error?: boolean;\n /**\n * Validation success state — paints the border and (when\n * `helperText` is also set) the helper-text color green. Matches\n * the Input + Select + Radio + Switch + Textarea convention; the\n * three feedback flags (`error`, `success`, `helperText`) cover\n * every form primitive in the DS. Error takes precedence when\n * both `error` and `success` are set.\n */\n success?: boolean;\n helperText?: string;\n indeterminate?: boolean;\n}\n\n/**\n * Checkbox Component\n *\n * A styled checkbox input component.\n * Uses Composite Pattern when combined with Label and ErrorMessage.\n *\n * @example\n * ```tsx\n * <Checkbox\n * id=\"terms\"\n * label=\"I agree to the terms\"\n * checked={checked}\n * onChange={handleChange}\n * />\n * ```\n */\nconst Checkbox = memo(\n forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n {\n id,\n label,\n error = false,\n success = false,\n helperText,\n className = \"\",\n disabled = false,\n indeterminate = false,\n ...props\n },\n ref,\n ) {\n // Stable fallback id when the consumer doesn't provide one. useId\n // is SSR-safe and stable across renders, replacing the deprecated\n // Math.random().substr() pattern.\n const reactId = useId();\n const checkboxId = id || `checkbox-${reactId}`;\n\n const errorId = useMemo(\n () => (error ? `${checkboxId}-error` : undefined),\n [error, checkboxId],\n );\n\n const helperId = useMemo(\n () => (helperText ? `${checkboxId}-helper` : undefined),\n [helperText, checkboxId],\n );\n\n // Memoize focus ring colors\n const primaryFocusRing = useMemo(() => \"focus:border-line-focus\", []);\n\n const errorFocusRing = useMemo(() => \"focus:border-error\", []);\n\n const focusRingColor = useMemo(\n () =>\n error\n ? errorFocusRing.replace(\"focus:border-\", \"focus:ring-\")\n : primaryFocusRing.replace(\"focus:border-\", \"focus:ring-\"),\n [error, errorFocusRing, primaryFocusRing],\n );\n\n // Memoize classes — error wins over success when both flags are\n // set (a field cannot be valid AND invalid; treat it as invalid).\n const checkboxClasses = useMemo(\n () =>\n cn(\n \"h-4\",\n \"w-4\",\n getRadiusClass(\"sm\"),\n \"border\",\n \"border-line-default\",\n \"text-fg-brand\",\n \"focus:ring-2\",\n focusRingColor,\n \"focus:ring-offset-2\",\n \"disabled:opacity-50\",\n \"disabled:cursor-not-allowed\",\n \"cursor-pointer\",\n error && \"border-error\",\n !error && success && \"border-success\",\n className,\n ),\n [focusRingColor, error, success, className],\n );\n\n const labelClasses = useMemo(\n () =>\n cn(\n getTypographyClasses(\"label\"),\n getSpacingClass(\"sm\", \"ml\"),\n disabled ? \"opacity-50 cursor-not-allowed\" : \"cursor-pointer\",\n ),\n [disabled],\n );\n\n // Set indeterminate state via ref\n const internalRef = useRef<HTMLInputElement>(null);\n\n // Memoize callback ref\n const setRef = useCallback(\n (element: HTMLInputElement | null) => {\n internalRef.current = element;\n\n // Handle forwarded ref (can be function or object)\n if (typeof ref === \"function\") {\n ref(element);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current =\n element;\n }\n\n // Set indeterminate state\n if (element) {\n element.indeterminate = indeterminate;\n }\n },\n [ref, indeterminate],\n );\n\n useEffect(() => {\n if (internalRef.current) {\n internalRef.current.indeterminate = indeterminate;\n }\n }, [indeterminate]);\n\n return (\n <div className={cn(\"flex\", \"flex-col\", getSpacingClass(\"sm\", \"my\"))}>\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n id={checkboxId}\n ref={setRef}\n className={checkboxClasses}\n disabled={disabled}\n aria-invalid={error}\n aria-describedby={errorId || helperId || undefined}\n aria-label={!label ? \"Checkbox\" : undefined}\n {...props}\n />\n {label && (\n <label htmlFor={checkboxId} className={labelClasses}>\n {label}\n </label>\n )}\n </div>\n {(error || success || helperText) && (\n <div\n id={errorId || helperId}\n className={cn(\n getSpacingClass(\"xs\", \"mt\"),\n getTypographyClasses(\"caption\"),\n error\n ? \"text-fg-error\"\n : success\n ? \"text-fg-success\"\n : \"text-fg-secondary\",\n )}\n role={error || success ? \"alert\" : undefined}\n >\n {error ? helperText || \"This field has an error\" : helperText}\n </div>\n )}\n </div>\n );\n }),\n);\n\nCheckbox.displayName = \"Checkbox\";\n\nexport default Checkbox;\n"],"names":["Checkbox","memo","forwardRef","_a","ref","_b","id","label","error","success","helperText","className","disabled","indeterminate","props","__objRest","reactId","useId","checkboxId","errorId","useMemo","helperId","primaryFocusRing","errorFocusRing","focusRingColor","checkboxClasses","cn","getRadiusClass","labelClasses","getTypographyClasses","getSpacingClass","internalRef","useRef","setRef","useCallback","element","useEffect","jsxs","jsx","__spreadValues"],"mappings":"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"}
@@ -1,21 +1,21 @@
1
1
  "use client";
2
- import { jsx as n, jsxs as L } from "react/jsx-runtime";
3
- import { forwardRef as z } from "react";
4
- import { X as R } from "lucide-react";
5
- import { Slot as S } from "@radix-ui/react-slot";
6
- import { getRadiusClass as u } from "../../tokens/radius.js";
7
- import { getSpacingClass as r } from "../../tokens/spacing.js";
8
- import { getTypographySize as c } from "../../tokens/typography.js";
2
+ import { jsx as n, jsxs as k } from "react/jsx-runtime";
3
+ import { forwardRef as B } from "react";
4
+ import { X as D } from "lucide-react";
5
+ import { Slot as I } from "@radix-ui/react-slot";
6
+ import { getRadiusClass as c } from "../../tokens/radius.js";
7
+ import { getSpacingClass as t } from "../../tokens/spacing.js";
8
+ import { getTypographyWeight as V, getTypographySize as f } from "../../tokens/typography.js";
9
9
  import { cn as e } from "../../utils/cn.js";
10
- import { cva as j } from "../../utils/cva.js";
11
- const h = j(
10
+ import { cva as $ } from "../../utils/cva.js";
11
+ const N = $(
12
12
  // Base classes
13
13
  e(
14
14
  "inline-flex",
15
15
  "items-center",
16
16
  "font-medium",
17
- u("full"),
18
- r("xs", "gap")
17
+ c("full"),
18
+ t("xs", "gap")
19
19
  ),
20
20
  {
21
21
  variants: {
@@ -41,19 +41,19 @@ const h = j(
41
41
  },
42
42
  size: {
43
43
  sm: e(
44
- r("xs", "px"),
45
- r("xs", "py"),
46
- c("caption")
44
+ t("xs", "px"),
45
+ t("xs", "py"),
46
+ f("caption")
47
47
  ),
48
48
  md: e(
49
- r("sm", "px"),
50
- r("xs", "py"),
51
- c("bodySmall")
49
+ t("sm", "px"),
50
+ t("xs", "py"),
51
+ f("bodySmall")
52
52
  ),
53
53
  lg: e(
54
- r("md", "px"),
55
- r("sm", "py"),
56
- c("body")
54
+ t("md", "px"),
55
+ t("sm", "py"),
56
+ f("body")
57
57
  )
58
58
  },
59
59
  selected: {
@@ -97,70 +97,89 @@ const h = j(
97
97
  disabled: !1
98
98
  }
99
99
  }
100
- ), k = z(function(p, b) {
100
+ ), A = B(function(v, x) {
101
101
  const {
102
- children: a,
103
- variant: m = "default",
104
- size: g = "md",
105
- selected: l = !1,
102
+ children: r,
103
+ variant: u = "default",
104
+ size: h = "md",
105
+ selected: o = !1,
106
106
  disabled: s = !1,
107
- className: v = "",
108
- "aria-label": o,
109
- tabIndex: d,
110
- asChild: C = !1
111
- } = p, x = (() => {
112
- if (o) return o;
113
- if (typeof a == "string") return a;
114
- if (typeof a == "object" && a !== null && "props" in a) {
115
- const t = a.props;
116
- if (t != null && t.children && typeof t.children == "string")
117
- return t.children;
107
+ className: y = "",
108
+ "aria-label": l,
109
+ tabIndex: p,
110
+ asChild: w = !1
111
+ } = v, d = (() => {
112
+ if (l) return l;
113
+ if (typeof r == "string") return r;
114
+ if (typeof r == "object" && r !== null && "props" in r) {
115
+ const a = r.props;
116
+ if (a != null && a.children && typeof a.children == "string")
117
+ return a.children;
118
118
  }
119
119
  })();
120
- if (C)
120
+ if (w)
121
121
  return /* @__PURE__ */ n(
122
- S,
122
+ I,
123
123
  {
124
- ref: b,
124
+ ref: x,
125
125
  className: e(
126
- h({ variant: m, size: g, selected: l, disabled: s }),
127
- v
126
+ N({ variant: u, size: h, selected: o, disabled: s }),
127
+ y
128
128
  ),
129
- "aria-label": o,
129
+ "aria-label": l,
130
130
  "aria-disabled": s || void 0,
131
- tabIndex: d,
132
- children: a
131
+ tabIndex: p,
132
+ children: r
133
133
  }
134
134
  );
135
- const { onRemove: f, onClick: i } = p, y = i !== void 0, N = y && !s, w = (t) => {
136
- s || (t.key === "Enter" || t.key === " ") && (t.preventDefault(), i == null || i());
137
- };
138
- return /* @__PURE__ */ L(
135
+ const { onRemove: b, onClick: i, count: m } = v, g = i !== void 0, L = g && !s, j = (a) => {
136
+ s || (a.key === "Enter" || a.key === " ") && (a.preventDefault(), i == null || i());
137
+ }, C = m !== void 0, z = o || u === "filled", R = C ? /* @__PURE__ */ n(
138
+ "span",
139
+ {
140
+ "aria-hidden": g || void 0,
141
+ className: e(
142
+ "inline-flex",
143
+ "items-center",
144
+ "justify-center",
145
+ "tabular-nums",
146
+ "leading-none",
147
+ c("full"),
148
+ t("xs", "px"),
149
+ t("0.5", "py"),
150
+ f("caption"),
151
+ V("label"),
152
+ z ? e("bg-surface-base", "text-fg-brand-emphasis") : e("bg-surface-brand-strong", "text-fg-inverse")
153
+ ),
154
+ children: m
155
+ }
156
+ ) : null, S = C && d !== void 0 ? `${d}, ${m}` : d;
157
+ return /* @__PURE__ */ k(
139
158
  "div",
140
159
  {
141
- ref: b,
160
+ ref: x,
142
161
  className: e(
143
- h({ variant: m, size: g, selected: l, disabled: s }),
144
- f && r("xs", "pr"),
145
- v
162
+ N({ variant: u, size: h, selected: o, disabled: s }),
163
+ b && t("xs", "pr"),
164
+ y
146
165
  ),
147
166
  "aria-disabled": s,
148
167
  children: [
149
- y ? /* @__PURE__ */ n(
168
+ g ? /* @__PURE__ */ n(
150
169
  "button",
151
170
  {
152
171
  type: "button",
153
172
  onClick: s ? void 0 : i,
154
- onKeyDown: w,
173
+ onKeyDown: j,
155
174
  disabled: s,
156
- "aria-pressed": l ? !0 : void 0,
157
- "aria-label": o || x,
158
- tabIndex: d !== void 0 ? d : N ? 0 : void 0,
175
+ "aria-pressed": o ? !0 : void 0,
176
+ "aria-label": l || S,
177
+ tabIndex: p !== void 0 ? p : L ? 0 : void 0,
159
178
  className: e(
160
179
  "flex-1",
161
180
  "bg-transparent",
162
181
  "border-0",
163
- r("none", "p"),
182
+ t("none", "p"),
164
183
  "text-inherit",
165
184
  "text-left",
166
185
  "cursor-pointer",
@@ -168,39 +187,40 @@ const h = j(
168
187
  "focus:ring-2",
169
188
  "focus:ring-line-focus",
170
189
  "focus:ring-offset-2",
171
- u("full")
190
+ c("full")
172
191
  ),
173
- children: a
192
+ children: r
174
193
  }
175
- ) : /* @__PURE__ */ n("span", { children: a }),
176
- f && !s && /* @__PURE__ */ n(
194
+ ) : /* @__PURE__ */ n("span", { children: r }),
195
+ R,
196
+ b && !s && /* @__PURE__ */ n(
177
197
  "button",
178
198
  {
179
199
  type: "button",
180
- onClick: (t) => {
181
- t.stopPropagation(), f();
200
+ onClick: (a) => {
201
+ a.stopPropagation(), b();
182
202
  },
183
203
  className: e(
184
- r("xs", "ml"),
204
+ t("xs", "ml"),
185
205
  "hover:bg-tint-hover",
186
- u("full"),
187
- r("xs", "p"),
206
+ c("full"),
207
+ t("xs", "p"),
188
208
  "transition-colors",
189
209
  "focus:outline-none",
190
210
  "focus:ring-2",
191
211
  "focus:ring-line-focus",
192
212
  "focus:ring-offset-1"
193
213
  ),
194
- "aria-label": `Remove ${x || "chip"}`,
195
- children: /* @__PURE__ */ n(R, { className: "h-3 w-3", "aria-hidden": "true" })
214
+ "aria-label": `Remove ${d || "chip"}`,
215
+ children: /* @__PURE__ */ n(D, { className: "h-3 w-3", "aria-hidden": "true" })
196
216
  }
197
217
  )
198
218
  ]
199
219
  }
200
220
  );
201
221
  });
202
- k.displayName = "Chip";
222
+ A.displayName = "Chip";
203
223
  export {
204
- k as default
224
+ A as default
205
225
  };
206
226
  //# sourceMappingURL=Chip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Chip.js","sources":["../../../../../src/ui/primitives/Chip/Chip.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef, type ReactNode } from \"react\";\nimport { X } from \"lucide-react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { getTypographySize } from \"../../tokens/typography\";\nimport { cn, cva } from \"../../utils\";\n\nexport type ChipVariant = \"default\" | \"outlined\" | \"filled\";\nexport type ChipSize = \"sm\" | \"md\" | \"lg\";\n\ninterface ChipBaseProps {\n children: ReactNode;\n variant?: ChipVariant;\n size?: ChipSize;\n selected?: boolean;\n disabled?: boolean;\n className?: string;\n \"aria-label\"?: string;\n tabIndex?: number;\n}\n\ninterface ChipStandardProps extends ChipBaseProps {\n asChild?: false;\n onRemove?: () => void;\n onClick?: () => void;\n}\n\n/**\n * `asChild` collapses the chip into a single node provided by the\n * consumer (typically `<Link>`). The non-interactive frame + inner\n * label-button + X structure is intentionally NOT rendered — the child\n * IS the chip. As a consequence:\n *\n * - `onClick` and `onRemove` are forbidden at the type level. The\n * child's own click handler (and `href`) is what fires; consumers\n * who need a removable selected filter use the standard\n * (non-asChild) form.\n * - `selected` still applies the visual classes via `chipVariants`,\n * but NO `aria-pressed` is emitted. Toggle-button semantics on\n * `<a>` would lie — a link isn't a two-state control. Consumers\n * that need the selected route surfaced to AT users should pass\n * `aria-current=\"page\"` (or similar) directly on the child Link.\n *\n * @see `.claude/rules/components.md` and the inline a11y notes below.\n */\ninterface ChipAsChildProps extends ChipBaseProps {\n asChild: true;\n /**\n * `onClick` is forbidden when `asChild` is true — the child element\n * owns interaction. Pass the handler (or `href`) on the child.\n */\n onClick?: never;\n /**\n * `onRemove` is forbidden when `asChild` is true — the collapsed\n * node has no slot for an X button. Use the standard (non-asChild)\n * form when removal is required.\n */\n onRemove?: never;\n}\n\nexport type ChipProps = ChipStandardProps | ChipAsChildProps;\n\n/**\n * Chip Component\n *\n * A chip/tag for labels, filters, or selected items.\n *\n * Standard form: an outer `<div>` frame (never interactive) with an\n * inner `<button>` label (when `onClick`) and a sibling X `<button>`\n * (when `onRemove`). This shape closes two axe violations the older\n * implementation hit — `aria-required-parent` (role=option without a\n * listbox) and `nested-interactive` (clickable outer + clickable X).\n *\n * `asChild` form: a single node provided by the consumer (e.g.\n * `<Link>`), with the chip's classes projected via Radix `Slot`. See\n * the `ChipAsChildProps` JSDoc for the a11y responsibility transfer\n * — the consumer's child carries `href`, focus behavior, and any\n * route-state ARIA (`aria-current`). Forbidden in this form:\n * `onClick`, `onRemove` (TS-level).\n *\n * @example\n * ```tsx\n * <Chip>Tag</Chip>\n * <Chip onRemove={() => console.log('removed')}>Removable</Chip>\n *\n * // Navigation chip — server-rendered, zero-JS-friendly.\n * <Chip asChild variant=\"filled\">\n * <Link href=\"/filtros/ativo\" prefetch aria-current=\"page\">Active</Link>\n * </Chip>\n * ```\n */\n// Chip variants using CVA\nconst chipVariants = cva(\n // Base classes\n cn(\n \"inline-flex\",\n \"items-center\",\n \"font-medium\",\n getRadiusClass(\"full\"),\n getSpacingClass(\"xs\", \"gap\"),\n ),\n {\n variants: {\n variant: {\n default: cn(\n \"bg-surface-muted\",\n \"text-fg-primary\",\n \"border\",\n \"border-line-default\",\n ),\n outlined: cn(\n \"bg-transparent\",\n \"text-fg-primary\",\n \"border\",\n \"border-line-default\",\n ),\n filled: cn(\n \"bg-surface-brand-strong\",\n \"text-fg-inverse\",\n \"border\",\n \"border-transparent\",\n ),\n },\n size: {\n sm: cn(\n getSpacingClass(\"xs\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"caption\"),\n ),\n md: cn(\n getSpacingClass(\"sm\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"bodySmall\"),\n ),\n lg: cn(\n getSpacingClass(\"md\", \"px\"),\n getSpacingClass(\"sm\", \"py\"),\n getTypographySize(\"body\"),\n ),\n },\n selected: {\n true: cn(\n \"bg-surface-brand-strong\",\n \"text-fg-inverse\",\n \"border\",\n \"border-line-brand\",\n ),\n false: \"\",\n },\n disabled: {\n true: \"opacity-50 cursor-not-allowed\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n selected: true,\n variant: \"default\",\n class: \"\", // Override variant when selected\n },\n {\n selected: true,\n variant: \"outlined\",\n class: \"\", // Override variant when selected\n },\n {\n selected: true,\n variant: \"filled\",\n class: \"\", // Override variant when selected\n },\n ],\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n selected: false,\n disabled: false,\n },\n },\n);\n\nconst Chip = forwardRef<HTMLDivElement, ChipProps>(function Chip(props, ref) {\n const {\n children,\n variant = \"default\",\n size = \"md\",\n selected = false,\n disabled = false,\n className = \"\",\n \"aria-label\": ariaLabel,\n tabIndex,\n asChild = false,\n } = props;\n\n // Generate accessible label\n const getAccessibleLabel = (): string | undefined => {\n if (ariaLabel) return ariaLabel;\n if (typeof children === \"string\") return children;\n // For non-string children, try to extract text content\n if (\n typeof children === \"object\" &&\n children !== null &&\n \"props\" in children\n ) {\n const childProps = (children as { props?: { children?: unknown } }).props;\n if (childProps?.children && typeof childProps.children === \"string\") {\n return childProps.children;\n }\n }\n return undefined;\n };\n\n const accessibleLabel = getAccessibleLabel();\n\n // asChild path: collapse the entire chip structure (frame + label\n // button + X) into the single consumer-provided node. The frame's\n // visual classes are projected onto the child via Slot.\n //\n // A11Y RESPONSIBILITY TRANSFER. The child element owns:\n // - focus (its native focus ring, or its own focus utilities)\n // - activation (its own click handler / href for navigation)\n // - route-state semantics: `aria-current=\"page\"` on a selected\n // Link is the right tool. `aria-pressed` is intentionally NOT\n // emitted here — a link is not a toggle button.\n // - disabled semantics: `aria-disabled` is set when `disabled` is\n // true, but it does NOT block navigation. Consumers that must\n // truly disable navigation should also gate `href` upstream.\n //\n // TS forbids `onClick` / `onRemove` in this form (see ChipAsChildProps).\n if (asChild) {\n return (\n <Slot\n ref={ref}\n className={cn(\n chipVariants({ variant, size, selected, disabled }),\n className,\n )}\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n tabIndex={tabIndex}\n >\n {children}\n </Slot>\n );\n }\n\n // Standard form below. Narrow `props` so the union picks up\n // onClick/onRemove handlers (forbidden when asChild=true at TS level).\n const { onRemove, onClick } = props as ChipStandardProps;\n\n // Architecture:\n // The label is a real `<button>` whenever the chip is meant to be\n // activated (`onClick` provided). The X is a sibling `<button>` when\n // `onRemove` is provided. The outer `<div>` is NEVER interactive —\n // no `role`, no `tabIndex`, no event handlers. This unifies what\n // used to be three structural variants:\n // - `onClick` only → outer `role=\"button\"` [old]\n // - `onClick` + `onRemove` (no selected) → label-button [PR68]\n // - `selected` → outer `role=\"option\"` [old, axe-flagged]\n // into one consistent shape: label is the actor, outer is the chip\n // chrome (visual frame).\n //\n // Why this matters for a11y:\n // - `role=\"option\"` outside `role=\"listbox\"` violates `aria-required-\n // parent`. The old `selected` path failed axe in every standalone\n // chip. Moving the action to a native `<button>` with\n // `aria-pressed={selected}` (toggle button pattern) communicates\n // state correctly without requiring a listbox parent.\n // - The interactive outer + inner X button produced nested-interactive\n // whenever the consumer combined `selected` (or `onClick`) with\n // `onRemove`. Outer non-interactive + sibling buttons fixes both\n // cases at once.\n //\n // `selected` with no `onClick` is decorative only — the chip CANNOT\n // toggle, so it gets no `aria-pressed` (which would lie) and no role.\n // The visual `selected` styling (chipVariants.selected) applies, but\n // AT users read it as static text. Consumers who want the state\n // communicated must also pass `onClick` to make it a real toggle.\n const useLabelButton = onClick !== undefined;\n const interactive = useLabelButton && !disabled;\n\n // Keyboard handler for the label-button. Native `<button>` activates on\n // Enter/Space in real browsers, but JSDOM does NOT simulate Enter → click,\n // so this preserves the previous test-friendly behavior AND adds explicit\n // `preventDefault` (the original outer-as-button needed it; on a native\n // button this is mostly belt-and-suspenders but harmless).\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick?.();\n }\n };\n\n return (\n <div\n ref={ref}\n className={cn(\n chipVariants({ variant, size, selected, disabled }),\n onRemove && getSpacingClass(\"xs\", \"pr\"),\n className,\n )}\n aria-disabled={disabled}\n >\n {useLabelButton ? (\n <button\n type=\"button\"\n onClick={disabled ? undefined : onClick}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n aria-pressed={selected ? true : undefined}\n aria-label={ariaLabel || accessibleLabel}\n tabIndex={\n tabIndex !== undefined ? tabIndex : interactive ? 0 : undefined\n }\n className={cn(\n \"flex-1\",\n \"bg-transparent\",\n \"border-0\",\n getSpacingClass(\"none\", \"p\"),\n \"text-inherit\",\n \"text-left\",\n \"cursor-pointer\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-line-focus\",\n \"focus:ring-offset-2\",\n getRadiusClass(\"full\"),\n )}\n >\n {children}\n </button>\n ) : (\n <span>{children}</span>\n )}\n {onRemove && !disabled && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n className={cn(\n getSpacingClass(\"xs\", \"ml\"),\n \"hover:bg-tint-hover\",\n getRadiusClass(\"full\"),\n getSpacingClass(\"xs\", \"p\"),\n \"transition-colors\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-line-focus\",\n \"focus:ring-offset-1\",\n )}\n aria-label={`Remove ${accessibleLabel || \"chip\"}`}\n >\n <X className=\"h-3 w-3\" aria-hidden=\"true\" />\n </button>\n )}\n </div>\n );\n});\n\nChip.displayName = \"Chip\";\n\nexport default Chip;\n"],"names":["chipVariants","cva","cn","getRadiusClass","getSpacingClass","getTypographySize","Chip","forwardRef","props","ref","children","variant","size","selected","disabled","className","ariaLabel","tabIndex","asChild","accessibleLabel","childProps","jsx","Slot","onRemove","onClick","useLabelButton","interactive","handleKeyDown","e","jsxs","X"],"mappings":"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"}
1
+ {"version":3,"file":"Chip.js","sources":["../../../../../src/ui/primitives/Chip/Chip.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef, type ReactNode } from \"react\";\nimport { X } from \"lucide-react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport {\n getTypographySize,\n getTypographyWeight,\n} from \"../../tokens/typography\";\nimport { cn, cva } from \"../../utils\";\n\nexport type ChipVariant = \"default\" | \"outlined\" | \"filled\";\nexport type ChipSize = \"sm\" | \"md\" | \"lg\";\n\ninterface ChipBaseProps {\n children: ReactNode;\n variant?: ChipVariant;\n size?: ChipSize;\n selected?: boolean;\n disabled?: boolean;\n className?: string;\n \"aria-label\"?: string;\n tabIndex?: number;\n}\n\ninterface ChipStandardProps extends ChipBaseProps {\n asChild?: false;\n onRemove?: () => void;\n onClick?: () => void;\n /**\n * Optional count sub-badge rendered at the end of the chip (before the\n * remove ✕, if any) — e.g. `Casa 12`, `Tramitando 340` in a filter bar.\n *\n * The sub-badge inverts with the chip surface so it always contrasts:\n * a brand pill on neutral chips, a light pill on brand chips\n * (`selected` / `variant=\"filled\"`). The number is folded into the\n * interactive chip's accessible name (`\"Casa, 12\"`) so AT users hear\n * it; pass an explicit `aria-label` to override that phrasing.\n *\n * Forbidden in the `asChild` form (the consumer composes the node).\n * `0` is a legitimate value and renders `0`; omit the prop for \"no\n * count\".\n */\n count?: number;\n}\n\n/**\n * `asChild` collapses the chip into a single node provided by the\n * consumer (typically `<Link>`). The non-interactive frame + inner\n * label-button + X structure is intentionally NOT rendered — the child\n * IS the chip. As a consequence:\n *\n * - `onClick` and `onRemove` are forbidden at the type level. The\n * child's own click handler (and `href`) is what fires; consumers\n * who need a removable selected filter use the standard\n * (non-asChild) form.\n * - `selected` still applies the visual classes via `chipVariants`,\n * but NO `aria-pressed` is emitted. Toggle-button semantics on\n * `<a>` would lie — a link isn't a two-state control. Consumers\n * that need the selected route surfaced to AT users should pass\n * `aria-current=\"page\"` (or similar) directly on the child Link.\n *\n * @see `.claude/rules/components.md` and the inline a11y notes below.\n */\ninterface ChipAsChildProps extends ChipBaseProps {\n asChild: true;\n /**\n * `onClick` is forbidden when `asChild` is true — the child element\n * owns interaction. Pass the handler (or `href`) on the child.\n */\n onClick?: never;\n /**\n * `onRemove` is forbidden when `asChild` is true — the collapsed\n * node has no slot for an X button. Use the standard (non-asChild)\n * form when removal is required.\n */\n onRemove?: never;\n /**\n * `count` is forbidden when `asChild` is true — the collapsed node is\n * a single consumer element with no slot for the sub-badge. Render the\n * count inside the child yourself, or use the standard form.\n */\n count?: never;\n}\n\nexport type ChipProps = ChipStandardProps | ChipAsChildProps;\n\n/**\n * Chip Component\n *\n * A chip/tag for labels, filters, or selected items.\n *\n * Standard form: an outer `<div>` frame (never interactive) with an\n * inner `<button>` label (when `onClick`) and a sibling X `<button>`\n * (when `onRemove`). This shape closes two axe violations the older\n * implementation hit — `aria-required-parent` (role=option without a\n * listbox) and `nested-interactive` (clickable outer + clickable X).\n *\n * `asChild` form: a single node provided by the consumer (e.g.\n * `<Link>`), with the chip's classes projected via Radix `Slot`. See\n * the `ChipAsChildProps` JSDoc for the a11y responsibility transfer\n * — the consumer's child carries `href`, focus behavior, and any\n * route-state ARIA (`aria-current`). Forbidden in this form:\n * `onClick`, `onRemove` (TS-level).\n *\n * @example\n * ```tsx\n * <Chip>Tag</Chip>\n * <Chip onRemove={() => console.log('removed')}>Removable</Chip>\n *\n * // Navigation chip — server-rendered, zero-JS-friendly.\n * <Chip asChild variant=\"filled\">\n * <Link href=\"/filtros/ativo\" prefetch aria-current=\"page\">Active</Link>\n * </Chip>\n * ```\n */\n// Chip variants using CVA\nconst chipVariants = cva(\n // Base classes\n cn(\n \"inline-flex\",\n \"items-center\",\n \"font-medium\",\n getRadiusClass(\"full\"),\n getSpacingClass(\"xs\", \"gap\"),\n ),\n {\n variants: {\n variant: {\n default: cn(\n \"bg-surface-muted\",\n \"text-fg-primary\",\n \"border\",\n \"border-line-default\",\n ),\n outlined: cn(\n \"bg-transparent\",\n \"text-fg-primary\",\n \"border\",\n \"border-line-default\",\n ),\n filled: cn(\n \"bg-surface-brand-strong\",\n \"text-fg-inverse\",\n \"border\",\n \"border-transparent\",\n ),\n },\n size: {\n sm: cn(\n getSpacingClass(\"xs\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"caption\"),\n ),\n md: cn(\n getSpacingClass(\"sm\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"bodySmall\"),\n ),\n lg: cn(\n getSpacingClass(\"md\", \"px\"),\n getSpacingClass(\"sm\", \"py\"),\n getTypographySize(\"body\"),\n ),\n },\n selected: {\n true: cn(\n \"bg-surface-brand-strong\",\n \"text-fg-inverse\",\n \"border\",\n \"border-line-brand\",\n ),\n false: \"\",\n },\n disabled: {\n true: \"opacity-50 cursor-not-allowed\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n selected: true,\n variant: \"default\",\n class: \"\", // Override variant when selected\n },\n {\n selected: true,\n variant: \"outlined\",\n class: \"\", // Override variant when selected\n },\n {\n selected: true,\n variant: \"filled\",\n class: \"\", // Override variant when selected\n },\n ],\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n selected: false,\n disabled: false,\n },\n },\n);\n\nconst Chip = forwardRef<HTMLDivElement, ChipProps>(function Chip(props, ref) {\n const {\n children,\n variant = \"default\",\n size = \"md\",\n selected = false,\n disabled = false,\n className = \"\",\n \"aria-label\": ariaLabel,\n tabIndex,\n asChild = false,\n } = props;\n\n // Generate accessible label\n const getAccessibleLabel = (): string | undefined => {\n if (ariaLabel) return ariaLabel;\n if (typeof children === \"string\") return children;\n // For non-string children, try to extract text content\n if (\n typeof children === \"object\" &&\n children !== null &&\n \"props\" in children\n ) {\n const childProps = (children as { props?: { children?: unknown } }).props;\n if (childProps?.children && typeof childProps.children === \"string\") {\n return childProps.children;\n }\n }\n return undefined;\n };\n\n const accessibleLabel = getAccessibleLabel();\n\n // asChild path: collapse the entire chip structure (frame + label\n // button + X) into the single consumer-provided node. The frame's\n // visual classes are projected onto the child via Slot.\n //\n // A11Y RESPONSIBILITY TRANSFER. The child element owns:\n // - focus (its native focus ring, or its own focus utilities)\n // - activation (its own click handler / href for navigation)\n // - route-state semantics: `aria-current=\"page\"` on a selected\n // Link is the right tool. `aria-pressed` is intentionally NOT\n // emitted here — a link is not a toggle button.\n // - disabled semantics: `aria-disabled` is set when `disabled` is\n // true, but it does NOT block navigation. Consumers that must\n // truly disable navigation should also gate `href` upstream.\n //\n // TS forbids `onClick` / `onRemove` in this form (see ChipAsChildProps).\n if (asChild) {\n return (\n <Slot\n ref={ref}\n className={cn(\n chipVariants({ variant, size, selected, disabled }),\n className,\n )}\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n tabIndex={tabIndex}\n >\n {children}\n </Slot>\n );\n }\n\n // Standard form below. Narrow `props` so the union picks up\n // onClick/onRemove/count (forbidden when asChild=true at TS level).\n const { onRemove, onClick, count } = props as ChipStandardProps;\n\n // Architecture:\n // The label is a real `<button>` whenever the chip is meant to be\n // activated (`onClick` provided). The X is a sibling `<button>` when\n // `onRemove` is provided. The outer `<div>` is NEVER interactive —\n // no `role`, no `tabIndex`, no event handlers. This unifies what\n // used to be three structural variants:\n // - `onClick` only → outer `role=\"button\"` [old]\n // - `onClick` + `onRemove` (no selected) → label-button [PR68]\n // - `selected` → outer `role=\"option\"` [old, axe-flagged]\n // into one consistent shape: label is the actor, outer is the chip\n // chrome (visual frame).\n //\n // Why this matters for a11y:\n // - `role=\"option\"` outside `role=\"listbox\"` violates `aria-required-\n // parent`. The old `selected` path failed axe in every standalone\n // chip. Moving the action to a native `<button>` with\n // `aria-pressed={selected}` (toggle button pattern) communicates\n // state correctly without requiring a listbox parent.\n // - The interactive outer + inner X button produced nested-interactive\n // whenever the consumer combined `selected` (or `onClick`) with\n // `onRemove`. Outer non-interactive + sibling buttons fixes both\n // cases at once.\n //\n // `selected` with no `onClick` is decorative only — the chip CANNOT\n // toggle, so it gets no `aria-pressed` (which would lie) and no role.\n // The visual `selected` styling (chipVariants.selected) applies, but\n // AT users read it as static text. Consumers who want the state\n // communicated must also pass `onClick` to make it a real toggle.\n const useLabelButton = onClick !== undefined;\n const interactive = useLabelButton && !disabled;\n\n // Keyboard handler for the label-button. Native `<button>` activates on\n // Enter/Space in real browsers, but JSDOM does NOT simulate Enter → click,\n // so this preserves the previous test-friendly behavior AND adds explicit\n // `preventDefault` (the original outer-as-button needed it; on a native\n // button this is mostly belt-and-suspenders but harmless).\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick?.();\n }\n };\n\n // Count sub-badge (issue #222). Rendered as a sibling of the label so\n // the outer flex's `items-center` + `gap` handle alignment/spacing.\n // The pill inverts with the chip surface so it always contrasts:\n // - brand-backed chip (selected || filled) → light pill\n // (bg-surface-base + text-fg-brand-emphasis)\n // - neutral chip (default/outlined) → brand pill\n // (bg-surface-brand-strong + text-fg-inverse, the filled-chip combo)\n // Both pairs are AA-proven elsewhere in the system.\n const hasCount = count !== undefined;\n const chipIsBrandFilled = selected || variant === \"filled\";\n const countBadge = hasCount ? (\n <span\n // Interactive chips fold the count into the label-button's\n // aria-label below, so the visible badge is hidden from AT to\n // avoid a double announce. Non-interactive chips have no\n // overriding name — the badge stays readable as inline content.\n aria-hidden={useLabelButton || undefined}\n className={cn(\n \"inline-flex\",\n \"items-center\",\n \"justify-center\",\n \"tabular-nums\",\n \"leading-none\",\n getRadiusClass(\"full\"),\n getSpacingClass(\"xs\", \"px\"),\n getSpacingClass(\"0.5\", \"py\"),\n getTypographySize(\"caption\"),\n getTypographyWeight(\"label\"),\n chipIsBrandFilled\n ? cn(\"bg-surface-base\", \"text-fg-brand-emphasis\")\n : cn(\"bg-surface-brand-strong\", \"text-fg-inverse\"),\n )}\n >\n {count}\n </span>\n ) : null;\n\n // When a count is present, fold it into the interactive chip's\n // accessible name (\"Casa, 12\") so AT users hear it. An explicit\n // consumer aria-label always wins (they own the phrasing).\n const labelWithCount =\n hasCount && accessibleLabel !== undefined\n ? `${accessibleLabel}, ${count}`\n : accessibleLabel;\n\n return (\n <div\n ref={ref}\n className={cn(\n chipVariants({ variant, size, selected, disabled }),\n onRemove && getSpacingClass(\"xs\", \"pr\"),\n className,\n )}\n aria-disabled={disabled}\n >\n {useLabelButton ? (\n <button\n type=\"button\"\n onClick={disabled ? undefined : onClick}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n aria-pressed={selected ? true : undefined}\n aria-label={ariaLabel || labelWithCount}\n tabIndex={\n tabIndex !== undefined ? tabIndex : interactive ? 0 : undefined\n }\n className={cn(\n \"flex-1\",\n \"bg-transparent\",\n \"border-0\",\n getSpacingClass(\"none\", \"p\"),\n \"text-inherit\",\n \"text-left\",\n \"cursor-pointer\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-line-focus\",\n \"focus:ring-offset-2\",\n getRadiusClass(\"full\"),\n )}\n >\n {children}\n </button>\n ) : (\n <span>{children}</span>\n )}\n {countBadge}\n {onRemove && !disabled && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n className={cn(\n getSpacingClass(\"xs\", \"ml\"),\n \"hover:bg-tint-hover\",\n getRadiusClass(\"full\"),\n getSpacingClass(\"xs\", \"p\"),\n \"transition-colors\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-line-focus\",\n \"focus:ring-offset-1\",\n )}\n aria-label={`Remove ${accessibleLabel || \"chip\"}`}\n >\n <X className=\"h-3 w-3\" aria-hidden=\"true\" />\n </button>\n )}\n </div>\n );\n});\n\nChip.displayName = \"Chip\";\n\nexport default Chip;\n"],"names":["chipVariants","cva","cn","getRadiusClass","getSpacingClass","getTypographySize","Chip","forwardRef","props","ref","children","variant","size","selected","disabled","className","ariaLabel","tabIndex","asChild","accessibleLabel","childProps","jsx","Slot","onRemove","onClick","count","useLabelButton","interactive","handleKeyDown","e","hasCount","chipIsBrandFilled","countBadge","getTypographyWeight","labelWithCount","jsxs","X"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorMessage.js","sources":["../../../../../src/ui/primitives/ErrorMessage/ErrorMessage.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\nimport { AlertCircle } from \"lucide-react\";\nimport { getTypographySize } from \"../../tokens/typography\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn } from \"../../utils\";\n\nexport interface ErrorMessageProps extends HTMLAttributes<HTMLDivElement> {\n message: string;\n id?: string;\n}\n\n/**\n * ErrorMessage Component\n *\n * A component for displaying validation error messages.\n * Follows Atomic Design principles as an Atom component.\n *\n * @example\n * ```tsx\n * <ErrorMessage message=\"This field is required\" id=\"email-error\" />\n * ```\n */\nexport default function ErrorMessage({\n message,\n id,\n className = \"\",\n ...props\n}: ErrorMessageProps) {\n const baseClasses = [\n getSpacingClass(\"xs\", \"mt\"),\n getTypographySize(\"bodySmall\"),\n \"text-fg-error\",\n \"flex\",\n \"items-center\",\n getSpacingClass(\"xs\", \"gap\"),\n ];\n\n const classes = cn(...baseClasses, className);\n\n return (\n <div role=\"alert\" id={id} className={classes} aria-live=\"polite\" {...props}>\n <AlertCircle className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span>{message}</span>\n </div>\n );\n}\n"],"names":["ErrorMessage","_a","_b","message","id","className","props","__objRest","baseClasses","getSpacingClass","getTypographySize","classes","cn","jsxs","__spreadProps","__spreadValues","jsx","AlertCircle"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAwBA,EAAaC,GAKf;AALe,MAAAC,IAAAD,GACnC;AAAA,aAAAE;AAAA,IACA,IAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,MAHuBH,GAIhCI,IAAAC,EAJgCL,GAIhC;AAAA,IAHH;AAAA,IACA;AAAA,IACA;AAAA;AAGA,QAAMM,IAAc;AAAA,IAClBC,EAAgB,MAAM,IAAI;AAAA,IAC1BC,EAAkB,WAAW;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACAD,EAAgB,MAAM,KAAK;AAAA,EAAA,GAGvBE,IAAUC,EAAG,GAAGJ,GAAaH,CAAS;AAE5C,SACE,gBAAAQ,EAAC,OAAAC,EAAAC,EAAA,EAAI,MAAK,SAAQ,IAAAX,GAAQ,WAAWO,GAAS,aAAU,YAAaL,IAApE,EACC,UAAA;AAAA,IAAA,gBAAAU,EAACC,GAAA,EAAY,WAAU,oBAAmB,eAAY,QAAO;AAAA,IAC7D,gBAAAD,EAAC,UAAM,UAAAb,EAAA,CAAQ;AAAA,EAAA,IACjB;AAEJ;"}
1
+ {"version":3,"file":"ErrorMessage.js","sources":["../../../../../src/ui/primitives/ErrorMessage/ErrorMessage.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\nimport { AlertCircle } from \"lucide-react\";\nimport { getTypographySize } from \"../../tokens/typography\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn } from \"../../utils\";\n\nexport interface ErrorMessageProps extends HTMLAttributes<HTMLDivElement> {\n message: string;\n id?: string;\n}\n\n/**\n * ErrorMessage Component\n *\n * A component for displaying validation error messages.\n *\n * @example\n * ```tsx\n * <ErrorMessage message=\"This field is required\" id=\"email-error\" />\n * ```\n */\nexport default function ErrorMessage({\n message,\n id,\n className = \"\",\n ...props\n}: ErrorMessageProps) {\n const baseClasses = [\n getSpacingClass(\"xs\", \"mt\"),\n getTypographySize(\"bodySmall\"),\n \"text-fg-error\",\n \"flex\",\n \"items-center\",\n getSpacingClass(\"xs\", \"gap\"),\n ];\n\n const classes = cn(...baseClasses, className);\n\n return (\n <div role=\"alert\" id={id} className={classes} aria-live=\"polite\" {...props}>\n <AlertCircle className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span>{message}</span>\n </div>\n );\n}\n"],"names":["ErrorMessage","_a","_b","message","id","className","props","__objRest","baseClasses","getSpacingClass","getTypographySize","classes","cn","jsxs","__spreadProps","__spreadValues","jsx","AlertCircle"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,SAAwBA,EAAaC,GAKf;AALe,MAAAC,IAAAD,GACnC;AAAA,aAAAE;AAAA,IACA,IAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,MAHuBH,GAIhCI,IAAAC,EAJgCL,GAIhC;AAAA,IAHH;AAAA,IACA;AAAA,IACA;AAAA;AAGA,QAAMM,IAAc;AAAA,IAClBC,EAAgB,MAAM,IAAI;AAAA,IAC1BC,EAAkB,WAAW;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACAD,EAAgB,MAAM,KAAK;AAAA,EAAA,GAGvBE,IAAUC,EAAG,GAAGJ,GAAaH,CAAS;AAE5C,SACE,gBAAAQ,EAAC,OAAAC,EAAAC,EAAA,EAAI,MAAK,SAAQ,IAAAX,GAAQ,WAAWO,GAAS,aAAU,YAAaL,IAApE,EACC,UAAA;AAAA,IAAA,gBAAAU,EAACC,GAAA,EAAY,WAAU,oBAAmB,eAAY,QAAO;AAAA,IAC7D,gBAAAD,EAAC,UAAM,UAAAb,EAAA,CAAQ;AAAA,EAAA,IACjB;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sources":["../../../../../src/ui/primitives/Input/Input.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef, useState, memo, useId, useMemo, useCallback } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport {\n getTypographyClasses,\n getTypographySize,\n} from \"../../tokens/typography\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn, cva } from \"../../utils\";\nimport { X, Eye, EyeOff } from \"lucide-react\";\nimport Button from \"../Button/Button\";\n\n/**\n * Helper Text Component\n * Memoized component for helper/error text\n */\nconst HelperText = memo(function HelperText({\n error,\n success,\n helperText,\n errorId,\n helperId,\n}: {\n error: boolean;\n success: boolean;\n helperText?: string;\n errorId?: string;\n helperId?: string;\n}) {\n const helperClasses = useMemo(\n () =>\n cn(\n getSpacingClass(\"xs\", \"mt\"),\n getTypographyClasses(\"caption\"),\n error && \"text-fg-error\",\n success && \"text-fg-success\",\n !error && !success && \"text-fg-secondary\",\n ),\n [error, success],\n );\n\n const text = useMemo(\n () => helperText || (error ? \"Error\" : success ? \"Success\" : \"\"),\n [helperText, error, success],\n );\n\n return (\n <div\n id={errorId || helperId}\n className={helperClasses}\n role={error || success ? \"alert\" : undefined}\n >\n {text}\n </div>\n );\n});\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\nexport type InputVariant = \"default\" | \"outlined\" | \"filled\";\nexport type InputState = \"default\" | \"error\" | \"success\";\n\nexport interface InputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"size\"\n> {\n label?: ReactNode;\n error?: boolean;\n success?: boolean;\n helperText?: string;\n size?: InputSize;\n variant?: InputVariant;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n showClearButton?: boolean;\n onClear?: () => void;\n}\n\n/**\n * Input Component\n *\n * A styled text input component with label, error/success states, icons, and clear button.\n * Follows Atomic Design principles as an Atom component.\n * Uses Composite Pattern when combined with Label and ErrorMessage.\n *\n * @example\n * ```tsx\n * <Input\n * id=\"email\"\n * label=\"Email\"\n * type=\"email\"\n * placeholder=\"Enter your email\"\n * error={hasError}\n * helperText={errorMessage}\n * leftIcon={<MailIcon />}\n * />\n * ```\n */\nconst Input = memo(\n forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n id,\n label,\n error = false,\n success = false,\n helperText,\n size = \"md\",\n variant = \"outlined\",\n leftIcon,\n rightIcon,\n showClearButton = false,\n onClear,\n className = \"\",\n disabled = false,\n type = \"text\",\n value,\n onChange,\n ...props\n },\n ref,\n ) {\n // Stable fallback id when the consumer doesn't provide one. useId\n // is SSR-safe and stable across renders, replacing the deprecated\n // Math.random().substr() pattern.\n const reactId = useId();\n const inputId = id || `input-${reactId}`;\n\n // Memoize error and helper IDs\n const errorId = useMemo(\n () => (error ? `${inputId}-error` : undefined),\n [error, inputId],\n );\n\n const helperId = useMemo(\n () => (helperText ? `${inputId}-helper` : undefined),\n [helperText, inputId],\n );\n\n // Password toggle state\n const [showPassword, setShowPassword] = useState(false);\n\n // Memoize password-related values\n const isPassword = useMemo(() => type === \"password\", [type]);\n const inputType = useMemo(\n () => (isPassword && showPassword ? \"text\" : type),\n [isPassword, showPassword, type],\n );\n\n // Memoize state\n const state = useMemo<InputState>(\n () => (error ? \"error\" : success ? \"success\" : \"default\"),\n [error, success],\n );\n\n // Memoize clear button visibility\n const hasValue = useMemo(\n () => value !== undefined && value !== null && value !== \"\",\n [value],\n );\n\n const shouldShowClear = useMemo(\n () => showClearButton && hasValue && !disabled,\n [showClearButton, hasValue, disabled],\n );\n\n // Memoize focus ring colors\n const primaryFocusRing = useMemo(() => \"focus:border-line-focus\", []);\n\n const errorFocusRing = useMemo(() => \"focus:border-error\", []);\n\n const successFocusRing = useMemo(() => \"focus:border-success\", []);\n\n const getFocusRingColor = useMemo(\n () => primaryFocusRing.replace(\"focus:border-\", \"focus:ring-\"),\n [primaryFocusRing],\n );\n\n const getStateFocusRingColor = useCallback(\n (stateType: \"error\" | \"success\"): string => {\n return stateType === \"error\"\n ? errorFocusRing.replace(\"focus:border-\", \"focus:ring-\")\n : successFocusRing.replace(\"focus:border-\", \"focus:ring-\");\n },\n [errorFocusRing, successFocusRing],\n );\n\n // Input variants using CVA — memoize so the function reference is\n // stable across renders. inputClasses below depends on this; without\n // memoization a fresh cva() each render would invalidate that memo\n // on every render (defeating its purpose).\n const inputVariants = useMemo(\n () =>\n cva(\n // Base classes\n cn(\n \"w-full\",\n getRadiusClass(\"md\"),\n \"transition-colors\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-offset-2\",\n \"disabled:opacity-50\",\n \"disabled:cursor-not-allowed\",\n ),\n {\n variants: {\n variant: {\n default: cn(\n \"border-0\",\n \"border-b-2\",\n \"border-line-default\",\n \"focus:border-line-focus\",\n ),\n outlined: cn(\n \"border\",\n \"border-line-default\",\n \"focus:border-line-focus\",\n ),\n filled: cn(\n \"bg-surface-muted\",\n \"border-0\",\n \"focus:bg-surface-base\",\n \"focus:ring-2\",\n getFocusRingColor,\n ),\n },\n size: {\n sm: cn(\n \"h-8\",\n getTypographySize(\"bodySmall\"),\n getSpacingClass(\"md\", \"px\"),\n ),\n md: cn(\n \"h-10\",\n getTypographySize(\"body\"),\n getSpacingClass(\"base\", \"px\"),\n ),\n lg: cn(\n \"h-12\",\n getTypographySize(\"bodyLarge\"),\n getSpacingClass(\"lg\", \"px\"),\n ),\n },\n state: {\n default: \"\",\n error: cn(\n \"border-error\",\n \"focus:border-error\",\n getStateFocusRingColor(\"error\"),\n ),\n success: cn(\n \"border-success\",\n \"focus:border-success\",\n getStateFocusRingColor(\"success\"),\n ),\n },\n },\n defaultVariants: {\n variant: \"outlined\",\n size: \"md\",\n state: \"default\",\n },\n },\n ),\n [getFocusRingColor, getStateFocusRingColor],\n );\n\n // Memoize input classes\n const inputClasses = useMemo(\n () =>\n cn(\n inputVariants({ variant, size, state }),\n // Icon padding - specific values for icon positioning.\n // `pl-9` / `pr-9` aren't on the spacing scale (no semantic\n // key for 36px); they stay raw until a future PR either\n // extends the scale or refactors the icon-padding contract.\n leftIcon &&\n (size === \"sm\"\n ? \"pl-9\"\n : size === \"lg\"\n ? getSpacingClass(\"3xl\", \"pl\")\n : getSpacingClass(\"2xl\", \"pl\")),\n (rightIcon || shouldShowClear || isPassword) &&\n (size === \"sm\"\n ? \"pr-9\"\n : size === \"lg\"\n ? getSpacingClass(\"3xl\", \"pr\")\n : getSpacingClass(\"2xl\", \"pr\")),\n className,\n ),\n [\n inputVariants,\n variant,\n size,\n state,\n leftIcon,\n rightIcon,\n shouldShowClear,\n isPassword,\n className,\n ],\n );\n\n // Memoize label classes\n const labelClasses = useMemo(\n () =>\n cn(\n \"block\",\n getTypographyClasses(\"label\"),\n getSpacingClass(\"xs\", \"mb\"),\n disabled && \"opacity-50\",\n ),\n [disabled],\n );\n\n // Memoize icon size and position\n const iconSize = useMemo(\n () => (size === \"sm\" ? \"h-4 w-4\" : size === \"lg\" ? \"h-5 w-5\" : \"h-4 w-4\"),\n [size],\n );\n\n const iconPosition = useMemo(\n () => (size === \"sm\" ? \"top-2\" : size === \"lg\" ? \"top-3.5\" : \"top-2.5\"),\n [size],\n );\n\n // Memoize clear handler\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onClear) {\n onClear();\n } else if (onChange) {\n // Create synthetic event to clear input\n const inputElement = e.currentTarget\n .closest(\".relative\")\n ?.querySelector(\"input\") as HTMLInputElement;\n if (inputElement) {\n const syntheticEvent = {\n target: inputElement,\n currentTarget: inputElement,\n bubbles: true,\n cancelable: true,\n defaultPrevented: false,\n eventPhase: 2,\n isTrusted: false,\n nativeEvent: new Event(\"change\"),\n preventDefault: () => {},\n stopPropagation: () => {},\n persist: () => {},\n timeStamp: Date.now(),\n } as unknown as React.ChangeEvent<HTMLInputElement>;\n Object.defineProperty(syntheticEvent.target, \"value\", {\n value: \"\",\n writable: true,\n });\n Object.defineProperty(syntheticEvent.currentTarget, \"value\", {\n value: \"\",\n writable: true,\n });\n onChange(syntheticEvent);\n }\n }\n },\n [onClear, onChange],\n );\n\n // Memoize password toggle handler\n const handleTogglePassword = useCallback(() => {\n setShowPassword((prev) => !prev);\n }, []);\n\n return (\n <div className=\"w-full\">\n {label && (\n <label htmlFor={inputId} className={labelClasses}>\n {label}\n </label>\n )}\n <div className=\"relative\">\n {leftIcon && (\n <div\n className={`absolute left-3 ${iconPosition} text-fg-secondary opacity-60 pointer-events-none`}\n >\n <div className={iconSize}>{leftIcon}</div>\n </div>\n )}\n <input\n id={inputId}\n ref={ref}\n type={inputType}\n className={inputClasses}\n disabled={disabled}\n value={value}\n onChange={onChange}\n aria-invalid={error}\n aria-required={props.required}\n aria-describedby={errorId || helperId}\n suppressHydrationWarning\n {...props}\n />\n <div\n className={`absolute right-3 top-0 bottom-0 flex items-center ${getSpacingClass(\"xs\", \"gap\")}`}\n >\n {shouldShowClear && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleClear}\n className={`h-auto ${getSpacingClass(\"xs\", \"p\")}`}\n aria-label=\"Clear input\"\n >\n <X className={iconSize} />\n </Button>\n )}\n {isPassword && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleTogglePassword}\n className={`h-auto ${getSpacingClass(\"xs\", \"p\")}`}\n aria-label={showPassword ? \"Hide password\" : \"Show password\"}\n >\n {showPassword ? (\n <EyeOff className={iconSize} />\n ) : (\n <Eye className={iconSize} />\n )}\n </Button>\n )}\n {rightIcon && !shouldShowClear && !isPassword && (\n <div\n className={`text-fg-secondary opacity-60 pointer-events-none ${iconSize}`}\n >\n {rightIcon}\n </div>\n )}\n </div>\n </div>\n {(error || success || helperText) && (\n <HelperText\n error={error}\n success={success}\n helperText={helperText}\n errorId={errorId}\n helperId={helperId}\n />\n )}\n </div>\n );\n }),\n);\n\nInput.displayName = \"Input\";\n\nexport default Input;\n"],"names":["HelperText","memo","error","success","helperText","errorId","helperId","helperClasses","useMemo","cn","getSpacingClass","getTypographyClasses","text","jsx","Input","forwardRef","_a","ref","_b","id","label","size","variant","leftIcon","rightIcon","showClearButton","onClear","className","disabled","type","value","onChange","props","__objRest","reactId","useId","inputId","showPassword","setShowPassword","useState","isPassword","inputType","state","hasValue","shouldShowClear","primaryFocusRing","errorFocusRing","successFocusRing","getFocusRingColor","getStateFocusRingColor","useCallback","stateType","inputVariants","cva","getRadiusClass","getTypographySize","inputClasses","labelClasses","iconSize","iconPosition","handleClear","e","inputElement","syntheticEvent","handleTogglePassword","prev","jsxs","__spreadValues","Button","X","EyeOff","Eye"],"mappings":"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"}
1
+ {"version":3,"file":"Input.js","sources":["../../../../../src/ui/primitives/Input/Input.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef, useState, memo, useId, useMemo, useCallback } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport {\n getTypographyClasses,\n getTypographySize,\n} from \"../../tokens/typography\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn, cva } from \"../../utils\";\nimport { X, Eye, EyeOff } from \"lucide-react\";\nimport Button from \"../Button/Button\";\n\n/**\n * Helper Text Component\n * Memoized component for helper/error text\n */\nconst HelperText = memo(function HelperText({\n error,\n success,\n helperText,\n errorId,\n helperId,\n}: {\n error: boolean;\n success: boolean;\n helperText?: string;\n errorId?: string;\n helperId?: string;\n}) {\n const helperClasses = useMemo(\n () =>\n cn(\n getSpacingClass(\"xs\", \"mt\"),\n getTypographyClasses(\"caption\"),\n error && \"text-fg-error\",\n success && \"text-fg-success\",\n !error && !success && \"text-fg-secondary\",\n ),\n [error, success],\n );\n\n const text = useMemo(\n () => helperText || (error ? \"Error\" : success ? \"Success\" : \"\"),\n [helperText, error, success],\n );\n\n return (\n <div\n id={errorId || helperId}\n className={helperClasses}\n role={error || success ? \"alert\" : undefined}\n >\n {text}\n </div>\n );\n});\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\nexport type InputVariant = \"default\" | \"outlined\" | \"filled\";\nexport type InputState = \"default\" | \"error\" | \"success\";\n\nexport interface InputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"size\"\n> {\n label?: ReactNode;\n error?: boolean;\n success?: boolean;\n helperText?: string;\n size?: InputSize;\n variant?: InputVariant;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n showClearButton?: boolean;\n onClear?: () => void;\n}\n\n/**\n * Input Component\n *\n * A styled text input component with label, error/success states, icons, and clear button.\n * Uses Composite Pattern when combined with Label and ErrorMessage.\n *\n * @example\n * ```tsx\n * <Input\n * id=\"email\"\n * label=\"Email\"\n * type=\"email\"\n * placeholder=\"Enter your email\"\n * error={hasError}\n * helperText={errorMessage}\n * leftIcon={<MailIcon />}\n * />\n * ```\n */\nconst Input = memo(\n forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n id,\n label,\n error = false,\n success = false,\n helperText,\n size = \"md\",\n variant = \"outlined\",\n leftIcon,\n rightIcon,\n showClearButton = false,\n onClear,\n className = \"\",\n disabled = false,\n type = \"text\",\n value,\n onChange,\n ...props\n },\n ref,\n ) {\n // Stable fallback id when the consumer doesn't provide one. useId\n // is SSR-safe and stable across renders, replacing the deprecated\n // Math.random().substr() pattern.\n const reactId = useId();\n const inputId = id || `input-${reactId}`;\n\n // Memoize error and helper IDs\n const errorId = useMemo(\n () => (error ? `${inputId}-error` : undefined),\n [error, inputId],\n );\n\n const helperId = useMemo(\n () => (helperText ? `${inputId}-helper` : undefined),\n [helperText, inputId],\n );\n\n // Password toggle state\n const [showPassword, setShowPassword] = useState(false);\n\n // Memoize password-related values\n const isPassword = useMemo(() => type === \"password\", [type]);\n const inputType = useMemo(\n () => (isPassword && showPassword ? \"text\" : type),\n [isPassword, showPassword, type],\n );\n\n // Memoize state\n const state = useMemo<InputState>(\n () => (error ? \"error\" : success ? \"success\" : \"default\"),\n [error, success],\n );\n\n // Memoize clear button visibility\n const hasValue = useMemo(\n () => value !== undefined && value !== null && value !== \"\",\n [value],\n );\n\n const shouldShowClear = useMemo(\n () => showClearButton && hasValue && !disabled,\n [showClearButton, hasValue, disabled],\n );\n\n // Memoize focus ring colors\n const primaryFocusRing = useMemo(() => \"focus:border-line-focus\", []);\n\n const errorFocusRing = useMemo(() => \"focus:border-error\", []);\n\n const successFocusRing = useMemo(() => \"focus:border-success\", []);\n\n const getFocusRingColor = useMemo(\n () => primaryFocusRing.replace(\"focus:border-\", \"focus:ring-\"),\n [primaryFocusRing],\n );\n\n const getStateFocusRingColor = useCallback(\n (stateType: \"error\" | \"success\"): string => {\n return stateType === \"error\"\n ? errorFocusRing.replace(\"focus:border-\", \"focus:ring-\")\n : successFocusRing.replace(\"focus:border-\", \"focus:ring-\");\n },\n [errorFocusRing, successFocusRing],\n );\n\n // Input variants using CVA — memoize so the function reference is\n // stable across renders. inputClasses below depends on this; without\n // memoization a fresh cva() each render would invalidate that memo\n // on every render (defeating its purpose).\n const inputVariants = useMemo(\n () =>\n cva(\n // Base classes\n cn(\n \"w-full\",\n getRadiusClass(\"md\"),\n \"transition-colors\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-offset-2\",\n \"disabled:opacity-50\",\n \"disabled:cursor-not-allowed\",\n ),\n {\n variants: {\n variant: {\n default: cn(\n \"border-0\",\n \"border-b-2\",\n \"border-line-default\",\n \"focus:border-line-focus\",\n ),\n outlined: cn(\n \"border\",\n \"border-line-default\",\n \"focus:border-line-focus\",\n ),\n filled: cn(\n \"bg-surface-muted\",\n \"border-0\",\n \"focus:bg-surface-base\",\n \"focus:ring-2\",\n getFocusRingColor,\n ),\n },\n size: {\n sm: cn(\n \"h-8\",\n getTypographySize(\"bodySmall\"),\n getSpacingClass(\"md\", \"px\"),\n ),\n md: cn(\n \"h-10\",\n getTypographySize(\"body\"),\n getSpacingClass(\"base\", \"px\"),\n ),\n lg: cn(\n \"h-12\",\n getTypographySize(\"bodyLarge\"),\n getSpacingClass(\"lg\", \"px\"),\n ),\n },\n state: {\n default: \"\",\n error: cn(\n \"border-error\",\n \"focus:border-error\",\n getStateFocusRingColor(\"error\"),\n ),\n success: cn(\n \"border-success\",\n \"focus:border-success\",\n getStateFocusRingColor(\"success\"),\n ),\n },\n },\n defaultVariants: {\n variant: \"outlined\",\n size: \"md\",\n state: \"default\",\n },\n },\n ),\n [getFocusRingColor, getStateFocusRingColor],\n );\n\n // Memoize input classes\n const inputClasses = useMemo(\n () =>\n cn(\n inputVariants({ variant, size, state }),\n // Icon padding - specific values for icon positioning.\n // `pl-9` / `pr-9` aren't on the spacing scale (no semantic\n // key for 36px); they stay raw until a future PR either\n // extends the scale or refactors the icon-padding contract.\n leftIcon &&\n (size === \"sm\"\n ? \"pl-9\"\n : size === \"lg\"\n ? getSpacingClass(\"3xl\", \"pl\")\n : getSpacingClass(\"2xl\", \"pl\")),\n (rightIcon || shouldShowClear || isPassword) &&\n (size === \"sm\"\n ? \"pr-9\"\n : size === \"lg\"\n ? getSpacingClass(\"3xl\", \"pr\")\n : getSpacingClass(\"2xl\", \"pr\")),\n className,\n ),\n [\n inputVariants,\n variant,\n size,\n state,\n leftIcon,\n rightIcon,\n shouldShowClear,\n isPassword,\n className,\n ],\n );\n\n // Memoize label classes\n const labelClasses = useMemo(\n () =>\n cn(\n \"block\",\n getTypographyClasses(\"label\"),\n getSpacingClass(\"xs\", \"mb\"),\n disabled && \"opacity-50\",\n ),\n [disabled],\n );\n\n // Memoize icon size and position\n const iconSize = useMemo(\n () => (size === \"sm\" ? \"h-4 w-4\" : size === \"lg\" ? \"h-5 w-5\" : \"h-4 w-4\"),\n [size],\n );\n\n const iconPosition = useMemo(\n () => (size === \"sm\" ? \"top-2\" : size === \"lg\" ? \"top-3.5\" : \"top-2.5\"),\n [size],\n );\n\n // Memoize clear handler\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onClear) {\n onClear();\n } else if (onChange) {\n // Create synthetic event to clear input\n const inputElement = e.currentTarget\n .closest(\".relative\")\n ?.querySelector(\"input\") as HTMLInputElement;\n if (inputElement) {\n const syntheticEvent = {\n target: inputElement,\n currentTarget: inputElement,\n bubbles: true,\n cancelable: true,\n defaultPrevented: false,\n eventPhase: 2,\n isTrusted: false,\n nativeEvent: new Event(\"change\"),\n preventDefault: () => {},\n stopPropagation: () => {},\n persist: () => {},\n timeStamp: Date.now(),\n } as unknown as React.ChangeEvent<HTMLInputElement>;\n Object.defineProperty(syntheticEvent.target, \"value\", {\n value: \"\",\n writable: true,\n });\n Object.defineProperty(syntheticEvent.currentTarget, \"value\", {\n value: \"\",\n writable: true,\n });\n onChange(syntheticEvent);\n }\n }\n },\n [onClear, onChange],\n );\n\n // Memoize password toggle handler\n const handleTogglePassword = useCallback(() => {\n setShowPassword((prev) => !prev);\n }, []);\n\n return (\n <div className=\"w-full\">\n {label && (\n <label htmlFor={inputId} className={labelClasses}>\n {label}\n </label>\n )}\n <div className=\"relative\">\n {leftIcon && (\n <div\n className={`absolute left-3 ${iconPosition} text-fg-secondary opacity-60 pointer-events-none`}\n >\n <div className={iconSize}>{leftIcon}</div>\n </div>\n )}\n <input\n id={inputId}\n ref={ref}\n type={inputType}\n className={inputClasses}\n disabled={disabled}\n value={value}\n onChange={onChange}\n aria-invalid={error}\n aria-required={props.required}\n aria-describedby={errorId || helperId}\n suppressHydrationWarning\n {...props}\n />\n <div\n className={`absolute right-3 top-0 bottom-0 flex items-center ${getSpacingClass(\"xs\", \"gap\")}`}\n >\n {shouldShowClear && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleClear}\n className={`h-auto ${getSpacingClass(\"xs\", \"p\")}`}\n aria-label=\"Clear input\"\n >\n <X className={iconSize} />\n </Button>\n )}\n {isPassword && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleTogglePassword}\n className={`h-auto ${getSpacingClass(\"xs\", \"p\")}`}\n aria-label={showPassword ? \"Hide password\" : \"Show password\"}\n >\n {showPassword ? (\n <EyeOff className={iconSize} />\n ) : (\n <Eye className={iconSize} />\n )}\n </Button>\n )}\n {rightIcon && !shouldShowClear && !isPassword && (\n <div\n className={`text-fg-secondary opacity-60 pointer-events-none ${iconSize}`}\n >\n {rightIcon}\n </div>\n )}\n </div>\n </div>\n {(error || success || helperText) && (\n <HelperText\n error={error}\n success={success}\n helperText={helperText}\n errorId={errorId}\n helperId={helperId}\n />\n )}\n </div>\n );\n }),\n);\n\nInput.displayName = \"Input\";\n\nexport default Input;\n"],"names":["HelperText","memo","error","success","helperText","errorId","helperId","helperClasses","useMemo","cn","getSpacingClass","getTypographyClasses","text","jsx","Input","forwardRef","_a","ref","_b","id","label","size","variant","leftIcon","rightIcon","showClearButton","onClear","className","disabled","type","value","onChange","props","__objRest","reactId","useId","inputId","showPassword","setShowPassword","useState","isPassword","inputType","state","hasValue","shouldShowClear","primaryFocusRing","errorFocusRing","successFocusRing","getFocusRingColor","getStateFocusRingColor","useCallback","stateType","inputVariants","cva","getRadiusClass","getTypographySize","inputClasses","labelClasses","iconSize","iconPosition","handleClear","e","inputElement","syntheticEvent","handleTogglePassword","prev","jsxs","__spreadValues","Button","X","EyeOff","Eye"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,MAAMA,KAAaC,EAAK,SAAoB;AAAA,EAC1C,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AACF,GAMG;AACD,QAAMC,IAAgBC;AAAA,IACpB,MACEC;AAAA,MACEC,EAAgB,MAAM,IAAI;AAAA,MAC1BC,EAAqB,SAAS;AAAA,MAC9BT,KAAS;AAAA,MACTC,KAAW;AAAA,MACX,CAACD,KAAS,CAACC,KAAW;AAAA,IAAA;AAAA,IAE1B,CAACD,GAAOC,CAAO;AAAA,EAAA,GAGXS,IAAOJ;AAAA,IACX,MAAMJ,MAAeF,IAAQ,UAAUC,IAAU,YAAY;AAAA,IAC7D,CAACC,GAAYF,GAAOC,CAAO;AAAA,EAAA;AAG7B,SACE,gBAAAU;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAIR,KAAWC;AAAA,MACf,WAAWC;AAAA,MACX,MAAML,KAASC,IAAU,UAAU;AAAA,MAElC,UAAAS;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC,GAyCKE,KAAQb;AAAA,EACZc,GAAyC,SACvCC,IAmBAC,IACA;AApBA,QAAAC,IAAAF,IACE;AAAA,UAAAG;AAAA,MACA,OAAAC;AAAA,MACA,OAAAlB,IAAQ;AAAA,MACR,SAAAC,IAAU;AAAA,MACV,YAAAC;AAAA,MACA,MAAAiB,IAAO;AAAA,MACP,SAAAC,IAAU;AAAA,MACV,UAAAC;AAAA,MACA,WAAAC;AAAA,MACA,iBAAAC,IAAkB;AAAA,MAClB,SAAAC;AAAA,MACA,WAAAC,IAAY;AAAA,MACZ,UAAAC,IAAW;AAAA,MACX,MAAAC,IAAO;AAAA,MACP,OAAAC;AAAA,MACA,UAAAC;AAAA,QAhBFb,GAiBKc,IAAAC,EAjBLf,GAiBK;AAAA,MAhBH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAQF,UAAMgB,KAAUC,GAAA,GACVC,IAAUjB,KAAM,SAASe,EAAO,IAGhC7B,IAAUG;AAAA,MACd,MAAON,IAAQ,GAAGkC,CAAO,WAAW;AAAA,MACpC,CAAClC,GAAOkC,CAAO;AAAA,IAAA,GAGX9B,IAAWE;AAAA,MACf,MAAOJ,IAAa,GAAGgC,CAAO,YAAY;AAAA,MAC1C,CAAChC,GAAYgC,CAAO;AAAA,IAAA,GAIhB,CAACC,GAAcC,EAAe,IAAIC,GAAS,EAAK,GAGhDC,IAAahC,EAAQ,MAAMqB,MAAS,YAAY,CAACA,CAAI,CAAC,GACtDY,KAAYjC;AAAA,MAChB,MAAOgC,KAAcH,IAAe,SAASR;AAAA,MAC7C,CAACW,GAAYH,GAAcR,CAAI;AAAA,IAAA,GAI3Ba,IAAQlC;AAAA,MACZ,MAAON,IAAQ,UAAUC,IAAU,YAAY;AAAA,MAC/C,CAACD,GAAOC,CAAO;AAAA,IAAA,GAIXwC,IAAWnC;AAAA,MACf,MAA6BsB,KAAU,QAAQA,MAAU;AAAA,MACzD,CAACA,CAAK;AAAA,IAAA,GAGFc,IAAkBpC;AAAA,MACtB,MAAMiB,KAAmBkB,KAAY,CAACf;AAAA,MACtC,CAACH,GAAiBkB,GAAUf,CAAQ;AAAA,IAAA,GAIhCiB,IAAmBrC,EAAQ,MAAM,2BAA2B,CAAA,CAAE,GAE9DsC,IAAiBtC,EAAQ,MAAM,sBAAsB,CAAA,CAAE,GAEvDuC,IAAmBvC,EAAQ,MAAM,wBAAwB,CAAA,CAAE,GAE3DwC,IAAoBxC;AAAA,MACxB,MAAMqC,EAAiB,QAAQ,iBAAiB,aAAa;AAAA,MAC7D,CAACA,CAAgB;AAAA,IAAA,GAGbI,IAAyBC;AAAA,MAC7B,CAACC,MACQA,MAAc,UACjBL,EAAe,QAAQ,iBAAiB,aAAa,IACrDC,EAAiB,QAAQ,iBAAiB,aAAa;AAAA,MAE7D,CAACD,GAAgBC,CAAgB;AAAA,IAAA,GAO7BK,IAAgB5C;AAAA,MACpB,MACE6C;AAAA;AAAA,QAEE5C;AAAA,UACE;AAAA,UACA6C,GAAe,IAAI;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAEF;AAAA,UACE,UAAU;AAAA,YACR,SAAS;AAAA,cACP,SAAS7C;AAAA,gBACP;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cAAA;AAAA,cAEF,UAAUA;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA;AAAA,cAAA;AAAA,cAEF,QAAQA;AAAA,gBACN;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACAuC;AAAA,cAAA;AAAA,YACF;AAAA,YAEF,MAAM;AAAA,cACJ,IAAIvC;AAAA,gBACF;AAAA,gBACA8C,EAAkB,WAAW;AAAA,gBAC7B7C,EAAgB,MAAM,IAAI;AAAA,cAAA;AAAA,cAE5B,IAAID;AAAA,gBACF;AAAA,gBACA8C,EAAkB,MAAM;AAAA,gBACxB7C,EAAgB,QAAQ,IAAI;AAAA,cAAA;AAAA,cAE9B,IAAID;AAAA,gBACF;AAAA,gBACA8C,EAAkB,WAAW;AAAA,gBAC7B7C,EAAgB,MAAM,IAAI;AAAA,cAAA;AAAA,YAC5B;AAAA,YAEF,OAAO;AAAA,cACL,SAAS;AAAA,cACT,OAAOD;AAAA,gBACL;AAAA,gBACA;AAAA,gBACAwC,EAAuB,OAAO;AAAA,cAAA;AAAA,cAEhC,SAASxC;AAAA,gBACP;AAAA,gBACA;AAAA,gBACAwC,EAAuB,SAAS;AAAA,cAAA;AAAA,YAClC;AAAA,UACF;AAAA,UAEF,iBAAiB;AAAA,YACf,SAAS;AAAA,YACT,MAAM;AAAA,YACN,OAAO;AAAA,UAAA;AAAA,QACT;AAAA,MACF;AAAA,MAEJ,CAACD,GAAmBC,CAAsB;AAAA,IAAA,GAItCO,KAAehD;AAAA,MACnB,MACEC;AAAA,QACE2C,EAAc,EAAE,SAAA9B,GAAS,MAAAD,GAAM,OAAAqB,GAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAKtCnB,MACGF,MAAS,OACN,SACAA,MAAS,OACPX,EAAgB,OAAO,IAAI,IAC3BA,EAAgB,OAAO,IAAI;AAAA,SAClCc,KAAaoB,KAAmBJ,OAC9BnB,MAAS,OACN,SACAA,MAAS,OACPX,EAAgB,OAAO,IAAI,IAC3BA,EAAgB,OAAO,IAAI;AAAA,QACnCiB;AAAA,MAAA;AAAA,MAEJ;AAAA,QACEyB;AAAA,QACA9B;AAAA,QACAD;AAAA,QACAqB;AAAA,QACAnB;AAAA,QACAC;AAAA,QACAoB;AAAA,QACAJ;AAAA,QACAb;AAAA,MAAA;AAAA,IACF,GAII8B,KAAejD;AAAA,MACnB,MACEC;AAAA,QACE;AAAA,QACAE,EAAqB,OAAO;AAAA,QAC5BD,EAAgB,MAAM,IAAI;AAAA,QAC1BkB,KAAY;AAAA,MAAA;AAAA,MAEhB,CAACA,CAAQ;AAAA,IAAA,GAIL8B,IAAWlD;AAAA,MACf,MAAOa,MAAS,OAAO,YAAYA,MAAS,OAAO,YAAY;AAAA,MAC/D,CAACA,CAAI;AAAA,IAAA,GAGDsC,KAAenD;AAAA,MACnB,MAAOa,MAAS,OAAO,UAAUA,MAAS,OAAO,YAAY;AAAA,MAC7D,CAACA,CAAI;AAAA,IAAA,GAIDuC,KAAcV;AAAA,MAClB,CAACW,MAAwB;;AAEvB,YADAA,EAAE,gBAAA,GACEnC;AACF,UAAAA,EAAA;AAAA,iBACSK,GAAU;AAEnB,gBAAM+B,KAAe9C,IAAA6C,EAAE,cACpB,QAAQ,WAAW,MADD,gBAAA7C,EAEjB,cAAc;AAClB,cAAI8C,GAAc;AAChB,kBAAMC,IAAiB;AAAA,cACrB,QAAQD;AAAA,cACR,eAAeA;AAAA,cACf,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,kBAAkB;AAAA,cAClB,YAAY;AAAA,cACZ,WAAW;AAAA,cACX,aAAa,IAAI,MAAM,QAAQ;AAAA,cAC/B,gBAAgB,MAAM;AAAA,cAAC;AAAA,cACvB,iBAAiB,MAAM;AAAA,cAAC;AAAA,cACxB,SAAS,MAAM;AAAA,cAAC;AAAA,cAChB,WAAW,KAAK,IAAA;AAAA,YAAI;AAEtB,mBAAO,eAAeC,EAAe,QAAQ,SAAS;AAAA,cACpD,OAAO;AAAA,cACP,UAAU;AAAA,YAAA,CACX,GACD,OAAO,eAAeA,EAAe,eAAe,SAAS;AAAA,cAC3D,OAAO;AAAA,cACP,UAAU;AAAA,YAAA,CACX,GACDhC,EAASgC,CAAc;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,MACA,CAACrC,GAASK,CAAQ;AAAA,IAAA,GAIdiC,KAAuBd,EAAY,MAAM;AAC7C,MAAAZ,GAAgB,CAAC2B,MAAS,CAACA,CAAI;AAAA,IACjC,GAAG,CAAA,CAAE;AAEL,WACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,UACZ,UAAA;AAAA,MAAA9C,uBACE,SAAA,EAAM,SAASgB,GAAS,WAAWqB,IACjC,UAAArC,GACH;AAAA,MAEF,gBAAA8C,EAAC,OAAA,EAAI,WAAU,YACZ,UAAA;AAAA,QAAA3C,KACC,gBAAAV;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,mBAAmB8C,EAAY;AAAA,YAE1C,UAAA,gBAAA9C,EAAC,OAAA,EAAI,WAAW6C,GAAW,UAAAnC,EAAA,CAAS;AAAA,UAAA;AAAA,QAAA;AAAA,QAGxC,gBAAAV;AAAA,UAAC;AAAA,UAAAsD,EAAA;AAAA,YACC,IAAI/B;AAAA,YACJ,KAAAnB;AAAA,YACA,MAAMwB;AAAA,YACN,WAAWe;AAAA,YACX,UAAA5B;AAAA,YACA,OAAAE;AAAA,YACA,UAAAC;AAAA,YACA,gBAAc7B;AAAA,YACd,iBAAe8B,EAAM;AAAA,YACrB,oBAAkB3B,KAAWC;AAAA,YAC7B,0BAAwB;AAAA,aACpB0B;AAAA,QAAA;AAAA,QAEN,gBAAAkC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,qDAAqDxD,EAAgB,MAAM,KAAK,CAAC;AAAA,YAE3F,UAAA;AAAA,cAAAkC,KACC,gBAAA/B;AAAA,gBAACuD;AAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,SAASR;AAAA,kBACT,WAAW,UAAUlD,EAAgB,MAAM,GAAG,CAAC;AAAA,kBAC/C,cAAW;AAAA,kBAEX,UAAA,gBAAAG,EAACwD,IAAA,EAAE,WAAWX,EAAA,CAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,cAG3BlB,KACC,gBAAA3B;AAAA,gBAACuD;AAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,SAASJ;AAAA,kBACT,WAAW,UAAUtD,EAAgB,MAAM,GAAG,CAAC;AAAA,kBAC/C,cAAY2B,IAAe,kBAAkB;AAAA,kBAE5C,UAAAA,sBACEiC,IAAA,EAAO,WAAWZ,GAAU,IAE7B,gBAAA7C,EAAC0D,IAAA,EAAI,WAAWb,EAAA,CAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,cAI/BlC,KAAa,CAACoB,KAAmB,CAACJ,KACjC,gBAAA3B;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAW,oDAAoD6C,CAAQ;AAAA,kBAEtE,UAAAlC;AAAA,gBAAA;AAAA,cAAA;AAAA,YACH;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ,GACF;AAAA,OACEtB,KAASC,KAAWC,MACpB,gBAAAS;AAAA,QAACb;AAAA,QAAA;AAAA,UACC,OAAAE;AAAA,UACA,SAAAC;AAAA,UACA,YAAAC;AAAA,UACA,SAAAC;AAAA,UACA,UAAAC;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,GAEJ;AAAA,EAEJ,CAAC;AACH;AAEAQ,GAAM,cAAc;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Label.js","sources":["../../../../../src/ui/primitives/Label/Label.tsx"],"sourcesContent":["import type { LabelHTMLAttributes } from \"react\";\nimport { forwardRef, memo } from \"react\";\nimport {\n getTypographySize,\n getTypographyWeight,\n} from \"../../tokens/typography\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn } from \"../../utils\";\n\ninterface Props extends LabelHTMLAttributes<HTMLLabelElement> {\n variant?: \"default\" | \"required\" | \"optional\";\n children: React.ReactNode;\n}\n\nconst labelBaseClasses = cn(\n \"block\",\n getTypographySize(\"label\"),\n getTypographyWeight(\"label\"),\n \"text-fg-primary\",\n);\n\nconst labelVariantClasses: Record<NonNullable<Props[\"variant\"]>, string> = {\n default: \"\",\n required: cn(\n \"after:content-['*']\",\n `after:${getSpacingClass(\"0.5\", \"ml\")}`,\n \"after:text-fg-error\",\n ),\n optional: cn(\n \"after:content-['(optional)']\",\n `after:${getSpacingClass(\"xs\", \"ml\")}`,\n \"after:text-fg-tertiary\",\n \"after:font-normal\",\n ),\n};\n\n/**\n * Label Component\n *\n * A styled label component for form inputs.\n * Follows Atomic Design principles as an Atom component.\n *\n * @example\n * ```tsx\n * <Label htmlFor=\"email\" variant=\"required\">\n * Email Address\n * </Label>\n * ```\n */\nconst Label = memo(\n forwardRef<HTMLLabelElement, Props>(function Label(\n { variant = \"default\", className = \"\", children, ...props },\n ref,\n ) {\n const classes = cn(\n labelBaseClasses,\n labelVariantClasses[variant],\n className,\n );\n\n return (\n <label ref={ref} className={classes} {...props}>\n {children}\n </label>\n );\n }),\n);\n\nLabel.displayName = \"Label\";\n\nexport default Label;\n"],"names":["labelBaseClasses","cn","getTypographySize","getTypographyWeight","labelVariantClasses","getSpacingClass","Label","memo","forwardRef","_a","ref","_b","variant","className","children","props","__objRest","classes","__spreadProps","__spreadValues"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,MAAMA,IAAmBC;AAAA,EACvB;AAAA,EACAC,EAAkB,OAAO;AAAA,EACzBC,EAAoB,OAAO;AAAA,EAC3B;AACF,GAEMC,IAAqE;AAAA,EACzE,SAAS;AAAA,EACT,UAAUH;AAAA,IACR;AAAA,IACA,SAASI,EAAgB,OAAO,IAAI,CAAC;AAAA,IACrC;AAAA,EAAA;AAAA,EAEF,UAAUJ;AAAA,IACR;AAAA,IACA,SAASI,EAAgB,MAAM,IAAI,CAAC;AAAA,IACpC;AAAA,IACA;AAAA,EAAA;AAEJ,GAeMC,IAAQC;AAAA,EACZC,EAAoC,SAClCC,GACAC,GACA;AAFA,QAAAC,IAAAF,GAAE,WAAAG,IAAU,WAAW,WAAAC,IAAY,IAAI,UAAAC,MAAvCH,GAAoDI,IAAAC,EAApDL,GAAoD,CAAlD,WAAqB,aAAgB;AAGvC,UAAMM,IAAUhB;AAAA,MACdD;AAAA,MACAI,EAAoBQ,CAAO;AAAA,MAC3BC;AAAA,IAAA;AAGF,6BACG,SAAAK,EAAAC,EAAA,EAAM,KAAAT,GAAU,WAAWO,KAAaF,IAAxC,EACE,UAAAD,IACH;AAAA,EAEJ,CAAC;AACH;AAEAR,EAAM,cAAc;"}
1
+ {"version":3,"file":"Label.js","sources":["../../../../../src/ui/primitives/Label/Label.tsx"],"sourcesContent":["import type { LabelHTMLAttributes } from \"react\";\nimport { forwardRef, memo } from \"react\";\nimport {\n getTypographySize,\n getTypographyWeight,\n} from \"../../tokens/typography\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { cn } from \"../../utils\";\n\ninterface Props extends LabelHTMLAttributes<HTMLLabelElement> {\n variant?: \"default\" | \"required\" | \"optional\";\n children: React.ReactNode;\n}\n\nconst labelBaseClasses = cn(\n \"block\",\n getTypographySize(\"label\"),\n getTypographyWeight(\"label\"),\n \"text-fg-primary\",\n);\n\nconst labelVariantClasses: Record<NonNullable<Props[\"variant\"]>, string> = {\n default: \"\",\n required: cn(\n \"after:content-['*']\",\n `after:${getSpacingClass(\"0.5\", \"ml\")}`,\n \"after:text-fg-error\",\n ),\n optional: cn(\n \"after:content-['(optional)']\",\n `after:${getSpacingClass(\"xs\", \"ml\")}`,\n \"after:text-fg-tertiary\",\n \"after:font-normal\",\n ),\n};\n\n/**\n * Label Component\n *\n * A styled label component for form inputs.\n *\n * @example\n * ```tsx\n * <Label htmlFor=\"email\" variant=\"required\">\n * Email Address\n * </Label>\n * ```\n */\nconst Label = memo(\n forwardRef<HTMLLabelElement, Props>(function Label(\n { variant = \"default\", className = \"\", children, ...props },\n ref,\n ) {\n const classes = cn(\n labelBaseClasses,\n labelVariantClasses[variant],\n className,\n );\n\n return (\n <label ref={ref} className={classes} {...props}>\n {children}\n </label>\n );\n }),\n);\n\nLabel.displayName = \"Label\";\n\nexport default Label;\n"],"names":["labelBaseClasses","cn","getTypographySize","getTypographyWeight","labelVariantClasses","getSpacingClass","Label","memo","forwardRef","_a","ref","_b","variant","className","children","props","__objRest","classes","__spreadProps","__spreadValues"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,MAAMA,IAAmBC;AAAA,EACvB;AAAA,EACAC,EAAkB,OAAO;AAAA,EACzBC,EAAoB,OAAO;AAAA,EAC3B;AACF,GAEMC,IAAqE;AAAA,EACzE,SAAS;AAAA,EACT,UAAUH;AAAA,IACR;AAAA,IACA,SAASI,EAAgB,OAAO,IAAI,CAAC;AAAA,IACrC;AAAA,EAAA;AAAA,EAEF,UAAUJ;AAAA,IACR;AAAA,IACA,SAASI,EAAgB,MAAM,IAAI,CAAC;AAAA,IACpC;AAAA,IACA;AAAA,EAAA;AAEJ,GAcMC,IAAQC;AAAA,EACZC,EAAoC,SAClCC,GACAC,GACA;AAFA,QAAAC,IAAAF,GAAE,WAAAG,IAAU,WAAW,WAAAC,IAAY,IAAI,UAAAC,MAAvCH,GAAoDI,IAAAC,EAApDL,GAAoD,CAAlD,WAAqB,aAAgB;AAGvC,UAAMM,IAAUhB;AAAA,MACdD;AAAA,MACAI,EAAoBQ,CAAO;AAAA,MAC3BC;AAAA,IAAA;AAGF,6BACG,SAAAK,EAAAC,EAAA,EAAM,KAAAT,GAAU,WAAWO,KAAaF,IAAxC,EACE,UAAAD,IACH;AAAA,EAEJ,CAAC;AACH;AAEAR,EAAM,cAAc;"}
@@ -1 +1 @@
1
- {"version":3,"file":"NavLink.js","sources":["../../../../../src/ui/primitives/NavLink/NavLink.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * NavLink Component\n *\n * Navigation link component with active state detection and Next.js integration.\n *\n * @see EPIC-001: NavLink Component (Atom)\n * @see RFC-001: NavLink Hook Strategy (APPROVED)\n * @see RFC-002: Next.js Integration Strategy (APPROVED)\n * @see ADR-001: Active State Detection (ACCEPTED)\n */\n\nimport React, { forwardRef, useMemo, useCallback } from \"react\";\nimport type { NavLinkProps } from \"./types\";\nimport { useNavLink } from \"./hooks/useNavLink\";\nimport { cn, cva } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { getTypographySize } from \"../../tokens/typography\";\nimport { getRadiusClass } from \"../../tokens/radius\";\n\n/**\n * NavLink Variants using CVA\n * Type-safe variant system for NavLink component\n */\nconst navLinkVariants = cva(\n // Base classes\n cn(\n \"inline-flex\",\n \"items-center\",\n \"transition-colors\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-offset-2\",\n \"disabled:opacity-50\",\n \"disabled:cursor-not-allowed\",\n \"disabled:pointer-events-none\",\n \"no-underline\",\n ),\n {\n variants: {\n variant: {\n default: cn(\n \"text-fg-primary\",\n \"hover:opacity-80\",\n \"focus-visible:opacity-100\",\n \"focus:ring-line-brand\",\n ),\n underline: cn(\n \"text-fg-primary\",\n \"hover:opacity-80\",\n \"focus-visible:opacity-100\",\n \"border-b-2\",\n \"border-transparent\",\n \"hover:border-current\",\n \"focus:ring-line-brand\",\n ),\n background: cn(\n \"text-fg-primary\",\n \"hover:bg-surface-hover\",\n getRadiusClass(\"md\"),\n \"focus:ring-line-brand\",\n ),\n },\n size: {\n sm: cn(\n getSpacingClass(\"sm\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"bodySmall\"),\n ),\n md: cn(\n getSpacingClass(\"base\", \"px\"),\n getSpacingClass(\"sm\", \"py\"),\n getTypographySize(\"body\"),\n ),\n lg: cn(\n getSpacingClass(\"lg\", \"px\"),\n getSpacingClass(\"md\", \"py\"),\n getTypographySize(\"bodyLarge\"),\n ),\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n compoundVariants: [\n {\n variant: \"underline\",\n size: \"sm\",\n class: getSpacingClass(\"0.5\", \"pb\"),\n },\n {\n variant: \"underline\",\n size: \"md\",\n class: getSpacingClass(\"xs\", \"pb\"),\n },\n {\n variant: \"underline\",\n size: \"lg\",\n class: getSpacingClass(\"1.5\", \"pb\"),\n },\n {\n variant: \"background\",\n size: \"sm\",\n class: getSpacingClass(\"xs\", \"px\"),\n },\n {\n variant: \"background\",\n size: \"md\",\n class: getSpacingClass(\"sm\", \"px\"),\n },\n {\n variant: \"background\",\n size: \"lg\",\n class: getSpacingClass(\"base\", \"px\"),\n },\n ],\n },\n);\n\n/**\n * NavLink Component\n *\n * Navigation link with active state detection and Next.js integration.\n *\n * @example\n * ```tsx\n * <NavLink href=\"/home\">Home</NavLink>\n * <NavLink href=\"/about\" variant=\"underline\" active>About</NavLink>\n * <NavLink href=\"/contact\" variant=\"background\" size=\"lg\">Contact</NavLink>\n * ```\n *\n * Note: Auto-detection of active state via usePathname is deferred to a future enhancement\n * to avoid issues with conditional hook calls. For now, use the `active` prop manually\n * or implement pathname detection in the parent component.\n */\nexport const NavLink = forwardRef<HTMLAnchorElement, NavLinkProps>(\n function NavLink(\n {\n href,\n children,\n active,\n disabled = false,\n variant = \"default\",\n size = \"md\",\n as,\n className,\n \"aria-label\": ariaLabel,\n onClick,\n onKeyDown,\n ...props\n },\n ref,\n ) {\n // Calculate active state\n // Priority: manual active > false (ADR-001)\n // TODO: Add auto-detect via usePathname in future enhancement\n // This requires a wrapper component pattern to avoid conditional hook calls\n const calculatedActive = useMemo(() => {\n // Manual active prop has priority (ADR-001)\n if (active !== undefined) {\n return active;\n }\n\n // Default to false\n // TODO: Auto-detect using usePathname (if Next.js available)\n return false;\n }, [active]);\n\n // Use hook for Next.js Link integration\n const { NextLink } = useNavLink({ href, active: calculatedActive });\n\n // Determine Link component\n // Priority: as prop > NextLink (auto-detected) > 'a' (RFC-002)\n const LinkComponent: React.ElementType = as || NextLink || \"a\";\n\n // Active state classes\n const activeClasses = useMemo(() => {\n if (!calculatedActive) return \"\";\n\n switch (variant) {\n case \"underline\":\n return cn(\n \"border-b-2\",\n \"border-line-brand\",\n \"text-fg-brand-emphasis\",\n );\n case \"background\":\n return cn(\"bg-surface-brand-muted\", \"text-fg-brand-emphasis\");\n case \"default\":\n default:\n return cn(\"text-fg-brand-emphasis\", \"font-semibold\");\n }\n }, [calculatedActive, variant]);\n\n // Handle disabled state\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLAnchorElement>) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e);\n },\n [disabled, onClick],\n );\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLAnchorElement>) => {\n if (disabled) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n e.stopPropagation();\n }\n return;\n }\n onKeyDown?.(e);\n },\n [disabled, onKeyDown],\n );\n\n // Prepare props for LinkComponent\n // Next.js Link has different prop structure, so we need to handle it\n const linkProps = useMemo(() => {\n const baseProps = {\n className: cn(\n navLinkVariants({ variant, size }),\n activeClasses,\n disabled && \"opacity-50 cursor-not-allowed pointer-events-none\",\n className,\n ),\n \"aria-current\": calculatedActive ? \"page\" : undefined,\n \"aria-disabled\": disabled ? true : undefined,\n \"aria-label\": ariaLabel,\n tabIndex: disabled ? -1 : undefined,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n \"data-active\": calculatedActive,\n \"data-disabled\": disabled,\n ...props,\n };\n\n // For Next.js Link, we need to pass href differently\n if (NextLink && !as) {\n return {\n ...baseProps,\n href: disabled ? undefined : href,\n };\n }\n\n // For regular anchor or custom component\n return {\n ...baseProps,\n href: disabled ? undefined : href,\n };\n }, [\n variant,\n size,\n activeClasses,\n disabled,\n className,\n calculatedActive,\n ariaLabel,\n handleClick,\n handleKeyDown,\n href,\n NextLink,\n as,\n props,\n ]);\n\n return (\n <LinkComponent ref={ref} {...linkProps}>\n {children}\n </LinkComponent>\n );\n },\n);\n\nNavLink.displayName = \"NavLink\";\n\nexport default NavLink;\n"],"names":["navLinkVariants","cva","cn","getRadiusClass","getSpacingClass","getTypographySize","NavLink","forwardRef","_a","ref","_b","href","children","active","disabled","variant","size","as","className","ariaLabel","onClick","onKeyDown","props","__objRest","calculatedActive","useMemo","NextLink","useNavLink","LinkComponent","activeClasses","handleClick","useCallback","e","handleKeyDown","linkProps","baseProps","__spreadValues","__spreadProps","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"NavLink.js","sources":["../../../../../src/ui/primitives/NavLink/NavLink.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * NavLink Component\n *\n * Navigation link component with active state detection and Next.js integration.\n *\n * @see EPIC-001: NavLink Component\n * @see RFC-001: NavLink Hook Strategy (APPROVED)\n * @see RFC-002: Next.js Integration Strategy (APPROVED)\n * @see ADR-001: Active State Detection (ACCEPTED)\n */\n\nimport React, { forwardRef, useMemo, useCallback } from \"react\";\nimport type { NavLinkProps } from \"./types\";\nimport { useNavLink } from \"./hooks/useNavLink\";\nimport { cn, cva } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { getTypographySize } from \"../../tokens/typography\";\nimport { getRadiusClass } from \"../../tokens/radius\";\n\n/**\n * NavLink Variants using CVA\n * Type-safe variant system for NavLink component\n */\nconst navLinkVariants = cva(\n // Base classes\n cn(\n \"inline-flex\",\n \"items-center\",\n \"transition-colors\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-offset-2\",\n \"disabled:opacity-50\",\n \"disabled:cursor-not-allowed\",\n \"disabled:pointer-events-none\",\n \"no-underline\",\n ),\n {\n variants: {\n variant: {\n default: cn(\n \"text-fg-primary\",\n \"hover:opacity-80\",\n \"focus-visible:opacity-100\",\n \"focus:ring-line-brand\",\n ),\n underline: cn(\n \"text-fg-primary\",\n \"hover:opacity-80\",\n \"focus-visible:opacity-100\",\n \"border-b-2\",\n \"border-transparent\",\n \"hover:border-current\",\n \"focus:ring-line-brand\",\n ),\n background: cn(\n \"text-fg-primary\",\n \"hover:bg-surface-hover\",\n getRadiusClass(\"md\"),\n \"focus:ring-line-brand\",\n ),\n },\n size: {\n sm: cn(\n getSpacingClass(\"sm\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"bodySmall\"),\n ),\n md: cn(\n getSpacingClass(\"base\", \"px\"),\n getSpacingClass(\"sm\", \"py\"),\n getTypographySize(\"body\"),\n ),\n lg: cn(\n getSpacingClass(\"lg\", \"px\"),\n getSpacingClass(\"md\", \"py\"),\n getTypographySize(\"bodyLarge\"),\n ),\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n compoundVariants: [\n {\n variant: \"underline\",\n size: \"sm\",\n class: getSpacingClass(\"0.5\", \"pb\"),\n },\n {\n variant: \"underline\",\n size: \"md\",\n class: getSpacingClass(\"xs\", \"pb\"),\n },\n {\n variant: \"underline\",\n size: \"lg\",\n class: getSpacingClass(\"1.5\", \"pb\"),\n },\n {\n variant: \"background\",\n size: \"sm\",\n class: getSpacingClass(\"xs\", \"px\"),\n },\n {\n variant: \"background\",\n size: \"md\",\n class: getSpacingClass(\"sm\", \"px\"),\n },\n {\n variant: \"background\",\n size: \"lg\",\n class: getSpacingClass(\"base\", \"px\"),\n },\n ],\n },\n);\n\n/**\n * NavLink Component\n *\n * Navigation link with active state detection and Next.js integration.\n *\n * @example\n * ```tsx\n * <NavLink href=\"/home\">Home</NavLink>\n * <NavLink href=\"/about\" variant=\"underline\" active>About</NavLink>\n * <NavLink href=\"/contact\" variant=\"background\" size=\"lg\">Contact</NavLink>\n * ```\n *\n * Note: Auto-detection of active state via usePathname is deferred to a future enhancement\n * to avoid issues with conditional hook calls. For now, use the `active` prop manually\n * or implement pathname detection in the parent component.\n */\nexport const NavLink = forwardRef<HTMLAnchorElement, NavLinkProps>(\n function NavLink(\n {\n href,\n children,\n active,\n disabled = false,\n variant = \"default\",\n size = \"md\",\n as,\n className,\n \"aria-label\": ariaLabel,\n onClick,\n onKeyDown,\n ...props\n },\n ref,\n ) {\n // Calculate active state\n // Priority: manual active > false (ADR-001)\n // TODO: Add auto-detect via usePathname in future enhancement\n // This requires a wrapper component pattern to avoid conditional hook calls\n const calculatedActive = useMemo(() => {\n // Manual active prop has priority (ADR-001)\n if (active !== undefined) {\n return active;\n }\n\n // Default to false\n // TODO: Auto-detect using usePathname (if Next.js available)\n return false;\n }, [active]);\n\n // Use hook for Next.js Link integration\n const { NextLink } = useNavLink({ href, active: calculatedActive });\n\n // Determine Link component\n // Priority: as prop > NextLink (auto-detected) > 'a' (RFC-002)\n const LinkComponent: React.ElementType = as || NextLink || \"a\";\n\n // Active state classes\n const activeClasses = useMemo(() => {\n if (!calculatedActive) return \"\";\n\n switch (variant) {\n case \"underline\":\n return cn(\n \"border-b-2\",\n \"border-line-brand\",\n \"text-fg-brand-emphasis\",\n );\n case \"background\":\n return cn(\"bg-surface-brand-muted\", \"text-fg-brand-emphasis\");\n case \"default\":\n default:\n return cn(\"text-fg-brand-emphasis\", \"font-semibold\");\n }\n }, [calculatedActive, variant]);\n\n // Handle disabled state\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLAnchorElement>) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e);\n },\n [disabled, onClick],\n );\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLAnchorElement>) => {\n if (disabled) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n e.stopPropagation();\n }\n return;\n }\n onKeyDown?.(e);\n },\n [disabled, onKeyDown],\n );\n\n // Prepare props for LinkComponent\n // Next.js Link has different prop structure, so we need to handle it\n const linkProps = useMemo(() => {\n const baseProps = {\n className: cn(\n navLinkVariants({ variant, size }),\n activeClasses,\n disabled && \"opacity-50 cursor-not-allowed pointer-events-none\",\n className,\n ),\n \"aria-current\": calculatedActive ? \"page\" : undefined,\n \"aria-disabled\": disabled ? true : undefined,\n \"aria-label\": ariaLabel,\n tabIndex: disabled ? -1 : undefined,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n \"data-active\": calculatedActive,\n \"data-disabled\": disabled,\n ...props,\n };\n\n // For Next.js Link, we need to pass href differently\n if (NextLink && !as) {\n return {\n ...baseProps,\n href: disabled ? undefined : href,\n };\n }\n\n // For regular anchor or custom component\n return {\n ...baseProps,\n href: disabled ? undefined : href,\n };\n }, [\n variant,\n size,\n activeClasses,\n disabled,\n className,\n calculatedActive,\n ariaLabel,\n handleClick,\n handleKeyDown,\n href,\n NextLink,\n as,\n props,\n ]);\n\n return (\n <LinkComponent ref={ref} {...linkProps}>\n {children}\n </LinkComponent>\n );\n },\n);\n\nNavLink.displayName = \"NavLink\";\n\nexport default NavLink;\n"],"names":["navLinkVariants","cva","cn","getRadiusClass","getSpacingClass","getTypographySize","NavLink","forwardRef","_a","ref","_b","href","children","active","disabled","variant","size","as","className","ariaLabel","onClick","onKeyDown","props","__objRest","calculatedActive","useMemo","NextLink","useNavLink","LinkComponent","activeClasses","handleClick","useCallback","e","handleKeyDown","linkProps","baseProps","__spreadValues","__spreadProps","jsx"],"mappings":"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"}