@squadbase/vantage 0.6.2 → 0.7.0-dev1.1197de7
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.
- package/dist/add-4GHF2TX2.js +6 -0
- package/dist/add-4GHF2TX2.js.map +1 -0
- package/dist/{build-O5TVNH4E.js → build-U7GO26HR.js} +9 -9
- package/dist/{build-O5TVNH4E.js.map → build-U7GO26HR.js.map} +1 -1
- package/dist/{check-WFBEDHDR.js → check-MRVAIHG5.js} +7 -7
- package/dist/{check-WFBEDHDR.js.map → check-MRVAIHG5.js.map} +1 -1
- package/dist/{chunk-QDZA5JSL.js → chunk-AABMKHEU.js} +4 -4
- package/dist/{chunk-QDZA5JSL.js.map → chunk-AABMKHEU.js.map} +1 -1
- package/dist/{chunk-PVTHHV7X.js → chunk-ANZLVSEP.js} +28 -7
- package/dist/chunk-ANZLVSEP.js.map +1 -0
- package/dist/chunk-CKWPK4RO.js +50 -0
- package/dist/chunk-CKWPK4RO.js.map +1 -0
- package/dist/chunk-EG4PX726.js +678 -0
- package/dist/chunk-EG4PX726.js.map +1 -0
- package/dist/{chunk-3G43C6OL.js → chunk-GNXCX4WE.js} +46 -3
- package/dist/chunk-GNXCX4WE.js.map +1 -0
- package/dist/chunk-LYUGDHSF.js +61 -0
- package/dist/chunk-LYUGDHSF.js.map +1 -0
- package/dist/{chunk-RPZAALCX.js → chunk-MQUIAP66.js} +321 -165
- package/dist/chunk-MQUIAP66.js.map +1 -0
- package/dist/chunk-P2KIHF65.js +152 -0
- package/dist/chunk-P2KIHF65.js.map +1 -0
- package/dist/{chunk-BCE22JSM.js → chunk-PJ4SPXHS.js} +52 -16
- package/dist/chunk-PJ4SPXHS.js.map +1 -0
- package/dist/{chunk-ZVANIULZ.js → chunk-RNTDBX6S.js} +4 -4
- package/dist/{chunk-ZVANIULZ.js.map → chunk-RNTDBX6S.js.map} +1 -1
- package/dist/{chunk-PXRX5PEC.js → chunk-ROHNXP7J.js} +73 -4
- package/dist/chunk-ROHNXP7J.js.map +1 -0
- package/dist/chunk-S5MDTHH7.js +466 -0
- package/dist/chunk-S5MDTHH7.js.map +1 -0
- package/dist/chunk-SDJTTMLK.js +1877 -0
- package/dist/chunk-SDJTTMLK.js.map +1 -0
- package/dist/{chunk-EP6JHXSR.js → chunk-SHZM3EXB.js} +68 -12
- package/dist/chunk-SHZM3EXB.js.map +1 -0
- package/dist/{chunk-A2UUGASH.js → chunk-U736PVHY.js} +2 -2
- package/dist/chunk-U736PVHY.js.map +1 -0
- package/dist/{chunk-JGRMRXXZ.js → chunk-UWSQUHX6.js} +4 -99
- package/dist/chunk-UWSQUHX6.js.map +1 -0
- package/dist/chunk-XRKSIC5Z.js +176 -0
- package/dist/chunk-XRKSIC5Z.js.map +1 -0
- package/dist/chunk-YJQCB3UP.js +10764 -0
- package/dist/chunk-YJQCB3UP.js.map +1 -0
- package/dist/cli.js +15 -11
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts +34 -3
- package/dist/client/index.js +211 -12
- package/dist/client/index.js.map +1 -1
- package/dist/components/index.d.ts +2389 -31
- package/dist/components/index.js +7 -4
- package/dist/delta-text-tav2Lh5d.d.ts +17 -0
- package/dist/{dev-NZRLOQCL.js → dev-O42JFQ64.js} +24 -13
- package/dist/dev-O42JFQ64.js.map +1 -0
- package/dist/doc/index.d.ts +215 -2
- package/dist/doc/index.js +423 -5
- package/dist/doc/index.js.map +1 -1
- package/dist/{docs-ZGDJUHJI.js → docs-JVP4RPKT.js} +3 -3
- package/dist/{docs-ZGDJUHJI.js.map → docs-JVP4RPKT.js.map} +1 -1
- package/dist/{doctor-VFKEMR54.js → doctor-YD3XAAOT.js} +8 -8
- package/dist/doctor-YD3XAAOT.js.map +1 -0
- package/dist/format-D34piCei.d.ts +250 -0
- package/dist/geo-japan-7BMSOJRX.js +8 -0
- package/dist/geo-japan-7BMSOJRX.js.map +1 -0
- package/dist/geo-us-GVOG7VXH.js +8 -0
- package/dist/geo-us-GVOG7VXH.js.map +1 -0
- package/dist/geo-world-35HL56UU.js +8 -0
- package/dist/geo-world-35HL56UU.js.map +1 -0
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/index.js.map +1 -1
- package/dist/{preview-QDCIVVSR.js → preview-T6CLSQVX.js} +12 -4
- package/dist/preview-T6CLSQVX.js.map +1 -0
- package/dist/query/index.d.ts +0 -11
- package/dist/query/index.js +2 -2
- package/dist/{routes-RHP5FVGD.js → routes-PVKNT777.js} +6 -6
- package/dist/{routes-RHP5FVGD.js.map → routes-PVKNT777.js.map} +1 -1
- package/dist/{search-RFBELGY7.js → search-5LC4XPB5.js} +3 -3
- package/dist/{search-RFBELGY7.js.map → search-5LC4XPB5.js.map} +1 -1
- package/dist/slide/index.d.ts +272 -1
- package/dist/slide/index.js +1086 -19
- package/dist/slide/index.js.map +1 -1
- package/dist/table/index.js +13 -10
- package/dist/table/index.js.map +1 -1
- package/dist/ui/index.d.ts +148 -12
- package/dist/ui/index.js +1339 -88
- package/dist/ui/index.js.map +1 -1
- package/dist/{upgrade-GF2P67M6.js → upgrade-6DT7ADRP.js} +7 -7
- package/dist/{upgrade-GF2P67M6.js.map → upgrade-6DT7ADRP.js.map} +1 -1
- package/dist/vite/index.d.ts +10 -0
- package/dist/vite/index.js +4 -4
- package/docs/en/agent-skills.md +1 -1
- package/docs/en/changelog.md +82 -0
- package/docs/en/cli-reference.md +30 -0
- package/docs/en/components.md +42 -17
- package/docs/en/doc/delta-text.md +40 -0
- package/docs/en/doc/doc-action-items.md +49 -0
- package/docs/en/doc/doc-callout.md +38 -0
- package/docs/en/doc/doc-data-table.md +60 -0
- package/docs/en/doc/doc-executive-summary.md +64 -0
- package/docs/en/doc/doc-figure.md +56 -0
- package/docs/en/doc/doc-key-findings.md +61 -0
- package/docs/en/doc/doc-kpi-scorecard.md +80 -0
- package/docs/en/doc/doc-notes-and-sources.md +43 -0
- package/docs/en/doc/doc-report-header.md +46 -0
- package/docs/en/pages-and-metadata.md +15 -0
- package/docs/en/parts/area-chart.md +99 -0
- package/docs/en/parts/bar-chart.md +91 -0
- package/docs/en/parts/bar-list.md +50 -0
- package/docs/en/parts/category-bar.md +37 -0
- package/docs/en/parts/chart-frame.md +39 -0
- package/docs/en/parts/data-table.md +22 -0
- package/docs/en/parts/delta.md +51 -0
- package/docs/en/parts/donut-chart.md +72 -0
- package/docs/en/parts/draft-chart.md +42 -0
- package/docs/en/parts/format.md +43 -0
- package/docs/en/parts/funnel-steps.md +2 -1
- package/docs/en/parts/heatmap.md +53 -0
- package/docs/en/parts/kpi-card.md +58 -0
- package/docs/en/parts/legend.md +35 -0
- package/docs/en/parts/line-chart.md +94 -0
- package/docs/en/parts/metric-value.md +3 -2
- package/docs/en/parts/page-shell.md +2 -2
- package/docs/en/parts/progress-circle.md +33 -0
- package/docs/en/parts/sample-data.md +39 -0
- package/docs/en/parts/scatter-chart.md +56 -0
- package/docs/en/parts/sparkline.md +1 -1
- package/docs/en/parts/tracker.md +36 -0
- package/docs/en/parts/trend-indicator.md +17 -1
- package/docs/en/parts/updated-at.md +30 -0
- package/docs/en/parts/waterfall-chart.md +56 -0
- package/docs/en/slide/slide-chart-full.md +48 -0
- package/docs/en/slide/slide-chart-insight.md +52 -0
- package/docs/en/slide/slide-columns.md +46 -0
- package/docs/en/slide/slide-comparison.md +68 -0
- package/docs/en/slide/slide-cover.md +39 -0
- package/docs/en/slide/slide-exec-summary.md +47 -0
- package/docs/en/slide/slide-heading.md +38 -0
- package/docs/en/slide/slide-kpi-grid.md +55 -0
- package/docs/en/slide/slide-kpi-hero.md +58 -0
- package/docs/en/slide/slide-next-actions.md +49 -0
- package/docs/en/slide/slide-scorecard-table.md +54 -0
- package/docs/en/slide/slide-section.md +44 -0
- package/docs/en/slide/slide-source-line.md +34 -0
- package/docs/en/ui/alert-dialog.md +42 -0
- package/docs/en/ui/avatar.md +31 -0
- package/docs/en/ui/combobox.md +74 -0
- package/docs/en/ui/drawer.md +41 -0
- package/docs/en/ui/empty.md +1 -1
- package/docs/en/ui/error-state.md +4 -3
- package/docs/en/ui/field.md +42 -0
- package/docs/en/ui/hover-card.md +21 -0
- package/docs/en/ui/kbd.md +17 -0
- package/docs/en/ui/loading.md +1 -1
- package/docs/en/ui/pagination.md +36 -0
- package/docs/en/ui/radio-group.md +21 -0
- package/docs/en/ui/toast.md +44 -0
- package/docs/en/ui/toggle-group.md +4 -3
- package/docs/en/ui-and-theming.md +1 -1
- package/docs/index.json +1222 -132
- package/docs/ja/agent-skills.md +1 -1
- package/docs/ja/changelog.md +84 -0
- package/docs/ja/cli-reference.md +29 -0
- package/docs/ja/components.md +68 -101
- package/docs/ja/doc/delta-text.md +40 -0
- package/docs/ja/doc/doc-action-items.md +49 -0
- package/docs/ja/doc/doc-callout.md +38 -0
- package/docs/ja/doc/doc-data-table.md +60 -0
- package/docs/ja/doc/doc-executive-summary.md +64 -0
- package/docs/ja/doc/doc-figure.md +56 -0
- package/docs/ja/doc/doc-key-findings.md +61 -0
- package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
- package/docs/ja/doc/doc-notes-and-sources.md +43 -0
- package/docs/ja/doc/doc-report-header.md +46 -0
- package/docs/ja/page-types/csv.md +83 -0
- package/docs/ja/page-types/doc.md +83 -0
- package/docs/ja/page-types/excel.md +82 -0
- package/docs/ja/page-types/slide.md +133 -0
- package/docs/ja/page-types.md +47 -0
- package/docs/ja/pages-and-metadata.md +15 -0
- package/docs/ja/parts/area-chart.md +85 -0
- package/docs/ja/parts/bar-chart.md +95 -0
- package/docs/ja/parts/bar-list.md +58 -0
- package/docs/ja/parts/category-bar.md +36 -0
- package/docs/ja/parts/chart-frame.md +36 -0
- package/docs/ja/parts/data-table.md +22 -0
- package/docs/ja/parts/delta.md +51 -0
- package/docs/ja/parts/donut-chart.md +66 -0
- package/docs/ja/parts/draft-chart.md +40 -0
- package/docs/ja/parts/echart.md +3 -0
- package/docs/ja/parts/format.md +44 -0
- package/docs/ja/parts/funnel-steps.md +27 -8
- package/docs/ja/parts/heatmap.md +45 -0
- package/docs/ja/parts/kpi-card.md +56 -0
- package/docs/ja/parts/legend.md +36 -0
- package/docs/ja/parts/line-chart.md +84 -0
- package/docs/ja/parts/metric-value.md +3 -2
- package/docs/ja/parts/page-shell.md +2 -2
- package/docs/ja/parts/progress-circle.md +34 -0
- package/docs/ja/parts/sample-data.md +61 -0
- package/docs/ja/parts/scatter-chart.md +69 -0
- package/docs/ja/parts/sparkline.md +2 -2
- package/docs/ja/parts/tracker.md +32 -0
- package/docs/ja/parts/trend-indicator.md +17 -1
- package/docs/ja/parts/updated-at.md +27 -0
- package/docs/ja/parts/waterfall-chart.md +61 -0
- package/docs/ja/routing.md +8 -86
- package/docs/ja/slide/slide-chart-full.md +48 -0
- package/docs/ja/slide/slide-chart-insight.md +52 -0
- package/docs/ja/slide/slide-columns.md +46 -0
- package/docs/ja/slide/slide-comparison.md +68 -0
- package/docs/ja/slide/slide-cover.md +39 -0
- package/docs/ja/slide/slide-exec-summary.md +47 -0
- package/docs/ja/slide/slide-heading.md +38 -0
- package/docs/ja/slide/slide-kpi-grid.md +55 -0
- package/docs/ja/slide/slide-kpi-hero.md +58 -0
- package/docs/ja/slide/slide-next-actions.md +49 -0
- package/docs/ja/slide/slide-scorecard-table.md +54 -0
- package/docs/ja/slide/slide-section.md +44 -0
- package/docs/ja/slide/slide-source-line.md +34 -0
- package/docs/ja/ui/alert-dialog.md +41 -0
- package/docs/ja/ui/avatar.md +31 -0
- package/docs/ja/ui/combobox.md +74 -0
- package/docs/ja/ui/drawer.md +41 -0
- package/docs/ja/ui/empty.md +1 -1
- package/docs/ja/ui/error-state.md +4 -3
- package/docs/ja/ui/field.md +42 -0
- package/docs/ja/ui/hover-card.md +21 -0
- package/docs/ja/ui/kbd.md +16 -0
- package/docs/ja/ui/loading.md +1 -1
- package/docs/ja/ui/pagination.md +36 -0
- package/docs/ja/ui/radio-group.md +21 -0
- package/docs/ja/ui/toast.md +46 -0
- package/docs/ja/ui/toggle-group.md +4 -3
- package/docs/ja/ui-and-theming.md +14 -7
- package/package.json +43 -29
- package/registry/parts.json +5221 -0
- package/registry/ui/accordion.tsx +76 -0
- package/registry/ui/alert-dialog.tsx +189 -0
- package/registry/ui/alert.tsx +80 -0
- package/registry/ui/app-shell.tsx +424 -0
- package/registry/ui/area-chart.tsx +3960 -0
- package/registry/ui/attention-list.tsx +465 -0
- package/registry/ui/avatar.tsx +110 -0
- package/registry/ui/badge.tsx +56 -0
- package/registry/ui/bar-chart.tsx +3954 -0
- package/registry/ui/bar-list.tsx +3998 -0
- package/registry/ui/box-plot-chart.tsx +4214 -0
- package/registry/ui/breadcrumb.tsx +128 -0
- package/registry/ui/button.tsx +62 -0
- package/registry/ui/calendar.tsx +223 -0
- package/registry/ui/card.tsx +107 -0
- package/registry/ui/category-bar.tsx +1498 -0
- package/registry/ui/chart-frame.tsx +1612 -0
- package/registry/ui/checkbox.tsx +30 -0
- package/registry/ui/collapsible.tsx +23 -0
- package/registry/ui/combo-chart.tsx +1852 -0
- package/registry/ui/combobox.tsx +310 -0
- package/registry/ui/command.tsx +198 -0
- package/registry/ui/dashboard-card.tsx +219 -0
- package/registry/ui/data-table.tsx +899 -158
- package/registry/ui/date-range-picker.tsx +544 -0
- package/registry/ui/delta.tsx +352 -0
- package/registry/ui/dialog.tsx +161 -0
- package/registry/ui/donut-chart.tsx +4006 -0
- package/registry/ui/drawer.tsx +229 -0
- package/registry/ui/dropdown-menu.tsx +274 -0
- package/registry/ui/echart.tsx +1178 -0
- package/registry/ui/field.tsx +240 -0
- package/registry/ui/filter-bar.tsx +553 -0
- package/registry/ui/forecast-chart.tsx +4734 -0
- package/registry/ui/funnel-steps.tsx +3843 -0
- package/registry/ui/heatmap.tsx +2027 -0
- package/registry/ui/histogram-chart.tsx +4284 -0
- package/registry/ui/hover-card.tsx +52 -0
- package/registry/ui/input-group.tsx +160 -0
- package/registry/ui/input.tsx +24 -0
- package/registry/ui/kbd.tsx +30 -0
- package/registry/ui/kpi-card.tsx +907 -0
- package/registry/ui/label.tsx +22 -0
- package/registry/ui/legend.tsx +3817 -0
- package/registry/ui/line-chart.tsx +3958 -0
- package/registry/ui/metric-value.tsx +62 -0
- package/registry/ui/multi-select.tsx +382 -0
- package/registry/ui/page-shell.tsx +441 -0
- package/registry/ui/pagination.tsx +140 -0
- package/registry/ui/paired-chart.tsx +4086 -0
- package/registry/ui/pivot-table.tsx +1260 -0
- package/registry/ui/placeholder.tsx +36 -0
- package/registry/ui/popover.tsx +92 -0
- package/registry/ui/progress-circle.tsx +1033 -0
- package/registry/ui/progress.tsx +85 -0
- package/registry/ui/radio-group.tsx +39 -0
- package/registry/ui/sample-data.tsx +230 -0
- package/registry/ui/scatter-chart.tsx +4503 -0
- package/registry/ui/scroll-area.tsx +56 -0
- package/registry/ui/searchable-select.tsx +352 -0
- package/registry/ui/section-header.tsx +43 -0
- package/registry/ui/segmented-control.tsx +76 -0
- package/registry/ui/select.tsx +255 -0
- package/registry/ui/separator.tsx +27 -0
- package/registry/ui/sheet.tsx +139 -0
- package/registry/ui/sidebar.tsx +725 -0
- package/registry/ui/skeleton.tsx +17 -0
- package/registry/ui/slider.tsx +56 -0
- package/registry/ui/sparkline.tsx +230 -0
- package/registry/ui/spinner.tsx +14 -0
- package/registry/ui/states.tsx +247 -0
- package/registry/ui/status-badge.tsx +286 -0
- package/registry/ui/switch.tsx +34 -0
- package/registry/ui/table.tsx +118 -0
- package/registry/ui/tabs.tsx +84 -0
- package/registry/ui/textarea.tsx +22 -0
- package/registry/ui/toast.tsx +250 -0
- package/registry/ui/toggle-group.tsx +91 -0
- package/registry/ui/toggle.tsx +47 -0
- package/registry/ui/tooltip.tsx +72 -0
- package/registry/ui/tracker.tsx +1015 -0
- package/registry/ui/treemap.tsx +1917 -0
- package/registry/ui/trend-indicator.tsx +217 -0
- package/registry/ui/updated-at.tsx +276 -0
- package/registry/ui/waterfall-chart.tsx +4561 -0
- package/skills/vantage-add-feature/SKILL.md +14 -7
- package/skills/vantage-design/SKILL.md +62 -52
- package/skills/vantage-design/references/extract.md +26 -27
- package/skills/vantage-design/references/format.md +12 -172
- package/skills/vantage-design/references/presets.md +50 -110
- package/skills/vantage-pitfalls/SKILL.md +10 -1
- package/skills/vantage-slide/SKILL.md +71 -36
- package/templates/AGENTS.md +54 -16
- package/templates/agents/api.md +36 -0
- package/templates/agents/csv.md +2 -1
- package/templates/agents/doc.md +52 -3
- package/templates/agents/page.md +91 -10
- package/templates/agents/slide.md +90 -4
- package/templates/agents/xlsx.md +2 -1
- package/theme.css +247 -132
- package/dist/add-EISGSZAH.js +0 -6
- package/dist/add-EISGSZAH.js.map +0 -1
- package/dist/chunk-3G43C6OL.js.map +0 -1
- package/dist/chunk-5ZOP4SQR.js +0 -47
- package/dist/chunk-5ZOP4SQR.js.map +0 -1
- package/dist/chunk-A2UUGASH.js.map +0 -1
- package/dist/chunk-BCE22JSM.js.map +0 -1
- package/dist/chunk-DTDVSFRY.js +0 -29
- package/dist/chunk-DTDVSFRY.js.map +0 -1
- package/dist/chunk-EP6JHXSR.js.map +0 -1
- package/dist/chunk-JGRMRXXZ.js.map +0 -1
- package/dist/chunk-KLEIVDUV.js +0 -165
- package/dist/chunk-KLEIVDUV.js.map +0 -1
- package/dist/chunk-LSRMRIXA.js +0 -2227
- package/dist/chunk-LSRMRIXA.js.map +0 -1
- package/dist/chunk-PVTHHV7X.js.map +0 -1
- package/dist/chunk-PXRX5PEC.js.map +0 -1
- package/dist/chunk-RPZAALCX.js.map +0 -1
- package/dist/chunk-T3FLAGI6.js +0 -316
- package/dist/chunk-T3FLAGI6.js.map +0 -1
- package/dist/dev-NZRLOQCL.js.map +0 -1
- package/dist/doctor-VFKEMR54.js.map +0 -1
- package/dist/preview-QDCIVVSR.js.map +0 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Copied by `vantage add ui metric-value`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/metric-value.tsx by `pnpm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* MetricValue — the large number in a dashboard tile (with `MetricUnit`, its
|
|
7
|
+
* trailing unit, sized as a pair so the unit stays subordinate at every size).
|
|
8
|
+
*
|
|
9
|
+
* @deprecated KPI の数字は KpiCard を使う。KpiCard は書式(`format`、単位は
|
|
10
|
+
* `{ type: "number", unit: "社" }`)・比較ラベル・増減を値から計算するので、
|
|
11
|
+
* 手書きの数字と TrendIndicator の組み合わせのように食い違わない。
|
|
12
|
+
*/
|
|
13
|
+
import { forwardRef, type HTMLAttributes } from "react"
|
|
14
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
15
|
+
|
|
16
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
17
|
+
|
|
18
|
+
export const metricValueVariants = cva("font-medium tracking-tight", {
|
|
19
|
+
variants: {
|
|
20
|
+
size: {
|
|
21
|
+
sm: "text-base",
|
|
22
|
+
md: "text-2xl",
|
|
23
|
+
lg: "text-3xl",
|
|
24
|
+
xl: "text-4xl",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: {
|
|
28
|
+
size: "md",
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export interface MetricValueProps
|
|
33
|
+
extends HTMLAttributes<HTMLDivElement>,
|
|
34
|
+
VariantProps<typeof metricValueVariants> {}
|
|
35
|
+
|
|
36
|
+
/** @deprecated KPI の数字は KpiCard を使う。 */
|
|
37
|
+
export const MetricValue = forwardRef<HTMLDivElement, MetricValueProps>(
|
|
38
|
+
({ className, size, ...props }, ref) => (
|
|
39
|
+
<div
|
|
40
|
+
ref={ref}
|
|
41
|
+
data-slot="metric-value"
|
|
42
|
+
className={cn("my-4", metricValueVariants({ size }), className)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
MetricValue.displayName = "MetricValue"
|
|
48
|
+
|
|
49
|
+
export interface MetricUnitProps extends HTMLAttributes<HTMLSpanElement> {}
|
|
50
|
+
|
|
51
|
+
/** @deprecated KPI の単位は KpiCard の `format`(`{ type: "number", unit: "社" }`)で付ける。 */
|
|
52
|
+
export const MetricUnit = forwardRef<HTMLSpanElement, MetricUnitProps>(
|
|
53
|
+
({ className, ...props }, ref) => (
|
|
54
|
+
<span
|
|
55
|
+
ref={ref}
|
|
56
|
+
data-slot="metric-unit"
|
|
57
|
+
className={cn("text-sm font-normal text-muted-foreground", className)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
MetricUnit.displayName = "MetricUnit"
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
// Copied by `vantage add ui multi-select`. This file is yours to edit.
|
|
2
|
+
// Generated from @squadbase/squadkit registry/components/multi-select.tsx by `pnpm run registry` (in Vantage, edit packages/squadkit, not registry/).
|
|
3
|
+
"use client"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* MultiSelect — a multi-value combobox that shows the selection as removable
|
|
7
|
+
* badges. Past `maxCount` badges the rest collapse into a "+N more" (ja: "+N件") counter.
|
|
8
|
+
* Pass `onSearch` to take filtering over yourself (server-side search).
|
|
9
|
+
*/
|
|
10
|
+
import { forwardRef, useId, useMemo, useState } from "react"
|
|
11
|
+
import { ChevronDownIcon } from "lucide-react"
|
|
12
|
+
|
|
13
|
+
import { cn } from "@squadbase/vantage/ui"
|
|
14
|
+
import { Badge } from "@squadbase/vantage/ui"
|
|
15
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@squadbase/vantage/ui"
|
|
16
|
+
import { flattenOptions, type SelectOptions } from "@squadbase/vantage/components"
|
|
17
|
+
import { useSyncExternalStore } from "react"
|
|
18
|
+
import type { KeyboardEvent, MouseEvent } from "react"
|
|
19
|
+
import { CheckIcon, LoaderIcon, XIcon } from "lucide-react"
|
|
20
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@squadbase/vantage/ui"
|
|
21
|
+
import { isGroupedOptions, type SelectOption } from "@squadbase/vantage/components"
|
|
22
|
+
|
|
23
|
+
/* ---------- inlined from @squadbase/squadkit registry/lib/locale.ts (internal to @squadbase/vantage) ---------- */
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The display language of the parts and the defaults that follow it.
|
|
27
|
+
*
|
|
28
|
+
* The language comes from `<html lang>`: a tag starting with `ja` reads Japanese, anything else English.
|
|
29
|
+
* Without a usable `lang` (missing, invalid, or no `document` — SSR, Node) the locale is `FALLBACK_LOCALE`
|
|
30
|
+
* (`en-US`). A `locale` passed explicitly (a prop, an argument) always wins.
|
|
31
|
+
*
|
|
32
|
+
* Parts read the locale through `useLocale` (`hooks/use-locale`) and pass it down; the pure helpers here
|
|
33
|
+
* and in `format` / `comparison` / `chart-*` take it as an argument and fall back to `documentLocale()`.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** The language of the built-in wording: Japanese or English. */
|
|
37
|
+
type UiLanguage = "ja" | "en"
|
|
38
|
+
|
|
39
|
+
/** The locale used when `<html lang>` gives none (and on the server). */
|
|
40
|
+
const FALLBACK_LOCALE = "en-US"
|
|
41
|
+
|
|
42
|
+
/** `"ja"` when `locale` starts with `ja` (`ja`, `ja-JP`), else `"en"`. A missing locale is `"en"`. */
|
|
43
|
+
function uiLanguage(locale: string | null | undefined): UiLanguage {
|
|
44
|
+
return typeof locale === "string" && locale.trim().toLowerCase().startsWith("ja") ? "ja" : "en"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** A BCP 47 tag in its canonical form (`en-gb` → `en-GB`), or `FALLBACK_LOCALE` when it is empty or invalid. */
|
|
48
|
+
function normalizeLocale(tag: string | null | undefined): string {
|
|
49
|
+
const value = tag?.trim()
|
|
50
|
+
if (!value) return FALLBACK_LOCALE
|
|
51
|
+
try {
|
|
52
|
+
return Intl.getCanonicalLocales(value)[0] ?? FALLBACK_LOCALE
|
|
53
|
+
} catch {
|
|
54
|
+
return FALLBACK_LOCALE
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The locale of the page: `document.documentElement.lang`, canonicalized. `FALLBACK_LOCALE` when it is empty or
|
|
60
|
+
* invalid, or there is no `document`. Parts read it through `useLocale`, never while rendering.
|
|
61
|
+
*/
|
|
62
|
+
function documentLocale(): string {
|
|
63
|
+
if (typeof document === "undefined") return FALLBACK_LOCALE
|
|
64
|
+
return normalizeLocale(document.documentElement?.getAttribute("lang"))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** `locale` when given, else the page's locale (`documentLocale()`). */
|
|
68
|
+
function resolveLocale(locale?: string | null): string {
|
|
69
|
+
return locale || documentLocale()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Picks the wording table of the locale's language. */
|
|
73
|
+
function pickLocale<T>(table: { ja: T; en: T }, locale?: string | null): T {
|
|
74
|
+
return table[uiLanguage(resolveLocale(locale))]
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** The currency `format="currency"` uses without a `currency`: JPY for Japanese, USD otherwise. */
|
|
78
|
+
function defaultCurrency(locale?: string | null): string {
|
|
79
|
+
return uiLanguage(resolveLocale(locale)) === "ja" ? "JPY" : "USD"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** The month a fiscal year starts in (1–12) when none is given: April for Japanese, January otherwise. */
|
|
83
|
+
function defaultFiscalYearStartMonth(locale?: string | null): number {
|
|
84
|
+
return uiLanguage(resolveLocale(locale)) === "ja" ? 4 : 1
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** A day of the week, 0 = Sunday … 6 = Saturday (the `Date#getDay` / date-fns numbering). */
|
|
88
|
+
type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6
|
|
89
|
+
|
|
90
|
+
/** Locales whose week starts on Sunday when the runtime has no week data. */
|
|
91
|
+
const SUNDAY_FIRST = new Set(["en", "en-US", "en-CA"])
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The first day of the week: Monday for Japanese; otherwise the locale's convention from `Intl.Locale`
|
|
95
|
+
* (`en-US` Sunday, `en-GB` Monday). Without week data in the runtime: Sunday for `en` / `en-US` / `en-CA`,
|
|
96
|
+
* Monday for the rest.
|
|
97
|
+
*/
|
|
98
|
+
function weekStartsOn(locale?: string | null): WeekDay {
|
|
99
|
+
const tag = normalizeLocale(resolveLocale(locale))
|
|
100
|
+
if (uiLanguage(tag) === "ja") return 1
|
|
101
|
+
try {
|
|
102
|
+
const info = new Intl.Locale(tag) as Intl.Locale & {
|
|
103
|
+
getWeekInfo?: () => { firstDay: number }
|
|
104
|
+
weekInfo?: { firstDay: number }
|
|
105
|
+
}
|
|
106
|
+
const firstDay = info.getWeekInfo?.().firstDay ?? info.weekInfo?.firstDay
|
|
107
|
+
if (typeof firstDay === "number" && firstDay >= 1 && firstDay <= 7) return (firstDay % 7) as WeekDay
|
|
108
|
+
} catch {
|
|
109
|
+
// Fall through to the table below.
|
|
110
|
+
}
|
|
111
|
+
return SUNDAY_FIRST.has(tag) ? 0 : 1
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* ---------- inlined from @squadbase/squadkit registry/hooks/use-locale.ts (internal to @squadbase/vantage) ---------- */
|
|
115
|
+
|
|
116
|
+
const listeners = new Set<() => void>()
|
|
117
|
+
let observer: MutationObserver | null = null
|
|
118
|
+
|
|
119
|
+
/** One observer on `<html lang>` for every subscribed part. */
|
|
120
|
+
function subscribe(onChange: () => void): () => void {
|
|
121
|
+
if (typeof document === "undefined" || typeof MutationObserver === "undefined") return () => {}
|
|
122
|
+
listeners.add(onChange)
|
|
123
|
+
if (!observer) {
|
|
124
|
+
observer = new MutationObserver(() => {
|
|
125
|
+
for (const listener of [...listeners]) listener()
|
|
126
|
+
})
|
|
127
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["lang"] })
|
|
128
|
+
}
|
|
129
|
+
return () => {
|
|
130
|
+
listeners.delete(onChange)
|
|
131
|
+
if (listeners.size === 0 && observer) {
|
|
132
|
+
observer.disconnect()
|
|
133
|
+
observer = null
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const serverLocale = () => FALLBACK_LOCALE
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The page's locale (`<html lang>`), following changes made while the page runs. On the server and during
|
|
142
|
+
* hydration it is `FALLBACK_LOCALE` (`en-US`), so the markup matches; it switches right after.
|
|
143
|
+
*/
|
|
144
|
+
function useDocumentLocale(): string {
|
|
145
|
+
return useSyncExternalStore(subscribe, documentLocale, serverLocale)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** The locale a part renders in: its `locale` prop when given, else the page's (`useDocumentLocale`). */
|
|
149
|
+
function useLocale(locale?: string | null): string {
|
|
150
|
+
const page = useDocumentLocale()
|
|
151
|
+
return locale || page
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* ---------- inlined from @squadbase/squadkit registry/components/option-command.tsx (internal to @squadbase/vantage) ---------- */
|
|
155
|
+
|
|
156
|
+
interface OptionCommandListProps {
|
|
157
|
+
options: SelectOptions
|
|
158
|
+
/** Whether the given option value is currently selected (drives the check). */
|
|
159
|
+
isSelected: (value: string) => boolean
|
|
160
|
+
onSelect: (value: string) => void
|
|
161
|
+
/** Take filtering over yourself (server-side search); turns off built-in filter. */
|
|
162
|
+
onSearch?: (query: string) => void
|
|
163
|
+
isLoading: boolean
|
|
164
|
+
searchPlaceholder: string
|
|
165
|
+
emptyText: string
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** The searchable list body — flat or grouped, with loading and empty states. */
|
|
169
|
+
function OptionCommandList({
|
|
170
|
+
options,
|
|
171
|
+
isSelected,
|
|
172
|
+
onSelect,
|
|
173
|
+
onSearch,
|
|
174
|
+
isLoading,
|
|
175
|
+
searchPlaceholder,
|
|
176
|
+
emptyText,
|
|
177
|
+
}: OptionCommandListProps) {
|
|
178
|
+
const renderOptions = (items: SelectOption[]) =>
|
|
179
|
+
items.map((option) => (
|
|
180
|
+
<CommandItem
|
|
181
|
+
key={option.value}
|
|
182
|
+
value={option.value}
|
|
183
|
+
keywords={[option.label]}
|
|
184
|
+
disabled={option.disabled}
|
|
185
|
+
onSelect={onSelect}
|
|
186
|
+
>
|
|
187
|
+
{option.icon && <option.icon className="size-4 shrink-0" />}
|
|
188
|
+
<span className="flex-1 truncate">
|
|
189
|
+
{option.label}
|
|
190
|
+
{option.description && (
|
|
191
|
+
<span className="ml-2 text-xs text-muted-foreground">{option.description}</span>
|
|
192
|
+
)}
|
|
193
|
+
</span>
|
|
194
|
+
<CheckIcon
|
|
195
|
+
className={cn("size-4 shrink-0", isSelected(option.value) ? "opacity-100" : "opacity-0")}
|
|
196
|
+
/>
|
|
197
|
+
</CommandItem>
|
|
198
|
+
))
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<Command shouldFilter={!onSearch}>
|
|
202
|
+
<CommandInput placeholder={searchPlaceholder} onValueChange={onSearch} />
|
|
203
|
+
<CommandList>
|
|
204
|
+
{isLoading ? (
|
|
205
|
+
<div className="flex items-center justify-center py-6">
|
|
206
|
+
<LoaderIcon className="size-4 animate-spin text-muted-foreground" />
|
|
207
|
+
</div>
|
|
208
|
+
) : (
|
|
209
|
+
<>
|
|
210
|
+
<CommandEmpty>{emptyText}</CommandEmpty>
|
|
211
|
+
{isGroupedOptions(options)
|
|
212
|
+
? options.map((group) => (
|
|
213
|
+
<CommandGroup key={group.label} heading={group.label}>
|
|
214
|
+
{renderOptions(group.options)}
|
|
215
|
+
</CommandGroup>
|
|
216
|
+
))
|
|
217
|
+
: renderOptions(options)}
|
|
218
|
+
</>
|
|
219
|
+
)}
|
|
220
|
+
</CommandList>
|
|
221
|
+
</Command>
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
interface RemoveButtonProps {
|
|
226
|
+
label: string
|
|
227
|
+
/** Runs on click and on Enter/Space; propagation is stopped for you. */
|
|
228
|
+
onRemove: () => void
|
|
229
|
+
/** Override the X icon size (default `size-3.5`). */
|
|
230
|
+
iconClassName?: string
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** The keyboard-accessible ×-affordance inside a badge or trigger. */
|
|
234
|
+
function RemoveButton({ label, onRemove, iconClassName }: RemoveButtonProps) {
|
|
235
|
+
const handle = (e: MouseEvent | KeyboardEvent) => {
|
|
236
|
+
e.stopPropagation()
|
|
237
|
+
onRemove()
|
|
238
|
+
}
|
|
239
|
+
return (
|
|
240
|
+
<span
|
|
241
|
+
role="button"
|
|
242
|
+
tabIndex={0}
|
|
243
|
+
aria-label={label}
|
|
244
|
+
className="rounded-sm opacity-50 hover:opacity-100 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none"
|
|
245
|
+
onClick={handle}
|
|
246
|
+
onKeyDown={(e) => {
|
|
247
|
+
if (e.key === "Enter" || e.key === " ") handle(e)
|
|
248
|
+
}}
|
|
249
|
+
>
|
|
250
|
+
<XIcon className={cn("size-3.5", iconClassName)} />
|
|
251
|
+
</span>
|
|
252
|
+
)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* ---------- end of inlined code ---------- */
|
|
256
|
+
|
|
257
|
+
export interface MultiSelectProps {
|
|
258
|
+
options: SelectOptions
|
|
259
|
+
value: string[]
|
|
260
|
+
onChange?: (value: string[]) => void
|
|
261
|
+
onSearch?: (query: string) => void
|
|
262
|
+
maxCount?: number
|
|
263
|
+
placeholder?: string
|
|
264
|
+
searchPlaceholder?: string
|
|
265
|
+
emptyText?: string
|
|
266
|
+
isLoading?: boolean
|
|
267
|
+
disabled?: boolean
|
|
268
|
+
className?: string
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const TEXT = {
|
|
272
|
+
ja: {
|
|
273
|
+
placeholder: "選択してください",
|
|
274
|
+
search: "検索...",
|
|
275
|
+
empty: "見つかりませんでした",
|
|
276
|
+
remove: (label: string) => `${label}を削除`,
|
|
277
|
+
more: (count: number) => `+${count}件`,
|
|
278
|
+
},
|
|
279
|
+
en: {
|
|
280
|
+
placeholder: "Select options",
|
|
281
|
+
search: "Search...",
|
|
282
|
+
empty: "No results found.",
|
|
283
|
+
remove: (label: string) => `Remove ${label}`,
|
|
284
|
+
more: (count: number) => `+${count} more`,
|
|
285
|
+
},
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Not given yet (a draft fills props in steps): render empty, keep the same value between renders. */
|
|
289
|
+
const NO_OPTIONS: never[] = []
|
|
290
|
+
const NO_VALUES: string[] = []
|
|
291
|
+
|
|
292
|
+
export const MultiSelect = forwardRef<HTMLDivElement, MultiSelectProps>(function MultiSelect(
|
|
293
|
+
{
|
|
294
|
+
options = NO_OPTIONS,
|
|
295
|
+
value = NO_VALUES,
|
|
296
|
+
onChange,
|
|
297
|
+
onSearch,
|
|
298
|
+
maxCount = 3,
|
|
299
|
+
placeholder,
|
|
300
|
+
searchPlaceholder,
|
|
301
|
+
emptyText,
|
|
302
|
+
isLoading = false,
|
|
303
|
+
disabled = false,
|
|
304
|
+
className,
|
|
305
|
+
},
|
|
306
|
+
ref,
|
|
307
|
+
) {
|
|
308
|
+
const [open, setOpen] = useState(false)
|
|
309
|
+
const listId = useId()
|
|
310
|
+
const t = TEXT[uiLanguage(useLocale())]
|
|
311
|
+
|
|
312
|
+
const allOptions = useMemo(() => flattenOptions(options), [options])
|
|
313
|
+
const selectedOptions = useMemo(
|
|
314
|
+
() => allOptions.filter((opt) => value.includes(opt.value)),
|
|
315
|
+
[allOptions, value],
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
function handleSelect(selectedValue: string) {
|
|
319
|
+
if (value.includes(selectedValue)) {
|
|
320
|
+
onChange?.(value.filter((v) => v !== selectedValue))
|
|
321
|
+
} else {
|
|
322
|
+
onChange?.([...value, selectedValue])
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const visibleBadges = selectedOptions.slice(0, maxCount)
|
|
327
|
+
const overflowCount = selectedOptions.length - maxCount
|
|
328
|
+
|
|
329
|
+
return (
|
|
330
|
+
<div ref={ref} data-slot="multi-select">
|
|
331
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
332
|
+
<PopoverTrigger
|
|
333
|
+
role="combobox"
|
|
334
|
+
aria-expanded={open}
|
|
335
|
+
aria-controls={listId}
|
|
336
|
+
disabled={disabled}
|
|
337
|
+
className={cn(
|
|
338
|
+
"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-[color,background-color,border-color,box-shadow] 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",
|
|
339
|
+
className,
|
|
340
|
+
)}
|
|
341
|
+
>
|
|
342
|
+
<span className="flex min-w-0 flex-1 flex-wrap items-center gap-1">
|
|
343
|
+
{selectedOptions.length === 0 ? (
|
|
344
|
+
<span className="text-muted-foreground">{placeholder ?? t.placeholder}</span>
|
|
345
|
+
) : (
|
|
346
|
+
<>
|
|
347
|
+
{visibleBadges.map((option) => (
|
|
348
|
+
<Badge key={option.value} variant="secondary" className="shrink-0 gap-1 pr-1">
|
|
349
|
+
<span className="max-w-[120px] truncate">{option.label}</span>
|
|
350
|
+
<RemoveButton
|
|
351
|
+
label={t.remove(option.label)}
|
|
352
|
+
onRemove={() => onChange?.(value.filter((v) => v !== option.value))}
|
|
353
|
+
iconClassName="size-3"
|
|
354
|
+
/>
|
|
355
|
+
</Badge>
|
|
356
|
+
))}
|
|
357
|
+
{overflowCount > 0 && (
|
|
358
|
+
<Badge variant="secondary" className="shrink-0">
|
|
359
|
+
{t.more(overflowCount)}
|
|
360
|
+
</Badge>
|
|
361
|
+
)}
|
|
362
|
+
</>
|
|
363
|
+
)}
|
|
364
|
+
</span>
|
|
365
|
+
<ChevronDownIcon className="size-4 shrink-0 opacity-50" />
|
|
366
|
+
</PopoverTrigger>
|
|
367
|
+
<PopoverContent id={listId} className="w-(--anchor-width) p-0" align="start">
|
|
368
|
+
<OptionCommandList
|
|
369
|
+
options={options}
|
|
370
|
+
isSelected={(v) => value.includes(v)}
|
|
371
|
+
onSelect={handleSelect}
|
|
372
|
+
onSearch={onSearch}
|
|
373
|
+
isLoading={isLoading}
|
|
374
|
+
searchPlaceholder={searchPlaceholder ?? t.search}
|
|
375
|
+
emptyText={emptyText ?? t.empty}
|
|
376
|
+
/>
|
|
377
|
+
</PopoverContent>
|
|
378
|
+
</Popover>
|
|
379
|
+
</div>
|
|
380
|
+
)
|
|
381
|
+
})
|
|
382
|
+
MultiSelect.displayName = "MultiSelect"
|