@squadbase/vantage 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +21 -4
  2. package/dist/chunk-A2UUGASH.js +12 -0
  3. package/dist/chunk-A2UUGASH.js.map +1 -0
  4. package/dist/{chunk-ZGDU5YLH.js → chunk-PRFBSQA4.js} +9 -5
  5. package/dist/chunk-PRFBSQA4.js.map +1 -0
  6. package/dist/chunk-WQZYXXQW.js +2249 -0
  7. package/dist/chunk-WQZYXXQW.js.map +1 -0
  8. package/dist/{chunk-73J5ZD4C.js → chunk-YLAB6UQS.js} +17 -3
  9. package/dist/chunk-YLAB6UQS.js.map +1 -0
  10. package/dist/cli.js +607 -36
  11. package/dist/cli.js.map +1 -1
  12. package/dist/components/index.d.ts +554 -0
  13. package/dist/components/index.js +1983 -0
  14. package/dist/components/index.js.map +1 -0
  15. package/dist/markdown/index.d.ts +9 -0
  16. package/dist/markdown/index.js +26 -0
  17. package/dist/markdown/index.js.map +1 -0
  18. package/dist/query/index.d.ts +27 -1
  19. package/dist/query/index.js +18 -0
  20. package/dist/query/index.js.map +1 -1
  21. package/dist/server/node.js +6 -1
  22. package/dist/server/node.js.map +1 -1
  23. package/dist/ui/index.d.ts +316 -200
  24. package/dist/ui/index.js +566 -511
  25. package/dist/ui/index.js.map +1 -1
  26. package/dist/vite/index.js +2 -2
  27. package/docs/en/agent-skills.md +89 -0
  28. package/docs/en/api-and-server.md +84 -0
  29. package/docs/en/build-and-deploy.md +280 -0
  30. package/docs/en/cli-reference.md +311 -0
  31. package/docs/en/components.md +233 -0
  32. package/docs/en/data-fetching.md +78 -0
  33. package/docs/en/environment-variables.md +69 -0
  34. package/docs/en/getting-started.md +95 -0
  35. package/docs/en/index.md +65 -0
  36. package/docs/en/markdown/markdown-renderer.md +44 -0
  37. package/docs/en/pages-and-metadata.md +56 -0
  38. package/docs/en/parts/app-shell.md +54 -0
  39. package/docs/en/parts/dashboard-card.md +64 -0
  40. package/docs/en/parts/data-table.md +86 -0
  41. package/docs/en/parts/date-range-picker.md +41 -0
  42. package/docs/en/parts/echart.md +53 -0
  43. package/docs/en/parts/filter-bar.md +66 -0
  44. package/docs/en/parts/funnel-steps.md +33 -0
  45. package/docs/en/parts/metric-value.md +23 -0
  46. package/docs/en/parts/multi-select.md +27 -0
  47. package/docs/en/parts/page-shell.md +45 -0
  48. package/docs/en/parts/searchable-select.md +47 -0
  49. package/docs/en/parts/section-header.md +20 -0
  50. package/docs/en/parts/segmented-control.md +25 -0
  51. package/docs/en/parts/status-badge.md +44 -0
  52. package/docs/en/parts/trend-indicator.md +26 -0
  53. package/docs/en/routing.md +95 -0
  54. package/docs/en/ui/accordion.md +36 -0
  55. package/docs/en/ui/alert.md +31 -0
  56. package/docs/en/ui/badge.md +23 -0
  57. package/docs/en/ui/breadcrumb.md +38 -0
  58. package/docs/en/ui/button.md +39 -0
  59. package/docs/en/ui/calendar.md +28 -0
  60. package/docs/en/ui/card.md +35 -0
  61. package/docs/en/ui/checkbox.md +34 -0
  62. package/docs/en/ui/cn.md +34 -0
  63. package/docs/en/ui/collapsible.md +21 -0
  64. package/docs/en/ui/command.md +37 -0
  65. package/docs/en/ui/dialog.md +52 -0
  66. package/docs/en/ui/dropdown-menu.md +50 -0
  67. package/docs/en/ui/empty.md +22 -0
  68. package/docs/en/ui/error-state.md +50 -0
  69. package/docs/en/ui/input-group.md +30 -0
  70. package/docs/en/ui/input.md +28 -0
  71. package/docs/en/ui/label.md +19 -0
  72. package/docs/en/ui/loading.md +19 -0
  73. package/docs/en/ui/popover.md +34 -0
  74. package/docs/en/ui/progress.md +28 -0
  75. package/docs/en/ui/scroll-area.md +23 -0
  76. package/docs/en/ui/select.md +63 -0
  77. package/docs/en/ui/separator.md +15 -0
  78. package/docs/en/ui/sheet.md +28 -0
  79. package/docs/en/ui/sidebar.md +92 -0
  80. package/docs/en/ui/skeleton.md +16 -0
  81. package/docs/en/ui/slider.md +21 -0
  82. package/docs/en/ui/spinner.md +14 -0
  83. package/docs/en/ui/switch.md +19 -0
  84. package/docs/en/ui/table.md +24 -0
  85. package/docs/en/ui/tabs.md +23 -0
  86. package/docs/en/ui/textarea.md +15 -0
  87. package/docs/en/ui/toggle-group.md +26 -0
  88. package/docs/en/ui/toggle.md +19 -0
  89. package/docs/en/ui/tooltip.md +22 -0
  90. package/docs/en/ui/use-is-mobile.md +18 -0
  91. package/docs/en/ui-and-theming.md +95 -0
  92. package/docs/index.json +1306 -0
  93. package/docs/ja/agent-skills.md +87 -0
  94. package/docs/ja/api-and-server.md +84 -0
  95. package/docs/ja/build-and-deploy.md +279 -0
  96. package/docs/ja/cli-reference.md +305 -0
  97. package/docs/ja/components.md +229 -0
  98. package/docs/ja/data-fetching.md +78 -0
  99. package/docs/ja/environment-variables.md +68 -0
  100. package/docs/ja/getting-started.md +95 -0
  101. package/docs/ja/index.md +65 -0
  102. package/docs/ja/markdown/markdown-renderer.md +43 -0
  103. package/docs/ja/pages-and-metadata.md +56 -0
  104. package/docs/ja/parts/app-shell.md +54 -0
  105. package/docs/ja/parts/dashboard-card.md +64 -0
  106. package/docs/ja/parts/data-table.md +85 -0
  107. package/docs/ja/parts/date-range-picker.md +41 -0
  108. package/docs/ja/parts/echart.md +52 -0
  109. package/docs/ja/parts/filter-bar.md +64 -0
  110. package/docs/ja/parts/funnel-steps.md +33 -0
  111. package/docs/ja/parts/metric-value.md +25 -0
  112. package/docs/ja/parts/multi-select.md +27 -0
  113. package/docs/ja/parts/page-shell.md +45 -0
  114. package/docs/ja/parts/searchable-select.md +47 -0
  115. package/docs/ja/parts/section-header.md +20 -0
  116. package/docs/ja/parts/segmented-control.md +26 -0
  117. package/docs/ja/parts/status-badge.md +44 -0
  118. package/docs/ja/parts/trend-indicator.md +26 -0
  119. package/docs/ja/routing.md +95 -0
  120. package/docs/ja/ui/accordion.md +37 -0
  121. package/docs/ja/ui/alert.md +31 -0
  122. package/docs/ja/ui/badge.md +23 -0
  123. package/docs/ja/ui/breadcrumb.md +38 -0
  124. package/docs/ja/ui/button.md +39 -0
  125. package/docs/ja/ui/calendar.md +28 -0
  126. package/docs/ja/ui/card.md +35 -0
  127. package/docs/ja/ui/checkbox.md +34 -0
  128. package/docs/ja/ui/cn.md +34 -0
  129. package/docs/ja/ui/collapsible.md +21 -0
  130. package/docs/ja/ui/command.md +36 -0
  131. package/docs/ja/ui/dialog.md +51 -0
  132. package/docs/ja/ui/dropdown-menu.md +50 -0
  133. package/docs/ja/ui/empty.md +22 -0
  134. package/docs/ja/ui/error-state.md +50 -0
  135. package/docs/ja/ui/input-group.md +30 -0
  136. package/docs/ja/ui/input.md +28 -0
  137. package/docs/ja/ui/label.md +19 -0
  138. package/docs/ja/ui/loading.md +19 -0
  139. package/docs/ja/ui/popover.md +34 -0
  140. package/docs/ja/ui/progress.md +28 -0
  141. package/docs/ja/ui/scroll-area.md +24 -0
  142. package/docs/ja/ui/select.md +64 -0
  143. package/docs/ja/ui/separator.md +15 -0
  144. package/docs/ja/ui/sheet.md +28 -0
  145. package/docs/ja/ui/sidebar.md +92 -0
  146. package/docs/ja/ui/skeleton.md +16 -0
  147. package/docs/ja/ui/slider.md +21 -0
  148. package/docs/ja/ui/spinner.md +14 -0
  149. package/docs/ja/ui/switch.md +19 -0
  150. package/docs/ja/ui/table.md +24 -0
  151. package/docs/ja/ui/tabs.md +24 -0
  152. package/docs/ja/ui/textarea.md +15 -0
  153. package/docs/ja/ui/toggle-group.md +27 -0
  154. package/docs/ja/ui/toggle.md +19 -0
  155. package/docs/ja/ui/tooltip.md +22 -0
  156. package/docs/ja/ui/use-is-mobile.md +18 -0
  157. package/docs/ja/ui-and-theming.md +95 -0
  158. package/package.json +29 -4
  159. package/registry/blocks/sales-overview.tsx +43 -19
  160. package/registry/ui/data-table.tsx +702 -102
  161. package/skills/vantage-add-feature/SKILL.md +150 -0
  162. package/skills/vantage-app/SKILL.md +258 -0
  163. package/skills/vantage-pitfalls/SKILL.md +115 -0
  164. package/templates/AGENTS.md +268 -0
  165. package/theme.css +178 -40
  166. package/dist/chunk-73J5ZD4C.js.map +0 -1
  167. package/dist/chunk-ZGDU5YLH.js.map +0 -1
@@ -0,0 +1,1983 @@
1
+ import { SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Button, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, Badge, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Skeleton, Checkbox } from '../chunk-WQZYXXQW.js';
2
+ import { cn } from '../chunk-A2UUGASH.js';
3
+ import { forwardRef, useRef, useState, useEffect, useCallback, Fragment, createContext, useMemo, useId, useContext } from 'react';
4
+ import { cva } from 'class-variance-authority';
5
+ import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
6
+ import { Check, Copy, Download, Search, ArrowUp, ArrowDown, ArrowUpDown, Columns3, CalendarIcon, ChevronDownIcon, Minus, ChevronRight, XIcon, LoaderIcon, CheckIcon, ChevronDown, X } from 'lucide-react';
7
+ import * as echarts from 'echarts';
8
+ import { flexRender, useReactTable, getPaginationRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
9
+ import { format, endOfDay, startOfDay, subDays, startOfMonth, subMonths, endOfMonth } from 'date-fns';
10
+ import { ja } from 'date-fns/locale';
11
+
12
+ // @squadbase/vantage — generated build. Do not edit.
13
+ var PageShell = forwardRef(
14
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "page-shell", className: cn("flex flex-col", className), ...props })
15
+ );
16
+ PageShell.displayName = "PageShell";
17
+ var PageShellHeader = forwardRef(
18
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
19
+ "div",
20
+ {
21
+ ref,
22
+ "data-slot": "page-shell-header",
23
+ className: cn(
24
+ "grid grid-cols-[1fr_auto] items-start gap-x-4 gap-y-6 border-b px-6 py-12",
25
+ className
26
+ ),
27
+ ...props
28
+ }
29
+ )
30
+ );
31
+ PageShellHeader.displayName = "PageShellHeader";
32
+ var PageShellHeading = forwardRef(
33
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "page-shell-heading", className: cn("min-w-0", className), ...props })
34
+ );
35
+ PageShellHeading.displayName = "PageShellHeading";
36
+ var PageShellTitle = forwardRef(
37
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38
+ "h1",
39
+ {
40
+ ref,
41
+ "data-slot": "page-shell-title",
42
+ className: cn("text-2xl font-bold tracking-tight text-foreground", className),
43
+ ...props
44
+ }
45
+ )
46
+ );
47
+ PageShellTitle.displayName = "PageShellTitle";
48
+ var PageShellDescription = forwardRef(
49
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
50
+ "p",
51
+ {
52
+ ref,
53
+ "data-slot": "page-shell-description",
54
+ className: cn("mt-1 text-sm text-muted-foreground", className),
55
+ ...props
56
+ }
57
+ )
58
+ );
59
+ PageShellDescription.displayName = "PageShellDescription";
60
+ var PageShellHeaderEnd = forwardRef(
61
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
62
+ "div",
63
+ {
64
+ ref,
65
+ "data-slot": "page-shell-header-end",
66
+ className: cn("flex shrink-0 flex-col items-end gap-2", className),
67
+ ...props
68
+ }
69
+ )
70
+ );
71
+ PageShellHeaderEnd.displayName = "PageShellHeaderEnd";
72
+ var PageShellMeta = forwardRef(
73
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ ref,
77
+ "data-slot": "page-shell-meta",
78
+ className: cn("text-sm text-muted-foreground", className),
79
+ ...props
80
+ }
81
+ )
82
+ );
83
+ PageShellMeta.displayName = "PageShellMeta";
84
+ var PageShellActions = forwardRef(
85
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
86
+ "div",
87
+ {
88
+ ref,
89
+ "data-slot": "page-shell-actions",
90
+ className: cn("flex items-center gap-2", className),
91
+ ...props
92
+ }
93
+ )
94
+ );
95
+ PageShellActions.displayName = "PageShellActions";
96
+ var PageShellSummary = forwardRef(
97
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
98
+ "div",
99
+ {
100
+ ref,
101
+ "data-slot": "page-shell-summary",
102
+ className: cn(
103
+ "col-span-full grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
104
+ className
105
+ ),
106
+ ...props
107
+ }
108
+ )
109
+ );
110
+ PageShellSummary.displayName = "PageShellSummary";
111
+ var pageShellSummaryCardVariants = cva(
112
+ "relative flex items-start gap-3 rounded-lg border bg-background px-4 py-3 text-sm [&>svg]:mt-0.5 [&>svg]:size-4 [&>svg]:shrink-0",
113
+ {
114
+ variants: {
115
+ accent: {
116
+ default: "text-card-foreground",
117
+ accent: "border-[var(--chart-1)]/30 bg-linear-to-r from-[var(--chart-1)]/5 to-[var(--chart-1)]/5 [&>svg]:text-[var(--chart-1)]",
118
+ amber: "border-amber-300 bg-amber-50 [&>svg]:text-amber-600 dark:border-amber-800 dark:bg-amber-950/50 dark:[&>svg]:text-amber-400",
119
+ blue: "border-blue-300 bg-blue-50 [&>svg]:text-blue-600 dark:border-blue-800 dark:bg-blue-950/50 dark:[&>svg]:text-blue-400",
120
+ emerald: "border-emerald-300 bg-emerald-50 [&>svg]:text-emerald-600 dark:border-emerald-800 dark:bg-emerald-950/50 dark:[&>svg]:text-emerald-400",
121
+ red: "border-red-300 bg-red-50 [&>svg]:text-red-600 dark:border-red-800 dark:bg-red-950/50 dark:[&>svg]:text-red-400",
122
+ violet: "border-violet-300 bg-violet-50 [&>svg]:text-violet-600 dark:border-violet-800 dark:bg-violet-950/50 dark:[&>svg]:text-violet-400",
123
+ orange: "border-orange-300 bg-orange-50 [&>svg]:text-orange-600 dark:border-orange-800 dark:bg-orange-950/50 dark:[&>svg]:text-orange-400",
124
+ cyan: "border-cyan-300 bg-cyan-50 [&>svg]:text-cyan-600 dark:border-cyan-800 dark:bg-cyan-950/50 dark:[&>svg]:text-cyan-400",
125
+ slate: "border-slate-300 bg-slate-50 [&>svg]:text-slate-600 dark:border-slate-800 dark:bg-slate-950/50 dark:[&>svg]:text-slate-400",
126
+ green: "border-green-300 bg-green-50 [&>svg]:text-green-600 dark:border-green-800 dark:bg-green-950/50 dark:[&>svg]:text-green-400",
127
+ teal: "border-teal-300 bg-teal-50 [&>svg]:text-teal-600 dark:border-teal-800 dark:bg-teal-950/50 dark:[&>svg]:text-teal-400",
128
+ sky: "border-sky-300 bg-sky-50 [&>svg]:text-sky-600 dark:border-sky-800 dark:bg-sky-950/50 dark:[&>svg]:text-sky-400",
129
+ indigo: "border-indigo-300 bg-indigo-50 [&>svg]:text-indigo-600 dark:border-indigo-800 dark:bg-indigo-950/50 dark:[&>svg]:text-indigo-400",
130
+ purple: "border-purple-300 bg-purple-50 [&>svg]:text-purple-600 dark:border-purple-800 dark:bg-purple-950/50 dark:[&>svg]:text-purple-400",
131
+ pink: "border-pink-300 bg-pink-50 [&>svg]:text-pink-600 dark:border-pink-800 dark:bg-pink-950/50 dark:[&>svg]:text-pink-400",
132
+ rose: "border-rose-300 bg-rose-50 [&>svg]:text-rose-600 dark:border-rose-800 dark:bg-rose-950/50 dark:[&>svg]:text-rose-400",
133
+ yellow: "border-yellow-300 bg-yellow-50 [&>svg]:text-yellow-600 dark:border-yellow-800 dark:bg-yellow-950/50 dark:[&>svg]:text-yellow-400",
134
+ lime: "border-lime-300 bg-lime-50 [&>svg]:text-lime-600 dark:border-lime-800 dark:bg-lime-950/50 dark:[&>svg]:text-lime-400",
135
+ gray: "border-gray-300 bg-gray-50 [&>svg]:text-gray-600 dark:border-gray-800 dark:bg-gray-950/50 dark:[&>svg]:text-gray-400",
136
+ zinc: "border-zinc-300 bg-zinc-50 [&>svg]:text-zinc-600 dark:border-zinc-800 dark:bg-zinc-950/50 dark:[&>svg]:text-zinc-400",
137
+ neutral: "border-neutral-300 bg-neutral-50 [&>svg]:text-neutral-600 dark:border-neutral-800 dark:bg-neutral-950/50 dark:[&>svg]:text-neutral-400",
138
+ stone: "border-stone-300 bg-stone-50 [&>svg]:text-stone-600 dark:border-stone-800 dark:bg-stone-950/50 dark:[&>svg]:text-stone-400",
139
+ fuchsia: "border-fuchsia-300 bg-fuchsia-50 [&>svg]:text-fuchsia-600 dark:border-fuchsia-800 dark:bg-fuchsia-950/50 dark:[&>svg]:text-fuchsia-400"
140
+ }
141
+ },
142
+ defaultVariants: {
143
+ accent: "default"
144
+ }
145
+ }
146
+ );
147
+ var PageShellSummaryCard = forwardRef(
148
+ ({ className, accent, ...props }, ref) => /* @__PURE__ */ jsx(
149
+ "div",
150
+ {
151
+ ref,
152
+ "data-slot": "page-shell-summary-card",
153
+ className: cn(pageShellSummaryCardVariants({ accent }), className),
154
+ ...props
155
+ }
156
+ )
157
+ );
158
+ PageShellSummaryCard.displayName = "PageShellSummaryCard";
159
+ var PageShellContent = forwardRef(
160
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
161
+ "div",
162
+ {
163
+ ref,
164
+ "data-slot": "page-shell-content",
165
+ className: cn("flex-1 p-6", className),
166
+ ...props
167
+ }
168
+ )
169
+ );
170
+ PageShellContent.displayName = "PageShellContent";
171
+ function flattenItems(item) {
172
+ if (item.children && item.children.length > 0) {
173
+ return item.children.flatMap(flattenItems);
174
+ }
175
+ return [item];
176
+ }
177
+ function NavSelect({
178
+ groups,
179
+ onNavigate
180
+ }) {
181
+ const allItems = groups.flatMap((g) => g.items.flatMap(flattenItems));
182
+ const currentValue = allItems.find((item) => item.isActive)?.href ?? "";
183
+ return /* @__PURE__ */ jsxs(
184
+ Select,
185
+ {
186
+ items: Object.fromEntries(allItems.map((item) => [item.href, item.label])),
187
+ value: currentValue,
188
+ onValueChange: (href) => {
189
+ if (href !== null) onNavigate(href);
190
+ },
191
+ children: [
192
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u30DA\u30FC\u30B8\u3092\u9078\u629E" }) }),
193
+ /* @__PURE__ */ jsx(SelectContent, { children: groups.map((group, index) => /* @__PURE__ */ jsxs(SelectGroup, { children: [
194
+ group.label && /* @__PURE__ */ jsx(SelectLabel, { children: group.label }),
195
+ group.items.flatMap(flattenItems).map((item) => /* @__PURE__ */ jsx(SelectItem, { value: item.href, disabled: item.disabled, children: item.label }, item.href))
196
+ ] }, group.label ?? index)) })
197
+ ]
198
+ }
199
+ );
200
+ }
201
+ function NavItemWithChildren({
202
+ item,
203
+ linkComponent: LinkComponent = "a"
204
+ }) {
205
+ return /* @__PURE__ */ jsxs(
206
+ Collapsible,
207
+ {
208
+ defaultOpen: item.isActive,
209
+ className: "group/collapsible",
210
+ render: /* @__PURE__ */ jsx(SidebarMenuItem, {}),
211
+ children: [
212
+ /* @__PURE__ */ jsxs(
213
+ CollapsibleTrigger,
214
+ {
215
+ render: /* @__PURE__ */ jsx(
216
+ SidebarMenuButton,
217
+ {
218
+ tooltip: item.label,
219
+ "aria-disabled": item.disabled,
220
+ className: cn(item.disabled && "pointer-events-none")
221
+ }
222
+ ),
223
+ children: [
224
+ item.icon && /* @__PURE__ */ jsx(item.icon, {}),
225
+ /* @__PURE__ */ jsx("span", { children: item.label }),
226
+ /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto transition-transform duration-200 group-data-open/collapsible:rotate-90" })
227
+ ]
228
+ }
229
+ ),
230
+ item.badge && /* @__PURE__ */ jsx(SidebarMenuBadge, { children: item.badge }),
231
+ /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarMenuSub, { children: item.children.map((child) => /* @__PURE__ */ jsx(SidebarMenuSubItem, { children: /* @__PURE__ */ jsxs(
232
+ SidebarMenuSubButton,
233
+ {
234
+ isActive: child.isActive,
235
+ render: /* @__PURE__ */ jsx(
236
+ LinkComponent,
237
+ {
238
+ href: child.href,
239
+ "aria-disabled": child.disabled,
240
+ tabIndex: child.disabled ? -1 : void 0,
241
+ className: cn(child.disabled && "pointer-events-none opacity-50")
242
+ }
243
+ ),
244
+ children: [
245
+ child.icon && /* @__PURE__ */ jsx(child.icon, {}),
246
+ /* @__PURE__ */ jsx("span", { children: child.label })
247
+ ]
248
+ }
249
+ ) }, child.href)) }) })
250
+ ]
251
+ }
252
+ );
253
+ }
254
+ function NavItemLink({
255
+ item,
256
+ linkComponent: LinkComponent = "a"
257
+ }) {
258
+ return /* @__PURE__ */ jsxs(SidebarMenuItem, { children: [
259
+ /* @__PURE__ */ jsxs(
260
+ SidebarMenuButton,
261
+ {
262
+ tooltip: item.label,
263
+ isActive: item.isActive,
264
+ render: /* @__PURE__ */ jsx(
265
+ LinkComponent,
266
+ {
267
+ href: item.href,
268
+ "aria-disabled": item.disabled,
269
+ tabIndex: item.disabled ? -1 : void 0,
270
+ className: cn(item.disabled && "pointer-events-none")
271
+ }
272
+ ),
273
+ children: [
274
+ item.icon && /* @__PURE__ */ jsx(item.icon, {}),
275
+ /* @__PURE__ */ jsx("span", { children: item.label })
276
+ ]
277
+ }
278
+ ),
279
+ item.badge && /* @__PURE__ */ jsx(SidebarMenuBadge, { children: item.badge })
280
+ ] });
281
+ }
282
+ var defaultNavigate = (href) => {
283
+ window.location.assign(href);
284
+ };
285
+ var AppShell = forwardRef((props, ref) => {
286
+ const {
287
+ variant = "sidebar",
288
+ groups,
289
+ actions,
290
+ header,
291
+ children,
292
+ className,
293
+ linkComponent,
294
+ onNavigate = defaultNavigate
295
+ } = props;
296
+ if (variant === "header") {
297
+ return /* @__PURE__ */ jsxs("div", { ref, "data-slot": "app-shell", className: cn("flex h-full flex-col", className), children: [
298
+ header !== void 0 ? header : /* @__PURE__ */ jsxs("header", { className: "flex h-14 shrink-0 items-center gap-3 border-b px-4", children: [
299
+ groups.length > 0 && /* @__PURE__ */ jsx(NavSelect, { groups, onNavigate }),
300
+ actions && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-2", children: actions })
301
+ ] }),
302
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto", children })
303
+ ] });
304
+ }
305
+ const { defaultOpen = true } = props;
306
+ return /* @__PURE__ */ jsxs(SidebarProvider, { defaultOpen, children: [
307
+ /* @__PURE__ */ jsxs(Sidebar, { "data-slot": "app-sidebar", collapsible: "offcanvas", children: [
308
+ /* @__PURE__ */ jsx(SidebarContent, { children: groups.map((group, index) => /* @__PURE__ */ jsxs(SidebarGroup, { children: [
309
+ group.label && /* @__PURE__ */ jsx(SidebarGroupLabel, { children: group.label }),
310
+ /* @__PURE__ */ jsx(SidebarMenu, { children: group.items.map(
311
+ (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(
312
+ NavItemWithChildren,
313
+ {
314
+ item,
315
+ linkComponent
316
+ },
317
+ item.href
318
+ ) : /* @__PURE__ */ jsx(NavItemLink, { item, linkComponent }, item.href)
319
+ ) })
320
+ ] }, group.label ?? index)) }),
321
+ actions && /* @__PURE__ */ jsx(SidebarFooter, { children: actions }),
322
+ /* @__PURE__ */ jsx(SidebarRail, {})
323
+ ] }),
324
+ /* @__PURE__ */ jsxs(SidebarInset, { ref, "data-slot": "app-shell", className, children: [
325
+ header !== void 0 ? header : /* @__PURE__ */ jsxs("header", { className: "flex h-14 shrink-0 items-center gap-2 border-b px-4", children: [
326
+ /* @__PURE__ */ jsx(SidebarTrigger, {}),
327
+ /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-4" })
328
+ ] }),
329
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto", children })
330
+ ] })
331
+ ] });
332
+ });
333
+ AppShell.displayName = "AppShell";
334
+ var headingStyles = {
335
+ h1: "text-3xl font-bold tracking-tight",
336
+ h2: "text-2xl font-semibold tracking-tight",
337
+ h3: "text-xl font-semibold",
338
+ h4: "text-lg font-semibold"
339
+ };
340
+ var SectionHeader = forwardRef(
341
+ ({ title, description, actions, className, as: Comp = "h2" }, ref) => /* @__PURE__ */ jsxs(
342
+ "div",
343
+ {
344
+ ref,
345
+ "data-slot": "section-header",
346
+ className: cn("flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", className),
347
+ children: [
348
+ /* @__PURE__ */ jsxs("div", { children: [
349
+ /* @__PURE__ */ jsx(Comp, { className: headingStyles[Comp], children: title }),
350
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
351
+ ] }),
352
+ actions && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: actions })
353
+ ]
354
+ }
355
+ )
356
+ );
357
+ SectionHeader.displayName = "SectionHeader";
358
+ var DashboardCard = forwardRef(
359
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
360
+ "div",
361
+ {
362
+ ref,
363
+ "data-slot": "dashboard-card",
364
+ className: cn(
365
+ "group rounded-lg border bg-card px-1 py-1 text-card-foreground",
366
+ className
367
+ ),
368
+ ...props
369
+ }
370
+ )
371
+ );
372
+ DashboardCard.displayName = "DashboardCard";
373
+ var DashboardCardHeader = forwardRef(
374
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
375
+ "div",
376
+ {
377
+ ref,
378
+ "data-slot": "dashboard-card-header",
379
+ className: cn("flex flex-row items-start justify-between gap-4 px-3 py-3", className),
380
+ ...props
381
+ }
382
+ )
383
+ );
384
+ DashboardCardHeader.displayName = "DashboardCardHeader";
385
+ var DashboardCardTitle = forwardRef(
386
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
387
+ "h3",
388
+ {
389
+ ref,
390
+ "data-slot": "dashboard-card-title",
391
+ className: cn("text-sm leading-none font-semibold tracking-tight", className),
392
+ ...props
393
+ }
394
+ )
395
+ );
396
+ DashboardCardTitle.displayName = "DashboardCardTitle";
397
+ var DashboardCardDescription = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
398
+ "p",
399
+ {
400
+ ref,
401
+ "data-slot": "dashboard-card-description",
402
+ className: cn("text-xs text-muted-foreground", className),
403
+ ...props
404
+ }
405
+ ));
406
+ DashboardCardDescription.displayName = "DashboardCardDescription";
407
+ var DashboardCardAction = forwardRef(
408
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
409
+ "div",
410
+ {
411
+ ref,
412
+ "data-slot": "dashboard-card-action",
413
+ className: cn("ml-auto shrink-0", className),
414
+ ...props
415
+ }
416
+ )
417
+ );
418
+ DashboardCardAction.displayName = "DashboardCardAction";
419
+ var DashboardCardContent = forwardRef(
420
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "dashboard-card-content", className: cn("p-3", className), ...props })
421
+ );
422
+ DashboardCardContent.displayName = "DashboardCardContent";
423
+ var DashboardCardFooter = forwardRef(
424
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
425
+ "div",
426
+ {
427
+ ref,
428
+ "data-slot": "dashboard-card-footer",
429
+ className: cn("flex items-center px-3 py-1.5", className),
430
+ ...props
431
+ }
432
+ )
433
+ );
434
+ DashboardCardFooter.displayName = "DashboardCardFooter";
435
+ function DashboardCardSkeleton({ className }) {
436
+ return /* @__PURE__ */ jsxs(
437
+ "div",
438
+ {
439
+ "data-slot": "dashboard-card-skeleton",
440
+ className: cn("rounded-lg border bg-card p-6 shadow-sm", className),
441
+ children: [
442
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 pb-4", children: [
443
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-32" }),
444
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-8 rounded-md" })
445
+ ] }),
446
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }),
447
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-4 w-3/4" })
448
+ ]
449
+ }
450
+ );
451
+ }
452
+ function DashboardCardPreset({
453
+ title,
454
+ description,
455
+ actions,
456
+ footer,
457
+ children,
458
+ headerClassName,
459
+ contentClassName,
460
+ footerClassName,
461
+ className,
462
+ ...props
463
+ }) {
464
+ const hasHeader = title || description || actions;
465
+ return /* @__PURE__ */ jsxs(DashboardCard, { className, ...props, children: [
466
+ hasHeader && /* @__PURE__ */ jsxs(DashboardCardHeader, { className: headerClassName, children: [
467
+ (title || description) && /* @__PURE__ */ jsxs("div", { children: [
468
+ title && /* @__PURE__ */ jsx(DashboardCardTitle, { children: title }),
469
+ description && /* @__PURE__ */ jsx(DashboardCardDescription, { children: description })
470
+ ] }),
471
+ actions && /* @__PURE__ */ jsx(DashboardCardAction, { children: actions })
472
+ ] }),
473
+ children && /* @__PURE__ */ jsx(DashboardCardContent, { className: contentClassName, children }),
474
+ footer && /* @__PURE__ */ jsx(DashboardCardFooter, { className: footerClassName, children: footer })
475
+ ] });
476
+ }
477
+ var EChart = forwardRef(function EChart2({
478
+ option,
479
+ height,
480
+ loading = false,
481
+ theme,
482
+ onEvents,
483
+ ariaLabel,
484
+ className,
485
+ actions = false,
486
+ fileName = "chart.png"
487
+ }, ref) {
488
+ const containerRef = useRef(null);
489
+ const [instance, setInstance] = useState(null);
490
+ const [copied, setCopied] = useState(false);
491
+ useEffect(() => {
492
+ const container = containerRef.current;
493
+ if (!container) return;
494
+ const inst = echarts.init(container, theme, { renderer: "canvas" });
495
+ setInstance(inst);
496
+ const observer = new ResizeObserver(() => inst.resize());
497
+ observer.observe(container);
498
+ return () => {
499
+ observer.disconnect();
500
+ inst.dispose();
501
+ };
502
+ }, [theme]);
503
+ useEffect(() => {
504
+ if (!instance) return;
505
+ instance.setOption(option, { notMerge: true, lazyUpdate: true });
506
+ }, [instance, option]);
507
+ useEffect(() => {
508
+ if (!instance) return;
509
+ if (loading) instance.showLoading();
510
+ else instance.hideLoading();
511
+ }, [instance, loading]);
512
+ useEffect(() => {
513
+ if (!instance || !onEvents) return;
514
+ const entries = Object.entries(onEvents);
515
+ for (const [event, handler] of entries) {
516
+ instance.on(event, handler);
517
+ }
518
+ return () => {
519
+ if (instance.isDisposed()) return;
520
+ for (const [event, handler] of entries) {
521
+ instance.off(event, handler);
522
+ }
523
+ };
524
+ }, [instance, onEvents]);
525
+ const getPngDataUrl = useCallback(() => {
526
+ if (!instance) return null;
527
+ const pageBg = getComputedStyle(document.documentElement).backgroundColor;
528
+ return instance.getDataURL({
529
+ type: "png",
530
+ pixelRatio: 2,
531
+ backgroundColor: pageBg && pageBg !== "rgba(0, 0, 0, 0)" ? pageBg : "#ffffff"
532
+ });
533
+ }, [instance]);
534
+ const handleCopy = useCallback(async () => {
535
+ const dataUrl = getPngDataUrl();
536
+ if (!dataUrl) return;
537
+ try {
538
+ const blob = await (await fetch(dataUrl)).blob();
539
+ await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
540
+ setCopied(true);
541
+ setTimeout(() => setCopied(false), 2e3);
542
+ } catch {
543
+ }
544
+ }, [getPngDataUrl]);
545
+ const handleDownload = useCallback(() => {
546
+ const dataUrl = getPngDataUrl();
547
+ if (!dataUrl) return;
548
+ const link = document.createElement("a");
549
+ link.href = dataUrl;
550
+ link.download = fileName;
551
+ link.click();
552
+ }, [getPngDataUrl, fileName]);
553
+ const styleHeight = height == null ? void 0 : typeof height === "number" ? `${height}px` : height;
554
+ return /* @__PURE__ */ jsxs(
555
+ "div",
556
+ {
557
+ ref,
558
+ "data-slot": "echart",
559
+ className: cn("group relative w-full", height == null && "h-[400px]", className),
560
+ style: styleHeight != null ? { height: styleHeight } : void 0,
561
+ role: "img",
562
+ "aria-label": ariaLabel ?? "\u30C1\u30E3\u30FC\u30C8",
563
+ children: [
564
+ /* @__PURE__ */ jsx("div", { ref: containerRef, "data-slot": "echart-canvas", className: "h-full w-full" }),
565
+ actions && /* @__PURE__ */ jsxs(
566
+ "div",
567
+ {
568
+ "data-slot": "echart-actions",
569
+ className: "absolute top-2 right-2 z-10 flex gap-1 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100",
570
+ children: [
571
+ /* @__PURE__ */ jsx(
572
+ Button,
573
+ {
574
+ type: "button",
575
+ variant: "ghost",
576
+ size: "icon-sm",
577
+ onClick: handleCopy,
578
+ "aria-label": copied ? "\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F" : "PNG \u3092\u30AF\u30EA\u30C3\u30D7\u30DC\u30FC\u30C9\u306B\u30B3\u30D4\u30FC",
579
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-4" }) : /* @__PURE__ */ jsx(Copy, { className: "size-4" })
580
+ }
581
+ ),
582
+ /* @__PURE__ */ jsx(
583
+ Button,
584
+ {
585
+ type: "button",
586
+ variant: "ghost",
587
+ size: "icon-sm",
588
+ onClick: handleDownload,
589
+ "aria-label": "PNG \u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9",
590
+ children: /* @__PURE__ */ jsx(Download, { className: "size-4" })
591
+ }
592
+ )
593
+ ]
594
+ }
595
+ )
596
+ ]
597
+ }
598
+ );
599
+ });
600
+ EChart.displayName = "EChart";
601
+ var DEFAULT_COLORS = [
602
+ "bg-chart-1",
603
+ "bg-chart-2",
604
+ "bg-chart-3",
605
+ "bg-chart-4",
606
+ "bg-chart-5"
607
+ ];
608
+ var funnelStepsVariants = cva("flex w-full", {
609
+ variants: {
610
+ size: {
611
+ sm: "",
612
+ md: "",
613
+ lg: ""
614
+ },
615
+ direction: {
616
+ vertical: "flex-col",
617
+ horizontal: "flex-row"
618
+ }
619
+ },
620
+ compoundVariants: [
621
+ { direction: "vertical", size: "sm", className: "gap-1" },
622
+ { direction: "vertical", size: "md", className: "gap-1.5" },
623
+ { direction: "vertical", size: "lg", className: "gap-2" },
624
+ { direction: "horizontal", size: "sm", className: "gap-2" },
625
+ { direction: "horizontal", size: "md", className: "gap-3" },
626
+ { direction: "horizontal", size: "lg", className: "gap-4" }
627
+ ],
628
+ defaultVariants: {
629
+ size: "md",
630
+ direction: "vertical"
631
+ }
632
+ });
633
+ var funnelBarVariants = cva("rounded-sm transition-[width] ease-out", {
634
+ variants: {
635
+ size: {
636
+ sm: "h-6",
637
+ md: "h-8",
638
+ lg: "h-10"
639
+ }
640
+ },
641
+ defaultVariants: {
642
+ size: "md"
643
+ }
644
+ });
645
+ var funnelBarContainerHorizontalVariants = cva(
646
+ "relative flex w-full items-end overflow-hidden rounded-sm bg-muted",
647
+ {
648
+ variants: {
649
+ size: {
650
+ sm: "h-20",
651
+ md: "h-28",
652
+ lg: "h-36"
653
+ }
654
+ },
655
+ defaultVariants: {
656
+ size: "md"
657
+ }
658
+ }
659
+ );
660
+ var funnelLabelVariants = cva("flex w-full items-center justify-between text-muted-foreground", {
661
+ variants: {
662
+ size: {
663
+ sm: "text-xs",
664
+ md: "text-sm",
665
+ lg: "text-sm"
666
+ }
667
+ },
668
+ defaultVariants: {
669
+ size: "md"
670
+ }
671
+ });
672
+ var funnelConversionVariants = cva("flex items-center text-muted-foreground", {
673
+ variants: {
674
+ size: {
675
+ sm: "text-[10px]",
676
+ md: "text-xs",
677
+ lg: "text-xs"
678
+ },
679
+ direction: {
680
+ vertical: "justify-end",
681
+ horizontal: "shrink-0 justify-center self-center"
682
+ }
683
+ },
684
+ compoundVariants: [
685
+ { direction: "vertical", size: "sm", className: "py-0" },
686
+ { direction: "vertical", size: "md", className: "py-0.5" },
687
+ { direction: "vertical", size: "lg", className: "py-0.5" }
688
+ ],
689
+ defaultVariants: {
690
+ size: "md",
691
+ direction: "vertical"
692
+ }
693
+ });
694
+ function defaultFormatValue(value) {
695
+ return value.toLocaleString();
696
+ }
697
+ function computeConversionRate(current, previous) {
698
+ if (previous === 0) return "--";
699
+ return `${(current / previous * 100).toFixed(1)}%`;
700
+ }
701
+ var FunnelSteps = forwardRef(function FunnelSteps2({
702
+ data,
703
+ showConversion = false,
704
+ formatValue = defaultFormatValue,
705
+ animate = false,
706
+ size = "md",
707
+ direction = "vertical",
708
+ className,
709
+ ...props
710
+ }, ref) {
711
+ const [mounted, setMounted] = useState(false);
712
+ const isHorizontal = direction === "horizontal";
713
+ useEffect(() => {
714
+ if (animate) setMounted(true);
715
+ }, [animate]);
716
+ const maxValue = data.length > 0 ? data[0].value : 0;
717
+ return /* @__PURE__ */ jsx(
718
+ "div",
719
+ {
720
+ ref,
721
+ "data-slot": "funnel-steps",
722
+ role: "list",
723
+ "aria-label": "\u30D5\u30A1\u30CD\u30EB",
724
+ className: cn(funnelStepsVariants({ size, direction }), className),
725
+ ...props,
726
+ children: data.map((step, index) => {
727
+ const percentage = maxValue > 0 ? step.value / maxValue * 100 : 0;
728
+ const barSize = step.value > 0 && percentage < 2 ? 2 : percentage;
729
+ const color = step.color ?? DEFAULT_COLORS[index % DEFAULT_COLORS.length];
730
+ const isClickable = !!step.onClick;
731
+ const barInteractionProps = isClickable ? {
732
+ role: "button",
733
+ tabIndex: 0,
734
+ onClick: step.onClick,
735
+ onKeyDown: (e) => {
736
+ if (e.key === "Enter" || e.key === " ") {
737
+ e.preventDefault();
738
+ step.onClick?.();
739
+ }
740
+ }
741
+ } : {};
742
+ const barInteractionClasses = isClickable ? "cursor-pointer hover:brightness-110 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none" : void 0;
743
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
744
+ isHorizontal ? /* @__PURE__ */ jsxs(
745
+ "div",
746
+ {
747
+ role: "listitem",
748
+ className: "flex min-w-0 flex-1 flex-col items-center gap-1",
749
+ "aria-label": `${step.label}: ${formatValue(step.value)}`,
750
+ children: [
751
+ /* @__PURE__ */ jsx(
752
+ "span",
753
+ {
754
+ "data-slot": "funnel-value",
755
+ className: cn(
756
+ "text-muted-foreground tabular-nums",
757
+ size === "sm" ? "text-xs" : "text-sm"
758
+ ),
759
+ children: formatValue(step.value)
760
+ }
761
+ ),
762
+ /* @__PURE__ */ jsx("div", { className: funnelBarContainerHorizontalVariants({ size }), children: /* @__PURE__ */ jsx(
763
+ "div",
764
+ {
765
+ ...barInteractionProps,
766
+ className: cn(
767
+ "w-full rounded-sm transition-[height] ease-out",
768
+ color,
769
+ barInteractionClasses
770
+ ),
771
+ style: {
772
+ height: animate ? mounted ? `${barSize}%` : "0%" : `${barSize}%`,
773
+ transitionDuration: "0.5s",
774
+ transitionDelay: animate ? `${index * 0.08}s` : void 0
775
+ }
776
+ }
777
+ ) }),
778
+ /* @__PURE__ */ jsx(
779
+ "span",
780
+ {
781
+ className: cn(
782
+ "w-full truncate text-center text-muted-foreground",
783
+ size === "sm" ? "text-[10px]" : "text-xs"
784
+ ),
785
+ children: step.label
786
+ }
787
+ )
788
+ ]
789
+ }
790
+ ) : /* @__PURE__ */ jsxs("div", { role: "listitem", "aria-label": `${step.label}: ${formatValue(step.value)}`, children: [
791
+ /* @__PURE__ */ jsxs("div", { className: funnelLabelVariants({ size }), children: [
792
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: step.label }),
793
+ /* @__PURE__ */ jsx("span", { "data-slot": "funnel-value", className: "tabular-nums", children: formatValue(step.value) })
794
+ ] }),
795
+ /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-hidden rounded-sm bg-muted", children: /* @__PURE__ */ jsx(
796
+ "div",
797
+ {
798
+ ...barInteractionProps,
799
+ className: cn(funnelBarVariants({ size }), color, barInteractionClasses),
800
+ style: {
801
+ width: animate ? mounted ? `${barSize}%` : "0%" : `${barSize}%`,
802
+ transitionDuration: "0.5s",
803
+ transitionDelay: animate ? `${index * 0.08}s` : void 0
804
+ }
805
+ }
806
+ ) })
807
+ ] }),
808
+ showConversion && index < data.length - 1 && /* @__PURE__ */ jsx("div", { className: funnelConversionVariants({ size, direction }), "aria-hidden": "true", children: /* @__PURE__ */ jsxs("span", { children: [
809
+ "\u2192 ",
810
+ computeConversionRate(data[index + 1].value, step.value)
811
+ ] }) })
812
+ ] }, index);
813
+ })
814
+ }
815
+ );
816
+ });
817
+ FunnelSteps.displayName = "FunnelSteps";
818
+ function useControlledState(controlledValue, defaultValue, onChange) {
819
+ const [internalValue, setInternalValue] = useState(defaultValue);
820
+ const isControlled = controlledValue !== void 0;
821
+ const value = isControlled ? controlledValue : internalValue;
822
+ const setValue = useCallback(
823
+ (updaterOrValue) => {
824
+ onChange?.(updaterOrValue);
825
+ if (!isControlled) {
826
+ setInternalValue(updaterOrValue);
827
+ }
828
+ },
829
+ [onChange, isControlled]
830
+ );
831
+ return [value, setValue];
832
+ }
833
+ var DataTableContext = createContext(null);
834
+ function useDataTable() {
835
+ const ctx = useContext(DataTableContext);
836
+ if (!ctx) throw new Error("useDataTable must be used inside <DataTable>");
837
+ return ctx;
838
+ }
839
+ function DataTable({
840
+ columns,
841
+ data,
842
+ enableSorting = true,
843
+ sorting: sortingProp,
844
+ onSortingChange,
845
+ enableFiltering = false,
846
+ columnFilters: columnFiltersProp,
847
+ onColumnFiltersChange,
848
+ globalFilter: globalFilterProp,
849
+ onGlobalFilterChange,
850
+ enablePagination = false,
851
+ pagination: paginationProp,
852
+ onPaginationChange,
853
+ pageCount,
854
+ enableRowSelection = false,
855
+ rowSelection: rowSelectionProp,
856
+ onRowSelectionChange,
857
+ columnVisibility: columnVisibilityProp,
858
+ onColumnVisibilityChange,
859
+ meta,
860
+ className,
861
+ children
862
+ }) {
863
+ const [sorting, setSorting] = useControlledState(sortingProp, [], onSortingChange);
864
+ const [columnFilters, setColumnFilters] = useControlledState(
865
+ columnFiltersProp,
866
+ [],
867
+ onColumnFiltersChange
868
+ );
869
+ const [globalFilter, setGlobalFilter] = useControlledState(
870
+ globalFilterProp,
871
+ "",
872
+ onGlobalFilterChange
873
+ );
874
+ const [rowSelection, setRowSelection] = useControlledState(
875
+ rowSelectionProp,
876
+ {},
877
+ onRowSelectionChange
878
+ );
879
+ const [columnVisibility, setColumnVisibility] = useControlledState(
880
+ columnVisibilityProp,
881
+ {},
882
+ onColumnVisibilityChange
883
+ );
884
+ const [pagination, setPagination] = useControlledState(
885
+ paginationProp,
886
+ { pageIndex: 0, pageSize: 10 },
887
+ onPaginationChange
888
+ );
889
+ const allColumns = useMemo(() => {
890
+ if (!enableRowSelection) return columns;
891
+ const selectionColumn = {
892
+ id: "_select",
893
+ header: ({ table: table2 }) => /* @__PURE__ */ jsx(
894
+ Checkbox,
895
+ {
896
+ checked: table2.getIsAllPageRowsSelected(),
897
+ indeterminate: table2.getIsSomePageRowsSelected(),
898
+ onCheckedChange: (checked) => table2.toggleAllPageRowsSelected(checked),
899
+ "aria-label": "\u5168\u3066\u9078\u629E"
900
+ }
901
+ ),
902
+ cell: ({ row }) => /* @__PURE__ */ jsx(
903
+ Checkbox,
904
+ {
905
+ checked: row.getIsSelected(),
906
+ onCheckedChange: (checked) => row.toggleSelected(checked),
907
+ "aria-label": "\u884C\u3092\u9078\u629E"
908
+ }
909
+ ),
910
+ enableSorting: false,
911
+ enableHiding: false
912
+ };
913
+ return [selectionColumn, ...columns];
914
+ }, [columns, enableRowSelection]);
915
+ const table = useReactTable({
916
+ data,
917
+ columns: allColumns,
918
+ state: {
919
+ sorting,
920
+ columnFilters,
921
+ globalFilter,
922
+ rowSelection,
923
+ columnVisibility,
924
+ ...enablePagination ? { pagination } : {}
925
+ },
926
+ enableSorting,
927
+ enableRowSelection,
928
+ onSortingChange: setSorting,
929
+ onColumnFiltersChange: setColumnFilters,
930
+ onGlobalFilterChange: setGlobalFilter,
931
+ onRowSelectionChange: setRowSelection,
932
+ onColumnVisibilityChange: setColumnVisibility,
933
+ ...enablePagination ? { onPaginationChange: setPagination } : {},
934
+ ...pageCount !== void 0 ? { pageCount, manualPagination: true } : {},
935
+ getCoreRowModel: getCoreRowModel(),
936
+ getSortedRowModel: getSortedRowModel(),
937
+ getFilteredRowModel: getFilteredRowModel(),
938
+ ...enablePagination ? { getPaginationRowModel: getPaginationRowModel() } : {},
939
+ meta
940
+ });
941
+ const selectedRows = useMemo(
942
+ () => table.getFilteredSelectedRowModel().rows.map((row) => row.original),
943
+ // `table` is a stable reference, so the selection state is the real input.
944
+ // eslint-disable-next-line react-hooks/exhaustive-deps
945
+ [rowSelection, data]
946
+ );
947
+ const hasSelection = selectedRows.length > 0;
948
+ const contextValue = useMemo(
949
+ () => ({
950
+ table,
951
+ selectedRows,
952
+ hasSelection,
953
+ globalFilter,
954
+ setGlobalFilter,
955
+ enableFiltering,
956
+ enablePagination,
957
+ enableRowSelection,
958
+ visibleColumnCount: allColumns.length
959
+ }),
960
+ // `useReactTable` returns the same object every render, so each piece of
961
+ // table state has to be tracked explicitly to re-render the consumers.
962
+ // eslint-disable-next-line react-hooks/exhaustive-deps
963
+ [
964
+ table,
965
+ selectedRows,
966
+ hasSelection,
967
+ globalFilter,
968
+ setGlobalFilter,
969
+ enableFiltering,
970
+ enablePagination,
971
+ enableRowSelection,
972
+ allColumns.length,
973
+ sorting,
974
+ columnFilters,
975
+ columnVisibility,
976
+ pagination,
977
+ rowSelection
978
+ ]
979
+ );
980
+ return /* @__PURE__ */ jsx(DataTableContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { "data-slot": "data-table", className: cn("space-y-4", className), children }) });
981
+ }
982
+ DataTable.displayName = "DataTable";
983
+ var DataTableToolbar = forwardRef(
984
+ ({ showSearch, toolbar, bulkActions, className, ...props }, ref) => {
985
+ const { globalFilter, setGlobalFilter, hasSelection, selectedRows, enableFiltering } = useDataTable();
986
+ const showSearchEffective = showSearch ?? enableFiltering;
987
+ const hasContent = showSearchEffective || toolbar != null || hasSelection && bulkActions != null;
988
+ if (!hasContent) return null;
989
+ return /* @__PURE__ */ jsxs(
990
+ "div",
991
+ {
992
+ ref,
993
+ "data-slot": "data-table-toolbar",
994
+ className: cn("flex flex-wrap items-center gap-2", className),
995
+ ...props,
996
+ children: [
997
+ showSearchEffective && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
998
+ /* @__PURE__ */ jsx(Search, { className: "absolute top-2.5 left-2.5 size-4 text-muted-foreground" }),
999
+ /* @__PURE__ */ jsx(
1000
+ Input,
1001
+ {
1002
+ value: globalFilter,
1003
+ onChange: (e) => setGlobalFilter(e.target.value),
1004
+ className: "max-w-sm pl-8"
1005
+ }
1006
+ )
1007
+ ] }),
1008
+ toolbar,
1009
+ hasSelection && bulkActions && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-2", children: bulkActions(selectedRows) })
1010
+ ]
1011
+ }
1012
+ );
1013
+ }
1014
+ );
1015
+ DataTableToolbar.displayName = "DataTableToolbar";
1016
+ var DataTableContent = forwardRef(
1017
+ ({ className, ...props }, ref) => {
1018
+ const { table, visibleColumnCount } = useDataTable();
1019
+ return /* @__PURE__ */ jsx(
1020
+ "div",
1021
+ {
1022
+ ref,
1023
+ "data-slot": "data-table-content",
1024
+ className: cn("overflow-x-auto", className),
1025
+ ...props,
1026
+ children: /* @__PURE__ */ jsxs(Table, { children: [
1027
+ /* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx(TableHead, { children: header.isPlaceholder ? null : header.column.getCanSort() ? /* @__PURE__ */ jsxs(
1028
+ "button",
1029
+ {
1030
+ type: "button",
1031
+ className: "inline-flex items-center gap-1 rounded hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none",
1032
+ onClick: header.column.getToggleSortingHandler(),
1033
+ "aria-sort": header.column.getIsSorted() === "asc" ? "ascending" : header.column.getIsSorted() === "desc" ? "descending" : "none",
1034
+ children: [
1035
+ flexRender(header.column.columnDef.header, header.getContext()),
1036
+ header.column.getIsSorted() === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-4" }) : header.column.getIsSorted() === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "size-4" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "size-4 text-muted-foreground" })
1037
+ ]
1038
+ }
1039
+ ) : flexRender(header.column.columnDef.header, header.getContext()) }, header.id)) }, headerGroup.id)) }),
1040
+ /* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(TableRow, { "data-state": row.getIsSelected() ? "selected" : void 0, children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id)) }, row.id)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
1041
+ TableCell,
1042
+ {
1043
+ colSpan: visibleColumnCount,
1044
+ className: "h-24 text-center text-muted-foreground",
1045
+ children: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093"
1046
+ }
1047
+ ) }) })
1048
+ ] })
1049
+ }
1050
+ );
1051
+ }
1052
+ );
1053
+ DataTableContent.displayName = "DataTableContent";
1054
+ var DataTablePagination = forwardRef(
1055
+ ({ pageSizeOptions = [10, 20, 50], className, ...props }, ref) => {
1056
+ const { table } = useDataTable();
1057
+ const totalRows = table.getFilteredRowModel().rows.length;
1058
+ const currentPageSize = table.getState().pagination.pageSize;
1059
+ const currentPageIndex = table.getState().pagination.pageIndex;
1060
+ const rangeStart = currentPageIndex * currentPageSize + 1;
1061
+ const rangeEnd = Math.min((currentPageIndex + 1) * currentPageSize, totalRows);
1062
+ return /* @__PURE__ */ jsxs(
1063
+ "div",
1064
+ {
1065
+ ref,
1066
+ "data-slot": "data-table-pagination",
1067
+ className: cn("flex flex-wrap items-center justify-between gap-4", className),
1068
+ ...props,
1069
+ children: [
1070
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
1071
+ /* @__PURE__ */ jsxs("span", { children: [
1072
+ totalRows,
1073
+ "\u4EF6\u4E2D ",
1074
+ rangeStart,
1075
+ " - ",
1076
+ rangeEnd,
1077
+ " \u3092\u8868\u793A"
1078
+ ] }),
1079
+ /* @__PURE__ */ jsxs(
1080
+ Select,
1081
+ {
1082
+ items: Object.fromEntries(pageSizeOptions.map((size) => [String(size), `${size}\u4EF6`])),
1083
+ value: String(currentPageSize),
1084
+ onValueChange: (value) => table.setPageSize(Number(value)),
1085
+ children: [
1086
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-[80px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
1087
+ /* @__PURE__ */ jsx(SelectContent, { children: pageSizeOptions.map((size) => /* @__PURE__ */ jsxs(SelectItem, { value: String(size), children: [
1088
+ size,
1089
+ "\u4EF6"
1090
+ ] }, size)) })
1091
+ ]
1092
+ }
1093
+ )
1094
+ ] }),
1095
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1096
+ /* @__PURE__ */ jsx(
1097
+ Button,
1098
+ {
1099
+ variant: "outline",
1100
+ size: "sm",
1101
+ onClick: () => table.firstPage(),
1102
+ disabled: !table.getCanPreviousPage(),
1103
+ children: "\u6700\u521D"
1104
+ }
1105
+ ),
1106
+ /* @__PURE__ */ jsx(
1107
+ Button,
1108
+ {
1109
+ variant: "outline",
1110
+ size: "sm",
1111
+ onClick: () => table.previousPage(),
1112
+ disabled: !table.getCanPreviousPage(),
1113
+ children: "\u524D\u3078"
1114
+ }
1115
+ ),
1116
+ /* @__PURE__ */ jsx(
1117
+ Button,
1118
+ {
1119
+ variant: "outline",
1120
+ size: "sm",
1121
+ onClick: () => table.nextPage(),
1122
+ disabled: !table.getCanNextPage(),
1123
+ children: "\u6B21\u3078"
1124
+ }
1125
+ ),
1126
+ /* @__PURE__ */ jsx(
1127
+ Button,
1128
+ {
1129
+ variant: "outline",
1130
+ size: "sm",
1131
+ onClick: () => table.lastPage(),
1132
+ disabled: !table.getCanNextPage(),
1133
+ children: "\u6700\u5F8C"
1134
+ }
1135
+ )
1136
+ ] })
1137
+ ]
1138
+ }
1139
+ );
1140
+ }
1141
+ );
1142
+ DataTablePagination.displayName = "DataTablePagination";
1143
+ var DataTableColumnVisibility = forwardRef(({ columnLabels, className }, ref) => {
1144
+ const { table } = useDataTable();
1145
+ const hideableColumns = table.getAllColumns().filter((column) => column.getCanHide());
1146
+ if (hideableColumns.length === 0) return null;
1147
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
1148
+ /* @__PURE__ */ jsx(
1149
+ DropdownMenuTrigger,
1150
+ {
1151
+ ref,
1152
+ render: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: cn(className) }),
1153
+ "data-slot": "data-table-column-visibility",
1154
+ children: /* @__PURE__ */ jsx(Columns3, { className: "size-4" })
1155
+ }
1156
+ ),
1157
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", className: "min-w-[10rem]", children: hideableColumns.map((column) => {
1158
+ const label = columnLabels?.[column.id] ?? (typeof column.columnDef.header === "string" ? column.columnDef.header : column.id);
1159
+ return /* @__PURE__ */ jsx(
1160
+ DropdownMenuCheckboxItem,
1161
+ {
1162
+ checked: column.getIsVisible(),
1163
+ onCheckedChange: (checked) => column.toggleVisibility(checked),
1164
+ children: label
1165
+ },
1166
+ column.id
1167
+ );
1168
+ }) })
1169
+ ] });
1170
+ });
1171
+ DataTableColumnVisibility.displayName = "DataTableColumnVisibility";
1172
+ function DataTablePreset({
1173
+ enableColumnVisibility = false,
1174
+ columnLabels,
1175
+ toolbar,
1176
+ bulkActions,
1177
+ ...tableProps
1178
+ }) {
1179
+ const toolbarSlot = toolbar || enableColumnVisibility ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
1180
+ toolbar,
1181
+ enableColumnVisibility && /* @__PURE__ */ jsx(DataTableColumnVisibility, { columnLabels })
1182
+ ] }) : void 0;
1183
+ return /* @__PURE__ */ jsxs(DataTable, { ...tableProps, children: [
1184
+ /* @__PURE__ */ jsx(
1185
+ DataTableToolbar,
1186
+ {
1187
+ showSearch: tableProps.enableFiltering,
1188
+ toolbar: toolbarSlot,
1189
+ bulkActions
1190
+ }
1191
+ ),
1192
+ /* @__PURE__ */ jsx(DataTableContent, {}),
1193
+ tableProps.enablePagination && /* @__PURE__ */ jsx(DataTablePagination, {})
1194
+ ] });
1195
+ }
1196
+ DataTablePreset.displayName = "DataTablePreset";
1197
+ var FilterBarContext = createContext(null);
1198
+ function useFilterBar() {
1199
+ const ctx = useContext(FilterBarContext);
1200
+ if (!ctx) throw new Error("useFilterBar must be used within <FilterBar>");
1201
+ return ctx;
1202
+ }
1203
+ var FilterBar = forwardRef(
1204
+ ({ value, onChange, onClear, className, children, ...props }, ref) => /* @__PURE__ */ jsx(FilterBarContext.Provider, { value: { value, onChange, onClear }, children: /* @__PURE__ */ jsx(
1205
+ "div",
1206
+ {
1207
+ ref,
1208
+ role: "search",
1209
+ "aria-label": "\u30D5\u30A3\u30EB\u30BF\u30FC",
1210
+ "data-slot": "filter-bar",
1211
+ className: cn("flex flex-wrap items-center gap-2", className),
1212
+ ...props,
1213
+ children
1214
+ }
1215
+ ) })
1216
+ );
1217
+ FilterBar.displayName = "FilterBar";
1218
+ function FilterBarSelect({
1219
+ filterKey,
1220
+ label,
1221
+ options,
1222
+ placeholder,
1223
+ className
1224
+ }) {
1225
+ const { value, onChange } = useFilterBar();
1226
+ const handleChange = (selected) => onChange({ ...value, [filterKey]: selected ?? void 0 });
1227
+ const items = useMemo(
1228
+ () => Object.fromEntries(options.map((option) => [option.value, option.label])),
1229
+ [options]
1230
+ );
1231
+ return /* @__PURE__ */ jsxs(
1232
+ Select,
1233
+ {
1234
+ items,
1235
+ value: value[filterKey] ?? "",
1236
+ onValueChange: handleChange,
1237
+ children: [
1238
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", "aria-label": label, "data-slot": "filter-bar-select", className, children: /* @__PURE__ */ jsx(SelectValue, { placeholder: placeholder ?? label }) }),
1239
+ /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value)) })
1240
+ ]
1241
+ }
1242
+ );
1243
+ }
1244
+ FilterBarSelect.displayName = "FilterBarSelect";
1245
+ function FilterBarMultiSelect({
1246
+ filterKey,
1247
+ label,
1248
+ options,
1249
+ placeholder,
1250
+ className
1251
+ }) {
1252
+ const { value, onChange } = useFilterBar();
1253
+ const selected = value[filterKey] ?? [];
1254
+ const handleToggle = (option) => {
1255
+ const next = selected.includes(option) ? selected.filter((v) => v !== option) : [...selected, option];
1256
+ onChange({ ...value, [filterKey]: next.length > 0 ? next : void 0 });
1257
+ };
1258
+ return /* @__PURE__ */ jsxs(Popover, { children: [
1259
+ /* @__PURE__ */ jsxs(
1260
+ PopoverTrigger,
1261
+ {
1262
+ render: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: cn("h-8 gap-1", className) }),
1263
+ "aria-label": `${placeholder ?? label}${selected.length > 0 ? ` (${selected.length}\u4EF6\u9078\u629E\u4E2D)` : ""}`,
1264
+ "data-slot": "filter-bar-multi-select",
1265
+ children: [
1266
+ placeholder ?? label,
1267
+ selected.length > 0 && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "ml-1 px-1.5 py-0 text-xs", children: selected.length }),
1268
+ /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 opacity-50", "aria-hidden": "true" })
1269
+ ]
1270
+ }
1271
+ ),
1272
+ /* @__PURE__ */ jsx(PopoverContent, { align: "start", className: "w-56 p-2", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", role: "group", "aria-label": label, children: options.map((option) => /* @__PURE__ */ jsxs(
1273
+ "label",
1274
+ {
1275
+ className: "flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent",
1276
+ children: [
1277
+ /* @__PURE__ */ jsx(
1278
+ Checkbox,
1279
+ {
1280
+ checked: selected.includes(option.value),
1281
+ disabled: option.disabled,
1282
+ onCheckedChange: () => handleToggle(option.value)
1283
+ }
1284
+ ),
1285
+ option.label
1286
+ ]
1287
+ },
1288
+ option.value
1289
+ )) }) })
1290
+ ] });
1291
+ }
1292
+ FilterBarMultiSelect.displayName = "FilterBarMultiSelect";
1293
+ function FilterBarActiveChips({ filters, className }) {
1294
+ const { value, onChange } = useFilterBar();
1295
+ const getActiveChips = () => {
1296
+ const chips = [];
1297
+ const pushRaw = (key, v) => {
1298
+ if (typeof v === "string") {
1299
+ chips.push({ key, filterLabel: key, optionLabel: v, isMulti: false });
1300
+ } else {
1301
+ for (const val of v) {
1302
+ chips.push({ key, filterLabel: key, optionLabel: val, optionValue: val, isMulti: true });
1303
+ }
1304
+ }
1305
+ };
1306
+ for (const [key, v] of Object.entries(value)) {
1307
+ if (v === void 0 || v === "") continue;
1308
+ const filter = filters?.find((f) => f.key === key);
1309
+ if (!filter) {
1310
+ pushRaw(key, v);
1311
+ continue;
1312
+ }
1313
+ if (filter.type === "select" && typeof v === "string") {
1314
+ const option = filter.options?.find((o) => o.value === v);
1315
+ chips.push({
1316
+ key,
1317
+ filterLabel: filter.label,
1318
+ optionLabel: option?.label ?? v,
1319
+ isMulti: false
1320
+ });
1321
+ } else if (filter.type === "multi-select" && Array.isArray(v)) {
1322
+ for (const val of v) {
1323
+ const option = filter.options?.find((o) => o.value === val);
1324
+ chips.push({
1325
+ key,
1326
+ filterLabel: filter.label,
1327
+ optionLabel: option?.label ?? val,
1328
+ optionValue: val,
1329
+ isMulti: true
1330
+ });
1331
+ }
1332
+ }
1333
+ }
1334
+ return chips;
1335
+ };
1336
+ const handleRemoveFilter = (key, optionValue) => {
1337
+ if (optionValue !== void 0) {
1338
+ const current = value[key] ?? [];
1339
+ const next = current.filter((v) => v !== optionValue);
1340
+ onChange({ ...value, [key]: next.length > 0 ? next : void 0 });
1341
+ } else {
1342
+ onChange({ ...value, [key]: void 0 });
1343
+ }
1344
+ };
1345
+ const activeChips = getActiveChips();
1346
+ if (activeChips.length === 0) return null;
1347
+ return /* @__PURE__ */ jsx(Fragment$1, { children: activeChips.map((chip) => /* @__PURE__ */ jsxs(
1348
+ Badge,
1349
+ {
1350
+ variant: "secondary",
1351
+ className: cn("gap-1 pr-1", className),
1352
+ "data-slot": "filter-bar-chip",
1353
+ children: [
1354
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
1355
+ chip.filterLabel,
1356
+ ":"
1357
+ ] }),
1358
+ chip.optionLabel,
1359
+ /* @__PURE__ */ jsx(
1360
+ "button",
1361
+ {
1362
+ type: "button",
1363
+ className: "ml-0.5 rounded-full p-0.5 hover:bg-muted-foreground/20",
1364
+ onClick: () => handleRemoveFilter(chip.key, chip.optionValue),
1365
+ "aria-label": `${chip.filterLabel}: ${chip.optionLabel} \u3092\u524A\u9664`,
1366
+ children: /* @__PURE__ */ jsx(X, { className: "size-3", "aria-hidden": "true" })
1367
+ }
1368
+ )
1369
+ ]
1370
+ },
1371
+ `${chip.key}-${chip.optionValue ?? "single"}`
1372
+ )) });
1373
+ }
1374
+ FilterBarActiveChips.displayName = "FilterBarActiveChips";
1375
+ function FilterBarClearButton({ label = "\u30AF\u30EA\u30A2", className }) {
1376
+ const { value, onClear } = useFilterBar();
1377
+ const hasActiveFilters = Object.values(value).some(
1378
+ (v) => Array.isArray(v) ? v.length > 0 : v !== void 0 && v !== ""
1379
+ );
1380
+ if (!hasActiveFilters || !onClear) return null;
1381
+ return /* @__PURE__ */ jsx(
1382
+ Button,
1383
+ {
1384
+ variant: "ghost",
1385
+ size: "sm",
1386
+ className: cn("h-7 px-2 text-xs", className),
1387
+ onClick: onClear,
1388
+ "aria-label": "\u3059\u3079\u3066\u306E\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u30AF\u30EA\u30A2",
1389
+ "data-slot": "filter-bar-clear-button",
1390
+ children: label
1391
+ }
1392
+ );
1393
+ }
1394
+ FilterBarClearButton.displayName = "FilterBarClearButton";
1395
+ function FilterBarPreset({
1396
+ filters,
1397
+ value,
1398
+ onChange,
1399
+ onClear,
1400
+ className
1401
+ }) {
1402
+ return /* @__PURE__ */ jsxs(FilterBar, { value, onChange, onClear, className, children: [
1403
+ filters.map((filter) => {
1404
+ if (filter.type === "select") {
1405
+ return /* @__PURE__ */ jsx(
1406
+ FilterBarSelect,
1407
+ {
1408
+ filterKey: filter.key,
1409
+ label: filter.label,
1410
+ placeholder: filter.placeholder,
1411
+ options: filter.options ?? []
1412
+ },
1413
+ filter.key
1414
+ );
1415
+ }
1416
+ if (filter.type === "multi-select") {
1417
+ return /* @__PURE__ */ jsx(
1418
+ FilterBarMultiSelect,
1419
+ {
1420
+ filterKey: filter.key,
1421
+ label: filter.label,
1422
+ placeholder: filter.placeholder,
1423
+ options: filter.options ?? []
1424
+ },
1425
+ filter.key
1426
+ );
1427
+ }
1428
+ return null;
1429
+ }),
1430
+ /* @__PURE__ */ jsx(FilterBarActiveChips, { filters }),
1431
+ onClear && /* @__PURE__ */ jsx(FilterBarClearButton, {})
1432
+ ] });
1433
+ }
1434
+ FilterBarPreset.displayName = "FilterBarPreset";
1435
+ var defaultPresets = [
1436
+ {
1437
+ label: "Today",
1438
+ getValue: () => {
1439
+ const today = /* @__PURE__ */ new Date();
1440
+ return { from: startOfDay(today), to: endOfDay(today) };
1441
+ }
1442
+ },
1443
+ {
1444
+ label: "Yesterday",
1445
+ getValue: () => {
1446
+ const yesterday = subDays(/* @__PURE__ */ new Date(), 1);
1447
+ return { from: startOfDay(yesterday), to: endOfDay(yesterday) };
1448
+ }
1449
+ },
1450
+ {
1451
+ label: "Last 7 days",
1452
+ getValue: () => {
1453
+ const today = /* @__PURE__ */ new Date();
1454
+ return { from: startOfDay(subDays(today, 6)), to: endOfDay(today) };
1455
+ }
1456
+ },
1457
+ {
1458
+ label: "Last 14 days",
1459
+ getValue: () => {
1460
+ const today = /* @__PURE__ */ new Date();
1461
+ return { from: startOfDay(subDays(today, 13)), to: endOfDay(today) };
1462
+ }
1463
+ },
1464
+ {
1465
+ label: "Last 30 days",
1466
+ getValue: () => {
1467
+ const today = /* @__PURE__ */ new Date();
1468
+ return { from: startOfDay(subDays(today, 29)), to: endOfDay(today) };
1469
+ }
1470
+ },
1471
+ {
1472
+ label: "Last 90 days",
1473
+ getValue: () => {
1474
+ const today = /* @__PURE__ */ new Date();
1475
+ return { from: startOfDay(subDays(today, 89)), to: endOfDay(today) };
1476
+ }
1477
+ },
1478
+ {
1479
+ label: "This month",
1480
+ getValue: () => {
1481
+ const today = /* @__PURE__ */ new Date();
1482
+ return { from: startOfMonth(today), to: endOfDay(today) };
1483
+ }
1484
+ },
1485
+ {
1486
+ label: "Last month",
1487
+ getValue: () => {
1488
+ const lastMonth = subMonths(/* @__PURE__ */ new Date(), 1);
1489
+ return { from: startOfMonth(lastMonth), to: endOfMonth(lastMonth) };
1490
+ }
1491
+ }
1492
+ ];
1493
+ var DateRangePicker = forwardRef(
1494
+ function DateRangePicker2({
1495
+ value,
1496
+ onChange,
1497
+ presets = defaultPresets,
1498
+ showPresets = true,
1499
+ maxDate,
1500
+ minDate,
1501
+ placeholder = "Select date range",
1502
+ disabled = false,
1503
+ className,
1504
+ align = "start"
1505
+ }, ref) {
1506
+ const [open, setOpen] = useState(false);
1507
+ const isMobile = useIsMobile();
1508
+ const handleCalendarSelect = useCallback(
1509
+ (range) => {
1510
+ onChange?.({ from: range?.from, to: range?.to });
1511
+ },
1512
+ [onChange]
1513
+ );
1514
+ const handlePresetClick = useCallback(
1515
+ (preset) => {
1516
+ onChange?.(preset.getValue());
1517
+ setOpen(false);
1518
+ },
1519
+ [onChange]
1520
+ );
1521
+ const formatDateRange = () => {
1522
+ if (!value?.from) return placeholder;
1523
+ if (!value.to) return format(value.from, "yyyy/MM/dd", { locale: ja });
1524
+ return `${format(value.from, "yyyy/MM/dd", { locale: ja })} - ${format(value.to, "yyyy/MM/dd", { locale: ja })}`;
1525
+ };
1526
+ const calendarSelected = value?.from ? { from: value.from, to: value.to ?? void 0 } : void 0;
1527
+ return /* @__PURE__ */ jsx("div", { ref, "data-slot": "date-range-picker", children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
1528
+ /* @__PURE__ */ jsxs(
1529
+ PopoverTrigger,
1530
+ {
1531
+ render: /* @__PURE__ */ jsx(
1532
+ Button,
1533
+ {
1534
+ variant: "outline",
1535
+ disabled,
1536
+ className: cn(
1537
+ "w-auto justify-start text-left font-normal",
1538
+ !value?.from && "text-muted-foreground",
1539
+ className
1540
+ )
1541
+ }
1542
+ ),
1543
+ "aria-label": formatDateRange(),
1544
+ "aria-expanded": open,
1545
+ children: [
1546
+ /* @__PURE__ */ jsx(CalendarIcon, { className: "size-4", "aria-hidden": "true" }),
1547
+ /* @__PURE__ */ jsx("span", { children: formatDateRange() })
1548
+ ]
1549
+ }
1550
+ ),
1551
+ /* @__PURE__ */ jsxs(
1552
+ PopoverContent,
1553
+ {
1554
+ align,
1555
+ className: cn("w-auto p-0", isMobile ? "flex flex-col" : "flex"),
1556
+ children: [
1557
+ showPresets && /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1 p-3", isMobile ? "border-b" : "border-r"), children: presets.map((preset) => /* @__PURE__ */ jsx(
1558
+ Button,
1559
+ {
1560
+ variant: "ghost",
1561
+ size: "sm",
1562
+ className: "justify-start text-xs",
1563
+ onClick: () => handlePresetClick(preset),
1564
+ children: preset.label
1565
+ },
1566
+ preset.label
1567
+ )) }),
1568
+ /* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsx(
1569
+ Calendar,
1570
+ {
1571
+ mode: "range",
1572
+ numberOfMonths: isMobile ? 1 : 2,
1573
+ selected: calendarSelected,
1574
+ onSelect: handleCalendarSelect,
1575
+ disabled: (date) => {
1576
+ if (maxDate && date > maxDate) return true;
1577
+ if (minDate && date < minDate) return true;
1578
+ return false;
1579
+ }
1580
+ }
1581
+ ) })
1582
+ ]
1583
+ }
1584
+ )
1585
+ ] }) });
1586
+ }
1587
+ );
1588
+ DateRangePicker.displayName = "DateRangePicker";
1589
+ var iconSizes = {
1590
+ sm: "size-3.5",
1591
+ default: "size-4",
1592
+ lg: "size-5"
1593
+ };
1594
+ var SegmentedControl = forwardRef(
1595
+ function SegmentedControl2({ options, value, onChange, size = "default", fullWidth = false, ariaLabel, className }, ref) {
1596
+ return /* @__PURE__ */ jsx(
1597
+ ToggleGroup,
1598
+ {
1599
+ ref,
1600
+ "data-slot": "segmented-control",
1601
+ value: [value],
1602
+ onValueChange: (next) => {
1603
+ const picked = next.find((item) => item !== value) ?? next[0];
1604
+ if (typeof picked === "string") onChange(picked);
1605
+ },
1606
+ variant: "outline",
1607
+ size,
1608
+ spacing: 0,
1609
+ "aria-label": ariaLabel,
1610
+ className: cn(fullWidth && "w-full", className),
1611
+ children: options.map((option) => {
1612
+ const Icon = option.icon;
1613
+ return /* @__PURE__ */ jsxs(
1614
+ ToggleGroupItem,
1615
+ {
1616
+ value: option.value,
1617
+ disabled: option.disabled,
1618
+ "aria-label": option.label,
1619
+ className: cn(fullWidth && "flex-1"),
1620
+ children: [
1621
+ Icon && /* @__PURE__ */ jsx(Icon, { className: iconSizes[size], "aria-hidden": "true" }),
1622
+ option.label
1623
+ ]
1624
+ },
1625
+ option.value
1626
+ );
1627
+ })
1628
+ }
1629
+ );
1630
+ }
1631
+ );
1632
+ SegmentedControl.displayName = "SegmentedControl";
1633
+
1634
+ // src/components/types.ts
1635
+ function isGroupedOptions(options) {
1636
+ return options.length > 0 && "options" in options[0];
1637
+ }
1638
+ function flattenOptions(options) {
1639
+ if (isGroupedOptions(options)) {
1640
+ return options.flatMap((group) => group.options);
1641
+ }
1642
+ return options;
1643
+ }
1644
+ function OptionCommandList({
1645
+ options,
1646
+ isSelected,
1647
+ onSelect,
1648
+ onSearch,
1649
+ isLoading,
1650
+ searchPlaceholder,
1651
+ emptyText
1652
+ }) {
1653
+ const renderOptions = (items) => items.map((option) => /* @__PURE__ */ jsxs(
1654
+ CommandItem,
1655
+ {
1656
+ value: option.value,
1657
+ keywords: [option.label],
1658
+ disabled: option.disabled,
1659
+ onSelect,
1660
+ children: [
1661
+ option.icon && /* @__PURE__ */ jsx(option.icon, { className: "size-4 shrink-0" }),
1662
+ /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate", children: [
1663
+ option.label,
1664
+ option.description && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: option.description })
1665
+ ] }),
1666
+ /* @__PURE__ */ jsx(
1667
+ CheckIcon,
1668
+ {
1669
+ className: cn("size-4 shrink-0", isSelected(option.value) ? "opacity-100" : "opacity-0")
1670
+ }
1671
+ )
1672
+ ]
1673
+ },
1674
+ option.value
1675
+ ));
1676
+ return /* @__PURE__ */ jsxs(Command, { shouldFilter: !onSearch, children: [
1677
+ /* @__PURE__ */ jsx(CommandInput, { placeholder: searchPlaceholder, onValueChange: onSearch }),
1678
+ /* @__PURE__ */ jsx(CommandList, { children: isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx(LoaderIcon, { className: "size-4 animate-spin text-muted-foreground" }) }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
1679
+ /* @__PURE__ */ jsx(CommandEmpty, { children: emptyText }),
1680
+ isGroupedOptions(options) ? options.map((group) => /* @__PURE__ */ jsx(CommandGroup, { heading: group.label, children: renderOptions(group.options) }, group.label)) : renderOptions(options)
1681
+ ] }) })
1682
+ ] });
1683
+ }
1684
+ function RemoveButton({ label, onRemove, iconClassName }) {
1685
+ const handle = (e) => {
1686
+ e.stopPropagation();
1687
+ onRemove();
1688
+ };
1689
+ return /* @__PURE__ */ jsx(
1690
+ "span",
1691
+ {
1692
+ role: "button",
1693
+ tabIndex: 0,
1694
+ "aria-label": label,
1695
+ className: "rounded-sm opacity-50 hover:opacity-100 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
1696
+ onClick: handle,
1697
+ onKeyDown: (e) => {
1698
+ if (e.key === "Enter" || e.key === " ") handle(e);
1699
+ },
1700
+ children: /* @__PURE__ */ jsx(XIcon, { className: cn("size-3.5", iconClassName) })
1701
+ }
1702
+ );
1703
+ }
1704
+ var SearchableSelect = forwardRef(
1705
+ function SearchableSelect2({
1706
+ options,
1707
+ value,
1708
+ onChange,
1709
+ onSearch,
1710
+ placeholder = "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
1711
+ searchPlaceholder = "\u691C\u7D22...",
1712
+ emptyText = "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F",
1713
+ isLoading = false,
1714
+ disabled = false,
1715
+ clearable = true,
1716
+ className
1717
+ }, ref) {
1718
+ const [open, setOpen] = useState(false);
1719
+ const allOptions = useMemo(() => flattenOptions(options), [options]);
1720
+ const selectedOption = useMemo(
1721
+ () => allOptions.find((opt) => opt.value === value),
1722
+ [allOptions, value]
1723
+ );
1724
+ function handleSelect(selectedValue) {
1725
+ onChange?.(selectedValue === value ? void 0 : selectedValue);
1726
+ setOpen(false);
1727
+ }
1728
+ return /* @__PURE__ */ jsx("div", { ref, "data-slot": "searchable-select", children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
1729
+ /* @__PURE__ */ jsxs(
1730
+ PopoverTrigger,
1731
+ {
1732
+ render: /* @__PURE__ */ jsx(
1733
+ Button,
1734
+ {
1735
+ variant: "outline",
1736
+ disabled,
1737
+ className: cn(
1738
+ "w-full justify-between font-normal",
1739
+ !selectedOption && "text-muted-foreground",
1740
+ className
1741
+ )
1742
+ }
1743
+ ),
1744
+ role: "combobox",
1745
+ "aria-expanded": open,
1746
+ children: [
1747
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: selectedOption ? selectedOption.label : placeholder }),
1748
+ /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
1749
+ clearable && value && /* @__PURE__ */ jsx(RemoveButton, { label: "\u30AF\u30EA\u30A2", onRemove: () => onChange?.(void 0) }),
1750
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" })
1751
+ ] })
1752
+ ]
1753
+ }
1754
+ ),
1755
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-(--anchor-width) p-0", align: "start", children: /* @__PURE__ */ jsx(
1756
+ OptionCommandList,
1757
+ {
1758
+ options,
1759
+ isSelected: (v) => value === v,
1760
+ onSelect: handleSelect,
1761
+ onSearch,
1762
+ isLoading,
1763
+ searchPlaceholder,
1764
+ emptyText
1765
+ }
1766
+ ) })
1767
+ ] }) });
1768
+ }
1769
+ );
1770
+ SearchableSelect.displayName = "SearchableSelect";
1771
+ var MultiSelect = forwardRef(function MultiSelect2({
1772
+ options,
1773
+ value,
1774
+ onChange,
1775
+ onSearch,
1776
+ maxCount = 3,
1777
+ placeholder = "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
1778
+ searchPlaceholder = "\u691C\u7D22...",
1779
+ emptyText = "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F",
1780
+ isLoading = false,
1781
+ disabled = false,
1782
+ className
1783
+ }, ref) {
1784
+ const [open, setOpen] = useState(false);
1785
+ const listId = useId();
1786
+ const allOptions = useMemo(() => flattenOptions(options), [options]);
1787
+ const selectedOptions = useMemo(
1788
+ () => allOptions.filter((opt) => value.includes(opt.value)),
1789
+ [allOptions, value]
1790
+ );
1791
+ function handleSelect(selectedValue) {
1792
+ if (value.includes(selectedValue)) {
1793
+ onChange?.(value.filter((v) => v !== selectedValue));
1794
+ } else {
1795
+ onChange?.([...value, selectedValue]);
1796
+ }
1797
+ }
1798
+ const visibleBadges = selectedOptions.slice(0, maxCount);
1799
+ const overflowCount = selectedOptions.length - maxCount;
1800
+ return /* @__PURE__ */ jsx("div", { ref, "data-slot": "multi-select", children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
1801
+ /* @__PURE__ */ jsxs(
1802
+ PopoverTrigger,
1803
+ {
1804
+ role: "combobox",
1805
+ "aria-expanded": open,
1806
+ "aria-controls": listId,
1807
+ disabled,
1808
+ className: cn(
1809
+ "inline-flex min-h-9 w-full items-center justify-between gap-2 rounded-md border bg-background px-3 py-1.5 text-sm shadow-xs transition-all outline-none hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
1810
+ className
1811
+ ),
1812
+ children: [
1813
+ /* @__PURE__ */ jsx("span", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-1", children: selectedOptions.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
1814
+ visibleBadges.map((option) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "shrink-0 gap-1 pr-1", children: [
1815
+ /* @__PURE__ */ jsx("span", { className: "max-w-[120px] truncate", children: option.label }),
1816
+ /* @__PURE__ */ jsx(
1817
+ RemoveButton,
1818
+ {
1819
+ label: `${option.label}\u3092\u524A\u9664`,
1820
+ onRemove: () => onChange?.(value.filter((v) => v !== option.value)),
1821
+ iconClassName: "size-3"
1822
+ }
1823
+ )
1824
+ ] }, option.value)),
1825
+ overflowCount > 0 && /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "shrink-0", children: [
1826
+ "+",
1827
+ overflowCount,
1828
+ "\u4EF6"
1829
+ ] })
1830
+ ] }) }),
1831
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 shrink-0 opacity-50" })
1832
+ ]
1833
+ }
1834
+ ),
1835
+ /* @__PURE__ */ jsx(PopoverContent, { id: listId, className: "w-(--anchor-width) p-0", align: "start", children: /* @__PURE__ */ jsx(
1836
+ OptionCommandList,
1837
+ {
1838
+ options,
1839
+ isSelected: (v) => value.includes(v),
1840
+ onSelect: handleSelect,
1841
+ onSearch,
1842
+ isLoading,
1843
+ searchPlaceholder,
1844
+ emptyText
1845
+ }
1846
+ ) })
1847
+ ] }) });
1848
+ });
1849
+ MultiSelect.displayName = "MultiSelect";
1850
+ var metricValueVariants = cva("font-medium tracking-tight", {
1851
+ variants: {
1852
+ size: {
1853
+ sm: "text-base",
1854
+ md: "text-2xl",
1855
+ lg: "text-3xl",
1856
+ xl: "text-4xl"
1857
+ }
1858
+ },
1859
+ defaultVariants: {
1860
+ size: "md"
1861
+ }
1862
+ });
1863
+ var MetricValue = forwardRef(
1864
+ ({ className, size, ...props }, ref) => /* @__PURE__ */ jsx(
1865
+ "div",
1866
+ {
1867
+ ref,
1868
+ "data-slot": "metric-value",
1869
+ className: cn("my-4", metricValueVariants({ size }), className),
1870
+ ...props
1871
+ }
1872
+ )
1873
+ );
1874
+ MetricValue.displayName = "MetricValue";
1875
+ var MetricUnit = forwardRef(
1876
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1877
+ "span",
1878
+ {
1879
+ ref,
1880
+ "data-slot": "metric-unit",
1881
+ className: cn("text-sm font-normal text-muted-foreground", className),
1882
+ ...props
1883
+ }
1884
+ )
1885
+ );
1886
+ MetricUnit.displayName = "MetricUnit";
1887
+ var trendIndicatorVariants = cva("inline-flex items-center gap-0.5 text-sm font-medium", {
1888
+ variants: {
1889
+ sentiment: {
1890
+ positive: "text-chart-1",
1891
+ negative: "text-primary",
1892
+ neutral: "text-muted-foreground"
1893
+ }
1894
+ },
1895
+ defaultVariants: {
1896
+ sentiment: "neutral"
1897
+ }
1898
+ });
1899
+ var TrendIndicator = forwardRef(
1900
+ ({ value, direction, positiveIsGood = true, className }, ref) => {
1901
+ const isGood = direction === "neutral" ? null : direction === "up" === positiveIsGood;
1902
+ const sentiment = isGood === null ? "neutral" : isGood ? "positive" : "negative";
1903
+ const Icon = direction === "up" ? ArrowUp : direction === "down" ? ArrowDown : Minus;
1904
+ const ariaLabel = direction === "neutral" ? `\u5909\u5316\u306A\u3057 ${value}%` : direction === "up" ? `${value}% \u5897\u52A0` : `${value}% \u6E1B\u5C11`;
1905
+ return /* @__PURE__ */ jsxs(
1906
+ "span",
1907
+ {
1908
+ ref,
1909
+ "data-slot": "trend-indicator",
1910
+ className: cn(trendIndicatorVariants({ sentiment }), className),
1911
+ "aria-label": ariaLabel,
1912
+ children: [
1913
+ /* @__PURE__ */ jsx(Icon, { className: "size-3.5", "aria-hidden": "true" }),
1914
+ /* @__PURE__ */ jsxs("span", { children: [
1915
+ value,
1916
+ "%"
1917
+ ] })
1918
+ ]
1919
+ }
1920
+ );
1921
+ }
1922
+ );
1923
+ TrendIndicator.displayName = "TrendIndicator";
1924
+ var defaultColorMap = {
1925
+ active: "green",
1926
+ inactive: "gray",
1927
+ warning: "yellow",
1928
+ error: "red",
1929
+ pending: "blue"
1930
+ };
1931
+ var colorStyles = {
1932
+ green: {
1933
+ dot: "bg-green-500",
1934
+ bg: "bg-green-50 dark:bg-green-950",
1935
+ text: "text-green-700 dark:text-green-300"
1936
+ },
1937
+ gray: {
1938
+ dot: "bg-gray-500",
1939
+ bg: "bg-gray-50 dark:bg-gray-950",
1940
+ text: "text-gray-700 dark:text-gray-300"
1941
+ },
1942
+ yellow: {
1943
+ dot: "bg-yellow-500",
1944
+ bg: "bg-yellow-50 dark:bg-yellow-950",
1945
+ text: "text-yellow-700 dark:text-yellow-300"
1946
+ },
1947
+ red: {
1948
+ dot: "bg-red-500",
1949
+ bg: "bg-red-50 dark:bg-red-950",
1950
+ text: "text-red-700 dark:text-red-300"
1951
+ },
1952
+ blue: {
1953
+ dot: "bg-blue-500",
1954
+ bg: "bg-blue-50 dark:bg-blue-950",
1955
+ text: "text-blue-700 dark:text-blue-300"
1956
+ }
1957
+ };
1958
+ var fallbackStyle = colorStyles.gray;
1959
+ var StatusBadge = forwardRef(function StatusBadge2({ status, label, colorMap, className }, ref) {
1960
+ const mergedColorMap = { ...defaultColorMap, ...colorMap };
1961
+ const color = mergedColorMap[status] ?? "gray";
1962
+ const style = colorStyles[color] ?? fallbackStyle;
1963
+ const displayLabel = label ?? status;
1964
+ return /* @__PURE__ */ jsxs(
1965
+ Badge,
1966
+ {
1967
+ ref,
1968
+ "data-slot": "status-badge",
1969
+ variant: "outline",
1970
+ className: cn("gap-1.5 border-transparent", style.bg, style.text, className),
1971
+ "aria-label": displayLabel,
1972
+ children: [
1973
+ /* @__PURE__ */ jsx("span", { className: cn("inline-block size-2 rounded-full", style.dot), "aria-hidden": "true" }),
1974
+ displayLabel
1975
+ ]
1976
+ }
1977
+ );
1978
+ });
1979
+ StatusBadge.displayName = "StatusBadge";
1980
+
1981
+ export { AppShell, DashboardCard, DashboardCardAction, DashboardCardContent, DashboardCardDescription, DashboardCardFooter, DashboardCardHeader, DashboardCardPreset, DashboardCardSkeleton, DashboardCardTitle, DataTable, DataTableColumnVisibility, DataTableContent, DataTablePagination, DataTablePreset, DataTableToolbar, DateRangePicker, EChart, FilterBar, FilterBarActiveChips, FilterBarClearButton, FilterBarMultiSelect, FilterBarPreset, FilterBarSelect, FunnelSteps, MetricUnit, MetricValue, MultiSelect, PageShell, PageShellActions, PageShellContent, PageShellDescription, PageShellHeader, PageShellHeaderEnd, PageShellHeading, PageShellMeta, PageShellSummary, PageShellSummaryCard, PageShellTitle, SearchableSelect, SectionHeader, SegmentedControl, StatusBadge, TrendIndicator, defaultPresets, flattenOptions, funnelStepsVariants, isGroupedOptions, metricValueVariants, pageShellSummaryCardVariants, useDataTable };
1982
+ //# sourceMappingURL=index.js.map
1983
+ //# sourceMappingURL=index.js.map