@squadbase/vantage 0.7.0-dev1.3b0e616 → 0.7.0-dev1.6e23119
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/{chunk-NYQJ5UY4.js → chunk-DULE4EDK.js} +2008 -273
- package/dist/chunk-DULE4EDK.js.map +1 -0
- package/dist/{chunk-TRMHNMMZ.js → chunk-LYUGDHSF.js} +3 -3
- package/dist/{chunk-TRMHNMMZ.js.map → chunk-LYUGDHSF.js.map} +1 -1
- package/dist/{chunk-QNOX7WLZ.js → chunk-MQUIAP66.js} +69 -4
- package/dist/chunk-MQUIAP66.js.map +1 -0
- package/dist/{chunk-2IAPIOPS.js → chunk-P2KIHF65.js} +2 -2
- package/dist/chunk-P2KIHF65.js.map +1 -0
- package/dist/{chunk-3RJEOP3J.js → chunk-XRKSIC5Z.js} +5 -3
- package/dist/chunk-XRKSIC5Z.js.map +1 -0
- package/dist/components/index.d.ts +276 -6
- package/dist/components/index.js +4 -4
- package/dist/{delta-text-CbrOaW83.d.ts → delta-text-tav2Lh5d.d.ts} +1 -1
- package/dist/doc/index.d.ts +2 -2
- package/dist/doc/index.js +4 -4
- package/dist/{format-DihQkL1N.d.ts → format-D34piCei.d.ts} +2 -1
- package/dist/slide/index.d.ts +2 -2
- package/dist/slide/index.js +3 -3
- package/dist/table/index.js +4 -5
- package/dist/table/index.js.map +1 -1
- package/dist/ui/index.js +2 -3
- package/dist/ui/index.js.map +1 -1
- package/docs/en/parts/draft-chart.md +42 -0
- package/docs/en/parts/page-shell.md +1 -1
- package/docs/index.json +68 -48
- package/docs/ja/parts/draft-chart.md +40 -0
- package/docs/ja/parts/page-shell.md +1 -1
- package/package.json +2 -2
- package/registry/parts.json +5214 -0
- package/registry/ui/chart-frame.tsx +8 -0
- package/registry/ui/combo-chart.tsx +2 -1
- package/registry/ui/dashboard-card.tsx +3 -1
- package/registry/ui/data-table.tsx +3 -1
- package/registry/ui/delta.tsx +3 -1
- package/registry/ui/filter-bar.tsx +3 -1
- package/registry/ui/forecast-chart.tsx +4726 -0
- package/registry/ui/funnel-steps.tsx +1 -1
- package/registry/ui/kpi-card.tsx +3 -1
- package/registry/ui/metric-value.tsx +2 -2
- package/registry/ui/page-shell.tsx +25 -4
- package/registry/ui/paired-chart.tsx +1 -1
- package/registry/ui/pivot-table.tsx +2 -1
- package/registry/ui/progress-circle.tsx +2 -2
- package/registry/ui/sparkline.tsx +1 -1
- package/registry/ui/treemap.tsx +2 -1
- package/dist/chunk-2IAPIOPS.js.map +0 -1
- package/dist/chunk-3RJEOP3J.js.map +0 -1
- package/dist/chunk-NYQJ5UY4.js.map +0 -1
- package/dist/chunk-NZ5QIIG4.js +0 -74
- package/dist/chunk-NZ5QIIG4.js.map +0 -1
- package/dist/chunk-QNOX7WLZ.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ChartFrameContext, useChartSurface, resolveChartColors,
|
|
2
|
-
import { Sparkline } from './chunk-
|
|
3
|
-
import { formatDateRange, EMPTY_VALUE,
|
|
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-
|
|
1
|
+
import { ChartFrameContext, useChartSurface, resolveChartColors, resolveFillColors, EChart, CHART_OTHER_COLOR } from './chunk-EG4PX726.js';
|
|
2
|
+
import { Sparkline } from './chunk-P2KIHF65.js';
|
|
3
|
+
import { formatDateRange, EMPTY_VALUE, toValueFormatter, formatDate, formatValue, formatPoints, formatKind, formatDelta, MINUS_SIGN, DEFAULT_LOCALE, formatDatesInText } from './chunk-XRKSIC5Z.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, Empty, Checkbox, Card, CardHeader, CardDescription, CardTitle, CardAction, CardFooter } from './chunk-MQUIAP66.js';
|
|
5
5
|
import { useLocale, uiLanguage, Button, weekStartsOn, resolveLocale, defaultFiscalYearStartMonth, FALLBACK_LOCALE } from './chunk-ROHNXP7J.js';
|
|
6
6
|
import { cn } from './chunk-U736PVHY.js';
|
|
7
|
-
import { forwardRef, useState, useEffect, createContext, useId, useMemo, useRef, useCallback, Fragment as Fragment$1, useContext } from 'react';
|
|
7
|
+
import { forwardRef, useState, useEffect, createContext, useId, useMemo, useRef, useCallback, Fragment as Fragment$1, useContext, useInsertionEffect, useLayoutEffect } from 'react';
|
|
8
8
|
import { cva } from 'class-variance-authority';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
10
|
import { Search, Columns3, CalendarIcon, ChevronDownIcon, ArrowUp, ArrowDown, ArrowRight, Minus, ChevronRight, ArrowUpDown, XIcon, LoaderIcon, CheckIcon, Download, ChevronDown, X, CircleX, TriangleAlert, CircleCheck } from 'lucide-react';
|
|
@@ -12,8 +12,8 @@ import { use, registerMap } from 'echarts/core';
|
|
|
12
12
|
import { GraphicComponent, VisualMapComponent, GeoComponent } from 'echarts/components';
|
|
13
13
|
import { ScatterChart as ScatterChart$1, HeatmapChart, MapChart, TreemapChart } from 'echarts/charts';
|
|
14
14
|
import 'echarts';
|
|
15
|
+
import { subMonths, subDays, endOfDay, startOfDay, startOfWeek, subWeeks, endOfWeek, startOfMonth, endOfMonth, isSameDay, addMonths, differenceInCalendarDays, parseISO } from 'date-fns';
|
|
15
16
|
import { flexRender, useReactTable, getPaginationRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
|
|
16
|
-
import { subMonths, subDays, endOfDay, startOfDay, startOfWeek, subWeeks, endOfWeek, startOfMonth, endOfMonth, isSameDay, addMonths } from 'date-fns';
|
|
17
17
|
import { ja } from 'date-fns/locale';
|
|
18
18
|
|
|
19
19
|
// @squadbase/vantage — generated build. Do not edit.
|
|
@@ -127,7 +127,13 @@ var UpdatedAt = forwardRef(
|
|
|
127
127
|
);
|
|
128
128
|
UpdatedAt.displayName = "UpdatedAt";
|
|
129
129
|
var PageShell = forwardRef(
|
|
130
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "page-shell", className: cn("flex flex-col", className), ...props
|
|
130
|
+
({ className, title, description, children, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "page-shell", className: cn("flex flex-col", className), ...props, children: title === void 0 ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
131
|
+
/* @__PURE__ */ jsx(PageShellHeader, { children: /* @__PURE__ */ jsxs(PageShellHeading, { children: [
|
|
132
|
+
/* @__PURE__ */ jsx(PageShellTitle, { children: title }),
|
|
133
|
+
description ? /* @__PURE__ */ jsx(PageShellDescription, { children: description }) : null
|
|
134
|
+
] }) }),
|
|
135
|
+
/* @__PURE__ */ jsx(PageShellContent, { children })
|
|
136
|
+
] }) })
|
|
131
137
|
);
|
|
132
138
|
PageShell.displayName = "PageShell";
|
|
133
139
|
var SOURCE_PREFIX = { ja: "\u51FA\u5178\uFF1A", en: "Source: " };
|
|
@@ -690,6 +696,7 @@ var ChartFrame = forwardRef(function ChartFrame2({
|
|
|
690
696
|
ariaLabel,
|
|
691
697
|
plotRole = "img",
|
|
692
698
|
dataTable,
|
|
699
|
+
footnote,
|
|
693
700
|
className,
|
|
694
701
|
children,
|
|
695
702
|
...props
|
|
@@ -720,6 +727,7 @@ var ChartFrame = forwardRef(function ChartFrame2({
|
|
|
720
727
|
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 })
|
|
721
728
|
}
|
|
722
729
|
),
|
|
730
|
+
footnote && /* @__PURE__ */ jsx("p", { "data-slot": "chart-frame-footnote", className: "text-xs leading-snug text-muted-foreground", children: footnote }),
|
|
723
731
|
state === "ready" && dataTable && dataTable.rows.length > 0 && /* @__PURE__ */ jsx(ChartDataTableView, { table: dataTable, fallbackCaption: title ?? ariaLabel })
|
|
724
732
|
] });
|
|
725
733
|
});
|
|
@@ -743,7 +751,7 @@ function ChartDataTableView({ table, fallbackCaption }) {
|
|
|
743
751
|
caption && /* @__PURE__ */ jsx("caption", { children: caption }),
|
|
744
752
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: table.columns.map((column, i) => /* @__PURE__ */ jsx("th", { scope: "col", children: column }, i)) }) }),
|
|
745
753
|
/* @__PURE__ */ jsx("tbody", { children: table.rows.map((row, r) => /* @__PURE__ */ jsx("tr", { children: row.map(
|
|
746
|
-
(
|
|
754
|
+
(cell2, c) => c === 0 ? /* @__PURE__ */ jsx("th", { scope: "row", children: cell2 }, c) : /* @__PURE__ */ jsx("td", { children: cell2 }, c)
|
|
747
755
|
) }, r)) })
|
|
748
756
|
] }) });
|
|
749
757
|
}
|
|
@@ -800,8 +808,8 @@ function chartColorAt(colors, i) {
|
|
|
800
808
|
const palette = colors && colors.length > 0 ? colors : DEFAULT_CHART_COLORS;
|
|
801
809
|
return palette[i % palette.length];
|
|
802
810
|
}
|
|
803
|
-
function tintCss(cssColor,
|
|
804
|
-
return `color-mix(in oklab, ${cssColor} ${
|
|
811
|
+
function tintCss(cssColor, percent2) {
|
|
812
|
+
return `color-mix(in oklab, ${cssColor} ${percent2}%, transparent)`;
|
|
805
813
|
}
|
|
806
814
|
function resolveValueFormatter(valueFormatter, format, locale) {
|
|
807
815
|
return valueFormatter ?? toValueFormatter(format, locale);
|
|
@@ -1217,20 +1225,20 @@ function baselineOfLabel(named, language) {
|
|
|
1217
1225
|
}
|
|
1218
1226
|
return named;
|
|
1219
1227
|
}
|
|
1220
|
-
function comparisonBaseline(vs, grain, label2,
|
|
1228
|
+
function comparisonBaseline(vs, grain, label2, toDate3, locale) {
|
|
1221
1229
|
const language = uiLanguage(resolveLocale(locale));
|
|
1222
1230
|
const nouns = BASELINE_NOUNS[language];
|
|
1223
1231
|
const named = label2?.trim();
|
|
1224
1232
|
if (named) return baselineOfLabel(named, language);
|
|
1225
|
-
if (vs === "custom") return nouns.custom;
|
|
1226
1233
|
if (vs === "target") return nouns.target;
|
|
1227
|
-
if (vs === "prior-year" &&
|
|
1234
|
+
if (vs === "prior-year" && toDate3) return nouns["prior-year"].unknown;
|
|
1235
|
+
if (vs !== "prior-year" && vs !== "prior-period") return nouns.custom;
|
|
1228
1236
|
return nouns[vs][grain ?? "unknown"];
|
|
1229
1237
|
}
|
|
1230
|
-
function comparisonLabel(vs, grain, label2,
|
|
1238
|
+
function comparisonLabel(vs, grain, label2, toDate3, locale) {
|
|
1231
1239
|
if (label2?.trim()) return label2;
|
|
1232
1240
|
const resolved = resolveLocale(locale);
|
|
1233
|
-
return LABEL_OF[uiLanguage(resolved)](comparisonBaseline(vs, grain, void 0,
|
|
1241
|
+
return LABEL_OF[uiLanguage(resolved)](comparisonBaseline(vs, grain, void 0, toDate3, resolved));
|
|
1234
1242
|
}
|
|
1235
1243
|
var toNumber = (v) => v === null || v === void 0 || Number.isNaN(v) ? null : v;
|
|
1236
1244
|
function computeComparison(current, comparison, options) {
|
|
@@ -1740,9 +1748,9 @@ function buildCartesianOption(cfg) {
|
|
|
1740
1748
|
const text = chartText(locale);
|
|
1741
1749
|
const provisionalLabel = cfg.provisionalLabel ?? text.provisional;
|
|
1742
1750
|
const stacked = kind !== "line" && type !== "default";
|
|
1743
|
-
const
|
|
1751
|
+
const percent2 = kind !== "line" && type === "percent";
|
|
1744
1752
|
const horizontalBars = kind === "bar" && layout === "vertical";
|
|
1745
|
-
const comparison = kind !== "bar" && !
|
|
1753
|
+
const comparison = kind !== "bar" && !percent2 ? cfg.comparison : void 0;
|
|
1746
1754
|
const compIdx = comparison ? categories.indexOf(comparison.category) : -1;
|
|
1747
1755
|
const mainIdx = categories.map((_, i) => i).filter((i) => i !== compIdx);
|
|
1748
1756
|
const seriesType = kind === "line" ? "default" : type;
|
|
@@ -1757,11 +1765,11 @@ function buildCartesianOption(cfg) {
|
|
|
1757
1765
|
const rawIndex = data.map((row) => row[index]);
|
|
1758
1766
|
const lastActual = labels.length - 1;
|
|
1759
1767
|
const provStart = categories.length > 0 ? provisionalStart(rawIndex, cfg.provisionalFrom) : -1;
|
|
1760
|
-
const
|
|
1768
|
+
const forecast2 = kind !== "bar" && !percent2 && cfg.forecast && cfg.forecast.data.length > 0 && data.length > 0 && categories.length > 0 ? cfg.forecast : void 0;
|
|
1761
1769
|
const forecastAt = [];
|
|
1762
|
-
if (
|
|
1770
|
+
if (forecast2) {
|
|
1763
1771
|
const position = new Map(labels.map((label2, i) => [label2, i]));
|
|
1764
|
-
for (const row of
|
|
1772
|
+
for (const row of forecast2.data) {
|
|
1765
1773
|
const label2 = String(row[index] ?? "");
|
|
1766
1774
|
let at = position.get(label2);
|
|
1767
1775
|
if (at === void 0 || at <= lastActual) {
|
|
@@ -1798,14 +1806,14 @@ function buildCartesianOption(cfg) {
|
|
|
1798
1806
|
(title, i) => nameLabels ? hasLabel(nameLabels, labels[i] ?? "") ? labelOf(labels[i] ?? "", nameLabels) : title : title
|
|
1799
1807
|
);
|
|
1800
1808
|
const highlight = cfg.highlight ?? defaultChartHighlight(kind, data, index);
|
|
1801
|
-
const stackTotals = stacked && !
|
|
1809
|
+
const stackTotals = stacked && !percent2 ? stackTotalsOf(mainIdx.map((i) => values[i])) : null;
|
|
1802
1810
|
const highlightSeries = (stackTotals ? mainIdx[mainIdx.length - 1] : mainIdx[0]) ?? 0;
|
|
1803
|
-
const shareHighlight =
|
|
1804
|
-
const picked = highlight !== "auto" || mainIdx.length === 0 ||
|
|
1811
|
+
const shareHighlight = percent2 && kind === "area";
|
|
1812
|
+
const picked = highlight !== "auto" || mainIdx.length === 0 || percent2 && !shareHighlight ? [] : shareHighlight ? categories.length <= 2 ? pickShareHighlightPoints(values[0] ?? []) : [] : stackTotals ? pickHighlightPoints(stackTotals) : mainIdx.length <= 2 ? pickHighlightPoints(values[highlightSeries] ?? []) : [];
|
|
1805
1813
|
const pointGap = plotWidth && labels.length > 1 ? plotWidth / (kind === "bar" ? labels.length : labels.length - 1) : null;
|
|
1806
1814
|
const latestOnly = cfg.highlight === void 0 && !shareHighlight && picked.length === 2;
|
|
1807
1815
|
const highlightPoints = latestOnly ? [picked[1]] : picked.length === 2 && pointGap !== null && Math.abs(picked[1].index - picked[0].index) * pointGap < HIGHLIGHT_LABEL_WIDTH ? [picked[1]] : picked;
|
|
1808
|
-
const boundaryIndex = kind !== "bar" && !
|
|
1816
|
+
const boundaryIndex = kind !== "bar" && !percent2 && cfg.forecast && cfg.forecast.data.length > 0 ? lastActual : -1;
|
|
1809
1817
|
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;
|
|
1810
1818
|
const perBarTarget = kind === "bar" && Boolean(targetKey);
|
|
1811
1819
|
const hasTarget = !perBarTarget && target !== void 0 && Number.isFinite(target);
|
|
@@ -1826,7 +1834,7 @@ function buildCartesianOption(cfg) {
|
|
|
1826
1834
|
const hideTargetLabel = kind === "line" && targetLabelPosition === "legend" || !shareHighlight && plotWidth !== void 0 && plotWidth < TARGET_LABEL_NARROW_WIDTH && highlightPoints.some((p) => p.index === labels.length - 1 && (nearTargetLabel(p, "under") || nearTargetLabel(p, "over")));
|
|
1827
1835
|
const below = (p) => !shareHighlight && !hideTargetLabel && nearTargetLabel(p, "under");
|
|
1828
1836
|
const targetLabelBelow = !shareHighlight && !hideTargetLabel && highlightPoints.some((p) => nearTargetLabel(p, "over"));
|
|
1829
|
-
const barTargets = perBarTarget && targetKey && !
|
|
1837
|
+
const barTargets = perBarTarget && targetKey && !percent2 && (stacked || categories.length === 1) ? barTargetValues(data, targetKey) : null;
|
|
1830
1838
|
const barTargetName = targetLabel ?? text.target;
|
|
1831
1839
|
const barTargetColor = labelColor ?? guideColor;
|
|
1832
1840
|
const markPointFor = (c, color) => c === highlightSeries && highlightPoints.length > 0 ? {
|
|
@@ -1951,7 +1959,7 @@ function buildCartesianOption(cfg) {
|
|
|
1951
1959
|
symbolSize: 6,
|
|
1952
1960
|
showSymbol: showDots || data.length === 1,
|
|
1953
1961
|
// 100% stacked: the top band's upper edge is the 100% line, not a value — drawn, it reads as「this band = 100%」.
|
|
1954
|
-
lineStyle:
|
|
1962
|
+
lineStyle: percent2 && c === categories.length - 1 ? { width: 0, color, opacity: 0 } : { width: 2, color, opacity: dimSeries ? DIMMED : 1 },
|
|
1955
1963
|
itemStyle: { color, opacity: dimSeries ? DIMMED : 1 },
|
|
1956
1964
|
// Hovering a series fades the others (not for a stack, where the bands read together).
|
|
1957
1965
|
emphasis: stacked ? void 0 : { focus: "series" },
|
|
@@ -1980,7 +1988,7 @@ function buildCartesianOption(cfg) {
|
|
|
1980
1988
|
symbol: "circle",
|
|
1981
1989
|
symbolSize: 6,
|
|
1982
1990
|
showSymbol: showDots || data.length === 1,
|
|
1983
|
-
lineStyle:
|
|
1991
|
+
lineStyle: percent2 && c === categories.length - 1 ? { width: 0, color, opacity: 0 } : { width: 2, type: "dashed", color, opacity },
|
|
1984
1992
|
itemStyle: { color, opacity },
|
|
1985
1993
|
areaStyle: solid.areaStyle ? { ...solid.areaStyle, opacity: (solid.areaStyle.opacity ?? 1) * PROVISIONAL_OPACITY } : void 0,
|
|
1986
1994
|
markPoint: void 0,
|
|
@@ -2006,11 +2014,11 @@ function buildCartesianOption(cfg) {
|
|
|
2006
2014
|
data: []
|
|
2007
2015
|
});
|
|
2008
2016
|
}
|
|
2009
|
-
const forecastLabel =
|
|
2017
|
+
const forecastLabel = forecast2?.label ?? text.forecast;
|
|
2010
2018
|
const forecastBandAlpha = isDarkSurface(labelBackground) ? FORECAST_BAND_ALPHA_DARK : FORECAST_BAND_ALPHA_LIGHT;
|
|
2011
2019
|
const forecastValues = [];
|
|
2012
|
-
if (
|
|
2013
|
-
const category =
|
|
2020
|
+
if (forecast2) {
|
|
2021
|
+
const category = forecast2.category !== void 0 && categories.includes(forecast2.category) && forecast2.category !== comparison?.category ? forecast2.category : categories[mainIdx[0] ?? 0];
|
|
2014
2022
|
const c = categories.indexOf(category);
|
|
2015
2023
|
const color = palette[c] || void 0;
|
|
2016
2024
|
const actual = values[c];
|
|
@@ -2030,7 +2038,7 @@ function buildCartesianOption(cfg) {
|
|
|
2030
2038
|
range[start] = 0;
|
|
2031
2039
|
}
|
|
2032
2040
|
let hasBand = false;
|
|
2033
|
-
|
|
2041
|
+
forecast2.data.forEach((row, k) => {
|
|
2034
2042
|
const at = forecastAt[k];
|
|
2035
2043
|
line[at] = cellNumber(row.value);
|
|
2036
2044
|
const lo = cellNumber(row.lower);
|
|
@@ -2096,7 +2104,7 @@ function buildCartesianOption(cfg) {
|
|
|
2096
2104
|
const totals = labels.map(
|
|
2097
2105
|
(_, i) => stacked ? values.reduce((sum, v) => sum + Math.max(0, v[i] ?? 0), 0) : Math.max(0, ...values.map((v) => v[i] ?? 0))
|
|
2098
2106
|
);
|
|
2099
|
-
const top =
|
|
2107
|
+
const top = percent2 ? 100 : maxValue ?? Math.max(target, ...totals);
|
|
2100
2108
|
if (!(top > 0)) return "center";
|
|
2101
2109
|
const ratio = Math.min(1, Math.max(0, target / top));
|
|
2102
2110
|
const half = (estimateTextWidth(targetText) + 8) / 2;
|
|
@@ -2129,7 +2137,7 @@ function buildCartesianOption(cfg) {
|
|
|
2129
2137
|
}
|
|
2130
2138
|
});
|
|
2131
2139
|
}
|
|
2132
|
-
if (
|
|
2140
|
+
if (forecast2) {
|
|
2133
2141
|
const forecastSpan = plotWidth && labels.length > 1 ? Math.max(1, plotWidth - (showYAxis ? yAxisWidth ?? Y_AXIS_ESTIMATE : 0) - LINE_RIGHT_MARGIN) / (labels.length - 1) * (labels.length - 1 - lastActual) + LINE_RIGHT_MARGIN : null;
|
|
2134
2142
|
markLines.push({
|
|
2135
2143
|
name: "forecast-boundary",
|
|
@@ -2280,16 +2288,16 @@ function buildCartesianOption(cfg) {
|
|
|
2280
2288
|
const fit = kind === "line" && (fitToData ?? autoMinValue);
|
|
2281
2289
|
const valueSplitNumber = (() => {
|
|
2282
2290
|
if (!horizontalBars || !plotWidth) return void 0;
|
|
2283
|
-
const top =
|
|
2291
|
+
const top = percent2 ? 100 : maxValue ?? Math.max(0, ...(stacked ? stackTotalsOf(values) : values.flat()).map((v) => v ?? 0));
|
|
2284
2292
|
const categoryColumn = showYAxis ? (yAxisWidth ?? Math.min(160, Math.max(0, ...labels.map(estimateTextWidth)))) + 8 : 0;
|
|
2285
2293
|
const plot = plotWidth - categoryColumn - (highlightPoints.length > 0 ? 64 : 16) - 4;
|
|
2286
|
-
const text2 =
|
|
2294
|
+
const text2 = percent2 ? (v) => `${v}%` : (v) => axisFormatter(v);
|
|
2287
2295
|
return valueAxisSplitNumber(plot, [text2(0), text2(top)]);
|
|
2288
2296
|
})();
|
|
2289
2297
|
const limits = valueAxisLimits({ minValue, maxValue }, kind !== "line");
|
|
2290
2298
|
const splitNumber = horizontalBars ? valueSplitNumber : valueAxisSplitCount(plotHeight);
|
|
2291
2299
|
const tickFormatter = (() => {
|
|
2292
|
-
if (!cfg.axisTicks ||
|
|
2300
|
+
if (!cfg.axisTicks || percent2) return axisFormatter;
|
|
2293
2301
|
const extentValues = [];
|
|
2294
2302
|
const addAll = (list) => {
|
|
2295
2303
|
for (const v of list) if (v !== null && Number.isFinite(v)) extentValues.push(v);
|
|
@@ -2297,7 +2305,7 @@ function buildCartesianOption(cfg) {
|
|
|
2297
2305
|
if (stackTotals) addAll(stackTotals);
|
|
2298
2306
|
else values.forEach(addAll);
|
|
2299
2307
|
addAll(forecastValues);
|
|
2300
|
-
if (
|
|
2308
|
+
if (forecast2) addAll(forecast2.data.flatMap((row) => [cellNumber(row.lower), cellNumber(row.upper)]));
|
|
2301
2309
|
if (barTargets) addAll(barTargets);
|
|
2302
2310
|
if (hasTarget && target !== void 0) extentValues.push(target);
|
|
2303
2311
|
if (maxValue !== void 0 && Number.isFinite(maxValue)) extentValues.push(maxValue);
|
|
@@ -2314,8 +2322,8 @@ function buildCartesianOption(cfg) {
|
|
|
2314
2322
|
show: horizontalBars ? showXAxis : showYAxis,
|
|
2315
2323
|
// Bars and areas always start at 0 (a positive `minValue` can't lift them, a negative one makes room below);
|
|
2316
2324
|
// lines do too unless asked to fit the data. A limit never cuts the data: the axis widens to it.
|
|
2317
|
-
min:
|
|
2318
|
-
max:
|
|
2325
|
+
min: percent2 ? 0 : kind === "line" ? minValue === void 0 ? fit ? void 0 : zeroBasedMin : limits.min : limits.min,
|
|
2326
|
+
max: percent2 ? 100 : limits.max,
|
|
2319
2327
|
scale: fit && minValue == null,
|
|
2320
2328
|
splitNumber,
|
|
2321
2329
|
minInterval: allowDecimals ? void 0 : 1,
|
|
@@ -2323,7 +2331,7 @@ function buildCartesianOption(cfg) {
|
|
|
2323
2331
|
axisTick: { show: false },
|
|
2324
2332
|
splitLine: { show: showGridLines },
|
|
2325
2333
|
axisLabel: {
|
|
2326
|
-
formatter:
|
|
2334
|
+
formatter: percent2 ? (v) => `${v}%` : (v) => tickFormatter(v),
|
|
2327
2335
|
// Fitted to the data: the lowest tick would print over the first x label at the bottom left. The gridline stays.
|
|
2328
2336
|
showMinLabel: fit && minValue == null && !horizontalBars ? false : void 0,
|
|
2329
2337
|
// Horizontal: ticks that would still touch on a narrow plot are dropped.
|
|
@@ -2337,7 +2345,7 @@ function buildCartesianOption(cfg) {
|
|
|
2337
2345
|
};
|
|
2338
2346
|
const legendItems = [
|
|
2339
2347
|
...categories,
|
|
2340
|
-
...
|
|
2348
|
+
...forecast2 ? [forecastLabel] : [],
|
|
2341
2349
|
...provStart !== -1 ? [provisionalLabel] : [],
|
|
2342
2350
|
...barTargets ? [barTargetName] : [],
|
|
2343
2351
|
...hasTarget ? [targetText] : []
|
|
@@ -2358,7 +2366,7 @@ function buildCartesianOption(cfg) {
|
|
|
2358
2366
|
// The target marker is a tick, not a dot.
|
|
2359
2367
|
// The target is a row of dots and the forecast a row of dashes — their lines' patterns — and a per-bar target a tick.
|
|
2360
2368
|
data: legendItems.map(
|
|
2361
|
-
(name) => barTargets && name === barTargetName ? { name, icon: TARGET_LEGEND_ICON } :
|
|
2369
|
+
(name) => barTargets && name === barTargetName ? { name, icon: TARGET_LEGEND_ICON } : forecast2 && name === forecastLabel ? { name, icon: FORECAST_DASHED_ICON } : hasTarget && name === targetText ? { name, icon: TARGET_DOTTED_ICON } : name
|
|
2362
2370
|
),
|
|
2363
2371
|
formatter: nameLabels ? (name) => labelOf(name, nameLabels) : void 0
|
|
2364
2372
|
},
|
|
@@ -2366,7 +2374,7 @@ function buildCartesianOption(cfg) {
|
|
|
2366
2374
|
top: (showLegend ? 12 + LEGEND_LINE_HEIGHT * legendLines(legendItems, plotWidth, reserveActions ? ACTIONS_RESERVE : 0) : 12) + // The flat target label of a horizontal bar chart sits above the plot.
|
|
2367
2375
|
(horizontalBars && hasTarget ? 18 : 0) + // The label of a band over bars sits above the plot's top edge.
|
|
2368
2376
|
(kind === "bar" && notes.some((n) => n.to !== void 0) ? BAND_LABEL_ROOM : 0) + // The boundary label of a forecast sits above the plot's top edge too.
|
|
2369
|
-
(
|
|
2377
|
+
(forecast2 ? FORECAST_LABEL_ROOM : 0),
|
|
2370
2378
|
// Lines start and end on the outermost ticks, so the last x label (and an edge
|
|
2371
2379
|
// highlight) hangs past the plot; a horizontal bar's highlight sits past its end.
|
|
2372
2380
|
right: horizontalBars ? highlightPoints.length > 0 ? 64 : 16 : kind === "bar" ? 16 : LINE_RIGHT_MARGIN,
|
|
@@ -2397,7 +2405,7 @@ function buildCartesianOption(cfg) {
|
|
|
2397
2405
|
)
|
|
2398
2406
|
};
|
|
2399
2407
|
};
|
|
2400
|
-
const shares =
|
|
2408
|
+
const shares = percent2 ? cartesianSeriesValues(i <= lastActual ? [row] : [], categories, "percent") : null;
|
|
2401
2409
|
const legendRank = (p) => {
|
|
2402
2410
|
const at = categories.indexOf(p.seriesName ?? "");
|
|
2403
2411
|
return at === -1 ? categories.length : at;
|
|
@@ -2647,7 +2655,7 @@ function AreaChartImpl({
|
|
|
2647
2655
|
height,
|
|
2648
2656
|
chartOptions,
|
|
2649
2657
|
areaOptions,
|
|
2650
|
-
forecast,
|
|
2658
|
+
forecast: forecast2,
|
|
2651
2659
|
comparison,
|
|
2652
2660
|
highlight,
|
|
2653
2661
|
target,
|
|
@@ -2729,7 +2737,7 @@ function AreaChartImpl({
|
|
|
2729
2737
|
target,
|
|
2730
2738
|
targetLabel,
|
|
2731
2739
|
annotations,
|
|
2732
|
-
forecast,
|
|
2740
|
+
forecast: forecast2,
|
|
2733
2741
|
comparison: comparisonConfig,
|
|
2734
2742
|
comparisonFormat: format,
|
|
2735
2743
|
provisionalFrom,
|
|
@@ -2775,7 +2783,7 @@ function AreaChartImpl({
|
|
|
2775
2783
|
target,
|
|
2776
2784
|
targetLabel,
|
|
2777
2785
|
annotations,
|
|
2778
|
-
|
|
2786
|
+
forecast2,
|
|
2779
2787
|
comparisonConfig,
|
|
2780
2788
|
format,
|
|
2781
2789
|
height,
|
|
@@ -3032,7 +3040,7 @@ function LineChartImpl({
|
|
|
3032
3040
|
height,
|
|
3033
3041
|
chartOptions,
|
|
3034
3042
|
lineOptions,
|
|
3035
|
-
forecast,
|
|
3043
|
+
forecast: forecast2,
|
|
3036
3044
|
comparison,
|
|
3037
3045
|
highlight,
|
|
3038
3046
|
target,
|
|
@@ -3115,7 +3123,7 @@ function LineChartImpl({
|
|
|
3115
3123
|
targetLabel,
|
|
3116
3124
|
targetLabelPosition,
|
|
3117
3125
|
annotations,
|
|
3118
|
-
forecast,
|
|
3126
|
+
forecast: forecast2,
|
|
3119
3127
|
comparison: comparisonConfig,
|
|
3120
3128
|
comparisonFormat: format,
|
|
3121
3129
|
provisionalFrom,
|
|
@@ -3162,7 +3170,7 @@ function LineChartImpl({
|
|
|
3162
3170
|
targetLabel,
|
|
3163
3171
|
targetLabelPosition,
|
|
3164
3172
|
annotations,
|
|
3165
|
-
|
|
3173
|
+
forecast2,
|
|
3166
3174
|
comparisonConfig,
|
|
3167
3175
|
format,
|
|
3168
3176
|
height,
|
|
@@ -5083,10 +5091,10 @@ var HEATMAP_CELL_PADDING = 4;
|
|
|
5083
5091
|
var HEATMAP_BUCKET_MID = 20;
|
|
5084
5092
|
function heatmapCellFontSize(plotWidth, columns, rowNames, texts) {
|
|
5085
5093
|
const widest = (items) => items.reduce((m, t) => Math.max(m, estimateTextWidth2(t)), 0);
|
|
5086
|
-
const
|
|
5094
|
+
const cell2 = (plotWidth + HEATMAP_BUCKET_MID - HEATMAP_GRID_X - (widest(rowNames) + 8)) / Math.max(1, columns);
|
|
5087
5095
|
const text = widest(texts);
|
|
5088
|
-
if (text + HEATMAP_CELL_PADDING <=
|
|
5089
|
-
return text * 10 / 12 + HEATMAP_CELL_PADDING <=
|
|
5096
|
+
if (text + HEATMAP_CELL_PADDING <= cell2) return 12;
|
|
5097
|
+
return text * 10 / 12 + HEATMAP_CELL_PADDING <= cell2 ? 10 : null;
|
|
5090
5098
|
}
|
|
5091
5099
|
var TEXT13 = {
|
|
5092
5100
|
ja: {
|
|
@@ -5114,24 +5122,24 @@ function buildHeatmapOption(config) {
|
|
|
5114
5122
|
const base = config.color || "#6366f1";
|
|
5115
5123
|
const range = [mixIntoSurface(base, config.surfaceColor, HEATMAP_FLOOR_SHARE), base];
|
|
5116
5124
|
const gapColor = "rgba(0, 0, 0, 0)";
|
|
5117
|
-
const flagged = (
|
|
5118
|
-
const tooltip = (
|
|
5119
|
-
const head = `${escapeHtml2(label2(model.ys[
|
|
5120
|
-
const main =
|
|
5125
|
+
const flagged = (cell2) => cell2.flagged ? { borderColor: config.flagColor, borderWidth: 3, borderType: "solid" } : { borderColor: "transparent", borderWidth: 1 };
|
|
5126
|
+
const tooltip = (cell2) => {
|
|
5127
|
+
const head = `${escapeHtml2(label2(model.ys[cell2.yi]))} ${escapeHtml2(label2(model.xs[cell2.xi]))}`;
|
|
5128
|
+
const main = cell2.value === null ? EMPTY_VALUE : escapeHtml2(valueFormatter(cell2.value));
|
|
5121
5129
|
const extras = (config.details ?? []).map((key) => {
|
|
5122
|
-
const n =
|
|
5130
|
+
const n = cell2.row ? toChartNumber(cell2.row[key]) : null;
|
|
5123
5131
|
return `${escapeHtml2(label2(key))} ${n === null ? EMPTY_VALUE : escapeHtml2(valueFormatter(n))}`;
|
|
5124
5132
|
}).join(t.join);
|
|
5125
|
-
const flag =
|
|
5133
|
+
const flag = cell2.flagged ? `${t.join}${t.flagged}` : "";
|
|
5126
5134
|
return `${head} ${main}${extras ? `${t.join}${extras}` : ""}${flag}`;
|
|
5127
5135
|
};
|
|
5128
5136
|
const cellFont = config.plotWidth ? heatmapCellFontSize(
|
|
5129
5137
|
config.plotWidth,
|
|
5130
5138
|
model.xs.length,
|
|
5131
5139
|
model.ys.map(label2),
|
|
5132
|
-
model.cells.flatMap((
|
|
5140
|
+
model.cells.flatMap((cell2) => cell2.value === null ? [] : [valueFormatter(cell2.value)])
|
|
5133
5141
|
) : 12;
|
|
5134
|
-
const point = (
|
|
5142
|
+
const point = (cell2) => ({ value: [cell2.xi, cell2.yi, cell2.value], cell: cell2 });
|
|
5135
5143
|
const option = {
|
|
5136
5144
|
animation: false,
|
|
5137
5145
|
tooltip: config.showTooltip ? { trigger: "item", formatter: (p) => tooltip(p.data.cell) } : { show: false },
|
|
@@ -5179,11 +5187,11 @@ function buildHeatmapOption(config) {
|
|
|
5179
5187
|
{
|
|
5180
5188
|
id: "values",
|
|
5181
5189
|
type: "heatmap",
|
|
5182
|
-
data: present.map((
|
|
5183
|
-
...point(
|
|
5184
|
-
itemStyle: flagged(
|
|
5190
|
+
data: present.map((cell2) => ({
|
|
5191
|
+
...point(cell2),
|
|
5192
|
+
itemStyle: flagged(cell2),
|
|
5185
5193
|
label: {
|
|
5186
|
-
color: heatmapRatio(
|
|
5194
|
+
color: heatmapRatio(cell2.value, model.min, model.max) >= HEATMAP_LIGHT_TEXT_FROM ? config.darkCellText : config.lightCellText
|
|
5187
5195
|
}
|
|
5188
5196
|
})),
|
|
5189
5197
|
label: {
|
|
@@ -5198,7 +5206,7 @@ function buildHeatmapOption(config) {
|
|
|
5198
5206
|
{
|
|
5199
5207
|
id: "gaps",
|
|
5200
5208
|
type: "heatmap",
|
|
5201
|
-
data: missing.map((
|
|
5209
|
+
data: missing.map((cell2) => ({ value: [cell2.xi, cell2.yi, 0], cell: cell2, itemStyle: flagged(cell2) })),
|
|
5202
5210
|
label: { show: false },
|
|
5203
5211
|
itemStyle: {
|
|
5204
5212
|
color: gapColor,
|
|
@@ -5234,7 +5242,7 @@ function heatmapDataTable(model, names, formatter, labels, locale) {
|
|
|
5234
5242
|
}
|
|
5235
5243
|
function buildHeatmapSummary(model, formatter, title, labels, locale) {
|
|
5236
5244
|
let best;
|
|
5237
|
-
for (const
|
|
5245
|
+
for (const cell2 of model.cells) if (cell2.value !== null && (!best || cell2.value > best.value)) best = cell2;
|
|
5238
5246
|
if (!best) return void 0;
|
|
5239
5247
|
const label2 = (key) => labels?.[key] ?? key;
|
|
5240
5248
|
const head = title ? `${title}: ` : "";
|
|
@@ -5347,6 +5355,1061 @@ function HeatmapLegend({
|
|
|
5347
5355
|
}
|
|
5348
5356
|
var Heatmap = forwardRef(HeatmapImpl);
|
|
5349
5357
|
Heatmap.displayName = "Heatmap";
|
|
5358
|
+
var TEXT14 = {
|
|
5359
|
+
ja: { item: "\u9805\u76EE", chart: (keys) => `${keys.join("\u30FB")}\u306E\u63A8\u79FB(\u4E0A\u6BB5 \u68D2\u3001\u4E0B\u6BB5 \u7DDA)` },
|
|
5360
|
+
en: { item: "Item", chart: (keys) => `Trend of ${keys.join(", ")} (bars on top, line below)` }
|
|
5361
|
+
};
|
|
5362
|
+
var NO_ROWS12 = [];
|
|
5363
|
+
var NO_KEYS = [];
|
|
5364
|
+
var PANEL_GAP = 20;
|
|
5365
|
+
var LEGEND_LINE = 24;
|
|
5366
|
+
var DEFAULT_HEIGHT = 400;
|
|
5367
|
+
var DEFAULT_Y_AXIS_WIDTH = 64;
|
|
5368
|
+
function pairedPalette(barKeys, lineKeys, barColors, lineColors) {
|
|
5369
|
+
const bars = seriesColorsFor(barKeys, barColors, CHART_OTHER_COLOR);
|
|
5370
|
+
const line = lineColors ? seriesColorsFor(lineKeys, lineColors, CHART_OTHER_COLOR) : lineKeys.map((_, i) => DEFAULT_CHART_COLORS[(barKeys.length + i) % DEFAULT_CHART_COLORS.length]);
|
|
5371
|
+
return { bars, line };
|
|
5372
|
+
}
|
|
5373
|
+
function buildPairedOption(cfg) {
|
|
5374
|
+
const { data, index, labels, barKeys, lineKeys, height, heightRatio, yAxisWidth, showLegend, showTooltip } = cfg;
|
|
5375
|
+
const legendNames = [...barKeys, ...lineKeys];
|
|
5376
|
+
const legendWidth = legendNames.reduce((sum, name) => sum + [...labels?.[name] ?? name].length * 12 + 29, 0);
|
|
5377
|
+
const budget = Math.max(80, Math.min(cfg.plotWidth ?? 720, 720) - (cfg.reserveActions ? 80 : 0));
|
|
5378
|
+
const legendRows = showLegend ? Math.min(3, Math.max(1, Math.ceil(legendWidth / budget))) : 0;
|
|
5379
|
+
const top = (showLegend ? 12 + LEGEND_LINE * legendRows : 12) + 4;
|
|
5380
|
+
const room = Math.max(120, height - top - PANEL_GAP);
|
|
5381
|
+
const [a, b] = heightRatio;
|
|
5382
|
+
const upper = Math.round(room * a / (a + b));
|
|
5383
|
+
const common = {
|
|
5384
|
+
data,
|
|
5385
|
+
index,
|
|
5386
|
+
labels,
|
|
5387
|
+
showLegend: false,
|
|
5388
|
+
showTooltip: false,
|
|
5389
|
+
highlight: "none",
|
|
5390
|
+
yAxisWidth,
|
|
5391
|
+
reducedMotion: false,
|
|
5392
|
+
locale: cfg.locale
|
|
5393
|
+
};
|
|
5394
|
+
const barOpt = buildCartesianOption({
|
|
5395
|
+
...common,
|
|
5396
|
+
kind: "bar",
|
|
5397
|
+
categories: barKeys,
|
|
5398
|
+
palette: cfg.barPalette,
|
|
5399
|
+
valueFormatter: cfg.barFormatter,
|
|
5400
|
+
axisFormatter: cfg.barAxis,
|
|
5401
|
+
axisTicks: cfg.barTicks,
|
|
5402
|
+
type: cfg.type,
|
|
5403
|
+
showXAxis: false,
|
|
5404
|
+
yAxisLabel: cfg.barAxisLabel,
|
|
5405
|
+
maxValue: cfg.barMax,
|
|
5406
|
+
plotWidth: cfg.plotWidth,
|
|
5407
|
+
plotHeight: upper
|
|
5408
|
+
});
|
|
5409
|
+
const lineOpt = buildCartesianOption({
|
|
5410
|
+
...common,
|
|
5411
|
+
kind: "line",
|
|
5412
|
+
categories: lineKeys,
|
|
5413
|
+
palette: cfg.linePalette,
|
|
5414
|
+
valueFormatter: cfg.lineFormatter,
|
|
5415
|
+
axisFormatter: cfg.lineAxis,
|
|
5416
|
+
axisTicks: cfg.lineTicks,
|
|
5417
|
+
fitToData: cfg.fitToData,
|
|
5418
|
+
showXAxis: true,
|
|
5419
|
+
yAxisLabel: cfg.lineAxisLabel,
|
|
5420
|
+
minValue: cfg.lineMin,
|
|
5421
|
+
maxValue: cfg.lineMax,
|
|
5422
|
+
guideColor: cfg.guideColor,
|
|
5423
|
+
plotWidth: cfg.plotWidth,
|
|
5424
|
+
plotHeight: room - upper
|
|
5425
|
+
});
|
|
5426
|
+
const times = timeTooltipLabels(data.map((row) => row[index]), cfg.locale);
|
|
5427
|
+
const titles = labelRows(data, index, labels).map((row, i) => String(times?.[i] ?? row[index] ?? ""));
|
|
5428
|
+
const cell2 = (row, key) => {
|
|
5429
|
+
const v = row[key];
|
|
5430
|
+
const n = typeof v === "number" ? v : typeof v === "string" && v.trim() !== "" ? Number(v) : NaN;
|
|
5431
|
+
return Number.isFinite(n) ? n : null;
|
|
5432
|
+
};
|
|
5433
|
+
const rowsOf = (row, keys, palette) => keys.map((key, i) => ({ name: labelOf(key, labels), color: palette[i] || "currentColor", value: cell2(row, key) }));
|
|
5434
|
+
const emptyTitle = tooltipHtml("", [], String, [], cfg.locale);
|
|
5435
|
+
const tooltipFormatter = (params) => {
|
|
5436
|
+
const list = Array.isArray(params) ? params : [params];
|
|
5437
|
+
const i = list[0]?.dataIndex ?? 0;
|
|
5438
|
+
const row = data[i] ?? {};
|
|
5439
|
+
const upperHtml = tooltipHtml(titles[i] ?? "", rowsOf(row, barKeys, cfg.barPalette), cfg.barFormatter, [], cfg.locale);
|
|
5440
|
+
const lowerHtml = tooltipHtml("", rowsOf(row, lineKeys, cfg.linePalette), cfg.lineFormatter, [], cfg.locale).slice(emptyTitle.length);
|
|
5441
|
+
return `${upperHtml}${lowerHtml}`;
|
|
5442
|
+
};
|
|
5443
|
+
const lineX = { ...lineOpt.xAxis, id: "x-line", gridIndex: 1, boundaryGap: true };
|
|
5444
|
+
const barX = { ...barOpt.xAxis, id: "x-bars", gridIndex: 0, show: true, axisLine: { show: false }, axisLabel: { show: false } };
|
|
5445
|
+
const gridLeft = barOpt.grid.left ?? 4;
|
|
5446
|
+
const right = 16;
|
|
5447
|
+
const option = {
|
|
5448
|
+
...barOpt,
|
|
5449
|
+
legend: { ...barOpt.legend, show: showLegend, data: legendNames, right: cfg.reserveActions ? 80 : 0 },
|
|
5450
|
+
grid: [
|
|
5451
|
+
{ top, height: upper, left: gridLeft, right, containLabel: true },
|
|
5452
|
+
{ top: top + upper + PANEL_GAP, bottom: 4, left: gridLeft, right, containLabel: true }
|
|
5453
|
+
],
|
|
5454
|
+
xAxis: [barX, lineX],
|
|
5455
|
+
yAxis: [
|
|
5456
|
+
{ ...barOpt.yAxis, id: "y-bars", gridIndex: 0 },
|
|
5457
|
+
{ ...lineOpt.yAxis, id: "y-line", gridIndex: 1 }
|
|
5458
|
+
],
|
|
5459
|
+
series: [
|
|
5460
|
+
...barOpt.series.map((s) => ({ ...s, xAxisIndex: 0, yAxisIndex: 0 })),
|
|
5461
|
+
...lineOpt.series.map((s) => ({ ...s, xAxisIndex: 1, yAxisIndex: 1 }))
|
|
5462
|
+
],
|
|
5463
|
+
tooltip: {
|
|
5464
|
+
...barOpt.tooltip,
|
|
5465
|
+
show: showTooltip,
|
|
5466
|
+
trigger: "axis",
|
|
5467
|
+
axisPointer: { type: "line", link: [{ xAxisIndex: "all" }] },
|
|
5468
|
+
formatter: tooltipFormatter
|
|
5469
|
+
},
|
|
5470
|
+
axisPointer: { link: [{ xAxisIndex: "all" }] }
|
|
5471
|
+
};
|
|
5472
|
+
return mergeChartOptions(option, cfg.chartOptions);
|
|
5473
|
+
}
|
|
5474
|
+
function PairedChartImpl({
|
|
5475
|
+
data = NO_ROWS12,
|
|
5476
|
+
index,
|
|
5477
|
+
labels,
|
|
5478
|
+
bars,
|
|
5479
|
+
line,
|
|
5480
|
+
title,
|
|
5481
|
+
summary,
|
|
5482
|
+
actions,
|
|
5483
|
+
fileName,
|
|
5484
|
+
isLoading,
|
|
5485
|
+
emptyState,
|
|
5486
|
+
height = DEFAULT_HEIGHT,
|
|
5487
|
+
heightRatio = [3, 2],
|
|
5488
|
+
yAxisWidth = DEFAULT_Y_AXIS_WIDTH,
|
|
5489
|
+
showLegend = true,
|
|
5490
|
+
showTooltip = true,
|
|
5491
|
+
chartOptions,
|
|
5492
|
+
ariaLabel,
|
|
5493
|
+
className,
|
|
5494
|
+
...rest
|
|
5495
|
+
}, ref) {
|
|
5496
|
+
const { ref: frameRef, width: plotWidth, tokens } = useChartSurface(ref);
|
|
5497
|
+
const barKeys = bars?.categories ?? NO_KEYS;
|
|
5498
|
+
const lineKeys = line?.categories ?? NO_KEYS;
|
|
5499
|
+
const locale = useLocale();
|
|
5500
|
+
const t = TEXT14[uiLanguage(locale)];
|
|
5501
|
+
const barFormatter = useMemo(() => resolveValueFormatter(bars?.valueFormatter, bars?.format, locale), [bars?.valueFormatter, bars?.format, locale]);
|
|
5502
|
+
const lineFormatter = useMemo(() => resolveValueFormatter(line?.valueFormatter, line?.format, locale), [line?.valueFormatter, line?.format, locale]);
|
|
5503
|
+
const barAxis = useMemo(() => resolveAxisFormatter(bars?.valueFormatter, bars?.format, locale), [bars?.valueFormatter, bars?.format, locale]);
|
|
5504
|
+
const lineAxis = useMemo(() => resolveAxisFormatter(line?.valueFormatter, line?.format, locale), [line?.valueFormatter, line?.format, locale]);
|
|
5505
|
+
const barTicks = useMemo(() => resolveAxisTickFormatter(bars?.valueFormatter, bars?.format, locale), [bars?.valueFormatter, bars?.format, locale]);
|
|
5506
|
+
const lineTicks = useMemo(() => resolveAxisTickFormatter(line?.valueFormatter, line?.format, locale), [line?.valueFormatter, line?.format, locale]);
|
|
5507
|
+
const palette = useMemo(() => {
|
|
5508
|
+
const p = pairedPalette(barKeys, lineKeys, bars?.colors, line?.colors);
|
|
5509
|
+
return { bars: resolveChartColors(p.bars, tokens), line: resolveChartColors(p.line, tokens) };
|
|
5510
|
+
}, [barKeys, lineKeys, bars?.colors, line?.colors, tokens]);
|
|
5511
|
+
const option = useMemo(
|
|
5512
|
+
() => buildPairedOption({
|
|
5513
|
+
data,
|
|
5514
|
+
index,
|
|
5515
|
+
labels,
|
|
5516
|
+
barKeys,
|
|
5517
|
+
lineKeys,
|
|
5518
|
+
barPalette: palette.bars,
|
|
5519
|
+
linePalette: palette.line,
|
|
5520
|
+
barFormatter,
|
|
5521
|
+
lineFormatter,
|
|
5522
|
+
barAxis,
|
|
5523
|
+
lineAxis,
|
|
5524
|
+
barTicks,
|
|
5525
|
+
lineTicks,
|
|
5526
|
+
type: bars?.type,
|
|
5527
|
+
fitToData: line?.fitToData,
|
|
5528
|
+
barAxisLabel: bars?.yAxisLabel,
|
|
5529
|
+
lineAxisLabel: line?.yAxisLabel,
|
|
5530
|
+
barMax: bars?.maxValue,
|
|
5531
|
+
lineMax: line?.maxValue,
|
|
5532
|
+
lineMin: line?.minValue,
|
|
5533
|
+
height,
|
|
5534
|
+
heightRatio,
|
|
5535
|
+
yAxisWidth,
|
|
5536
|
+
showLegend,
|
|
5537
|
+
showTooltip,
|
|
5538
|
+
reserveActions: Boolean(actions),
|
|
5539
|
+
plotWidth,
|
|
5540
|
+
guideColor: tokens?.mutedForeground ?? void 0,
|
|
5541
|
+
chartOptions,
|
|
5542
|
+
locale
|
|
5543
|
+
}),
|
|
5544
|
+
[
|
|
5545
|
+
data,
|
|
5546
|
+
index,
|
|
5547
|
+
labels,
|
|
5548
|
+
barKeys,
|
|
5549
|
+
lineKeys,
|
|
5550
|
+
palette,
|
|
5551
|
+
barFormatter,
|
|
5552
|
+
lineFormatter,
|
|
5553
|
+
barAxis,
|
|
5554
|
+
lineAxis,
|
|
5555
|
+
barTicks,
|
|
5556
|
+
lineTicks,
|
|
5557
|
+
bars?.type,
|
|
5558
|
+
bars?.yAxisLabel,
|
|
5559
|
+
bars?.maxValue,
|
|
5560
|
+
line?.fitToData,
|
|
5561
|
+
line?.yAxisLabel,
|
|
5562
|
+
line?.maxValue,
|
|
5563
|
+
line?.minValue,
|
|
5564
|
+
height,
|
|
5565
|
+
heightRatio,
|
|
5566
|
+
yAxisWidth,
|
|
5567
|
+
showLegend,
|
|
5568
|
+
showTooltip,
|
|
5569
|
+
actions,
|
|
5570
|
+
plotWidth,
|
|
5571
|
+
tokens,
|
|
5572
|
+
chartOptions,
|
|
5573
|
+
locale
|
|
5574
|
+
]
|
|
5575
|
+
);
|
|
5576
|
+
const dataTable = useMemo(() => {
|
|
5577
|
+
const upper = chartDataTable(labelRows(data, index, labels), index, barKeys, barFormatter, labels, t.item);
|
|
5578
|
+
const lower = chartDataTable(labelRows(data, index, labels), index, lineKeys, lineFormatter, labels, t.item);
|
|
5579
|
+
const times = timeTooltipLabels(data.map((row) => row[index]), locale);
|
|
5580
|
+
return {
|
|
5581
|
+
...upper,
|
|
5582
|
+
columns: [...upper.columns, ...lower.columns.slice(1)],
|
|
5583
|
+
rows: upper.rows.map((r, i) => [times?.[i] ?? r[0] ?? "", ...r.slice(1), ...(lower.rows[i] ?? []).slice(1)])
|
|
5584
|
+
};
|
|
5585
|
+
}, [data, index, labels, barKeys, lineKeys, barFormatter, lineFormatter, t, locale]);
|
|
5586
|
+
const label2 = ariaLabel ?? t.chart([...barKeys, ...lineKeys]);
|
|
5587
|
+
return /* @__PURE__ */ jsx(
|
|
5588
|
+
ChartFrame,
|
|
5589
|
+
{
|
|
5590
|
+
...chartRootProps(rest),
|
|
5591
|
+
ref: frameRef,
|
|
5592
|
+
title,
|
|
5593
|
+
summary: summary === "auto" ? void 0 : summary,
|
|
5594
|
+
isLoading: isLoading ?? false,
|
|
5595
|
+
isEmpty: data.length === 0,
|
|
5596
|
+
emptyState,
|
|
5597
|
+
height,
|
|
5598
|
+
variant: "bar",
|
|
5599
|
+
ariaLabel: label2,
|
|
5600
|
+
className,
|
|
5601
|
+
dataTable,
|
|
5602
|
+
children: /* @__PURE__ */ jsx(EChart, { option, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary: summary === "auto" ? void 0 : summary } })
|
|
5603
|
+
}
|
|
5604
|
+
);
|
|
5605
|
+
}
|
|
5606
|
+
var PairedChart = forwardRef(PairedChartImpl);
|
|
5607
|
+
PairedChart.displayName = "PairedChart";
|
|
5608
|
+
|
|
5609
|
+
// ../squadkit/registry/lib/distribution.ts
|
|
5610
|
+
function toFinite(value) {
|
|
5611
|
+
const n = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : NaN;
|
|
5612
|
+
return Number.isFinite(n) ? n : null;
|
|
5613
|
+
}
|
|
5614
|
+
function sortedNumbers(values) {
|
|
5615
|
+
const out = [];
|
|
5616
|
+
for (const v of values) {
|
|
5617
|
+
const n = toFinite(v);
|
|
5618
|
+
if (n !== null) out.push(n);
|
|
5619
|
+
}
|
|
5620
|
+
return out.sort((a, b) => a - b);
|
|
5621
|
+
}
|
|
5622
|
+
function quantile(sorted, p) {
|
|
5623
|
+
if (sorted.length === 0) return null;
|
|
5624
|
+
const pos = (sorted.length - 1) * Math.min(1, Math.max(0, p));
|
|
5625
|
+
const lo = Math.floor(pos);
|
|
5626
|
+
const hi = Math.ceil(pos);
|
|
5627
|
+
return sorted[lo] + (sorted[hi] - sorted[lo]) * (pos - lo);
|
|
5628
|
+
}
|
|
5629
|
+
function boxStats(values, whisker = 1.5) {
|
|
5630
|
+
const sorted = sortedNumbers(values);
|
|
5631
|
+
if (sorted.length === 0) return null;
|
|
5632
|
+
const q1 = quantile(sorted, 0.25);
|
|
5633
|
+
const median = quantile(sorted, 0.5);
|
|
5634
|
+
const q3 = quantile(sorted, 0.75);
|
|
5635
|
+
const reach = Math.max(0, whisker) * (q3 - q1);
|
|
5636
|
+
const low = q1 - reach;
|
|
5637
|
+
const high = q3 + reach;
|
|
5638
|
+
const inside = sorted.filter((v) => v >= low && v <= high);
|
|
5639
|
+
return {
|
|
5640
|
+
count: sorted.length,
|
|
5641
|
+
min: sorted[0],
|
|
5642
|
+
max: sorted[sorted.length - 1],
|
|
5643
|
+
q1,
|
|
5644
|
+
median,
|
|
5645
|
+
q3,
|
|
5646
|
+
whiskerLow: inside[0] ?? q1,
|
|
5647
|
+
whiskerHigh: inside[inside.length - 1] ?? q3,
|
|
5648
|
+
outliers: sorted.filter((v) => v < low || v > high)
|
|
5649
|
+
};
|
|
5650
|
+
}
|
|
5651
|
+
function niceBinWidth(span, target = 10) {
|
|
5652
|
+
if (!(span > 0) || !Number.isFinite(span)) return 1;
|
|
5653
|
+
const raw = span / target;
|
|
5654
|
+
const pow = 10 ** Math.floor(Math.log10(raw));
|
|
5655
|
+
const f = raw / pow;
|
|
5656
|
+
return (f <= 1 ? 1 : f <= 2 ? 2 : f <= 2.5 ? 2.5 : f <= 5 ? 5 : 10) * pow;
|
|
5657
|
+
}
|
|
5658
|
+
var MAX_BINS = 200;
|
|
5659
|
+
function tidy(n, step) {
|
|
5660
|
+
const digits = Math.min(100, Math.max(0, Math.ceil(-Math.log10(step)) + 6));
|
|
5661
|
+
const rounded = Number(n.toFixed(digits));
|
|
5662
|
+
return Number.isFinite(rounded) ? rounded : n;
|
|
5663
|
+
}
|
|
5664
|
+
function histogramBins(values, config = {}) {
|
|
5665
|
+
const sorted = sortedNumbers(values);
|
|
5666
|
+
if (sorted.length === 0) return [];
|
|
5667
|
+
const width = config.binWidth !== void 0 && Number.isFinite(config.binWidth) && config.binWidth > 0 ? config.binWidth : null;
|
|
5668
|
+
const lo = sorted[0];
|
|
5669
|
+
const hi = sorted[sorted.length - 1];
|
|
5670
|
+
const cap = config.max !== void 0 && Number.isFinite(config.max) ? config.max : null;
|
|
5671
|
+
const end = cap !== null ? cap : hi;
|
|
5672
|
+
const first = config.start !== void 0 && Number.isFinite(config.start) ? config.start : null;
|
|
5673
|
+
let step = width ?? niceBinWidth((cap !== null ? Math.min(hi, cap) : hi) - (first ?? lo));
|
|
5674
|
+
const start = first ?? tidy(Math.floor(lo / step) * step, step);
|
|
5675
|
+
const countFor = (w) => Math.ceil((end - start) / w - 1e-9);
|
|
5676
|
+
if (countFor(step) > MAX_BINS) step = niceBinWidth(end - start, MAX_BINS);
|
|
5677
|
+
const n = Math.min(MAX_BINS, Math.max(cap === null ? 1 : 0, countFor(step)));
|
|
5678
|
+
const bins = [];
|
|
5679
|
+
for (let i = 0; i < n; i++) {
|
|
5680
|
+
const from = i === 0 ? start : bins[i - 1].to;
|
|
5681
|
+
let to = tidy(start + (i + 1) * step, step);
|
|
5682
|
+
if (!(to > from)) to = start + (i + 1) * step;
|
|
5683
|
+
if (cap !== null) to = Math.min(to, cap);
|
|
5684
|
+
bins.push({ from, to, count: 0, overflow: false });
|
|
5685
|
+
}
|
|
5686
|
+
const inRange = cap === null ? sorted : sorted.filter((v) => v < cap);
|
|
5687
|
+
const over = cap === null ? [] : sorted.filter((v) => v >= cap);
|
|
5688
|
+
for (const v of inRange) {
|
|
5689
|
+
if (v < start || bins.length === 0) continue;
|
|
5690
|
+
const i = Math.min(bins.length - 1, Math.floor((v - start) / step + 1e-9));
|
|
5691
|
+
bins[i].count += 1;
|
|
5692
|
+
}
|
|
5693
|
+
if (over.length > 0) bins.push({ from: cap, to: Math.max(hi, cap), count: over.length, overflow: true });
|
|
5694
|
+
return bins;
|
|
5695
|
+
}
|
|
5696
|
+
var TEXT15 = {
|
|
5697
|
+
ja: {
|
|
5698
|
+
countUnit: "\u4EF6",
|
|
5699
|
+
atOrAbove: (from) => `${from}\u4EE5\u4E0A`,
|
|
5700
|
+
range: (from, to) => `${from}\u301C${to}`,
|
|
5701
|
+
count: (n, unit) => `${n}${unit}`,
|
|
5702
|
+
countHeader: (unit) => `${unit}\u6570`,
|
|
5703
|
+
share: "\u69CB\u6210\u6BD4",
|
|
5704
|
+
value: "\u5024",
|
|
5705
|
+
valueInSentence: "\u5024",
|
|
5706
|
+
threshold: "\u3057\u304D\u3044\u5024",
|
|
5707
|
+
peak: (total, bin, count, unit) => `${total}${unit}\u306E\u3046\u3061\u6700\u3082\u591A\u3044\u306E\u306F ${bin}\uFF08${count}${unit}\uFF09`,
|
|
5708
|
+
overThreshold: (name, value, count, share) => `${name}\uFF08${value}\uFF09\u4EE5\u4E0A\u306F ${count}\uFF08${share}\uFF09`,
|
|
5709
|
+
sentenceJoin: "\u3002",
|
|
5710
|
+
chart: (label2) => `${label2}\u306E\u30D2\u30B9\u30C8\u30B0\u30E9\u30E0`
|
|
5711
|
+
},
|
|
5712
|
+
en: {
|
|
5713
|
+
countUnit: "",
|
|
5714
|
+
atOrAbove: (from) => `${from}+`,
|
|
5715
|
+
range: (from, to) => `${from}\u2013${to}`,
|
|
5716
|
+
count: (n, unit) => unit ? `${n} ${unit}` : `${n}`,
|
|
5717
|
+
countHeader: () => "Count",
|
|
5718
|
+
share: "Share",
|
|
5719
|
+
value: "Value",
|
|
5720
|
+
valueInSentence: "values",
|
|
5721
|
+
threshold: "Threshold",
|
|
5722
|
+
peak: (total, bin, count, unit) => `Most common: ${bin} (${unit ? `${count} ${unit}` : count} of ${total})`,
|
|
5723
|
+
overThreshold: (name, value, count, share) => `At or above ${name} (${value}): ${count} (${share})`,
|
|
5724
|
+
sentenceJoin: ". ",
|
|
5725
|
+
chart: (label2) => `Histogram of ${label2}`
|
|
5726
|
+
}
|
|
5727
|
+
};
|
|
5728
|
+
var textOf4 = (locale) => TEXT15[uiLanguage(resolveLocale(locale))];
|
|
5729
|
+
function binLabel(bin, formatter, locale) {
|
|
5730
|
+
const t = textOf4(locale);
|
|
5731
|
+
return bin.overflow ? t.atOrAbove(formatter(bin.from)) : t.range(formatter(bin.from), formatter(bin.to));
|
|
5732
|
+
}
|
|
5733
|
+
function thresholdPosition(bins, value) {
|
|
5734
|
+
const lastIndex = bins.length - 1;
|
|
5735
|
+
const i = bins.findIndex((b, k) => k === lastIndex ? value >= b.from && (b.overflow || value <= b.to) : value >= b.from && value < b.to);
|
|
5736
|
+
const bin = bins[i];
|
|
5737
|
+
if (!bin) return null;
|
|
5738
|
+
return bin.overflow ? i - 0.5 : i - 0.5 + (value - bin.from) / (bin.to - bin.from);
|
|
5739
|
+
}
|
|
5740
|
+
function countAtOrAbove(values, value, from = -Infinity) {
|
|
5741
|
+
return sortedNumbers(values).filter((v) => v >= value && v >= from).length;
|
|
5742
|
+
}
|
|
5743
|
+
var percent = (n, total) => total === 0 ? "0%" : `${Math.round(n / total * 100)}%`;
|
|
5744
|
+
function buildHistogramSummary(bins, formatter, config) {
|
|
5745
|
+
if (bins.length === 0 || config.total === 0) return void 0;
|
|
5746
|
+
const t = textOf4(config.locale);
|
|
5747
|
+
const count = (n) => t.count(n, config.countUnit);
|
|
5748
|
+
const peak = bins.reduce((a, b) => b.count > a.count ? b : a);
|
|
5749
|
+
const parts = [t.peak(config.total, binLabel(peak, formatter, config.locale), peak.count, config.countUnit)];
|
|
5750
|
+
if (config.threshold && config.atOrAbove !== void 0) {
|
|
5751
|
+
const name = config.threshold.label ?? t.threshold;
|
|
5752
|
+
parts.push(t.overThreshold(name, formatter(config.threshold.value), count(config.atOrAbove), percent(config.atOrAbove, config.total)));
|
|
5753
|
+
}
|
|
5754
|
+
return parts.join(t.sentenceJoin);
|
|
5755
|
+
}
|
|
5756
|
+
function histogramDataTable(bins, formatter, config) {
|
|
5757
|
+
const t = textOf4(config.locale);
|
|
5758
|
+
return {
|
|
5759
|
+
columns: [config.valueLabel ?? t.value, t.countHeader(config.countUnit), t.share],
|
|
5760
|
+
rows: bins.map((b) => [binLabel(b, formatter, config.locale), `${b.count}`, percent(b.count, config.total)])
|
|
5761
|
+
};
|
|
5762
|
+
}
|
|
5763
|
+
function thresholdPoint(bins, value) {
|
|
5764
|
+
const pos = thresholdPosition(bins, value) ?? 0;
|
|
5765
|
+
const index = Math.min(bins.length - 1, Math.max(0, Math.round(pos)));
|
|
5766
|
+
return [index, 0, pos - index];
|
|
5767
|
+
}
|
|
5768
|
+
function thresholdRenderer(style) {
|
|
5769
|
+
return (params, api) => {
|
|
5770
|
+
const { x: gx, y: gy, width, height } = params.coordSys;
|
|
5771
|
+
const band = Math.abs(api.size([1, 0])[0] ?? 0);
|
|
5772
|
+
const x = (api.coord([api.value(0), 0])[0] ?? 0) + api.value(2) * band;
|
|
5773
|
+
const nearRight = x > gx + width * 0.7;
|
|
5774
|
+
return {
|
|
5775
|
+
type: "group",
|
|
5776
|
+
children: [
|
|
5777
|
+
{
|
|
5778
|
+
type: "line",
|
|
5779
|
+
shape: { x1: x, y1: gy, x2: x, y2: gy + height },
|
|
5780
|
+
style: { stroke: style.lineColor || "#888", lineWidth: 1.5, lineDash: [4, 4], fill: "none" }
|
|
5781
|
+
},
|
|
5782
|
+
{
|
|
5783
|
+
type: "text",
|
|
5784
|
+
style: {
|
|
5785
|
+
text: style.text,
|
|
5786
|
+
x,
|
|
5787
|
+
y: gy - 4,
|
|
5788
|
+
fill: style.labelColor || "#888",
|
|
5789
|
+
textAlign: nearRight ? "right" : "left",
|
|
5790
|
+
textVerticalAlign: "bottom"
|
|
5791
|
+
}
|
|
5792
|
+
}
|
|
5793
|
+
]
|
|
5794
|
+
};
|
|
5795
|
+
};
|
|
5796
|
+
}
|
|
5797
|
+
var ROW_STYLE3 = "display:flex;align-items:center;gap:8px;line-height:20px";
|
|
5798
|
+
function buildHistogramOption(config) {
|
|
5799
|
+
const { locale } = config;
|
|
5800
|
+
const t = textOf4(locale);
|
|
5801
|
+
const { bins, total, colors, valueFormatter, threshold, showTooltip = true, countUnit = t.countUnit } = config;
|
|
5802
|
+
const pos = threshold ? thresholdPosition(bins, threshold.value) : null;
|
|
5803
|
+
const option = {
|
|
5804
|
+
...chartMotion(false),
|
|
5805
|
+
legend: { show: false },
|
|
5806
|
+
grid: { top: pos === null ? 16 : 28, right: 16, bottom: 4, left: 4, containLabel: true },
|
|
5807
|
+
tooltip: {
|
|
5808
|
+
show: showTooltip,
|
|
5809
|
+
trigger: "axis",
|
|
5810
|
+
axisPointer: { type: "shadow" },
|
|
5811
|
+
formatter: (params) => {
|
|
5812
|
+
const list = Array.isArray(params) ? params : [params];
|
|
5813
|
+
const bin = bins[(list.find((p) => p.seriesId === "count") ?? list[0])?.dataIndex ?? 0];
|
|
5814
|
+
if (!bin) return "";
|
|
5815
|
+
const color = escapeHtml((bin.overflow ? colors.overflow : colors.bar) || "currentColor");
|
|
5816
|
+
const line = (name, text) => `<div style="${ROW_STYLE3}"><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>`;
|
|
5817
|
+
return `<div style="font-weight:500;margin-bottom:4px">${escapeHtml(binLabel(bin, valueFormatter, locale))}</div>` + line(t.countHeader(countUnit), t.count(bin.count, countUnit)) + line(t.share, percent(bin.count, total));
|
|
5818
|
+
}
|
|
5819
|
+
},
|
|
5820
|
+
xAxis: {
|
|
5821
|
+
type: "category",
|
|
5822
|
+
data: bins.map((b) => binLabel(b, valueFormatter, locale)),
|
|
5823
|
+
axisTick: { show: false },
|
|
5824
|
+
axisLabel: { hideOverlap: true }
|
|
5825
|
+
},
|
|
5826
|
+
yAxis: {
|
|
5827
|
+
type: "value",
|
|
5828
|
+
minInterval: 1,
|
|
5829
|
+
axisLine: { show: false },
|
|
5830
|
+
axisTick: { show: false },
|
|
5831
|
+
splitLine: { show: true }
|
|
5832
|
+
},
|
|
5833
|
+
series: [
|
|
5834
|
+
{
|
|
5835
|
+
id: "count",
|
|
5836
|
+
type: "bar",
|
|
5837
|
+
barCategoryGap: "6%",
|
|
5838
|
+
data: bins.map((b) => ({
|
|
5839
|
+
value: b.count,
|
|
5840
|
+
itemStyle: { color: (b.overflow ? colors.overflow : colors.bar) || void 0, borderRadius: [2, 2, 0, 0] }
|
|
5841
|
+
})),
|
|
5842
|
+
label: { show: false, color: config.labelColor, fontVariantNumeric: "tabular-nums" }
|
|
5843
|
+
},
|
|
5844
|
+
...threshold && pos !== null ? [
|
|
5845
|
+
{
|
|
5846
|
+
id: "threshold",
|
|
5847
|
+
type: "custom",
|
|
5848
|
+
silent: true,
|
|
5849
|
+
z: 10,
|
|
5850
|
+
animation: false,
|
|
5851
|
+
tooltip: { show: false },
|
|
5852
|
+
encode: { x: 0, y: 1 },
|
|
5853
|
+
// [階級の添字, 0(y の位置は使わない), 階級の中での位置(左端 -0.5 〜 右端 0.5)]
|
|
5854
|
+
data: [thresholdPoint(bins, threshold.value)],
|
|
5855
|
+
renderItem: thresholdRenderer({
|
|
5856
|
+
text: `${threshold.label ?? t.threshold} ${valueFormatter(threshold.value)}`,
|
|
5857
|
+
lineColor: config.lineColor,
|
|
5858
|
+
labelColor: config.labelColor
|
|
5859
|
+
})
|
|
5860
|
+
}
|
|
5861
|
+
] : []
|
|
5862
|
+
]
|
|
5863
|
+
};
|
|
5864
|
+
return mergeChartOptions(option, config.chartOptions);
|
|
5865
|
+
}
|
|
5866
|
+
var NO_VALUES = [];
|
|
5867
|
+
var HistogramChart = forwardRef(function HistogramChart2({
|
|
5868
|
+
values = NO_VALUES,
|
|
5869
|
+
binWidth,
|
|
5870
|
+
start,
|
|
5871
|
+
max,
|
|
5872
|
+
threshold,
|
|
5873
|
+
countUnit: countUnitProp,
|
|
5874
|
+
valueLabel,
|
|
5875
|
+
format,
|
|
5876
|
+
valueFormatter: valueFormatterProp,
|
|
5877
|
+
showTooltip = true,
|
|
5878
|
+
title,
|
|
5879
|
+
summary,
|
|
5880
|
+
actions,
|
|
5881
|
+
fileName,
|
|
5882
|
+
isLoading,
|
|
5883
|
+
emptyState,
|
|
5884
|
+
height,
|
|
5885
|
+
chartOptions,
|
|
5886
|
+
ariaLabel,
|
|
5887
|
+
className,
|
|
5888
|
+
...rest
|
|
5889
|
+
}, ref) {
|
|
5890
|
+
const { ref: frameRef, tokens } = useChartSurface(ref);
|
|
5891
|
+
const locale = useLocale();
|
|
5892
|
+
const t = TEXT15[uiLanguage(locale)];
|
|
5893
|
+
const countUnit = countUnitProp ?? t.countUnit;
|
|
5894
|
+
const valueFormatter = useMemo(
|
|
5895
|
+
() => valueFormatterProp ?? (format === void 0 ? toValueFormatter("number", locale) : resolveValueFormatter(void 0, format, locale)),
|
|
5896
|
+
[valueFormatterProp, format, locale]
|
|
5897
|
+
);
|
|
5898
|
+
const bins = useMemo(() => histogramBins(values, { binWidth, start, max }), [values, binWidth, start, max]);
|
|
5899
|
+
const total = useMemo(() => bins.reduce((sum, b) => sum + b.count, 0), [bins]);
|
|
5900
|
+
const colors = useMemo(() => {
|
|
5901
|
+
const [bar = ""] = resolveChartColors(["chart-1"], tokens);
|
|
5902
|
+
return { bar, overflow: resolveFillColors(tokens).neutral };
|
|
5903
|
+
}, [tokens]);
|
|
5904
|
+
const option = useMemo(
|
|
5905
|
+
() => buildHistogramOption({
|
|
5906
|
+
bins,
|
|
5907
|
+
total,
|
|
5908
|
+
colors,
|
|
5909
|
+
valueFormatter,
|
|
5910
|
+
countUnit,
|
|
5911
|
+
threshold,
|
|
5912
|
+
showTooltip,
|
|
5913
|
+
labelColor: tokens?.foreground ?? void 0,
|
|
5914
|
+
lineColor: tokens?.mutedForeground ?? void 0,
|
|
5915
|
+
chartOptions,
|
|
5916
|
+
locale
|
|
5917
|
+
}),
|
|
5918
|
+
[bins, total, colors, valueFormatter, countUnit, threshold, showTooltip, tokens, chartOptions, locale]
|
|
5919
|
+
);
|
|
5920
|
+
const dataTable = useMemo(
|
|
5921
|
+
() => histogramDataTable(bins, valueFormatter, { total, countUnit, valueLabel, locale }),
|
|
5922
|
+
[bins, valueFormatter, total, countUnit, valueLabel, locale]
|
|
5923
|
+
);
|
|
5924
|
+
const resolvedSummary = useMemo(
|
|
5925
|
+
() => summary === "auto" ? buildHistogramSummary(bins, valueFormatter, {
|
|
5926
|
+
total,
|
|
5927
|
+
countUnit,
|
|
5928
|
+
threshold,
|
|
5929
|
+
atOrAbove: threshold ? countAtOrAbove(values, threshold.value, bins[0]?.from) : void 0,
|
|
5930
|
+
locale
|
|
5931
|
+
}) : summary,
|
|
5932
|
+
[summary, bins, valueFormatter, total, countUnit, threshold, values, locale]
|
|
5933
|
+
);
|
|
5934
|
+
const label2 = ariaLabel ?? t.chart(valueLabel ?? t.valueInSentence);
|
|
5935
|
+
return /* @__PURE__ */ jsx(
|
|
5936
|
+
ChartFrame,
|
|
5937
|
+
{
|
|
5938
|
+
...chartRootProps(rest),
|
|
5939
|
+
ref: frameRef,
|
|
5940
|
+
title,
|
|
5941
|
+
summary: resolvedSummary,
|
|
5942
|
+
isLoading: isLoading ?? false,
|
|
5943
|
+
isEmpty: bins.length === 0,
|
|
5944
|
+
emptyState,
|
|
5945
|
+
height,
|
|
5946
|
+
variant: "bar",
|
|
5947
|
+
ariaLabel: label2,
|
|
5948
|
+
className,
|
|
5949
|
+
dataTable,
|
|
5950
|
+
children: /* @__PURE__ */ jsx(EChart, { option, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary: resolvedSummary } })
|
|
5951
|
+
}
|
|
5952
|
+
);
|
|
5953
|
+
});
|
|
5954
|
+
HistogramChart.displayName = "HistogramChart";
|
|
5955
|
+
var TEXT16 = {
|
|
5956
|
+
ja: {
|
|
5957
|
+
value: "\u5024",
|
|
5958
|
+
valueInSentence: "\u5024",
|
|
5959
|
+
medianOf: (name, label2, median) => `${name}\u306E${label2}\u306E\u4E2D\u592E\u5024\u306F ${median}`,
|
|
5960
|
+
medianRange: (label2, top, topMedian, low, lowMedian) => `${label2}\u306E\u4E2D\u592E\u5024\u304C\u6700\u3082\u9AD8\u3044\u306E\u306F ${top}\uFF08${topMedian}\uFF09\u3001\u6700\u3082\u4F4E\u3044\u306E\u306F ${low}\uFF08${lowMedian}\uFF09`,
|
|
5961
|
+
outliers: (n) => `\u5916\u308C\u5024\u306F ${n} \u4EF6`,
|
|
5962
|
+
sentenceJoin: "\u3002",
|
|
5963
|
+
columns: ["\u7FA4", "\u4EF6\u6570", "\u6700\u5C0F\uFF08\u3072\u3052\uFF09", "\u7B2C1\u56DB\u5206\u4F4D", "\u4E2D\u592E\u5024", "\u7B2C3\u56DB\u5206\u4F4D", "\u6700\u5927\uFF08\u3072\u3052\uFF09", "\u5916\u308C\u5024"],
|
|
5964
|
+
listJoin: "\u3001",
|
|
5965
|
+
none: "\u306A\u3057",
|
|
5966
|
+
tooltipTitle: (name, label2, count) => `${name}\uFF08${label2}\u30FB${count}\u4EF6\uFF09`,
|
|
5967
|
+
max: "\u6700\u5927\uFF08\u3072\u3052\uFF09",
|
|
5968
|
+
q3: "\u7B2C3\u56DB\u5206\u4F4D",
|
|
5969
|
+
median: "\u4E2D\u592E\u5024",
|
|
5970
|
+
q1: "\u7B2C1\u56DB\u5206\u4F4D",
|
|
5971
|
+
min: "\u6700\u5C0F\uFF08\u3072\u3052\uFF09",
|
|
5972
|
+
outlierRow: "\u5916\u308C\u5024",
|
|
5973
|
+
chart: (label2) => `${label2}\u306E\u7BB1\u3072\u3052\u56F3`
|
|
5974
|
+
},
|
|
5975
|
+
en: {
|
|
5976
|
+
value: "Value",
|
|
5977
|
+
valueInSentence: "value",
|
|
5978
|
+
medianOf: (name, label2, median) => `Median ${label2} for ${name}: ${median}`,
|
|
5979
|
+
medianRange: (label2, top, topMedian, low, lowMedian) => `Highest median ${label2}: ${top} (${topMedian}); lowest: ${low} (${lowMedian})`,
|
|
5980
|
+
outliers: (n) => n === 1 ? "1 outlier" : `${n} outliers`,
|
|
5981
|
+
sentenceJoin: ". ",
|
|
5982
|
+
columns: ["Group", "Count", "Min (whisker)", "Q1", "Median", "Q3", "Max (whisker)", "Outliers"],
|
|
5983
|
+
listJoin: ", ",
|
|
5984
|
+
none: "None",
|
|
5985
|
+
tooltipTitle: (name, label2, count) => `${name} (${label2}, n=${count})`,
|
|
5986
|
+
max: "Max (whisker)",
|
|
5987
|
+
q3: "Q3",
|
|
5988
|
+
median: "Median",
|
|
5989
|
+
q1: "Q1",
|
|
5990
|
+
min: "Min (whisker)",
|
|
5991
|
+
outlierRow: "Outliers",
|
|
5992
|
+
chart: (label2) => `Box plot of ${label2}`
|
|
5993
|
+
}
|
|
5994
|
+
};
|
|
5995
|
+
var textOf5 = (locale) => TEXT16[uiLanguage(resolveLocale(locale))];
|
|
5996
|
+
function boxPlotEntries(groups, whisker) {
|
|
5997
|
+
return groups.map((g) => ({ name: g.name, stats: boxStats(g.values, whisker) }));
|
|
5998
|
+
}
|
|
5999
|
+
function buildBoxPlotSummary(entries, formatter, valueLabel, locale) {
|
|
6000
|
+
const t = textOf5(locale);
|
|
6001
|
+
const label2 = valueLabel ?? t.valueInSentence;
|
|
6002
|
+
const real = entries.filter((e) => e.stats !== null);
|
|
6003
|
+
if (real.length === 0) return void 0;
|
|
6004
|
+
const top = real.reduce((a, b) => b.stats.median > a.stats.median ? b : a);
|
|
6005
|
+
const low = real.reduce((a, b) => b.stats.median < a.stats.median ? b : a);
|
|
6006
|
+
const parts = [
|
|
6007
|
+
real.length === 1 ? t.medianOf(top.name, label2, formatter(top.stats.median)) : t.medianRange(label2, top.name, formatter(top.stats.median), low.name, formatter(low.stats.median))
|
|
6008
|
+
];
|
|
6009
|
+
const outliers = real.reduce((sum, e) => sum + e.stats.outliers.length, 0);
|
|
6010
|
+
if (outliers > 0) parts.push(t.outliers(outliers));
|
|
6011
|
+
return parts.join(t.sentenceJoin);
|
|
6012
|
+
}
|
|
6013
|
+
function boxPlotDataTable(entries, formatter, locale) {
|
|
6014
|
+
const t = textOf5(locale);
|
|
6015
|
+
const f = (n) => n === void 0 ? EMPTY_VALUE : formatter(n);
|
|
6016
|
+
return {
|
|
6017
|
+
columns: [...t.columns],
|
|
6018
|
+
rows: entries.map(({ name, stats: s }) => [
|
|
6019
|
+
name,
|
|
6020
|
+
s ? `${s.count}` : EMPTY_VALUE,
|
|
6021
|
+
f(s?.whiskerLow),
|
|
6022
|
+
f(s?.q1),
|
|
6023
|
+
f(s?.median),
|
|
6024
|
+
f(s?.q3),
|
|
6025
|
+
f(s?.whiskerHigh),
|
|
6026
|
+
s ? s.outliers.length > 0 ? s.outliers.map(formatter).join(t.listJoin) : t.none : EMPTY_VALUE
|
|
6027
|
+
])
|
|
6028
|
+
};
|
|
6029
|
+
}
|
|
6030
|
+
var ROW_STYLE4 = "display:flex;align-items:center;gap:8px;line-height:20px";
|
|
6031
|
+
var BOX_SHARE = 0.4;
|
|
6032
|
+
function boxPlotRenderer(color, outliers) {
|
|
6033
|
+
return (_params, api) => {
|
|
6034
|
+
const x = api.coord([api.value(0), api.value(3)])[0] ?? 0;
|
|
6035
|
+
const y = (dim) => api.coord([api.value(0), api.value(dim)])[1] ?? 0;
|
|
6036
|
+
const band = Math.abs(api.size([1, 0])[0] ?? 0);
|
|
6037
|
+
const half = band * BOX_SHARE / 2;
|
|
6038
|
+
const cap = half / 2;
|
|
6039
|
+
const [yLow, yQ1, yMed, yQ3, yHigh] = [y(1), y(2), y(3), y(4), y(5)];
|
|
6040
|
+
const stroke = { stroke: color, lineWidth: 1.5, fill: "none" };
|
|
6041
|
+
const line = (x1, y1, x2, y2) => ({ type: "line", shape: { x1, y1, x2, y2 }, style: stroke });
|
|
6042
|
+
return {
|
|
6043
|
+
type: "group",
|
|
6044
|
+
children: [
|
|
6045
|
+
line(x, yHigh, x, yQ3),
|
|
6046
|
+
line(x, yQ1, x, yLow),
|
|
6047
|
+
line(x - cap, yHigh, x + cap, yHigh),
|
|
6048
|
+
line(x - cap, yLow, x + cap, yLow),
|
|
6049
|
+
{
|
|
6050
|
+
type: "rect",
|
|
6051
|
+
shape: { x: x - half, y: Math.min(yQ3, yQ1), width: half * 2, height: Math.abs(yQ1 - yQ3), r: 2 },
|
|
6052
|
+
style: { fill: withAlpha(color, 0.25), stroke: color, lineWidth: 1.5 }
|
|
6053
|
+
},
|
|
6054
|
+
line(x - half, yMed, x + half, yMed),
|
|
6055
|
+
...(outliers[api.value(0)] ?? []).map((v) => ({
|
|
6056
|
+
type: "circle",
|
|
6057
|
+
shape: { cx: x, cy: api.coord([api.value(0), v])[1] ?? 0, r: 3 },
|
|
6058
|
+
style: { fill: "transparent", stroke: color, lineWidth: 1.5 }
|
|
6059
|
+
}))
|
|
6060
|
+
]
|
|
6061
|
+
};
|
|
6062
|
+
};
|
|
6063
|
+
}
|
|
6064
|
+
function buildBoxPlotOption(config) {
|
|
6065
|
+
const t = textOf5(config.locale);
|
|
6066
|
+
const { entries, valueFormatter, showTooltip = true, valueLabel = t.value } = config;
|
|
6067
|
+
const axisFormatter = config.axisFormatter ?? valueFormatter;
|
|
6068
|
+
const color = config.color || "#888";
|
|
6069
|
+
const data = entries.flatMap((e, i) => e.stats ? [[i, e.stats.whiskerLow, e.stats.q1, e.stats.median, e.stats.q3, e.stats.whiskerHigh, e.stats.min, e.stats.max]] : []);
|
|
6070
|
+
const entryAt = (i) => entries[i];
|
|
6071
|
+
const option = {
|
|
6072
|
+
...chartMotion(false),
|
|
6073
|
+
legend: { show: false },
|
|
6074
|
+
grid: { top: 16, right: 16, bottom: 4, left: 4, containLabel: true },
|
|
6075
|
+
tooltip: {
|
|
6076
|
+
show: showTooltip,
|
|
6077
|
+
trigger: "item",
|
|
6078
|
+
formatter: (params) => {
|
|
6079
|
+
const entry = entryAt(params.value?.[0] ?? -1);
|
|
6080
|
+
const s = entry?.stats;
|
|
6081
|
+
if (!entry || !s) return "";
|
|
6082
|
+
const line = (name, text) => `<div style="${ROW_STYLE4}"><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>`;
|
|
6083
|
+
return `<div style="font-weight:500;margin-bottom:4px">${escapeHtml(t.tooltipTitle(entry.name, valueLabel, s.count))}</div>` + line(t.max, valueFormatter(s.whiskerHigh)) + line(t.q3, valueFormatter(s.q3)) + line(t.median, valueFormatter(s.median)) + line(t.q1, valueFormatter(s.q1)) + line(t.min, valueFormatter(s.whiskerLow)) + (s.outliers.length > 0 ? line(t.outlierRow, s.outliers.map(valueFormatter).join(t.listJoin)) : "");
|
|
6084
|
+
}
|
|
6085
|
+
},
|
|
6086
|
+
xAxis: { type: "category", data: entries.map((e) => e.name), axisTick: { show: false }, axisLabel: { interval: 0, hideOverlap: false } },
|
|
6087
|
+
yAxis: {
|
|
6088
|
+
type: "value",
|
|
6089
|
+
axisLine: { show: false },
|
|
6090
|
+
axisTick: { show: false },
|
|
6091
|
+
splitLine: { show: true },
|
|
6092
|
+
axisLabel: { formatter: (v) => axisFormatter(v) }
|
|
6093
|
+
},
|
|
6094
|
+
series: [
|
|
6095
|
+
{
|
|
6096
|
+
id: "box",
|
|
6097
|
+
type: "custom",
|
|
6098
|
+
encode: { x: 0, y: [1, 2, 3, 4, 5, 6, 7] },
|
|
6099
|
+
data,
|
|
6100
|
+
renderItem: boxPlotRenderer(color, entries.map((e) => e.stats?.outliers ?? []))
|
|
6101
|
+
}
|
|
6102
|
+
]
|
|
6103
|
+
};
|
|
6104
|
+
return mergeChartOptions(option, config.chartOptions);
|
|
6105
|
+
}
|
|
6106
|
+
var NO_GROUPS = [];
|
|
6107
|
+
var BoxPlotChart = forwardRef(function BoxPlotChart2({
|
|
6108
|
+
groups = NO_GROUPS,
|
|
6109
|
+
whisker,
|
|
6110
|
+
valueLabel,
|
|
6111
|
+
format,
|
|
6112
|
+
valueFormatter: valueFormatterProp,
|
|
6113
|
+
showTooltip = true,
|
|
6114
|
+
title,
|
|
6115
|
+
summary,
|
|
6116
|
+
actions,
|
|
6117
|
+
fileName,
|
|
6118
|
+
isLoading,
|
|
6119
|
+
emptyState,
|
|
6120
|
+
height,
|
|
6121
|
+
chartOptions,
|
|
6122
|
+
ariaLabel,
|
|
6123
|
+
className,
|
|
6124
|
+
...rest
|
|
6125
|
+
}, ref) {
|
|
6126
|
+
const { ref: frameRef, tokens } = useChartSurface(ref);
|
|
6127
|
+
const locale = useLocale();
|
|
6128
|
+
const t = TEXT16[uiLanguage(locale)];
|
|
6129
|
+
const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
|
|
6130
|
+
const entries = useMemo(() => boxPlotEntries(groups, whisker), [groups, whisker]);
|
|
6131
|
+
const [color = ""] = useMemo(() => resolveChartColors(["chart-1"], tokens), [tokens]);
|
|
6132
|
+
const option = useMemo(
|
|
6133
|
+
() => buildBoxPlotOption({ entries, color, valueFormatter, valueLabel, showTooltip, labelColor: tokens?.foreground ?? void 0, chartOptions, locale }),
|
|
6134
|
+
[entries, color, valueFormatter, valueLabel, showTooltip, tokens, chartOptions, locale]
|
|
6135
|
+
);
|
|
6136
|
+
const dataTable = useMemo(() => boxPlotDataTable(entries, valueFormatter, locale), [entries, valueFormatter, locale]);
|
|
6137
|
+
const resolvedSummary = useMemo(
|
|
6138
|
+
() => summary === "auto" ? buildBoxPlotSummary(entries, valueFormatter, valueLabel, locale) : summary,
|
|
6139
|
+
[summary, entries, valueFormatter, valueLabel, locale]
|
|
6140
|
+
);
|
|
6141
|
+
const label2 = ariaLabel ?? t.chart(valueLabel ?? t.valueInSentence);
|
|
6142
|
+
return /* @__PURE__ */ jsx(
|
|
6143
|
+
ChartFrame,
|
|
6144
|
+
{
|
|
6145
|
+
...chartRootProps(rest),
|
|
6146
|
+
ref: frameRef,
|
|
6147
|
+
title,
|
|
6148
|
+
summary: resolvedSummary,
|
|
6149
|
+
isLoading: isLoading ?? false,
|
|
6150
|
+
isEmpty: entries.length === 0,
|
|
6151
|
+
emptyState,
|
|
6152
|
+
height,
|
|
6153
|
+
variant: "bar",
|
|
6154
|
+
ariaLabel: label2,
|
|
6155
|
+
className,
|
|
6156
|
+
dataTable,
|
|
6157
|
+
children: /* @__PURE__ */ jsx(EChart, { option, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary: resolvedSummary } })
|
|
6158
|
+
}
|
|
6159
|
+
);
|
|
6160
|
+
});
|
|
6161
|
+
BoxPlotChart.displayName = "BoxPlotChart";
|
|
6162
|
+
var STATUS_LABELS = {
|
|
6163
|
+
ja: {
|
|
6164
|
+
success: "\u6B63\u5E38",
|
|
6165
|
+
partial: "\u4E00\u90E8\u5931\u6557",
|
|
6166
|
+
failed: "\u5931\u6557",
|
|
6167
|
+
delayed: "\u9045\u5EF6",
|
|
6168
|
+
running: "\u5B9F\u884C\u4E2D",
|
|
6169
|
+
stopped: "\u505C\u6B62\u4E2D",
|
|
6170
|
+
active: "\u6709\u52B9",
|
|
6171
|
+
inactive: "\u7121\u52B9",
|
|
6172
|
+
warning: "\u8B66\u544A",
|
|
6173
|
+
error: "\u30A8\u30E9\u30FC",
|
|
6174
|
+
pending: "\u4FDD\u7559\u4E2D"
|
|
6175
|
+
},
|
|
6176
|
+
en: {
|
|
6177
|
+
success: "Healthy",
|
|
6178
|
+
partial: "Partially failed",
|
|
6179
|
+
failed: "Failed",
|
|
6180
|
+
delayed: "Delayed",
|
|
6181
|
+
running: "Running",
|
|
6182
|
+
stopped: "Stopped",
|
|
6183
|
+
active: "Active",
|
|
6184
|
+
inactive: "Inactive",
|
|
6185
|
+
warning: "Warning",
|
|
6186
|
+
error: "Error",
|
|
6187
|
+
pending: "Pending"
|
|
6188
|
+
}
|
|
6189
|
+
};
|
|
6190
|
+
var STATUS_VOCABULARY = {
|
|
6191
|
+
success: { label: STATUS_LABELS.en.success, tone: "positive" },
|
|
6192
|
+
partial: { label: STATUS_LABELS.en.partial, tone: "warning" },
|
|
6193
|
+
failed: { label: STATUS_LABELS.en.failed, tone: "negative" },
|
|
6194
|
+
delayed: { label: STATUS_LABELS.en.delayed, tone: "warning" },
|
|
6195
|
+
running: { label: STATUS_LABELS.en.running, tone: "info" },
|
|
6196
|
+
stopped: { label: STATUS_LABELS.en.stopped, tone: "neutral" },
|
|
6197
|
+
active: { label: STATUS_LABELS.en.active, tone: "positive" },
|
|
6198
|
+
inactive: { label: STATUS_LABELS.en.inactive, tone: "neutral" },
|
|
6199
|
+
warning: { label: STATUS_LABELS.en.warning, tone: "warning" },
|
|
6200
|
+
error: { label: STATUS_LABELS.en.error, tone: "negative" },
|
|
6201
|
+
pending: { label: STATUS_LABELS.en.pending, tone: "info" }
|
|
6202
|
+
};
|
|
6203
|
+
function statusLabel(status, locale) {
|
|
6204
|
+
return Object.hasOwn(STATUS_VOCABULARY, status) ? STATUS_LABELS[uiLanguage(resolveLocale(locale))][status] : status;
|
|
6205
|
+
}
|
|
6206
|
+
var defaultColorMap = Object.fromEntries(
|
|
6207
|
+
Object.entries(STATUS_VOCABULARY).map(([key, { tone }]) => [key, tone])
|
|
6208
|
+
);
|
|
6209
|
+
var legacyColorTones = {
|
|
6210
|
+
green: "positive",
|
|
6211
|
+
gray: "neutral",
|
|
6212
|
+
yellow: "warning",
|
|
6213
|
+
red: "negative",
|
|
6214
|
+
blue: "info"
|
|
6215
|
+
};
|
|
6216
|
+
var toneStyles = {
|
|
6217
|
+
positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive", border: "border-positive/20 dark:border-positive/25" },
|
|
6218
|
+
negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative", border: "border-negative/20 dark:border-negative/25" },
|
|
6219
|
+
warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning", border: "border-warning/20 dark:border-warning/25" },
|
|
6220
|
+
info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info", border: "border-info/20 dark:border-info/25" },
|
|
6221
|
+
neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral", border: "border-neutral/20 dark:border-neutral/25" }
|
|
6222
|
+
};
|
|
6223
|
+
var resolveTone = (color) => {
|
|
6224
|
+
if (color === void 0) return "neutral";
|
|
6225
|
+
if (Object.hasOwn(toneStyles, color)) return color;
|
|
6226
|
+
return legacyColorTones[color] ?? "neutral";
|
|
6227
|
+
};
|
|
6228
|
+
var StatusBadge = forwardRef(function StatusBadge2({ status, label: label2, colorMap, className }, ref) {
|
|
6229
|
+
const locale = useLocale();
|
|
6230
|
+
const mergedColorMap = { ...defaultColorMap, ...colorMap };
|
|
6231
|
+
const style = toneStyles[resolveTone(mergedColorMap[status])];
|
|
6232
|
+
const displayLabel = label2 ?? statusLabel(status, locale);
|
|
6233
|
+
return /* @__PURE__ */ jsxs(
|
|
6234
|
+
Badge,
|
|
6235
|
+
{
|
|
6236
|
+
ref,
|
|
6237
|
+
"data-slot": "status-badge",
|
|
6238
|
+
variant: "outline",
|
|
6239
|
+
className: cn("gap-1.5 rounded-md", style.border, style.bg, style.text, className),
|
|
6240
|
+
"aria-label": displayLabel,
|
|
6241
|
+
children: [
|
|
6242
|
+
/* @__PURE__ */ jsx("span", { className: cn("inline-block size-1.5 rounded-full", style.dot), "aria-hidden": "true" }),
|
|
6243
|
+
displayLabel
|
|
6244
|
+
]
|
|
6245
|
+
}
|
|
6246
|
+
);
|
|
6247
|
+
});
|
|
6248
|
+
StatusBadge.displayName = "StatusBadge";
|
|
6249
|
+
var KIND_ORDER = ["overdue", "risk", "dueSoon", "stale"];
|
|
6250
|
+
var KIND_TONES = {
|
|
6251
|
+
overdue: "negative",
|
|
6252
|
+
risk: "negative",
|
|
6253
|
+
dueSoon: "warning",
|
|
6254
|
+
stale: "info"
|
|
6255
|
+
};
|
|
6256
|
+
var daysEn = (n) => n === 1 ? "1 day" : `${n} days`;
|
|
6257
|
+
var TEXT17 = {
|
|
6258
|
+
ja: {
|
|
6259
|
+
labels: { overdue: "\u671F\u65E5\u8D85\u904E", risk: "\u30EA\u30B9\u30AF", dueSoon: "\u671F\u9650\u9593\u8FD1", stale: "\u6EDE\u7559" },
|
|
6260
|
+
overdue: (days) => `\u671F\u65E5\u3092 ${days} \u65E5\u904E\u304E\u3066\u3044\u307E\u3059`,
|
|
6261
|
+
dueToday: "\u671F\u65E5\u306F\u4ECA\u65E5\u3067\u3059",
|
|
6262
|
+
dueIn: (days) => `\u671F\u65E5\u307E\u3067\u3042\u3068 ${days} \u65E5\u3067\u3059`,
|
|
6263
|
+
stale: (days) => `${days} \u65E5\u9593\u52D5\u304D\u304C\u3042\u308A\u307E\u305B\u3093`,
|
|
6264
|
+
empty: "\u5BFE\u5FDC\u304C\u5FC5\u8981\u306A\u9805\u76EE\u306F\u3042\u308A\u307E\u305B\u3093",
|
|
6265
|
+
due: "\u671F\u65E5",
|
|
6266
|
+
nextAction: "\u6B21\u306E\u4E00\u624B: "
|
|
6267
|
+
},
|
|
6268
|
+
en: {
|
|
6269
|
+
labels: { overdue: "Overdue", risk: "At risk", dueSoon: "Due soon", stale: "Stalled" },
|
|
6270
|
+
overdue: (days) => `${daysEn(days)} overdue`,
|
|
6271
|
+
dueToday: "Due today",
|
|
6272
|
+
dueIn: (days) => `Due in ${daysEn(days)}`,
|
|
6273
|
+
stale: (days) => `No activity for ${daysEn(days)}`,
|
|
6274
|
+
empty: "Nothing needs attention",
|
|
6275
|
+
due: "Due",
|
|
6276
|
+
nextAction: "Next step: "
|
|
6277
|
+
}
|
|
6278
|
+
};
|
|
6279
|
+
TEXT17.en.labels;
|
|
6280
|
+
function toDate2(value) {
|
|
6281
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
6282
|
+
const date = typeof value === "string" ? parseISO(value) : value;
|
|
6283
|
+
return Number.isFinite(date.getTime()) ? date : null;
|
|
6284
|
+
}
|
|
6285
|
+
function judgeAttention(input) {
|
|
6286
|
+
const asOf = toDate2(input.asOf);
|
|
6287
|
+
if (!asOf) return null;
|
|
6288
|
+
const dueSoonDays = input.dueSoonDays ?? 7;
|
|
6289
|
+
const due = toDate2(input.dueDate);
|
|
6290
|
+
if (due) {
|
|
6291
|
+
const untilDue = differenceInCalendarDays(due, asOf);
|
|
6292
|
+
if (untilDue < 0) return { kind: "overdue", days: -untilDue };
|
|
6293
|
+
}
|
|
6294
|
+
if (input.risk) return { kind: "risk", days: 0 };
|
|
6295
|
+
if (due) {
|
|
6296
|
+
const untilDue = differenceInCalendarDays(due, asOf);
|
|
6297
|
+
if (untilDue <= dueSoonDays) return { kind: "dueSoon", days: untilDue };
|
|
6298
|
+
}
|
|
6299
|
+
const last = toDate2(input.lastActivityAt);
|
|
6300
|
+
if (last && input.staleDays !== void 0) {
|
|
6301
|
+
const idle = differenceInCalendarDays(asOf, last);
|
|
6302
|
+
if (idle >= input.staleDays) return { kind: "stale", days: idle };
|
|
6303
|
+
}
|
|
6304
|
+
return null;
|
|
6305
|
+
}
|
|
6306
|
+
function compareAttention(a, b) {
|
|
6307
|
+
if (!a || !b) return a ? -1 : b ? 1 : 0;
|
|
6308
|
+
const byKind = KIND_ORDER.indexOf(a.kind) - KIND_ORDER.indexOf(b.kind);
|
|
6309
|
+
if (byKind !== 0) return byKind;
|
|
6310
|
+
return a.kind === "dueSoon" ? a.days - b.days : b.days - a.days;
|
|
6311
|
+
}
|
|
6312
|
+
function defaultReason(j, labels, t) {
|
|
6313
|
+
switch (j.kind) {
|
|
6314
|
+
case "overdue":
|
|
6315
|
+
return t.overdue(j.days);
|
|
6316
|
+
case "dueSoon":
|
|
6317
|
+
return j.days === 0 ? t.dueToday : t.dueIn(j.days);
|
|
6318
|
+
case "stale":
|
|
6319
|
+
return t.stale(j.days);
|
|
6320
|
+
case "risk":
|
|
6321
|
+
return labels.risk;
|
|
6322
|
+
}
|
|
6323
|
+
}
|
|
6324
|
+
function cell(row, key) {
|
|
6325
|
+
if (!key || row === null || typeof row !== "object") return void 0;
|
|
6326
|
+
return row[key];
|
|
6327
|
+
}
|
|
6328
|
+
function asDateInput(value) {
|
|
6329
|
+
return typeof value === "string" || value instanceof Date ? value : void 0;
|
|
6330
|
+
}
|
|
6331
|
+
function asNode(value) {
|
|
6332
|
+
return typeof value === "string" || typeof value === "number" ? value : null;
|
|
6333
|
+
}
|
|
6334
|
+
function AttentionList({
|
|
6335
|
+
rows,
|
|
6336
|
+
asOf,
|
|
6337
|
+
dueSoonDays,
|
|
6338
|
+
staleDays,
|
|
6339
|
+
labels,
|
|
6340
|
+
getRowId,
|
|
6341
|
+
getTitle,
|
|
6342
|
+
getDueDate,
|
|
6343
|
+
getLastActivityAt,
|
|
6344
|
+
isRisk,
|
|
6345
|
+
idKey,
|
|
6346
|
+
titleKey,
|
|
6347
|
+
dueDateKey,
|
|
6348
|
+
lastActivityAtKey,
|
|
6349
|
+
riskKey,
|
|
6350
|
+
nextActionKey,
|
|
6351
|
+
getReason,
|
|
6352
|
+
getNextAction,
|
|
6353
|
+
getMeta,
|
|
6354
|
+
onRowClick,
|
|
6355
|
+
includeUnflagged = false,
|
|
6356
|
+
emptyTitle,
|
|
6357
|
+
emptyDescription,
|
|
6358
|
+
className,
|
|
6359
|
+
...rest
|
|
6360
|
+
}) {
|
|
6361
|
+
const locale = useLocale();
|
|
6362
|
+
const t = TEXT17[uiLanguage(locale)];
|
|
6363
|
+
const mergedLabels = useMemo(() => ({ ...t.labels, ...labels }), [t, labels]);
|
|
6364
|
+
const colorMap = KIND_TONES;
|
|
6365
|
+
const dueOf = (row) => getDueDate ? getDueDate(row) : asDateInput(cell(row, dueDateKey));
|
|
6366
|
+
const nextActionOf = (row, j) => getNextAction ? getNextAction(row, j) : asNode(cell(row, nextActionKey));
|
|
6367
|
+
const items = (rows ?? []).map((row, index) => ({
|
|
6368
|
+
row,
|
|
6369
|
+
index,
|
|
6370
|
+
judgement: judgeAttention({
|
|
6371
|
+
dueDate: dueOf(row),
|
|
6372
|
+
lastActivityAt: getLastActivityAt ? getLastActivityAt(row) : asDateInput(cell(row, lastActivityAtKey)),
|
|
6373
|
+
risk: isRisk ? isRisk(row) : Boolean(cell(row, riskKey)),
|
|
6374
|
+
asOf,
|
|
6375
|
+
dueSoonDays,
|
|
6376
|
+
staleDays
|
|
6377
|
+
})
|
|
6378
|
+
})).filter((item) => includeUnflagged || item.judgement).sort((a, b) => compareAttention(a.judgement, b.judgement) || a.index - b.index);
|
|
6379
|
+
if (items.length === 0) {
|
|
6380
|
+
return /* @__PURE__ */ jsx(Empty, { title: emptyTitle ?? t.empty, description: emptyDescription, className });
|
|
6381
|
+
}
|
|
6382
|
+
return /* @__PURE__ */ jsx("ul", { "data-slot": "attention-list", className: cn("divide-y divide-border", className), ...rest, children: items.map(({ row, index, judgement }) => {
|
|
6383
|
+
const due = dueOf(row);
|
|
6384
|
+
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6385
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1", children: [
|
|
6386
|
+
judgement && /* @__PURE__ */ jsx(StatusBadge, { status: judgement.kind, label: mergedLabels[judgement.kind], colorMap }),
|
|
6387
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 font-medium", children: getTitle ? getTitle(row) : asNode(cell(row, titleKey)) }),
|
|
6388
|
+
getMeta && /* @__PURE__ */ jsx("span", { className: "text-sm tabular-nums text-muted-foreground", children: getMeta(row) }),
|
|
6389
|
+
due ? /* @__PURE__ */ jsxs("span", { className: "ml-auto text-sm tabular-nums text-muted-foreground", children: [
|
|
6390
|
+
t.due,
|
|
6391
|
+
" ",
|
|
6392
|
+
formatDate(due, "date", locale)
|
|
6393
|
+
] }) : null
|
|
6394
|
+
] }),
|
|
6395
|
+
judgement && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: getReason ? getReason(row, judgement) : defaultReason(judgement, mergedLabels, t) }),
|
|
6396
|
+
judgement && (getNextAction || nextActionKey) && nextActionOf(row, judgement) ? /* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm", children: [
|
|
6397
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t.nextAction }),
|
|
6398
|
+
nextActionOf(row, judgement)
|
|
6399
|
+
] }) : null
|
|
6400
|
+
] });
|
|
6401
|
+
return /* @__PURE__ */ jsx("li", { "data-slot": "attention-list-row", children: onRowClick ? /* @__PURE__ */ jsx(
|
|
6402
|
+
"button",
|
|
6403
|
+
{
|
|
6404
|
+
type: "button",
|
|
6405
|
+
onClick: () => onRowClick(row),
|
|
6406
|
+
className: "block w-full px-3 py-3 text-left transition-colors hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6407
|
+
children: body
|
|
6408
|
+
}
|
|
6409
|
+
) : /* @__PURE__ */ jsx("div", { className: "px-3 py-3", children: body }) }, getRowId ? getRowId(row) : String(cell(row, idKey) ?? index));
|
|
6410
|
+
}) });
|
|
6411
|
+
}
|
|
6412
|
+
AttentionList.displayName = "AttentionList";
|
|
5350
6413
|
function niceStep2(raw) {
|
|
5351
6414
|
if (!(raw > 0) || !Number.isFinite(raw)) return 1;
|
|
5352
6415
|
const exp10 = 10 ** Math.floor(Math.log10(raw));
|
|
@@ -5374,11 +6437,11 @@ var splitCountFor = (height) => height < 200 ? 3 : height < 300 ? 4 : 5;
|
|
|
5374
6437
|
function escapeHtml3(text) {
|
|
5375
6438
|
return text.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
5376
6439
|
}
|
|
5377
|
-
var
|
|
6440
|
+
var TEXT18 = {
|
|
5378
6441
|
ja: { item: "\u9805\u76EE", chart: "\u8907\u5408\u30B0\u30E9\u30D5" },
|
|
5379
6442
|
en: { item: "Item", chart: "Combination chart" }
|
|
5380
6443
|
};
|
|
5381
|
-
var
|
|
6444
|
+
var textOf6 = (locale) => TEXT18[uiLanguage(resolveLocale(locale))];
|
|
5382
6445
|
var axisOf = (s) => s.axis === "right" ? "right" : "left";
|
|
5383
6446
|
function comboSeriesList(series) {
|
|
5384
6447
|
if (!Array.isArray(series)) return [];
|
|
@@ -5531,7 +6594,7 @@ function comboChartDataTable(data, index, series, formatters, labels, locale) {
|
|
|
5531
6594
|
const list = comboSeriesList(series);
|
|
5532
6595
|
const label2 = (key) => labels?.[key] ?? key;
|
|
5533
6596
|
return {
|
|
5534
|
-
columns: [labels?.[index] ??
|
|
6597
|
+
columns: [labels?.[index] ?? textOf6(locale).item, ...list.map((s) => s.label ?? label2(s.key))],
|
|
5535
6598
|
rows: data.map((row) => [
|
|
5536
6599
|
label2(String(row?.[index] ?? "")),
|
|
5537
6600
|
...list.map((s) => {
|
|
@@ -5541,11 +6604,11 @@ function comboChartDataTable(data, index, series, formatters, labels, locale) {
|
|
|
5541
6604
|
])
|
|
5542
6605
|
};
|
|
5543
6606
|
}
|
|
5544
|
-
var
|
|
6607
|
+
var NO_ROWS13 = [];
|
|
5545
6608
|
function ComboChartImpl({
|
|
5546
|
-
data =
|
|
6609
|
+
data = NO_ROWS13,
|
|
5547
6610
|
index,
|
|
5548
|
-
series =
|
|
6611
|
+
series = NO_ROWS13,
|
|
5549
6612
|
format,
|
|
5550
6613
|
rightFormat,
|
|
5551
6614
|
labels,
|
|
@@ -5567,7 +6630,7 @@ function ComboChartImpl({
|
|
|
5567
6630
|
ariaLabel,
|
|
5568
6631
|
...rest
|
|
5569
6632
|
}, ref) {
|
|
5570
|
-
const rows = Array.isArray(data) ? data :
|
|
6633
|
+
const rows = Array.isArray(data) ? data : NO_ROWS13;
|
|
5571
6634
|
const list = useMemo(() => comboSeriesList(series), [series]);
|
|
5572
6635
|
const { ref: frameRef, tokens } = useChartSurface(ref);
|
|
5573
6636
|
const locale = useLocale();
|
|
@@ -5579,40 +6642,743 @@ function ComboChartImpl({
|
|
|
5579
6642
|
() => ({ left: resolveAxisTickFormatter(void 0, format, locale), right: resolveAxisTickFormatter(void 0, rightFormat ?? format, locale) }),
|
|
5580
6643
|
[format, rightFormat, locale]
|
|
5581
6644
|
);
|
|
5582
|
-
const palette = useMemo(() => resolveColors(tokens, list), [tokens, list]);
|
|
5583
|
-
const option = useMemo(
|
|
5584
|
-
() => buildComboChartOption({
|
|
6645
|
+
const palette = useMemo(() => resolveColors(tokens, list), [tokens, list]);
|
|
6646
|
+
const option = useMemo(
|
|
6647
|
+
() => buildComboChartOption({
|
|
6648
|
+
data: rows,
|
|
6649
|
+
index,
|
|
6650
|
+
series: list,
|
|
6651
|
+
palette: palette.series,
|
|
6652
|
+
referenceColor: palette.reference,
|
|
6653
|
+
labels,
|
|
6654
|
+
formatters,
|
|
6655
|
+
ticks,
|
|
6656
|
+
referenceLines,
|
|
6657
|
+
stacked,
|
|
6658
|
+
layout,
|
|
6659
|
+
showLegend,
|
|
6660
|
+
showTooltip,
|
|
6661
|
+
plotHeight: height,
|
|
6662
|
+
chartOptions
|
|
6663
|
+
}),
|
|
6664
|
+
[rows, index, list, palette, labels, formatters, ticks, referenceLines, stacked, layout, showLegend, showTooltip, height, chartOptions]
|
|
6665
|
+
);
|
|
6666
|
+
const onEvents = useMemo(
|
|
6667
|
+
() => onSelect ? {
|
|
6668
|
+
click: (params) => {
|
|
6669
|
+
const p = params;
|
|
6670
|
+
if (p.componentType !== "series" || (p.seriesIndex ?? Infinity) >= list.length) return;
|
|
6671
|
+
const row = rows[p.dataIndex ?? -1];
|
|
6672
|
+
if (row) onSelect(row);
|
|
6673
|
+
}
|
|
6674
|
+
} : void 0,
|
|
6675
|
+
[onSelect, rows, list.length]
|
|
6676
|
+
);
|
|
6677
|
+
const dataTable = useMemo(() => comboChartDataTable(rows, index, list, formatters, labels, locale), [rows, index, list, formatters, labels, locale]);
|
|
6678
|
+
const label2 = ariaLabel ?? textOf6(locale).chart;
|
|
6679
|
+
return /* @__PURE__ */ jsx(
|
|
6680
|
+
ChartFrame,
|
|
6681
|
+
{
|
|
6682
|
+
...chartRootProps(rest),
|
|
6683
|
+
ref: frameRef,
|
|
6684
|
+
title,
|
|
6685
|
+
summary,
|
|
6686
|
+
isLoading: isLoading ?? false,
|
|
6687
|
+
isEmpty: rows.length === 0,
|
|
6688
|
+
emptyState,
|
|
6689
|
+
height,
|
|
6690
|
+
variant: "bar",
|
|
6691
|
+
ariaLabel: label2,
|
|
6692
|
+
className,
|
|
6693
|
+
dataTable,
|
|
6694
|
+
children: /* @__PURE__ */ jsx(EChart, { option, onEvents, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary } })
|
|
6695
|
+
}
|
|
6696
|
+
);
|
|
6697
|
+
}
|
|
6698
|
+
function resolveColors(tokens, series) {
|
|
6699
|
+
const resolved = resolveChartColors(
|
|
6700
|
+
["var(--muted-foreground)", ...series.map((s, i) => s.color ?? DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length])],
|
|
6701
|
+
tokens
|
|
6702
|
+
);
|
|
6703
|
+
return { reference: resolved[0] ?? "", series: resolved.slice(1) };
|
|
6704
|
+
}
|
|
6705
|
+
var ComboChart = forwardRef(ComboChartImpl);
|
|
6706
|
+
ComboChart.displayName = "ComboChart";
|
|
6707
|
+
|
|
6708
|
+
// ../squadkit/registry/lib/forecast.ts
|
|
6709
|
+
var FORECAST_MIN_POINTS = 5;
|
|
6710
|
+
var FORECAST_MAX_FIT_POINTS = 1e3;
|
|
6711
|
+
function inverseNormal(p) {
|
|
6712
|
+
if (!(p > 0 && p < 1)) return p <= 0 ? -Infinity : Infinity;
|
|
6713
|
+
const a = [-39.69683028665376, 220.9460984245205, -275.9285104469687, 138.357751867269, -30.66479806614716, 2.506628277459239];
|
|
6714
|
+
const b = [-54.47609879822406, 161.5858368580409, -155.6989798598866, 66.80131188771972, -13.28068155288572];
|
|
6715
|
+
const c = [-0.007784894002430293, -0.3223964580411365, -2.400758277161838, -2.549732539343734, 4.374664141464968, 2.938163982698783];
|
|
6716
|
+
const d = [0.007784695709041462, 0.3224671290700398, 2.445134137142996, 3.754408661907416];
|
|
6717
|
+
const low = 0.02425;
|
|
6718
|
+
if (p < low) {
|
|
6719
|
+
const q2 = Math.sqrt(-2 * Math.log(p));
|
|
6720
|
+
return (((((c[0] * q2 + c[1]) * q2 + c[2]) * q2 + c[3]) * q2 + c[4]) * q2 + c[5]) / ((((d[0] * q2 + d[1]) * q2 + d[2]) * q2 + d[3]) * q2 + 1);
|
|
6721
|
+
}
|
|
6722
|
+
if (p > 1 - low) {
|
|
6723
|
+
const q2 = Math.sqrt(-2 * Math.log(1 - p));
|
|
6724
|
+
return -(((((c[0] * q2 + c[1]) * q2 + c[2]) * q2 + c[3]) * q2 + c[4]) * q2 + c[5]) / ((((d[0] * q2 + d[1]) * q2 + d[2]) * q2 + d[3]) * q2 + 1);
|
|
6725
|
+
}
|
|
6726
|
+
const q = p - 0.5;
|
|
6727
|
+
const r = q * q;
|
|
6728
|
+
return (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q / (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1);
|
|
6729
|
+
}
|
|
6730
|
+
function nelderMead(f, start, step, maxEvals) {
|
|
6731
|
+
const dim = start.length;
|
|
6732
|
+
const simplex = [{ x: start.slice(), fx: f(start) }];
|
|
6733
|
+
for (let i = 0; i < dim; i++) {
|
|
6734
|
+
const x = start.slice();
|
|
6735
|
+
x[i] = x[i] + step;
|
|
6736
|
+
simplex.push({ x, fx: f(x) });
|
|
6737
|
+
}
|
|
6738
|
+
let evals = dim + 1;
|
|
6739
|
+
const combine = (a, b, t) => a.map((v, i) => v + t * (b[i] - v));
|
|
6740
|
+
while (evals < maxEvals) {
|
|
6741
|
+
simplex.sort((p, q) => p.fx - q.fx);
|
|
6742
|
+
const best = simplex[0];
|
|
6743
|
+
const worst = simplex[dim];
|
|
6744
|
+
const spread = Math.abs(worst.fx - best.fx);
|
|
6745
|
+
if (spread <= 1e-10 * (Math.abs(best.fx) + 1e-20)) break;
|
|
6746
|
+
const centroid = new Array(dim).fill(0);
|
|
6747
|
+
for (let i = 0; i < dim; i++) for (let j = 0; j < dim; j++) centroid[j] += simplex[i].x[j] / dim;
|
|
6748
|
+
const reflected = combine(centroid, worst.x, -1);
|
|
6749
|
+
const fr = f(reflected);
|
|
6750
|
+
evals++;
|
|
6751
|
+
if (fr < best.fx) {
|
|
6752
|
+
const expanded = combine(centroid, worst.x, -2);
|
|
6753
|
+
const fe = f(expanded);
|
|
6754
|
+
evals++;
|
|
6755
|
+
simplex[dim] = fe < fr ? { x: expanded, fx: fe } : { x: reflected, fx: fr };
|
|
6756
|
+
continue;
|
|
6757
|
+
}
|
|
6758
|
+
if (fr < simplex[dim - 1].fx) {
|
|
6759
|
+
simplex[dim] = { x: reflected, fx: fr };
|
|
6760
|
+
continue;
|
|
6761
|
+
}
|
|
6762
|
+
const outside = fr < worst.fx;
|
|
6763
|
+
const contracted = outside ? combine(centroid, reflected, 0.5) : combine(centroid, worst.x, 0.5);
|
|
6764
|
+
const fc = f(contracted);
|
|
6765
|
+
evals++;
|
|
6766
|
+
if (fc < (outside ? fr : worst.fx)) {
|
|
6767
|
+
simplex[dim] = { x: contracted, fx: fc };
|
|
6768
|
+
continue;
|
|
6769
|
+
}
|
|
6770
|
+
for (let i = 1; i <= dim; i++) {
|
|
6771
|
+
const x = combine(best.x, simplex[i].x, 0.5);
|
|
6772
|
+
simplex[i] = { x, fx: f(x) };
|
|
6773
|
+
evals++;
|
|
6774
|
+
}
|
|
6775
|
+
}
|
|
6776
|
+
simplex.sort((p, q) => p.fx - q.fx);
|
|
6777
|
+
return simplex[0];
|
|
6778
|
+
}
|
|
6779
|
+
function run(y, spec, p) {
|
|
6780
|
+
let l = p.l0;
|
|
6781
|
+
let b = spec.trend === "additive" ? p.b0 : 0;
|
|
6782
|
+
const s = spec.season === "none" ? [] : p.s0.slice();
|
|
6783
|
+
const mult = spec.season === "multiplicative";
|
|
6784
|
+
let sse = 0;
|
|
6785
|
+
for (let t = 0; t < y.length; t++) {
|
|
6786
|
+
const j = t % spec.m;
|
|
6787
|
+
const base = l + b;
|
|
6788
|
+
const sj = spec.season === "none" ? mult ? 1 : 0 : s[j];
|
|
6789
|
+
if (mult && (sj <= 0 || base <= 0)) return null;
|
|
6790
|
+
const yhat = mult ? base * sj : base + sj;
|
|
6791
|
+
const e = y[t] - yhat;
|
|
6792
|
+
if (!Number.isFinite(e)) return null;
|
|
6793
|
+
sse += e * e;
|
|
6794
|
+
if (mult) {
|
|
6795
|
+
l = base + p.alpha * e / sj;
|
|
6796
|
+
if (spec.trend === "additive") b = b + p.beta * e / sj;
|
|
6797
|
+
s[j] = sj + p.gamma * e / base;
|
|
6798
|
+
} else {
|
|
6799
|
+
l = base + p.alpha * e;
|
|
6800
|
+
if (spec.trend === "additive") b = b + p.beta * e;
|
|
6801
|
+
if (spec.season === "additive") s[j] = sj + p.gamma * e;
|
|
6802
|
+
}
|
|
6803
|
+
}
|
|
6804
|
+
return Number.isFinite(sse) ? { sse, level: l, slope: b, season: s } : null;
|
|
6805
|
+
}
|
|
6806
|
+
function initialSeason(y, m, mult) {
|
|
6807
|
+
const len = Math.min(Math.floor(y.length / m), 3) * m;
|
|
6808
|
+
const half = Math.floor(m / 2);
|
|
6809
|
+
const sums = new Array(m).fill(0);
|
|
6810
|
+
const counts = new Array(m).fill(0);
|
|
6811
|
+
for (let t = half; t < len - half; t++) {
|
|
6812
|
+
let trend;
|
|
6813
|
+
if (m % 2 === 0) {
|
|
6814
|
+
let sum = 0.5 * y[t - half] + 0.5 * y[t + half];
|
|
6815
|
+
for (let k = t - half + 1; k < t + half; k++) sum += y[k];
|
|
6816
|
+
trend = sum / m;
|
|
6817
|
+
} else {
|
|
6818
|
+
let sum = 0;
|
|
6819
|
+
for (let k = t - half; k <= t + half; k++) sum += y[k];
|
|
6820
|
+
trend = sum / m;
|
|
6821
|
+
}
|
|
6822
|
+
if (mult && trend <= 0) continue;
|
|
6823
|
+
sums[t % m] += mult ? y[t] / trend : y[t] - trend;
|
|
6824
|
+
counts[t % m]++;
|
|
6825
|
+
}
|
|
6826
|
+
const raw = sums.map((v, j) => counts[j] > 0 ? v / counts[j] : mult ? 1 : 0);
|
|
6827
|
+
const mean = raw.reduce((a, v) => a + v, 0) / m;
|
|
6828
|
+
return mult ? raw.map((v) => mean > 0 ? v / mean : 1) : raw.map((v) => v - mean);
|
|
6829
|
+
}
|
|
6830
|
+
function linearFit(z) {
|
|
6831
|
+
const n = z.length;
|
|
6832
|
+
if (n < 2) return { intercept: z[0] ?? 0, slope: 0 };
|
|
6833
|
+
const mt = (n - 1) / 2;
|
|
6834
|
+
const mz = z.reduce((a, v) => a + v, 0) / n;
|
|
6835
|
+
let num = 0;
|
|
6836
|
+
let den = 0;
|
|
6837
|
+
z.forEach((v, t) => {
|
|
6838
|
+
num += (t - mt) * (v - mz);
|
|
6839
|
+
den += (t - mt) * (t - mt);
|
|
6840
|
+
});
|
|
6841
|
+
const slope = den === 0 ? 0 : num / den;
|
|
6842
|
+
return { intercept: mz - slope * mt, slope };
|
|
6843
|
+
}
|
|
6844
|
+
var logistic = (x) => 1 / (1 + Math.exp(-x));
|
|
6845
|
+
var logit = (p) => Math.log(p / (1 - p));
|
|
6846
|
+
var EDGE = 1e-4;
|
|
6847
|
+
function fitModel(y, spec) {
|
|
6848
|
+
const n = y.length;
|
|
6849
|
+
const { m } = spec;
|
|
6850
|
+
const seasonal = spec.season !== "none";
|
|
6851
|
+
const mult = spec.season === "multiplicative";
|
|
6852
|
+
const s0 = seasonal ? initialSeason(y, m, mult) : [];
|
|
6853
|
+
const adjusted = y.map((v, t) => !seasonal ? v : mult ? v / s0[t % m] : v - s0[t % m]);
|
|
6854
|
+
const head = adjusted.slice(0, seasonal ? Math.min(n, Math.max(2 * m, 10)) : Math.min(n, 10));
|
|
6855
|
+
const line = linearFit(head);
|
|
6856
|
+
const trend = spec.trend === "additive";
|
|
6857
|
+
const l0Init = trend ? line.intercept - line.slope : head.slice(0, Math.min(head.length, 4)).reduce((a, v) => a + v, 0) / Math.min(head.length, 4);
|
|
6858
|
+
const b0Init = trend ? line.slope : 0;
|
|
6859
|
+
const mean = y.reduce((a, v) => a + v, 0) / n;
|
|
6860
|
+
const sd = Math.sqrt(y.reduce((a, v) => a + (v - mean) * (v - mean), 0) / n);
|
|
6861
|
+
const scale = Math.max(sd, Math.abs(mean) * 1e-3, 1e-9);
|
|
6862
|
+
const decode = (x) => {
|
|
6863
|
+
let i = 0;
|
|
6864
|
+
const alpha = EDGE + (1 - 2 * EDGE) * logistic(x[i++]);
|
|
6865
|
+
const beta = trend ? alpha * (EDGE + (1 - 2 * EDGE) * logistic(x[i++])) : 0;
|
|
6866
|
+
const gamma = seasonal ? (1 - alpha) * (EDGE + (1 - 2 * EDGE) * logistic(x[i++])) : 0;
|
|
6867
|
+
const l0 = l0Init + x[i++] * scale;
|
|
6868
|
+
const b0 = trend ? b0Init + x[i++] * scale * 0.1 : 0;
|
|
6869
|
+
return { alpha, beta, gamma, l0, b0, s0 };
|
|
6870
|
+
};
|
|
6871
|
+
const objective = (x) => run(y, spec, decode(x))?.sse ?? Infinity;
|
|
6872
|
+
const starts = [
|
|
6873
|
+
[0.2, 0.1, 0.1],
|
|
6874
|
+
[0.5, 0.3, 0.3],
|
|
6875
|
+
[0.05, 0.5, 0.05]
|
|
6876
|
+
];
|
|
6877
|
+
let best = null;
|
|
6878
|
+
for (const [a, b, g] of starts) {
|
|
6879
|
+
const x0 = [logit(a), ...trend ? [logit(b)] : [], ...seasonal ? [logit(g)] : [], 0, ...trend ? [0] : []];
|
|
6880
|
+
let found = nelderMead(objective, x0, 1, 300 * x0.length);
|
|
6881
|
+
found = nelderMead(objective, found.x, 0.25, 200 * x0.length);
|
|
6882
|
+
if (best === null || found.fx < best.fx) best = found;
|
|
6883
|
+
}
|
|
6884
|
+
if (best === null || !Number.isFinite(best.fx)) return null;
|
|
6885
|
+
const params = decode(best.x);
|
|
6886
|
+
const state = run(y, spec, params);
|
|
6887
|
+
if (!state) return null;
|
|
6888
|
+
const k = 2 + (trend ? 2 : 0) + (seasonal ? 1 + (m - 1) : 0);
|
|
6889
|
+
const sse = Math.max(state.sse, 1e-12 * Math.max(1, mean * mean) * n);
|
|
6890
|
+
const aic = n * Math.log(sse / n) + 2 * k;
|
|
6891
|
+
const aicc = n - k - 1 > 0 ? aic + 2 * k * (k + 1) / (n - k - 1) : Infinity;
|
|
6892
|
+
return { spec, params, state, k, aicc };
|
|
6893
|
+
}
|
|
6894
|
+
function varianceMultiplier(fit, h, seasonIndex) {
|
|
6895
|
+
const { alpha: a, beta: b, gamma: g } = fit.params;
|
|
6896
|
+
const { m } = fit.spec;
|
|
6897
|
+
const trend = fit.spec.trend === "additive";
|
|
6898
|
+
const seasonal = fit.spec.season !== "none";
|
|
6899
|
+
const k = Math.floor((h - 1) / m);
|
|
6900
|
+
let extra = trend ? (h - 1) * (a * a + a * b * h + b * b * h * (2 * h - 1) / 6) : (h - 1) * a * a;
|
|
6901
|
+
if (seasonal) extra += trend ? g * k * (2 * a + g + b * m * (k + 1)) : g * k * (2 * a + g);
|
|
6902
|
+
if (fit.spec.season === "multiplicative") extra *= seasonIndex * seasonIndex;
|
|
6903
|
+
return 1 + extra;
|
|
6904
|
+
}
|
|
6905
|
+
function forecast(values, options = {}) {
|
|
6906
|
+
const finite = (v) => typeof v === "number" && Number.isFinite(v);
|
|
6907
|
+
let first = 0;
|
|
6908
|
+
while (first < values.length && !finite(values[first])) first++;
|
|
6909
|
+
let last = values.length - 1;
|
|
6910
|
+
while (last >= first && !finite(values[last])) last--;
|
|
6911
|
+
if (last < first) return null;
|
|
6912
|
+
const ignore = Math.max(0, Math.floor(options.ignoreLast ?? 0));
|
|
6913
|
+
const end = last + 1 - ignore;
|
|
6914
|
+
let start = first;
|
|
6915
|
+
if (end - start > FORECAST_MAX_FIT_POINTS) start = end - FORECAST_MAX_FIT_POINTS;
|
|
6916
|
+
if (end - start < FORECAST_MIN_POINTS) return null;
|
|
6917
|
+
const y = [];
|
|
6918
|
+
for (let t = start; t < end; t++) {
|
|
6919
|
+
const v = values[t];
|
|
6920
|
+
if (finite(v)) {
|
|
6921
|
+
y.push(v);
|
|
6922
|
+
continue;
|
|
6923
|
+
}
|
|
6924
|
+
let lo = t - 1;
|
|
6925
|
+
while (lo >= start && !finite(values[lo])) lo--;
|
|
6926
|
+
let hi = t + 1;
|
|
6927
|
+
while (hi < end && !finite(values[hi])) hi++;
|
|
6928
|
+
const a = lo >= start ? values[lo] : void 0;
|
|
6929
|
+
const b = hi < end ? values[hi] : void 0;
|
|
6930
|
+
y.push(a !== void 0 && b !== void 0 ? a + (b - a) * (t - lo) / (hi - lo) : a ?? b ?? 0);
|
|
6931
|
+
}
|
|
6932
|
+
const n = y.length;
|
|
6933
|
+
const m = Math.max(1, Math.floor(options.seasonLength ?? 1));
|
|
6934
|
+
const seasonOption = options.season ?? "auto";
|
|
6935
|
+
const trendOption = options.trend ?? "auto";
|
|
6936
|
+
const canSeason = m > 1 && n >= 2 * m && seasonOption !== "none";
|
|
6937
|
+
const positive = y.every((v) => v > 0);
|
|
6938
|
+
const seasons = !canSeason ? ["none"] : seasonOption === "additive" ? ["additive"] : seasonOption === "multiplicative" ? [positive ? "multiplicative" : "additive"] : positive ? ["none", "additive", "multiplicative"] : ["none", "additive"];
|
|
6939
|
+
const trends = trendOption === "none" ? ["none"] : trendOption === "auto" ? ["none", "additive"] : ["additive"];
|
|
6940
|
+
let chosen = null;
|
|
6941
|
+
for (const trend of trends) {
|
|
6942
|
+
for (const season of seasons) {
|
|
6943
|
+
const fit = fitModel(y, { trend, season, m: season === "none" ? 1 : m });
|
|
6944
|
+
if (!fit) continue;
|
|
6945
|
+
if (chosen === null || fit.aicc < chosen.aicc || !Number.isFinite(chosen.aicc) && fit.k < chosen.k) chosen = fit;
|
|
6946
|
+
}
|
|
6947
|
+
}
|
|
6948
|
+
if (!chosen) return null;
|
|
6949
|
+
const dof = n - (chosen.k - 1);
|
|
6950
|
+
const sigma = Math.sqrt(chosen.state.sse / (dof >= 1 ? dof : n));
|
|
6951
|
+
const confidence = options.confidence !== void 0 && options.confidence > 0 && options.confidence < 1 ? options.confidence : 0.95;
|
|
6952
|
+
const z = inverseNormal(1 - (1 - confidence) / 2);
|
|
6953
|
+
const horizon = options.horizon !== void 0 && Number.isFinite(options.horizon) ? Math.max(0, Math.floor(options.horizon)) : m > 1 ? m : Math.min(12, Math.max(1, Math.round(n / 4)));
|
|
6954
|
+
const steps = values.length - end + horizon;
|
|
6955
|
+
const { spec, state } = chosen;
|
|
6956
|
+
const points = [];
|
|
6957
|
+
for (let h = 1; h <= steps; h++) {
|
|
6958
|
+
const base = state.level + h * state.slope;
|
|
6959
|
+
const s = spec.season === "none" ? void 0 : state.season[(n - 1 + h) % spec.m];
|
|
6960
|
+
const value = s === void 0 ? base : spec.season === "multiplicative" ? base * s : base + s;
|
|
6961
|
+
const half = z * sigma * Math.sqrt(varianceMultiplier(chosen, h, s ?? 1));
|
|
6962
|
+
points.push({ value, lower: value - half, upper: value + half });
|
|
6963
|
+
}
|
|
6964
|
+
const { alpha, beta, gamma } = chosen.params;
|
|
6965
|
+
return {
|
|
6966
|
+
model: {
|
|
6967
|
+
trend: spec.trend,
|
|
6968
|
+
season: spec.season,
|
|
6969
|
+
alpha,
|
|
6970
|
+
...spec.trend === "additive" ? { beta } : {},
|
|
6971
|
+
...spec.season !== "none" ? { gamma, seasonLength: spec.m } : {}
|
|
6972
|
+
},
|
|
6973
|
+
fitted: n,
|
|
6974
|
+
end,
|
|
6975
|
+
sigma,
|
|
6976
|
+
points
|
|
6977
|
+
};
|
|
6978
|
+
}
|
|
6979
|
+
var TEXT19 = {
|
|
6980
|
+
ja: {
|
|
6981
|
+
forecast: "\u4E88\u6E2C",
|
|
6982
|
+
note: "\u4E88\u6E2C\u306F\u6307\u6570\u5E73\u6ED1\u6CD5\u306B\u3088\u308B\u8FD1\u4F3C\u5024\u3067\u3059\u3002\u5143\u306E\u30C4\u30FC\u30EB\u306E\u5024\u3068\u306F\u4E00\u81F4\u3057\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002",
|
|
6983
|
+
interval: (pct, lo, hi) => `${pct} \u4E88\u6E2C\u533A\u9593 ${lo}\u301C${hi}`,
|
|
6984
|
+
chart: (names) => `${names.join("\u30FB")}\u306E\u5B9F\u7E3E\u3068\u4E88\u6E2C\u306E\u6298\u308C\u7DDA\u30B0\u30E9\u30D5`,
|
|
6985
|
+
item: "\u671F\u9593"
|
|
6986
|
+
},
|
|
6987
|
+
en: {
|
|
6988
|
+
forecast: "Forecast",
|
|
6989
|
+
note: "Forecast is an approximation (exponential smoothing); values may differ from the source tool.",
|
|
6990
|
+
interval: (pct, lo, hi) => `${pct} interval ${lo} \u2013 ${hi}`,
|
|
6991
|
+
chart: (names) => `Line chart of actuals and forecast for ${names.join(", ")}`,
|
|
6992
|
+
item: "Period"
|
|
6993
|
+
}
|
|
6994
|
+
};
|
|
6995
|
+
var LEGEND_DASHED_ICON = "path://M0,0 L42,0 L42,24 L0,24 Z M58,0 L100,0 L100,24 L58,24 Z";
|
|
6996
|
+
var BOUNDARY_LABEL_ROOM = 18;
|
|
6997
|
+
var MAX_PERIODS = 5e3;
|
|
6998
|
+
var DAY_MS = 864e5;
|
|
6999
|
+
var NO_ROWS14 = [];
|
|
7000
|
+
var DATE_RE = /^(\d{4})(?:[-/](\d{1,2})(?:[-/](\d{1,2}))?)?(?:[T ].*)?$/;
|
|
7001
|
+
var QUARTER_RE = /^(\d{4})[-\s]?Q([1-4])$/i;
|
|
7002
|
+
function parseDate(value) {
|
|
7003
|
+
if (value instanceof Date) {
|
|
7004
|
+
return Number.isNaN(value.getTime()) ? null : { y: value.getFullYear(), m: value.getMonth() + 1, d: value.getDate(), precision: "day" };
|
|
7005
|
+
}
|
|
7006
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
7007
|
+
if (Number.isInteger(value) && value >= 1e3 && value <= 9999) return { y: value, m: 1, d: 1, precision: "year" };
|
|
7008
|
+
return parseDate(new Date(value));
|
|
7009
|
+
}
|
|
7010
|
+
if (typeof value !== "string") return null;
|
|
7011
|
+
const text = value.trim();
|
|
7012
|
+
const q = QUARTER_RE.exec(text);
|
|
7013
|
+
if (q) return { y: Number(q[1]), m: (Number(q[2]) - 1) * 3 + 1, d: 1, precision: "month" };
|
|
7014
|
+
const m = DATE_RE.exec(text);
|
|
7015
|
+
if (m) {
|
|
7016
|
+
const month = m[2] === void 0 ? 1 : Number(m[2]);
|
|
7017
|
+
const day = m[3] === void 0 ? 1 : Number(m[3]);
|
|
7018
|
+
if (month < 1 || month > 12 || day < 1 || day > 31) return null;
|
|
7019
|
+
return { y: Number(m[1]), m: month, d: day, precision: m[3] !== void 0 ? "day" : m[2] !== void 0 ? "month" : "year" };
|
|
7020
|
+
}
|
|
7021
|
+
if (text === "") return null;
|
|
7022
|
+
const parsed = new Date(text);
|
|
7023
|
+
return Number.isNaN(parsed.getTime()) ? null : parseDate(parsed);
|
|
7024
|
+
}
|
|
7025
|
+
var dayOrdinal = (p) => Math.round(Date.UTC(p.y, p.m - 1, p.d) / DAY_MS);
|
|
7026
|
+
function ordinal(p, period) {
|
|
7027
|
+
switch (period) {
|
|
7028
|
+
case "year":
|
|
7029
|
+
return p.y;
|
|
7030
|
+
case "quarter":
|
|
7031
|
+
return p.y * 4 + Math.floor((p.m - 1) / 3);
|
|
7032
|
+
case "month":
|
|
7033
|
+
return p.y * 12 + (p.m - 1);
|
|
7034
|
+
default:
|
|
7035
|
+
return dayOrdinal(p);
|
|
7036
|
+
}
|
|
7037
|
+
}
|
|
7038
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
7039
|
+
function ordinalLabel(o, period) {
|
|
7040
|
+
if (period === "year") return String(o);
|
|
7041
|
+
if (period === "quarter") return `${Math.floor(o / 4)}-${pad2(o % 4 * 3 + 1)}`;
|
|
7042
|
+
if (period === "month") return `${Math.floor(o / 12)}-${pad2(o % 12 + 1)}`;
|
|
7043
|
+
const d = new Date(o * DAY_MS);
|
|
7044
|
+
return `${d.getUTCFullYear()}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())}`;
|
|
7045
|
+
}
|
|
7046
|
+
function inferPeriod(dates) {
|
|
7047
|
+
if (dates.every((d) => d.precision === "year")) return "year";
|
|
7048
|
+
const coarse = dates.every((d) => d.precision !== "day");
|
|
7049
|
+
const keys = [...new Set(dates.map((d) => coarse ? ordinal(d, "month") : dayOrdinal(d)))].sort((a, b) => a - b);
|
|
7050
|
+
const gaps = keys.slice(1).map((k, i) => k - keys[i]).sort((a, b) => a - b);
|
|
7051
|
+
const gap = gaps.length === 0 ? coarse ? 1 : 1 : gaps[Math.floor(gaps.length / 2)];
|
|
7052
|
+
if (coarse) return gap >= 12 ? "year" : gap >= 3 ? "quarter" : "month";
|
|
7053
|
+
return gap >= 360 ? "year" : gap >= 85 ? "quarter" : gap >= 28 ? "month" : gap >= 7 ? "week" : "day";
|
|
7054
|
+
}
|
|
7055
|
+
var SEASON_LENGTH = { day: 7, week: 52, month: 12, quarter: 4, year: 1 };
|
|
7056
|
+
function buildForecastModel(data, x, y, seriesKey, period, options, singleName, otherLabel) {
|
|
7057
|
+
if (!x || !y || !Array.isArray(data)) return null;
|
|
7058
|
+
const points = [];
|
|
7059
|
+
for (const row of data) {
|
|
7060
|
+
if (!row || typeof row !== "object") continue;
|
|
7061
|
+
const date = parseDate(row[x]);
|
|
7062
|
+
const value = toChartNumber(row[y]);
|
|
7063
|
+
if (!date || value === null) continue;
|
|
7064
|
+
const raw = seriesKey ? row[seriesKey] : singleName;
|
|
7065
|
+
const name = raw === null || raw === void 0 || raw === "" ? "\u2014" : String(raw);
|
|
7066
|
+
points.push({ date, name, value });
|
|
7067
|
+
}
|
|
7068
|
+
if (points.length === 0) return null;
|
|
7069
|
+
const grain = period ?? inferPeriod(points.map((p) => p.date));
|
|
7070
|
+
const step = grain === "week" ? 7 : 1;
|
|
7071
|
+
const keyed = points.map((p) => ({ ...p, key: ordinal(p.date, grain) }));
|
|
7072
|
+
let min = Math.min(...keyed.map((p) => p.key));
|
|
7073
|
+
const max = Math.max(...keyed.map((p) => p.key));
|
|
7074
|
+
if ((max - min) / step + 1 > MAX_PERIODS) min = max - (MAX_PERIODS - 1) * step;
|
|
7075
|
+
const count = Math.floor((max - min) / step) + 1;
|
|
7076
|
+
const slot = (key) => Math.floor((key - min) / step);
|
|
7077
|
+
const sums = /* @__PURE__ */ new Map();
|
|
7078
|
+
for (const p of keyed) {
|
|
7079
|
+
const at = slot(p.key);
|
|
7080
|
+
if (at < 0) continue;
|
|
7081
|
+
let list = sums.get(p.name);
|
|
7082
|
+
if (!list) {
|
|
7083
|
+
list = Array(count).fill(null);
|
|
7084
|
+
sums.set(p.name, list);
|
|
7085
|
+
}
|
|
7086
|
+
list[at] = (list[at] ?? 0) + p.value;
|
|
7087
|
+
}
|
|
7088
|
+
const all = [...sums.keys()];
|
|
7089
|
+
const totals = all.map((name) => ({ name, value: sums.get(name).reduce((a, v) => a + (v ?? 0), 0) }));
|
|
7090
|
+
const { top, rest, other } = aggregateTopN(totals, void 0, otherLabel);
|
|
7091
|
+
const names = top.map((t) => t.name);
|
|
7092
|
+
const actual = names.map((n) => sums.get(n));
|
|
7093
|
+
if (other) {
|
|
7094
|
+
const folded = Array(count).fill(null);
|
|
7095
|
+
for (const r of rest) sums.get(r.name).forEach((v, i) => v === null ? void 0 : folded[i] = (folded[i] ?? 0) + v);
|
|
7096
|
+
names.push(other.name);
|
|
7097
|
+
actual.push(folded);
|
|
7098
|
+
}
|
|
7099
|
+
const resolved = { ...options, seasonLength: options?.seasonLength ?? SEASON_LENGTH[grain] };
|
|
7100
|
+
const results = actual.map((values) => {
|
|
7101
|
+
try {
|
|
7102
|
+
return forecast(values.map((v) => v === null ? NaN : v), resolved);
|
|
7103
|
+
} catch {
|
|
7104
|
+
return null;
|
|
7105
|
+
}
|
|
7106
|
+
});
|
|
7107
|
+
const length = Math.max(count, ...results.map((r) => r ? r.end + r.points.length : 0));
|
|
7108
|
+
const labels = Array.from({ length }, (_, i) => ordinalLabel(min + i * step, grain));
|
|
7109
|
+
const predicted = results.map((r) => {
|
|
7110
|
+
const out = Array(length).fill(null);
|
|
7111
|
+
r?.points.forEach((p, k) => out[r.end + k] = p);
|
|
7112
|
+
return out;
|
|
7113
|
+
});
|
|
7114
|
+
return {
|
|
7115
|
+
labels,
|
|
7116
|
+
actualCount: count,
|
|
7117
|
+
names,
|
|
7118
|
+
otherName: other ? other.name : null,
|
|
7119
|
+
actual: actual.map((list) => [...list, ...Array(length - count).fill(null)]),
|
|
7120
|
+
predicted,
|
|
7121
|
+
fittedEnd: results.map((r) => r ? r.end - 1 : -1),
|
|
7122
|
+
results
|
|
7123
|
+
};
|
|
7124
|
+
}
|
|
7125
|
+
var FORECAST_ID = "__forecast:";
|
|
7126
|
+
var BAND_BASE_ID = "__forecast-band-base:";
|
|
7127
|
+
var BAND_RANGE_ID = "__forecast-band-range:";
|
|
7128
|
+
function ForecastChartImpl({
|
|
7129
|
+
data = NO_ROWS14,
|
|
7130
|
+
x,
|
|
7131
|
+
y,
|
|
7132
|
+
series: seriesKey,
|
|
7133
|
+
period,
|
|
7134
|
+
forecast: forecast2,
|
|
7135
|
+
forecastLabel,
|
|
7136
|
+
forecastNote,
|
|
7137
|
+
colors,
|
|
7138
|
+
labels,
|
|
7139
|
+
valueFormatter,
|
|
7140
|
+
format,
|
|
7141
|
+
title,
|
|
7142
|
+
summary,
|
|
7143
|
+
actions,
|
|
7144
|
+
fileName,
|
|
7145
|
+
isLoading,
|
|
7146
|
+
emptyState,
|
|
7147
|
+
height,
|
|
7148
|
+
chartOptions,
|
|
7149
|
+
showLegend = true,
|
|
7150
|
+
showTooltip = true,
|
|
7151
|
+
showGridLines = true,
|
|
7152
|
+
showXAxis = true,
|
|
7153
|
+
showYAxis = true,
|
|
7154
|
+
yAxisWidth,
|
|
7155
|
+
minValue,
|
|
7156
|
+
maxValue,
|
|
7157
|
+
fitToData = false,
|
|
7158
|
+
xAxisLabel,
|
|
7159
|
+
yAxisLabel,
|
|
7160
|
+
ariaLabel,
|
|
7161
|
+
className,
|
|
7162
|
+
...rest
|
|
7163
|
+
}, ref) {
|
|
7164
|
+
const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
|
|
7165
|
+
const locale = useLocale();
|
|
7166
|
+
const t = TEXT19[uiLanguage(locale)];
|
|
7167
|
+
const fcLabel = forecastLabel ?? t.forecast;
|
|
7168
|
+
const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
7169
|
+
const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
7170
|
+
const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
|
|
7171
|
+
const singleName = labels?.[y] ?? y ?? "";
|
|
7172
|
+
const model = useMemo(
|
|
7173
|
+
() => buildForecastModel(data, x, y, seriesKey, period, forecast2, singleName, otherSeriesLabel(locale)),
|
|
7174
|
+
// forecast はオブジェクトリテラルで渡されることが多いので中身で比べる
|
|
7175
|
+
[data, x, y, seriesKey, period, JSON.stringify(forecast2 ?? null), singleName, locale]
|
|
7176
|
+
);
|
|
7177
|
+
const palette = useMemo(
|
|
7178
|
+
() => model ? resolveChartColors(seriesColorsFor(model.names, colors, CHART_OTHER_COLOR, model.otherName), tokens) : [],
|
|
7179
|
+
[model, colors, tokens]
|
|
7180
|
+
);
|
|
7181
|
+
const option = useMemo(() => {
|
|
7182
|
+
if (!model) return null;
|
|
7183
|
+
const index = "__period";
|
|
7184
|
+
const rows = model.labels.map((label3, i) => {
|
|
7185
|
+
const row = { [index]: label3 };
|
|
7186
|
+
model.names.forEach((name, c) => row[name] = model.actual[c][i]);
|
|
7187
|
+
return row;
|
|
7188
|
+
});
|
|
7189
|
+
const base = buildCartesianOption({
|
|
7190
|
+
kind: "line",
|
|
5585
7191
|
data: rows,
|
|
5586
7192
|
index,
|
|
5587
|
-
|
|
5588
|
-
palette
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
stacked,
|
|
5595
|
-
layout,
|
|
7193
|
+
categories: model.names,
|
|
7194
|
+
palette,
|
|
7195
|
+
valueFormatter: tooltipFormatter,
|
|
7196
|
+
axisFormatter,
|
|
7197
|
+
axisTicks,
|
|
7198
|
+
curveType: "linear",
|
|
7199
|
+
connectNulls: false,
|
|
5596
7200
|
showLegend,
|
|
5597
7201
|
showTooltip,
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
7202
|
+
showGridLines,
|
|
7203
|
+
showXAxis,
|
|
7204
|
+
showYAxis,
|
|
7205
|
+
startEndOnly: false,
|
|
7206
|
+
yAxisWidth,
|
|
7207
|
+
minValue,
|
|
7208
|
+
maxValue,
|
|
7209
|
+
fitToData,
|
|
7210
|
+
allowDecimals: true,
|
|
7211
|
+
xAxisLabel,
|
|
7212
|
+
yAxisLabel,
|
|
7213
|
+
showDots: false,
|
|
7214
|
+
active: null,
|
|
7215
|
+
highlight: "none",
|
|
7216
|
+
reserveActions: Boolean(actions),
|
|
7217
|
+
guideColor: tokens?.mutedForeground ?? void 0,
|
|
7218
|
+
labelBackground: surface,
|
|
7219
|
+
labelColor: tokens?.foreground ?? void 0,
|
|
7220
|
+
plotWidth,
|
|
7221
|
+
plotHeight: typeof height === "number" ? height : void 0,
|
|
7222
|
+
locale
|
|
7223
|
+
});
|
|
7224
|
+
const bandAlpha = isDarkSurface(surface) ? FORECAST_BAND_ALPHA_DARK : FORECAST_BAND_ALPHA_LIGHT;
|
|
7225
|
+
const helper = {
|
|
7226
|
+
type: "line",
|
|
7227
|
+
symbol: "none",
|
|
7228
|
+
showSymbol: false,
|
|
7229
|
+
connectNulls: true,
|
|
7230
|
+
legendHoverLink: false,
|
|
7231
|
+
emphasis: { disabled: true }
|
|
7232
|
+
};
|
|
7233
|
+
const lines = [];
|
|
7234
|
+
const bands = [];
|
|
7235
|
+
model.names.forEach((name, c) => {
|
|
7236
|
+
const start = model.fittedEnd[c];
|
|
7237
|
+
if (start < 0) return;
|
|
7238
|
+
const color = palette[c] || void 0;
|
|
7239
|
+
const predicted = model.predicted[c];
|
|
7240
|
+
const startValue = model.actual[c][start] ?? null;
|
|
7241
|
+
const line = predicted.map((p, i) => i === start ? startValue : p?.value ?? null);
|
|
7242
|
+
const lower = predicted.map((p, i) => i === start ? startValue : p ? Math.min(p.lower, p.upper) : null);
|
|
7243
|
+
const range = predicted.map((p, i) => i === start ? startValue === null ? null : 0 : p ? Math.abs(p.upper - p.lower) : null);
|
|
7244
|
+
lines.push({
|
|
7245
|
+
...helper,
|
|
7246
|
+
id: FORECAST_ID + name,
|
|
7247
|
+
name: fcLabel,
|
|
7248
|
+
z: 3,
|
|
7249
|
+
lineStyle: { width: 2, type: FORECAST_LINE_DASH, color, opacity: 0.7 },
|
|
7250
|
+
itemStyle: { color, opacity: 0.7 },
|
|
7251
|
+
data: line
|
|
7252
|
+
});
|
|
7253
|
+
bands.push(
|
|
7254
|
+
{ ...helper, id: BAND_BASE_ID + name, name: fcLabel, silent: true, z: 1, stack: BAND_BASE_ID + name, tooltip: { show: false }, lineStyle: { opacity: 0 }, itemStyle: { color }, data: lower },
|
|
7255
|
+
{
|
|
7256
|
+
...helper,
|
|
7257
|
+
id: BAND_RANGE_ID + name,
|
|
7258
|
+
name: fcLabel,
|
|
7259
|
+
silent: true,
|
|
7260
|
+
z: 1,
|
|
7261
|
+
stack: BAND_BASE_ID + name,
|
|
7262
|
+
tooltip: { show: false },
|
|
7263
|
+
lineStyle: { opacity: 0 },
|
|
7264
|
+
itemStyle: { color },
|
|
7265
|
+
areaStyle: color ? { color: withAlpha(color, bandAlpha), opacity: 1 } : { opacity: bandAlpha },
|
|
7266
|
+
data: range
|
|
7267
|
+
}
|
|
7268
|
+
);
|
|
7269
|
+
});
|
|
7270
|
+
if (lines.length === 0) return mergeChartOptions(base, chartOptions);
|
|
7271
|
+
const boundary = Math.max(...model.fittedEnd);
|
|
7272
|
+
const total = model.labels.length;
|
|
7273
|
+
const span = plotWidth && total > 1 ? (plotWidth - 64) / (total - 1) * (total - 1 - boundary) : null;
|
|
7274
|
+
const boundaryText = forecastBoundaryText(fcLabel);
|
|
7275
|
+
lines[0] = {
|
|
7276
|
+
...lines[0],
|
|
7277
|
+
markLine: {
|
|
7278
|
+
silent: true,
|
|
7279
|
+
symbol: "none",
|
|
7280
|
+
animation: false,
|
|
7281
|
+
data: [
|
|
7282
|
+
{
|
|
7283
|
+
name: "forecast-boundary",
|
|
7284
|
+
xAxis: boundary,
|
|
7285
|
+
lineStyle: { type: "dashed", width: 1, color: tokens?.mutedForeground ?? void 0 },
|
|
7286
|
+
label: {
|
|
7287
|
+
show: true,
|
|
7288
|
+
position: "end",
|
|
7289
|
+
rotate: 0,
|
|
7290
|
+
align: forecastLabelAlign(span, boundaryText),
|
|
7291
|
+
verticalAlign: "bottom",
|
|
7292
|
+
distance: 4,
|
|
7293
|
+
fontSize: 12,
|
|
7294
|
+
color: tokens?.mutedForeground ?? void 0,
|
|
7295
|
+
formatter: boundaryText
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
]
|
|
5610
7299
|
}
|
|
5611
|
-
}
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
7300
|
+
};
|
|
7301
|
+
const legend = base.legend;
|
|
7302
|
+
const grid = base.grid;
|
|
7303
|
+
const times = timeTooltipLabels(model.labels, locale);
|
|
7304
|
+
const pct = `${Math.round((forecast2?.confidence && forecast2.confidence > 0 && forecast2.confidence < 1 ? forecast2.confidence : 0.95) * 100)}%`;
|
|
7305
|
+
const option2 = {
|
|
7306
|
+
...base,
|
|
7307
|
+
legend: legend ? { ...legend, data: [...legend.data ?? [], { name: fcLabel, icon: LEGEND_DASHED_ICON }] } : legend,
|
|
7308
|
+
grid: grid ? { ...grid, top: (grid.top ?? 12) + BOUNDARY_LABEL_ROOM } : grid,
|
|
7309
|
+
tooltip: {
|
|
7310
|
+
...base.tooltip,
|
|
7311
|
+
formatter: (params) => {
|
|
7312
|
+
const list = Array.isArray(params) ? params : [params];
|
|
7313
|
+
const i = list[0]?.dataIndex ?? 0;
|
|
7314
|
+
const shown = new Set(list.map((p) => p.seriesId ?? ""));
|
|
7315
|
+
const visible = (id) => list.length === 0 || shown.has(id);
|
|
7316
|
+
const rows2 = [];
|
|
7317
|
+
model.names.forEach((name, c) => {
|
|
7318
|
+
const color = palette[c] || "currentColor";
|
|
7319
|
+
const value = model.actual[c][i] ?? null;
|
|
7320
|
+
if (value !== null && visible(`series:${name}`)) rows2.push({ name, color, value });
|
|
7321
|
+
const p = model.predicted[c][i];
|
|
7322
|
+
if (p && visible(FORECAST_ID + name)) {
|
|
7323
|
+
rows2.push({
|
|
7324
|
+
name: model.names.length > 1 ? `${name} \xB7 ${fcLabel}` : fcLabel,
|
|
7325
|
+
color,
|
|
7326
|
+
value: p.value,
|
|
7327
|
+
note: t.interval(pct, tooltipFormatter(Math.min(p.lower, p.upper)), tooltipFormatter(Math.max(p.lower, p.upper)))
|
|
7328
|
+
});
|
|
7329
|
+
}
|
|
7330
|
+
});
|
|
7331
|
+
return tooltipHtml(times?.[i] ?? model.labels[i] ?? "", rows2, tooltipFormatter, [], locale);
|
|
7332
|
+
}
|
|
7333
|
+
},
|
|
7334
|
+
series: [...base.series ?? [], ...lines, ...bands]
|
|
7335
|
+
};
|
|
7336
|
+
return mergeChartOptions(option2, chartOptions);
|
|
7337
|
+
}, [
|
|
7338
|
+
model,
|
|
7339
|
+
palette,
|
|
7340
|
+
tooltipFormatter,
|
|
7341
|
+
axisFormatter,
|
|
7342
|
+
axisTicks,
|
|
7343
|
+
showLegend,
|
|
7344
|
+
showTooltip,
|
|
7345
|
+
showGridLines,
|
|
7346
|
+
showXAxis,
|
|
7347
|
+
showYAxis,
|
|
7348
|
+
yAxisWidth,
|
|
7349
|
+
minValue,
|
|
7350
|
+
maxValue,
|
|
7351
|
+
fitToData,
|
|
7352
|
+
xAxisLabel,
|
|
7353
|
+
yAxisLabel,
|
|
7354
|
+
actions,
|
|
7355
|
+
tokens,
|
|
7356
|
+
surface,
|
|
7357
|
+
plotWidth,
|
|
7358
|
+
height,
|
|
7359
|
+
locale,
|
|
7360
|
+
fcLabel,
|
|
7361
|
+
forecast2?.confidence,
|
|
7362
|
+
t,
|
|
7363
|
+
chartOptions
|
|
7364
|
+
]);
|
|
7365
|
+
const dataTable = useMemo(() => {
|
|
7366
|
+
if (!model) return void 0;
|
|
7367
|
+
const forecastColumns = model.names.map((name) => `${name} (${fcLabel})`);
|
|
7368
|
+
const rows = model.labels.map((label3, i) => {
|
|
7369
|
+
const row = { period: label3 };
|
|
7370
|
+
model.names.forEach((name, c) => {
|
|
7371
|
+
row[name] = model.actual[c][i];
|
|
7372
|
+
row[forecastColumns[c]] = model.predicted[c][i]?.value ?? null;
|
|
7373
|
+
});
|
|
7374
|
+
return row;
|
|
7375
|
+
});
|
|
7376
|
+
const columns = model.names.flatMap((name, c) => model.fittedEnd[c] >= 0 ? [name, forecastColumns[c]] : [name]);
|
|
7377
|
+
const table = chartDataTable(rows, "period", columns, tooltipFormatter, void 0, t.item);
|
|
7378
|
+
const times = timeTooltipLabels(model.labels, locale);
|
|
7379
|
+
return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
|
|
7380
|
+
}, [model, fcLabel, tooltipFormatter, t, locale]);
|
|
7381
|
+
const label2 = ariaLabel ?? t.chart(model?.names ?? [singleName]);
|
|
5616
7382
|
return /* @__PURE__ */ jsx(
|
|
5617
7383
|
ChartFrame,
|
|
5618
7384
|
{
|
|
@@ -5621,26 +7387,20 @@ function ComboChartImpl({
|
|
|
5621
7387
|
title,
|
|
5622
7388
|
summary,
|
|
5623
7389
|
isLoading: isLoading ?? false,
|
|
5624
|
-
isEmpty:
|
|
7390
|
+
isEmpty: !model || !option,
|
|
5625
7391
|
emptyState,
|
|
5626
7392
|
height,
|
|
5627
|
-
variant: "
|
|
7393
|
+
variant: "line",
|
|
5628
7394
|
ariaLabel: label2,
|
|
5629
7395
|
className,
|
|
5630
7396
|
dataTable,
|
|
5631
|
-
|
|
7397
|
+
footnote: forecastNote ?? t.note,
|
|
7398
|
+
children: option && /* @__PURE__ */ jsx(EChart, { option, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary } })
|
|
5632
7399
|
}
|
|
5633
7400
|
);
|
|
5634
7401
|
}
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
["var(--muted-foreground)", ...series.map((s, i) => s.color ?? DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length])],
|
|
5638
|
-
tokens
|
|
5639
|
-
);
|
|
5640
|
-
return { reference: resolved[0] ?? "", series: resolved.slice(1) };
|
|
5641
|
-
}
|
|
5642
|
-
var ComboChart = forwardRef(ComboChartImpl);
|
|
5643
|
-
ComboChart.displayName = "ComboChart";
|
|
7402
|
+
var ForecastChart = forwardRef(ForecastChartImpl);
|
|
7403
|
+
ForecastChart.displayName = "ForecastChart";
|
|
5644
7404
|
|
|
5645
7405
|
// ../squadkit/registry/lib/color-ramp.ts
|
|
5646
7406
|
var RAMP_FLOOR_SHARE = 0.2;
|
|
@@ -5896,7 +7656,7 @@ function buildFilledMapModel(config) {
|
|
|
5896
7656
|
function escapeHtml4(text) {
|
|
5897
7657
|
return text.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
5898
7658
|
}
|
|
5899
|
-
var
|
|
7659
|
+
var TEXT20 = {
|
|
5900
7660
|
ja: {
|
|
5901
7661
|
join: "\u30FB",
|
|
5902
7662
|
region: "\u5730\u57DF",
|
|
@@ -5912,7 +7672,7 @@ var TEXT15 = {
|
|
|
5912
7672
|
chart: (value) => `Map of ${value}`
|
|
5913
7673
|
}
|
|
5914
7674
|
};
|
|
5915
|
-
var
|
|
7675
|
+
var textOf7 = (locale) => TEXT20[uiLanguage(resolveLocale(locale))];
|
|
5916
7676
|
function detailText(raw, formatter) {
|
|
5917
7677
|
if (raw === null || raw === void 0 || raw === "") return EMPTY_VALUE;
|
|
5918
7678
|
const n = typeof raw === "string" ? null : toChartNumber(raw);
|
|
@@ -5920,7 +7680,7 @@ function detailText(raw, formatter) {
|
|
|
5920
7680
|
}
|
|
5921
7681
|
function buildFilledMapOption(config) {
|
|
5922
7682
|
const { model, labels, valueFormatter } = config;
|
|
5923
|
-
const t =
|
|
7683
|
+
const t = textOf7(config.locale);
|
|
5924
7684
|
const label2 = (key) => labels?.[key] ?? key;
|
|
5925
7685
|
const base = config.color || "#6366f1";
|
|
5926
7686
|
const border = config.surfaceColor ?? "#ffffff";
|
|
@@ -5974,7 +7734,7 @@ function mergeDeep3(a, b) {
|
|
|
5974
7734
|
return out;
|
|
5975
7735
|
}
|
|
5976
7736
|
function filledMapDataTable(model, names, formatter, details = [], labels, locale) {
|
|
5977
|
-
const t =
|
|
7737
|
+
const t = textOf7(locale);
|
|
5978
7738
|
const label2 = (key) => labels?.[key] ?? key;
|
|
5979
7739
|
const cells = (row, value) => [
|
|
5980
7740
|
value === null ? EMPTY_VALUE : formatter(value),
|
|
@@ -5990,15 +7750,15 @@ function buildFilledMapSummary(model, formatter, title, locale) {
|
|
|
5990
7750
|
let best;
|
|
5991
7751
|
for (const r of model.regions) if (r.value !== null && (!best || r.value > best.value)) best = r;
|
|
5992
7752
|
if (!best) return void 0;
|
|
5993
|
-
return `${title ? `${title}: ` : ""}${
|
|
7753
|
+
return `${title ? `${title}: ` : ""}${textOf7(locale).top(best.name, formatter(best.value))}`;
|
|
5994
7754
|
}
|
|
5995
7755
|
function colorsFor2(tokens, tone) {
|
|
5996
7756
|
const [color = "", empty = "", hover = ""] = resolveChartColors([tone, "var(--muted)", "var(--foreground)"], tokens);
|
|
5997
7757
|
return { color, empty, hover };
|
|
5998
7758
|
}
|
|
5999
|
-
var
|
|
7759
|
+
var NO_ROWS15 = [];
|
|
6000
7760
|
function FilledMapImpl({
|
|
6001
|
-
data =
|
|
7761
|
+
data = NO_ROWS15,
|
|
6002
7762
|
region,
|
|
6003
7763
|
value,
|
|
6004
7764
|
map = "auto",
|
|
@@ -6024,7 +7784,7 @@ function FilledMapImpl({
|
|
|
6024
7784
|
ariaLabel,
|
|
6025
7785
|
...rest
|
|
6026
7786
|
}, ref) {
|
|
6027
|
-
const rows = Array.isArray(data) ? data :
|
|
7787
|
+
const rows = Array.isArray(data) ? data : NO_ROWS15;
|
|
6028
7788
|
const { ref: frameRef, surface, tokens } = useChartSurface(ref);
|
|
6029
7789
|
const locale = useLocale();
|
|
6030
7790
|
const formatter = useMemo(() => resolveValueFormatter(valueFormatter, format ?? "number", locale), [valueFormatter, format, locale]);
|
|
@@ -6068,7 +7828,7 @@ function FilledMapImpl({
|
|
|
6068
7828
|
() => summary === "auto" ? model ? buildFilledMapSummary(model, formatter, title, locale) : void 0 : summary,
|
|
6069
7829
|
[summary, model, formatter, title, locale]
|
|
6070
7830
|
);
|
|
6071
|
-
const label2 = ariaLabel ??
|
|
7831
|
+
const label2 = ariaLabel ?? textOf7(locale).chart(labels?.[value] ?? value ?? "");
|
|
6072
7832
|
const isEmpty = rows.length === 0;
|
|
6073
7833
|
return /* @__PURE__ */ jsx(
|
|
6074
7834
|
ChartFrame,
|
|
@@ -6144,7 +7904,7 @@ function symbolMapSize(value, max, hasSize) {
|
|
|
6144
7904
|
function escapeHtml5(text) {
|
|
6145
7905
|
return text.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
6146
7906
|
}
|
|
6147
|
-
var
|
|
7907
|
+
var TEXT21 = {
|
|
6148
7908
|
ja: {
|
|
6149
7909
|
join: "\u30FB",
|
|
6150
7910
|
point: "\u5730\u70B9",
|
|
@@ -6162,7 +7922,7 @@ var TEXT16 = {
|
|
|
6162
7922
|
chart: "Map of points"
|
|
6163
7923
|
}
|
|
6164
7924
|
};
|
|
6165
|
-
var
|
|
7925
|
+
var textOf8 = (locale) => TEXT21[uiLanguage(resolveLocale(locale))];
|
|
6166
7926
|
var coordText = (n) => n === null ? EMPTY_VALUE : n.toFixed(4).replace(/\.?0+$/, "");
|
|
6167
7927
|
function buildSymbolMapOption(config) {
|
|
6168
7928
|
const { model, labels, valueFormatter, sizeFormatter } = config;
|
|
@@ -6239,7 +7999,7 @@ function mergeDeep4(a, b) {
|
|
|
6239
7999
|
return out;
|
|
6240
8000
|
}
|
|
6241
8001
|
function symbolMapDataTable(model, names, formatters, details = [], labels, locale) {
|
|
6242
|
-
const t =
|
|
8002
|
+
const t = textOf8(locale);
|
|
6243
8003
|
const label2 = (key) => labels?.[key] ?? key;
|
|
6244
8004
|
const extra = [names.size, names.color].filter((k) => !!k && k !== names.latitude && k !== names.longitude);
|
|
6245
8005
|
const keys = [.../* @__PURE__ */ new Set([...extra, ...details])];
|
|
@@ -6264,9 +8024,9 @@ function colorsFor3(tokens, tone) {
|
|
|
6264
8024
|
const [toneColor = "", land = "", border = ""] = resolved;
|
|
6265
8025
|
return { toneColor, land, border, categories: resolved.slice(3) };
|
|
6266
8026
|
}
|
|
6267
|
-
var
|
|
8027
|
+
var NO_ROWS16 = [];
|
|
6268
8028
|
function SymbolMapImpl({
|
|
6269
|
-
data =
|
|
8029
|
+
data = NO_ROWS16,
|
|
6270
8030
|
latitude,
|
|
6271
8031
|
longitude,
|
|
6272
8032
|
name,
|
|
@@ -6294,7 +8054,7 @@ function SymbolMapImpl({
|
|
|
6294
8054
|
ariaLabel,
|
|
6295
8055
|
...rest
|
|
6296
8056
|
}, ref) {
|
|
6297
|
-
const rows = Array.isArray(data) ? data :
|
|
8057
|
+
const rows = Array.isArray(data) ? data : NO_ROWS16;
|
|
6298
8058
|
const { ref: frameRef, surface, tokens } = useChartSurface(ref);
|
|
6299
8059
|
const locale = useLocale();
|
|
6300
8060
|
const formatter = useMemo(() => resolveValueFormatter(void 0, format ?? "number", locale), [format, locale]);
|
|
@@ -6304,7 +8064,7 @@ function SymbolMapImpl({
|
|
|
6304
8064
|
() => basemap === "auto" ? detectBasemap(model.points.map((p) => [p.lon, p.lat])) : basemap,
|
|
6305
8065
|
[basemap, model]
|
|
6306
8066
|
);
|
|
6307
|
-
const geo = useGeoMap(
|
|
8067
|
+
const geo = useGeoMap(NO_ROWS16, resolvedBasemap);
|
|
6308
8068
|
const colors = useMemo(() => colorsFor3(tokens, tone), [tokens, tone]);
|
|
6309
8069
|
const option = useMemo(
|
|
6310
8070
|
() => geo ? buildSymbolMapOption({
|
|
@@ -6339,7 +8099,7 @@ function SymbolMapImpl({
|
|
|
6339
8099
|
() => symbolMapDataTable(model, { latitude, longitude, name, size, color }, { value: formatter, size: sizeFormatter }, details, labels, locale),
|
|
6340
8100
|
[model, latitude, longitude, name, size, color, formatter, sizeFormatter, details, labels, locale]
|
|
6341
8101
|
);
|
|
6342
|
-
const label2 = ariaLabel ??
|
|
8102
|
+
const label2 = ariaLabel ?? textOf8(locale).chart;
|
|
6343
8103
|
const isEmpty = rows.length === 0;
|
|
6344
8104
|
const legendCategories = model.categories.length > MAX_CATEGORIES ? [...model.categories.slice(0, MAX_CATEGORIES), otherSeriesLabel(locale)] : model.categories;
|
|
6345
8105
|
const legend = !showLegend ? null : model.colorMode === "numeric" ? /* @__PURE__ */ jsx("div", { "data-slot": "symbol-map-legend", className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground tabular-nums", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
@@ -6408,7 +8168,7 @@ function buildTreemapModel(config) {
|
|
|
6408
8168
|
function escapeHtml6(text) {
|
|
6409
8169
|
return text.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
6410
8170
|
}
|
|
6411
|
-
var
|
|
8171
|
+
var TEXT22 = {
|
|
6412
8172
|
ja: {
|
|
6413
8173
|
join: "\u30FB",
|
|
6414
8174
|
item: "\u9805\u76EE",
|
|
@@ -6426,10 +8186,10 @@ var TEXT17 = {
|
|
|
6426
8186
|
chart: (value) => `Treemap of ${value}`
|
|
6427
8187
|
}
|
|
6428
8188
|
};
|
|
6429
|
-
var
|
|
8189
|
+
var textOf9 = (locale) => TEXT22[uiLanguage(resolveLocale(locale))];
|
|
6430
8190
|
function buildTreemapOption(config) {
|
|
6431
8191
|
const { model, labels, valueFormatter } = config;
|
|
6432
|
-
const t =
|
|
8192
|
+
const t = textOf9(config.locale);
|
|
6433
8193
|
const label2 = (key) => labels?.[key] ?? key;
|
|
6434
8194
|
const surface = config.surfaceColor ?? "#ffffff";
|
|
6435
8195
|
const base = config.toneColor || "#6366f1";
|
|
@@ -6518,7 +8278,7 @@ function mergeDeep5(a, b) {
|
|
|
6518
8278
|
return out;
|
|
6519
8279
|
}
|
|
6520
8280
|
function treemapDataTable(model, names, formatters, labels, locale) {
|
|
6521
|
-
const t =
|
|
8281
|
+
const t = textOf9(locale);
|
|
6522
8282
|
const label2 = (key) => labels?.[key] ?? key;
|
|
6523
8283
|
const share = (v) => v === null || v <= 0 || model.total <= 0 ? EMPTY_VALUE : formatValue(v / model.total, "percent", locale);
|
|
6524
8284
|
return {
|
|
@@ -6542,16 +8302,16 @@ function buildTreemapSummary(model, title, labels, locale) {
|
|
|
6542
8302
|
let best;
|
|
6543
8303
|
for (const g of model.groups) for (const l of g.leaves) if (!best || l.value > best.value) best = l;
|
|
6544
8304
|
if (!best || model.total <= 0) return void 0;
|
|
6545
|
-
return `${title ? `${title}: ` : ""}${
|
|
8305
|
+
return `${title ? `${title}: ` : ""}${textOf9(locale).top(labels?.[best.name] ?? best.name, formatValue(best.value / model.total, "percent", locale))}`;
|
|
6546
8306
|
}
|
|
6547
8307
|
function colorsFor4(tokens, tone) {
|
|
6548
8308
|
const resolved = resolveChartColors([tone, "var(--foreground)", ...DEFAULT_CHART_COLORS, CHART_OTHER_COLOR], tokens);
|
|
6549
8309
|
const [toneColor = "", foreground = ""] = resolved;
|
|
6550
8310
|
return { toneColor, foreground, categories: resolved.slice(2) };
|
|
6551
8311
|
}
|
|
6552
|
-
var
|
|
8312
|
+
var NO_ROWS17 = [];
|
|
6553
8313
|
function TreemapImpl({
|
|
6554
|
-
data =
|
|
8314
|
+
data = NO_ROWS17,
|
|
6555
8315
|
index,
|
|
6556
8316
|
group,
|
|
6557
8317
|
value,
|
|
@@ -6576,7 +8336,7 @@ function TreemapImpl({
|
|
|
6576
8336
|
ariaLabel,
|
|
6577
8337
|
...rest
|
|
6578
8338
|
}, ref) {
|
|
6579
|
-
const rows = Array.isArray(data) ? data :
|
|
8339
|
+
const rows = Array.isArray(data) ? data : NO_ROWS17;
|
|
6580
8340
|
const { ref: frameRef, surface, tokens } = useChartSurface(ref);
|
|
6581
8341
|
const locale = useLocale();
|
|
6582
8342
|
const formatter = useMemo(() => resolveValueFormatter(valueFormatter, format ?? "number", locale), [valueFormatter, format, locale]);
|
|
@@ -6620,7 +8380,7 @@ function TreemapImpl({
|
|
|
6620
8380
|
() => summary === "auto" ? buildTreemapSummary(model, title, labels, locale) : summary,
|
|
6621
8381
|
[summary, model, title, labels, locale]
|
|
6622
8382
|
);
|
|
6623
|
-
const label2 = ariaLabel ??
|
|
8383
|
+
const label2 = ariaLabel ?? textOf9(locale).chart(labels?.[value] ?? value ?? "");
|
|
6624
8384
|
const legendCategories = model.categories.length > MAX_CATEGORIES2 ? [...model.categories.slice(0, MAX_CATEGORIES2), otherSeriesLabel(locale)] : model.categories;
|
|
6625
8385
|
const legend = !showLegend ? null : colorMode === "numeric" ? /* @__PURE__ */ jsx("div", { "data-slot": "treemap-legend", className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground tabular-nums", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
6626
8386
|
color && /* @__PURE__ */ jsx("span", { children: labels?.[color] ?? color }),
|
|
@@ -6652,7 +8412,7 @@ function TreemapImpl({
|
|
|
6652
8412
|
}
|
|
6653
8413
|
var Treemap = forwardRef(TreemapImpl);
|
|
6654
8414
|
Treemap.displayName = "Treemap";
|
|
6655
|
-
var
|
|
8415
|
+
var TEXT23 = {
|
|
6656
8416
|
ja: {
|
|
6657
8417
|
tones: { positive: "\u826F\u597D", warning: "\u6CE8\u610F", negative: "\u8981\u5BFE\u5FDC", neutral: "\u4E2D\u7ACB" },
|
|
6658
8418
|
toneNote: (label2) => `\uFF08${label2}\uFF09`,
|
|
@@ -6686,7 +8446,7 @@ var TEXT18 = {
|
|
|
6686
8446
|
exportCsv: "Export CSV"
|
|
6687
8447
|
}
|
|
6688
8448
|
};
|
|
6689
|
-
var useText = () =>
|
|
8449
|
+
var useText = () => TEXT23[uiLanguage(useLocale())];
|
|
6690
8450
|
function resolveFormat(format, row) {
|
|
6691
8451
|
return typeof format === "function" ? format(row) : format;
|
|
6692
8452
|
}
|
|
@@ -6749,10 +8509,10 @@ function useDataTable() {
|
|
|
6749
8509
|
if (!ctx) throw new Error("useDataTable must be used inside <DataTable>");
|
|
6750
8510
|
return ctx;
|
|
6751
8511
|
}
|
|
6752
|
-
var
|
|
8512
|
+
var NO_ROWS18 = [];
|
|
6753
8513
|
function DataTable({
|
|
6754
|
-
columns =
|
|
6755
|
-
data =
|
|
8514
|
+
columns = NO_ROWS18,
|
|
8515
|
+
data = NO_ROWS18,
|
|
6756
8516
|
enableSorting = true,
|
|
6757
8517
|
sorting: sortingProp,
|
|
6758
8518
|
onSortingChange,
|
|
@@ -6779,7 +8539,7 @@ function DataTable({
|
|
|
6779
8539
|
children
|
|
6780
8540
|
}) {
|
|
6781
8541
|
const locale = useLocale();
|
|
6782
|
-
const t =
|
|
8542
|
+
const t = TEXT23[uiLanguage(locale)];
|
|
6783
8543
|
const [sorting, setSorting] = useControlledState(sortingProp, [], onSortingChange);
|
|
6784
8544
|
const [columnFilters, setColumnFilters] = useControlledState(
|
|
6785
8545
|
columnFiltersProp,
|
|
@@ -7063,19 +8823,19 @@ var DataTableContent = forwardRef(
|
|
|
7063
8823
|
}) }, headerGroup.id)) }),
|
|
7064
8824
|
/* @__PURE__ */ jsx(TableBody, { children: isLoading ? Array.from({ length: enablePagination ? table.getState().pagination.pageSize : 5 }).map(
|
|
7065
8825
|
(_, i) => /* @__PURE__ */ jsx(TableRow, { "data-slot": "data-table-skeleton-row", children: Array.from({ length: visibleColumnCount }).map((__, j) => /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }) }, j)) }, i)
|
|
7066
|
-
) : table.getRowModel().rows.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(TableRow, { "data-state": row.getIsSelected() ? "selected" : void 0, children: row.getVisibleCells().map((
|
|
7067
|
-
const meta =
|
|
7068
|
-
const comparisonColumn = comparisonOf.get(
|
|
8826
|
+
) : table.getRowModel().rows.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(TableRow, { "data-state": row.getIsSelected() ? "selected" : void 0, children: row.getVisibleCells().map((cell2) => {
|
|
8827
|
+
const meta = cell2.column.columnDef.meta;
|
|
8828
|
+
const comparisonColumn = comparisonOf.get(cell2.column.id);
|
|
7069
8829
|
const comparisonCell = comparisonColumn ? row.getVisibleCells().find((c) => c.column.id === comparisonColumn.id) : void 0;
|
|
7070
8830
|
return /* @__PURE__ */ jsxs(
|
|
7071
8831
|
TableCell,
|
|
7072
8832
|
{
|
|
7073
8833
|
className: columnClassName(meta, {
|
|
7074
|
-
isComparison: comparisonIds.has(
|
|
7075
|
-
isHost: comparisonOf.has(
|
|
8834
|
+
isComparison: comparisonIds.has(cell2.column.id),
|
|
8835
|
+
isHost: comparisonOf.has(cell2.column.id)
|
|
7076
8836
|
}),
|
|
7077
8837
|
children: [
|
|
7078
|
-
flexRender(
|
|
8838
|
+
flexRender(cell2.column.columnDef.cell, cell2.getContext()),
|
|
7079
8839
|
comparisonCell && /* @__PURE__ */ jsx(
|
|
7080
8840
|
"div",
|
|
7081
8841
|
{
|
|
@@ -7090,7 +8850,7 @@ var DataTableContent = forwardRef(
|
|
|
7090
8850
|
)
|
|
7091
8851
|
]
|
|
7092
8852
|
},
|
|
7093
|
-
|
|
8853
|
+
cell2.id
|
|
7094
8854
|
);
|
|
7095
8855
|
}) }, row.id)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
|
|
7096
8856
|
TableCell,
|
|
@@ -7225,16 +8985,16 @@ DataTableColumnVisibility.displayName = "DataTableColumnVisibility";
|
|
|
7225
8985
|
var SIGNED_NUMBER = /^[+-]\s?[^\d\s=+\-@]{0,3}\d[\d,.]*[^\d\s=+\-@]{0,4}$/;
|
|
7226
8986
|
function toCsv(header, rows, options = {}) {
|
|
7227
8987
|
const { bom = true, guardFormulas = false } = options;
|
|
7228
|
-
const field = (
|
|
7229
|
-
let text =
|
|
7230
|
-
if (guard && typeof
|
|
8988
|
+
const field = (cell2, guard) => {
|
|
8989
|
+
let text = cell2 === null || cell2 === void 0 ? "" : String(cell2);
|
|
8990
|
+
if (guard && typeof cell2 === "string" && /^[=+\-@]/.test(text) && !SIGNED_NUMBER.test(text)) {
|
|
7231
8991
|
text = `'${text}`;
|
|
7232
8992
|
}
|
|
7233
8993
|
return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
7234
8994
|
};
|
|
7235
8995
|
const lines = [
|
|
7236
8996
|
header.map((h) => field(h, false)).join(","),
|
|
7237
|
-
...rows.map((row) => row.map((
|
|
8997
|
+
...rows.map((row) => row.map((cell2) => field(cell2, guardFormulas)).join(","))
|
|
7238
8998
|
];
|
|
7239
8999
|
return (bom ? "\uFEFF" : "") + lines.join("\r\n");
|
|
7240
9000
|
}
|
|
@@ -7288,7 +9048,7 @@ function DataTableExport({
|
|
|
7288
9048
|
disabled: isLoading,
|
|
7289
9049
|
children: [
|
|
7290
9050
|
/* @__PURE__ */ jsx(Download, { className: "size-4", "aria-hidden": "true" }),
|
|
7291
|
-
children ??
|
|
9051
|
+
children ?? TEXT23[uiLanguage(locale)].exportCsv
|
|
7292
9052
|
]
|
|
7293
9053
|
}
|
|
7294
9054
|
);
|
|
@@ -7368,14 +9128,14 @@ function pivotSpans(keys, level) {
|
|
|
7368
9128
|
});
|
|
7369
9129
|
return out;
|
|
7370
9130
|
}
|
|
7371
|
-
var
|
|
9131
|
+
var TEXT24 = {
|
|
7372
9132
|
ja: { table: "\u30D4\u30DC\u30C3\u30C8\u8868" },
|
|
7373
9133
|
en: { table: "Pivot table" }
|
|
7374
9134
|
};
|
|
7375
|
-
var
|
|
9135
|
+
var NO_ROWS19 = [];
|
|
7376
9136
|
var asList = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
7377
9137
|
function PivotTable({
|
|
7378
|
-
data =
|
|
9138
|
+
data = NO_ROWS19,
|
|
7379
9139
|
rows: rowDims,
|
|
7380
9140
|
columns: colDims,
|
|
7381
9141
|
values: valueKeys,
|
|
@@ -7393,8 +9153,8 @@ function PivotTable({
|
|
|
7393
9153
|
ariaLabel
|
|
7394
9154
|
}) {
|
|
7395
9155
|
const locale = useLocale();
|
|
7396
|
-
const t =
|
|
7397
|
-
const dataRows = Array.isArray(data) ? data :
|
|
9156
|
+
const t = TEXT24[uiLanguage(resolveLocale(locale))];
|
|
9157
|
+
const dataRows = Array.isArray(data) ? data : NO_ROWS19;
|
|
7398
9158
|
const rows = useMemo(() => asList(rowDims), [rowDims]);
|
|
7399
9159
|
const columns = useMemo(() => asList(colDims), [colDims]);
|
|
7400
9160
|
const values = useMemo(() => asList(valueKeys), [valueKeys]);
|
|
@@ -7465,7 +9225,7 @@ function PivotTable({
|
|
|
7465
9225
|
);
|
|
7466
9226
|
}
|
|
7467
9227
|
var FilterBarContext = createContext(null);
|
|
7468
|
-
var
|
|
9228
|
+
var TEXT25 = {
|
|
7469
9229
|
ja: {
|
|
7470
9230
|
filters: "\u30D5\u30A3\u30EB\u30BF\u30FC",
|
|
7471
9231
|
selected: (count) => ` (${count}\u4EF6\u9078\u629E\u4E2D)`,
|
|
@@ -7481,7 +9241,7 @@ var TEXT20 = {
|
|
|
7481
9241
|
clearAll: "Clear all filters"
|
|
7482
9242
|
}
|
|
7483
9243
|
};
|
|
7484
|
-
var useText2 = () =>
|
|
9244
|
+
var useText2 = () => TEXT25[uiLanguage(useLocale())];
|
|
7485
9245
|
function useFilterBar() {
|
|
7486
9246
|
const ctx = useContext(FilterBarContext);
|
|
7487
9247
|
if (!ctx) throw new Error("useFilterBar must be used within <FilterBar>");
|
|
@@ -7784,7 +9544,7 @@ var PRESET_LABELS = {
|
|
|
7784
9544
|
lastFiscalYear: "Last fiscal year"
|
|
7785
9545
|
}
|
|
7786
9546
|
};
|
|
7787
|
-
var
|
|
9547
|
+
var TEXT26 = {
|
|
7788
9548
|
ja: { placeholder: "\u671F\u9593\u3092\u9078\u629E", rangeSeparator: " - " },
|
|
7789
9549
|
en: { placeholder: "Pick a date range", rangeSeparator: " \u2013 " }
|
|
7790
9550
|
};
|
|
@@ -7802,7 +9562,7 @@ function createDatePresets({
|
|
|
7802
9562
|
const today = now();
|
|
7803
9563
|
return { from: startOfDay(subDays(today, days - 1)), to: endOfDay(today) };
|
|
7804
9564
|
};
|
|
7805
|
-
const
|
|
9565
|
+
const toDate3 = (unit) => () => {
|
|
7806
9566
|
const today = now();
|
|
7807
9567
|
return {
|
|
7808
9568
|
from: fiscalPeriodRange(today, { unit, fiscalYearStartMonth: startMonth }).from,
|
|
@@ -7852,9 +9612,9 @@ function createDatePresets({
|
|
|
7852
9612
|
return { from: startOfMonth(lastMonth), to: endOfMonth(lastMonth) };
|
|
7853
9613
|
}
|
|
7854
9614
|
},
|
|
7855
|
-
{ label: t.thisQuarter, getValue:
|
|
9615
|
+
{ label: t.thisQuarter, getValue: toDate3("quarter") },
|
|
7856
9616
|
{ label: t.lastQuarter, getValue: previous("quarter") },
|
|
7857
|
-
{ label: t.thisFiscalYear, getValue:
|
|
9617
|
+
{ label: t.thisFiscalYear, getValue: toDate3("year") },
|
|
7858
9618
|
{ label: t.lastFiscalYear, getValue: previous("year") }
|
|
7859
9619
|
];
|
|
7860
9620
|
}
|
|
@@ -7885,7 +9645,7 @@ var DateRangePicker = forwardRef(
|
|
|
7885
9645
|
const [open, setOpen] = useState(false);
|
|
7886
9646
|
const isMobile = useIsMobile();
|
|
7887
9647
|
const locale = useLocale(localeProp);
|
|
7888
|
-
const t =
|
|
9648
|
+
const t = TEXT26[uiLanguage(locale)];
|
|
7889
9649
|
const presets = useMemo(
|
|
7890
9650
|
() => presetsProp ?? createDatePresets({ locale, fiscalYearStartMonth }),
|
|
7891
9651
|
[presetsProp, locale, fiscalYearStartMonth]
|
|
@@ -8102,7 +9862,7 @@ function RemoveButton({ label: label2, onRemove, iconClassName }) {
|
|
|
8102
9862
|
}
|
|
8103
9863
|
);
|
|
8104
9864
|
}
|
|
8105
|
-
var
|
|
9865
|
+
var TEXT27 = {
|
|
8106
9866
|
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" },
|
|
8107
9867
|
en: { placeholder: "Select an option", search: "Search...", empty: "No results found.", clear: "Clear" }
|
|
8108
9868
|
};
|
|
@@ -8122,7 +9882,7 @@ var SearchableSelect = forwardRef(
|
|
|
8122
9882
|
className
|
|
8123
9883
|
}, ref) {
|
|
8124
9884
|
const [open, setOpen] = useState(false);
|
|
8125
|
-
const t =
|
|
9885
|
+
const t = TEXT27[uiLanguage(useLocale())];
|
|
8126
9886
|
const allOptions = useMemo(() => flattenOptions(options), [options]);
|
|
8127
9887
|
const selectedOption = useMemo(
|
|
8128
9888
|
() => allOptions.find((opt) => opt.value === value),
|
|
@@ -8175,7 +9935,7 @@ var SearchableSelect = forwardRef(
|
|
|
8175
9935
|
}
|
|
8176
9936
|
);
|
|
8177
9937
|
SearchableSelect.displayName = "SearchableSelect";
|
|
8178
|
-
var
|
|
9938
|
+
var TEXT28 = {
|
|
8179
9939
|
ja: {
|
|
8180
9940
|
placeholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
8181
9941
|
search: "\u691C\u7D22...",
|
|
@@ -8192,10 +9952,10 @@ var TEXT23 = {
|
|
|
8192
9952
|
}
|
|
8193
9953
|
};
|
|
8194
9954
|
var NO_OPTIONS3 = [];
|
|
8195
|
-
var
|
|
9955
|
+
var NO_VALUES2 = [];
|
|
8196
9956
|
var MultiSelect = forwardRef(function MultiSelect2({
|
|
8197
9957
|
options = NO_OPTIONS3,
|
|
8198
|
-
value =
|
|
9958
|
+
value = NO_VALUES2,
|
|
8199
9959
|
onChange,
|
|
8200
9960
|
onSearch,
|
|
8201
9961
|
maxCount = 3,
|
|
@@ -8208,7 +9968,7 @@ var MultiSelect = forwardRef(function MultiSelect2({
|
|
|
8208
9968
|
}, ref) {
|
|
8209
9969
|
const [open, setOpen] = useState(false);
|
|
8210
9970
|
const listId = useId();
|
|
8211
|
-
const t =
|
|
9971
|
+
const t = TEXT28[uiLanguage(useLocale())];
|
|
8212
9972
|
const allOptions = useMemo(() => flattenOptions(options), [options]);
|
|
8213
9973
|
const selectedOptions = useMemo(
|
|
8214
9974
|
() => allOptions.filter((opt) => value.includes(opt.value)),
|
|
@@ -8338,10 +10098,10 @@ function computeTargetProgress(current, target, options) {
|
|
|
8338
10098
|
elapsed
|
|
8339
10099
|
};
|
|
8340
10100
|
}
|
|
8341
|
-
var
|
|
10101
|
+
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
8342
10102
|
function inferPeriodGrain(period) {
|
|
8343
10103
|
if (!period) return void 0;
|
|
8344
|
-
const days = (toTime(period.end) - toTime(period.start)) /
|
|
10104
|
+
const days = (toTime(period.end) - toTime(period.start)) / DAY_MS2;
|
|
8345
10105
|
if (!Number.isFinite(days)) return void 0;
|
|
8346
10106
|
const near = (min, max) => days >= min - 1 / 24 && days <= max + 1 / 24;
|
|
8347
10107
|
if (near(1, 1)) return "day";
|
|
@@ -8490,7 +10250,7 @@ var LONG_VALUE_CHARS = 10;
|
|
|
8490
10250
|
var DELTA_UNDER_PLACEMENT = "col-start-1 row-span-1 row-start-3 justify-self-start";
|
|
8491
10251
|
var KPI_FOOTER_CLASS = "flex-col items-start gap-2 rounded-none border-t-0 bg-transparent pt-0 text-sm";
|
|
8492
10252
|
var PLACEHOLDER = /\{(\w+)\}/g;
|
|
8493
|
-
var
|
|
10253
|
+
var TEXT29 = {
|
|
8494
10254
|
ja: {
|
|
8495
10255
|
target: "\u76EE\u6A19",
|
|
8496
10256
|
provisional: "\u901F\u5831",
|
|
@@ -8622,7 +10382,7 @@ function KpiCard({
|
|
|
8622
10382
|
...props
|
|
8623
10383
|
}) {
|
|
8624
10384
|
const locale = useLocale(localeProp);
|
|
8625
|
-
const t =
|
|
10385
|
+
const t = TEXT29[uiLanguage(locale)];
|
|
8626
10386
|
const allComparisons = [...comparisonProp ? [comparisonProp] : [], ...comparisons ?? []];
|
|
8627
10387
|
const comparison = allComparisons[0];
|
|
8628
10388
|
const isProvisional = provisional !== void 0 && provisional !== false;
|
|
@@ -8873,7 +10633,7 @@ function updatedAtText(updatedAt, display, locale, t, now, timeZone) {
|
|
|
8873
10633
|
const absolute2 = formatDate(updatedAt, "datetime", locale, { timeZone });
|
|
8874
10634
|
return display === "absolute" ? t.updatedAbsolute(absolute2) : t.updatedBoth(absolute2, relative2);
|
|
8875
10635
|
}
|
|
8876
|
-
var
|
|
10636
|
+
var TEXT30 = {
|
|
8877
10637
|
ja: {
|
|
8878
10638
|
flat: (value) => `\u5909\u5316\u306A\u3057 ${value}%`,
|
|
8879
10639
|
up: (value) => `${value}% \u5897\u52A0`,
|
|
@@ -8902,7 +10662,7 @@ var TrendIndicator = forwardRef(
|
|
|
8902
10662
|
const isGood = direction === "neutral" ? null : direction === "up" === positiveIsGood;
|
|
8903
10663
|
const sentiment = isGood === null ? "neutral" : isGood ? "positive" : "negative";
|
|
8904
10664
|
const Icon = direction === "up" ? ArrowUp : direction === "down" ? ArrowDown : Minus;
|
|
8905
|
-
const t =
|
|
10665
|
+
const t = TEXT30[uiLanguage(useLocale())];
|
|
8906
10666
|
const ariaLabel = direction === "neutral" ? t.flat(value) : direction === "up" ? t.up(value) : t.down(value);
|
|
8907
10667
|
return /* @__PURE__ */ jsxs(
|
|
8908
10668
|
"span",
|
|
@@ -8923,93 +10683,6 @@ var TrendIndicator = forwardRef(
|
|
|
8923
10683
|
}
|
|
8924
10684
|
);
|
|
8925
10685
|
TrendIndicator.displayName = "TrendIndicator";
|
|
8926
|
-
var STATUS_LABELS = {
|
|
8927
|
-
ja: {
|
|
8928
|
-
success: "\u6B63\u5E38",
|
|
8929
|
-
partial: "\u4E00\u90E8\u5931\u6557",
|
|
8930
|
-
failed: "\u5931\u6557",
|
|
8931
|
-
delayed: "\u9045\u5EF6",
|
|
8932
|
-
running: "\u5B9F\u884C\u4E2D",
|
|
8933
|
-
stopped: "\u505C\u6B62\u4E2D",
|
|
8934
|
-
active: "\u6709\u52B9",
|
|
8935
|
-
inactive: "\u7121\u52B9",
|
|
8936
|
-
warning: "\u8B66\u544A",
|
|
8937
|
-
error: "\u30A8\u30E9\u30FC",
|
|
8938
|
-
pending: "\u4FDD\u7559\u4E2D"
|
|
8939
|
-
},
|
|
8940
|
-
en: {
|
|
8941
|
-
success: "Healthy",
|
|
8942
|
-
partial: "Partially failed",
|
|
8943
|
-
failed: "Failed",
|
|
8944
|
-
delayed: "Delayed",
|
|
8945
|
-
running: "Running",
|
|
8946
|
-
stopped: "Stopped",
|
|
8947
|
-
active: "Active",
|
|
8948
|
-
inactive: "Inactive",
|
|
8949
|
-
warning: "Warning",
|
|
8950
|
-
error: "Error",
|
|
8951
|
-
pending: "Pending"
|
|
8952
|
-
}
|
|
8953
|
-
};
|
|
8954
|
-
var STATUS_VOCABULARY = {
|
|
8955
|
-
success: { label: STATUS_LABELS.en.success, tone: "positive" },
|
|
8956
|
-
partial: { label: STATUS_LABELS.en.partial, tone: "warning" },
|
|
8957
|
-
failed: { label: STATUS_LABELS.en.failed, tone: "negative" },
|
|
8958
|
-
delayed: { label: STATUS_LABELS.en.delayed, tone: "warning" },
|
|
8959
|
-
running: { label: STATUS_LABELS.en.running, tone: "info" },
|
|
8960
|
-
stopped: { label: STATUS_LABELS.en.stopped, tone: "neutral" },
|
|
8961
|
-
active: { label: STATUS_LABELS.en.active, tone: "positive" },
|
|
8962
|
-
inactive: { label: STATUS_LABELS.en.inactive, tone: "neutral" },
|
|
8963
|
-
warning: { label: STATUS_LABELS.en.warning, tone: "warning" },
|
|
8964
|
-
error: { label: STATUS_LABELS.en.error, tone: "negative" },
|
|
8965
|
-
pending: { label: STATUS_LABELS.en.pending, tone: "info" }
|
|
8966
|
-
};
|
|
8967
|
-
function statusLabel(status, locale) {
|
|
8968
|
-
return Object.hasOwn(STATUS_VOCABULARY, status) ? STATUS_LABELS[uiLanguage(resolveLocale(locale))][status] : status;
|
|
8969
|
-
}
|
|
8970
|
-
var defaultColorMap = Object.fromEntries(
|
|
8971
|
-
Object.entries(STATUS_VOCABULARY).map(([key, { tone }]) => [key, tone])
|
|
8972
|
-
);
|
|
8973
|
-
var legacyColorTones = {
|
|
8974
|
-
green: "positive",
|
|
8975
|
-
gray: "neutral",
|
|
8976
|
-
yellow: "warning",
|
|
8977
|
-
red: "negative",
|
|
8978
|
-
blue: "info"
|
|
8979
|
-
};
|
|
8980
|
-
var toneStyles = {
|
|
8981
|
-
positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive", border: "border-positive/20 dark:border-positive/25" },
|
|
8982
|
-
negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative", border: "border-negative/20 dark:border-negative/25" },
|
|
8983
|
-
warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning", border: "border-warning/20 dark:border-warning/25" },
|
|
8984
|
-
info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info", border: "border-info/20 dark:border-info/25" },
|
|
8985
|
-
neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral", border: "border-neutral/20 dark:border-neutral/25" }
|
|
8986
|
-
};
|
|
8987
|
-
var resolveTone = (color) => {
|
|
8988
|
-
if (color === void 0) return "neutral";
|
|
8989
|
-
if (Object.hasOwn(toneStyles, color)) return color;
|
|
8990
|
-
return legacyColorTones[color] ?? "neutral";
|
|
8991
|
-
};
|
|
8992
|
-
var StatusBadge = forwardRef(function StatusBadge2({ status, label: label2, colorMap, className }, ref) {
|
|
8993
|
-
const locale = useLocale();
|
|
8994
|
-
const mergedColorMap = { ...defaultColorMap, ...colorMap };
|
|
8995
|
-
const style = toneStyles[resolveTone(mergedColorMap[status])];
|
|
8996
|
-
const displayLabel = label2 ?? statusLabel(status, locale);
|
|
8997
|
-
return /* @__PURE__ */ jsxs(
|
|
8998
|
-
Badge,
|
|
8999
|
-
{
|
|
9000
|
-
ref,
|
|
9001
|
-
"data-slot": "status-badge",
|
|
9002
|
-
variant: "outline",
|
|
9003
|
-
className: cn("gap-1.5 rounded-md", style.border, style.bg, style.text, className),
|
|
9004
|
-
"aria-label": displayLabel,
|
|
9005
|
-
children: [
|
|
9006
|
-
/* @__PURE__ */ jsx("span", { className: cn("inline-block size-1.5 rounded-full", style.dot), "aria-hidden": "true" }),
|
|
9007
|
-
displayLabel
|
|
9008
|
-
]
|
|
9009
|
-
}
|
|
9010
|
-
);
|
|
9011
|
-
});
|
|
9012
|
-
StatusBadge.displayName = "StatusBadge";
|
|
9013
10686
|
var Placeholder = forwardRef(function Placeholder2({ className, ...props }, ref) {
|
|
9014
10687
|
return /* @__PURE__ */ jsx(
|
|
9015
10688
|
"span",
|
|
@@ -9022,7 +10695,69 @@ var Placeholder = forwardRef(function Placeholder2({ className, ...props }, ref)
|
|
|
9022
10695
|
);
|
|
9023
10696
|
});
|
|
9024
10697
|
Placeholder.displayName = "Placeholder";
|
|
10698
|
+
function DraftChart({ children }) {
|
|
10699
|
+
if (!import.meta.env.DEV) return null;
|
|
10700
|
+
return /* @__PURE__ */ jsx(DraftChartPreview, { children });
|
|
10701
|
+
}
|
|
10702
|
+
var STYLE_ID = "vantage-draft-chart";
|
|
10703
|
+
var DRAFT_CSS = `@layer components {
|
|
10704
|
+
[data-sq-draft] {
|
|
10705
|
+
position: relative;
|
|
10706
|
+
isolation: isolate;
|
|
10707
|
+
}
|
|
10708
|
+
[data-sq-draft]::after {
|
|
10709
|
+
content: "";
|
|
10710
|
+
position: absolute;
|
|
10711
|
+
inset: -1px;
|
|
10712
|
+
z-index: 2147483647;
|
|
10713
|
+
border-radius: inherit;
|
|
10714
|
+
background-color: var(--background);
|
|
10715
|
+
opacity: 0.75;
|
|
10716
|
+
pointer-events: none;
|
|
10717
|
+
transition: opacity 200ms ease;
|
|
10718
|
+
}
|
|
10719
|
+
[data-sq-draft]:hover::after {
|
|
10720
|
+
opacity: 0;
|
|
10721
|
+
}
|
|
10722
|
+
@media (prefers-reduced-motion: reduce) {
|
|
10723
|
+
[data-sq-draft]::after {
|
|
10724
|
+
transition: none;
|
|
10725
|
+
}
|
|
10726
|
+
}
|
|
10727
|
+
}`;
|
|
10728
|
+
function DraftChartPreview({ children }) {
|
|
10729
|
+
const ref = useRef(null);
|
|
10730
|
+
useInsertionEffect(() => {
|
|
10731
|
+
let style = document.getElementById(STYLE_ID);
|
|
10732
|
+
if (!style) {
|
|
10733
|
+
style = document.createElement("style");
|
|
10734
|
+
style.id = STYLE_ID;
|
|
10735
|
+
document.head.appendChild(style);
|
|
10736
|
+
}
|
|
10737
|
+
if (style.textContent !== DRAFT_CSS) style.textContent = DRAFT_CSS;
|
|
10738
|
+
}, []);
|
|
10739
|
+
useLayoutEffect(() => {
|
|
10740
|
+
const wrapper = ref.current;
|
|
10741
|
+
if (!wrapper) return;
|
|
10742
|
+
let marked = null;
|
|
10743
|
+
const mark = () => {
|
|
10744
|
+
const root = wrapper.firstElementChild;
|
|
10745
|
+
if (root === marked) return;
|
|
10746
|
+
marked?.removeAttribute("data-sq-draft");
|
|
10747
|
+
root?.setAttribute("data-sq-draft", "");
|
|
10748
|
+
marked = root;
|
|
10749
|
+
};
|
|
10750
|
+
mark();
|
|
10751
|
+
const observer = new MutationObserver(mark);
|
|
10752
|
+
observer.observe(wrapper, { childList: true });
|
|
10753
|
+
return () => {
|
|
10754
|
+
observer.disconnect();
|
|
10755
|
+
marked?.removeAttribute("data-sq-draft");
|
|
10756
|
+
};
|
|
10757
|
+
}, []);
|
|
10758
|
+
return /* @__PURE__ */ jsx("div", { ref, "data-slot": "draft-chart", style: { display: "contents" }, children });
|
|
10759
|
+
}
|
|
9025
10760
|
|
|
9026
|
-
export { AppShell, AreaChart, BarChart, BarList, COMPARISON_LABELS, CategoryBar, ChartFrame, ComboChart, 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, FilledMap, 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, PivotTable, Placeholder, ProgressCircle, RECORD_MIN_POINTS, SampleBadge, SampleClaim, SampleData, ScatterChart, SearchableSelect, SectionHeader, SegmentedControl, StatusBadge, SymbolMap, Tracker, Treemap, 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 };
|
|
9027
|
-
//# sourceMappingURL=chunk-
|
|
9028
|
-
//# sourceMappingURL=chunk-
|
|
10761
|
+
export { AppShell, AreaChart, AttentionList, BarChart, BarList, BoxPlotChart, COMPARISON_LABELS, CategoryBar, ChartFrame, ComboChart, 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, DraftChart, FilledMap, FilterBar, FilterBarActiveChips, FilterBarClearButton, FilterBarMultiSelect, FilterBarPreset, FilterBarSelect, ForecastChart, FunnelSteps, Heatmap, HistogramChart, KpiCard, Legend, LineChart, MetricUnit, MetricValue, MultiSelect, PageShell, PageShellActions, PageShellContent, PageShellDescription, PageShellHeader, PageShellHeaderEnd, PageShellHeading, PageShellMeta, PageShellSummary, PageShellSummaryCard, PageShellTitle, PairedChart, PivotTable, Placeholder, ProgressCircle, RECORD_MIN_POINTS, SampleBadge, SampleClaim, SampleData, ScatterChart, SearchableSelect, SectionHeader, SegmentedControl, StatusBadge, SymbolMap, Tracker, Treemap, 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 };
|
|
10762
|
+
//# sourceMappingURL=chunk-DULE4EDK.js.map
|
|
10763
|
+
//# sourceMappingURL=chunk-DULE4EDK.js.map
|