banhaten 0.1.0 → 0.1.2

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 (81) hide show
  1. package/README.md +21 -9
  2. package/package.json +8 -2
  3. package/registry/components/accordion.tsx +37 -1
  4. package/registry/components/alert.tsx +14 -28
  5. package/registry/components/attribute.tsx +6 -10
  6. package/registry/components/autocomplete.tsx +637 -0
  7. package/registry/components/avatar.tsx +259 -24
  8. package/registry/components/badge.tsx +97 -35
  9. package/registry/components/button-group.tsx +1 -1
  10. package/registry/components/card.tsx +1 -1
  11. package/registry/components/checkbox.tsx +19 -16
  12. package/registry/components/date-picker-state.ts +253 -0
  13. package/registry/components/date-picker.tsx +115 -158
  14. package/registry/components/expanded/ActivityFeed.tsx +37 -23
  15. package/registry/components/expanded/Banner.tsx +54 -19
  16. package/registry/components/expanded/Breadcrumbs.tsx +10 -38
  17. package/registry/components/expanded/CatalogComponentsShowcase.tsx +11 -16
  18. package/registry/components/expanded/CatalogTag.tsx +4 -11
  19. package/registry/components/expanded/CommandBar.tsx +33 -53
  20. package/registry/components/expanded/EmptyState.tsx +155 -0
  21. package/registry/components/expanded/FileUpload.tsx +362 -59
  22. package/registry/components/expanded/OnboardingStepListItem.tsx +6 -10
  23. package/registry/components/expanded/PageHeader.tsx +2 -11
  24. package/registry/components/expanded/Slideout.tsx +12 -23
  25. package/registry/components/expanded/Steps.tsx +6 -8
  26. package/registry/components/expanded/Table.tsx +18 -40
  27. package/registry/components/expanded/Timeline.tsx +5 -24
  28. package/registry/components/expanded/activityFeed.css +10 -54
  29. package/registry/components/expanded/banner.css +8 -75
  30. package/registry/components/expanded/breadcrumbs.css +1 -1
  31. package/registry/components/expanded/commandBar.css +23 -26
  32. package/registry/components/expanded/divider.css +1 -1
  33. package/registry/components/expanded/emptyState.css +111 -0
  34. package/registry/components/expanded/fileUpload.css +304 -75
  35. package/registry/components/expanded/pageHeader.css +1 -1
  36. package/registry/components/expanded/slideout.css +1 -0
  37. package/registry/components/expanded/steps.css +15 -51
  38. package/registry/components/expanded/table.css +6 -1
  39. package/registry/components/expanded/timeline.css +18 -15
  40. package/registry/components/input-otp.tsx +574 -0
  41. package/registry/components/input.tsx +140 -59
  42. package/registry/components/menu.tsx +470 -80
  43. package/registry/components/pagination.tsx +6 -18
  44. package/registry/components/popover.tsx +840 -0
  45. package/registry/components/radio-card.tsx +25 -31
  46. package/registry/components/select-content.tsx +28 -123
  47. package/registry/components/select.tsx +13 -9
  48. package/registry/components/skeleton.css +57 -0
  49. package/registry/components/skeleton.tsx +482 -0
  50. package/registry/components/social-button.tsx +24 -90
  51. package/registry/components/spinner.tsx +91 -7
  52. package/registry/components/textarea.tsx +21 -36
  53. package/registry/components/toggle.tsx +7 -23
  54. package/registry/components/tooltip.tsx +8 -4
  55. package/registry/examples/attribute-demo.tsx +2 -2
  56. package/registry/examples/autocomplete-demo.tsx +109 -0
  57. package/registry/examples/avatar-demo.tsx +102 -47
  58. package/registry/examples/badge-demo.tsx +16 -0
  59. package/registry/examples/checkbox-demo.tsx +3 -8
  60. package/registry/examples/date-picker-demo.tsx +75 -22
  61. package/registry/examples/expanded/banner-demo.tsx +31 -6
  62. package/registry/examples/expanded/breadcrumbs-demo.tsx +59 -0
  63. package/registry/examples/expanded/command-bar-demo.tsx +236 -0
  64. package/registry/examples/expanded/empty-state-demo.tsx +39 -0
  65. package/registry/examples/expanded/file-upload-demo.tsx +60 -0
  66. package/registry/examples/expanded/steps-demo.tsx +11 -0
  67. package/registry/examples/expanded/table-demo.tsx +142 -0
  68. package/registry/examples/input-demo.tsx +1 -1
  69. package/registry/examples/input-otp-demo.tsx +72 -0
  70. package/registry/examples/menu-demo.tsx +101 -88
  71. package/registry/examples/popover-demo.tsx +546 -0
  72. package/registry/examples/progress-demo.tsx +2 -2
  73. package/registry/examples/select-demo.tsx +32 -18
  74. package/registry/examples/skeleton-demo.tsx +56 -0
  75. package/registry/examples/social-button-demo.tsx +33 -33
  76. package/registry/examples/spinner-demo.tsx +59 -0
  77. package/registry/examples/tag-demo.tsx +1 -1
  78. package/registry/examples/textarea-demo.tsx +1 -1
  79. package/registry/index.json +266 -20
  80. package/registry/styles/globals.css +93 -3
  81. package/src/cli/index.js +997 -62
@@ -3,36 +3,145 @@
3
3
  import * as React from "react"
4
4
  import * as AvatarPrimitive from "@radix-ui/react-avatar"
5
5
  import { cva, type VariantProps } from "class-variance-authority"
6
+ import {
7
+ BadgeCheckIcon,
8
+ BanIcon,
9
+ PencilIcon,
10
+ PlusIcon,
11
+ UserIcon,
12
+ XIcon,
13
+ } from "lucide-react"
6
14
 
7
15
  import { cn } from "@/lib/utils"
8
16
 
9
- const avatarVariants = cva("relative flex shrink-0 rounded-[var(--bh-radius-full)]", {
10
- variants: {
11
- size: {
12
- sm: "size-[var(--bh-space-6xl-32)]",
13
- default: "size-[var(--bh-space-7xl-40)]",
14
- lg: "size-[var(--bh-space-8xl-48)]",
15
- xl: "size-[var(--bh-space-9xl-64)]",
17
+ const avatarSizeVariants = {
18
+ "2xs":
19
+ "[--bh-avatar-size:var(--bh-avatar-size-2xs)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-2xs)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-2xs)]",
20
+ xs: "[--bh-avatar-size:var(--bh-avatar-size-xs)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-xs)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-xs)]",
21
+ sm: "[--bh-avatar-size:var(--bh-avatar-size-sm)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-sm)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-sm)]",
22
+ md: "[--bh-avatar-size:var(--bh-avatar-size-md)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-md)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-md)]",
23
+ lg: "[--bh-avatar-size:var(--bh-avatar-size-lg)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-lg)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-lg)]",
24
+ default:
25
+ "[--bh-avatar-size:var(--bh-avatar-size-xl)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-xl)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-xl)]",
26
+ xl: "[--bh-avatar-size:var(--bh-avatar-size-xl)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-xl)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-xl)]",
27
+ "2xl":
28
+ "[--bh-avatar-size:var(--bh-avatar-size-2xl)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-2xl)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-2xl)]",
29
+ "3xl":
30
+ "[--bh-avatar-size:var(--bh-avatar-size-3xl)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-3xl)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-3xl)]",
31
+ "4xl":
32
+ "[--bh-avatar-size:var(--bh-avatar-size-4xl)] [--bh-avatar-fallback-size:var(--bh-avatar-fallback-font-size-4xl)] [--bh-avatar-icon-size:var(--bh-avatar-icon-size-4xl)]",
33
+ } as const
34
+
35
+ const avatarVariants = cva(
36
+ "relative flex size-[var(--bh-avatar-size)] shrink-0 items-center justify-center overflow-visible rounded-[var(--bh-avatar-radius)] [--bh-avatar-radius:var(--bh-radius-full)]",
37
+ {
38
+ variants: {
39
+ size: avatarSizeVariants,
40
+ shape: {
41
+ circular: "[--bh-avatar-radius:var(--bh-radius-full)]",
42
+ rounded: "[--bh-avatar-radius:var(--bh-radius-lg-8)]",
43
+ },
44
+ },
45
+ defaultVariants: {
46
+ size: "default",
47
+ shape: "circular",
16
48
  },
17
- },
18
- defaultVariants: {
19
- size: "default",
20
- },
21
- })
49
+ }
50
+ )
22
51
 
23
52
  const avatarFallbackVariants = cva(
24
- "flex size-full items-center justify-center rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-neutral-subtle)] whitespace-nowrap text-[var(--bh-content-subtle)]",
53
+ "flex size-full items-center justify-center rounded-[var(--bh-avatar-radius,var(--bh-radius-full))] bg-[var(--bh-bg-neutral-subtle)] text-[length:var(--bh-avatar-fallback-size,var(--bh-text-body-sm-medium-font-size))] font-[var(--bh-font-weight-semibold)] leading-none text-[var(--bh-content-subtle)] whitespace-nowrap",
54
+ {
55
+ variants: {
56
+ size: avatarSizeVariants,
57
+ },
58
+ defaultVariants: {
59
+ size: "default",
60
+ },
61
+ }
62
+ )
63
+
64
+ const avatarIconVariants = cva(
65
+ "flex size-full items-center justify-center rounded-[var(--bh-avatar-radius,var(--bh-radius-full))] bg-[var(--bh-bg-neutral-subtle)] text-[var(--bh-content-subtle)]",
66
+ {
67
+ variants: {
68
+ size: avatarSizeVariants,
69
+ },
70
+ defaultVariants: {
71
+ size: "default",
72
+ },
73
+ }
74
+ )
75
+
76
+ const avatarStatusVariants = cva(
77
+ "absolute end-0 bottom-0 flex size-[var(--bh-avatar-status-size)] items-center justify-center rounded-[var(--bh-radius-full)] border-[var(--bh-avatar-status-ring)] border-[var(--bh-bg-default)] shadow-[var(--shadow-avatar-badge)]",
25
78
  {
26
79
  variants: {
27
80
  size: {
28
- sm: "text-[length:var(--bh-text-body-xs-medium-font-size)] font-[var(--bh-text-body-xs-medium-font-weight)] leading-[var(--bh-text-body-xs-medium-line-height)] tracking-[var(--bh-text-body-xs-medium-letter-spacing)]",
29
- default: "text-[length:var(--bh-text-body-sm-medium-font-size)] font-[var(--bh-text-body-sm-medium-font-weight)] leading-[var(--bh-text-body-sm-medium-line-height)] tracking-[var(--bh-text-body-sm-medium-letter-spacing)]",
30
- lg: "text-[length:var(--bh-text-body-sm-medium-font-size)] font-[var(--bh-text-body-sm-medium-font-weight)] leading-[var(--bh-text-body-sm-medium-line-height)] tracking-[var(--bh-text-body-sm-medium-letter-spacing)]",
31
- xl: "text-[length:var(--bh-text-body-md-medium-font-size)] font-[var(--bh-text-body-md-medium-font-weight)] leading-[var(--bh-text-body-md-medium-line-height)] tracking-[var(--bh-text-body-md-medium-letter-spacing)]",
81
+ tiny:
82
+ "[--bh-avatar-status-size:var(--bh-avatar-status-size-tiny)] [--bh-avatar-status-ring:var(--bh-avatar-status-ring-thin)]",
83
+ xsmall:
84
+ "[--bh-avatar-status-size:var(--bh-avatar-status-size-xsmall)] [--bh-avatar-status-ring:var(--bh-avatar-status-ring-thin)]",
85
+ small:
86
+ "[--bh-avatar-status-size:var(--bh-avatar-status-size-small)] [--bh-avatar-status-ring:var(--bh-avatar-status-ring-default)]",
87
+ medium:
88
+ "[--bh-avatar-status-size:var(--bh-avatar-status-size-medium)] [--bh-avatar-status-ring:var(--bh-avatar-status-ring-default)]",
89
+ large:
90
+ "[--bh-avatar-status-size:var(--bh-avatar-status-size-large)] [--bh-avatar-status-ring:var(--bh-avatar-status-ring-default)]",
91
+ xlarge:
92
+ "[--bh-avatar-status-size:var(--bh-avatar-status-size-xlarge)] [--bh-avatar-status-ring:var(--bh-avatar-status-ring-default)]",
93
+ },
94
+ status: {
95
+ offline: "bg-[var(--bh-bg-neutral-medium)]",
96
+ busy: "bg-[var(--bh-bg-accent-red-default)]",
97
+ blocked:
98
+ "bg-[var(--bh-bg-default)] text-[var(--bh-bg-accent-red-default)] ring-[var(--bh-border-width-default)] ring-inset ring-[var(--bh-bg-accent-red-default)]",
99
+ available: "bg-[var(--bh-bg-success-default)]",
100
+ away: "bg-[var(--bh-bg-accent-golden-default)]",
32
101
  },
33
102
  },
34
103
  defaultVariants: {
35
- size: "default",
104
+ size: "medium",
105
+ status: "available",
106
+ },
107
+ }
108
+ )
109
+
110
+ const avatarActionVariants = cva(
111
+ "absolute end-0 top-0 flex size-[var(--bh-avatar-action-size)] translate-x-1/4 -translate-y-1/4 items-center justify-center rounded-[var(--bh-radius-full)] text-[var(--bh-content-on-brand)] rtl:-translate-x-1/4",
112
+ {
113
+ variants: {
114
+ size: {
115
+ tiny:
116
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-tiny)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-tiny)]",
117
+ xsmall:
118
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-xsmall)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-xsmall)]",
119
+ small:
120
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-small)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-small)]",
121
+ medium:
122
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-medium)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-medium)]",
123
+ large:
124
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-large)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-large)]",
125
+ xlarge:
126
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-xlarge)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-xlarge)]",
127
+ "2xl":
128
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-2xl)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-2xl)]",
129
+ "3xl":
130
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-3xl)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-3xl)]",
131
+ "4xl":
132
+ "[--bh-avatar-action-size:var(--bh-avatar-action-size-4xl)] [--bh-avatar-action-icon-size:var(--bh-avatar-action-icon-size-4xl)]",
133
+ },
134
+ type: {
135
+ custom: "bg-[var(--bh-bg-neutral-default)]",
136
+ edit: "bg-[var(--bh-interactive-brand-default)]",
137
+ remove: "bg-[var(--bh-interactive-danger-default)]",
138
+ verified:
139
+ "border-0 bg-transparent p-0 text-[var(--bh-bg-accent-sky-base)] shadow-none",
140
+ },
141
+ },
142
+ defaultVariants: {
143
+ size: "medium",
144
+ type: "custom",
36
145
  },
37
146
  }
38
147
  )
@@ -40,6 +149,7 @@ const avatarFallbackVariants = cva(
40
149
  function Avatar({
41
150
  className,
42
151
  size,
152
+ shape,
43
153
  ...props
44
154
  }: React.ComponentProps<typeof AvatarPrimitive.Root> &
45
155
  VariantProps<typeof avatarVariants>) {
@@ -47,7 +157,8 @@ function Avatar({
47
157
  <AvatarPrimitive.Root
48
158
  data-slot="avatar"
49
159
  data-size={size ?? "default"}
50
- className={cn(avatarVariants({ size, className }))}
160
+ data-shape={shape ?? "circular"}
161
+ className={cn(avatarVariants({ size, shape, className }))}
51
162
  {...props}
52
163
  />
53
164
  )
@@ -60,7 +171,10 @@ function AvatarImage({
60
171
  return (
61
172
  <AvatarPrimitive.Image
62
173
  data-slot="avatar-image"
63
- className={cn("size-full rounded-[var(--bh-radius-full)] object-cover", className)}
174
+ className={cn(
175
+ "size-full rounded-[var(--bh-avatar-radius,var(--bh-radius-full))] object-cover",
176
+ className
177
+ )}
64
178
  {...props}
65
179
  />
66
180
  )
@@ -81,6 +195,30 @@ function AvatarFallback({
81
195
  )
82
196
  }
83
197
 
198
+ function AvatarIcon({
199
+ className,
200
+ children,
201
+ size,
202
+ ...props
203
+ }: React.ComponentProps<"span"> & VariantProps<typeof avatarIconVariants>) {
204
+ return (
205
+ <span
206
+ aria-hidden={props["aria-label"] ? undefined : true}
207
+ data-slot="avatar-icon"
208
+ className={cn(avatarIconVariants({ size, className }))}
209
+ {...props}
210
+ >
211
+ {children ?? (
212
+ <UserIcon
213
+ aria-hidden="true"
214
+ className="size-[var(--bh-avatar-icon-size)]"
215
+ strokeWidth={2.1}
216
+ />
217
+ )}
218
+ </span>
219
+ )
220
+ }
221
+
84
222
  function AvatarBadge({
85
223
  className,
86
224
  ...props
@@ -97,6 +235,53 @@ function AvatarBadge({
97
235
  )
98
236
  }
99
237
 
238
+ function AvatarStatus({
239
+ className,
240
+ size,
241
+ status,
242
+ ...props
243
+ }: React.ComponentProps<"span"> & VariantProps<typeof avatarStatusVariants>) {
244
+ return (
245
+ <span
246
+ aria-hidden={props["aria-label"] ? undefined : true}
247
+ data-slot="avatar-status"
248
+ data-status={status ?? "available"}
249
+ className={cn(avatarStatusVariants({ size, status, className }))}
250
+ {...props}
251
+ >
252
+ {status === "blocked" ? (
253
+ <BanIcon
254
+ aria-hidden="true"
255
+ className="size-full"
256
+ strokeWidth={2.4}
257
+ />
258
+ ) : null}
259
+ </span>
260
+ )
261
+ }
262
+
263
+ function AvatarAction({
264
+ className,
265
+ children,
266
+ size,
267
+ type,
268
+ ...props
269
+ }: React.ComponentProps<"span"> & VariantProps<typeof avatarActionVariants>) {
270
+ const resolvedType = type ?? "custom"
271
+
272
+ return (
273
+ <span
274
+ aria-hidden={props["aria-label"] ? undefined : true}
275
+ data-slot="avatar-action"
276
+ data-type={resolvedType}
277
+ className={cn(avatarActionVariants({ size, type, className }))}
278
+ {...props}
279
+ >
280
+ {children ?? <AvatarActionIcon type={resolvedType} />}
281
+ </span>
282
+ )
283
+ }
284
+
100
285
  function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
101
286
  return (
102
287
  <div
@@ -114,29 +299,79 @@ function AvatarGroupCount({
114
299
  className,
115
300
  children,
116
301
  dir = "ltr",
302
+ size,
117
303
  ...props
118
- }: React.ComponentProps<"span">) {
304
+ }: React.ComponentProps<"span"> & VariantProps<typeof avatarVariants>) {
119
305
  return (
120
306
  <span
121
307
  data-slot="avatar-group-count"
122
- dir={dir}
123
308
  className={cn(
124
- "-ms-[var(--bh-space-md-8)] flex size-[var(--bh-space-7xl-40)] items-center justify-center rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-neutral-subtle)] text-[length:var(--bh-text-body-sm-medium-font-size)] font-[var(--bh-text-body-sm-medium-font-weight)] leading-[var(--bh-text-body-sm-medium-line-height)] tracking-[var(--bh-text-body-sm-medium-letter-spacing)] text-[var(--bh-content-default)] ring-[var(--bh-space-xxs-2)] ring-[var(--bh-bg-default)]",
309
+ avatarVariants({ size }),
310
+ "-ms-[var(--bh-space-md-8)] bg-[var(--bh-bg-neutral-subtle)] text-[length:var(--bh-avatar-fallback-size,var(--bh-text-body-sm-medium-font-size))] font-[var(--bh-font-weight-semibold)] leading-none text-[var(--bh-content-subtle)] ring-[var(--bh-space-xxs-2)] ring-[var(--bh-bg-default)]",
125
311
  className
126
312
  )}
127
313
  {...props}
128
314
  >
129
- {children}
315
+ <span dir={dir}>{children}</span>
130
316
  </span>
131
317
  )
132
318
  }
133
319
 
320
+ function AvatarActionIcon({
321
+ type,
322
+ }: {
323
+ type: NonNullable<VariantProps<typeof avatarActionVariants>["type"]>
324
+ }) {
325
+ if (type === "edit") {
326
+ return (
327
+ <PencilIcon
328
+ aria-hidden="true"
329
+ className="size-[var(--bh-avatar-action-icon-size)]"
330
+ strokeWidth={2.6}
331
+ />
332
+ )
333
+ }
334
+
335
+ if (type === "remove") {
336
+ return (
337
+ <XIcon
338
+ aria-hidden="true"
339
+ className="size-[var(--bh-avatar-action-icon-size)]"
340
+ strokeWidth={2.8}
341
+ />
342
+ )
343
+ }
344
+
345
+ if (type === "verified") {
346
+ return (
347
+ <BadgeCheckIcon
348
+ aria-hidden="true"
349
+ className="size-[var(--bh-avatar-action-size)] fill-current text-[var(--bh-bg-accent-sky-base)] [stroke:var(--bh-content-on-brand)]"
350
+ strokeWidth={2.4}
351
+ />
352
+ )
353
+ }
354
+
355
+ return (
356
+ <PlusIcon
357
+ aria-hidden="true"
358
+ className="size-[var(--bh-avatar-action-icon-size)]"
359
+ strokeWidth={2.6}
360
+ />
361
+ )
362
+ }
363
+
134
364
  export {
135
365
  Avatar,
366
+ AvatarAction,
136
367
  AvatarImage,
368
+ AvatarIcon,
137
369
  AvatarFallback,
138
370
  AvatarBadge,
139
371
  AvatarGroup,
140
372
  AvatarGroupCount,
373
+ AvatarStatus,
374
+ avatarActionVariants,
141
375
  avatarVariants,
376
+ avatarStatusVariants,
142
377
  }