@squadbase/vantage 0.5.3-dev.71d2349 → 0.6.0-dev.3cc6138

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