@squadbase/vantage 0.6.1-dev2.5f947f1 → 0.6.2-dev1.31accb1
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-DY4AXANK.js +6 -0
- package/dist/add-DY4AXANK.js.map +1 -0
- package/dist/{build-O5TVNH4E.js → build-TVKFIVFQ.js} +8 -8
- package/dist/{build-O5TVNH4E.js.map → build-TVKFIVFQ.js.map} +1 -1
- package/dist/{check-WFBEDHDR.js → check-3KHZXZMQ.js} +6 -6
- package/dist/{check-WFBEDHDR.js.map → check-3KHZXZMQ.js.map} +1 -1
- package/dist/{chunk-LSRMRIXA.js → chunk-AG6RZ2RR.js} +1004 -23
- package/dist/chunk-AG6RZ2RR.js.map +1 -0
- package/dist/{chunk-KLEIVDUV.js → chunk-CEXAQQ5W.js} +150 -11
- package/dist/chunk-CEXAQQ5W.js.map +1 -0
- package/dist/{chunk-JGRMRXXZ.js → chunk-JKLLFVEU.js} +3 -3
- package/dist/{chunk-JGRMRXXZ.js.map → chunk-JKLLFVEU.js.map} +1 -1
- package/dist/{chunk-EP6JHXSR.js → chunk-LMUACBMA.js} +3 -3
- package/dist/{chunk-EP6JHXSR.js.map → chunk-LMUACBMA.js.map} +1 -1
- package/dist/{chunk-RPZAALCX.js → chunk-OB6UBJXF.js} +153 -153
- package/dist/{chunk-RPZAALCX.js.map → chunk-OB6UBJXF.js.map} +1 -1
- package/dist/{chunk-BCE22JSM.js → chunk-P7W4LR3Z.js} +32 -13
- package/dist/chunk-P7W4LR3Z.js.map +1 -0
- package/dist/{chunk-3G43C6OL.js → chunk-QI3XQKHS.js} +39 -3
- package/dist/chunk-QI3XQKHS.js.map +1 -0
- package/dist/{chunk-QDZA5JSL.js → chunk-U2M6HGKQ.js} +3 -3
- package/dist/{chunk-QDZA5JSL.js.map → chunk-U2M6HGKQ.js.map} +1 -1
- package/dist/{chunk-T3FLAGI6.js → chunk-VA776YE5.js} +3 -3
- package/dist/{chunk-T3FLAGI6.js.map → chunk-VA776YE5.js.map} +1 -1
- package/dist/cli.js +14 -11
- package/dist/cli.js.map +1 -1
- package/dist/components/index.d.ts +223 -1
- package/dist/components/index.js +2 -2
- package/dist/{dev-NZRLOQCL.js → dev-GDKATCC7.js} +22 -11
- package/dist/dev-GDKATCC7.js.map +1 -0
- package/dist/doc/index.js +2 -0
- package/dist/doc/index.js.map +1 -1
- package/dist/{docs-ZGDJUHJI.js → docs-EJJ3BECT.js} +3 -3
- package/dist/{docs-ZGDJUHJI.js.map → docs-EJJ3BECT.js.map} +1 -1
- package/dist/{doctor-VFKEMR54.js → doctor-WQXPXP6K.js} +7 -7
- package/dist/doctor-WQXPXP6K.js.map +1 -0
- package/dist/{preview-QDCIVVSR.js → preview-OGMCNQUO.js} +12 -4
- package/dist/preview-OGMCNQUO.js.map +1 -0
- package/dist/{routes-RHP5FVGD.js → routes-MWBWWOJ2.js} +5 -5
- package/dist/{routes-RHP5FVGD.js.map → routes-MWBWWOJ2.js.map} +1 -1
- package/dist/{search-RFBELGY7.js → search-6Y422SV6.js} +3 -3
- package/dist/{search-RFBELGY7.js.map → search-6Y422SV6.js.map} +1 -1
- package/dist/slide/index.js +61 -15
- package/dist/slide/index.js.map +1 -1
- package/dist/table/index.js +6 -5
- package/dist/table/index.js.map +1 -1
- package/dist/ui/index.d.ts +140 -10
- package/dist/ui/index.js +1405 -63
- package/dist/ui/index.js.map +1 -1
- package/dist/{upgrade-GF2P67M6.js → upgrade-HCANX4GQ.js} +6 -6
- package/dist/{upgrade-GF2P67M6.js.map → upgrade-HCANX4GQ.js.map} +1 -1
- package/dist/vite/index.js +3 -3
- package/docs/en/changelog.md +24 -0
- package/docs/en/cli-reference.md +30 -0
- package/docs/en/parts/page-shell.md +1 -1
- package/docs/index.json +291 -61
- package/docs/ja/changelog.md +50 -0
- package/docs/ja/cli-reference.md +29 -0
- package/docs/ja/components.md +33 -89
- 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/donut-chart.md +47 -0
- package/docs/ja/parts/echart.md +3 -0
- package/docs/ja/parts/line-chart.md +58 -0
- package/docs/ja/parts/page-shell.md +1 -1
- package/docs/ja/parts/progress-circle.md +34 -0
- package/docs/ja/parts/sparkline.md +1 -1
- package/docs/ja/parts/tracker.md +32 -0
- 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 +18 -12
- package/registry/ui/accordion.tsx +74 -0
- package/registry/ui/alert-dialog.tsx +189 -0
- package/registry/ui/alert.tsx +78 -0
- package/registry/ui/app-shell.tsx +281 -0
- package/registry/ui/area-chart.tsx +1015 -0
- package/registry/ui/avatar.tsx +110 -0
- package/registry/ui/badge.tsx +54 -0
- package/registry/ui/bar-chart.tsx +1013 -0
- package/registry/ui/bar-list.tsx +302 -0
- package/registry/ui/breadcrumb.tsx +126 -0
- package/registry/ui/button.tsx +60 -0
- package/registry/ui/calendar.tsx +221 -0
- package/registry/ui/card.tsx +105 -0
- package/registry/ui/category-bar.tsx +281 -0
- package/registry/ui/checkbox.tsx +28 -0
- package/registry/ui/collapsible.tsx +21 -0
- package/registry/ui/combobox.tsx +310 -0
- package/registry/ui/command.tsx +196 -0
- package/registry/ui/dashboard-card.tsx +174 -0
- package/registry/ui/data-table.tsx +16 -91
- package/registry/ui/date-range-picker.tsx +209 -0
- package/registry/ui/dialog.tsx +159 -0
- package/registry/ui/donut-chart.tsx +1004 -0
- package/registry/ui/drawer.tsx +229 -0
- package/registry/ui/dropdown-menu.tsx +272 -0
- package/registry/ui/echart.tsx +486 -0
- package/registry/ui/field.tsx +240 -0
- package/registry/ui/filter-bar.tsx +365 -0
- package/registry/ui/funnel-steps.tsx +274 -0
- package/registry/ui/hover-card.tsx +52 -0
- package/registry/ui/input-group.tsx +158 -0
- package/registry/ui/input.tsx +22 -0
- package/registry/ui/kbd.tsx +28 -0
- package/registry/ui/label.tsx +20 -0
- package/registry/ui/line-chart.tsx +1007 -0
- package/registry/ui/metric-value.tsx +54 -0
- package/registry/ui/multi-select.tsx +226 -0
- package/registry/ui/page-shell.tsx +227 -0
- package/registry/ui/pagination.tsx +138 -0
- package/registry/ui/placeholder.tsx +30 -0
- package/registry/ui/popover.tsx +90 -0
- package/registry/ui/progress-circle.tsx +272 -0
- package/registry/ui/progress.tsx +83 -0
- package/registry/ui/radio-group.tsx +39 -0
- package/registry/ui/scroll-area.tsx +55 -0
- package/registry/ui/searchable-select.tsx +209 -0
- package/registry/ui/section-header.tsx +41 -0
- package/registry/ui/segmented-control.tsx +71 -0
- package/registry/ui/select.tsx +253 -0
- package/registry/ui/separator.tsx +25 -0
- package/registry/ui/sheet.tsx +137 -0
- package/registry/ui/sidebar.tsx +723 -0
- package/registry/ui/skeleton.tsx +15 -0
- package/registry/ui/slider.tsx +54 -0
- package/registry/ui/sparkline.tsx +155 -0
- package/registry/ui/spinner.tsx +12 -0
- package/registry/ui/states.tsx +61 -0
- package/registry/ui/status-badge.tsx +79 -0
- package/registry/ui/switch.tsx +32 -0
- package/registry/ui/table.tsx +116 -0
- package/registry/ui/tabs.tsx +82 -0
- package/registry/ui/textarea.tsx +20 -0
- package/registry/ui/toast.tsx +250 -0
- package/registry/ui/toggle-group.tsx +89 -0
- package/registry/ui/toggle.tsx +45 -0
- package/registry/ui/tooltip.tsx +66 -0
- package/registry/ui/tracker.tsx +236 -0
- package/registry/ui/trend-indicator.tsx +62 -0
- package/skills/vantage-add-feature/SKILL.md +9 -7
- package/skills/vantage-design/SKILL.md +3 -1
- package/skills/vantage-design/references/format.md +1 -1
- package/skills/vantage-pitfalls/SKILL.md +5 -1
- package/skills/vantage-slide/SKILL.md +17 -0
- package/templates/AGENTS.md +10 -1
- package/templates/agents/api.md +29 -0
- package/templates/agents/csv.md +2 -1
- package/templates/agents/doc.md +4 -3
- package/templates/agents/page.md +22 -8
- package/templates/agents/slide.md +13 -1
- package/templates/agents/xlsx.md +2 -1
- package/theme.css +15 -1
- package/dist/add-EISGSZAH.js +0 -6
- package/dist/add-EISGSZAH.js.map +0 -1
- package/dist/chunk-3G43C6OL.js.map +0 -1
- package/dist/chunk-BCE22JSM.js.map +0 -1
- package/dist/chunk-KLEIVDUV.js.map +0 -1
- package/dist/chunk-LSRMRIXA.js.map +0 -1
- package/dist/dev-NZRLOQCL.js.map +0 -1
- package/dist/doctor-VFKEMR54.js.map +0 -1
- package/dist/preview-QDCIVVSR.js.map +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copied by `vantage add ui skeleton`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/skeleton.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
4
|
+
|
|
5
|
+
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="skeleton"
|
|
9
|
+
className={cn("animate-pulse rounded-md bg-muted", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { Skeleton }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Copied by `vantage add ui slider`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/slider.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import { Slider as SliderPrimitive } from "@base-ui/react/slider"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
6
|
+
|
|
7
|
+
function Slider({
|
|
8
|
+
className,
|
|
9
|
+
defaultValue,
|
|
10
|
+
value,
|
|
11
|
+
min = 0,
|
|
12
|
+
max = 100,
|
|
13
|
+
...props
|
|
14
|
+
}: SliderPrimitive.Root.Props) {
|
|
15
|
+
const _values = Array.isArray(value)
|
|
16
|
+
? value
|
|
17
|
+
: Array.isArray(defaultValue)
|
|
18
|
+
? defaultValue
|
|
19
|
+
: [min, max]
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<SliderPrimitive.Root
|
|
23
|
+
className={cn("data-horizontal:w-full data-vertical:h-full", className)}
|
|
24
|
+
data-slot="slider"
|
|
25
|
+
defaultValue={defaultValue}
|
|
26
|
+
value={value}
|
|
27
|
+
min={min}
|
|
28
|
+
max={max}
|
|
29
|
+
thumbAlignment="edge"
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
<SliderPrimitive.Control className="relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:min-h-40 data-vertical:w-auto data-vertical:flex-col">
|
|
33
|
+
<SliderPrimitive.Track
|
|
34
|
+
data-slot="slider-track"
|
|
35
|
+
className="relative grow overflow-hidden rounded-full bg-muted select-none data-horizontal:h-1 data-horizontal:w-full data-vertical:h-full data-vertical:w-1"
|
|
36
|
+
>
|
|
37
|
+
<SliderPrimitive.Indicator
|
|
38
|
+
data-slot="slider-range"
|
|
39
|
+
className="bg-primary select-none data-horizontal:h-full data-vertical:w-full"
|
|
40
|
+
/>
|
|
41
|
+
</SliderPrimitive.Track>
|
|
42
|
+
{Array.from({ length: _values.length }, (_, index) => (
|
|
43
|
+
<SliderPrimitive.Thumb
|
|
44
|
+
data-slot="slider-thumb"
|
|
45
|
+
key={index}
|
|
46
|
+
className="relative block size-3 shrink-0 rounded-full border border-ring bg-white ring-ring/50 transition-[color,box-shadow] select-none after:absolute after:-inset-2 hover:ring-3 focus-visible:ring-3 focus-visible:outline-hidden active:ring-3 disabled:pointer-events-none disabled:opacity-50"
|
|
47
|
+
/>
|
|
48
|
+
))}
|
|
49
|
+
</SliderPrimitive.Control>
|
|
50
|
+
</SliderPrimitive.Root>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { Slider }
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Copied by `vantage add ui sparkline`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/components/sparkline.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
/**
|
|
4
|
+
* Sparkline — an inline trend micro-chart. Deliberately *not* an `EChart`: a
|
|
5
|
+
* sparkline sits inside table cells and KPI tiles by the dozen, where one
|
|
6
|
+
* ECharts instance per cell would be wasteful. This renders a single stateless
|
|
7
|
+
* `<svg>` instead, so hundreds of them stay cheap.
|
|
8
|
+
*/
|
|
9
|
+
import { forwardRef, useEffect, useState, type SVGAttributes } from "react"
|
|
10
|
+
|
|
11
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
12
|
+
|
|
13
|
+
export type SparklineVariant = "line" | "bar"
|
|
14
|
+
|
|
15
|
+
export interface SparklineDataPoint {
|
|
16
|
+
value: number
|
|
17
|
+
label?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SparklineProps extends SVGAttributes<SVGSVGElement> {
|
|
21
|
+
data: SparklineDataPoint[]
|
|
22
|
+
variant?: SparklineVariant
|
|
23
|
+
height?: number
|
|
24
|
+
/** Tailwind text-colour class; drives both stroke and fill via `currentColor`. */
|
|
25
|
+
color?: string
|
|
26
|
+
area?: boolean
|
|
27
|
+
animate?: boolean
|
|
28
|
+
className?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const VB_WIDTH = 100
|
|
32
|
+
|
|
33
|
+
/** Map raw values onto SVG y-coordinates (inverted, padded). */
|
|
34
|
+
function normalizeData(values: number[], height: number, vPad = 2): number[] {
|
|
35
|
+
const min = Math.min(...values)
|
|
36
|
+
const max = Math.max(...values)
|
|
37
|
+
const range = max - min
|
|
38
|
+
const drawHeight = height - vPad * 2
|
|
39
|
+
if (range === 0) return values.map(() => vPad + drawHeight / 2)
|
|
40
|
+
return values.map((v) => height - vPad - ((v - min) / range) * drawHeight)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function buildLinePath(ys: number[]): string {
|
|
44
|
+
if (ys.length === 0) return ""
|
|
45
|
+
const step = ys.length > 1 ? VB_WIDTH / (ys.length - 1) : 0
|
|
46
|
+
return ys
|
|
47
|
+
.map((y, i) => `${i === 0 ? "M" : "L"}${(i * step).toFixed(2)},${y.toFixed(2)}`)
|
|
48
|
+
.join(" ")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function buildAreaPath(ys: number[], height: number): string {
|
|
52
|
+
if (ys.length === 0) return ""
|
|
53
|
+
const step = ys.length > 1 ? VB_WIDTH / (ys.length - 1) : 0
|
|
54
|
+
const lastX = ((ys.length - 1) * step).toFixed(2)
|
|
55
|
+
return `${buildLinePath(ys)} L${lastX},${height} L0,${height} Z`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface BarRect {
|
|
59
|
+
x: number
|
|
60
|
+
y: number
|
|
61
|
+
w: number
|
|
62
|
+
h: number
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function buildBarRects(ys: number[], height: number, gap = 1): BarRect[] {
|
|
66
|
+
const barW = Math.max(1, VB_WIDTH / ys.length - gap)
|
|
67
|
+
return ys.map((y, i) => ({ x: i * (barW + gap), y, w: barW, h: height - y }))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const Sparkline = forwardRef<SVGSVGElement, SparklineProps>(function Sparkline(
|
|
71
|
+
{
|
|
72
|
+
data,
|
|
73
|
+
variant = "line",
|
|
74
|
+
height = 40,
|
|
75
|
+
color = "text-chart-1",
|
|
76
|
+
area = false,
|
|
77
|
+
animate = false,
|
|
78
|
+
className,
|
|
79
|
+
...props
|
|
80
|
+
},
|
|
81
|
+
ref,
|
|
82
|
+
) {
|
|
83
|
+
const [mounted, setMounted] = useState(false)
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (animate) setMounted(true)
|
|
87
|
+
}, [animate])
|
|
88
|
+
|
|
89
|
+
if (data.length === 0) return null
|
|
90
|
+
|
|
91
|
+
const ys = normalizeData(
|
|
92
|
+
data.map((d) => d.value),
|
|
93
|
+
height,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<svg
|
|
98
|
+
ref={ref}
|
|
99
|
+
data-slot="sparkline"
|
|
100
|
+
viewBox={`0 0 ${VB_WIDTH} ${height}`}
|
|
101
|
+
preserveAspectRatio="none"
|
|
102
|
+
width="100%"
|
|
103
|
+
height={height}
|
|
104
|
+
aria-hidden="true"
|
|
105
|
+
className={cn("overflow-visible", className)}
|
|
106
|
+
{...props}
|
|
107
|
+
>
|
|
108
|
+
{variant === "line" && (
|
|
109
|
+
<>
|
|
110
|
+
{area && (
|
|
111
|
+
<path
|
|
112
|
+
d={buildAreaPath(ys, height)}
|
|
113
|
+
strokeWidth={0}
|
|
114
|
+
className={cn("fill-current opacity-15", color)}
|
|
115
|
+
/>
|
|
116
|
+
)}
|
|
117
|
+
<path
|
|
118
|
+
d={buildLinePath(ys)}
|
|
119
|
+
fill="none"
|
|
120
|
+
strokeWidth={1.5}
|
|
121
|
+
strokeLinecap="round"
|
|
122
|
+
strokeLinejoin="round"
|
|
123
|
+
vectorEffect="non-scaling-stroke"
|
|
124
|
+
pathLength={animate ? 1 : undefined}
|
|
125
|
+
strokeDasharray={animate ? 1 : undefined}
|
|
126
|
+
strokeDashoffset={animate ? (mounted ? 0 : 1) : undefined}
|
|
127
|
+
className={cn("stroke-current", color)}
|
|
128
|
+
style={animate ? { transition: "stroke-dashoffset 0.6s ease-in-out" } : undefined}
|
|
129
|
+
/>
|
|
130
|
+
</>
|
|
131
|
+
)}
|
|
132
|
+
|
|
133
|
+
{variant === "bar" &&
|
|
134
|
+
buildBarRects(ys, height).map((rect, i) => (
|
|
135
|
+
<rect
|
|
136
|
+
key={i}
|
|
137
|
+
x={rect.x}
|
|
138
|
+
y={animate ? (mounted ? rect.y : height) : rect.y}
|
|
139
|
+
width={rect.w}
|
|
140
|
+
height={animate ? (mounted ? rect.h : 0) : rect.h}
|
|
141
|
+
rx={0.5}
|
|
142
|
+
className={cn("fill-current", color)}
|
|
143
|
+
style={
|
|
144
|
+
animate
|
|
145
|
+
? {
|
|
146
|
+
transition: `height 0.4s ease-out ${i * 0.02}s, y 0.4s ease-out ${i * 0.02}s`,
|
|
147
|
+
}
|
|
148
|
+
: undefined
|
|
149
|
+
}
|
|
150
|
+
/>
|
|
151
|
+
))}
|
|
152
|
+
</svg>
|
|
153
|
+
)
|
|
154
|
+
})
|
|
155
|
+
Sparkline.displayName = "Sparkline"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copied by `vantage add ui spinner`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/spinner.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
4
|
+
import { Loader2Icon } from "lucide-react"
|
|
5
|
+
|
|
6
|
+
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
|
7
|
+
return (
|
|
8
|
+
<Loader2Icon data-slot="spinner" role="status" aria-label="Loading" className={cn("size-4 animate-spin", className)} {...props} />
|
|
9
|
+
)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { Spinner }
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Copied by `vantage add ui states`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/states.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import type { ReactNode } from "react"
|
|
4
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
5
|
+
|
|
6
|
+
export function Loading({ label = "Loading…", className }: { label?: string; className?: string }) {
|
|
7
|
+
return (
|
|
8
|
+
<div className={cn("flex min-h-[30vh] items-center justify-center", className)} role="status" aria-live="polite">
|
|
9
|
+
<div className="flex items-center gap-3 text-sm text-muted-foreground">
|
|
10
|
+
<span className="h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
|
|
11
|
+
{label}
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function Empty({
|
|
18
|
+
title = "Nothing here yet",
|
|
19
|
+
description,
|
|
20
|
+
icon,
|
|
21
|
+
action,
|
|
22
|
+
className,
|
|
23
|
+
}: {
|
|
24
|
+
title?: string
|
|
25
|
+
description?: string
|
|
26
|
+
icon?: ReactNode
|
|
27
|
+
action?: ReactNode
|
|
28
|
+
className?: string
|
|
29
|
+
}) {
|
|
30
|
+
return (
|
|
31
|
+
<div className={cn("flex flex-col items-center justify-center gap-2 p-10 text-center", className)}>
|
|
32
|
+
{icon ? <div className="text-3xl text-muted-foreground">{icon}</div> : null}
|
|
33
|
+
<p className="font-medium">{title}</p>
|
|
34
|
+
{description ? <p className="max-w-sm text-sm text-muted-foreground">{description}</p> : null}
|
|
35
|
+
{action ? <div className="mt-2">{action}</div> : null}
|
|
36
|
+
</div>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function ErrorState({
|
|
41
|
+
title = "Something went wrong",
|
|
42
|
+
message,
|
|
43
|
+
action,
|
|
44
|
+
className,
|
|
45
|
+
}: {
|
|
46
|
+
title?: string
|
|
47
|
+
message?: ReactNode
|
|
48
|
+
action?: ReactNode
|
|
49
|
+
className?: string
|
|
50
|
+
}) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
className={cn("rounded-xl border border-destructive/30 bg-destructive/5 p-6", className)}
|
|
54
|
+
role="alert"
|
|
55
|
+
>
|
|
56
|
+
<p className="font-semibold text-destructive">{title}</p>
|
|
57
|
+
{message ? <p className="mt-1 text-sm text-muted-foreground">{message}</p> : null}
|
|
58
|
+
{action ? <div className="mt-3">{action}</div> : null}
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copied by `vantage add ui status-badge`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/components/status-badge.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
/**
|
|
4
|
+
* StatusBadge — a dot-plus-label badge for row/record status. Statuses map to
|
|
5
|
+
* colours through `defaultColorMap`; pass `colorMap` to extend or override it.
|
|
6
|
+
*/
|
|
7
|
+
import { forwardRef } from "react"
|
|
8
|
+
|
|
9
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
10
|
+
import { Badge } from "@squadbase/vantage/ui"
|
|
11
|
+
|
|
12
|
+
const defaultColorMap: Record<string, string> = {
|
|
13
|
+
active: "green",
|
|
14
|
+
inactive: "gray",
|
|
15
|
+
warning: "yellow",
|
|
16
|
+
error: "red",
|
|
17
|
+
pending: "blue",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const colorStyles: Record<string, { dot: string; bg: string; text: string }> = {
|
|
21
|
+
green: {
|
|
22
|
+
dot: "bg-green-500",
|
|
23
|
+
bg: "bg-green-50 dark:bg-green-950",
|
|
24
|
+
text: "text-green-700 dark:text-green-300",
|
|
25
|
+
},
|
|
26
|
+
gray: {
|
|
27
|
+
dot: "bg-gray-500",
|
|
28
|
+
bg: "bg-gray-50 dark:bg-gray-950",
|
|
29
|
+
text: "text-gray-700 dark:text-gray-300",
|
|
30
|
+
},
|
|
31
|
+
yellow: {
|
|
32
|
+
dot: "bg-yellow-500",
|
|
33
|
+
bg: "bg-yellow-50 dark:bg-yellow-950",
|
|
34
|
+
text: "text-yellow-700 dark:text-yellow-300",
|
|
35
|
+
},
|
|
36
|
+
red: {
|
|
37
|
+
dot: "bg-red-500",
|
|
38
|
+
bg: "bg-red-50 dark:bg-red-950",
|
|
39
|
+
text: "text-red-700 dark:text-red-300",
|
|
40
|
+
},
|
|
41
|
+
blue: {
|
|
42
|
+
dot: "bg-blue-500",
|
|
43
|
+
bg: "bg-blue-50 dark:bg-blue-950",
|
|
44
|
+
text: "text-blue-700 dark:text-blue-300",
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const fallbackStyle = colorStyles.gray!
|
|
49
|
+
|
|
50
|
+
export interface StatusBadgeProps {
|
|
51
|
+
status: string
|
|
52
|
+
label?: string
|
|
53
|
+
colorMap?: Partial<Record<string, string>>
|
|
54
|
+
className?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const StatusBadge = forwardRef<HTMLSpanElement, StatusBadgeProps>(function StatusBadge(
|
|
58
|
+
{ status, label, colorMap, className },
|
|
59
|
+
ref,
|
|
60
|
+
) {
|
|
61
|
+
const mergedColorMap = { ...defaultColorMap, ...colorMap }
|
|
62
|
+
const color = mergedColorMap[status] ?? "gray"
|
|
63
|
+
const style = colorStyles[color] ?? fallbackStyle
|
|
64
|
+
const displayLabel = label ?? status
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<Badge
|
|
68
|
+
ref={ref}
|
|
69
|
+
data-slot="status-badge"
|
|
70
|
+
variant="outline"
|
|
71
|
+
className={cn("gap-1.5 border-transparent", style.bg, style.text, className)}
|
|
72
|
+
aria-label={displayLabel}
|
|
73
|
+
>
|
|
74
|
+
<span className={cn("inline-block size-2 rounded-full", style.dot)} aria-hidden="true" />
|
|
75
|
+
{displayLabel}
|
|
76
|
+
</Badge>
|
|
77
|
+
)
|
|
78
|
+
})
|
|
79
|
+
StatusBadge.displayName = "StatusBadge"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Copied by `vantage add ui switch`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/switch.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
6
|
+
|
|
7
|
+
function Switch({
|
|
8
|
+
className,
|
|
9
|
+
size = "default",
|
|
10
|
+
...props
|
|
11
|
+
}: SwitchPrimitive.Root.Props & {
|
|
12
|
+
size?: "sm" | "default"
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<SwitchPrimitive.Root
|
|
16
|
+
data-slot="switch"
|
|
17
|
+
data-size={size}
|
|
18
|
+
className={cn(
|
|
19
|
+
"peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
>
|
|
24
|
+
<SwitchPrimitive.Thumb
|
|
25
|
+
data-slot="switch-thumb"
|
|
26
|
+
className="pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] dark:data-checked:bg-primary-foreground group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground"
|
|
27
|
+
/>
|
|
28
|
+
</SwitchPrimitive.Root>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { Switch }
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Copied by `vantage add ui table`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/table.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
6
|
+
|
|
7
|
+
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
data-slot="table-container"
|
|
11
|
+
className="relative w-full overflow-x-auto"
|
|
12
|
+
>
|
|
13
|
+
<table
|
|
14
|
+
data-slot="table"
|
|
15
|
+
className={cn("w-full caption-bottom text-sm", className)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
|
23
|
+
return (
|
|
24
|
+
<thead
|
|
25
|
+
data-slot="table-header"
|
|
26
|
+
className={cn("[&_tr]:border-b", className)}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
|
33
|
+
return (
|
|
34
|
+
<tbody
|
|
35
|
+
data-slot="table-body"
|
|
36
|
+
className={cn("[&_tr:last-child]:border-0", className)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
|
43
|
+
return (
|
|
44
|
+
<tfoot
|
|
45
|
+
data-slot="table-footer"
|
|
46
|
+
className={cn(
|
|
47
|
+
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
|
48
|
+
className
|
|
49
|
+
)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|
56
|
+
return (
|
|
57
|
+
<tr
|
|
58
|
+
data-slot="table-row"
|
|
59
|
+
className={cn(
|
|
60
|
+
"border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
|
|
61
|
+
className
|
|
62
|
+
)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
69
|
+
return (
|
|
70
|
+
<th
|
|
71
|
+
data-slot="table-head"
|
|
72
|
+
className={cn(
|
|
73
|
+
"h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
|
|
74
|
+
className
|
|
75
|
+
)}
|
|
76
|
+
{...props}
|
|
77
|
+
/>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
|
82
|
+
return (
|
|
83
|
+
<td
|
|
84
|
+
data-slot="table-cell"
|
|
85
|
+
className={cn(
|
|
86
|
+
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
|
|
87
|
+
className
|
|
88
|
+
)}
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function TableCaption({
|
|
95
|
+
className,
|
|
96
|
+
...props
|
|
97
|
+
}: React.ComponentProps<"caption">) {
|
|
98
|
+
return (
|
|
99
|
+
<caption
|
|
100
|
+
data-slot="table-caption"
|
|
101
|
+
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
|
102
|
+
{...props}
|
|
103
|
+
/>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
Table,
|
|
109
|
+
TableHeader,
|
|
110
|
+
TableBody,
|
|
111
|
+
TableFooter,
|
|
112
|
+
TableHead,
|
|
113
|
+
TableRow,
|
|
114
|
+
TableCell,
|
|
115
|
+
TableCaption,
|
|
116
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copied by `vantage add ui tabs`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/tabs.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import { Tabs as TabsPrimitive } from "@base-ui/react/tabs"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
7
|
+
|
|
8
|
+
function Tabs({
|
|
9
|
+
className,
|
|
10
|
+
orientation = "horizontal",
|
|
11
|
+
...props
|
|
12
|
+
}: TabsPrimitive.Root.Props) {
|
|
13
|
+
return (
|
|
14
|
+
<TabsPrimitive.Root
|
|
15
|
+
data-slot="tabs"
|
|
16
|
+
data-orientation={orientation}
|
|
17
|
+
className={cn(
|
|
18
|
+
"group/tabs flex gap-2 data-horizontal:flex-col",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const tabsListVariants = cva(
|
|
27
|
+
"group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none",
|
|
28
|
+
{
|
|
29
|
+
variants: {
|
|
30
|
+
variant: {
|
|
31
|
+
default: "bg-muted",
|
|
32
|
+
line: "gap-1 bg-transparent",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
defaultVariants: {
|
|
36
|
+
variant: "default",
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
function TabsList({
|
|
42
|
+
className,
|
|
43
|
+
variant = "default",
|
|
44
|
+
...props
|
|
45
|
+
}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {
|
|
46
|
+
return (
|
|
47
|
+
<TabsPrimitive.List
|
|
48
|
+
data-slot="tabs-list"
|
|
49
|
+
data-variant={variant}
|
|
50
|
+
className={cn(tabsListVariants({ variant }), className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
|
|
57
|
+
return (
|
|
58
|
+
<TabsPrimitive.Tab
|
|
59
|
+
data-slot="tabs-trigger"
|
|
60
|
+
className={cn(
|
|
61
|
+
"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 aria-disabled:pointer-events-none aria-disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
62
|
+
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
|
|
63
|
+
"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground",
|
|
64
|
+
"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {
|
|
73
|
+
return (
|
|
74
|
+
<TabsPrimitive.Panel
|
|
75
|
+
data-slot="tabs-content"
|
|
76
|
+
className={cn("flex-1 text-sm outline-none", className)}
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copied by `vantage add ui textarea`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/vantage src/ui/textarea.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
6
|
+
|
|
7
|
+
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|
8
|
+
return (
|
|
9
|
+
<textarea
|
|
10
|
+
data-slot="textarea"
|
|
11
|
+
className={cn(
|
|
12
|
+
"flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
13
|
+
className
|
|
14
|
+
)}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { Textarea }
|