@squadbase/vantage 0.6.2-dev1.a7c4a3e → 0.6.2-dev1.ac99e02

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 (186) hide show
  1. package/dist/add-4GHF2TX2.js +6 -0
  2. package/dist/add-4GHF2TX2.js.map +1 -0
  3. package/dist/{build-JB4VOMUI.js → build-MFWRPYKW.js} +9 -9
  4. package/dist/{build-JB4VOMUI.js.map → build-MFWRPYKW.js.map} +1 -1
  5. package/dist/{check-ZJYK6RLG.js → check-ZBIH422T.js} +7 -7
  6. package/dist/{check-ZJYK6RLG.js.map → check-ZBIH422T.js.map} +1 -1
  7. package/dist/{chunk-BCE22JSM.js → chunk-7DZGJQ3P.js} +33 -14
  8. package/dist/chunk-7DZGJQ3P.js.map +1 -0
  9. package/dist/{chunk-U2M6HGKQ.js → chunk-AABMKHEU.js} +4 -4
  10. package/dist/{chunk-U2M6HGKQ.js.map → chunk-AABMKHEU.js.map} +1 -1
  11. package/dist/{chunk-MP3QSOXL.js → chunk-AG6RZ2RR.js} +992 -16
  12. package/dist/chunk-AG6RZ2RR.js.map +1 -0
  13. package/dist/{chunk-KLEIVDUV.js → chunk-CEXAQQ5W.js} +150 -11
  14. package/dist/chunk-CEXAQQ5W.js.map +1 -0
  15. package/dist/{chunk-QI3XQKHS.js → chunk-GNXCX4WE.js} +10 -3
  16. package/dist/chunk-GNXCX4WE.js.map +1 -0
  17. package/dist/chunk-IBGOCWJB.js +1716 -0
  18. package/dist/chunk-IBGOCWJB.js.map +1 -0
  19. package/dist/{chunk-JGRMRXXZ.js → chunk-JKLLFVEU.js} +3 -3
  20. package/dist/{chunk-JGRMRXXZ.js.map → chunk-JKLLFVEU.js.map} +1 -1
  21. package/dist/{chunk-RPZAALCX.js → chunk-OB6UBJXF.js} +153 -153
  22. package/dist/{chunk-RPZAALCX.js.map → chunk-OB6UBJXF.js.map} +1 -1
  23. package/dist/{chunk-EP6JHXSR.js → chunk-QEWCYW3I.js} +44 -9
  24. package/dist/chunk-QEWCYW3I.js.map +1 -0
  25. package/dist/{chunk-ZVANIULZ.js → chunk-RNTDBX6S.js} +4 -4
  26. package/dist/{chunk-ZVANIULZ.js.map → chunk-RNTDBX6S.js.map} +1 -1
  27. package/dist/{chunk-PVTHHV7X.js → chunk-V3LF7BE7.js} +27 -5
  28. package/dist/chunk-V3LF7BE7.js.map +1 -0
  29. package/dist/{chunk-DTDVSFRY.js → chunk-XQUSGIDG.js} +17 -3
  30. package/dist/chunk-XQUSGIDG.js.map +1 -0
  31. package/dist/cli.js +12 -11
  32. package/dist/cli.js.map +1 -1
  33. package/dist/client/index.d.ts +32 -3
  34. package/dist/client/index.js +205 -12
  35. package/dist/client/index.js.map +1 -1
  36. package/dist/components/index.d.ts +216 -1
  37. package/dist/components/index.js +2 -2
  38. package/dist/{dev-FCEC3UKQ.js → dev-DCTOHQ6W.js} +10 -10
  39. package/dist/dev-DCTOHQ6W.js.map +1 -0
  40. package/dist/{docs-EJJ3BECT.js → docs-JVP4RPKT.js} +3 -3
  41. package/dist/{docs-EJJ3BECT.js.map → docs-JVP4RPKT.js.map} +1 -1
  42. package/dist/{doctor-WHZXPERA.js → doctor-5E2VEZPK.js} +7 -7
  43. package/dist/{doctor-WHZXPERA.js.map → doctor-5E2VEZPK.js.map} +1 -1
  44. package/dist/{preview-OGMCNQUO.js → preview-T6CLSQVX.js} +3 -3
  45. package/dist/{preview-OGMCNQUO.js.map → preview-T6CLSQVX.js.map} +1 -1
  46. package/dist/query/index.d.ts +0 -11
  47. package/dist/query/index.js +2 -2
  48. package/dist/{routes-GTFO5PUF.js → routes-3SGAFDMC.js} +6 -6
  49. package/dist/{routes-GTFO5PUF.js.map → routes-3SGAFDMC.js.map} +1 -1
  50. package/dist/{search-6Y422SV6.js → search-5LC4XPB5.js} +3 -3
  51. package/dist/{search-6Y422SV6.js.map → search-5LC4XPB5.js.map} +1 -1
  52. package/dist/slide/index.js +47 -10
  53. package/dist/slide/index.js.map +1 -1
  54. package/dist/table/index.js +8 -7
  55. package/dist/table/index.js.map +1 -1
  56. package/dist/ui/index.d.ts +140 -10
  57. package/dist/ui/index.js +1405 -63
  58. package/dist/ui/index.js.map +1 -1
  59. package/dist/{upgrade-AL4KZZR4.js → upgrade-DBBE6GIR.js} +7 -7
  60. package/dist/{upgrade-AL4KZZR4.js.map → upgrade-DBBE6GIR.js.map} +1 -1
  61. package/dist/vite/index.d.ts +10 -0
  62. package/dist/vite/index.js +4 -4
  63. package/docs/index.json +291 -61
  64. package/docs/ja/changelog.md +26 -0
  65. package/docs/ja/components.md +33 -89
  66. package/docs/ja/page-types/csv.md +83 -0
  67. package/docs/ja/page-types/doc.md +83 -0
  68. package/docs/ja/page-types/excel.md +82 -0
  69. package/docs/ja/page-types/slide.md +132 -0
  70. package/docs/ja/page-types.md +47 -0
  71. package/docs/ja/parts/area-chart.md +61 -0
  72. package/docs/ja/parts/bar-chart.md +69 -0
  73. package/docs/ja/parts/bar-list.md +35 -0
  74. package/docs/ja/parts/category-bar.md +36 -0
  75. package/docs/ja/parts/donut-chart.md +47 -0
  76. package/docs/ja/parts/echart.md +3 -0
  77. package/docs/ja/parts/line-chart.md +58 -0
  78. package/docs/ja/parts/progress-circle.md +34 -0
  79. package/docs/ja/parts/sparkline.md +1 -1
  80. package/docs/ja/parts/tracker.md +32 -0
  81. package/docs/ja/routing.md +8 -86
  82. package/docs/ja/ui/alert-dialog.md +41 -0
  83. package/docs/ja/ui/avatar.md +31 -0
  84. package/docs/ja/ui/combobox.md +74 -0
  85. package/docs/ja/ui/drawer.md +41 -0
  86. package/docs/ja/ui/field.md +42 -0
  87. package/docs/ja/ui/hover-card.md +21 -0
  88. package/docs/ja/ui/kbd.md +16 -0
  89. package/docs/ja/ui/pagination.md +36 -0
  90. package/docs/ja/ui/radio-group.md +21 -0
  91. package/docs/ja/ui/toast.md +46 -0
  92. package/docs/ja/ui-and-theming.md +14 -7
  93. package/package.json +25 -13
  94. package/registry/ui/accordion.tsx +74 -0
  95. package/registry/ui/alert-dialog.tsx +189 -0
  96. package/registry/ui/alert.tsx +78 -0
  97. package/registry/ui/app-shell.tsx +281 -0
  98. package/registry/ui/area-chart.tsx +1015 -0
  99. package/registry/ui/avatar.tsx +110 -0
  100. package/registry/ui/badge.tsx +54 -0
  101. package/registry/ui/bar-chart.tsx +1013 -0
  102. package/registry/ui/bar-list.tsx +302 -0
  103. package/registry/ui/breadcrumb.tsx +126 -0
  104. package/registry/ui/button.tsx +60 -0
  105. package/registry/ui/calendar.tsx +221 -0
  106. package/registry/ui/card.tsx +105 -0
  107. package/registry/ui/category-bar.tsx +281 -0
  108. package/registry/ui/checkbox.tsx +28 -0
  109. package/registry/ui/collapsible.tsx +21 -0
  110. package/registry/ui/combobox.tsx +310 -0
  111. package/registry/ui/command.tsx +196 -0
  112. package/registry/ui/dashboard-card.tsx +174 -0
  113. package/registry/ui/data-table.tsx +16 -91
  114. package/registry/ui/date-range-picker.tsx +209 -0
  115. package/registry/ui/dialog.tsx +159 -0
  116. package/registry/ui/donut-chart.tsx +1004 -0
  117. package/registry/ui/drawer.tsx +229 -0
  118. package/registry/ui/dropdown-menu.tsx +272 -0
  119. package/registry/ui/echart.tsx +486 -0
  120. package/registry/ui/field.tsx +240 -0
  121. package/registry/ui/filter-bar.tsx +365 -0
  122. package/registry/ui/funnel-steps.tsx +274 -0
  123. package/registry/ui/hover-card.tsx +52 -0
  124. package/registry/ui/input-group.tsx +158 -0
  125. package/registry/ui/input.tsx +22 -0
  126. package/registry/ui/kbd.tsx +28 -0
  127. package/registry/ui/label.tsx +20 -0
  128. package/registry/ui/line-chart.tsx +1007 -0
  129. package/registry/ui/metric-value.tsx +54 -0
  130. package/registry/ui/multi-select.tsx +226 -0
  131. package/registry/ui/page-shell.tsx +227 -0
  132. package/registry/ui/pagination.tsx +138 -0
  133. package/registry/ui/placeholder.tsx +30 -0
  134. package/registry/ui/popover.tsx +90 -0
  135. package/registry/ui/progress-circle.tsx +272 -0
  136. package/registry/ui/progress.tsx +83 -0
  137. package/registry/ui/radio-group.tsx +39 -0
  138. package/registry/ui/scroll-area.tsx +55 -0
  139. package/registry/ui/searchable-select.tsx +209 -0
  140. package/registry/ui/section-header.tsx +41 -0
  141. package/registry/ui/segmented-control.tsx +71 -0
  142. package/registry/ui/select.tsx +253 -0
  143. package/registry/ui/separator.tsx +25 -0
  144. package/registry/ui/sheet.tsx +137 -0
  145. package/registry/ui/sidebar.tsx +723 -0
  146. package/registry/ui/skeleton.tsx +15 -0
  147. package/registry/ui/slider.tsx +54 -0
  148. package/registry/ui/sparkline.tsx +155 -0
  149. package/registry/ui/spinner.tsx +12 -0
  150. package/registry/ui/states.tsx +61 -0
  151. package/registry/ui/status-badge.tsx +79 -0
  152. package/registry/ui/switch.tsx +32 -0
  153. package/registry/ui/table.tsx +116 -0
  154. package/registry/ui/tabs.tsx +82 -0
  155. package/registry/ui/textarea.tsx +20 -0
  156. package/registry/ui/toast.tsx +250 -0
  157. package/registry/ui/toggle-group.tsx +89 -0
  158. package/registry/ui/toggle.tsx +45 -0
  159. package/registry/ui/tooltip.tsx +66 -0
  160. package/registry/ui/tracker.tsx +236 -0
  161. package/registry/ui/trend-indicator.tsx +62 -0
  162. package/skills/vantage-add-feature/SKILL.md +9 -7
  163. package/skills/vantage-design/SKILL.md +3 -1
  164. package/skills/vantage-design/references/format.md +1 -1
  165. package/skills/vantage-pitfalls/SKILL.md +5 -1
  166. package/skills/vantage-slide/SKILL.md +17 -0
  167. package/templates/AGENTS.md +10 -1
  168. package/templates/agents/api.md +29 -0
  169. package/templates/agents/csv.md +2 -1
  170. package/templates/agents/doc.md +4 -3
  171. package/templates/agents/page.md +22 -8
  172. package/templates/agents/slide.md +13 -1
  173. package/templates/agents/xlsx.md +2 -1
  174. package/theme.css +7 -1
  175. package/dist/add-DY4AXANK.js +0 -6
  176. package/dist/add-DY4AXANK.js.map +0 -1
  177. package/dist/chunk-BCE22JSM.js.map +0 -1
  178. package/dist/chunk-DTDVSFRY.js.map +0 -1
  179. package/dist/chunk-EP6JHXSR.js.map +0 -1
  180. package/dist/chunk-KLEIVDUV.js.map +0 -1
  181. package/dist/chunk-MP3QSOXL.js.map +0 -1
  182. package/dist/chunk-PVTHHV7X.js.map +0 -1
  183. package/dist/chunk-QI3XQKHS.js.map +0 -1
  184. package/dist/chunk-T3FLAGI6.js +0 -316
  185. package/dist/chunk-T3FLAGI6.js.map +0 -1
  186. package/dist/dev-FCEC3UKQ.js.map +0 -1
@@ -0,0 +1,250 @@
1
+ // Copied by `vantage add ui toast`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/ui/toast.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ "use client"
4
+
5
+ import * as React from "react"
6
+ import { Toast as ToastPrimitive } from "@base-ui/react/toast"
7
+ import { cn } from "@squadbase/vantage/ui"
8
+
9
+ import { Button } from "@squadbase/vantage/ui"
10
+ import { CircleCheckIcon, InfoIcon, Loader2Icon, OctagonXIcon, TriangleAlertIcon, XIcon } from "lucide-react"
11
+
12
+ const toast = ToastPrimitive.createToastManager()
13
+
14
+ function ToastProvider({ ...props }: ToastPrimitive.Provider.Props) {
15
+ return <ToastPrimitive.Provider {...props} />
16
+ }
17
+
18
+ function ToastPortal({ ...props }: ToastPrimitive.Portal.Props) {
19
+ return <ToastPrimitive.Portal data-slot="toast-portal" {...props} />
20
+ }
21
+
22
+ function ToastViewport({ className, ...props }: ToastPrimitive.Viewport.Props) {
23
+ return (
24
+ <ToastPrimitive.Viewport
25
+ data-slot="toast-viewport"
26
+ className={cn(
27
+ "pointer-events-none fixed inset-x-4 bottom-4 z-50 mx-auto w-auto max-w-sm outline-none sm:right-4 sm:left-auto sm:mx-0 sm:w-full",
28
+ className
29
+ )}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ function Toast({ className, ...props }: ToastPrimitive.Root.Props) {
36
+ return (
37
+ <ToastPrimitive.Root
38
+ data-slot="toast"
39
+ className={cn(
40
+ "group/toast pointer-events-auto absolute right-0 bottom-0 z-[calc(1000-var(--toast-index))] w-full origin-bottom rounded-2xl border bg-popover text-popover-foreground shadow-lg will-change-transform outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
41
+ "[--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))]",
42
+ "h-(--height) [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))] [transition:transform_500ms_cubic-bezier(0.22,1,0.36,1),opacity_500ms,height_150ms]",
43
+ "after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']",
44
+ "data-expanded:h-(--toast-height) data-expanded:[transform:translateX(var(--toast-swipe-movement-x))_translateY(var(--offset-y))]",
45
+ "data-limited:opacity-0 data-starting-style:[transform:translateY(150%)]",
46
+ "[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]",
47
+ "data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
48
+ "data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
49
+ "data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
50
+ "data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
51
+ "data-expanded:data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
52
+ "data-expanded:data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
53
+ "data-expanded:data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
54
+ "data-expanded:data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
55
+ className
56
+ )}
57
+ {...props}
58
+ />
59
+ )
60
+ }
61
+
62
+ function ToastContent({ className, ...props }: ToastPrimitive.Content.Props) {
63
+ return (
64
+ <ToastPrimitive.Content
65
+ data-slot="toast-content"
66
+ className={cn(
67
+ "flex h-full items-center gap-3 overflow-hidden p-4 transition-opacity duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] data-behind:opacity-0 data-expanded:opacity-100",
68
+ className
69
+ )}
70
+ {...props}
71
+ />
72
+ )
73
+ }
74
+
75
+ function ToastTitle({ className, ...props }: ToastPrimitive.Title.Props) {
76
+ return (
77
+ <ToastPrimitive.Title
78
+ data-slot="toast-title"
79
+ className={cn("text-sm font-medium", className)}
80
+ {...props}
81
+ />
82
+ )
83
+ }
84
+
85
+ function ToastDescription({
86
+ className,
87
+ ...props
88
+ }: ToastPrimitive.Description.Props) {
89
+ return (
90
+ <ToastPrimitive.Description
91
+ data-slot="toast-description"
92
+ className={cn("text-sm text-muted-foreground", className)}
93
+ {...props}
94
+ />
95
+ )
96
+ }
97
+
98
+ function ToastAction({
99
+ className,
100
+ render = <Button variant="outline" size="sm" />,
101
+ ...props
102
+ }: ToastPrimitive.Action.Props) {
103
+ return (
104
+ <ToastPrimitive.Action
105
+ data-slot="toast-action"
106
+ render={render}
107
+ className={cn("shrink-0", className)}
108
+ {...props}
109
+ />
110
+ )
111
+ }
112
+
113
+ function ToastClose({
114
+ className,
115
+ children,
116
+ render = <Button variant="ghost" size="icon-sm" />,
117
+ ...props
118
+ }: ToastPrimitive.Close.Props) {
119
+ return (
120
+ <ToastPrimitive.Close
121
+ data-slot="toast-close"
122
+ aria-label="Close toast"
123
+ render={render}
124
+ className={cn(
125
+ "relative shrink-0 text-muted-foreground after:absolute after:-inset-2 after:content-[''] hover:text-foreground",
126
+ className
127
+ )}
128
+ {...props}
129
+ >
130
+ {children ?? (
131
+ <XIcon
132
+ aria-hidden="true"
133
+ />
134
+ )}
135
+ </ToastPrimitive.Close>
136
+ )
137
+ }
138
+
139
+ function ToastIcon({ type }: { type: string | undefined }) {
140
+ let icon: React.ReactNode = null
141
+
142
+ if (type === "success") {
143
+ icon = (
144
+ <CircleCheckIcon
145
+ aria-hidden="true"
146
+ />
147
+ )
148
+ }
149
+
150
+ if (type === "info") {
151
+ icon = (
152
+ <InfoIcon
153
+ aria-hidden="true"
154
+ />
155
+ )
156
+ }
157
+
158
+ if (type === "warning") {
159
+ icon = (
160
+ <TriangleAlertIcon
161
+ aria-hidden="true"
162
+ />
163
+ )
164
+ }
165
+
166
+ if (type === "error") {
167
+ icon = (
168
+ <OctagonXIcon
169
+ className="text-destructive"
170
+ aria-hidden="true"
171
+ />
172
+ )
173
+ }
174
+
175
+ if (type === "loading") {
176
+ icon = (
177
+ <Loader2Icon
178
+ className="animate-spin"
179
+ aria-hidden="true"
180
+ />
181
+ )
182
+ }
183
+
184
+ if (!icon) {
185
+ return null
186
+ }
187
+
188
+ return (
189
+ <span
190
+ data-slot="toast-icon"
191
+ className="shrink-0 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4"
192
+ >
193
+ {icon}
194
+ </span>
195
+ )
196
+ }
197
+
198
+ function ToastList() {
199
+ const { toasts } = ToastPrimitive.useToastManager()
200
+
201
+ return toasts.map((toastItem) => (
202
+ <Toast key={toastItem.id} toast={toastItem}>
203
+ <ToastContent>
204
+ <ToastIcon type={toastItem.type} />
205
+ <div className="flex min-w-0 flex-1 flex-col gap-1">
206
+ <ToastTitle />
207
+ <ToastDescription />
208
+ </div>
209
+ <ToastAction />
210
+ <ToastClose />
211
+ </ToastContent>
212
+ </Toast>
213
+ ))
214
+ }
215
+
216
+ function Toaster({
217
+ children,
218
+ toastManager = toast,
219
+ ...props
220
+ }: ToastPrimitive.Provider.Props) {
221
+ return (
222
+ <ToastProvider toastManager={toastManager} {...props}>
223
+ {children}
224
+ <ToastPortal>
225
+ <ToastViewport>
226
+ <ToastList />
227
+ </ToastViewport>
228
+ </ToastPortal>
229
+ </ToastProvider>
230
+ )
231
+ }
232
+
233
+ const createToastManager = ToastPrimitive.createToastManager
234
+ const useToastManager = ToastPrimitive.useToastManager
235
+
236
+ export {
237
+ Toaster,
238
+ Toast,
239
+ ToastAction,
240
+ ToastClose,
241
+ ToastContent,
242
+ ToastDescription,
243
+ ToastPortal,
244
+ ToastProvider,
245
+ ToastTitle,
246
+ ToastViewport,
247
+ createToastManager,
248
+ toast,
249
+ useToastManager,
250
+ }
@@ -0,0 +1,89 @@
1
+ // Copied by `vantage add ui toggle-group`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/ui/toggle-group.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ import * as React from "react"
4
+ import { Toggle as TogglePrimitive } from "@base-ui/react/toggle"
5
+ import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group"
6
+ import { type VariantProps } from "class-variance-authority"
7
+
8
+ import { cn } from "@squadbase/vantage/ui"
9
+ import { toggleVariants } from "@squadbase/vantage/ui"
10
+
11
+ const ToggleGroupContext = React.createContext<
12
+ VariantProps<typeof toggleVariants> & {
13
+ spacing?: number
14
+ orientation?: "horizontal" | "vertical"
15
+ }
16
+ >({
17
+ size: "default",
18
+ variant: "default",
19
+ spacing: 2,
20
+ orientation: "horizontal",
21
+ })
22
+
23
+ function ToggleGroup({
24
+ className,
25
+ variant,
26
+ size,
27
+ spacing = 2,
28
+ orientation = "horizontal",
29
+ children,
30
+ ...props
31
+ }: ToggleGroupPrimitive.Props &
32
+ VariantProps<typeof toggleVariants> & {
33
+ spacing?: number
34
+ orientation?: "horizontal" | "vertical"
35
+ }) {
36
+ return (
37
+ <ToggleGroupPrimitive
38
+ data-slot="toggle-group"
39
+ data-variant={variant}
40
+ data-size={size}
41
+ data-spacing={spacing}
42
+ data-orientation={orientation}
43
+ style={{ "--gap": spacing } as React.CSSProperties}
44
+ className={cn(
45
+ "group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-vertical:flex-col data-vertical:items-stretch",
46
+ className
47
+ )}
48
+ {...props}
49
+ >
50
+ <ToggleGroupContext.Provider
51
+ value={{ variant, size, spacing, orientation }}
52
+ >
53
+ {children}
54
+ </ToggleGroupContext.Provider>
55
+ </ToggleGroupPrimitive>
56
+ )
57
+ }
58
+
59
+ function ToggleGroupItem({
60
+ className,
61
+ children,
62
+ variant = "default",
63
+ size = "default",
64
+ ...props
65
+ }: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
66
+ const context = React.useContext(ToggleGroupContext)
67
+
68
+ return (
69
+ <TogglePrimitive
70
+ data-slot="toggle-group-item"
71
+ data-variant={context.variant || variant}
72
+ data-size={context.size || size}
73
+ data-spacing={context.spacing}
74
+ className={cn(
75
+ "shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",
76
+ toggleVariants({
77
+ variant: context.variant || variant,
78
+ size: context.size || size,
79
+ }),
80
+ className
81
+ )}
82
+ {...props}
83
+ >
84
+ {children}
85
+ </TogglePrimitive>
86
+ )
87
+ }
88
+
89
+ export { ToggleGroup, ToggleGroupItem }
@@ -0,0 +1,45 @@
1
+ // Copied by `vantage add ui toggle`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/ui/toggle.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ import { Toggle as TogglePrimitive } from "@base-ui/react/toggle"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+
6
+ import { cn } from "@squadbase/vantage/ui"
7
+
8
+ const toggleVariants = cva(
9
+ "group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-[state=on]:bg-muted 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-transparent",
14
+ outline: "border border-input bg-transparent hover:bg-muted",
15
+ },
16
+ size: {
17
+ default:
18
+ "h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
19
+ sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
20
+ lg: "h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: "default",
25
+ size: "default",
26
+ },
27
+ }
28
+ )
29
+
30
+ function Toggle({
31
+ className,
32
+ variant = "default",
33
+ size = "default",
34
+ ...props
35
+ }: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
36
+ return (
37
+ <TogglePrimitive
38
+ data-slot="toggle"
39
+ className={cn(toggleVariants({ variant, size, className }))}
40
+ {...props}
41
+ />
42
+ )
43
+ }
44
+
45
+ export { Toggle, toggleVariants }
@@ -0,0 +1,66 @@
1
+ // Copied by `vantage add ui tooltip`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/ui/tooltip.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
4
+
5
+ import { cn } from "@squadbase/vantage/ui"
6
+
7
+ function TooltipProvider({
8
+ delay = 0,
9
+ ...props
10
+ }: TooltipPrimitive.Provider.Props) {
11
+ return (
12
+ <TooltipPrimitive.Provider
13
+ data-slot="tooltip-provider"
14
+ delay={delay}
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
21
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
22
+ }
23
+
24
+ function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
25
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
26
+ }
27
+
28
+ function TooltipContent({
29
+ className,
30
+ side = "top",
31
+ sideOffset = 4,
32
+ align = "center",
33
+ alignOffset = 0,
34
+ children,
35
+ ...props
36
+ }: TooltipPrimitive.Popup.Props &
37
+ Pick<
38
+ TooltipPrimitive.Positioner.Props,
39
+ "align" | "alignOffset" | "side" | "sideOffset"
40
+ >) {
41
+ return (
42
+ <TooltipPrimitive.Portal>
43
+ <TooltipPrimitive.Positioner
44
+ align={align}
45
+ alignOffset={alignOffset}
46
+ side={side}
47
+ sideOffset={sideOffset}
48
+ className="isolate z-50"
49
+ >
50
+ <TooltipPrimitive.Popup
51
+ data-slot="tooltip-content"
52
+ className={cn(
53
+ "z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 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-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
54
+ className
55
+ )}
56
+ {...props}
57
+ >
58
+ {children}
59
+ <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" />
60
+ </TooltipPrimitive.Popup>
61
+ </TooltipPrimitive.Positioner>
62
+ </TooltipPrimitive.Portal>
63
+ )
64
+ }
65
+
66
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -0,0 +1,236 @@
1
+ // Copied by `vantage add ui tracker`. This file is yours to edit.
2
+ // Generated from @squadbase/vantage src/components/tracker.tsx by `npm run registry` (in Vantage, edit src/, not registry/).
3
+ /**
4
+ * Tracker — a row of small blocks, one per period, each coloured by status:
5
+ * uptime per day, batch-job results, daily target hit/miss. Hover a block to
6
+ * see its tooltip. Plain HTML/CSS.
7
+ */
8
+ import { forwardRef, type ComponentProps } from "react"
9
+
10
+ import { cn } from "@squadbase/vantage/ui"
11
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@squadbase/vantage/ui"
12
+ import type { ChartColor } from "@squadbase/vantage/components"
13
+ import type { ValueFormatter } from "@squadbase/vantage/components"
14
+
15
+ /* ---------- inlined from src/components/chart-utils.ts (internal to @squadbase/vantage) ---------- */
16
+
17
+ /** The series tokens, in palette order — the default `colors` of every typed chart. */
18
+ const DEFAULT_CHART_COLORS: readonly ChartColor[] = [
19
+ "chart-1",
20
+ "chart-2",
21
+ "chart-3",
22
+ "chart-4",
23
+ "chart-5",
24
+ ]
25
+
26
+ const TOKEN_NAME_RE = /^chart-[1-5]$/
27
+
28
+ /**
29
+ * A chart colour as a CSS value: `"chart-2"` → `var(--chart-2)` (so it follows
30
+ * light/dark on its own), anything else passes through unchanged.
31
+ */
32
+ function chartColorToCss(color: ChartColor): string {
33
+ const value = color.trim()
34
+ return TOKEN_NAME_RE.test(value) ? `var(--${value})` : value
35
+ }
36
+
37
+ /** The `i`-th colour, cycling through `colors` (the token palette when empty). */
38
+ function chartColorAt(colors: readonly ChartColor[] | undefined, i: number): ChartColor {
39
+ const palette = colors && colors.length > 0 ? colors : DEFAULT_CHART_COLORS
40
+ return palette[i % palette.length]!
41
+ }
42
+
43
+ /** `colors` extended (by cycling) to exactly `count` entries. */
44
+ function chartColorsFor(colors: readonly ChartColor[] | undefined, count: number): ChartColor[] {
45
+ return Array.from({ length: count }, (_, i) => chartColorAt(colors, i))
46
+ }
47
+
48
+ /** A translucent version of a CSS colour (works for `var(--…)` too). */
49
+ function tintCss(cssColor: string, percent: number): string {
50
+ return `color-mix(in oklab, ${cssColor} ${percent}%, transparent)`
51
+ }
52
+
53
+ const numberFormat = new Intl.NumberFormat("ja-JP", { maximumFractionDigits: 2 })
54
+
55
+ /** Default `valueFormatter`: grouped digits, up to two decimals (`1,234.5`). */
56
+ const defaultValueFormatter: ValueFormatter = (value) => numberFormat.format(value)
57
+
58
+ /**
59
+ * A data cell as a number, or `null` for a gap. Numeric strings count — SQL
60
+ * `DECIMAL` / `BIGINT` columns usually arrive as strings.
61
+ */
62
+ function toChartNumber(value: unknown): number | null {
63
+ if (typeof value === "number") return Number.isFinite(value) ? value : null
64
+ if (typeof value === "bigint") return Number(value)
65
+ if (typeof value === "string" && value.trim() !== "") {
66
+ const n = Number(value)
67
+ return Number.isFinite(n) ? n : null
68
+ }
69
+ return null
70
+ }
71
+
72
+ /** Clamp `value` into `[min, max]`. */
73
+ function clamp(value: number, min: number, max: number): number {
74
+ return Math.min(max, Math.max(min, value))
75
+ }
76
+
77
+ /* ---------------------------------------------------------------- BarList */
78
+
79
+ type BarListSortOrder = "ascending" | "descending" | "none"
80
+
81
+ /** Sort a copy of the rows by value; `"none"` keeps the given order. */
82
+ function sortBarListData<T extends { value: number }>(data: readonly T[], sortOrder: BarListSortOrder): T[] {
83
+ const rows = [...data]
84
+ if (sortOrder === "ascending") rows.sort((a, b) => a.value - b.value)
85
+ else if (sortOrder === "descending") rows.sort((a, b) => b.value - a.value)
86
+ return rows
87
+ }
88
+
89
+ /** Bar widths in percent of the largest value (at least a sliver for non-zero values). */
90
+ function barListWidths(values: readonly number[]): number[] {
91
+ const max = Math.max(0, ...values)
92
+ if (max === 0) return values.map(() => 0)
93
+ return values.map((v) => (v <= 0 ? 0 : Math.max(1, (v / max) * 100)))
94
+ }
95
+
96
+ /* ------------------------------------------------------------ CategoryBar */
97
+
98
+ interface CategoryBarSegment {
99
+ /** Width in percent of the whole bar. */
100
+ width: number
101
+ /** Where the segment starts, in percent. */
102
+ start: number
103
+ /** The running total at the segment's end — what its right-hand label shows. */
104
+ end: number
105
+ }
106
+
107
+ /** Lay the values side by side; negative values count as zero. */
108
+ function categoryBarSegments(values: readonly number[]): CategoryBarSegment[] {
109
+ const clean = values.map((v) => (Number.isFinite(v) && v > 0 ? v : 0))
110
+ const total = clean.reduce((sum, v) => sum + v, 0)
111
+ let running = 0
112
+ return clean.map((v) => {
113
+ const start = total === 0 ? 0 : (running / total) * 100
114
+ running += v
115
+ return { width: total === 0 ? 0 : (v / total) * 100, start, end: running }
116
+ })
117
+ }
118
+
119
+ interface CategoryBarLabel {
120
+ /** Position in percent of the bar. */
121
+ position: number
122
+ /** The running total printed there. */
123
+ value: number
124
+ }
125
+
126
+ /**
127
+ * Tick labels under the bar: `0` at the start, then the running total at each
128
+ * segment's end. A label closer than `minGap` percent to the one before is
129
+ * dropped so narrow segments don't print on top of each other — except the
130
+ * last one (the total), which replaces its neighbour instead.
131
+ */
132
+ function categoryBarLabels(values: readonly number[], minGap = 8): CategoryBarLabel[] {
133
+ const segments = categoryBarSegments(values).filter((s) => s.width > 0)
134
+ if (segments.length === 0) return []
135
+ const labels: CategoryBarLabel[] = [{ position: 0, value: 0 }]
136
+ segments.forEach((s, i) => {
137
+ const label = { position: s.start + s.width, value: s.end }
138
+ const prev = labels[labels.length - 1]!
139
+ if (label.position - prev.position >= minGap) labels.push(label)
140
+ else if (i === segments.length - 1 && labels.length > 1) labels[labels.length - 1] = label
141
+ })
142
+ return labels
143
+ }
144
+
145
+ /** Marker position in percent of the bar, clamped to its ends. */
146
+ function categoryBarMarkerPosition(value: number, values: readonly number[]): number {
147
+ const total = values.reduce((sum, v) => sum + (Number.isFinite(v) && v > 0 ? v : 0), 0)
148
+ if (total === 0) return 0
149
+ return clamp((value / total) * 100, 0, 100)
150
+ }
151
+
152
+ /** Index of the segment the marker sits on (the last one for a value past the end). */
153
+ function categoryBarMarkerSegment(value: number, values: readonly number[]): number {
154
+ const segments = categoryBarSegments(values)
155
+ const index = segments.findIndex((s) => s.width > 0 && value <= s.end)
156
+ if (index !== -1) return index
157
+ for (let i = segments.length - 1; i >= 0; i--) if (segments[i]!.width > 0) return i
158
+ return 0
159
+ }
160
+
161
+ /* --------------------------------------------------------- ProgressCircle */
162
+
163
+ interface ProgressCircleGeometry {
164
+ /** SVG width/height. */
165
+ size: number
166
+ /** Radius of the stroke's centre line. */
167
+ normalizedRadius: number
168
+ circumference: number
169
+ /** `stroke-dashoffset` for the value arc. */
170
+ offset: number
171
+ /** The value as a fraction of `max`, clamped to `[0, 1]`. */
172
+ ratio: number
173
+ }
174
+
175
+ function progressCircleGeometry(
176
+ value: number,
177
+ max: number,
178
+ radius: number,
179
+ strokeWidth: number,
180
+ ): ProgressCircleGeometry {
181
+ const ratio = max > 0 && Number.isFinite(value) ? clamp(value / max, 0, 1) : 0
182
+ const normalizedRadius = Math.max(0, radius - strokeWidth / 2)
183
+ const circumference = 2 * Math.PI * normalizedRadius
184
+ return { size: radius * 2, normalizedRadius, circumference, offset: circumference * (1 - ratio), ratio }
185
+ }
186
+
187
+ /* ---------- end of inlined code ---------- */
188
+
189
+ export interface TrackerBlock {
190
+ /** React の key。省略時は位置。 */
191
+ key?: string | number
192
+ /** ブロックの色。`"chart-1"`〜`"chart-5"` か CSS カラー(`"var(--destructive)"` など)。省略時は `defaultColor`。 */
193
+ color?: ChartColor
194
+ /** ホバーで出す説明(例: `"10/12 稼働率 99.2%"`)。 */
195
+ tooltip?: string
196
+ }
197
+
198
+ export interface TrackerProps extends Omit<ComponentProps<"div">, "children"> {
199
+ data: TrackerBlock[]
200
+ /** `color` の無いブロックの色。既定は muted-foreground を淡くした灰色。 */
201
+ defaultColor?: ChartColor
202
+ /** ホバー中のブロックを薄くする。既定 `true`。 */
203
+ hoverEffect?: boolean
204
+ }
205
+
206
+ const DEFAULT_BLOCK_COLOR = "color-mix(in oklab, var(--muted-foreground) 35%, transparent)"
207
+
208
+ export const Tracker = forwardRef<HTMLDivElement, TrackerProps>(function Tracker(
209
+ { data, defaultColor, hoverEffect = true, className, ...props },
210
+ ref,
211
+ ) {
212
+ const fallback = defaultColor ? chartColorToCss(defaultColor) : DEFAULT_BLOCK_COLOR
213
+ return (
214
+ <div ref={ref} data-slot="tracker" className={cn("flex h-8 w-full gap-px", className)} {...props}>
215
+ {data.map((block, i) => {
216
+ const blockClass = cn(
217
+ "h-full min-w-0 flex-1 rounded-[1px] first:rounded-l-[4px] last:rounded-r-[4px]",
218
+ hoverEffect && "transition-opacity hover:opacity-60",
219
+ )
220
+ const style = { background: block.color ? chartColorToCss(block.color) : fallback }
221
+ return block.tooltip ? (
222
+ <Tooltip key={block.key ?? i}>
223
+ <TooltipTrigger
224
+ delay={0}
225
+ render={<div data-slot="tracker-block" aria-label={block.tooltip} className={blockClass} style={style} />}
226
+ />
227
+ <TooltipContent>{block.tooltip}</TooltipContent>
228
+ </Tooltip>
229
+ ) : (
230
+ <div key={block.key ?? i} data-slot="tracker-block" className={blockClass} style={style} />
231
+ )
232
+ })}
233
+ </div>
234
+ )
235
+ })
236
+ Tracker.displayName = "Tracker"