banhaten 0.1.2 → 0.1.3
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/README.md +93 -328
- package/banhaten.config.example.json +1 -1
- package/docs/design-system/README.md +11 -0
- package/docs/design-system/appearance-presets.md +184 -0
- package/docs/design-system/appearances/default.md +94 -0
- package/docs/design-system/appearances/rounded.md +95 -0
- package/docs/design-system/appearances/sharp.md +95 -0
- package/docs/design-system/component-showcase-consistency-report.md +217 -0
- package/docs/design-system/component-token-consistency-audit.md +163 -0
- package/docs/design-system/components/README.md +74 -0
- package/docs/design-system/components/accordion.md +51 -0
- package/docs/design-system/components/activity-feed.md +92 -0
- package/docs/design-system/components/alert-dialog.md +70 -0
- package/docs/design-system/components/alert.md +79 -0
- package/docs/design-system/components/aspect-ratio.md +44 -0
- package/docs/design-system/components/attribute.md +87 -0
- package/docs/design-system/components/autocomplete.md +74 -0
- package/docs/design-system/components/avatar.md +52 -0
- package/docs/design-system/components/badge.md +53 -0
- package/docs/design-system/components/banner.md +85 -0
- package/docs/design-system/components/breadcrumbs.md +174 -0
- package/docs/design-system/components/button-group.md +83 -0
- package/docs/design-system/components/button.md +77 -0
- package/docs/design-system/components/card.md +78 -0
- package/docs/design-system/components/carousel.md +44 -0
- package/docs/design-system/components/catalog-components.md +45 -0
- package/docs/design-system/components/chart.md +43 -0
- package/docs/design-system/components/checkbox.md +52 -0
- package/docs/design-system/components/collapsible.md +48 -0
- package/docs/design-system/components/command-bar.md +57 -0
- package/docs/design-system/components/command.md +60 -0
- package/docs/design-system/components/context-menu.md +44 -0
- package/docs/design-system/components/date-picker.md +77 -0
- package/docs/design-system/components/divider.md +101 -0
- package/docs/design-system/components/empty-state.md +55 -0
- package/docs/design-system/components/field.md +69 -0
- package/docs/design-system/components/file-upload.md +185 -0
- package/docs/design-system/components/hover-card.md +46 -0
- package/docs/design-system/components/icons.md +48 -0
- package/docs/design-system/components/input-group.md +56 -0
- package/docs/design-system/components/input-otp.md +55 -0
- package/docs/design-system/components/input.md +48 -0
- package/docs/design-system/components/kbd.md +44 -0
- package/docs/design-system/components/label.md +48 -0
- package/docs/design-system/components/menu.md +59 -0
- package/docs/design-system/components/menubar.md +45 -0
- package/docs/design-system/components/modal.md +98 -0
- package/docs/design-system/components/native-select.md +52 -0
- package/docs/design-system/components/navigation-menu.md +48 -0
- package/docs/design-system/components/onboarding-step-list-item.md +80 -0
- package/docs/design-system/components/page-header.md +84 -0
- package/docs/design-system/components/pagination.md +49 -0
- package/docs/design-system/components/popover.md +58 -0
- package/docs/design-system/components/progress-slider.md +48 -0
- package/docs/design-system/components/progress.md +75 -0
- package/docs/design-system/components/radio-card.md +49 -0
- package/docs/design-system/components/radio-group.md +55 -0
- package/docs/design-system/components/resizable.md +42 -0
- package/docs/design-system/components/scroll-area.md +45 -0
- package/docs/design-system/components/select.md +50 -0
- package/docs/design-system/components/sheet.md +65 -0
- package/docs/design-system/components/sidebar.md +68 -0
- package/docs/design-system/components/skeleton.md +73 -0
- package/docs/design-system/components/slideout.md +63 -0
- package/docs/design-system/components/slider.md +61 -0
- package/docs/design-system/components/social-button.md +47 -0
- package/docs/design-system/components/spinner.md +61 -0
- package/docs/design-system/components/steps.md +63 -0
- package/docs/design-system/components/table.md +397 -0
- package/docs/design-system/components/tabs.md +52 -0
- package/docs/design-system/components/tag.md +78 -0
- package/docs/design-system/components/textarea.md +48 -0
- package/docs/design-system/components/timeline.md +81 -0
- package/docs/design-system/components/toast.md +56 -0
- package/docs/design-system/components/toggle.md +79 -0
- package/docs/design-system/components/toolbar.md +85 -0
- package/docs/design-system/components/tooltip.md +90 -0
- package/docs/design-system/components/typography.md +18 -0
- package/docs/design-system/design-system-test-missing-items.md +368 -0
- package/docs/design-system/icons.md +69 -0
- package/docs/design-system/registry-and-cli.md +41 -0
- package/docs/design-system/tabs.md +53 -0
- package/docs/design-system/token-governance.md +38 -0
- package/package.json +83 -65
- package/registry/components/alert-dialog.tsx +297 -0
- package/registry/components/aspect-ratio.tsx +30 -0
- package/registry/components/carousel.tsx +234 -0
- package/registry/components/chart.tsx +170 -0
- package/registry/components/collapsible.tsx +69 -0
- package/registry/components/command.tsx +174 -0
- package/registry/components/context-menu.tsx +236 -0
- package/registry/components/date-picker.tsx +1 -1
- package/registry/components/expanded/PageHeader.tsx +1 -1
- package/registry/components/expanded/breadcrumbs.css +139 -139
- package/registry/components/expanded/catalogComponentsShowcase.css +83 -83
- package/registry/components/expanded/steps.css +274 -274
- package/registry/components/expanded/timeline.css +264 -264
- package/registry/components/field.tsx +230 -0
- package/registry/components/hover-card.tsx +48 -0
- package/registry/components/input-group.tsx +130 -0
- package/registry/components/input.tsx +2 -2
- package/registry/components/kbd.tsx +44 -0
- package/registry/components/label.tsx +78 -0
- package/registry/components/menu.tsx +3 -1
- package/registry/components/menubar.tsx +226 -0
- package/registry/components/modal.tsx +109 -76
- package/registry/components/native-select.tsx +205 -0
- package/registry/components/navigation-menu.tsx +171 -0
- package/registry/components/radio-group.tsx +1 -1
- package/registry/components/resizable.tsx +74 -0
- package/registry/components/scroll-area.tsx +67 -0
- package/registry/components/select.tsx +2 -4
- package/registry/components/sheet.tsx +305 -0
- package/registry/components/sidebar.tsx +352 -0
- package/registry/components/social-button.tsx +74 -10
- package/registry/components/{expanded/tabs.css → tabs.css} +127 -106
- package/registry/components/tabs.tsx +242 -0
- package/registry/components/textarea.tsx +1 -1
- package/registry/components/toast.tsx +131 -0
- package/registry/examples/alert-dialog-demo.tsx +42 -0
- package/registry/examples/aspect-ratio-demo.tsx +11 -0
- package/registry/examples/carousel-demo.tsx +25 -0
- package/registry/examples/chart-demo.tsx +33 -0
- package/registry/examples/collapsible-demo.tsx +16 -0
- package/registry/examples/command-demo.tsx +42 -0
- package/registry/examples/context-menu-demo.tsx +29 -0
- package/registry/examples/expanded/tabs-demo.tsx +1 -1
- package/registry/examples/field-demo.tsx +51 -0
- package/registry/examples/hover-card-demo.tsx +23 -0
- package/registry/examples/input-group-demo.tsx +16 -0
- package/registry/examples/kbd-demo.tsx +11 -0
- package/registry/examples/label-demo.tsx +20 -0
- package/registry/examples/menubar-demo.tsx +34 -0
- package/registry/examples/native-select-demo.tsx +16 -0
- package/registry/examples/navigation-menu-demo.tsx +29 -0
- package/registry/examples/resizable-demo.tsx +22 -0
- package/registry/examples/scroll-area-demo.tsx +15 -0
- package/registry/examples/sheet-demo.tsx +47 -0
- package/registry/examples/sidebar-demo.tsx +55 -0
- package/registry/examples/tabs-demo.tsx +13 -0
- package/registry/examples/toast-demo.tsx +35 -0
- package/registry/index.json +655 -11
- package/registry/styles/globals.css +4733 -4690
- package/registry.json +1612 -0
- package/schema/config.schema.json +48 -0
- package/schema/registry.schema.json +85 -0
- package/schema/tokens.schema.json +63 -0
- package/src/cli/index.js +312 -18
- package/tokens/banhaten.tokens.json +1 -1
- package/registry/assets/avatars/avatar-02.jpg +0 -0
- package/registry/assets/avatars/avatar-03.jpg +0 -0
- package/registry/assets/avatars/avatar-04.jpg +0 -0
- package/registry/assets/avatars/avatar-05.jpg +0 -0
- package/registry/assets/avatars/avatar-06.jpg +0 -0
- package/registry/assets/avatars/avatar-07.jpg +0 -0
- package/registry/assets/avatars/avatar-08.jpg +0 -0
- package/registry/assets/avatars/avatar-09.jpg +0 -0
- package/registry/assets/avatars/avatar-10.jpg +0 -0
- package/registry/assets/avatars/avatar-11.jpg +0 -0
- package/registry/assets/avatars/avatar-12.jpg +0 -0
- package/registry/assets/avatars/avatar-13.jpg +0 -0
- package/registry/assets/avatars/avatar-14.jpg +0 -0
- package/registry/assets/avatars/avatar-15.jpg +0 -0
- package/registry/assets/avatars/avatar-16.jpg +0 -0
- package/registry/assets/avatars/avatar-17.jpg +0 -0
- package/registry/assets/avatars/avatar-18.jpg +0 -0
- package/registry/assets/avatars/avatar-19.jpg +0 -0
- package/registry/assets/avatars/avatar-20.jpg +0 -0
- package/registry/assets/avatars/avatar-21.jpg +0 -0
- package/registry/assets/avatars/avatar-22.jpg +0 -0
- package/registry/assets/avatars/avatar-23.jpg +0 -0
- package/registry/assets/avatars/avatar-24.jpg +0 -0
- package/registry/assets/avatars/avatar-25.jpg +0 -0
- package/registry/assets/avatars/avatar-26.jpg +0 -0
- package/registry/assets/avatars/avatar-27.jpg +0 -0
- package/registry/assets/avatars/avatar-28.jpg +0 -0
- package/registry/assets/avatars/avatar-29.jpg +0 -0
- package/registry/assets/avatars/avatar-30.jpg +0 -0
- package/registry/assets/avatars/avatar-31.jpg +0 -0
- package/registry/assets/avatars/avatar-32.jpg +0 -0
- package/registry/assets/avatars/avatar-33.jpg +0 -0
- package/registry/assets/avatars/avatar-34.jpg +0 -0
- package/registry/assets/avatars/avatar-35.jpg +0 -0
- package/registry/assets/image-assets.json +0 -744
- package/registry/assets/images/art-02.jpg +0 -0
- package/registry/assets/images/art-03.jpg +0 -0
- package/registry/assets/images/art-04.jpg +0 -0
- package/registry/assets/images/art-05.jpg +0 -0
- package/registry/assets/images/art-06.jpg +0 -0
- package/registry/assets/images/art-07.jpg +0 -0
- package/registry/assets/images/art-08.jpg +0 -0
- package/registry/assets/images/art-09.jpg +0 -0
- package/registry/assets/images/art-10.jpg +0 -0
- package/registry/assets/images/art-11.jpg +0 -0
- package/registry/assets/images/art-12.jpg +0 -0
- package/registry/assets/images/art-13.jpg +0 -0
- package/registry/assets/images/art-14.jpg +0 -0
- package/registry/assets/images/art-15.jpg +0 -0
- package/registry/assets/images/art-16.jpg +0 -0
- package/registry/assets/images/art-17.jpg +0 -0
- package/registry/assets/images/art-18.jpg +0 -0
- package/registry/assets/images/art-19.jpg +0 -0
- package/registry/assets/images/art-20.jpg +0 -0
- package/registry/assets/images/art-21.jpg +0 -0
- package/registry/assets/images/art-22.jpg +0 -0
- package/registry/assets/images/art-23.jpg +0 -0
- package/registry/assets/images/art-24.jpg +0 -0
- package/registry/assets/images/art-25.jpg +0 -0
- package/registry/assets/images/art-26.jpg +0 -0
- package/registry/assets/images/art-27.jpg +0 -0
- package/registry/assets/images/nature-01.jpg +0 -0
- package/registry/assets/images/nature-02.jpg +0 -0
- package/registry/assets/images/nature-03.jpg +0 -0
- package/registry/assets/images/nature-04.jpg +0 -0
- package/registry/assets/images/nature-05.jpg +0 -0
- package/registry/assets/images/nature-06.jpg +0 -0
- package/registry/assets/images/nature-07.jpg +0 -0
- package/registry/assets/images/nature-08.jpg +0 -0
- package/registry/assets/images/nature-09.jpg +0 -0
- package/registry/assets/images/nature-10.jpg +0 -0
- package/registry/assets/images/nature-11.jpg +0 -0
- package/registry/assets/images/nature-12.jpg +0 -0
- package/registry/assets/images/nature-13.jpg +0 -0
- package/registry/assets/images/nature-14.jpg +0 -0
- package/registry/assets/images/nature-15.jpg +0 -0
- package/registry/assets/images/nature-16.jpg +0 -0
- package/registry/assets/images/nature-17.jpg +0 -0
- package/registry/assets/images/nature-18.jpg +0 -0
- package/registry/assets/images/nature-19.jpg +0 -0
- package/registry/assets/images/nature-20.jpg +0 -0
- package/registry/components/expanded/Tabs.tsx +0 -86
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as MenubarPrimitive from "@radix-ui/react-menubar"
|
|
5
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
8
|
+
|
|
9
|
+
type MenubarProps = React.ComponentProps<typeof MenubarPrimitive.Root>
|
|
10
|
+
type MenubarTriggerProps = React.ComponentPropsWithoutRef<
|
|
11
|
+
typeof MenubarPrimitive.Trigger
|
|
12
|
+
>
|
|
13
|
+
type MenubarContentProps = React.ComponentPropsWithoutRef<
|
|
14
|
+
typeof MenubarPrimitive.Content
|
|
15
|
+
>
|
|
16
|
+
type MenubarItemProps = React.ComponentPropsWithoutRef<
|
|
17
|
+
typeof MenubarPrimitive.Item
|
|
18
|
+
> & {
|
|
19
|
+
inset?: boolean
|
|
20
|
+
}
|
|
21
|
+
type MenubarCheckboxItemProps = React.ComponentPropsWithoutRef<
|
|
22
|
+
typeof MenubarPrimitive.CheckboxItem
|
|
23
|
+
>
|
|
24
|
+
type MenubarRadioItemProps = React.ComponentPropsWithoutRef<
|
|
25
|
+
typeof MenubarPrimitive.RadioItem
|
|
26
|
+
>
|
|
27
|
+
type MenubarLabelProps = React.ComponentPropsWithoutRef<
|
|
28
|
+
typeof MenubarPrimitive.Label
|
|
29
|
+
> & {
|
|
30
|
+
inset?: boolean
|
|
31
|
+
}
|
|
32
|
+
type MenubarSeparatorProps = React.ComponentPropsWithoutRef<
|
|
33
|
+
typeof MenubarPrimitive.Separator
|
|
34
|
+
>
|
|
35
|
+
type MenubarShortcutProps = React.ComponentProps<"span">
|
|
36
|
+
|
|
37
|
+
const MenubarMenu = MenubarPrimitive.Menu
|
|
38
|
+
const MenubarGroup = MenubarPrimitive.Group
|
|
39
|
+
const MenubarPortal = MenubarPrimitive.Portal
|
|
40
|
+
const MenubarSub = MenubarPrimitive.Sub
|
|
41
|
+
const MenubarRadioGroup = MenubarPrimitive.RadioGroup
|
|
42
|
+
|
|
43
|
+
const Menubar = React.forwardRef<
|
|
44
|
+
React.ElementRef<typeof MenubarPrimitive.Root>,
|
|
45
|
+
MenubarProps
|
|
46
|
+
>(function Menubar({ className, ...props }, ref) {
|
|
47
|
+
return (
|
|
48
|
+
<MenubarPrimitive.Root
|
|
49
|
+
data-slot="menubar"
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={cn(
|
|
52
|
+
"flex h-[var(--bh-space-7xl-40)] items-center gap-[var(--bh-space-xs-4)] rounded-[var(--bh-radius-lg-8)] border border-[var(--bh-border-subtle)] bg-[var(--bh-bg-raised)] p-[var(--bh-space-xs-4)] shadow-[var(--shadow-component-default)]",
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const MenubarTrigger = React.forwardRef<
|
|
61
|
+
React.ElementRef<typeof MenubarPrimitive.Trigger>,
|
|
62
|
+
MenubarTriggerProps
|
|
63
|
+
>(function MenubarTrigger({ className, ...props }, ref) {
|
|
64
|
+
return (
|
|
65
|
+
<MenubarPrimitive.Trigger
|
|
66
|
+
data-slot="menubar-trigger"
|
|
67
|
+
ref={ref}
|
|
68
|
+
className={cn(
|
|
69
|
+
"flex h-[var(--bh-space-6xl-32)] items-center rounded-[var(--bh-radius-md-6)] px-[var(--bh-space-md-8)] text-[length:var(--bh-text-body-sm-medium-font-size)] font-[var(--bh-text-body-sm-medium-font-weight)] leading-[var(--bh-text-body-sm-medium-line-height)] tracking-[var(--bh-text-body-sm-medium-letter-spacing)] text-[var(--bh-content-default)] outline-none data-[highlighted]:bg-[var(--bh-interactive-ghost-hover)] data-[state=open]:bg-[var(--bh-interactive-soft-default)]",
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const menuContentClassName =
|
|
78
|
+
"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)]"
|
|
79
|
+
|
|
80
|
+
const menuItemClassName =
|
|
81
|
+
"relative flex min-h-[var(--bh-menu-item-min-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)]"
|
|
82
|
+
|
|
83
|
+
const MenubarContent = React.forwardRef<
|
|
84
|
+
React.ElementRef<typeof MenubarPrimitive.Content>,
|
|
85
|
+
MenubarContentProps
|
|
86
|
+
>(function MenubarContent({ align = "start", className, ...props }, ref) {
|
|
87
|
+
return (
|
|
88
|
+
<MenubarPortal>
|
|
89
|
+
<MenubarPrimitive.Content
|
|
90
|
+
align={align}
|
|
91
|
+
data-slot="menubar-content"
|
|
92
|
+
ref={ref}
|
|
93
|
+
className={cn(menuContentClassName, className)}
|
|
94
|
+
{...props}
|
|
95
|
+
/>
|
|
96
|
+
</MenubarPortal>
|
|
97
|
+
)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const MenubarItem = React.forwardRef<
|
|
101
|
+
React.ElementRef<typeof MenubarPrimitive.Item>,
|
|
102
|
+
MenubarItemProps
|
|
103
|
+
>(function MenubarItem({ className, inset, ...props }, ref) {
|
|
104
|
+
return (
|
|
105
|
+
<MenubarPrimitive.Item
|
|
106
|
+
data-inset={inset ? "true" : undefined}
|
|
107
|
+
data-slot="menubar-item"
|
|
108
|
+
ref={ref}
|
|
109
|
+
className={cn(menuItemClassName, inset && "ps-[var(--bh-space-8xl-48)]", className)}
|
|
110
|
+
{...props}
|
|
111
|
+
/>
|
|
112
|
+
)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
const MenubarCheckboxItem = React.forwardRef<
|
|
116
|
+
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
|
|
117
|
+
MenubarCheckboxItemProps
|
|
118
|
+
>(function MenubarCheckboxItem({ children, className, checked, ...props }, ref) {
|
|
119
|
+
return (
|
|
120
|
+
<MenubarPrimitive.CheckboxItem
|
|
121
|
+
checked={checked}
|
|
122
|
+
data-slot="menubar-checkbox-item"
|
|
123
|
+
ref={ref}
|
|
124
|
+
className={cn(menuItemClassName, "ps-[var(--bh-space-8xl-48)]", className)}
|
|
125
|
+
{...props}
|
|
126
|
+
>
|
|
127
|
+
<span className="absolute start-[var(--bh-space-md-8)] inline-flex size-[var(--bh-space-5xl-24)] items-center justify-center">
|
|
128
|
+
<MenubarPrimitive.ItemIndicator>
|
|
129
|
+
<CheckIcon className="size-[var(--bh-space-3xl-16)]" />
|
|
130
|
+
</MenubarPrimitive.ItemIndicator>
|
|
131
|
+
</span>
|
|
132
|
+
{children}
|
|
133
|
+
</MenubarPrimitive.CheckboxItem>
|
|
134
|
+
)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
const MenubarRadioItem = React.forwardRef<
|
|
138
|
+
React.ElementRef<typeof MenubarPrimitive.RadioItem>,
|
|
139
|
+
MenubarRadioItemProps
|
|
140
|
+
>(function MenubarRadioItem({ children, className, ...props }, ref) {
|
|
141
|
+
return (
|
|
142
|
+
<MenubarPrimitive.RadioItem
|
|
143
|
+
data-slot="menubar-radio-item"
|
|
144
|
+
ref={ref}
|
|
145
|
+
className={cn(menuItemClassName, "ps-[var(--bh-space-8xl-48)]", className)}
|
|
146
|
+
{...props}
|
|
147
|
+
>
|
|
148
|
+
<span className="absolute start-[var(--bh-space-md-8)] inline-flex size-[var(--bh-space-5xl-24)] items-center justify-center">
|
|
149
|
+
<MenubarPrimitive.ItemIndicator>
|
|
150
|
+
<CircleIcon className="size-[var(--bh-space-md-8)] fill-current" />
|
|
151
|
+
</MenubarPrimitive.ItemIndicator>
|
|
152
|
+
</span>
|
|
153
|
+
{children}
|
|
154
|
+
</MenubarPrimitive.RadioItem>
|
|
155
|
+
)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
const MenubarLabel = React.forwardRef<
|
|
159
|
+
React.ElementRef<typeof MenubarPrimitive.Label>,
|
|
160
|
+
MenubarLabelProps
|
|
161
|
+
>(function MenubarLabel({ className, inset, ...props }, ref) {
|
|
162
|
+
return (
|
|
163
|
+
<MenubarPrimitive.Label
|
|
164
|
+
data-slot="menubar-label"
|
|
165
|
+
ref={ref}
|
|
166
|
+
className={cn(
|
|
167
|
+
"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)]",
|
|
168
|
+
inset && "ps-[var(--bh-space-8xl-48)]",
|
|
169
|
+
className
|
|
170
|
+
)}
|
|
171
|
+
{...props}
|
|
172
|
+
/>
|
|
173
|
+
)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
const MenubarSeparator = React.forwardRef<
|
|
177
|
+
React.ElementRef<typeof MenubarPrimitive.Separator>,
|
|
178
|
+
MenubarSeparatorProps
|
|
179
|
+
>(function MenubarSeparator({ className, ...props }, ref) {
|
|
180
|
+
return (
|
|
181
|
+
<MenubarPrimitive.Separator
|
|
182
|
+
data-slot="menubar-separator"
|
|
183
|
+
ref={ref}
|
|
184
|
+
className={cn("my-[var(--bh-space-xs-4)] h-[var(--bh-border-width-default)] bg-[var(--bh-border-subtle)]", className)}
|
|
185
|
+
{...props}
|
|
186
|
+
/>
|
|
187
|
+
)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
function MenubarShortcut({ className, ...props }: MenubarShortcutProps) {
|
|
191
|
+
return (
|
|
192
|
+
<span
|
|
193
|
+
data-slot="menubar-shortcut"
|
|
194
|
+
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)}
|
|
195
|
+
{...props}
|
|
196
|
+
/>
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export {
|
|
201
|
+
Menubar,
|
|
202
|
+
MenubarCheckboxItem,
|
|
203
|
+
MenubarContent,
|
|
204
|
+
MenubarGroup,
|
|
205
|
+
MenubarItem,
|
|
206
|
+
MenubarLabel,
|
|
207
|
+
MenubarMenu,
|
|
208
|
+
MenubarPortal,
|
|
209
|
+
MenubarRadioGroup,
|
|
210
|
+
MenubarRadioItem,
|
|
211
|
+
MenubarSeparator,
|
|
212
|
+
MenubarShortcut,
|
|
213
|
+
MenubarSub,
|
|
214
|
+
MenubarTrigger,
|
|
215
|
+
}
|
|
216
|
+
export type {
|
|
217
|
+
MenubarCheckboxItemProps,
|
|
218
|
+
MenubarContentProps,
|
|
219
|
+
MenubarItemProps,
|
|
220
|
+
MenubarLabelProps,
|
|
221
|
+
MenubarProps,
|
|
222
|
+
MenubarRadioItemProps,
|
|
223
|
+
MenubarSeparatorProps,
|
|
224
|
+
MenubarShortcutProps,
|
|
225
|
+
MenubarTriggerProps,
|
|
226
|
+
}
|
|
@@ -5,6 +5,15 @@ import * as DialogPrimitive from "@radix-ui/react-dialog"
|
|
|
5
5
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
6
6
|
import { InfoIcon, TriangleAlertIcon, XIcon } from "lucide-react"
|
|
7
7
|
|
|
8
|
+
import {
|
|
9
|
+
AlertDialog,
|
|
10
|
+
AlertDialogAction,
|
|
11
|
+
AlertDialogCancel,
|
|
12
|
+
AlertDialogContent,
|
|
13
|
+
AlertDialogDescription,
|
|
14
|
+
AlertDialogTitle,
|
|
15
|
+
type AlertDialogContentProps,
|
|
16
|
+
} from "@/components/ui/alert-dialog"
|
|
8
17
|
import { Button, type ButtonProps } from "@/components/ui/button"
|
|
9
18
|
import { Checkbox, type CheckboxProps } from "@/components/ui/checkbox"
|
|
10
19
|
import { Spinner } from "@/components/ui/spinner"
|
|
@@ -57,6 +66,12 @@ const modalHeaderIconIntentClassNames: Record<ModalIntent, string> = {
|
|
|
57
66
|
"rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-warning-subtle)] text-[var(--bh-content-warning-default)]",
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
const modalTitleClassName =
|
|
70
|
+
"min-w-0 flex-1 text-start text-[length:var(--bh-text-heading-sm-semibold-font-size)] font-[var(--bh-text-heading-sm-semibold-font-weight)] leading-[var(--bh-text-heading-sm-semibold-line-height)] tracking-[var(--bh-text-heading-sm-semibold-letter-spacing)] text-[var(--bh-content-default)]"
|
|
71
|
+
|
|
72
|
+
const modalDescriptionClassName =
|
|
73
|
+
"min-w-0 flex-1 text-start text-[length:var(--bh-text-body-md-regular-font-size)] font-[var(--bh-text-body-md-regular-font-weight)] leading-[var(--bh-text-body-md-regular-line-height)] tracking-[var(--bh-text-body-md-regular-letter-spacing)] text-[var(--bh-content-subtle)]"
|
|
74
|
+
|
|
60
75
|
type ModalRootProps = React.ComponentProps<typeof DialogPrimitive.Root>
|
|
61
76
|
type ModalContentProps = React.ComponentPropsWithoutRef<
|
|
62
77
|
typeof DialogPrimitive.Content
|
|
@@ -79,6 +94,7 @@ type ModalHeaderIconProps = React.ComponentProps<"span"> & {
|
|
|
79
94
|
type ModalCloseButtonProps = React.ComponentProps<"button"> & {
|
|
80
95
|
label?: string
|
|
81
96
|
}
|
|
97
|
+
type ConfirmModalContentProps = AlertDialogContentProps
|
|
82
98
|
type ModalFooterCheckboxProps = Omit<React.ComponentProps<"div">, "children"> & {
|
|
83
99
|
checked?: CheckboxProps["checked"]
|
|
84
100
|
defaultChecked?: CheckboxProps["defaultChecked"]
|
|
@@ -238,13 +254,10 @@ const ModalTitle = React.forwardRef<
|
|
|
238
254
|
>(function ModalTitle({ className, dir = "auto", ...props }, ref) {
|
|
239
255
|
return (
|
|
240
256
|
<DialogPrimitive.Title
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"min-w-0 flex-1 text-start text-[length:var(--bh-text-heading-sm-semibold-font-size)] font-[var(--bh-text-heading-sm-semibold-font-weight)] leading-[var(--bh-text-heading-sm-semibold-line-height)] tracking-[var(--bh-text-heading-sm-semibold-letter-spacing)] text-[var(--bh-content-default)]",
|
|
246
|
-
className
|
|
247
|
-
)}
|
|
257
|
+
data-slot="modal-title"
|
|
258
|
+
dir={dir}
|
|
259
|
+
ref={ref}
|
|
260
|
+
className={cn(modalTitleClassName, className)}
|
|
248
261
|
{...props}
|
|
249
262
|
/>
|
|
250
263
|
)
|
|
@@ -256,18 +269,47 @@ const ModalDescription = React.forwardRef<
|
|
|
256
269
|
>(function ModalDescription({ className, dir = "auto", ...props }, ref) {
|
|
257
270
|
return (
|
|
258
271
|
<DialogPrimitive.Description
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
"min-w-0 flex-1 text-start text-[length:var(--bh-text-body-md-regular-font-size)] font-[var(--bh-text-body-md-regular-font-weight)] leading-[var(--bh-text-body-md-regular-line-height)] tracking-[var(--bh-text-body-md-regular-letter-spacing)] text-[var(--bh-content-subtle)]",
|
|
264
|
-
className
|
|
265
|
-
)}
|
|
272
|
+
data-slot="modal-description"
|
|
273
|
+
dir={dir}
|
|
274
|
+
ref={ref}
|
|
275
|
+
className={cn(modalDescriptionClassName, className)}
|
|
266
276
|
{...props}
|
|
267
277
|
/>
|
|
268
278
|
)
|
|
269
279
|
})
|
|
270
280
|
|
|
281
|
+
const ConfirmModalCloseButton = React.forwardRef<
|
|
282
|
+
HTMLButtonElement,
|
|
283
|
+
ModalCloseButtonProps
|
|
284
|
+
>(function ConfirmModalCloseButton(
|
|
285
|
+
{ children, className, label = "Close modal", type = "button", ...props },
|
|
286
|
+
ref
|
|
287
|
+
) {
|
|
288
|
+
return (
|
|
289
|
+
<AlertDialogCancel asChild>
|
|
290
|
+
<button
|
|
291
|
+
aria-label={label}
|
|
292
|
+
data-slot="modal-close"
|
|
293
|
+
ref={ref}
|
|
294
|
+
type={type}
|
|
295
|
+
className={cn(
|
|
296
|
+
"absolute end-[var(--bh-space-3xl-16)] top-1/2 inline-flex size-[var(--bh-space-6xl-32)] -translate-y-1/2 items-center justify-center rounded-[var(--bh-radius-full)] border-0 bg-transparent p-0 text-[var(--bh-content-subtle)] outline-none transition-[background-color,box-shadow,color] hover:bg-[var(--bh-interactive-ghost-hover)] hover:text-[var(--bh-content-default)] focus-visible:shadow-[var(--shadow-button-focus)]",
|
|
297
|
+
className
|
|
298
|
+
)}
|
|
299
|
+
{...props}
|
|
300
|
+
>
|
|
301
|
+
{children ?? (
|
|
302
|
+
<XIcon
|
|
303
|
+
aria-hidden="true"
|
|
304
|
+
className="size-[var(--bh-space-5xl-24)]"
|
|
305
|
+
strokeWidth={2}
|
|
306
|
+
/>
|
|
307
|
+
)}
|
|
308
|
+
</button>
|
|
309
|
+
</AlertDialogCancel>
|
|
310
|
+
)
|
|
311
|
+
})
|
|
312
|
+
|
|
271
313
|
const ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(function ModalBody({
|
|
272
314
|
className,
|
|
273
315
|
...props
|
|
@@ -539,18 +581,18 @@ function ConfirmModal({
|
|
|
539
581
|
description,
|
|
540
582
|
dir,
|
|
541
583
|
intent = "danger",
|
|
542
|
-
modal = true,
|
|
584
|
+
modal: _modal = true,
|
|
543
585
|
onCancel,
|
|
544
586
|
onConfirm,
|
|
545
587
|
onEscapeKeyDown,
|
|
546
|
-
onInteractOutside,
|
|
547
588
|
onOpenAutoFocus,
|
|
548
589
|
onOpenChange,
|
|
549
|
-
|
|
590
|
+
onInteractOutside: _onInteractOutside,
|
|
591
|
+
onPointerDownOutside: _onPointerDownOutside,
|
|
550
592
|
open,
|
|
551
593
|
overlayClassName,
|
|
552
594
|
preventEscapeDismiss = false,
|
|
553
|
-
preventOutsideDismiss = true,
|
|
595
|
+
preventOutsideDismiss: _preventOutsideDismiss = true,
|
|
554
596
|
showCancelButton = true,
|
|
555
597
|
showCloseButton = false,
|
|
556
598
|
showDivider = true,
|
|
@@ -565,8 +607,8 @@ function ConfirmModal({
|
|
|
565
607
|
const isRtl = dir === "rtl"
|
|
566
608
|
const rootProps =
|
|
567
609
|
open === undefined
|
|
568
|
-
? { defaultOpen,
|
|
569
|
-
: {
|
|
610
|
+
? { defaultOpen, onOpenChange }
|
|
611
|
+
: { onOpenChange, open }
|
|
570
612
|
const resolvedTitle = title ?? (isRtl ? defaultRtlConfirmTitle : defaultConfirmTitle)
|
|
571
613
|
const resolvedDescription =
|
|
572
614
|
description ?? (isRtl ? defaultRtlConfirmDescription : defaultConfirmDescription)
|
|
@@ -592,57 +634,36 @@ function ConfirmModal({
|
|
|
592
634
|
} = confirmButtonProps ?? {}
|
|
593
635
|
const isConfirmDisabled = confirmDisabled || confirmLoading || confirmButtonDisabled
|
|
594
636
|
|
|
595
|
-
const handleOpenAutoFocus: NonNullable<
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
637
|
+
const handleOpenAutoFocus: NonNullable<
|
|
638
|
+
ConfirmModalContentProps["onOpenAutoFocus"]
|
|
639
|
+
> = React.useCallback(
|
|
640
|
+
(event) => {
|
|
641
|
+
onOpenAutoFocus?.(event)
|
|
642
|
+
if (event.defaultPrevented) return
|
|
600
643
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
644
|
+
const focusTarget = showCancelButton
|
|
645
|
+
? cancelButtonRef.current
|
|
646
|
+
: confirmButtonRef.current
|
|
647
|
+
if (!focusTarget) return
|
|
605
648
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
649
|
+
event.preventDefault()
|
|
650
|
+
focusTarget.focus()
|
|
651
|
+
},
|
|
652
|
+
[onOpenAutoFocus, showCancelButton]
|
|
653
|
+
)
|
|
611
654
|
|
|
612
|
-
const
|
|
613
|
-
|
|
655
|
+
const handleEscapeKeyDown: NonNullable<
|
|
656
|
+
ConfirmModalContentProps["onEscapeKeyDown"]
|
|
614
657
|
> = React.useCallback(
|
|
615
658
|
(event) => {
|
|
616
|
-
|
|
617
|
-
if (!event.defaultPrevented &&
|
|
659
|
+
onEscapeKeyDown?.(event)
|
|
660
|
+
if (!event.defaultPrevented && preventEscapeDismiss) {
|
|
618
661
|
event.preventDefault()
|
|
619
662
|
}
|
|
620
663
|
},
|
|
621
|
-
[
|
|
664
|
+
[onEscapeKeyDown, preventEscapeDismiss]
|
|
622
665
|
)
|
|
623
666
|
|
|
624
|
-
const handleInteractOutside: NonNullable<ModalContentProps["onInteractOutside"]> =
|
|
625
|
-
React.useCallback(
|
|
626
|
-
(event) => {
|
|
627
|
-
onInteractOutside?.(event)
|
|
628
|
-
if (!event.defaultPrevented && preventOutsideDismiss) {
|
|
629
|
-
event.preventDefault()
|
|
630
|
-
}
|
|
631
|
-
},
|
|
632
|
-
[onInteractOutside, preventOutsideDismiss]
|
|
633
|
-
)
|
|
634
|
-
|
|
635
|
-
const handleEscapeKeyDown: NonNullable<ModalContentProps["onEscapeKeyDown"]> =
|
|
636
|
-
React.useCallback(
|
|
637
|
-
(event) => {
|
|
638
|
-
onEscapeKeyDown?.(event)
|
|
639
|
-
if (!event.defaultPrevented && preventEscapeDismiss) {
|
|
640
|
-
event.preventDefault()
|
|
641
|
-
}
|
|
642
|
-
},
|
|
643
|
-
[onEscapeKeyDown, preventEscapeDismiss]
|
|
644
|
-
)
|
|
645
|
-
|
|
646
667
|
const handleCancel: React.MouseEventHandler<HTMLButtonElement> = (event) => {
|
|
647
668
|
cancelButtonOnClick?.(event)
|
|
648
669
|
if (!event.defaultPrevented) {
|
|
@@ -691,26 +712,26 @@ function ConfirmModal({
|
|
|
691
712
|
)
|
|
692
713
|
|
|
693
714
|
return (
|
|
694
|
-
<
|
|
695
|
-
<
|
|
715
|
+
<AlertDialog {...rootProps}>
|
|
716
|
+
<AlertDialogContent
|
|
696
717
|
data-intent={intent}
|
|
718
|
+
data-size={size}
|
|
697
719
|
data-slot="confirm-modal"
|
|
698
720
|
dir={dir}
|
|
721
|
+
className={cn(modalContentVariants({ size, className }))}
|
|
699
722
|
overlayClassName={overlayClassName}
|
|
700
|
-
role="alertdialog"
|
|
701
|
-
size={size}
|
|
702
|
-
className={className}
|
|
703
723
|
onEscapeKeyDown={handleEscapeKeyDown}
|
|
704
|
-
onInteractOutside={handleInteractOutside}
|
|
705
724
|
onOpenAutoFocus={handleOpenAutoFocus}
|
|
706
|
-
onPointerDownOutside={handlePointerDownOutside}
|
|
707
725
|
{...props}
|
|
708
726
|
>
|
|
709
727
|
<ModalHeader>
|
|
710
728
|
{showIcon ? (
|
|
711
729
|
<ModalHeaderIcon intent={intent}>
|
|
712
730
|
{intent === "default" ? (
|
|
713
|
-
<InfoIcon
|
|
731
|
+
<InfoIcon
|
|
732
|
+
className="size-[var(--bh-space-3xl-16)]"
|
|
733
|
+
strokeWidth={2}
|
|
734
|
+
/>
|
|
714
735
|
) : (
|
|
715
736
|
<TriangleAlertIcon
|
|
716
737
|
className="size-[var(--bh-space-3xl-16)]"
|
|
@@ -719,31 +740,43 @@ function ConfirmModal({
|
|
|
719
740
|
)}
|
|
720
741
|
</ModalHeaderIcon>
|
|
721
742
|
) : null}
|
|
722
|
-
<
|
|
723
|
-
|
|
743
|
+
<AlertDialogTitle
|
|
744
|
+
data-slot="modal-title"
|
|
745
|
+
className={modalTitleClassName}
|
|
746
|
+
>
|
|
747
|
+
{resolvedTitle}
|
|
748
|
+
</AlertDialogTitle>
|
|
749
|
+
{showCloseButton ? <ConfirmModalCloseButton /> : null}
|
|
724
750
|
</ModalHeader>
|
|
725
751
|
<ModalBody>
|
|
726
|
-
{children ??
|
|
752
|
+
{children ?? (
|
|
753
|
+
<AlertDialogDescription
|
|
754
|
+
data-slot="modal-description"
|
|
755
|
+
className={modalDescriptionClassName}
|
|
756
|
+
>
|
|
757
|
+
{resolvedDescription}
|
|
758
|
+
</AlertDialogDescription>
|
|
759
|
+
)}
|
|
727
760
|
</ModalBody>
|
|
728
761
|
{showDivider ? <ModalDivider /> : null}
|
|
729
762
|
{showFooter ? (
|
|
730
763
|
<ModalFooter>
|
|
731
764
|
<ModalActions>
|
|
732
765
|
{cancelAction && closeOnCancel ? (
|
|
733
|
-
<
|
|
766
|
+
<AlertDialogCancel asChild>{cancelAction}</AlertDialogCancel>
|
|
734
767
|
) : (
|
|
735
768
|
cancelAction
|
|
736
769
|
)}
|
|
737
770
|
{closeOnConfirm ? (
|
|
738
|
-
<
|
|
771
|
+
<AlertDialogAction asChild>{confirmAction}</AlertDialogAction>
|
|
739
772
|
) : (
|
|
740
773
|
confirmAction
|
|
741
774
|
)}
|
|
742
775
|
</ModalActions>
|
|
743
776
|
</ModalFooter>
|
|
744
777
|
) : null}
|
|
745
|
-
</
|
|
746
|
-
</
|
|
778
|
+
</AlertDialogContent>
|
|
779
|
+
</AlertDialog>
|
|
747
780
|
)
|
|
748
781
|
}
|
|
749
782
|
|