@squadbase/vantage 0.6.1 → 0.6.2-dev1.0010f67

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 (346) hide show
  1. package/dist/add-4GHF2TX2.js +6 -0
  2. package/dist/add-4GHF2TX2.js.map +1 -0
  3. package/dist/{build-O5TVNH4E.js → build-U7GO26HR.js} +9 -9
  4. package/dist/{build-O5TVNH4E.js.map → build-U7GO26HR.js.map} +1 -1
  5. package/dist/{check-WFBEDHDR.js → check-MRVAIHG5.js} +7 -7
  6. package/dist/{check-WFBEDHDR.js.map → check-MRVAIHG5.js.map} +1 -1
  7. package/dist/chunk-2IAPIOPS.js +152 -0
  8. package/dist/chunk-2IAPIOPS.js.map +1 -0
  9. package/dist/chunk-3RJEOP3J.js +174 -0
  10. package/dist/chunk-3RJEOP3J.js.map +1 -0
  11. package/dist/chunk-77CISBMG.js +7581 -0
  12. package/dist/chunk-77CISBMG.js.map +1 -0
  13. package/dist/{chunk-QDZA5JSL.js → chunk-AABMKHEU.js} +4 -4
  14. package/dist/{chunk-QDZA5JSL.js.map → chunk-AABMKHEU.js.map} +1 -1
  15. package/dist/{chunk-PVTHHV7X.js → chunk-ANZLVSEP.js} +28 -7
  16. package/dist/chunk-ANZLVSEP.js.map +1 -0
  17. package/dist/chunk-CKWPK4RO.js +50 -0
  18. package/dist/chunk-CKWPK4RO.js.map +1 -0
  19. package/dist/chunk-EG4PX726.js +678 -0
  20. package/dist/chunk-EG4PX726.js.map +1 -0
  21. package/dist/{chunk-3G43C6OL.js → chunk-GNXCX4WE.js} +46 -3
  22. package/dist/chunk-GNXCX4WE.js.map +1 -0
  23. package/dist/chunk-NZ5QIIG4.js +74 -0
  24. package/dist/chunk-NZ5QIIG4.js.map +1 -0
  25. package/dist/{chunk-BCE22JSM.js → chunk-PJ4SPXHS.js} +52 -16
  26. package/dist/chunk-PJ4SPXHS.js.map +1 -0
  27. package/dist/{chunk-MXI3PZFT.js → chunk-QNOX7WLZ.js} +257 -210
  28. package/dist/chunk-QNOX7WLZ.js.map +1 -0
  29. package/dist/{chunk-ZVANIULZ.js → chunk-RNTDBX6S.js} +4 -4
  30. package/dist/{chunk-ZVANIULZ.js.map → chunk-RNTDBX6S.js.map} +1 -1
  31. package/dist/chunk-ROHNXP7J.js +123 -0
  32. package/dist/chunk-ROHNXP7J.js.map +1 -0
  33. package/dist/chunk-S5MDTHH7.js +466 -0
  34. package/dist/chunk-S5MDTHH7.js.map +1 -0
  35. package/dist/chunk-SDJTTMLK.js +1877 -0
  36. package/dist/chunk-SDJTTMLK.js.map +1 -0
  37. package/dist/{chunk-EP6JHXSR.js → chunk-SHZM3EXB.js} +68 -12
  38. package/dist/chunk-SHZM3EXB.js.map +1 -0
  39. package/dist/chunk-TRMHNMMZ.js +61 -0
  40. package/dist/chunk-TRMHNMMZ.js.map +1 -0
  41. package/dist/{chunk-A2UUGASH.js → chunk-U736PVHY.js} +2 -2
  42. package/dist/chunk-U736PVHY.js.map +1 -0
  43. package/dist/{chunk-JGRMRXXZ.js → chunk-UWSQUHX6.js} +4 -99
  44. package/dist/chunk-UWSQUHX6.js.map +1 -0
  45. package/dist/cli.js +15 -11
  46. package/dist/cli.js.map +1 -1
  47. package/dist/client/index.d.ts +34 -3
  48. package/dist/client/index.js +211 -12
  49. package/dist/client/index.js.map +1 -1
  50. package/dist/components/index.d.ts +1768 -30
  51. package/dist/components/index.js +7 -3
  52. package/dist/delta-text-CbrOaW83.d.ts +17 -0
  53. package/dist/{dev-NZRLOQCL.js → dev-O42JFQ64.js} +24 -13
  54. package/dist/dev-O42JFQ64.js.map +1 -0
  55. package/dist/doc/index.d.ts +219 -2
  56. package/dist/doc/index.js +525 -11
  57. package/dist/doc/index.js.map +1 -1
  58. package/dist/{docs-ZGDJUHJI.js → docs-JVP4RPKT.js} +3 -3
  59. package/dist/{docs-ZGDJUHJI.js.map → docs-JVP4RPKT.js.map} +1 -1
  60. package/dist/{doctor-VFKEMR54.js → doctor-YD3XAAOT.js} +8 -8
  61. package/dist/doctor-YD3XAAOT.js.map +1 -0
  62. package/dist/format-DihQkL1N.d.ts +249 -0
  63. package/dist/markdown/index.js +1 -1
  64. package/dist/markdown/index.js.map +1 -1
  65. package/dist/{preview-QDCIVVSR.js → preview-T6CLSQVX.js} +12 -4
  66. package/dist/preview-T6CLSQVX.js.map +1 -0
  67. package/dist/query/index.d.ts +0 -11
  68. package/dist/query/index.js +2 -2
  69. package/dist/{routes-RHP5FVGD.js → routes-PVKNT777.js} +6 -6
  70. package/dist/{routes-RHP5FVGD.js.map → routes-PVKNT777.js.map} +1 -1
  71. package/dist/{search-RFBELGY7.js → search-5LC4XPB5.js} +3 -3
  72. package/dist/{search-RFBELGY7.js.map → search-5LC4XPB5.js.map} +1 -1
  73. package/dist/slide/index.d.ts +272 -1
  74. package/dist/slide/index.js +1086 -19
  75. package/dist/slide/index.js.map +1 -1
  76. package/dist/table/index.js +14 -9
  77. package/dist/table/index.js.map +1 -1
  78. package/dist/ui/index.d.ts +148 -12
  79. package/dist/ui/index.js +1340 -87
  80. package/dist/ui/index.js.map +1 -1
  81. package/dist/{upgrade-GF2P67M6.js → upgrade-6DT7ADRP.js} +7 -7
  82. package/dist/{upgrade-GF2P67M6.js.map → upgrade-6DT7ADRP.js.map} +1 -1
  83. package/dist/vite/index.d.ts +10 -0
  84. package/dist/vite/index.js +4 -4
  85. package/docs/en/agent-skills.md +1 -1
  86. package/docs/en/changelog.md +26 -0
  87. package/docs/en/cli-reference.md +30 -0
  88. package/docs/en/components.md +42 -17
  89. package/docs/en/doc/delta-text.md +40 -0
  90. package/docs/en/doc/doc-action-items.md +49 -0
  91. package/docs/en/doc/doc-callout.md +38 -0
  92. package/docs/en/doc/doc-data-table.md +60 -0
  93. package/docs/en/doc/doc-executive-summary.md +64 -0
  94. package/docs/en/doc/doc-figure.md +56 -0
  95. package/docs/en/doc/doc-key-findings.md +61 -0
  96. package/docs/en/doc/doc-kpi-scorecard.md +80 -0
  97. package/docs/en/doc/doc-notes-and-sources.md +43 -0
  98. package/docs/en/doc/doc-report-header.md +46 -0
  99. package/docs/en/pages-and-metadata.md +15 -0
  100. package/docs/en/parts/area-chart.md +99 -0
  101. package/docs/en/parts/bar-chart.md +91 -0
  102. package/docs/en/parts/bar-list.md +50 -0
  103. package/docs/en/parts/category-bar.md +37 -0
  104. package/docs/en/parts/chart-frame.md +39 -0
  105. package/docs/en/parts/data-table.md +22 -0
  106. package/docs/en/parts/delta.md +51 -0
  107. package/docs/en/parts/donut-chart.md +72 -0
  108. package/docs/en/parts/format.md +43 -0
  109. package/docs/en/parts/funnel-steps.md +2 -1
  110. package/docs/en/parts/heatmap.md +53 -0
  111. package/docs/en/parts/kpi-card.md +58 -0
  112. package/docs/en/parts/legend.md +35 -0
  113. package/docs/en/parts/line-chart.md +94 -0
  114. package/docs/en/parts/metric-value.md +3 -2
  115. package/docs/en/parts/page-shell.md +1 -1
  116. package/docs/en/parts/progress-circle.md +33 -0
  117. package/docs/en/parts/sample-data.md +39 -0
  118. package/docs/en/parts/scatter-chart.md +56 -0
  119. package/docs/en/parts/sparkline.md +1 -1
  120. package/docs/en/parts/tracker.md +36 -0
  121. package/docs/en/parts/trend-indicator.md +17 -1
  122. package/docs/en/parts/updated-at.md +30 -0
  123. package/docs/en/parts/waterfall-chart.md +56 -0
  124. package/docs/en/routing.md +4 -2
  125. package/docs/en/slide/slide-chart-full.md +48 -0
  126. package/docs/en/slide/slide-chart-insight.md +52 -0
  127. package/docs/en/slide/slide-columns.md +46 -0
  128. package/docs/en/slide/slide-comparison.md +68 -0
  129. package/docs/en/slide/slide-cover.md +39 -0
  130. package/docs/en/slide/slide-exec-summary.md +47 -0
  131. package/docs/en/slide/slide-heading.md +38 -0
  132. package/docs/en/slide/slide-kpi-grid.md +55 -0
  133. package/docs/en/slide/slide-kpi-hero.md +58 -0
  134. package/docs/en/slide/slide-next-actions.md +49 -0
  135. package/docs/en/slide/slide-scorecard-table.md +54 -0
  136. package/docs/en/slide/slide-section.md +44 -0
  137. package/docs/en/slide/slide-source-line.md +34 -0
  138. package/docs/en/ui/alert-dialog.md +42 -0
  139. package/docs/en/ui/avatar.md +31 -0
  140. package/docs/en/ui/combobox.md +74 -0
  141. package/docs/en/ui/drawer.md +41 -0
  142. package/docs/en/ui/empty.md +1 -1
  143. package/docs/en/ui/error-state.md +4 -3
  144. package/docs/en/ui/field.md +42 -0
  145. package/docs/en/ui/hover-card.md +21 -0
  146. package/docs/en/ui/kbd.md +17 -0
  147. package/docs/en/ui/loading.md +1 -1
  148. package/docs/en/ui/pagination.md +36 -0
  149. package/docs/en/ui/radio-group.md +21 -0
  150. package/docs/en/ui/toast.md +44 -0
  151. package/docs/en/ui/toggle-group.md +4 -3
  152. package/docs/en/ui-and-theming.md +1 -1
  153. package/docs/index.json +1184 -114
  154. package/docs/ja/agent-skills.md +1 -1
  155. package/docs/ja/changelog.md +57 -0
  156. package/docs/ja/cli-reference.md +29 -0
  157. package/docs/ja/components.md +68 -101
  158. package/docs/ja/doc/delta-text.md +40 -0
  159. package/docs/ja/doc/doc-action-items.md +49 -0
  160. package/docs/ja/doc/doc-callout.md +38 -0
  161. package/docs/ja/doc/doc-data-table.md +60 -0
  162. package/docs/ja/doc/doc-executive-summary.md +64 -0
  163. package/docs/ja/doc/doc-figure.md +56 -0
  164. package/docs/ja/doc/doc-key-findings.md +61 -0
  165. package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
  166. package/docs/ja/doc/doc-notes-and-sources.md +43 -0
  167. package/docs/ja/doc/doc-report-header.md +46 -0
  168. package/docs/ja/page-types/csv.md +83 -0
  169. package/docs/ja/page-types/doc.md +83 -0
  170. package/docs/ja/page-types/excel.md +82 -0
  171. package/docs/ja/page-types/slide.md +133 -0
  172. package/docs/ja/page-types.md +47 -0
  173. package/docs/ja/pages-and-metadata.md +15 -0
  174. package/docs/ja/parts/area-chart.md +85 -0
  175. package/docs/ja/parts/bar-chart.md +95 -0
  176. package/docs/ja/parts/bar-list.md +58 -0
  177. package/docs/ja/parts/category-bar.md +36 -0
  178. package/docs/ja/parts/chart-frame.md +36 -0
  179. package/docs/ja/parts/data-table.md +22 -0
  180. package/docs/ja/parts/delta.md +51 -0
  181. package/docs/ja/parts/donut-chart.md +66 -0
  182. package/docs/ja/parts/echart.md +3 -0
  183. package/docs/ja/parts/format.md +44 -0
  184. package/docs/ja/parts/funnel-steps.md +27 -8
  185. package/docs/ja/parts/heatmap.md +45 -0
  186. package/docs/ja/parts/kpi-card.md +56 -0
  187. package/docs/ja/parts/legend.md +36 -0
  188. package/docs/ja/parts/line-chart.md +84 -0
  189. package/docs/ja/parts/metric-value.md +3 -2
  190. package/docs/ja/parts/page-shell.md +1 -1
  191. package/docs/ja/parts/progress-circle.md +34 -0
  192. package/docs/ja/parts/sample-data.md +61 -0
  193. package/docs/ja/parts/scatter-chart.md +69 -0
  194. package/docs/ja/parts/sparkline.md +2 -2
  195. package/docs/ja/parts/tracker.md +32 -0
  196. package/docs/ja/parts/trend-indicator.md +17 -1
  197. package/docs/ja/parts/updated-at.md +27 -0
  198. package/docs/ja/parts/waterfall-chart.md +61 -0
  199. package/docs/ja/routing.md +8 -84
  200. package/docs/ja/slide/slide-chart-full.md +48 -0
  201. package/docs/ja/slide/slide-chart-insight.md +52 -0
  202. package/docs/ja/slide/slide-columns.md +46 -0
  203. package/docs/ja/slide/slide-comparison.md +68 -0
  204. package/docs/ja/slide/slide-cover.md +39 -0
  205. package/docs/ja/slide/slide-exec-summary.md +47 -0
  206. package/docs/ja/slide/slide-heading.md +38 -0
  207. package/docs/ja/slide/slide-kpi-grid.md +55 -0
  208. package/docs/ja/slide/slide-kpi-hero.md +58 -0
  209. package/docs/ja/slide/slide-next-actions.md +49 -0
  210. package/docs/ja/slide/slide-scorecard-table.md +54 -0
  211. package/docs/ja/slide/slide-section.md +44 -0
  212. package/docs/ja/slide/slide-source-line.md +34 -0
  213. package/docs/ja/ui/alert-dialog.md +41 -0
  214. package/docs/ja/ui/avatar.md +31 -0
  215. package/docs/ja/ui/combobox.md +74 -0
  216. package/docs/ja/ui/drawer.md +41 -0
  217. package/docs/ja/ui/empty.md +1 -1
  218. package/docs/ja/ui/error-state.md +4 -3
  219. package/docs/ja/ui/field.md +42 -0
  220. package/docs/ja/ui/hover-card.md +21 -0
  221. package/docs/ja/ui/kbd.md +16 -0
  222. package/docs/ja/ui/loading.md +1 -1
  223. package/docs/ja/ui/pagination.md +36 -0
  224. package/docs/ja/ui/radio-group.md +21 -0
  225. package/docs/ja/ui/toast.md +46 -0
  226. package/docs/ja/ui/toggle-group.md +4 -3
  227. package/docs/ja/ui-and-theming.md +14 -7
  228. package/package.json +43 -29
  229. package/registry/ui/accordion.tsx +76 -0
  230. package/registry/ui/alert-dialog.tsx +189 -0
  231. package/registry/ui/alert.tsx +80 -0
  232. package/registry/ui/app-shell.tsx +424 -0
  233. package/registry/ui/area-chart.tsx +3960 -0
  234. package/registry/ui/attention-list.tsx +465 -0
  235. package/registry/ui/avatar.tsx +110 -0
  236. package/registry/ui/badge.tsx +56 -0
  237. package/registry/ui/bar-chart.tsx +3954 -0
  238. package/registry/ui/bar-list.tsx +3998 -0
  239. package/registry/ui/box-plot-chart.tsx +4214 -0
  240. package/registry/ui/breadcrumb.tsx +128 -0
  241. package/registry/ui/button.tsx +62 -0
  242. package/registry/ui/calendar.tsx +223 -0
  243. package/registry/ui/card.tsx +107 -0
  244. package/registry/ui/category-bar.tsx +1498 -0
  245. package/registry/ui/chart-frame.tsx +1604 -0
  246. package/registry/ui/checkbox.tsx +30 -0
  247. package/registry/ui/collapsible.tsx +23 -0
  248. package/registry/ui/combobox.tsx +310 -0
  249. package/registry/ui/command.tsx +198 -0
  250. package/registry/ui/dashboard-card.tsx +217 -0
  251. package/registry/ui/data-table.tsx +896 -157
  252. package/registry/ui/date-range-picker.tsx +544 -0
  253. package/registry/ui/delta.tsx +350 -0
  254. package/registry/ui/dialog.tsx +161 -0
  255. package/registry/ui/donut-chart.tsx +4006 -0
  256. package/registry/ui/drawer.tsx +229 -0
  257. package/registry/ui/dropdown-menu.tsx +274 -0
  258. package/registry/ui/echart.tsx +1178 -0
  259. package/registry/ui/field.tsx +240 -0
  260. package/registry/ui/filter-bar.tsx +551 -0
  261. package/registry/ui/funnel-steps.tsx +3843 -0
  262. package/registry/ui/heatmap.tsx +2027 -0
  263. package/registry/ui/histogram-chart.tsx +4284 -0
  264. package/registry/ui/hover-card.tsx +52 -0
  265. package/registry/ui/input-group.tsx +160 -0
  266. package/registry/ui/input.tsx +24 -0
  267. package/registry/ui/kbd.tsx +30 -0
  268. package/registry/ui/kpi-card.tsx +905 -0
  269. package/registry/ui/label.tsx +22 -0
  270. package/registry/ui/legend.tsx +3817 -0
  271. package/registry/ui/line-chart.tsx +3958 -0
  272. package/registry/ui/metric-value.tsx +62 -0
  273. package/registry/ui/multi-select.tsx +382 -0
  274. package/registry/ui/page-shell.tsx +420 -0
  275. package/registry/ui/pagination.tsx +140 -0
  276. package/registry/ui/paired-chart.tsx +4086 -0
  277. package/registry/ui/placeholder.tsx +36 -0
  278. package/registry/ui/popover.tsx +92 -0
  279. package/registry/ui/progress-circle.tsx +1033 -0
  280. package/registry/ui/progress.tsx +85 -0
  281. package/registry/ui/radio-group.tsx +39 -0
  282. package/registry/ui/sample-data.tsx +230 -0
  283. package/registry/ui/scatter-chart.tsx +4503 -0
  284. package/registry/ui/scroll-area.tsx +56 -0
  285. package/registry/ui/searchable-select.tsx +352 -0
  286. package/registry/ui/section-header.tsx +43 -0
  287. package/registry/ui/segmented-control.tsx +76 -0
  288. package/registry/ui/select.tsx +255 -0
  289. package/registry/ui/separator.tsx +27 -0
  290. package/registry/ui/sheet.tsx +139 -0
  291. package/registry/ui/sidebar.tsx +725 -0
  292. package/registry/ui/skeleton.tsx +17 -0
  293. package/registry/ui/slider.tsx +56 -0
  294. package/registry/ui/sparkline.tsx +230 -0
  295. package/registry/ui/spinner.tsx +14 -0
  296. package/registry/ui/states.tsx +247 -0
  297. package/registry/ui/status-badge.tsx +286 -0
  298. package/registry/ui/switch.tsx +34 -0
  299. package/registry/ui/table.tsx +118 -0
  300. package/registry/ui/tabs.tsx +84 -0
  301. package/registry/ui/textarea.tsx +22 -0
  302. package/registry/ui/toast.tsx +250 -0
  303. package/registry/ui/toggle-group.tsx +91 -0
  304. package/registry/ui/toggle.tsx +47 -0
  305. package/registry/ui/tooltip.tsx +72 -0
  306. package/registry/ui/tracker.tsx +1015 -0
  307. package/registry/ui/trend-indicator.tsx +217 -0
  308. package/registry/ui/updated-at.tsx +276 -0
  309. package/registry/ui/waterfall-chart.tsx +4561 -0
  310. package/skills/vantage-add-feature/SKILL.md +9 -7
  311. package/skills/vantage-design/SKILL.md +62 -52
  312. package/skills/vantage-design/references/extract.md +26 -27
  313. package/skills/vantage-design/references/format.md +12 -172
  314. package/skills/vantage-design/references/presets.md +50 -110
  315. package/skills/vantage-pitfalls/SKILL.md +10 -1
  316. package/skills/vantage-slide/SKILL.md +71 -36
  317. package/templates/AGENTS.md +53 -16
  318. package/templates/agents/api.md +29 -0
  319. package/templates/agents/csv.md +2 -1
  320. package/templates/agents/doc.md +54 -3
  321. package/templates/agents/page.md +55 -10
  322. package/templates/agents/slide.md +90 -4
  323. package/templates/agents/xlsx.md +2 -1
  324. package/theme.css +287 -128
  325. package/dist/add-EISGSZAH.js +0 -6
  326. package/dist/add-EISGSZAH.js.map +0 -1
  327. package/dist/chunk-3G43C6OL.js.map +0 -1
  328. package/dist/chunk-5ZOP4SQR.js +0 -47
  329. package/dist/chunk-5ZOP4SQR.js.map +0 -1
  330. package/dist/chunk-A2UUGASH.js.map +0 -1
  331. package/dist/chunk-BCE22JSM.js.map +0 -1
  332. package/dist/chunk-DTDVSFRY.js +0 -29
  333. package/dist/chunk-DTDVSFRY.js.map +0 -1
  334. package/dist/chunk-EP6JHXSR.js.map +0 -1
  335. package/dist/chunk-JGRMRXXZ.js.map +0 -1
  336. package/dist/chunk-KLEIVDUV.js +0 -165
  337. package/dist/chunk-KLEIVDUV.js.map +0 -1
  338. package/dist/chunk-MXI3PZFT.js.map +0 -1
  339. package/dist/chunk-PLST5Q7T.js +0 -2221
  340. package/dist/chunk-PLST5Q7T.js.map +0 -1
  341. package/dist/chunk-PVTHHV7X.js.map +0 -1
  342. package/dist/chunk-T3FLAGI6.js +0 -316
  343. package/dist/chunk-T3FLAGI6.js.map +0 -1
  344. package/dist/dev-NZRLOQCL.js.map +0 -1
  345. package/dist/doctor-VFKEMR54.js.map +0 -1
  346. package/dist/preview-QDCIVVSR.js.map +0 -1
@@ -0,0 +1,544 @@
1
+ // Copied by `vantage add ui date-range-picker`. This file is yours to edit.
2
+ // Generated from @squadbase/squadkit registry/components/date-range-picker.tsx by `pnpm run registry` (in Vantage, edit packages/squadkit, not registry/).
3
+ "use client"
4
+
5
+ /**
6
+ * DateRangePicker — a range calendar in a popover with quick presets down the
7
+ * side. On mobile the presets stack above a single month; on desktop they sit
8
+ * beside a two-month view. The labels, the date format, the fiscal year start and the
9
+ * first day of the week follow the page (`<html lang>`) unless `locale` is given.
10
+ */
11
+ import { forwardRef, useCallback, useMemo, useState } from "react"
12
+ import { CalendarIcon } from "lucide-react"
13
+ import {
14
+ addMonths,
15
+ endOfDay,
16
+ endOfMonth,
17
+ endOfWeek,
18
+ isSameDay,
19
+ startOfDay,
20
+ startOfMonth,
21
+ startOfWeek,
22
+ subDays,
23
+ subMonths,
24
+ subWeeks,
25
+ } from "date-fns"
26
+ import { ja } from "date-fns/locale"
27
+ import type { DateRange as RdpDateRange } from "react-day-picker"
28
+
29
+ import { cn } from "@squadbase/vantage/ui"
30
+ import { useIsMobile } from "@squadbase/vantage/ui"
31
+ import { formatDate } from "@squadbase/vantage/components"
32
+ import { Button } from "@squadbase/vantage/ui"
33
+ import { Calendar } from "@squadbase/vantage/ui"
34
+ import { Popover, PopoverContent, PopoverTrigger } from "@squadbase/vantage/ui"
35
+ import type { DateRange, PresetItem } from "@squadbase/vantage/components"
36
+ import { useSyncExternalStore } from "react"
37
+
38
+ /* ---------- inlined from @squadbase/squadkit registry/lib/locale.ts (internal to @squadbase/vantage) ---------- */
39
+
40
+ /**
41
+ * The display language of the parts and the defaults that follow it.
42
+ *
43
+ * The language comes from `<html lang>`: a tag starting with `ja` reads Japanese, anything else English.
44
+ * Without a usable `lang` (missing, invalid, or no `document` — SSR, Node) the locale is `FALLBACK_LOCALE`
45
+ * (`en-US`). A `locale` passed explicitly (a prop, an argument) always wins.
46
+ *
47
+ * Parts read the locale through `useLocale` (`hooks/use-locale`) and pass it down; the pure helpers here
48
+ * and in `format` / `comparison` / `chart-*` take it as an argument and fall back to `documentLocale()`.
49
+ */
50
+
51
+ /** The language of the built-in wording: Japanese or English. */
52
+ type UiLanguage = "ja" | "en"
53
+
54
+ /** The locale used when `<html lang>` gives none (and on the server). */
55
+ const FALLBACK_LOCALE = "en-US"
56
+
57
+ /** `"ja"` when `locale` starts with `ja` (`ja`, `ja-JP`), else `"en"`. A missing locale is `"en"`. */
58
+ function uiLanguage(locale: string | null | undefined): UiLanguage {
59
+ return typeof locale === "string" && locale.trim().toLowerCase().startsWith("ja") ? "ja" : "en"
60
+ }
61
+
62
+ /** A BCP 47 tag in its canonical form (`en-gb` → `en-GB`), or `FALLBACK_LOCALE` when it is empty or invalid. */
63
+ function normalizeLocale(tag: string | null | undefined): string {
64
+ const value = tag?.trim()
65
+ if (!value) return FALLBACK_LOCALE
66
+ try {
67
+ return Intl.getCanonicalLocales(value)[0] ?? FALLBACK_LOCALE
68
+ } catch {
69
+ return FALLBACK_LOCALE
70
+ }
71
+ }
72
+
73
+ /**
74
+ * The locale of the page: `document.documentElement.lang`, canonicalized. `FALLBACK_LOCALE` when it is empty or
75
+ * invalid, or there is no `document`. Parts read it through `useLocale`, never while rendering.
76
+ */
77
+ function documentLocale(): string {
78
+ if (typeof document === "undefined") return FALLBACK_LOCALE
79
+ return normalizeLocale(document.documentElement?.getAttribute("lang"))
80
+ }
81
+
82
+ /** `locale` when given, else the page's locale (`documentLocale()`). */
83
+ function resolveLocale(locale?: string | null): string {
84
+ return locale || documentLocale()
85
+ }
86
+
87
+ /** Picks the wording table of the locale's language. */
88
+ function pickLocale<T>(table: { ja: T; en: T }, locale?: string | null): T {
89
+ return table[uiLanguage(resolveLocale(locale))]
90
+ }
91
+
92
+ /** The currency `format="currency"` uses without a `currency`: JPY for Japanese, USD otherwise. */
93
+ function defaultCurrency(locale?: string | null): string {
94
+ return uiLanguage(resolveLocale(locale)) === "ja" ? "JPY" : "USD"
95
+ }
96
+
97
+ /** The month a fiscal year starts in (1–12) when none is given: April for Japanese, January otherwise. */
98
+ function defaultFiscalYearStartMonth(locale?: string | null): number {
99
+ return uiLanguage(resolveLocale(locale)) === "ja" ? 4 : 1
100
+ }
101
+
102
+ /** A day of the week, 0 = Sunday … 6 = Saturday (the `Date#getDay` / date-fns numbering). */
103
+ type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6
104
+
105
+ /** Locales whose week starts on Sunday when the runtime has no week data. */
106
+ const SUNDAY_FIRST = new Set(["en", "en-US", "en-CA"])
107
+
108
+ /**
109
+ * The first day of the week: Monday for Japanese; otherwise the locale's convention from `Intl.Locale`
110
+ * (`en-US` Sunday, `en-GB` Monday). Without week data in the runtime: Sunday for `en` / `en-US` / `en-CA`,
111
+ * Monday for the rest.
112
+ */
113
+ function weekStartsOn(locale?: string | null): WeekDay {
114
+ const tag = normalizeLocale(resolveLocale(locale))
115
+ if (uiLanguage(tag) === "ja") return 1
116
+ try {
117
+ const info = new Intl.Locale(tag) as Intl.Locale & {
118
+ getWeekInfo?: () => { firstDay: number }
119
+ weekInfo?: { firstDay: number }
120
+ }
121
+ const firstDay = info.getWeekInfo?.().firstDay ?? info.weekInfo?.firstDay
122
+ if (typeof firstDay === "number" && firstDay >= 1 && firstDay <= 7) return (firstDay % 7) as WeekDay
123
+ } catch {
124
+ // Fall through to the table below.
125
+ }
126
+ return SUNDAY_FIRST.has(tag) ? 0 : 1
127
+ }
128
+
129
+ /* ---------- inlined from @squadbase/squadkit registry/hooks/use-locale.ts (internal to @squadbase/vantage) ---------- */
130
+
131
+ const listeners = new Set<() => void>()
132
+ let observer: MutationObserver | null = null
133
+
134
+ /** One observer on `<html lang>` for every subscribed part. */
135
+ function subscribe(onChange: () => void): () => void {
136
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") return () => {}
137
+ listeners.add(onChange)
138
+ if (!observer) {
139
+ observer = new MutationObserver(() => {
140
+ for (const listener of [...listeners]) listener()
141
+ })
142
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["lang"] })
143
+ }
144
+ return () => {
145
+ listeners.delete(onChange)
146
+ if (listeners.size === 0 && observer) {
147
+ observer.disconnect()
148
+ observer = null
149
+ }
150
+ }
151
+ }
152
+
153
+ const serverLocale = () => FALLBACK_LOCALE
154
+
155
+ /**
156
+ * The page's locale (`<html lang>`), following changes made while the page runs. On the server and during
157
+ * hydration it is `FALLBACK_LOCALE` (`en-US`), so the markup matches; it switches right after.
158
+ */
159
+ function useDocumentLocale(): string {
160
+ return useSyncExternalStore(subscribe, documentLocale, serverLocale)
161
+ }
162
+
163
+ /** The locale a part renders in: its `locale` prop when given, else the page's (`useDocumentLocale`). */
164
+ function useLocale(locale?: string | null): string {
165
+ const page = useDocumentLocale()
166
+ return locale || page
167
+ }
168
+
169
+ /* ---------- end of inlined code ---------- */
170
+
171
+ /**
172
+ * 会計年度の開始月のフォールバック(1 月始まり)。ロケールから決まる既定は `defaultFiscalYearStartMonth`
173
+ * (`<html lang>` が ja なら 4 月、それ以外は 1 月)。
174
+ */
175
+ export const DEFAULT_FISCAL_YEAR_START_MONTH = 1
176
+
177
+ /** ラベルの言語のフォールバック(英語)。`locale` を渡さなければ、ほかの部品と同じくページの `<html lang>` に従う。 */
178
+ export const DEFAULT_DATE_PICKER_LOCALE = FALLBACK_LOCALE
179
+
180
+ /**
181
+ * 1〜12 の整数だけを開始月として受け、それ以外は `locale` の既定(ja は 4 月、それ以外は 1 月)に戻す。
182
+ * `locale` の既定はページのロケール(`<html lang>`)。
183
+ */
184
+ export function normalizeFiscalYearStartMonth(month: number | undefined, locale?: string): number {
185
+ return typeof month === "number" && Number.isInteger(month) && month >= 1 && month <= 12
186
+ ? month
187
+ : defaultFiscalYearStartMonth(locale)
188
+ }
189
+
190
+ /**
191
+ * `date` を含む年度(または年度基準の四半期)の全期間。`offset` で前後にずらす(`-1` が前の年度/四半期)。
192
+ * 年度は `fiscalYearStartMonth`(1-12)の 1 日に始まり 12 か月続く。四半期は年度の初日から 3 か月ごと。
193
+ * `fiscalYearStartMonth` を省くと `locale`(既定はページのロケール)の既定(ja は 4 月、それ以外は 1 月)。
194
+ *
195
+ * @example
196
+ * // 4 月始まりで 2026-02-10 は 2025 年度(2025-04-01〜2026-03-31)
197
+ * fiscalPeriodRange(new Date(2026, 1, 10), { unit: "year", fiscalYearStartMonth: 4 })
198
+ */
199
+ export function fiscalPeriodRange(
200
+ date: Date,
201
+ {
202
+ unit,
203
+ fiscalYearStartMonth,
204
+ offset = 0,
205
+ locale,
206
+ }: { unit: "year" | "quarter"; fiscalYearStartMonth?: number; offset?: number; locale?: string },
207
+ ): { from: Date; to: Date } {
208
+ const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth, locale)
209
+ const length = unit === "year" ? 12 : 3
210
+ const sinceYearStart = (date.getMonth() - (startMonth - 1) + 12) % 12
211
+ const into = unit === "year" ? sinceYearStart : sinceYearStart % 3
212
+ const periodStart = addMonths(startOfMonth(subMonths(date, into)), offset * length)
213
+ return { from: periodStart, to: endOfMonth(addMonths(periodStart, length - 1)) }
214
+ }
215
+
216
+ const PRESET_LABELS = {
217
+ ja: {
218
+ today: "今日",
219
+ yesterday: "昨日",
220
+ last7: "過去 7 日間",
221
+ last14: "過去 14 日間",
222
+ last28: "過去 28 日間",
223
+ last30: "過去 30 日間",
224
+ last90: "過去 90 日間",
225
+ thisWeek: "今週",
226
+ lastWeek: "先週",
227
+ thisMonth: "今月",
228
+ lastMonth: "先月",
229
+ thisQuarter: "今四半期",
230
+ lastQuarter: "前四半期",
231
+ thisFiscalYear: "今年度",
232
+ lastFiscalYear: "前年度",
233
+ },
234
+ en: {
235
+ today: "Today",
236
+ yesterday: "Yesterday",
237
+ last7: "Last 7 days",
238
+ last14: "Last 14 days",
239
+ last28: "Last 28 days",
240
+ last30: "Last 30 days",
241
+ last90: "Last 90 days",
242
+ thisWeek: "This week",
243
+ lastWeek: "Last week",
244
+ thisMonth: "This month",
245
+ lastMonth: "Last month",
246
+ thisQuarter: "This quarter",
247
+ lastQuarter: "Last quarter",
248
+ thisFiscalYear: "This fiscal year",
249
+ lastFiscalYear: "Last fiscal year",
250
+ },
251
+ } as const
252
+
253
+ const TEXT = {
254
+ ja: { placeholder: "期間を選択", rangeSeparator: " - " },
255
+ en: { placeholder: "Pick a date range", rangeSeparator: " – " },
256
+ }
257
+
258
+ /** カレンダーに渡す date-fns の locale。`ja*` なら日本語、それ以外は react-day-picker の既定(英語)。 */
259
+ const calendarLocale = (locale: string) => (uiLanguage(locale) === "ja" ? ja : undefined)
260
+
261
+ /**
262
+ * 既定のプリセット一覧を作る。ラベルは `locale`(`ja*` なら日本語、それ以外は英語)、
263
+ * 「今四半期」「前四半期」「今年度」「前年度」は `fiscalYearStartMonth`(省くと ja は 4 月、それ以外は 1 月)を基準にする。
264
+ * 「今〜」は期の初日から今日まで、「前〜」「先月」「先週」は前の期の全期間。週の始まりは `locale` の慣習
265
+ * (ja は月曜、`en-US` は日曜、`en-GB` は月曜。`weekStartsOn`)。`getValue` は押した時点の日付で計算する。
266
+ * `locale` の既定はページのロケール(`<html lang>`、無ければ `"en-US"`)。
267
+ *
268
+ * @example
269
+ * createDatePresets({ locale: "ja-JP", fiscalYearStartMonth: 4 })
270
+ */
271
+ export function createDatePresets({
272
+ locale: localeArg,
273
+ fiscalYearStartMonth,
274
+ now = () => new Date(),
275
+ }: { locale?: string; fiscalYearStartMonth?: number; now?: () => Date } = {}): PresetItem[] {
276
+ const locale = resolveLocale(localeArg)
277
+ const t = PRESET_LABELS[uiLanguage(locale)]
278
+ const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth, locale)
279
+ const WEEK_OPTIONS = { weekStartsOn: weekStartsOn(locale) }
280
+ const lastDays = (days: number) => () => {
281
+ const today = now()
282
+ return { from: startOfDay(subDays(today, days - 1)), to: endOfDay(today) }
283
+ }
284
+ const toDate = (unit: "year" | "quarter") => () => {
285
+ const today = now()
286
+ return {
287
+ from: fiscalPeriodRange(today, { unit, fiscalYearStartMonth: startMonth }).from,
288
+ to: endOfDay(today),
289
+ }
290
+ }
291
+ const previous = (unit: "year" | "quarter") => () =>
292
+ fiscalPeriodRange(now(), { unit, fiscalYearStartMonth: startMonth, offset: -1 })
293
+ return [
294
+ { label: t.today, getValue: lastDays(1) },
295
+ {
296
+ label: t.yesterday,
297
+ getValue: () => {
298
+ const yesterday = subDays(now(), 1)
299
+ return { from: startOfDay(yesterday), to: endOfDay(yesterday) }
300
+ },
301
+ },
302
+ { label: t.last7, getValue: lastDays(7) },
303
+ { label: t.last14, getValue: lastDays(14) },
304
+ { label: t.last28, getValue: lastDays(28) },
305
+ { label: t.last30, getValue: lastDays(30) },
306
+ { label: t.last90, getValue: lastDays(90) },
307
+ {
308
+ label: t.thisWeek,
309
+ getValue: () => {
310
+ const today = now()
311
+ return { from: startOfWeek(today, WEEK_OPTIONS), to: endOfDay(today) }
312
+ },
313
+ },
314
+ {
315
+ label: t.lastWeek,
316
+ getValue: () => {
317
+ const lastWeek = subWeeks(now(), 1)
318
+ return { from: startOfWeek(lastWeek, WEEK_OPTIONS), to: endOfWeek(lastWeek, WEEK_OPTIONS) }
319
+ },
320
+ },
321
+ {
322
+ label: t.thisMonth,
323
+ getValue: () => {
324
+ const today = now()
325
+ return { from: startOfMonth(today), to: endOfDay(today) }
326
+ },
327
+ },
328
+ {
329
+ label: t.lastMonth,
330
+ getValue: () => {
331
+ const lastMonth = subMonths(now(), 1)
332
+ return { from: startOfMonth(lastMonth), to: endOfMonth(lastMonth) }
333
+ },
334
+ },
335
+ { label: t.thisQuarter, getValue: toDate("quarter") },
336
+ { label: t.lastQuarter, getValue: previous("quarter") },
337
+ { label: t.thisFiscalYear, getValue: toDate("year") },
338
+ { label: t.lastFiscalYear, getValue: previous("year") },
339
+ ]
340
+ }
341
+
342
+ /**
343
+ * `value` と日単位で同じ範囲を返す最初のプリセットを探す(無ければ `undefined`)。`getValue` は呼んだ時点の日付で計算される。
344
+ * 「今日」と「今週」が月曜に重なるときなど、複数が一致したら並びの早いほうを返す。
345
+ */
346
+ export function findMatchingPreset(presets: PresetItem[], value: DateRange | undefined): PresetItem | undefined {
347
+ const { from, to } = value ?? {}
348
+ if (!from || !to) return undefined
349
+ return presets.find((preset) => {
350
+ const range = preset.getValue()
351
+ return range.from != null && range.to != null && isSameDay(range.from, from) && isSameDay(range.to, to)
352
+ })
353
+ }
354
+
355
+ /**
356
+ * フォールバック(`en-US`:英語・1 月始まり・日曜始まり)のプリセット。DateRangePicker は `presets` を渡さなければ
357
+ * ページのロケールからプリセットを作るので、これを渡す必要はない。`locale` / `fiscalYearStartMonth` を変えるなら
358
+ * `createDatePresets` か DateRangePicker の同名 props。
359
+ */
360
+ export const defaultPresets: PresetItem[] = createDatePresets({ locale: FALLBACK_LOCALE })
361
+
362
+ export interface DateRangePickerProps {
363
+ /**
364
+ * 選択中の日付範囲。型はこの部品独自の `DateRange`。
365
+ * react-day-picker の `DateRange` とは別物なので注意 — そちらが必要なら
366
+ * このファイルの末尾で re-export している `RdpDateRange` を使う。
367
+ *
368
+ * @example
369
+ * import { DateRangePicker, type DateRange } from "@/components/date-range-picker"
370
+ * // Vantage: import { DateRangePicker, type DateRange } from "@squadbase/vantage/components"
371
+ *
372
+ * const [range, setRange] = useState<DateRange | undefined>()
373
+ * <DateRangePicker value={range} onChange={setRange} />
374
+ */
375
+ value?: DateRange
376
+ onChange?: (range: DateRange) => void
377
+ /**
378
+ * ショートカットの一覧。指定すると `locale` / `fiscalYearStartMonth` による既定の一覧の代わりに使う。
379
+ *
380
+ * @example
381
+ * presets={[{ label: "直近 10 日", getValue: () => ({ from: subDays(new Date(), 9), to: new Date() }) }]}
382
+ */
383
+ presets?: PresetItem[]
384
+ showPresets?: boolean
385
+ /**
386
+ * プリセットのラベル・日付の書式・カレンダーの月名と曜日・週の始まりのロケール。`ja*` なら日本語、それ以外は英語。
387
+ * 既定はページのロケール(`<html lang>`、無ければ `"en-US"`)。
388
+ *
389
+ * @example
390
+ * <DateRangePicker locale="ja-JP" />
391
+ */
392
+ locale?: string
393
+ /**
394
+ * 年度の開始月(1-12)。「今年度」「前年度」と、年度基準の「今四半期」「前四半期」の区切りになる。
395
+ * 既定はロケールで決まる(ja は `4`、それ以外は `1`)。範囲外・整数でない値はその既定として扱う。
396
+ *
397
+ * @example
398
+ * <DateRangePicker fiscalYearStartMonth={1} />
399
+ */
400
+ fiscalYearStartMonth?: number
401
+ maxDate?: Date
402
+ minDate?: Date
403
+ placeholder?: string
404
+ disabled?: boolean
405
+ className?: string
406
+ align?: "start" | "center" | "end"
407
+ }
408
+
409
+ export const DateRangePicker = forwardRef<HTMLDivElement, DateRangePickerProps>(
410
+ function DateRangePicker(
411
+ {
412
+ value,
413
+ onChange,
414
+ presets: presetsProp,
415
+ showPresets = true,
416
+ locale: localeProp,
417
+ fiscalYearStartMonth,
418
+ maxDate,
419
+ minDate,
420
+ placeholder,
421
+ disabled = false,
422
+ className,
423
+ align = "start",
424
+ },
425
+ ref,
426
+ ) {
427
+ const [open, setOpen] = useState(false)
428
+ const isMobile = useIsMobile()
429
+ const locale = useLocale(localeProp)
430
+ const t = TEXT[uiLanguage(locale)]
431
+ const presets = useMemo(
432
+ () => presetsProp ?? createDatePresets({ locale, fiscalYearStartMonth }),
433
+ [presetsProp, locale, fiscalYearStartMonth],
434
+ )
435
+
436
+ const handleCalendarSelect = useCallback(
437
+ (range: RdpDateRange | undefined) => {
438
+ onChange?.({ from: range?.from, to: range?.to })
439
+ },
440
+ [onChange],
441
+ )
442
+
443
+ const handlePresetClick = useCallback(
444
+ (preset: PresetItem) => {
445
+ onChange?.(preset.getValue())
446
+ setOpen(false)
447
+ },
448
+ [onChange],
449
+ )
450
+
451
+ const formatDateRange = () => {
452
+ if (!value?.from) return placeholder ?? t.placeholder
453
+ if (!value.to) return formatDate(value.from, "date", locale)
454
+ return `${formatDate(value.from, "date", locale)}${t.rangeSeparator}${formatDate(value.to, "date", locale)}`
455
+ }
456
+ // 選んだ期間がプリセットの結果と一致するときは、日付の前にそのプリセット名を出す。
457
+ const selectedPreset = findMatchingPreset(presets, value)
458
+ const presetLabel = selectedPreset?.label
459
+
460
+ // 開いたとき、右の月が終了月・左がその前月になるよう、表示月(左の月)を決める。1 か月表示(モバイル)は終了月。
461
+ const endMonth = value?.to ?? value?.from
462
+ const defaultMonth = endMonth ? (isMobile ? endMonth : subMonths(endMonth, 1)) : undefined
463
+
464
+ const calendarSelected: RdpDateRange | undefined = value?.from
465
+ ? { from: value.from, to: value.to ?? undefined }
466
+ : undefined
467
+
468
+ return (
469
+ <div ref={ref} data-slot="date-range-picker">
470
+ <Popover open={open} onOpenChange={setOpen}>
471
+ <PopoverTrigger
472
+ render={
473
+ <Button
474
+ variant="outline"
475
+ disabled={disabled}
476
+ className={cn(
477
+ "w-auto justify-start text-left font-normal",
478
+ !value?.from && "text-muted-foreground",
479
+ className,
480
+ )}
481
+ />
482
+ }
483
+ aria-label={presetLabel ? `${presetLabel} ${formatDateRange()}` : formatDateRange()}
484
+ aria-expanded={open}
485
+ >
486
+ <CalendarIcon className="size-4" aria-hidden="true" />
487
+ {presetLabel ? (
488
+ <>
489
+ <span>{presetLabel}</span>
490
+ <span className="text-muted-foreground">{formatDateRange()}</span>
491
+ </>
492
+ ) : (
493
+ <span>{formatDateRange()}</span>
494
+ )}
495
+ </PopoverTrigger>
496
+ <PopoverContent
497
+ align={align}
498
+ className={cn("w-auto gap-0 p-0", isMobile ? "flex-col" : "flex-row")}
499
+ >
500
+ {showPresets && (
501
+ <div className={cn("flex flex-col gap-1 p-3", isMobile ? "border-b" : "border-r")}>
502
+ {presets.map((preset) => (
503
+ <Button
504
+ key={preset.label}
505
+ variant="ghost"
506
+ size="sm"
507
+ aria-pressed={selectedPreset === preset}
508
+ className={cn(
509
+ "justify-start text-xs",
510
+ selectedPreset === preset && "bg-primary/10 text-primary hover:bg-primary/15 hover:text-primary",
511
+ )}
512
+ onClick={() => handlePresetClick(preset)}
513
+ >
514
+ {preset.label}
515
+ </Button>
516
+ ))}
517
+ </div>
518
+ )}
519
+ <div className="p-3">
520
+ <Calendar
521
+ key={`${open}-${isMobile}`}
522
+ mode="range"
523
+ defaultMonth={defaultMonth}
524
+ locale={calendarLocale(locale)}
525
+ weekStartsOn={weekStartsOn(locale)}
526
+ numberOfMonths={isMobile ? 1 : 2}
527
+ selected={calendarSelected}
528
+ onSelect={handleCalendarSelect}
529
+ disabled={(date) => {
530
+ if (maxDate && date > maxDate) return true
531
+ if (minDate && date < minDate) return true
532
+ return false
533
+ }}
534
+ />
535
+ </div>
536
+ </PopoverContent>
537
+ </Popover>
538
+ </div>
539
+ )
540
+ },
541
+ )
542
+ DateRangePicker.displayName = "DateRangePicker"
543
+
544
+ export type { DateRange as RdpDateRange } from "react-day-picker"