@squadbase/vantage 0.6.2-dev1.b332e5a → 0.6.2-dev1.d7c0911

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