@karakuri-ui/react 0.2.3 → 0.3.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 (244) hide show
  1. package/README.md +0 -1
  2. package/dist/components/ui/accordion.d.mts +40 -0
  3. package/dist/components/ui/accordion.d.ts +40 -0
  4. package/dist/components/ui/accordion.js +215 -0
  5. package/dist/components/ui/accordion.js.map +1 -0
  6. package/dist/components/ui/accordion.mjs +176 -0
  7. package/dist/components/ui/accordion.mjs.map +1 -0
  8. package/dist/components/ui/alert.d.mts +38 -0
  9. package/dist/components/ui/alert.d.ts +38 -0
  10. package/dist/components/ui/alert.js +217 -0
  11. package/dist/components/ui/alert.js.map +1 -0
  12. package/dist/components/ui/alert.mjs +180 -0
  13. package/dist/components/ui/alert.mjs.map +1 -0
  14. package/dist/components/ui/avatar.d.mts +223 -0
  15. package/dist/components/ui/avatar.d.ts +223 -0
  16. package/dist/components/ui/avatar.js +245 -0
  17. package/dist/components/ui/avatar.js.map +1 -0
  18. package/dist/components/ui/avatar.mjs +204 -0
  19. package/dist/components/ui/avatar.mjs.map +1 -0
  20. package/dist/components/ui/badge.d.mts +31 -0
  21. package/dist/components/ui/badge.d.ts +31 -0
  22. package/dist/components/ui/badge.js +205 -0
  23. package/dist/components/ui/badge.js.map +1 -0
  24. package/dist/components/ui/badge.mjs +170 -0
  25. package/dist/components/ui/badge.mjs.map +1 -0
  26. package/dist/components/ui/breadcrumb.d.mts +46 -0
  27. package/dist/components/ui/breadcrumb.d.ts +46 -0
  28. package/dist/components/ui/breadcrumb.js +201 -0
  29. package/dist/components/ui/breadcrumb.js.map +1 -0
  30. package/dist/components/ui/breadcrumb.mjs +160 -0
  31. package/dist/components/ui/breadcrumb.mjs.map +1 -0
  32. package/dist/components/ui/button-group.d.mts +22 -0
  33. package/dist/components/ui/button-group.d.ts +22 -0
  34. package/dist/components/ui/button-group.js +107 -0
  35. package/dist/components/ui/button-group.js.map +1 -0
  36. package/dist/components/ui/button-group.mjs +72 -0
  37. package/dist/components/ui/button-group.mjs.map +1 -0
  38. package/dist/components/ui/button.d.mts +31 -0
  39. package/dist/components/ui/button.d.ts +31 -0
  40. package/dist/components/ui/button.js +176 -0
  41. package/dist/components/ui/button.js.map +1 -0
  42. package/dist/components/ui/button.mjs +141 -0
  43. package/dist/components/ui/button.mjs.map +1 -0
  44. package/dist/components/ui/card.d.mts +60 -0
  45. package/dist/components/ui/card.d.ts +60 -0
  46. package/dist/components/ui/card.js +361 -0
  47. package/dist/components/ui/card.js.map +1 -0
  48. package/dist/components/ui/card.mjs +319 -0
  49. package/dist/components/ui/card.mjs.map +1 -0
  50. package/dist/{chart.d.mts → components/ui/chart.d.mts} +2 -18
  51. package/dist/{chart.d.ts → components/ui/chart.d.ts} +2 -18
  52. package/dist/{chart.js → components/ui/chart.js} +30 -55
  53. package/dist/components/ui/chart.js.map +1 -0
  54. package/dist/{chart.mjs → components/ui/chart.mjs} +22 -46
  55. package/dist/components/ui/chart.mjs.map +1 -0
  56. package/dist/components/ui/checkbox.d.mts +24 -0
  57. package/dist/components/ui/checkbox.d.ts +24 -0
  58. package/dist/components/ui/checkbox.js +173 -0
  59. package/dist/components/ui/checkbox.js.map +1 -0
  60. package/dist/components/ui/checkbox.mjs +138 -0
  61. package/dist/components/ui/checkbox.mjs.map +1 -0
  62. package/dist/components/ui/divider.d.mts +27 -0
  63. package/dist/components/ui/divider.d.ts +27 -0
  64. package/dist/components/ui/divider.js +147 -0
  65. package/dist/components/ui/divider.js.map +1 -0
  66. package/dist/components/ui/divider.mjs +112 -0
  67. package/dist/components/ui/divider.mjs.map +1 -0
  68. package/dist/components/ui/drawer.d.mts +36 -0
  69. package/dist/components/ui/drawer.d.ts +36 -0
  70. package/dist/components/ui/drawer.js +211 -0
  71. package/dist/components/ui/drawer.js.map +1 -0
  72. package/dist/components/ui/drawer.mjs +165 -0
  73. package/dist/components/ui/drawer.mjs.map +1 -0
  74. package/dist/components/ui/dropdown.d.mts +34 -0
  75. package/dist/components/ui/dropdown.d.ts +34 -0
  76. package/dist/components/ui/dropdown.js +295 -0
  77. package/dist/components/ui/dropdown.js.map +1 -0
  78. package/dist/components/ui/dropdown.mjs +248 -0
  79. package/dist/components/ui/dropdown.mjs.map +1 -0
  80. package/dist/components/ui/field.d.mts +26 -0
  81. package/dist/components/ui/field.d.ts +26 -0
  82. package/dist/components/ui/field.js +141 -0
  83. package/dist/components/ui/field.js.map +1 -0
  84. package/dist/components/ui/field.mjs +103 -0
  85. package/dist/components/ui/field.mjs.map +1 -0
  86. package/dist/components/ui/icon-button.d.mts +20 -0
  87. package/dist/components/ui/icon-button.d.ts +20 -0
  88. package/dist/components/ui/icon-button.js +147 -0
  89. package/dist/components/ui/icon-button.js.map +1 -0
  90. package/dist/components/ui/icon-button.mjs +112 -0
  91. package/dist/components/ui/icon-button.mjs.map +1 -0
  92. package/dist/components/ui/index.d.mts +55 -0
  93. package/dist/components/ui/index.d.ts +55 -0
  94. package/dist/components/ui/index.js +468 -0
  95. package/dist/components/ui/index.js.map +1 -0
  96. package/dist/components/ui/index.mjs +242 -0
  97. package/dist/components/ui/index.mjs.map +1 -0
  98. package/dist/components/ui/input.d.mts +20 -0
  99. package/dist/components/ui/input.d.ts +20 -0
  100. package/dist/components/ui/input.js +250 -0
  101. package/dist/components/ui/input.js.map +1 -0
  102. package/dist/components/ui/input.mjs +215 -0
  103. package/dist/components/ui/input.mjs.map +1 -0
  104. package/dist/components/ui/metric-card.d.mts +38 -0
  105. package/dist/components/ui/metric-card.d.ts +38 -0
  106. package/dist/components/ui/metric-card.js +250 -0
  107. package/dist/components/ui/metric-card.js.map +1 -0
  108. package/dist/components/ui/metric-card.mjs +209 -0
  109. package/dist/components/ui/metric-card.mjs.map +1 -0
  110. package/dist/components/ui/modal.d.mts +47 -0
  111. package/dist/components/ui/modal.d.ts +47 -0
  112. package/dist/components/ui/modal.js +371 -0
  113. package/dist/components/ui/modal.js.map +1 -0
  114. package/dist/components/ui/modal.mjs +313 -0
  115. package/dist/components/ui/modal.mjs.map +1 -0
  116. package/dist/components/ui/navigation-menu.d.mts +120 -0
  117. package/dist/components/ui/navigation-menu.d.ts +120 -0
  118. package/dist/components/ui/navigation-menu.js +521 -0
  119. package/dist/components/ui/navigation-menu.js.map +1 -0
  120. package/dist/components/ui/navigation-menu.mjs +478 -0
  121. package/dist/components/ui/navigation-menu.mjs.map +1 -0
  122. package/dist/components/ui/pagination.d.mts +113 -0
  123. package/dist/components/ui/pagination.d.ts +113 -0
  124. package/dist/components/ui/pagination.js +484 -0
  125. package/dist/components/ui/pagination.js.map +1 -0
  126. package/dist/components/ui/pagination.mjs +438 -0
  127. package/dist/components/ui/pagination.mjs.map +1 -0
  128. package/dist/components/ui/popover.d.mts +29 -0
  129. package/dist/components/ui/popover.d.ts +29 -0
  130. package/dist/components/ui/popover.js +165 -0
  131. package/dist/components/ui/popover.js.map +1 -0
  132. package/dist/components/ui/popover.mjs +124 -0
  133. package/dist/components/ui/popover.mjs.map +1 -0
  134. package/dist/components/ui/progress.d.mts +35 -0
  135. package/dist/components/ui/progress.d.ts +35 -0
  136. package/dist/components/ui/progress.js +194 -0
  137. package/dist/components/ui/progress.js.map +1 -0
  138. package/dist/components/ui/progress.mjs +159 -0
  139. package/dist/components/ui/progress.mjs.map +1 -0
  140. package/dist/components/ui/radio-group.d.mts +35 -0
  141. package/dist/components/ui/radio-group.d.ts +35 -0
  142. package/dist/components/ui/radio-group.js +174 -0
  143. package/dist/components/ui/radio-group.js.map +1 -0
  144. package/dist/components/ui/radio-group.mjs +137 -0
  145. package/dist/components/ui/radio-group.mjs.map +1 -0
  146. package/dist/components/ui/segmented.d.mts +25 -0
  147. package/dist/components/ui/segmented.d.ts +25 -0
  148. package/dist/components/ui/segmented.js +238 -0
  149. package/dist/components/ui/segmented.js.map +1 -0
  150. package/dist/components/ui/segmented.mjs +201 -0
  151. package/dist/components/ui/segmented.mjs.map +1 -0
  152. package/dist/components/ui/select.d.mts +20 -0
  153. package/dist/components/ui/select.d.ts +20 -0
  154. package/dist/components/ui/select.js +308 -0
  155. package/dist/components/ui/select.js.map +1 -0
  156. package/dist/components/ui/select.mjs +267 -0
  157. package/dist/components/ui/select.mjs.map +1 -0
  158. package/dist/components/ui/skeleton.d.mts +26 -0
  159. package/dist/components/ui/skeleton.d.ts +26 -0
  160. package/dist/components/ui/skeleton.js +144 -0
  161. package/dist/components/ui/skeleton.js.map +1 -0
  162. package/dist/components/ui/skeleton.mjs +109 -0
  163. package/dist/components/ui/skeleton.mjs.map +1 -0
  164. package/dist/components/ui/slider.d.mts +38 -0
  165. package/dist/components/ui/slider.d.ts +38 -0
  166. package/dist/components/ui/slider.js +180 -0
  167. package/dist/components/ui/slider.js.map +1 -0
  168. package/dist/components/ui/slider.mjs +145 -0
  169. package/dist/components/ui/slider.mjs.map +1 -0
  170. package/dist/components/ui/spinner.d.mts +23 -0
  171. package/dist/components/ui/spinner.d.ts +23 -0
  172. package/dist/components/ui/spinner.js +471 -0
  173. package/dist/components/ui/spinner.js.map +1 -0
  174. package/dist/components/ui/spinner.mjs +436 -0
  175. package/dist/components/ui/spinner.mjs.map +1 -0
  176. package/dist/components/ui/switch.d.mts +22 -0
  177. package/dist/components/ui/switch.d.ts +22 -0
  178. package/dist/components/ui/switch.js +173 -0
  179. package/dist/components/ui/switch.js.map +1 -0
  180. package/dist/components/ui/switch.mjs +138 -0
  181. package/dist/components/ui/switch.mjs.map +1 -0
  182. package/dist/components/ui/table.d.mts +60 -0
  183. package/dist/components/ui/table.d.ts +60 -0
  184. package/dist/components/ui/table.js +231 -0
  185. package/dist/components/ui/table.js.map +1 -0
  186. package/dist/components/ui/table.mjs +190 -0
  187. package/dist/components/ui/table.mjs.map +1 -0
  188. package/dist/components/ui/tabs.d.mts +31 -0
  189. package/dist/components/ui/tabs.d.ts +31 -0
  190. package/dist/components/ui/tabs.js +233 -0
  191. package/dist/components/ui/tabs.js.map +1 -0
  192. package/dist/components/ui/tabs.mjs +194 -0
  193. package/dist/components/ui/tabs.mjs.map +1 -0
  194. package/dist/components/ui/textarea.d.mts +19 -0
  195. package/dist/components/ui/textarea.d.ts +19 -0
  196. package/dist/components/ui/textarea.js +181 -0
  197. package/dist/components/ui/textarea.js.map +1 -0
  198. package/dist/components/ui/textarea.mjs +146 -0
  199. package/dist/components/ui/textarea.mjs.map +1 -0
  200. package/dist/components/ui/toast.d.mts +93 -0
  201. package/dist/components/ui/toast.d.ts +93 -0
  202. package/dist/components/ui/toast.js +429 -0
  203. package/dist/components/ui/toast.js.map +1 -0
  204. package/dist/components/ui/toast.mjs +393 -0
  205. package/dist/components/ui/toast.mjs.map +1 -0
  206. package/dist/components/ui/toggle-group.d.mts +42 -0
  207. package/dist/components/ui/toggle-group.d.ts +42 -0
  208. package/dist/components/ui/toggle-group.js +183 -0
  209. package/dist/components/ui/toggle-group.js.map +1 -0
  210. package/dist/components/ui/toggle-group.mjs +146 -0
  211. package/dist/components/ui/toggle-group.mjs.map +1 -0
  212. package/dist/components/ui/toggle.d.mts +19 -0
  213. package/dist/components/ui/toggle.d.ts +19 -0
  214. package/dist/components/ui/toggle.js +194 -0
  215. package/dist/components/ui/toggle.js.map +1 -0
  216. package/dist/components/ui/toggle.mjs +159 -0
  217. package/dist/components/ui/toggle.mjs.map +1 -0
  218. package/dist/components/ui/tooltip.d.mts +26 -0
  219. package/dist/components/ui/tooltip.d.ts +26 -0
  220. package/dist/components/ui/tooltip.js +128 -0
  221. package/dist/components/ui/tooltip.js.map +1 -0
  222. package/dist/components/ui/tooltip.mjs +88 -0
  223. package/dist/components/ui/tooltip.mjs.map +1 -0
  224. package/dist/lib/code-generator.d.mts +60 -0
  225. package/dist/lib/code-generator.d.ts +60 -0
  226. package/dist/lib/code-generator.js +224 -0
  227. package/dist/lib/code-generator.js.map +1 -0
  228. package/dist/lib/code-generator.mjs +159 -0
  229. package/dist/lib/code-generator.mjs.map +1 -0
  230. package/dist/lib/utils.d.mts +10 -0
  231. package/dist/lib/utils.d.ts +10 -0
  232. package/dist/lib/utils.js +33 -0
  233. package/dist/lib/utils.js.map +1 -0
  234. package/dist/lib/utils.mjs +9 -0
  235. package/dist/lib/utils.mjs.map +1 -0
  236. package/package.json +11 -11
  237. package/dist/chart.js.map +0 -1
  238. package/dist/chart.mjs.map +0 -1
  239. package/dist/index.d.mts +0 -1636
  240. package/dist/index.d.ts +0 -1636
  241. package/dist/index.js +0 -7291
  242. package/dist/index.js.map +0 -1
  243. package/dist/index.mjs +0 -7048
  244. package/dist/index.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/ui/avatar.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as AvatarPrimitive from '@radix-ui/react-avatar'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\n\n// Avatar root variants\nconst avatarVariants = cva(\n 'relative inline-flex items-center justify-center overflow-hidden bg-background-muted select-none',\n {\n variants: {\n size: {\n xs: 'w-6 h-6', // 24px\n sm: 'w-8 h-8', // 32px\n default: 'w-10 h-10', // 40px\n lg: 'w-12 h-12', // 48px\n xl: 'w-16 h-16', // 64px\n '2xl': 'w-20 h-20', // 80px\n },\n shape: {\n circle: 'rounded-full',\n square: 'rounded-xl',\n },\n },\n defaultVariants: { size: 'default', shape: 'circle' },\n }\n)\n\n// Status dot sizes per avatar size\nconst statusDotSizes = {\n xs: 'w-1.5 h-1.5',\n sm: 'w-2 h-2',\n default: 'w-2.5 h-2.5',\n lg: 'w-3 h-3',\n xl: 'w-3.5 h-3.5',\n '2xl': 'w-4 h-4',\n}\n\n// Status dot colors\nconst statusColors = {\n online: 'bg-success',\n offline: 'bg-text-muted',\n busy: 'bg-error',\n away: 'bg-warning',\n}\n\n// Fallback font sizes per avatar size\nconst fallbackFontSizes = {\n xs: 'text-2xs',\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n}\n\n// Negative margin per size for AvatarGroup overlap\nconst groupNegativeMargins = {\n xs: '-space-x-1.5',\n sm: '-space-x-2',\n default: '-space-x-2.5',\n lg: '-space-x-3',\n xl: '-space-x-4',\n '2xl': '-space-x-5',\n}\n\n// Colorized fallback palette (12 colors × 2 variants) — exception 13 in TOKEN-EXCEPTIONS.md\nconst avatarColors = [\n { vivid: { bg: 'bg-[#DC2626]', text: 'text-white' }, soft: { bg: 'bg-[#FEE2E2]', text: 'text-[#DC2626]' } }, // red\n { vivid: { bg: 'bg-[#EA580C]', text: 'text-white' }, soft: { bg: 'bg-[#FFEDD5]', text: 'text-[#EA580C]' } }, // orange\n { vivid: { bg: 'bg-[#D97706]', text: 'text-white' }, soft: { bg: 'bg-[#FEF3C7]', text: 'text-[#B45309]' } }, // amber\n { vivid: { bg: 'bg-[#CA8A04]', text: 'text-white' }, soft: { bg: 'bg-[#FEF9C3]', text: 'text-[#A16207]' } }, // yellow\n { vivid: { bg: 'bg-[#059669]', text: 'text-white' }, soft: { bg: 'bg-[#D1FAE5]', text: 'text-[#047857]' } }, // emerald\n { vivid: { bg: 'bg-[#0D9488]', text: 'text-white' }, soft: { bg: 'bg-[#CCFBF1]', text: 'text-[#0F766E]' } }, // teal\n { vivid: { bg: 'bg-[#0891B2]', text: 'text-white' }, soft: { bg: 'bg-[#CFFAFE]', text: 'text-[#0E7490]' } }, // cyan\n { vivid: { bg: 'bg-[#2563EB]', text: 'text-white' }, soft: { bg: 'bg-[#DBEAFE]', text: 'text-[#1D4ED8]' } }, // blue\n { vivid: { bg: 'bg-[#4F46E5]', text: 'text-white' }, soft: { bg: 'bg-[#E0E7FF]', text: 'text-[#4338CA]' } }, // indigo\n { vivid: { bg: 'bg-[#7C3AED]', text: 'text-white' }, soft: { bg: 'bg-[#EDE9FE]', text: 'text-[#6D28D9]' } }, // violet\n { vivid: { bg: 'bg-[#9333EA]', text: 'text-white' }, soft: { bg: 'bg-[#F3E8FF]', text: 'text-[#7E22CE]' } }, // purple\n { vivid: { bg: 'bg-[#DB2777]', text: 'text-white' }, soft: { bg: 'bg-[#FCE7F3]', text: 'text-[#BE185D]' } }, // pink\n] as const\n\nexport type AvatarColorVariant = 'vivid' | 'soft'\n\n/** Extract initials from a name string (e.g. \"John Doe\" → \"JD\", \"김민수\" → \"김민\") */\nfunction getAvatarInitials(name: string, maxChars = 2): string {\n const trimmed = name.trim()\n if (!trimmed) return ''\n\n // CJK: use first character(s) directly\n const cjkRegex = /[\\u3000-\\u9fff\\uac00-\\ud7af\\uff00-\\uffef]/\n if (cjkRegex.test(trimmed.charAt(0))) {\n return trimmed.slice(0, maxChars)\n }\n\n // Split on spaces, hyphens, underscores, dots\n const parts = trimmed.split(/[\\s\\-_.]+/).filter(Boolean)\n if (parts.length === 1) {\n return parts[0].charAt(0).toUpperCase()\n }\n\n // First + last part initials\n return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0))\n .toUpperCase()\n .slice(0, maxChars)\n}\n\n/** Hash a name string to a deterministic avatar color pair (djb2 xor variant) */\nfunction getAvatarColor(name: string, variant: AvatarColorVariant = 'vivid') {\n let hash = 5381\n for (let i = 0; i < name.length; i++) {\n hash = ((hash << 5) + hash) ^ name.charCodeAt(i)\n }\n return avatarColors[(hash >>> 0) % avatarColors.length][variant]\n}\n\nexport type AvatarSize = 'xs' | 'sm' | 'default' | 'lg' | 'xl' | '2xl'\nexport type AvatarShape = 'circle' | 'square'\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away'\n\nexport interface AvatarProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n VariantProps<typeof avatarVariants> {\n status?: AvatarStatus\n}\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(({ className, size, shape, status, children, ...props }, ref) => {\n const resolvedSize = size || 'default'\n\n if (!status) {\n return (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n )\n }\n\n // Wrap with an outer span so the status dot is not clipped by overflow-hidden\n return (\n <span className=\"relative inline-flex\">\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n <span\n className={cn(\n 'absolute bottom-0 right-0 rounded-full ring-2 ring-background',\n statusDotSizes[resolvedSize],\n statusColors[status]\n )}\n />\n </span>\n )\n})\nAvatar.displayName = 'Avatar'\n\nexport interface AvatarImageProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> {}\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n AvatarImageProps\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn('object-cover w-full h-full', className)}\n {...props}\n />\n))\nAvatarImage.displayName = 'AvatarImage'\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {\n size?: AvatarSize\n /** Shorthand: auto-generates initials + color from a name. Children override auto-initials. */\n name?: string\n /** Pass a name/key to enable colorized mode. The string is hashed to pick a deterministic color. */\n colorized?: string\n /** Color style: \"vivid\" (strong bg + white text) or \"soft\" (pastel bg + dark text). Default: \"vivid\" */\n colorVariant?: AvatarColorVariant\n}\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, size, name, colorized, colorVariant = 'vivid', children, ...props }, ref) => {\n const resolvedSize = size || 'default'\n const colorKey = name || colorized\n const color = colorKey ? getAvatarColor(colorKey, colorVariant) : null\n const resolvedChildren = children ?? (name ? getAvatarInitials(name) : undefined)\n return (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n 'flex items-center justify-center w-full h-full font-semibold',\n color ? [color.bg, color.text] : 'bg-background-muted text-text-muted',\n fallbackFontSizes[resolvedSize],\n className\n )}\n {...props}\n >\n {resolvedChildren}\n </AvatarPrimitive.Fallback>\n )\n})\nAvatarFallback.displayName = 'AvatarFallback'\n\nexport interface AvatarGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n max?: number\n size?: AvatarSize\n shape?: AvatarShape\n}\n\nconst AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(\n ({ className, max, size = 'default', shape = 'circle', children, ...props }, ref) => {\n const childArray = React.Children.toArray(children)\n const visibleChildren = max ? childArray.slice(0, max) : childArray\n const overflowCount = max ? childArray.length - max : 0\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center',\n groupNegativeMargins[size],\n '[&>*]:ring-2 [&>*]:ring-background',\n className\n )}\n {...props}\n >\n {visibleChildren}\n {overflowCount > 0 && (\n <Avatar size={size} shape={shape}>\n <AvatarFallback size={size}>+{overflowCount}</AvatarFallback>\n </Avatar>\n )}\n </div>\n )\n }\n)\nAvatarGroup.displayName = 'AvatarGroup'\n\nexport { Avatar, AvatarImage, AvatarFallback, AvatarGroup, avatarVariants, avatarColors, getAvatarColor, getAvatarInitials }\n"],"mappings":"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","names":[]}
@@ -0,0 +1,204 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
4
+ import { cva } from "class-variance-authority";
5
+ import { cn } from "../../lib/utils";
6
+ const avatarVariants = cva(
7
+ "relative inline-flex items-center justify-center overflow-hidden bg-background-muted select-none",
8
+ {
9
+ variants: {
10
+ size: {
11
+ xs: "w-6 h-6",
12
+ // 24px
13
+ sm: "w-8 h-8",
14
+ // 32px
15
+ default: "w-10 h-10",
16
+ // 40px
17
+ lg: "w-12 h-12",
18
+ // 48px
19
+ xl: "w-16 h-16",
20
+ // 64px
21
+ "2xl": "w-20 h-20"
22
+ // 80px
23
+ },
24
+ shape: {
25
+ circle: "rounded-full",
26
+ square: "rounded-xl"
27
+ }
28
+ },
29
+ defaultVariants: { size: "default", shape: "circle" }
30
+ }
31
+ );
32
+ const statusDotSizes = {
33
+ xs: "w-1.5 h-1.5",
34
+ sm: "w-2 h-2",
35
+ default: "w-2.5 h-2.5",
36
+ lg: "w-3 h-3",
37
+ xl: "w-3.5 h-3.5",
38
+ "2xl": "w-4 h-4"
39
+ };
40
+ const statusColors = {
41
+ online: "bg-success",
42
+ offline: "bg-text-muted",
43
+ busy: "bg-error",
44
+ away: "bg-warning"
45
+ };
46
+ const fallbackFontSizes = {
47
+ xs: "text-2xs",
48
+ sm: "text-xs",
49
+ default: "text-sm",
50
+ lg: "text-base",
51
+ xl: "text-xl",
52
+ "2xl": "text-2xl"
53
+ };
54
+ const groupNegativeMargins = {
55
+ xs: "-space-x-1.5",
56
+ sm: "-space-x-2",
57
+ default: "-space-x-2.5",
58
+ lg: "-space-x-3",
59
+ xl: "-space-x-4",
60
+ "2xl": "-space-x-5"
61
+ };
62
+ const avatarColors = [
63
+ { vivid: { bg: "bg-[#DC2626]", text: "text-white" }, soft: { bg: "bg-[#FEE2E2]", text: "text-[#DC2626]" } },
64
+ // red
65
+ { vivid: { bg: "bg-[#EA580C]", text: "text-white" }, soft: { bg: "bg-[#FFEDD5]", text: "text-[#EA580C]" } },
66
+ // orange
67
+ { vivid: { bg: "bg-[#D97706]", text: "text-white" }, soft: { bg: "bg-[#FEF3C7]", text: "text-[#B45309]" } },
68
+ // amber
69
+ { vivid: { bg: "bg-[#CA8A04]", text: "text-white" }, soft: { bg: "bg-[#FEF9C3]", text: "text-[#A16207]" } },
70
+ // yellow
71
+ { vivid: { bg: "bg-[#059669]", text: "text-white" }, soft: { bg: "bg-[#D1FAE5]", text: "text-[#047857]" } },
72
+ // emerald
73
+ { vivid: { bg: "bg-[#0D9488]", text: "text-white" }, soft: { bg: "bg-[#CCFBF1]", text: "text-[#0F766E]" } },
74
+ // teal
75
+ { vivid: { bg: "bg-[#0891B2]", text: "text-white" }, soft: { bg: "bg-[#CFFAFE]", text: "text-[#0E7490]" } },
76
+ // cyan
77
+ { vivid: { bg: "bg-[#2563EB]", text: "text-white" }, soft: { bg: "bg-[#DBEAFE]", text: "text-[#1D4ED8]" } },
78
+ // blue
79
+ { vivid: { bg: "bg-[#4F46E5]", text: "text-white" }, soft: { bg: "bg-[#E0E7FF]", text: "text-[#4338CA]" } },
80
+ // indigo
81
+ { vivid: { bg: "bg-[#7C3AED]", text: "text-white" }, soft: { bg: "bg-[#EDE9FE]", text: "text-[#6D28D9]" } },
82
+ // violet
83
+ { vivid: { bg: "bg-[#9333EA]", text: "text-white" }, soft: { bg: "bg-[#F3E8FF]", text: "text-[#7E22CE]" } },
84
+ // purple
85
+ { vivid: { bg: "bg-[#DB2777]", text: "text-white" }, soft: { bg: "bg-[#FCE7F3]", text: "text-[#BE185D]" } }
86
+ // pink
87
+ ];
88
+ function getAvatarInitials(name, maxChars = 2) {
89
+ const trimmed = name.trim();
90
+ if (!trimmed) return "";
91
+ const cjkRegex = /[\u3000-\u9fff\uac00-\ud7af\uff00-\uffef]/;
92
+ if (cjkRegex.test(trimmed.charAt(0))) {
93
+ return trimmed.slice(0, maxChars);
94
+ }
95
+ const parts = trimmed.split(/[\s\-_.]+/).filter(Boolean);
96
+ if (parts.length === 1) {
97
+ return parts[0].charAt(0).toUpperCase();
98
+ }
99
+ return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase().slice(0, maxChars);
100
+ }
101
+ function getAvatarColor(name, variant = "vivid") {
102
+ let hash = 5381;
103
+ for (let i = 0; i < name.length; i++) {
104
+ hash = (hash << 5) + hash ^ name.charCodeAt(i);
105
+ }
106
+ return avatarColors[(hash >>> 0) % avatarColors.length][variant];
107
+ }
108
+ const Avatar = React.forwardRef(({ className, size, shape, status, children, ...props }, ref) => {
109
+ const resolvedSize = size || "default";
110
+ if (!status) {
111
+ return /* @__PURE__ */ React.createElement(
112
+ AvatarPrimitive.Root,
113
+ {
114
+ ref,
115
+ className: cn(avatarVariants({ size, shape }), className),
116
+ ...props
117
+ },
118
+ children
119
+ );
120
+ }
121
+ return /* @__PURE__ */ React.createElement("span", { className: "relative inline-flex" }, /* @__PURE__ */ React.createElement(
122
+ AvatarPrimitive.Root,
123
+ {
124
+ ref,
125
+ className: cn(avatarVariants({ size, shape }), className),
126
+ ...props
127
+ },
128
+ children
129
+ ), /* @__PURE__ */ React.createElement(
130
+ "span",
131
+ {
132
+ className: cn(
133
+ "absolute bottom-0 right-0 rounded-full ring-2 ring-background",
134
+ statusDotSizes[resolvedSize],
135
+ statusColors[status]
136
+ )
137
+ }
138
+ ));
139
+ });
140
+ Avatar.displayName = "Avatar";
141
+ const AvatarImage = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React.createElement(
142
+ AvatarPrimitive.Image,
143
+ {
144
+ ref,
145
+ className: cn("object-cover w-full h-full", className),
146
+ ...props
147
+ }
148
+ ));
149
+ AvatarImage.displayName = "AvatarImage";
150
+ const AvatarFallback = React.forwardRef(({ className, size, name, colorized, colorVariant = "vivid", children, ...props }, ref) => {
151
+ const resolvedSize = size || "default";
152
+ const colorKey = name || colorized;
153
+ const color = colorKey ? getAvatarColor(colorKey, colorVariant) : null;
154
+ const resolvedChildren = children ?? (name ? getAvatarInitials(name) : void 0);
155
+ return /* @__PURE__ */ React.createElement(
156
+ AvatarPrimitive.Fallback,
157
+ {
158
+ ref,
159
+ className: cn(
160
+ "flex items-center justify-center w-full h-full font-semibold",
161
+ color ? [color.bg, color.text] : "bg-background-muted text-text-muted",
162
+ fallbackFontSizes[resolvedSize],
163
+ className
164
+ ),
165
+ ...props
166
+ },
167
+ resolvedChildren
168
+ );
169
+ });
170
+ AvatarFallback.displayName = "AvatarFallback";
171
+ const AvatarGroup = React.forwardRef(
172
+ ({ className, max, size = "default", shape = "circle", children, ...props }, ref) => {
173
+ const childArray = React.Children.toArray(children);
174
+ const visibleChildren = max ? childArray.slice(0, max) : childArray;
175
+ const overflowCount = max ? childArray.length - max : 0;
176
+ return /* @__PURE__ */ React.createElement(
177
+ "div",
178
+ {
179
+ ref,
180
+ className: cn(
181
+ "flex items-center",
182
+ groupNegativeMargins[size],
183
+ "[&>*]:ring-2 [&>*]:ring-background",
184
+ className
185
+ ),
186
+ ...props
187
+ },
188
+ visibleChildren,
189
+ overflowCount > 0 && /* @__PURE__ */ React.createElement(Avatar, { size, shape }, /* @__PURE__ */ React.createElement(AvatarFallback, { size }, "+", overflowCount))
190
+ );
191
+ }
192
+ );
193
+ AvatarGroup.displayName = "AvatarGroup";
194
+ export {
195
+ Avatar,
196
+ AvatarFallback,
197
+ AvatarGroup,
198
+ AvatarImage,
199
+ avatarColors,
200
+ avatarVariants,
201
+ getAvatarColor,
202
+ getAvatarInitials
203
+ };
204
+ //# sourceMappingURL=avatar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/ui/avatar.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as AvatarPrimitive from '@radix-ui/react-avatar'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\n\n// Avatar root variants\nconst avatarVariants = cva(\n 'relative inline-flex items-center justify-center overflow-hidden bg-background-muted select-none',\n {\n variants: {\n size: {\n xs: 'w-6 h-6', // 24px\n sm: 'w-8 h-8', // 32px\n default: 'w-10 h-10', // 40px\n lg: 'w-12 h-12', // 48px\n xl: 'w-16 h-16', // 64px\n '2xl': 'w-20 h-20', // 80px\n },\n shape: {\n circle: 'rounded-full',\n square: 'rounded-xl',\n },\n },\n defaultVariants: { size: 'default', shape: 'circle' },\n }\n)\n\n// Status dot sizes per avatar size\nconst statusDotSizes = {\n xs: 'w-1.5 h-1.5',\n sm: 'w-2 h-2',\n default: 'w-2.5 h-2.5',\n lg: 'w-3 h-3',\n xl: 'w-3.5 h-3.5',\n '2xl': 'w-4 h-4',\n}\n\n// Status dot colors\nconst statusColors = {\n online: 'bg-success',\n offline: 'bg-text-muted',\n busy: 'bg-error',\n away: 'bg-warning',\n}\n\n// Fallback font sizes per avatar size\nconst fallbackFontSizes = {\n xs: 'text-2xs',\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n}\n\n// Negative margin per size for AvatarGroup overlap\nconst groupNegativeMargins = {\n xs: '-space-x-1.5',\n sm: '-space-x-2',\n default: '-space-x-2.5',\n lg: '-space-x-3',\n xl: '-space-x-4',\n '2xl': '-space-x-5',\n}\n\n// Colorized fallback palette (12 colors × 2 variants) — exception 13 in TOKEN-EXCEPTIONS.md\nconst avatarColors = [\n { vivid: { bg: 'bg-[#DC2626]', text: 'text-white' }, soft: { bg: 'bg-[#FEE2E2]', text: 'text-[#DC2626]' } }, // red\n { vivid: { bg: 'bg-[#EA580C]', text: 'text-white' }, soft: { bg: 'bg-[#FFEDD5]', text: 'text-[#EA580C]' } }, // orange\n { vivid: { bg: 'bg-[#D97706]', text: 'text-white' }, soft: { bg: 'bg-[#FEF3C7]', text: 'text-[#B45309]' } }, // amber\n { vivid: { bg: 'bg-[#CA8A04]', text: 'text-white' }, soft: { bg: 'bg-[#FEF9C3]', text: 'text-[#A16207]' } }, // yellow\n { vivid: { bg: 'bg-[#059669]', text: 'text-white' }, soft: { bg: 'bg-[#D1FAE5]', text: 'text-[#047857]' } }, // emerald\n { vivid: { bg: 'bg-[#0D9488]', text: 'text-white' }, soft: { bg: 'bg-[#CCFBF1]', text: 'text-[#0F766E]' } }, // teal\n { vivid: { bg: 'bg-[#0891B2]', text: 'text-white' }, soft: { bg: 'bg-[#CFFAFE]', text: 'text-[#0E7490]' } }, // cyan\n { vivid: { bg: 'bg-[#2563EB]', text: 'text-white' }, soft: { bg: 'bg-[#DBEAFE]', text: 'text-[#1D4ED8]' } }, // blue\n { vivid: { bg: 'bg-[#4F46E5]', text: 'text-white' }, soft: { bg: 'bg-[#E0E7FF]', text: 'text-[#4338CA]' } }, // indigo\n { vivid: { bg: 'bg-[#7C3AED]', text: 'text-white' }, soft: { bg: 'bg-[#EDE9FE]', text: 'text-[#6D28D9]' } }, // violet\n { vivid: { bg: 'bg-[#9333EA]', text: 'text-white' }, soft: { bg: 'bg-[#F3E8FF]', text: 'text-[#7E22CE]' } }, // purple\n { vivid: { bg: 'bg-[#DB2777]', text: 'text-white' }, soft: { bg: 'bg-[#FCE7F3]', text: 'text-[#BE185D]' } }, // pink\n] as const\n\nexport type AvatarColorVariant = 'vivid' | 'soft'\n\n/** Extract initials from a name string (e.g. \"John Doe\" → \"JD\", \"김민수\" → \"김민\") */\nfunction getAvatarInitials(name: string, maxChars = 2): string {\n const trimmed = name.trim()\n if (!trimmed) return ''\n\n // CJK: use first character(s) directly\n const cjkRegex = /[\\u3000-\\u9fff\\uac00-\\ud7af\\uff00-\\uffef]/\n if (cjkRegex.test(trimmed.charAt(0))) {\n return trimmed.slice(0, maxChars)\n }\n\n // Split on spaces, hyphens, underscores, dots\n const parts = trimmed.split(/[\\s\\-_.]+/).filter(Boolean)\n if (parts.length === 1) {\n return parts[0].charAt(0).toUpperCase()\n }\n\n // First + last part initials\n return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0))\n .toUpperCase()\n .slice(0, maxChars)\n}\n\n/** Hash a name string to a deterministic avatar color pair (djb2 xor variant) */\nfunction getAvatarColor(name: string, variant: AvatarColorVariant = 'vivid') {\n let hash = 5381\n for (let i = 0; i < name.length; i++) {\n hash = ((hash << 5) + hash) ^ name.charCodeAt(i)\n }\n return avatarColors[(hash >>> 0) % avatarColors.length][variant]\n}\n\nexport type AvatarSize = 'xs' | 'sm' | 'default' | 'lg' | 'xl' | '2xl'\nexport type AvatarShape = 'circle' | 'square'\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away'\n\nexport interface AvatarProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n VariantProps<typeof avatarVariants> {\n status?: AvatarStatus\n}\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(({ className, size, shape, status, children, ...props }, ref) => {\n const resolvedSize = size || 'default'\n\n if (!status) {\n return (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n )\n }\n\n // Wrap with an outer span so the status dot is not clipped by overflow-hidden\n return (\n <span className=\"relative inline-flex\">\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n <span\n className={cn(\n 'absolute bottom-0 right-0 rounded-full ring-2 ring-background',\n statusDotSizes[resolvedSize],\n statusColors[status]\n )}\n />\n </span>\n )\n})\nAvatar.displayName = 'Avatar'\n\nexport interface AvatarImageProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> {}\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n AvatarImageProps\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn('object-cover w-full h-full', className)}\n {...props}\n />\n))\nAvatarImage.displayName = 'AvatarImage'\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {\n size?: AvatarSize\n /** Shorthand: auto-generates initials + color from a name. Children override auto-initials. */\n name?: string\n /** Pass a name/key to enable colorized mode. The string is hashed to pick a deterministic color. */\n colorized?: string\n /** Color style: \"vivid\" (strong bg + white text) or \"soft\" (pastel bg + dark text). Default: \"vivid\" */\n colorVariant?: AvatarColorVariant\n}\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, size, name, colorized, colorVariant = 'vivid', children, ...props }, ref) => {\n const resolvedSize = size || 'default'\n const colorKey = name || colorized\n const color = colorKey ? getAvatarColor(colorKey, colorVariant) : null\n const resolvedChildren = children ?? (name ? getAvatarInitials(name) : undefined)\n return (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n 'flex items-center justify-center w-full h-full font-semibold',\n color ? [color.bg, color.text] : 'bg-background-muted text-text-muted',\n fallbackFontSizes[resolvedSize],\n className\n )}\n {...props}\n >\n {resolvedChildren}\n </AvatarPrimitive.Fallback>\n )\n})\nAvatarFallback.displayName = 'AvatarFallback'\n\nexport interface AvatarGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n max?: number\n size?: AvatarSize\n shape?: AvatarShape\n}\n\nconst AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(\n ({ className, max, size = 'default', shape = 'circle', children, ...props }, ref) => {\n const childArray = React.Children.toArray(children)\n const visibleChildren = max ? childArray.slice(0, max) : childArray\n const overflowCount = max ? childArray.length - max : 0\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center',\n groupNegativeMargins[size],\n '[&>*]:ring-2 [&>*]:ring-background',\n className\n )}\n {...props}\n >\n {visibleChildren}\n {overflowCount > 0 && (\n <Avatar size={size} shape={shape}>\n <AvatarFallback size={size}>+{overflowCount}</AvatarFallback>\n </Avatar>\n )}\n </div>\n )\n }\n)\nAvatarGroup.displayName = 'AvatarGroup'\n\nexport { Avatar, AvatarImage, AvatarFallback, AvatarGroup, avatarVariants, avatarColors, getAvatarColor, getAvatarInitials }\n"],"mappings":"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","names":[]}
@@ -0,0 +1,31 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import * as React from 'react';
3
+ import { VariantProps } from 'class-variance-authority';
4
+
5
+ declare const badgeVariants: (props?: ({
6
+ size?: "default" | "sm" | "lg" | null | undefined;
7
+ radius?: "sm" | "lg" | "base" | "md" | "full" | null | undefined;
8
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
9
+ type BadgeVariant = 'solid' | 'subtle' | 'outline';
10
+ type BadgeColor = 'default' | 'primary' | 'success' | 'warning' | 'error' | 'info';
11
+ type BadgeSize = 'sm' | 'default' | 'lg';
12
+ type BadgeRadius = 'sm' | 'base' | 'md' | 'lg' | 'full';
13
+ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
14
+ /** Visual style */
15
+ variant?: BadgeVariant;
16
+ /** Semantic color */
17
+ color?: BadgeColor;
18
+ /** Leading icon slot */
19
+ icon?: React.ReactNode;
20
+ /** Show a status dot before text */
21
+ dot?: boolean;
22
+ /** Show a remove button */
23
+ removable?: boolean;
24
+ /** Callback when remove button is clicked */
25
+ onRemove?: () => void;
26
+ /** Render as child element (Slot pattern) */
27
+ asChild?: boolean;
28
+ }
29
+ declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
30
+
31
+ export { Badge, type BadgeColor, type BadgeProps, type BadgeRadius, type BadgeSize, type BadgeVariant, badgeVariants };
@@ -0,0 +1,31 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import * as React from 'react';
3
+ import { VariantProps } from 'class-variance-authority';
4
+
5
+ declare const badgeVariants: (props?: ({
6
+ size?: "default" | "sm" | "lg" | null | undefined;
7
+ radius?: "sm" | "lg" | "base" | "md" | "full" | null | undefined;
8
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
9
+ type BadgeVariant = 'solid' | 'subtle' | 'outline';
10
+ type BadgeColor = 'default' | 'primary' | 'success' | 'warning' | 'error' | 'info';
11
+ type BadgeSize = 'sm' | 'default' | 'lg';
12
+ type BadgeRadius = 'sm' | 'base' | 'md' | 'lg' | 'full';
13
+ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
14
+ /** Visual style */
15
+ variant?: BadgeVariant;
16
+ /** Semantic color */
17
+ color?: BadgeColor;
18
+ /** Leading icon slot */
19
+ icon?: React.ReactNode;
20
+ /** Show a status dot before text */
21
+ dot?: boolean;
22
+ /** Show a remove button */
23
+ removable?: boolean;
24
+ /** Callback when remove button is clicked */
25
+ onRemove?: () => void;
26
+ /** Render as child element (Slot pattern) */
27
+ asChild?: boolean;
28
+ }
29
+ declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
30
+
31
+ export { Badge, type BadgeColor, type BadgeProps, type BadgeRadius, type BadgeSize, type BadgeVariant, badgeVariants };
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var badge_exports = {};
31
+ __export(badge_exports, {
32
+ Badge: () => Badge,
33
+ badgeVariants: () => badgeVariants
34
+ });
35
+ module.exports = __toCommonJS(badge_exports);
36
+ var React = __toESM(require("react"));
37
+ var import_react_slot = require("@radix-ui/react-slot");
38
+ var import_class_variance_authority = require("class-variance-authority");
39
+ var import_utils = require("../../lib/utils");
40
+ const colorMap = {
41
+ default: {
42
+ solid: "bg-foreground text-background",
43
+ subtle: "bg-background-muted text-foreground",
44
+ outline: "border-border text-foreground"
45
+ },
46
+ primary: {
47
+ solid: "bg-primary text-primary-foreground",
48
+ subtle: "bg-primary-tint text-text-primary",
49
+ outline: "border-primary text-text-primary"
50
+ },
51
+ success: {
52
+ solid: "bg-success text-success-foreground",
53
+ subtle: "bg-success-tint text-text-success",
54
+ outline: "border-success text-text-success"
55
+ },
56
+ warning: {
57
+ solid: "bg-warning text-warning-foreground",
58
+ subtle: "bg-warning-tint text-text-warning",
59
+ outline: "border-warning text-text-warning"
60
+ },
61
+ error: {
62
+ solid: "bg-error text-error-foreground",
63
+ subtle: "bg-error-tint text-text-error",
64
+ outline: "border-error text-text-error"
65
+ },
66
+ info: {
67
+ solid: "bg-info text-info-foreground",
68
+ subtle: "bg-info-tint text-text-info",
69
+ outline: "border-info text-text-info"
70
+ }
71
+ };
72
+ const badgeVariants = (0, import_class_variance_authority.cva)(
73
+ "inline-flex items-center justify-center whitespace-nowrap font-semibold transition-colors select-none",
74
+ {
75
+ variants: {
76
+ size: {
77
+ sm: "h-5 min-w-5 px-1.5 text-2xs gap-1",
78
+ // 20px height, 6px paddingX, 11px font
79
+ default: "h-6 min-w-6 px-2 text-xs gap-1",
80
+ // 24px height, 8px paddingX, 12px font
81
+ lg: "h-7 min-w-7 px-2.5 text-sm gap-1.5"
82
+ // 28px height, 10px paddingX, 13px font
83
+ },
84
+ radius: {
85
+ sm: "rounded-sm",
86
+ // 2px
87
+ base: "rounded",
88
+ // 4px
89
+ md: "rounded-md",
90
+ // 6px
91
+ lg: "rounded-lg",
92
+ // 8px
93
+ full: "rounded-full"
94
+ // 9999px
95
+ }
96
+ },
97
+ defaultVariants: {
98
+ size: "default",
99
+ radius: "full"
100
+ }
101
+ }
102
+ );
103
+ const badgeIconSizes = {
104
+ sm: "icon-2xs",
105
+ // 12px
106
+ default: "icon-2xs",
107
+ // 12px
108
+ lg: "icon-xs"
109
+ // 14px
110
+ };
111
+ const badgeDotSizes = {
112
+ sm: "w-1 h-1",
113
+ default: "w-1.5 h-1.5",
114
+ lg: "w-1.5 h-1.5"
115
+ };
116
+ const dotColorMap = {
117
+ default: "bg-foreground",
118
+ primary: "bg-primary",
119
+ success: "bg-success",
120
+ warning: "bg-warning",
121
+ error: "bg-error",
122
+ info: "bg-info"
123
+ };
124
+ const Badge = React.forwardRef(
125
+ ({
126
+ className,
127
+ variant = "subtle",
128
+ color = "default",
129
+ size,
130
+ radius,
131
+ icon,
132
+ dot = false,
133
+ removable = false,
134
+ onRemove,
135
+ asChild = false,
136
+ children,
137
+ ...props
138
+ }, ref) => {
139
+ const Comp = asChild ? import_react_slot.Slot : "span";
140
+ const resolvedSize = size || "default";
141
+ const colorClasses = colorMap[color][variant];
142
+ const outlineClasses = variant === "outline" ? "border bg-transparent" : "";
143
+ const dotColor = variant === "solid" ? "bg-current" : dotColorMap[color];
144
+ return /* @__PURE__ */ React.createElement(
145
+ Comp,
146
+ {
147
+ ref,
148
+ className: (0, import_utils.cn)(
149
+ badgeVariants({ size, radius }),
150
+ colorClasses,
151
+ outlineClasses,
152
+ className
153
+ ),
154
+ ...props
155
+ },
156
+ dot && /* @__PURE__ */ React.createElement(
157
+ "span",
158
+ {
159
+ className: (0, import_utils.cn)("shrink-0 rounded-full", badgeDotSizes[resolvedSize], dotColor),
160
+ "aria-hidden": "true"
161
+ }
162
+ ),
163
+ icon && /* @__PURE__ */ React.createElement(
164
+ "span",
165
+ {
166
+ className: (0, import_utils.cn)("shrink-0 [&>svg]:w-full [&>svg]:h-full", badgeIconSizes[resolvedSize]),
167
+ "aria-hidden": "true"
168
+ },
169
+ icon
170
+ ),
171
+ children,
172
+ removable && /* @__PURE__ */ React.createElement(
173
+ "button",
174
+ {
175
+ type: "button",
176
+ className: "shrink-0 -mr-0.5 ml-0.5 rounded-full p-0.5 opacity-70 hover:opacity-100 transition-opacity focus-visible:focus-ring",
177
+ onClick: (e) => {
178
+ e.stopPropagation();
179
+ onRemove?.();
180
+ },
181
+ "aria-label": "Remove"
182
+ },
183
+ /* @__PURE__ */ React.createElement(
184
+ "svg",
185
+ {
186
+ className: "w-3 h-3",
187
+ fill: "none",
188
+ viewBox: "0 0 24 24",
189
+ stroke: "currentColor",
190
+ strokeWidth: 2,
191
+ "aria-hidden": "true"
192
+ },
193
+ /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
194
+ )
195
+ )
196
+ );
197
+ }
198
+ );
199
+ Badge.displayName = "Badge";
200
+ // Annotate the CommonJS export names for ESM import in node:
201
+ 0 && (module.exports = {
202
+ Badge,
203
+ badgeVariants
204
+ });
205
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/ui/badge.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\n\n// Badge color maps for variant × color combinations\n// Uses semantic tokens (*.tint, text-text-*) for v4 dark mode compatibility\nconst colorMap = {\n default: {\n solid: 'bg-foreground text-background',\n subtle: 'bg-background-muted text-foreground',\n outline: 'border-border text-foreground',\n },\n primary: {\n solid: 'bg-primary text-primary-foreground',\n subtle: 'bg-primary-tint text-text-primary',\n outline: 'border-primary text-text-primary',\n },\n success: {\n solid: 'bg-success text-success-foreground',\n subtle: 'bg-success-tint text-text-success',\n outline: 'border-success text-text-success',\n },\n warning: {\n solid: 'bg-warning text-warning-foreground',\n subtle: 'bg-warning-tint text-text-warning',\n outline: 'border-warning text-text-warning',\n },\n error: {\n solid: 'bg-error text-error-foreground',\n subtle: 'bg-error-tint text-text-error',\n outline: 'border-error text-text-error',\n },\n info: {\n solid: 'bg-info text-info-foreground',\n subtle: 'bg-info-tint text-text-info',\n outline: 'border-info text-text-info',\n },\n} as const\n\nconst badgeVariants = cva(\n 'inline-flex items-center justify-center whitespace-nowrap font-semibold transition-colors select-none',\n {\n variants: {\n size: {\n sm: 'h-5 min-w-5 px-1.5 text-2xs gap-1', // 20px height, 6px paddingX, 11px font\n default: 'h-6 min-w-6 px-2 text-xs gap-1', // 24px height, 8px paddingX, 12px font\n lg: 'h-7 min-w-7 px-2.5 text-sm gap-1.5', // 28px height, 10px paddingX, 13px font\n },\n radius: {\n sm: 'rounded-sm', // 2px\n base: 'rounded', // 4px\n md: 'rounded-md', // 6px\n lg: 'rounded-lg', // 8px\n full: 'rounded-full', // 9999px\n },\n },\n defaultVariants: {\n size: 'default',\n radius: 'full',\n },\n }\n)\n\n// Icon sizes per badge size\nconst badgeIconSizes = {\n sm: 'icon-2xs', // 12px\n default: 'icon-2xs', // 12px\n lg: 'icon-xs', // 14px\n} as const\n\n// Dot sizes per badge size\nconst badgeDotSizes = {\n sm: 'w-1 h-1',\n default: 'w-1.5 h-1.5',\n lg: 'w-1.5 h-1.5',\n} as const\n\n// Dot colors per color (matches the solid background)\nconst dotColorMap = {\n default: 'bg-foreground',\n primary: 'bg-primary',\n success: 'bg-success',\n warning: 'bg-warning',\n error: 'bg-error',\n info: 'bg-info',\n} as const\n\nexport type BadgeVariant = 'solid' | 'subtle' | 'outline'\nexport type BadgeColor = 'default' | 'primary' | 'success' | 'warning' | 'error' | 'info'\nexport type BadgeSize = 'sm' | 'default' | 'lg'\nexport type BadgeRadius = 'sm' | 'base' | 'md' | 'lg' | 'full'\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof badgeVariants> {\n /** Visual style */\n variant?: BadgeVariant\n /** Semantic color */\n color?: BadgeColor\n /** Leading icon slot */\n icon?: React.ReactNode\n /** Show a status dot before text */\n dot?: boolean\n /** Show a remove button */\n removable?: boolean\n /** Callback when remove button is clicked */\n onRemove?: () => void\n /** Render as child element (Slot pattern) */\n asChild?: boolean\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({\n className,\n variant = 'subtle',\n color = 'default',\n size,\n radius,\n icon,\n dot = false,\n removable = false,\n onRemove,\n asChild = false,\n children,\n ...props\n }, ref) => {\n const Comp = asChild ? Slot : 'span'\n const resolvedSize = size || 'default'\n\n // Color classes from variant × color map\n const colorClasses = colorMap[color][variant]\n // Outline variant needs border\n const outlineClasses = variant === 'outline' ? 'border bg-transparent' : ''\n\n // Dot color: in solid variant use currentColor (white/foreground), otherwise use semantic color\n const dotColor = variant === 'solid' ? 'bg-current' : dotColorMap[color]\n\n return (\n <Comp\n ref={ref}\n className={cn(\n badgeVariants({ size, radius }),\n colorClasses,\n outlineClasses,\n className\n )}\n {...props}\n >\n {dot && (\n <span\n className={cn('shrink-0 rounded-full', badgeDotSizes[resolvedSize], dotColor)}\n aria-hidden=\"true\"\n />\n )}\n {icon && (\n <span\n className={cn('shrink-0 [&>svg]:w-full [&>svg]:h-full', badgeIconSizes[resolvedSize])}\n aria-hidden=\"true\"\n >\n {icon}\n </span>\n )}\n {children}\n {removable && (\n <button\n type=\"button\"\n className=\"shrink-0 -mr-0.5 ml-0.5 rounded-full p-0.5 opacity-70 hover:opacity-100 transition-opacity focus-visible:focus-ring\"\n onClick={(e) => {\n e.stopPropagation()\n onRemove?.()\n }}\n aria-label=\"Remove\"\n >\n <svg\n className=\"w-3 h-3\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </Comp>\n )\n }\n)\nBadge.displayName = 'Badge'\n\nexport { Badge, badgeVariants }\n"],"mappings":"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","names":[]}