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,360 @@
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 SocialPlatform =
8
+ | "apple"
9
+ | "facebook"
10
+ | "google"
11
+ | "linkedin"
12
+ | "twitter"
13
+ | "whatsapp"
14
+
15
+ type SocialButtonVariant = "solid" | "outline"
16
+ type SocialButtonSize = "default" | "icon"
17
+
18
+ type SocialPlatformConfig = {
19
+ label: string
20
+ labelAr: string
21
+ solidBg: string
22
+ solidHover: string
23
+ solidBorder: string
24
+ solidIconBorder?: string
25
+ solidFg: string
26
+ solidIcon: string
27
+ outlineIcon: string
28
+ width: {
29
+ ltr: string
30
+ rtl: string
31
+ }
32
+ }
33
+
34
+ const socialPlatformConfig: Record<SocialPlatform, SocialPlatformConfig> = {
35
+ apple: {
36
+ label: "Sign in with Apple",
37
+ labelAr: "تسجيل الدخول باستخدام آبل",
38
+ solidBg: "var(--bh-social-apple-bg)",
39
+ solidHover: "var(--bh-social-apple-hover)",
40
+ solidBorder: "var(--bh-social-apple-border)",
41
+ solidIconBorder: "var(--bh-social-apple-icon-border)",
42
+ solidFg: "var(--bh-social-apple-fg)",
43
+ solidIcon: "var(--bh-social-apple-icon)",
44
+ outlineIcon: "var(--bh-social-apple-outline-icon)",
45
+ width: { ltr: "var(--bh-social-apple-width)", rtl: "var(--bh-social-apple-width-rtl)" },
46
+ },
47
+ facebook: {
48
+ label: "Sign in with Facebook",
49
+ labelAr: "تسجيل الدخول باستخدام فيسبوك",
50
+ solidBg: "var(--bh-social-facebook-bg)",
51
+ solidHover: "var(--bh-social-facebook-hover)",
52
+ solidBorder: "transparent",
53
+ solidFg: "var(--bh-social-facebook-fg)",
54
+ solidIcon: "var(--bh-social-facebook-icon)",
55
+ outlineIcon: "var(--bh-social-facebook-outline-icon)",
56
+ width: { ltr: "var(--bh-social-facebook-width)", rtl: "var(--bh-social-facebook-width-rtl)" },
57
+ },
58
+ google: {
59
+ label: "Sign in with Google",
60
+ labelAr: "تسجيل الدخول باستخدام جوجل",
61
+ solidBg: "var(--bh-social-google-bg)",
62
+ solidHover: "var(--bh-social-google-hover)",
63
+ solidBorder: "var(--bh-social-google-border)",
64
+ solidFg: "var(--bh-social-google-fg)",
65
+ solidIcon: "currentColor",
66
+ outlineIcon: "currentColor",
67
+ width: { ltr: "var(--bh-social-google-width)", rtl: "var(--bh-social-google-width-rtl)" },
68
+ },
69
+ linkedin: {
70
+ label: "Sign in with LinkedIn",
71
+ labelAr: "تسجيل الدخول باستخدام لينكد إن",
72
+ solidBg: "var(--bh-social-linkedin-bg)",
73
+ solidHover: "var(--bh-social-linkedin-hover)",
74
+ solidBorder: "transparent",
75
+ solidFg: "var(--bh-social-linkedin-fg)",
76
+ solidIcon: "var(--bh-social-linkedin-icon)",
77
+ outlineIcon: "var(--bh-social-linkedin-outline-icon)",
78
+ width: { ltr: "var(--bh-social-linkedin-width)", rtl: "var(--bh-social-linkedin-width-rtl)" },
79
+ },
80
+ twitter: {
81
+ label: "Sign in with Twitter",
82
+ labelAr: "تسجيل الدخول باستخدام تويتر",
83
+ solidBg: "var(--bh-social-twitter-bg)",
84
+ solidHover: "var(--bh-social-twitter-hover)",
85
+ solidBorder: "var(--bh-social-twitter-border)",
86
+ solidIconBorder: "var(--bh-social-twitter-icon-border)",
87
+ solidFg: "var(--bh-social-twitter-fg)",
88
+ solidIcon: "var(--bh-social-twitter-icon)",
89
+ outlineIcon: "var(--bh-social-twitter-outline-icon)",
90
+ width: { ltr: "var(--bh-social-twitter-width)", rtl: "var(--bh-social-twitter-width-rtl)" },
91
+ },
92
+ whatsapp: {
93
+ label: "Sign in with WhatsApp",
94
+ labelAr: "تسجيل الدخول باستخدام واتساب",
95
+ solidBg: "var(--bh-social-whatsapp-bg)",
96
+ solidHover: "var(--bh-social-whatsapp-hover)",
97
+ solidBorder: "transparent",
98
+ solidFg: "var(--bh-social-whatsapp-fg)",
99
+ solidIcon: "var(--bh-social-whatsapp-icon)",
100
+ outlineIcon: "var(--bh-social-whatsapp-outline-icon)",
101
+ width: { ltr: "var(--bh-social-whatsapp-width)", rtl: "var(--bh-social-whatsapp-width-rtl)" },
102
+ },
103
+ }
104
+
105
+ const socialButtonVariants = cva(
106
+ "group/social-button relative inline-flex items-center justify-center whitespace-nowrap rounded-[var(--bh-social-button-radius)] bg-[var(--bh-social-button-bg)] text-[var(--bh-social-button-fg)] shadow-[var(--shadow-social-button)] outline-none transition-[background-color,box-shadow,color] [--bh-social-button-current-border:var(--bh-social-button-border)] [--shadow-social-button:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-social-button-current-border,var(--bh-social-button-border,transparent)),var(--shadow-component-default)] rtl:[--bh-social-button-width:var(--bh-social-button-width-rtl)] hover:bg-[var(--bh-social-button-bg-hover)] focus-visible:[--bh-social-button-current-border:var(--bh-social-button-focus-border)] focus-visible:shadow-[var(--shadow-social-button-focus)] disabled:pointer-events-none disabled:opacity-[var(--bh-opacity-50)] [&_svg]:pointer-events-none [&_svg]:shrink-0",
107
+ {
108
+ variants: {
109
+ variant: {
110
+ solid: "",
111
+ outline: "",
112
+ },
113
+ size: {
114
+ default:
115
+ "h-[var(--bh-social-button-height)] w-[var(--bh-social-button-width)] gap-[var(--bh-social-button-gap)] px-[var(--bh-social-button-padding-x)] py-[var(--bh-social-button-padding-y)] text-[length:var(--bh-text-button-font-size)] font-[var(--bh-text-button-font-weight)] leading-[var(--bh-text-button-line-height)] tracking-[var(--bh-text-button-letter-spacing)]",
116
+ icon: "size-[var(--bh-social-button-height)] p-0",
117
+ },
118
+ },
119
+ defaultVariants: {
120
+ variant: "solid",
121
+ size: "default",
122
+ },
123
+ }
124
+ )
125
+
126
+ type SocialButtonProps = Omit<React.ComponentProps<"button">, "children"> &
127
+ VariantProps<typeof socialButtonVariants> & {
128
+ platform: SocialPlatform
129
+ asChild?: boolean
130
+ children?: React.ReactNode
131
+ label?: string
132
+ }
133
+
134
+ const SocialButton = React.forwardRef<HTMLButtonElement, SocialButtonProps>(function SocialButton({
135
+ className,
136
+ platform,
137
+ variant = "solid",
138
+ size = "default",
139
+ label,
140
+ asChild = false,
141
+ children,
142
+ dir,
143
+ style,
144
+ type,
145
+ "aria-label": ariaLabel,
146
+ ...props
147
+ }, ref) {
148
+ const config = socialPlatformConfig[platform]
149
+ const selectedVariant = variant || "solid"
150
+ const selectedSize = size || "default"
151
+ const isIcon = selectedSize === "icon"
152
+ const defaultLabel = getDefaultLabel(config, dir)
153
+ const visibleLabel = label || (isSimpleLabel(children) ? children : defaultLabel)
154
+ const accessibleLabel =
155
+ typeof visibleLabel === "string" || typeof visibleLabel === "number"
156
+ ? String(visibleLabel)
157
+ : defaultLabel
158
+ const Comp = asChild ? Slot : "button"
159
+ const cssVars = getSocialButtonVars(config, selectedVariant, isIcon)
160
+ const content = (
161
+ <>
162
+ <SocialButtonIcon platform={platform} variant={selectedVariant} />
163
+ {!isIcon && (
164
+ <span
165
+ data-slot="social-button-label"
166
+ dir="auto"
167
+ className="min-w-0 pe-[var(--bh-social-button-label-padding-inline-end)]"
168
+ >
169
+ {visibleLabel}
170
+ </span>
171
+ )}
172
+ </>
173
+ )
174
+ const slottedChildren =
175
+ asChild && React.isValidElement(children)
176
+ ? React.cloneElement(children, undefined, content)
177
+ : content
178
+
179
+ return (
180
+ <Comp
181
+ aria-label={isIcon ? ariaLabel || accessibleLabel : ariaLabel}
182
+ data-platform={platform}
183
+ data-size={selectedSize}
184
+ data-slot="social-button"
185
+ data-variant={selectedVariant}
186
+ dir={dir}
187
+ ref={ref}
188
+ className={cn(
189
+ socialButtonVariants({
190
+ variant: selectedVariant,
191
+ size: selectedSize,
192
+ className,
193
+ })
194
+ )}
195
+ style={{ ...cssVars, ...style }}
196
+ {...(!asChild ? { type: type || "button" } : {})}
197
+ {...props}
198
+ >
199
+ {slottedChildren}
200
+ </Comp>
201
+ )
202
+ })
203
+
204
+ function isSimpleLabel(
205
+ value: React.ReactNode
206
+ ): value is string | number {
207
+ return typeof value === "string" || typeof value === "number"
208
+ }
209
+
210
+ function getDefaultLabel(
211
+ config: SocialPlatformConfig,
212
+ dir: React.HTMLAttributes<HTMLElement>["dir"]
213
+ ) {
214
+ return dir === "rtl" ? config.labelAr : config.label
215
+ }
216
+
217
+ function getSocialButtonVars(
218
+ config: SocialPlatformConfig,
219
+ variant: SocialButtonVariant,
220
+ isIcon: boolean
221
+ ) {
222
+ const isSolid = variant === "solid"
223
+ const border = isSolid
224
+ ? isIcon
225
+ ? config.solidIconBorder || config.solidBorder
226
+ : config.solidBorder
227
+ : "var(--bh-border-default)"
228
+
229
+ return {
230
+ "--bh-social-button-bg": isSolid ? config.solidBg : "var(--bh-bg-raised)",
231
+ "--bh-social-button-bg-hover": isSolid
232
+ ? config.solidHover
233
+ : "var(--bh-bg-raised-hover)",
234
+ "--bh-social-button-border": border,
235
+ "--bh-social-button-focus-border": isSolid
236
+ ? border
237
+ : "var(--bh-border-focus)",
238
+ "--bh-social-button-fg": isSolid
239
+ ? config.solidFg
240
+ : "var(--bh-content-default)",
241
+ "--bh-social-button-icon": isSolid ? config.solidIcon : config.outlineIcon,
242
+ "--bh-social-button-width": isIcon
243
+ ? "var(--bh-social-button-height)"
244
+ : config.width.ltr,
245
+ "--bh-social-button-width-rtl": isIcon
246
+ ? "var(--bh-social-button-height)"
247
+ : config.width.rtl,
248
+ } as React.CSSProperties
249
+ }
250
+
251
+ function SocialButtonIcon({
252
+ platform,
253
+ variant,
254
+ }: {
255
+ platform: SocialPlatform
256
+ variant: SocialButtonVariant
257
+ }) {
258
+ const color =
259
+ platform === "google" ? undefined : "var(--bh-social-button-icon)"
260
+
261
+ return (
262
+ <svg
263
+ aria-hidden="true"
264
+ className="size-[var(--bh-social-button-icon-size)]"
265
+ data-slot="social-button-icon"
266
+ fill="none"
267
+ focusable="false"
268
+ viewBox="0 0 18 18"
269
+ >
270
+ {platform === "apple" && <AppleIcon color={color} />}
271
+ {platform === "facebook" && <FacebookIcon color={color} />}
272
+ {platform === "google" && <GoogleIcon />}
273
+ {platform === "linkedin" && <LinkedInIcon color={color} />}
274
+ {platform === "twitter" && <TwitterIcon color={color} />}
275
+ {platform === "whatsapp" && <WhatsAppIcon color={color} />}
276
+ </svg>
277
+ )
278
+ }
279
+
280
+ function AppleIcon({ color }: { color?: string }) {
281
+ return (
282
+ <path
283
+ d="M13.54 9.55c-.02-1.86 1.52-2.75 1.59-2.79-.87-1.27-2.22-1.44-2.7-1.46-1.15-.12-2.24.68-2.82.68-.59 0-1.49-.66-2.45-.64-1.26.02-2.42.73-3.07 1.86-1.31 2.27-.34 5.63.94 7.47.62.9 1.37 1.91 2.35 1.87.94-.04 1.3-.61 2.44-.61 1.13 0 1.46.61 2.45.59 1.01-.02 1.66-.92 2.28-1.82.72-1.05 1.02-2.07 1.03-2.12-.02-.01-1.99-.76-2.03-3.03ZM11.68 4.1c.52-.63.87-1.5.77-2.37-.74.03-1.64.49-2.17 1.12-.48.55-.9 1.44-.79 2.29.83.06 1.67-.42 2.19-1.04Z"
284
+ fill={color}
285
+ />
286
+ )
287
+ }
288
+
289
+ function FacebookIcon({ color }: { color?: string }) {
290
+ return (
291
+ <path
292
+ d="M18 9A9 9 0 1 0 7.59 17.9v-6.3H5.3V9h2.29V6.98c0-2.27 1.35-3.52 3.42-3.52.99 0 2.02.18 2.02.18v2.22h-1.14c-1.12 0-1.47.7-1.47 1.41V9h2.51l-.4 2.6h-2.11v6.3A9 9 0 0 0 18 9Z"
293
+ fill={color}
294
+ />
295
+ )
296
+ }
297
+
298
+ function GoogleIcon() {
299
+ return (
300
+ <>
301
+ <path
302
+ d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z"
303
+ fill="var(--bh-social-google-blue)"
304
+ />
305
+ <path
306
+ d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.35 0-4.34-1.59-5.05-3.72H.93v2.33A9 9 0 0 0 9 18Z"
307
+ fill="var(--bh-social-google-green)"
308
+ />
309
+ <path
310
+ d="M3.95 10.7A5.41 5.41 0 0 1 3.66 9c0-.59.1-1.16.29-1.7V4.97H.93A9 9 0 0 0 0 9c0 1.45.34 2.82.93 4.03l3.02-2.33Z"
311
+ fill="var(--bh-social-google-yellow)"
312
+ />
313
+ <path
314
+ d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58C13.47.9 11.43 0 9 0A9 9 0 0 0 .93 4.97L3.95 7.3C4.66 5.17 6.65 3.58 9 3.58Z"
315
+ fill="var(--bh-social-google-red)"
316
+ />
317
+ </>
318
+ )
319
+ }
320
+
321
+ function LinkedInIcon({ color }: { color?: string }) {
322
+ return (
323
+ <>
324
+ <path
325
+ d="M3.23 7.2h2.43V15H3.23V7.2Zm1.22-3.88a1.41 1.41 0 1 1 0 2.82 1.41 1.41 0 0 1 0-2.82Z"
326
+ fill={color}
327
+ />
328
+ <path
329
+ d="M7.18 7.2h2.33v1.07h.03c.32-.61 1.12-1.26 2.3-1.26 2.47 0 2.93 1.63 2.93 3.74V15h-2.43v-3.77c0-.9-.02-2.06-1.26-2.06-1.26 0-1.45.98-1.45 1.99V15H7.18V7.2Z"
330
+ fill={color}
331
+ />
332
+ </>
333
+ )
334
+ }
335
+
336
+ function TwitterIcon({ color }: { color?: string }) {
337
+ return (
338
+ <path
339
+ d="M10.65 7.72 16.16 1.5h-1.31l-4.78 5.4-3.82-5.4H1.83l5.78 8.17-5.78 6.83h1.31l5.05-5.97 4.04 5.97h4.42l-6-8.78Zm-1.79 2.08-.58-.82-4.66-6.4h1.72l3.76 5.17.58.82 4.89 6.72h-1.72L8.86 9.8Z"
340
+ fill={color}
341
+ />
342
+ )
343
+ }
344
+
345
+ function WhatsAppIcon({ color }: { color?: string }) {
346
+ return (
347
+ <path
348
+ d="M9.03 1.5A7.42 7.42 0 0 0 2.6 12.62L1.5 16.5l3.98-1.05A7.43 7.43 0 1 0 9.03 1.5Zm0 13.56c-1.22 0-2.35-.36-3.3-.98l-.24-.15-2.36.62.63-2.3-.16-.24a6.1 6.1 0 1 1 5.43 3.05Zm3.34-4.57c-.18-.09-1.08-.53-1.25-.59-.17-.06-.29-.09-.42.09-.12.18-.48.59-.59.71-.11.12-.22.13-.4.04-.18-.09-.77-.28-1.47-.9-.54-.48-.91-1.08-1.02-1.26-.11-.18-.01-.28.08-.37.08-.08.18-.22.27-.33.09-.11.12-.18.18-.3.06-.12.03-.23-.01-.33-.05-.09-.42-1-.57-1.37-.15-.36-.3-.31-.42-.32h-.36c-.12 0-.33.05-.5.23-.17.18-.65.64-.65 1.56 0 .92.67 1.81.76 1.94.09.12 1.32 2.02 3.2 2.83.45.19.8.31 1.07.4.45.14.86.12 1.18.07.36-.05 1.08-.44 1.23-.86.15-.42.15-.79.11-.86-.05-.08-.17-.13-.35-.22Z"
349
+ fill={color}
350
+ />
351
+ )
352
+ }
353
+
354
+ export { SocialButton, socialButtonVariants, socialPlatformConfig }
355
+ export type {
356
+ SocialButtonProps,
357
+ SocialButtonSize,
358
+ SocialButtonVariant,
359
+ SocialPlatform,
360
+ }
@@ -0,0 +1,31 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
6
+ return (
7
+ <svg
8
+ aria-hidden="true"
9
+ data-slot="spinner"
10
+ viewBox="0 0 24 24"
11
+ className={cn("size-[var(--bh-spinner-size)] animate-spin text-current", className)}
12
+ {...props}
13
+ >
14
+ <circle
15
+ cx="12"
16
+ cy="12"
17
+ r="10"
18
+ fill="none"
19
+ stroke="currentColor"
20
+ strokeWidth="4"
21
+ opacity="var(--bh-opacity-25)"
22
+ />
23
+ <path
24
+ fill="currentColor"
25
+ d="M22 12a10 10 0 0 1-10 10v-4a6 6 0 0 0 6-6z"
26
+ />
27
+ </svg>
28
+ )
29
+ }
30
+
31
+ export { Spinner }