banhaten 0.3.0 → 0.5.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 +139 -73
- package/CONTRIBUTING.md +46 -44
- package/README.md +192 -190
- package/SECURITY.md +15 -15
- package/banhaten.config.example.json +11 -11
- package/docs/design-spacing.md +13 -0
- package/docs/design-system/README.md +22 -20
- package/docs/design-system/adoption-quality-remediation.md +87 -87
- package/docs/design-system/agent-usage.md +13 -13
- package/docs/design-system/appearance-presets.md +189 -189
- package/docs/design-system/appearances/default.md +94 -94
- package/docs/design-system/appearances/rounded.md +95 -95
- package/docs/design-system/appearances/sharp.md +95 -95
- package/docs/design-system/component-docs-pattern.md +81 -81
- package/docs/design-system/component-implementation-ownership-audit.md +245 -244
- package/docs/design-system/component-quality-audit-2026-08-20.md +225 -223
- package/docs/design-system/component-showcase-consistency-report.md +219 -219
- package/docs/design-system/component-token-consistency-audit.md +173 -173
- package/docs/design-system/components/README.md +90 -76
- package/docs/design-system/components/accordion.md +53 -53
- package/docs/design-system/components/activity-feed.md +94 -94
- package/docs/design-system/components/activity-heatmap.md +57 -57
- package/docs/design-system/components/agent-input.md +85 -0
- package/docs/design-system/components/alert-dialog.md +72 -72
- package/docs/design-system/components/alert.md +98 -98
- package/docs/design-system/components/approval-card.md +134 -0
- package/docs/design-system/components/aspect-ratio.md +45 -45
- package/docs/design-system/components/attribute.md +89 -89
- package/docs/design-system/components/autocomplete.md +75 -75
- package/docs/design-system/components/avatar.md +54 -54
- package/docs/design-system/components/badge.md +54 -54
- package/docs/design-system/components/banner.md +87 -87
- package/docs/design-system/components/breadcrumbs.md +177 -176
- package/docs/design-system/components/button-group.md +98 -98
- package/docs/design-system/components/button.md +83 -80
- package/docs/design-system/components/card.md +88 -88
- package/docs/design-system/components/carousel.md +46 -46
- package/docs/design-system/components/catalog-components.md +47 -47
- package/docs/design-system/components/chart.md +95 -24
- package/docs/design-system/components/checkbox.md +54 -54
- package/docs/design-system/components/collapsible.md +67 -53
- package/docs/design-system/components/command.md +62 -62
- package/docs/design-system/components/context-menu.md +46 -46
- package/docs/design-system/components/date-picker.md +81 -79
- package/docs/design-system/components/divider.md +102 -102
- package/docs/design-system/components/empty-state.md +56 -56
- package/docs/design-system/components/field.md +70 -70
- package/docs/design-system/components/file-upload.md +187 -187
- package/docs/design-system/components/hover-card.md +48 -48
- package/docs/design-system/components/icons.md +48 -48
- package/docs/design-system/components/inline-citations.md +93 -0
- package/docs/design-system/components/input-group.md +58 -58
- package/docs/design-system/components/input-otp.md +56 -56
- package/docs/design-system/components/input.md +117 -61
- package/docs/design-system/components/item.md +59 -57
- package/docs/design-system/components/kbd.md +54 -49
- package/docs/design-system/components/label.md +49 -49
- package/docs/design-system/components/menu.md +71 -61
- package/docs/design-system/components/menubar.md +47 -47
- package/docs/design-system/components/modal.md +105 -105
- package/docs/design-system/components/native-select.md +54 -54
- package/docs/design-system/components/navigation-menu.md +50 -50
- package/docs/design-system/components/onboarding-step-list-item.md +82 -82
- package/docs/design-system/components/page-header.md +93 -86
- package/docs/design-system/components/pagination.md +57 -57
- package/docs/design-system/components/popover.md +60 -60
- package/docs/design-system/components/progress-slider.md +50 -50
- package/docs/design-system/components/progress.md +76 -76
- package/docs/design-system/components/radio-card.md +51 -51
- package/docs/design-system/components/radio-group.md +57 -57
- package/docs/design-system/components/resizable.md +44 -44
- package/docs/design-system/components/rolling-count.md +61 -0
- package/docs/design-system/components/scroll-area.md +51 -51
- package/docs/design-system/components/segmented-control.md +54 -54
- package/docs/design-system/components/select.md +68 -62
- package/docs/design-system/components/sheet.md +67 -67
- package/docs/design-system/components/shimmer-text.md +67 -0
- package/docs/design-system/components/sidebar.md +127 -76
- package/docs/design-system/components/skeleton.md +75 -75
- package/docs/design-system/components/slideout.md +65 -65
- package/docs/design-system/components/slider.md +63 -63
- package/docs/design-system/components/social-button.md +50 -50
- package/docs/design-system/components/spinner.md +62 -62
- package/docs/design-system/components/steps.md +65 -65
- package/docs/design-system/components/streaming-text.md +82 -0
- package/docs/design-system/components/table.md +419 -414
- package/docs/design-system/components/tabs.md +59 -55
- package/docs/design-system/components/tag.md +80 -80
- package/docs/design-system/components/task-list.md +95 -0
- package/docs/design-system/components/textarea.md +50 -50
- package/docs/design-system/components/thinking-reasoning.md +72 -0
- package/docs/design-system/components/thinking-state.md +67 -0
- package/docs/design-system/components/timeline.md +83 -83
- package/docs/design-system/components/toast.md +58 -58
- package/docs/design-system/components/toggle.md +81 -81
- package/docs/design-system/components/toolbar.md +92 -87
- package/docs/design-system/components/tooltip.md +94 -92
- package/docs/design-system/components/typography.md +18 -18
- package/docs/design-system/density-and-elevation.md +65 -61
- package/docs/design-system/design-system-test-missing-items.md +368 -368
- package/docs/design-system/direction-and-localization.md +23 -23
- package/docs/design-system/form-recipes.md +73 -73
- package/docs/design-system/gap-promotion-policy.md +21 -21
- package/docs/design-system/icons.md +74 -69
- package/docs/design-system/installation.md +70 -68
- package/docs/design-system/launch-comparison-shadcn.md +98 -98
- package/docs/design-system/registry-and-cli.md +64 -64
- package/docs/design-system/release-policy.md +30 -30
- package/docs/design-system/roadmap.md +14 -14
- package/docs/design-system/support-matrix.md +23 -23
- package/docs/design-system/tabs.md +54 -53
- package/docs/design-system/template-gap-audit.md +32 -0
- package/docs/design-system/templates.md +59 -0
- package/docs/design-system/token-governance.md +72 -60
- package/package.json +98 -98
- package/registry/component-contract.json +40 -40
- package/registry/components/accordion.tsx +155 -155
- package/registry/components/agent-input-parts.tsx +552 -0
- package/registry/components/agent-input-state.ts +156 -0
- package/registry/components/agent-input.css +307 -0
- package/registry/components/agent-input.tsx +382 -0
- package/registry/components/alert-dialog.tsx +297 -297
- package/registry/components/alert.tsx +293 -293
- package/registry/components/approval-card.css +409 -0
- package/registry/components/approval-card.tsx +401 -0
- package/registry/components/approval-frame.tsx +108 -0
- package/registry/components/approval-questions.tsx +559 -0
- package/registry/components/aspect-ratio.tsx +30 -30
- package/registry/components/attribute.tsx +454 -448
- package/registry/components/autocomplete.tsx +598 -651
- package/registry/components/avatar.tsx +385 -381
- package/registry/components/badge.tsx +629 -629
- package/registry/components/button-group.tsx +565 -565
- package/registry/components/button.tsx +127 -123
- package/registry/components/card.tsx +638 -638
- package/registry/components/carousel.tsx +296 -296
- package/registry/components/chart-block-data.ts +177 -0
- package/registry/components/chart-block.css +171 -0
- package/registry/components/chart-block.tsx +260 -0
- package/registry/components/chart-interactions.ts +123 -0
- package/registry/components/chart-options.cartesian.ts +162 -0
- package/registry/components/chart-options.paint.ts +99 -0
- package/registry/components/chart-options.parts.ts +72 -0
- package/registry/components/chart-options.radial.ts +109 -0
- package/registry/components/chart-options.ts +44 -0
- package/registry/components/chart-options.types.ts +67 -0
- package/registry/components/chart.tsx +203 -203
- package/registry/components/checkbox.tsx +247 -247
- package/registry/components/collapsible.tsx +109 -69
- package/registry/components/command.tsx +208 -208
- package/registry/components/context-menu.tsx +236 -236
- package/registry/components/data-chart.tsx +40 -0
- package/registry/components/date-picker.tsx +1289 -1277
- package/registry/components/echart-theme.ts +246 -0
- package/registry/components/echart.css +49 -0
- package/registry/components/echart.tsx +178 -0
- package/registry/components/expanded/ActivityFeed.tsx +227 -227
- package/registry/components/expanded/ActivityHeatmap.tsx +64 -64
- package/registry/components/expanded/Banner.tsx +179 -179
- package/registry/components/expanded/Breadcrumbs.tsx +131 -131
- package/registry/components/expanded/CatalogComponentsShowcase.tsx +205 -205
- package/registry/components/expanded/CatalogDivider.tsx +49 -49
- package/registry/components/expanded/EmptyState.tsx +155 -155
- package/registry/components/expanded/FileUpload.tsx +543 -543
- package/registry/components/expanded/OnboardingStepListItem.tsx +60 -59
- package/registry/components/expanded/PageHeader.tsx +179 -166
- package/registry/components/expanded/Slideout.tsx +108 -108
- package/registry/components/expanded/Steps.tsx +402 -402
- package/registry/components/expanded/Table.tsx +1092 -1071
- package/registry/components/expanded/Timeline.tsx +203 -203
- package/registry/components/expanded/activityFeed.css +248 -248
- package/registry/components/expanded/activityHeatmap.css +66 -66
- package/registry/components/expanded/banner.css +260 -255
- package/registry/components/expanded/breadcrumbs.css +140 -140
- package/registry/components/expanded/catalogComponentsShowcase.css +87 -87
- package/registry/components/expanded/divider.css +75 -75
- package/registry/components/expanded/emptyState.css +111 -111
- package/registry/components/expanded/fileUpload.css +457 -457
- package/registry/components/expanded/onboardingStepListItem.css +135 -126
- package/registry/components/expanded/pageHeader.css +248 -290
- package/registry/components/expanded/slideout.css +276 -276
- package/registry/components/expanded/steps.css +356 -356
- package/registry/components/expanded/table.css +606 -603
- package/registry/components/expanded/timeline.css +286 -286
- package/registry/components/field.tsx +283 -283
- package/registry/components/hover-card.tsx +48 -48
- package/registry/components/inline-citations.css +126 -0
- package/registry/components/inline-citations.tsx +292 -0
- package/registry/components/input-content.ts +107 -107
- package/registry/components/input-group.tsx +130 -130
- package/registry/components/input-otp.tsx +584 -584
- package/registry/components/input.tsx +990 -972
- package/registry/components/item.tsx +189 -189
- package/registry/components/kbd.tsx +246 -151
- package/registry/components/label.tsx +78 -78
- package/registry/components/menu.tsx +978 -986
- package/registry/components/menubar.tsx +226 -226
- package/registry/components/modal.tsx +872 -872
- package/registry/components/native-select.tsx +205 -205
- package/registry/components/navigation-menu.tsx +171 -171
- package/registry/components/pagination.css +36 -36
- package/registry/components/pagination.tsx +560 -555
- package/registry/components/popover.tsx +338 -338
- package/registry/components/progress-slider.tsx +216 -216
- package/registry/components/radio-card.tsx +676 -677
- package/registry/components/radio-group.tsx +570 -570
- package/registry/components/resizable.tsx +108 -108
- package/registry/components/rolling-count.css +37 -0
- package/registry/components/rolling-count.tsx +110 -0
- package/registry/components/scroll-area.tsx +91 -91
- package/registry/components/segmented-control.tsx +87 -87
- package/registry/components/select-content.tsx +218 -218
- package/registry/components/select.tsx +937 -932
- package/registry/components/sheet.tsx +305 -305
- package/registry/components/shimmer-text.css +69 -0
- package/registry/components/shimmer-text.tsx +43 -0
- package/registry/components/sidebar.tsx +1433 -358
- package/registry/components/skeleton.css +54 -54
- package/registry/components/skeleton.tsx +482 -482
- package/registry/components/slider.tsx +380 -380
- package/registry/components/social-button.tsx +387 -387
- package/registry/components/spinner.tsx +78 -78
- package/registry/components/streaming-text.css +45 -0
- package/registry/components/streaming-text.tsx +165 -0
- package/registry/components/table-elements.tsx +128 -128
- package/registry/components/tabs.css +222 -218
- package/registry/components/tabs.tsx +241 -241
- package/registry/components/tag.tsx +423 -423
- package/registry/components/task-list.css +328 -0
- package/registry/components/task-list.tsx +429 -0
- package/registry/components/textarea.tsx +610 -610
- package/registry/components/thinking-reasoning.css +178 -0
- package/registry/components/thinking-reasoning.tsx +253 -0
- package/registry/components/thinking-state.css +8 -0
- package/registry/components/thinking-state.tsx +46 -0
- package/registry/components/toast.tsx +136 -136
- package/registry/components/toggle.tsx +256 -256
- package/registry/components/toolbar.tsx +539 -539
- package/registry/components/tooltip.tsx +433 -431
- package/registry/examples/agent-input-demo.tsx +90 -0
- package/registry/examples/alert-demo.tsx +34 -34
- package/registry/examples/alert-dialog-demo.tsx +42 -42
- package/registry/examples/approval-card-demo.tsx +83 -0
- package/registry/examples/aspect-ratio-demo.tsx +11 -11
- package/registry/examples/attribute-demo.tsx +65 -65
- package/registry/examples/autocomplete-demo.tsx +109 -109
- package/registry/examples/avatar-demo.tsx +132 -132
- package/registry/examples/badge-demo.tsx +69 -69
- package/registry/examples/button-demo.tsx +86 -83
- package/registry/examples/button-group-demo.tsx +63 -63
- package/registry/examples/card-demo.tsx +86 -86
- package/registry/examples/carousel-demo.tsx +43 -43
- package/registry/examples/chart-block-demo.tsx +5 -0
- package/registry/examples/chart-demo.tsx +18 -33
- package/registry/examples/checkbox-demo.tsx +62 -62
- package/registry/examples/collapsible-demo.tsx +16 -16
- package/registry/examples/collection-filter-bar-demo.tsx +135 -135
- package/registry/examples/command-demo.tsx +42 -42
- package/registry/examples/command-palette-demo.tsx +235 -236
- package/registry/examples/context-menu-demo.tsx +29 -29
- package/registry/examples/control-density-contract-demo.tsx +65 -61
- package/registry/examples/date-picker-demo.tsx +127 -127
- package/registry/examples/divider-demo.tsx +17 -17
- package/registry/examples/expanded/activity-heatmap-demo.tsx +29 -29
- package/registry/examples/expanded/banner-demo.tsx +48 -48
- package/registry/examples/expanded/breadcrumbs-demo.tsx +59 -59
- package/registry/examples/expanded/empty-state-demo.tsx +39 -39
- package/registry/examples/expanded/file-upload-demo.tsx +60 -60
- package/registry/examples/expanded/onboarding-step-demo.tsx +11 -11
- package/registry/examples/expanded/slideout-demo.tsx +15 -15
- package/registry/examples/expanded/steps-demo.tsx +29 -29
- package/registry/examples/expanded/tabs-demo.tsx +13 -13
- package/registry/examples/expanded/timeline-demo.tsx +18 -18
- package/registry/examples/field-demo.tsx +51 -51
- package/registry/examples/hover-card-demo.tsx +23 -23
- package/registry/examples/inline-citations-demo.tsx +31 -0
- package/registry/examples/input-actions-demo.tsx +36 -0
- package/registry/examples/input-demo.tsx +87 -87
- package/registry/examples/input-group-demo.tsx +16 -16
- package/registry/examples/input-otp-demo.tsx +72 -72
- package/registry/examples/item-demo.tsx +46 -46
- package/registry/examples/kbd-demo.tsx +12 -11
- package/registry/examples/label-demo.tsx +20 -20
- package/registry/examples/menu-demo.tsx +122 -122
- package/registry/examples/menubar-demo.tsx +34 -34
- package/registry/examples/modal-demo.tsx +74 -74
- package/registry/examples/native-select-demo.tsx +16 -16
- package/registry/examples/navigation-menu-demo.tsx +29 -29
- package/registry/examples/pagination-demo.tsx +20 -20
- package/registry/examples/popover-demo.tsx +547 -546
- package/registry/examples/progress-demo.tsx +37 -37
- package/registry/examples/progress-slider-demo.tsx +29 -29
- package/registry/examples/radio-card-demo.tsx +51 -51
- package/registry/examples/radio-group-demo.tsx +62 -62
- package/registry/examples/resizable-demo.tsx +22 -22
- package/registry/examples/results-toolbar-demo.tsx +44 -44
- package/registry/examples/rolling-count-demo.tsx +39 -0
- package/registry/examples/scroll-area-demo.tsx +15 -15
- package/registry/examples/segmented-control-demo.tsx +39 -39
- package/registry/examples/select-demo.tsx +87 -87
- package/registry/examples/sheet-demo.tsx +47 -47
- package/registry/examples/shimmer-text-demo.tsx +20 -0
- package/registry/examples/sidebar-demo.tsx +101 -57
- package/registry/examples/slider-demo.tsx +31 -31
- package/registry/examples/social-button-demo.tsx +61 -61
- package/registry/examples/spinner-demo.tsx +59 -59
- package/registry/examples/streaming-text-demo.tsx +28 -0
- package/registry/examples/tabs-demo.tsx +13 -13
- package/registry/examples/tag-demo.tsx +29 -29
- package/registry/examples/task-list-demo.tsx +74 -0
- package/registry/examples/textarea-demo.tsx +79 -79
- package/registry/examples/thinking-reasoning-demo.tsx +74 -0
- package/registry/examples/thinking-state-demo.tsx +13 -0
- package/registry/examples/toast-demo.tsx +35 -35
- package/registry/examples/toggle-demo.tsx +59 -59
- package/registry/examples/tooltip-demo.tsx +115 -115
- package/registry/guidance/USAGE.md +27 -27
- package/registry/guidance/charts.LICENSE.txt +24 -0
- package/registry/hooks/use-controllable-state.ts +33 -0
- package/registry/hooks/use-direction.ts +207 -207
- package/registry/hooks/use-listbox-navigation.ts +73 -0
- package/registry/hooks/use-motion-end.ts +55 -0
- package/registry/hooks/use-reduced-motion.ts +28 -0
- package/registry/index.json +1634 -184
- package/registry/styles/globals.css +1462 -1570
- package/registry.json +364 -10
- package/schema/config.schema.json +51 -51
- package/schema/registry.schema.json +194 -190
- package/schema/tokens.schema.json +167 -163
- package/src/cli/command-line.js +194 -194
- package/src/cli/config-editors.js +9 -9
- package/src/cli/doctor.js +399 -399
- package/src/cli/file-transaction.js +302 -295
- package/src/cli/global-css.js +153 -153
- package/src/cli/index.js +1002 -1009
- package/src/cli/install-plan.js +592 -592
- package/src/cli/install-receipt.js +171 -171
- package/src/cli/jsonc.js +203 -203
- package/src/cli/package-install-state.js +254 -254
- package/src/cli/package-manager.js +238 -238
- package/src/cli/package-plan.js +185 -185
- package/src/cli/package-version.js +97 -97
- package/src/cli/registry-query.js +207 -207
- package/src/cli/reporting.js +55 -55
- package/src/cli/schema-validation.js +19 -19
- package/src/cli/source-scanner.js +686 -686
- package/src/cli/vite-config.js +478 -478
- package/tokens/banhaten.tokens.json +458 -224
|
@@ -1,236 +1,236 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
|
|
5
|
-
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
|
6
|
-
|
|
7
|
-
import { cn } from "@/lib/utils"
|
|
8
|
-
|
|
9
|
-
type ContextMenuProps = React.ComponentProps<typeof ContextMenuPrimitive.Root>
|
|
10
|
-
type ContextMenuTriggerProps = React.ComponentPropsWithoutRef<
|
|
11
|
-
typeof ContextMenuPrimitive.Trigger
|
|
12
|
-
>
|
|
13
|
-
type ContextMenuContentProps = React.ComponentPropsWithoutRef<
|
|
14
|
-
typeof ContextMenuPrimitive.Content
|
|
15
|
-
>
|
|
16
|
-
type ContextMenuItemProps = React.ComponentPropsWithoutRef<
|
|
17
|
-
typeof ContextMenuPrimitive.Item
|
|
18
|
-
> & {
|
|
19
|
-
inset?: boolean
|
|
20
|
-
}
|
|
21
|
-
type ContextMenuCheckboxItemProps = React.ComponentPropsWithoutRef<
|
|
22
|
-
typeof ContextMenuPrimitive.CheckboxItem
|
|
23
|
-
>
|
|
24
|
-
type ContextMenuRadioItemProps = React.ComponentPropsWithoutRef<
|
|
25
|
-
typeof ContextMenuPrimitive.RadioItem
|
|
26
|
-
>
|
|
27
|
-
type ContextMenuLabelProps = React.ComponentPropsWithoutRef<
|
|
28
|
-
typeof ContextMenuPrimitive.Label
|
|
29
|
-
> & {
|
|
30
|
-
inset?: boolean
|
|
31
|
-
}
|
|
32
|
-
type ContextMenuSeparatorProps = React.ComponentPropsWithoutRef<
|
|
33
|
-
typeof ContextMenuPrimitive.Separator
|
|
34
|
-
>
|
|
35
|
-
type ContextMenuSubTriggerProps = React.ComponentPropsWithoutRef<
|
|
36
|
-
typeof ContextMenuPrimitive.SubTrigger
|
|
37
|
-
> & {
|
|
38
|
-
inset?: boolean
|
|
39
|
-
}
|
|
40
|
-
type ContextMenuSubContentProps = React.ComponentPropsWithoutRef<
|
|
41
|
-
typeof ContextMenuPrimitive.SubContent
|
|
42
|
-
>
|
|
43
|
-
type ContextMenuShortcutProps = React.ComponentProps<"span">
|
|
44
|
-
|
|
45
|
-
const ContextMenu = ContextMenuPrimitive.Root
|
|
46
|
-
const ContextMenuTrigger = ContextMenuPrimitive.Trigger
|
|
47
|
-
const ContextMenuGroup = ContextMenuPrimitive.Group
|
|
48
|
-
const ContextMenuPortal = ContextMenuPrimitive.Portal
|
|
49
|
-
const ContextMenuSub = ContextMenuPrimitive.Sub
|
|
50
|
-
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
|
|
51
|
-
|
|
52
|
-
const menuContentClassName =
|
|
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(--
|
|
54
|
-
|
|
55
|
-
const menuItemClassName =
|
|
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
|
-
|
|
58
|
-
const ContextMenuContent = React.forwardRef<
|
|
59
|
-
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
|
60
|
-
ContextMenuContentProps
|
|
61
|
-
>(function ContextMenuContent({ className, ...props }, ref) {
|
|
62
|
-
return (
|
|
63
|
-
<ContextMenuPortal>
|
|
64
|
-
<ContextMenuPrimitive.Content
|
|
65
|
-
data-slot="context-menu-content"
|
|
66
|
-
ref={ref}
|
|
67
|
-
className={cn(menuContentClassName, className)}
|
|
68
|
-
{...props}
|
|
69
|
-
/>
|
|
70
|
-
</ContextMenuPortal>
|
|
71
|
-
)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
const ContextMenuItem = React.forwardRef<
|
|
75
|
-
React.ElementRef<typeof ContextMenuPrimitive.Item>,
|
|
76
|
-
ContextMenuItemProps
|
|
77
|
-
>(function ContextMenuItem({ className, inset, ...props }, ref) {
|
|
78
|
-
return (
|
|
79
|
-
<ContextMenuPrimitive.Item
|
|
80
|
-
data-inset={inset ? "true" : undefined}
|
|
81
|
-
data-slot="context-menu-item"
|
|
82
|
-
ref={ref}
|
|
83
|
-
className={cn(menuItemClassName, inset && "ps-[var(--bh-space-8xl-48)]", className)}
|
|
84
|
-
{...props}
|
|
85
|
-
/>
|
|
86
|
-
)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
const ContextMenuCheckboxItem = React.forwardRef<
|
|
90
|
-
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
|
91
|
-
ContextMenuCheckboxItemProps
|
|
92
|
-
>(function ContextMenuCheckboxItem({ children, className, checked, ...props }, ref) {
|
|
93
|
-
return (
|
|
94
|
-
<ContextMenuPrimitive.CheckboxItem
|
|
95
|
-
checked={checked}
|
|
96
|
-
data-slot="context-menu-checkbox-item"
|
|
97
|
-
ref={ref}
|
|
98
|
-
className={cn(menuItemClassName, "ps-[var(--bh-space-8xl-48)]", className)}
|
|
99
|
-
{...props}
|
|
100
|
-
>
|
|
101
|
-
<span className="absolute start-[var(--bh-space-md-8)] inline-flex size-[var(--bh-space-5xl-24)] items-center justify-center">
|
|
102
|
-
<ContextMenuPrimitive.ItemIndicator>
|
|
103
|
-
<CheckIcon className="size-[var(--bh-space-3xl-16)]" />
|
|
104
|
-
</ContextMenuPrimitive.ItemIndicator>
|
|
105
|
-
</span>
|
|
106
|
-
{children}
|
|
107
|
-
</ContextMenuPrimitive.CheckboxItem>
|
|
108
|
-
)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
const ContextMenuRadioItem = React.forwardRef<
|
|
112
|
-
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
|
|
113
|
-
ContextMenuRadioItemProps
|
|
114
|
-
>(function ContextMenuRadioItem({ children, className, ...props }, ref) {
|
|
115
|
-
return (
|
|
116
|
-
<ContextMenuPrimitive.RadioItem
|
|
117
|
-
data-slot="context-menu-radio-item"
|
|
118
|
-
ref={ref}
|
|
119
|
-
className={cn(menuItemClassName, "ps-[var(--bh-space-8xl-48)]", className)}
|
|
120
|
-
{...props}
|
|
121
|
-
>
|
|
122
|
-
<span className="absolute start-[var(--bh-space-md-8)] inline-flex size-[var(--bh-space-5xl-24)] items-center justify-center">
|
|
123
|
-
<ContextMenuPrimitive.ItemIndicator>
|
|
124
|
-
<CircleIcon className="size-[var(--bh-space-md-8)] fill-current" />
|
|
125
|
-
</ContextMenuPrimitive.ItemIndicator>
|
|
126
|
-
</span>
|
|
127
|
-
{children}
|
|
128
|
-
</ContextMenuPrimitive.RadioItem>
|
|
129
|
-
)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
const ContextMenuLabel = React.forwardRef<
|
|
133
|
-
React.ElementRef<typeof ContextMenuPrimitive.Label>,
|
|
134
|
-
ContextMenuLabelProps
|
|
135
|
-
>(function ContextMenuLabel({ className, inset, ...props }, ref) {
|
|
136
|
-
return (
|
|
137
|
-
<ContextMenuPrimitive.Label
|
|
138
|
-
data-inset={inset ? "true" : undefined}
|
|
139
|
-
data-slot="context-menu-label"
|
|
140
|
-
ref={ref}
|
|
141
|
-
className={cn(
|
|
142
|
-
"px-[var(--bh-space-md-8)] py-[var(--bh-space-sm-6)] 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)] text-[var(--bh-content-muted)]",
|
|
143
|
-
inset && "ps-[var(--bh-space-8xl-48)]",
|
|
144
|
-
className
|
|
145
|
-
)}
|
|
146
|
-
{...props}
|
|
147
|
-
/>
|
|
148
|
-
)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
const ContextMenuSeparator = React.forwardRef<
|
|
152
|
-
React.ElementRef<typeof ContextMenuPrimitive.Separator>,
|
|
153
|
-
ContextMenuSeparatorProps
|
|
154
|
-
>(function ContextMenuSeparator({ className, ...props }, ref) {
|
|
155
|
-
return (
|
|
156
|
-
<ContextMenuPrimitive.Separator
|
|
157
|
-
data-slot="context-menu-separator"
|
|
158
|
-
ref={ref}
|
|
159
|
-
className={cn("my-[var(--bh-space-xs-4)] h-[var(--bh-border-width-default)] bg-[var(--bh-border-subtle)]", className)}
|
|
160
|
-
{...props}
|
|
161
|
-
/>
|
|
162
|
-
)
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
const ContextMenuSubTrigger = React.forwardRef<
|
|
166
|
-
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
|
|
167
|
-
ContextMenuSubTriggerProps
|
|
168
|
-
>(function ContextMenuSubTrigger({ children, className, inset, ...props }, ref) {
|
|
169
|
-
return (
|
|
170
|
-
<ContextMenuPrimitive.SubTrigger
|
|
171
|
-
data-inset={inset ? "true" : undefined}
|
|
172
|
-
data-slot="context-menu-sub-trigger"
|
|
173
|
-
ref={ref}
|
|
174
|
-
className={cn(menuItemClassName, inset && "ps-[var(--bh-space-8xl-48)]", className)}
|
|
175
|
-
{...props}
|
|
176
|
-
>
|
|
177
|
-
{children}
|
|
178
|
-
<ChevronRightIcon className="ms-auto size-[var(--bh-space-3xl-16)] rtl:-scale-x-100" />
|
|
179
|
-
</ContextMenuPrimitive.SubTrigger>
|
|
180
|
-
)
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
const ContextMenuSubContent = React.forwardRef<
|
|
184
|
-
React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
|
|
185
|
-
ContextMenuSubContentProps
|
|
186
|
-
>(function ContextMenuSubContent({ className, ...props }, ref) {
|
|
187
|
-
return (
|
|
188
|
-
<ContextMenuPrimitive.SubContent
|
|
189
|
-
data-slot="context-menu-sub-content"
|
|
190
|
-
ref={ref}
|
|
191
|
-
className={cn(menuContentClassName, className)}
|
|
192
|
-
{...props}
|
|
193
|
-
/>
|
|
194
|
-
)
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
function ContextMenuShortcut({ className, ...props }: ContextMenuShortcutProps) {
|
|
198
|
-
return (
|
|
199
|
-
<span
|
|
200
|
-
data-slot="context-menu-shortcut"
|
|
201
|
-
className={cn("ms-auto text-[length:var(--bh-text-body-xs-medium-font-size)] font-[var(--bh-text-body-xs-medium-font-weight)] text-[var(--bh-content-muted)]", className)}
|
|
202
|
-
{...props}
|
|
203
|
-
/>
|
|
204
|
-
)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export {
|
|
208
|
-
ContextMenu,
|
|
209
|
-
ContextMenuCheckboxItem,
|
|
210
|
-
ContextMenuContent,
|
|
211
|
-
ContextMenuGroup,
|
|
212
|
-
ContextMenuItem,
|
|
213
|
-
ContextMenuLabel,
|
|
214
|
-
ContextMenuPortal,
|
|
215
|
-
ContextMenuRadioGroup,
|
|
216
|
-
ContextMenuRadioItem,
|
|
217
|
-
ContextMenuSeparator,
|
|
218
|
-
ContextMenuShortcut,
|
|
219
|
-
ContextMenuSub,
|
|
220
|
-
ContextMenuSubContent,
|
|
221
|
-
ContextMenuSubTrigger,
|
|
222
|
-
ContextMenuTrigger,
|
|
223
|
-
}
|
|
224
|
-
export type {
|
|
225
|
-
ContextMenuCheckboxItemProps,
|
|
226
|
-
ContextMenuContentProps,
|
|
227
|
-
ContextMenuItemProps,
|
|
228
|
-
ContextMenuLabelProps,
|
|
229
|
-
ContextMenuProps,
|
|
230
|
-
ContextMenuRadioItemProps,
|
|
231
|
-
ContextMenuSeparatorProps,
|
|
232
|
-
ContextMenuShortcutProps,
|
|
233
|
-
ContextMenuSubContentProps,
|
|
234
|
-
ContextMenuSubTriggerProps,
|
|
235
|
-
ContextMenuTriggerProps,
|
|
236
|
-
}
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
|
|
5
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
8
|
+
|
|
9
|
+
type ContextMenuProps = React.ComponentProps<typeof ContextMenuPrimitive.Root>
|
|
10
|
+
type ContextMenuTriggerProps = React.ComponentPropsWithoutRef<
|
|
11
|
+
typeof ContextMenuPrimitive.Trigger
|
|
12
|
+
>
|
|
13
|
+
type ContextMenuContentProps = React.ComponentPropsWithoutRef<
|
|
14
|
+
typeof ContextMenuPrimitive.Content
|
|
15
|
+
>
|
|
16
|
+
type ContextMenuItemProps = React.ComponentPropsWithoutRef<
|
|
17
|
+
typeof ContextMenuPrimitive.Item
|
|
18
|
+
> & {
|
|
19
|
+
inset?: boolean
|
|
20
|
+
}
|
|
21
|
+
type ContextMenuCheckboxItemProps = React.ComponentPropsWithoutRef<
|
|
22
|
+
typeof ContextMenuPrimitive.CheckboxItem
|
|
23
|
+
>
|
|
24
|
+
type ContextMenuRadioItemProps = React.ComponentPropsWithoutRef<
|
|
25
|
+
typeof ContextMenuPrimitive.RadioItem
|
|
26
|
+
>
|
|
27
|
+
type ContextMenuLabelProps = React.ComponentPropsWithoutRef<
|
|
28
|
+
typeof ContextMenuPrimitive.Label
|
|
29
|
+
> & {
|
|
30
|
+
inset?: boolean
|
|
31
|
+
}
|
|
32
|
+
type ContextMenuSeparatorProps = React.ComponentPropsWithoutRef<
|
|
33
|
+
typeof ContextMenuPrimitive.Separator
|
|
34
|
+
>
|
|
35
|
+
type ContextMenuSubTriggerProps = React.ComponentPropsWithoutRef<
|
|
36
|
+
typeof ContextMenuPrimitive.SubTrigger
|
|
37
|
+
> & {
|
|
38
|
+
inset?: boolean
|
|
39
|
+
}
|
|
40
|
+
type ContextMenuSubContentProps = React.ComponentPropsWithoutRef<
|
|
41
|
+
typeof ContextMenuPrimitive.SubContent
|
|
42
|
+
>
|
|
43
|
+
type ContextMenuShortcutProps = React.ComponentProps<"span">
|
|
44
|
+
|
|
45
|
+
const ContextMenu = ContextMenuPrimitive.Root
|
|
46
|
+
const ContextMenuTrigger = ContextMenuPrimitive.Trigger
|
|
47
|
+
const ContextMenuGroup = ContextMenuPrimitive.Group
|
|
48
|
+
const ContextMenuPortal = ContextMenuPrimitive.Portal
|
|
49
|
+
const ContextMenuSub = ContextMenuPrimitive.Sub
|
|
50
|
+
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
|
|
51
|
+
|
|
52
|
+
const menuContentClassName =
|
|
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(--elevation-menu)]"
|
|
54
|
+
|
|
55
|
+
const menuItemClassName =
|
|
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
|
+
|
|
58
|
+
const ContextMenuContent = React.forwardRef<
|
|
59
|
+
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
|
60
|
+
ContextMenuContentProps
|
|
61
|
+
>(function ContextMenuContent({ className, ...props }, ref) {
|
|
62
|
+
return (
|
|
63
|
+
<ContextMenuPortal>
|
|
64
|
+
<ContextMenuPrimitive.Content
|
|
65
|
+
data-slot="context-menu-content"
|
|
66
|
+
ref={ref}
|
|
67
|
+
className={cn(menuContentClassName, className)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
</ContextMenuPortal>
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const ContextMenuItem = React.forwardRef<
|
|
75
|
+
React.ElementRef<typeof ContextMenuPrimitive.Item>,
|
|
76
|
+
ContextMenuItemProps
|
|
77
|
+
>(function ContextMenuItem({ className, inset, ...props }, ref) {
|
|
78
|
+
return (
|
|
79
|
+
<ContextMenuPrimitive.Item
|
|
80
|
+
data-inset={inset ? "true" : undefined}
|
|
81
|
+
data-slot="context-menu-item"
|
|
82
|
+
ref={ref}
|
|
83
|
+
className={cn(menuItemClassName, inset && "ps-[var(--bh-space-8xl-48)]", className)}
|
|
84
|
+
{...props}
|
|
85
|
+
/>
|
|
86
|
+
)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
const ContextMenuCheckboxItem = React.forwardRef<
|
|
90
|
+
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
|
91
|
+
ContextMenuCheckboxItemProps
|
|
92
|
+
>(function ContextMenuCheckboxItem({ children, className, checked, ...props }, ref) {
|
|
93
|
+
return (
|
|
94
|
+
<ContextMenuPrimitive.CheckboxItem
|
|
95
|
+
checked={checked}
|
|
96
|
+
data-slot="context-menu-checkbox-item"
|
|
97
|
+
ref={ref}
|
|
98
|
+
className={cn(menuItemClassName, "ps-[var(--bh-space-8xl-48)]", className)}
|
|
99
|
+
{...props}
|
|
100
|
+
>
|
|
101
|
+
<span className="absolute start-[var(--bh-space-md-8)] inline-flex size-[var(--bh-space-5xl-24)] items-center justify-center">
|
|
102
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
103
|
+
<CheckIcon className="size-[var(--bh-space-3xl-16)]" />
|
|
104
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
105
|
+
</span>
|
|
106
|
+
{children}
|
|
107
|
+
</ContextMenuPrimitive.CheckboxItem>
|
|
108
|
+
)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const ContextMenuRadioItem = React.forwardRef<
|
|
112
|
+
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
|
|
113
|
+
ContextMenuRadioItemProps
|
|
114
|
+
>(function ContextMenuRadioItem({ children, className, ...props }, ref) {
|
|
115
|
+
return (
|
|
116
|
+
<ContextMenuPrimitive.RadioItem
|
|
117
|
+
data-slot="context-menu-radio-item"
|
|
118
|
+
ref={ref}
|
|
119
|
+
className={cn(menuItemClassName, "ps-[var(--bh-space-8xl-48)]", className)}
|
|
120
|
+
{...props}
|
|
121
|
+
>
|
|
122
|
+
<span className="absolute start-[var(--bh-space-md-8)] inline-flex size-[var(--bh-space-5xl-24)] items-center justify-center">
|
|
123
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
124
|
+
<CircleIcon className="size-[var(--bh-space-md-8)] fill-current" />
|
|
125
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
126
|
+
</span>
|
|
127
|
+
{children}
|
|
128
|
+
</ContextMenuPrimitive.RadioItem>
|
|
129
|
+
)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const ContextMenuLabel = React.forwardRef<
|
|
133
|
+
React.ElementRef<typeof ContextMenuPrimitive.Label>,
|
|
134
|
+
ContextMenuLabelProps
|
|
135
|
+
>(function ContextMenuLabel({ className, inset, ...props }, ref) {
|
|
136
|
+
return (
|
|
137
|
+
<ContextMenuPrimitive.Label
|
|
138
|
+
data-inset={inset ? "true" : undefined}
|
|
139
|
+
data-slot="context-menu-label"
|
|
140
|
+
ref={ref}
|
|
141
|
+
className={cn(
|
|
142
|
+
"px-[var(--bh-space-md-8)] py-[var(--bh-space-sm-6)] 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)] text-[var(--bh-content-muted)]",
|
|
143
|
+
inset && "ps-[var(--bh-space-8xl-48)]",
|
|
144
|
+
className
|
|
145
|
+
)}
|
|
146
|
+
{...props}
|
|
147
|
+
/>
|
|
148
|
+
)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
const ContextMenuSeparator = React.forwardRef<
|
|
152
|
+
React.ElementRef<typeof ContextMenuPrimitive.Separator>,
|
|
153
|
+
ContextMenuSeparatorProps
|
|
154
|
+
>(function ContextMenuSeparator({ className, ...props }, ref) {
|
|
155
|
+
return (
|
|
156
|
+
<ContextMenuPrimitive.Separator
|
|
157
|
+
data-slot="context-menu-separator"
|
|
158
|
+
ref={ref}
|
|
159
|
+
className={cn("my-[var(--bh-space-xs-4)] h-[var(--bh-border-width-default)] bg-[var(--bh-border-subtle)]", className)}
|
|
160
|
+
{...props}
|
|
161
|
+
/>
|
|
162
|
+
)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
const ContextMenuSubTrigger = React.forwardRef<
|
|
166
|
+
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
|
|
167
|
+
ContextMenuSubTriggerProps
|
|
168
|
+
>(function ContextMenuSubTrigger({ children, className, inset, ...props }, ref) {
|
|
169
|
+
return (
|
|
170
|
+
<ContextMenuPrimitive.SubTrigger
|
|
171
|
+
data-inset={inset ? "true" : undefined}
|
|
172
|
+
data-slot="context-menu-sub-trigger"
|
|
173
|
+
ref={ref}
|
|
174
|
+
className={cn(menuItemClassName, inset && "ps-[var(--bh-space-8xl-48)]", className)}
|
|
175
|
+
{...props}
|
|
176
|
+
>
|
|
177
|
+
{children}
|
|
178
|
+
<ChevronRightIcon className="ms-auto size-[var(--bh-space-3xl-16)] rtl:-scale-x-100" />
|
|
179
|
+
</ContextMenuPrimitive.SubTrigger>
|
|
180
|
+
)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
const ContextMenuSubContent = React.forwardRef<
|
|
184
|
+
React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
|
|
185
|
+
ContextMenuSubContentProps
|
|
186
|
+
>(function ContextMenuSubContent({ className, ...props }, ref) {
|
|
187
|
+
return (
|
|
188
|
+
<ContextMenuPrimitive.SubContent
|
|
189
|
+
data-slot="context-menu-sub-content"
|
|
190
|
+
ref={ref}
|
|
191
|
+
className={cn(menuContentClassName, className)}
|
|
192
|
+
{...props}
|
|
193
|
+
/>
|
|
194
|
+
)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
function ContextMenuShortcut({ className, ...props }: ContextMenuShortcutProps) {
|
|
198
|
+
return (
|
|
199
|
+
<span
|
|
200
|
+
data-slot="context-menu-shortcut"
|
|
201
|
+
className={cn("ms-auto text-[length:var(--bh-text-body-xs-medium-font-size)] font-[var(--bh-text-body-xs-medium-font-weight)] text-[var(--bh-content-muted)]", className)}
|
|
202
|
+
{...props}
|
|
203
|
+
/>
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
ContextMenu,
|
|
209
|
+
ContextMenuCheckboxItem,
|
|
210
|
+
ContextMenuContent,
|
|
211
|
+
ContextMenuGroup,
|
|
212
|
+
ContextMenuItem,
|
|
213
|
+
ContextMenuLabel,
|
|
214
|
+
ContextMenuPortal,
|
|
215
|
+
ContextMenuRadioGroup,
|
|
216
|
+
ContextMenuRadioItem,
|
|
217
|
+
ContextMenuSeparator,
|
|
218
|
+
ContextMenuShortcut,
|
|
219
|
+
ContextMenuSub,
|
|
220
|
+
ContextMenuSubContent,
|
|
221
|
+
ContextMenuSubTrigger,
|
|
222
|
+
ContextMenuTrigger,
|
|
223
|
+
}
|
|
224
|
+
export type {
|
|
225
|
+
ContextMenuCheckboxItemProps,
|
|
226
|
+
ContextMenuContentProps,
|
|
227
|
+
ContextMenuItemProps,
|
|
228
|
+
ContextMenuLabelProps,
|
|
229
|
+
ContextMenuProps,
|
|
230
|
+
ContextMenuRadioItemProps,
|
|
231
|
+
ContextMenuSeparatorProps,
|
|
232
|
+
ContextMenuShortcutProps,
|
|
233
|
+
ContextMenuSubContentProps,
|
|
234
|
+
ContextMenuSubTriggerProps,
|
|
235
|
+
ContextMenuTriggerProps,
|
|
236
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { EChart, type EChartProps, type EChartTheme } from "./echart"
|
|
5
|
+
import { createChartOption, type ChartSpec } from "./chart-options"
|
|
6
|
+
import { attachChartInteractions } from "./chart-interactions"
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
8
|
+
|
|
9
|
+
export type DataChartProps = Omit<EChartProps, "option"> & {
|
|
10
|
+
spec: ChartSpec
|
|
11
|
+
loading?: boolean
|
|
12
|
+
loadingLabel?: string
|
|
13
|
+
emptyLabel?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** The ready-to-use Banhaten chart surface, including the source interactions. */
|
|
17
|
+
export function DataChart({ spec, label, description, loading = false, loadingLabel = "Loading chart…", emptyLabel = "No data available", onReady, className, ...props }: DataChartProps) {
|
|
18
|
+
const option = React.useCallback((theme: EChartTheme) => createChartOption(theme, spec), [spec])
|
|
19
|
+
const setup = React.useCallback<NonNullable<EChartProps["onReady"]>>((chart, theme) => {
|
|
20
|
+
const cleanup = attachChartInteractions(chart, theme, spec)
|
|
21
|
+
const cleanupConsumer = onReady?.(chart, theme)
|
|
22
|
+
return () => { cleanup(); cleanupConsumer?.() }
|
|
23
|
+
}, [spec, onReady])
|
|
24
|
+
const empty = spec.family === "sankey" ? !((spec.nodes?.length ?? spec.data.length) && spec.links?.length) : spec.data.length === 0
|
|
25
|
+
if (loading || empty) {
|
|
26
|
+
return (
|
|
27
|
+
<div
|
|
28
|
+
{...props}
|
|
29
|
+
role="status"
|
|
30
|
+
aria-label={label}
|
|
31
|
+
aria-busy={loading}
|
|
32
|
+
data-slot="data-chart-state"
|
|
33
|
+
className={cn("flex h-[var(--bh-space-19xl-384)] w-full items-center justify-center rounded-[var(--bh-radius-lg-8)] bg-[var(--bh-bg-neutral-subtle)] 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-muted)]", className)}
|
|
34
|
+
>
|
|
35
|
+
{loading ? loadingLabel : emptyLabel}
|
|
36
|
+
</div>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
return <EChart {...props} label={label} description={description} className={className} option={option} onReady={setup} />
|
|
40
|
+
}
|