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
|
@@ -2,6 +2,7 @@ import * as React from "react"
|
|
|
2
2
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
3
|
import { Building2Icon, CreditCardIcon, UserIcon } from "lucide-react"
|
|
4
4
|
|
|
5
|
+
import { useResolvedDirection, type Direction } from "@/hooks/use-direction"
|
|
5
6
|
import { cn } from "@/lib/utils"
|
|
6
7
|
|
|
7
8
|
type RadioCardType =
|
|
@@ -14,7 +15,7 @@ type RadioCardType =
|
|
|
14
15
|
| "radio-label"
|
|
15
16
|
|
|
16
17
|
type RadioCardState = "default" | "active" | "disabled"
|
|
17
|
-
type RadioCardDirection =
|
|
18
|
+
type RadioCardDirection = Direction
|
|
18
19
|
|
|
19
20
|
const radioCardVariants = cva(
|
|
20
21
|
[
|
|
@@ -69,91 +70,119 @@ type RadioCardProps = Omit<
|
|
|
69
70
|
inputProps?: Omit<React.ComponentProps<"input">, "type">
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
73
|
+
const RadioCard = React.forwardRef<HTMLLabelElement, RadioCardProps>(
|
|
74
|
+
function RadioCard(
|
|
75
|
+
{
|
|
76
|
+
className,
|
|
77
|
+
type = "with-icon",
|
|
78
|
+
state = "default",
|
|
79
|
+
direction,
|
|
80
|
+
dir,
|
|
81
|
+
checked,
|
|
82
|
+
disabled,
|
|
83
|
+
label,
|
|
84
|
+
description,
|
|
85
|
+
supportLabel,
|
|
86
|
+
supportDescription,
|
|
87
|
+
showDescription = true,
|
|
88
|
+
showSupportItems = true,
|
|
89
|
+
showSupportDescription = true,
|
|
90
|
+
icon,
|
|
91
|
+
media,
|
|
92
|
+
inputProps,
|
|
93
|
+
...props
|
|
94
|
+
},
|
|
95
|
+
forwardedRef
|
|
96
|
+
) {
|
|
97
|
+
const directionBoundaryRef = React.useRef<HTMLLabelElement | null>(null)
|
|
98
|
+
const explicitDirection =
|
|
99
|
+
direction ?? (dir === "ltr" || dir === "rtl" ? dir : undefined)
|
|
100
|
+
const resolvedDirection = useResolvedDirection(
|
|
101
|
+
explicitDirection,
|
|
102
|
+
directionBoundaryRef
|
|
103
|
+
)
|
|
104
|
+
const setDirectionBoundaryRef = React.useCallback(
|
|
105
|
+
(node: HTMLLabelElement | null) => {
|
|
106
|
+
directionBoundaryRef.current = node
|
|
107
|
+
|
|
108
|
+
if (typeof forwardedRef === "function") {
|
|
109
|
+
forwardedRef(node)
|
|
110
|
+
} else if (forwardedRef) {
|
|
111
|
+
forwardedRef.current = node
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
[forwardedRef]
|
|
115
|
+
)
|
|
116
|
+
const hasControlledChecked =
|
|
117
|
+
checked !== undefined || inputProps?.checked !== undefined
|
|
118
|
+
const controlledChecked = checked ?? inputProps?.checked
|
|
119
|
+
const inputChecked =
|
|
120
|
+
controlledChecked ?? Boolean(inputProps?.defaultChecked)
|
|
121
|
+
const inputReadOnly =
|
|
122
|
+
inputProps?.readOnly ??
|
|
123
|
+
(hasControlledChecked && inputProps?.onChange === undefined
|
|
124
|
+
? true
|
|
125
|
+
: undefined)
|
|
126
|
+
const isDisabled = disabled ?? inputProps?.disabled ?? state === "disabled"
|
|
127
|
+
const visualState: RadioCardState = isDisabled
|
|
128
|
+
? "disabled"
|
|
129
|
+
: inputChecked || state === "active"
|
|
130
|
+
? "active"
|
|
131
|
+
: state ?? "default"
|
|
132
|
+
const isRtl = resolvedDirection === "rtl"
|
|
133
|
+
const textLabel = label
|
|
134
|
+
const textDescription = description
|
|
110
135
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
<input
|
|
122
|
-
aria-label={typeof textLabel === "string" ? textLabel : undefined}
|
|
123
|
-
{...inputProps}
|
|
124
|
-
checked={hasControlledChecked ? controlledChecked : undefined}
|
|
125
|
-
className={cn("sr-only", inputProps?.className)}
|
|
126
|
-
defaultChecked={hasControlledChecked ? undefined : inputProps?.defaultChecked}
|
|
127
|
-
disabled={isDisabled}
|
|
128
|
-
readOnly={inputReadOnly}
|
|
129
|
-
type="radio"
|
|
130
|
-
/>
|
|
131
|
-
<span
|
|
132
|
-
data-slot="radio-card-layout"
|
|
133
|
-
className={cn(
|
|
134
|
-
"flex min-w-0 items-start [direction:ltr]",
|
|
135
|
-
type === "radio-label" && "items-center",
|
|
136
|
-
getCardGapClass(type, isRtl)
|
|
137
|
-
)}
|
|
136
|
+
return (
|
|
137
|
+
<label
|
|
138
|
+
data-slot="radio-card"
|
|
139
|
+
data-state={visualState}
|
|
140
|
+
data-type={type}
|
|
141
|
+
{...props}
|
|
142
|
+
ref={setDirectionBoundaryRef}
|
|
143
|
+
data-direction={resolvedDirection}
|
|
144
|
+
dir={resolvedDirection}
|
|
145
|
+
className={cn(radioCardVariants({ state: visualState }), className)}
|
|
138
146
|
>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
147
|
+
<input
|
|
148
|
+
aria-label={typeof textLabel === "string" ? textLabel : undefined}
|
|
149
|
+
{...inputProps}
|
|
150
|
+
checked={hasControlledChecked ? controlledChecked : undefined}
|
|
151
|
+
className={cn("sr-only", inputProps?.className)}
|
|
152
|
+
defaultChecked={
|
|
153
|
+
hasControlledChecked ? undefined : inputProps?.defaultChecked
|
|
154
|
+
}
|
|
155
|
+
disabled={isDisabled}
|
|
156
|
+
readOnly={inputReadOnly}
|
|
157
|
+
type="radio"
|
|
158
|
+
/>
|
|
159
|
+
<span
|
|
160
|
+
data-slot="radio-card-layout"
|
|
161
|
+
className={cn(
|
|
162
|
+
"flex min-w-0 items-start [direction:ltr]",
|
|
163
|
+
type === "radio-label" && "items-center",
|
|
164
|
+
getCardGapClass(type, isRtl)
|
|
165
|
+
)}
|
|
166
|
+
>
|
|
167
|
+
{renderRadioCardContent({
|
|
168
|
+
type,
|
|
169
|
+
direction: resolvedDirection,
|
|
170
|
+
state: visualState,
|
|
171
|
+
label: textLabel,
|
|
172
|
+
description: textDescription,
|
|
173
|
+
supportLabel,
|
|
174
|
+
supportDescription,
|
|
175
|
+
showDescription,
|
|
176
|
+
showSupportItems,
|
|
177
|
+
showSupportDescription,
|
|
178
|
+
icon,
|
|
179
|
+
media,
|
|
180
|
+
})}
|
|
181
|
+
</span>
|
|
182
|
+
</label>
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
)
|
|
157
186
|
|
|
158
187
|
function renderRadioCardContent({
|
|
159
188
|
type,
|
|
@@ -564,7 +593,7 @@ function RadioCardUserIcon() {
|
|
|
564
593
|
<UserIcon
|
|
565
594
|
aria-hidden="true"
|
|
566
595
|
className="size-[var(--bh-space-4xl-20)]"
|
|
567
|
-
strokeWidth=
|
|
596
|
+
strokeWidth="var(--bh-icon-stroke-200)"
|
|
568
597
|
/>
|
|
569
598
|
)
|
|
570
599
|
}
|
|
@@ -578,7 +607,7 @@ function RadioCardPaymentIcon() {
|
|
|
578
607
|
<CreditCardIcon
|
|
579
608
|
aria-hidden="true"
|
|
580
609
|
className="h-[var(--bh-radio-card-payment-logo-height)] w-[var(--bh-radio-card-payment-logo-width)]"
|
|
581
|
-
strokeWidth=
|
|
610
|
+
strokeWidth="var(--bh-icon-stroke-200)"
|
|
582
611
|
/>
|
|
583
612
|
</span>
|
|
584
613
|
)
|
|
@@ -610,7 +639,7 @@ function RadioCardCompanyIcon({ disabled }: { disabled: boolean }) {
|
|
|
610
639
|
<Building2Icon
|
|
611
640
|
aria-hidden="true"
|
|
612
641
|
className="size-[var(--bh-space-5xl-24)] text-[var(--bh-radio-card-company-mark-color)]"
|
|
613
|
-
strokeWidth=
|
|
642
|
+
strokeWidth="var(--bh-icon-stroke-180)"
|
|
614
643
|
/>
|
|
615
644
|
</span>
|
|
616
645
|
)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ButtonGroupLabel,
|
|
7
|
+
ToggleGroup,
|
|
8
|
+
ToggleGroupItem,
|
|
9
|
+
type ButtonGroupLabelProps,
|
|
10
|
+
type ControlDensity,
|
|
11
|
+
type ToggleGroupItemProps,
|
|
12
|
+
type ToggleGroupProps,
|
|
13
|
+
} from "@/components/ui/button-group"
|
|
14
|
+
|
|
15
|
+
type SegmentedControlProps = Omit<
|
|
16
|
+
ToggleGroupProps,
|
|
17
|
+
"itemWidth" | "mode"
|
|
18
|
+
> & {
|
|
19
|
+
"aria-label": string
|
|
20
|
+
density?: ControlDensity
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const SegmentedControl = React.forwardRef<
|
|
24
|
+
HTMLDivElement,
|
|
25
|
+
SegmentedControlProps
|
|
26
|
+
>(function SegmentedControl(
|
|
27
|
+
{ density = "default", type = "single", ...props },
|
|
28
|
+
ref
|
|
29
|
+
) {
|
|
30
|
+
return (
|
|
31
|
+
<ToggleGroup
|
|
32
|
+
data-slot="segmented-control"
|
|
33
|
+
density={density}
|
|
34
|
+
itemWidth="content"
|
|
35
|
+
mode="default"
|
|
36
|
+
ref={ref}
|
|
37
|
+
type={type}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
type SegmentedControlItemProps = ToggleGroupItemProps
|
|
44
|
+
|
|
45
|
+
const SegmentedControlItem = React.forwardRef<
|
|
46
|
+
HTMLButtonElement,
|
|
47
|
+
SegmentedControlItemProps
|
|
48
|
+
>(function SegmentedControlItem(props, ref) {
|
|
49
|
+
return (
|
|
50
|
+
<ToggleGroupItem
|
|
51
|
+
data-slot="segmented-control-item"
|
|
52
|
+
itemWidth="content"
|
|
53
|
+
ref={ref}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
type SegmentedControlLabelProps = Omit<
|
|
60
|
+
ButtonGroupLabelProps,
|
|
61
|
+
"itemWidth"
|
|
62
|
+
>
|
|
63
|
+
|
|
64
|
+
const SegmentedControlLabel = React.forwardRef<
|
|
65
|
+
HTMLSpanElement,
|
|
66
|
+
SegmentedControlLabelProps
|
|
67
|
+
>(function SegmentedControlLabel(props, ref) {
|
|
68
|
+
return (
|
|
69
|
+
<ButtonGroupLabel
|
|
70
|
+
data-slot="segmented-control-label"
|
|
71
|
+
itemWidth="content"
|
|
72
|
+
ref={ref}
|
|
73
|
+
{...props}
|
|
74
|
+
/>
|
|
75
|
+
)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
SegmentedControl,
|
|
80
|
+
SegmentedControlItem,
|
|
81
|
+
SegmentedControlLabel,
|
|
82
|
+
}
|
|
83
|
+
export type {
|
|
84
|
+
SegmentedControlItemProps,
|
|
85
|
+
SegmentedControlLabelProps,
|
|
86
|
+
SegmentedControlProps,
|
|
87
|
+
}
|
|
@@ -104,7 +104,7 @@ function SelectItemCompanyLogo({
|
|
|
104
104
|
aria-hidden="true"
|
|
105
105
|
className="size-[var(--bh-select-company-icon-size)]"
|
|
106
106
|
focusable="false"
|
|
107
|
-
strokeWidth=
|
|
107
|
+
strokeWidth="var(--bh-icon-stroke-220)"
|
|
108
108
|
/>
|
|
109
109
|
</span>
|
|
110
110
|
)
|
|
@@ -177,7 +177,7 @@ function SelectIcon({
|
|
|
177
177
|
"aria-hidden": true,
|
|
178
178
|
className: iconClassName,
|
|
179
179
|
focusable: false,
|
|
180
|
-
strokeWidth:
|
|
180
|
+
strokeWidth: "var(--bh-icon-stroke-200)",
|
|
181
181
|
} as const
|
|
182
182
|
|
|
183
183
|
if (name === "user") {
|
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
type SelectStatusTone,
|
|
17
17
|
} from "./select-content"
|
|
18
18
|
|
|
19
|
-
type
|
|
19
|
+
type ControlDensity = "compact" | "default" | "comfortable"
|
|
20
|
+
type SelectSize = "lg" | "md" | "comfortable"
|
|
20
21
|
type SelectVisualState = "default" | "filled" | "error" | "disabled"
|
|
21
22
|
type SelectVariant = "default" | "soft"
|
|
22
23
|
type SelectSelectionType = "default" | "checkbox"
|
|
@@ -39,6 +40,7 @@ const selectTrigger = cva(
|
|
|
39
40
|
{
|
|
40
41
|
variants: {
|
|
41
42
|
size: {
|
|
43
|
+
comfortable: "py-[var(--bh-select-trigger-padding-y-comfortable)]",
|
|
42
44
|
lg: "py-[var(--bh-select-trigger-padding-y-lg)]",
|
|
43
45
|
md: "py-[var(--bh-select-trigger-padding-y-md)]",
|
|
44
46
|
},
|
|
@@ -120,6 +122,7 @@ const SelectRadixItemContext = React.createContext(false)
|
|
|
120
122
|
type SelectProps = Omit<React.ComponentProps<"div">, "children" | "dir"> & {
|
|
121
123
|
children?: React.ReactNode
|
|
122
124
|
defaultSelectValue?: string
|
|
125
|
+
density?: ControlDensity
|
|
123
126
|
dir?: "ltr" | "rtl" | "auto"
|
|
124
127
|
errorMessage?: React.ReactNode
|
|
125
128
|
expandIcon?: React.ReactNode | false
|
|
@@ -133,7 +136,7 @@ type SelectProps = Omit<React.ComponentProps<"div">, "children" | "dir"> & {
|
|
|
133
136
|
isOptional?: boolean
|
|
134
137
|
isRequired?: boolean
|
|
135
138
|
label?: React.ReactNode
|
|
136
|
-
leadingIcon?: React.ReactNode
|
|
139
|
+
leadingIcon?: React.ReactNode | false
|
|
137
140
|
onOpenChange?: (open: boolean) => void
|
|
138
141
|
onTriggerClick?: React.MouseEventHandler<HTMLButtonElement>
|
|
139
142
|
onValueChange?: (value: string) => void
|
|
@@ -158,7 +161,7 @@ type SelectProps = Omit<React.ComponentProps<"div">, "children" | "dir"> & {
|
|
|
158
161
|
| "value"
|
|
159
162
|
| "variant"
|
|
160
163
|
>
|
|
161
|
-
trailingIcon?: React.ReactNode
|
|
164
|
+
trailingIcon?: React.ReactNode | false
|
|
162
165
|
value?: React.ReactNode
|
|
163
166
|
variant?: SelectVariant
|
|
164
167
|
}
|
|
@@ -167,6 +170,7 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>(function Select({
|
|
|
167
170
|
children,
|
|
168
171
|
className,
|
|
169
172
|
defaultSelectValue,
|
|
173
|
+
density,
|
|
170
174
|
dir,
|
|
171
175
|
errorMessage,
|
|
172
176
|
expandIcon,
|
|
@@ -174,8 +178,8 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>(function Select({
|
|
|
174
178
|
hasHelperText,
|
|
175
179
|
hasInformationIcon = false,
|
|
176
180
|
hasLabel,
|
|
177
|
-
hasLeadingIcon
|
|
178
|
-
hasTrailingIcon
|
|
181
|
+
hasLeadingIcon,
|
|
182
|
+
hasTrailingIcon,
|
|
179
183
|
helperText,
|
|
180
184
|
isOptional = false,
|
|
181
185
|
isRequired = false,
|
|
@@ -188,7 +192,7 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>(function Select({
|
|
|
188
192
|
optionalText,
|
|
189
193
|
placeholder,
|
|
190
194
|
selectValue,
|
|
191
|
-
size
|
|
195
|
+
size,
|
|
192
196
|
state = "default",
|
|
193
197
|
triggerClassName,
|
|
194
198
|
triggerId,
|
|
@@ -199,6 +203,7 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>(function Select({
|
|
|
199
203
|
...props
|
|
200
204
|
}, ref) {
|
|
201
205
|
const generatedId = React.useId()
|
|
206
|
+
const resolvedSize = resolveSelectSize(density, size)
|
|
202
207
|
const resolvedDir = dir
|
|
203
208
|
const triggerVisualState = triggerProps?.disabled ? "disabled" : state
|
|
204
209
|
const isError = triggerVisualState === "error"
|
|
@@ -210,6 +215,12 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>(function Select({
|
|
|
210
215
|
const shouldRenderLabel = hasLabel ?? hasRenderableContent(selectedLabel)
|
|
211
216
|
const shouldRenderHelperText =
|
|
212
217
|
hasHelperText ?? hasRenderableContent(selectedHelper)
|
|
218
|
+
const shouldShowLeadingIcon =
|
|
219
|
+
leadingIcon !== false &&
|
|
220
|
+
(hasLeadingIcon ?? hasRenderableContent(leadingIcon))
|
|
221
|
+
const shouldShowTrailingIcon =
|
|
222
|
+
trailingIcon !== false &&
|
|
223
|
+
(hasTrailingIcon ?? hasRenderableContent(trailingIcon))
|
|
213
224
|
const shouldRenderMenu = React.Children.count(children) > 0
|
|
214
225
|
const selectId = triggerId || generatedId
|
|
215
226
|
const helperId = `${selectId}-helper`
|
|
@@ -226,6 +237,8 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>(function Select({
|
|
|
226
237
|
{...rootOpenProps}
|
|
227
238
|
>
|
|
228
239
|
<SelectRoot
|
|
240
|
+
data-density={density}
|
|
241
|
+
data-size={resolvedSize}
|
|
229
242
|
data-state={triggerVisualState}
|
|
230
243
|
data-variant={variant}
|
|
231
244
|
dir={resolvedDir}
|
|
@@ -254,12 +267,20 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>(function Select({
|
|
|
254
267
|
aria-invalid={isError || undefined}
|
|
255
268
|
expandIcon={expandIcon}
|
|
256
269
|
id={selectId}
|
|
257
|
-
leadingIcon={
|
|
270
|
+
leadingIcon={
|
|
271
|
+
shouldShowLeadingIcon
|
|
272
|
+
? (leadingIcon ?? <SelectIcon name="user" />)
|
|
273
|
+
: false
|
|
274
|
+
}
|
|
258
275
|
onClick={onTriggerClick}
|
|
259
276
|
placeholder={selectedPlaceholder}
|
|
260
|
-
size={
|
|
277
|
+
size={resolvedSize}
|
|
261
278
|
state={triggerVisualState}
|
|
262
|
-
trailingIcon={
|
|
279
|
+
trailingIcon={
|
|
280
|
+
shouldShowTrailingIcon
|
|
281
|
+
? (trailingIcon ?? <SelectIcon name="info" />)
|
|
282
|
+
: false
|
|
283
|
+
}
|
|
263
284
|
value={selectedValue}
|
|
264
285
|
variant={variant}
|
|
265
286
|
className={triggerClassName}
|
|
@@ -464,6 +485,7 @@ type SelectTriggerProps = Omit<
|
|
|
464
485
|
"children" | "value"
|
|
465
486
|
> &
|
|
466
487
|
VariantProps<typeof selectTrigger> & {
|
|
488
|
+
density?: ControlDensity
|
|
467
489
|
expandIcon?: React.ReactNode | false
|
|
468
490
|
leadingIcon?: React.ReactNode | false
|
|
469
491
|
placeholder?: React.ReactNode
|
|
@@ -475,11 +497,12 @@ const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(
|
|
|
475
497
|
(
|
|
476
498
|
{
|
|
477
499
|
className,
|
|
500
|
+
density,
|
|
478
501
|
disabled,
|
|
479
502
|
expandIcon,
|
|
480
503
|
leadingIcon,
|
|
481
504
|
placeholder,
|
|
482
|
-
size
|
|
505
|
+
size,
|
|
483
506
|
state,
|
|
484
507
|
trailingIcon,
|
|
485
508
|
type = "button",
|
|
@@ -489,13 +512,15 @@ const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(
|
|
|
489
512
|
},
|
|
490
513
|
ref
|
|
491
514
|
) => {
|
|
515
|
+
const resolvedSize = resolveSelectSize(density, size)
|
|
492
516
|
const hasValue = value !== undefined && value !== null && value !== ""
|
|
493
517
|
const visualState = disabled ? "disabled" : state ?? (hasValue ? "filled" : "default")
|
|
494
518
|
const isDisabled = visualState === "disabled"
|
|
495
519
|
|
|
496
520
|
return (
|
|
497
521
|
<button
|
|
498
|
-
data-
|
|
522
|
+
data-density={density}
|
|
523
|
+
data-size={resolvedSize}
|
|
499
524
|
data-slot="select-trigger"
|
|
500
525
|
data-state={visualState}
|
|
501
526
|
data-variant={variant}
|
|
@@ -503,7 +528,7 @@ const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(
|
|
|
503
528
|
ref={ref}
|
|
504
529
|
type={type}
|
|
505
530
|
className={cn(
|
|
506
|
-
selectTrigger({ size, state: visualState, variant }),
|
|
531
|
+
selectTrigger({ size: resolvedSize, state: visualState, variant }),
|
|
507
532
|
className
|
|
508
533
|
)}
|
|
509
534
|
{...props}
|
|
@@ -512,12 +537,12 @@ const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(
|
|
|
512
537
|
data-slot="select-trigger-main"
|
|
513
538
|
className="flex min-w-0 flex-1 items-center gap-[var(--bh-select-content-gap)]"
|
|
514
539
|
>
|
|
515
|
-
{leadingIcon
|
|
540
|
+
{hasRenderableContent(leadingIcon) ? (
|
|
516
541
|
<span
|
|
517
542
|
data-slot="select-leading-icon"
|
|
518
543
|
className="flex size-[var(--bh-select-icon-slot-size)] shrink-0 items-center justify-center text-[var(--bh-select-trigger-icon-color)] group-data-[state=disabled]/select-trigger:text-[var(--bh-content-disabled)] [&_svg:not([class*='size-'])]:size-[var(--bh-select-icon-size)]"
|
|
519
544
|
>
|
|
520
|
-
{leadingIcon
|
|
545
|
+
{leadingIcon}
|
|
521
546
|
</span>
|
|
522
547
|
) : null}
|
|
523
548
|
|
|
@@ -541,12 +566,12 @@ const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(
|
|
|
541
566
|
</span>
|
|
542
567
|
</span>
|
|
543
568
|
|
|
544
|
-
{trailingIcon
|
|
569
|
+
{hasRenderableContent(trailingIcon) ? (
|
|
545
570
|
<span
|
|
546
571
|
data-slot="select-trailing-icon"
|
|
547
572
|
className="flex size-[var(--bh-select-icon-slot-size)] shrink-0 items-center justify-center text-[var(--bh-select-trigger-icon-color)] group-data-[state=disabled]/select-trigger:text-[var(--bh-content-disabled)] [&_svg:not([class*='size-'])]:size-[var(--bh-select-icon-size)]"
|
|
548
573
|
>
|
|
549
|
-
{trailingIcon
|
|
574
|
+
{trailingIcon}
|
|
550
575
|
</span>
|
|
551
576
|
) : null}
|
|
552
577
|
|
|
@@ -799,6 +824,16 @@ function getFocusableSelectItems(root: HTMLElement) {
|
|
|
799
824
|
).filter((item) => !item.hasAttribute("disabled"))
|
|
800
825
|
}
|
|
801
826
|
|
|
827
|
+
function resolveSelectSize(
|
|
828
|
+
density: ControlDensity | undefined,
|
|
829
|
+
size: SelectSize | null | undefined
|
|
830
|
+
): SelectSize {
|
|
831
|
+
if (density === "compact") return "md"
|
|
832
|
+
if (density === "default") return "lg"
|
|
833
|
+
if (density === "comfortable") return "comfortable"
|
|
834
|
+
return size ?? "lg"
|
|
835
|
+
}
|
|
836
|
+
|
|
802
837
|
type SelectCheckboxIndicatorProps = {
|
|
803
838
|
checked?: boolean
|
|
804
839
|
className?: string
|
|
@@ -860,6 +895,7 @@ export {
|
|
|
860
895
|
selectTrigger,
|
|
861
896
|
}
|
|
862
897
|
export type {
|
|
898
|
+
ControlDensity,
|
|
863
899
|
SelectItemType,
|
|
864
900
|
SelectMenuItemProps,
|
|
865
901
|
SelectProps,
|
|
@@ -265,7 +265,7 @@ const SidebarToggle = React.forwardRef<HTMLButtonElement, SidebarToggleProps>(
|
|
|
265
265
|
<PanelLeftIcon
|
|
266
266
|
aria-hidden="true"
|
|
267
267
|
className="size-[var(--bh-space-5xl-24)] rtl:-scale-x-100"
|
|
268
|
-
strokeWidth=
|
|
268
|
+
strokeWidth="var(--bh-icon-stroke-200)"
|
|
269
269
|
/>
|
|
270
270
|
)}
|
|
271
271
|
</button>
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
[data-slot="skeleton"] {
|
|
2
2
|
--bh-skeleton-bg: var(--bh-bg-muted);
|
|
3
3
|
--bh-skeleton-highlight: var(--bh-bg-raised-subtle);
|
|
4
|
-
--bh-skeleton-duration: 1.4s;
|
|
5
4
|
--bh-skeleton-radius: var(--bh-radius-md-6);
|
|
6
|
-
--bh-skeleton-shimmer-width: 62%;
|
|
7
|
-
--bh-skeleton-width: 100%;
|
|
8
5
|
--bh-skeleton-height: var(--bh-space-4xl-20);
|
|
9
6
|
}
|
|
10
7
|
|