@squadbase/vantage 0.6.2-dev1.b332e5a → 0.6.2-dev1.d7c0911
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/dist/add-4GHF2TX2.js +6 -0
- package/dist/add-4GHF2TX2.js.map +1 -0
- package/dist/{build-TVKFIVFQ.js → build-X5NVCQKT.js} +7 -7
- package/dist/{build-TVKFIVFQ.js.map → build-X5NVCQKT.js.map} +1 -1
- package/dist/{check-3KHZXZMQ.js → check-ZBIH422T.js} +5 -5
- package/dist/{check-3KHZXZMQ.js.map → check-ZBIH422T.js.map} +1 -1
- package/dist/chunk-2ICNHUG6.js +1820 -0
- package/dist/chunk-2ICNHUG6.js.map +1 -0
- package/dist/{chunk-5ZOP4SQR.js → chunk-2N72FKLB.js} +12 -7
- package/dist/chunk-2N72FKLB.js.map +1 -0
- package/dist/{chunk-P7W4LR3Z.js → chunk-7DZGJQ3P.js} +3 -3
- package/dist/{chunk-P7W4LR3Z.js.map → chunk-7DZGJQ3P.js.map} +1 -1
- package/dist/{chunk-U2M6HGKQ.js → chunk-AABMKHEU.js} +4 -4
- package/dist/{chunk-U2M6HGKQ.js.map → chunk-AABMKHEU.js.map} +1 -1
- package/dist/{chunk-QI3XQKHS.js → chunk-GNXCX4WE.js} +10 -3
- package/dist/chunk-GNXCX4WE.js.map +1 -0
- package/dist/{chunk-PXRX5PEC.js → chunk-PDOBHMUQ.js} +3 -3
- package/dist/chunk-PDOBHMUQ.js.map +1 -0
- package/dist/{chunk-ZVANIULZ.js → chunk-RNTDBX6S.js} +4 -4
- package/dist/{chunk-ZVANIULZ.js.map → chunk-RNTDBX6S.js.map} +1 -1
- package/dist/{chunk-A2UUGASH.js → chunk-U736PVHY.js} +2 -2
- package/dist/chunk-U736PVHY.js.map +1 -0
- package/dist/{chunk-PVTHHV7X.js → chunk-V3LF7BE7.js} +27 -5
- package/dist/chunk-V3LF7BE7.js.map +1 -0
- package/dist/{chunk-LMUACBMA.js → chunk-WAMZWZJB.js} +53 -8
- package/dist/chunk-WAMZWZJB.js.map +1 -0
- package/dist/chunk-WRSX2MDK.js +7866 -0
- package/dist/chunk-WRSX2MDK.js.map +1 -0
- package/dist/{chunk-RPZAALCX.js → chunk-XPQSTZUU.js} +254 -164
- package/dist/chunk-XPQSTZUU.js.map +1 -0
- package/dist/{chunk-DTDVSFRY.js → chunk-XQUSGIDG.js} +17 -3
- package/dist/chunk-XQUSGIDG.js.map +1 -0
- package/dist/cli.js +12 -11
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts +32 -3
- package/dist/client/index.js +205 -12
- package/dist/client/index.js.map +1 -1
- package/dist/components/index.d.ts +1975 -28
- package/dist/components/index.js +4 -4
- package/dist/{dev-GDKATCC7.js → dev-4XEDTELV.js} +8 -8
- package/dist/dev-4XEDTELV.js.map +1 -0
- package/dist/doc/index.js +2 -2
- package/dist/doc/index.js.map +1 -1
- package/dist/{docs-EJJ3BECT.js → docs-JVP4RPKT.js} +3 -3
- package/dist/{docs-EJJ3BECT.js.map → docs-JVP4RPKT.js.map} +1 -1
- package/dist/{doctor-WQXPXP6K.js → doctor-5E2VEZPK.js} +5 -5
- package/dist/{doctor-WQXPXP6K.js.map → doctor-5E2VEZPK.js.map} +1 -1
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/index.js.map +1 -1
- package/dist/{preview-OGMCNQUO.js → preview-T6CLSQVX.js} +3 -3
- package/dist/{preview-OGMCNQUO.js.map → preview-T6CLSQVX.js.map} +1 -1
- package/dist/query/index.d.ts +0 -11
- package/dist/query/index.js +2 -2
- package/dist/{routes-MWBWWOJ2.js → routes-3SGAFDMC.js} +4 -4
- package/dist/{routes-MWBWWOJ2.js.map → routes-3SGAFDMC.js.map} +1 -1
- package/dist/{search-6Y422SV6.js → search-5LC4XPB5.js} +3 -3
- package/dist/{search-6Y422SV6.js.map → search-5LC4XPB5.js.map} +1 -1
- package/dist/table/index.js +10 -9
- package/dist/table/index.js.map +1 -1
- package/dist/ui/index.d.ts +144 -11
- package/dist/ui/index.js +1339 -87
- package/dist/ui/index.js.map +1 -1
- package/dist/{upgrade-HCANX4GQ.js → upgrade-JHXZBGQS.js} +6 -6
- package/dist/{upgrade-HCANX4GQ.js.map → upgrade-JHXZBGQS.js.map} +1 -1
- package/dist/vite/index.d.ts +10 -0
- package/dist/vite/index.js +3 -3
- package/docs/en/components.md +29 -15
- package/docs/en/parts/data-table.md +22 -0
- package/docs/en/parts/delta.md +50 -0
- package/docs/en/parts/format.md +43 -0
- package/docs/en/parts/kpi-card.md +57 -0
- package/docs/en/parts/metric-value.md +3 -2
- package/docs/en/parts/sparkline.md +1 -1
- package/docs/en/parts/trend-indicator.md +17 -1
- package/docs/en/ui-and-theming.md +1 -1
- package/docs/index.json +366 -76
- package/docs/ja/changelog.md +31 -0
- package/docs/ja/components.md +57 -101
- package/docs/ja/page-types/csv.md +83 -0
- package/docs/ja/page-types/doc.md +83 -0
- package/docs/ja/page-types/excel.md +82 -0
- package/docs/ja/page-types/slide.md +132 -0
- package/docs/ja/page-types.md +47 -0
- package/docs/ja/parts/area-chart.md +61 -0
- package/docs/ja/parts/bar-chart.md +69 -0
- package/docs/ja/parts/bar-list.md +35 -0
- package/docs/ja/parts/category-bar.md +36 -0
- package/docs/ja/parts/data-table.md +22 -0
- package/docs/ja/parts/delta.md +50 -0
- package/docs/ja/parts/donut-chart.md +47 -0
- package/docs/ja/parts/echart.md +3 -0
- package/docs/ja/parts/format.md +44 -0
- package/docs/ja/parts/kpi-card.md +55 -0
- package/docs/ja/parts/line-chart.md +58 -0
- package/docs/ja/parts/metric-value.md +3 -2
- package/docs/ja/parts/progress-circle.md +34 -0
- package/docs/ja/parts/sparkline.md +2 -2
- package/docs/ja/parts/tracker.md +32 -0
- package/docs/ja/parts/trend-indicator.md +17 -1
- package/docs/ja/routing.md +8 -86
- package/docs/ja/ui/alert-dialog.md +41 -0
- package/docs/ja/ui/avatar.md +31 -0
- package/docs/ja/ui/combobox.md +74 -0
- package/docs/ja/ui/drawer.md +41 -0
- package/docs/ja/ui/field.md +42 -0
- package/docs/ja/ui/hover-card.md +21 -0
- package/docs/ja/ui/kbd.md +16 -0
- package/docs/ja/ui/pagination.md +36 -0
- package/docs/ja/ui/radio-group.md +21 -0
- package/docs/ja/ui/toast.md +46 -0
- package/docs/ja/ui-and-theming.md +14 -7
- package/package.json +13 -4
- package/registry/ui/accordion.tsx +76 -0
- package/registry/ui/alert-dialog.tsx +189 -0
- package/registry/ui/alert.tsx +80 -0
- package/registry/ui/app-shell.tsx +287 -0
- package/registry/ui/area-chart.tsx +3639 -0
- package/registry/ui/avatar.tsx +110 -0
- package/registry/ui/badge.tsx +56 -0
- package/registry/ui/bar-chart.tsx +3636 -0
- package/registry/ui/bar-list.tsx +3680 -0
- package/registry/ui/breadcrumb.tsx +128 -0
- package/registry/ui/button.tsx +62 -0
- package/registry/ui/calendar.tsx +223 -0
- package/registry/ui/card.tsx +107 -0
- package/registry/ui/category-bar.tsx +1255 -0
- package/registry/ui/chart-frame.tsx +1358 -0
- package/registry/ui/checkbox.tsx +30 -0
- package/registry/ui/collapsible.tsx +23 -0
- package/registry/ui/combobox.tsx +310 -0
- package/registry/ui/command.tsx +198 -0
- package/registry/ui/dashboard-card.tsx +217 -0
- package/registry/ui/data-table.tsx +693 -146
- package/registry/ui/date-range-picker.tsx +390 -0
- package/registry/ui/delta.tsx +188 -0
- package/registry/ui/dialog.tsx +161 -0
- package/registry/ui/donut-chart.tsx +3688 -0
- package/registry/ui/drawer.tsx +229 -0
- package/registry/ui/dropdown-menu.tsx +274 -0
- package/registry/ui/echart.tsx +890 -0
- package/registry/ui/field.tsx +240 -0
- package/registry/ui/filter-bar.tsx +392 -0
- package/registry/ui/funnel-steps.tsx +3541 -0
- package/registry/ui/heatmap.tsx +1752 -0
- package/registry/ui/hover-card.tsx +52 -0
- package/registry/ui/input-group.tsx +160 -0
- package/registry/ui/input.tsx +24 -0
- package/registry/ui/kbd.tsx +30 -0
- package/registry/ui/kpi-card.tsx +677 -0
- package/registry/ui/label.tsx +22 -0
- package/registry/ui/legend.tsx +3500 -0
- package/registry/ui/line-chart.tsx +3637 -0
- package/registry/ui/metric-value.tsx +62 -0
- package/registry/ui/multi-select.tsx +232 -0
- package/registry/ui/page-shell.tsx +282 -0
- package/registry/ui/pagination.tsx +140 -0
- package/registry/ui/placeholder.tsx +36 -0
- package/registry/ui/popover.tsx +92 -0
- package/registry/ui/progress-circle.tsx +867 -0
- package/registry/ui/progress.tsx +85 -0
- package/registry/ui/radio-group.tsx +39 -0
- package/registry/ui/sample-data.tsx +86 -0
- package/registry/ui/scatter-chart.tsx +4150 -0
- package/registry/ui/scroll-area.tsx +56 -0
- package/registry/ui/searchable-select.tsx +214 -0
- package/registry/ui/section-header.tsx +43 -0
- package/registry/ui/segmented-control.tsx +76 -0
- package/registry/ui/select.tsx +255 -0
- package/registry/ui/separator.tsx +27 -0
- package/registry/ui/sheet.tsx +139 -0
- package/registry/ui/sidebar.tsx +725 -0
- package/registry/ui/skeleton.tsx +17 -0
- package/registry/ui/slider.tsx +56 -0
- package/registry/ui/sparkline.tsx +230 -0
- package/registry/ui/spinner.tsx +14 -0
- package/registry/ui/states.tsx +90 -0
- package/registry/ui/status-badge.tsx +121 -0
- package/registry/ui/switch.tsx +34 -0
- package/registry/ui/table.tsx +118 -0
- package/registry/ui/tabs.tsx +84 -0
- package/registry/ui/textarea.tsx +22 -0
- package/registry/ui/toast.tsx +250 -0
- package/registry/ui/toggle-group.tsx +91 -0
- package/registry/ui/toggle.tsx +47 -0
- package/registry/ui/tooltip.tsx +68 -0
- package/registry/ui/tracker.tsx +843 -0
- package/registry/ui/trend-indicator.tsx +74 -0
- package/registry/ui/updated-at.tsx +122 -0
- package/registry/ui/waterfall-chart.tsx +4186 -0
- package/skills/vantage-add-feature/SKILL.md +9 -7
- package/skills/vantage-pitfalls/SKILL.md +5 -1
- package/templates/AGENTS.md +22 -1
- package/templates/agents/csv.md +2 -1
- package/templates/agents/doc.md +4 -3
- package/templates/agents/page.md +20 -6
- package/templates/agents/xlsx.md +2 -1
- package/theme.css +237 -136
- package/dist/add-DY4AXANK.js +0 -6
- package/dist/add-DY4AXANK.js.map +0 -1
- package/dist/chunk-5ZOP4SQR.js.map +0 -1
- package/dist/chunk-A2UUGASH.js.map +0 -1
- package/dist/chunk-DTDVSFRY.js.map +0 -1
- package/dist/chunk-LMUACBMA.js.map +0 -1
- package/dist/chunk-NKFBFDRZ.js +0 -2241
- package/dist/chunk-NKFBFDRZ.js.map +0 -1
- package/dist/chunk-PVTHHV7X.js.map +0 -1
- package/dist/chunk-PXRX5PEC.js.map +0 -1
- package/dist/chunk-QI3XQKHS.js.map +0 -1
- package/dist/chunk-RPZAALCX.js.map +0 -1
- package/dist/chunk-VA776YE5.js +0 -316
- package/dist/chunk-VA776YE5.js.map +0 -1
- package/dist/dev-GDKATCC7.js.map +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Copied by `vantage add ui scroll-area`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/scroll-area.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
8
|
+
|
|
9
|
+
function ScrollArea({
|
|
10
|
+
className,
|
|
11
|
+
children,
|
|
12
|
+
...props
|
|
13
|
+
}: ScrollAreaPrimitive.Root.Props) {
|
|
14
|
+
return (
|
|
15
|
+
<ScrollAreaPrimitive.Root
|
|
16
|
+
data-slot="scroll-area"
|
|
17
|
+
className={cn("relative", className)}
|
|
18
|
+
{...props}
|
|
19
|
+
>
|
|
20
|
+
<ScrollAreaPrimitive.Viewport
|
|
21
|
+
data-slot="scroll-area-viewport"
|
|
22
|
+
className="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1"
|
|
23
|
+
>
|
|
24
|
+
{children}
|
|
25
|
+
</ScrollAreaPrimitive.Viewport>
|
|
26
|
+
<ScrollBar />
|
|
27
|
+
<ScrollAreaPrimitive.Corner />
|
|
28
|
+
</ScrollAreaPrimitive.Root>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function ScrollBar({
|
|
33
|
+
className,
|
|
34
|
+
orientation = "vertical",
|
|
35
|
+
...props
|
|
36
|
+
}: ScrollAreaPrimitive.Scrollbar.Props) {
|
|
37
|
+
return (
|
|
38
|
+
<ScrollAreaPrimitive.Scrollbar
|
|
39
|
+
data-slot="scroll-area-scrollbar"
|
|
40
|
+
data-orientation={orientation}
|
|
41
|
+
orientation={orientation}
|
|
42
|
+
className={cn(
|
|
43
|
+
"flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",
|
|
44
|
+
className
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
<ScrollAreaPrimitive.Thumb
|
|
49
|
+
data-slot="scroll-area-thumb"
|
|
50
|
+
className="relative flex-1 rounded-full bg-border"
|
|
51
|
+
/>
|
|
52
|
+
</ScrollAreaPrimitive.Scrollbar>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { ScrollArea, ScrollBar }
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Copied by `vantage add ui searchable-select`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/searchable-select.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SearchableSelect — a single-select combobox with a filter box. Filtering runs
|
|
7
|
+
* client-side over the given options; pass `onSearch` to take it over yourself
|
|
8
|
+
* (server-side search), which turns the built-in filter off.
|
|
9
|
+
*/
|
|
10
|
+
import { forwardRef, useMemo, useState } from "react"
|
|
11
|
+
import { ChevronDownIcon } from "lucide-react"
|
|
12
|
+
|
|
13
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
14
|
+
import { Button } from "@squadbase/vantage/ui"
|
|
15
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@squadbase/vantage/ui"
|
|
16
|
+
import { flattenOptions, type SelectOptions } from "@squadbase/vantage/components"
|
|
17
|
+
import type { KeyboardEvent, MouseEvent } from "react"
|
|
18
|
+
import { CheckIcon, LoaderIcon, XIcon } from "lucide-react"
|
|
19
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@squadbase/vantage/ui"
|
|
20
|
+
import { isGroupedOptions, type SelectOption } from "@squadbase/vantage/components"
|
|
21
|
+
|
|
22
|
+
/* ---------- inlined from @squadbase/squadkit registry/components/option-command.tsx (internal to @squadbase/vantage) ---------- */
|
|
23
|
+
|
|
24
|
+
interface OptionCommandListProps {
|
|
25
|
+
options: SelectOptions
|
|
26
|
+
/** Whether the given option value is currently selected (drives the check). */
|
|
27
|
+
isSelected: (value: string) => boolean
|
|
28
|
+
onSelect: (value: string) => void
|
|
29
|
+
/** Take filtering over yourself (server-side search); turns off built-in filter. */
|
|
30
|
+
onSearch?: (query: string) => void
|
|
31
|
+
isLoading: boolean
|
|
32
|
+
searchPlaceholder: string
|
|
33
|
+
emptyText: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The searchable list body — flat or grouped, with loading and empty states. */
|
|
37
|
+
function OptionCommandList({
|
|
38
|
+
options,
|
|
39
|
+
isSelected,
|
|
40
|
+
onSelect,
|
|
41
|
+
onSearch,
|
|
42
|
+
isLoading,
|
|
43
|
+
searchPlaceholder,
|
|
44
|
+
emptyText,
|
|
45
|
+
}: OptionCommandListProps) {
|
|
46
|
+
const renderOptions = (items: SelectOption[]) =>
|
|
47
|
+
items.map((option) => (
|
|
48
|
+
<CommandItem
|
|
49
|
+
key={option.value}
|
|
50
|
+
value={option.value}
|
|
51
|
+
keywords={[option.label]}
|
|
52
|
+
disabled={option.disabled}
|
|
53
|
+
onSelect={onSelect}
|
|
54
|
+
>
|
|
55
|
+
{option.icon && <option.icon className="size-4 shrink-0" />}
|
|
56
|
+
<span className="flex-1 truncate">
|
|
57
|
+
{option.label}
|
|
58
|
+
{option.description && (
|
|
59
|
+
<span className="ml-2 text-xs text-muted-foreground">{option.description}</span>
|
|
60
|
+
)}
|
|
61
|
+
</span>
|
|
62
|
+
<CheckIcon
|
|
63
|
+
className={cn("size-4 shrink-0", isSelected(option.value) ? "opacity-100" : "opacity-0")}
|
|
64
|
+
/>
|
|
65
|
+
</CommandItem>
|
|
66
|
+
))
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Command shouldFilter={!onSearch}>
|
|
70
|
+
<CommandInput placeholder={searchPlaceholder} onValueChange={onSearch} />
|
|
71
|
+
<CommandList>
|
|
72
|
+
{isLoading ? (
|
|
73
|
+
<div className="flex items-center justify-center py-6">
|
|
74
|
+
<LoaderIcon className="size-4 animate-spin text-muted-foreground" />
|
|
75
|
+
</div>
|
|
76
|
+
) : (
|
|
77
|
+
<>
|
|
78
|
+
<CommandEmpty>{emptyText}</CommandEmpty>
|
|
79
|
+
{isGroupedOptions(options)
|
|
80
|
+
? options.map((group) => (
|
|
81
|
+
<CommandGroup key={group.label} heading={group.label}>
|
|
82
|
+
{renderOptions(group.options)}
|
|
83
|
+
</CommandGroup>
|
|
84
|
+
))
|
|
85
|
+
: renderOptions(options)}
|
|
86
|
+
</>
|
|
87
|
+
)}
|
|
88
|
+
</CommandList>
|
|
89
|
+
</Command>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface RemoveButtonProps {
|
|
94
|
+
label: string
|
|
95
|
+
/** Runs on click and on Enter/Space; propagation is stopped for you. */
|
|
96
|
+
onRemove: () => void
|
|
97
|
+
/** Override the X icon size (default `size-3.5`). */
|
|
98
|
+
iconClassName?: string
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The keyboard-accessible ×-affordance inside a badge or trigger. */
|
|
102
|
+
function RemoveButton({ label, onRemove, iconClassName }: RemoveButtonProps) {
|
|
103
|
+
const handle = (e: MouseEvent | KeyboardEvent) => {
|
|
104
|
+
e.stopPropagation()
|
|
105
|
+
onRemove()
|
|
106
|
+
}
|
|
107
|
+
return (
|
|
108
|
+
<span
|
|
109
|
+
role="button"
|
|
110
|
+
tabIndex={0}
|
|
111
|
+
aria-label={label}
|
|
112
|
+
className="rounded-sm opacity-50 hover:opacity-100 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none"
|
|
113
|
+
onClick={handle}
|
|
114
|
+
onKeyDown={(e) => {
|
|
115
|
+
if (e.key === "Enter" || e.key === " ") handle(e)
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<XIcon className={cn("size-3.5", iconClassName)} />
|
|
119
|
+
</span>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ---------- end of inlined code ---------- */
|
|
124
|
+
|
|
125
|
+
export interface SearchableSelectProps {
|
|
126
|
+
options: SelectOptions
|
|
127
|
+
value?: string
|
|
128
|
+
onChange?: (value: string | undefined) => void
|
|
129
|
+
onSearch?: (query: string) => void
|
|
130
|
+
placeholder?: string
|
|
131
|
+
searchPlaceholder?: string
|
|
132
|
+
emptyText?: string
|
|
133
|
+
isLoading?: boolean
|
|
134
|
+
disabled?: boolean
|
|
135
|
+
clearable?: boolean
|
|
136
|
+
className?: string
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Not given yet (a draft fills props in steps): render empty, keep the same value between renders. */
|
|
140
|
+
const NO_OPTIONS: never[] = []
|
|
141
|
+
|
|
142
|
+
export const SearchableSelect = forwardRef<HTMLDivElement, SearchableSelectProps>(
|
|
143
|
+
function SearchableSelect(
|
|
144
|
+
{
|
|
145
|
+
options = NO_OPTIONS,
|
|
146
|
+
value,
|
|
147
|
+
onChange,
|
|
148
|
+
onSearch,
|
|
149
|
+
placeholder = "選択してください",
|
|
150
|
+
searchPlaceholder = "検索...",
|
|
151
|
+
emptyText = "見つかりませんでした",
|
|
152
|
+
isLoading = false,
|
|
153
|
+
disabled = false,
|
|
154
|
+
clearable = true,
|
|
155
|
+
className,
|
|
156
|
+
},
|
|
157
|
+
ref,
|
|
158
|
+
) {
|
|
159
|
+
const [open, setOpen] = useState(false)
|
|
160
|
+
|
|
161
|
+
const allOptions = useMemo(() => flattenOptions(options), [options])
|
|
162
|
+
const selectedOption = useMemo(
|
|
163
|
+
() => allOptions.find((opt) => opt.value === value),
|
|
164
|
+
[allOptions, value],
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
function handleSelect(selectedValue: string) {
|
|
168
|
+
onChange?.(selectedValue === value ? undefined : selectedValue)
|
|
169
|
+
setOpen(false)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div ref={ref} data-slot="searchable-select">
|
|
174
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
175
|
+
<PopoverTrigger
|
|
176
|
+
render={
|
|
177
|
+
<Button
|
|
178
|
+
variant="outline"
|
|
179
|
+
disabled={disabled}
|
|
180
|
+
className={cn(
|
|
181
|
+
"w-full justify-between font-normal",
|
|
182
|
+
!selectedOption && "text-muted-foreground",
|
|
183
|
+
className,
|
|
184
|
+
)}
|
|
185
|
+
/>
|
|
186
|
+
}
|
|
187
|
+
role="combobox"
|
|
188
|
+
aria-expanded={open}
|
|
189
|
+
>
|
|
190
|
+
<span className="truncate">{selectedOption ? selectedOption.label : placeholder}</span>
|
|
191
|
+
<span className="flex shrink-0 items-center gap-1">
|
|
192
|
+
{clearable && value && (
|
|
193
|
+
<RemoveButton label="クリア" onRemove={() => onChange?.(undefined)} />
|
|
194
|
+
)}
|
|
195
|
+
<ChevronDownIcon className="size-4 opacity-50" />
|
|
196
|
+
</span>
|
|
197
|
+
</PopoverTrigger>
|
|
198
|
+
<PopoverContent className="w-(--anchor-width) p-0" align="start">
|
|
199
|
+
<OptionCommandList
|
|
200
|
+
options={options}
|
|
201
|
+
isSelected={(v) => value === v}
|
|
202
|
+
onSelect={handleSelect}
|
|
203
|
+
onSearch={onSearch}
|
|
204
|
+
isLoading={isLoading}
|
|
205
|
+
searchPlaceholder={searchPlaceholder}
|
|
206
|
+
emptyText={emptyText}
|
|
207
|
+
/>
|
|
208
|
+
</PopoverContent>
|
|
209
|
+
</Popover>
|
|
210
|
+
</div>
|
|
211
|
+
)
|
|
212
|
+
},
|
|
213
|
+
)
|
|
214
|
+
SearchableSelect.displayName = "SearchableSelect"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copied by `vantage add ui section-header`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/section-header.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SectionHeader — a titled divider inside a page: heading, optional
|
|
7
|
+
* description, and right-aligned actions that wrap below on narrow screens.
|
|
8
|
+
*/
|
|
9
|
+
import { forwardRef, type ReactNode } from "react"
|
|
10
|
+
|
|
11
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
12
|
+
|
|
13
|
+
const headingStyles = {
|
|
14
|
+
h1: "text-3xl font-bold tracking-tight",
|
|
15
|
+
h2: "text-xl font-semibold tracking-tight",
|
|
16
|
+
h3: "text-xl font-semibold",
|
|
17
|
+
h4: "text-lg font-semibold",
|
|
18
|
+
} as const
|
|
19
|
+
|
|
20
|
+
export interface SectionHeaderProps {
|
|
21
|
+
title: string
|
|
22
|
+
description?: string
|
|
23
|
+
actions?: ReactNode
|
|
24
|
+
className?: string
|
|
25
|
+
as?: keyof typeof headingStyles
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const SectionHeader = forwardRef<HTMLDivElement, SectionHeaderProps>(
|
|
29
|
+
({ title, description, actions, className, as: Comp = "h2" }, ref) => (
|
|
30
|
+
<div
|
|
31
|
+
ref={ref}
|
|
32
|
+
data-slot="section-header"
|
|
33
|
+
className={cn("flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", className)}
|
|
34
|
+
>
|
|
35
|
+
<div>
|
|
36
|
+
<Comp className={headingStyles[Comp]}>{title}</Comp>
|
|
37
|
+
{description && <p className="mt-1 text-sm text-muted-foreground">{description}</p>}
|
|
38
|
+
</div>
|
|
39
|
+
{actions && <div className="shrink-0">{actions}</div>}
|
|
40
|
+
</div>
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
SectionHeader.displayName = "SectionHeader"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copied by `vantage add ui segmented-control`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/segmented-control.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SegmentedControl — a single-select row of buttons over `ToggleGroup`. Base
|
|
7
|
+
* UI's toggle group is multi-value by default, so this wrapper narrows it to
|
|
8
|
+
* one value and refuses to deselect the active segment.
|
|
9
|
+
*/
|
|
10
|
+
import { forwardRef } from "react"
|
|
11
|
+
|
|
12
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
13
|
+
import { ToggleGroup, ToggleGroupItem } from "@squadbase/vantage/ui"
|
|
14
|
+
import type { SegmentOption } from "@squadbase/vantage/components"
|
|
15
|
+
|
|
16
|
+
const iconSizes = {
|
|
17
|
+
sm: "size-3.5",
|
|
18
|
+
default: "size-4",
|
|
19
|
+
lg: "size-5",
|
|
20
|
+
} as const
|
|
21
|
+
|
|
22
|
+
export interface SegmentedControlProps {
|
|
23
|
+
options: SegmentOption[]
|
|
24
|
+
value: string
|
|
25
|
+
onChange: (value: string) => void
|
|
26
|
+
size?: keyof typeof iconSizes
|
|
27
|
+
fullWidth?: boolean
|
|
28
|
+
ariaLabel?: string
|
|
29
|
+
className?: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Not given yet (a draft fills props in steps): render empty, keep the same value between renders. */
|
|
33
|
+
const NO_OPTIONS: never[] = []
|
|
34
|
+
|
|
35
|
+
export const SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
36
|
+
function SegmentedControl(
|
|
37
|
+
{ options = NO_OPTIONS, value, onChange, size = "default", fullWidth = false, ariaLabel, className },
|
|
38
|
+
ref,
|
|
39
|
+
) {
|
|
40
|
+
return (
|
|
41
|
+
<ToggleGroup
|
|
42
|
+
ref={ref}
|
|
43
|
+
data-slot="segmented-control"
|
|
44
|
+
value={[value]}
|
|
45
|
+
onValueChange={(next) => {
|
|
46
|
+
// Base UI reports the full pressed set; keep the newly added segment
|
|
47
|
+
// and ignore the empty set so the control never loses its selection.
|
|
48
|
+
const picked = next.find((item) => item !== value) ?? next[0]
|
|
49
|
+
if (typeof picked === "string") onChange(picked)
|
|
50
|
+
}}
|
|
51
|
+
variant="outline"
|
|
52
|
+
size={size}
|
|
53
|
+
spacing={0}
|
|
54
|
+
aria-label={ariaLabel}
|
|
55
|
+
className={cn(fullWidth && "w-full", className)}
|
|
56
|
+
>
|
|
57
|
+
{options.map((option) => {
|
|
58
|
+
const Icon = option.icon
|
|
59
|
+
return (
|
|
60
|
+
<ToggleGroupItem
|
|
61
|
+
key={option.value}
|
|
62
|
+
value={option.value}
|
|
63
|
+
disabled={option.disabled}
|
|
64
|
+
aria-label={option.label}
|
|
65
|
+
className={cn(fullWidth && "flex-1")}
|
|
66
|
+
>
|
|
67
|
+
{Icon && <Icon className={iconSizes[size]} aria-hidden="true" />}
|
|
68
|
+
{option.label}
|
|
69
|
+
</ToggleGroupItem>
|
|
70
|
+
)
|
|
71
|
+
})}
|
|
72
|
+
</ToggleGroup>
|
|
73
|
+
)
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
SegmentedControl.displayName = "SegmentedControl"
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
// Copied by `vantage add ui select`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/select.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
import * as React from "react"
|
|
6
|
+
import { Select as SelectPrimitive } from "@base-ui/react/select"
|
|
7
|
+
|
|
8
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
9
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
10
|
+
|
|
11
|
+
type DerivedSelectItem = { label: React.ReactNode; value: unknown }
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Collect every reachable `SelectItem`'s `value` → children pair.
|
|
15
|
+
*
|
|
16
|
+
* Base UI's `Select.Value` renders the selected *value*, not the matching
|
|
17
|
+
* item's children — without `items` the trigger shows a raw `"kanto"` where the
|
|
18
|
+
* list says "関東". Deriving `items` from the children here means the ordinary
|
|
19
|
+
* case is right by default. The walk only sees `SelectItem` elements present in
|
|
20
|
+
* this tree, so options produced by an intermediate component still need
|
|
21
|
+
* `items` passed explicitly (an explicit `items` always wins).
|
|
22
|
+
*/
|
|
23
|
+
function collectSelectItems(
|
|
24
|
+
node: React.ReactNode,
|
|
25
|
+
into: DerivedSelectItem[] = [],
|
|
26
|
+
): DerivedSelectItem[] {
|
|
27
|
+
React.Children.forEach(node, (child) => {
|
|
28
|
+
if (!React.isValidElement(child)) return
|
|
29
|
+
const props = child.props as { value?: unknown; children?: React.ReactNode }
|
|
30
|
+
if (child.type === SelectItem) {
|
|
31
|
+
if (props.value !== undefined) into.push({ label: props.children, value: props.value })
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if (props.children !== undefined) collectSelectItems(props.children, into)
|
|
35
|
+
})
|
|
36
|
+
return into
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function Select<Value, Multiple extends boolean | undefined = false>({
|
|
40
|
+
items,
|
|
41
|
+
children,
|
|
42
|
+
...props
|
|
43
|
+
}: SelectPrimitive.Root.Props<Value, Multiple>) {
|
|
44
|
+
const derivedItems = React.useMemo(() => {
|
|
45
|
+
if (items) return items
|
|
46
|
+
const collected = collectSelectItems(children)
|
|
47
|
+
return collected.length > 0 ? collected : undefined
|
|
48
|
+
}, [items, children])
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<SelectPrimitive.Root<Value, Multiple> items={derivedItems} {...props}>
|
|
52
|
+
{children}
|
|
53
|
+
</SelectPrimitive.Root>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
|
|
58
|
+
return (
|
|
59
|
+
<SelectPrimitive.Group
|
|
60
|
+
data-slot="select-group"
|
|
61
|
+
className={cn("scroll-my-1 p-1", className)}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
|
|
68
|
+
return (
|
|
69
|
+
<SelectPrimitive.Value
|
|
70
|
+
data-slot="select-value"
|
|
71
|
+
className={cn("flex flex-1 text-left", className)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function SelectTrigger({
|
|
78
|
+
className,
|
|
79
|
+
size = "default",
|
|
80
|
+
children,
|
|
81
|
+
...props
|
|
82
|
+
}: SelectPrimitive.Trigger.Props & {
|
|
83
|
+
size?: "sm" | "default"
|
|
84
|
+
}) {
|
|
85
|
+
return (
|
|
86
|
+
<SelectPrimitive.Trigger
|
|
87
|
+
data-slot="select-trigger"
|
|
88
|
+
data-size={size}
|
|
89
|
+
className={cn(
|
|
90
|
+
"flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
91
|
+
className
|
|
92
|
+
)}
|
|
93
|
+
{...props}
|
|
94
|
+
>
|
|
95
|
+
{children}
|
|
96
|
+
<SelectPrimitive.Icon
|
|
97
|
+
render={
|
|
98
|
+
<ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
|
|
99
|
+
}
|
|
100
|
+
/>
|
|
101
|
+
</SelectPrimitive.Trigger>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function SelectContent({
|
|
106
|
+
className,
|
|
107
|
+
children,
|
|
108
|
+
side = "bottom",
|
|
109
|
+
sideOffset = 4,
|
|
110
|
+
align = "center",
|
|
111
|
+
alignOffset = 0,
|
|
112
|
+
alignItemWithTrigger = true,
|
|
113
|
+
...props
|
|
114
|
+
}: SelectPrimitive.Popup.Props &
|
|
115
|
+
Pick<
|
|
116
|
+
SelectPrimitive.Positioner.Props,
|
|
117
|
+
"align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
|
|
118
|
+
>) {
|
|
119
|
+
return (
|
|
120
|
+
<SelectPrimitive.Portal>
|
|
121
|
+
<SelectPrimitive.Positioner
|
|
122
|
+
side={side}
|
|
123
|
+
sideOffset={sideOffset}
|
|
124
|
+
align={align}
|
|
125
|
+
alignOffset={alignOffset}
|
|
126
|
+
alignItemWithTrigger={alignItemWithTrigger}
|
|
127
|
+
className="isolate z-50"
|
|
128
|
+
>
|
|
129
|
+
<SelectPrimitive.Popup
|
|
130
|
+
data-slot="select-content"
|
|
131
|
+
data-align-trigger={alignItemWithTrigger}
|
|
132
|
+
className={cn(
|
|
133
|
+
"cn-menu-target cn-menu-translucent relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in motion-reduce:animate-none! data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
134
|
+
className
|
|
135
|
+
)}
|
|
136
|
+
{...props}
|
|
137
|
+
>
|
|
138
|
+
<SelectScrollUpButton />
|
|
139
|
+
<SelectPrimitive.List>{children}</SelectPrimitive.List>
|
|
140
|
+
<SelectScrollDownButton />
|
|
141
|
+
</SelectPrimitive.Popup>
|
|
142
|
+
</SelectPrimitive.Positioner>
|
|
143
|
+
</SelectPrimitive.Portal>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function SelectLabel({
|
|
148
|
+
className,
|
|
149
|
+
...props
|
|
150
|
+
}: SelectPrimitive.GroupLabel.Props) {
|
|
151
|
+
return (
|
|
152
|
+
<SelectPrimitive.GroupLabel
|
|
153
|
+
data-slot="select-label"
|
|
154
|
+
className={cn("px-1.5 py-1 text-xs text-muted-foreground", className)}
|
|
155
|
+
{...props}
|
|
156
|
+
/>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function SelectItem({
|
|
161
|
+
className,
|
|
162
|
+
children,
|
|
163
|
+
...props
|
|
164
|
+
}: SelectPrimitive.Item.Props) {
|
|
165
|
+
return (
|
|
166
|
+
<SelectPrimitive.Item
|
|
167
|
+
data-slot="select-item"
|
|
168
|
+
className={cn(
|
|
169
|
+
"relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
170
|
+
className
|
|
171
|
+
)}
|
|
172
|
+
{...props}
|
|
173
|
+
>
|
|
174
|
+
{/*
|
|
175
|
+
`line-clamp-1` rather than `truncate`: the item's width is capped by the
|
|
176
|
+
popup (`--anchor-width`), and a label longer than that must stop before
|
|
177
|
+
the `pr-8` reserved for the check indicator. `text-overflow: ellipsis`
|
|
178
|
+
does not apply to a flex container's anonymous text, so it would clip
|
|
179
|
+
without an ellipsis; `-webkit-line-clamp` ellipsizes the text node.
|
|
180
|
+
*/}
|
|
181
|
+
<SelectPrimitive.ItemText className="min-w-0 flex-1 line-clamp-1">
|
|
182
|
+
{children}
|
|
183
|
+
</SelectPrimitive.ItemText>
|
|
184
|
+
<SelectPrimitive.ItemIndicator
|
|
185
|
+
render={
|
|
186
|
+
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
|
|
187
|
+
}
|
|
188
|
+
>
|
|
189
|
+
<CheckIcon className="pointer-events-none" />
|
|
190
|
+
</SelectPrimitive.ItemIndicator>
|
|
191
|
+
</SelectPrimitive.Item>
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function SelectSeparator({
|
|
196
|
+
className,
|
|
197
|
+
...props
|
|
198
|
+
}: SelectPrimitive.Separator.Props) {
|
|
199
|
+
return (
|
|
200
|
+
<SelectPrimitive.Separator
|
|
201
|
+
data-slot="select-separator"
|
|
202
|
+
className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
|
|
203
|
+
{...props}
|
|
204
|
+
/>
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function SelectScrollUpButton({
|
|
209
|
+
className,
|
|
210
|
+
...props
|
|
211
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {
|
|
212
|
+
return (
|
|
213
|
+
<SelectPrimitive.ScrollUpArrow
|
|
214
|
+
data-slot="select-scroll-up-button"
|
|
215
|
+
className={cn(
|
|
216
|
+
"top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
217
|
+
className
|
|
218
|
+
)}
|
|
219
|
+
{...props}
|
|
220
|
+
>
|
|
221
|
+
<ChevronUpIcon />
|
|
222
|
+
</SelectPrimitive.ScrollUpArrow>
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function SelectScrollDownButton({
|
|
227
|
+
className,
|
|
228
|
+
...props
|
|
229
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {
|
|
230
|
+
return (
|
|
231
|
+
<SelectPrimitive.ScrollDownArrow
|
|
232
|
+
data-slot="select-scroll-down-button"
|
|
233
|
+
className={cn(
|
|
234
|
+
"bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
235
|
+
className
|
|
236
|
+
)}
|
|
237
|
+
{...props}
|
|
238
|
+
>
|
|
239
|
+
<ChevronDownIcon />
|
|
240
|
+
</SelectPrimitive.ScrollDownArrow>
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export {
|
|
245
|
+
Select,
|
|
246
|
+
SelectContent,
|
|
247
|
+
SelectGroup,
|
|
248
|
+
SelectItem,
|
|
249
|
+
SelectLabel,
|
|
250
|
+
SelectScrollDownButton,
|
|
251
|
+
SelectScrollUpButton,
|
|
252
|
+
SelectSeparator,
|
|
253
|
+
SelectTrigger,
|
|
254
|
+
SelectValue,
|
|
255
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copied by `vantage add ui separator`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/ui/separator.tsx by `npm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
8
|
+
|
|
9
|
+
function Separator({
|
|
10
|
+
className,
|
|
11
|
+
orientation = "horizontal",
|
|
12
|
+
...props
|
|
13
|
+
}: SeparatorPrimitive.Props) {
|
|
14
|
+
return (
|
|
15
|
+
<SeparatorPrimitive
|
|
16
|
+
data-slot="separator"
|
|
17
|
+
orientation={orientation}
|
|
18
|
+
className={cn(
|
|
19
|
+
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { Separator }
|