@squadbase/vantage 0.7.0 → 0.7.1-dev1.5e06644

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 (73) hide show
  1. package/README.md +1 -1
  2. package/dist/add-AU3EDPNW.js +6 -0
  3. package/dist/add-AU3EDPNW.js.map +1 -0
  4. package/dist/{chunk-AABMKHEU.js → chunk-35B3YIBF.js} +16 -7
  5. package/dist/chunk-35B3YIBF.js.map +1 -0
  6. package/dist/{chunk-TRMHNMMZ.js → chunk-LYUGDHSF.js} +3 -3
  7. package/dist/{chunk-TRMHNMMZ.js.map → chunk-LYUGDHSF.js.map} +1 -1
  8. package/dist/{chunk-QNOX7WLZ.js → chunk-MQUIAP66.js} +69 -4
  9. package/dist/chunk-MQUIAP66.js.map +1 -0
  10. package/dist/{chunk-2IAPIOPS.js → chunk-P2KIHF65.js} +2 -2
  11. package/dist/chunk-P2KIHF65.js.map +1 -0
  12. package/dist/{chunk-3RJEOP3J.js → chunk-XRKSIC5Z.js} +5 -3
  13. package/dist/chunk-XRKSIC5Z.js.map +1 -0
  14. package/dist/{chunk-77CISBMG.js → chunk-YJQCB3UP.js} +3387 -204
  15. package/dist/chunk-YJQCB3UP.js.map +1 -0
  16. package/dist/cli.js +2 -2
  17. package/dist/components/index.d.ts +627 -7
  18. package/dist/components/index.js +4 -4
  19. package/dist/{delta-text-CbrOaW83.d.ts → delta-text-tav2Lh5d.d.ts} +1 -1
  20. package/dist/doc/index.d.ts +2 -2
  21. package/dist/doc/index.js +4 -4
  22. package/dist/{format-DihQkL1N.d.ts → format-D34piCei.d.ts} +2 -1
  23. package/dist/geo-japan-7BMSOJRX.js +8 -0
  24. package/dist/geo-japan-7BMSOJRX.js.map +1 -0
  25. package/dist/geo-us-GVOG7VXH.js +8 -0
  26. package/dist/geo-us-GVOG7VXH.js.map +1 -0
  27. package/dist/geo-world-35HL56UU.js +8 -0
  28. package/dist/geo-world-35HL56UU.js.map +1 -0
  29. package/dist/slide/index.d.ts +2 -2
  30. package/dist/slide/index.js +3 -3
  31. package/dist/table/index.js +4 -5
  32. package/dist/table/index.js.map +1 -1
  33. package/dist/ui/index.js +2 -3
  34. package/dist/ui/index.js.map +1 -1
  35. package/dist/{upgrade-6DT7ADRP.js → upgrade-MCHMELWC.js} +3 -3
  36. package/dist/{upgrade-6DT7ADRP.js.map → upgrade-MCHMELWC.js.map} +1 -1
  37. package/docs/en/agent-skills.md +13 -14
  38. package/docs/en/changelog.md +8 -0
  39. package/docs/en/parts/draft-chart.md +42 -0
  40. package/docs/en/parts/page-shell.md +1 -1
  41. package/docs/index.json +70 -50
  42. package/docs/ja/agent-skills.md +14 -14
  43. package/docs/ja/changelog.md +8 -0
  44. package/docs/ja/parts/draft-chart.md +40 -0
  45. package/docs/ja/parts/page-shell.md +1 -1
  46. package/package.json +2 -2
  47. package/registry/parts.json +5221 -0
  48. package/registry/ui/chart-frame.tsx +8 -0
  49. package/registry/ui/combo-chart.tsx +1852 -0
  50. package/registry/ui/dashboard-card.tsx +3 -1
  51. package/registry/ui/data-table.tsx +3 -1
  52. package/registry/ui/delta.tsx +3 -1
  53. package/registry/ui/filter-bar.tsx +3 -1
  54. package/registry/ui/forecast-chart.tsx +4734 -0
  55. package/registry/ui/funnel-steps.tsx +1 -1
  56. package/registry/ui/kpi-card.tsx +3 -1
  57. package/registry/ui/metric-value.tsx +2 -2
  58. package/registry/ui/page-shell.tsx +25 -4
  59. package/registry/ui/paired-chart.tsx +1 -1
  60. package/registry/ui/pivot-table.tsx +1260 -0
  61. package/registry/ui/progress-circle.tsx +2 -2
  62. package/registry/ui/sparkline.tsx +1 -1
  63. package/registry/ui/treemap.tsx +1917 -0
  64. package/templates/AGENTS.md +1 -1
  65. package/dist/add-4GHF2TX2.js +0 -6
  66. package/dist/add-4GHF2TX2.js.map +0 -1
  67. package/dist/chunk-2IAPIOPS.js.map +0 -1
  68. package/dist/chunk-3RJEOP3J.js.map +0 -1
  69. package/dist/chunk-77CISBMG.js.map +0 -1
  70. package/dist/chunk-AABMKHEU.js.map +0 -1
  71. package/dist/chunk-NZ5QIIG4.js +0 -74
  72. package/dist/chunk-NZ5QIIG4.js.map +0 -1
  73. package/dist/chunk-QNOX7WLZ.js.map +0 -1
@@ -1,19 +1,19 @@
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';
11
- import { use } from 'echarts/core';
12
- import { GraphicComponent, VisualMapComponent } from 'echarts/components';
13
- import { ScatterChart as ScatterChart$1, HeatmapChart } from 'echarts/charts';
11
+ import { use, registerMap } from 'echarts/core';
12
+ import { GraphicComponent, VisualMapComponent, GeoComponent } from 'echarts/components';
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;
@@ -2642,12 +2650,12 @@ function AreaChartImpl({
2642
2650
  provisionalFrom,
2643
2651
  provisionalLabel,
2644
2652
  isLoading,
2645
- loading,
2653
+ loading: loading2,
2646
2654
  emptyState,
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,
@@ -2803,7 +2811,7 @@ function AreaChartImpl({
2803
2811
  ref: frameRef,
2804
2812
  title,
2805
2813
  summary: resolvedSummary,
2806
- isLoading: isLoading ?? loading ?? false,
2814
+ isLoading: isLoading ?? loading2 ?? false,
2807
2815
  isEmpty: data.length === 0,
2808
2816
  emptyState,
2809
2817
  height,
@@ -2837,7 +2845,7 @@ function BarChartImpl({
2837
2845
  provisionalFrom,
2838
2846
  provisionalLabel,
2839
2847
  isLoading,
2840
- loading,
2848
+ loading: loading2,
2841
2849
  emptyState,
2842
2850
  height,
2843
2851
  chartOptions,
@@ -2993,7 +3001,7 @@ function BarChartImpl({
2993
3001
  ref: frameRef,
2994
3002
  title,
2995
3003
  summary: resolvedSummary,
2996
- isLoading: isLoading ?? loading ?? false,
3004
+ isLoading: isLoading ?? loading2 ?? false,
2997
3005
  isEmpty: data.length === 0,
2998
3006
  emptyState,
2999
3007
  height,
@@ -3027,12 +3035,12 @@ function LineChartImpl({
3027
3035
  provisionalFrom,
3028
3036
  provisionalLabel,
3029
3037
  isLoading,
3030
- loading,
3038
+ loading: loading2,
3031
3039
  emptyState,
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,
@@ -3190,7 +3198,7 @@ function LineChartImpl({
3190
3198
  ref: frameRef,
3191
3199
  title,
3192
3200
  summary: resolvedSummary,
3193
- isLoading: isLoading ?? loading ?? false,
3201
+ isLoading: isLoading ?? loading2 ?? false,
3194
3202
  isEmpty: data.length === 0,
3195
3203
  emptyState,
3196
3204
  height,
@@ -3234,7 +3242,7 @@ function DonutChartImpl({
3234
3242
  actions,
3235
3243
  fileName,
3236
3244
  isLoading,
3237
- loading,
3245
+ loading: loading2,
3238
3246
  emptyState,
3239
3247
  height,
3240
3248
  chartOptions,
@@ -3328,7 +3336,7 @@ function DonutChartImpl({
3328
3336
  ref: frameRef,
3329
3337
  title,
3330
3338
  summary: resolvedSummary,
3331
- isLoading: isLoading ?? loading ?? false,
3339
+ isLoading: isLoading ?? loading2 ?? false,
3332
3340
  isEmpty: data.length === 0,
3333
3341
  emptyState,
3334
3342
  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}: ` : "";
@@ -5348,6 +5356,3064 @@ function HeatmapLegend({
5348
5356
  var Heatmap = forwardRef(HeatmapImpl);
5349
5357
  Heatmap.displayName = "Heatmap";
5350
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";
6413
+ function niceStep2(raw) {
6414
+ if (!(raw > 0) || !Number.isFinite(raw)) return 1;
6415
+ const exp10 = 10 ** Math.floor(Math.log10(raw));
6416
+ const f = raw / exp10;
6417
+ return (f < 1.5 ? 1 : f < 2.5 ? 2 : f < 4 ? 3 : f < 7 ? 5 : 10) * exp10;
6418
+ }
6419
+ var round = (n) => Number(n.toPrecision(12));
6420
+ function comboAxisScale(lo, hi, splitNumber, ticks) {
6421
+ let low = Math.min(0, Number.isFinite(lo) ? lo : 0);
6422
+ let high = Math.max(0, Number.isFinite(hi) ? hi : 0);
6423
+ if (high <= low) high = low + 1;
6424
+ let step = niceStep2((high - low) / Math.max(1, splitNumber));
6425
+ for (let attempt = 0; ; attempt++) {
6426
+ const min = round(Math.floor(low / step) * step);
6427
+ const max = round(Math.ceil(high / step) * step);
6428
+ const tick = ticks(Math.max(Math.abs(min), Math.abs(max)));
6429
+ const count = Math.round((max - min) / step);
6430
+ const labels = Array.from({ length: count + 1 }, (_, i) => tick(round(min + i * step)));
6431
+ if (new Set(labels).size === labels.length || attempt >= 6) return { min, max, interval: step, tick };
6432
+ step = niceStep2(step * 2);
6433
+ }
6434
+ }
6435
+ var DEFAULT_CHART_HEIGHT2 = 288;
6436
+ var splitCountFor = (height) => height < 200 ? 3 : height < 300 ? 4 : 5;
6437
+ function escapeHtml3(text) {
6438
+ return text.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
6439
+ }
6440
+ var TEXT18 = {
6441
+ ja: { item: "\u9805\u76EE", chart: "\u8907\u5408\u30B0\u30E9\u30D5" },
6442
+ en: { item: "Item", chart: "Combination chart" }
6443
+ };
6444
+ var textOf6 = (locale) => TEXT18[uiLanguage(resolveLocale(locale))];
6445
+ var axisOf = (s) => s.axis === "right" ? "right" : "left";
6446
+ function comboSeriesList(series) {
6447
+ if (!Array.isArray(series)) return [];
6448
+ return series.filter(
6449
+ (s) => !!s && typeof s === "object" && typeof s.key === "string" && ["bar", "line", "area"].includes(s.type)
6450
+ );
6451
+ }
6452
+ function buildComboChartOption(config) {
6453
+ const { data, index, labels, formatters } = config;
6454
+ const series = comboSeriesList(config.series);
6455
+ const label2 = (key) => labels?.[key] ?? key;
6456
+ const seriesName = (s) => s.label ?? label2(s.key);
6457
+ const vertical = config.layout === "vertical";
6458
+ const categories = data.map((row) => String(row?.[index] ?? ""));
6459
+ const values = series.map((s) => data.map((row) => toChartNumber(row?.[s.key])));
6460
+ const hasRight = series.some((s) => axisOf(s) === "right");
6461
+ const axes = hasRight ? ["left", "right"] : ["left"];
6462
+ const extent = (axis) => {
6463
+ let [lo, hi] = [0, 0];
6464
+ const add = (v) => {
6465
+ if (v !== null && Number.isFinite(v)) [lo, hi] = [Math.min(lo, v), Math.max(hi, v)];
6466
+ };
6467
+ const stacks = /* @__PURE__ */ new Map();
6468
+ series.forEach((s, i) => {
6469
+ if (axisOf(s) !== axis) return;
6470
+ if (config.stacked && s.type !== "line") {
6471
+ const stack = stacks.get(s.type) ?? { pos: data.map(() => 0), neg: data.map(() => 0) };
6472
+ values[i].forEach((v, j) => {
6473
+ if (v === null) return;
6474
+ if (v >= 0) stack.pos[j] += v;
6475
+ else stack.neg[j] += v;
6476
+ });
6477
+ stacks.set(s.type, stack);
6478
+ } else values[i].forEach(add);
6479
+ });
6480
+ for (const stack of stacks.values()) [...stack.pos, ...stack.neg].forEach(add);
6481
+ for (const ref of config.referenceLines ?? []) if (axisOf(ref) === axis) add(toChartNumber(ref.value));
6482
+ return [lo, hi];
6483
+ };
6484
+ const split = splitCountFor(config.plotHeight ?? DEFAULT_CHART_HEIGHT2);
6485
+ const scales = Object.fromEntries(axes.map((axis) => [axis, comboAxisScale(...extent(axis), split, config.ticks[axis])]));
6486
+ const valueAxes = axes.map((axis) => ({
6487
+ type: "value",
6488
+ position: vertical ? axis === "left" ? "bottom" : "top" : axis,
6489
+ min: scales[axis].min,
6490
+ max: scales[axis].max,
6491
+ interval: scales[axis].interval,
6492
+ axisLine: { show: false },
6493
+ axisTick: { show: false },
6494
+ splitLine: { show: axis === "left" },
6495
+ axisLabel: { formatter: (v) => scales[axis].tick(v), hideOverlap: vertical ? true : void 0 }
6496
+ }));
6497
+ const categoryAxis = {
6498
+ type: "category",
6499
+ data: categories,
6500
+ inverse: vertical,
6501
+ axisTick: { show: false },
6502
+ axisLabel: { formatter: (v) => label2(v), hideOverlap: true }
6503
+ };
6504
+ const axisIndex = (s) => axisOf(s) === "right" ? 1 : 0;
6505
+ const drawn = series.map((s, i) => {
6506
+ const color = config.palette[i] || void 0;
6507
+ const common = {
6508
+ id: `series-${i}`,
6509
+ name: seriesName(s),
6510
+ data: values[i],
6511
+ [vertical ? "xAxisIndex" : "yAxisIndex"]: axisIndex(s),
6512
+ emphasis: { focus: "none" }
6513
+ };
6514
+ if (s.type === "bar")
6515
+ return {
6516
+ ...common,
6517
+ type: "bar",
6518
+ stack: config.stacked ? `bar-${axisOf(s)}` : void 0,
6519
+ barMaxWidth: 40,
6520
+ itemStyle: { color, borderRadius: vertical ? [0, 2, 2, 0] : [2, 2, 0, 0] }
6521
+ };
6522
+ return {
6523
+ ...common,
6524
+ type: "line",
6525
+ stack: config.stacked && s.type === "area" ? `area-${axisOf(s)}` : void 0,
6526
+ symbol: "circle",
6527
+ symbolSize: 6,
6528
+ showSymbol: data.length <= 24,
6529
+ connectNulls: false,
6530
+ lineStyle: { width: 2, color },
6531
+ itemStyle: { color },
6532
+ areaStyle: s.type === "area" ? { color, opacity: 0.18 } : void 0,
6533
+ z: 3
6534
+ };
6535
+ });
6536
+ const references = axes.flatMap((axis) => {
6537
+ const lines = (config.referenceLines ?? []).filter((r) => axisOf(r) === axis && toChartNumber(r.value) !== null);
6538
+ if (lines.length === 0) return [];
6539
+ return [
6540
+ {
6541
+ id: `reference-${axis}`,
6542
+ type: "line",
6543
+ data: data.map(() => null),
6544
+ [vertical ? "xAxisIndex" : "yAxisIndex"]: axis === "right" ? 1 : 0,
6545
+ silent: true,
6546
+ symbol: "none",
6547
+ tooltip: { show: false },
6548
+ markLine: {
6549
+ silent: true,
6550
+ symbol: "none",
6551
+ lineStyle: { type: "dashed", color: config.referenceColor || void 0, width: 1 },
6552
+ label: { position: "insideEndTop", color: config.referenceColor || void 0 },
6553
+ data: lines.map((r) => ({
6554
+ [vertical ? "xAxis" : "yAxis"]: toChartNumber(r.value),
6555
+ label: { formatter: r.label ?? config.formatters[axis](toChartNumber(r.value)) }
6556
+ }))
6557
+ }
6558
+ }
6559
+ ];
6560
+ });
6561
+ const showLegend = (config.showLegend ?? true) && series.length > 1;
6562
+ const tooltip = (params) => {
6563
+ const items = Array.isArray(params) ? params : [params];
6564
+ const first = items[0];
6565
+ if (!first) return "";
6566
+ const head = escapeHtml3(label2(categories[first.dataIndex] ?? ""));
6567
+ const lines = items.filter((p) => p.seriesIndex < series.length).map((p) => {
6568
+ const s = series[p.seriesIndex];
6569
+ const v = values[p.seriesIndex][p.dataIndex];
6570
+ return `${p.marker ?? ""}${escapeHtml3(seriesName(s))} ${v === null || v === void 0 ? EMPTY_VALUE : escapeHtml3(formatters[axisOf(s)](v))}`;
6571
+ });
6572
+ return [head, ...lines].join("<br/>");
6573
+ };
6574
+ const option = {
6575
+ animation: false,
6576
+ legend: { show: showLegend, top: 0, left: 0, data: series.map(seriesName) },
6577
+ tooltip: config.showTooltip === false ? { show: false } : { trigger: "axis", axisPointer: { type: "shadow" }, formatter: tooltip },
6578
+ grid: { left: 8, right: 8, top: showLegend ? 36 : 12, bottom: 8, containLabel: true },
6579
+ xAxis: vertical ? valueAxes : categoryAxis,
6580
+ yAxis: vertical ? categoryAxis : valueAxes,
6581
+ series: [...drawn, ...references]
6582
+ };
6583
+ return config.chartOptions ? mergeDeep2(option, config.chartOptions) : option;
6584
+ }
6585
+ function mergeDeep2(a, b) {
6586
+ const out = { ...a };
6587
+ for (const [k, v] of Object.entries(b)) {
6588
+ const cur = out[k];
6589
+ out[k] = v && cur && typeof v === "object" && typeof cur === "object" && !Array.isArray(v) && !Array.isArray(cur) ? mergeDeep2(cur, v) : v;
6590
+ }
6591
+ return out;
6592
+ }
6593
+ function comboChartDataTable(data, index, series, formatters, labels, locale) {
6594
+ const list = comboSeriesList(series);
6595
+ const label2 = (key) => labels?.[key] ?? key;
6596
+ return {
6597
+ columns: [labels?.[index] ?? textOf6(locale).item, ...list.map((s) => s.label ?? label2(s.key))],
6598
+ rows: data.map((row) => [
6599
+ label2(String(row?.[index] ?? "")),
6600
+ ...list.map((s) => {
6601
+ const n = toChartNumber(row?.[s.key]);
6602
+ return n === null ? EMPTY_VALUE : formatters[axisOf(s)](n);
6603
+ })
6604
+ ])
6605
+ };
6606
+ }
6607
+ var NO_ROWS13 = [];
6608
+ function ComboChartImpl({
6609
+ data = NO_ROWS13,
6610
+ index,
6611
+ series = NO_ROWS13,
6612
+ format,
6613
+ rightFormat,
6614
+ labels,
6615
+ referenceLines,
6616
+ stacked = false,
6617
+ layout = "horizontal",
6618
+ showLegend = true,
6619
+ showTooltip = true,
6620
+ onSelect,
6621
+ title,
6622
+ summary,
6623
+ isLoading,
6624
+ emptyState,
6625
+ height,
6626
+ chartOptions,
6627
+ actions,
6628
+ fileName,
6629
+ className,
6630
+ ariaLabel,
6631
+ ...rest
6632
+ }, ref) {
6633
+ const rows = Array.isArray(data) ? data : NO_ROWS13;
6634
+ const list = useMemo(() => comboSeriesList(series), [series]);
6635
+ const { ref: frameRef, tokens } = useChartSurface(ref);
6636
+ const locale = useLocale();
6637
+ const formatters = useMemo(
6638
+ () => ({ left: resolveValueFormatter(void 0, format, locale), right: resolveValueFormatter(void 0, rightFormat ?? format, locale) }),
6639
+ [format, rightFormat, locale]
6640
+ );
6641
+ const ticks = useMemo(
6642
+ () => ({ left: resolveAxisTickFormatter(void 0, format, locale), right: resolveAxisTickFormatter(void 0, rightFormat ?? format, locale) }),
6643
+ [format, rightFormat, locale]
6644
+ );
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: (source) => source ? `\u4E88\u6E2C\u306F\u6307\u6570\u5E73\u6ED1\u6CD5\u306B\u3088\u308B\u8FD1\u4F3C\u5024\u3067\u3059\u3002${source} \u306E\u4E88\u6E2C\u5024\u3068\u306F\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002` : "\u4E88\u6E2C\u306F\u6307\u6570\u5E73\u6ED1\u6CD5\u306B\u3088\u308B\u8FD1\u4F3C\u5024\u3067\u3059\u3002\u5143\u306E\u30C4\u30FC\u30EB\u306E\u4E88\u6E2C\u5024\u3068\u306F\u4E00\u81F4\u3057\u307E\u305B\u3093\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: (source) => `Forecast is an approximation (exponential smoothing); values do not match ${source ? `${source}'s` : "the source tool's"} forecast.`,
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
+ forecastSource,
7137
+ forecastNote,
7138
+ colors,
7139
+ labels,
7140
+ valueFormatter,
7141
+ format,
7142
+ title,
7143
+ summary,
7144
+ actions,
7145
+ fileName,
7146
+ isLoading,
7147
+ emptyState,
7148
+ height,
7149
+ chartOptions,
7150
+ showLegend = true,
7151
+ showTooltip = true,
7152
+ showGridLines = true,
7153
+ showXAxis = true,
7154
+ showYAxis = true,
7155
+ yAxisWidth,
7156
+ minValue,
7157
+ maxValue,
7158
+ fitToData = false,
7159
+ xAxisLabel,
7160
+ yAxisLabel,
7161
+ ariaLabel,
7162
+ className,
7163
+ ...rest
7164
+ }, ref) {
7165
+ const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
7166
+ const locale = useLocale();
7167
+ const t = TEXT19[uiLanguage(locale)];
7168
+ const fcLabel = forecastLabel ?? t.forecast;
7169
+ const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
7170
+ const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
7171
+ const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
7172
+ const singleName = labels?.[y] ?? y ?? "";
7173
+ const model = useMemo(
7174
+ () => buildForecastModel(data, x, y, seriesKey, period, forecast2, singleName, otherSeriesLabel(locale)),
7175
+ // forecast はオブジェクトリテラルで渡されることが多いので中身で比べる
7176
+ [data, x, y, seriesKey, period, JSON.stringify(forecast2 ?? null), singleName, locale]
7177
+ );
7178
+ const palette = useMemo(
7179
+ () => model ? resolveChartColors(seriesColorsFor(model.names, colors, CHART_OTHER_COLOR, model.otherName), tokens) : [],
7180
+ [model, colors, tokens]
7181
+ );
7182
+ const option = useMemo(() => {
7183
+ if (!model) return null;
7184
+ const index = "__period";
7185
+ const rows = model.labels.map((label3, i) => {
7186
+ const row = { [index]: label3 };
7187
+ model.names.forEach((name, c) => row[name] = model.actual[c][i]);
7188
+ return row;
7189
+ });
7190
+ const base = buildCartesianOption({
7191
+ kind: "line",
7192
+ data: rows,
7193
+ index,
7194
+ categories: model.names,
7195
+ palette,
7196
+ valueFormatter: tooltipFormatter,
7197
+ axisFormatter,
7198
+ axisTicks,
7199
+ curveType: "linear",
7200
+ connectNulls: false,
7201
+ showLegend,
7202
+ showTooltip,
7203
+ showGridLines,
7204
+ showXAxis,
7205
+ showYAxis,
7206
+ startEndOnly: false,
7207
+ yAxisWidth,
7208
+ minValue,
7209
+ maxValue,
7210
+ fitToData,
7211
+ allowDecimals: true,
7212
+ xAxisLabel,
7213
+ yAxisLabel,
7214
+ showDots: false,
7215
+ active: null,
7216
+ highlight: "none",
7217
+ reserveActions: Boolean(actions),
7218
+ guideColor: tokens?.mutedForeground ?? void 0,
7219
+ labelBackground: surface,
7220
+ labelColor: tokens?.foreground ?? void 0,
7221
+ plotWidth,
7222
+ plotHeight: typeof height === "number" ? height : void 0,
7223
+ locale
7224
+ });
7225
+ const bandAlpha = isDarkSurface(surface) ? FORECAST_BAND_ALPHA_DARK : FORECAST_BAND_ALPHA_LIGHT;
7226
+ const helper = {
7227
+ type: "line",
7228
+ symbol: "none",
7229
+ showSymbol: false,
7230
+ connectNulls: true,
7231
+ legendHoverLink: false,
7232
+ emphasis: { disabled: true }
7233
+ };
7234
+ const lines = [];
7235
+ const bands = [];
7236
+ model.names.forEach((name, c) => {
7237
+ const start = model.fittedEnd[c];
7238
+ if (start < 0) return;
7239
+ const color = palette[c] || void 0;
7240
+ const predicted = model.predicted[c];
7241
+ const startValue = model.actual[c][start] ?? null;
7242
+ const line = predicted.map((p, i) => i === start ? startValue : p?.value ?? null);
7243
+ const lower = predicted.map((p, i) => i === start ? startValue : p ? Math.min(p.lower, p.upper) : null);
7244
+ const range = predicted.map((p, i) => i === start ? startValue === null ? null : 0 : p ? Math.abs(p.upper - p.lower) : null);
7245
+ lines.push({
7246
+ ...helper,
7247
+ id: FORECAST_ID + name,
7248
+ name: fcLabel,
7249
+ z: 3,
7250
+ lineStyle: { width: 2, type: FORECAST_LINE_DASH, color, opacity: 0.7 },
7251
+ itemStyle: { color, opacity: 0.7 },
7252
+ data: line
7253
+ });
7254
+ bands.push(
7255
+ { ...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 },
7256
+ {
7257
+ ...helper,
7258
+ id: BAND_RANGE_ID + name,
7259
+ name: fcLabel,
7260
+ silent: true,
7261
+ z: 1,
7262
+ stack: BAND_BASE_ID + name,
7263
+ tooltip: { show: false },
7264
+ lineStyle: { opacity: 0 },
7265
+ itemStyle: { color },
7266
+ areaStyle: color ? { color: withAlpha(color, bandAlpha), opacity: 1 } : { opacity: bandAlpha },
7267
+ data: range
7268
+ }
7269
+ );
7270
+ });
7271
+ if (lines.length === 0) return mergeChartOptions(base, chartOptions);
7272
+ const boundary = Math.max(...model.fittedEnd);
7273
+ const total = model.labels.length;
7274
+ const span = plotWidth && total > 1 ? (plotWidth - 64) / (total - 1) * (total - 1 - boundary) : null;
7275
+ const boundaryText = forecastBoundaryText(fcLabel);
7276
+ lines[0] = {
7277
+ ...lines[0],
7278
+ markLine: {
7279
+ silent: true,
7280
+ symbol: "none",
7281
+ animation: false,
7282
+ data: [
7283
+ {
7284
+ name: "forecast-boundary",
7285
+ xAxis: boundary,
7286
+ lineStyle: { type: "dashed", width: 1, color: tokens?.mutedForeground ?? void 0 },
7287
+ label: {
7288
+ show: true,
7289
+ position: "end",
7290
+ rotate: 0,
7291
+ align: forecastLabelAlign(span, boundaryText),
7292
+ verticalAlign: "bottom",
7293
+ distance: 4,
7294
+ fontSize: 12,
7295
+ color: tokens?.mutedForeground ?? void 0,
7296
+ formatter: boundaryText
7297
+ }
7298
+ }
7299
+ ]
7300
+ }
7301
+ };
7302
+ const legend = base.legend;
7303
+ const grid = base.grid;
7304
+ const times = timeTooltipLabels(model.labels, locale);
7305
+ const pct = `${Math.round((forecast2?.confidence && forecast2.confidence > 0 && forecast2.confidence < 1 ? forecast2.confidence : 0.95) * 100)}%`;
7306
+ const option2 = {
7307
+ ...base,
7308
+ legend: legend ? { ...legend, data: [...legend.data ?? [], { name: fcLabel, icon: LEGEND_DASHED_ICON }] } : legend,
7309
+ grid: grid ? { ...grid, top: (grid.top ?? 12) + BOUNDARY_LABEL_ROOM } : grid,
7310
+ tooltip: {
7311
+ ...base.tooltip,
7312
+ formatter: (params) => {
7313
+ const list = Array.isArray(params) ? params : [params];
7314
+ const i = list[0]?.dataIndex ?? 0;
7315
+ const shown = new Set(list.map((p) => p.seriesId ?? ""));
7316
+ const visible = (id) => list.length === 0 || shown.has(id);
7317
+ const rows2 = [];
7318
+ model.names.forEach((name, c) => {
7319
+ const color = palette[c] || "currentColor";
7320
+ const value = model.actual[c][i] ?? null;
7321
+ if (value !== null && visible(`series:${name}`)) rows2.push({ name, color, value });
7322
+ const p = model.predicted[c][i];
7323
+ if (p && visible(FORECAST_ID + name)) {
7324
+ rows2.push({
7325
+ name: model.names.length > 1 ? `${name} \xB7 ${fcLabel}` : fcLabel,
7326
+ color,
7327
+ value: p.value,
7328
+ note: t.interval(pct, tooltipFormatter(Math.min(p.lower, p.upper)), tooltipFormatter(Math.max(p.lower, p.upper)))
7329
+ });
7330
+ }
7331
+ });
7332
+ return tooltipHtml(times?.[i] ?? model.labels[i] ?? "", rows2, tooltipFormatter, [], locale);
7333
+ }
7334
+ },
7335
+ series: [...base.series ?? [], ...lines, ...bands]
7336
+ };
7337
+ return mergeChartOptions(option2, chartOptions);
7338
+ }, [
7339
+ model,
7340
+ palette,
7341
+ tooltipFormatter,
7342
+ axisFormatter,
7343
+ axisTicks,
7344
+ showLegend,
7345
+ showTooltip,
7346
+ showGridLines,
7347
+ showXAxis,
7348
+ showYAxis,
7349
+ yAxisWidth,
7350
+ minValue,
7351
+ maxValue,
7352
+ fitToData,
7353
+ xAxisLabel,
7354
+ yAxisLabel,
7355
+ actions,
7356
+ tokens,
7357
+ surface,
7358
+ plotWidth,
7359
+ height,
7360
+ locale,
7361
+ fcLabel,
7362
+ forecast2?.confidence,
7363
+ t,
7364
+ chartOptions
7365
+ ]);
7366
+ const dataTable = useMemo(() => {
7367
+ if (!model) return void 0;
7368
+ const forecastColumns = model.names.map((name) => `${name} (${fcLabel})`);
7369
+ const rows = model.labels.map((label3, i) => {
7370
+ const row = { period: label3 };
7371
+ model.names.forEach((name, c) => {
7372
+ row[name] = model.actual[c][i];
7373
+ row[forecastColumns[c]] = model.predicted[c][i]?.value ?? null;
7374
+ });
7375
+ return row;
7376
+ });
7377
+ const columns = model.names.flatMap((name, c) => model.fittedEnd[c] >= 0 ? [name, forecastColumns[c]] : [name]);
7378
+ const table = chartDataTable(rows, "period", columns, tooltipFormatter, void 0, t.item);
7379
+ const times = timeTooltipLabels(model.labels, locale);
7380
+ return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
7381
+ }, [model, fcLabel, tooltipFormatter, t, locale]);
7382
+ const label2 = ariaLabel ?? t.chart(model?.names ?? [singleName]);
7383
+ return /* @__PURE__ */ jsx(
7384
+ ChartFrame,
7385
+ {
7386
+ ...chartRootProps(rest),
7387
+ ref: frameRef,
7388
+ title,
7389
+ summary,
7390
+ isLoading: isLoading ?? false,
7391
+ isEmpty: !model || !option,
7392
+ emptyState,
7393
+ height,
7394
+ variant: "line",
7395
+ ariaLabel: label2,
7396
+ className,
7397
+ dataTable,
7398
+ footnote: [t.note(forecastSource), forecastNote].filter(Boolean).join(" "),
7399
+ children: option && /* @__PURE__ */ jsx(EChart, { option, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary } })
7400
+ }
7401
+ );
7402
+ }
7403
+ var ForecastChart = forwardRef(ForecastChartImpl);
7404
+ ForecastChart.displayName = "ForecastChart";
7405
+
7406
+ // ../squadkit/registry/lib/color-ramp.ts
7407
+ var RAMP_FLOOR_SHARE = 0.2;
7408
+ var RAMP_LIGHT_TEXT_FROM = 0.55;
7409
+ function parseRgb2(color) {
7410
+ const hex = /^#([0-9a-f]{6})$/i.exec(color.trim());
7411
+ if (hex) {
7412
+ const n = parseInt(hex[1], 16);
7413
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
7414
+ }
7415
+ const rgb = /^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)/i.exec(color.trim());
7416
+ return rgb ? [Number(rgb[1]), Number(rgb[2]), Number(rgb[3])] : null;
7417
+ }
7418
+ var toLinear2 = (c) => (c /= 255) <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
7419
+ var fromLinear2 = (c) => Math.round(255 * Math.min(1, Math.max(0, c <= 31308e-7 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055)));
7420
+ function toOklab2([r, g, b]) {
7421
+ const [lr, lg, lb] = [toLinear2(r), toLinear2(g), toLinear2(b)];
7422
+ const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);
7423
+ const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);
7424
+ const t = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);
7425
+ return [0.2104542553 * l + 0.793617785 * m - 0.0040720468 * t, 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * t, 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * t];
7426
+ }
7427
+ function fromOklab2([L, a, b]) {
7428
+ const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
7429
+ const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
7430
+ const t = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
7431
+ const rgb = [4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * t, -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * t, -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * t];
7432
+ return `rgb(${rgb.map(fromLinear2).join(", ")})`;
7433
+ }
7434
+ function withAlpha3(color, alpha) {
7435
+ const c = parseRgb2(color);
7436
+ return c ? `rgba(${c[0]}, ${c[1]}, ${c[2]}, ${alpha})` : color;
7437
+ }
7438
+ function mixIntoSurface2(color, surface, share) {
7439
+ const c = parseRgb2(color);
7440
+ const s = surface ? parseRgb2(surface) : null;
7441
+ if (!c || !s) return withAlpha3(color, share);
7442
+ const [c1, c2] = [toOklab2(c), toOklab2(s)];
7443
+ return fromOklab2([0, 1, 2].map((i) => c2[i] + (c1[i] - c2[i]) * share));
7444
+ }
7445
+ function rampRatio(value, min, max) {
7446
+ return max > min ? Math.min(1, Math.max(0, (value - min) / (max - min))) : 1;
7447
+ }
7448
+ function rampColor(color, surface, ratio) {
7449
+ return mixIntoSurface2(color, surface, RAMP_FLOOR_SHARE + (1 - RAMP_FLOOR_SHARE) * Math.min(1, Math.max(0, ratio)));
7450
+ }
7451
+ function rampGradientCss(tone) {
7452
+ return `linear-gradient(to right, color-mix(in oklch, var(--${tone}) ${RAMP_FLOOR_SHARE * 100}%, var(--card)), var(--${tone}))`;
7453
+ }
7454
+ var GEO_MAPS = ["japan", "us", "world"];
7455
+ var geoMapKey = (name) => `squadkit-${name}`;
7456
+ var GEO_ASPECT_SCALE = { japan: 0.8, us: 0.8, world: 0.75 };
7457
+ function fold(text) {
7458
+ return text.normalize("NFKC").normalize("NFD").replace(/[̀-ͯ]/g, "").normalize("NFC").toLowerCase().trim();
7459
+ }
7460
+ var SEPARATORS = /[\s.,'’`"()_\-‐・・]/g;
7461
+ var squash = (text) => text.replace(SEPARATORS, "");
7462
+ function regionKeys(raw) {
7463
+ if (raw === null || raw === void 0) return [];
7464
+ const text = fold(String(raw));
7465
+ if (!text) return [];
7466
+ const keys = [squash(text)];
7467
+ const stripped = text.replace(/[\s-]+(prefecture|pref|ken|fu|to|state)$/, "").replace(/^(state of|the)\s+/, "").replace(/(?<=..)(都|府|県|州)$/, "");
7468
+ if (stripped !== text) keys.push(squash(stripped));
7469
+ if (/^\d{1,2}$/.test(text)) keys.push(`jp${text.padStart(2, "0")}`);
7470
+ return [...new Set(keys.filter(Boolean))];
7471
+ }
7472
+ var ALIASES = {
7473
+ "US-DC": ["District of Columbia", "Washington DC", "Washington, D.C.", "\u30EF\u30B7\u30F3\u30C8\u30F3DC", "\u30B3\u30ED\u30F3\u30D3\u30A2\u7279\u5225\u533A"],
7474
+ USA: ["United States", "US", "USA", "America", "\u7C73\u56FD", "\u30A2\u30E1\u30EA\u30AB"],
7475
+ GBR: ["UK", "Great Britain", "Britain", "\u82F1\u56FD"],
7476
+ KOR: ["Korea", "Republic of Korea", "Korea, Republic of", "\u97D3\u56FD"],
7477
+ PRK: ["DPRK", "\u5317\u671D\u9BAE"],
7478
+ CHN: ["China", "\u4E2D\u56FD"],
7479
+ TWN: ["TW", "\u53F0\u6E7E"],
7480
+ RUS: ["Russian Federation"],
7481
+ CZE: ["Czechia"],
7482
+ VNM: ["Viet Nam"],
7483
+ CIV: ["C\xF4te d'Ivoire"],
7484
+ SWZ: ["Swaziland"],
7485
+ MKD: ["Macedonia"],
7486
+ COD: ["DR Congo", "Congo-Kinshasa"],
7487
+ COG: ["Congo", "Congo-Brazzaville"]
7488
+ };
7489
+ var SKIP_NAME = /* @__PURE__ */ new Set(["US-DC"]);
7490
+ var indexCache = /* @__PURE__ */ new WeakMap();
7491
+ function buildGeoIndex(map, collection) {
7492
+ const cached = indexCache.get(collection);
7493
+ if (cached) return cached;
7494
+ const byKey = /* @__PURE__ */ new Map();
7495
+ const byCode = /* @__PURE__ */ new Map();
7496
+ const add = (key, code) => {
7497
+ for (const k of regionKeys(key)) if (!byKey.has(k)) byKey.set(k, code);
7498
+ };
7499
+ for (const { properties: p } of collection.features) {
7500
+ byCode.set(p.code, p);
7501
+ add(p.code, p.code);
7502
+ const short = p.code.split("-")[1];
7503
+ if (short) add(short, p.code);
7504
+ if (p.alpha2) add(p.alpha2, p.code);
7505
+ if (map === "japan" && short) add(String(Number(short)), p.code);
7506
+ }
7507
+ for (const { properties: p } of collection.features) {
7508
+ if (!SKIP_NAME.has(p.code)) add(p.name, p.code);
7509
+ add(p.name_ja, p.code);
7510
+ for (const alias of ALIASES[p.code] ?? []) add(alias, p.code);
7511
+ }
7512
+ const index = { map, byKey, byCode };
7513
+ indexCache.set(collection, index);
7514
+ return index;
7515
+ }
7516
+ function matchRegion(index, raw) {
7517
+ for (const key of regionKeys(raw)) {
7518
+ const code = index.byKey.get(key);
7519
+ if (code) return code;
7520
+ }
7521
+ return null;
7522
+ }
7523
+ function regionName(properties, language) {
7524
+ return language === "ja" && properties.name_ja ? properties.name_ja : properties.name.replace(/ Prefecture$/, "");
7525
+ }
7526
+ function detectGeoMap(values, loaded2) {
7527
+ const distinct = [...new Set(values.filter((v) => v !== null && v !== void 0 && String(v).trim() !== "").map(String))];
7528
+ let best = null;
7529
+ let bestCount = 0;
7530
+ for (const map of GEO_MAPS) {
7531
+ const collection = loaded2[map];
7532
+ if (!collection) continue;
7533
+ const index = buildGeoIndex(map, collection);
7534
+ const count = distinct.filter((v) => matchRegion(index, v) !== null).length;
7535
+ if (count > bestCount) [best, bestCount] = [map, count];
7536
+ }
7537
+ return best;
7538
+ }
7539
+ var BOUNDS = {
7540
+ japan: [122, 20, 154, 46.5],
7541
+ us: [-180, 18, -65, 72]
7542
+ };
7543
+ function detectBasemap(points) {
7544
+ if (points.length === 0) return "world";
7545
+ for (const map of ["japan", "us"]) {
7546
+ const [w, s, e, n] = BOUNDS[map];
7547
+ if (points.every(([lon, lat]) => lon >= w && lon <= e && lat >= s && lat <= n)) return map;
7548
+ }
7549
+ return "world";
7550
+ }
7551
+ var US_INSETS = [
7552
+ // Alaska (the Aleutians stop short of the antimeridian in this data).
7553
+ { box: [-180, 51, -129.5, 72], center: [-149, 63], to: [-117, 25.5], scale: 0.35 },
7554
+ // Hawaii.
7555
+ { box: [-161, 18.5, -154.5, 22.5], center: [-157.5, 20.5], to: [-106, 25.5], scale: 1 }
7556
+ ];
7557
+ function insetUsPoint(lon, lat) {
7558
+ for (const inset of US_INSETS) {
7559
+ const [w, s, e, n] = inset.box;
7560
+ if (lon >= w && lon <= e && lat >= s && lat <= n) {
7561
+ return [inset.to[0] + (lon - inset.center[0]) * inset.scale, inset.to[1] + (lat - inset.center[1]) * inset.scale];
7562
+ }
7563
+ }
7564
+ return [lon, lat];
7565
+ }
7566
+ function insetUs(collection) {
7567
+ const moveRing = (ring) => ring.map(([lon, lat]) => insetUsPoint(lon, lat));
7568
+ return {
7569
+ type: "FeatureCollection",
7570
+ features: collection.features.map((f) => {
7571
+ if (f.properties.code !== "US-AK" && f.properties.code !== "US-HI") return f;
7572
+ const g = f.geometry;
7573
+ const geometry = g.type === "Polygon" ? { type: "Polygon", coordinates: g.coordinates.map(moveRing) } : { type: "MultiPolygon", coordinates: g.coordinates.map((poly) => poly.map(moveRing)) };
7574
+ return { ...f, geometry };
7575
+ })
7576
+ };
7577
+ }
7578
+ var loading = /* @__PURE__ */ new Map();
7579
+ var loaded = /* @__PURE__ */ new Map();
7580
+ function loadedGeoMap(name) {
7581
+ return loaded.get(name);
7582
+ }
7583
+ function loadGeoMap(name) {
7584
+ const pending = loading.get(name);
7585
+ if (pending) return pending;
7586
+ const promise = (name === "japan" ? import('./geo-japan-7BMSOJRX.js').then((m) => m.JAPAN_PREFECTURES) : name === "us" ? import('./geo-us-GVOG7VXH.js').then((m) => insetUs(m.US_STATES)) : import('./geo-world-35HL56UU.js').then((m) => m.WORLD_COUNTRIES)).then((collection) => {
7587
+ registerMap(geoMapKey(name), collection);
7588
+ loaded.set(name, collection);
7589
+ return collection;
7590
+ });
7591
+ promise.catch(() => loading.delete(name));
7592
+ loading.set(name, promise);
7593
+ return promise;
7594
+ }
7595
+ async function loadGeoMapFor(values, map) {
7596
+ if (map !== "auto") return { name: map, collection: await loadGeoMap(map) };
7597
+ const distinct = [...new Set(values.filter((v) => v !== null && v !== void 0).map(String))];
7598
+ const [japan, us] = await Promise.all([loadGeoMap("japan"), loadGeoMap("us")]);
7599
+ const local = { japan, us };
7600
+ const pick = detectGeoMap(distinct, local);
7601
+ if (pick) {
7602
+ const index = buildGeoIndex(pick, local[pick]);
7603
+ const matched = distinct.filter((v) => matchRegion(index, v) !== null).length;
7604
+ if (matched * 2 >= distinct.length) return { name: pick, collection: local[pick] };
7605
+ }
7606
+ const world = await loadGeoMap("world");
7607
+ const name = detectGeoMap(distinct, { ...local, world }) ?? "world";
7608
+ return { name, collection: name === "world" ? world : local[name] };
7609
+ }
7610
+ function useGeoMap(values, map) {
7611
+ const key = useMemo(() => [...new Set(values.map((v) => v === null || v === void 0 ? "" : String(v)))].join("\0"), [values]);
7612
+ const [state, setState] = useState(null);
7613
+ const wanted = `${map}${key}`;
7614
+ useEffect(() => {
7615
+ let alive = true;
7616
+ loadGeoMapFor(key ? key.split("\0") : [], map).then(
7617
+ (result) => alive && setState({ key: wanted, result }),
7618
+ () => {
7619
+ }
7620
+ );
7621
+ return () => {
7622
+ alive = false;
7623
+ };
7624
+ }, [wanted]);
7625
+ if (state?.key === wanted) return state.result;
7626
+ const ready = map !== "auto" ? loadedGeoMap(map) : void 0;
7627
+ return ready && map !== "auto" ? { name: map, collection: ready } : null;
7628
+ }
7629
+ use([MapChart]);
7630
+ function buildFilledMapModel(config) {
7631
+ const { data, region, value, map, collection } = config;
7632
+ const language = uiLanguage(resolveLocale(config.locale));
7633
+ const index = buildGeoIndex(map, collection);
7634
+ const byCode = /* @__PURE__ */ new Map();
7635
+ const unmatched = [];
7636
+ for (const row of data) {
7637
+ if (!row || typeof row !== "object") continue;
7638
+ const code = matchRegion(index, row[region]);
7639
+ if (code) byCode.set(code, row);
7640
+ else unmatched.push(row);
7641
+ }
7642
+ let lo = Infinity;
7643
+ let hi = -Infinity;
7644
+ const regions = collection.features.map(({ properties }) => {
7645
+ const row = byCode.get(properties.code) ?? null;
7646
+ const n = row ? toChartNumber(row[value]) : null;
7647
+ if (n !== null) [lo, hi] = [Math.min(lo, n), Math.max(hi, n)];
7648
+ const key = row ? String(row[region]) : null;
7649
+ return { code: properties.code, key, name: (key !== null ? config.labels?.[key] : void 0) ?? regionName(properties, language), value: n, row };
7650
+ });
7651
+ const min = config.scale?.min ?? (Number.isFinite(lo) ? lo : 0);
7652
+ let max = config.scale?.max ?? (Number.isFinite(hi) ? hi : 1);
7653
+ if (max <= min) max = min + 1;
7654
+ const selectedCodes = config.selected && config.selected.length > 0 ? new Set(config.selected.map((v) => matchRegion(index, v)).filter((c) => c !== null)) : null;
7655
+ return { map, regions, unmatched, selectedCodes, min, max };
7656
+ }
7657
+ function escapeHtml4(text) {
7658
+ return text.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
7659
+ }
7660
+ var TEXT20 = {
7661
+ ja: {
7662
+ join: "\u30FB",
7663
+ region: "\u5730\u57DF",
7664
+ notOnMap: "(\u5730\u56F3\u306B\u7121\u3044)",
7665
+ top: (name, value) => `\u6700\u5927\u306F ${name} \u306E ${value}`,
7666
+ chart: (value) => `${value}\u306E\u5730\u56F3`
7667
+ },
7668
+ en: {
7669
+ join: ", ",
7670
+ region: "Region",
7671
+ notOnMap: " (not on the map)",
7672
+ top: (name, value) => `Highest: ${name} (${value})`,
7673
+ chart: (value) => `Map of ${value}`
7674
+ }
7675
+ };
7676
+ var textOf7 = (locale) => TEXT20[uiLanguage(resolveLocale(locale))];
7677
+ function detailText(raw, formatter) {
7678
+ if (raw === null || raw === void 0 || raw === "") return EMPTY_VALUE;
7679
+ const n = typeof raw === "string" ? null : toChartNumber(raw);
7680
+ return n === null ? String(raw) : formatter(n);
7681
+ }
7682
+ function buildFilledMapOption(config) {
7683
+ const { model, labels, valueFormatter } = config;
7684
+ const t = textOf7(config.locale);
7685
+ const label2 = (key) => labels?.[key] ?? key;
7686
+ const base = config.color || "#6366f1";
7687
+ const border = config.surfaceColor ?? "#ffffff";
7688
+ const dimmed = (r) => model.selectedCodes !== null && !model.selectedCodes.has(r.code);
7689
+ const tooltip = (r) => {
7690
+ const head = `${escapeHtml4(r.name)} ${r.value === null ? EMPTY_VALUE : escapeHtml4(valueFormatter(r.value))}`;
7691
+ const extras = (config.details ?? []).map((key) => `${escapeHtml4(label2(key))} ${escapeHtml4(detailText(r.row?.[key], valueFormatter))}`).join(t.join);
7692
+ return extras ? `${head}${t.join}${extras}` : head;
7693
+ };
7694
+ const option = {
7695
+ animation: false,
7696
+ tooltip: config.showTooltip ? { trigger: "item", formatter: (p) => tooltip(p.data.region) } : { show: false },
7697
+ series: [
7698
+ {
7699
+ id: "regions",
7700
+ type: "map",
7701
+ map: geoMapKey(model.map),
7702
+ nameProperty: "code",
7703
+ aspectScale: GEO_ASPECT_SCALE[model.map],
7704
+ roam: false,
7705
+ selectedMode: false,
7706
+ left: 8,
7707
+ right: 8,
7708
+ top: 8,
7709
+ bottom: 8,
7710
+ label: { show: false },
7711
+ itemStyle: { areaColor: config.emptyColor, borderColor: border, borderWidth: 0.6 },
7712
+ emphasis: { label: { show: false }, itemStyle: { borderColor: config.hoverColor, borderWidth: 1.2 } },
7713
+ data: model.regions.map((r) => {
7714
+ const fill = r.value === null ? config.emptyColor : rampColor(base, config.surfaceColor, rampRatio(r.value, model.min, model.max));
7715
+ const areaColor = dimmed(r) ? mixIntoSurface2(fill, config.surfaceColor, 0.3) : fill;
7716
+ return {
7717
+ name: r.code,
7718
+ value: r.value ?? void 0,
7719
+ region: r,
7720
+ itemStyle: { areaColor },
7721
+ emphasis: { itemStyle: { areaColor } }
7722
+ };
7723
+ })
7724
+ }
7725
+ ]
7726
+ };
7727
+ return config.chartOptions ? mergeDeep3(option, config.chartOptions) : option;
7728
+ }
7729
+ function mergeDeep3(a, b) {
7730
+ const out = { ...a };
7731
+ for (const [k, v] of Object.entries(b)) {
7732
+ const cur = out[k];
7733
+ out[k] = v && cur && typeof v === "object" && typeof cur === "object" && !Array.isArray(v) && !Array.isArray(cur) ? mergeDeep3(cur, v) : v;
7734
+ }
7735
+ return out;
7736
+ }
7737
+ function filledMapDataTable(model, names, formatter, details = [], labels, locale) {
7738
+ const t = textOf7(locale);
7739
+ const label2 = (key) => labels?.[key] ?? key;
7740
+ const cells = (row, value) => [
7741
+ value === null ? EMPTY_VALUE : formatter(value),
7742
+ ...details.map((key) => detailText(row?.[key], formatter))
7743
+ ];
7744
+ const rows = [
7745
+ ...model.regions.filter((r) => r.row !== null).map((r) => [r.name, ...cells(r.row, r.value)]),
7746
+ ...model.unmatched.map((row) => [`${label2(String(row[names.region] ?? EMPTY_VALUE))}${t.notOnMap}`, ...cells(row, toChartNumber(row[names.value]))])
7747
+ ];
7748
+ return { columns: [labels?.[names.region] ?? t.region, label2(names.value), ...details.map(label2)], rows };
7749
+ }
7750
+ function buildFilledMapSummary(model, formatter, title, locale) {
7751
+ let best;
7752
+ for (const r of model.regions) if (r.value !== null && (!best || r.value > best.value)) best = r;
7753
+ if (!best) return void 0;
7754
+ return `${title ? `${title}: ` : ""}${textOf7(locale).top(best.name, formatter(best.value))}`;
7755
+ }
7756
+ function colorsFor2(tokens, tone) {
7757
+ const [color = "", empty = "", hover = ""] = resolveChartColors([tone, "var(--muted)", "var(--foreground)"], tokens);
7758
+ return { color, empty, hover };
7759
+ }
7760
+ var NO_ROWS15 = [];
7761
+ function FilledMapImpl({
7762
+ data = NO_ROWS15,
7763
+ region,
7764
+ value,
7765
+ map = "auto",
7766
+ labels,
7767
+ format,
7768
+ valueFormatter,
7769
+ tone = "chart-1",
7770
+ scale,
7771
+ showLegend = true,
7772
+ showTooltip = true,
7773
+ details,
7774
+ selected,
7775
+ onSelect,
7776
+ title,
7777
+ summary,
7778
+ isLoading,
7779
+ emptyState,
7780
+ height,
7781
+ chartOptions,
7782
+ actions,
7783
+ fileName,
7784
+ className,
7785
+ ariaLabel,
7786
+ ...rest
7787
+ }, ref) {
7788
+ const rows = Array.isArray(data) ? data : NO_ROWS15;
7789
+ const { ref: frameRef, surface, tokens } = useChartSurface(ref);
7790
+ const locale = useLocale();
7791
+ const formatter = useMemo(() => resolveValueFormatter(valueFormatter, format ?? "number", locale), [valueFormatter, format, locale]);
7792
+ const regionValues = useMemo(() => rows.map((row) => row && typeof row === "object" ? row[region] : void 0), [rows, region]);
7793
+ const geo = useGeoMap(regionValues, map);
7794
+ const model = useMemo(
7795
+ () => geo ? buildFilledMapModel({ data: rows, region, value, map: geo.name, collection: geo.collection, scale, labels, selected, locale }) : null,
7796
+ [geo, rows, region, value, scale?.min, scale?.max, labels, selected, locale]
7797
+ );
7798
+ const colors = useMemo(() => colorsFor2(tokens, tone), [tokens, tone]);
7799
+ const option = useMemo(
7800
+ () => model ? buildFilledMapOption({
7801
+ model,
7802
+ color: colors.color,
7803
+ surfaceColor: surface ?? void 0,
7804
+ emptyColor: colors.empty || "rgba(128, 128, 128, 0.15)",
7805
+ hoverColor: colors.hover || "#000000",
7806
+ labels,
7807
+ valueFormatter: formatter,
7808
+ details,
7809
+ showTooltip,
7810
+ chartOptions,
7811
+ locale
7812
+ }) : null,
7813
+ [model, value, colors, surface, labels, formatter, details, showTooltip, chartOptions, locale]
7814
+ );
7815
+ const onEvents = useMemo(
7816
+ () => onSelect ? {
7817
+ click: (params) => {
7818
+ const r = params.data?.region;
7819
+ if (r?.row) onSelect(String(r.row[region]), r.row);
7820
+ }
7821
+ } : void 0,
7822
+ [onSelect, region]
7823
+ );
7824
+ const dataTable = useMemo(
7825
+ () => model ? filledMapDataTable(model, { region, value }, formatter, details, labels, locale) : void 0,
7826
+ [model, region, value, formatter, details, labels, locale]
7827
+ );
7828
+ const resolvedSummary = useMemo(
7829
+ () => summary === "auto" ? model ? buildFilledMapSummary(model, formatter, title, locale) : void 0 : summary,
7830
+ [summary, model, formatter, title, locale]
7831
+ );
7832
+ const label2 = ariaLabel ?? textOf7(locale).chart(labels?.[value] ?? value ?? "");
7833
+ const isEmpty = rows.length === 0;
7834
+ return /* @__PURE__ */ jsx(
7835
+ ChartFrame,
7836
+ {
7837
+ ...chartRootProps(rest),
7838
+ ref: frameRef,
7839
+ title,
7840
+ summary: resolvedSummary,
7841
+ isLoading: (isLoading ?? false) || !isEmpty && !option,
7842
+ isEmpty,
7843
+ emptyState,
7844
+ height,
7845
+ variant: "bar",
7846
+ ariaLabel: label2,
7847
+ className,
7848
+ dataTable,
7849
+ children: /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col gap-2", children: [
7850
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: option && /* @__PURE__ */ jsx(EChart, { option, onEvents, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary: resolvedSummary } }) }),
7851
+ showLegend && model ? /* @__PURE__ */ jsx(RampLegend, { min: model.min, max: model.max, formatter, tone }) : null
7852
+ ] })
7853
+ }
7854
+ );
7855
+ }
7856
+ function RampLegend({ min, max, formatter, tone }) {
7857
+ return /* @__PURE__ */ jsx("div", { "data-slot": "filled-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: [
7858
+ /* @__PURE__ */ jsx("span", { children: formatter(min) }),
7859
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-2 w-24 rounded-sm", style: { backgroundImage: rampGradientCss(tone) } }),
7860
+ /* @__PURE__ */ jsx("span", { children: formatter(max) })
7861
+ ] }) });
7862
+ }
7863
+ var FilledMap = forwardRef(FilledMapImpl);
7864
+ FilledMap.displayName = "FilledMap";
7865
+ use([ScatterChart$1, GeoComponent]);
7866
+ var SYMBOL_MAP_MIN_SIZE = 6;
7867
+ var SYMBOL_MAP_MAX_SIZE = 36;
7868
+ var SYMBOL_MAP_DEFAULT_SIZE = 10;
7869
+ var MAX_CATEGORIES = 5;
7870
+ var isBlank = (v) => v === null || v === void 0 || typeof v === "string" && v.trim() === "";
7871
+ function buildSymbolMapModel(config) {
7872
+ const { data, latitude, longitude, name, size, color } = config;
7873
+ const rows = data.filter((row) => row && typeof row === "object");
7874
+ const colorValues = color ? rows.map((row) => row[color]).filter((v) => !isBlank(v)) : [];
7875
+ const colorMode = !color || colorValues.length === 0 ? "none" : colorValues.every((v) => toChartNumber(v) !== null) ? "numeric" : "category";
7876
+ const points = [];
7877
+ const unplotted = [];
7878
+ const categories = [];
7879
+ let [lo, hi, sizeMax] = [Infinity, -Infinity, 0];
7880
+ for (const row of rows) {
7881
+ const lat = toChartNumber(row[latitude]);
7882
+ const lon = toChartNumber(row[longitude]);
7883
+ if (lat === null || lon === null || Math.abs(lat) > 90 || Math.abs(lon) > 180) {
7884
+ unplotted.push(row);
7885
+ continue;
7886
+ }
7887
+ const s = size ? toChartNumber(row[size]) : null;
7888
+ if (s !== null && s > sizeMax) sizeMax = s;
7889
+ const shade = colorMode === "numeric" ? toChartNumber(row[color]) : null;
7890
+ if (shade !== null) [lo, hi] = [Math.min(lo, shade), Math.max(hi, shade)];
7891
+ const category = colorMode === "category" && !isBlank(row[color]) ? String(row[color]) : null;
7892
+ if (category !== null && !categories.includes(category)) categories.push(category);
7893
+ points.push({ lon, lat, name: name && !isBlank(row[name]) ? String(row[name]) : null, size: s, shade, category, row });
7894
+ }
7895
+ const shadeMin = Number.isFinite(lo) ? lo : 0;
7896
+ let shadeMax = Number.isFinite(hi) ? hi : 1;
7897
+ if (shadeMax <= shadeMin) shadeMax = shadeMin + 1;
7898
+ return { points, unplotted, colorMode, categories, shadeMin, shadeMax, sizeMax };
7899
+ }
7900
+ function symbolMapSize(value, max, hasSize) {
7901
+ if (!hasSize) return SYMBOL_MAP_DEFAULT_SIZE;
7902
+ if (value === null || value <= 0 || !(max > 0)) return SYMBOL_MAP_MIN_SIZE;
7903
+ return SYMBOL_MAP_MIN_SIZE + (SYMBOL_MAP_MAX_SIZE - SYMBOL_MAP_MIN_SIZE) * Math.sqrt(Math.min(1, value / max));
7904
+ }
7905
+ function escapeHtml5(text) {
7906
+ return text.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
7907
+ }
7908
+ var TEXT21 = {
7909
+ ja: {
7910
+ join: "\u30FB",
7911
+ point: "\u5730\u70B9",
7912
+ latitude: "\u7DEF\u5EA6",
7913
+ longitude: "\u7D4C\u5EA6",
7914
+ notPlotted: "(\u5EA7\u6A19\u306A\u3057)",
7915
+ chart: "\u5730\u70B9\u306E\u5730\u56F3"
7916
+ },
7917
+ en: {
7918
+ join: ", ",
7919
+ point: "Point",
7920
+ latitude: "Latitude",
7921
+ longitude: "Longitude",
7922
+ notPlotted: " (no coordinates)",
7923
+ chart: "Map of points"
7924
+ }
7925
+ };
7926
+ var textOf8 = (locale) => TEXT21[uiLanguage(resolveLocale(locale))];
7927
+ var coordText = (n) => n === null ? EMPTY_VALUE : n.toFixed(4).replace(/\.?0+$/, "");
7928
+ function buildSymbolMapOption(config) {
7929
+ const { model, labels, valueFormatter, sizeFormatter } = config;
7930
+ const label2 = (key) => labels?.[key] ?? key;
7931
+ const base = config.toneColor || "#6366f1";
7932
+ const selected = config.selected && config.selected.length > 0 ? new Set(config.selected.map(String)) : null;
7933
+ const fillOf = (p) => {
7934
+ if (model.colorMode === "numeric") return p.shade === null ? config.landColor : rampColor(base, config.surfaceColor, rampRatio(p.shade, model.shadeMin, model.shadeMax));
7935
+ if (model.colorMode === "category") {
7936
+ const at = p.category === null ? -1 : model.categories.indexOf(p.category);
7937
+ return at === -1 ? config.categoryColors[MAX_CATEGORIES] ?? base : config.categoryColors[Math.min(at, MAX_CATEGORIES)] ?? base;
7938
+ }
7939
+ return base;
7940
+ };
7941
+ const tooltip = (p) => {
7942
+ const lines = [escapeHtml5(p.name ?? `${coordText(p.lat)}, ${coordText(p.lon)}`)];
7943
+ if (config.size) lines.push(`${escapeHtml5(label2(config.size))} ${p.size === null ? EMPTY_VALUE : escapeHtml5(sizeFormatter(p.size))}`);
7944
+ if (config.color && config.color !== config.size)
7945
+ lines.push(`${escapeHtml5(label2(config.color))} ${model.colorMode === "numeric" ? p.shade === null ? EMPTY_VALUE : escapeHtml5(valueFormatter(p.shade)) : escapeHtml5(label2(p.category ?? EMPTY_VALUE))}`);
7946
+ for (const key of config.details ?? []) lines.push(`${escapeHtml5(label2(key))} ${escapeHtml5(cellText(p.row[key], valueFormatter))}`);
7947
+ return lines.join("<br/>");
7948
+ };
7949
+ const order = [...model.points].sort((a, b) => (b.size ?? 0) - (a.size ?? 0));
7950
+ const option = {
7951
+ animation: false,
7952
+ tooltip: config.showTooltip ? { trigger: "item", formatter: (p) => tooltip(p.data.point) } : { show: false },
7953
+ geo: {
7954
+ map: geoMapKey(config.basemap),
7955
+ silent: true,
7956
+ roam: false,
7957
+ aspectScale: GEO_ASPECT_SCALE[config.basemap],
7958
+ left: 8,
7959
+ right: 8,
7960
+ top: 8,
7961
+ bottom: 8,
7962
+ label: { show: false },
7963
+ itemStyle: { areaColor: config.landColor, borderColor: config.borderColor, borderWidth: 0.6 },
7964
+ emphasis: { disabled: true }
7965
+ },
7966
+ series: [
7967
+ {
7968
+ id: "points",
7969
+ type: "scatter",
7970
+ coordinateSystem: "geo",
7971
+ data: order.map((p) => {
7972
+ const [x, y] = config.basemap === "us" ? insetUsPoint(p.lon, p.lat) : [p.lon, p.lat];
7973
+ const fill = fillOf(p);
7974
+ const dim = selected !== null && !(p.name !== null && selected.has(p.name));
7975
+ return {
7976
+ value: [x, y],
7977
+ point: p,
7978
+ symbolSize: symbolMapSize(p.size, model.sizeMax, !!config.size),
7979
+ itemStyle: { color: dim ? mixIntoSurface2(fill, config.surfaceColor, 0.3) : fill, opacity: dim ? 1 : 0.85 }
7980
+ };
7981
+ }),
7982
+ itemStyle: { borderColor: config.surfaceColor ?? "#ffffff", borderWidth: 1 },
7983
+ emphasis: { scale: false, itemStyle: { opacity: 1, borderColor: config.borderColor, borderWidth: 1.5 } }
7984
+ }
7985
+ ]
7986
+ };
7987
+ return config.chartOptions ? mergeDeep4(option, config.chartOptions) : option;
7988
+ }
7989
+ function cellText(raw, formatter) {
7990
+ if (isBlank(raw)) return EMPTY_VALUE;
7991
+ const n = typeof raw === "string" ? null : toChartNumber(raw);
7992
+ return n === null ? String(raw) : formatter(n);
7993
+ }
7994
+ function mergeDeep4(a, b) {
7995
+ const out = { ...a };
7996
+ for (const [k, v] of Object.entries(b)) {
7997
+ const cur = out[k];
7998
+ out[k] = v && cur && typeof v === "object" && typeof cur === "object" && !Array.isArray(v) && !Array.isArray(cur) ? mergeDeep4(cur, v) : v;
7999
+ }
8000
+ return out;
8001
+ }
8002
+ function symbolMapDataTable(model, names, formatters, details = [], labels, locale) {
8003
+ const t = textOf8(locale);
8004
+ const label2 = (key) => labels?.[key] ?? key;
8005
+ const extra = [names.size, names.color].filter((k) => !!k && k !== names.latitude && k !== names.longitude);
8006
+ const keys = [.../* @__PURE__ */ new Set([...extra, ...details])];
8007
+ const rowCells = (row) => keys.map((key) => key === names.size ? cellText(row[key], formatters.size) : key === names.color && model.colorMode === "category" ? isBlank(row[key]) ? EMPTY_VALUE : label2(String(row[key])) : cellText(row[key], formatters.value));
8008
+ const nameOf = (row) => names.name && !isBlank(row[names.name]) ? String(row[names.name]) : EMPTY_VALUE;
8009
+ const rows = [
8010
+ ...model.points.map((p) => [nameOf(p.row), coordText(p.lat), coordText(p.lon), ...rowCells(p.row)]),
8011
+ ...model.unplotted.map((row) => [
8012
+ `${nameOf(row)}${t.notPlotted}`,
8013
+ coordText(toChartNumber(row[names.latitude])),
8014
+ coordText(toChartNumber(row[names.longitude])),
8015
+ ...rowCells(row)
8016
+ ])
8017
+ ];
8018
+ return {
8019
+ columns: [names.name ? label2(names.name) : t.point, labels?.[names.latitude] ?? t.latitude, labels?.[names.longitude] ?? t.longitude, ...keys.map(label2)],
8020
+ rows
8021
+ };
8022
+ }
8023
+ function colorsFor3(tokens, tone) {
8024
+ const resolved = resolveChartColors([tone, "var(--muted)", "var(--border)", ...DEFAULT_CHART_COLORS, CHART_OTHER_COLOR], tokens);
8025
+ const [toneColor = "", land = "", border = ""] = resolved;
8026
+ return { toneColor, land, border, categories: resolved.slice(3) };
8027
+ }
8028
+ var NO_ROWS16 = [];
8029
+ function SymbolMapImpl({
8030
+ data = NO_ROWS16,
8031
+ latitude,
8032
+ longitude,
8033
+ name,
8034
+ size,
8035
+ color,
8036
+ basemap = "auto",
8037
+ labels,
8038
+ format,
8039
+ sizeFormat,
8040
+ tone = "chart-1",
8041
+ showLegend = true,
8042
+ showTooltip = true,
8043
+ details,
8044
+ selected,
8045
+ onSelect,
8046
+ title,
8047
+ summary,
8048
+ isLoading,
8049
+ emptyState,
8050
+ height,
8051
+ chartOptions,
8052
+ actions,
8053
+ fileName,
8054
+ className,
8055
+ ariaLabel,
8056
+ ...rest
8057
+ }, ref) {
8058
+ const rows = Array.isArray(data) ? data : NO_ROWS16;
8059
+ const { ref: frameRef, surface, tokens } = useChartSurface(ref);
8060
+ const locale = useLocale();
8061
+ const formatter = useMemo(() => resolveValueFormatter(void 0, format ?? "number", locale), [format, locale]);
8062
+ const sizeFormatter = useMemo(() => resolveValueFormatter(void 0, sizeFormat ?? format ?? "number", locale), [sizeFormat, format, locale]);
8063
+ const model = useMemo(() => buildSymbolMapModel({ data: rows, latitude, longitude, name, size, color }), [rows, latitude, longitude, name, size, color]);
8064
+ const resolvedBasemap = useMemo(
8065
+ () => basemap === "auto" ? detectBasemap(model.points.map((p) => [p.lon, p.lat])) : basemap,
8066
+ [basemap, model]
8067
+ );
8068
+ const geo = useGeoMap(NO_ROWS16, resolvedBasemap);
8069
+ const colors = useMemo(() => colorsFor3(tokens, tone), [tokens, tone]);
8070
+ const option = useMemo(
8071
+ () => geo ? buildSymbolMapOption({
8072
+ model,
8073
+ basemap: geo.name,
8074
+ size,
8075
+ color,
8076
+ toneColor: colors.toneColor,
8077
+ categoryColors: colors.categories,
8078
+ surfaceColor: surface ?? void 0,
8079
+ landColor: colors.land || "rgba(128, 128, 128, 0.15)",
8080
+ borderColor: colors.border || "rgba(128, 128, 128, 0.4)",
8081
+ labels,
8082
+ valueFormatter: formatter,
8083
+ sizeFormatter,
8084
+ details,
8085
+ selected,
8086
+ showTooltip,
8087
+ chartOptions}) : null,
8088
+ [geo, model, size, color, colors, surface, labels, formatter, sizeFormatter, details, selected, showTooltip, chartOptions, locale]
8089
+ );
8090
+ const onEvents = useMemo(
8091
+ () => onSelect ? {
8092
+ click: (params) => {
8093
+ const p = params.data?.point;
8094
+ if (p) onSelect(p.row);
8095
+ }
8096
+ } : void 0,
8097
+ [onSelect]
8098
+ );
8099
+ const dataTable = useMemo(
8100
+ () => symbolMapDataTable(model, { latitude, longitude, name, size, color }, { value: formatter, size: sizeFormatter }, details, labels, locale),
8101
+ [model, latitude, longitude, name, size, color, formatter, sizeFormatter, details, labels, locale]
8102
+ );
8103
+ const label2 = ariaLabel ?? textOf8(locale).chart;
8104
+ const isEmpty = rows.length === 0;
8105
+ const legendCategories = model.categories.length > MAX_CATEGORIES ? [...model.categories.slice(0, MAX_CATEGORIES), otherSeriesLabel(locale)] : model.categories;
8106
+ 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: [
8107
+ color && /* @__PURE__ */ jsx("span", { children: labels?.[color] ?? color }),
8108
+ /* @__PURE__ */ jsx("span", { children: formatter(model.shadeMin) }),
8109
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-2 w-24 rounded-sm", style: { backgroundImage: rampGradientCss(tone) } }),
8110
+ /* @__PURE__ */ jsx("span", { children: formatter(model.shadeMax) })
8111
+ ] }) }) : model.colorMode === "category" ? /* @__PURE__ */ jsx(Legend, { categories: legendCategories, labels }) : null;
8112
+ return /* @__PURE__ */ jsx(
8113
+ ChartFrame,
8114
+ {
8115
+ ...chartRootProps(rest),
8116
+ ref: frameRef,
8117
+ title,
8118
+ summary,
8119
+ isLoading: (isLoading ?? false) || !isEmpty && !option,
8120
+ isEmpty,
8121
+ emptyState,
8122
+ height,
8123
+ variant: "bar",
8124
+ ariaLabel: label2,
8125
+ className,
8126
+ dataTable,
8127
+ children: /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col gap-2", children: [
8128
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: option && /* @__PURE__ */ jsx(EChart, { option, onEvents, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary } }) }),
8129
+ legend
8130
+ ] })
8131
+ }
8132
+ );
8133
+ }
8134
+ var SymbolMap = forwardRef(SymbolMapImpl);
8135
+ SymbolMap.displayName = "SymbolMap";
8136
+ use([TreemapChart]);
8137
+ var MAX_CATEGORIES2 = 5;
8138
+ function buildTreemapModel(config) {
8139
+ const { data, index, group, value, color } = config;
8140
+ const leaves = [];
8141
+ let [lo, hi] = [Infinity, -Infinity];
8142
+ for (const row of data) {
8143
+ if (!row || typeof row !== "object") continue;
8144
+ const shade = color ? toChartNumber(row[color]) : null;
8145
+ if (shade !== null) [lo, hi] = [Math.min(lo, shade), Math.max(hi, shade)];
8146
+ leaves.push({
8147
+ name: String(row[index] ?? EMPTY_VALUE),
8148
+ group: group ? String(row[group] ?? EMPTY_VALUE) : null,
8149
+ value: toChartNumber(row[value]),
8150
+ shade,
8151
+ row
8152
+ });
8153
+ }
8154
+ const byGroup = /* @__PURE__ */ new Map();
8155
+ for (const leaf of leaves) {
8156
+ if (leaf.value === null || leaf.value <= 0) continue;
8157
+ const list = byGroup.get(leaf.group) ?? [];
8158
+ list.push(leaf);
8159
+ byGroup.set(leaf.group, list);
8160
+ }
8161
+ const groups = [...byGroup.entries()].map(([name, list]) => ({ name, total: list.reduce((s, l) => s + l.value, 0), leaves: [...list].sort((a, b) => b.value - a.value) })).sort((a, b) => b.total - a.total);
8162
+ const total = groups.reduce((s, g) => s + g.total, 0);
8163
+ const categories = group ? groups.map((g) => g.name) : [...new Set(groups.flatMap((g) => g.leaves.map((l) => l.name)))];
8164
+ const shadeMin = Number.isFinite(lo) ? lo : 0;
8165
+ let shadeMax = Number.isFinite(hi) ? hi : 1;
8166
+ if (shadeMax <= shadeMin) shadeMax = shadeMin + 1;
8167
+ return { leaves, groups, categories, total, shadeMin, shadeMax };
8168
+ }
8169
+ function escapeHtml6(text) {
8170
+ return text.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
8171
+ }
8172
+ var TEXT22 = {
8173
+ ja: {
8174
+ join: "\u30FB",
8175
+ item: "\u9805\u76EE",
8176
+ group: "\u30B0\u30EB\u30FC\u30D7",
8177
+ share: "\u69CB\u6210\u6BD4",
8178
+ top: (name, share) => `\u6700\u5927\u306F ${name}(\u5168\u4F53\u306E ${share})`,
8179
+ chart: (value) => `${value}\u306E\u30C4\u30EA\u30FC\u30DE\u30C3\u30D7`
8180
+ },
8181
+ en: {
8182
+ join: ", ",
8183
+ item: "Item",
8184
+ group: "Group",
8185
+ share: "Share",
8186
+ top: (name, share) => `Largest: ${name} (${share} of the total)`,
8187
+ chart: (value) => `Treemap of ${value}`
8188
+ }
8189
+ };
8190
+ var textOf9 = (locale) => TEXT22[uiLanguage(resolveLocale(locale))];
8191
+ function buildTreemapOption(config) {
8192
+ const { model, labels, valueFormatter } = config;
8193
+ const t = textOf9(config.locale);
8194
+ const label2 = (key) => labels?.[key] ?? key;
8195
+ const surface = config.surfaceColor ?? "#ffffff";
8196
+ const base = config.toneColor || "#6366f1";
8197
+ const categoryColor = (name) => {
8198
+ const at = model.categories.indexOf(name);
8199
+ return config.categoryColors[at === -1 ? MAX_CATEGORIES2 : Math.min(at, MAX_CATEGORIES2)] ?? base;
8200
+ };
8201
+ const share = (v) => formatValue(model.total > 0 ? v / model.total : 0, "percent", config.locale);
8202
+ const leafNode = (leaf) => {
8203
+ let fill;
8204
+ let dark = true;
8205
+ if (config.colorMode === "numeric") {
8206
+ const ratio = leaf.shade === null ? 0 : rampRatio(leaf.shade, model.shadeMin, model.shadeMax);
8207
+ fill = rampColor(base, config.surfaceColor, ratio);
8208
+ dark = ratio >= RAMP_LIGHT_TEXT_FROM;
8209
+ } else fill = categoryColor(config.hasGroup ? leaf.group : leaf.name);
8210
+ return {
8211
+ name: label2(leaf.name),
8212
+ value: leaf.value,
8213
+ leaf,
8214
+ itemStyle: { color: fill },
8215
+ label: { color: dark ? surface : config.foregroundColor }
8216
+ };
8217
+ };
8218
+ const tooltip = (leaf, name, value) => {
8219
+ const head = leaf?.group != null ? `${escapeHtml6(label2(leaf.group))} / ${escapeHtml6(name)}` : escapeHtml6(name);
8220
+ const parts = [`${head} ${escapeHtml6(valueFormatter(value))}`, `${t.share} ${escapeHtml6(share(value))}`];
8221
+ if (leaf && config.colorKey && config.colorMode === "numeric")
8222
+ parts.push(`${escapeHtml6(label2(config.colorKey))} ${leaf.shade === null ? EMPTY_VALUE : escapeHtml6(config.colorFormatter(leaf.shade))}`);
8223
+ return parts.join(t.join);
8224
+ };
8225
+ const data = config.hasGroup ? model.groups.map((g) => ({
8226
+ name: label2(g.name),
8227
+ value: g.total,
8228
+ itemStyle: { color: config.colorMode === "numeric" ? config.foregroundColor : categoryColor(g.name) },
8229
+ children: g.leaves.map(leafNode)
8230
+ })) : model.groups.flatMap((g) => g.leaves.map(leafNode));
8231
+ const option = {
8232
+ animation: false,
8233
+ tooltip: config.showTooltip ? {
8234
+ trigger: "item",
8235
+ formatter: (p) => {
8236
+ const d = p;
8237
+ return tooltip(d.data?.leaf, d.name, Number(d.value));
8238
+ }
8239
+ } : { show: false },
8240
+ series: [
8241
+ {
8242
+ id: "tiles",
8243
+ type: "treemap",
8244
+ left: 0,
8245
+ right: 0,
8246
+ top: 0,
8247
+ bottom: 0,
8248
+ roam: false,
8249
+ nodeClick: false,
8250
+ breadcrumb: { show: false },
8251
+ squareRatio: 0.5 * (1 + Math.sqrt(5)),
8252
+ label: {
8253
+ show: true,
8254
+ position: "insideTopLeft",
8255
+ overflow: "truncate",
8256
+ lineHeight: 16,
8257
+ formatter: (p) => {
8258
+ const d = p;
8259
+ return `${d.name}
8260
+ ${valueFormatter(Number(d.value))}`;
8261
+ }
8262
+ },
8263
+ upperLabel: { show: config.hasGroup, height: 20, color: surface, fontWeight: 600 },
8264
+ itemStyle: { borderColor: surface, borderWidth: 1, gapWidth: 1 },
8265
+ emphasis: { disabled: true },
8266
+ levels: config.hasGroup ? [{ itemStyle: { borderColor: surface, borderWidth: 2, gapWidth: 2 } }, { itemStyle: { borderColor: surface, borderWidth: 0, gapWidth: 1 } }] : [{ itemStyle: { borderColor: surface, borderWidth: 0, gapWidth: 1 } }],
8267
+ data
8268
+ }
8269
+ ]
8270
+ };
8271
+ return config.chartOptions ? mergeDeep5(option, config.chartOptions) : option;
8272
+ }
8273
+ function mergeDeep5(a, b) {
8274
+ const out = { ...a };
8275
+ for (const [k, v] of Object.entries(b)) {
8276
+ const cur = out[k];
8277
+ out[k] = v && cur && typeof v === "object" && typeof cur === "object" && !Array.isArray(v) && !Array.isArray(cur) ? mergeDeep5(cur, v) : v;
8278
+ }
8279
+ return out;
8280
+ }
8281
+ function treemapDataTable(model, names, formatters, labels, locale) {
8282
+ const t = textOf9(locale);
8283
+ const label2 = (key) => labels?.[key] ?? key;
8284
+ const share = (v) => v === null || v <= 0 || model.total <= 0 ? EMPTY_VALUE : formatValue(v / model.total, "percent", locale);
8285
+ return {
8286
+ columns: [
8287
+ ...names.group ? [labels?.[names.group] ?? t.group] : [],
8288
+ labels?.[names.index] ?? t.item,
8289
+ label2(names.value),
8290
+ t.share,
8291
+ ...names.color && names.color !== names.value ? [label2(names.color)] : []
8292
+ ],
8293
+ rows: model.leaves.map((leaf) => [
8294
+ ...names.group ? [label2(leaf.group ?? EMPTY_VALUE)] : [],
8295
+ label2(leaf.name),
8296
+ leaf.value === null ? EMPTY_VALUE : formatters.value(leaf.value),
8297
+ share(leaf.value),
8298
+ ...names.color && names.color !== names.value ? [leaf.shade === null ? EMPTY_VALUE : formatters.color(leaf.shade)] : []
8299
+ ])
8300
+ };
8301
+ }
8302
+ function buildTreemapSummary(model, title, labels, locale) {
8303
+ let best;
8304
+ for (const g of model.groups) for (const l of g.leaves) if (!best || l.value > best.value) best = l;
8305
+ if (!best || model.total <= 0) return void 0;
8306
+ return `${title ? `${title}: ` : ""}${textOf9(locale).top(labels?.[best.name] ?? best.name, formatValue(best.value / model.total, "percent", locale))}`;
8307
+ }
8308
+ function colorsFor4(tokens, tone) {
8309
+ const resolved = resolveChartColors([tone, "var(--foreground)", ...DEFAULT_CHART_COLORS, CHART_OTHER_COLOR], tokens);
8310
+ const [toneColor = "", foreground = ""] = resolved;
8311
+ return { toneColor, foreground, categories: resolved.slice(2) };
8312
+ }
8313
+ var NO_ROWS17 = [];
8314
+ function TreemapImpl({
8315
+ data = NO_ROWS17,
8316
+ index,
8317
+ group,
8318
+ value,
8319
+ color,
8320
+ labels,
8321
+ format,
8322
+ colorFormat,
8323
+ valueFormatter,
8324
+ tone = "chart-1",
8325
+ showLegend = true,
8326
+ showTooltip = true,
8327
+ onSelect,
8328
+ title,
8329
+ summary,
8330
+ isLoading,
8331
+ emptyState,
8332
+ height,
8333
+ chartOptions,
8334
+ actions,
8335
+ fileName,
8336
+ className,
8337
+ ariaLabel,
8338
+ ...rest
8339
+ }, ref) {
8340
+ const rows = Array.isArray(data) ? data : NO_ROWS17;
8341
+ const { ref: frameRef, surface, tokens } = useChartSurface(ref);
8342
+ const locale = useLocale();
8343
+ const formatter = useMemo(() => resolveValueFormatter(valueFormatter, format ?? "number", locale), [valueFormatter, format, locale]);
8344
+ const colorFormatter = useMemo(() => resolveValueFormatter(void 0, colorFormat ?? format ?? "number", locale), [colorFormat, format, locale]);
8345
+ const model = useMemo(() => buildTreemapModel({ data: rows, index, group, value, color }), [rows, index, group, value, color]);
8346
+ const colorMode = color ? "numeric" : "category";
8347
+ const colors = useMemo(() => colorsFor4(tokens, tone), [tokens, tone]);
8348
+ const option = useMemo(
8349
+ () => buildTreemapOption({
8350
+ model,
8351
+ hasGroup: !!group,
8352
+ colorMode,
8353
+ toneColor: colors.toneColor,
8354
+ categoryColors: colors.categories,
8355
+ surfaceColor: surface ?? void 0,
8356
+ foregroundColor: colors.foreground || tokens?.foreground || "#111111",
8357
+ labels,
8358
+ valueFormatter: formatter,
8359
+ colorFormatter,
8360
+ colorKey: color,
8361
+ showTooltip,
8362
+ chartOptions,
8363
+ locale
8364
+ }),
8365
+ [model, group, colorMode, colors, surface, tokens, labels, formatter, colorFormatter, color, showTooltip, chartOptions, locale]
8366
+ );
8367
+ const onEvents = useMemo(
8368
+ () => onSelect ? {
8369
+ click: (params) => {
8370
+ const leaf = params.data?.leaf;
8371
+ if (leaf) onSelect(leaf.row);
8372
+ }
8373
+ } : void 0,
8374
+ [onSelect]
8375
+ );
8376
+ const dataTable = useMemo(
8377
+ () => treemapDataTable(model, { index, group, value, color }, { value: formatter, color: colorFormatter }, labels, locale),
8378
+ [model, index, group, value, color, formatter, colorFormatter, labels, locale]
8379
+ );
8380
+ const resolvedSummary = useMemo(
8381
+ () => summary === "auto" ? buildTreemapSummary(model, title, labels, locale) : summary,
8382
+ [summary, model, title, labels, locale]
8383
+ );
8384
+ const label2 = ariaLabel ?? textOf9(locale).chart(labels?.[value] ?? value ?? "");
8385
+ const legendCategories = model.categories.length > MAX_CATEGORIES2 ? [...model.categories.slice(0, MAX_CATEGORIES2), otherSeriesLabel(locale)] : model.categories;
8386
+ 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: [
8387
+ color && /* @__PURE__ */ jsx("span", { children: labels?.[color] ?? color }),
8388
+ /* @__PURE__ */ jsx("span", { children: colorFormatter(model.shadeMin) }),
8389
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-2 w-24 rounded-sm", style: { backgroundImage: rampGradientCss(tone) } }),
8390
+ /* @__PURE__ */ jsx("span", { children: colorFormatter(model.shadeMax) })
8391
+ ] }) }) : group ? /* @__PURE__ */ jsx(Legend, { categories: legendCategories, labels }) : null;
8392
+ return /* @__PURE__ */ jsx(
8393
+ ChartFrame,
8394
+ {
8395
+ ...chartRootProps(rest),
8396
+ ref: frameRef,
8397
+ title,
8398
+ summary: resolvedSummary,
8399
+ isLoading: isLoading ?? false,
8400
+ isEmpty: rows.length === 0,
8401
+ emptyState,
8402
+ height,
8403
+ variant: "bar",
8404
+ ariaLabel: label2,
8405
+ className,
8406
+ dataTable,
8407
+ children: /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col gap-2", children: [
8408
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(EChart, { option, onEvents, height: "100%", ariaLabel: label2, actions, fileName, exportHeader: { title, summary: resolvedSummary } }) }),
8409
+ legend
8410
+ ] })
8411
+ }
8412
+ );
8413
+ }
8414
+ var Treemap = forwardRef(TreemapImpl);
8415
+ Treemap.displayName = "Treemap";
8416
+ var TEXT23 = {
5351
8417
  ja: {
5352
8418
  tones: { positive: "\u826F\u597D", warning: "\u6CE8\u610F", negative: "\u8981\u5BFE\u5FDC", neutral: "\u4E2D\u7ACB" },
5353
8419
  toneNote: (label2) => `\uFF08${label2}\uFF09`,
@@ -5381,7 +8447,7 @@ var TEXT14 = {
5381
8447
  exportCsv: "Export CSV"
5382
8448
  }
5383
8449
  };
5384
- var useText = () => TEXT14[uiLanguage(useLocale())];
8450
+ var useText = () => TEXT23[uiLanguage(useLocale())];
5385
8451
  function resolveFormat(format, row) {
5386
8452
  return typeof format === "function" ? format(row) : format;
5387
8453
  }
@@ -5444,10 +8510,10 @@ function useDataTable() {
5444
8510
  if (!ctx) throw new Error("useDataTable must be used inside <DataTable>");
5445
8511
  return ctx;
5446
8512
  }
5447
- var NO_ROWS12 = [];
8513
+ var NO_ROWS18 = [];
5448
8514
  function DataTable({
5449
- columns = NO_ROWS12,
5450
- data = NO_ROWS12,
8515
+ columns = NO_ROWS18,
8516
+ data = NO_ROWS18,
5451
8517
  enableSorting = true,
5452
8518
  sorting: sortingProp,
5453
8519
  onSortingChange,
@@ -5474,7 +8540,7 @@ function DataTable({
5474
8540
  children
5475
8541
  }) {
5476
8542
  const locale = useLocale();
5477
- const t = TEXT14[uiLanguage(locale)];
8543
+ const t = TEXT23[uiLanguage(locale)];
5478
8544
  const [sorting, setSorting] = useControlledState(sortingProp, [], onSortingChange);
5479
8545
  const [columnFilters, setColumnFilters] = useControlledState(
5480
8546
  columnFiltersProp,
@@ -5758,19 +8824,19 @@ var DataTableContent = forwardRef(
5758
8824
  }) }, headerGroup.id)) }),
5759
8825
  /* @__PURE__ */ jsx(TableBody, { children: isLoading ? Array.from({ length: enablePagination ? table.getState().pagination.pageSize : 5 }).map(
5760
8826
  (_, 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)
5761
- ) : table.getRowModel().rows.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(TableRow, { "data-state": row.getIsSelected() ? "selected" : void 0, children: row.getVisibleCells().map((cell) => {
5762
- const meta = cell.column.columnDef.meta;
5763
- const comparisonColumn = comparisonOf.get(cell.column.id);
8827
+ ) : table.getRowModel().rows.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(TableRow, { "data-state": row.getIsSelected() ? "selected" : void 0, children: row.getVisibleCells().map((cell2) => {
8828
+ const meta = cell2.column.columnDef.meta;
8829
+ const comparisonColumn = comparisonOf.get(cell2.column.id);
5764
8830
  const comparisonCell = comparisonColumn ? row.getVisibleCells().find((c) => c.column.id === comparisonColumn.id) : void 0;
5765
8831
  return /* @__PURE__ */ jsxs(
5766
8832
  TableCell,
5767
8833
  {
5768
8834
  className: columnClassName(meta, {
5769
- isComparison: comparisonIds.has(cell.column.id),
5770
- isHost: comparisonOf.has(cell.column.id)
8835
+ isComparison: comparisonIds.has(cell2.column.id),
8836
+ isHost: comparisonOf.has(cell2.column.id)
5771
8837
  }),
5772
8838
  children: [
5773
- flexRender(cell.column.columnDef.cell, cell.getContext()),
8839
+ flexRender(cell2.column.columnDef.cell, cell2.getContext()),
5774
8840
  comparisonCell && /* @__PURE__ */ jsx(
5775
8841
  "div",
5776
8842
  {
@@ -5785,7 +8851,7 @@ var DataTableContent = forwardRef(
5785
8851
  )
5786
8852
  ]
5787
8853
  },
5788
- cell.id
8854
+ cell2.id
5789
8855
  );
5790
8856
  }) }, row.id)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
5791
8857
  TableCell,
@@ -5920,16 +8986,16 @@ DataTableColumnVisibility.displayName = "DataTableColumnVisibility";
5920
8986
  var SIGNED_NUMBER = /^[+-]\s?[^\d\s=+\-@]{0,3}\d[\d,.]*[^\d\s=+\-@]{0,4}$/;
5921
8987
  function toCsv(header, rows, options = {}) {
5922
8988
  const { bom = true, guardFormulas = false } = options;
5923
- const field = (cell, guard) => {
5924
- let text = cell === null || cell === void 0 ? "" : String(cell);
5925
- if (guard && typeof cell === "string" && /^[=+\-@]/.test(text) && !SIGNED_NUMBER.test(text)) {
8989
+ const field = (cell2, guard) => {
8990
+ let text = cell2 === null || cell2 === void 0 ? "" : String(cell2);
8991
+ if (guard && typeof cell2 === "string" && /^[=+\-@]/.test(text) && !SIGNED_NUMBER.test(text)) {
5926
8992
  text = `'${text}`;
5927
8993
  }
5928
8994
  return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
5929
8995
  };
5930
8996
  const lines = [
5931
8997
  header.map((h) => field(h, false)).join(","),
5932
- ...rows.map((row) => row.map((cell) => field(cell, guardFormulas)).join(","))
8998
+ ...rows.map((row) => row.map((cell2) => field(cell2, guardFormulas)).join(","))
5933
8999
  ];
5934
9000
  return (bom ? "\uFEFF" : "") + lines.join("\r\n");
5935
9001
  }
@@ -5983,7 +9049,7 @@ function DataTableExport({
5983
9049
  disabled: isLoading,
5984
9050
  children: [
5985
9051
  /* @__PURE__ */ jsx(Download, { className: "size-4", "aria-hidden": "true" }),
5986
- children ?? TEXT14[uiLanguage(locale)].exportCsv
9052
+ children ?? TEXT23[uiLanguage(locale)].exportCsv
5987
9053
  ]
5988
9054
  }
5989
9055
  );
@@ -6017,8 +9083,150 @@ function DataTablePreset({
6017
9083
  ] });
6018
9084
  }
6019
9085
  DataTablePreset.displayName = "DataTablePreset";
9086
+ var FLOOR_SHARE = 0.2;
9087
+ var DEFAULT_CHART_HEIGHT3 = 288;
9088
+ var LIGHT_TEXT_FROM = 0.55;
9089
+ var dimText = (v) => v === null || v === void 0 || v === "" ? EMPTY_VALUE : String(v);
9090
+ var pivotCellKey = (rowKey, colKey) => `${rowKey.join("")}\0${colKey.join("")}`;
9091
+ function buildPivotModel(config) {
9092
+ const { data, rows, columns, values } = config;
9093
+ const rowKeys = /* @__PURE__ */ new Map();
9094
+ const colKeys = /* @__PURE__ */ new Map();
9095
+ const cells = /* @__PURE__ */ new Map();
9096
+ for (const row of data) {
9097
+ if (!row || typeof row !== "object") continue;
9098
+ const rk = rows.map((d) => dimText(row[d]));
9099
+ const ck = columns.map((d) => dimText(row[d]));
9100
+ const rId = rk.join("");
9101
+ const cId = ck.join("");
9102
+ if (!rowKeys.has(rId)) rowKeys.set(rId, rk);
9103
+ if (!colKeys.has(cId)) colKeys.set(cId, ck);
9104
+ cells.set(pivotCellKey(rk, ck), row);
9105
+ }
9106
+ const ranges = {};
9107
+ for (const value of values) {
9108
+ let [lo, hi] = [Infinity, -Infinity];
9109
+ for (const row of cells.values()) {
9110
+ const n = toChartNumber(row[value]);
9111
+ if (n !== null) [lo, hi] = [Math.min(lo, n), Math.max(hi, n)];
9112
+ }
9113
+ ranges[value] = { min: Number.isFinite(lo) ? lo : 0, max: Number.isFinite(hi) ? hi : 0 };
9114
+ }
9115
+ return {
9116
+ rowKeys: rowKeys.size > 0 ? [...rowKeys.values()] : [rows.map(() => EMPTY_VALUE)],
9117
+ colKeys: colKeys.size > 0 ? [...colKeys.values()] : [columns.map(() => EMPTY_VALUE)],
9118
+ cells,
9119
+ ranges
9120
+ };
9121
+ }
9122
+ function pivotSpans(keys, level) {
9123
+ const out = [];
9124
+ const prefix = (k) => k.slice(0, level + 1).join("");
9125
+ keys.forEach((key, i) => {
9126
+ const last = out[out.length - 1];
9127
+ if (last && prefix(keys[last.start]) === prefix(key)) last.span++;
9128
+ else out.push({ text: key[level] ?? "", start: i, span: 1 });
9129
+ });
9130
+ return out;
9131
+ }
9132
+ var TEXT24 = {
9133
+ ja: { table: "\u30D4\u30DC\u30C3\u30C8\u8868" },
9134
+ en: { table: "Pivot table" }
9135
+ };
9136
+ var NO_ROWS19 = [];
9137
+ var asList = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
9138
+ function PivotTable({
9139
+ data = NO_ROWS19,
9140
+ rows: rowDims,
9141
+ columns: colDims,
9142
+ values: valueKeys,
9143
+ formats,
9144
+ labels,
9145
+ highlight = false,
9146
+ tone = "chart-1",
9147
+ onSelect,
9148
+ title,
9149
+ summary,
9150
+ isLoading,
9151
+ emptyState,
9152
+ maxHeight = 480,
9153
+ className,
9154
+ ariaLabel
9155
+ }) {
9156
+ const locale = useLocale();
9157
+ const t = TEXT24[uiLanguage(resolveLocale(locale))];
9158
+ const dataRows = Array.isArray(data) ? data : NO_ROWS19;
9159
+ const rows = useMemo(() => asList(rowDims), [rowDims]);
9160
+ const columns = useMemo(() => asList(colDims), [colDims]);
9161
+ const values = useMemo(() => asList(valueKeys), [valueKeys]);
9162
+ const model = useMemo(() => buildPivotModel({ data: dataRows, rows, columns, values }), [dataRows, rows, columns, values]);
9163
+ const label2 = (key) => labels?.[key] ?? key;
9164
+ const R = rows.length;
9165
+ const C = columns.length;
9166
+ const V = values.length;
9167
+ const valueRow = V > 1 || C === 0;
9168
+ const H = C + (valueRow ? 1 : 0);
9169
+ const shaded = (value) => highlight === true || highlight === value;
9170
+ const isEmpty = dataRows.length === 0;
9171
+ const ready = !isLoading && !isEmpty;
9172
+ const cellStyle = (value, n) => {
9173
+ if (n === null || !shaded(value)) return void 0;
9174
+ const { min, max } = model.ranges[value] ?? { min: 0, max: 0 };
9175
+ const ratio = max > min ? Math.min(1, Math.max(0, (n - min) / (max - min))) : 1;
9176
+ const share = Math.round((FLOOR_SHARE + (1 - FLOOR_SHARE) * ratio) * 100);
9177
+ return {
9178
+ backgroundColor: `color-mix(in oklch, var(--${tone}) ${share}%, var(--card))`,
9179
+ color: ratio >= LIGHT_TEXT_FROM ? "var(--card)" : void 0
9180
+ };
9181
+ };
9182
+ const headerRows = Array.from({ length: H }, (_, h) => {
9183
+ const lead = h === H - 1 ? rows.map((d, level) => /* @__PURE__ */ jsx(TableHead, { scope: "col", className: cn(level === 0 && "pl-0"), children: label2(d) }, `dim-${d}`)) : h === 0 && R > 0 ? [/* @__PURE__ */ jsx(TableHead, { colSpan: R, rowSpan: H - 1, "aria-hidden": "true" }, "corner")] : [];
9184
+ const cells = h < C ? pivotSpans(model.colKeys, h).map((s) => /* @__PURE__ */ jsx(TableHead, { scope: "colgroup", colSpan: s.span * Math.max(1, V), className: "text-right", children: label2(s.text) }, `c-${h}-${s.start}`)) : model.colKeys.flatMap(
9185
+ (_2, ci) => values.map((v) => /* @__PURE__ */ jsx(TableHead, { scope: "col", className: "text-right", children: label2(v) }, `v-${ci}-${v}`))
9186
+ );
9187
+ return /* @__PURE__ */ jsxs(TableRow, { className: "hover:bg-transparent", children: [
9188
+ lead,
9189
+ cells
9190
+ ] }, `h-${h}`);
9191
+ });
9192
+ const rowSpans = rows.map((_, level) => new Map(pivotSpans(model.rowKeys, level).map((s) => [s.start, s.span])));
9193
+ const body = model.rowKeys.map((rk, ri) => /* @__PURE__ */ jsxs(TableRow, { children: [
9194
+ rows.map((d, level) => {
9195
+ const span = rowSpans[level].get(ri);
9196
+ if (span === void 0) return null;
9197
+ return /* @__PURE__ */ jsx(TableHead, { scope: span > 1 ? "rowgroup" : "row", rowSpan: span, className: cn("align-top font-medium text-foreground", level === 0 && "pl-0"), children: label2(rk[level] ?? "") }, `rh-${d}`);
9198
+ }),
9199
+ model.colKeys.flatMap(
9200
+ (ck, ci) => values.map((v) => {
9201
+ const row = model.cells.get(pivotCellKey(rk, ck));
9202
+ const n = row ? toChartNumber(row[v]) : null;
9203
+ const text = formatValue(n, formats?.[v] ?? "number", locale);
9204
+ return /* @__PURE__ */ jsx(TableCell, { className: "text-right tabular-nums", style: cellStyle(v, n), children: onSelect && row ? /* @__PURE__ */ jsx("button", { type: "button", className: "w-full cursor-pointer text-right tabular-nums", onClick: () => onSelect(row), children: text }) : text }, `c-${ci}-${v}`);
9205
+ })
9206
+ )
9207
+ ] }, `r-${ri}`));
9208
+ return /* @__PURE__ */ jsx(
9209
+ ChartFrame,
9210
+ {
9211
+ title,
9212
+ summary,
9213
+ isLoading: isLoading ?? false,
9214
+ isEmpty,
9215
+ emptyState,
9216
+ height: ready ? "auto" : DEFAULT_CHART_HEIGHT3,
9217
+ variant: "list",
9218
+ plotRole: "group",
9219
+ ariaLabel: ariaLabel ?? title ?? t.table,
9220
+ className,
9221
+ children: /* @__PURE__ */ jsx("div", { "data-slot": "pivot-table", className: "relative w-full overflow-auto", style: { maxHeight }, children: /* @__PURE__ */ jsxs("table", { "data-slot": "table", "aria-label": ariaLabel ?? title ?? t.table, className: "w-full caption-bottom text-sm", children: [
9222
+ /* @__PURE__ */ jsx(TableHeader, { className: "sticky top-0 z-10 bg-card", children: headerRows }),
9223
+ /* @__PURE__ */ jsx(TableBody, { children: body })
9224
+ ] }) })
9225
+ }
9226
+ );
9227
+ }
6020
9228
  var FilterBarContext = createContext(null);
6021
- var TEXT15 = {
9229
+ var TEXT25 = {
6022
9230
  ja: {
6023
9231
  filters: "\u30D5\u30A3\u30EB\u30BF\u30FC",
6024
9232
  selected: (count) => ` (${count}\u4EF6\u9078\u629E\u4E2D)`,
@@ -6034,7 +9242,7 @@ var TEXT15 = {
6034
9242
  clearAll: "Clear all filters"
6035
9243
  }
6036
9244
  };
6037
- var useText2 = () => TEXT15[uiLanguage(useLocale())];
9245
+ var useText2 = () => TEXT25[uiLanguage(useLocale())];
6038
9246
  function useFilterBar() {
6039
9247
  const ctx = useContext(FilterBarContext);
6040
9248
  if (!ctx) throw new Error("useFilterBar must be used within <FilterBar>");
@@ -6337,7 +9545,7 @@ var PRESET_LABELS = {
6337
9545
  lastFiscalYear: "Last fiscal year"
6338
9546
  }
6339
9547
  };
6340
- var TEXT16 = {
9548
+ var TEXT26 = {
6341
9549
  ja: { placeholder: "\u671F\u9593\u3092\u9078\u629E", rangeSeparator: " - " },
6342
9550
  en: { placeholder: "Pick a date range", rangeSeparator: " \u2013 " }
6343
9551
  };
@@ -6355,7 +9563,7 @@ function createDatePresets({
6355
9563
  const today = now();
6356
9564
  return { from: startOfDay(subDays(today, days - 1)), to: endOfDay(today) };
6357
9565
  };
6358
- const toDate2 = (unit) => () => {
9566
+ const toDate3 = (unit) => () => {
6359
9567
  const today = now();
6360
9568
  return {
6361
9569
  from: fiscalPeriodRange(today, { unit, fiscalYearStartMonth: startMonth }).from,
@@ -6405,9 +9613,9 @@ function createDatePresets({
6405
9613
  return { from: startOfMonth(lastMonth), to: endOfMonth(lastMonth) };
6406
9614
  }
6407
9615
  },
6408
- { label: t.thisQuarter, getValue: toDate2("quarter") },
9616
+ { label: t.thisQuarter, getValue: toDate3("quarter") },
6409
9617
  { label: t.lastQuarter, getValue: previous("quarter") },
6410
- { label: t.thisFiscalYear, getValue: toDate2("year") },
9618
+ { label: t.thisFiscalYear, getValue: toDate3("year") },
6411
9619
  { label: t.lastFiscalYear, getValue: previous("year") }
6412
9620
  ];
6413
9621
  }
@@ -6438,7 +9646,7 @@ var DateRangePicker = forwardRef(
6438
9646
  const [open, setOpen] = useState(false);
6439
9647
  const isMobile = useIsMobile();
6440
9648
  const locale = useLocale(localeProp);
6441
- const t = TEXT16[uiLanguage(locale)];
9649
+ const t = TEXT26[uiLanguage(locale)];
6442
9650
  const presets = useMemo(
6443
9651
  () => presetsProp ?? createDatePresets({ locale, fiscalYearStartMonth }),
6444
9652
  [presetsProp, locale, fiscalYearStartMonth]
@@ -6655,7 +9863,7 @@ function RemoveButton({ label: label2, onRemove, iconClassName }) {
6655
9863
  }
6656
9864
  );
6657
9865
  }
6658
- var TEXT17 = {
9866
+ var TEXT27 = {
6659
9867
  ja: { placeholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044", search: "\u691C\u7D22...", empty: "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F", clear: "\u30AF\u30EA\u30A2" },
6660
9868
  en: { placeholder: "Select an option", search: "Search...", empty: "No results found.", clear: "Clear" }
6661
9869
  };
@@ -6675,7 +9883,7 @@ var SearchableSelect = forwardRef(
6675
9883
  className
6676
9884
  }, ref) {
6677
9885
  const [open, setOpen] = useState(false);
6678
- const t = TEXT17[uiLanguage(useLocale())];
9886
+ const t = TEXT27[uiLanguage(useLocale())];
6679
9887
  const allOptions = useMemo(() => flattenOptions(options), [options]);
6680
9888
  const selectedOption = useMemo(
6681
9889
  () => allOptions.find((opt) => opt.value === value),
@@ -6728,7 +9936,7 @@ var SearchableSelect = forwardRef(
6728
9936
  }
6729
9937
  );
6730
9938
  SearchableSelect.displayName = "SearchableSelect";
6731
- var TEXT18 = {
9939
+ var TEXT28 = {
6732
9940
  ja: {
6733
9941
  placeholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
6734
9942
  search: "\u691C\u7D22...",
@@ -6745,10 +9953,10 @@ var TEXT18 = {
6745
9953
  }
6746
9954
  };
6747
9955
  var NO_OPTIONS3 = [];
6748
- var NO_VALUES = [];
9956
+ var NO_VALUES2 = [];
6749
9957
  var MultiSelect = forwardRef(function MultiSelect2({
6750
9958
  options = NO_OPTIONS3,
6751
- value = NO_VALUES,
9959
+ value = NO_VALUES2,
6752
9960
  onChange,
6753
9961
  onSearch,
6754
9962
  maxCount = 3,
@@ -6761,7 +9969,7 @@ var MultiSelect = forwardRef(function MultiSelect2({
6761
9969
  }, ref) {
6762
9970
  const [open, setOpen] = useState(false);
6763
9971
  const listId = useId();
6764
- const t = TEXT18[uiLanguage(useLocale())];
9972
+ const t = TEXT28[uiLanguage(useLocale())];
6765
9973
  const allOptions = useMemo(() => flattenOptions(options), [options]);
6766
9974
  const selectedOptions = useMemo(
6767
9975
  () => allOptions.filter((opt) => value.includes(opt.value)),
@@ -6891,10 +10099,10 @@ function computeTargetProgress(current, target, options) {
6891
10099
  elapsed
6892
10100
  };
6893
10101
  }
6894
- var DAY_MS = 24 * 60 * 60 * 1e3;
10102
+ var DAY_MS2 = 24 * 60 * 60 * 1e3;
6895
10103
  function inferPeriodGrain(period) {
6896
10104
  if (!period) return void 0;
6897
- const days = (toTime(period.end) - toTime(period.start)) / DAY_MS;
10105
+ const days = (toTime(period.end) - toTime(period.start)) / DAY_MS2;
6898
10106
  if (!Number.isFinite(days)) return void 0;
6899
10107
  const near = (min, max) => days >= min - 1 / 24 && days <= max + 1 / 24;
6900
10108
  if (near(1, 1)) return "day";
@@ -7043,7 +10251,7 @@ var LONG_VALUE_CHARS = 10;
7043
10251
  var DELTA_UNDER_PLACEMENT = "col-start-1 row-span-1 row-start-3 justify-self-start";
7044
10252
  var KPI_FOOTER_CLASS = "flex-col items-start gap-2 rounded-none border-t-0 bg-transparent pt-0 text-sm";
7045
10253
  var PLACEHOLDER = /\{(\w+)\}/g;
7046
- var TEXT19 = {
10254
+ var TEXT29 = {
7047
10255
  ja: {
7048
10256
  target: "\u76EE\u6A19",
7049
10257
  provisional: "\u901F\u5831",
@@ -7175,7 +10383,7 @@ function KpiCard({
7175
10383
  ...props
7176
10384
  }) {
7177
10385
  const locale = useLocale(localeProp);
7178
- const t = TEXT19[uiLanguage(locale)];
10386
+ const t = TEXT29[uiLanguage(locale)];
7179
10387
  const allComparisons = [...comparisonProp ? [comparisonProp] : [], ...comparisons ?? []];
7180
10388
  const comparison = allComparisons[0];
7181
10389
  const isProvisional = provisional !== void 0 && provisional !== false;
@@ -7426,7 +10634,7 @@ function updatedAtText(updatedAt, display, locale, t, now, timeZone) {
7426
10634
  const absolute2 = formatDate(updatedAt, "datetime", locale, { timeZone });
7427
10635
  return display === "absolute" ? t.updatedAbsolute(absolute2) : t.updatedBoth(absolute2, relative2);
7428
10636
  }
7429
- var TEXT20 = {
10637
+ var TEXT30 = {
7430
10638
  ja: {
7431
10639
  flat: (value) => `\u5909\u5316\u306A\u3057 ${value}%`,
7432
10640
  up: (value) => `${value}% \u5897\u52A0`,
@@ -7455,7 +10663,7 @@ var TrendIndicator = forwardRef(
7455
10663
  const isGood = direction === "neutral" ? null : direction === "up" === positiveIsGood;
7456
10664
  const sentiment = isGood === null ? "neutral" : isGood ? "positive" : "negative";
7457
10665
  const Icon = direction === "up" ? ArrowUp : direction === "down" ? ArrowDown : Minus;
7458
- const t = TEXT20[uiLanguage(useLocale())];
10666
+ const t = TEXT30[uiLanguage(useLocale())];
7459
10667
  const ariaLabel = direction === "neutral" ? t.flat(value) : direction === "up" ? t.up(value) : t.down(value);
7460
10668
  return /* @__PURE__ */ jsxs(
7461
10669
  "span",
@@ -7476,93 +10684,6 @@ var TrendIndicator = forwardRef(
7476
10684
  }
7477
10685
  );
7478
10686
  TrendIndicator.displayName = "TrendIndicator";
7479
- var STATUS_LABELS = {
7480
- ja: {
7481
- success: "\u6B63\u5E38",
7482
- partial: "\u4E00\u90E8\u5931\u6557",
7483
- failed: "\u5931\u6557",
7484
- delayed: "\u9045\u5EF6",
7485
- running: "\u5B9F\u884C\u4E2D",
7486
- stopped: "\u505C\u6B62\u4E2D",
7487
- active: "\u6709\u52B9",
7488
- inactive: "\u7121\u52B9",
7489
- warning: "\u8B66\u544A",
7490
- error: "\u30A8\u30E9\u30FC",
7491
- pending: "\u4FDD\u7559\u4E2D"
7492
- },
7493
- en: {
7494
- success: "Healthy",
7495
- partial: "Partially failed",
7496
- failed: "Failed",
7497
- delayed: "Delayed",
7498
- running: "Running",
7499
- stopped: "Stopped",
7500
- active: "Active",
7501
- inactive: "Inactive",
7502
- warning: "Warning",
7503
- error: "Error",
7504
- pending: "Pending"
7505
- }
7506
- };
7507
- var STATUS_VOCABULARY = {
7508
- success: { label: STATUS_LABELS.en.success, tone: "positive" },
7509
- partial: { label: STATUS_LABELS.en.partial, tone: "warning" },
7510
- failed: { label: STATUS_LABELS.en.failed, tone: "negative" },
7511
- delayed: { label: STATUS_LABELS.en.delayed, tone: "warning" },
7512
- running: { label: STATUS_LABELS.en.running, tone: "info" },
7513
- stopped: { label: STATUS_LABELS.en.stopped, tone: "neutral" },
7514
- active: { label: STATUS_LABELS.en.active, tone: "positive" },
7515
- inactive: { label: STATUS_LABELS.en.inactive, tone: "neutral" },
7516
- warning: { label: STATUS_LABELS.en.warning, tone: "warning" },
7517
- error: { label: STATUS_LABELS.en.error, tone: "negative" },
7518
- pending: { label: STATUS_LABELS.en.pending, tone: "info" }
7519
- };
7520
- function statusLabel(status, locale) {
7521
- return Object.hasOwn(STATUS_VOCABULARY, status) ? STATUS_LABELS[uiLanguage(resolveLocale(locale))][status] : status;
7522
- }
7523
- var defaultColorMap = Object.fromEntries(
7524
- Object.entries(STATUS_VOCABULARY).map(([key, { tone }]) => [key, tone])
7525
- );
7526
- var legacyColorTones = {
7527
- green: "positive",
7528
- gray: "neutral",
7529
- yellow: "warning",
7530
- red: "negative",
7531
- blue: "info"
7532
- };
7533
- var toneStyles = {
7534
- positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive", border: "border-positive/20 dark:border-positive/25" },
7535
- negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative", border: "border-negative/20 dark:border-negative/25" },
7536
- warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning", border: "border-warning/20 dark:border-warning/25" },
7537
- info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info", border: "border-info/20 dark:border-info/25" },
7538
- neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral", border: "border-neutral/20 dark:border-neutral/25" }
7539
- };
7540
- var resolveTone = (color) => {
7541
- if (color === void 0) return "neutral";
7542
- if (Object.hasOwn(toneStyles, color)) return color;
7543
- return legacyColorTones[color] ?? "neutral";
7544
- };
7545
- var StatusBadge = forwardRef(function StatusBadge2({ status, label: label2, colorMap, className }, ref) {
7546
- const locale = useLocale();
7547
- const mergedColorMap = { ...defaultColorMap, ...colorMap };
7548
- const style = toneStyles[resolveTone(mergedColorMap[status])];
7549
- const displayLabel = label2 ?? statusLabel(status, locale);
7550
- return /* @__PURE__ */ jsxs(
7551
- Badge,
7552
- {
7553
- ref,
7554
- "data-slot": "status-badge",
7555
- variant: "outline",
7556
- className: cn("gap-1.5 rounded-md", style.border, style.bg, style.text, className),
7557
- "aria-label": displayLabel,
7558
- children: [
7559
- /* @__PURE__ */ jsx("span", { className: cn("inline-block size-1.5 rounded-full", style.dot), "aria-hidden": "true" }),
7560
- displayLabel
7561
- ]
7562
- }
7563
- );
7564
- });
7565
- StatusBadge.displayName = "StatusBadge";
7566
10687
  var Placeholder = forwardRef(function Placeholder2({ className, ...props }, ref) {
7567
10688
  return /* @__PURE__ */ jsx(
7568
10689
  "span",
@@ -7575,7 +10696,69 @@ var Placeholder = forwardRef(function Placeholder2({ className, ...props }, ref)
7575
10696
  );
7576
10697
  });
7577
10698
  Placeholder.displayName = "Placeholder";
10699
+ function DraftChart({ children }) {
10700
+ if (!import.meta.env.DEV) return null;
10701
+ return /* @__PURE__ */ jsx(DraftChartPreview, { children });
10702
+ }
10703
+ var STYLE_ID = "vantage-draft-chart";
10704
+ var DRAFT_CSS = `@layer components {
10705
+ [data-sq-draft] {
10706
+ position: relative;
10707
+ isolation: isolate;
10708
+ }
10709
+ [data-sq-draft]::after {
10710
+ content: "";
10711
+ position: absolute;
10712
+ inset: -1px;
10713
+ z-index: 2147483647;
10714
+ border-radius: inherit;
10715
+ background-color: var(--background);
10716
+ opacity: 0.75;
10717
+ pointer-events: none;
10718
+ transition: opacity 200ms ease;
10719
+ }
10720
+ [data-sq-draft]:hover::after {
10721
+ opacity: 0;
10722
+ }
10723
+ @media (prefers-reduced-motion: reduce) {
10724
+ [data-sq-draft]::after {
10725
+ transition: none;
10726
+ }
10727
+ }
10728
+ }`;
10729
+ function DraftChartPreview({ children }) {
10730
+ const ref = useRef(null);
10731
+ useInsertionEffect(() => {
10732
+ let style = document.getElementById(STYLE_ID);
10733
+ if (!style) {
10734
+ style = document.createElement("style");
10735
+ style.id = STYLE_ID;
10736
+ document.head.appendChild(style);
10737
+ }
10738
+ if (style.textContent !== DRAFT_CSS) style.textContent = DRAFT_CSS;
10739
+ }, []);
10740
+ useLayoutEffect(() => {
10741
+ const wrapper = ref.current;
10742
+ if (!wrapper) return;
10743
+ let marked = null;
10744
+ const mark = () => {
10745
+ const root = wrapper.firstElementChild;
10746
+ if (root === marked) return;
10747
+ marked?.removeAttribute("data-sq-draft");
10748
+ root?.setAttribute("data-sq-draft", "");
10749
+ marked = root;
10750
+ };
10751
+ mark();
10752
+ const observer = new MutationObserver(mark);
10753
+ observer.observe(wrapper, { childList: true });
10754
+ return () => {
10755
+ observer.disconnect();
10756
+ marked?.removeAttribute("data-sq-draft");
10757
+ };
10758
+ }, []);
10759
+ return /* @__PURE__ */ jsx("div", { ref, "data-slot": "draft-chart", style: { display: "contents" }, children });
10760
+ }
7578
10761
 
7579
- export { AppShell, AreaChart, BarChart, BarList, COMPARISON_LABELS, CategoryBar, ChartFrame, DEFAULT_SAMPLE_LABEL, DELTA_NOT_COMPARABLE, DashboardCard, DashboardCardAction, DashboardCardContent, DashboardCardDescription, DashboardCardFooter, DashboardCardHeader, DashboardCardPreset, DashboardCardSkeleton, DashboardCardTitle, DataTable, DataTableColumnVisibility, DataTableContent, DataTableExport, DataTablePagination, DataTablePreset, DataTableToolbar, DateRangePicker, Delta, DonutChart, FilterBar, FilterBarActiveChips, FilterBarClearButton, FilterBarMultiSelect, FilterBarPreset, FilterBarSelect, FunnelSteps, Heatmap, KpiCard, Legend, LineChart, MetricUnit, MetricValue, MultiSelect, PageShell, PageShellActions, PageShellContent, PageShellDescription, PageShellHeader, PageShellHeaderEnd, PageShellHeading, PageShellMeta, PageShellSummary, PageShellSummaryCard, PageShellTitle, Placeholder, ProgressCircle, RECORD_MIN_POINTS, SampleBadge, SampleClaim, SampleData, ScatterChart, SearchableSelect, SectionHeader, SegmentedControl, StatusBadge, Tracker, TrendIndicator, UpdatedAt, WaterfallChart, comparisonBaseline, comparisonLabel, computeComparison, computeTargetProgress, defaultChangeDisplay, defaultPresets, deltaVariants, detectRecord, fillKpiTemplate, flattenOptions, formatChange, formatChangeAmount, formatRelativeTime, funnelStepsVariants, inferPeriodGrain, isGroupedOptions, metricValueVariants, pageShellSummaryCardVariants, tableToCsv, toCsv, toneForValue, useDataTable, useSampleMark };
7580
- //# sourceMappingURL=chunk-77CISBMG.js.map
7581
- //# sourceMappingURL=chunk-77CISBMG.js.map
10762
+ 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 };
10763
+ //# sourceMappingURL=chunk-YJQCB3UP.js.map
10764
+ //# sourceMappingURL=chunk-YJQCB3UP.js.map