banhaten 0.1.3 → 0.2.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.
- package/CHANGELOG.md +45 -0
- package/CONTRIBUTING.md +44 -0
- package/README.md +65 -13
- package/SECURITY.md +15 -0
- package/banhaten.config.example.json +0 -2
- package/docs/design-system/README.md +9 -0
- package/docs/design-system/adoption-quality-remediation.md +87 -0
- package/docs/design-system/agent-usage.md +13 -0
- package/docs/design-system/appearance-presets.md +6 -1
- package/docs/design-system/component-docs-pattern.md +81 -0
- package/docs/design-system/component-token-consistency-audit.md +13 -3
- package/docs/design-system/components/README.md +3 -2
- package/docs/design-system/components/accordion.md +16 -0
- package/docs/design-system/components/activity-feed.md +15 -1
- package/docs/design-system/components/alert-dialog.md +17 -0
- package/docs/design-system/components/alert.md +46 -14
- package/docs/design-system/components/aspect-ratio.md +15 -0
- package/docs/design-system/components/attribute.md +16 -0
- package/docs/design-system/components/autocomplete.md +19 -0
- package/docs/design-system/components/avatar.md +18 -0
- package/docs/design-system/components/badge.md +19 -0
- package/docs/design-system/components/banner.md +15 -1
- package/docs/design-system/components/breadcrumbs.md +14 -0
- package/docs/design-system/components/button-group.md +34 -0
- package/docs/design-system/components/button.md +18 -0
- package/docs/design-system/components/card.md +18 -1
- package/docs/design-system/components/carousel.md +20 -3
- package/docs/design-system/components/catalog-components.md +15 -1
- package/docs/design-system/components/chart.md +15 -0
- package/docs/design-system/components/checkbox.md +16 -0
- package/docs/design-system/components/collapsible.md +15 -0
- package/docs/design-system/components/command.md +15 -0
- package/docs/design-system/components/context-menu.md +15 -0
- package/docs/design-system/components/date-picker.md +21 -1
- package/docs/design-system/components/divider.md +16 -0
- package/docs/design-system/components/empty-state.md +17 -0
- package/docs/design-system/components/field.md +17 -0
- package/docs/design-system/components/file-upload.md +14 -0
- package/docs/design-system/components/hover-card.md +15 -0
- package/docs/design-system/components/input-group.md +17 -0
- package/docs/design-system/components/input-otp.md +18 -0
- package/docs/design-system/components/input.md +43 -7
- package/docs/design-system/components/item.md +72 -0
- package/docs/design-system/components/kbd.md +18 -0
- package/docs/design-system/components/label.md +16 -0
- package/docs/design-system/components/menu.md +17 -0
- package/docs/design-system/components/menubar.md +15 -0
- package/docs/design-system/components/modal.md +25 -4
- package/docs/design-system/components/native-select.md +18 -0
- package/docs/design-system/components/navigation-menu.md +15 -0
- package/docs/design-system/components/onboarding-step-list-item.md +15 -1
- package/docs/design-system/components/page-header.md +15 -1
- package/docs/design-system/components/pagination.md +30 -8
- package/docs/design-system/components/popover.md +19 -0
- package/docs/design-system/components/progress-slider.md +18 -0
- package/docs/design-system/components/progress.md +17 -0
- package/docs/design-system/components/radio-card.md +16 -0
- package/docs/design-system/components/radio-group.md +17 -0
- package/docs/design-system/components/resizable.md +15 -0
- package/docs/design-system/components/scroll-area.md +15 -0
- package/docs/design-system/components/segmented-control.md +71 -0
- package/docs/design-system/components/select.md +44 -7
- package/docs/design-system/components/sheet.md +17 -0
- package/docs/design-system/components/sidebar.md +15 -0
- package/docs/design-system/components/skeleton.md +18 -0
- package/docs/design-system/components/slideout.md +14 -0
- package/docs/design-system/components/slider.md +20 -0
- package/docs/design-system/components/social-button.md +21 -3
- package/docs/design-system/components/spinner.md +16 -0
- package/docs/design-system/components/steps.md +14 -0
- package/docs/design-system/components/table.md +15 -1
- package/docs/design-system/components/tabs.md +17 -0
- package/docs/design-system/components/tag.md +17 -0
- package/docs/design-system/components/textarea.md +16 -0
- package/docs/design-system/components/timeline.md +14 -0
- package/docs/design-system/components/toast.md +17 -0
- package/docs/design-system/components/toggle.md +17 -0
- package/docs/design-system/components/toolbar.md +21 -1
- package/docs/design-system/components/tooltip.md +18 -1
- package/docs/design-system/density-and-elevation.md +44 -0
- package/docs/design-system/direction-and-localization.md +23 -0
- package/docs/design-system/form-recipes.md +73 -0
- package/docs/design-system/gap-promotion-policy.md +21 -0
- package/docs/design-system/gap-promotion-report.md +166 -0
- package/docs/design-system/installation.md +68 -0
- package/docs/design-system/launch-comparison-shadcn.md +98 -0
- package/docs/design-system/registry-and-cli.md +30 -7
- package/docs/design-system/release-policy.md +30 -0
- package/docs/design-system/roadmap.md +14 -0
- package/docs/design-system/support-matrix.md +23 -0
- package/docs/design-system/tabs.md +1 -1
- package/docs/design-system/token-governance.md +23 -1
- package/package.json +29 -15
- package/registry/component-contract.json +40 -0
- package/registry/components/alert-dialog.tsx +1 -1
- package/registry/components/alert.tsx +86 -65
- package/registry/components/autocomplete.tsx +23 -9
- package/registry/components/avatar.tsx +7 -7
- package/registry/components/badge.tsx +1 -1
- package/registry/components/button-group.tsx +321 -4
- package/registry/components/button.tsx +38 -17
- package/registry/components/card.tsx +68 -59
- package/registry/components/carousel.tsx +53 -5
- package/registry/components/chart.tsx +36 -3
- package/registry/components/checkbox.tsx +3 -3
- package/registry/components/collapsible.tsx +1 -1
- package/registry/components/command.tsx +1 -1
- package/registry/components/context-menu.tsx +1 -1
- package/registry/components/date-picker.tsx +245 -104
- package/registry/components/expanded/ActivityFeed.tsx +6 -15
- package/registry/components/expanded/Banner.tsx +3 -3
- package/registry/components/expanded/Breadcrumbs.tsx +5 -5
- package/registry/components/expanded/CatalogComponentsShowcase.tsx +13 -13
- package/registry/components/expanded/CatalogDivider.tsx +1 -1
- package/registry/components/expanded/EmptyState.tsx +1 -1
- package/registry/components/expanded/FileUpload.tsx +9 -2
- package/registry/components/expanded/OnboardingStepListItem.tsx +2 -4
- package/registry/components/expanded/PageHeader.tsx +13 -13
- package/registry/components/expanded/Slideout.tsx +15 -415
- package/registry/components/expanded/Steps.tsx +4 -4
- package/registry/components/expanded/Table.tsx +116 -69
- package/registry/components/expanded/Timeline.tsx +3 -3
- package/registry/components/expanded/activityFeed.css +1 -1
- package/registry/components/expanded/breadcrumbs.css +1 -1
- package/registry/components/expanded/divider.css +1 -1
- package/registry/components/expanded/emptyState.css +1 -1
- package/registry/components/expanded/fileUpload.css +6 -6
- package/registry/components/expanded/slideout.css +9 -685
- package/registry/components/expanded/steps.css +3 -3
- package/registry/components/expanded/table.css +2 -2
- package/registry/components/expanded/timeline.css +2 -2
- package/registry/components/input-content.ts +1 -0
- package/registry/components/input-otp.tsx +13 -3
- package/registry/components/input.tsx +68 -43
- package/registry/components/item.tsx +189 -0
- package/registry/components/kbd.tsx +111 -4
- package/registry/components/menu.tsx +31 -245
- package/registry/components/menubar.tsx +1 -1
- package/registry/components/modal.tsx +142 -102
- package/registry/components/native-select.tsx +2 -2
- package/registry/components/pagination.tsx +80 -58
- package/registry/components/popover.tsx +162 -664
- package/registry/components/radio-card.tsx +116 -87
- package/registry/components/segmented-control.tsx +87 -0
- package/registry/components/select-content.tsx +2 -2
- package/registry/components/select.tsx +52 -16
- package/registry/components/sheet.tsx +1 -1
- package/registry/components/sidebar.tsx +1 -1
- package/registry/components/skeleton.css +0 -3
- package/registry/components/social-button.tsx +47 -25
- package/registry/components/spinner.tsx +18 -55
- package/registry/components/tabs.css +1 -1
- package/registry/components/tabs.tsx +8 -4
- package/registry/components/tag.tsx +2 -2
- package/registry/components/textarea.tsx +3 -3
- package/registry/components/toast.tsx +16 -11
- package/registry/components/toggle.tsx +2 -2
- package/registry/components/toolbar.tsx +89 -17
- package/registry/components/tooltip.tsx +1 -1
- package/registry/examples/alert-demo.tsx +25 -5
- package/registry/examples/attribute-demo.tsx +1 -1
- package/registry/examples/autocomplete-demo.tsx +3 -3
- package/registry/examples/avatar-demo.tsx +7 -7
- package/registry/examples/badge-demo.tsx +1 -1
- package/registry/examples/button-demo.tsx +6 -6
- package/registry/examples/button-group-demo.tsx +23 -2
- package/registry/examples/card-demo.tsx +46 -8
- package/registry/examples/carousel-demo.tsx +20 -2
- package/registry/examples/chart-demo.tsx +1 -1
- package/registry/examples/checkbox-demo.tsx +5 -5
- package/registry/examples/collection-filter-bar-demo.tsx +135 -0
- package/registry/examples/command-demo.tsx +3 -3
- package/registry/examples/{expanded/command-bar-demo.tsx → command-palette-demo.tsx} +5 -15
- package/registry/examples/context-menu-demo.tsx +1 -1
- package/registry/examples/control-density-contract-demo.tsx +61 -0
- package/registry/examples/date-picker-demo.tsx +12 -12
- package/registry/examples/divider-demo.tsx +3 -3
- package/registry/examples/expanded/banner-demo.tsx +1 -1
- package/registry/examples/expanded/breadcrumbs-demo.tsx +1 -1
- package/registry/examples/expanded/empty-state-demo.tsx +1 -1
- package/registry/examples/expanded/file-upload-demo.tsx +1 -1
- package/registry/examples/expanded/onboarding-step-demo.tsx +1 -1
- package/registry/examples/expanded/slideout-demo.tsx +2 -2
- package/registry/examples/expanded/steps-demo.tsx +1 -1
- package/registry/examples/expanded/tabs-demo.tsx +1 -1
- package/registry/examples/expanded/timeline-demo.tsx +1 -1
- package/registry/examples/hover-card-demo.tsx +2 -2
- package/registry/examples/input-demo.tsx +6 -6
- package/registry/examples/input-otp-demo.tsx +4 -4
- package/registry/examples/item-demo.tsx +46 -0
- package/registry/examples/kbd-demo.tsx +1 -1
- package/registry/examples/label-demo.tsx +1 -1
- package/registry/examples/menu-demo.tsx +1 -1
- package/registry/examples/modal-demo.tsx +67 -9
- package/registry/examples/navigation-menu-demo.tsx +1 -1
- package/registry/examples/pagination-demo.tsx +6 -3
- package/registry/examples/popover-demo.tsx +19 -19
- package/registry/examples/progress-demo.tsx +1 -1
- package/registry/examples/progress-slider-demo.tsx +1 -1
- package/registry/examples/radio-card-demo.tsx +4 -4
- package/registry/examples/radio-group-demo.tsx +2 -2
- package/registry/examples/resizable-demo.tsx +1 -1
- package/registry/examples/results-toolbar-demo.tsx +44 -0
- package/registry/examples/scroll-area-demo.tsx +3 -3
- package/registry/examples/segmented-control-demo.tsx +39 -0
- package/registry/examples/select-demo.tsx +1 -1
- package/registry/examples/sidebar-demo.tsx +1 -1
- package/registry/examples/slider-demo.tsx +3 -3
- package/registry/examples/social-button-demo.tsx +18 -8
- package/registry/examples/spinner-demo.tsx +13 -13
- package/registry/examples/tabs-demo.tsx +1 -1
- package/registry/examples/tag-demo.tsx +1 -1
- package/registry/examples/textarea-demo.tsx +4 -4
- package/registry/examples/toast-demo.tsx +1 -1
- package/registry/examples/toggle-demo.tsx +6 -6
- package/registry/examples/tooltip-demo.tsx +4 -4
- package/registry/guidance/USAGE.md +27 -0
- package/registry/hooks/use-direction.ts +193 -13
- package/registry/index.json +5311 -377
- package/registry/styles/globals.css +2440 -4061
- package/registry.json +119 -149
- package/schema/config.schema.json +11 -8
- package/schema/registry.schema.json +150 -45
- package/schema/tokens.schema.json +134 -34
- package/src/cli/command-line.js +194 -0
- package/src/cli/config-editors.js +9 -0
- package/src/cli/doctor.js +399 -0
- package/src/cli/file-transaction.js +295 -0
- package/src/cli/global-css.js +153 -0
- package/src/cli/index.js +567 -1613
- package/src/cli/install-plan.js +592 -0
- package/src/cli/install-receipt.js +171 -0
- package/src/cli/jsonc.js +203 -0
- package/src/cli/package-install-state.js +254 -0
- package/src/cli/package-manager.js +238 -0
- package/src/cli/package-plan.js +185 -0
- package/src/cli/package-version.js +97 -0
- package/src/cli/registry-query.js +207 -0
- package/src/cli/reporting.js +55 -0
- package/src/cli/schema-validation.js +19 -0
- package/src/cli/source-scanner.js +686 -0
- package/src/cli/vite-config.js +478 -0
- package/tokens/banhaten.tokens.json +4312 -309
- package/docs/design-system/components/command-bar.md +0 -57
- package/registry/components/expanded/BannerBoard.tsx +0 -225
- package/registry/components/expanded/CatalogTag.tsx +0 -85
- package/registry/components/expanded/CommandBar.tsx +0 -386
- package/registry/components/expanded/IconExplorer.tsx +0 -612
- package/registry/components/expanded/TimelineShowcase.tsx +0 -158
- package/registry/components/expanded/commandBar.css +0 -470
- package/registry/components/expanded/iconExplorer.css +0 -764
- package/registry/components/expanded/iconPacks.ts +0 -866
- package/registry/components/expanded/tag.css +0 -148
- package/registry/examples/expanded/icons-demo.tsx +0 -5
- package/tokens/Color mode.zip +0 -0
- package/tokens/Numbers.zip +0 -0
- package/tokens/Radius.zip +0 -0
- package/tokens/Theme.zip +0 -0
|
@@ -121,15 +121,15 @@ const Card = React.forwardRef<HTMLElement, CardProps>(function Card({
|
|
|
121
121
|
moreButtonLabel = "Open card menu",
|
|
122
122
|
onMoreClick,
|
|
123
123
|
orientation = "vertical",
|
|
124
|
-
primaryActionLabel
|
|
124
|
+
primaryActionLabel,
|
|
125
125
|
primaryActionProps,
|
|
126
|
-
secondaryActionLabel
|
|
126
|
+
secondaryActionLabel,
|
|
127
127
|
secondaryActionProps,
|
|
128
|
-
showDescription
|
|
129
|
-
showFooter
|
|
130
|
-
showImage
|
|
131
|
-
showMoreButton
|
|
132
|
-
showSubtitle
|
|
128
|
+
showDescription,
|
|
129
|
+
showFooter,
|
|
130
|
+
showImage,
|
|
131
|
+
showMoreButton,
|
|
132
|
+
showSubtitle,
|
|
133
133
|
subtitle,
|
|
134
134
|
title,
|
|
135
135
|
type = "leading-image",
|
|
@@ -142,13 +142,15 @@ const Card = React.forwardRef<HTMLElement, CardProps>(function Card({
|
|
|
142
142
|
? "leading-image"
|
|
143
143
|
: type ?? "leading-image"
|
|
144
144
|
const fullImage = cardOrientation === "vertical" && cardType === "full-image"
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
const shouldShowDescription = showDescription ?? description !== undefined
|
|
146
|
+
const shouldShowFooter =
|
|
147
|
+
showFooter ??
|
|
148
|
+
Boolean(footer || actions || primaryActionLabel || secondaryActionLabel)
|
|
149
|
+
const shouldShowImage = showImage ?? Boolean(imageSrc)
|
|
150
|
+
const shouldShowMoreButton = showMoreButton ?? Boolean(onMoreClick)
|
|
151
|
+
const shouldShowSubtitle = showSubtitle ?? subtitle !== undefined
|
|
150
152
|
|
|
151
|
-
const media =
|
|
153
|
+
const media = shouldShowImage ? (
|
|
152
154
|
<CardMedia
|
|
153
155
|
imageAlt={imageAlt}
|
|
154
156
|
imageSrc={imageSrc}
|
|
@@ -160,7 +162,7 @@ const Card = React.forwardRef<HTMLElement, CardProps>(function Card({
|
|
|
160
162
|
<CardBody
|
|
161
163
|
actions={actions}
|
|
162
164
|
breakpoint={cardBreakpoint}
|
|
163
|
-
description={
|
|
165
|
+
description={description}
|
|
164
166
|
footer={footer}
|
|
165
167
|
moreButtonLabel={moreButtonLabel}
|
|
166
168
|
onMoreClick={onMoreClick}
|
|
@@ -169,12 +171,12 @@ const Card = React.forwardRef<HTMLElement, CardProps>(function Card({
|
|
|
169
171
|
primaryActionProps={primaryActionProps}
|
|
170
172
|
secondaryActionLabel={secondaryActionLabel}
|
|
171
173
|
secondaryActionProps={secondaryActionProps}
|
|
172
|
-
showDescription={
|
|
173
|
-
showFooter={
|
|
174
|
-
showMoreButton={
|
|
175
|
-
showSubtitle={
|
|
176
|
-
subtitle={
|
|
177
|
-
title={
|
|
174
|
+
showDescription={shouldShowDescription}
|
|
175
|
+
showFooter={shouldShowFooter && !fullImage}
|
|
176
|
+
showMoreButton={shouldShowMoreButton}
|
|
177
|
+
showSubtitle={shouldShowSubtitle}
|
|
178
|
+
subtitle={subtitle}
|
|
179
|
+
title={title}
|
|
178
180
|
/>
|
|
179
181
|
)
|
|
180
182
|
|
|
@@ -206,10 +208,10 @@ const Card = React.forwardRef<HTMLElement, CardProps>(function Card({
|
|
|
206
208
|
breakpoint={cardBreakpoint}
|
|
207
209
|
moreButtonLabel={moreButtonLabel}
|
|
208
210
|
onMoreClick={onMoreClick}
|
|
209
|
-
showMoreButton={
|
|
210
|
-
showSubtitle={
|
|
211
|
-
subtitle={
|
|
212
|
-
title={
|
|
211
|
+
showMoreButton={shouldShowMoreButton}
|
|
212
|
+
showSubtitle={shouldShowSubtitle}
|
|
213
|
+
subtitle={subtitle}
|
|
214
|
+
title={title}
|
|
213
215
|
/>
|
|
214
216
|
</>
|
|
215
217
|
) : cardOrientation === "horizontal" &&
|
|
@@ -275,9 +277,9 @@ const CardActions = React.forwardRef<HTMLDivElement, CardActionsProps>(
|
|
|
275
277
|
function CardActions({
|
|
276
278
|
children,
|
|
277
279
|
className,
|
|
278
|
-
primaryLabel
|
|
280
|
+
primaryLabel,
|
|
279
281
|
primaryProps,
|
|
280
|
-
secondaryLabel
|
|
282
|
+
secondaryLabel,
|
|
281
283
|
secondaryProps,
|
|
282
284
|
...props
|
|
283
285
|
}, ref) {
|
|
@@ -286,23 +288,28 @@ const CardActions = React.forwardRef<HTMLDivElement, CardActionsProps>(
|
|
|
286
288
|
data-slot="card-actions"
|
|
287
289
|
ref={ref}
|
|
288
290
|
className={cn(
|
|
289
|
-
"grid w-full max-w-[var(--bh-card-actions-max-width)]
|
|
291
|
+
"grid w-full max-w-[var(--bh-card-actions-max-width)] gap-[var(--bh-space-xl-12)]",
|
|
292
|
+
primaryLabel && secondaryLabel ? "grid-cols-2" : "grid-cols-1",
|
|
290
293
|
className
|
|
291
294
|
)}
|
|
292
295
|
{...props}
|
|
293
296
|
>
|
|
294
297
|
{children ?? (
|
|
295
298
|
<>
|
|
296
|
-
|
|
297
|
-
{
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
299
|
+
{primaryLabel ? (
|
|
300
|
+
<Button {...primaryProps} className={cn("min-w-0", primaryProps?.className)}>
|
|
301
|
+
{primaryLabel}
|
|
302
|
+
</Button>
|
|
303
|
+
) : null}
|
|
304
|
+
{secondaryLabel ? (
|
|
305
|
+
<Button
|
|
306
|
+
variant="soft"
|
|
307
|
+
{...secondaryProps}
|
|
308
|
+
className={cn("min-w-0", secondaryProps?.className)}
|
|
309
|
+
>
|
|
310
|
+
{secondaryLabel}
|
|
311
|
+
</Button>
|
|
312
|
+
) : null}
|
|
306
313
|
</>
|
|
307
314
|
)}
|
|
308
315
|
</div>
|
|
@@ -331,21 +338,21 @@ function CardBody({
|
|
|
331
338
|
}: {
|
|
332
339
|
actions?: React.ReactNode
|
|
333
340
|
breakpoint: CardBreakpoint
|
|
334
|
-
description
|
|
341
|
+
description?: React.ReactNode
|
|
335
342
|
footer?: React.ReactNode
|
|
336
343
|
moreButtonLabel: string
|
|
337
344
|
onMoreClick?: React.MouseEventHandler<HTMLButtonElement>
|
|
338
345
|
orientation: CardOrientation
|
|
339
|
-
primaryActionLabel
|
|
346
|
+
primaryActionLabel?: React.ReactNode
|
|
340
347
|
primaryActionProps?: ButtonProps
|
|
341
|
-
secondaryActionLabel
|
|
348
|
+
secondaryActionLabel?: React.ReactNode
|
|
342
349
|
secondaryActionProps?: ButtonProps
|
|
343
350
|
showDescription: boolean
|
|
344
351
|
showFooter: boolean
|
|
345
352
|
showMoreButton: boolean
|
|
346
353
|
showSubtitle: boolean
|
|
347
|
-
subtitle
|
|
348
|
-
title
|
|
354
|
+
subtitle?: React.ReactNode
|
|
355
|
+
title?: React.ReactNode
|
|
349
356
|
}) {
|
|
350
357
|
const horizontal = orientation === "horizontal"
|
|
351
358
|
|
|
@@ -378,7 +385,7 @@ function CardBody({
|
|
|
378
385
|
title={title}
|
|
379
386
|
subtitleClassName={getSubtitleClassName(breakpoint)}
|
|
380
387
|
/>
|
|
381
|
-
{showDescription ? (
|
|
388
|
+
{showDescription && description !== undefined ? (
|
|
382
389
|
<p
|
|
383
390
|
data-slot="card-description"
|
|
384
391
|
dir="auto"
|
|
@@ -423,8 +430,8 @@ function CardFullImageContent({
|
|
|
423
430
|
onMoreClick?: React.MouseEventHandler<HTMLButtonElement>
|
|
424
431
|
showMoreButton: boolean
|
|
425
432
|
showSubtitle: boolean
|
|
426
|
-
subtitle
|
|
427
|
-
title
|
|
433
|
+
subtitle?: React.ReactNode
|
|
434
|
+
title?: React.ReactNode
|
|
428
435
|
}) {
|
|
429
436
|
return (
|
|
430
437
|
<div
|
|
@@ -475,20 +482,22 @@ function CardHeader({
|
|
|
475
482
|
className="flex min-w-0 items-start gap-[var(--bh-space-3xl-16)]"
|
|
476
483
|
>
|
|
477
484
|
<div className="flex min-w-0 flex-1 flex-col gap-[var(--bh-space-xxs-2)]">
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
485
|
+
{title !== undefined ? (
|
|
486
|
+
<h3
|
|
487
|
+
data-slot="card-title"
|
|
488
|
+
dir="auto"
|
|
489
|
+
className={cn(
|
|
490
|
+
"min-w-0 break-words text-[length:var(--bh-text-heading-sm-semibold-font-size)]",
|
|
491
|
+
"font-[var(--bh-text-heading-sm-semibold-font-weight)]",
|
|
492
|
+
"leading-[var(--bh-text-heading-sm-semibold-line-height)]",
|
|
493
|
+
"tracking-[var(--bh-text-heading-sm-semibold-letter-spacing)]",
|
|
494
|
+
onImage ? "text-[var(--bh-content-on-color)]" : "text-[var(--bh-content-default)]"
|
|
495
|
+
)}
|
|
496
|
+
>
|
|
497
|
+
{title}
|
|
498
|
+
</h3>
|
|
499
|
+
) : null}
|
|
500
|
+
{showSubtitle && subtitle !== undefined ? (
|
|
492
501
|
<p
|
|
493
502
|
data-slot="card-subtitle"
|
|
494
503
|
dir="auto"
|
|
@@ -8,6 +8,7 @@ import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
|
|
|
8
8
|
|
|
9
9
|
import { Button } from "@/components/ui/button"
|
|
10
10
|
import { cn } from "@/lib/utils"
|
|
11
|
+
import { useResolvedDirection, type Direction } from "@/hooks/use-direction"
|
|
11
12
|
|
|
12
13
|
type CarouselApi = UseEmblaCarouselType[1]
|
|
13
14
|
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
|
@@ -15,7 +16,23 @@ type CarouselOptions = UseCarouselParameters[0]
|
|
|
15
16
|
type CarouselPlugin = UseCarouselParameters[1]
|
|
16
17
|
type CarouselOrientation = "horizontal" | "vertical"
|
|
17
18
|
|
|
19
|
+
type CarouselMessages = {
|
|
20
|
+
nextSlide: string
|
|
21
|
+
previousSlide: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const defaultCarouselMessages: CarouselMessages = {
|
|
25
|
+
nextSlide: "Next slide",
|
|
26
|
+
previousSlide: "Previous slide",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const arabicCarouselMessages: CarouselMessages = {
|
|
30
|
+
nextSlide: "\u0627\u0644\u0634\u0631\u064a\u062d\u0629 \u0627\u0644\u062a\u0627\u0644\u064a\u0629",
|
|
31
|
+
previousSlide: "\u0627\u0644\u0634\u0631\u064a\u062d\u0629 \u0627\u0644\u0633\u0627\u0628\u0642\u0629",
|
|
32
|
+
}
|
|
33
|
+
|
|
18
34
|
type CarouselProps = React.ComponentProps<"div"> & {
|
|
35
|
+
messages?: Partial<CarouselMessages>
|
|
19
36
|
opts?: CarouselOptions
|
|
20
37
|
orientation?: CarouselOrientation
|
|
21
38
|
plugins?: CarouselPlugin
|
|
@@ -29,6 +46,8 @@ type CarouselContextValue = {
|
|
|
29
46
|
api: CarouselApi
|
|
30
47
|
canScrollNext: boolean
|
|
31
48
|
canScrollPrev: boolean
|
|
49
|
+
direction: Direction
|
|
50
|
+
messages: CarouselMessages
|
|
32
51
|
orientation: CarouselOrientation
|
|
33
52
|
scrollNext: () => void
|
|
34
53
|
scrollPrev: () => void
|
|
@@ -41,6 +60,8 @@ const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
|
|
|
41
60
|
{
|
|
42
61
|
children,
|
|
43
62
|
className,
|
|
63
|
+
dir,
|
|
64
|
+
messages: messageOverrides,
|
|
44
65
|
opts,
|
|
45
66
|
orientation = "horizontal",
|
|
46
67
|
plugins,
|
|
@@ -49,15 +70,33 @@ const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
|
|
|
49
70
|
},
|
|
50
71
|
ref
|
|
51
72
|
) {
|
|
73
|
+
const rootRef = React.useRef<HTMLDivElement | null>(null)
|
|
74
|
+
const direction = useResolvedDirection(
|
|
75
|
+
dir === "ltr" || dir === "rtl" ? dir : undefined,
|
|
76
|
+
rootRef
|
|
77
|
+
)
|
|
78
|
+
const setRootRef = React.useCallback(
|
|
79
|
+
(node: HTMLDivElement | null) => {
|
|
80
|
+
rootRef.current = node
|
|
81
|
+
if (typeof ref === "function") ref(node)
|
|
82
|
+
else if (ref) ref.current = node
|
|
83
|
+
},
|
|
84
|
+
[ref]
|
|
85
|
+
)
|
|
52
86
|
const [carouselRef, api] = useEmblaCarousel(
|
|
53
87
|
{
|
|
54
88
|
...opts,
|
|
55
89
|
axis: orientation === "horizontal" ? "x" : "y",
|
|
90
|
+
direction,
|
|
56
91
|
},
|
|
57
92
|
plugins
|
|
58
93
|
)
|
|
59
94
|
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
|
|
60
95
|
const [canScrollNext, setCanScrollNext] = React.useState(false)
|
|
96
|
+
const messages = React.useMemo(
|
|
97
|
+
() => ({ ...defaultCarouselMessages, ...messageOverrides }),
|
|
98
|
+
[messageOverrides]
|
|
99
|
+
)
|
|
61
100
|
|
|
62
101
|
const onSelect = React.useCallback((nextApi: CarouselApi) => {
|
|
63
102
|
if (!nextApi) return
|
|
@@ -86,6 +125,8 @@ const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
|
|
|
86
125
|
api,
|
|
87
126
|
canScrollNext,
|
|
88
127
|
canScrollPrev,
|
|
128
|
+
direction,
|
|
129
|
+
messages,
|
|
89
130
|
orientation,
|
|
90
131
|
scrollNext,
|
|
91
132
|
scrollPrev,
|
|
@@ -94,7 +135,8 @@ const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
|
|
|
94
135
|
<div
|
|
95
136
|
data-orientation={orientation}
|
|
96
137
|
data-slot="carousel"
|
|
97
|
-
|
|
138
|
+
dir={direction}
|
|
139
|
+
ref={setRootRef}
|
|
98
140
|
role="region"
|
|
99
141
|
className={cn("relative", className)}
|
|
100
142
|
{...props}
|
|
@@ -153,11 +195,13 @@ const CarouselItem = React.forwardRef<HTMLDivElement, CarouselItemProps>(
|
|
|
153
195
|
|
|
154
196
|
const CarouselPrevious = React.forwardRef<HTMLButtonElement, CarouselButtonProps>(
|
|
155
197
|
function CarouselPrevious({ className, variant = "outline", size = "icon", ...props }, ref) {
|
|
156
|
-
const { canScrollPrev, orientation, scrollPrev } = useCarousel()
|
|
198
|
+
const { canScrollPrev, messages, orientation, scrollPrev } = useCarousel()
|
|
157
199
|
|
|
158
200
|
return (
|
|
159
201
|
<Button
|
|
160
|
-
aria-label=
|
|
202
|
+
aria-label={
|
|
203
|
+
props["aria-label"] ?? messages.previousSlide
|
|
204
|
+
}
|
|
161
205
|
className={cn(
|
|
162
206
|
"absolute size-[var(--bh-space-7xl-40)] rounded-[var(--bh-radius-full)]",
|
|
163
207
|
orientation === "horizontal"
|
|
@@ -181,11 +225,13 @@ const CarouselPrevious = React.forwardRef<HTMLButtonElement, CarouselButtonProps
|
|
|
181
225
|
|
|
182
226
|
const CarouselNext = React.forwardRef<HTMLButtonElement, CarouselButtonProps>(
|
|
183
227
|
function CarouselNext({ className, variant = "outline", size = "icon", ...props }, ref) {
|
|
184
|
-
const { canScrollNext, orientation, scrollNext } = useCarousel()
|
|
228
|
+
const { canScrollNext, messages, orientation, scrollNext } = useCarousel()
|
|
185
229
|
|
|
186
230
|
return (
|
|
187
231
|
<Button
|
|
188
|
-
aria-label=
|
|
232
|
+
aria-label={
|
|
233
|
+
props["aria-label"] ?? messages.nextSlide
|
|
234
|
+
}
|
|
189
235
|
className={cn(
|
|
190
236
|
"absolute size-[var(--bh-space-7xl-40)] rounded-[var(--bh-radius-full)]",
|
|
191
237
|
orientation === "horizontal"
|
|
@@ -216,6 +262,7 @@ function useCarousel() {
|
|
|
216
262
|
}
|
|
217
263
|
|
|
218
264
|
export {
|
|
265
|
+
arabicCarouselMessages,
|
|
219
266
|
Carousel,
|
|
220
267
|
CarouselContent,
|
|
221
268
|
CarouselItem,
|
|
@@ -227,6 +274,7 @@ export type {
|
|
|
227
274
|
CarouselButtonProps,
|
|
228
275
|
CarouselContentProps,
|
|
229
276
|
CarouselItemProps,
|
|
277
|
+
CarouselMessages,
|
|
230
278
|
CarouselOptions,
|
|
231
279
|
CarouselOrientation,
|
|
232
280
|
CarouselPlugin,
|
|
@@ -37,6 +37,17 @@ type ChartLegendContentProps = React.ComponentProps<"div"> & {
|
|
|
37
37
|
payload?: ChartPayloadItem[]
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
const chartCategoricalTokens = [
|
|
41
|
+
"--bh-chart-categorical-brand",
|
|
42
|
+
"--bh-chart-categorical-success",
|
|
43
|
+
"--bh-chart-categorical-warning",
|
|
44
|
+
"--bh-chart-categorical-danger",
|
|
45
|
+
"--bh-chart-categorical-information",
|
|
46
|
+
"--bh-chart-categorical-purple",
|
|
47
|
+
"--bh-chart-categorical-aqua",
|
|
48
|
+
"--bh-chart-categorical-fuchsia",
|
|
49
|
+
] as const
|
|
50
|
+
|
|
40
51
|
function ChartContainer({
|
|
41
52
|
children,
|
|
42
53
|
className,
|
|
@@ -62,6 +73,26 @@ function ChartContainer({
|
|
|
62
73
|
const ChartTooltip = RechartsTooltip
|
|
63
74
|
const ChartLegend = RechartsLegend
|
|
64
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Recharts clones the element passed as `content` and injects its own internal
|
|
78
|
+
* props (`iconSize`, `verticalAlign`, `chartWidth`, `itemSorter`, …). Those are
|
|
79
|
+
* not valid DOM attributes, so forward only what a presentational element can
|
|
80
|
+
* legitimately receive.
|
|
81
|
+
*/
|
|
82
|
+
function forwardableDomProps(props: Record<string, unknown>) {
|
|
83
|
+
return Object.fromEntries(
|
|
84
|
+
Object.entries(props).filter(
|
|
85
|
+
([key]) =>
|
|
86
|
+
key === "id" ||
|
|
87
|
+
key === "role" ||
|
|
88
|
+
key === "style" ||
|
|
89
|
+
key === "tabIndex" ||
|
|
90
|
+
key.startsWith("aria-") ||
|
|
91
|
+
key.startsWith("data-")
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
65
96
|
function ChartTooltipContent({
|
|
66
97
|
active,
|
|
67
98
|
className,
|
|
@@ -79,7 +110,7 @@ function ChartTooltipContent({
|
|
|
79
110
|
"grid min-w-[var(--bh-space-17xl-288)] gap-[var(--bh-space-sm-6)] rounded-[var(--bh-radius-lg-8)] bg-[var(--bh-bg-raised)] p-[var(--bh-space-xl-12)] text-[length:var(--bh-text-body-xs-regular-font-size)] font-[var(--bh-text-body-xs-regular-font-weight)] leading-[var(--bh-text-body-xs-regular-line-height)] tracking-[var(--bh-text-body-xs-regular-letter-spacing)] text-[var(--bh-content-default)] shadow-[var(--shadow-popover)]",
|
|
80
111
|
className
|
|
81
112
|
)}
|
|
82
|
-
{...props}
|
|
113
|
+
{...forwardableDomProps(props)}
|
|
83
114
|
>
|
|
84
115
|
{!hideLabel && label ? (
|
|
85
116
|
<div className="font-[var(--bh-text-body-xs-medium-font-weight)]">
|
|
@@ -121,7 +152,7 @@ function ChartLegendContent({
|
|
|
121
152
|
<div
|
|
122
153
|
data-slot="chart-legend"
|
|
123
154
|
className={cn("flex flex-wrap items-center justify-center gap-[var(--bh-space-3xl-16)]", className)}
|
|
124
|
-
{...props}
|
|
155
|
+
{...forwardableDomProps(props)}
|
|
125
156
|
>
|
|
126
157
|
{payload.map((item, index) => (
|
|
127
158
|
<div
|
|
@@ -146,7 +177,9 @@ function getChartStyle(config?: ChartConfig): React.CSSProperties {
|
|
|
146
177
|
return Object.entries(config).reduce<React.CSSProperties>(
|
|
147
178
|
(style, [key, value], index) => ({
|
|
148
179
|
...style,
|
|
149
|
-
[`--color-${key}`]:
|
|
180
|
+
[`--color-${key}`]:
|
|
181
|
+
value.color ??
|
|
182
|
+
`var(${chartCategoricalTokens[index % chartCategoricalTokens.length]})`,
|
|
150
183
|
}),
|
|
151
184
|
{}
|
|
152
185
|
)
|
|
@@ -63,13 +63,13 @@ const Checkbox = React.forwardRef<
|
|
|
63
63
|
aria-hidden="true"
|
|
64
64
|
className="size-[var(--bh-checkbox-icon-size)] group-data-[state=indeterminate]/checkbox:hidden"
|
|
65
65
|
focusable="false"
|
|
66
|
-
strokeWidth=
|
|
66
|
+
strokeWidth="var(--bh-icon-stroke-300)"
|
|
67
67
|
/>
|
|
68
68
|
<MinusIcon
|
|
69
69
|
aria-hidden="true"
|
|
70
70
|
className="hidden size-[var(--bh-checkbox-icon-size)] group-data-[state=indeterminate]/checkbox:block"
|
|
71
71
|
focusable="false"
|
|
72
|
-
strokeWidth=
|
|
72
|
+
strokeWidth="var(--bh-icon-stroke-300)"
|
|
73
73
|
/>
|
|
74
74
|
</CheckboxPrimitive.Indicator>
|
|
75
75
|
</CheckboxPrimitive.Root>
|
|
@@ -231,7 +231,7 @@ function CheckboxCardIndicator({
|
|
|
231
231
|
aria-hidden="true"
|
|
232
232
|
className="absolute top-1/2 left-1/2 size-[var(--bh-checkbox-icon-size)] -translate-x-1/2 -translate-y-1/2 text-[var(--bh-content-on-color)]"
|
|
233
233
|
focusable="false"
|
|
234
|
-
strokeWidth=
|
|
234
|
+
strokeWidth="var(--bh-icon-stroke-300)"
|
|
235
235
|
/>
|
|
236
236
|
) : null}
|
|
237
237
|
</span>
|
|
@@ -38,7 +38,7 @@ const CollapsibleTrigger = React.forwardRef<
|
|
|
38
38
|
<ChevronDownIcon
|
|
39
39
|
aria-hidden="true"
|
|
40
40
|
className="size-[var(--bh-space-3xl-16)] shrink-0 text-[var(--bh-content-subtle)] transition-transform group-data-[state=open]/collapsible-trigger:rotate-180"
|
|
41
|
-
strokeWidth=
|
|
41
|
+
strokeWidth="var(--bh-icon-stroke-200)"
|
|
42
42
|
/>
|
|
43
43
|
</CollapsiblePrimitive.Trigger>
|
|
44
44
|
)
|
|
@@ -44,7 +44,7 @@ const CommandInput = React.forwardRef<HTMLInputElement, CommandInputProps>(
|
|
|
44
44
|
<SearchIcon
|
|
45
45
|
aria-hidden="true"
|
|
46
46
|
className="size-[var(--bh-space-5xl-24)] shrink-0 text-[var(--bh-content-muted)]"
|
|
47
|
-
strokeWidth=
|
|
47
|
+
strokeWidth="var(--bh-icon-stroke-200)"
|
|
48
48
|
/>
|
|
49
49
|
<CommandPrimitive.Input
|
|
50
50
|
data-slot="command-input"
|
|
@@ -53,7 +53,7 @@ const menuContentClassName =
|
|
|
53
53
|
"z-[var(--bh-z-popover)] min-w-[var(--bh-menu-width)] overflow-hidden rounded-[var(--bh-radius-xl-10)] bg-[var(--bh-bg-raised)] p-[var(--bh-space-xs-4)] text-[var(--bh-content-default)] shadow-[var(--shadow-menu)]"
|
|
54
54
|
|
|
55
55
|
const menuItemClassName =
|
|
56
|
-
"relative flex min-h-[var(--bh-menu-item-
|
|
56
|
+
"relative flex min-h-[var(--bh-menu-item-default-height)] cursor-default select-none items-center gap-[var(--bh-space-md-8)] rounded-[var(--bh-radius-md-6)] px-[var(--bh-space-md-8)] py-[var(--bh-space-sm-6)] text-start text-[length:var(--bh-text-body-sm-regular-font-size)] font-[var(--bh-text-body-sm-regular-font-weight)] leading-[var(--bh-text-body-sm-regular-line-height)] tracking-[var(--bh-text-body-sm-regular-letter-spacing)] text-[var(--bh-content-default)] outline-none data-[disabled]:pointer-events-none data-[disabled]:text-[var(--bh-content-disabled)] data-[highlighted]:bg-[var(--bh-menu-item-hover-bg)]"
|
|
57
57
|
|
|
58
58
|
const ContextMenuContent = React.forwardRef<
|
|
59
59
|
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|