@squadbase/vantage 0.6.2-dev1.9365dcd → 0.6.2-dev1.9d7130b
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/{build-X5NVCQKT.js → build-U7GO26HR.js} +7 -7
- package/dist/{build-X5NVCQKT.js.map → build-U7GO26HR.js.map} +1 -1
- package/dist/{check-ZBIH422T.js → check-MRVAIHG5.js} +5 -5
- package/dist/{check-ZBIH422T.js.map → check-MRVAIHG5.js.map} +1 -1
- package/dist/chunk-2IAPIOPS.js +152 -0
- package/dist/chunk-2IAPIOPS.js.map +1 -0
- package/dist/chunk-3RJEOP3J.js +174 -0
- package/dist/chunk-3RJEOP3J.js.map +1 -0
- package/dist/{chunk-HKSVYMYJ.js → chunk-77CISBMG.js} +1049 -1387
- package/dist/chunk-77CISBMG.js.map +1 -0
- package/dist/{chunk-V3LF7BE7.js → chunk-ANZLVSEP.js} +4 -5
- package/dist/chunk-ANZLVSEP.js.map +1 -0
- package/dist/{chunk-XQUSGIDG.js → chunk-CKWPK4RO.js} +10 -3
- 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-2N72FKLB.js → chunk-NZ5QIIG4.js} +33 -11
- package/dist/chunk-NZ5QIIG4.js.map +1 -0
- package/dist/{chunk-7DZGJQ3P.js → chunk-PJ4SPXHS.js} +23 -6
- package/dist/chunk-PJ4SPXHS.js.map +1 -0
- package/dist/{chunk-XPQSTZUU.js → chunk-QNOX7WLZ.js} +5 -4
- package/dist/chunk-QNOX7WLZ.js.map +1 -0
- package/dist/{chunk-PDOBHMUQ.js → chunk-ROHNXP7J.js} +72 -3
- package/dist/chunk-ROHNXP7J.js.map +1 -0
- package/dist/{chunk-CEXAQQ5W.js → chunk-S5MDTHH7.js} +180 -18
- package/dist/chunk-S5MDTHH7.js.map +1 -0
- package/dist/{chunk-2ICNHUG6.js → chunk-SDJTTMLK.js} +64 -7
- package/dist/chunk-SDJTTMLK.js.map +1 -0
- package/dist/{chunk-WAMZWZJB.js → chunk-SHZM3EXB.js} +19 -8
- package/dist/chunk-SHZM3EXB.js.map +1 -0
- package/dist/chunk-TRMHNMMZ.js +61 -0
- package/dist/chunk-TRMHNMMZ.js.map +1 -0
- package/dist/{chunk-JKLLFVEU.js → chunk-UWSQUHX6.js} +4 -99
- package/dist/chunk-UWSQUHX6.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +8 -2
- package/dist/client/index.js.map +1 -1
- package/dist/components/index.d.ts +57 -273
- package/dist/components/index.js +6 -3
- package/dist/delta-text-CbrOaW83.d.ts +17 -0
- package/dist/{dev-4XEDTELV.js → dev-O42JFQ64.js} +7 -7
- package/dist/{dev-4XEDTELV.js.map → dev-O42JFQ64.js.map} +1 -1
- package/dist/doc/index.d.ts +215 -2
- package/dist/doc/index.js +422 -4
- package/dist/doc/index.js.map +1 -1
- package/dist/{doctor-5E2VEZPK.js → doctor-YD3XAAOT.js} +5 -5
- package/dist/{doctor-5E2VEZPK.js.map → doctor-YD3XAAOT.js.map} +1 -1
- package/dist/format-DihQkL1N.d.ts +249 -0
- package/dist/query/index.js +2 -2
- package/dist/{routes-3SGAFDMC.js → routes-PVKNT777.js} +4 -4
- package/dist/{routes-3SGAFDMC.js.map → routes-PVKNT777.js.map} +1 -1
- package/dist/slide/index.d.ts +272 -1
- package/dist/slide/index.js +1023 -2
- package/dist/slide/index.js.map +1 -1
- package/dist/table/index.js +9 -6
- package/dist/table/index.js.map +1 -1
- package/dist/ui/index.d.ts +5 -2
- package/dist/ui/index.js +6 -6
- package/dist/ui/index.js.map +1 -1
- package/dist/{upgrade-JHXZBGQS.js → upgrade-6DT7ADRP.js} +4 -4
- package/dist/{upgrade-JHXZBGQS.js.map → upgrade-6DT7ADRP.js.map} +1 -1
- package/dist/vite/index.js +3 -3
- package/docs/en/agent-skills.md +1 -1
- package/docs/en/changelog.md +2 -0
- package/docs/en/components.md +13 -2
- 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/delta.md +4 -3
- package/docs/en/parts/donut-chart.md +72 -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 +2 -1
- package/docs/en/parts/legend.md +35 -0
- package/docs/en/parts/line-chart.md +94 -0
- 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/tracker.md +36 -0
- 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/index.json +857 -77
- package/docs/ja/agent-skills.md +1 -1
- package/docs/ja/changelog.md +2 -0
- package/docs/ja/components.md +12 -1
- 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/slide.md +1 -0
- package/docs/ja/pages-and-metadata.md +15 -0
- package/docs/ja/parts/area-chart.md +49 -25
- package/docs/ja/parts/bar-chart.md +50 -24
- package/docs/ja/parts/bar-list.md +31 -8
- package/docs/ja/parts/chart-frame.md +36 -0
- package/docs/ja/parts/delta.md +5 -4
- package/docs/ja/parts/donut-chart.md +45 -26
- package/docs/ja/parts/funnel-steps.md +27 -8
- package/docs/ja/parts/heatmap.md +45 -0
- package/docs/ja/parts/kpi-card.md +2 -1
- package/docs/ja/parts/legend.md +36 -0
- package/docs/ja/parts/line-chart.md +48 -22
- package/docs/ja/parts/sample-data.md +61 -0
- package/docs/ja/parts/scatter-chart.md +69 -0
- package/docs/ja/parts/updated-at.md +27 -0
- package/docs/ja/parts/waterfall-chart.md +61 -0
- 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/empty.md +1 -1
- package/docs/ja/ui/error-state.md +4 -3
- package/docs/ja/ui/loading.md +1 -1
- package/docs/ja/ui/toggle-group.md +4 -3
- package/package.json +2 -2
- package/registry/ui/app-shell.tsx +138 -1
- package/registry/ui/area-chart.tsx +389 -104
- package/registry/ui/attention-list.tsx +177 -15
- package/registry/ui/bar-chart.tsx +386 -104
- package/registry/ui/bar-list.tsx +376 -94
- package/registry/ui/box-plot-chart.tsx +450 -116
- package/registry/ui/category-bar.tsx +292 -57
- package/registry/ui/chart-frame.tsx +301 -63
- package/registry/ui/data-table.tsx +229 -37
- package/registry/ui/date-range-picker.tsx +190 -36
- package/registry/ui/delta.tsx +181 -19
- package/registry/ui/donut-chart.tsx +385 -103
- package/registry/ui/echart.tsx +313 -58
- package/registry/ui/filter-bar.tsx +179 -20
- package/registry/ui/funnel-steps.tsx +354 -80
- package/registry/ui/heatmap.tsx +338 -71
- package/registry/ui/histogram-chart.tsx +440 -116
- package/registry/ui/kpi-card.tsx +254 -48
- package/registry/ui/legend.tsx +374 -93
- package/registry/ui/line-chart.tsx +389 -104
- package/registry/ui/multi-select.tsx +159 -9
- package/registry/ui/page-shell.tsx +148 -10
- package/registry/ui/paired-chart.tsx +394 -109
- package/registry/ui/progress-circle.tsx +205 -39
- package/registry/ui/sample-data.tsx +154 -10
- package/registry/ui/scatter-chart.tsx +436 -119
- package/registry/ui/searchable-select.tsx +145 -7
- package/registry/ui/slider.tsx +1 -1
- package/registry/ui/states.tsx +170 -13
- package/registry/ui/status-badge.tsx +201 -36
- package/registry/ui/tooltip.tsx +6 -2
- package/registry/ui/tracker.tsx +214 -42
- package/registry/ui/trend-indicator.tsx +151 -8
- package/registry/ui/updated-at.tsx +170 -16
- package/registry/ui/waterfall-chart.tsx +460 -121
- package/skills/vantage-add-feature/SKILL.md +5 -0
- package/skills/vantage-design/SKILL.md +54 -54
- 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 +5 -0
- package/skills/vantage-slide/SKILL.md +54 -36
- package/templates/AGENTS.md +35 -18
- package/templates/agents/api.md +7 -0
- package/templates/agents/doc.md +48 -0
- package/templates/agents/page.md +59 -2
- package/templates/agents/slide.md +77 -3
- package/theme.css +23 -19
- package/dist/chunk-2ICNHUG6.js.map +0 -1
- package/dist/chunk-2N72FKLB.js.map +0 -1
- package/dist/chunk-7DZGJQ3P.js.map +0 -1
- package/dist/chunk-CEXAQQ5W.js.map +0 -1
- package/dist/chunk-HKSVYMYJ.js.map +0 -1
- package/dist/chunk-JKLLFVEU.js.map +0 -1
- package/dist/chunk-PDOBHMUQ.js.map +0 -1
- package/dist/chunk-V3LF7BE7.js.map +0 -1
- package/dist/chunk-WAMZWZJB.js.map +0 -1
- package/dist/chunk-XPQSTZUU.js.map +0 -1
- package/dist/chunk-XQUSGIDG.js.map +0 -1
|
@@ -1,179 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ChartFrameContext, useChartSurface, resolveChartColors, CHART_OTHER_COLOR, EChart, resolveFillColors } from './chunk-EG4PX726.js';
|
|
2
|
+
import { Sparkline } from './chunk-2IAPIOPS.js';
|
|
3
|
+
import { formatDateRange, EMPTY_VALUE, formatDate, toValueFormatter, formatValue, formatPoints, formatKind, formatDelta, MINUS_SIGN, formatDatesInText, DEFAULT_LOCALE } from './chunk-3RJEOP3J.js';
|
|
4
|
+
import { Tooltip, TooltipTrigger, TooltipContent, Badge, SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Checkbox, Card, CardHeader, CardDescription, CardTitle, CardAction, CardFooter } from './chunk-QNOX7WLZ.js';
|
|
5
|
+
import { useLocale, uiLanguage, Button, weekStartsOn, resolveLocale, defaultFiscalYearStartMonth, FALLBACK_LOCALE } from './chunk-ROHNXP7J.js';
|
|
3
6
|
import { cn } from './chunk-U736PVHY.js';
|
|
4
|
-
import { forwardRef, useState, useEffect, createContext, useId,
|
|
7
|
+
import { forwardRef, useState, useEffect, createContext, useId, useMemo, useRef, useCallback, Fragment as Fragment$1, useContext } from 'react';
|
|
5
8
|
import { cva } from 'class-variance-authority';
|
|
6
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
import {
|
|
8
|
-
import { use
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { CanvasRenderer } from 'echarts/renderers';
|
|
10
|
+
import { Search, Columns3, CalendarIcon, ChevronDownIcon, ArrowUp, ArrowDown, ArrowRight, Minus, ChevronRight, ArrowUpDown, XIcon, LoaderIcon, CheckIcon, Download, ChevronDown, X, CircleX, TriangleAlert, CircleCheck } from 'lucide-react';
|
|
11
|
+
import { use } from 'echarts/core';
|
|
12
|
+
import { GraphicComponent, VisualMapComponent } from 'echarts/components';
|
|
13
|
+
import { ScatterChart as ScatterChart$1, HeatmapChart } from 'echarts/charts';
|
|
12
14
|
import 'echarts';
|
|
13
15
|
import { flexRender, useReactTable, getPaginationRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
|
|
14
|
-
import { subMonths, subDays, endOfDay, startOfDay, startOfWeek, subWeeks, endOfWeek, startOfMonth, endOfMonth, isSameDay,
|
|
16
|
+
import { subMonths, subDays, endOfDay, startOfDay, startOfWeek, subWeeks, endOfWeek, startOfMonth, endOfMonth, isSameDay, addMonths } from 'date-fns';
|
|
15
17
|
import { ja } from 'date-fns/locale';
|
|
16
18
|
|
|
17
19
|
// @squadbase/vantage — generated build. Do not edit.
|
|
18
20
|
|
|
19
|
-
// ../squadkit/registry/lib/format.ts
|
|
20
|
-
var DEFAULT_LOCALE = "ja-JP";
|
|
21
|
-
var EMPTY_VALUE = "\u2014";
|
|
22
|
-
var MINUS_SIGN = "\u2212";
|
|
23
|
-
var PERCENT_DIGITS = 1;
|
|
24
|
-
var DEFAULT_CURRENCY = "JPY";
|
|
25
|
-
var MULTIPLE_SUFFIX = "\xD7";
|
|
26
|
-
var POINTS_SUFFIX = "pt";
|
|
27
|
-
function normalize(format2) {
|
|
28
|
-
if (format2 === void 0) return { type: "compact" };
|
|
29
|
-
return typeof format2 === "string" ? { type: format2 } : format2;
|
|
30
|
-
}
|
|
31
|
-
function formatKind(format2) {
|
|
32
|
-
return normalize(format2).type;
|
|
33
|
-
}
|
|
34
|
-
function digitOptions(digits, defaultMax, significantDigits) {
|
|
35
|
-
if (significantDigits !== void 0) return { maximumSignificantDigits: significantDigits };
|
|
36
|
-
if (digits !== void 0) return { minimumFractionDigits: digits, maximumFractionDigits: digits };
|
|
37
|
-
return defaultMax === void 0 ? {} : { maximumFractionDigits: defaultMax };
|
|
38
|
-
}
|
|
39
|
-
function formatParts(locale, options, value) {
|
|
40
|
-
if (options.notation === "compact") {
|
|
41
|
-
const compact = new Intl.NumberFormat(locale, {
|
|
42
|
-
...options,
|
|
43
|
-
useGrouping: "always"
|
|
44
|
-
}).formatToParts(value);
|
|
45
|
-
if (!compact.some((p) => p.type === "compact")) return formatParts(locale, { ...options, notation: "standard" }, value);
|
|
46
|
-
return joinParts(compact);
|
|
47
|
-
}
|
|
48
|
-
return joinParts(new Intl.NumberFormat(locale, options).formatToParts(value));
|
|
49
|
-
}
|
|
50
|
-
var joinParts = (parts) => parts.map((p) => p.type === "currency" ? p.value.normalize("NFKC") : p.type === "minusSign" ? MINUS_SIGN : p.value).join("");
|
|
51
|
-
function formatValue(value, format2, locale = DEFAULT_LOCALE, options) {
|
|
52
|
-
if (value === null || value === void 0 || Number.isNaN(value)) return EMPTY_VALUE;
|
|
53
|
-
const { type, digits, currency, notation, unit, divisor, durationUnit } = normalize(format2);
|
|
54
|
-
if (divisor !== void 0 && Number.isFinite(divisor) && divisor !== 0) value = value / divisor;
|
|
55
|
-
const signDisplay = options?.signDisplay ?? "auto";
|
|
56
|
-
const sig = options?.significantDigits;
|
|
57
|
-
const withUnit = (s) => unit ? `${s}${unit}` : s;
|
|
58
|
-
switch (type) {
|
|
59
|
-
case "number":
|
|
60
|
-
return withUnit(formatParts(locale, { ...digitOptions(digits, 2, sig), signDisplay }, value));
|
|
61
|
-
case "percent":
|
|
62
|
-
return formatParts(locale, { style: "percent", ...digitOptions(digits ?? PERCENT_DIGITS, void 0, sig), signDisplay }, value);
|
|
63
|
-
case "currency":
|
|
64
|
-
return withUnit(
|
|
65
|
-
formatParts(
|
|
66
|
-
locale,
|
|
67
|
-
{
|
|
68
|
-
style: "currency",
|
|
69
|
-
currency: currency ?? DEFAULT_CURRENCY,
|
|
70
|
-
notation: notation ?? "compact",
|
|
71
|
-
...digitOptions(digits, notation === "standard" ? void 0 : 1, sig),
|
|
72
|
-
signDisplay
|
|
73
|
-
},
|
|
74
|
-
value
|
|
75
|
-
)
|
|
76
|
-
);
|
|
77
|
-
case "multiple":
|
|
78
|
-
return `${formatParts(locale, { ...digitOptions(digits, 2, sig), signDisplay }, value)}${unit || MULTIPLE_SUFFIX}`;
|
|
79
|
-
case "compact":
|
|
80
|
-
return withUnit(formatParts(locale, { ...digitOptions(digits, 1, sig), signDisplay, notation: "compact" }, value));
|
|
81
|
-
case "duration":
|
|
82
|
-
return formatDuration(value, durationUnit ?? "second", locale, digits, signDisplay);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
var SECONDS_PER = { second: 1, minute: 60, hour: 3600, day: 86400 };
|
|
86
|
-
function durationWords(locale) {
|
|
87
|
-
return locale.toLowerCase().startsWith("ja") ? { day: "\u65E5", hour: "\u6642\u9593", minute: "\u5206", second: "\u79D2", sep: "" } : { day: "d", hour: "h", minute: "min", second: "s", sep: " " };
|
|
88
|
-
}
|
|
89
|
-
function formatDuration(value, unit, locale, digits, signDisplay) {
|
|
90
|
-
const w = durationWords(locale);
|
|
91
|
-
const abs = Math.round(Math.abs(value) * SECONDS_PER[unit]);
|
|
92
|
-
const join = (...parts) => parts.filter(([n]) => n !== 0).map(([n, u]) => `${n}${w.sep}${u}`).join(w.sep) || `0${w.sep}${parts.at(-1)?.[1] ?? w.second}`;
|
|
93
|
-
let body;
|
|
94
|
-
let zero = false;
|
|
95
|
-
if (abs >= 86400) {
|
|
96
|
-
const days = new Intl.NumberFormat(locale, { maximumFractionDigits: digits ?? 1, minimumFractionDigits: digits ?? 0 });
|
|
97
|
-
body = `${days.format(abs / 86400)}${w.sep}${w.day}`;
|
|
98
|
-
} else if (abs >= 3600) {
|
|
99
|
-
const minutes = Math.round(abs / 60);
|
|
100
|
-
body = join([Math.floor(minutes / 60), w.hour], [minutes % 60, w.minute]);
|
|
101
|
-
} else if (abs >= 60) {
|
|
102
|
-
body = join([Math.floor(abs / 60), w.minute], [abs % 60, w.second]);
|
|
103
|
-
} else {
|
|
104
|
-
zero = abs === 0;
|
|
105
|
-
body = `${abs}${w.sep}${w.second}`;
|
|
106
|
-
}
|
|
107
|
-
const sign = zero ? "" : value < 0 ? MINUS_SIGN : signDisplay === "exceptZero" ? "+" : "";
|
|
108
|
-
return `${sign}${body}`;
|
|
109
|
-
}
|
|
110
|
-
function formatDelta(value, format2, locale = DEFAULT_LOCALE) {
|
|
111
|
-
return formatValue(value, format2, locale, { signDisplay: "exceptZero" });
|
|
112
|
-
}
|
|
113
|
-
function formatPoints(difference, locale = DEFAULT_LOCALE, options) {
|
|
114
|
-
if (difference === null || difference === void 0 || Number.isNaN(difference)) return EMPTY_VALUE;
|
|
115
|
-
const digits = options?.digits ?? PERCENT_DIGITS;
|
|
116
|
-
const number = formatParts(
|
|
117
|
-
locale,
|
|
118
|
-
{ minimumFractionDigits: digits, maximumFractionDigits: digits, signDisplay: options?.signDisplay ?? "exceptZero" },
|
|
119
|
-
difference * 100
|
|
120
|
-
);
|
|
121
|
-
return `${number}${POINTS_SUFFIX}`;
|
|
122
|
-
}
|
|
123
|
-
function toValueFormatter(format2, locale = DEFAULT_LOCALE) {
|
|
124
|
-
return (value) => formatValue(value, format2, locale);
|
|
125
|
-
}
|
|
126
|
-
var DATE_STYLE_OPTIONS = {
|
|
127
|
-
date: { year: "numeric", month: "2-digit", day: "2-digit" },
|
|
128
|
-
datetime: { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hourCycle: "h23" },
|
|
129
|
-
month: { month: "short" },
|
|
130
|
-
"year-month": { year: "numeric", month: "long" },
|
|
131
|
-
year: { year: "numeric" }
|
|
132
|
-
};
|
|
133
|
-
var CALENDAR_DATE = /^\d{4}-\d{2}(-\d{2})?$/;
|
|
134
|
-
function formatDate(value, style = "date", locale = DEFAULT_LOCALE, options) {
|
|
135
|
-
if (value === null || value === void 0 || value === "") return EMPTY_VALUE;
|
|
136
|
-
const calendar = typeof value === "string" && CALENDAR_DATE.test(value);
|
|
137
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
138
|
-
if (!Number.isFinite(date.getTime())) return EMPTY_VALUE;
|
|
139
|
-
return new Intl.DateTimeFormat(locale, {
|
|
140
|
-
...DATE_STYLE_OPTIONS[style],
|
|
141
|
-
timeZone: calendar ? "UTC" : options?.timeZone
|
|
142
|
-
}).format(date);
|
|
143
|
-
}
|
|
144
|
-
function formatDateRange(start, end, options) {
|
|
145
|
-
const locale = options?.locale ?? DEFAULT_LOCALE;
|
|
146
|
-
const parse = (value) => {
|
|
147
|
-
if (value === null || value === void 0 || value === "") return null;
|
|
148
|
-
const calendar = typeof value === "string" && CALENDAR_DATE.test(value);
|
|
149
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
150
|
-
if (!Number.isFinite(date.getTime())) return null;
|
|
151
|
-
return { date, timeZone: calendar ? "UTC" : options?.timeZone };
|
|
152
|
-
};
|
|
153
|
-
const a = parse(start);
|
|
154
|
-
const b = parse(end);
|
|
155
|
-
if (!a || !b) return EMPTY_VALUE;
|
|
156
|
-
const full = (x, withYear) => new Intl.DateTimeFormat(locale, {
|
|
157
|
-
...withYear ? { year: "numeric" } : {},
|
|
158
|
-
month: "numeric",
|
|
159
|
-
day: "numeric",
|
|
160
|
-
timeZone: x.timeZone
|
|
161
|
-
}).format(x.date);
|
|
162
|
-
const year = (x) => new Intl.DateTimeFormat("en-US", { year: "numeric", timeZone: x.timeZone }).format(x.date);
|
|
163
|
-
const startText = full(a, true);
|
|
164
|
-
const sameYear = year(a) === year(b);
|
|
165
|
-
const endFull = full(b, true);
|
|
166
|
-
if (startText === endFull) return startText;
|
|
167
|
-
const separator = locale.toLowerCase().startsWith("ja") ? "\u301C" : " \u2013 ";
|
|
168
|
-
return `${startText}${separator}${sameYear ? full(b, false) : endFull}`;
|
|
169
|
-
}
|
|
170
|
-
function formatDatesInText(text, locale = DEFAULT_LOCALE) {
|
|
171
|
-
return text.replace(
|
|
172
|
-
/(?<![\d-])(\d{4})-(0[1-9]|1[0-2])(-(0[1-9]|[12]\d|3[01]))?(?![\d-])/g,
|
|
173
|
-
(match, _y, _m, day) => formatDate(match, day ? "date" : "year-month", locale)
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
21
|
// ../squadkit/registry/lib/relative-time.ts
|
|
178
22
|
var SECOND = 1e3;
|
|
179
23
|
var MINUTE = 60 * SECOND;
|
|
@@ -197,36 +41,50 @@ function formatRelativeTime(date, options) {
|
|
|
197
41
|
const now = nowValue instanceof Date ? nowValue.getTime() : nowValue;
|
|
198
42
|
if (!Number.isFinite(time) || !Number.isFinite(now)) return EMPTY_VALUE;
|
|
199
43
|
const diff = time - now;
|
|
200
|
-
const rtf = new Intl.RelativeTimeFormat(options?.locale
|
|
44
|
+
const rtf = new Intl.RelativeTimeFormat(resolveLocale(options?.locale), { numeric: "always" });
|
|
201
45
|
for (const [unit, size] of UNITS) {
|
|
202
46
|
if (Math.abs(diff) >= size) return rtf.format(Math.trunc(diff / size), unit);
|
|
203
47
|
}
|
|
204
48
|
return rtf.format(Math.trunc(diff / SECOND), "second");
|
|
205
49
|
}
|
|
206
50
|
var REFRESH_MS = 6e4;
|
|
51
|
+
var TEXT = {
|
|
52
|
+
ja: {
|
|
53
|
+
justNow: "\u305F\u3063\u305F\u4ECA",
|
|
54
|
+
relative: (relative2) => `${relative2}\u306B\u66F4\u65B0`,
|
|
55
|
+
absoluteFirst: (shown, relative2) => `${shown} \u66F4\u65B0\uFF08${relative2}\uFF09`
|
|
56
|
+
},
|
|
57
|
+
en: {
|
|
58
|
+
justNow: "just now",
|
|
59
|
+
relative: (relative2) => `Updated ${relative2}`,
|
|
60
|
+
absoluteFirst: (shown, relative2) => `Updated ${shown} (${relative2})`
|
|
61
|
+
}
|
|
62
|
+
};
|
|
207
63
|
var toMs = (value) => value instanceof Date ? value.getTime() : new Date(value).getTime();
|
|
208
|
-
function relative(at, now) {
|
|
209
|
-
if (now - at < REFRESH_MS && now - at > -REFRESH_MS) return
|
|
210
|
-
return formatRelativeTime(at, { now });
|
|
64
|
+
function relative(at, now, locale) {
|
|
65
|
+
if (now - at < REFRESH_MS && now - at > -REFRESH_MS) return TEXT[uiLanguage(locale)].justNow;
|
|
66
|
+
return formatRelativeTime(at, { now, locale });
|
|
211
67
|
}
|
|
212
|
-
function absolute(at, timeZone) {
|
|
68
|
+
function absolute(at, locale, timeZone) {
|
|
213
69
|
if (!Number.isFinite(at)) return void 0;
|
|
214
|
-
const zone = new Intl.DateTimeFormat(
|
|
215
|
-
const text = formatDate(at, "datetime",
|
|
70
|
+
const zone = new Intl.DateTimeFormat(locale, { timeZone, timeZoneName: "short" }).formatToParts(at).find((part) => part.type === "timeZoneName")?.value;
|
|
71
|
+
const text = formatDate(at, "datetime", locale, { timeZone });
|
|
216
72
|
return zone ? `${text} ${zone}` : text;
|
|
217
73
|
}
|
|
218
|
-
function label(at, now, variant, timeZone) {
|
|
74
|
+
function label(at, now, variant, locale, timeZone) {
|
|
219
75
|
if (!Number.isFinite(at) || !Number.isFinite(now)) return EMPTY_VALUE;
|
|
76
|
+
const t = TEXT[uiLanguage(locale)];
|
|
220
77
|
if (variant === "relative") {
|
|
221
|
-
return now - at < REFRESH_MS && now - at > -REFRESH_MS ? "
|
|
78
|
+
return now - at < REFRESH_MS && now - at > -REFRESH_MS ? uiLanguage(locale) === "ja" ? t.justNow : t.relative(t.justNow) : t.relative(relative(at, now, locale));
|
|
222
79
|
}
|
|
223
|
-
const today = formatDate(at, "date",
|
|
224
|
-
const when = formatDate(at, "datetime",
|
|
80
|
+
const today = formatDate(at, "date", locale, { timeZone }) === formatDate(now, "date", locale, { timeZone });
|
|
81
|
+
const when = formatDate(at, "datetime", locale, { timeZone });
|
|
225
82
|
const shown = today ? when.slice(-5) : when;
|
|
226
|
-
return
|
|
83
|
+
return t.absoluteFirst(shown, relative(at, now, locale));
|
|
227
84
|
}
|
|
228
85
|
var UpdatedAt = forwardRef(
|
|
229
86
|
({ at, variant = "relative", timeZone, prefix, now, className }, ref) => {
|
|
87
|
+
const locale = useLocale();
|
|
230
88
|
const atMs = toMs(at);
|
|
231
89
|
const [current, setCurrent] = useState(null);
|
|
232
90
|
const fixed = now === void 0 ? void 0 : toMs(now);
|
|
@@ -239,9 +97,9 @@ var UpdatedAt = forwardRef(
|
|
|
239
97
|
const clock = fixed ?? current;
|
|
240
98
|
const ready = clock !== null;
|
|
241
99
|
const dateTime = Number.isFinite(atMs) ? new Date(atMs).toISOString() : void 0;
|
|
242
|
-
const full = ready ? absolute(atMs, timeZone) : void 0;
|
|
100
|
+
const full = ready ? absolute(atMs, locale, timeZone) : void 0;
|
|
243
101
|
const classes = cn("text-sm text-muted-foreground tabular-nums", className);
|
|
244
|
-
const text = ready ? `${prefix ?? ""}${label(atMs, clock, variant, timeZone)}` : null;
|
|
102
|
+
const text = ready ? `${prefix ?? ""}${label(atMs, clock, variant, locale, timeZone)}` : null;
|
|
245
103
|
if (!full) {
|
|
246
104
|
return /* @__PURE__ */ jsx("time", { ref, "data-slot": "updated-at", dateTime, className: classes, suppressHydrationWarning: true, children: text });
|
|
247
105
|
}
|
|
@@ -272,9 +130,11 @@ var PageShell = forwardRef(
|
|
|
272
130
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "page-shell", className: cn("flex flex-col", className), ...props })
|
|
273
131
|
);
|
|
274
132
|
PageShell.displayName = "PageShell";
|
|
133
|
+
var SOURCE_PREFIX = { ja: "\u51FA\u5178\uFF1A", en: "Source: " };
|
|
275
134
|
var PageShellHeader = forwardRef(
|
|
276
135
|
({ className, updatedAt, updatedAtVariant, timeZone, source, period, status, children, ...props }, ref) => {
|
|
277
|
-
const
|
|
136
|
+
const locale = useLocale();
|
|
137
|
+
const periodText = period ? formatDateRange(period.start, period.end, { timeZone, locale }) : void 0;
|
|
278
138
|
const hasChips = Boolean(source) || periodText !== void 0 && periodText !== EMPTY_VALUE;
|
|
279
139
|
const hasStatus = status !== void 0 && status !== null && status !== false && status !== "";
|
|
280
140
|
return /* @__PURE__ */ jsxs(
|
|
@@ -288,11 +148,11 @@ var PageShellHeader = forwardRef(
|
|
|
288
148
|
children,
|
|
289
149
|
updatedAt !== void 0 && updatedAt !== null ? /* @__PURE__ */ jsx("div", { "data-slot": "page-shell-updated-at", className: "ml-auto max-w-full shrink-0 text-right", children: /* @__PURE__ */ jsx(UpdatedAt, { at: updatedAt, variant: updatedAtVariant, timeZone }) }) : null,
|
|
290
150
|
hasChips ? /* @__PURE__ */ jsxs("div", { "data-slot": "page-shell-chips", className: "order-1 flex basis-full flex-wrap gap-1.5", children: [
|
|
291
|
-
source ? /* @__PURE__ */ jsxs(Badge, { variant: "outline", className: "h-auto max-w-full whitespace-normal", children: [
|
|
292
|
-
|
|
151
|
+
source ? /* @__PURE__ */ jsxs(Badge, { variant: "outline", className: "h-auto max-w-full whitespace-normal text-muted-foreground", children: [
|
|
152
|
+
SOURCE_PREFIX[uiLanguage(locale)],
|
|
293
153
|
source
|
|
294
154
|
] }) : null,
|
|
295
|
-
periodText && periodText !== EMPTY_VALUE ? /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "tabular-nums", children: periodText }) : null
|
|
155
|
+
periodText && periodText !== EMPTY_VALUE ? /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "tabular-nums text-muted-foreground", children: periodText }) : null
|
|
296
156
|
] }) : null,
|
|
297
157
|
hasStatus ? /* @__PURE__ */ jsx("div", { "data-slot": "page-shell-status", className: "order-2 min-w-0 basis-full", children: status }) : null
|
|
298
158
|
]
|
|
@@ -389,11 +249,11 @@ var PageShellSummary = forwardRef(
|
|
|
389
249
|
);
|
|
390
250
|
PageShellSummary.displayName = "PageShellSummary";
|
|
391
251
|
var summaryCardTones = {
|
|
392
|
-
positive: "border-positive/
|
|
393
|
-
negative: "border-negative/
|
|
394
|
-
warning: "border-warning/
|
|
395
|
-
info: "border-info/
|
|
396
|
-
neutral: "border-neutral/
|
|
252
|
+
positive: "border-positive/20 dark:border-positive/25 bg-positive-subtle [&>svg]:text-positive",
|
|
253
|
+
negative: "border-negative/20 dark:border-negative/25 bg-negative-subtle [&>svg]:text-negative",
|
|
254
|
+
warning: "border-warning/20 dark:border-warning/25 bg-warning-subtle [&>svg]:text-warning",
|
|
255
|
+
info: "border-info/20 dark:border-info/25 bg-info-subtle [&>svg]:text-info",
|
|
256
|
+
neutral: "border-neutral/20 dark:border-neutral/25 bg-neutral-subtle [&>svg]:text-neutral",
|
|
397
257
|
violet: "border-chart-4/30 bg-chart-4/5 [&>svg]:text-chart-4",
|
|
398
258
|
pink: "border-chart-5/30 bg-chart-5/5 [&>svg]:text-chart-5"
|
|
399
259
|
};
|
|
@@ -457,6 +317,7 @@ var PageShellContent = forwardRef(
|
|
|
457
317
|
)
|
|
458
318
|
);
|
|
459
319
|
PageShellContent.displayName = "PageShellContent";
|
|
320
|
+
var PAGE_PLACEHOLDER = { ja: "\u30DA\u30FC\u30B8\u3092\u9078\u629E", en: "Select a page" };
|
|
460
321
|
function flattenItems(item) {
|
|
461
322
|
if (item.children && item.children.length > 0) {
|
|
462
323
|
return item.children.flatMap(flattenItems);
|
|
@@ -470,6 +331,7 @@ function NavSelect({
|
|
|
470
331
|
const allItems = groups.flatMap((g) => g.items.flatMap(flattenItems));
|
|
471
332
|
const currentValue = allItems.find((item) => item.isActive)?.href ?? "";
|
|
472
333
|
const selectItems = allItems.map((item) => ({ value: item.href, label: item.label }));
|
|
334
|
+
const placeholder = PAGE_PLACEHOLDER[uiLanguage(useLocale())];
|
|
473
335
|
return /* @__PURE__ */ jsxs(
|
|
474
336
|
Select,
|
|
475
337
|
{
|
|
@@ -479,7 +341,7 @@ function NavSelect({
|
|
|
479
341
|
if (href !== null) onNavigate(href);
|
|
480
342
|
},
|
|
481
343
|
children: [
|
|
482
|
-
/* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, { placeholder
|
|
344
|
+
/* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }),
|
|
483
345
|
/* @__PURE__ */ jsx(
|
|
484
346
|
SelectContent,
|
|
485
347
|
{
|
|
@@ -652,8 +514,11 @@ var SectionHeader = forwardRef(
|
|
|
652
514
|
)
|
|
653
515
|
);
|
|
654
516
|
SectionHeader.displayName = "SectionHeader";
|
|
655
|
-
var
|
|
656
|
-
|
|
517
|
+
var TEXT2 = {
|
|
518
|
+
ja: { label: "\u898B\u672C\u306E\u5024", title: "\u5B9F\u30C7\u30FC\u30BF\u306B\u307E\u3060\u3064\u306A\u304C\u3063\u3066\u3044\u306A\u3044\u898B\u672C\u306E\u5024\u3067\u3059" },
|
|
519
|
+
en: { label: "Sample data", title: "Sample values, not connected to real data yet" }
|
|
520
|
+
};
|
|
521
|
+
var DEFAULT_SAMPLE_LABEL = TEXT2.en.label;
|
|
657
522
|
var SampleContext = createContext(null);
|
|
658
523
|
function useSampleMark() {
|
|
659
524
|
return useContext(SampleContext);
|
|
@@ -661,20 +526,22 @@ function useSampleMark() {
|
|
|
661
526
|
function SampleClaim({ children }) {
|
|
662
527
|
return /* @__PURE__ */ jsx(SampleContext.Provider, { value: null, children });
|
|
663
528
|
}
|
|
664
|
-
function SampleBadge({ label: label2
|
|
529
|
+
function SampleBadge({ label: label2, className, ...props }) {
|
|
530
|
+
const t = TEXT2[uiLanguage(useLocale())];
|
|
665
531
|
return /* @__PURE__ */ jsx(
|
|
666
532
|
Badge,
|
|
667
533
|
{
|
|
668
534
|
"data-slot": "sample-badge",
|
|
669
|
-
title:
|
|
670
|
-
className: cn("border-warning/
|
|
535
|
+
title: t.title,
|
|
536
|
+
className: cn("border-warning/20 dark:border-warning/25 bg-warning-subtle text-warning align-middle", className),
|
|
671
537
|
...props,
|
|
672
|
-
children: label2
|
|
538
|
+
children: label2 ?? t.label
|
|
673
539
|
}
|
|
674
540
|
);
|
|
675
541
|
}
|
|
676
|
-
function SampleData({ label: label2
|
|
677
|
-
const
|
|
542
|
+
function SampleData({ label: label2, children }) {
|
|
543
|
+
const shown = label2 ?? TEXT2[uiLanguage(useLocale())].label;
|
|
544
|
+
const state = useMemo(() => ({ label: shown }), [shown]);
|
|
678
545
|
return /* @__PURE__ */ jsx("div", { "data-slot": "sample-data", style: { display: "contents" }, children: /* @__PURE__ */ jsx(SampleContext.Provider, { value: state, children }) });
|
|
679
546
|
}
|
|
680
547
|
var SUBGRID_CLASS = {
|
|
@@ -807,230 +674,11 @@ function DashboardCardPreset({
|
|
|
807
674
|
footer && /* @__PURE__ */ jsx(DashboardCardFooter, { className: cn(subgrid === 3 && "row-start-3", footerClassName), children: footer })
|
|
808
675
|
] }) });
|
|
809
676
|
}
|
|
810
|
-
var CHART_OTHER_COLOR = "color-mix(in oklab, var(--neutral) 50%, var(--background))";
|
|
811
|
-
var ChartFrameContext = createContext(false);
|
|
812
|
-
var SERIES_TOKENS = ["--chart-1", "--chart-2", "--chart-3", "--chart-4", "--chart-5"];
|
|
813
|
-
var normalizeContext;
|
|
814
|
-
var ZRENDER_COLOR_RE = /^(?:#[0-9a-f]{6}|rgba?\()/i;
|
|
815
|
-
function toCanvasColor(value) {
|
|
816
|
-
const raw = value.trim();
|
|
817
|
-
if (!raw) return null;
|
|
818
|
-
if (normalizeContext === void 0) {
|
|
819
|
-
const canvas = document.createElement("canvas");
|
|
820
|
-
canvas.width = 1;
|
|
821
|
-
canvas.height = 1;
|
|
822
|
-
normalizeContext = canvas.getContext("2d", { willReadFrequently: true });
|
|
823
|
-
}
|
|
824
|
-
const ctx = normalizeContext;
|
|
825
|
-
if (!ctx) return raw;
|
|
826
|
-
ctx.fillStyle = "#000000";
|
|
827
|
-
ctx.fillStyle = raw;
|
|
828
|
-
const onBlack = ctx.fillStyle;
|
|
829
|
-
ctx.fillStyle = "#ffffff";
|
|
830
|
-
ctx.fillStyle = raw;
|
|
831
|
-
if (onBlack !== ctx.fillStyle || typeof onBlack !== "string") return null;
|
|
832
|
-
if (ZRENDER_COLOR_RE.test(onBlack)) return onBlack;
|
|
833
|
-
ctx.clearRect(0, 0, 1, 1);
|
|
834
|
-
ctx.fillRect(0, 0, 1, 1);
|
|
835
|
-
const [r = 0, g = 0, b = 0, a = 0] = ctx.getImageData(0, 0, 1, 1).data;
|
|
836
|
-
return a === 255 ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${Math.round(a / 255 * 1e3) / 1e3})`;
|
|
837
|
-
}
|
|
838
|
-
function readChartTokens(el) {
|
|
839
|
-
if (typeof document === "undefined") return null;
|
|
840
|
-
const target = document.documentElement;
|
|
841
|
-
if (!target) return null;
|
|
842
|
-
const styles = getComputedStyle(target);
|
|
843
|
-
const read = (name) => toCanvasColor(styles.getPropertyValue(name));
|
|
844
|
-
const series = [];
|
|
845
|
-
for (const token of SERIES_TOKENS) {
|
|
846
|
-
const color = read(token);
|
|
847
|
-
if (color) series.push(color);
|
|
848
|
-
}
|
|
849
|
-
return {
|
|
850
|
-
series,
|
|
851
|
-
...styles.fontFamily ? { fontFamily: styles.fontFamily } : {},
|
|
852
|
-
foreground: read("--foreground"),
|
|
853
|
-
mutedForeground: read("--muted-foreground"),
|
|
854
|
-
border: read("--border"),
|
|
855
|
-
popover: read("--popover"),
|
|
856
|
-
popoverForeground: read("--popover-foreground")
|
|
857
|
-
};
|
|
858
|
-
}
|
|
859
|
-
function sameChartTokens(a, b) {
|
|
860
|
-
if (a === b) return true;
|
|
861
|
-
if (!a || !b) return false;
|
|
862
|
-
return a.series.length === b.series.length && a.series.every((color, i) => color === b.series[i]) && a.fontFamily === b.fontFamily && a.foreground === b.foreground && a.mutedForeground === b.mutedForeground && a.border === b.border && a.popover === b.popover && a.popoverForeground === b.popoverForeground;
|
|
863
|
-
}
|
|
864
|
-
function watchChartTokens(onChange) {
|
|
865
|
-
if (typeof document === "undefined") return () => {
|
|
866
|
-
};
|
|
867
|
-
let frame = 0;
|
|
868
|
-
const schedule = () => {
|
|
869
|
-
if (frame) return;
|
|
870
|
-
frame = requestAnimationFrame(() => {
|
|
871
|
-
frame = 0;
|
|
872
|
-
onChange();
|
|
873
|
-
});
|
|
874
|
-
};
|
|
875
|
-
const themeObserver = new MutationObserver(schedule);
|
|
876
|
-
const attributeFilter = ["class", "style", "data-theme"];
|
|
877
|
-
themeObserver.observe(document.documentElement, { attributes: true, attributeFilter });
|
|
878
|
-
if (document.body) themeObserver.observe(document.body, { attributes: true, attributeFilter });
|
|
879
|
-
const styleObserver = new MutationObserver(schedule);
|
|
880
|
-
if (document.head) {
|
|
881
|
-
styleObserver.observe(document.head, {
|
|
882
|
-
childList: true,
|
|
883
|
-
subtree: true,
|
|
884
|
-
characterData: true,
|
|
885
|
-
attributes: true,
|
|
886
|
-
attributeFilter: ["href", "media", "disabled"]
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
const onLoad = (event) => {
|
|
890
|
-
if (event.target instanceof HTMLLinkElement) schedule();
|
|
891
|
-
};
|
|
892
|
-
document.addEventListener("load", onLoad, true);
|
|
893
|
-
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
894
|
-
media.addEventListener("change", schedule);
|
|
895
|
-
return () => {
|
|
896
|
-
if (frame) cancelAnimationFrame(frame);
|
|
897
|
-
themeObserver.disconnect();
|
|
898
|
-
styleObserver.disconnect();
|
|
899
|
-
document.removeEventListener("load", onLoad, true);
|
|
900
|
-
media.removeEventListener("change", schedule);
|
|
901
|
-
};
|
|
902
|
-
}
|
|
903
|
-
function axisTheme(tokens, splitLine) {
|
|
904
|
-
const line = tokens.border ?? void 0;
|
|
905
|
-
return {
|
|
906
|
-
axisLine: { show: false },
|
|
907
|
-
axisTick: { show: false },
|
|
908
|
-
axisLabel: { show: true, color: tokens.mutedForeground ?? void 0, fontSize: 12 },
|
|
909
|
-
// Faint horizontal rules only: the border colour at low opacity.
|
|
910
|
-
splitLine: { show: splitLine, lineStyle: { color: line ? [line] : void 0, opacity: 0.5, width: 1 } },
|
|
911
|
-
splitArea: { show: false }
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
function buildChartTheme(tokens) {
|
|
915
|
-
const text = tokens.foreground ?? void 0;
|
|
916
|
-
const muted = tokens.mutedForeground ?? void 0;
|
|
917
|
-
const line = tokens.border ?? void 0;
|
|
918
|
-
return {
|
|
919
|
-
// Let the page background show through: charts sit on cards, not on a canvas.
|
|
920
|
-
backgroundColor: "transparent",
|
|
921
|
-
...tokens.series.length > 0 ? { color: tokens.series } : {},
|
|
922
|
-
textStyle: { color: text, ...tokens.fontFamily ? { fontFamily: tokens.fontFamily } : {} },
|
|
923
|
-
title: { textStyle: { color: text }, subtextStyle: { color: muted } },
|
|
924
|
-
legend: { textStyle: { color: muted } },
|
|
925
|
-
categoryAxis: axisTheme(tokens, false),
|
|
926
|
-
valueAxis: axisTheme(tokens, true),
|
|
927
|
-
logAxis: axisTheme(tokens, true),
|
|
928
|
-
timeAxis: axisTheme(tokens, true),
|
|
929
|
-
tooltip: {
|
|
930
|
-
// ECharts' default 0.4s transform lags the tooltip ~300ms behind the cursor.
|
|
931
|
-
transitionDuration: 0,
|
|
932
|
-
backgroundColor: tokens.popover ?? void 0,
|
|
933
|
-
borderColor: line,
|
|
934
|
-
borderWidth: 1,
|
|
935
|
-
padding: [8, 12],
|
|
936
|
-
// Rounded card with a soft shadow; in dark mode the shadow barely shows, so the border carries the edge.
|
|
937
|
-
extraCssText: "border-radius:8px;box-shadow:var(--shadow-card, 0 4px 12px rgb(0 0 0 / 0.08));",
|
|
938
|
-
textStyle: {
|
|
939
|
-
color: tokens.popoverForeground ?? void 0,
|
|
940
|
-
fontSize: 12,
|
|
941
|
-
...tokens.fontFamily ? { fontFamily: tokens.fontFamily } : {}
|
|
942
|
-
},
|
|
943
|
-
axisPointer: { lineStyle: { color: line }, crossStyle: { color: line } }
|
|
944
|
-
}
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
|
-
function useChartTokens() {
|
|
948
|
-
const [tokens, setTokens] = useState(() => readChartTokens());
|
|
949
|
-
const tokensRef = useRef(tokens);
|
|
950
|
-
useEffect(() => {
|
|
951
|
-
const sync = () => {
|
|
952
|
-
const next = readChartTokens();
|
|
953
|
-
if (sameChartTokens(tokensRef.current, next)) return;
|
|
954
|
-
tokensRef.current = next;
|
|
955
|
-
setTokens(next);
|
|
956
|
-
};
|
|
957
|
-
sync();
|
|
958
|
-
return watchChartTokens(sync);
|
|
959
|
-
}, []);
|
|
960
|
-
return tokens;
|
|
961
|
-
}
|
|
962
|
-
var SERIES_TOKEN_NAME_RE = /^chart-([1-5])$/;
|
|
963
|
-
var TONE_NAME_RE = /^(?:positive|warning|negative|neutral|info)(?:-fill)?$/;
|
|
964
|
-
var CSS_VAR_RE = /^var\(\s*(--[\w-]+)\s*(?:,\s*(.+))?\)$/;
|
|
965
|
-
var EMBEDDED_VAR_RE = /var\(\s*(--[\w-]+)\s*\)/g;
|
|
966
|
-
function resolveChartColors(colors, tokens) {
|
|
967
|
-
return colors.map((color) => {
|
|
968
|
-
const token = SERIES_TOKEN_NAME_RE.exec(color.trim());
|
|
969
|
-
if (token) return tokens?.series[Number(token[1]) - 1] ?? "";
|
|
970
|
-
if (TONE_NAME_RE.test(color.trim())) {
|
|
971
|
-
if (typeof document === "undefined") return "";
|
|
972
|
-
return toCanvasColor(getComputedStyle(document.documentElement).getPropertyValue(`--${color.trim()}`)) ?? "";
|
|
973
|
-
}
|
|
974
|
-
if (typeof document === "undefined") return color;
|
|
975
|
-
let value = color.trim();
|
|
976
|
-
const cssVar = CSS_VAR_RE.exec(value);
|
|
977
|
-
const styles = getComputedStyle(document.documentElement);
|
|
978
|
-
if (cssVar) {
|
|
979
|
-
value = styles.getPropertyValue(cssVar[1]).trim() || (cssVar[2] ?? "").trim();
|
|
980
|
-
} else if (value.includes("var(")) {
|
|
981
|
-
value = value.replace(EMBEDDED_VAR_RE, (_, name) => styles.getPropertyValue(name).trim());
|
|
982
|
-
}
|
|
983
|
-
return toCanvasColor(value) ?? "";
|
|
984
|
-
});
|
|
985
|
-
}
|
|
986
|
-
function resolveFillColors(tokens) {
|
|
987
|
-
const [positive = "", warning = "", negative = "", neutral = ""] = resolveChartColors(
|
|
988
|
-
["positive-fill", "warning-fill", "negative-fill", "neutral-fill"],
|
|
989
|
-
tokens
|
|
990
|
-
);
|
|
991
|
-
return { positive, warning, negative, neutral };
|
|
992
|
-
}
|
|
993
|
-
var TRANSPARENT_RE = /^(?:transparent|rgba\([^)]*,\s*0(?:\.0+)?\))$/i;
|
|
994
|
-
function readChartSurface(el) {
|
|
995
|
-
if (typeof document === "undefined") return null;
|
|
996
|
-
for (let node = el; node; node = node.parentElement) {
|
|
997
|
-
const bg = getComputedStyle(node).backgroundColor.trim();
|
|
998
|
-
if (bg && !TRANSPARENT_RE.test(bg)) {
|
|
999
|
-
const color = toCanvasColor(bg);
|
|
1000
|
-
if (color) return color;
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
return toCanvasColor(getComputedStyle(document.documentElement).getPropertyValue("--background"));
|
|
1004
|
-
}
|
|
1005
|
-
var WIDTH_BUCKET = 40;
|
|
1006
|
-
function useChartSurface(forwarded, tokens) {
|
|
1007
|
-
const [node, setNode] = useState(null);
|
|
1008
|
-
const [surface, setSurface] = useState(void 0);
|
|
1009
|
-
const [width, setWidth] = useState(void 0);
|
|
1010
|
-
const ref = useCallback(
|
|
1011
|
-
(el) => {
|
|
1012
|
-
setNode(el);
|
|
1013
|
-
if (typeof forwarded === "function") forwarded(el);
|
|
1014
|
-
else if (forwarded) forwarded.current = el;
|
|
1015
|
-
},
|
|
1016
|
-
[forwarded]
|
|
1017
|
-
);
|
|
1018
|
-
useEffect(() => {
|
|
1019
|
-
if (!node) return;
|
|
1020
|
-
setSurface(readChartSurface(node) ?? void 0);
|
|
1021
|
-
}, [node, tokens]);
|
|
1022
|
-
useEffect(() => {
|
|
1023
|
-
if (!node || typeof ResizeObserver === "undefined") return;
|
|
1024
|
-
const update = (w) => setWidth(Math.floor(w / WIDTH_BUCKET) * WIDTH_BUCKET);
|
|
1025
|
-
update(node.getBoundingClientRect().width);
|
|
1026
|
-
const observer = new ResizeObserver((entries) => update(entries[0]?.contentRect.width ?? 0));
|
|
1027
|
-
observer.observe(node);
|
|
1028
|
-
return () => observer.disconnect();
|
|
1029
|
-
}, [node]);
|
|
1030
|
-
return { ref, surface, width };
|
|
1031
|
-
}
|
|
1032
677
|
var DEFAULT_CHART_HEIGHT = 288;
|
|
1033
|
-
var
|
|
678
|
+
var TEXT3 = {
|
|
679
|
+
ja: { emptyTitle: "\u8868\u793A\u3067\u304D\u308B\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093", loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D" },
|
|
680
|
+
en: { emptyTitle: "No data to display", loading: "Loading" }
|
|
681
|
+
};
|
|
1034
682
|
var ChartFrame = forwardRef(function ChartFrame2({
|
|
1035
683
|
title,
|
|
1036
684
|
summary,
|
|
@@ -1047,6 +695,7 @@ var ChartFrame = forwardRef(function ChartFrame2({
|
|
|
1047
695
|
...props
|
|
1048
696
|
}, ref) {
|
|
1049
697
|
const id = useId();
|
|
698
|
+
const t = TEXT3[uiLanguage(useLocale())];
|
|
1050
699
|
const titleId = title ? `${id}-title` : void 0;
|
|
1051
700
|
const summaryId = summary ? `${id}-summary` : void 0;
|
|
1052
701
|
const state = isLoading ? "loading" : isEmpty ? "empty" : "ready";
|
|
@@ -1068,7 +717,7 @@ var ChartFrame = forwardRef(function ChartFrame2({
|
|
|
1068
717
|
"aria-busy": isLoading || void 0,
|
|
1069
718
|
className: "relative w-full min-w-0",
|
|
1070
719
|
style: { height: typeof height === "number" ? `${height}px` : height },
|
|
1071
|
-
children: state === "loading" ? /* @__PURE__ */ jsx(ChartSkeleton, { variant }) : state === "empty" ? /* @__PURE__ */ jsx(ChartEmpty, { ...emptyState }) : /* @__PURE__ */ jsx(ChartFrameContext.Provider, { value: true, children })
|
|
720
|
+
children: state === "loading" ? /* @__PURE__ */ jsx(ChartSkeleton, { variant, loadingText: t.loading }) : state === "empty" ? /* @__PURE__ */ jsx(ChartEmpty, { ...emptyState, defaultTitle: t.emptyTitle }) : /* @__PURE__ */ jsx(ChartFrameContext.Provider, { value: true, children })
|
|
1072
721
|
}
|
|
1073
722
|
),
|
|
1074
723
|
state === "ready" && dataTable && dataTable.rows.length > 0 && /* @__PURE__ */ jsx(ChartDataTableView, { table: dataTable, fallbackCaption: title ?? ariaLabel })
|
|
@@ -1078,14 +727,14 @@ ChartFrame.displayName = "ChartFrame";
|
|
|
1078
727
|
var BAR_HEIGHTS = [58, 74, 46, 88, 64, 80, 52];
|
|
1079
728
|
var LIST_WIDTHS = [92, 76, 64, 48, 36];
|
|
1080
729
|
var LINE_POINTS = "0,70 16,58 33,62 50,40 66,46 83,28 100,34";
|
|
1081
|
-
function ChartSkeleton({ variant }) {
|
|
730
|
+
function ChartSkeleton({ variant, loadingText }) {
|
|
1082
731
|
const pulse = "animate-pulse motion-reduce:animate-none";
|
|
1083
732
|
return /* @__PURE__ */ jsxs("div", { "data-slot": "chart-skeleton", "data-variant": variant, className: "absolute inset-0 flex flex-col gap-3", children: [
|
|
1084
733
|
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "contents", children: variant === "list" ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-1 flex-col justify-around", pulse), children: LIST_WIDTHS.map((w) => /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsx("div", { className: "h-5 rounded-sm bg-muted", style: { width: `${w}%` } }) }, w)) }) : variant === "donut" ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-1 items-center justify-center", pulse), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 100 100", className: "h-full max-h-full w-auto text-muted", children: /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r: "40", fill: "none", stroke: "currentColor", strokeWidth: "14" }) }) }) : variant === "bar" ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-1 items-end gap-3 px-1", pulse), children: BAR_HEIGHTS.map((h, i) => /* @__PURE__ */ jsx("div", { className: "flex-1 rounded-t-sm bg-muted", style: { height: `${h}%` } }, i)) }) : (
|
|
1085
734
|
// A soft muted silhouette only — no stroke, no baseline, nothing that reads as a data line.
|
|
1086
735
|
/* @__PURE__ */ jsx("div", { className: cn("relative flex-1", pulse), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 100 100", preserveAspectRatio: "none", className: "absolute inset-0 h-full w-full text-muted", children: /* @__PURE__ */ jsx("polygon", { points: `${LINE_POINTS} 100,100 0,100`, fill: "currentColor", opacity: variant === "area" ? 0.8 : 0.5 }) }) })
|
|
1087
736
|
) }),
|
|
1088
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children:
|
|
737
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: loadingText })
|
|
1089
738
|
] });
|
|
1090
739
|
}
|
|
1091
740
|
function ChartDataTableView({ table, fallbackCaption }) {
|
|
@@ -1098,370 +747,20 @@ function ChartDataTableView({ table, fallbackCaption }) {
|
|
|
1098
747
|
) }, r)) })
|
|
1099
748
|
] }) });
|
|
1100
749
|
}
|
|
1101
|
-
function ChartEmpty({ title, description, action }) {
|
|
750
|
+
function ChartEmpty({ title, description, action, defaultTitle }) {
|
|
1102
751
|
return /* @__PURE__ */ jsxs(
|
|
1103
752
|
"div",
|
|
1104
753
|
{
|
|
1105
754
|
"data-slot": "chart-empty",
|
|
1106
755
|
className: "absolute inset-0 flex flex-col items-center justify-center gap-1 rounded-md border border-dashed border-border p-6 text-center",
|
|
1107
756
|
children: [
|
|
1108
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-balance", children: title ??
|
|
757
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-balance", children: title ?? defaultTitle }),
|
|
1109
758
|
description && /* @__PURE__ */ jsx("p", { className: "max-w-prose text-sm text-balance text-muted-foreground", children: description }),
|
|
1110
759
|
action && /* @__PURE__ */ jsx("div", { className: "mt-3", children: action })
|
|
1111
760
|
]
|
|
1112
761
|
}
|
|
1113
762
|
);
|
|
1114
763
|
}
|
|
1115
|
-
use([
|
|
1116
|
-
BarChart,
|
|
1117
|
-
CustomChart,
|
|
1118
|
-
LineChart,
|
|
1119
|
-
PieChart,
|
|
1120
|
-
GridComponent,
|
|
1121
|
-
LegendComponent,
|
|
1122
|
-
MarkAreaComponent,
|
|
1123
|
-
MarkLineComponent,
|
|
1124
|
-
MarkPointComponent,
|
|
1125
|
-
TooltipComponent,
|
|
1126
|
-
CanvasRenderer
|
|
1127
|
-
]);
|
|
1128
|
-
var HEADER_PAD_X = 16;
|
|
1129
|
-
var HEADER_PAD_TOP = 16;
|
|
1130
|
-
var HEADER_PAD_BOTTOM = 12;
|
|
1131
|
-
var HEADER_LINE_HEIGHT = 20;
|
|
1132
|
-
var HEADER_GAP = 4;
|
|
1133
|
-
var HEADER_FONT_SIZE = 14;
|
|
1134
|
-
function wrapChartText(text, maxWidth, measure) {
|
|
1135
|
-
const lines = [];
|
|
1136
|
-
let line = "";
|
|
1137
|
-
for (const ch of text) {
|
|
1138
|
-
if (ch === "\n") {
|
|
1139
|
-
lines.push(line);
|
|
1140
|
-
line = "";
|
|
1141
|
-
continue;
|
|
1142
|
-
}
|
|
1143
|
-
if (line !== "" && measure(line + ch) > maxWidth) {
|
|
1144
|
-
lines.push(line);
|
|
1145
|
-
line = ch.trim() === "" ? "" : ch;
|
|
1146
|
-
} else {
|
|
1147
|
-
line += ch;
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
if (line !== "" || lines.length === 0) lines.push(line);
|
|
1151
|
-
return lines.filter((l, i) => l !== "" || i < lines.length - 1);
|
|
1152
|
-
}
|
|
1153
|
-
function chartExportHeaderLayout(header, width, measure) {
|
|
1154
|
-
const title = header?.title?.trim();
|
|
1155
|
-
const summary = header?.summary?.trim();
|
|
1156
|
-
if (!title && !summary) return { lines: [], height: 0 };
|
|
1157
|
-
const room = Math.max(40, width - HEADER_PAD_X * 2);
|
|
1158
|
-
const lines = [
|
|
1159
|
-
...title ? wrapChartText(title, room, (t) => measure(t, "title")).map((text) => ({ text, kind: "title" })) : [],
|
|
1160
|
-
...summary ? wrapChartText(summary, room, (t) => measure(t, "summary")).map((text) => ({ text, kind: "summary" })) : []
|
|
1161
|
-
];
|
|
1162
|
-
const gap = title && summary ? HEADER_GAP : 0;
|
|
1163
|
-
return { lines, height: HEADER_PAD_TOP + lines.length * HEADER_LINE_HEIGHT + gap + HEADER_PAD_BOTTOM };
|
|
1164
|
-
}
|
|
1165
|
-
function loadImage(src) {
|
|
1166
|
-
return new Promise((resolve, reject) => {
|
|
1167
|
-
const image = new Image();
|
|
1168
|
-
image.onload = () => resolve(image);
|
|
1169
|
-
image.onerror = () => reject(new Error("PNG \u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F"));
|
|
1170
|
-
image.src = src;
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
async function pngWithHeader(dataUrl, header, look, pixelRatio) {
|
|
1174
|
-
const image = await loadImage(dataUrl);
|
|
1175
|
-
const width = image.width / pixelRatio;
|
|
1176
|
-
const plotHeight = image.height / pixelRatio;
|
|
1177
|
-
const canvas = document.createElement("canvas");
|
|
1178
|
-
const ctx = canvas.getContext("2d");
|
|
1179
|
-
if (!ctx) return dataUrl;
|
|
1180
|
-
const font = (kind) => `${kind === "title" ? 500 : 400} ${HEADER_FONT_SIZE}px ${look.fontFamily}`;
|
|
1181
|
-
ctx.font = font("title");
|
|
1182
|
-
const layout = chartExportHeaderLayout(header, width, (text, kind) => {
|
|
1183
|
-
ctx.font = font(kind);
|
|
1184
|
-
return ctx.measureText(text).width;
|
|
1185
|
-
});
|
|
1186
|
-
if (layout.height === 0) return dataUrl;
|
|
1187
|
-
canvas.width = Math.round(image.width);
|
|
1188
|
-
canvas.height = Math.round((layout.height + plotHeight) * pixelRatio);
|
|
1189
|
-
ctx.scale(pixelRatio, pixelRatio);
|
|
1190
|
-
ctx.fillStyle = look.background;
|
|
1191
|
-
ctx.fillRect(0, 0, width, layout.height + plotHeight);
|
|
1192
|
-
ctx.textBaseline = "middle";
|
|
1193
|
-
let y = HEADER_PAD_TOP;
|
|
1194
|
-
let previous = null;
|
|
1195
|
-
for (const line of layout.lines) {
|
|
1196
|
-
if (previous === "title" && line.kind === "summary") y += HEADER_GAP;
|
|
1197
|
-
ctx.font = font(line.kind);
|
|
1198
|
-
ctx.fillStyle = line.kind === "title" ? look.color : look.mutedColor;
|
|
1199
|
-
ctx.fillText(line.text, HEADER_PAD_X, y + HEADER_LINE_HEIGHT / 2);
|
|
1200
|
-
y += HEADER_LINE_HEIGHT;
|
|
1201
|
-
previous = line.kind;
|
|
1202
|
-
}
|
|
1203
|
-
ctx.drawImage(image, 0, layout.height, width, plotHeight);
|
|
1204
|
-
return canvas.toDataURL("image/png");
|
|
1205
|
-
}
|
|
1206
|
-
function useResolvedChartColors(colors) {
|
|
1207
|
-
const tokens = useChartTokens();
|
|
1208
|
-
const key = colors.join("\0");
|
|
1209
|
-
return useMemo(() => resolveChartColors(colors, tokens), [key, tokens]);
|
|
1210
|
-
}
|
|
1211
|
-
var COMPONENT_MAIN_TYPES = /* @__PURE__ */ new Set([
|
|
1212
|
-
"title",
|
|
1213
|
-
"legend",
|
|
1214
|
-
"grid",
|
|
1215
|
-
"xAxis",
|
|
1216
|
-
"yAxis",
|
|
1217
|
-
"polar",
|
|
1218
|
-
"radiusAxis",
|
|
1219
|
-
"angleAxis",
|
|
1220
|
-
"radar",
|
|
1221
|
-
"dataZoom",
|
|
1222
|
-
"visualMap",
|
|
1223
|
-
"tooltip",
|
|
1224
|
-
"axisPointer",
|
|
1225
|
-
"toolbox",
|
|
1226
|
-
"brush",
|
|
1227
|
-
"geo",
|
|
1228
|
-
"parallel",
|
|
1229
|
-
"parallelAxis",
|
|
1230
|
-
"singleAxis",
|
|
1231
|
-
"graphic",
|
|
1232
|
-
"calendar",
|
|
1233
|
-
"dataset",
|
|
1234
|
-
"series",
|
|
1235
|
-
"matrix",
|
|
1236
|
-
"thumbnail"
|
|
1237
|
-
]);
|
|
1238
|
-
function echartSetOptionOpts(prev, next) {
|
|
1239
|
-
const special = (o) => "timeline" in o || "baseOption" in o || "options" in o || "media" in o;
|
|
1240
|
-
if (!prev || special(prev) || special(next)) return { notMerge: true, lazyUpdate: true };
|
|
1241
|
-
const types = /* @__PURE__ */ new Set();
|
|
1242
|
-
for (const key of [...Object.keys(prev), ...Object.keys(next)]) if (COMPONENT_MAIN_TYPES.has(key)) types.add(key);
|
|
1243
|
-
return { notMerge: false, replaceMerge: [...types], lazyUpdate: true };
|
|
1244
|
-
}
|
|
1245
|
-
function withGraphicFont(option, fontFamily) {
|
|
1246
|
-
const graphic = option.graphic;
|
|
1247
|
-
if (!fontFamily || !Array.isArray(graphic)) return option;
|
|
1248
|
-
return {
|
|
1249
|
-
...option,
|
|
1250
|
-
graphic: graphic.map(
|
|
1251
|
-
(g) => g && g.type === "text" && g.style && !g.style.fontFamily ? { ...g, style: { ...g.style, fontFamily } } : g
|
|
1252
|
-
)
|
|
1253
|
-
};
|
|
1254
|
-
}
|
|
1255
|
-
function withMotionPreference(option, reducedMotion) {
|
|
1256
|
-
return { ...option, animation: reducedMotion ? false : option.animation ?? true };
|
|
1257
|
-
}
|
|
1258
|
-
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
1259
|
-
function usePrefersReducedMotion() {
|
|
1260
|
-
const [reduced, setReduced] = useState(
|
|
1261
|
-
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(REDUCED_MOTION_QUERY).matches
|
|
1262
|
-
);
|
|
1263
|
-
useEffect(() => {
|
|
1264
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1265
|
-
const media = window.matchMedia(REDUCED_MOTION_QUERY);
|
|
1266
|
-
const sync = () => setReduced(media.matches);
|
|
1267
|
-
sync();
|
|
1268
|
-
media.addEventListener("change", sync);
|
|
1269
|
-
return () => media.removeEventListener("change", sync);
|
|
1270
|
-
}, []);
|
|
1271
|
-
return reduced;
|
|
1272
|
-
}
|
|
1273
|
-
var EChart = forwardRef(function EChart2({
|
|
1274
|
-
option,
|
|
1275
|
-
height,
|
|
1276
|
-
loading = false,
|
|
1277
|
-
theme,
|
|
1278
|
-
onEvents,
|
|
1279
|
-
ariaLabel,
|
|
1280
|
-
className,
|
|
1281
|
-
actions = false,
|
|
1282
|
-
fileName = "chart.png",
|
|
1283
|
-
exportHeader
|
|
1284
|
-
}, ref) {
|
|
1285
|
-
const containerRef = useRef(null);
|
|
1286
|
-
const [instance, setInstance] = useState(null);
|
|
1287
|
-
const [copied, setCopied] = useState(false);
|
|
1288
|
-
const [tokens, setTokens] = useState(() => readChartTokens());
|
|
1289
|
-
const reducedMotion = usePrefersReducedMotion();
|
|
1290
|
-
const appliedRef = useRef(null);
|
|
1291
|
-
const tokensRef = useRef(tokens);
|
|
1292
|
-
useEffect(() => {
|
|
1293
|
-
if (theme !== void 0) return;
|
|
1294
|
-
const sync = () => {
|
|
1295
|
-
const base = readChartTokens();
|
|
1296
|
-
const font = containerRef.current ? getComputedStyle(containerRef.current).fontFamily : "";
|
|
1297
|
-
const next = base && font ? { ...base, fontFamily: font } : base;
|
|
1298
|
-
if (sameChartTokens(tokensRef.current, next)) return;
|
|
1299
|
-
tokensRef.current = next;
|
|
1300
|
-
setTokens(next);
|
|
1301
|
-
};
|
|
1302
|
-
sync();
|
|
1303
|
-
const stop = watchChartTokens(sync);
|
|
1304
|
-
const ancestors = new MutationObserver(sync);
|
|
1305
|
-
for (let node = containerRef.current?.parentElement; node; node = node.parentElement) {
|
|
1306
|
-
ancestors.observe(node, { attributes: true, attributeFilter: ["class", "style"] });
|
|
1307
|
-
}
|
|
1308
|
-
return () => {
|
|
1309
|
-
stop();
|
|
1310
|
-
ancestors.disconnect();
|
|
1311
|
-
};
|
|
1312
|
-
}, [theme]);
|
|
1313
|
-
const autoTheme = useMemo(() => tokens ? buildChartTheme(tokens) : void 0, [tokens]);
|
|
1314
|
-
const resolvedTheme = theme ?? autoTheme;
|
|
1315
|
-
useEffect(() => {
|
|
1316
|
-
const container = containerRef.current;
|
|
1317
|
-
if (!container) return;
|
|
1318
|
-
const inst = init(container, resolvedTheme, { renderer: "canvas" });
|
|
1319
|
-
appliedRef.current = null;
|
|
1320
|
-
container.dataset.rendering = "";
|
|
1321
|
-
inst.on("finished", () => {
|
|
1322
|
-
delete container.dataset.rendering;
|
|
1323
|
-
});
|
|
1324
|
-
setInstance(inst);
|
|
1325
|
-
let frame = 0;
|
|
1326
|
-
const observer = new ResizeObserver(() => {
|
|
1327
|
-
cancelAnimationFrame(frame);
|
|
1328
|
-
frame = requestAnimationFrame(() => {
|
|
1329
|
-
if (!inst.isDisposed()) inst.resize();
|
|
1330
|
-
});
|
|
1331
|
-
});
|
|
1332
|
-
observer.observe(container);
|
|
1333
|
-
return () => {
|
|
1334
|
-
observer.disconnect();
|
|
1335
|
-
cancelAnimationFrame(frame);
|
|
1336
|
-
inst.dispose();
|
|
1337
|
-
};
|
|
1338
|
-
}, [resolvedTheme]);
|
|
1339
|
-
useEffect(() => {
|
|
1340
|
-
if (!instance) return;
|
|
1341
|
-
if (containerRef.current) containerRef.current.dataset.rendering = "";
|
|
1342
|
-
const next = withGraphicFont(withMotionPreference(option, reducedMotion), theme === void 0 ? tokens?.fontFamily : void 0);
|
|
1343
|
-
instance.setOption(next, echartSetOptionOpts(appliedRef.current, next));
|
|
1344
|
-
appliedRef.current = next;
|
|
1345
|
-
}, [instance, option, reducedMotion, theme, tokens?.fontFamily]);
|
|
1346
|
-
useEffect(() => {
|
|
1347
|
-
if (!instance) return;
|
|
1348
|
-
if (loading) instance.showLoading();
|
|
1349
|
-
else instance.hideLoading();
|
|
1350
|
-
}, [instance, loading]);
|
|
1351
|
-
useEffect(() => {
|
|
1352
|
-
if (!instance || !onEvents) return;
|
|
1353
|
-
const entries = Object.entries(onEvents);
|
|
1354
|
-
for (const [event, handler] of entries) {
|
|
1355
|
-
instance.on(event, handler);
|
|
1356
|
-
}
|
|
1357
|
-
return () => {
|
|
1358
|
-
if (instance.isDisposed()) return;
|
|
1359
|
-
for (const [event, handler] of entries) {
|
|
1360
|
-
instance.off(event, handler);
|
|
1361
|
-
}
|
|
1362
|
-
};
|
|
1363
|
-
}, [instance, onEvents]);
|
|
1364
|
-
const includeTitle = typeof actions === "object" ? actions.includeTitle ?? true : true;
|
|
1365
|
-
const getPngDataUrl = useCallback(async () => {
|
|
1366
|
-
if (!instance) return null;
|
|
1367
|
-
let backgroundColor = "#ffffff";
|
|
1368
|
-
for (let el = containerRef.current; el; el = el.parentElement) {
|
|
1369
|
-
const bg = getComputedStyle(el).backgroundColor;
|
|
1370
|
-
if (bg && bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent") {
|
|
1371
|
-
backgroundColor = bg;
|
|
1372
|
-
break;
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
const pixelRatio = 2;
|
|
1376
|
-
const dataUrl = instance.getDataURL({ type: "png", pixelRatio, backgroundColor });
|
|
1377
|
-
if (!includeTitle || !exportHeader || !(exportHeader.title || exportHeader.summary) || !containerRef.current) return dataUrl;
|
|
1378
|
-
try {
|
|
1379
|
-
const style = getComputedStyle(containerRef.current);
|
|
1380
|
-
return await pngWithHeader(
|
|
1381
|
-
dataUrl,
|
|
1382
|
-
exportHeader,
|
|
1383
|
-
{ background: backgroundColor, color: style.color, mutedColor: tokens?.mutedForeground ?? style.color, fontFamily: style.fontFamily },
|
|
1384
|
-
pixelRatio
|
|
1385
|
-
);
|
|
1386
|
-
} catch {
|
|
1387
|
-
return dataUrl;
|
|
1388
|
-
}
|
|
1389
|
-
}, [instance, includeTitle, exportHeader, tokens]);
|
|
1390
|
-
const handleCopy = useCallback(async () => {
|
|
1391
|
-
const dataUrl = await getPngDataUrl();
|
|
1392
|
-
if (!dataUrl) return;
|
|
1393
|
-
try {
|
|
1394
|
-
const blob = await (await fetch(dataUrl)).blob();
|
|
1395
|
-
await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
|
|
1396
|
-
setCopied(true);
|
|
1397
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
1398
|
-
} catch {
|
|
1399
|
-
}
|
|
1400
|
-
}, [getPngDataUrl]);
|
|
1401
|
-
const handleDownload = useCallback(async () => {
|
|
1402
|
-
const dataUrl = await getPngDataUrl();
|
|
1403
|
-
if (!dataUrl) return;
|
|
1404
|
-
const link = document.createElement("a");
|
|
1405
|
-
link.href = dataUrl;
|
|
1406
|
-
link.download = fileName;
|
|
1407
|
-
link.click();
|
|
1408
|
-
}, [getPngDataUrl, fileName]);
|
|
1409
|
-
const inFrame = useContext(ChartFrameContext);
|
|
1410
|
-
const styleHeight = height == null ? void 0 : typeof height === "number" ? `${height}px` : height;
|
|
1411
|
-
return /* @__PURE__ */ jsxs(
|
|
1412
|
-
"div",
|
|
1413
|
-
{
|
|
1414
|
-
ref,
|
|
1415
|
-
"data-slot": "echart",
|
|
1416
|
-
className: cn("group relative w-full", height == null && "h-[400px]", className),
|
|
1417
|
-
style: styleHeight != null ? { height: styleHeight } : void 0,
|
|
1418
|
-
children: [
|
|
1419
|
-
/* @__PURE__ */ jsx(
|
|
1420
|
-
"div",
|
|
1421
|
-
{
|
|
1422
|
-
ref: containerRef,
|
|
1423
|
-
"data-slot": "echart-canvas",
|
|
1424
|
-
className: "h-full w-full",
|
|
1425
|
-
role: inFrame ? void 0 : "img",
|
|
1426
|
-
"aria-label": inFrame ? void 0 : ariaLabel ?? "\u30C1\u30E3\u30FC\u30C8"
|
|
1427
|
-
}
|
|
1428
|
-
),
|
|
1429
|
-
actions && /* @__PURE__ */ jsxs(
|
|
1430
|
-
"div",
|
|
1431
|
-
{
|
|
1432
|
-
"data-slot": "echart-actions",
|
|
1433
|
-
className: "absolute top-2 right-2 z-10 flex gap-1 pointer-events-none opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100 [@media(hover:none)]:pointer-events-auto [@media(hover:none)]:opacity-100",
|
|
1434
|
-
children: [
|
|
1435
|
-
/* @__PURE__ */ jsx(
|
|
1436
|
-
Button,
|
|
1437
|
-
{
|
|
1438
|
-
type: "button",
|
|
1439
|
-
variant: "ghost",
|
|
1440
|
-
size: "icon-sm",
|
|
1441
|
-
onClick: handleCopy,
|
|
1442
|
-
"aria-label": copied ? "\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F" : "PNG \u3092\u30AF\u30EA\u30C3\u30D7\u30DC\u30FC\u30C9\u306B\u30B3\u30D4\u30FC",
|
|
1443
|
-
children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-4" }) : /* @__PURE__ */ jsx(Copy, { className: "size-4" })
|
|
1444
|
-
}
|
|
1445
|
-
),
|
|
1446
|
-
/* @__PURE__ */ jsx(
|
|
1447
|
-
Button,
|
|
1448
|
-
{
|
|
1449
|
-
type: "button",
|
|
1450
|
-
variant: "ghost",
|
|
1451
|
-
size: "icon-sm",
|
|
1452
|
-
onClick: handleDownload,
|
|
1453
|
-
"aria-label": "PNG \u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9",
|
|
1454
|
-
children: /* @__PURE__ */ jsx(Download, { className: "size-4" })
|
|
1455
|
-
}
|
|
1456
|
-
)
|
|
1457
|
-
]
|
|
1458
|
-
}
|
|
1459
|
-
)
|
|
1460
|
-
]
|
|
1461
|
-
}
|
|
1462
|
-
);
|
|
1463
|
-
});
|
|
1464
|
-
EChart.displayName = "EChart";
|
|
1465
764
|
|
|
1466
765
|
// ../squadkit/registry/lib/chart-utils.ts
|
|
1467
766
|
var ROOT_PROP_KEYS = /* @__PURE__ */ new Set(["id", "style", "role", "tabIndex", "lang", "hidden"]);
|
|
@@ -1504,37 +803,63 @@ function chartColorAt(colors, i) {
|
|
|
1504
803
|
function tintCss(cssColor, percent) {
|
|
1505
804
|
return `color-mix(in oklab, ${cssColor} ${percent}%, transparent)`;
|
|
1506
805
|
}
|
|
1507
|
-
function resolveValueFormatter(valueFormatter,
|
|
1508
|
-
return valueFormatter ?? toValueFormatter(
|
|
806
|
+
function resolveValueFormatter(valueFormatter, format, locale) {
|
|
807
|
+
return valueFormatter ?? toValueFormatter(format, locale);
|
|
1509
808
|
}
|
|
1510
|
-
function resolveAxisFormatter(valueFormatter,
|
|
809
|
+
function resolveAxisFormatter(valueFormatter, format, localeArg) {
|
|
1511
810
|
if (valueFormatter) return valueFormatter;
|
|
1512
|
-
const
|
|
1513
|
-
|
|
811
|
+
const locale = resolveLocale(localeArg);
|
|
812
|
+
const spec = format === void 0 ? { type: "compact" } : typeof format === "string" ? { type: format } : format;
|
|
813
|
+
if (spec.type !== "compact" && spec.type !== "number" && spec.type !== "currency") return toValueFormatter(format, locale);
|
|
1514
814
|
const currency = "currency" in spec ? spec.currency : void 0;
|
|
1515
815
|
const short = spec.type === "currency" ? { type: "currency", currency, notation: "compact" } : { type: "compact" };
|
|
1516
816
|
return (value) => formatValue(value, short, locale);
|
|
1517
817
|
}
|
|
1518
|
-
var
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
];
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
818
|
+
var compactUnitCache = /* @__PURE__ */ new Map();
|
|
819
|
+
function compactUnits(locale) {
|
|
820
|
+
const cached = compactUnitCache.get(locale);
|
|
821
|
+
if (cached !== void 0) return cached;
|
|
822
|
+
let units = [];
|
|
823
|
+
try {
|
|
824
|
+
const compact = new Intl.NumberFormat(locale, { notation: "compact" });
|
|
825
|
+
const seen = /* @__PURE__ */ new Set();
|
|
826
|
+
for (let exp = 3; exp <= 15; exp++) {
|
|
827
|
+
const parts = compact.formatToParts(10 ** exp);
|
|
828
|
+
const at = parts.findIndex((p) => p.type === "compact");
|
|
829
|
+
if (at === -1) continue;
|
|
830
|
+
if (parts[at - 1]?.type !== "integer" || at !== parts.length - 1) {
|
|
831
|
+
units = null;
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
834
|
+
const token = parts[at].value;
|
|
835
|
+
if (seen.has(token)) continue;
|
|
836
|
+
seen.add(token);
|
|
837
|
+
units.push({ token, size: 10 ** exp });
|
|
838
|
+
}
|
|
839
|
+
} catch {
|
|
840
|
+
units = null;
|
|
841
|
+
}
|
|
842
|
+
const sorted = units && units.length > 0 ? units.sort((a, b) => b.size - a.size) : null;
|
|
843
|
+
compactUnitCache.set(locale, sorted);
|
|
844
|
+
return sorted;
|
|
845
|
+
}
|
|
846
|
+
var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
847
|
+
function resolveAxisTickFormatter(valueFormatter, format, localeArg) {
|
|
848
|
+
const locale = resolveLocale(localeArg);
|
|
849
|
+
const base = resolveAxisFormatter(valueFormatter, format, locale);
|
|
850
|
+
const spec = format === void 0 ? { type: "compact" } : typeof format === "string" ? { type: format } : format;
|
|
851
|
+
const units = !valueFormatter && (spec.type === "compact" || spec.type === "number" || spec.type === "currency") ? compactUnits(locale) : null;
|
|
852
|
+
if (!units) return () => base;
|
|
1529
853
|
const number = new Intl.NumberFormat(locale, { maximumFractionDigits: 3 });
|
|
854
|
+
const numberToken = new RegExp(`\\d[\\d,]*(?:\\.\\d+)?(?:${units.map((u) => escapeRegExp(u.token)).join("|")})?`);
|
|
1530
855
|
return (top) => {
|
|
1531
|
-
const unit =
|
|
856
|
+
const unit = units.find((u) => Math.abs(top) >= u.size);
|
|
1532
857
|
if (!unit) return base;
|
|
1533
858
|
return (value) => {
|
|
1534
859
|
const text = base(value);
|
|
1535
860
|
if (value === 0 || !Number.isFinite(value)) return text;
|
|
1536
|
-
const scaled = `${number.format(Math.abs(value) / unit.size)}${unit.
|
|
1537
|
-
return text.replace(
|
|
861
|
+
const scaled = `${number.format(Math.abs(value) / unit.size)}${unit.token}`;
|
|
862
|
+
return text.replace(numberToken, () => scaled);
|
|
1538
863
|
};
|
|
1539
864
|
};
|
|
1540
865
|
}
|
|
@@ -1551,8 +876,15 @@ function clamp(value, min, max) {
|
|
|
1551
876
|
return Math.min(max, Math.max(min, value));
|
|
1552
877
|
}
|
|
1553
878
|
var MAX_CHART_SERIES = 5;
|
|
1554
|
-
var
|
|
1555
|
-
function
|
|
879
|
+
var OTHER_SERIES_LABELS = { ja: "\u305D\u306E\u4ED6", en: "Other" };
|
|
880
|
+
function otherSeriesLabel(locale) {
|
|
881
|
+
return OTHER_SERIES_LABELS[uiLanguage(resolveLocale(locale))];
|
|
882
|
+
}
|
|
883
|
+
var OTHER_NAMES = new Set(Object.values(OTHER_SERIES_LABELS));
|
|
884
|
+
function isOtherName(name) {
|
|
885
|
+
return typeof name === "string" && OTHER_NAMES.has(name);
|
|
886
|
+
}
|
|
887
|
+
function aggregateTopN(items, n = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
|
|
1556
888
|
if (items.length <= n) return { top: [...items], rest: [], other: null };
|
|
1557
889
|
const ranked = items.map((item, i) => ({ item, i })).sort((a, b) => b.item.value - a.item.value || a.i - b.i);
|
|
1558
890
|
const keep = new Set(ranked.slice(0, n).map((r) => r.i));
|
|
@@ -1560,7 +892,7 @@ function aggregateTopN(items, n = MAX_CHART_SERIES, otherLabel = OTHER_SERIES_LA
|
|
|
1560
892
|
const rest = items.filter((_, i) => !keep.has(i));
|
|
1561
893
|
return { top, rest, other: { name: otherLabel, value: rest.reduce((sum, item) => sum + item.value, 0) } };
|
|
1562
894
|
}
|
|
1563
|
-
function aggregateSeries(data, categories, n = MAX_CHART_SERIES, otherLabel =
|
|
895
|
+
function aggregateSeries(data, categories, n = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
|
|
1564
896
|
const totals = categories.map((name) => ({
|
|
1565
897
|
name,
|
|
1566
898
|
value: data.reduce((sum, row) => sum + (toChartNumber(row[name]) ?? 0), 0)
|
|
@@ -1581,12 +913,13 @@ function aggregateSeries(data, categories, n = MAX_CHART_SERIES, otherLabel = OT
|
|
|
1581
913
|
otherCategory: other.name
|
|
1582
914
|
};
|
|
1583
915
|
}
|
|
1584
|
-
function aggregateSeriesKeeping(data, categories, keep, n = MAX_CHART_SERIES) {
|
|
1585
|
-
if (keep === void 0 || !categories.includes(keep)) return aggregateSeries(data, categories, n);
|
|
916
|
+
function aggregateSeriesKeeping(data, categories, keep, n = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
|
|
917
|
+
if (keep === void 0 || !categories.includes(keep)) return aggregateSeries(data, categories, n, otherLabel);
|
|
1586
918
|
const aggregated = aggregateSeries(
|
|
1587
919
|
data,
|
|
1588
920
|
categories.filter((c) => c !== keep),
|
|
1589
|
-
n
|
|
921
|
+
n,
|
|
922
|
+
otherLabel
|
|
1590
923
|
);
|
|
1591
924
|
return { ...aggregated, categories: [...aggregated.categories, keep] };
|
|
1592
925
|
}
|
|
@@ -1608,7 +941,7 @@ function seriesColorsFor(categories, colors, otherColor, otherCategory = null, a
|
|
|
1608
941
|
const list = Array.isArray(colors) ? colors : void 0;
|
|
1609
942
|
const record = !Array.isArray(colors) && colors ? colors : void 0;
|
|
1610
943
|
return categories.map((category, i) => {
|
|
1611
|
-
if (otherCategory !== null && category === otherCategory || category
|
|
944
|
+
if (otherCategory !== null && category === otherCategory || isOtherName(category)) return otherColor;
|
|
1612
945
|
const fromRecord = record?.[category];
|
|
1613
946
|
if (fromRecord) return fromRecord;
|
|
1614
947
|
if (list && list.length > 0) {
|
|
@@ -1618,7 +951,7 @@ function seriesColorsFor(categories, colors, otherColor, otherCategory = null, a
|
|
|
1618
951
|
return DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length];
|
|
1619
952
|
});
|
|
1620
953
|
}
|
|
1621
|
-
function donutSlices(data, { index, value, colors, maxSlices = MAX_CHART_SERIES, otherColor, otherLabel =
|
|
954
|
+
function donutSlices(data, { index, value, colors, maxSlices = MAX_CHART_SERIES, otherColor, otherLabel = otherSeriesLabel() }) {
|
|
1622
955
|
const items = data.map((row, i) => {
|
|
1623
956
|
const n = toChartNumber(row[value]);
|
|
1624
957
|
return { name: String(row[index] ?? ""), value: n !== null && n > 0 ? n : 0, row, i };
|
|
@@ -1628,7 +961,8 @@ function donutSlices(data, { index, value, colors, maxSlices = MAX_CHART_SERIES,
|
|
|
1628
961
|
const slices = top.map((item, rank) => ({
|
|
1629
962
|
name: item.name,
|
|
1630
963
|
value: item.value,
|
|
1631
|
-
|
|
964
|
+
// A row the data itself names「その他」/ "Other" is the same remainder: grey, like the folded slice.
|
|
965
|
+
color: isOtherName(item.name) ? otherColor : palette[rank % palette.length],
|
|
1632
966
|
isOther: false,
|
|
1633
967
|
row: item.row
|
|
1634
968
|
}));
|
|
@@ -1649,7 +983,7 @@ function sortBarListData(data, sortOrder) {
|
|
|
1649
983
|
else if (sortOrder === "descending") rows.sort((a, b) => b.value - a.value);
|
|
1650
984
|
return rows;
|
|
1651
985
|
}
|
|
1652
|
-
function barListRows(data, { index = "name", category = "value", sortOrder = "descending", maxItems = MAX_CHART_SERIES, otherLabel =
|
|
986
|
+
function barListRows(data, { index = "name", category = "value", sortOrder = "descending", maxItems = MAX_CHART_SERIES, otherLabel = otherSeriesLabel(), exclude } = {}) {
|
|
1653
987
|
const items = data.map((row) => {
|
|
1654
988
|
const cells = row;
|
|
1655
989
|
const name = String(cells[index] ?? "");
|
|
@@ -1683,7 +1017,7 @@ var BAR_LIST_TINT = 45;
|
|
|
1683
1017
|
var BAR_LIST_OTHER_TINT = 30;
|
|
1684
1018
|
function barListFills(rows, color, otherColor) {
|
|
1685
1019
|
return rows.map(
|
|
1686
|
-
(row) => row.isOther ? tintCss(otherColor, BAR_LIST_OTHER_TINT) : tintCss(chartColorToCss(row.color ?? color), BAR_LIST_TINT)
|
|
1020
|
+
(row) => row.isOther || isOtherName(row.name) ? tintCss(otherColor, BAR_LIST_OTHER_TINT) : tintCss(chartColorToCss(row.color ?? color), BAR_LIST_TINT)
|
|
1687
1021
|
);
|
|
1688
1022
|
}
|
|
1689
1023
|
function barListShareText(value, total) {
|
|
@@ -1780,6 +1114,22 @@ function progressCircleGeometry(value, max, radius, strokeWidth) {
|
|
|
1780
1114
|
const circumference = 2 * Math.PI * normalizedRadius;
|
|
1781
1115
|
return { size: radius * 2, normalizedRadius, circumference, offset: circumference * (1 - ratio), ratio };
|
|
1782
1116
|
}
|
|
1117
|
+
var SUMMARY_TEXT = {
|
|
1118
|
+
ja: {
|
|
1119
|
+
up: "\u3001\u524D\u306E\u70B9\u3088\u308A\u5897\u52A0",
|
|
1120
|
+
down: "\u3001\u524D\u306E\u70B9\u3088\u308A\u6E1B\u5C11",
|
|
1121
|
+
flat: "\u3001\u524D\u306E\u70B9\u3068\u6A2A\u3070\u3044",
|
|
1122
|
+
latest: (label2, value) => `\u6700\u65B0 ${label2} \u306F ${value}`,
|
|
1123
|
+
top: (name, share) => `\u6700\u5927\u306F ${name}(${share})`
|
|
1124
|
+
},
|
|
1125
|
+
en: {
|
|
1126
|
+
up: ", up from the previous point",
|
|
1127
|
+
down: ", down from the previous point",
|
|
1128
|
+
flat: ", flat from the previous point",
|
|
1129
|
+
latest: (label2, value) => `Latest ${label2}: ${value}`,
|
|
1130
|
+
top: (name, share) => `Largest: ${name} (${share})`
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1783
1133
|
function buildChartSummary(input) {
|
|
1784
1134
|
const key = input.categories[0];
|
|
1785
1135
|
if (key === void 0) return void 0;
|
|
@@ -1791,54 +1141,96 @@ function buildChartSummary(input) {
|
|
|
1791
1141
|
}
|
|
1792
1142
|
const latest = points[points.length - 1];
|
|
1793
1143
|
if (!latest) return void 0;
|
|
1794
|
-
const
|
|
1144
|
+
const locale = resolveLocale(input.locale);
|
|
1145
|
+
const t = SUMMARY_TEXT[uiLanguage(locale)];
|
|
1146
|
+
const text = input.valueFormatter ?? toValueFormatter(input.format ?? "compact", locale);
|
|
1795
1147
|
const prev = points[points.length - 2];
|
|
1796
|
-
const direction = !prev ? "" : latest.value > prev.value ?
|
|
1148
|
+
const direction = !prev ? "" : latest.value > prev.value ? t.up : latest.value < prev.value ? t.down : t.flat;
|
|
1797
1149
|
const head = input.title ? `${input.title}: ` : "";
|
|
1798
|
-
return `${head}
|
|
1150
|
+
return `${head}${t.latest(latest.label, text(latest.value))}${direction}`;
|
|
1799
1151
|
}
|
|
1800
|
-
function buildShareSummary(slices, title) {
|
|
1152
|
+
function buildShareSummary(slices, title, locale) {
|
|
1801
1153
|
const total = slices.reduce((sum, s) => sum + s.value, 0);
|
|
1802
1154
|
const top = slices[0];
|
|
1803
1155
|
if (!top || total <= 0) return void 0;
|
|
1804
1156
|
const share = `${Math.round(top.value / total * 1e3) / 10}%`;
|
|
1805
|
-
return `${title ? `${title}: ` : ""}
|
|
1157
|
+
return `${title ? `${title}: ` : ""}${SUMMARY_TEXT[uiLanguage(resolveLocale(locale))].top(top.name, share)}`;
|
|
1806
1158
|
}
|
|
1807
1159
|
|
|
1808
1160
|
// ../squadkit/registry/lib/comparison.ts
|
|
1809
1161
|
var COMPARISON_LABELS = {
|
|
1810
|
-
"prior-period": "
|
|
1811
|
-
"prior-year": "
|
|
1812
|
-
target: "
|
|
1162
|
+
"prior-period": "vs. prior period",
|
|
1163
|
+
"prior-year": "vs. same period last year",
|
|
1164
|
+
target: "vs. target"
|
|
1813
1165
|
};
|
|
1814
1166
|
var BASELINE_NOUNS = {
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1167
|
+
ja: {
|
|
1168
|
+
"prior-period": {
|
|
1169
|
+
day: "\u524D\u65E5",
|
|
1170
|
+
week: "\u524D\u9031",
|
|
1171
|
+
month: "\u524D\u6708",
|
|
1172
|
+
quarter: "\u524D\u56DB\u534A\u671F",
|
|
1173
|
+
year: "\u524D\u5E74",
|
|
1174
|
+
unknown: "\u524D\u671F"
|
|
1175
|
+
},
|
|
1176
|
+
"prior-year": {
|
|
1177
|
+
day: "\u524D\u5E74\u540C\u65E5",
|
|
1178
|
+
week: "\u524D\u5E74\u540C\u9031",
|
|
1179
|
+
month: "\u524D\u5E74\u540C\u6708",
|
|
1180
|
+
quarter: "\u524D\u5E74\u540C\u671F",
|
|
1181
|
+
year: "\u524D\u5E74",
|
|
1182
|
+
unknown: "\u524D\u5E74\u540C\u671F"
|
|
1183
|
+
},
|
|
1184
|
+
target: "\u76EE\u6A19",
|
|
1185
|
+
custom: "\u6BD4\u8F03\u5BFE\u8C61"
|
|
1822
1186
|
},
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1187
|
+
en: {
|
|
1188
|
+
"prior-period": {
|
|
1189
|
+
day: "prior day",
|
|
1190
|
+
week: "prior week",
|
|
1191
|
+
month: "prior month",
|
|
1192
|
+
quarter: "prior quarter",
|
|
1193
|
+
year: "prior year",
|
|
1194
|
+
unknown: "prior period"
|
|
1195
|
+
},
|
|
1196
|
+
"prior-year": {
|
|
1197
|
+
day: "same day last year",
|
|
1198
|
+
week: "same week last year",
|
|
1199
|
+
month: "same month last year",
|
|
1200
|
+
quarter: "same quarter last year",
|
|
1201
|
+
year: "prior year",
|
|
1202
|
+
unknown: "same period last year"
|
|
1203
|
+
},
|
|
1204
|
+
target: "target",
|
|
1205
|
+
custom: "baseline"
|
|
1830
1206
|
}
|
|
1831
1207
|
};
|
|
1832
|
-
|
|
1208
|
+
var LABEL_OF = {
|
|
1209
|
+
ja: (baseline) => `${baseline}\u6BD4`,
|
|
1210
|
+
en: (baseline) => `vs. ${baseline}`
|
|
1211
|
+
};
|
|
1212
|
+
function baselineOfLabel(named, language) {
|
|
1213
|
+
if (named.length > 1 && named.endsWith("\u6BD4")) return named.slice(0, -1);
|
|
1214
|
+
if (language === "en") {
|
|
1215
|
+
const stripped = named.replace(/^vs\.?\s+/i, "");
|
|
1216
|
+
if (stripped) return stripped;
|
|
1217
|
+
}
|
|
1218
|
+
return named;
|
|
1219
|
+
}
|
|
1220
|
+
function comparisonBaseline(vs, grain, label2, toDate2, locale) {
|
|
1221
|
+
const language = uiLanguage(resolveLocale(locale));
|
|
1222
|
+
const nouns = BASELINE_NOUNS[language];
|
|
1833
1223
|
const named = label2?.trim();
|
|
1834
|
-
if (named) return
|
|
1835
|
-
if (vs === "custom") return
|
|
1836
|
-
if (vs === "target") return
|
|
1837
|
-
if (vs === "prior-year" && toDate2) return
|
|
1838
|
-
return
|
|
1224
|
+
if (named) return baselineOfLabel(named, language);
|
|
1225
|
+
if (vs === "custom") return nouns.custom;
|
|
1226
|
+
if (vs === "target") return nouns.target;
|
|
1227
|
+
if (vs === "prior-year" && toDate2) return nouns["prior-year"].unknown;
|
|
1228
|
+
return nouns[vs][grain ?? "unknown"];
|
|
1839
1229
|
}
|
|
1840
|
-
function comparisonLabel(vs, grain, label2, toDate2) {
|
|
1841
|
-
|
|
1230
|
+
function comparisonLabel(vs, grain, label2, toDate2, locale) {
|
|
1231
|
+
if (label2?.trim()) return label2;
|
|
1232
|
+
const resolved = resolveLocale(locale);
|
|
1233
|
+
return LABEL_OF[uiLanguage(resolved)](comparisonBaseline(vs, grain, void 0, toDate2, resolved));
|
|
1842
1234
|
}
|
|
1843
1235
|
var toNumber = (v) => v === null || v === void 0 || Number.isNaN(v) ? null : v;
|
|
1844
1236
|
function computeComparison(current, comparison, options) {
|
|
@@ -1846,7 +1238,7 @@ function computeComparison(current, comparison, options) {
|
|
|
1846
1238
|
const neutralBand = options?.neutralBand ?? 0.01;
|
|
1847
1239
|
const cur = toNumber(current);
|
|
1848
1240
|
const prev = toNumber(comparison.previous);
|
|
1849
|
-
const label2 = comparisonLabel(comparison.vs, comparison.grain, comparison.label, comparison.toDate);
|
|
1241
|
+
const label2 = comparisonLabel(comparison.vs, comparison.grain, comparison.label, comparison.toDate, options?.locale);
|
|
1850
1242
|
const difference = cur !== null && prev !== null ? cur - prev : null;
|
|
1851
1243
|
const ratio = difference !== null && prev !== null && prev !== 0 ? difference / Math.abs(prev) : null;
|
|
1852
1244
|
let direction;
|
|
@@ -1859,20 +1251,20 @@ function computeComparison(current, comparison, options) {
|
|
|
1859
1251
|
else if (direction === "down") sentiment = polarity === "higher-is-better" ? "negative" : "positive";
|
|
1860
1252
|
return { current: cur, previous: prev, difference, ratio, direction, sentiment, label: label2, vs: comparison.vs };
|
|
1861
1253
|
}
|
|
1862
|
-
function defaultChangeDisplay(
|
|
1863
|
-
return formatKind(
|
|
1254
|
+
function defaultChangeDisplay(format) {
|
|
1255
|
+
return formatKind(format) === "percent" ? "points" : "relative";
|
|
1864
1256
|
}
|
|
1865
|
-
function formatChange(result, display = "relative", locale
|
|
1257
|
+
function formatChange(result, display = "relative", locale, format, digits) {
|
|
1866
1258
|
if (result.direction === "none") return null;
|
|
1867
|
-
if (display === "difference") return result.difference === null ? null : formatDelta(result.difference,
|
|
1259
|
+
if (display === "difference") return result.difference === null ? null : formatDelta(result.difference, format, locale);
|
|
1868
1260
|
if (display === "points")
|
|
1869
1261
|
return result.difference === null ? null : formatPoints(result.difference, locale, digits === void 0 ? void 0 : { digits });
|
|
1870
1262
|
return result.ratio === null ? null : formatDelta(result.ratio, digits === void 0 ? "percent" : { type: "percent", digits }, locale);
|
|
1871
1263
|
}
|
|
1872
|
-
function formatChangeAmount(result, display = "relative", locale
|
|
1264
|
+
function formatChangeAmount(result, display = "relative", locale, format, digits) {
|
|
1873
1265
|
if (result.direction === "none") return null;
|
|
1874
1266
|
if (display === "difference")
|
|
1875
|
-
return result.difference === null ? null : formatValue(Math.abs(result.difference),
|
|
1267
|
+
return result.difference === null ? null : formatValue(Math.abs(result.difference), format, locale);
|
|
1876
1268
|
if (display === "points")
|
|
1877
1269
|
return result.difference === null ? null : formatPoints(result.difference, locale, { signDisplay: "never", ...digits === void 0 ? {} : { digits } });
|
|
1878
1270
|
return result.ratio === null ? null : formatValue(Math.abs(result.ratio), digits === void 0 ? "percent" : { type: "percent", digits }, locale);
|
|
@@ -1891,6 +1283,29 @@ function toneForValue(value, thresholds) {
|
|
|
1891
1283
|
}
|
|
1892
1284
|
|
|
1893
1285
|
// ../squadkit/registry/lib/chart-options.ts
|
|
1286
|
+
var CHART_TEXT = {
|
|
1287
|
+
ja: {
|
|
1288
|
+
target: "\u76EE\u6A19",
|
|
1289
|
+
forecast: "\u4E88\u6E2C",
|
|
1290
|
+
total: "\u5408\u8A08",
|
|
1291
|
+
provisional: "\u901F\u5831",
|
|
1292
|
+
noComparison: "\u6BD4\u8F03\u306A\u3057",
|
|
1293
|
+
share: (share) => `\uFF08${share}\uFF09`,
|
|
1294
|
+
targetRate: (rate) => `\uFF08\u9054\u6210\u7387 ${rate}\uFF09`,
|
|
1295
|
+
provisionalTitle: (title, label2) => `${title}(${label2})`
|
|
1296
|
+
},
|
|
1297
|
+
en: {
|
|
1298
|
+
target: "Target",
|
|
1299
|
+
forecast: "Forecast",
|
|
1300
|
+
total: "Total",
|
|
1301
|
+
provisional: "Preliminary",
|
|
1302
|
+
noComparison: "No comparison",
|
|
1303
|
+
share: (share) => ` (${share})`,
|
|
1304
|
+
targetRate: (rate) => ` (${rate} achieved)`,
|
|
1305
|
+
provisionalTitle: (title, label2) => `${title} (${label2})`
|
|
1306
|
+
}
|
|
1307
|
+
};
|
|
1308
|
+
var chartText = (locale) => CHART_TEXT[uiLanguage(resolveLocale(locale))];
|
|
1894
1309
|
function chartMotion(reducedMotion) {
|
|
1895
1310
|
if (reducedMotion) return { animation: false };
|
|
1896
1311
|
return { animation: true, animationDuration: 0, animationDurationUpdate: 300, animationEasingUpdate: "cubicOut" };
|
|
@@ -1955,12 +1370,12 @@ function parseTimeIndex(values) {
|
|
|
1955
1370
|
var timeFormatCache = /* @__PURE__ */ new Map();
|
|
1956
1371
|
function timeFormat(locale, options) {
|
|
1957
1372
|
const key = `${locale}|${JSON.stringify(options)}`;
|
|
1958
|
-
let
|
|
1959
|
-
if (!
|
|
1960
|
-
|
|
1961
|
-
timeFormatCache.set(key,
|
|
1373
|
+
let format = timeFormatCache.get(key);
|
|
1374
|
+
if (!format) {
|
|
1375
|
+
format = new Intl.DateTimeFormat(locale, options);
|
|
1376
|
+
timeFormatCache.set(key, format);
|
|
1962
1377
|
}
|
|
1963
|
-
return
|
|
1378
|
+
return format;
|
|
1964
1379
|
}
|
|
1965
1380
|
var toDate = (t) => new Date(t.year, t.month - 1, t.day);
|
|
1966
1381
|
var TIME_AXIS_MAX_LABELS = 6;
|
|
@@ -1979,9 +1394,10 @@ function timeAxisLabelStep(values, maxLabels = TIME_AXIS_MAX_LABELS) {
|
|
|
1979
1394
|
const steps = TIME_AXIS_STEPS[parsed.granularity];
|
|
1980
1395
|
return steps.find((step) => Math.ceil(count / step) <= max) ?? Math.ceil(count / max);
|
|
1981
1396
|
}
|
|
1982
|
-
function timeAxisLabels(values,
|
|
1397
|
+
function timeAxisLabels(values, localeArg, shown = () => true) {
|
|
1983
1398
|
const parsed = parseTimeIndex(values);
|
|
1984
1399
|
if (!parsed) return null;
|
|
1400
|
+
const locale = resolveLocale(localeArg);
|
|
1985
1401
|
const { granularity, times } = parsed;
|
|
1986
1402
|
let prevYear = null;
|
|
1987
1403
|
return times.map((t, i) => {
|
|
@@ -1993,9 +1409,10 @@ function timeAxisLabels(values, locale = DEFAULT_LOCALE, shown = () => true) {
|
|
|
1993
1409
|
return timeFormat(locale, options).format(toDate(t));
|
|
1994
1410
|
});
|
|
1995
1411
|
}
|
|
1996
|
-
function timeTooltipLabels(values,
|
|
1412
|
+
function timeTooltipLabels(values, localeArg) {
|
|
1997
1413
|
const parsed = parseTimeIndex(values);
|
|
1998
1414
|
if (!parsed) return null;
|
|
1415
|
+
const locale = resolveLocale(localeArg);
|
|
1999
1416
|
const options = parsed.granularity === "year" ? { year: "numeric" } : parsed.granularity === "month" ? { year: "numeric", month: "long" } : { year: "numeric", month: "long", day: "numeric" };
|
|
2000
1417
|
return parsed.times.map((t, i) => t === null ? String(values[i] ?? "") : timeFormat(locale, options).format(toDate(t)));
|
|
2001
1418
|
}
|
|
@@ -2072,16 +1489,16 @@ function escapeHtml(value) {
|
|
|
2072
1489
|
}
|
|
2073
1490
|
var shareFormat = new Intl.NumberFormat(DEFAULT_LOCALE, { maximumFractionDigits: 1 });
|
|
2074
1491
|
var formatShare = (share) => `${shareFormat.format(share)}%`;
|
|
2075
|
-
function tooltipHtml(title, rows, valueFormatter, notes = []) {
|
|
1492
|
+
function tooltipHtml(title, rows, valueFormatter, notes = [], locale) {
|
|
1493
|
+
const t = chartText(locale);
|
|
2076
1494
|
const lines = rows.map(
|
|
2077
|
-
(row) => `<div style="display:flex;align-items:center;gap:8px;line-height:20px"><span style="display:inline-block;width:8px;height:8px;border-radius:9999px;background:${escapeHtml(row.color)}"></span><span style="flex:1;opacity:.8">${escapeHtml(row.name)}</span><span style="font-weight:600;font-variant-numeric:tabular-nums;margin-left:12px">${row.value === null ? EMPTY_VALUE : escapeHtml(valueFormatter(row.value))}${row.share === void 0 ? "" : `<span style="opacity:.6;margin-left:4px"
|
|
1495
|
+
(row) => `<div style="display:flex;align-items:center;gap:8px;line-height:20px"><span style="display:inline-block;width:8px;height:8px;border-radius:9999px;background:${escapeHtml(row.color)}"></span><span style="flex:1;opacity:.8">${escapeHtml(row.name)}</span><span style="font-weight:600;font-variant-numeric:tabular-nums;margin-left:12px">${row.value === null ? EMPTY_VALUE : escapeHtml(valueFormatter(row.value))}${row.share === void 0 ? "" : `<span style="opacity:.6;margin-left:4px">${escapeHtml(t.share(formatShare(row.share)))}</span>`}</span></div>` + (row.note === void 0 ? "" : `<div style="padding-left:16px;line-height:18px;font-size:12px;opacity:.7;font-variant-numeric:tabular-nums">${escapeHtml(row.note)}</div>`)
|
|
2078
1496
|
);
|
|
2079
1497
|
const noteLines = notes.map(
|
|
2080
1498
|
(note) => `<div style="margin-top:4px;line-height:18px;font-size:12px;opacity:.7">${escapeHtml(note)}</div>`
|
|
2081
1499
|
);
|
|
2082
1500
|
return `<div style="font-weight:500;margin-bottom:4px">${escapeHtml(title)}</div>${lines.join("")}${noteLines.join("")}`;
|
|
2083
1501
|
}
|
|
2084
|
-
var BAR_TARGET_LABEL = "\u76EE\u6A19";
|
|
2085
1502
|
var TARGET_MARKER_OVERHANG = 4;
|
|
2086
1503
|
function targetMarkerRenderer(horizontalBars, barCategoryGap, color) {
|
|
2087
1504
|
return (_params, api) => {
|
|
@@ -2107,10 +1524,10 @@ function achievementRate(value, target) {
|
|
|
2107
1524
|
if (value === null || value === void 0 || target === null || target === void 0 || !(target > 0)) return null;
|
|
2108
1525
|
return value / target * 100;
|
|
2109
1526
|
}
|
|
2110
|
-
function barTargetNote(label2, value, target, valueFormatter) {
|
|
1527
|
+
function barTargetNote(label2, value, target, valueFormatter, locale) {
|
|
2111
1528
|
if (target === null) return null;
|
|
2112
1529
|
const rate = achievementRate(value, target);
|
|
2113
|
-
return `${label2} ${valueFormatter(target)}${rate === null ? "" :
|
|
1530
|
+
return `${label2} ${valueFormatter(target)}${rate === null ? "" : chartText(locale).targetRate(formatShare(rate))}`;
|
|
2114
1531
|
}
|
|
2115
1532
|
function barHalfWidth(barCategoryGap) {
|
|
2116
1533
|
const gap = typeof barCategoryGap === "string" && /^\d+(\.\d+)?%$/.test(barCategoryGap.trim()) ? parseFloat(barCategoryGap) / 100 : 0.2;
|
|
@@ -2158,9 +1575,8 @@ var OVERLAY_SERIES_ID = "__overlay";
|
|
|
2158
1575
|
var TARGET_MARKER_SERIES_ID = "__target-marker";
|
|
2159
1576
|
var TARGET_LEGEND_SERIES_ID = "__target-legend";
|
|
2160
1577
|
var TARGET_LEGEND_ICON = "path://M0,0 L100,0 L100,24 L0,24 Z";
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
return `${label2} \u2192`;
|
|
1578
|
+
function forecastBoundaryText(label2, locale) {
|
|
1579
|
+
return `${label2 ?? chartText(locale).forecast} \u2192`;
|
|
2164
1580
|
}
|
|
2165
1581
|
var COMPARISON_LINE_WIDTH = 1.5;
|
|
2166
1582
|
var COMPARISON_OPACITY = 0.6;
|
|
@@ -2186,7 +1602,6 @@ function isDarkSurface(color) {
|
|
|
2186
1602
|
});
|
|
2187
1603
|
return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.4;
|
|
2188
1604
|
}
|
|
2189
|
-
var STACK_TOTAL_LABEL = "\u5408\u8A08";
|
|
2190
1605
|
function stackTotalsOf(values) {
|
|
2191
1606
|
const length = Math.max(0, ...values.map((v) => v.length));
|
|
2192
1607
|
return Array.from({ length }, (_, i) => {
|
|
@@ -2252,13 +1667,15 @@ function indexGrain(values) {
|
|
|
2252
1667
|
const parsed = parseTimeIndex(values);
|
|
2253
1668
|
return parsed ? parsed.granularity : null;
|
|
2254
1669
|
}
|
|
2255
|
-
function comparisonNote(current, previous, comparison, grain,
|
|
1670
|
+
function comparisonNote(current, previous, comparison, grain, format, localeArg) {
|
|
1671
|
+
const locale = resolveLocale(localeArg);
|
|
2256
1672
|
const result = computeComparison(
|
|
2257
1673
|
current,
|
|
2258
|
-
comparison.vs === "custom" ? { previous, vs: "custom", label: comparison.label ?? "", grain } : { previous, vs: comparison.vs, label: comparison.label, grain }
|
|
1674
|
+
comparison.vs === "custom" ? { previous, vs: "custom", label: comparison.label ?? "", grain } : { previous, vs: comparison.vs, label: comparison.label, grain },
|
|
1675
|
+
{ locale }
|
|
2259
1676
|
);
|
|
2260
|
-
const text = formatChange(result, defaultChangeDisplay(
|
|
2261
|
-
if (text === null) return
|
|
1677
|
+
const text = formatChange(result, defaultChangeDisplay(format), locale, format);
|
|
1678
|
+
if (text === null) return `${chartText(locale).noComparison} ${result.label}`;
|
|
2262
1679
|
const arrow = result.direction === "up" ? "\u2191" : result.direction === "down" ? "\u2193" : "\u2192";
|
|
2263
1680
|
return `${arrow} ${text.replace(/^-/, "\u2212")} ${result.label}`;
|
|
2264
1681
|
}
|
|
@@ -2283,7 +1700,6 @@ function buildCartesianOption(cfg) {
|
|
|
2283
1700
|
toneColors,
|
|
2284
1701
|
valueFormatter,
|
|
2285
1702
|
axisFormatter = valueFormatter,
|
|
2286
|
-
locale = DEFAULT_LOCALE,
|
|
2287
1703
|
type = "default",
|
|
2288
1704
|
layout = "horizontal",
|
|
2289
1705
|
curveType = "linear",
|
|
@@ -2320,7 +1736,9 @@ function buildCartesianOption(cfg) {
|
|
|
2320
1736
|
chartOptions,
|
|
2321
1737
|
reserveActions = false
|
|
2322
1738
|
} = cfg;
|
|
2323
|
-
const
|
|
1739
|
+
const locale = resolveLocale(cfg.locale);
|
|
1740
|
+
const text = chartText(locale);
|
|
1741
|
+
const provisionalLabel = cfg.provisionalLabel ?? text.provisional;
|
|
2324
1742
|
const stacked = kind !== "line" && type !== "default";
|
|
2325
1743
|
const percent = kind !== "line" && type === "percent";
|
|
2326
1744
|
const horizontalBars = kind === "bar" && layout === "vertical";
|
|
@@ -2391,8 +1809,8 @@ function buildCartesianOption(cfg) {
|
|
|
2391
1809
|
const edgeAlign = (i) => horizontalBars || labels.length < 2 ? void 0 : i === boundaryIndex && i !== last ? { align: "right", offset: [-6, 0] } : i === last ? { align: "right", ...kind === "bar" ? { offset: [8, 0] } : {} } : i === 0 ? { align: "left", ...kind === "bar" ? { offset: [-8, 0] } : {} } : void 0;
|
|
2392
1810
|
const perBarTarget = kind === "bar" && Boolean(targetKey);
|
|
2393
1811
|
const hasTarget = !perBarTarget && target !== void 0 && Number.isFinite(target);
|
|
2394
|
-
const targetText = hasTarget ? targetLabel ??
|
|
2395
|
-
const highlightText = (value) => shareHighlight ? `${Math.round(value)}%` : `${stackTotals ? `${
|
|
1812
|
+
const targetText = hasTarget ? targetLabel ?? `${text.target} ${axisFormatter(target)}` : "";
|
|
1813
|
+
const highlightText = (value) => shareHighlight ? `${Math.round(value)}%` : `${stackTotals ? `${text.total} ` : ""}${axisFormatter(value)}`;
|
|
2396
1814
|
const nearTargetLabel = (p, side) => {
|
|
2397
1815
|
if (!hasTarget || !plotWidth || kind === "bar" || labels.length < 2) return false;
|
|
2398
1816
|
if (side === "under" ? p.value > target : p.value <= target) return false;
|
|
@@ -2409,7 +1827,7 @@ function buildCartesianOption(cfg) {
|
|
|
2409
1827
|
const below = (p) => !shareHighlight && !hideTargetLabel && nearTargetLabel(p, "under");
|
|
2410
1828
|
const targetLabelBelow = !shareHighlight && !hideTargetLabel && highlightPoints.some((p) => nearTargetLabel(p, "over"));
|
|
2411
1829
|
const barTargets = perBarTarget && targetKey && !percent && (stacked || categories.length === 1) ? barTargetValues(data, targetKey) : null;
|
|
2412
|
-
const barTargetName = targetLabel ??
|
|
1830
|
+
const barTargetName = targetLabel ?? text.target;
|
|
2413
1831
|
const barTargetColor = labelColor ?? guideColor;
|
|
2414
1832
|
const markPointFor = (c, color) => c === highlightSeries && highlightPoints.length > 0 ? {
|
|
2415
1833
|
silent: true,
|
|
@@ -2588,7 +2006,7 @@ function buildCartesianOption(cfg) {
|
|
|
2588
2006
|
data: []
|
|
2589
2007
|
});
|
|
2590
2008
|
}
|
|
2591
|
-
const forecastLabel = forecast?.label ??
|
|
2009
|
+
const forecastLabel = forecast?.label ?? text.forecast;
|
|
2592
2010
|
const forecastBandAlpha = isDarkSurface(labelBackground) ? FORECAST_BAND_ALPHA_DARK : FORECAST_BAND_ALPHA_LIGHT;
|
|
2593
2011
|
const forecastValues = [];
|
|
2594
2012
|
if (forecast) {
|
|
@@ -2865,8 +2283,8 @@ function buildCartesianOption(cfg) {
|
|
|
2865
2283
|
const top = percent ? 100 : maxValue ?? Math.max(0, ...(stacked ? stackTotalsOf(values) : values.flat()).map((v) => v ?? 0));
|
|
2866
2284
|
const categoryColumn = showYAxis ? (yAxisWidth ?? Math.min(160, Math.max(0, ...labels.map(estimateTextWidth)))) + 8 : 0;
|
|
2867
2285
|
const plot = plotWidth - categoryColumn - (highlightPoints.length > 0 ? 64 : 16) - 4;
|
|
2868
|
-
const
|
|
2869
|
-
return valueAxisSplitNumber(plot, [
|
|
2286
|
+
const text2 = percent ? (v) => `${v}%` : (v) => axisFormatter(v);
|
|
2287
|
+
return valueAxisSplitNumber(plot, [text2(0), text2(top)]);
|
|
2870
2288
|
})();
|
|
2871
2289
|
const limits = valueAxisLimits({ minValue, maxValue }, kind !== "line");
|
|
2872
2290
|
const splitNumber = horizontalBars ? valueSplitNumber : valueAxisSplitCount(plotHeight);
|
|
@@ -3004,7 +2422,7 @@ function buildCartesianOption(cfg) {
|
|
|
3004
2422
|
});
|
|
3005
2423
|
}
|
|
3006
2424
|
if (stackTotals && i <= lastActual && rows.length > 1) {
|
|
3007
|
-
rows.push({ name:
|
|
2425
|
+
rows.push({ name: text.total, color: "transparent", value: stackTotals[i] ?? null });
|
|
3008
2426
|
}
|
|
3009
2427
|
const provisional = provStart !== -1 && i >= provStart && i <= lastActual;
|
|
3010
2428
|
if (provisional) {
|
|
@@ -3019,19 +2437,19 @@ function buildCartesianOption(cfg) {
|
|
|
3019
2437
|
...noteFor(at)
|
|
3020
2438
|
});
|
|
3021
2439
|
});
|
|
3022
|
-
if (stackTotals && rows.length > 1) rows.push({ name:
|
|
2440
|
+
if (stackTotals && rows.length > 1) rows.push({ name: text.total, color: "transparent", value: stackTotals[i] ?? null });
|
|
3023
2441
|
}
|
|
3024
2442
|
const title = tooltipTitles[i] ?? labels[i] ?? "";
|
|
3025
2443
|
const lines = [];
|
|
3026
2444
|
if (barTargets && i <= lastActual) {
|
|
3027
2445
|
const total = stackTotals ? stackTotals[i] ?? null : values[0]?.[i] ?? null;
|
|
3028
|
-
const note = barTargetNote(barTargetName, total, barTargets[i] ?? null, valueFormatter);
|
|
2446
|
+
const note = barTargetNote(barTargetName, total, barTargets[i] ?? null, valueFormatter, locale);
|
|
3029
2447
|
if (note) lines.push(note);
|
|
3030
2448
|
}
|
|
3031
2449
|
for (const note of notes) {
|
|
3032
2450
|
if (note.to === void 0 ? note.from === i : note.from <= i && i <= note.to) lines.push(note.label);
|
|
3033
2451
|
}
|
|
3034
|
-
return tooltipHtml(provisional ?
|
|
2452
|
+
return tooltipHtml(provisional ? text.provisionalTitle(title, provisionalLabel) : title, rows, valueFormatter, lines, locale);
|
|
3035
2453
|
}
|
|
3036
2454
|
},
|
|
3037
2455
|
xAxis: horizontalBars ? valueAxis : categoryAxis,
|
|
@@ -3060,7 +2478,6 @@ function donutTopText(slices, labels) {
|
|
|
3060
2478
|
return top ? { label: labelOf(top.name, labels), amount: donutShareText(top.value, total) } : null;
|
|
3061
2479
|
}
|
|
3062
2480
|
var DONUT_OUTSIDE_LABELS = 2;
|
|
3063
|
-
var DEFAULT_TOTAL_LABEL = "\u5408\u8A08";
|
|
3064
2481
|
var sliceValue = (value) => Number.isFinite(value) && value > 0 ? value : 0;
|
|
3065
2482
|
function donutShareText(value, total) {
|
|
3066
2483
|
const v = sliceValue(value);
|
|
@@ -3072,7 +2489,8 @@ function donutLegendItems(slices) {
|
|
|
3072
2489
|
const total = slices.reduce((sum, s) => sum + sliceValue(s.value), 0);
|
|
3073
2490
|
return slices.map((s, slice) => ({ name: s.name, value: sliceValue(s.value), share: donutShareText(s.value, total), isOther: Boolean(s.isOther), slice })).sort((a, b) => Number(a.isOther) - Number(b.isOther) || b.value - a.value || a.slice - b.slice);
|
|
3074
2491
|
}
|
|
3075
|
-
function donutCenterText(total, valueFormatter, { totalLabel
|
|
2492
|
+
function donutCenterText(total, valueFormatter, { totalLabel, unit, locale } = {}) {
|
|
2493
|
+
totalLabel ??= chartText(locale).total;
|
|
3076
2494
|
const amount = valueFormatter(total);
|
|
3077
2495
|
return { label: totalLabel, value: unit ? `${amount} ${unit}` : amount, amount, ...unit ? { unit } : {} };
|
|
3078
2496
|
}
|
|
@@ -3192,7 +2610,6 @@ function labelRows(data, index, labels) {
|
|
|
3192
2610
|
function hasLabel(labels, key) {
|
|
3193
2611
|
return Boolean(labels) && Object.prototype.hasOwnProperty.call(labels, key);
|
|
3194
2612
|
}
|
|
3195
|
-
var DEFAULT_PROVISIONAL_LABEL = "\u901F\u5831";
|
|
3196
2613
|
function provisionalStart(indexValues, from) {
|
|
3197
2614
|
if (from === void 0 || from === null) return -1;
|
|
3198
2615
|
const key = String(from);
|
|
@@ -3205,6 +2622,10 @@ function splitProvisional(values, start) {
|
|
|
3205
2622
|
provisional: values.map((v, i) => i >= Math.max(0, start - 1) ? v : null)
|
|
3206
2623
|
};
|
|
3207
2624
|
}
|
|
2625
|
+
var TEXT4 = {
|
|
2626
|
+
ja: { item: "\u9805\u76EE", chart: (categories) => `${categories.join("\u30FB")}\u306E\u9762\u30B0\u30E9\u30D5` },
|
|
2627
|
+
en: { item: "Item", chart: (categories) => `Area chart of ${categories.join(", ")}` }
|
|
2628
|
+
};
|
|
3208
2629
|
var NO_ROWS = [];
|
|
3209
2630
|
function AreaChartImpl({
|
|
3210
2631
|
data = NO_ROWS,
|
|
@@ -3213,7 +2634,7 @@ function AreaChartImpl({
|
|
|
3213
2634
|
colors,
|
|
3214
2635
|
labels,
|
|
3215
2636
|
valueFormatter,
|
|
3216
|
-
format
|
|
2637
|
+
format,
|
|
3217
2638
|
title,
|
|
3218
2639
|
summary,
|
|
3219
2640
|
actions,
|
|
@@ -3252,14 +2673,18 @@ function AreaChartImpl({
|
|
|
3252
2673
|
className,
|
|
3253
2674
|
...rest
|
|
3254
2675
|
}, ref) {
|
|
3255
|
-
const tokens =
|
|
3256
|
-
const
|
|
3257
|
-
const
|
|
3258
|
-
const
|
|
3259
|
-
const
|
|
2676
|
+
const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
|
|
2677
|
+
const locale = useLocale();
|
|
2678
|
+
const t = TEXT4[uiLanguage(locale)];
|
|
2679
|
+
const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
2680
|
+
const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
2681
|
+
const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
3260
2682
|
const comparisonCategory = comparison && categories.includes(comparison.category) ? comparison.category : void 0;
|
|
3261
2683
|
const comparisonConfig = comparisonCategory === void 0 ? void 0 : comparison;
|
|
3262
|
-
const series = useMemo(
|
|
2684
|
+
const series = useMemo(
|
|
2685
|
+
() => aggregateSeriesKeeping(data, categories, comparisonCategory, void 0, otherSeriesLabel(locale)),
|
|
2686
|
+
[data, categories, comparisonCategory, locale]
|
|
2687
|
+
);
|
|
3263
2688
|
const palette = useMemo(
|
|
3264
2689
|
() => resolveChartColors(
|
|
3265
2690
|
seriesColorsWithComparison(series.categories, colors, CHART_OTHER_COLOR, series.otherCategory, categories, comparisonCategory),
|
|
@@ -3306,7 +2731,7 @@ function AreaChartImpl({
|
|
|
3306
2731
|
annotations,
|
|
3307
2732
|
forecast,
|
|
3308
2733
|
comparison: comparisonConfig,
|
|
3309
|
-
comparisonFormat:
|
|
2734
|
+
comparisonFormat: format,
|
|
3310
2735
|
provisionalFrom,
|
|
3311
2736
|
provisionalLabel,
|
|
3312
2737
|
reserveActions: Boolean(actions),
|
|
@@ -3315,7 +2740,8 @@ function AreaChartImpl({
|
|
|
3315
2740
|
labelColor: tokens?.foreground ?? void 0,
|
|
3316
2741
|
plotWidth,
|
|
3317
2742
|
plotHeight: typeof height === "number" ? height : void 0,
|
|
3318
|
-
chartOptions
|
|
2743
|
+
chartOptions,
|
|
2744
|
+
locale
|
|
3319
2745
|
}),
|
|
3320
2746
|
[
|
|
3321
2747
|
series,
|
|
@@ -3351,23 +2777,24 @@ function AreaChartImpl({
|
|
|
3351
2777
|
annotations,
|
|
3352
2778
|
forecast,
|
|
3353
2779
|
comparisonConfig,
|
|
3354
|
-
|
|
2780
|
+
format,
|
|
3355
2781
|
height,
|
|
3356
2782
|
tokens,
|
|
3357
2783
|
surface,
|
|
3358
2784
|
plotWidth,
|
|
3359
|
-
chartOptions
|
|
2785
|
+
chartOptions,
|
|
2786
|
+
locale
|
|
3360
2787
|
]
|
|
3361
2788
|
);
|
|
3362
2789
|
const dataTable = useMemo(() => {
|
|
3363
|
-
const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels,
|
|
3364
|
-
const times = timeTooltipLabels(series.data.map((row) => row[index]));
|
|
2790
|
+
const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, t.item);
|
|
2791
|
+
const times = timeTooltipLabels(series.data.map((row) => row[index]), locale);
|
|
3365
2792
|
return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
|
|
3366
|
-
}, [series, index, tooltipFormatter, labels]);
|
|
3367
|
-
const label2 = ariaLabel ??
|
|
2793
|
+
}, [series, index, tooltipFormatter, labels, t, locale]);
|
|
2794
|
+
const label2 = ariaLabel ?? t.chart(categories);
|
|
3368
2795
|
const resolvedSummary = useMemo(
|
|
3369
|
-
() => summary === "auto" ? buildChartSummary({ data, index, categories, title, format
|
|
3370
|
-
[summary, data, index, categories, title,
|
|
2796
|
+
() => summary === "auto" ? buildChartSummary({ data, index, categories, title, format, valueFormatter, locale }) : summary,
|
|
2797
|
+
[summary, data, index, categories, title, format, valueFormatter, locale]
|
|
3371
2798
|
);
|
|
3372
2799
|
return /* @__PURE__ */ jsx(
|
|
3373
2800
|
ChartFrame,
|
|
@@ -3390,6 +2817,10 @@ function AreaChartImpl({
|
|
|
3390
2817
|
}
|
|
3391
2818
|
var AreaChart = forwardRef(AreaChartImpl);
|
|
3392
2819
|
AreaChart.displayName = "AreaChart";
|
|
2820
|
+
var TEXT5 = {
|
|
2821
|
+
ja: { item: "\u9805\u76EE", chart: (categories) => `${categories.join("\u30FB")}\u306E\u68D2\u30B0\u30E9\u30D5` },
|
|
2822
|
+
en: { item: "Item", chart: (categories) => `Bar chart of ${categories.join(", ")}` }
|
|
2823
|
+
};
|
|
3393
2824
|
var NO_ROWS2 = [];
|
|
3394
2825
|
function BarChartImpl({
|
|
3395
2826
|
data = NO_ROWS2,
|
|
@@ -3398,7 +2829,7 @@ function BarChartImpl({
|
|
|
3398
2829
|
colors,
|
|
3399
2830
|
labels,
|
|
3400
2831
|
valueFormatter,
|
|
3401
|
-
format
|
|
2832
|
+
format,
|
|
3402
2833
|
title,
|
|
3403
2834
|
summary,
|
|
3404
2835
|
actions,
|
|
@@ -3435,12 +2866,13 @@ function BarChartImpl({
|
|
|
3435
2866
|
className,
|
|
3436
2867
|
...rest
|
|
3437
2868
|
}, ref) {
|
|
3438
|
-
const tokens =
|
|
3439
|
-
const
|
|
3440
|
-
const
|
|
3441
|
-
const
|
|
3442
|
-
const
|
|
3443
|
-
const
|
|
2869
|
+
const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
|
|
2870
|
+
const locale = useLocale();
|
|
2871
|
+
const t = TEXT5[uiLanguage(locale)];
|
|
2872
|
+
const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
2873
|
+
const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
2874
|
+
const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
2875
|
+
const series = useMemo(() => aggregateSeries(data, categories, void 0, otherSeriesLabel(locale)), [data, categories, locale]);
|
|
3444
2876
|
const palette = useMemo(
|
|
3445
2877
|
() => resolveChartColors(
|
|
3446
2878
|
// Meaning colours on bars are AREA colours (`warning` -> `--warning-fill`), the same as the thresholds' and a legend's.
|
|
@@ -3498,7 +2930,8 @@ function BarChartImpl({
|
|
|
3498
2930
|
labelColor: tokens?.foreground ?? void 0,
|
|
3499
2931
|
plotWidth,
|
|
3500
2932
|
plotHeight: typeof height === "number" ? height : void 0,
|
|
3501
|
-
chartOptions
|
|
2933
|
+
chartOptions,
|
|
2934
|
+
locale
|
|
3502
2935
|
}),
|
|
3503
2936
|
[
|
|
3504
2937
|
series,
|
|
@@ -3539,18 +2972,19 @@ function BarChartImpl({
|
|
|
3539
2972
|
tokens,
|
|
3540
2973
|
surface,
|
|
3541
2974
|
plotWidth,
|
|
3542
|
-
chartOptions
|
|
2975
|
+
chartOptions,
|
|
2976
|
+
locale
|
|
3543
2977
|
]
|
|
3544
2978
|
);
|
|
3545
2979
|
const dataTable = useMemo(() => {
|
|
3546
|
-
const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels,
|
|
3547
|
-
const times = timeTooltipLabels(series.data.map((row) => row[index]));
|
|
2980
|
+
const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, t.item);
|
|
2981
|
+
const times = timeTooltipLabels(series.data.map((row) => row[index]), locale);
|
|
3548
2982
|
return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
|
|
3549
|
-
}, [series, index, tooltipFormatter, labels]);
|
|
3550
|
-
const label2 = ariaLabel ??
|
|
2983
|
+
}, [series, index, tooltipFormatter, labels, t, locale]);
|
|
2984
|
+
const label2 = ariaLabel ?? t.chart(categories);
|
|
3551
2985
|
const resolvedSummary = useMemo(
|
|
3552
|
-
() => summary === "auto" ? buildChartSummary({ data, index, categories, title, format
|
|
3553
|
-
[summary, data, index, categories, title,
|
|
2986
|
+
() => summary === "auto" ? buildChartSummary({ data, index, categories, title, format, valueFormatter, locale }) : summary,
|
|
2987
|
+
[summary, data, index, categories, title, format, valueFormatter, locale]
|
|
3554
2988
|
);
|
|
3555
2989
|
return /* @__PURE__ */ jsx(
|
|
3556
2990
|
ChartFrame,
|
|
@@ -3571,8 +3005,12 @@ function BarChartImpl({
|
|
|
3571
3005
|
}
|
|
3572
3006
|
);
|
|
3573
3007
|
}
|
|
3574
|
-
var
|
|
3575
|
-
|
|
3008
|
+
var BarChart = forwardRef(BarChartImpl);
|
|
3009
|
+
BarChart.displayName = "BarChart";
|
|
3010
|
+
var TEXT6 = {
|
|
3011
|
+
ja: { item: "\u9805\u76EE", chart: (categories) => `${categories.join("\u30FB")}\u306E\u6298\u308C\u7DDA\u30B0\u30E9\u30D5` },
|
|
3012
|
+
en: { item: "Item", chart: (categories) => `Line chart of ${categories.join(", ")}` }
|
|
3013
|
+
};
|
|
3576
3014
|
var NO_ROWS3 = [];
|
|
3577
3015
|
function LineChartImpl({
|
|
3578
3016
|
data = NO_ROWS3,
|
|
@@ -3581,7 +3019,7 @@ function LineChartImpl({
|
|
|
3581
3019
|
colors,
|
|
3582
3020
|
labels,
|
|
3583
3021
|
valueFormatter,
|
|
3584
|
-
format
|
|
3022
|
+
format,
|
|
3585
3023
|
title,
|
|
3586
3024
|
summary,
|
|
3587
3025
|
actions,
|
|
@@ -3620,14 +3058,18 @@ function LineChartImpl({
|
|
|
3620
3058
|
className,
|
|
3621
3059
|
...rest
|
|
3622
3060
|
}, ref) {
|
|
3623
|
-
const tokens =
|
|
3624
|
-
const
|
|
3625
|
-
const
|
|
3626
|
-
const
|
|
3627
|
-
const
|
|
3061
|
+
const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
|
|
3062
|
+
const locale = useLocale();
|
|
3063
|
+
const t = TEXT6[uiLanguage(locale)];
|
|
3064
|
+
const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
3065
|
+
const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
3066
|
+
const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
3628
3067
|
const comparisonCategory = comparison && categories.includes(comparison.category) ? comparison.category : void 0;
|
|
3629
3068
|
const comparisonConfig = comparisonCategory === void 0 ? void 0 : comparison;
|
|
3630
|
-
const series = useMemo(
|
|
3069
|
+
const series = useMemo(
|
|
3070
|
+
() => aggregateSeriesKeeping(data, categories, comparisonCategory, void 0, otherSeriesLabel(locale)),
|
|
3071
|
+
[data, categories, comparisonCategory, locale]
|
|
3072
|
+
);
|
|
3631
3073
|
const palette = useMemo(
|
|
3632
3074
|
() => resolveChartColors(
|
|
3633
3075
|
seriesColorsWithComparison(series.categories, colors, CHART_OTHER_COLOR, series.otherCategory, categories, comparisonCategory),
|
|
@@ -3675,7 +3117,7 @@ function LineChartImpl({
|
|
|
3675
3117
|
annotations,
|
|
3676
3118
|
forecast,
|
|
3677
3119
|
comparison: comparisonConfig,
|
|
3678
|
-
comparisonFormat:
|
|
3120
|
+
comparisonFormat: format,
|
|
3679
3121
|
provisionalFrom,
|
|
3680
3122
|
provisionalLabel,
|
|
3681
3123
|
reserveActions: Boolean(actions),
|
|
@@ -3684,7 +3126,8 @@ function LineChartImpl({
|
|
|
3684
3126
|
labelColor: tokens?.foreground ?? void 0,
|
|
3685
3127
|
plotWidth,
|
|
3686
3128
|
plotHeight: typeof height === "number" ? height : void 0,
|
|
3687
|
-
chartOptions
|
|
3129
|
+
chartOptions,
|
|
3130
|
+
locale
|
|
3688
3131
|
}),
|
|
3689
3132
|
[
|
|
3690
3133
|
series,
|
|
@@ -3721,23 +3164,24 @@ function LineChartImpl({
|
|
|
3721
3164
|
annotations,
|
|
3722
3165
|
forecast,
|
|
3723
3166
|
comparisonConfig,
|
|
3724
|
-
|
|
3167
|
+
format,
|
|
3725
3168
|
height,
|
|
3726
3169
|
tokens,
|
|
3727
3170
|
surface,
|
|
3728
3171
|
plotWidth,
|
|
3729
|
-
chartOptions
|
|
3172
|
+
chartOptions,
|
|
3173
|
+
locale
|
|
3730
3174
|
]
|
|
3731
3175
|
);
|
|
3732
3176
|
const dataTable = useMemo(() => {
|
|
3733
|
-
const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels,
|
|
3734
|
-
const times = timeTooltipLabels(series.data.map((row) => row[index]));
|
|
3177
|
+
const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, t.item);
|
|
3178
|
+
const times = timeTooltipLabels(series.data.map((row) => row[index]), locale);
|
|
3735
3179
|
return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
|
|
3736
|
-
}, [series, index, tooltipFormatter, labels]);
|
|
3737
|
-
const label2 = ariaLabel ??
|
|
3180
|
+
}, [series, index, tooltipFormatter, labels, t, locale]);
|
|
3181
|
+
const label2 = ariaLabel ?? t.chart(categories);
|
|
3738
3182
|
const resolvedSummary = useMemo(
|
|
3739
|
-
() => summary === "auto" ? buildChartSummary({ data, index, categories, title, format
|
|
3740
|
-
[summary, data, index, categories, title,
|
|
3183
|
+
() => summary === "auto" ? buildChartSummary({ data, index, categories, title, format, valueFormatter, locale }) : summary,
|
|
3184
|
+
[summary, data, index, categories, title, format, valueFormatter, locale]
|
|
3741
3185
|
);
|
|
3742
3186
|
return /* @__PURE__ */ jsx(
|
|
3743
3187
|
ChartFrame,
|
|
@@ -3758,8 +3202,12 @@ function LineChartImpl({
|
|
|
3758
3202
|
}
|
|
3759
3203
|
);
|
|
3760
3204
|
}
|
|
3761
|
-
var
|
|
3762
|
-
|
|
3205
|
+
var LineChart = forwardRef(LineChartImpl);
|
|
3206
|
+
LineChart.displayName = "LineChart";
|
|
3207
|
+
var TEXT7 = {
|
|
3208
|
+
ja: { item: "\u9805\u76EE", value: "\u5024", chart: (shares) => `\u69CB\u6210\u6BD4\u306E\u30C9\u30FC\u30CA\u30C4\u30B0\u30E9\u30D5\uFF08${shares.join("\u3001")}\uFF09` },
|
|
3209
|
+
en: { item: "Item", value: "Value", chart: (shares) => `Donut chart of shares (${shares.join(", ")})` }
|
|
3210
|
+
};
|
|
3763
3211
|
function useElementWidth() {
|
|
3764
3212
|
const [node, setNode] = useState(null);
|
|
3765
3213
|
const [width, setWidth] = useState(null);
|
|
@@ -3779,7 +3227,7 @@ function DonutChartImpl({
|
|
|
3779
3227
|
categories,
|
|
3780
3228
|
colors,
|
|
3781
3229
|
labels,
|
|
3782
|
-
format
|
|
3230
|
+
format,
|
|
3783
3231
|
valueFormatter: valueFormatterProp,
|
|
3784
3232
|
title,
|
|
3785
3233
|
summary,
|
|
@@ -3808,11 +3256,13 @@ function DonutChartImpl({
|
|
|
3808
3256
|
const center = resolveDonutCenter(donutOptions?.centerLabel, { showLabel: donutOptions?.showLabel ?? showLabel, label: label2 });
|
|
3809
3257
|
const maxSlices = donutOptions?.maxSlices;
|
|
3810
3258
|
const showLegend = donutOptions?.showLegend ?? true;
|
|
3811
|
-
const
|
|
3812
|
-
const
|
|
3259
|
+
const locale = useLocale();
|
|
3260
|
+
const t = TEXT7[uiLanguage(locale)];
|
|
3261
|
+
const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
|
|
3262
|
+
const { ref: frameRef, tokens } = useChartSurface(ref);
|
|
3813
3263
|
const slices = useMemo(
|
|
3814
|
-
() => donutSlices(data, { index: labelKey, value: valueKey, colors, maxSlices, otherColor: CHART_OTHER_COLOR }),
|
|
3815
|
-
[data, labelKey, valueKey, colors, maxSlices]
|
|
3264
|
+
() => donutSlices(data, { index: labelKey, value: valueKey, colors, maxSlices, otherColor: CHART_OTHER_COLOR, otherLabel: otherSeriesLabel(locale) }),
|
|
3265
|
+
[data, labelKey, valueKey, colors, maxSlices, locale]
|
|
3816
3266
|
);
|
|
3817
3267
|
const palette = useMemo(() => resolveChartColors(slices.map((s) => chartFillName(s.color)), tokens), [slices, tokens]);
|
|
3818
3268
|
const rows = useMemo(() => slices.map((s) => s.row), [slices]);
|
|
@@ -3849,13 +3299,13 @@ function DonutChartImpl({
|
|
|
3849
3299
|
let centerLabel = null;
|
|
3850
3300
|
if (center.kind === "custom") centerLabel = center.node;
|
|
3851
3301
|
else if (center.kind === "total") {
|
|
3852
|
-
const text = donutCenterText(total, valueFormatter, { totalLabel: donutOptions?.totalLabel, unit: donutOptions?.unit });
|
|
3302
|
+
const text = donutCenterText(total, valueFormatter, { totalLabel: donutOptions?.totalLabel, unit: donutOptions?.unit, locale });
|
|
3853
3303
|
centerLabel = caption(text.label, text.amount, text.unit);
|
|
3854
3304
|
} else if (center.kind === "top") {
|
|
3855
3305
|
const top = donutTopText(slices, labels);
|
|
3856
3306
|
centerLabel = top && caption(top.label, top.amount);
|
|
3857
3307
|
}
|
|
3858
|
-
const a11yLabel = ariaLabel ??
|
|
3308
|
+
const a11yLabel = ariaLabel ?? t.chart(legend.map((item) => `${labelOf(item.name, labels)} ${item.share}`));
|
|
3859
3309
|
const dataTable = useMemo(
|
|
3860
3310
|
() => chartDataTable(
|
|
3861
3311
|
// Fixed keys, so `labels` (which renames the rows) cannot collide with the column names.
|
|
@@ -3863,19 +3313,19 @@ function DonutChartImpl({
|
|
|
3863
3313
|
"name",
|
|
3864
3314
|
["value"],
|
|
3865
3315
|
valueFormatter,
|
|
3866
|
-
{ name: labels?.[labelKey] ??
|
|
3316
|
+
{ name: labels?.[labelKey] ?? t.item, value: labels?.[valueKey] ?? t.value }
|
|
3867
3317
|
),
|
|
3868
|
-
[rows, labelKey, valueKey, valueFormatter, labels]
|
|
3318
|
+
[rows, labelKey, valueKey, valueFormatter, labels, t]
|
|
3869
3319
|
);
|
|
3870
3320
|
const resolvedSummary = useMemo(
|
|
3871
|
-
() => summary === "auto" ? buildShareSummary(slices, title) : summary,
|
|
3872
|
-
[summary, slices, title]
|
|
3321
|
+
() => summary === "auto" ? buildShareSummary(slices, title, locale) : summary,
|
|
3322
|
+
[summary, slices, title, locale]
|
|
3873
3323
|
);
|
|
3874
3324
|
return /* @__PURE__ */ jsx(
|
|
3875
3325
|
ChartFrame,
|
|
3876
3326
|
{
|
|
3877
3327
|
...chartRootProps(rest),
|
|
3878
|
-
ref,
|
|
3328
|
+
ref: frameRef,
|
|
3879
3329
|
title,
|
|
3880
3330
|
summary: resolvedSummary,
|
|
3881
3331
|
isLoading: isLoading ?? loading ?? false,
|
|
@@ -3924,6 +3374,10 @@ function DonutChartImpl({
|
|
|
3924
3374
|
}
|
|
3925
3375
|
var DonutChart = forwardRef(DonutChartImpl);
|
|
3926
3376
|
DonutChart.displayName = "DonutChart";
|
|
3377
|
+
var TEXT8 = {
|
|
3378
|
+
ja: { item: "\u9805\u76EE", value: "\u5024" },
|
|
3379
|
+
en: { item: "Item", value: "Value" }
|
|
3380
|
+
};
|
|
3927
3381
|
var listHeight = (n) => n * 32 + Math.max(0, n - 1) * 6;
|
|
3928
3382
|
var isExternal = (href) => /^https?:\/\//.test(href);
|
|
3929
3383
|
var NO_ROWS5 = [];
|
|
@@ -3935,7 +3389,7 @@ function BarListImpl({
|
|
|
3935
3389
|
labels,
|
|
3936
3390
|
thresholds,
|
|
3937
3391
|
highlight,
|
|
3938
|
-
format
|
|
3392
|
+
format,
|
|
3939
3393
|
valueFormatter,
|
|
3940
3394
|
formatValue: formatValue2,
|
|
3941
3395
|
title,
|
|
@@ -3957,16 +3411,18 @@ function BarListImpl({
|
|
|
3957
3411
|
const frame = requestAnimationFrame(() => setMounted(true));
|
|
3958
3412
|
return () => cancelAnimationFrame(frame);
|
|
3959
3413
|
}, [showAnimation]);
|
|
3414
|
+
const locale = useLocale();
|
|
3415
|
+
const t = TEXT8[uiLanguage(locale)];
|
|
3960
3416
|
const maxItems = barListOptions?.maxItems ?? MAX_CHART_SERIES;
|
|
3961
3417
|
const token = Array.isArray(colors) ? colors[0] : colors;
|
|
3962
3418
|
const barColor = token ?? color ?? "chart-1";
|
|
3963
|
-
const formatter = resolveValueFormatter(valueFormatter ?? formatValue2,
|
|
3419
|
+
const formatter = resolveValueFormatter(valueFormatter ?? formatValue2, format, locale);
|
|
3964
3420
|
const baseRows = barListRows(data, {
|
|
3965
3421
|
index,
|
|
3966
3422
|
category: categories?.[0],
|
|
3967
3423
|
sortOrder: barListOptions?.sortOrder ?? sortOrder ?? "descending",
|
|
3968
3424
|
maxItems,
|
|
3969
|
-
otherLabel: barListOptions?.otherLabel,
|
|
3425
|
+
otherLabel: barListOptions?.otherLabel ?? otherSeriesLabel(locale),
|
|
3970
3426
|
exclude: barListOptions?.exclude
|
|
3971
3427
|
});
|
|
3972
3428
|
const rows = baseRows.map((row) => {
|
|
@@ -3985,7 +3441,7 @@ function BarListImpl({
|
|
|
3985
3441
|
"name",
|
|
3986
3442
|
["value"],
|
|
3987
3443
|
formatter,
|
|
3988
|
-
{ name: index && labels?.[index] ||
|
|
3444
|
+
{ name: index && labels?.[index] || t.item, value: categories?.[0] && labels?.[categories[0]] || t.value }
|
|
3989
3445
|
);
|
|
3990
3446
|
const list = /* @__PURE__ */ jsxs("div", { "data-slot": "bar-list", className: "flex justify-between gap-6 text-sm", ...props, children: [
|
|
3991
3447
|
/* @__PURE__ */ jsx("div", { className: "relative min-w-0 flex-1 space-y-1.5", children: rows.map((row, i) => {
|
|
@@ -4059,9 +3515,10 @@ function BarListImpl({
|
|
|
4059
3515
|
var BarList = forwardRef(BarListImpl);
|
|
4060
3516
|
BarList.displayName = "BarList";
|
|
4061
3517
|
var NO_ROWS6 = [];
|
|
4062
|
-
var CategoryBar = forwardRef(function CategoryBar2({ values = NO_ROWS6, colors, marker, showLabels = true, format
|
|
3518
|
+
var CategoryBar = forwardRef(function CategoryBar2({ values = NO_ROWS6, colors, marker, showLabels = true, format, valueFormatter: valueFormatterProp, className, ...props }, forwardedRef) {
|
|
4063
3519
|
const { ref, width } = useChartSurface(forwardedRef, null);
|
|
4064
|
-
const
|
|
3520
|
+
const locale = useLocale();
|
|
3521
|
+
const valueFormatter = useMemo(() => resolveAxisFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
|
|
4065
3522
|
const segments = categoryBarSegments(values);
|
|
4066
3523
|
const markerPosition = marker ? categoryBarMarkerPosition(marker.value, values) : 0;
|
|
4067
3524
|
const allLabels = showLabels ? categoryBarLabels(values, void 0, marker ? markerPosition : void 0) : [];
|
|
@@ -4191,8 +3648,14 @@ function blockColorToCss(color) {
|
|
|
4191
3648
|
}
|
|
4192
3649
|
var NO_ROWS7 = [];
|
|
4193
3650
|
var Tracker = forwardRef(function Tracker2({ data = NO_ROWS7, defaultColor, hoverEffect = true, className, ...props }, ref) {
|
|
3651
|
+
const containerRef = useRef(null);
|
|
3652
|
+
const setRef = useCallback((node) => {
|
|
3653
|
+
containerRef.current = node;
|
|
3654
|
+
if (typeof ref === "function") return ref(node);
|
|
3655
|
+
if (ref) ref.current = node;
|
|
3656
|
+
}, [ref]);
|
|
4194
3657
|
const fallback = defaultColor ? blockColorToCss(defaultColor) : DEFAULT_BLOCK_COLOR;
|
|
4195
|
-
return /* @__PURE__ */ jsx("div", { ref, "data-slot": "tracker", className: cn("flex h-6 w-full gap-0.5", className), ...props, children: data.map((block, i) => {
|
|
3658
|
+
return /* @__PURE__ */ jsx("div", { ref: setRef, "data-slot": "tracker", className: cn("flex h-6 w-full gap-0.5", className), ...props, children: data.map((block, i) => {
|
|
4196
3659
|
const blockClass = cn(
|
|
4197
3660
|
"h-full min-w-0 flex-1 rounded-[2px]",
|
|
4198
3661
|
hoverEffect && "transition-opacity hover:opacity-60 motion-reduce:transition-none"
|
|
@@ -4206,12 +3669,51 @@ var Tracker = forwardRef(function Tracker2({ data = NO_ROWS7, defaultColor, hove
|
|
|
4206
3669
|
render: /* @__PURE__ */ jsx("div", { "data-slot": "tracker-block", role: "img", tabIndex: 0, "aria-label": block.tooltip, className: blockClass, style })
|
|
4207
3670
|
}
|
|
4208
3671
|
),
|
|
4209
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: block.tooltip })
|
|
3672
|
+
/* @__PURE__ */ jsx(TooltipContent, { container: containerRef, children: block.tooltip })
|
|
4210
3673
|
] }, block.key ?? i) : /* @__PURE__ */ jsx("div", { "data-slot": "tracker-block", className: blockClass, style }, block.key ?? i);
|
|
4211
3674
|
}) });
|
|
4212
3675
|
});
|
|
4213
3676
|
Tracker.displayName = "Tracker";
|
|
4214
3677
|
use([GraphicComponent]);
|
|
3678
|
+
var TEXT9 = {
|
|
3679
|
+
ja: {
|
|
3680
|
+
net: "\u7D14\u5897",
|
|
3681
|
+
total: "\u5408\u8A08",
|
|
3682
|
+
change: "\u5897\u6E1B",
|
|
3683
|
+
cumulative: "\u7D2F\u8A08",
|
|
3684
|
+
cumulativeChange: "\u7D2F\u8A08\u5897\u6E1B",
|
|
3685
|
+
item: "\u9805\u76EE",
|
|
3686
|
+
start: "\u958B\u59CB",
|
|
3687
|
+
end: "\u7D42\u4E86",
|
|
3688
|
+
fromTo: (from, to, net) => `${from} \u2192 ${to}\uFF08${net}\uFF09`,
|
|
3689
|
+
from: (from, net) => `${from} \u304B\u3089 ${net}`,
|
|
3690
|
+
to: (to, net) => `${to}\uFF08${net}\uFF09`,
|
|
3691
|
+
netOnly: (net) => `\u5897\u6E1B\u306E\u5408\u8A08 ${net}`,
|
|
3692
|
+
increase: (name, value) => `\u6700\u5927\u306E\u5897\u52A0\u306F ${name}\uFF08${value}\uFF09`,
|
|
3693
|
+
decrease: (name, value) => `\u6700\u5927\u306E\u6E1B\u5C11\u306F ${name}\uFF08${value}\uFF09`,
|
|
3694
|
+
sentenceJoin: "\u3002",
|
|
3695
|
+
chart: (label2) => `${label2}\u306E\u30A6\u30A9\u30FC\u30BF\u30FC\u30D5\u30A9\u30FC\u30EB\u30C1\u30E3\u30FC\u30C8`
|
|
3696
|
+
},
|
|
3697
|
+
en: {
|
|
3698
|
+
net: "Net change",
|
|
3699
|
+
total: "Total",
|
|
3700
|
+
change: "Change",
|
|
3701
|
+
cumulative: "Cumulative",
|
|
3702
|
+
cumulativeChange: "Cumulative change",
|
|
3703
|
+
item: "Item",
|
|
3704
|
+
start: "Start",
|
|
3705
|
+
end: "End",
|
|
3706
|
+
fromTo: (from, to, net) => `${from} \u2192 ${to} (${net})`,
|
|
3707
|
+
from: (from, net) => `${net} from ${from}`,
|
|
3708
|
+
to: (to, net) => `${to} (${net})`,
|
|
3709
|
+
netOnly: (net) => `Net change ${net}`,
|
|
3710
|
+
increase: (name, value) => `Largest increase: ${name} (${value})`,
|
|
3711
|
+
decrease: (name, value) => `Largest decrease: ${name} (${value})`,
|
|
3712
|
+
sentenceJoin: ". ",
|
|
3713
|
+
chart: (label2) => `Waterfall chart of ${label2}`
|
|
3714
|
+
}
|
|
3715
|
+
};
|
|
3716
|
+
var textOf = (locale) => TEXT9[uiLanguage(resolveLocale(locale))];
|
|
4215
3717
|
function waterfallSteps(data, config) {
|
|
4216
3718
|
const totals = new Set(config.totals ?? []);
|
|
4217
3719
|
const delta = config.mode === "delta";
|
|
@@ -4230,11 +3732,13 @@ function waterfallSteps(data, config) {
|
|
|
4230
3732
|
return { name, kind: n > 0 ? "increase" : n < 0 ? "decrease" : "flat", value: n, start, end: running, row };
|
|
4231
3733
|
});
|
|
4232
3734
|
if (delta && steps.some((s) => s.kind !== "gap")) {
|
|
4233
|
-
steps.push({ name:
|
|
3735
|
+
steps.push({ name: deltaTotalName(config.locale), kind: "total", value: running, start: 0, end: running, row: {} });
|
|
4234
3736
|
}
|
|
4235
3737
|
return steps;
|
|
4236
3738
|
}
|
|
4237
|
-
|
|
3739
|
+
function deltaTotalName(locale) {
|
|
3740
|
+
return textOf(locale).net;
|
|
3741
|
+
}
|
|
4238
3742
|
function waterfallDeltaEnds(data, config) {
|
|
4239
3743
|
const totals = new Set(config.totals ?? []);
|
|
4240
3744
|
const kinds = data.map((row) => totals.has(String(row[config.index] ?? "")));
|
|
@@ -4250,16 +3754,17 @@ function waterfallDeltaEnds(data, config) {
|
|
|
4250
3754
|
const closing = closingRow && closingRow.value === null && opening?.value != null ? { ...closingRow, value: opening.value + net } : closingRow;
|
|
4251
3755
|
return { opening, closing, net };
|
|
4252
3756
|
}
|
|
4253
|
-
function waterfallDeltaNote(ends, formatter, labels) {
|
|
3757
|
+
function waterfallDeltaNote(ends, formatter, labels, locale) {
|
|
3758
|
+
const t = textOf(locale);
|
|
4254
3759
|
const net = signedText(ends.net, formatter);
|
|
4255
3760
|
const { opening, closing } = ends;
|
|
4256
3761
|
const side = (e) => e && e.value !== null ? `${labelOf(e.name, labels)} ${formatter(e.value)}` : null;
|
|
4257
3762
|
const from = side(opening);
|
|
4258
3763
|
const to = side(closing);
|
|
4259
|
-
if (from && to) return
|
|
4260
|
-
if (from) return
|
|
4261
|
-
if (to) return
|
|
4262
|
-
return
|
|
3764
|
+
if (from && to) return t.fromTo(from, to, net);
|
|
3765
|
+
if (from) return t.from(from, net);
|
|
3766
|
+
if (to) return t.to(to, net);
|
|
3767
|
+
return t.netOnly(net);
|
|
4263
3768
|
}
|
|
4264
3769
|
function waterfallStack(steps) {
|
|
4265
3770
|
const base = [];
|
|
@@ -4311,7 +3816,8 @@ function waterfallStepText(step, formatter, delta = false) {
|
|
|
4311
3816
|
if (step.value === null) return EMPTY_VALUE;
|
|
4312
3817
|
return step.kind === "total" && !delta ? formatter(step.value) : signedText(step.value, formatter);
|
|
4313
3818
|
}
|
|
4314
|
-
function buildWaterfallSummary(steps, formatter, title, labels, delta) {
|
|
3819
|
+
function buildWaterfallSummary(steps, formatter, title, labels, delta, locale) {
|
|
3820
|
+
const t = textOf(locale);
|
|
4315
3821
|
const real = steps.filter((s) => s.kind !== "gap");
|
|
4316
3822
|
const first = real[0];
|
|
4317
3823
|
const last = real[real.length - 1];
|
|
@@ -4319,7 +3825,7 @@ function buildWaterfallSummary(steps, formatter, title, labels, delta) {
|
|
|
4319
3825
|
const name = (s) => labelOf(s.name, labels);
|
|
4320
3826
|
const head = title ? `${title}: ` : "";
|
|
4321
3827
|
const parts = [
|
|
4322
|
-
delta ? waterfallDeltaNote(delta, formatter, labels) : real.length === 1 ? `${name(first)} ${formatter(first.end)}` : `${name(first)} ${formatter(first.end)} \u2192 ${name(last)} ${formatter(last.end)}`
|
|
3828
|
+
delta ? waterfallDeltaNote(delta, formatter, labels, locale) : real.length === 1 ? `${name(first)} ${formatter(first.end)}` : `${name(first)} ${formatter(first.end)} \u2192 ${name(last)} ${formatter(last.end)}`
|
|
4323
3829
|
];
|
|
4324
3830
|
let up;
|
|
4325
3831
|
let down;
|
|
@@ -4327,21 +3833,22 @@ function buildWaterfallSummary(steps, formatter, title, labels, delta) {
|
|
|
4327
3833
|
if (s.kind === "increase" && (!up || s.value > up.value)) up = s;
|
|
4328
3834
|
if (s.kind === "decrease" && (!down || s.value < down.value)) down = s;
|
|
4329
3835
|
}
|
|
4330
|
-
if (up) parts.push(
|
|
4331
|
-
if (down) parts.push(
|
|
4332
|
-
return `${head}${parts.join(
|
|
3836
|
+
if (up) parts.push(t.increase(name(up), signedText(up.value, formatter)));
|
|
3837
|
+
if (down) parts.push(t.decrease(name(down), signedText(down.value, formatter)));
|
|
3838
|
+
return `${head}${parts.join(t.sentenceJoin)}`;
|
|
4333
3839
|
}
|
|
4334
|
-
function waterfallDataTable(steps, names, formatter, labels, delta) {
|
|
3840
|
+
function waterfallDataTable(steps, names, formatter, labels, delta, locale) {
|
|
3841
|
+
const t = textOf(locale);
|
|
4335
3842
|
const label2 = (key) => labelOf(key, labels);
|
|
4336
3843
|
const rows = steps.map((s) => [
|
|
4337
3844
|
label2(s.name),
|
|
4338
|
-
s.kind === "total" ? delta ?
|
|
3845
|
+
s.kind === "total" ? delta ? t.net : t.total : s.value === null ? EMPTY_VALUE : signedText(s.value, formatter),
|
|
4339
3846
|
s.kind === "gap" ? EMPTY_VALUE : delta ? signedText(s.end, formatter) : formatter(s.end)
|
|
4340
3847
|
]);
|
|
4341
3848
|
const end = (e, role) => e && e.value !== null ? [[label2(e.name), role, formatter(e.value)]] : [];
|
|
4342
3849
|
return {
|
|
4343
|
-
columns: [labels?.[names.index] ??
|
|
4344
|
-
rows: delta ? [...end(delta.opening,
|
|
3850
|
+
columns: [labels?.[names.index] ?? t.item, t.change, delta ? t.cumulativeChange : t.cumulative],
|
|
3851
|
+
rows: delta ? [...end(delta.opening, t.start), ...rows, ...end(delta.closing, t.end)] : rows
|
|
4345
3852
|
};
|
|
4346
3853
|
}
|
|
4347
3854
|
var WATERFALL_BAR_SHARE = 0.45;
|
|
@@ -4423,6 +3930,7 @@ function waterfallConnectorRenderer(color) {
|
|
|
4423
3930
|
var ROW_STYLE = "display:flex;align-items:center;gap:8px;line-height:20px";
|
|
4424
3931
|
function buildWaterfallOption(config) {
|
|
4425
3932
|
const { steps, colors, polarity, labels, valueFormatter, showValues = true, showTooltip = true } = config;
|
|
3933
|
+
const t = textOf(config.locale);
|
|
4426
3934
|
const delta = config.mode === "delta";
|
|
4427
3935
|
const axisFormatter = config.axisFormatter ?? valueFormatter;
|
|
4428
3936
|
const noteWidth = config.plotWidth ? Math.max(120, config.plotWidth - 16) : void 0;
|
|
@@ -4493,7 +4001,7 @@ function buildWaterfallOption(config) {
|
|
|
4493
4001
|
if (!step) return "";
|
|
4494
4002
|
const color = escapeHtml(colorOf(step) ?? "currentColor");
|
|
4495
4003
|
const line = (name, text) => `<div style="${ROW_STYLE}"><span style="display:inline-block;width:8px;height:8px;border-radius:9999px;background:${color}"></span><span style="flex:1;opacity:.8">${escapeHtml(name)}</span><span style="font-weight:500;font-variant-numeric:tabular-nums;margin-left:12px">${escapeHtml(text)}</span></div>`;
|
|
4496
|
-
const rows = step.kind === "total" ? line(delta ?
|
|
4004
|
+
const rows = step.kind === "total" ? line(delta ? t.net : t.total, delta ? signedText(step.end, valueFormatter) : valueFormatter(step.end)) : line(t.change, waterfallStepText(step, valueFormatter)) + (step.kind === "gap" ? "" : delta ? line(t.cumulativeChange, signedText(step.end, valueFormatter)) : line(t.cumulative, valueFormatter(step.end)));
|
|
4497
4005
|
return `<div style="font-weight:500;margin-bottom:4px">${escapeHtml(labelOf(step.name, labels))}</div>${rows}`;
|
|
4498
4006
|
}
|
|
4499
4007
|
},
|
|
@@ -4563,7 +4071,7 @@ function WaterfallChartImpl({
|
|
|
4563
4071
|
mode = "total",
|
|
4564
4072
|
polarity = "higher-is-better",
|
|
4565
4073
|
labels,
|
|
4566
|
-
format
|
|
4074
|
+
format,
|
|
4567
4075
|
valueFormatter: valueFormatterProp,
|
|
4568
4076
|
showValues = true,
|
|
4569
4077
|
showTooltip = true,
|
|
@@ -4583,13 +4091,16 @@ function WaterfallChartImpl({
|
|
|
4583
4091
|
...rest
|
|
4584
4092
|
}, ref) {
|
|
4585
4093
|
const valueKey = categories[0] ?? "";
|
|
4586
|
-
const tokens =
|
|
4587
|
-
const
|
|
4588
|
-
const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp,
|
|
4589
|
-
const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatterProp,
|
|
4590
|
-
const steps = useMemo(
|
|
4094
|
+
const { ref: frameRef, width: plotWidth, tokens } = useChartSurface(ref);
|
|
4095
|
+
const locale = useLocale();
|
|
4096
|
+
const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
|
|
4097
|
+
const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
|
|
4098
|
+
const steps = useMemo(
|
|
4099
|
+
() => waterfallSteps(data, { index, value: valueKey, totals, mode, locale }),
|
|
4100
|
+
[data, index, valueKey, totals, mode, locale]
|
|
4101
|
+
);
|
|
4591
4102
|
const ends = useMemo(() => mode === "delta" ? waterfallDeltaEnds(data, { index, value: valueKey, totals }) : void 0, [data, index, valueKey, totals, mode]);
|
|
4592
|
-
const deltaNote = useMemo(() => ends ? waterfallDeltaNote(ends, valueFormatter, labels) : void 0, [ends, valueFormatter, labels]);
|
|
4103
|
+
const deltaNote = useMemo(() => ends ? waterfallDeltaNote(ends, valueFormatter, labels, locale) : void 0, [ends, valueFormatter, labels, locale]);
|
|
4593
4104
|
const colors = useMemo(() => {
|
|
4594
4105
|
const fills = resolveFillColors(tokens);
|
|
4595
4106
|
const [total = ""] = resolveChartColors(["chart-1"], tokens);
|
|
@@ -4619,19 +4130,21 @@ function WaterfallChartImpl({
|
|
|
4619
4130
|
chartOptions,
|
|
4620
4131
|
minValue,
|
|
4621
4132
|
maxValue,
|
|
4622
|
-
yAxisWidth
|
|
4133
|
+
yAxisWidth,
|
|
4134
|
+
locale
|
|
4623
4135
|
}),
|
|
4624
|
-
[steps, colors, polarity, labels, valueFormatter, axisFormatter, showValues, showTooltip, tokens, mode, deltaNote, plotWidth, chartOptions, minValue, maxValue, yAxisWidth]
|
|
4136
|
+
[steps, colors, polarity, labels, valueFormatter, axisFormatter, showValues, showTooltip, tokens, mode, deltaNote, plotWidth, chartOptions, minValue, maxValue, yAxisWidth, locale]
|
|
4625
4137
|
);
|
|
4626
4138
|
const dataTable = useMemo(
|
|
4627
|
-
() => waterfallDataTable(steps, { index}, valueFormatter, labels, ends),
|
|
4628
|
-
[steps, index, valueKey, valueFormatter, labels, ends]
|
|
4139
|
+
() => waterfallDataTable(steps, { index}, valueFormatter, labels, ends, locale),
|
|
4140
|
+
[steps, index, valueKey, valueFormatter, labels, ends, locale]
|
|
4629
4141
|
);
|
|
4630
4142
|
const resolvedSummary = useMemo(
|
|
4631
|
-
() => summary === "auto" ? buildWaterfallSummary(steps, valueFormatter, title, labels, ends) : summary,
|
|
4632
|
-
[summary, steps, valueFormatter, title, labels, ends]
|
|
4143
|
+
() => summary === "auto" ? buildWaterfallSummary(steps, valueFormatter, title, labels, ends, locale) : summary,
|
|
4144
|
+
[summary, steps, valueFormatter, title, labels, ends, locale]
|
|
4633
4145
|
);
|
|
4634
|
-
const
|
|
4146
|
+
const t = textOf(locale);
|
|
4147
|
+
const label2 = ariaLabel ?? t.chart(labelOf(valueKey, labels) || t.change.toLowerCase());
|
|
4635
4148
|
return /* @__PURE__ */ jsx(
|
|
4636
4149
|
ChartFrame,
|
|
4637
4150
|
{
|
|
@@ -4673,7 +4186,38 @@ function scatterPoints(data, config) {
|
|
|
4673
4186
|
}
|
|
4674
4187
|
return points;
|
|
4675
4188
|
}
|
|
4676
|
-
|
|
4189
|
+
var TEXT10 = {
|
|
4190
|
+
ja: {
|
|
4191
|
+
who: (name, value) => `${name}\uFF08${value}\uFF09`,
|
|
4192
|
+
summary: (count, y, who) => `${count}\u70B9\u3002${y}\u304C\u6700\u5927\u306A\u306E\u306F ${who}`,
|
|
4193
|
+
name: "\u540D\u524D",
|
|
4194
|
+
series: "\u7CFB\u5217",
|
|
4195
|
+
x: "\u6A2A\u8EF8",
|
|
4196
|
+
y: "\u7E26\u8EF8",
|
|
4197
|
+
size: "\u5927\u304D\u3055",
|
|
4198
|
+
pair: (y, x) => `${y}\xD7${x}`,
|
|
4199
|
+
first: (pair, count) => `${pair}\uFF08\u5148\u982D ${count} \u70B9\uFF09`,
|
|
4200
|
+
guide: (label2, axis, value) => `${label2}\uFF08${axis} ${value}\uFF09`,
|
|
4201
|
+
caption: (base, guides) => `${base}\u3002\u57FA\u6E96\u7DDA: ${guides.join("\u3001")}`,
|
|
4202
|
+
chart: (y, x) => `${y}\xD7${x}\u306E\u6563\u5E03\u56F3`
|
|
4203
|
+
},
|
|
4204
|
+
en: {
|
|
4205
|
+
who: (name, value) => `${name} (${value})`,
|
|
4206
|
+
summary: (count, y, who) => `${count === 1 ? "1 point" : `${count} points`}. Highest ${y}: ${who}`,
|
|
4207
|
+
name: "Name",
|
|
4208
|
+
series: "Series",
|
|
4209
|
+
x: "X",
|
|
4210
|
+
y: "Y",
|
|
4211
|
+
size: "Size",
|
|
4212
|
+
pair: (y, x) => `${y} \xD7 ${x}`,
|
|
4213
|
+
first: (pair, count) => `${pair} (first ${count} points)`,
|
|
4214
|
+
guide: (label2, axis, value) => `${label2} (${axis} ${value})`,
|
|
4215
|
+
caption: (base, guides) => `${base}. Reference lines: ${guides.join(", ")}`,
|
|
4216
|
+
chart: (y, x) => `Scatter plot of ${y} \xD7 ${x}`
|
|
4217
|
+
}
|
|
4218
|
+
};
|
|
4219
|
+
var textOf2 = (locale) => TEXT10[uiLanguage(resolveLocale(locale))];
|
|
4220
|
+
function scatterSeries(points, max = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
|
|
4677
4221
|
const order = [];
|
|
4678
4222
|
const counts = /* @__PURE__ */ new Map();
|
|
4679
4223
|
for (const p of points) {
|
|
@@ -4686,7 +4230,7 @@ function scatterSeries(points, max = MAX_CHART_SERIES) {
|
|
|
4686
4230
|
const ranked = order.map((name, at) => ({ name, at, n: counts.get(name) ?? 0 })).sort((a, b) => b.n - a.n || a.at - b.at);
|
|
4687
4231
|
const kept = new Set(ranked.slice(0, Math.max(1, max)).map((r) => r.name));
|
|
4688
4232
|
const result = order.filter((name) => kept.has(name)).map((name) => ({ name, isOther: false, points: points.filter((p) => p.series === name) }));
|
|
4689
|
-
result.push({ name:
|
|
4233
|
+
result.push({ name: otherLabel, isOther: true, points: points.filter((p) => !kept.has(p.series)) });
|
|
4690
4234
|
return result;
|
|
4691
4235
|
}
|
|
4692
4236
|
var SCATTER_FADED_OPACITY = 0.2;
|
|
@@ -4700,24 +4244,26 @@ function scatterBubbleSize(value, max) {
|
|
|
4700
4244
|
function pointTitle(point, labels) {
|
|
4701
4245
|
return labelOf(point.name || point.series, labels);
|
|
4702
4246
|
}
|
|
4703
|
-
function buildScatterSummary(points, yName, yFormatter, title, labels) {
|
|
4247
|
+
function buildScatterSummary(points, yName, yFormatter, title, labels, locale) {
|
|
4704
4248
|
if (points.length === 0) return void 0;
|
|
4249
|
+
const t = textOf2(locale);
|
|
4705
4250
|
let best = points[0];
|
|
4706
4251
|
for (const p of points) if (p.y > best.y) best = p;
|
|
4707
4252
|
const head = title ? `${title}: ` : "";
|
|
4708
|
-
const who = best.name ?
|
|
4709
|
-
return `${head}${points.length
|
|
4253
|
+
const who = best.name ? t.who(labelOf(best.name, labels), yFormatter(best.y)) : yFormatter(best.y);
|
|
4254
|
+
return `${head}${t.summary(points.length, labelOf(yName, labels), who)}`;
|
|
4710
4255
|
}
|
|
4711
4256
|
var SCATTER_TABLE_MAX_ROWS = 100;
|
|
4712
4257
|
function scatterDataTable(points, config) {
|
|
4258
|
+
const t = textOf2(config.locale);
|
|
4713
4259
|
const label2 = (key) => labelOf(key, config.labels);
|
|
4714
4260
|
const column = (key, fallback) => config.labels?.[key] ?? fallback;
|
|
4715
4261
|
const columns = [
|
|
4716
|
-
...config.index ? [column(config.index,
|
|
4717
|
-
...config.series ? [column(config.series,
|
|
4718
|
-
column(config.x,
|
|
4719
|
-
column(config.y,
|
|
4720
|
-
...config.size ? [column(config.size,
|
|
4262
|
+
...config.index ? [column(config.index, t.name)] : [],
|
|
4263
|
+
...config.series ? [column(config.series, t.series)] : [],
|
|
4264
|
+
column(config.x, t.x),
|
|
4265
|
+
column(config.y, t.y),
|
|
4266
|
+
...config.size ? [column(config.size, t.size)] : []
|
|
4721
4267
|
];
|
|
4722
4268
|
const shown = points.slice(0, SCATTER_TABLE_MAX_ROWS);
|
|
4723
4269
|
const rows = shown.map((p, i) => {
|
|
@@ -4730,14 +4276,15 @@ function scatterDataTable(points, config) {
|
|
|
4730
4276
|
];
|
|
4731
4277
|
return config.index ? cells : [String(i + 1), ...cells];
|
|
4732
4278
|
});
|
|
4733
|
-
const
|
|
4279
|
+
const pair = t.pair(label2(config.y), label2(config.x));
|
|
4280
|
+
const base = points.length > shown.length ? t.first(pair, shown.length) : pair;
|
|
4734
4281
|
const guides = (config.referenceLines ?? []).map((line) => {
|
|
4735
4282
|
const key = line.axis === "x" ? config.x : config.y;
|
|
4736
4283
|
const text = config.formatters[line.axis](line.value);
|
|
4737
|
-
return line.label ?
|
|
4284
|
+
return line.label ? t.guide(line.label, label2(key), text) : `${label2(key)} ${text}`;
|
|
4738
4285
|
});
|
|
4739
4286
|
return {
|
|
4740
|
-
caption: guides.length > 0 ?
|
|
4287
|
+
caption: guides.length > 0 ? t.caption(base, guides) : base,
|
|
4741
4288
|
columns: config.index ? columns : ["#", ...columns],
|
|
4742
4289
|
rows
|
|
4743
4290
|
};
|
|
@@ -4959,7 +4506,7 @@ function ScatterChartImpl({
|
|
|
4959
4506
|
referenceLines,
|
|
4960
4507
|
colors,
|
|
4961
4508
|
labels,
|
|
4962
|
-
format
|
|
4509
|
+
format,
|
|
4963
4510
|
xFormat,
|
|
4964
4511
|
yFormat,
|
|
4965
4512
|
sizeFormat,
|
|
@@ -4983,28 +4530,28 @@ function ScatterChartImpl({
|
|
|
4983
4530
|
className,
|
|
4984
4531
|
...rest
|
|
4985
4532
|
}, ref) {
|
|
4986
|
-
const tokens =
|
|
4987
|
-
const
|
|
4533
|
+
const { ref: frameRef, width: plotWidth, tokens } = useChartSurface(ref);
|
|
4534
|
+
const locale = useLocale();
|
|
4988
4535
|
const formatters = useMemo(
|
|
4989
4536
|
() => ({
|
|
4990
|
-
x: resolveValueFormatter(valueFormatter, xFormat ??
|
|
4991
|
-
y: resolveValueFormatter(valueFormatter, yFormat ??
|
|
4992
|
-
size: resolveValueFormatter(valueFormatter, sizeFormat ??
|
|
4537
|
+
x: resolveValueFormatter(valueFormatter, xFormat ?? format, locale),
|
|
4538
|
+
y: resolveValueFormatter(valueFormatter, yFormat ?? format, locale),
|
|
4539
|
+
size: resolveValueFormatter(valueFormatter, sizeFormat ?? format, locale)
|
|
4993
4540
|
}),
|
|
4994
|
-
[valueFormatter, xFormat, yFormat, sizeFormat,
|
|
4541
|
+
[valueFormatter, xFormat, yFormat, sizeFormat, format, locale]
|
|
4995
4542
|
);
|
|
4996
4543
|
const axisFormatters = useMemo(
|
|
4997
4544
|
() => ({
|
|
4998
|
-
x: resolveAxisFormatter(valueFormatter, xFormat ??
|
|
4999
|
-
y: resolveAxisFormatter(valueFormatter, yFormat ??
|
|
4545
|
+
x: resolveAxisFormatter(valueFormatter, xFormat ?? format, locale),
|
|
4546
|
+
y: resolveAxisFormatter(valueFormatter, yFormat ?? format, locale)
|
|
5000
4547
|
}),
|
|
5001
|
-
[valueFormatter, xFormat, yFormat,
|
|
4548
|
+
[valueFormatter, xFormat, yFormat, format, locale]
|
|
5002
4549
|
);
|
|
5003
4550
|
const points = useMemo(
|
|
5004
4551
|
() => scatterPoints(data, { x, y, size, index, series: seriesKey, labelKey }),
|
|
5005
4552
|
[data, x, y, size, index, seriesKey, labelKey]
|
|
5006
4553
|
);
|
|
5007
|
-
const series = useMemo(() => scatterSeries(points), [points]);
|
|
4554
|
+
const series = useMemo(() => scatterSeries(points, void 0, otherSeriesLabel(locale)), [points, locale]);
|
|
5008
4555
|
const palette = useMemo(
|
|
5009
4556
|
() => resolveChartColors(scatterSeriesColors(series, colors).map(chartFillName), tokens),
|
|
5010
4557
|
[series, colors, tokens]
|
|
@@ -5040,14 +4587,14 @@ function ScatterChartImpl({
|
|
|
5040
4587
|
[series, palette, x, y, size, seriesKey, seriesLabel, highlightList, referenceLines, labelKey, tokens, labels, formatters, axisFormatters, fitToData, showLegend, showTooltip, actions, plotWidth, chartOptions, minValue, maxValue, xMinValue, xMaxValue]
|
|
5041
4588
|
);
|
|
5042
4589
|
const dataTable = useMemo(
|
|
5043
|
-
() => scatterDataTable(points, { x, y, size, index: index ?? labelKey, series: seriesKey, formatters, labels, referenceLines }),
|
|
5044
|
-
[points, x, y, size, index, labelKey, seriesKey, formatters, labels, referenceLines]
|
|
4590
|
+
() => scatterDataTable(points, { x, y, size, index: index ?? labelKey, series: seriesKey, formatters, labels, referenceLines, locale }),
|
|
4591
|
+
[points, x, y, size, index, labelKey, seriesKey, formatters, labels, referenceLines, locale]
|
|
5045
4592
|
);
|
|
5046
4593
|
const resolvedSummary = useMemo(
|
|
5047
|
-
() => summary === "auto" ? buildScatterSummary(points, y, formatters.y, title, labels) : summary,
|
|
5048
|
-
[summary, points, y, formatters, title, labels]
|
|
4594
|
+
() => summary === "auto" ? buildScatterSummary(points, y, formatters.y, title, labels, locale) : summary,
|
|
4595
|
+
[summary, points, y, formatters, title, labels, locale]
|
|
5049
4596
|
);
|
|
5050
|
-
const label2 = ariaLabel ??
|
|
4597
|
+
const label2 = ariaLabel ?? textOf2(locale).chart(labelOf(y, labels), labelOf(x, labels));
|
|
5051
4598
|
return /* @__PURE__ */ jsx(
|
|
5052
4599
|
ChartFrame,
|
|
5053
4600
|
{
|
|
@@ -5072,7 +4619,12 @@ ScatterChart.displayName = "ScatterChart";
|
|
|
5072
4619
|
function legendColors(categories, colors) {
|
|
5073
4620
|
return seriesColorsFor(categories, colors, CHART_OTHER_COLOR).map((color) => chartFillToCss(color));
|
|
5074
4621
|
}
|
|
5075
|
-
var
|
|
4622
|
+
var TEXT11 = {
|
|
4623
|
+
ja: { legend: "\u51E1\u4F8B" },
|
|
4624
|
+
en: { legend: "Legend" }
|
|
4625
|
+
};
|
|
4626
|
+
var Legend = forwardRef(function Legend2({ categories, colors, labels, layout = "horizontal", ariaLabel, className }, ref) {
|
|
4627
|
+
const t = TEXT11[uiLanguage(useLocale())];
|
|
5076
4628
|
if (categories.length === 0) return null;
|
|
5077
4629
|
const swatches = legendColors(categories, colors);
|
|
5078
4630
|
return /* @__PURE__ */ jsx(
|
|
@@ -5081,7 +4633,7 @@ var Legend = forwardRef(function Legend2({ categories, colors, labels, layout =
|
|
|
5081
4633
|
ref,
|
|
5082
4634
|
"data-slot": "legend",
|
|
5083
4635
|
"data-layout": layout,
|
|
5084
|
-
"aria-label": ariaLabel,
|
|
4636
|
+
"aria-label": ariaLabel ?? t.legend,
|
|
5085
4637
|
className: cn("m-0 flex list-none gap-x-4 gap-y-1 p-0 text-xs", layout === "vertical" ? "flex-col" : "flex-row flex-wrap", className),
|
|
5086
4638
|
children: categories.map((category, i) => /* @__PURE__ */ jsxs("li", { "data-slot": "legend-item", className: "flex min-w-0 items-center gap-1.5", children: [
|
|
5087
4639
|
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "size-2.5 shrink-0 rounded-[2px]", style: { background: swatches[i] } }),
|
|
@@ -5179,9 +4731,27 @@ var funnelConversionVariants = cva("flex items-center text-muted-foreground", {
|
|
|
5179
4731
|
direction: "vertical"
|
|
5180
4732
|
}
|
|
5181
4733
|
});
|
|
5182
|
-
function resolveFunnelFormatter(valueFormatter, formatValue2,
|
|
5183
|
-
return resolveValueFormatter(valueFormatter ?? formatValue2,
|
|
4734
|
+
function resolveFunnelFormatter(valueFormatter, formatValue2, format, locale) {
|
|
4735
|
+
return resolveValueFormatter(valueFormatter ?? formatValue2, format, locale);
|
|
5184
4736
|
}
|
|
4737
|
+
var TEXT12 = {
|
|
4738
|
+
ja: {
|
|
4739
|
+
step: "\u30B9\u30C6\u30C3\u30D7",
|
|
4740
|
+
value: "\u5024",
|
|
4741
|
+
previous: "\u524D\u671F",
|
|
4742
|
+
previousHeader: "\u524D\u671F",
|
|
4743
|
+
change: (label2, points) => `(${label2}\u6BD4 ${points})`,
|
|
4744
|
+
funnel: "\u30D5\u30A1\u30CD\u30EB"
|
|
4745
|
+
},
|
|
4746
|
+
en: {
|
|
4747
|
+
step: "Step",
|
|
4748
|
+
value: "Value",
|
|
4749
|
+
previous: "prior period",
|
|
4750
|
+
previousHeader: "Prior period",
|
|
4751
|
+
change: (label2, points) => `(vs. ${label2} ${points})`,
|
|
4752
|
+
funnel: "Funnel"
|
|
4753
|
+
}
|
|
4754
|
+
};
|
|
5185
4755
|
function lowestConversionStep(values) {
|
|
5186
4756
|
if (values.length < 3) return -1;
|
|
5187
4757
|
let lowest = -1;
|
|
@@ -5263,7 +4833,9 @@ function FunnelStepsImpl({
|
|
|
5263
4833
|
}, ref) {
|
|
5264
4834
|
const [mounted, setMounted] = useState(false);
|
|
5265
4835
|
const isHorizontal = direction === "horizontal";
|
|
5266
|
-
const
|
|
4836
|
+
const locale = useLocale();
|
|
4837
|
+
const t = TEXT12[uiLanguage(locale)];
|
|
4838
|
+
const format = resolveFunnelFormatter(valueFormatter, formatValue2, valueFormat, locale);
|
|
5267
4839
|
useEffect(() => {
|
|
5268
4840
|
if (animate) setMounted(true);
|
|
5269
4841
|
}, [animate]);
|
|
@@ -5275,15 +4847,19 @@ function FunnelStepsImpl({
|
|
|
5275
4847
|
const maxValue = steps.length > 0 ? steps[0].value : 0;
|
|
5276
4848
|
const values = steps.map((s) => s.value);
|
|
5277
4849
|
const previous = comparison?.values;
|
|
5278
|
-
const comparisonLabel2 = comparison?.label ??
|
|
4850
|
+
const comparisonLabel2 = comparison?.label ?? t.previous;
|
|
5279
4851
|
const showRates = showConversion || previous !== void 0;
|
|
5280
4852
|
const focus = !showRates ? -1 : previous ? worstChangeStep(values, previous) : lowestConversionStep(values);
|
|
5281
4853
|
const dataTable = chartDataTable(
|
|
5282
4854
|
steps.map((step, i) => ({ label: step.label, value: step.value, previous: previous?.[i] ?? null })),
|
|
5283
4855
|
"label",
|
|
5284
4856
|
previous ? ["value", "previous"] : ["value"],
|
|
5285
|
-
|
|
5286
|
-
{
|
|
4857
|
+
format,
|
|
4858
|
+
{
|
|
4859
|
+
label: labels?.[index] ?? t.step,
|
|
4860
|
+
value: categories?.[0] && labels?.[categories[0]] || t.value,
|
|
4861
|
+
previous: comparison?.label ?? t.previousHeader
|
|
4862
|
+
}
|
|
5287
4863
|
);
|
|
5288
4864
|
const list = /* @__PURE__ */ jsx("div", { "data-slot": "funnel-steps", role: "list", className: funnelStepsVariants({ size, direction }), ...props, children: steps.map((step, index2) => {
|
|
5289
4865
|
const percentage = maxValue > 0 ? step.value / maxValue * 100 : 0;
|
|
@@ -5309,7 +4885,7 @@ function FunnelStepsImpl({
|
|
|
5309
4885
|
{
|
|
5310
4886
|
role: "listitem",
|
|
5311
4887
|
className: "flex min-w-0 flex-1 flex-col items-center gap-1",
|
|
5312
|
-
"aria-label": `${step.label}: ${
|
|
4888
|
+
"aria-label": `${step.label}: ${format(step.value)}`,
|
|
5313
4889
|
children: [
|
|
5314
4890
|
/* @__PURE__ */ jsx(
|
|
5315
4891
|
"span",
|
|
@@ -5319,7 +4895,7 @@ function FunnelStepsImpl({
|
|
|
5319
4895
|
"text-muted-foreground tabular-nums",
|
|
5320
4896
|
size === "sm" ? "text-xs" : "text-sm"
|
|
5321
4897
|
),
|
|
5322
|
-
children:
|
|
4898
|
+
children: format(step.value)
|
|
5323
4899
|
}
|
|
5324
4900
|
),
|
|
5325
4901
|
/* @__PURE__ */ jsx("div", { className: funnelBarContainerHorizontalVariants({ size }), children: /* @__PURE__ */ jsx(
|
|
@@ -5351,10 +4927,10 @@ function FunnelStepsImpl({
|
|
|
5351
4927
|
)
|
|
5352
4928
|
]
|
|
5353
4929
|
}
|
|
5354
|
-
) : /* @__PURE__ */ jsxs("div", { role: "listitem", "aria-label": `${step.label}: ${
|
|
4930
|
+
) : /* @__PURE__ */ jsxs("div", { role: "listitem", "aria-label": `${step.label}: ${format(step.value)}`, children: [
|
|
5355
4931
|
/* @__PURE__ */ jsxs("div", { className: funnelLabelVariants({ size }), children: [
|
|
5356
4932
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: step.label }),
|
|
5357
|
-
/* @__PURE__ */ jsx("span", { "data-slot": "funnel-value", className: "tabular-nums", children:
|
|
4933
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "funnel-value", className: "tabular-nums", children: format(step.value) })
|
|
5358
4934
|
] }),
|
|
5359
4935
|
/* @__PURE__ */ jsx("div", { className: "relative w-full overflow-hidden rounded-sm bg-muted", children: /* @__PURE__ */ jsx(
|
|
5360
4936
|
"div",
|
|
@@ -5378,13 +4954,7 @@ function FunnelStepsImpl({
|
|
|
5378
4954
|
children: [
|
|
5379
4955
|
"\u2192 ",
|
|
5380
4956
|
computeConversionRate(steps[index2 + 1].value, step.value),
|
|
5381
|
-
previous && /* @__PURE__ */
|
|
5382
|
-
"(",
|
|
5383
|
-
comparisonLabel2,
|
|
5384
|
-
"\u6BD4 ",
|
|
5385
|
-
formatPoints(conversionChange(values, previous, index2 + 1)),
|
|
5386
|
-
")"
|
|
5387
|
-
] })
|
|
4957
|
+
previous && /* @__PURE__ */ jsx("span", { "data-slot": "funnel-change", className: "ml-1 tabular-nums", children: t.change(comparisonLabel2, formatPoints(conversionChange(values, previous, index2 + 1), locale)) })
|
|
5388
4958
|
]
|
|
5389
4959
|
}
|
|
5390
4960
|
) })
|
|
@@ -5401,7 +4971,7 @@ function FunnelStepsImpl({
|
|
|
5401
4971
|
emptyState,
|
|
5402
4972
|
height: ready ? "auto" : FRAME_HEIGHT[size ?? "md"],
|
|
5403
4973
|
variant: "list",
|
|
5404
|
-
ariaLabel: ariaLabel ??
|
|
4974
|
+
ariaLabel: ariaLabel ?? t.funnel,
|
|
5405
4975
|
plotRole: "group",
|
|
5406
4976
|
dataTable,
|
|
5407
4977
|
className,
|
|
@@ -5518,8 +5088,26 @@ function heatmapCellFontSize(plotWidth, columns, rowNames, texts) {
|
|
|
5518
5088
|
if (text + HEATMAP_CELL_PADDING <= cell) return 12;
|
|
5519
5089
|
return text * 10 / 12 + HEATMAP_CELL_PADDING <= cell ? 10 : null;
|
|
5520
5090
|
}
|
|
5091
|
+
var TEXT13 = {
|
|
5092
|
+
ja: {
|
|
5093
|
+
join: "\u30FB",
|
|
5094
|
+
flagged: "\u8981\u6CE8\u610F",
|
|
5095
|
+
item: "\u9805\u76EE",
|
|
5096
|
+
top: (y, x, value) => `\u6700\u5927\u306F ${y} ${x} \u306E ${value}`,
|
|
5097
|
+
chart: (y, x) => `${y}\xD7${x}\u306E\u30D2\u30FC\u30C8\u30DE\u30C3\u30D7`
|
|
5098
|
+
},
|
|
5099
|
+
en: {
|
|
5100
|
+
join: ", ",
|
|
5101
|
+
flagged: "Needs attention",
|
|
5102
|
+
item: "Item",
|
|
5103
|
+
top: (y, x, value) => `Highest: ${y} ${x} (${value})`,
|
|
5104
|
+
chart: (y, x) => `Heatmap of ${y} \xD7 ${x}`
|
|
5105
|
+
}
|
|
5106
|
+
};
|
|
5107
|
+
var textOf3 = (locale) => TEXT13[uiLanguage(resolveLocale(locale))];
|
|
5521
5108
|
function buildHeatmapOption(config) {
|
|
5522
5109
|
const { model, labels, valueFormatter } = config;
|
|
5110
|
+
const t = textOf3(config.locale);
|
|
5523
5111
|
const label2 = (key) => labels?.[key] ?? key;
|
|
5524
5112
|
const present = model.cells.filter((c) => c.value !== null);
|
|
5525
5113
|
const missing = model.cells.filter((c) => c.value === null);
|
|
@@ -5533,9 +5121,9 @@ function buildHeatmapOption(config) {
|
|
|
5533
5121
|
const extras = (config.details ?? []).map((key) => {
|
|
5534
5122
|
const n = cell.row ? toChartNumber(cell.row[key]) : null;
|
|
5535
5123
|
return `${escapeHtml2(label2(key))} ${n === null ? EMPTY_VALUE : escapeHtml2(valueFormatter(n))}`;
|
|
5536
|
-
}).join(
|
|
5537
|
-
const flag = cell.flagged ?
|
|
5538
|
-
return `${head} ${main}${extras ?
|
|
5124
|
+
}).join(t.join);
|
|
5125
|
+
const flag = cell.flagged ? `${t.join}${t.flagged}` : "";
|
|
5126
|
+
return `${head} ${main}${extras ? `${t.join}${extras}` : ""}${flag}`;
|
|
5539
5127
|
};
|
|
5540
5128
|
const cellFont = config.plotWidth ? heatmapCellFontSize(
|
|
5541
5129
|
config.plotWidth,
|
|
@@ -5633,7 +5221,7 @@ function mergeDeep(a, b) {
|
|
|
5633
5221
|
}
|
|
5634
5222
|
return out;
|
|
5635
5223
|
}
|
|
5636
|
-
function heatmapDataTable(model, names, formatter, labels) {
|
|
5224
|
+
function heatmapDataTable(model, names, formatter, labels, locale) {
|
|
5637
5225
|
const label2 = (key) => labels?.[key] ?? key;
|
|
5638
5226
|
const rows = model.ys.map((yk, yi) => [
|
|
5639
5227
|
label2(yk),
|
|
@@ -5642,15 +5230,15 @@ function heatmapDataTable(model, names, formatter, labels) {
|
|
|
5642
5230
|
return v === null || v === void 0 ? EMPTY_VALUE : formatter(v);
|
|
5643
5231
|
})
|
|
5644
5232
|
]);
|
|
5645
|
-
return { caption: `${label2(names.y)}\xD7${label2(names.x)}`, columns: [labels?.[names.y] ??
|
|
5233
|
+
return { caption: `${label2(names.y)}\xD7${label2(names.x)}`, columns: [labels?.[names.y] ?? textOf3(locale).item, ...model.xs.map(label2)], rows };
|
|
5646
5234
|
}
|
|
5647
|
-
function buildHeatmapSummary(model, formatter, title, labels) {
|
|
5235
|
+
function buildHeatmapSummary(model, formatter, title, labels, locale) {
|
|
5648
5236
|
let best;
|
|
5649
5237
|
for (const cell of model.cells) if (cell.value !== null && (!best || cell.value > best.value)) best = cell;
|
|
5650
5238
|
if (!best) return void 0;
|
|
5651
5239
|
const label2 = (key) => labels?.[key] ?? key;
|
|
5652
5240
|
const head = title ? `${title}: ` : "";
|
|
5653
|
-
return `${head}
|
|
5241
|
+
return `${head}${textOf3(locale).top(label2(model.ys[best.yi]), label2(model.xs[best.xi]), formatter(best.value))}`;
|
|
5654
5242
|
}
|
|
5655
5243
|
function colorsFor(tokens, tone) {
|
|
5656
5244
|
const [color = "", flag = "", muted = ""] = resolveChartColors([tone, "negative", "var(--muted-foreground)"], tokens);
|
|
@@ -5665,7 +5253,7 @@ function HeatmapImpl({
|
|
|
5665
5253
|
xLabels,
|
|
5666
5254
|
yLabels,
|
|
5667
5255
|
labels,
|
|
5668
|
-
format
|
|
5256
|
+
format,
|
|
5669
5257
|
valueFormatter,
|
|
5670
5258
|
tone = "chart-1",
|
|
5671
5259
|
scale,
|
|
@@ -5688,9 +5276,9 @@ function HeatmapImpl({
|
|
|
5688
5276
|
ariaLabel,
|
|
5689
5277
|
...rest
|
|
5690
5278
|
}, ref) {
|
|
5691
|
-
const tokens =
|
|
5692
|
-
const
|
|
5693
|
-
const formatter = useMemo(() => resolveValueFormatter(valueFormatter,
|
|
5279
|
+
const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
|
|
5280
|
+
const locale = useLocale();
|
|
5281
|
+
const formatter = useMemo(() => resolveValueFormatter(valueFormatter, format ?? "number", locale), [valueFormatter, format, locale]);
|
|
5694
5282
|
const model = useMemo(
|
|
5695
5283
|
() => buildHeatmapModel({ data, x, y, value, xLabels, yLabels, flag, scale, minValue, maxValue }),
|
|
5696
5284
|
[data, x, y, value, xLabels, yLabels, flag, scale?.min, scale?.max, minValue, maxValue]
|
|
@@ -5711,16 +5299,17 @@ function HeatmapImpl({
|
|
|
5711
5299
|
showValues,
|
|
5712
5300
|
showTooltip,
|
|
5713
5301
|
plotWidth,
|
|
5714
|
-
chartOptions
|
|
5302
|
+
chartOptions,
|
|
5303
|
+
locale
|
|
5715
5304
|
}),
|
|
5716
|
-
[model, x, y, value, colors, surface, tokens, labels, formatter, details, showValues, showTooltip, plotWidth, chartOptions]
|
|
5305
|
+
[model, x, y, value, colors, surface, tokens, labels, formatter, details, showValues, showTooltip, plotWidth, chartOptions, locale]
|
|
5717
5306
|
);
|
|
5718
|
-
const dataTable = useMemo(() => heatmapDataTable(model, { x, y }, formatter, labels), [model, x, y, formatter, labels]);
|
|
5307
|
+
const dataTable = useMemo(() => heatmapDataTable(model, { x, y }, formatter, labels, locale), [model, x, y, formatter, labels, locale]);
|
|
5719
5308
|
const resolvedSummary = useMemo(
|
|
5720
|
-
() => summary === "auto" ? buildHeatmapSummary(model, formatter, title, labels) : summary,
|
|
5721
|
-
[summary, model, formatter, title, labels]
|
|
5309
|
+
() => summary === "auto" ? buildHeatmapSummary(model, formatter, title, labels, locale) : summary,
|
|
5310
|
+
[summary, model, formatter, title, labels, locale]
|
|
5722
5311
|
);
|
|
5723
|
-
const label2 = ariaLabel ??
|
|
5312
|
+
const label2 = ariaLabel ?? textOf3(locale).chart(labels?.[y] ?? y, labels?.[x] ?? x);
|
|
5724
5313
|
const legend = showLegend ? /* @__PURE__ */ jsx(HeatmapLegend, { model, formatter, tone }) : null;
|
|
5725
5314
|
return /* @__PURE__ */ jsx(
|
|
5726
5315
|
ChartFrame,
|
|
@@ -5758,174 +5347,68 @@ function HeatmapLegend({
|
|
|
5758
5347
|
}
|
|
5759
5348
|
var Heatmap = forwardRef(HeatmapImpl);
|
|
5760
5349
|
Heatmap.displayName = "Heatmap";
|
|
5761
|
-
var
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
}
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
}
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
return
|
|
5798
|
-
}
|
|
5799
|
-
function buildBarRects(ys, height, gap = 1) {
|
|
5800
|
-
const barW = Math.max(1, VB_WIDTH / ys.length - gap);
|
|
5801
|
-
return ys.map((y, i) => ({ x: i * (barW + gap), y, w: barW, h: height - y }));
|
|
5802
|
-
}
|
|
5803
|
-
var NO_ROWS12 = [];
|
|
5804
|
-
var Sparkline = forwardRef(function Sparkline2({
|
|
5805
|
-
data = NO_ROWS12,
|
|
5806
|
-
variant = "line",
|
|
5807
|
-
height = 40,
|
|
5808
|
-
color = "text-chart-1",
|
|
5809
|
-
area = false,
|
|
5810
|
-
animate = false,
|
|
5811
|
-
highlight = "auto",
|
|
5812
|
-
"aria-label": ariaLabel,
|
|
5813
|
-
className,
|
|
5814
|
-
...props
|
|
5815
|
-
}, ref) {
|
|
5816
|
-
const [mounted, setMounted] = useState(false);
|
|
5817
|
-
useEffect(() => {
|
|
5818
|
-
if (animate) setMounted(true);
|
|
5819
|
-
}, [animate]);
|
|
5820
|
-
if (data.length === 0) return null;
|
|
5821
|
-
const values = data.map((d) => d.value);
|
|
5822
|
-
const ys = normalizeData(values, height);
|
|
5823
|
-
const step = ys.length > 1 ? VB_WIDTH / (ys.length - 1) : 0;
|
|
5824
|
-
const points = variant !== "line" ? [] : highlight === "auto" ? sparklineHighlightPoints(values) : highlight === "latest" ? [{ kind: "latest", index: values.length - 1 }] : [];
|
|
5825
|
-
return /* @__PURE__ */ jsxs(
|
|
5826
|
-
"svg",
|
|
5827
|
-
{
|
|
5828
|
-
ref,
|
|
5829
|
-
"data-slot": "sparkline",
|
|
5830
|
-
viewBox: `0 0 ${VB_WIDTH} ${height}`,
|
|
5831
|
-
preserveAspectRatio: "none",
|
|
5832
|
-
width: "100%",
|
|
5833
|
-
height,
|
|
5834
|
-
role: ariaLabel ? "img" : void 0,
|
|
5835
|
-
"aria-label": ariaLabel,
|
|
5836
|
-
"aria-hidden": ariaLabel ? void 0 : true,
|
|
5837
|
-
className: cn("overflow-visible", className),
|
|
5838
|
-
...props,
|
|
5839
|
-
children: [
|
|
5840
|
-
variant === "line" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5841
|
-
area && /* @__PURE__ */ jsx(
|
|
5842
|
-
"path",
|
|
5843
|
-
{
|
|
5844
|
-
d: buildAreaPath(ys, height),
|
|
5845
|
-
strokeWidth: 0,
|
|
5846
|
-
className: cn("fill-current opacity-15", color)
|
|
5847
|
-
}
|
|
5848
|
-
),
|
|
5849
|
-
/* @__PURE__ */ jsx(
|
|
5850
|
-
"path",
|
|
5851
|
-
{
|
|
5852
|
-
d: buildLinePath(ys),
|
|
5853
|
-
fill: "none",
|
|
5854
|
-
strokeWidth: 1.5,
|
|
5855
|
-
strokeLinecap: "round",
|
|
5856
|
-
strokeLinejoin: "round",
|
|
5857
|
-
vectorEffect: "non-scaling-stroke",
|
|
5858
|
-
pathLength: animate ? 1 : void 0,
|
|
5859
|
-
strokeDasharray: animate ? 1 : void 0,
|
|
5860
|
-
strokeDashoffset: animate ? mounted ? 0 : 1 : void 0,
|
|
5861
|
-
className: cn("stroke-current", animate && "motion-reduce:transition-none!", color),
|
|
5862
|
-
style: animate ? { transition: "stroke-dashoffset 0.6s ease-in-out" } : void 0
|
|
5863
|
-
}
|
|
5864
|
-
),
|
|
5865
|
-
points.map((p) => {
|
|
5866
|
-
const x = (p.index * step).toFixed(2);
|
|
5867
|
-
const y = (ys[p.index] ?? 0).toFixed(2);
|
|
5868
|
-
return /* @__PURE__ */ jsx(
|
|
5869
|
-
"path",
|
|
5870
|
-
{
|
|
5871
|
-
"data-slot": "sparkline-point",
|
|
5872
|
-
"data-point": p.kind,
|
|
5873
|
-
d: `M${x},${y} L${x},${y}`,
|
|
5874
|
-
fill: "none",
|
|
5875
|
-
strokeWidth: p.kind === "latest" ? 5 : 4,
|
|
5876
|
-
strokeLinecap: "round",
|
|
5877
|
-
vectorEffect: "non-scaling-stroke",
|
|
5878
|
-
className: cn("stroke-current", p.kind === "latest" ? color : "text-muted-foreground")
|
|
5879
|
-
},
|
|
5880
|
-
p.kind
|
|
5881
|
-
);
|
|
5882
|
-
})
|
|
5883
|
-
] }),
|
|
5884
|
-
variant === "bar" && buildBarRects(ys, height).map((rect, i) => /* @__PURE__ */ jsx(
|
|
5885
|
-
"rect",
|
|
5886
|
-
{
|
|
5887
|
-
x: rect.x,
|
|
5888
|
-
y: animate ? mounted ? rect.y : height : rect.y,
|
|
5889
|
-
width: rect.w,
|
|
5890
|
-
height: animate ? mounted ? rect.h : 0 : rect.h,
|
|
5891
|
-
rx: 0.5,
|
|
5892
|
-
className: cn("fill-current", animate && "motion-reduce:transition-none!", color),
|
|
5893
|
-
style: animate ? {
|
|
5894
|
-
transition: `height 0.4s ease-out ${i * 0.02}s, y 0.4s ease-out ${i * 0.02}s`
|
|
5895
|
-
} : void 0
|
|
5896
|
-
},
|
|
5897
|
-
i
|
|
5898
|
-
))
|
|
5899
|
-
]
|
|
5900
|
-
}
|
|
5901
|
-
);
|
|
5902
|
-
});
|
|
5903
|
-
Sparkline.displayName = "Sparkline";
|
|
5904
|
-
function resolveFormat(format2, row) {
|
|
5905
|
-
return typeof format2 === "function" ? format2(row) : format2;
|
|
5350
|
+
var TEXT14 = {
|
|
5351
|
+
ja: {
|
|
5352
|
+
tones: { positive: "\u826F\u597D", warning: "\u6CE8\u610F", negative: "\u8981\u5BFE\u5FDC", neutral: "\u4E2D\u7ACB" },
|
|
5353
|
+
toneNote: (label2) => `\uFF08${label2}\uFF09`,
|
|
5354
|
+
selectAll: "\u5168\u3066\u9078\u629E",
|
|
5355
|
+
selectRow: "\u884C\u3092\u9078\u629E",
|
|
5356
|
+
trend: (points, first, last, min, max) => `${points}\u70B9\u306E\u63A8\u79FB\u3001${first}\u304B\u3089${last}\u3001\u6700\u5C0F${min}\u3001\u6700\u5927${max}`,
|
|
5357
|
+
noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
5358
|
+
pageSize: (size) => `${size}\u4EF6`,
|
|
5359
|
+
range: (total, start, end) => `${total}\u4EF6\u4E2D ${start} - ${end} \u3092\u8868\u793A`,
|
|
5360
|
+
first: "\u6700\u521D",
|
|
5361
|
+
previous: "\u524D\u3078",
|
|
5362
|
+
next: "\u6B21\u3078",
|
|
5363
|
+
last: "\u6700\u5F8C",
|
|
5364
|
+
columns: "\u8868\u793A\u3059\u308B\u5217",
|
|
5365
|
+
exportCsv: "CSV \u3092\u66F8\u304D\u51FA\u3059"
|
|
5366
|
+
},
|
|
5367
|
+
en: {
|
|
5368
|
+
tones: { positive: "Good", warning: "Caution", negative: "Needs action", neutral: "Neutral" },
|
|
5369
|
+
toneNote: (label2) => ` (${label2})`,
|
|
5370
|
+
selectAll: "Select all",
|
|
5371
|
+
selectRow: "Select row",
|
|
5372
|
+
trend: (points, first, last, min, max) => `Trend over ${points} points: ${first} to ${last}, min ${min}, max ${max}`,
|
|
5373
|
+
noData: "No results.",
|
|
5374
|
+
pageSize: (size) => `${size} / page`,
|
|
5375
|
+
range: (total, start, end) => `Showing ${start}\u2013${end} of ${total}`,
|
|
5376
|
+
first: "First",
|
|
5377
|
+
previous: "Previous",
|
|
5378
|
+
next: "Next",
|
|
5379
|
+
last: "Last",
|
|
5380
|
+
columns: "Columns",
|
|
5381
|
+
exportCsv: "Export CSV"
|
|
5382
|
+
}
|
|
5383
|
+
};
|
|
5384
|
+
var useText = () => TEXT14[uiLanguage(useLocale())];
|
|
5385
|
+
function resolveFormat(format, row) {
|
|
5386
|
+
return typeof format === "function" ? format(row) : format;
|
|
5906
5387
|
}
|
|
5907
5388
|
function isMissingCell(value) {
|
|
5908
5389
|
return value === null || value === void 0 || value === "" || typeof value === "number" && Number.isNaN(value);
|
|
5909
5390
|
}
|
|
5910
|
-
function formatCellText(value, row, meta) {
|
|
5391
|
+
function formatCellText(value, row, meta, locale) {
|
|
5911
5392
|
if (isMissingCell(value)) return meta.nullLabel ?? EMPTY_VALUE;
|
|
5912
5393
|
if (meta.dateFormat && (value instanceof Date || typeof value === "string" || typeof value === "number")) {
|
|
5913
|
-
const text = formatDate(value, meta.dateFormat,
|
|
5394
|
+
const text = formatDate(value, meta.dateFormat, locale, { timeZone: meta.timeZone });
|
|
5914
5395
|
return text === EMPTY_VALUE ? String(value) : text;
|
|
5915
5396
|
}
|
|
5916
5397
|
if (typeof value !== "number") return String(value);
|
|
5917
|
-
return formatValue(value, resolveFormat(meta.format, row));
|
|
5398
|
+
return formatValue(value, resolveFormat(meta.format, row), locale);
|
|
5918
5399
|
}
|
|
5919
5400
|
var THRESHOLD_TONE_STYLES = {
|
|
5920
|
-
positive: { Icon: CircleCheck, text: "text-positive"
|
|
5921
|
-
warning: { Icon: TriangleAlert, text: "text-warning"
|
|
5922
|
-
negative: { Icon: CircleX, text: "text-negative"
|
|
5923
|
-
neutral: { Icon: Minus, text: "text-neutral"
|
|
5401
|
+
positive: { Icon: CircleCheck, text: "text-positive" },
|
|
5402
|
+
warning: { Icon: TriangleAlert, text: "text-warning" },
|
|
5403
|
+
negative: { Icon: CircleX, text: "text-negative" },
|
|
5404
|
+
neutral: { Icon: Minus, text: "text-neutral" }
|
|
5924
5405
|
};
|
|
5925
5406
|
function ThresholdCell({ value, text, thresholds }) {
|
|
5407
|
+
const t = useText();
|
|
5926
5408
|
const tone = typeof value === "number" ? toneForValue(value, thresholds) : void 0;
|
|
5927
5409
|
if (!tone) return /* @__PURE__ */ jsx("div", { className: "text-right tabular-nums", children: text });
|
|
5928
|
-
const { Icon, text: toneClass
|
|
5410
|
+
const { Icon, text: toneClass } = THRESHOLD_TONE_STYLES[tone];
|
|
5411
|
+
const label2 = t.tones[tone];
|
|
5929
5412
|
return /* @__PURE__ */ jsxs(
|
|
5930
5413
|
"div",
|
|
5931
5414
|
{
|
|
@@ -5935,11 +5418,7 @@ function ThresholdCell({ value, text, thresholds }) {
|
|
|
5935
5418
|
children: [
|
|
5936
5419
|
/* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0", "aria-hidden": "true" }),
|
|
5937
5420
|
/* @__PURE__ */ jsx("span", { children: text }),
|
|
5938
|
-
/* @__PURE__ */
|
|
5939
|
-
"\uFF08",
|
|
5940
|
-
label2,
|
|
5941
|
-
"\uFF09"
|
|
5942
|
-
] })
|
|
5421
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: t.toneNote(label2) })
|
|
5943
5422
|
]
|
|
5944
5423
|
}
|
|
5945
5424
|
);
|
|
@@ -5965,10 +5444,10 @@ function useDataTable() {
|
|
|
5965
5444
|
if (!ctx) throw new Error("useDataTable must be used inside <DataTable>");
|
|
5966
5445
|
return ctx;
|
|
5967
5446
|
}
|
|
5968
|
-
var
|
|
5447
|
+
var NO_ROWS12 = [];
|
|
5969
5448
|
function DataTable({
|
|
5970
|
-
columns =
|
|
5971
|
-
data =
|
|
5449
|
+
columns = NO_ROWS12,
|
|
5450
|
+
data = NO_ROWS12,
|
|
5972
5451
|
enableSorting = true,
|
|
5973
5452
|
sorting: sortingProp,
|
|
5974
5453
|
onSortingChange,
|
|
@@ -5994,6 +5473,8 @@ function DataTable({
|
|
|
5994
5473
|
className,
|
|
5995
5474
|
children
|
|
5996
5475
|
}) {
|
|
5476
|
+
const locale = useLocale();
|
|
5477
|
+
const t = TEXT14[uiLanguage(locale)];
|
|
5997
5478
|
const [sorting, setSorting] = useControlledState(sortingProp, [], onSortingChange);
|
|
5998
5479
|
const [columnFilters, setColumnFilters] = useControlledState(
|
|
5999
5480
|
columnFiltersProp,
|
|
@@ -6032,7 +5513,7 @@ function DataTable({
|
|
|
6032
5513
|
...column,
|
|
6033
5514
|
cell: ({ row, getValue }) => {
|
|
6034
5515
|
const value = getValue();
|
|
6035
|
-
const text = formatCellText(value, row.original, meta2 ?? {});
|
|
5516
|
+
const text = formatCellText(value, row.original, meta2 ?? {}, locale);
|
|
6036
5517
|
if (thresholds) return /* @__PURE__ */ jsx(ThresholdCell, { value, text, thresholds });
|
|
6037
5518
|
if (aligned) return /* @__PURE__ */ jsx("div", { className: "text-right tabular-nums", children: text });
|
|
6038
5519
|
if (meta2?.dateFormat) return /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: text });
|
|
@@ -6049,7 +5530,7 @@ function DataTable({
|
|
|
6049
5530
|
checked: table2.getIsAllPageRowsSelected(),
|
|
6050
5531
|
indeterminate: table2.getIsSomePageRowsSelected(),
|
|
6051
5532
|
onCheckedChange: (checked) => table2.toggleAllPageRowsSelected(checked),
|
|
6052
|
-
"aria-label":
|
|
5533
|
+
"aria-label": t.selectAll
|
|
6053
5534
|
}
|
|
6054
5535
|
),
|
|
6055
5536
|
cell: ({ row }) => /* @__PURE__ */ jsx(
|
|
@@ -6057,14 +5538,14 @@ function DataTable({
|
|
|
6057
5538
|
{
|
|
6058
5539
|
checked: row.getIsSelected(),
|
|
6059
5540
|
onCheckedChange: (checked) => row.toggleSelected(checked),
|
|
6060
|
-
"aria-label":
|
|
5541
|
+
"aria-label": t.selectRow
|
|
6061
5542
|
}
|
|
6062
5543
|
),
|
|
6063
5544
|
enableSorting: false,
|
|
6064
5545
|
enableHiding: false
|
|
6065
5546
|
};
|
|
6066
5547
|
return [selectionColumn, ...formatted];
|
|
6067
|
-
}, [columns, enableRowSelection]);
|
|
5548
|
+
}, [columns, enableRowSelection, locale, t]);
|
|
6068
5549
|
const autoResetPage = enablePagination && pageCount === void 0 && rowCount === void 0;
|
|
6069
5550
|
const resetKey = useRef(null);
|
|
6070
5551
|
useEffect(() => {
|
|
@@ -6230,6 +5711,7 @@ function SortIcon({ sorted }) {
|
|
|
6230
5711
|
var DataTableContent = forwardRef(
|
|
6231
5712
|
({ className, ...props }, ref) => {
|
|
6232
5713
|
const { table, visibleColumnCount, isLoading, enablePagination } = useDataTable();
|
|
5714
|
+
const t = useText();
|
|
6233
5715
|
const { comparisonOf, comparisonIds } = pairComparisons(table.getVisibleLeafColumns());
|
|
6234
5716
|
return /* @__PURE__ */ jsx(
|
|
6235
5717
|
"div",
|
|
@@ -6310,7 +5792,7 @@ var DataTableContent = forwardRef(
|
|
|
6310
5792
|
{
|
|
6311
5793
|
colSpan: visibleColumnCount,
|
|
6312
5794
|
className: "h-24 text-center text-muted-foreground",
|
|
6313
|
-
children:
|
|
5795
|
+
children: t.noData
|
|
6314
5796
|
}
|
|
6315
5797
|
) }) })
|
|
6316
5798
|
] })
|
|
@@ -6322,6 +5804,7 @@ DataTableContent.displayName = "DataTableContent";
|
|
|
6322
5804
|
var DataTablePagination = forwardRef(
|
|
6323
5805
|
({ pageSizeOptions = [10, 20, 50], className, ...props }, ref) => {
|
|
6324
5806
|
const { table, isLoading } = useDataTable();
|
|
5807
|
+
const t = useText();
|
|
6325
5808
|
const totalRows = table.options.rowCount !== void 0 ? table.getRowCount() : table.getFilteredRowModel().rows.length;
|
|
6326
5809
|
const currentPageSize = table.getState().pagination.pageSize;
|
|
6327
5810
|
const currentPageIndex = table.getState().pagination.pageIndex;
|
|
@@ -6329,7 +5812,7 @@ var DataTablePagination = forwardRef(
|
|
|
6329
5812
|
const rangeEnd = Math.min((currentPageIndex + 1) * currentPageSize, totalRows);
|
|
6330
5813
|
const pageSizeItems = pageSizeOptions.map((size) => ({
|
|
6331
5814
|
value: String(size),
|
|
6332
|
-
label:
|
|
5815
|
+
label: t.pageSize(size)
|
|
6333
5816
|
}));
|
|
6334
5817
|
return /* @__PURE__ */ jsxs(
|
|
6335
5818
|
"div",
|
|
@@ -6341,14 +5824,7 @@ var DataTablePagination = forwardRef(
|
|
|
6341
5824
|
...props,
|
|
6342
5825
|
children: [
|
|
6343
5826
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
6344
|
-
/* @__PURE__ */
|
|
6345
|
-
totalRows,
|
|
6346
|
-
"\u4EF6\u4E2D ",
|
|
6347
|
-
rangeStart,
|
|
6348
|
-
" - ",
|
|
6349
|
-
rangeEnd,
|
|
6350
|
-
" \u3092\u8868\u793A"
|
|
6351
|
-
] }),
|
|
5827
|
+
/* @__PURE__ */ jsx("span", { children: t.range(totalRows, rangeStart, rangeEnd) }),
|
|
6352
5828
|
/* @__PURE__ */ jsxs(
|
|
6353
5829
|
Select,
|
|
6354
5830
|
{
|
|
@@ -6356,7 +5832,7 @@ var DataTablePagination = forwardRef(
|
|
|
6356
5832
|
value: String(currentPageSize),
|
|
6357
5833
|
onValueChange: (value) => table.setPageSize(Number(value)),
|
|
6358
5834
|
children: [
|
|
6359
|
-
/* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-[80px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
5835
|
+
/* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "min-w-[80px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
6360
5836
|
/* @__PURE__ */ jsx(SelectContent, { children: pageSizeItems.map((item) => /* @__PURE__ */ jsx(SelectItem, { value: item.value, children: item.label }, item.value)) })
|
|
6361
5837
|
]
|
|
6362
5838
|
}
|
|
@@ -6370,7 +5846,7 @@ var DataTablePagination = forwardRef(
|
|
|
6370
5846
|
size: "sm",
|
|
6371
5847
|
onClick: () => table.firstPage(),
|
|
6372
5848
|
disabled: isLoading || !table.getCanPreviousPage(),
|
|
6373
|
-
children:
|
|
5849
|
+
children: t.first
|
|
6374
5850
|
}
|
|
6375
5851
|
),
|
|
6376
5852
|
/* @__PURE__ */ jsx(
|
|
@@ -6380,7 +5856,7 @@ var DataTablePagination = forwardRef(
|
|
|
6380
5856
|
size: "sm",
|
|
6381
5857
|
onClick: () => table.previousPage(),
|
|
6382
5858
|
disabled: isLoading || !table.getCanPreviousPage(),
|
|
6383
|
-
children:
|
|
5859
|
+
children: t.previous
|
|
6384
5860
|
}
|
|
6385
5861
|
),
|
|
6386
5862
|
/* @__PURE__ */ jsx(
|
|
@@ -6390,7 +5866,7 @@ var DataTablePagination = forwardRef(
|
|
|
6390
5866
|
size: "sm",
|
|
6391
5867
|
onClick: () => table.nextPage(),
|
|
6392
5868
|
disabled: isLoading || !table.getCanNextPage(),
|
|
6393
|
-
children:
|
|
5869
|
+
children: t.next
|
|
6394
5870
|
}
|
|
6395
5871
|
),
|
|
6396
5872
|
/* @__PURE__ */ jsx(
|
|
@@ -6400,7 +5876,7 @@ var DataTablePagination = forwardRef(
|
|
|
6400
5876
|
size: "sm",
|
|
6401
5877
|
onClick: () => table.lastPage(),
|
|
6402
5878
|
disabled: isLoading || !table.getCanNextPage(),
|
|
6403
|
-
children:
|
|
5879
|
+
children: t.last
|
|
6404
5880
|
}
|
|
6405
5881
|
)
|
|
6406
5882
|
] })
|
|
@@ -6412,6 +5888,7 @@ var DataTablePagination = forwardRef(
|
|
|
6412
5888
|
DataTablePagination.displayName = "DataTablePagination";
|
|
6413
5889
|
var DataTableColumnVisibility = forwardRef(({ columnLabels, className }, ref) => {
|
|
6414
5890
|
const { table } = useDataTable();
|
|
5891
|
+
const t = useText();
|
|
6415
5892
|
const hideableColumns = table.getAllColumns().filter((column) => column.getCanHide());
|
|
6416
5893
|
if (hideableColumns.length === 0) return null;
|
|
6417
5894
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
@@ -6421,7 +5898,7 @@ var DataTableColumnVisibility = forwardRef(({ columnLabels, className }, ref) =>
|
|
|
6421
5898
|
ref,
|
|
6422
5899
|
render: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: cn(className) }),
|
|
6423
5900
|
"data-slot": "data-table-column-visibility",
|
|
6424
|
-
"aria-label":
|
|
5901
|
+
"aria-label": t.columns,
|
|
6425
5902
|
children: /* @__PURE__ */ jsx(Columns3, { className: "size-4", "aria-hidden": "true" })
|
|
6426
5903
|
}
|
|
6427
5904
|
),
|
|
@@ -6456,7 +5933,8 @@ function toCsv(header, rows, options = {}) {
|
|
|
6456
5933
|
];
|
|
6457
5934
|
return (bom ? "\uFEFF" : "") + lines.join("\r\n");
|
|
6458
5935
|
}
|
|
6459
|
-
function tableToCsv(table, { values = "display", scope = "filtered" } = {}) {
|
|
5936
|
+
function tableToCsv(table, { values = "display", scope = "filtered", locale: localeArg } = {}) {
|
|
5937
|
+
const locale = resolveLocale(localeArg);
|
|
6460
5938
|
const columns = table.getVisibleLeafColumns().filter((column) => column.id !== "_select");
|
|
6461
5939
|
const rows = scope === "page" ? table.getRowModel().rows : table.getSortedRowModel().rows;
|
|
6462
5940
|
const header = columns.map(
|
|
@@ -6466,7 +5944,7 @@ function tableToCsv(table, { values = "display", scope = "filtered" } = {}) {
|
|
|
6466
5944
|
(row) => columns.map((column) => {
|
|
6467
5945
|
const value = row.getValue(column.id);
|
|
6468
5946
|
const meta = column.columnDef.meta;
|
|
6469
|
-
if (values === "display" && (meta?.format || meta?.dateFormat)) return formatCellText(value, row.original, meta);
|
|
5947
|
+
if (values === "display" && (meta?.format || meta?.dateFormat)) return formatCellText(value, row.original, meta, locale);
|
|
6470
5948
|
if (value === null || value === void 0) return "";
|
|
6471
5949
|
if (typeof value === "number" || typeof value === "string") return value;
|
|
6472
5950
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -6479,12 +5957,13 @@ function DataTableExport({
|
|
|
6479
5957
|
fileName = "export.csv",
|
|
6480
5958
|
values = "display",
|
|
6481
5959
|
scope = "filtered",
|
|
6482
|
-
children
|
|
5960
|
+
children,
|
|
6483
5961
|
className
|
|
6484
5962
|
}) {
|
|
6485
5963
|
const { table, isLoading } = useDataTable();
|
|
5964
|
+
const locale = useLocale();
|
|
6486
5965
|
const onClick = () => {
|
|
6487
|
-
const csv = tableToCsv(table, { values, scope });
|
|
5966
|
+
const csv = tableToCsv(table, { values, scope, locale });
|
|
6488
5967
|
const url = URL.createObjectURL(new Blob([csv], { type: "text/csv;charset=utf-8" }));
|
|
6489
5968
|
const a = document.createElement("a");
|
|
6490
5969
|
a.href = url;
|
|
@@ -6504,7 +5983,7 @@ function DataTableExport({
|
|
|
6504
5983
|
disabled: isLoading,
|
|
6505
5984
|
children: [
|
|
6506
5985
|
/* @__PURE__ */ jsx(Download, { className: "size-4", "aria-hidden": "true" }),
|
|
6507
|
-
children
|
|
5986
|
+
children ?? TEXT14[uiLanguage(locale)].exportCsv
|
|
6508
5987
|
]
|
|
6509
5988
|
}
|
|
6510
5989
|
);
|
|
@@ -6539,24 +6018,44 @@ function DataTablePreset({
|
|
|
6539
6018
|
}
|
|
6540
6019
|
DataTablePreset.displayName = "DataTablePreset";
|
|
6541
6020
|
var FilterBarContext = createContext(null);
|
|
6021
|
+
var TEXT15 = {
|
|
6022
|
+
ja: {
|
|
6023
|
+
filters: "\u30D5\u30A3\u30EB\u30BF\u30FC",
|
|
6024
|
+
selected: (count) => ` (${count}\u4EF6\u9078\u629E\u4E2D)`,
|
|
6025
|
+
remove: (filter, option) => `${filter}: ${option} \u3092\u524A\u9664`,
|
|
6026
|
+
clear: "\u30AF\u30EA\u30A2",
|
|
6027
|
+
clearAll: "\u3059\u3079\u3066\u306E\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u30AF\u30EA\u30A2"
|
|
6028
|
+
},
|
|
6029
|
+
en: {
|
|
6030
|
+
filters: "Filters",
|
|
6031
|
+
selected: (count) => ` (${count} selected)`,
|
|
6032
|
+
remove: (filter, option) => `Remove ${filter}: ${option}`,
|
|
6033
|
+
clear: "Clear",
|
|
6034
|
+
clearAll: "Clear all filters"
|
|
6035
|
+
}
|
|
6036
|
+
};
|
|
6037
|
+
var useText2 = () => TEXT15[uiLanguage(useLocale())];
|
|
6542
6038
|
function useFilterBar() {
|
|
6543
6039
|
const ctx = useContext(FilterBarContext);
|
|
6544
6040
|
if (!ctx) throw new Error("useFilterBar must be used within <FilterBar>");
|
|
6545
6041
|
return ctx;
|
|
6546
6042
|
}
|
|
6547
6043
|
var FilterBar = forwardRef(
|
|
6548
|
-
({ value, onChange, onClear, className, children, ...props }, ref) =>
|
|
6549
|
-
|
|
6550
|
-
{
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6044
|
+
({ value, onChange, onClear, className, children, ...props }, ref) => {
|
|
6045
|
+
const t = useText2();
|
|
6046
|
+
return /* @__PURE__ */ jsx(FilterBarContext.Provider, { value: { value, onChange, onClear }, children: /* @__PURE__ */ jsx(
|
|
6047
|
+
"div",
|
|
6048
|
+
{
|
|
6049
|
+
ref,
|
|
6050
|
+
role: "search",
|
|
6051
|
+
"aria-label": t.filters,
|
|
6052
|
+
"data-slot": "filter-bar",
|
|
6053
|
+
className: cn("flex flex-wrap items-center gap-2", className),
|
|
6054
|
+
...props,
|
|
6055
|
+
children
|
|
6056
|
+
}
|
|
6057
|
+
) });
|
|
6058
|
+
}
|
|
6560
6059
|
);
|
|
6561
6060
|
FilterBar.displayName = "FilterBar";
|
|
6562
6061
|
var ALL_VALUE = "__squadkit_all__";
|
|
@@ -6598,6 +6097,7 @@ function FilterBarMultiSelect({
|
|
|
6598
6097
|
className
|
|
6599
6098
|
}) {
|
|
6600
6099
|
const { value, onChange } = useFilterBar();
|
|
6100
|
+
const t = useText2();
|
|
6601
6101
|
const selected = value[filterKey] ?? [];
|
|
6602
6102
|
const handleToggle = (option) => {
|
|
6603
6103
|
const next = selected.includes(option) ? selected.filter((v) => v !== option) : [...selected, option];
|
|
@@ -6608,7 +6108,7 @@ function FilterBarMultiSelect({
|
|
|
6608
6108
|
PopoverTrigger,
|
|
6609
6109
|
{
|
|
6610
6110
|
render: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: cn("h-8 gap-1", className) }),
|
|
6611
|
-
"aria-label": `${placeholder ?? label2}${selected.length > 0 ?
|
|
6111
|
+
"aria-label": `${placeholder ?? label2}${selected.length > 0 ? t.selected(selected.length) : ""}`,
|
|
6612
6112
|
"data-slot": "filter-bar-multi-select",
|
|
6613
6113
|
children: [
|
|
6614
6114
|
placeholder ?? label2,
|
|
@@ -6640,6 +6140,7 @@ function FilterBarMultiSelect({
|
|
|
6640
6140
|
FilterBarMultiSelect.displayName = "FilterBarMultiSelect";
|
|
6641
6141
|
function FilterBarActiveChips({ filters, className }) {
|
|
6642
6142
|
const { value, onChange } = useFilterBar();
|
|
6143
|
+
const t = useText2();
|
|
6643
6144
|
const getActiveChips = () => {
|
|
6644
6145
|
const chips = [];
|
|
6645
6146
|
const pushRaw = (key, v) => {
|
|
@@ -6710,7 +6211,7 @@ function FilterBarActiveChips({ filters, className }) {
|
|
|
6710
6211
|
type: "button",
|
|
6711
6212
|
className: "ml-0.5 rounded-full p-0.5 hover:bg-muted-foreground/20",
|
|
6712
6213
|
onClick: () => handleRemoveFilter(chip.key, chip.optionValue),
|
|
6713
|
-
"aria-label":
|
|
6214
|
+
"aria-label": t.remove(chip.filterLabel, chip.optionLabel),
|
|
6714
6215
|
children: /* @__PURE__ */ jsx(X, { className: "size-3", "aria-hidden": "true" })
|
|
6715
6216
|
}
|
|
6716
6217
|
)
|
|
@@ -6720,8 +6221,9 @@ function FilterBarActiveChips({ filters, className }) {
|
|
|
6720
6221
|
)) });
|
|
6721
6222
|
}
|
|
6722
6223
|
FilterBarActiveChips.displayName = "FilterBarActiveChips";
|
|
6723
|
-
function FilterBarClearButton({ label: label2
|
|
6224
|
+
function FilterBarClearButton({ label: label2, className }) {
|
|
6724
6225
|
const { value, onClear } = useFilterBar();
|
|
6226
|
+
const t = useText2();
|
|
6725
6227
|
const hasActiveFilters = Object.values(value).some(
|
|
6726
6228
|
(v) => Array.isArray(v) ? v.length > 0 : v !== void 0 && v !== ""
|
|
6727
6229
|
);
|
|
@@ -6733,9 +6235,9 @@ function FilterBarClearButton({ label: label2 = "\u30AF\u30EA\u30A2", className
|
|
|
6733
6235
|
size: "sm",
|
|
6734
6236
|
className: cn("h-7 px-2 text-xs", className),
|
|
6735
6237
|
onClick: onClear,
|
|
6736
|
-
"aria-label":
|
|
6238
|
+
"aria-label": t.clearAll,
|
|
6737
6239
|
"data-slot": "filter-bar-clear-button",
|
|
6738
|
-
children: label2
|
|
6240
|
+
children: label2 ?? t.clear
|
|
6739
6241
|
}
|
|
6740
6242
|
);
|
|
6741
6243
|
}
|
|
@@ -6783,13 +6285,16 @@ function FilterBarPreset({
|
|
|
6783
6285
|
] });
|
|
6784
6286
|
}
|
|
6785
6287
|
FilterBarPreset.displayName = "FilterBarPreset";
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6288
|
+
function normalizeFiscalYearStartMonth(month, locale) {
|
|
6289
|
+
return typeof month === "number" && Number.isInteger(month) && month >= 1 && month <= 12 ? month : defaultFiscalYearStartMonth(locale);
|
|
6290
|
+
}
|
|
6291
|
+
function fiscalPeriodRange(date, {
|
|
6292
|
+
unit,
|
|
6293
|
+
fiscalYearStartMonth,
|
|
6294
|
+
offset = 0,
|
|
6295
|
+
locale
|
|
6296
|
+
}) {
|
|
6297
|
+
const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth, locale);
|
|
6793
6298
|
const length = unit === "year" ? 12 : 3;
|
|
6794
6299
|
const sinceYearStart = (date.getMonth() - (startMonth - 1) + 12) % 12;
|
|
6795
6300
|
const into = unit === "year" ? sinceYearStart : sinceYearStart % 3;
|
|
@@ -6832,16 +6337,20 @@ var PRESET_LABELS = {
|
|
|
6832
6337
|
lastFiscalYear: "Last fiscal year"
|
|
6833
6338
|
}
|
|
6834
6339
|
};
|
|
6835
|
-
var
|
|
6836
|
-
|
|
6837
|
-
|
|
6340
|
+
var TEXT16 = {
|
|
6341
|
+
ja: { placeholder: "\u671F\u9593\u3092\u9078\u629E", rangeSeparator: " - " },
|
|
6342
|
+
en: { placeholder: "Pick a date range", rangeSeparator: " \u2013 " }
|
|
6343
|
+
};
|
|
6344
|
+
var calendarLocale = (locale) => uiLanguage(locale) === "ja" ? ja : void 0;
|
|
6838
6345
|
function createDatePresets({
|
|
6839
|
-
locale
|
|
6840
|
-
fiscalYearStartMonth
|
|
6346
|
+
locale: localeArg,
|
|
6347
|
+
fiscalYearStartMonth,
|
|
6841
6348
|
now = () => /* @__PURE__ */ new Date()
|
|
6842
6349
|
} = {}) {
|
|
6843
|
-
const
|
|
6844
|
-
const
|
|
6350
|
+
const locale = resolveLocale(localeArg);
|
|
6351
|
+
const t = PRESET_LABELS[uiLanguage(locale)];
|
|
6352
|
+
const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth, locale);
|
|
6353
|
+
const WEEK_OPTIONS = { weekStartsOn: weekStartsOn(locale) };
|
|
6845
6354
|
const lastDays = (days) => () => {
|
|
6846
6355
|
const today = now();
|
|
6847
6356
|
return { from: startOfDay(subDays(today, days - 1)), to: endOfDay(today) };
|
|
@@ -6910,24 +6419,26 @@ function findMatchingPreset(presets, value) {
|
|
|
6910
6419
|
return range.from != null && range.to != null && isSameDay(range.from, from) && isSameDay(range.to, to);
|
|
6911
6420
|
});
|
|
6912
6421
|
}
|
|
6913
|
-
var defaultPresets = createDatePresets();
|
|
6422
|
+
var defaultPresets = createDatePresets({ locale: FALLBACK_LOCALE });
|
|
6914
6423
|
var DateRangePicker = forwardRef(
|
|
6915
6424
|
function DateRangePicker2({
|
|
6916
6425
|
value,
|
|
6917
6426
|
onChange,
|
|
6918
6427
|
presets: presetsProp,
|
|
6919
6428
|
showPresets = true,
|
|
6920
|
-
locale
|
|
6921
|
-
fiscalYearStartMonth
|
|
6429
|
+
locale: localeProp,
|
|
6430
|
+
fiscalYearStartMonth,
|
|
6922
6431
|
maxDate,
|
|
6923
6432
|
minDate,
|
|
6924
|
-
placeholder
|
|
6433
|
+
placeholder,
|
|
6925
6434
|
disabled = false,
|
|
6926
6435
|
className,
|
|
6927
6436
|
align = "start"
|
|
6928
6437
|
}, ref) {
|
|
6929
6438
|
const [open, setOpen] = useState(false);
|
|
6930
6439
|
const isMobile = useIsMobile();
|
|
6440
|
+
const locale = useLocale(localeProp);
|
|
6441
|
+
const t = TEXT16[uiLanguage(locale)];
|
|
6931
6442
|
const presets = useMemo(
|
|
6932
6443
|
() => presetsProp ?? createDatePresets({ locale, fiscalYearStartMonth }),
|
|
6933
6444
|
[presetsProp, locale, fiscalYearStartMonth]
|
|
@@ -6946,9 +6457,9 @@ var DateRangePicker = forwardRef(
|
|
|
6946
6457
|
[onChange]
|
|
6947
6458
|
);
|
|
6948
6459
|
const formatDateRange2 = () => {
|
|
6949
|
-
if (!value?.from) return placeholder;
|
|
6950
|
-
if (!value.to) return
|
|
6951
|
-
return `${
|
|
6460
|
+
if (!value?.from) return placeholder ?? t.placeholder;
|
|
6461
|
+
if (!value.to) return formatDate(value.from, "date", locale);
|
|
6462
|
+
return `${formatDate(value.from, "date", locale)}${t.rangeSeparator}${formatDate(value.to, "date", locale)}`;
|
|
6952
6463
|
};
|
|
6953
6464
|
const selectedPreset = findMatchingPreset(presets, value);
|
|
6954
6465
|
const presetLabel = selectedPreset?.label;
|
|
@@ -7009,7 +6520,7 @@ var DateRangePicker = forwardRef(
|
|
|
7009
6520
|
mode: "range",
|
|
7010
6521
|
defaultMonth,
|
|
7011
6522
|
locale: calendarLocale(locale),
|
|
7012
|
-
weekStartsOn:
|
|
6523
|
+
weekStartsOn: weekStartsOn(locale),
|
|
7013
6524
|
numberOfMonths: isMobile ? 1 : 2,
|
|
7014
6525
|
selected: calendarSelected,
|
|
7015
6526
|
onSelect: handleCalendarSelect,
|
|
@@ -7144,6 +6655,10 @@ function RemoveButton({ label: label2, onRemove, iconClassName }) {
|
|
|
7144
6655
|
}
|
|
7145
6656
|
);
|
|
7146
6657
|
}
|
|
6658
|
+
var TEXT17 = {
|
|
6659
|
+
ja: { placeholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044", search: "\u691C\u7D22...", empty: "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F", clear: "\u30AF\u30EA\u30A2" },
|
|
6660
|
+
en: { placeholder: "Select an option", search: "Search...", empty: "No results found.", clear: "Clear" }
|
|
6661
|
+
};
|
|
7147
6662
|
var NO_OPTIONS2 = [];
|
|
7148
6663
|
var SearchableSelect = forwardRef(
|
|
7149
6664
|
function SearchableSelect2({
|
|
@@ -7151,15 +6666,16 @@ var SearchableSelect = forwardRef(
|
|
|
7151
6666
|
value,
|
|
7152
6667
|
onChange,
|
|
7153
6668
|
onSearch,
|
|
7154
|
-
placeholder
|
|
7155
|
-
searchPlaceholder
|
|
7156
|
-
emptyText
|
|
6669
|
+
placeholder,
|
|
6670
|
+
searchPlaceholder,
|
|
6671
|
+
emptyText,
|
|
7157
6672
|
isLoading = false,
|
|
7158
6673
|
disabled = false,
|
|
7159
6674
|
clearable = true,
|
|
7160
6675
|
className
|
|
7161
6676
|
}, ref) {
|
|
7162
6677
|
const [open, setOpen] = useState(false);
|
|
6678
|
+
const t = TEXT17[uiLanguage(useLocale())];
|
|
7163
6679
|
const allOptions = useMemo(() => flattenOptions(options), [options]);
|
|
7164
6680
|
const selectedOption = useMemo(
|
|
7165
6681
|
() => allOptions.find((opt) => opt.value === value),
|
|
@@ -7188,9 +6704,9 @@ var SearchableSelect = forwardRef(
|
|
|
7188
6704
|
role: "combobox",
|
|
7189
6705
|
"aria-expanded": open,
|
|
7190
6706
|
children: [
|
|
7191
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: selectedOption ? selectedOption.label : placeholder }),
|
|
6707
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: selectedOption ? selectedOption.label : placeholder ?? t.placeholder }),
|
|
7192
6708
|
/* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
|
|
7193
|
-
clearable && value && /* @__PURE__ */ jsx(RemoveButton, { label:
|
|
6709
|
+
clearable && value && /* @__PURE__ */ jsx(RemoveButton, { label: t.clear, onRemove: () => onChange?.(void 0) }),
|
|
7194
6710
|
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" })
|
|
7195
6711
|
] })
|
|
7196
6712
|
]
|
|
@@ -7204,14 +6720,30 @@ var SearchableSelect = forwardRef(
|
|
|
7204
6720
|
onSelect: handleSelect,
|
|
7205
6721
|
onSearch,
|
|
7206
6722
|
isLoading,
|
|
7207
|
-
searchPlaceholder,
|
|
7208
|
-
emptyText
|
|
6723
|
+
searchPlaceholder: searchPlaceholder ?? t.search,
|
|
6724
|
+
emptyText: emptyText ?? t.empty
|
|
7209
6725
|
}
|
|
7210
6726
|
) })
|
|
7211
6727
|
] }) });
|
|
7212
6728
|
}
|
|
7213
6729
|
);
|
|
7214
6730
|
SearchableSelect.displayName = "SearchableSelect";
|
|
6731
|
+
var TEXT18 = {
|
|
6732
|
+
ja: {
|
|
6733
|
+
placeholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
6734
|
+
search: "\u691C\u7D22...",
|
|
6735
|
+
empty: "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F",
|
|
6736
|
+
remove: (label2) => `${label2}\u3092\u524A\u9664`,
|
|
6737
|
+
more: (count) => `+${count}\u4EF6`
|
|
6738
|
+
},
|
|
6739
|
+
en: {
|
|
6740
|
+
placeholder: "Select options",
|
|
6741
|
+
search: "Search...",
|
|
6742
|
+
empty: "No results found.",
|
|
6743
|
+
remove: (label2) => `Remove ${label2}`,
|
|
6744
|
+
more: (count) => `+${count} more`
|
|
6745
|
+
}
|
|
6746
|
+
};
|
|
7215
6747
|
var NO_OPTIONS3 = [];
|
|
7216
6748
|
var NO_VALUES = [];
|
|
7217
6749
|
var MultiSelect = forwardRef(function MultiSelect2({
|
|
@@ -7220,15 +6752,16 @@ var MultiSelect = forwardRef(function MultiSelect2({
|
|
|
7220
6752
|
onChange,
|
|
7221
6753
|
onSearch,
|
|
7222
6754
|
maxCount = 3,
|
|
7223
|
-
placeholder
|
|
7224
|
-
searchPlaceholder
|
|
7225
|
-
emptyText
|
|
6755
|
+
placeholder,
|
|
6756
|
+
searchPlaceholder,
|
|
6757
|
+
emptyText,
|
|
7226
6758
|
isLoading = false,
|
|
7227
6759
|
disabled = false,
|
|
7228
6760
|
className
|
|
7229
6761
|
}, ref) {
|
|
7230
6762
|
const [open, setOpen] = useState(false);
|
|
7231
6763
|
const listId = useId();
|
|
6764
|
+
const t = TEXT18[uiLanguage(useLocale())];
|
|
7232
6765
|
const allOptions = useMemo(() => flattenOptions(options), [options]);
|
|
7233
6766
|
const selectedOptions = useMemo(
|
|
7234
6767
|
() => allOptions.filter((opt) => value.includes(opt.value)),
|
|
@@ -7256,23 +6789,19 @@ var MultiSelect = forwardRef(function MultiSelect2({
|
|
|
7256
6789
|
className
|
|
7257
6790
|
),
|
|
7258
6791
|
children: [
|
|
7259
|
-
/* @__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, { children: [
|
|
6792
|
+
/* @__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 ?? t.placeholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7260
6793
|
visibleBadges.map((option) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "shrink-0 gap-1 pr-1", children: [
|
|
7261
6794
|
/* @__PURE__ */ jsx("span", { className: "max-w-[120px] truncate", children: option.label }),
|
|
7262
6795
|
/* @__PURE__ */ jsx(
|
|
7263
6796
|
RemoveButton,
|
|
7264
6797
|
{
|
|
7265
|
-
label:
|
|
6798
|
+
label: t.remove(option.label),
|
|
7266
6799
|
onRemove: () => onChange?.(value.filter((v) => v !== option.value)),
|
|
7267
6800
|
iconClassName: "size-3"
|
|
7268
6801
|
}
|
|
7269
6802
|
)
|
|
7270
6803
|
] }, option.value)),
|
|
7271
|
-
overflowCount > 0 && /* @__PURE__ */
|
|
7272
|
-
"+",
|
|
7273
|
-
overflowCount,
|
|
7274
|
-
"\u4EF6"
|
|
7275
|
-
] })
|
|
6804
|
+
overflowCount > 0 && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "shrink-0", children: t.more(overflowCount) })
|
|
7276
6805
|
] }) }),
|
|
7277
6806
|
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 shrink-0 opacity-50" })
|
|
7278
6807
|
]
|
|
@@ -7286,8 +6815,8 @@ var MultiSelect = forwardRef(function MultiSelect2({
|
|
|
7286
6815
|
onSelect: handleSelect,
|
|
7287
6816
|
onSearch,
|
|
7288
6817
|
isLoading,
|
|
7289
|
-
searchPlaceholder,
|
|
7290
|
-
emptyText
|
|
6818
|
+
searchPlaceholder: searchPlaceholder ?? t.search,
|
|
6819
|
+
emptyText: emptyText ?? t.empty
|
|
7291
6820
|
}
|
|
7292
6821
|
) })
|
|
7293
6822
|
] }) });
|
|
@@ -7376,14 +6905,17 @@ function inferPeriodGrain(period) {
|
|
|
7376
6905
|
return void 0;
|
|
7377
6906
|
}
|
|
7378
6907
|
var RECORD_MIN_POINTS = 6;
|
|
7379
|
-
var
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
6908
|
+
var RECORD_TEXT = {
|
|
6909
|
+
ja: (span, grain, lower) => {
|
|
6910
|
+
const units = { day: "\u65E5", week: "\u9031", month: "\u304B\u6708", quarter: "\u56DB\u534A\u671F", year: "\u5E74" };
|
|
6911
|
+
return `\u904E\u53BB ${span} ${units[grain]}\u3067${lower ? "\u6700\u4F4E" : "\u6700\u9AD8"}`;
|
|
6912
|
+
},
|
|
6913
|
+
en: (span, grain, lower) => {
|
|
6914
|
+
const units = { day: "days", week: "weeks", month: "months", quarter: "quarters", year: "years" };
|
|
6915
|
+
return `${lower ? "Lowest" : "Highest"} in ${span} ${units[grain]}`;
|
|
6916
|
+
}
|
|
7385
6917
|
};
|
|
7386
|
-
function detectRecord(history, grain = "month", polarity = "higher-is-better") {
|
|
6918
|
+
function detectRecord(history, grain = "month", polarity = "higher-is-better", locale) {
|
|
7387
6919
|
if (!history) return null;
|
|
7388
6920
|
const points = history.filter(isFiniteNumber);
|
|
7389
6921
|
if (points.length < RECORD_MIN_POINTS) return null;
|
|
@@ -7396,7 +6928,7 @@ function detectRecord(history, grain = "month", polarity = "higher-is-better") {
|
|
|
7396
6928
|
span,
|
|
7397
6929
|
grain,
|
|
7398
6930
|
kind: lower ? "lowest" : "highest",
|
|
7399
|
-
label:
|
|
6931
|
+
label: RECORD_TEXT[uiLanguage(resolveLocale(locale))](span, grain, lower)
|
|
7400
6932
|
};
|
|
7401
6933
|
}
|
|
7402
6934
|
var deltaVariants = cva(
|
|
@@ -7404,7 +6936,7 @@ var deltaVariants = cva(
|
|
|
7404
6936
|
{
|
|
7405
6937
|
variants: {
|
|
7406
6938
|
variant: {
|
|
7407
|
-
badge: "h-5 rounded-
|
|
6939
|
+
badge: "h-5 rounded-md border px-2 py-0.5 text-xs font-medium [&>svg]:size-3",
|
|
7408
6940
|
inline: "text-sm [&>svg]:size-3.5"
|
|
7409
6941
|
},
|
|
7410
6942
|
sentiment: {
|
|
@@ -7414,9 +6946,9 @@ var deltaVariants = cva(
|
|
|
7414
6946
|
}
|
|
7415
6947
|
},
|
|
7416
6948
|
compoundVariants: [
|
|
7417
|
-
{ variant: "badge", sentiment: "positive", className: "bg-positive-subtle" },
|
|
7418
|
-
{ variant: "badge", sentiment: "negative", className: "bg-negative-subtle" },
|
|
7419
|
-
{ variant: "badge", sentiment: "neutral", className: "bg-neutral-subtle" }
|
|
6949
|
+
{ variant: "badge", sentiment: "positive", className: "border-positive/20 bg-positive-subtle dark:border-positive/25" },
|
|
6950
|
+
{ variant: "badge", sentiment: "negative", className: "border-negative/20 bg-negative-subtle dark:border-negative/25" },
|
|
6951
|
+
{ variant: "badge", sentiment: "neutral", className: "border-neutral/20 bg-neutral-subtle dark:border-neutral/25" }
|
|
7420
6952
|
],
|
|
7421
6953
|
defaultVariants: {
|
|
7422
6954
|
variant: "badge",
|
|
@@ -7425,37 +6957,59 @@ var deltaVariants = cva(
|
|
|
7425
6957
|
}
|
|
7426
6958
|
);
|
|
7427
6959
|
var DELTA_NOT_COMPARABLE = EMPTY_VALUE;
|
|
7428
|
-
|
|
6960
|
+
var ARIA_TEXT = {
|
|
6961
|
+
ja: {
|
|
6962
|
+
none: (label2) => `${label2} \u6BD4\u8F03\u3067\u304D\u307E\u305B\u3093`,
|
|
6963
|
+
flat: (label2) => `${label2} \u6A2A\u3070\u3044`,
|
|
6964
|
+
points: " \u30DD\u30A4\u30F3\u30C8",
|
|
6965
|
+
change: (label2, amount, up) => `${label2} ${amount} ${up ? "\u5897\u52A0" : "\u6E1B\u5C11"}`
|
|
6966
|
+
},
|
|
6967
|
+
en: {
|
|
6968
|
+
none: (label2) => `${label2}: not comparable`,
|
|
6969
|
+
flat: (label2) => `Flat ${label2}`,
|
|
6970
|
+
points: " points",
|
|
6971
|
+
change: (label2, amount, up) => `${up ? "Up" : "Down"} ${amount} ${label2}`
|
|
6972
|
+
}
|
|
6973
|
+
};
|
|
6974
|
+
function deltaAriaLabel(result, locale, change = "relative", format, digits) {
|
|
6975
|
+
const resolved = resolveLocale(locale);
|
|
6976
|
+
const t = ARIA_TEXT[uiLanguage(resolved)];
|
|
7429
6977
|
const { label: label2, direction, ratio } = result;
|
|
7430
|
-
if (direction === "none" || ratio === null) return
|
|
7431
|
-
if (direction === "flat") return
|
|
7432
|
-
const amount = formatChangeAmount(result, change,
|
|
7433
|
-
if (amount === null) return
|
|
7434
|
-
return
|
|
6978
|
+
if (direction === "none" || ratio === null) return t.none(label2);
|
|
6979
|
+
if (direction === "flat") return t.flat(label2);
|
|
6980
|
+
const amount = formatChangeAmount(result, change, resolved, format, digits);
|
|
6981
|
+
if (amount === null) return t.none(label2);
|
|
6982
|
+
return t.change(label2, change === "points" ? amount.replace(/pt$/, t.points) : amount, direction === "up");
|
|
7435
6983
|
}
|
|
7436
6984
|
var Delta = forwardRef(
|
|
7437
6985
|
({
|
|
7438
6986
|
value,
|
|
7439
6987
|
comparison,
|
|
6988
|
+
betterWhen,
|
|
7440
6989
|
polarity,
|
|
7441
6990
|
neutralBand,
|
|
7442
|
-
format
|
|
6991
|
+
format,
|
|
7443
6992
|
change,
|
|
7444
6993
|
digits,
|
|
7445
|
-
locale
|
|
6994
|
+
locale: localeProp,
|
|
7446
6995
|
showLabel = true,
|
|
7447
6996
|
variant = "badge",
|
|
7448
6997
|
className,
|
|
7449
6998
|
...props
|
|
7450
6999
|
}, ref) => {
|
|
7000
|
+
const locale = useLocale(localeProp);
|
|
7451
7001
|
if (!comparison) return null;
|
|
7452
|
-
const result = computeComparison(value, comparison, {
|
|
7453
|
-
|
|
7454
|
-
|
|
7002
|
+
const result = computeComparison(value, comparison, {
|
|
7003
|
+
polarity: betterWhen ? betterWhen === "down" ? "lower-is-better" : "higher-is-better" : polarity,
|
|
7004
|
+
neutralBand,
|
|
7005
|
+
locale
|
|
7006
|
+
});
|
|
7007
|
+
const display = change ?? defaultChangeDisplay(format);
|
|
7008
|
+
const formatDigits = typeof format === "object" && format !== null && "digits" in format ? format.digits : void 0;
|
|
7455
7009
|
const changeDigits = display === "points" ? digits ?? formatDigits : digits;
|
|
7456
7010
|
const comparable = result.direction !== "none";
|
|
7457
7011
|
const Icon = result.direction === "up" ? ArrowUp : result.direction === "down" ? ArrowDown : ArrowRight;
|
|
7458
|
-
const text = formatChange(result, display, locale,
|
|
7012
|
+
const text = formatChange(result, display, locale, format, changeDigits);
|
|
7459
7013
|
return /* @__PURE__ */ jsxs(
|
|
7460
7014
|
"span",
|
|
7461
7015
|
{
|
|
@@ -7464,7 +7018,7 @@ var Delta = forwardRef(
|
|
|
7464
7018
|
"data-slot": "delta",
|
|
7465
7019
|
"data-direction": result.direction,
|
|
7466
7020
|
"data-sentiment": result.sentiment,
|
|
7467
|
-
"aria-label": deltaAriaLabel(result, locale, display,
|
|
7021
|
+
"aria-label": deltaAriaLabel(result, locale, display, format, changeDigits),
|
|
7468
7022
|
className: cn(
|
|
7469
7023
|
deltaVariants({ variant, sentiment: result.sentiment }),
|
|
7470
7024
|
!comparable && "text-muted-foreground",
|
|
@@ -7489,7 +7043,69 @@ var LONG_VALUE_CHARS = 10;
|
|
|
7489
7043
|
var DELTA_UNDER_PLACEMENT = "col-start-1 row-span-1 row-start-3 justify-self-start";
|
|
7490
7044
|
var KPI_FOOTER_CLASS = "flex-col items-start gap-2 rounded-none border-t-0 bg-transparent pt-0 text-sm";
|
|
7491
7045
|
var PLACEHOLDER = /\{(\w+)\}/g;
|
|
7492
|
-
var
|
|
7046
|
+
var TEXT19 = {
|
|
7047
|
+
ja: {
|
|
7048
|
+
target: "\u76EE\u6A19",
|
|
7049
|
+
provisional: "\u901F\u5831",
|
|
7050
|
+
joiner: "\u30FB",
|
|
7051
|
+
countFrom: (count) => `${count}\u4EF6\u304B\u3089\u96C6\u8A08`,
|
|
7052
|
+
excluded: (count) => `${count}\u4EF6\u3092\u9664\u5916`,
|
|
7053
|
+
noBaseline: (baseline) => `${baseline}\u306E\u5B9F\u7E3E\u304C\u306A\u3044\u305F\u3081\u3001\u6BD4\u8F03\u3067\u304D\u307E\u305B\u3093\u3002`,
|
|
7054
|
+
previous: (baseline, value) => `${baseline} ${value}`,
|
|
7055
|
+
noPrevious: (baseline) => `${baseline}\u306E\u5B9F\u7E3E\u306A\u3057`,
|
|
7056
|
+
barLead: (tl, pct) => `${tl}\u306E ${pct}`,
|
|
7057
|
+
pace: (pct) => `\u3053\u306E\u30DA\u30FC\u30B9\u306A\u3089 ${pct}`,
|
|
7058
|
+
provisionalSuffix: "\uFF08\u78BA\u5B9A\u524D\uFF09",
|
|
7059
|
+
provisionalReached: (tl, target) => `${tl} ${target} \u306B\u5230\u9054\uFF08\u78BA\u5B9A\u524D\uFF09`,
|
|
7060
|
+
provisionalSoFar: (tl, target, pct) => `${tl} ${target} \u306B\u5BFE\u3057\u3066\u73FE\u6642\u70B9 ${pct}\uFF08\u78BA\u5B9A\u524D\uFF09`,
|
|
7061
|
+
provisionalToGo: (tl, target, distance) => `${tl} ${target} \u307E\u3067\u3042\u3068 ${distance}\uFF08\u78BA\u5B9A\u524D\uFF09`,
|
|
7062
|
+
provisionalToGoRate: (tl, distance, pct) => `${tl}\u307E\u3067\u3042\u3068 ${distance}\uFF08\u73FE\u6642\u70B9 ${pct}\u30FB\u78BA\u5B9A\u524D\uFF09`,
|
|
7063
|
+
met: (tl, target) => `${tl} ${target} \u3092\u9054\u6210`,
|
|
7064
|
+
toGo: (tl, target, distance) => `${tl} ${target} \u307E\u3067\u3042\u3068 ${distance}`,
|
|
7065
|
+
reached: (tl, target) => `${tl} ${target} \u306B\u5230\u9054`,
|
|
7066
|
+
reachedRate: (tl, target, pct) => `${tl} ${target} \u306B\u5230\u9054\uFF08${pct} \u9054\u6210\uFF09`,
|
|
7067
|
+
toGoRate: (tl, distance, pct) => `${tl}\u307E\u3067\u3042\u3068 ${distance}\uFF08${pct} \u9054\u6210\uFF09`,
|
|
7068
|
+
progressLabel: (tl) => `${tl}\u306B\u5BFE\u3059\u308B\u9032\u6357`,
|
|
7069
|
+
progressValue: (tl, target, value, pct) => `${tl} ${target} \u306B\u5BFE\u3057\u3066 ${value}\uFF08${pct}\uFF09`,
|
|
7070
|
+
history: (label2, points) => `${label2}\u306E\u63A8\u79FB\uFF08\u76F4\u8FD1 ${points} \u70B9\uFF09`,
|
|
7071
|
+
updatedRelative: (relative2) => `${relative2}\u306B\u66F4\u65B0`,
|
|
7072
|
+
updatedAbsolute: (absolute2) => `${absolute2} \u306B\u66F4\u65B0`,
|
|
7073
|
+
updatedBoth: (absolute2, relative2) => `${absolute2} \u306B\u66F4\u65B0\uFF08${relative2}\uFF09`,
|
|
7074
|
+
summaryExample: "{label}\u306F\u76EE\u6A19\u306E {achievement} \u307E\u3067\u6765\u3066\u3044\u307E\u3059\u3002"
|
|
7075
|
+
},
|
|
7076
|
+
en: {
|
|
7077
|
+
target: "Target",
|
|
7078
|
+
provisional: "Preliminary",
|
|
7079
|
+
joiner: " \xB7 ",
|
|
7080
|
+
countFrom: (count) => `Based on ${count} records`,
|
|
7081
|
+
excluded: (count) => `${count} excluded`,
|
|
7082
|
+
noBaseline: (baseline) => `No ${baseline} data to compare against.`,
|
|
7083
|
+
previous: (baseline, value) => `${capitalize(baseline)}: ${value}`,
|
|
7084
|
+
noPrevious: (baseline) => `No ${baseline} data`,
|
|
7085
|
+
barLead: (tl, pct) => `${tl}: ${pct}`,
|
|
7086
|
+
pace: (pct) => `On pace for ${pct}`,
|
|
7087
|
+
provisionalSuffix: " (preliminary)",
|
|
7088
|
+
provisionalReached: (tl, target) => `${tl} ${target}: reached (preliminary)`,
|
|
7089
|
+
provisionalSoFar: (tl, target, pct) => `${tl} ${target}: ${pct} so far (preliminary)`,
|
|
7090
|
+
provisionalToGo: (tl, target, distance) => `${tl} ${target}: ${distance} to go (preliminary)`,
|
|
7091
|
+
provisionalToGoRate: (tl, distance, pct) => `${tl}: ${distance} to go (${pct} so far, preliminary)`,
|
|
7092
|
+
met: (tl, target) => `${tl} ${target}: met`,
|
|
7093
|
+
toGo: (tl, target, distance) => `${tl} ${target}: ${distance} to go`,
|
|
7094
|
+
reached: (tl, target) => `${tl} ${target}: reached`,
|
|
7095
|
+
reachedRate: (tl, target, pct) => `${tl} ${target}: reached (${pct} achieved)`,
|
|
7096
|
+
toGoRate: (tl, distance, pct) => `${tl}: ${distance} to go (${pct} achieved)`,
|
|
7097
|
+
progressLabel: (tl) => `Progress toward ${tl}`,
|
|
7098
|
+
progressValue: (tl, target, value, pct) => `${value} of ${tl} ${target} (${pct})`,
|
|
7099
|
+
history: (label2, points) => `${label2} trend (last ${points} points)`,
|
|
7100
|
+
updatedRelative: (relative2) => `Updated ${relative2}`,
|
|
7101
|
+
updatedAbsolute: (absolute2) => `Updated ${absolute2}`,
|
|
7102
|
+
updatedBoth: (absolute2, relative2) => `Updated ${absolute2} (${relative2})`,
|
|
7103
|
+
summaryExample: "{label} is at {achievement} of target."
|
|
7104
|
+
}
|
|
7105
|
+
};
|
|
7106
|
+
function capitalize(text) {
|
|
7107
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
7108
|
+
}
|
|
7493
7109
|
var isMissing = (v) => v === null || v === void 0 || v === "";
|
|
7494
7110
|
function fillKpiTemplate(template, values, fallback) {
|
|
7495
7111
|
let missing = false;
|
|
@@ -7517,11 +7133,11 @@ function isProduction() {
|
|
|
7517
7133
|
return true;
|
|
7518
7134
|
}
|
|
7519
7135
|
}
|
|
7520
|
-
function warnShallowSummary(template) {
|
|
7136
|
+
function warnShallowSummary(template, t) {
|
|
7521
7137
|
if (shallowSummaryWarned || isProduction() || !isShallowSummary(template)) return;
|
|
7522
7138
|
shallowSummaryWarned = true;
|
|
7523
7139
|
console.warn(
|
|
7524
|
-
`[KpiCard] summary="${template}" only repeats the delta badge and the previous actual. Say one fact beyond the comparison \u2014 composition, target, record or rate (e.g. "{
|
|
7140
|
+
`[KpiCard] summary="${template}" only repeats the delta badge and the previous actual. Say one fact beyond the comparison \u2014 composition, target, record or rate (e.g. "${t.summaryExample}").`
|
|
7525
7141
|
);
|
|
7526
7142
|
}
|
|
7527
7143
|
function digitGroups(text) {
|
|
@@ -7530,18 +7146,19 @@ function digitGroups(text) {
|
|
|
7530
7146
|
function KpiCard({
|
|
7531
7147
|
label: label2,
|
|
7532
7148
|
value,
|
|
7533
|
-
format
|
|
7534
|
-
locale
|
|
7149
|
+
format,
|
|
7150
|
+
locale: localeProp,
|
|
7535
7151
|
comparison: comparisonProp,
|
|
7536
7152
|
comparisons,
|
|
7537
7153
|
provisional,
|
|
7538
|
-
|
|
7154
|
+
betterWhen,
|
|
7155
|
+
polarity: polarityProp,
|
|
7539
7156
|
change,
|
|
7540
7157
|
neutralBand,
|
|
7541
7158
|
showPrevious = true,
|
|
7542
7159
|
summary,
|
|
7543
7160
|
target,
|
|
7544
|
-
targetLabel
|
|
7161
|
+
targetLabel,
|
|
7545
7162
|
targetDisplay,
|
|
7546
7163
|
period,
|
|
7547
7164
|
history,
|
|
@@ -7557,21 +7174,24 @@ function KpiCard({
|
|
|
7557
7174
|
className,
|
|
7558
7175
|
...props
|
|
7559
7176
|
}) {
|
|
7177
|
+
const locale = useLocale(localeProp);
|
|
7178
|
+
const t = TEXT19[uiLanguage(locale)];
|
|
7560
7179
|
const allComparisons = [...comparisonProp ? [comparisonProp] : [], ...comparisons ?? []];
|
|
7561
7180
|
const comparison = allComparisons[0];
|
|
7562
7181
|
const isProvisional = provisional !== void 0 && provisional !== false;
|
|
7563
|
-
const provisionalLabel = typeof provisional === "object" && provisional.label ? provisional.label :
|
|
7182
|
+
const provisionalLabel = typeof provisional === "object" && provisional.label ? provisional.label : t.provisional;
|
|
7564
7183
|
const sample = useSampleMark();
|
|
7184
|
+
const polarity = betterWhen ? betterWhen === "down" ? "lower-is-better" : "higher-is-better" : polarityProp;
|
|
7565
7185
|
const neutral = polarity === "neutral";
|
|
7566
7186
|
const hasPrevious = comparison !== void 0 && showPrevious;
|
|
7567
7187
|
const stacked = allComparisons.length > 1;
|
|
7568
7188
|
const hasTarget = target !== void 0;
|
|
7569
7189
|
const grain = comparison?.grain ?? historyGrain ?? inferPeriodGrain(period);
|
|
7570
|
-
const record = isProvisional || neutral ? null : detectRecord(history, historyGrain ?? grain, polarity);
|
|
7190
|
+
const record = isProvisional || neutral ? null : detectRecord(history, historyGrain ?? grain, polarity, locale);
|
|
7571
7191
|
const sourceParts = source ? [
|
|
7572
7192
|
source.period !== void 0 ? formatDatesInText(source.period, locale) : void 0,
|
|
7573
|
-
source.count !== void 0 ?
|
|
7574
|
-
source.excluded !== void 0 && Number.isFinite(source.excluded) && source.excluded > 0 ?
|
|
7193
|
+
source.count !== void 0 ? t.countFrom(formatValue(source.count, "number", locale)) : void 0,
|
|
7194
|
+
source.excluded !== void 0 && Number.isFinite(source.excluded) && source.excluded > 0 ? t.excluded(formatValue(source.excluded, "number", locale)) : void 0,
|
|
7575
7195
|
source.name,
|
|
7576
7196
|
source.note
|
|
7577
7197
|
].filter((p) => typeof p === "string" && p !== "") : [];
|
|
@@ -7579,11 +7199,11 @@ function KpiCard({
|
|
|
7579
7199
|
const historyPoints = (history ?? []).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
7580
7200
|
const small = size === "sm";
|
|
7581
7201
|
const showSparkline = !small && showHistory && historyPoints.length >= SPARKLINE_MIN_POINTS;
|
|
7582
|
-
const isRate = formatKind(
|
|
7202
|
+
const isRate = formatKind(format) === "percent";
|
|
7583
7203
|
const byPoints = (targetDisplay ?? (isRate ? "points" : "achievement")) === "points";
|
|
7584
7204
|
const lower = polarity === "lower-is-better";
|
|
7585
7205
|
const targetBar = hasTarget && !neutral && !byPoints && !lower;
|
|
7586
|
-
if (summary !== void 0) warnShallowSummary(summary);
|
|
7206
|
+
if (summary !== void 0) warnShallowSummary(summary, t);
|
|
7587
7207
|
const cardClass = cn("row-span-2 grid content-start gap-y-0 grid-rows-subgrid", className);
|
|
7588
7208
|
const valueSize = small ? "text-xl @[218px]/card:text-2xl" : "text-2xl @[218px]/card:text-4xl";
|
|
7589
7209
|
if (isLoading) {
|
|
@@ -7625,15 +7245,15 @@ function KpiCard({
|
|
|
7625
7245
|
}
|
|
7626
7246
|
);
|
|
7627
7247
|
}
|
|
7628
|
-
const fmt = (v) => formatValue(v,
|
|
7248
|
+
const fmt = (v) => formatValue(v, format, locale);
|
|
7629
7249
|
const fmtDistance = (v) => isRate ? formatPoints(v, locale, { signDisplay: "never" }) : fmt(v);
|
|
7630
7250
|
const pct = (v) => formatValue(v, { type: "percent", digits: 0 }, locale);
|
|
7631
|
-
const tl = targetLabel;
|
|
7632
|
-
const display = change ?? defaultChangeDisplay(
|
|
7633
|
-
const digits = display === "points" && typeof
|
|
7251
|
+
const tl = targetLabel ?? t.target;
|
|
7252
|
+
const display = change ?? defaultChangeDisplay(format);
|
|
7253
|
+
const digits = display === "points" && typeof format === "object" && format !== null && "digits" in format ? format.digits : void 0;
|
|
7634
7254
|
const graded = comparison ? { ...comparison, grain } : void 0;
|
|
7635
|
-
const result = graded ? computeComparison(value, graded, { polarity, neutralBand }) : null;
|
|
7636
|
-
const baseline = graded ? comparisonBaseline(graded.vs, grain, graded.label, graded.toDate) : null;
|
|
7255
|
+
const result = graded ? computeComparison(value, graded, { polarity, neutralBand, locale }) : null;
|
|
7256
|
+
const baseline = graded ? comparisonBaseline(graded.vs, grain, graded.label, graded.toDate, locale) : null;
|
|
7637
7257
|
const progress = hasTarget && !neutral ? computeTargetProgress(value, target, { period, now, polarity }) : null;
|
|
7638
7258
|
const projectedValue = !isRate && !byPoints && progress?.projected != null && progress.elapsed ? value / progress.elapsed : null;
|
|
7639
7259
|
const summaryText = summary ? fillKpiTemplate(
|
|
@@ -7641,14 +7261,14 @@ function KpiCard({
|
|
|
7641
7261
|
{
|
|
7642
7262
|
value: fmt(value),
|
|
7643
7263
|
label: label2,
|
|
7644
|
-
delta: result ? formatChange(result, display, locale,
|
|
7645
|
-
difference: result?.difference != null ? isRate ? formatPoints(result.difference, locale) : formatDelta(result.difference,
|
|
7264
|
+
delta: result ? formatChange(result, display, locale, format, digits) : null,
|
|
7265
|
+
difference: result?.difference != null ? isRate ? formatPoints(result.difference, locale) : formatDelta(result.difference, format, locale) : null,
|
|
7646
7266
|
previous: result?.previous != null ? fmt(result.previous) : null,
|
|
7647
7267
|
target: hasTarget ? fmt(target) : null,
|
|
7648
7268
|
achievement: progress ? byPoints ? formatPoints(value - target, locale) : pct(progress.achievement) : null,
|
|
7649
7269
|
remaining: progress ? fmtDistance(progress.remaining) : null
|
|
7650
7270
|
},
|
|
7651
|
-
result && result.direction === "none" && baseline ?
|
|
7271
|
+
result && result.direction === "none" && baseline ? t.noBaseline(baseline) : null
|
|
7652
7272
|
) : null;
|
|
7653
7273
|
const bar = targetBar && progress ? progressBar() : null;
|
|
7654
7274
|
function progressBar() {
|
|
@@ -7656,9 +7276,9 @@ function KpiCard({
|
|
|
7656
7276
|
const projected = projectedValue !== null && projectedValue > actual ? projectedValue : actual;
|
|
7657
7277
|
const scale = Math.max(target, actual, projected);
|
|
7658
7278
|
const at = (v) => scale > 0 ? v / scale * 100 : 0;
|
|
7659
|
-
const parts = [
|
|
7279
|
+
const parts = [t.barLead(tl, pct(progress.achievement))];
|
|
7660
7280
|
if (projectedValue !== null && progress.projected != null)
|
|
7661
|
-
parts.push(
|
|
7281
|
+
parts.push(t.pace(formatValue(progress.projected, { type: "percent", digits: 0 }, locale)));
|
|
7662
7282
|
return {
|
|
7663
7283
|
actualAt: at(actual),
|
|
7664
7284
|
projectedAt: at(projected),
|
|
@@ -7671,13 +7291,13 @@ function KpiCard({
|
|
|
7671
7291
|
if (hasTarget && !bar) {
|
|
7672
7292
|
if (!progress) targetText = `${tl} ${fmt(target)}`;
|
|
7673
7293
|
else if (isProvisional)
|
|
7674
|
-
targetText = progress.achieved ? byPoints ?
|
|
7294
|
+
targetText = progress.achieved ? byPoints ? t.provisionalReached(tl, fmt(target)) : t.provisionalSoFar(tl, fmt(target), pct(progress.achievement)) : byPoints ? t.provisionalToGo(tl, fmt(target), fmtDistance(progress.remaining)) : t.provisionalToGoRate(tl, fmtDistance(progress.remaining), pct(progress.achievement));
|
|
7675
7295
|
else if (lower)
|
|
7676
|
-
targetText = progress.achieved ?
|
|
7296
|
+
targetText = progress.achieved ? t.met(tl, fmt(target)) : t.toGo(tl, fmt(target), fmtDistance(progress.remaining));
|
|
7677
7297
|
else if (byPoints)
|
|
7678
|
-
targetText = progress.achieved ?
|
|
7298
|
+
targetText = progress.achieved ? t.reached(tl, fmt(target)) : t.toGo(tl, fmt(target), fmtDistance(progress.remaining));
|
|
7679
7299
|
else
|
|
7680
|
-
targetText = progress.achieved ?
|
|
7300
|
+
targetText = progress.achieved ? t.reachedRate(tl, fmt(target), pct(progress.achievement)) : t.toGoRate(tl, fmtDistance(progress.remaining), pct(progress.achievement));
|
|
7681
7301
|
}
|
|
7682
7302
|
const hasFooter = Boolean(summaryText) || record !== null || Boolean(targetText) || sourceParts.length > 0 || hasUpdated || showSparkline;
|
|
7683
7303
|
const deltas = allComparisons.map((c, i) => /* @__PURE__ */ jsx(
|
|
@@ -7687,7 +7307,7 @@ function KpiCard({
|
|
|
7687
7307
|
comparison: i === 0 ? graded ?? c : { ...c, grain: c.grain ?? grain },
|
|
7688
7308
|
polarity,
|
|
7689
7309
|
neutralBand,
|
|
7690
|
-
format
|
|
7310
|
+
format,
|
|
7691
7311
|
change: display,
|
|
7692
7312
|
digits,
|
|
7693
7313
|
locale
|
|
@@ -7720,18 +7340,18 @@ function KpiCard({
|
|
|
7720
7340
|
}
|
|
7721
7341
|
),
|
|
7722
7342
|
comparison && (stacked ? /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-comparisons", className: "flex flex-wrap items-center gap-1", children: deltas }) : /* @__PURE__ */ jsx(CardAction, { className: longValue ? DELTA_UNDER_PLACEMENT : DELTA_PLACEMENT, children: deltas })),
|
|
7723
|
-
hasPrevious && comparison && /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-previous", className: "col-span-full text-sm text-muted-foreground tabular-nums", children: result?.previous != null ?
|
|
7343
|
+
hasPrevious && comparison && /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-previous", className: "col-span-full text-sm text-muted-foreground tabular-nums", children: result?.previous != null ? t.previous(baseline ?? "", fmt(result.previous)) : t.noPrevious(baseline ?? "") }),
|
|
7724
7344
|
bar && progress && /* @__PURE__ */ jsxs("div", { "data-slot": "kpi-card-target-progress", className: "col-span-full mt-1 flex min-w-0 flex-col gap-1.5", children: [
|
|
7725
7345
|
/* @__PURE__ */ jsxs(
|
|
7726
7346
|
"div",
|
|
7727
7347
|
{
|
|
7728
7348
|
"data-slot": "kpi-card-target-bar",
|
|
7729
7349
|
role: "progressbar",
|
|
7730
|
-
"aria-label":
|
|
7350
|
+
"aria-label": t.progressLabel(tl),
|
|
7731
7351
|
"aria-valuemin": 0,
|
|
7732
7352
|
"aria-valuemax": target,
|
|
7733
7353
|
"aria-valuenow": Math.min(Math.max(value, 0), target),
|
|
7734
|
-
"aria-valuetext":
|
|
7354
|
+
"aria-valuetext": t.progressValue(tl, fmt(target), fmt(value), pct(progress.achievement)),
|
|
7735
7355
|
className: "relative h-2 w-full overflow-hidden rounded-full bg-muted",
|
|
7736
7356
|
children: [
|
|
7737
7357
|
/* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 bg-chart-1", style: { width: `${bar.actualAt}%` } }),
|
|
@@ -7758,15 +7378,15 @@ function KpiCard({
|
|
|
7758
7378
|
"p",
|
|
7759
7379
|
{
|
|
7760
7380
|
"data-slot": "kpi-card-target",
|
|
7761
|
-
title: [bar.lead, bar.pace].filter(Boolean).join(
|
|
7381
|
+
title: [bar.lead, bar.pace].filter(Boolean).join(t.joiner),
|
|
7762
7382
|
className: "truncate text-sm text-muted-foreground tabular-nums",
|
|
7763
7383
|
children: [
|
|
7764
7384
|
bar.lead,
|
|
7765
7385
|
bar.pace && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7766
|
-
|
|
7386
|
+
t.joiner,
|
|
7767
7387
|
/* @__PURE__ */ jsx("span", { "data-slot": "kpi-card-projection", "data-estimate": "", children: bar.pace })
|
|
7768
7388
|
] }),
|
|
7769
|
-
isProvisional &&
|
|
7389
|
+
isProvisional && t.provisionalSuffix
|
|
7770
7390
|
]
|
|
7771
7391
|
}
|
|
7772
7392
|
)
|
|
@@ -7780,12 +7400,12 @@ function KpiCard({
|
|
|
7780
7400
|
"p",
|
|
7781
7401
|
{
|
|
7782
7402
|
"data-slot": "kpi-card-source",
|
|
7783
|
-
title: sourceParts.join(
|
|
7403
|
+
title: sourceParts.join(t.joiner),
|
|
7784
7404
|
className: "line-clamp-2 w-full text-xs leading-normal text-muted-foreground tabular-nums",
|
|
7785
|
-
children: sourceParts.join(
|
|
7405
|
+
children: sourceParts.join(t.joiner)
|
|
7786
7406
|
}
|
|
7787
7407
|
),
|
|
7788
|
-
hasUpdated && /* @__PURE__ */ jsx("p", { "data-slot": "kpi-card-updated", className: "text-xs leading-normal text-muted-foreground", children: updatedAtText(updatedAt, updatedAtDisplay, locale, now, timeZone) }),
|
|
7408
|
+
hasUpdated && /* @__PURE__ */ jsx("p", { "data-slot": "kpi-card-updated", className: "text-xs leading-normal text-muted-foreground", children: updatedAtText(updatedAt, updatedAtDisplay, locale, t, now, timeZone) }),
|
|
7789
7409
|
showSparkline && // mt-auto: the footers of a row are as tall as the tallest, so the sparklines share one bottom edge.
|
|
7790
7410
|
/* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-history", className: "mt-auto w-full pt-2 text-chart-1", children: /* @__PURE__ */ jsx(
|
|
7791
7411
|
Sparkline,
|
|
@@ -7794,23 +7414,35 @@ function KpiCard({
|
|
|
7794
7414
|
height: SPARKLINE_HEIGHT,
|
|
7795
7415
|
color: "text-chart-1",
|
|
7796
7416
|
highlight: "latest",
|
|
7797
|
-
"aria-label":
|
|
7417
|
+
"aria-label": t.history(label2, historyPoints.length)
|
|
7798
7418
|
}
|
|
7799
7419
|
) })
|
|
7800
7420
|
] })
|
|
7801
7421
|
] });
|
|
7802
7422
|
}
|
|
7803
|
-
function updatedAtText(updatedAt, display, locale, now, timeZone) {
|
|
7423
|
+
function updatedAtText(updatedAt, display, locale, t, now, timeZone) {
|
|
7804
7424
|
const relative2 = formatRelativeTime(updatedAt, { now, locale });
|
|
7805
|
-
if (display === "relative") return
|
|
7425
|
+
if (display === "relative") return t.updatedRelative(relative2);
|
|
7806
7426
|
const absolute2 = formatDate(updatedAt, "datetime", locale, { timeZone });
|
|
7807
|
-
return display === "absolute" ?
|
|
7427
|
+
return display === "absolute" ? t.updatedAbsolute(absolute2) : t.updatedBoth(absolute2, relative2);
|
|
7808
7428
|
}
|
|
7429
|
+
var TEXT20 = {
|
|
7430
|
+
ja: {
|
|
7431
|
+
flat: (value) => `\u5909\u5316\u306A\u3057 ${value}%`,
|
|
7432
|
+
up: (value) => `${value}% \u5897\u52A0`,
|
|
7433
|
+
down: (value) => `${value}% \u6E1B\u5C11`
|
|
7434
|
+
},
|
|
7435
|
+
en: {
|
|
7436
|
+
flat: (value) => `No change ${value}%`,
|
|
7437
|
+
up: (value) => `Up ${value}%`,
|
|
7438
|
+
down: (value) => `Down ${value}%`
|
|
7439
|
+
}
|
|
7440
|
+
};
|
|
7809
7441
|
var trendIndicatorVariants = cva("inline-flex items-center gap-0.5 text-sm font-medium", {
|
|
7810
7442
|
variants: {
|
|
7811
7443
|
sentiment: {
|
|
7812
|
-
positive: "text-
|
|
7813
|
-
negative: "text-
|
|
7444
|
+
positive: "text-positive",
|
|
7445
|
+
negative: "text-negative",
|
|
7814
7446
|
neutral: "text-muted-foreground"
|
|
7815
7447
|
}
|
|
7816
7448
|
},
|
|
@@ -7823,7 +7455,8 @@ var TrendIndicator = forwardRef(
|
|
|
7823
7455
|
const isGood = direction === "neutral" ? null : direction === "up" === positiveIsGood;
|
|
7824
7456
|
const sentiment = isGood === null ? "neutral" : isGood ? "positive" : "negative";
|
|
7825
7457
|
const Icon = direction === "up" ? ArrowUp : direction === "down" ? ArrowDown : Minus;
|
|
7826
|
-
const
|
|
7458
|
+
const t = TEXT20[uiLanguage(useLocale())];
|
|
7459
|
+
const ariaLabel = direction === "neutral" ? t.flat(value) : direction === "up" ? t.up(value) : t.down(value);
|
|
7827
7460
|
return /* @__PURE__ */ jsxs(
|
|
7828
7461
|
"span",
|
|
7829
7462
|
{
|
|
@@ -7843,21 +7476,49 @@ var TrendIndicator = forwardRef(
|
|
|
7843
7476
|
}
|
|
7844
7477
|
);
|
|
7845
7478
|
TrendIndicator.displayName = "TrendIndicator";
|
|
7479
|
+
var STATUS_LABELS = {
|
|
7480
|
+
ja: {
|
|
7481
|
+
success: "\u6B63\u5E38",
|
|
7482
|
+
partial: "\u4E00\u90E8\u5931\u6557",
|
|
7483
|
+
failed: "\u5931\u6557",
|
|
7484
|
+
delayed: "\u9045\u5EF6",
|
|
7485
|
+
running: "\u5B9F\u884C\u4E2D",
|
|
7486
|
+
stopped: "\u505C\u6B62\u4E2D",
|
|
7487
|
+
active: "\u6709\u52B9",
|
|
7488
|
+
inactive: "\u7121\u52B9",
|
|
7489
|
+
warning: "\u8B66\u544A",
|
|
7490
|
+
error: "\u30A8\u30E9\u30FC",
|
|
7491
|
+
pending: "\u4FDD\u7559\u4E2D"
|
|
7492
|
+
},
|
|
7493
|
+
en: {
|
|
7494
|
+
success: "Healthy",
|
|
7495
|
+
partial: "Partially failed",
|
|
7496
|
+
failed: "Failed",
|
|
7497
|
+
delayed: "Delayed",
|
|
7498
|
+
running: "Running",
|
|
7499
|
+
stopped: "Stopped",
|
|
7500
|
+
active: "Active",
|
|
7501
|
+
inactive: "Inactive",
|
|
7502
|
+
warning: "Warning",
|
|
7503
|
+
error: "Error",
|
|
7504
|
+
pending: "Pending"
|
|
7505
|
+
}
|
|
7506
|
+
};
|
|
7846
7507
|
var STATUS_VOCABULARY = {
|
|
7847
|
-
success: { label:
|
|
7848
|
-
partial: { label:
|
|
7849
|
-
failed: { label:
|
|
7850
|
-
delayed: { label:
|
|
7851
|
-
running: { label:
|
|
7852
|
-
stopped: { label:
|
|
7853
|
-
active: { label:
|
|
7854
|
-
inactive: { label:
|
|
7855
|
-
warning: { label:
|
|
7856
|
-
error: { label:
|
|
7857
|
-
pending: { label:
|
|
7508
|
+
success: { label: STATUS_LABELS.en.success, tone: "positive" },
|
|
7509
|
+
partial: { label: STATUS_LABELS.en.partial, tone: "warning" },
|
|
7510
|
+
failed: { label: STATUS_LABELS.en.failed, tone: "negative" },
|
|
7511
|
+
delayed: { label: STATUS_LABELS.en.delayed, tone: "warning" },
|
|
7512
|
+
running: { label: STATUS_LABELS.en.running, tone: "info" },
|
|
7513
|
+
stopped: { label: STATUS_LABELS.en.stopped, tone: "neutral" },
|
|
7514
|
+
active: { label: STATUS_LABELS.en.active, tone: "positive" },
|
|
7515
|
+
inactive: { label: STATUS_LABELS.en.inactive, tone: "neutral" },
|
|
7516
|
+
warning: { label: STATUS_LABELS.en.warning, tone: "warning" },
|
|
7517
|
+
error: { label: STATUS_LABELS.en.error, tone: "negative" },
|
|
7518
|
+
pending: { label: STATUS_LABELS.en.pending, tone: "info" }
|
|
7858
7519
|
};
|
|
7859
|
-
function statusLabel(status) {
|
|
7860
|
-
return Object.hasOwn(STATUS_VOCABULARY, status) ?
|
|
7520
|
+
function statusLabel(status, locale) {
|
|
7521
|
+
return Object.hasOwn(STATUS_VOCABULARY, status) ? STATUS_LABELS[uiLanguage(resolveLocale(locale))][status] : status;
|
|
7861
7522
|
}
|
|
7862
7523
|
var defaultColorMap = Object.fromEntries(
|
|
7863
7524
|
Object.entries(STATUS_VOCABULARY).map(([key, { tone }]) => [key, tone])
|
|
@@ -7870,11 +7531,11 @@ var legacyColorTones = {
|
|
|
7870
7531
|
blue: "info"
|
|
7871
7532
|
};
|
|
7872
7533
|
var toneStyles = {
|
|
7873
|
-
positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive" },
|
|
7874
|
-
negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative" },
|
|
7875
|
-
warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning" },
|
|
7876
|
-
info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info" },
|
|
7877
|
-
neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral" }
|
|
7534
|
+
positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive", border: "border-positive/20 dark:border-positive/25" },
|
|
7535
|
+
negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative", border: "border-negative/20 dark:border-negative/25" },
|
|
7536
|
+
warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning", border: "border-warning/20 dark:border-warning/25" },
|
|
7537
|
+
info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info", border: "border-info/20 dark:border-info/25" },
|
|
7538
|
+
neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral", border: "border-neutral/20 dark:border-neutral/25" }
|
|
7878
7539
|
};
|
|
7879
7540
|
var resolveTone = (color) => {
|
|
7880
7541
|
if (color === void 0) return "neutral";
|
|
@@ -7882,19 +7543,20 @@ var resolveTone = (color) => {
|
|
|
7882
7543
|
return legacyColorTones[color] ?? "neutral";
|
|
7883
7544
|
};
|
|
7884
7545
|
var StatusBadge = forwardRef(function StatusBadge2({ status, label: label2, colorMap, className }, ref) {
|
|
7546
|
+
const locale = useLocale();
|
|
7885
7547
|
const mergedColorMap = { ...defaultColorMap, ...colorMap };
|
|
7886
7548
|
const style = toneStyles[resolveTone(mergedColorMap[status])];
|
|
7887
|
-
const displayLabel = label2 ?? statusLabel(status);
|
|
7549
|
+
const displayLabel = label2 ?? statusLabel(status, locale);
|
|
7888
7550
|
return /* @__PURE__ */ jsxs(
|
|
7889
7551
|
Badge,
|
|
7890
7552
|
{
|
|
7891
7553
|
ref,
|
|
7892
7554
|
"data-slot": "status-badge",
|
|
7893
7555
|
variant: "outline",
|
|
7894
|
-
className: cn("gap-1.5
|
|
7556
|
+
className: cn("gap-1.5 rounded-md", style.border, style.bg, style.text, className),
|
|
7895
7557
|
"aria-label": displayLabel,
|
|
7896
7558
|
children: [
|
|
7897
|
-
/* @__PURE__ */ jsx("span", { className: cn("inline-block size-
|
|
7559
|
+
/* @__PURE__ */ jsx("span", { className: cn("inline-block size-1.5 rounded-full", style.dot), "aria-hidden": "true" }),
|
|
7898
7560
|
displayLabel
|
|
7899
7561
|
]
|
|
7900
7562
|
}
|
|
@@ -7914,6 +7576,6 @@ var Placeholder = forwardRef(function Placeholder2({ className, ...props }, ref)
|
|
|
7914
7576
|
});
|
|
7915
7577
|
Placeholder.displayName = "Placeholder";
|
|
7916
7578
|
|
|
7917
|
-
export { AppShell, AreaChart,
|
|
7918
|
-
//# sourceMappingURL=chunk-
|
|
7919
|
-
//# sourceMappingURL=chunk-
|
|
7579
|
+
export { AppShell, AreaChart, BarChart, BarList, COMPARISON_LABELS, CategoryBar, ChartFrame, DEFAULT_SAMPLE_LABEL, DELTA_NOT_COMPARABLE, DashboardCard, DashboardCardAction, DashboardCardContent, DashboardCardDescription, DashboardCardFooter, DashboardCardHeader, DashboardCardPreset, DashboardCardSkeleton, DashboardCardTitle, DataTable, DataTableColumnVisibility, DataTableContent, DataTableExport, DataTablePagination, DataTablePreset, DataTableToolbar, DateRangePicker, Delta, DonutChart, FilterBar, FilterBarActiveChips, FilterBarClearButton, FilterBarMultiSelect, FilterBarPreset, FilterBarSelect, FunnelSteps, Heatmap, KpiCard, Legend, LineChart, MetricUnit, MetricValue, MultiSelect, PageShell, PageShellActions, PageShellContent, PageShellDescription, PageShellHeader, PageShellHeaderEnd, PageShellHeading, PageShellMeta, PageShellSummary, PageShellSummaryCard, PageShellTitle, Placeholder, ProgressCircle, RECORD_MIN_POINTS, SampleBadge, SampleClaim, SampleData, ScatterChart, SearchableSelect, SectionHeader, SegmentedControl, StatusBadge, Tracker, TrendIndicator, UpdatedAt, WaterfallChart, comparisonBaseline, comparisonLabel, computeComparison, computeTargetProgress, defaultChangeDisplay, defaultPresets, deltaVariants, detectRecord, fillKpiTemplate, flattenOptions, formatChange, formatChangeAmount, formatRelativeTime, funnelStepsVariants, inferPeriodGrain, isGroupedOptions, metricValueVariants, pageShellSummaryCardVariants, tableToCsv, toCsv, toneForValue, useDataTable, useSampleMark };
|
|
7580
|
+
//# sourceMappingURL=chunk-77CISBMG.js.map
|
|
7581
|
+
//# sourceMappingURL=chunk-77CISBMG.js.map
|