@squadbase/vantage 0.7.0-dev1.5d49eae → 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.
Files changed (51) hide show
  1. package/dist/{chunk-NYQJ5UY4.js → chunk-DULE4EDK.js} +2008 -273
  2. package/dist/chunk-DULE4EDK.js.map +1 -0
  3. package/dist/{chunk-TRMHNMMZ.js → chunk-LYUGDHSF.js} +3 -3
  4. package/dist/{chunk-TRMHNMMZ.js.map → chunk-LYUGDHSF.js.map} +1 -1
  5. package/dist/{chunk-QNOX7WLZ.js → chunk-MQUIAP66.js} +69 -4
  6. package/dist/chunk-MQUIAP66.js.map +1 -0
  7. package/dist/{chunk-2IAPIOPS.js → chunk-P2KIHF65.js} +2 -2
  8. package/dist/chunk-P2KIHF65.js.map +1 -0
  9. package/dist/{chunk-3RJEOP3J.js → chunk-XRKSIC5Z.js} +5 -3
  10. package/dist/chunk-XRKSIC5Z.js.map +1 -0
  11. package/dist/components/index.d.ts +276 -6
  12. package/dist/components/index.js +4 -4
  13. package/dist/{delta-text-CbrOaW83.d.ts → delta-text-tav2Lh5d.d.ts} +1 -1
  14. package/dist/doc/index.d.ts +2 -2
  15. package/dist/doc/index.js +4 -4
  16. package/dist/{format-DihQkL1N.d.ts → format-D34piCei.d.ts} +2 -1
  17. package/dist/slide/index.d.ts +2 -2
  18. package/dist/slide/index.js +3 -3
  19. package/dist/table/index.js +4 -5
  20. package/dist/table/index.js.map +1 -1
  21. package/dist/ui/index.js +2 -3
  22. package/dist/ui/index.js.map +1 -1
  23. package/docs/en/parts/draft-chart.md +42 -0
  24. package/docs/en/parts/page-shell.md +1 -1
  25. package/docs/index.json +68 -48
  26. package/docs/ja/parts/draft-chart.md +40 -0
  27. package/docs/ja/parts/page-shell.md +1 -1
  28. package/package.json +2 -2
  29. package/registry/parts.json +5214 -0
  30. package/registry/ui/chart-frame.tsx +8 -0
  31. package/registry/ui/combo-chart.tsx +2 -1
  32. package/registry/ui/dashboard-card.tsx +3 -1
  33. package/registry/ui/data-table.tsx +3 -1
  34. package/registry/ui/delta.tsx +3 -1
  35. package/registry/ui/filter-bar.tsx +3 -1
  36. package/registry/ui/forecast-chart.tsx +4726 -0
  37. package/registry/ui/funnel-steps.tsx +1 -1
  38. package/registry/ui/kpi-card.tsx +3 -1
  39. package/registry/ui/metric-value.tsx +2 -2
  40. package/registry/ui/page-shell.tsx +25 -4
  41. package/registry/ui/paired-chart.tsx +1 -1
  42. package/registry/ui/pivot-table.tsx +2 -1
  43. package/registry/ui/progress-circle.tsx +2 -2
  44. package/registry/ui/sparkline.tsx +1 -1
  45. package/registry/ui/treemap.tsx +2 -1
  46. package/dist/chunk-2IAPIOPS.js.map +0 -1
  47. package/dist/chunk-3RJEOP3J.js.map +0 -1
  48. package/dist/chunk-NYQJ5UY4.js.map +0 -1
  49. package/dist/chunk-NZ5QIIG4.js +0 -74
  50. package/dist/chunk-NZ5QIIG4.js.map +0 -1
  51. package/dist/chunk-QNOX7WLZ.js.map +0 -1
@@ -1,10 +1,10 @@
1
- import { ChartFrameContext, useChartSurface, resolveChartColors, CHART_OTHER_COLOR, EChart, resolveFillColors } from './chunk-EG4PX726.js';
2
- import { Sparkline } from './chunk-2IAPIOPS.js';
3
- import { formatDateRange, EMPTY_VALUE, formatDate, toValueFormatter, formatValue, formatPoints, formatKind, formatDelta, MINUS_SIGN, formatDatesInText, DEFAULT_LOCALE } from './chunk-3RJEOP3J.js';
4
- import { Tooltip, TooltipTrigger, TooltipContent, Badge, SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Checkbox, Card, CardHeader, CardDescription, CardTitle, CardAction, CardFooter } from './chunk-QNOX7WLZ.js';
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
- (cell, c) => c === 0 ? /* @__PURE__ */ jsx("th", { scope: "row", children: cell }, c) : /* @__PURE__ */ jsx("td", { children: cell }, c)
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, percent) {
804
- return `color-mix(in oklab, ${cssColor} ${percent}%, transparent)`;
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, toDate2, locale) {
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" && toDate2) return nouns["prior-year"].unknown;
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, toDate2, locale) {
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, toDate2, resolved));
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 percent = kind !== "line" && type === "percent";
1751
+ const percent2 = kind !== "line" && type === "percent";
1744
1752
  const horizontalBars = kind === "bar" && layout === "vertical";
1745
- const comparison = kind !== "bar" && !percent ? cfg.comparison : void 0;
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 forecast = kind !== "bar" && !percent && cfg.forecast && cfg.forecast.data.length > 0 && data.length > 0 && categories.length > 0 ? cfg.forecast : void 0;
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 (forecast) {
1770
+ if (forecast2) {
1763
1771
  const position = new Map(labels.map((label2, i) => [label2, i]));
1764
- for (const row of forecast.data) {
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 && !percent ? stackTotalsOf(mainIdx.map((i) => values[i])) : null;
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 = percent && kind === "area";
1804
- const picked = highlight !== "auto" || mainIdx.length === 0 || percent && !shareHighlight ? [] : shareHighlight ? categories.length <= 2 ? pickShareHighlightPoints(values[0] ?? []) : [] : stackTotals ? pickHighlightPoints(stackTotals) : mainIdx.length <= 2 ? pickHighlightPoints(values[highlightSeries] ?? []) : [];
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" && !percent && cfg.forecast && cfg.forecast.data.length > 0 ? lastActual : -1;
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 && !percent && (stacked || categories.length === 1) ? barTargetValues(data, targetKey) : null;
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: percent && c === categories.length - 1 ? { width: 0, color, opacity: 0 } : { width: 2, color, opacity: dimSeries ? DIMMED : 1 },
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: percent && c === categories.length - 1 ? { width: 0, color, opacity: 0 } : { width: 2, type: "dashed", color, opacity },
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 = forecast?.label ?? text.forecast;
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 (forecast) {
2013
- const category = forecast.category !== void 0 && categories.includes(forecast.category) && forecast.category !== comparison?.category ? forecast.category : categories[mainIdx[0] ?? 0];
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
- forecast.data.forEach((row, k) => {
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 = percent ? 100 : maxValue ?? Math.max(target, ...totals);
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 (forecast) {
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 = percent ? 100 : maxValue ?? Math.max(0, ...(stacked ? stackTotalsOf(values) : values.flat()).map((v) => v ?? 0));
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 = percent ? (v) => `${v}%` : (v) => axisFormatter(v);
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 || percent) return axisFormatter;
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 (forecast) addAll(forecast.data.flatMap((row) => [cellNumber(row.lower), cellNumber(row.upper)]));
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: percent ? 0 : kind === "line" ? minValue === void 0 ? fit ? void 0 : zeroBasedMin : limits.min : limits.min,
2318
- max: percent ? 100 : limits.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: percent ? (v) => `${v}%` : (v) => tickFormatter(v),
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
- ...forecast ? [forecastLabel] : [],
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 } : forecast && name === forecastLabel ? { name, icon: FORECAST_DASHED_ICON } : hasTarget && name === targetText ? { name, icon: TARGET_DOTTED_ICON } : name
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
- (forecast ? FORECAST_LABEL_ROOM : 0),
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 = percent ? cartesianSeriesValues(i <= lastActual ? [row] : [], categories, "percent") : null;
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
- forecast,
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
- forecast,
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 cell = (plotWidth + HEATMAP_BUCKET_MID - HEATMAP_GRID_X - (widest(rowNames) + 8)) / Math.max(1, columns);
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 <= cell) return 12;
5089
- return text * 10 / 12 + HEATMAP_CELL_PADDING <= cell ? 10 : null;
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 = (cell) => cell.flagged ? { borderColor: config.flagColor, borderWidth: 3, borderType: "solid" } : { borderColor: "transparent", borderWidth: 1 };
5118
- const tooltip = (cell) => {
5119
- const head = `${escapeHtml2(label2(model.ys[cell.yi]))} ${escapeHtml2(label2(model.xs[cell.xi]))}`;
5120
- const main = cell.value === null ? EMPTY_VALUE : escapeHtml2(valueFormatter(cell.value));
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 = cell.row ? toChartNumber(cell.row[key]) : null;
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 = cell.flagged ? `${t.join}${t.flagged}` : "";
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((cell) => cell.value === null ? [] : [valueFormatter(cell.value)])
5140
+ model.cells.flatMap((cell2) => cell2.value === null ? [] : [valueFormatter(cell2.value)])
5133
5141
  ) : 12;
5134
- const point = (cell) => ({ value: [cell.xi, cell.yi, cell.value], cell });
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((cell) => ({
5183
- ...point(cell),
5184
- itemStyle: flagged(cell),
5190
+ data: present.map((cell2) => ({
5191
+ ...point(cell2),
5192
+ itemStyle: flagged(cell2),
5185
5193
  label: {
5186
- color: heatmapRatio(cell.value, model.min, model.max) >= HEATMAP_LIGHT_TEXT_FROM ? config.darkCellText : config.lightCellText
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((cell) => ({ value: [cell.xi, cell.yi, 0], cell, itemStyle: flagged(cell) })),
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 cell of model.cells) if (cell.value !== null && (!best || cell.value > best.value)) best = cell;
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) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
5376
6439
  }
5377
- var TEXT14 = {
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 textOf4 = (locale) => TEXT14[uiLanguage(resolveLocale(locale))];
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] ?? textOf4(locale).item, ...list.map((s) => s.label ?? label2(s.key))],
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 NO_ROWS12 = [];
6607
+ var NO_ROWS13 = [];
5545
6608
  function ComboChartImpl({
5546
- data = NO_ROWS12,
6609
+ data = NO_ROWS13,
5547
6610
  index,
5548
- series = NO_ROWS12,
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 : NO_ROWS12;
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
- series: list,
5588
- palette: palette.series,
5589
- referenceColor: palette.reference,
5590
- labels,
5591
- formatters,
5592
- ticks,
5593
- referenceLines,
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
- plotHeight: height,
5599
- chartOptions
5600
- }),
5601
- [rows, index, list, palette, labels, formatters, ticks, referenceLines, stacked, layout, showLegend, showTooltip, height, chartOptions]
5602
- );
5603
- const onEvents = useMemo(
5604
- () => onSelect ? {
5605
- click: (params) => {
5606
- const p = params;
5607
- if (p.componentType !== "series" || (p.seriesIndex ?? Infinity) >= list.length) return;
5608
- const row = rows[p.dataIndex ?? -1];
5609
- if (row) onSelect(row);
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
- } : void 0,
5612
- [onSelect, rows, list.length]
5613
- );
5614
- const dataTable = useMemo(() => comboChartDataTable(rows, index, list, formatters, labels, locale), [rows, index, list, formatters, labels, locale]);
5615
- const label2 = ariaLabel ?? textOf4(locale).chart;
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: rows.length === 0,
7390
+ isEmpty: !model || !option,
5625
7391
  emptyState,
5626
7392
  height,
5627
- variant: "bar",
7393
+ variant: "line",
5628
7394
  ariaLabel: label2,
5629
7395
  className,
5630
7396
  dataTable,
5631
- children: /* @__PURE__ */ jsx(EChart, { option, onEvents, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary } })
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
- function resolveColors(tokens, series) {
5636
- const resolved = resolveChartColors(
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) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
5898
7658
  }
5899
- var TEXT15 = {
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 textOf5 = (locale) => TEXT15[uiLanguage(resolveLocale(locale))];
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 = textOf5(config.locale);
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 = textOf5(locale);
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}: ` : ""}${textOf5(locale).top(best.name, formatter(best.value))}`;
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 NO_ROWS13 = [];
7759
+ var NO_ROWS15 = [];
6000
7760
  function FilledMapImpl({
6001
- data = NO_ROWS13,
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 : NO_ROWS13;
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 ?? textOf5(locale).chart(labels?.[value] ?? value ?? "");
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) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
6146
7906
  }
6147
- var TEXT16 = {
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 textOf6 = (locale) => TEXT16[uiLanguage(resolveLocale(locale))];
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 = textOf6(locale);
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 NO_ROWS14 = [];
8027
+ var NO_ROWS16 = [];
6268
8028
  function SymbolMapImpl({
6269
- data = NO_ROWS14,
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 : NO_ROWS14;
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(NO_ROWS14, resolvedBasemap);
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 ?? textOf6(locale).chart;
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) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
6410
8170
  }
6411
- var TEXT17 = {
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 textOf7 = (locale) => TEXT17[uiLanguage(resolveLocale(locale))];
8189
+ var textOf9 = (locale) => TEXT22[uiLanguage(resolveLocale(locale))];
6430
8190
  function buildTreemapOption(config) {
6431
8191
  const { model, labels, valueFormatter } = config;
6432
- const t = textOf7(config.locale);
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 = textOf7(locale);
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}: ` : ""}${textOf7(locale).top(labels?.[best.name] ?? best.name, formatValue(best.value / model.total, "percent", locale))}`;
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 NO_ROWS15 = [];
8312
+ var NO_ROWS17 = [];
6553
8313
  function TreemapImpl({
6554
- data = NO_ROWS15,
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 : NO_ROWS15;
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 ?? textOf7(locale).chart(labels?.[value] ?? value ?? "");
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 TEXT18 = {
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 = () => TEXT18[uiLanguage(useLocale())];
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 NO_ROWS16 = [];
8512
+ var NO_ROWS18 = [];
6753
8513
  function DataTable({
6754
- columns = NO_ROWS16,
6755
- data = NO_ROWS16,
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 = TEXT18[uiLanguage(locale)];
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((cell) => {
7067
- const meta = cell.column.columnDef.meta;
7068
- const comparisonColumn = comparisonOf.get(cell.column.id);
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(cell.column.id),
7075
- isHost: comparisonOf.has(cell.column.id)
8834
+ isComparison: comparisonIds.has(cell2.column.id),
8835
+ isHost: comparisonOf.has(cell2.column.id)
7076
8836
  }),
7077
8837
  children: [
7078
- flexRender(cell.column.columnDef.cell, cell.getContext()),
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
- cell.id
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 = (cell, guard) => {
7229
- let text = cell === null || cell === void 0 ? "" : String(cell);
7230
- if (guard && typeof cell === "string" && /^[=+\-@]/.test(text) && !SIGNED_NUMBER.test(text)) {
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((cell) => field(cell, guardFormulas)).join(","))
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 ?? TEXT18[uiLanguage(locale)].exportCsv
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 TEXT19 = {
9131
+ var TEXT24 = {
7372
9132
  ja: { table: "\u30D4\u30DC\u30C3\u30C8\u8868" },
7373
9133
  en: { table: "Pivot table" }
7374
9134
  };
7375
- var NO_ROWS17 = [];
9135
+ var NO_ROWS19 = [];
7376
9136
  var asList = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
7377
9137
  function PivotTable({
7378
- data = NO_ROWS17,
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 = TEXT19[uiLanguage(resolveLocale(locale))];
7397
- const dataRows = Array.isArray(data) ? data : NO_ROWS17;
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 TEXT20 = {
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 = () => TEXT20[uiLanguage(useLocale())];
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 TEXT21 = {
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 toDate2 = (unit) => () => {
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: toDate2("quarter") },
9615
+ { label: t.thisQuarter, getValue: toDate3("quarter") },
7856
9616
  { label: t.lastQuarter, getValue: previous("quarter") },
7857
- { label: t.thisFiscalYear, getValue: toDate2("year") },
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 = TEXT21[uiLanguage(locale)];
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 TEXT22 = {
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 = TEXT22[uiLanguage(useLocale())];
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 TEXT23 = {
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 NO_VALUES = [];
9955
+ var NO_VALUES2 = [];
8196
9956
  var MultiSelect = forwardRef(function MultiSelect2({
8197
9957
  options = NO_OPTIONS3,
8198
- value = NO_VALUES,
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 = TEXT23[uiLanguage(useLocale())];
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 DAY_MS = 24 * 60 * 60 * 1e3;
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)) / DAY_MS;
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 TEXT24 = {
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 = TEXT24[uiLanguage(locale)];
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 TEXT25 = {
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 = TEXT25[uiLanguage(useLocale())];
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-NYQJ5UY4.js.map
9028
- //# sourceMappingURL=chunk-NYQJ5UY4.js.map
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