@squadbase/vantage 0.6.1 → 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.
Files changed (183) hide show
  1. package/dist/add-DY4AXANK.js +6 -0
  2. package/dist/add-DY4AXANK.js.map +1 -0
  3. package/dist/{build-O5TVNH4E.js → build-TVKFIVFQ.js} +8 -8
  4. package/dist/{build-O5TVNH4E.js.map → build-TVKFIVFQ.js.map} +1 -1
  5. package/dist/{check-WFBEDHDR.js → check-3KHZXZMQ.js} +6 -6
  6. package/dist/{check-WFBEDHDR.js.map → check-3KHZXZMQ.js.map} +1 -1
  7. package/dist/{chunk-PLST5Q7T.js → chunk-AG6RZ2RR.js} +1010 -23
  8. package/dist/chunk-AG6RZ2RR.js.map +1 -0
  9. package/dist/{chunk-KLEIVDUV.js → chunk-CEXAQQ5W.js} +150 -11
  10. package/dist/chunk-CEXAQQ5W.js.map +1 -0
  11. package/dist/{chunk-JGRMRXXZ.js → chunk-JKLLFVEU.js} +3 -3
  12. package/dist/{chunk-JGRMRXXZ.js.map → chunk-JKLLFVEU.js.map} +1 -1
  13. package/dist/{chunk-EP6JHXSR.js → chunk-LMUACBMA.js} +3 -3
  14. package/dist/{chunk-EP6JHXSR.js.map → chunk-LMUACBMA.js.map} +1 -1
  15. package/dist/{chunk-MXI3PZFT.js → chunk-OB6UBJXF.js} +156 -200
  16. package/dist/chunk-OB6UBJXF.js.map +1 -0
  17. package/dist/{chunk-BCE22JSM.js → chunk-P7W4LR3Z.js} +32 -13
  18. package/dist/chunk-P7W4LR3Z.js.map +1 -0
  19. package/dist/chunk-PXRX5PEC.js +54 -0
  20. package/dist/chunk-PXRX5PEC.js.map +1 -0
  21. package/dist/{chunk-3G43C6OL.js → chunk-QI3XQKHS.js} +39 -3
  22. package/dist/chunk-QI3XQKHS.js.map +1 -0
  23. package/dist/{chunk-QDZA5JSL.js → chunk-U2M6HGKQ.js} +3 -3
  24. package/dist/{chunk-QDZA5JSL.js.map → chunk-U2M6HGKQ.js.map} +1 -1
  25. package/dist/{chunk-T3FLAGI6.js → chunk-VA776YE5.js} +3 -3
  26. package/dist/{chunk-T3FLAGI6.js.map → chunk-VA776YE5.js.map} +1 -1
  27. package/dist/cli.js +14 -11
  28. package/dist/cli.js.map +1 -1
  29. package/dist/components/index.d.ts +223 -1
  30. package/dist/components/index.js +3 -2
  31. package/dist/{dev-NZRLOQCL.js → dev-GDKATCC7.js} +22 -11
  32. package/dist/dev-GDKATCC7.js.map +1 -0
  33. package/dist/doc/index.d.ts +4 -0
  34. package/dist/doc/index.js +107 -11
  35. package/dist/doc/index.js.map +1 -1
  36. package/dist/{docs-ZGDJUHJI.js → docs-EJJ3BECT.js} +3 -3
  37. package/dist/{docs-ZGDJUHJI.js.map → docs-EJJ3BECT.js.map} +1 -1
  38. package/dist/{doctor-VFKEMR54.js → doctor-WQXPXP6K.js} +7 -7
  39. package/dist/doctor-WQXPXP6K.js.map +1 -0
  40. package/dist/{preview-QDCIVVSR.js → preview-OGMCNQUO.js} +12 -4
  41. package/dist/preview-OGMCNQUO.js.map +1 -0
  42. package/dist/{routes-RHP5FVGD.js → routes-MWBWWOJ2.js} +5 -5
  43. package/dist/{routes-RHP5FVGD.js.map → routes-MWBWWOJ2.js.map} +1 -1
  44. package/dist/{search-RFBELGY7.js → search-6Y422SV6.js} +3 -3
  45. package/dist/{search-RFBELGY7.js.map → search-6Y422SV6.js.map} +1 -1
  46. package/dist/slide/index.js +61 -15
  47. package/dist/slide/index.js.map +1 -1
  48. package/dist/table/index.js +7 -5
  49. package/dist/table/index.js.map +1 -1
  50. package/dist/ui/index.d.ts +140 -10
  51. package/dist/ui/index.js +1406 -63
  52. package/dist/ui/index.js.map +1 -1
  53. package/dist/{upgrade-GF2P67M6.js → upgrade-HCANX4GQ.js} +6 -6
  54. package/dist/{upgrade-GF2P67M6.js.map → upgrade-HCANX4GQ.js.map} +1 -1
  55. package/dist/vite/index.js +3 -3
  56. package/docs/en/changelog.md +24 -0
  57. package/docs/en/cli-reference.md +30 -0
  58. package/docs/en/parts/page-shell.md +1 -1
  59. package/docs/en/routing.md +4 -2
  60. package/docs/index.json +291 -61
  61. package/docs/ja/changelog.md +50 -0
  62. package/docs/ja/cli-reference.md +29 -0
  63. package/docs/ja/components.md +33 -89
  64. package/docs/ja/page-types/csv.md +83 -0
  65. package/docs/ja/page-types/doc.md +83 -0
  66. package/docs/ja/page-types/excel.md +82 -0
  67. package/docs/ja/page-types/slide.md +132 -0
  68. package/docs/ja/page-types.md +47 -0
  69. package/docs/ja/parts/area-chart.md +61 -0
  70. package/docs/ja/parts/bar-chart.md +69 -0
  71. package/docs/ja/parts/bar-list.md +35 -0
  72. package/docs/ja/parts/category-bar.md +36 -0
  73. package/docs/ja/parts/donut-chart.md +47 -0
  74. package/docs/ja/parts/echart.md +3 -0
  75. package/docs/ja/parts/line-chart.md +58 -0
  76. package/docs/ja/parts/page-shell.md +1 -1
  77. package/docs/ja/parts/progress-circle.md +34 -0
  78. package/docs/ja/parts/sparkline.md +1 -1
  79. package/docs/ja/parts/tracker.md +32 -0
  80. package/docs/ja/routing.md +8 -84
  81. package/docs/ja/ui/alert-dialog.md +41 -0
  82. package/docs/ja/ui/avatar.md +31 -0
  83. package/docs/ja/ui/combobox.md +74 -0
  84. package/docs/ja/ui/drawer.md +41 -0
  85. package/docs/ja/ui/field.md +42 -0
  86. package/docs/ja/ui/hover-card.md +21 -0
  87. package/docs/ja/ui/kbd.md +16 -0
  88. package/docs/ja/ui/pagination.md +36 -0
  89. package/docs/ja/ui/radio-group.md +21 -0
  90. package/docs/ja/ui/toast.md +46 -0
  91. package/docs/ja/ui-and-theming.md +14 -7
  92. package/package.json +18 -12
  93. package/registry/ui/accordion.tsx +74 -0
  94. package/registry/ui/alert-dialog.tsx +189 -0
  95. package/registry/ui/alert.tsx +78 -0
  96. package/registry/ui/app-shell.tsx +281 -0
  97. package/registry/ui/area-chart.tsx +1015 -0
  98. package/registry/ui/avatar.tsx +110 -0
  99. package/registry/ui/badge.tsx +54 -0
  100. package/registry/ui/bar-chart.tsx +1013 -0
  101. package/registry/ui/bar-list.tsx +302 -0
  102. package/registry/ui/breadcrumb.tsx +126 -0
  103. package/registry/ui/button.tsx +60 -0
  104. package/registry/ui/calendar.tsx +221 -0
  105. package/registry/ui/card.tsx +105 -0
  106. package/registry/ui/category-bar.tsx +281 -0
  107. package/registry/ui/checkbox.tsx +28 -0
  108. package/registry/ui/collapsible.tsx +21 -0
  109. package/registry/ui/combobox.tsx +310 -0
  110. package/registry/ui/command.tsx +196 -0
  111. package/registry/ui/dashboard-card.tsx +174 -0
  112. package/registry/ui/data-table.tsx +16 -91
  113. package/registry/ui/date-range-picker.tsx +209 -0
  114. package/registry/ui/dialog.tsx +159 -0
  115. package/registry/ui/donut-chart.tsx +1004 -0
  116. package/registry/ui/drawer.tsx +229 -0
  117. package/registry/ui/dropdown-menu.tsx +272 -0
  118. package/registry/ui/echart.tsx +486 -0
  119. package/registry/ui/field.tsx +240 -0
  120. package/registry/ui/filter-bar.tsx +365 -0
  121. package/registry/ui/funnel-steps.tsx +274 -0
  122. package/registry/ui/hover-card.tsx +52 -0
  123. package/registry/ui/input-group.tsx +158 -0
  124. package/registry/ui/input.tsx +22 -0
  125. package/registry/ui/kbd.tsx +28 -0
  126. package/registry/ui/label.tsx +20 -0
  127. package/registry/ui/line-chart.tsx +1007 -0
  128. package/registry/ui/metric-value.tsx +54 -0
  129. package/registry/ui/multi-select.tsx +226 -0
  130. package/registry/ui/page-shell.tsx +227 -0
  131. package/registry/ui/pagination.tsx +138 -0
  132. package/registry/ui/placeholder.tsx +30 -0
  133. package/registry/ui/popover.tsx +90 -0
  134. package/registry/ui/progress-circle.tsx +272 -0
  135. package/registry/ui/progress.tsx +83 -0
  136. package/registry/ui/radio-group.tsx +39 -0
  137. package/registry/ui/scroll-area.tsx +55 -0
  138. package/registry/ui/searchable-select.tsx +209 -0
  139. package/registry/ui/section-header.tsx +41 -0
  140. package/registry/ui/segmented-control.tsx +71 -0
  141. package/registry/ui/select.tsx +253 -0
  142. package/registry/ui/separator.tsx +25 -0
  143. package/registry/ui/sheet.tsx +137 -0
  144. package/registry/ui/sidebar.tsx +723 -0
  145. package/registry/ui/skeleton.tsx +15 -0
  146. package/registry/ui/slider.tsx +54 -0
  147. package/registry/ui/sparkline.tsx +155 -0
  148. package/registry/ui/spinner.tsx +12 -0
  149. package/registry/ui/states.tsx +61 -0
  150. package/registry/ui/status-badge.tsx +79 -0
  151. package/registry/ui/switch.tsx +32 -0
  152. package/registry/ui/table.tsx +116 -0
  153. package/registry/ui/tabs.tsx +82 -0
  154. package/registry/ui/textarea.tsx +20 -0
  155. package/registry/ui/toast.tsx +250 -0
  156. package/registry/ui/toggle-group.tsx +89 -0
  157. package/registry/ui/toggle.tsx +45 -0
  158. package/registry/ui/tooltip.tsx +66 -0
  159. package/registry/ui/tracker.tsx +236 -0
  160. package/registry/ui/trend-indicator.tsx +62 -0
  161. package/skills/vantage-add-feature/SKILL.md +9 -7
  162. package/skills/vantage-design/SKILL.md +3 -1
  163. package/skills/vantage-design/references/format.md +1 -1
  164. package/skills/vantage-pitfalls/SKILL.md +5 -1
  165. package/skills/vantage-slide/SKILL.md +17 -0
  166. package/templates/AGENTS.md +10 -1
  167. package/templates/agents/api.md +29 -0
  168. package/templates/agents/csv.md +2 -1
  169. package/templates/agents/doc.md +6 -3
  170. package/templates/agents/page.md +22 -8
  171. package/templates/agents/slide.md +13 -1
  172. package/templates/agents/xlsx.md +2 -1
  173. package/theme.css +51 -1
  174. package/dist/add-EISGSZAH.js +0 -6
  175. package/dist/add-EISGSZAH.js.map +0 -1
  176. package/dist/chunk-3G43C6OL.js.map +0 -1
  177. package/dist/chunk-BCE22JSM.js.map +0 -1
  178. package/dist/chunk-KLEIVDUV.js.map +0 -1
  179. package/dist/chunk-MXI3PZFT.js.map +0 -1
  180. package/dist/chunk-PLST5Q7T.js.map +0 -1
  181. package/dist/dev-NZRLOQCL.js.map +0 -1
  182. package/dist/doctor-VFKEMR54.js.map +0 -1
  183. package/dist/preview-QDCIVVSR.js.map +0 -1
@@ -0,0 +1,302 @@
1
+ // Copied by `vantage add ui bar-list`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/components/bar-list.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ /**
4
+ * BarList — a ranked list of horizontal bars with the value at the end of each
5
+ * row: top pages, sales by store, error counts by type. Plain HTML/CSS (no
6
+ * ECharts), so it stays cheap inside cards and follows the theme natively.
7
+ */
8
+ import { forwardRef, useEffect, useState, type ComponentProps } from "react"
9
+
10
+ import { cn } from "@squadbase/vantage/ui"
11
+ import type { ChartColor, ValueFormatter } from "@squadbase/vantage/components"
12
+
13
+ /* ---------- inlined from src/components/chart-utils.ts (internal to @squadbase/vantage) ---------- */
14
+
15
+ /** The series tokens, in palette order — the default `colors` of every typed chart. */
16
+ const DEFAULT_CHART_COLORS: readonly ChartColor[] = [
17
+ "chart-1",
18
+ "chart-2",
19
+ "chart-3",
20
+ "chart-4",
21
+ "chart-5",
22
+ ]
23
+
24
+ const TOKEN_NAME_RE = /^chart-[1-5]$/
25
+
26
+ /**
27
+ * A chart colour as a CSS value: `"chart-2"` → `var(--chart-2)` (so it follows
28
+ * light/dark on its own), anything else passes through unchanged.
29
+ */
30
+ function chartColorToCss(color: ChartColor): string {
31
+ const value = color.trim()
32
+ return TOKEN_NAME_RE.test(value) ? `var(--${value})` : value
33
+ }
34
+
35
+ /** The `i`-th colour, cycling through `colors` (the token palette when empty). */
36
+ function chartColorAt(colors: readonly ChartColor[] | undefined, i: number): ChartColor {
37
+ const palette = colors && colors.length > 0 ? colors : DEFAULT_CHART_COLORS
38
+ return palette[i % palette.length]!
39
+ }
40
+
41
+ /** `colors` extended (by cycling) to exactly `count` entries. */
42
+ function chartColorsFor(colors: readonly ChartColor[] | undefined, count: number): ChartColor[] {
43
+ return Array.from({ length: count }, (_, i) => chartColorAt(colors, i))
44
+ }
45
+
46
+ /** A translucent version of a CSS colour (works for `var(--…)` too). */
47
+ function tintCss(cssColor: string, percent: number): string {
48
+ return `color-mix(in oklab, ${cssColor} ${percent}%, transparent)`
49
+ }
50
+
51
+ const numberFormat = new Intl.NumberFormat("ja-JP", { maximumFractionDigits: 2 })
52
+
53
+ /** Default `valueFormatter`: grouped digits, up to two decimals (`1,234.5`). */
54
+ const defaultValueFormatter: ValueFormatter = (value) => numberFormat.format(value)
55
+
56
+ /**
57
+ * A data cell as a number, or `null` for a gap. Numeric strings count — SQL
58
+ * `DECIMAL` / `BIGINT` columns usually arrive as strings.
59
+ */
60
+ function toChartNumber(value: unknown): number | null {
61
+ if (typeof value === "number") return Number.isFinite(value) ? value : null
62
+ if (typeof value === "bigint") return Number(value)
63
+ if (typeof value === "string" && value.trim() !== "") {
64
+ const n = Number(value)
65
+ return Number.isFinite(n) ? n : null
66
+ }
67
+ return null
68
+ }
69
+
70
+ /** Clamp `value` into `[min, max]`. */
71
+ function clamp(value: number, min: number, max: number): number {
72
+ return Math.min(max, Math.max(min, value))
73
+ }
74
+
75
+ /* ---------------------------------------------------------------- BarList */
76
+
77
+ type BarListSortOrder = "ascending" | "descending" | "none"
78
+
79
+ /** Sort a copy of the rows by value; `"none"` keeps the given order. */
80
+ function sortBarListData<T extends { value: number }>(data: readonly T[], sortOrder: BarListSortOrder): T[] {
81
+ const rows = [...data]
82
+ if (sortOrder === "ascending") rows.sort((a, b) => a.value - b.value)
83
+ else if (sortOrder === "descending") rows.sort((a, b) => b.value - a.value)
84
+ return rows
85
+ }
86
+
87
+ /** Bar widths in percent of the largest value (at least a sliver for non-zero values). */
88
+ function barListWidths(values: readonly number[]): number[] {
89
+ const max = Math.max(0, ...values)
90
+ if (max === 0) return values.map(() => 0)
91
+ return values.map((v) => (v <= 0 ? 0 : Math.max(1, (v / max) * 100)))
92
+ }
93
+
94
+ /* ------------------------------------------------------------ CategoryBar */
95
+
96
+ interface CategoryBarSegment {
97
+ /** Width in percent of the whole bar. */
98
+ width: number
99
+ /** Where the segment starts, in percent. */
100
+ start: number
101
+ /** The running total at the segment's end — what its right-hand label shows. */
102
+ end: number
103
+ }
104
+
105
+ /** Lay the values side by side; negative values count as zero. */
106
+ function categoryBarSegments(values: readonly number[]): CategoryBarSegment[] {
107
+ const clean = values.map((v) => (Number.isFinite(v) && v > 0 ? v : 0))
108
+ const total = clean.reduce((sum, v) => sum + v, 0)
109
+ let running = 0
110
+ return clean.map((v) => {
111
+ const start = total === 0 ? 0 : (running / total) * 100
112
+ running += v
113
+ return { width: total === 0 ? 0 : (v / total) * 100, start, end: running }
114
+ })
115
+ }
116
+
117
+ interface CategoryBarLabel {
118
+ /** Position in percent of the bar. */
119
+ position: number
120
+ /** The running total printed there. */
121
+ value: number
122
+ }
123
+
124
+ /**
125
+ * Tick labels under the bar: `0` at the start, then the running total at each
126
+ * segment's end. A label closer than `minGap` percent to the one before is
127
+ * dropped so narrow segments don't print on top of each other — except the
128
+ * last one (the total), which replaces its neighbour instead.
129
+ */
130
+ function categoryBarLabels(values: readonly number[], minGap = 8): CategoryBarLabel[] {
131
+ const segments = categoryBarSegments(values).filter((s) => s.width > 0)
132
+ if (segments.length === 0) return []
133
+ const labels: CategoryBarLabel[] = [{ position: 0, value: 0 }]
134
+ segments.forEach((s, i) => {
135
+ const label = { position: s.start + s.width, value: s.end }
136
+ const prev = labels[labels.length - 1]!
137
+ if (label.position - prev.position >= minGap) labels.push(label)
138
+ else if (i === segments.length - 1 && labels.length > 1) labels[labels.length - 1] = label
139
+ })
140
+ return labels
141
+ }
142
+
143
+ /** Marker position in percent of the bar, clamped to its ends. */
144
+ function categoryBarMarkerPosition(value: number, values: readonly number[]): number {
145
+ const total = values.reduce((sum, v) => sum + (Number.isFinite(v) && v > 0 ? v : 0), 0)
146
+ if (total === 0) return 0
147
+ return clamp((value / total) * 100, 0, 100)
148
+ }
149
+
150
+ /** Index of the segment the marker sits on (the last one for a value past the end). */
151
+ function categoryBarMarkerSegment(value: number, values: readonly number[]): number {
152
+ const segments = categoryBarSegments(values)
153
+ const index = segments.findIndex((s) => s.width > 0 && value <= s.end)
154
+ if (index !== -1) return index
155
+ for (let i = segments.length - 1; i >= 0; i--) if (segments[i]!.width > 0) return i
156
+ return 0
157
+ }
158
+
159
+ /* --------------------------------------------------------- ProgressCircle */
160
+
161
+ interface ProgressCircleGeometry {
162
+ /** SVG width/height. */
163
+ size: number
164
+ /** Radius of the stroke's centre line. */
165
+ normalizedRadius: number
166
+ circumference: number
167
+ /** `stroke-dashoffset` for the value arc. */
168
+ offset: number
169
+ /** The value as a fraction of `max`, clamped to `[0, 1]`. */
170
+ ratio: number
171
+ }
172
+
173
+ function progressCircleGeometry(
174
+ value: number,
175
+ max: number,
176
+ radius: number,
177
+ strokeWidth: number,
178
+ ): ProgressCircleGeometry {
179
+ const ratio = max > 0 && Number.isFinite(value) ? clamp(value / max, 0, 1) : 0
180
+ const normalizedRadius = Math.max(0, radius - strokeWidth / 2)
181
+ const circumference = 2 * Math.PI * normalizedRadius
182
+ return { size: radius * 2, normalizedRadius, circumference, offset: circumference * (1 - ratio), ratio }
183
+ }
184
+
185
+ /* ---------- end of inlined code ---------- */
186
+
187
+ export interface BarListItem {
188
+ /** React の key。省略時は `name`。 */
189
+ key?: string
190
+ /** 行のラベル(バーの上に出る)。 */
191
+ name: string
192
+ value: number
193
+ /** 渡すとラベルがリンクになる。 */
194
+ href?: string
195
+ /** この行だけ色を変える。省略時は `color`。 */
196
+ color?: ChartColor
197
+ }
198
+
199
+ export interface BarListProps extends Omit<ComponentProps<"div">, "children"> {
200
+ data: BarListItem[]
201
+ /** 右端の数値の書式。 */
202
+ valueFormatter?: ValueFormatter
203
+ /** 並べ順。既定 `"descending"`(大きい順)。`"none"` は渡した順。 */
204
+ sortOrder?: BarListSortOrder
205
+ /** バーの色。`"chart-1"`〜`"chart-5"` か CSS カラー。既定 `"chart-1"`(淡く塗る)。 */
206
+ color?: ChartColor
207
+ /** マウント時にバーを伸ばす。 */
208
+ showAnimation?: boolean
209
+ /** 渡すと行がボタンになり、クリックした行を受け取る。 */
210
+ onValueChange?: (item: BarListItem) => void
211
+ }
212
+
213
+ export const BarList = forwardRef<HTMLDivElement, BarListProps>(function BarList(
214
+ {
215
+ data,
216
+ valueFormatter = defaultValueFormatter,
217
+ sortOrder = "descending",
218
+ color = "chart-1",
219
+ showAnimation = false,
220
+ onValueChange,
221
+ className,
222
+ ...props
223
+ },
224
+ ref,
225
+ ) {
226
+ const [mounted, setMounted] = useState(!showAnimation)
227
+ useEffect(() => {
228
+ if (!showAnimation) return
229
+ const frame = requestAnimationFrame(() => setMounted(true))
230
+ return () => cancelAnimationFrame(frame)
231
+ }, [showAnimation])
232
+
233
+ const rows = sortBarListData(data, sortOrder)
234
+ const widths = barListWidths(rows.map((row) => row.value))
235
+
236
+ return (
237
+ <div ref={ref} data-slot="bar-list" className={cn("flex justify-between gap-6 text-sm", className)} {...props}>
238
+ <div className="relative min-w-0 flex-1 space-y-1.5">
239
+ {rows.map((row, i) => {
240
+ const css = chartColorToCss(row.color ?? color)
241
+ const label = row.href ? (
242
+ <a
243
+ href={row.href}
244
+ target={/^https?:\/\//.test(row.href) ? "_blank" : undefined}
245
+ rel={/^https?:\/\//.test(row.href) ? "noreferrer" : undefined}
246
+ onClick={(event) => event.stopPropagation()}
247
+ className="truncate hover:underline"
248
+ >
249
+ {row.name}
250
+ </a>
251
+ ) : (
252
+ <span className="truncate">{row.name}</span>
253
+ )
254
+ const content = (
255
+ <>
256
+ <span
257
+ aria-hidden="true"
258
+ data-slot="bar-list-bar"
259
+ className={cn(
260
+ "absolute inset-y-0 left-0 rounded-sm",
261
+ showAnimation && "transition-[width] duration-700 ease-out",
262
+ )}
263
+ style={{ width: `${mounted ? widths[i] : 0}%`, background: tintCss(css, 28) }}
264
+ />
265
+ <span className="relative flex min-w-0 items-center px-2 text-foreground">{label}</span>
266
+ </>
267
+ )
268
+ const rowClass = "relative flex h-8 w-full items-center rounded-sm"
269
+ return onValueChange ? (
270
+ <button
271
+ key={row.key ?? row.name}
272
+ type="button"
273
+ data-slot="bar-list-row"
274
+ onClick={() => onValueChange(row)}
275
+ className={cn(
276
+ rowClass,
277
+ "text-left outline-none hover:bg-muted/60 focus-visible:ring-2 focus-visible:ring-ring",
278
+ )}
279
+ >
280
+ {content}
281
+ </button>
282
+ ) : (
283
+ <div key={row.key ?? row.name} data-slot="bar-list-row" className={rowClass}>
284
+ {content}
285
+ </div>
286
+ )
287
+ })}
288
+ </div>
289
+ <div className="shrink-0 space-y-1.5 text-right">
290
+ {rows.map((row) => (
291
+ <div
292
+ key={row.key ?? row.name}
293
+ className="flex h-8 items-center justify-end font-medium text-foreground tabular-nums"
294
+ >
295
+ {valueFormatter(row.value)}
296
+ </div>
297
+ ))}
298
+ </div>
299
+ </div>
300
+ )
301
+ })
302
+ BarList.displayName = "BarList"
@@ -0,0 +1,126 @@
1
+ // Copied by `vantage add ui breadcrumb`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/ui/breadcrumb.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ import * as React from "react"
4
+ import { mergeProps } from "@base-ui/react/merge-props"
5
+ import { useRender } from "@base-ui/react/use-render"
6
+
7
+ import { cn } from "@squadbase/vantage/ui"
8
+ import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
9
+
10
+ function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
11
+ return (
12
+ <nav
13
+ aria-label="breadcrumb"
14
+ data-slot="breadcrumb"
15
+ className={cn(className)}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
22
+ return (
23
+ <ol
24
+ data-slot="breadcrumb-list"
25
+ className={cn(
26
+ "flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground",
27
+ className
28
+ )}
29
+ {...props}
30
+ />
31
+ )
32
+ }
33
+
34
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
35
+ return (
36
+ <li
37
+ data-slot="breadcrumb-item"
38
+ className={cn("inline-flex items-center gap-1", className)}
39
+ {...props}
40
+ />
41
+ )
42
+ }
43
+
44
+ function BreadcrumbLink({
45
+ className,
46
+ render,
47
+ ...props
48
+ }: useRender.ComponentProps<"a">) {
49
+ return useRender({
50
+ defaultTagName: "a",
51
+ props: mergeProps<"a">(
52
+ {
53
+ className: cn("transition-colors hover:text-foreground", className),
54
+ },
55
+ props
56
+ ),
57
+ render,
58
+ state: {
59
+ slot: "breadcrumb-link",
60
+ },
61
+ })
62
+ }
63
+
64
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
65
+ return (
66
+ <span
67
+ data-slot="breadcrumb-page"
68
+ role="link"
69
+ aria-disabled="true"
70
+ aria-current="page"
71
+ className={cn("font-normal text-foreground", className)}
72
+ {...props}
73
+ />
74
+ )
75
+ }
76
+
77
+ function BreadcrumbSeparator({
78
+ children,
79
+ className,
80
+ ...props
81
+ }: React.ComponentProps<"li">) {
82
+ return (
83
+ <li
84
+ data-slot="breadcrumb-separator"
85
+ role="presentation"
86
+ aria-hidden="true"
87
+ className={cn("[&>svg]:size-3.5", className)}
88
+ {...props}
89
+ >
90
+ {children ?? (
91
+ <ChevronRightIcon className="cn-rtl-flip" />
92
+ )}
93
+ </li>
94
+ )
95
+ }
96
+
97
+ function BreadcrumbEllipsis({
98
+ className,
99
+ ...props
100
+ }: React.ComponentProps<"span">) {
101
+ return (
102
+ <span
103
+ data-slot="breadcrumb-ellipsis"
104
+ role="presentation"
105
+ aria-hidden="true"
106
+ className={cn(
107
+ "flex size-5 items-center justify-center [&>svg]:size-4",
108
+ className
109
+ )}
110
+ {...props}
111
+ >
112
+ <MoreHorizontalIcon />
113
+ <span className="sr-only">More</span>
114
+ </span>
115
+ )
116
+ }
117
+
118
+ export {
119
+ Breadcrumb,
120
+ BreadcrumbList,
121
+ BreadcrumbItem,
122
+ BreadcrumbLink,
123
+ BreadcrumbPage,
124
+ BreadcrumbSeparator,
125
+ BreadcrumbEllipsis,
126
+ }
@@ -0,0 +1,60 @@
1
+ // Copied by `vantage add ui button`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/ui/button.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ import { Button as ButtonPrimitive } from "@base-ui/react/button"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+
6
+ import { cn } from "@squadbase/vantage/ui"
7
+
8
+ const buttonVariants = cva(
9
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 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",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
14
+ outline:
15
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
16
+ secondary:
17
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
18
+ ghost:
19
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
20
+ destructive:
21
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
22
+ link: "text-primary underline-offset-4 hover:underline",
23
+ },
24
+ size: {
25
+ default:
26
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
27
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
28
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
29
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
30
+ icon: "size-8",
31
+ "icon-xs":
32
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
33
+ "icon-sm":
34
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
35
+ "icon-lg": "size-9",
36
+ },
37
+ },
38
+ defaultVariants: {
39
+ variant: "default",
40
+ size: "default",
41
+ },
42
+ }
43
+ )
44
+
45
+ function Button({
46
+ className,
47
+ variant = "default",
48
+ size = "default",
49
+ ...props
50
+ }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
51
+ return (
52
+ <ButtonPrimitive
53
+ data-slot="button"
54
+ className={cn(buttonVariants({ variant, size, className }))}
55
+ {...props}
56
+ />
57
+ )
58
+ }
59
+
60
+ export { Button, buttonVariants }