banhaten 0.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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +361 -0
  3. package/banhaten.config.example.json +13 -0
  4. package/package.json +59 -0
  5. package/registry/assets/activity-feed-avatar.png +0 -0
  6. package/registry/assets/avatars/avatar-01.jpg +0 -0
  7. package/registry/assets/avatars/avatar-02.jpg +0 -0
  8. package/registry/assets/avatars/avatar-03.jpg +0 -0
  9. package/registry/assets/avatars/avatar-04.jpg +0 -0
  10. package/registry/assets/avatars/avatar-05.jpg +0 -0
  11. package/registry/assets/avatars/avatar-06.jpg +0 -0
  12. package/registry/assets/avatars/avatar-07.jpg +0 -0
  13. package/registry/assets/avatars/avatar-08.jpg +0 -0
  14. package/registry/assets/avatars/avatar-09.jpg +0 -0
  15. package/registry/assets/avatars/avatar-10.jpg +0 -0
  16. package/registry/assets/avatars/avatar-11.jpg +0 -0
  17. package/registry/assets/avatars/avatar-12.jpg +0 -0
  18. package/registry/assets/avatars/avatar-13.jpg +0 -0
  19. package/registry/assets/avatars/avatar-14.jpg +0 -0
  20. package/registry/assets/avatars/avatar-15.jpg +0 -0
  21. package/registry/assets/avatars/avatar-16.jpg +0 -0
  22. package/registry/assets/avatars/avatar-17.jpg +0 -0
  23. package/registry/assets/avatars/avatar-18.jpg +0 -0
  24. package/registry/assets/avatars/avatar-19.jpg +0 -0
  25. package/registry/assets/avatars/avatar-20.jpg +0 -0
  26. package/registry/assets/avatars/avatar-21.jpg +0 -0
  27. package/registry/assets/avatars/avatar-22.jpg +0 -0
  28. package/registry/assets/avatars/avatar-23.jpg +0 -0
  29. package/registry/assets/avatars/avatar-24.jpg +0 -0
  30. package/registry/assets/avatars/avatar-25.jpg +0 -0
  31. package/registry/assets/avatars/avatar-26.jpg +0 -0
  32. package/registry/assets/avatars/avatar-27.jpg +0 -0
  33. package/registry/assets/avatars/avatar-28.jpg +0 -0
  34. package/registry/assets/avatars/avatar-29.jpg +0 -0
  35. package/registry/assets/avatars/avatar-30.jpg +0 -0
  36. package/registry/assets/avatars/avatar-31.jpg +0 -0
  37. package/registry/assets/avatars/avatar-32.jpg +0 -0
  38. package/registry/assets/avatars/avatar-33.jpg +0 -0
  39. package/registry/assets/avatars/avatar-34.jpg +0 -0
  40. package/registry/assets/avatars/avatar-35.jpg +0 -0
  41. package/registry/assets/image-assets.json +744 -0
  42. package/registry/assets/images/art-01.jpg +0 -0
  43. package/registry/assets/images/art-02.jpg +0 -0
  44. package/registry/assets/images/art-03.jpg +0 -0
  45. package/registry/assets/images/art-04.jpg +0 -0
  46. package/registry/assets/images/art-05.jpg +0 -0
  47. package/registry/assets/images/art-06.jpg +0 -0
  48. package/registry/assets/images/art-07.jpg +0 -0
  49. package/registry/assets/images/art-08.jpg +0 -0
  50. package/registry/assets/images/art-09.jpg +0 -0
  51. package/registry/assets/images/art-10.jpg +0 -0
  52. package/registry/assets/images/art-11.jpg +0 -0
  53. package/registry/assets/images/art-12.jpg +0 -0
  54. package/registry/assets/images/art-13.jpg +0 -0
  55. package/registry/assets/images/art-14.jpg +0 -0
  56. package/registry/assets/images/art-15.jpg +0 -0
  57. package/registry/assets/images/art-16.jpg +0 -0
  58. package/registry/assets/images/art-17.jpg +0 -0
  59. package/registry/assets/images/art-18.jpg +0 -0
  60. package/registry/assets/images/art-19.jpg +0 -0
  61. package/registry/assets/images/art-20.jpg +0 -0
  62. package/registry/assets/images/art-21.jpg +0 -0
  63. package/registry/assets/images/art-22.jpg +0 -0
  64. package/registry/assets/images/art-23.jpg +0 -0
  65. package/registry/assets/images/art-24.jpg +0 -0
  66. package/registry/assets/images/art-25.jpg +0 -0
  67. package/registry/assets/images/art-26.jpg +0 -0
  68. package/registry/assets/images/art-27.jpg +0 -0
  69. package/registry/assets/images/nature-01.jpg +0 -0
  70. package/registry/assets/images/nature-02.jpg +0 -0
  71. package/registry/assets/images/nature-03.jpg +0 -0
  72. package/registry/assets/images/nature-04.jpg +0 -0
  73. package/registry/assets/images/nature-05.jpg +0 -0
  74. package/registry/assets/images/nature-06.jpg +0 -0
  75. package/registry/assets/images/nature-07.jpg +0 -0
  76. package/registry/assets/images/nature-08.jpg +0 -0
  77. package/registry/assets/images/nature-09.jpg +0 -0
  78. package/registry/assets/images/nature-10.jpg +0 -0
  79. package/registry/assets/images/nature-11.jpg +0 -0
  80. package/registry/assets/images/nature-12.jpg +0 -0
  81. package/registry/assets/images/nature-13.jpg +0 -0
  82. package/registry/assets/images/nature-14.jpg +0 -0
  83. package/registry/assets/images/nature-15.jpg +0 -0
  84. package/registry/assets/images/nature-16.jpg +0 -0
  85. package/registry/assets/images/nature-17.jpg +0 -0
  86. package/registry/assets/images/nature-18.jpg +0 -0
  87. package/registry/assets/images/nature-19.jpg +0 -0
  88. package/registry/assets/images/nature-20.jpg +0 -0
  89. package/registry/components/accordion.tsx +119 -0
  90. package/registry/components/alert.tsx +282 -0
  91. package/registry/components/attribute.tsx +452 -0
  92. package/registry/components/avatar.tsx +142 -0
  93. package/registry/components/badge.tsx +567 -0
  94. package/registry/components/button-group.tsx +246 -0
  95. package/registry/components/button.tsx +102 -0
  96. package/registry/components/card.tsx +613 -0
  97. package/registry/components/checkbox.tsx +244 -0
  98. package/registry/components/date-picker.tsx +1143 -0
  99. package/registry/components/divider.tsx +82 -0
  100. package/registry/components/expanded/ActivityFeed.tsx +226 -0
  101. package/registry/components/expanded/Banner.tsx +145 -0
  102. package/registry/components/expanded/BannerBoard.tsx +225 -0
  103. package/registry/components/expanded/Breadcrumbs.tsx +156 -0
  104. package/registry/components/expanded/CatalogComponentsShowcase.tsx +211 -0
  105. package/registry/components/expanded/CatalogDivider.tsx +48 -0
  106. package/registry/components/expanded/CatalogTag.tsx +92 -0
  107. package/registry/components/expanded/CommandBar.tsx +406 -0
  108. package/registry/components/expanded/FileUpload.tsx +231 -0
  109. package/registry/components/expanded/IconExplorer.tsx +612 -0
  110. package/registry/components/expanded/OnboardingStepListItem.tsx +67 -0
  111. package/registry/components/expanded/PageHeader.tsx +184 -0
  112. package/registry/components/expanded/Slideout.tsx +514 -0
  113. package/registry/components/expanded/Steps.tsx +266 -0
  114. package/registry/components/expanded/Table.tsx +1014 -0
  115. package/registry/components/expanded/Tabs.tsx +86 -0
  116. package/registry/components/expanded/Timeline.tsx +235 -0
  117. package/registry/components/expanded/TimelineShowcase.tsx +158 -0
  118. package/registry/components/expanded/activityFeed.css +292 -0
  119. package/registry/components/expanded/banner.css +312 -0
  120. package/registry/components/expanded/breadcrumbs.css +140 -0
  121. package/registry/components/expanded/catalogComponentsShowcase.css +87 -0
  122. package/registry/components/expanded/commandBar.css +473 -0
  123. package/registry/components/expanded/divider.css +75 -0
  124. package/registry/components/expanded/fileUpload.css +228 -0
  125. package/registry/components/expanded/iconExplorer.css +764 -0
  126. package/registry/components/expanded/iconPacks.ts +866 -0
  127. package/registry/components/expanded/onboardingStepListItem.css +126 -0
  128. package/registry/components/expanded/pageHeader.css +287 -0
  129. package/registry/components/expanded/slideout.css +955 -0
  130. package/registry/components/expanded/steps.css +329 -0
  131. package/registry/components/expanded/table.css +607 -0
  132. package/registry/components/expanded/tabs.css +197 -0
  133. package/registry/components/expanded/tag.css +148 -0
  134. package/registry/components/expanded/timeline.css +282 -0
  135. package/registry/components/input-content.ts +106 -0
  136. package/registry/components/input.tsx +866 -0
  137. package/registry/components/menu.tsx +758 -0
  138. package/registry/components/modal.tsx +799 -0
  139. package/registry/components/pagination.tsx +543 -0
  140. package/registry/components/progress-slider.tsx +216 -0
  141. package/registry/components/progress.tsx +367 -0
  142. package/registry/components/radio-card.tsx +654 -0
  143. package/registry/components/radio-group.tsx +570 -0
  144. package/registry/components/select-content.tsx +313 -0
  145. package/registry/components/select.tsx +871 -0
  146. package/registry/components/slider.tsx +380 -0
  147. package/registry/components/social-button.tsx +360 -0
  148. package/registry/components/spinner.tsx +31 -0
  149. package/registry/components/tag.tsx +423 -0
  150. package/registry/components/textarea.tsx +625 -0
  151. package/registry/components/toggle.tsx +272 -0
  152. package/registry/components/toolbar.tsx +467 -0
  153. package/registry/components/tooltip.tsx +427 -0
  154. package/registry/examples/accordion-demo.tsx +34 -0
  155. package/registry/examples/alert-demo.tsx +14 -0
  156. package/registry/examples/attribute-demo.tsx +65 -0
  157. package/registry/examples/avatar-demo.tsx +74 -0
  158. package/registry/examples/badge-demo.tsx +53 -0
  159. package/registry/examples/button-demo.tsx +83 -0
  160. package/registry/examples/button-group-demo.tsx +42 -0
  161. package/registry/examples/card-demo.tsx +48 -0
  162. package/registry/examples/checkbox-demo.tsx +67 -0
  163. package/registry/examples/date-picker-demo.tsx +74 -0
  164. package/registry/examples/divider-demo.tsx +17 -0
  165. package/registry/examples/expanded/activity-feed-demo.tsx +22 -0
  166. package/registry/examples/expanded/banner-demo.tsx +23 -0
  167. package/registry/examples/expanded/catalog-components-demo.tsx +5 -0
  168. package/registry/examples/expanded/command-bar-demo.tsx +10 -0
  169. package/registry/examples/expanded/icons-demo.tsx +5 -0
  170. package/registry/examples/expanded/onboarding-step-demo.tsx +11 -0
  171. package/registry/examples/expanded/page-header-demo.tsx +19 -0
  172. package/registry/examples/expanded/slideout-demo.tsx +15 -0
  173. package/registry/examples/expanded/steps-demo.tsx +18 -0
  174. package/registry/examples/expanded/tabs-demo.tsx +13 -0
  175. package/registry/examples/expanded/timeline-demo.tsx +18 -0
  176. package/registry/examples/input-demo.tsx +87 -0
  177. package/registry/examples/menu-demo.tsx +109 -0
  178. package/registry/examples/modal-demo.tsx +16 -0
  179. package/registry/examples/pagination-demo.tsx +17 -0
  180. package/registry/examples/progress-demo.tsx +37 -0
  181. package/registry/examples/progress-slider-demo.tsx +29 -0
  182. package/registry/examples/radio-card-demo.tsx +51 -0
  183. package/registry/examples/radio-group-demo.tsx +62 -0
  184. package/registry/examples/select-demo.tsx +73 -0
  185. package/registry/examples/slider-demo.tsx +31 -0
  186. package/registry/examples/social-button-demo.tsx +51 -0
  187. package/registry/examples/tag-demo.tsx +29 -0
  188. package/registry/examples/textarea-demo.tsx +79 -0
  189. package/registry/examples/toggle-demo.tsx +59 -0
  190. package/registry/examples/toolbar-demo.tsx +80 -0
  191. package/registry/examples/tooltip-demo.tsx +115 -0
  192. package/registry/hooks/use-direction.ts +27 -0
  193. package/registry/index.json +1213 -0
  194. package/registry/styles/globals.css +4600 -0
  195. package/registry/utils/cn.ts +6 -0
  196. package/src/cli/index.js +826 -0
  197. package/tokens/Color mode.zip +0 -0
  198. package/tokens/Numbers.zip +0 -0
  199. package/tokens/Radius.zip +0 -0
  200. package/tokens/Theme.zip +0 -0
  201. package/tokens/banhaten.tokens.json +5525 -0
@@ -0,0 +1,567 @@
1
+ import * as React from "react"
2
+ import { Slot } from "@radix-ui/react-slot"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ type BadgeStyle = "light" | "outline" | "solid"
8
+ type BadgeColor =
9
+ | "neutral"
10
+ | "blue"
11
+ | "green"
12
+ | "amber"
13
+ | "danger"
14
+ | "purple"
15
+ | "fuchsia"
16
+ | "rose"
17
+ | "sky"
18
+ | "golden"
19
+ type BadgeType =
20
+ | "default"
21
+ | "leading-icon"
22
+ | "trailing-icon"
23
+ | "dot"
24
+ | "flag"
25
+ type BadgeSize = "xs" | "sm" | "default" | "lg"
26
+ type LegacyBadgeVariant =
27
+ | "default"
28
+ | "secondary"
29
+ | "success"
30
+ | "warning"
31
+ | "destructive"
32
+ | "outline"
33
+ | "soft"
34
+ | "soft-success"
35
+ | "soft-warning"
36
+ | "soft-destructive"
37
+ | "ghost"
38
+ | "link"
39
+
40
+ const legacyVariantMap: Record<
41
+ LegacyBadgeVariant,
42
+ { badgeStyle: BadgeStyle; color: BadgeColor; className?: string }
43
+ > = {
44
+ default: { badgeStyle: "solid", color: "blue" },
45
+ secondary: { badgeStyle: "light", color: "neutral" },
46
+ success: { badgeStyle: "solid", color: "green" },
47
+ warning: { badgeStyle: "solid", color: "amber" },
48
+ destructive: { badgeStyle: "solid", color: "danger" },
49
+ outline: { badgeStyle: "outline", color: "neutral" },
50
+ soft: { badgeStyle: "light", color: "blue" },
51
+ "soft-success": { badgeStyle: "light", color: "green" },
52
+ "soft-warning": { badgeStyle: "light", color: "amber" },
53
+ "soft-destructive": { badgeStyle: "light", color: "danger" },
54
+ ghost: {
55
+ badgeStyle: "light",
56
+ color: "neutral",
57
+ className: "bg-[var(--bh-interactive-ghost-default)]",
58
+ },
59
+ link: {
60
+ badgeStyle: "light",
61
+ color: "blue",
62
+ className:
63
+ "bg-[var(--bh-interactive-ghost-default)] px-[var(--bh-space-none)] text-[var(--bh-content-link)] underline-offset-4 [a&]:hover:underline",
64
+ },
65
+ }
66
+
67
+ const badgeVariants = cva(
68
+ [
69
+ "inline-flex min-w-0 shrink-0 items-center justify-center whitespace-nowrap",
70
+ "rounded-[var(--bh-radius-full)] border border-transparent outline-none",
71
+ "transition-[background-color,border-color,color,box-shadow]",
72
+ "focus-visible:border-[var(--bh-border-focus)] focus-visible:ring-[length:var(--bh-badge-focus-ring-width)] focus-visible:ring-[var(--ring)]",
73
+ "aria-invalid:border-[var(--bh-border-focus-danger)] aria-invalid:ring-[var(--danger-ring)]",
74
+ "[&_svg]:pointer-events-none [&_svg]:size-[var(--bh-space-3xl-16)] [&_svg]:shrink-0",
75
+ "rtl:[&_svg[data-rtl-flip='true']]:-scale-x-100",
76
+ ],
77
+ {
78
+ variants: {
79
+ badgeStyle: {
80
+ light: "border-transparent",
81
+ outline: "border-[length:var(--bh-badge-outline-border-width)] bg-transparent",
82
+ solid: "border-transparent",
83
+ },
84
+ color: {
85
+ neutral: "",
86
+ blue: "",
87
+ green: "",
88
+ amber: "",
89
+ danger: "",
90
+ purple: "",
91
+ fuchsia: "",
92
+ rose: "",
93
+ sky: "",
94
+ golden: "",
95
+ },
96
+ type: {
97
+ default: "gap-[var(--bh-space-none)]",
98
+ "leading-icon": "gap-[var(--bh-space-none)]",
99
+ "trailing-icon": "gap-[var(--bh-space-none)]",
100
+ dot: "gap-[var(--bh-space-xs-4)]",
101
+ flag: "gap-[var(--bh-space-xs-4)]",
102
+ },
103
+ size: {
104
+ xs: [
105
+ "h-[var(--bh-space-5xl-24)]",
106
+ "text-[length:var(--bh-text-body-3xs-medium-font-size)]",
107
+ "font-[var(--bh-text-body-3xs-medium-font-weight)]",
108
+ "leading-[var(--bh-text-body-3xs-medium-line-height)]",
109
+ "tracking-[var(--bh-text-body-3xs-medium-letter-spacing)]",
110
+ ],
111
+ sm: [
112
+ "h-[var(--bh-space-5xl-24)]",
113
+ "text-[length:var(--bh-text-body-3xs-medium-font-size)]",
114
+ "font-[var(--bh-text-body-3xs-medium-font-weight)]",
115
+ "leading-[var(--bh-text-body-3xs-medium-line-height)]",
116
+ "tracking-[var(--bh-text-body-3xs-medium-letter-spacing)]",
117
+ ],
118
+ default: [
119
+ "h-[var(--bh-space-5xl-24)]",
120
+ "text-[length:var(--bh-text-body-3xs-medium-font-size)]",
121
+ "font-[var(--bh-text-body-3xs-medium-font-weight)]",
122
+ "leading-[var(--bh-text-body-3xs-medium-line-height)]",
123
+ "tracking-[var(--bh-text-body-3xs-medium-letter-spacing)]",
124
+ ],
125
+ lg: [
126
+ "h-[calc(var(--bh-space-5xl-24)+var(--bh-space-xs-4))]",
127
+ "text-[length:var(--bh-text-body-2xs-medium-font-size)]",
128
+ "font-[var(--bh-text-body-2xs-medium-font-weight)]",
129
+ "leading-[var(--bh-text-body-2xs-medium-line-height)]",
130
+ "tracking-[var(--bh-text-body-2xs-medium-letter-spacing)]",
131
+ ],
132
+ },
133
+ showNumber: {
134
+ true: "gap-[var(--bh-space-none)] px-[var(--bh-space-xs-4)] text-center",
135
+ false: "",
136
+ },
137
+ },
138
+ compoundVariants: [
139
+ {
140
+ type: "default",
141
+ size: ["xs", "sm", "default"],
142
+ showNumber: false,
143
+ class: "px-[var(--bh-space-md-8)]",
144
+ },
145
+ {
146
+ type: "default",
147
+ size: "lg",
148
+ showNumber: false,
149
+ class: "px-[var(--bh-space-xl-12)]",
150
+ },
151
+ {
152
+ type: ["leading-icon", "trailing-icon", "dot"],
153
+ showNumber: false,
154
+ class: "px-[var(--bh-space-md-8)]",
155
+ },
156
+ {
157
+ type: "flag",
158
+ showNumber: false,
159
+ class: "ps-[var(--bh-space-xs-4)] pe-[var(--bh-space-md-8)]",
160
+ },
161
+ {
162
+ size: ["xs", "sm", "default"],
163
+ showNumber: true,
164
+ class:
165
+ "w-[var(--bh-space-5xl-24)] font-[var(--bh-text-body-3xs-semibold-font-weight)]",
166
+ },
167
+ {
168
+ size: "lg",
169
+ showNumber: true,
170
+ class:
171
+ "w-[calc(var(--bh-space-5xl-24)+var(--bh-space-xs-4))] font-[var(--bh-text-body-2xs-semibold-font-weight)]",
172
+ },
173
+ {
174
+ badgeStyle: "light",
175
+ color: "neutral",
176
+ class:
177
+ "bg-[var(--bh-bg-neutral-subtle)] text-[var(--bh-content-default)] [--badge-dot-color:var(--bh-content-muted)]",
178
+ },
179
+ {
180
+ badgeStyle: "outline",
181
+ color: "neutral",
182
+ class:
183
+ "border-[var(--bh-border-strong)] text-[var(--bh-content-subtle)] [--badge-dot-color:var(--bh-content-subtle)]",
184
+ },
185
+ {
186
+ badgeStyle: "solid",
187
+ color: "neutral",
188
+ class:
189
+ "bg-[var(--bh-bg-neutral-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
190
+ },
191
+ {
192
+ badgeStyle: "light",
193
+ color: "blue",
194
+ class:
195
+ "bg-[var(--bh-bg-accent-blue-subtle)] text-[var(--bh-content-accent-blue-strong)] [--badge-dot-color:var(--bh-content-accent-blue-default)]",
196
+ },
197
+ {
198
+ badgeStyle: "outline",
199
+ color: "blue",
200
+ class:
201
+ "border-[var(--bh-border-accent-blue-strong)] text-[var(--bh-content-accent-blue-default)] [--badge-dot-color:var(--bh-content-accent-blue-default)]",
202
+ },
203
+ {
204
+ badgeStyle: "solid",
205
+ color: "blue",
206
+ class:
207
+ "bg-[var(--bh-bg-accent-blue-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
208
+ },
209
+ {
210
+ badgeStyle: "light",
211
+ color: "green",
212
+ class:
213
+ "bg-[var(--bh-bg-accent-green-subtle)] text-[var(--bh-content-accent-green-strong)] [--badge-dot-color:var(--bh-content-accent-green-default)]",
214
+ },
215
+ {
216
+ badgeStyle: "outline",
217
+ color: "green",
218
+ class:
219
+ "border-[var(--bh-border-accent-green-strong)] text-[var(--bh-content-accent-green-default)] [--badge-dot-color:var(--bh-content-accent-green-default)]",
220
+ },
221
+ {
222
+ badgeStyle: "solid",
223
+ color: "green",
224
+ class:
225
+ "bg-[var(--bh-bg-accent-green-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
226
+ },
227
+ {
228
+ badgeStyle: "light",
229
+ color: "amber",
230
+ class:
231
+ "bg-[var(--bh-bg-accent-amber-subtle)] text-[var(--bh-content-accent-amber-strong)] [--badge-dot-color:var(--bh-content-accent-amber-default)]",
232
+ },
233
+ {
234
+ badgeStyle: "outline",
235
+ color: "amber",
236
+ class:
237
+ "border-[var(--bh-border-accent-amber-strong)] text-[var(--bh-content-accent-amber-default)] [--badge-dot-color:var(--bh-content-accent-amber-default)]",
238
+ },
239
+ {
240
+ badgeStyle: "solid",
241
+ color: "amber",
242
+ class:
243
+ "bg-[var(--bh-bg-accent-amber-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
244
+ },
245
+ {
246
+ badgeStyle: "light",
247
+ color: "danger",
248
+ class:
249
+ "bg-[var(--bh-bg-accent-red-subtle)] text-[var(--bh-content-accent-red-strong)] [--badge-dot-color:var(--bh-content-accent-red-default)]",
250
+ },
251
+ {
252
+ badgeStyle: "outline",
253
+ color: "danger",
254
+ class:
255
+ "border-[var(--bh-border-accent-red-strong)] text-[var(--bh-content-accent-red-default)] [--badge-dot-color:var(--bh-content-accent-red-default)]",
256
+ },
257
+ {
258
+ badgeStyle: "solid",
259
+ color: "danger",
260
+ class:
261
+ "bg-[var(--bh-bg-accent-red-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
262
+ },
263
+ {
264
+ badgeStyle: "light",
265
+ color: "purple",
266
+ class:
267
+ "bg-[var(--bh-bg-accent-purple-subtle)] text-[var(--bh-content-accent-purple-strong)] [--badge-dot-color:var(--bh-content-accent-purple-default)]",
268
+ },
269
+ {
270
+ badgeStyle: "outline",
271
+ color: "purple",
272
+ class:
273
+ "border-[var(--bh-border-accent-purple-strong)] text-[var(--bh-content-accent-purple-default)] [--badge-dot-color:var(--bh-content-accent-purple-default)]",
274
+ },
275
+ {
276
+ badgeStyle: "solid",
277
+ color: "purple",
278
+ class:
279
+ "bg-[var(--bh-bg-accent-purple-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
280
+ },
281
+ {
282
+ badgeStyle: "light",
283
+ color: "fuchsia",
284
+ class:
285
+ "bg-[var(--bh-bg-accent-fuchsia-subtle)] text-[var(--bh-content-accent-fuchsia-strong)] [--badge-dot-color:var(--bh-content-accent-fuchsia-default)]",
286
+ },
287
+ {
288
+ badgeStyle: "outline",
289
+ color: "fuchsia",
290
+ class:
291
+ "border-[var(--bh-border-accent-fuchsia-strong)] text-[var(--bh-content-accent-fuchsia-default)] [--badge-dot-color:var(--bh-content-accent-fuchsia-default)]",
292
+ },
293
+ {
294
+ badgeStyle: "solid",
295
+ color: "fuchsia",
296
+ class:
297
+ "bg-[var(--bh-bg-accent-fuchsia-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
298
+ },
299
+ {
300
+ badgeStyle: "light",
301
+ color: "rose",
302
+ class:
303
+ "bg-[var(--bh-bg-accent-rose-subtle)] text-[var(--bh-content-accent-rose-strong)] [--badge-dot-color:var(--bh-content-accent-rose-default)]",
304
+ },
305
+ {
306
+ badgeStyle: "outline",
307
+ color: "rose",
308
+ class:
309
+ "border-[var(--bh-border-accent-rose-strong)] text-[var(--bh-content-accent-rose-default)] [--badge-dot-color:var(--bh-content-accent-rose-default)]",
310
+ },
311
+ {
312
+ badgeStyle: "solid",
313
+ color: "rose",
314
+ class:
315
+ "bg-[var(--bh-bg-accent-rose-default)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
316
+ },
317
+ {
318
+ badgeStyle: "light",
319
+ color: "sky",
320
+ class:
321
+ "bg-[var(--bh-bg-accent-sky-subtle)] text-[var(--bh-content-accent-sky-strong)] [--badge-dot-color:var(--bh-content-accent-sky-default)]",
322
+ },
323
+ {
324
+ badgeStyle: "outline",
325
+ color: "sky",
326
+ class:
327
+ "border-[var(--bh-border-accent-sky-strong)] text-[var(--bh-content-accent-sky-default)] [--badge-dot-color:var(--bh-content-accent-sky-default)]",
328
+ },
329
+ {
330
+ badgeStyle: "solid",
331
+ color: "sky",
332
+ class:
333
+ "bg-[var(--bh-bg-accent-sky-base)] text-[var(--bh-content-on-color)] [--badge-dot-color:var(--bh-content-on-color)]",
334
+ },
335
+ {
336
+ badgeStyle: "light",
337
+ color: "golden",
338
+ class:
339
+ "bg-[var(--bh-bg-accent-golden-subtle)] text-[var(--bh-content-accent-golden-strong)] [--badge-dot-color:var(--bh-content-accent-golden-default)]",
340
+ },
341
+ {
342
+ badgeStyle: "outline",
343
+ color: "golden",
344
+ class:
345
+ "border-[var(--bh-border-accent-golden-strong)] text-[var(--bh-content-accent-golden-default)] [--badge-dot-color:var(--bh-content-accent-golden-default)]",
346
+ },
347
+ {
348
+ badgeStyle: "solid",
349
+ color: "golden",
350
+ class:
351
+ "bg-[var(--bh-bg-accent-golden-default)] text-[var(--bh-content-on-light)] [--badge-dot-color:var(--bh-content-on-light)]",
352
+ },
353
+ ],
354
+ defaultVariants: {
355
+ badgeStyle: "light",
356
+ color: "neutral",
357
+ type: "default",
358
+ size: "sm",
359
+ showNumber: false,
360
+ },
361
+ }
362
+ )
363
+
364
+ type BadgeProps = Omit<React.ComponentProps<"span">, "color"> &
365
+ VariantProps<typeof badgeVariants> & {
366
+ asChild?: boolean
367
+ variant?: LegacyBadgeVariant
368
+ flag?: React.ReactNode
369
+ number?: React.ReactNode
370
+ }
371
+
372
+ type BadgeContentProps = {
373
+ children: React.ReactNode
374
+ flag?: React.ReactNode
375
+ number?: React.ReactNode
376
+ showNumber: boolean
377
+ type: BadgeType
378
+ }
379
+
380
+ const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(function Badge({
381
+ className,
382
+ variant,
383
+ badgeStyle,
384
+ color,
385
+ type,
386
+ size,
387
+ showNumber = false,
388
+ number,
389
+ flag,
390
+ asChild = false,
391
+ dir = "auto",
392
+ children,
393
+ ...props
394
+ }, ref) {
395
+ const Comp = asChild ? Slot : "span"
396
+ const legacyVariant = variant ? legacyVariantMap[variant] : undefined
397
+ const isNumber = Boolean(showNumber)
398
+ const resolvedBadgeStyle = badgeStyle ?? legacyVariant?.badgeStyle ?? "light"
399
+ const resolvedColor = color ?? legacyVariant?.color ?? "neutral"
400
+ const resolvedType = isNumber ? "default" : type ?? "default"
401
+ const resolvedSize = size ?? "sm"
402
+ const contentProps = {
403
+ flag,
404
+ number,
405
+ showNumber: isNumber,
406
+ type: resolvedType,
407
+ }
408
+
409
+ return (
410
+ <Comp
411
+ data-slot="badge"
412
+ data-variant={
413
+ variant ?? `${resolvedBadgeStyle}-${resolvedColor}-${resolvedType}`
414
+ }
415
+ data-style={resolvedBadgeStyle}
416
+ data-color={resolvedColor}
417
+ data-type={resolvedType}
418
+ data-size={resolvedSize}
419
+ data-show-number={isNumber ? "true" : "false"}
420
+ dir={dir}
421
+ ref={ref}
422
+ className={cn(
423
+ badgeVariants({
424
+ badgeStyle: resolvedBadgeStyle,
425
+ color: resolvedColor,
426
+ type: resolvedType,
427
+ size: resolvedSize,
428
+ showNumber: isNumber,
429
+ }),
430
+ legacyVariant?.className,
431
+ className
432
+ )}
433
+ {...props}
434
+ >
435
+ {asChild ? (
436
+ renderBadgeSlotChild(children, contentProps)
437
+ ) : (
438
+ <BadgeContent {...contentProps}>
439
+ {children}
440
+ </BadgeContent>
441
+ )}
442
+ </Comp>
443
+ )
444
+ })
445
+
446
+ function renderBadgeSlotChild(
447
+ children: React.ReactNode,
448
+ contentProps: Omit<BadgeContentProps, "children">
449
+ ) {
450
+ if (!React.isValidElement<{ children?: React.ReactNode }>(children)) {
451
+ return children
452
+ }
453
+
454
+ return React.cloneElement(
455
+ children,
456
+ undefined,
457
+ <BadgeContent {...contentProps}>{children.props.children}</BadgeContent>
458
+ )
459
+ }
460
+
461
+ function BadgeContent({
462
+ children,
463
+ flag,
464
+ number,
465
+ showNumber,
466
+ type,
467
+ }: BadgeContentProps) {
468
+ const content = showNumber ? number ?? children : children
469
+
470
+ return (
471
+ <>
472
+ {!showNumber && type === "dot" ? <BadgeDot /> : null}
473
+ {!showNumber && type === "flag" ? <BadgeFlag>{flag}</BadgeFlag> : null}
474
+ {renderBadgeChildren(content, type)}
475
+ </>
476
+ )
477
+ }
478
+
479
+ function renderBadgeChildren(
480
+ children: React.ReactNode,
481
+ type: BadgeType,
482
+ keyPrefix = "badge-label"
483
+ ): React.ReactNode[] {
484
+ const labelClassName = cn(
485
+ "min-w-0",
486
+ (type === "leading-icon" || type === "trailing-icon") &&
487
+ "px-[var(--bh-space-xs-4)]"
488
+ )
489
+ const renderedChildren: React.ReactNode[] = []
490
+
491
+ React.Children.toArray(children).forEach((child, index) => {
492
+ if (
493
+ typeof child === "string" ||
494
+ typeof child === "number" ||
495
+ typeof child === "bigint"
496
+ ) {
497
+ renderedChildren.push(
498
+ <span
499
+ key={`${keyPrefix}-${index}`}
500
+ data-slot="badge-label"
501
+ dir="auto"
502
+ className={labelClassName}
503
+ >
504
+ {child}
505
+ </span>
506
+ )
507
+
508
+ return
509
+ }
510
+
511
+ if (
512
+ React.isValidElement<{ children?: React.ReactNode }>(child) &&
513
+ child.type === React.Fragment
514
+ ) {
515
+ renderedChildren.push(
516
+ ...renderBadgeChildren(
517
+ child.props.children,
518
+ type,
519
+ `${keyPrefix}-${index}`
520
+ )
521
+ )
522
+
523
+ return
524
+ }
525
+
526
+ renderedChildren.push(child)
527
+ })
528
+
529
+ return renderedChildren
530
+ }
531
+
532
+ function BadgeDot() {
533
+ return (
534
+ <span
535
+ data-slot="badge-dot"
536
+ aria-hidden="true"
537
+ className="flex size-[var(--bh-space-md-8)] shrink-0 items-center justify-center"
538
+ >
539
+ <span className="size-[var(--bh-space-sm-6)] rounded-[var(--bh-radius-full)] bg-[var(--badge-dot-color,currentColor)]" />
540
+ </span>
541
+ )
542
+ }
543
+
544
+ function BadgeFlag({ children }: { children?: React.ReactNode }) {
545
+ return (
546
+ <span
547
+ data-slot="badge-flag"
548
+ aria-hidden={children ? undefined : "true"}
549
+ className="flex size-[var(--bh-space-3xl-16)] shrink-0 items-center justify-center overflow-hidden rounded-[var(--bh-radius-xs-2)]"
550
+ >
551
+ {children ?? (
552
+ <span className="size-full rounded-[var(--bh-radius-xs-2)] bg-[var(--badge-dot-color,currentColor)] opacity-[var(--bh-opacity-35)]" />
553
+ )}
554
+ </span>
555
+ )
556
+ }
557
+
558
+ export {
559
+ Badge,
560
+ badgeVariants,
561
+ type BadgeColor,
562
+ type BadgeProps,
563
+ type BadgeSize,
564
+ type BadgeStyle,
565
+ type BadgeType,
566
+ type LegacyBadgeVariant,
567
+ }