@squadbase/vantage 0.6.2-dev1.48b34e1 → 0.6.2-dev1.51e401a

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 (71) hide show
  1. package/dist/{chunk-57GHR5LN.js → chunk-3RJEOP3J.js} +29 -18
  2. package/dist/chunk-3RJEOP3J.js.map +1 -0
  3. package/dist/{chunk-QOXXOFGL.js → chunk-77CISBMG.js} +994 -464
  4. package/dist/chunk-77CISBMG.js.map +1 -0
  5. package/dist/{chunk-JXFCSF3K.js → chunk-EG4PX726.js} +12 -7
  6. package/dist/chunk-EG4PX726.js.map +1 -0
  7. package/dist/{chunk-2N72FKLB.js → chunk-NZ5QIIG4.js} +33 -11
  8. package/dist/chunk-NZ5QIIG4.js.map +1 -0
  9. package/dist/{chunk-7S52M2SL.js → chunk-QNOX7WLZ.js} +3 -3
  10. package/dist/{chunk-7S52M2SL.js.map → chunk-QNOX7WLZ.js.map} +1 -1
  11. package/dist/{chunk-PDOBHMUQ.js → chunk-ROHNXP7J.js} +72 -3
  12. package/dist/chunk-ROHNXP7J.js.map +1 -0
  13. package/dist/{chunk-6OTTGAPO.js → chunk-TRMHNMMZ.js} +24 -7
  14. package/dist/chunk-TRMHNMMZ.js.map +1 -0
  15. package/dist/components/index.d.ts +49 -29
  16. package/dist/components/index.js +5 -5
  17. package/dist/{delta-text-CvwBGJ95.d.ts → delta-text-CbrOaW83.d.ts} +4 -2
  18. package/dist/doc/index.d.ts +14 -14
  19. package/dist/doc/index.js +198 -84
  20. package/dist/doc/index.js.map +1 -1
  21. package/dist/{format-U0cQl069.d.ts → format-DihQkL1N.d.ts} +17 -11
  22. package/dist/slide/index.d.ts +2 -2
  23. package/dist/slide/index.js +95 -44
  24. package/dist/slide/index.js.map +1 -1
  25. package/dist/table/index.js +6 -6
  26. package/dist/ui/index.d.ts +1 -1
  27. package/dist/ui/index.js +5 -5
  28. package/package.json +2 -2
  29. package/registry/ui/app-shell.tsx +138 -1
  30. package/registry/ui/area-chart.tsx +344 -85
  31. package/registry/ui/attention-list.tsx +177 -15
  32. package/registry/ui/bar-chart.tsx +341 -85
  33. package/registry/ui/bar-list.tsx +332 -77
  34. package/registry/ui/box-plot-chart.tsx +405 -97
  35. package/registry/ui/category-bar.tsx +248 -40
  36. package/registry/ui/chart-frame.tsx +257 -46
  37. package/registry/ui/data-table.tsx +229 -37
  38. package/registry/ui/date-range-picker.tsx +190 -36
  39. package/registry/ui/delta.tsx +171 -12
  40. package/registry/ui/donut-chart.tsx +339 -84
  41. package/registry/ui/echart.tsx +142 -4
  42. package/registry/ui/filter-bar.tsx +179 -20
  43. package/registry/ui/funnel-steps.tsx +354 -80
  44. package/registry/ui/heatmap.tsx +293 -52
  45. package/registry/ui/histogram-chart.tsx +395 -97
  46. package/registry/ui/kpi-card.tsx +245 -44
  47. package/registry/ui/legend.tsx +330 -76
  48. package/registry/ui/line-chart.tsx +344 -85
  49. package/registry/ui/multi-select.tsx +159 -9
  50. package/registry/ui/page-shell.tsx +141 -3
  51. package/registry/ui/paired-chart.tsx +349 -90
  52. package/registry/ui/progress-circle.tsx +205 -39
  53. package/registry/ui/sample-data.tsx +153 -9
  54. package/registry/ui/scatter-chart.tsx +391 -100
  55. package/registry/ui/searchable-select.tsx +145 -7
  56. package/registry/ui/states.tsx +170 -13
  57. package/registry/ui/status-badge.tsx +193 -28
  58. package/registry/ui/tracker.tsx +205 -39
  59. package/registry/ui/trend-indicator.tsx +149 -6
  60. package/registry/ui/updated-at.tsx +170 -16
  61. package/registry/ui/waterfall-chart.tsx +415 -102
  62. package/skills/vantage-add-feature/SKILL.md +5 -0
  63. package/templates/AGENTS.md +10 -8
  64. package/templates/agents/api.md +7 -0
  65. package/templates/agents/page.md +36 -0
  66. package/dist/chunk-2N72FKLB.js.map +0 -1
  67. package/dist/chunk-57GHR5LN.js.map +0 -1
  68. package/dist/chunk-6OTTGAPO.js.map +0 -1
  69. package/dist/chunk-JXFCSF3K.js.map +0 -1
  70. package/dist/chunk-PDOBHMUQ.js.map +0 -1
  71. package/dist/chunk-QOXXOFGL.js.map +0 -1
@@ -1,8 +1,8 @@
1
- import { ChartFrameContext, useChartSurface, resolveChartColors, CHART_OTHER_COLOR, EChart, resolveFillColors } from './chunk-JXFCSF3K.js';
1
+ import { ChartFrameContext, useChartSurface, resolveChartColors, CHART_OTHER_COLOR, EChart, resolveFillColors } from './chunk-EG4PX726.js';
2
2
  import { Sparkline } from './chunk-2IAPIOPS.js';
3
- import { formatDateRange, EMPTY_VALUE, DEFAULT_LOCALE, formatDate, toValueFormatter, formatValue, formatPoints, formatKind, formatDelta, MINUS_SIGN, formatDatesInText } from './chunk-57GHR5LN.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-7S52M2SL.js';
5
- import { Button } from './chunk-PDOBHMUQ.js';
3
+ import { formatDateRange, EMPTY_VALUE, formatDate, toValueFormatter, formatValue, formatPoints, formatKind, formatDelta, MINUS_SIGN, formatDatesInText, DEFAULT_LOCALE } from './chunk-3RJEOP3J.js';
4
+ import { Tooltip, TooltipTrigger, TooltipContent, Badge, SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Checkbox, Card, CardHeader, CardDescription, CardTitle, CardAction, CardFooter } from './chunk-QNOX7WLZ.js';
5
+ import { useLocale, uiLanguage, Button, weekStartsOn, resolveLocale, defaultFiscalYearStartMonth, FALLBACK_LOCALE } from './chunk-ROHNXP7J.js';
6
6
  import { cn } from './chunk-U736PVHY.js';
7
7
  import { forwardRef, useState, useEffect, createContext, useId, useMemo, useRef, useCallback, Fragment as Fragment$1, useContext } from 'react';
8
8
  import { cva } from 'class-variance-authority';
@@ -13,7 +13,7 @@ import { GraphicComponent, VisualMapComponent } from 'echarts/components';
13
13
  import { ScatterChart as ScatterChart$1, HeatmapChart } from 'echarts/charts';
14
14
  import 'echarts';
15
15
  import { flexRender, useReactTable, getPaginationRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
16
- import { subMonths, subDays, endOfDay, startOfDay, startOfWeek, subWeeks, endOfWeek, startOfMonth, endOfMonth, isSameDay, format, addMonths } from 'date-fns';
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.
@@ -41,36 +41,50 @@ function formatRelativeTime(date, options) {
41
41
  const now = nowValue instanceof Date ? nowValue.getTime() : nowValue;
42
42
  if (!Number.isFinite(time) || !Number.isFinite(now)) return EMPTY_VALUE;
43
43
  const diff = time - now;
44
- const rtf = new Intl.RelativeTimeFormat(options?.locale ?? DEFAULT_LOCALE, { numeric: "always" });
44
+ const rtf = new Intl.RelativeTimeFormat(resolveLocale(options?.locale), { numeric: "always" });
45
45
  for (const [unit, size] of UNITS) {
46
46
  if (Math.abs(diff) >= size) return rtf.format(Math.trunc(diff / size), unit);
47
47
  }
48
48
  return rtf.format(Math.trunc(diff / SECOND), "second");
49
49
  }
50
50
  var REFRESH_MS = 6e4;
51
+ var TEXT = {
52
+ ja: {
53
+ justNow: "\u305F\u3063\u305F\u4ECA",
54
+ relative: (relative2) => `${relative2}\u306B\u66F4\u65B0`,
55
+ absoluteFirst: (shown, relative2) => `${shown} \u66F4\u65B0\uFF08${relative2}\uFF09`
56
+ },
57
+ en: {
58
+ justNow: "just now",
59
+ relative: (relative2) => `Updated ${relative2}`,
60
+ absoluteFirst: (shown, relative2) => `Updated ${shown} (${relative2})`
61
+ }
62
+ };
51
63
  var toMs = (value) => value instanceof Date ? value.getTime() : new Date(value).getTime();
52
- function relative(at, now) {
53
- if (now - at < REFRESH_MS && now - at > -REFRESH_MS) return "\u305F\u3063\u305F\u4ECA";
54
- return formatRelativeTime(at, { now });
64
+ function relative(at, now, locale) {
65
+ if (now - at < REFRESH_MS && now - at > -REFRESH_MS) return TEXT[uiLanguage(locale)].justNow;
66
+ return formatRelativeTime(at, { now, locale });
55
67
  }
56
- function absolute(at, timeZone) {
68
+ function absolute(at, locale, timeZone) {
57
69
  if (!Number.isFinite(at)) return void 0;
58
- const zone = new Intl.DateTimeFormat("ja-JP", { timeZone, timeZoneName: "short" }).formatToParts(at).find((part) => part.type === "timeZoneName")?.value;
59
- const text = formatDate(at, "datetime", "ja-JP", { timeZone });
70
+ const zone = new Intl.DateTimeFormat(locale, { timeZone, timeZoneName: "short" }).formatToParts(at).find((part) => part.type === "timeZoneName")?.value;
71
+ const text = formatDate(at, "datetime", locale, { timeZone });
60
72
  return zone ? `${text} ${zone}` : text;
61
73
  }
62
- function label(at, now, variant, timeZone) {
74
+ function label(at, now, variant, locale, timeZone) {
63
75
  if (!Number.isFinite(at) || !Number.isFinite(now)) return EMPTY_VALUE;
76
+ const t = TEXT[uiLanguage(locale)];
64
77
  if (variant === "relative") {
65
- return now - at < REFRESH_MS && now - at > -REFRESH_MS ? "\u305F\u3063\u305F\u4ECA" : `${relative(at, now)}\u306B\u66F4\u65B0`;
78
+ return now - at < REFRESH_MS && now - at > -REFRESH_MS ? uiLanguage(locale) === "ja" ? t.justNow : t.relative(t.justNow) : t.relative(relative(at, now, locale));
66
79
  }
67
- const today = formatDate(at, "date", "ja-JP", { timeZone }) === formatDate(now, "date", "ja-JP", { timeZone });
68
- const when = formatDate(at, "datetime", "ja-JP", { timeZone });
80
+ const today = formatDate(at, "date", locale, { timeZone }) === formatDate(now, "date", locale, { timeZone });
81
+ const when = formatDate(at, "datetime", locale, { timeZone });
69
82
  const shown = today ? when.slice(-5) : when;
70
- return `${shown} \u66F4\u65B0\uFF08${relative(at, now)}\uFF09`;
83
+ return t.absoluteFirst(shown, relative(at, now, locale));
71
84
  }
72
85
  var UpdatedAt = forwardRef(
73
86
  ({ at, variant = "relative", timeZone, prefix, now, className }, ref) => {
87
+ const locale = useLocale();
74
88
  const atMs = toMs(at);
75
89
  const [current, setCurrent] = useState(null);
76
90
  const fixed = now === void 0 ? void 0 : toMs(now);
@@ -83,9 +97,9 @@ var UpdatedAt = forwardRef(
83
97
  const clock = fixed ?? current;
84
98
  const ready = clock !== null;
85
99
  const dateTime = Number.isFinite(atMs) ? new Date(atMs).toISOString() : void 0;
86
- const full = ready ? absolute(atMs, timeZone) : void 0;
100
+ const full = ready ? absolute(atMs, locale, timeZone) : void 0;
87
101
  const classes = cn("text-sm text-muted-foreground tabular-nums", className);
88
- const text = ready ? `${prefix ?? ""}${label(atMs, clock, variant, timeZone)}` : null;
102
+ const text = ready ? `${prefix ?? ""}${label(atMs, clock, variant, locale, timeZone)}` : null;
89
103
  if (!full) {
90
104
  return /* @__PURE__ */ jsx("time", { ref, "data-slot": "updated-at", dateTime, className: classes, suppressHydrationWarning: true, children: text });
91
105
  }
@@ -116,9 +130,11 @@ var PageShell = forwardRef(
116
130
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "page-shell", className: cn("flex flex-col", className), ...props })
117
131
  );
118
132
  PageShell.displayName = "PageShell";
133
+ var SOURCE_PREFIX = { ja: "\u51FA\u5178\uFF1A", en: "Source: " };
119
134
  var PageShellHeader = forwardRef(
120
135
  ({ className, updatedAt, updatedAtVariant, timeZone, source, period, status, children, ...props }, ref) => {
121
- const periodText = period ? formatDateRange(period.start, period.end, { timeZone }) : void 0;
136
+ const locale = useLocale();
137
+ const periodText = period ? formatDateRange(period.start, period.end, { timeZone, locale }) : void 0;
122
138
  const hasChips = Boolean(source) || periodText !== void 0 && periodText !== EMPTY_VALUE;
123
139
  const hasStatus = status !== void 0 && status !== null && status !== false && status !== "";
124
140
  return /* @__PURE__ */ jsxs(
@@ -133,7 +149,7 @@ var PageShellHeader = forwardRef(
133
149
  updatedAt !== void 0 && updatedAt !== null ? /* @__PURE__ */ jsx("div", { "data-slot": "page-shell-updated-at", className: "ml-auto max-w-full shrink-0 text-right", children: /* @__PURE__ */ jsx(UpdatedAt, { at: updatedAt, variant: updatedAtVariant, timeZone }) }) : null,
134
150
  hasChips ? /* @__PURE__ */ jsxs("div", { "data-slot": "page-shell-chips", className: "order-1 flex basis-full flex-wrap gap-1.5", children: [
135
151
  source ? /* @__PURE__ */ jsxs(Badge, { variant: "outline", className: "h-auto max-w-full whitespace-normal text-muted-foreground", children: [
136
- "\u51FA\u5178\uFF1A",
152
+ SOURCE_PREFIX[uiLanguage(locale)],
137
153
  source
138
154
  ] }) : null,
139
155
  periodText && periodText !== EMPTY_VALUE ? /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "tabular-nums text-muted-foreground", children: periodText }) : null
@@ -301,6 +317,7 @@ var PageShellContent = forwardRef(
301
317
  )
302
318
  );
303
319
  PageShellContent.displayName = "PageShellContent";
320
+ var PAGE_PLACEHOLDER = { ja: "\u30DA\u30FC\u30B8\u3092\u9078\u629E", en: "Select a page" };
304
321
  function flattenItems(item) {
305
322
  if (item.children && item.children.length > 0) {
306
323
  return item.children.flatMap(flattenItems);
@@ -314,6 +331,7 @@ function NavSelect({
314
331
  const allItems = groups.flatMap((g) => g.items.flatMap(flattenItems));
315
332
  const currentValue = allItems.find((item) => item.isActive)?.href ?? "";
316
333
  const selectItems = allItems.map((item) => ({ value: item.href, label: item.label }));
334
+ const placeholder = PAGE_PLACEHOLDER[uiLanguage(useLocale())];
317
335
  return /* @__PURE__ */ jsxs(
318
336
  Select,
319
337
  {
@@ -323,7 +341,7 @@ function NavSelect({
323
341
  if (href !== null) onNavigate(href);
324
342
  },
325
343
  children: [
326
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u30DA\u30FC\u30B8\u3092\u9078\u629E" }) }),
344
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }),
327
345
  /* @__PURE__ */ jsx(
328
346
  SelectContent,
329
347
  {
@@ -496,8 +514,11 @@ var SectionHeader = forwardRef(
496
514
  )
497
515
  );
498
516
  SectionHeader.displayName = "SectionHeader";
499
- var DEFAULT_SAMPLE_LABEL = "\u898B\u672C\u306E\u5024";
500
- var SAMPLE_TITLE = "\u5B9F\u30C7\u30FC\u30BF\u306B\u307E\u3060\u3064\u306A\u304C\u3063\u3066\u3044\u306A\u3044\u898B\u672C\u306E\u5024\u3067\u3059";
517
+ var TEXT2 = {
518
+ ja: { label: "\u898B\u672C\u306E\u5024", title: "\u5B9F\u30C7\u30FC\u30BF\u306B\u307E\u3060\u3064\u306A\u304C\u3063\u3066\u3044\u306A\u3044\u898B\u672C\u306E\u5024\u3067\u3059" },
519
+ en: { label: "Sample data", title: "Sample values, not connected to real data yet" }
520
+ };
521
+ var DEFAULT_SAMPLE_LABEL = TEXT2.en.label;
501
522
  var SampleContext = createContext(null);
502
523
  function useSampleMark() {
503
524
  return useContext(SampleContext);
@@ -505,20 +526,22 @@ function useSampleMark() {
505
526
  function SampleClaim({ children }) {
506
527
  return /* @__PURE__ */ jsx(SampleContext.Provider, { value: null, children });
507
528
  }
508
- function SampleBadge({ label: label2 = DEFAULT_SAMPLE_LABEL, className, ...props }) {
529
+ function SampleBadge({ label: label2, className, ...props }) {
530
+ const t = TEXT2[uiLanguage(useLocale())];
509
531
  return /* @__PURE__ */ jsx(
510
532
  Badge,
511
533
  {
512
534
  "data-slot": "sample-badge",
513
- title: SAMPLE_TITLE,
535
+ title: t.title,
514
536
  className: cn("border-warning/20 dark:border-warning/25 bg-warning-subtle text-warning align-middle", className),
515
537
  ...props,
516
- children: label2
538
+ children: label2 ?? t.label
517
539
  }
518
540
  );
519
541
  }
520
- function SampleData({ label: label2 = DEFAULT_SAMPLE_LABEL, children }) {
521
- const state = useMemo(() => ({ label: label2 }), [label2]);
542
+ function SampleData({ label: label2, children }) {
543
+ const shown = label2 ?? TEXT2[uiLanguage(useLocale())].label;
544
+ const state = useMemo(() => ({ label: shown }), [shown]);
522
545
  return /* @__PURE__ */ jsx("div", { "data-slot": "sample-data", style: { display: "contents" }, children: /* @__PURE__ */ jsx(SampleContext.Provider, { value: state, children }) });
523
546
  }
524
547
  var SUBGRID_CLASS = {
@@ -652,7 +675,10 @@ function DashboardCardPreset({
652
675
  ] }) });
653
676
  }
654
677
  var DEFAULT_CHART_HEIGHT = 288;
655
- var DEFAULT_EMPTY_TITLE = "\u8868\u793A\u3067\u304D\u308B\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093";
678
+ var TEXT3 = {
679
+ ja: { emptyTitle: "\u8868\u793A\u3067\u304D\u308B\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093", loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D" },
680
+ en: { emptyTitle: "No data to display", loading: "Loading" }
681
+ };
656
682
  var ChartFrame = forwardRef(function ChartFrame2({
657
683
  title,
658
684
  summary,
@@ -669,6 +695,7 @@ var ChartFrame = forwardRef(function ChartFrame2({
669
695
  ...props
670
696
  }, ref) {
671
697
  const id = useId();
698
+ const t = TEXT3[uiLanguage(useLocale())];
672
699
  const titleId = title ? `${id}-title` : void 0;
673
700
  const summaryId = summary ? `${id}-summary` : void 0;
674
701
  const state = isLoading ? "loading" : isEmpty ? "empty" : "ready";
@@ -690,7 +717,7 @@ var ChartFrame = forwardRef(function ChartFrame2({
690
717
  "aria-busy": isLoading || void 0,
691
718
  className: "relative w-full min-w-0",
692
719
  style: { height: typeof height === "number" ? `${height}px` : height },
693
- children: state === "loading" ? /* @__PURE__ */ jsx(ChartSkeleton, { variant }) : state === "empty" ? /* @__PURE__ */ jsx(ChartEmpty, { ...emptyState }) : /* @__PURE__ */ jsx(ChartFrameContext.Provider, { value: true, children })
720
+ children: state === "loading" ? /* @__PURE__ */ jsx(ChartSkeleton, { variant, loadingText: t.loading }) : state === "empty" ? /* @__PURE__ */ jsx(ChartEmpty, { ...emptyState, defaultTitle: t.emptyTitle }) : /* @__PURE__ */ jsx(ChartFrameContext.Provider, { value: true, children })
694
721
  }
695
722
  ),
696
723
  state === "ready" && dataTable && dataTable.rows.length > 0 && /* @__PURE__ */ jsx(ChartDataTableView, { table: dataTable, fallbackCaption: title ?? ariaLabel })
@@ -700,14 +727,14 @@ ChartFrame.displayName = "ChartFrame";
700
727
  var BAR_HEIGHTS = [58, 74, 46, 88, 64, 80, 52];
701
728
  var LIST_WIDTHS = [92, 76, 64, 48, 36];
702
729
  var LINE_POINTS = "0,70 16,58 33,62 50,40 66,46 83,28 100,34";
703
- function ChartSkeleton({ variant }) {
730
+ function ChartSkeleton({ variant, loadingText }) {
704
731
  const pulse = "animate-pulse motion-reduce:animate-none";
705
732
  return /* @__PURE__ */ jsxs("div", { "data-slot": "chart-skeleton", "data-variant": variant, className: "absolute inset-0 flex flex-col gap-3", children: [
706
733
  /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "contents", children: variant === "list" ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-1 flex-col justify-around", pulse), children: LIST_WIDTHS.map((w) => /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsx("div", { className: "h-5 rounded-sm bg-muted", style: { width: `${w}%` } }) }, w)) }) : variant === "donut" ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-1 items-center justify-center", pulse), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 100 100", className: "h-full max-h-full w-auto text-muted", children: /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r: "40", fill: "none", stroke: "currentColor", strokeWidth: "14" }) }) }) : variant === "bar" ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-1 items-end gap-3 px-1", pulse), children: BAR_HEIGHTS.map((h, i) => /* @__PURE__ */ jsx("div", { className: "flex-1 rounded-t-sm bg-muted", style: { height: `${h}%` } }, i)) }) : (
707
734
  // A soft muted silhouette only — no stroke, no baseline, nothing that reads as a data line.
708
735
  /* @__PURE__ */ jsx("div", { className: cn("relative flex-1", pulse), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 100 100", preserveAspectRatio: "none", className: "absolute inset-0 h-full w-full text-muted", children: /* @__PURE__ */ jsx("polygon", { points: `${LINE_POINTS} 100,100 0,100`, fill: "currentColor", opacity: variant === "area" ? 0.8 : 0.5 }) }) })
709
736
  ) }),
710
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "\u8AAD\u307F\u8FBC\u307F\u4E2D" })
737
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: loadingText })
711
738
  ] });
712
739
  }
713
740
  function ChartDataTableView({ table, fallbackCaption }) {
@@ -720,14 +747,14 @@ function ChartDataTableView({ table, fallbackCaption }) {
720
747
  ) }, r)) })
721
748
  ] }) });
722
749
  }
723
- function ChartEmpty({ title, description, action }) {
750
+ function ChartEmpty({ title, description, action, defaultTitle }) {
724
751
  return /* @__PURE__ */ jsxs(
725
752
  "div",
726
753
  {
727
754
  "data-slot": "chart-empty",
728
755
  className: "absolute inset-0 flex flex-col items-center justify-center gap-1 rounded-md border border-dashed border-border p-6 text-center",
729
756
  children: [
730
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-balance", children: title ?? DEFAULT_EMPTY_TITLE }),
757
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-balance", children: title ?? defaultTitle }),
731
758
  description && /* @__PURE__ */ jsx("p", { className: "max-w-prose text-sm text-balance text-muted-foreground", children: description }),
732
759
  action && /* @__PURE__ */ jsx("div", { className: "mt-3", children: action })
733
760
  ]
@@ -776,37 +803,63 @@ function chartColorAt(colors, i) {
776
803
  function tintCss(cssColor, percent) {
777
804
  return `color-mix(in oklab, ${cssColor} ${percent}%, transparent)`;
778
805
  }
779
- function resolveValueFormatter(valueFormatter, format2, locale) {
780
- return valueFormatter ?? toValueFormatter(format2, locale);
806
+ function resolveValueFormatter(valueFormatter, format, locale) {
807
+ return valueFormatter ?? toValueFormatter(format, locale);
781
808
  }
782
- function resolveAxisFormatter(valueFormatter, format2, locale = DEFAULT_LOCALE) {
809
+ function resolveAxisFormatter(valueFormatter, format, localeArg) {
783
810
  if (valueFormatter) return valueFormatter;
784
- const spec = format2 === void 0 ? { type: "compact" } : typeof format2 === "string" ? { type: format2 } : format2;
785
- if (spec.type !== "compact" && spec.type !== "number" && spec.type !== "currency") return toValueFormatter(format2, locale);
811
+ const locale = resolveLocale(localeArg);
812
+ const spec = format === void 0 ? { type: "compact" } : typeof format === "string" ? { type: format } : format;
813
+ if (spec.type !== "compact" && spec.type !== "number" && spec.type !== "currency") return toValueFormatter(format, locale);
786
814
  const currency = "currency" in spec ? spec.currency : void 0;
787
815
  const short = spec.type === "currency" ? { type: "currency", currency, notation: "compact" } : { type: "compact" };
788
816
  return (value) => formatValue(value, short, locale);
789
817
  }
790
- var JA_UNITS = [
791
- { char: "\u5146", size: 1e12 },
792
- { char: "\u5104", size: 1e8 },
793
- { char: "\u4E07", size: 1e4 }
794
- ];
795
- var JA_NUMBER_TOKEN_RE = /\d[\d,]*(?:\.\d+)?(?:兆|億|万)?/;
796
- function resolveAxisTickFormatter(valueFormatter, format2, locale = DEFAULT_LOCALE) {
797
- const base = resolveAxisFormatter(valueFormatter, format2, locale);
798
- const spec = format2 === void 0 ? { type: "compact" } : typeof format2 === "string" ? { type: format2 } : format2;
799
- const aligns = !valueFormatter && locale.toLowerCase().startsWith("ja") && (spec.type === "compact" || spec.type === "number" || spec.type === "currency");
800
- if (!aligns) return () => base;
818
+ var compactUnitCache = /* @__PURE__ */ new Map();
819
+ function compactUnits(locale) {
820
+ const cached = compactUnitCache.get(locale);
821
+ if (cached !== void 0) return cached;
822
+ let units = [];
823
+ try {
824
+ const compact = new Intl.NumberFormat(locale, { notation: "compact" });
825
+ const seen = /* @__PURE__ */ new Set();
826
+ for (let exp = 3; exp <= 15; exp++) {
827
+ const parts = compact.formatToParts(10 ** exp);
828
+ const at = parts.findIndex((p) => p.type === "compact");
829
+ if (at === -1) continue;
830
+ if (parts[at - 1]?.type !== "integer" || at !== parts.length - 1) {
831
+ units = null;
832
+ break;
833
+ }
834
+ const token = parts[at].value;
835
+ if (seen.has(token)) continue;
836
+ seen.add(token);
837
+ units.push({ token, size: 10 ** exp });
838
+ }
839
+ } catch {
840
+ units = null;
841
+ }
842
+ const sorted = units && units.length > 0 ? units.sort((a, b) => b.size - a.size) : null;
843
+ compactUnitCache.set(locale, sorted);
844
+ return sorted;
845
+ }
846
+ var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
847
+ function resolveAxisTickFormatter(valueFormatter, format, localeArg) {
848
+ const locale = resolveLocale(localeArg);
849
+ const base = resolveAxisFormatter(valueFormatter, format, locale);
850
+ const spec = format === void 0 ? { type: "compact" } : typeof format === "string" ? { type: format } : format;
851
+ const units = !valueFormatter && (spec.type === "compact" || spec.type === "number" || spec.type === "currency") ? compactUnits(locale) : null;
852
+ if (!units) return () => base;
801
853
  const number = new Intl.NumberFormat(locale, { maximumFractionDigits: 3 });
854
+ const numberToken = new RegExp(`\\d[\\d,]*(?:\\.\\d+)?(?:${units.map((u) => escapeRegExp(u.token)).join("|")})?`);
802
855
  return (top) => {
803
- const unit = JA_UNITS.find((u) => Math.abs(top) >= u.size);
856
+ const unit = units.find((u) => Math.abs(top) >= u.size);
804
857
  if (!unit) return base;
805
858
  return (value) => {
806
859
  const text = base(value);
807
860
  if (value === 0 || !Number.isFinite(value)) return text;
808
- const scaled = `${number.format(Math.abs(value) / unit.size)}${unit.char}`;
809
- return text.replace(JA_NUMBER_TOKEN_RE, () => scaled);
861
+ const scaled = `${number.format(Math.abs(value) / unit.size)}${unit.token}`;
862
+ return text.replace(numberToken, () => scaled);
810
863
  };
811
864
  };
812
865
  }
@@ -823,8 +876,15 @@ function clamp(value, min, max) {
823
876
  return Math.min(max, Math.max(min, value));
824
877
  }
825
878
  var MAX_CHART_SERIES = 5;
826
- var OTHER_SERIES_LABEL = "\u305D\u306E\u4ED6";
827
- function aggregateTopN(items, n = MAX_CHART_SERIES, otherLabel = OTHER_SERIES_LABEL) {
879
+ var OTHER_SERIES_LABELS = { ja: "\u305D\u306E\u4ED6", en: "Other" };
880
+ function otherSeriesLabel(locale) {
881
+ return OTHER_SERIES_LABELS[uiLanguage(resolveLocale(locale))];
882
+ }
883
+ var OTHER_NAMES = new Set(Object.values(OTHER_SERIES_LABELS));
884
+ function isOtherName(name) {
885
+ return typeof name === "string" && OTHER_NAMES.has(name);
886
+ }
887
+ function aggregateTopN(items, n = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
828
888
  if (items.length <= n) return { top: [...items], rest: [], other: null };
829
889
  const ranked = items.map((item, i) => ({ item, i })).sort((a, b) => b.item.value - a.item.value || a.i - b.i);
830
890
  const keep = new Set(ranked.slice(0, n).map((r) => r.i));
@@ -832,7 +892,7 @@ function aggregateTopN(items, n = MAX_CHART_SERIES, otherLabel = OTHER_SERIES_LA
832
892
  const rest = items.filter((_, i) => !keep.has(i));
833
893
  return { top, rest, other: { name: otherLabel, value: rest.reduce((sum, item) => sum + item.value, 0) } };
834
894
  }
835
- function aggregateSeries(data, categories, n = MAX_CHART_SERIES, otherLabel = OTHER_SERIES_LABEL) {
895
+ function aggregateSeries(data, categories, n = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
836
896
  const totals = categories.map((name) => ({
837
897
  name,
838
898
  value: data.reduce((sum, row) => sum + (toChartNumber(row[name]) ?? 0), 0)
@@ -853,12 +913,13 @@ function aggregateSeries(data, categories, n = MAX_CHART_SERIES, otherLabel = OT
853
913
  otherCategory: other.name
854
914
  };
855
915
  }
856
- function aggregateSeriesKeeping(data, categories, keep, n = MAX_CHART_SERIES) {
857
- if (keep === void 0 || !categories.includes(keep)) return aggregateSeries(data, categories, n);
916
+ function aggregateSeriesKeeping(data, categories, keep, n = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
917
+ if (keep === void 0 || !categories.includes(keep)) return aggregateSeries(data, categories, n, otherLabel);
858
918
  const aggregated = aggregateSeries(
859
919
  data,
860
920
  categories.filter((c) => c !== keep),
861
- n
921
+ n,
922
+ otherLabel
862
923
  );
863
924
  return { ...aggregated, categories: [...aggregated.categories, keep] };
864
925
  }
@@ -880,7 +941,7 @@ function seriesColorsFor(categories, colors, otherColor, otherCategory = null, a
880
941
  const list = Array.isArray(colors) ? colors : void 0;
881
942
  const record = !Array.isArray(colors) && colors ? colors : void 0;
882
943
  return categories.map((category, i) => {
883
- if (otherCategory !== null && category === otherCategory || category === OTHER_SERIES_LABEL) return otherColor;
944
+ if (otherCategory !== null && category === otherCategory || isOtherName(category)) return otherColor;
884
945
  const fromRecord = record?.[category];
885
946
  if (fromRecord) return fromRecord;
886
947
  if (list && list.length > 0) {
@@ -890,7 +951,7 @@ function seriesColorsFor(categories, colors, otherColor, otherCategory = null, a
890
951
  return DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length];
891
952
  });
892
953
  }
893
- function donutSlices(data, { index, value, colors, maxSlices = MAX_CHART_SERIES, otherColor, otherLabel = OTHER_SERIES_LABEL }) {
954
+ function donutSlices(data, { index, value, colors, maxSlices = MAX_CHART_SERIES, otherColor, otherLabel = otherSeriesLabel() }) {
894
955
  const items = data.map((row, i) => {
895
956
  const n = toChartNumber(row[value]);
896
957
  return { name: String(row[index] ?? ""), value: n !== null && n > 0 ? n : 0, row, i };
@@ -900,7 +961,8 @@ function donutSlices(data, { index, value, colors, maxSlices = MAX_CHART_SERIES,
900
961
  const slices = top.map((item, rank) => ({
901
962
  name: item.name,
902
963
  value: item.value,
903
- color: palette[rank % palette.length],
964
+ // A row the data itself names「その他」/ "Other" is the same remainder: grey, like the folded slice.
965
+ color: isOtherName(item.name) ? otherColor : palette[rank % palette.length],
904
966
  isOther: false,
905
967
  row: item.row
906
968
  }));
@@ -921,7 +983,7 @@ function sortBarListData(data, sortOrder) {
921
983
  else if (sortOrder === "descending") rows.sort((a, b) => b.value - a.value);
922
984
  return rows;
923
985
  }
924
- function barListRows(data, { index = "name", category = "value", sortOrder = "descending", maxItems = MAX_CHART_SERIES, otherLabel = OTHER_SERIES_LABEL, exclude } = {}) {
986
+ function barListRows(data, { index = "name", category = "value", sortOrder = "descending", maxItems = MAX_CHART_SERIES, otherLabel = otherSeriesLabel(), exclude } = {}) {
925
987
  const items = data.map((row) => {
926
988
  const cells = row;
927
989
  const name = String(cells[index] ?? "");
@@ -955,7 +1017,7 @@ var BAR_LIST_TINT = 45;
955
1017
  var BAR_LIST_OTHER_TINT = 30;
956
1018
  function barListFills(rows, color, otherColor) {
957
1019
  return rows.map(
958
- (row) => row.isOther ? tintCss(otherColor, BAR_LIST_OTHER_TINT) : tintCss(chartColorToCss(row.color ?? color), BAR_LIST_TINT)
1020
+ (row) => row.isOther || isOtherName(row.name) ? tintCss(otherColor, BAR_LIST_OTHER_TINT) : tintCss(chartColorToCss(row.color ?? color), BAR_LIST_TINT)
959
1021
  );
960
1022
  }
961
1023
  function barListShareText(value, total) {
@@ -1052,6 +1114,22 @@ function progressCircleGeometry(value, max, radius, strokeWidth) {
1052
1114
  const circumference = 2 * Math.PI * normalizedRadius;
1053
1115
  return { size: radius * 2, normalizedRadius, circumference, offset: circumference * (1 - ratio), ratio };
1054
1116
  }
1117
+ var SUMMARY_TEXT = {
1118
+ ja: {
1119
+ up: "\u3001\u524D\u306E\u70B9\u3088\u308A\u5897\u52A0",
1120
+ down: "\u3001\u524D\u306E\u70B9\u3088\u308A\u6E1B\u5C11",
1121
+ flat: "\u3001\u524D\u306E\u70B9\u3068\u6A2A\u3070\u3044",
1122
+ latest: (label2, value) => `\u6700\u65B0 ${label2} \u306F ${value}`,
1123
+ top: (name, share) => `\u6700\u5927\u306F ${name}(${share})`
1124
+ },
1125
+ en: {
1126
+ up: ", up from the previous point",
1127
+ down: ", down from the previous point",
1128
+ flat: ", flat from the previous point",
1129
+ latest: (label2, value) => `Latest ${label2}: ${value}`,
1130
+ top: (name, share) => `Largest: ${name} (${share})`
1131
+ }
1132
+ };
1055
1133
  function buildChartSummary(input) {
1056
1134
  const key = input.categories[0];
1057
1135
  if (key === void 0) return void 0;
@@ -1063,54 +1141,96 @@ function buildChartSummary(input) {
1063
1141
  }
1064
1142
  const latest = points[points.length - 1];
1065
1143
  if (!latest) return void 0;
1066
- const text = input.valueFormatter ?? toValueFormatter(input.format ?? "compact");
1144
+ const locale = resolveLocale(input.locale);
1145
+ const t = SUMMARY_TEXT[uiLanguage(locale)];
1146
+ const text = input.valueFormatter ?? toValueFormatter(input.format ?? "compact", locale);
1067
1147
  const prev = points[points.length - 2];
1068
- const direction = !prev ? "" : latest.value > prev.value ? "\u3001\u524D\u306E\u70B9\u3088\u308A\u5897\u52A0" : latest.value < prev.value ? "\u3001\u524D\u306E\u70B9\u3088\u308A\u6E1B\u5C11" : "\u3001\u524D\u306E\u70B9\u3068\u6A2A\u3070\u3044";
1148
+ const direction = !prev ? "" : latest.value > prev.value ? t.up : latest.value < prev.value ? t.down : t.flat;
1069
1149
  const head = input.title ? `${input.title}: ` : "";
1070
- return `${head}\u6700\u65B0 ${latest.label} \u306F ${text(latest.value)}${direction}`;
1150
+ return `${head}${t.latest(latest.label, text(latest.value))}${direction}`;
1071
1151
  }
1072
- function buildShareSummary(slices, title) {
1152
+ function buildShareSummary(slices, title, locale) {
1073
1153
  const total = slices.reduce((sum, s) => sum + s.value, 0);
1074
1154
  const top = slices[0];
1075
1155
  if (!top || total <= 0) return void 0;
1076
1156
  const share = `${Math.round(top.value / total * 1e3) / 10}%`;
1077
- return `${title ? `${title}: ` : ""}\u6700\u5927\u306F ${top.name}(${share})`;
1157
+ return `${title ? `${title}: ` : ""}${SUMMARY_TEXT[uiLanguage(resolveLocale(locale))].top(top.name, share)}`;
1078
1158
  }
1079
1159
 
1080
1160
  // ../squadkit/registry/lib/comparison.ts
1081
1161
  var COMPARISON_LABELS = {
1082
- "prior-period": "\u524D\u671F\u6BD4",
1083
- "prior-year": "\u524D\u5E74\u540C\u671F\u6BD4",
1084
- target: "\u76EE\u6A19\u6BD4"
1162
+ "prior-period": "vs. prior period",
1163
+ "prior-year": "vs. same period last year",
1164
+ target: "vs. target"
1085
1165
  };
1086
1166
  var BASELINE_NOUNS = {
1087
- "prior-period": {
1088
- day: "\u524D\u65E5",
1089
- week: "\u524D\u9031",
1090
- month: "\u524D\u6708",
1091
- quarter: "\u524D\u56DB\u534A\u671F",
1092
- year: "\u524D\u5E74",
1093
- unknown: "\u524D\u671F"
1167
+ ja: {
1168
+ "prior-period": {
1169
+ day: "\u524D\u65E5",
1170
+ week: "\u524D\u9031",
1171
+ month: "\u524D\u6708",
1172
+ quarter: "\u524D\u56DB\u534A\u671F",
1173
+ year: "\u524D\u5E74",
1174
+ unknown: "\u524D\u671F"
1175
+ },
1176
+ "prior-year": {
1177
+ day: "\u524D\u5E74\u540C\u65E5",
1178
+ week: "\u524D\u5E74\u540C\u9031",
1179
+ month: "\u524D\u5E74\u540C\u6708",
1180
+ quarter: "\u524D\u5E74\u540C\u671F",
1181
+ year: "\u524D\u5E74",
1182
+ unknown: "\u524D\u5E74\u540C\u671F"
1183
+ },
1184
+ target: "\u76EE\u6A19",
1185
+ custom: "\u6BD4\u8F03\u5BFE\u8C61"
1094
1186
  },
1095
- "prior-year": {
1096
- day: "\u524D\u5E74\u540C\u65E5",
1097
- week: "\u524D\u5E74\u540C\u9031",
1098
- month: "\u524D\u5E74\u540C\u6708",
1099
- quarter: "\u524D\u5E74\u540C\u671F",
1100
- year: "\u524D\u5E74",
1101
- unknown: "\u524D\u5E74\u540C\u671F"
1187
+ en: {
1188
+ "prior-period": {
1189
+ day: "prior day",
1190
+ week: "prior week",
1191
+ month: "prior month",
1192
+ quarter: "prior quarter",
1193
+ year: "prior year",
1194
+ unknown: "prior period"
1195
+ },
1196
+ "prior-year": {
1197
+ day: "same day last year",
1198
+ week: "same week last year",
1199
+ month: "same month last year",
1200
+ quarter: "same quarter last year",
1201
+ year: "prior year",
1202
+ unknown: "same period last year"
1203
+ },
1204
+ target: "target",
1205
+ custom: "baseline"
1102
1206
  }
1103
1207
  };
1104
- function comparisonBaseline(vs, grain, label2, toDate2) {
1208
+ var LABEL_OF = {
1209
+ ja: (baseline) => `${baseline}\u6BD4`,
1210
+ en: (baseline) => `vs. ${baseline}`
1211
+ };
1212
+ function baselineOfLabel(named, language) {
1213
+ if (named.length > 1 && named.endsWith("\u6BD4")) return named.slice(0, -1);
1214
+ if (language === "en") {
1215
+ const stripped = named.replace(/^vs\.?\s+/i, "");
1216
+ if (stripped) return stripped;
1217
+ }
1218
+ return named;
1219
+ }
1220
+ function comparisonBaseline(vs, grain, label2, toDate2, locale) {
1221
+ const language = uiLanguage(resolveLocale(locale));
1222
+ const nouns = BASELINE_NOUNS[language];
1105
1223
  const named = label2?.trim();
1106
- if (named) return named.length > 1 && named.endsWith("\u6BD4") ? named.slice(0, -1) : named;
1107
- if (vs === "custom") return "\u6BD4\u8F03\u5BFE\u8C61";
1108
- if (vs === "target") return "\u76EE\u6A19";
1109
- if (vs === "prior-year" && toDate2) return BASELINE_NOUNS["prior-year"].unknown;
1110
- return BASELINE_NOUNS[vs][grain ?? "unknown"];
1224
+ if (named) return baselineOfLabel(named, language);
1225
+ if (vs === "custom") return nouns.custom;
1226
+ if (vs === "target") return nouns.target;
1227
+ if (vs === "prior-year" && toDate2) return nouns["prior-year"].unknown;
1228
+ return nouns[vs][grain ?? "unknown"];
1111
1229
  }
1112
- function comparisonLabel(vs, grain, label2, toDate2) {
1113
- return label2?.trim() ? label2 : `${comparisonBaseline(vs, grain, void 0, toDate2)}\u6BD4`;
1230
+ function comparisonLabel(vs, grain, label2, toDate2, locale) {
1231
+ if (label2?.trim()) return label2;
1232
+ const resolved = resolveLocale(locale);
1233
+ return LABEL_OF[uiLanguage(resolved)](comparisonBaseline(vs, grain, void 0, toDate2, resolved));
1114
1234
  }
1115
1235
  var toNumber = (v) => v === null || v === void 0 || Number.isNaN(v) ? null : v;
1116
1236
  function computeComparison(current, comparison, options) {
@@ -1118,7 +1238,7 @@ function computeComparison(current, comparison, options) {
1118
1238
  const neutralBand = options?.neutralBand ?? 0.01;
1119
1239
  const cur = toNumber(current);
1120
1240
  const prev = toNumber(comparison.previous);
1121
- const label2 = comparisonLabel(comparison.vs, comparison.grain, comparison.label, comparison.toDate);
1241
+ const label2 = comparisonLabel(comparison.vs, comparison.grain, comparison.label, comparison.toDate, options?.locale);
1122
1242
  const difference = cur !== null && prev !== null ? cur - prev : null;
1123
1243
  const ratio = difference !== null && prev !== null && prev !== 0 ? difference / Math.abs(prev) : null;
1124
1244
  let direction;
@@ -1131,20 +1251,20 @@ function computeComparison(current, comparison, options) {
1131
1251
  else if (direction === "down") sentiment = polarity === "higher-is-better" ? "negative" : "positive";
1132
1252
  return { current: cur, previous: prev, difference, ratio, direction, sentiment, label: label2, vs: comparison.vs };
1133
1253
  }
1134
- function defaultChangeDisplay(format2) {
1135
- return formatKind(format2) === "percent" ? "points" : "relative";
1254
+ function defaultChangeDisplay(format) {
1255
+ return formatKind(format) === "percent" ? "points" : "relative";
1136
1256
  }
1137
- function formatChange(result, display = "relative", locale = DEFAULT_LOCALE, format2, digits) {
1257
+ function formatChange(result, display = "relative", locale, format, digits) {
1138
1258
  if (result.direction === "none") return null;
1139
- if (display === "difference") return result.difference === null ? null : formatDelta(result.difference, format2, locale);
1259
+ if (display === "difference") return result.difference === null ? null : formatDelta(result.difference, format, locale);
1140
1260
  if (display === "points")
1141
1261
  return result.difference === null ? null : formatPoints(result.difference, locale, digits === void 0 ? void 0 : { digits });
1142
1262
  return result.ratio === null ? null : formatDelta(result.ratio, digits === void 0 ? "percent" : { type: "percent", digits }, locale);
1143
1263
  }
1144
- function formatChangeAmount(result, display = "relative", locale = DEFAULT_LOCALE, format2, digits) {
1264
+ function formatChangeAmount(result, display = "relative", locale, format, digits) {
1145
1265
  if (result.direction === "none") return null;
1146
1266
  if (display === "difference")
1147
- return result.difference === null ? null : formatValue(Math.abs(result.difference), format2, locale);
1267
+ return result.difference === null ? null : formatValue(Math.abs(result.difference), format, locale);
1148
1268
  if (display === "points")
1149
1269
  return result.difference === null ? null : formatPoints(result.difference, locale, { signDisplay: "never", ...digits === void 0 ? {} : { digits } });
1150
1270
  return result.ratio === null ? null : formatValue(Math.abs(result.ratio), digits === void 0 ? "percent" : { type: "percent", digits }, locale);
@@ -1163,6 +1283,29 @@ function toneForValue(value, thresholds) {
1163
1283
  }
1164
1284
 
1165
1285
  // ../squadkit/registry/lib/chart-options.ts
1286
+ var CHART_TEXT = {
1287
+ ja: {
1288
+ target: "\u76EE\u6A19",
1289
+ forecast: "\u4E88\u6E2C",
1290
+ total: "\u5408\u8A08",
1291
+ provisional: "\u901F\u5831",
1292
+ noComparison: "\u6BD4\u8F03\u306A\u3057",
1293
+ share: (share) => `\uFF08${share}\uFF09`,
1294
+ targetRate: (rate) => `\uFF08\u9054\u6210\u7387 ${rate}\uFF09`,
1295
+ provisionalTitle: (title, label2) => `${title}(${label2})`
1296
+ },
1297
+ en: {
1298
+ target: "Target",
1299
+ forecast: "Forecast",
1300
+ total: "Total",
1301
+ provisional: "Preliminary",
1302
+ noComparison: "No comparison",
1303
+ share: (share) => ` (${share})`,
1304
+ targetRate: (rate) => ` (${rate} achieved)`,
1305
+ provisionalTitle: (title, label2) => `${title} (${label2})`
1306
+ }
1307
+ };
1308
+ var chartText = (locale) => CHART_TEXT[uiLanguage(resolveLocale(locale))];
1166
1309
  function chartMotion(reducedMotion) {
1167
1310
  if (reducedMotion) return { animation: false };
1168
1311
  return { animation: true, animationDuration: 0, animationDurationUpdate: 300, animationEasingUpdate: "cubicOut" };
@@ -1227,12 +1370,12 @@ function parseTimeIndex(values) {
1227
1370
  var timeFormatCache = /* @__PURE__ */ new Map();
1228
1371
  function timeFormat(locale, options) {
1229
1372
  const key = `${locale}|${JSON.stringify(options)}`;
1230
- let format2 = timeFormatCache.get(key);
1231
- if (!format2) {
1232
- format2 = new Intl.DateTimeFormat(locale, options);
1233
- timeFormatCache.set(key, format2);
1373
+ let format = timeFormatCache.get(key);
1374
+ if (!format) {
1375
+ format = new Intl.DateTimeFormat(locale, options);
1376
+ timeFormatCache.set(key, format);
1234
1377
  }
1235
- return format2;
1378
+ return format;
1236
1379
  }
1237
1380
  var toDate = (t) => new Date(t.year, t.month - 1, t.day);
1238
1381
  var TIME_AXIS_MAX_LABELS = 6;
@@ -1251,9 +1394,10 @@ function timeAxisLabelStep(values, maxLabels = TIME_AXIS_MAX_LABELS) {
1251
1394
  const steps = TIME_AXIS_STEPS[parsed.granularity];
1252
1395
  return steps.find((step) => Math.ceil(count / step) <= max) ?? Math.ceil(count / max);
1253
1396
  }
1254
- function timeAxisLabels(values, locale = DEFAULT_LOCALE, shown = () => true) {
1397
+ function timeAxisLabels(values, localeArg, shown = () => true) {
1255
1398
  const parsed = parseTimeIndex(values);
1256
1399
  if (!parsed) return null;
1400
+ const locale = resolveLocale(localeArg);
1257
1401
  const { granularity, times } = parsed;
1258
1402
  let prevYear = null;
1259
1403
  return times.map((t, i) => {
@@ -1265,9 +1409,10 @@ function timeAxisLabels(values, locale = DEFAULT_LOCALE, shown = () => true) {
1265
1409
  return timeFormat(locale, options).format(toDate(t));
1266
1410
  });
1267
1411
  }
1268
- function timeTooltipLabels(values, locale = DEFAULT_LOCALE) {
1412
+ function timeTooltipLabels(values, localeArg) {
1269
1413
  const parsed = parseTimeIndex(values);
1270
1414
  if (!parsed) return null;
1415
+ const locale = resolveLocale(localeArg);
1271
1416
  const options = parsed.granularity === "year" ? { year: "numeric" } : parsed.granularity === "month" ? { year: "numeric", month: "long" } : { year: "numeric", month: "long", day: "numeric" };
1272
1417
  return parsed.times.map((t, i) => t === null ? String(values[i] ?? "") : timeFormat(locale, options).format(toDate(t)));
1273
1418
  }
@@ -1344,16 +1489,16 @@ function escapeHtml(value) {
1344
1489
  }
1345
1490
  var shareFormat = new Intl.NumberFormat(DEFAULT_LOCALE, { maximumFractionDigits: 1 });
1346
1491
  var formatShare = (share) => `${shareFormat.format(share)}%`;
1347
- function tooltipHtml(title, rows, valueFormatter, notes = []) {
1492
+ function tooltipHtml(title, rows, valueFormatter, notes = [], locale) {
1493
+ const t = chartText(locale);
1348
1494
  const lines = rows.map(
1349
- (row) => `<div style="display:flex;align-items:center;gap:8px;line-height:20px"><span style="display:inline-block;width:8px;height:8px;border-radius:9999px;background:${escapeHtml(row.color)}"></span><span style="flex:1;opacity:.8">${escapeHtml(row.name)}</span><span style="font-weight:600;font-variant-numeric:tabular-nums;margin-left:12px">${row.value === null ? EMPTY_VALUE : escapeHtml(valueFormatter(row.value))}${row.share === void 0 ? "" : `<span style="opacity:.6;margin-left:4px">\uFF08${escapeHtml(formatShare(row.share))}\uFF09</span>`}</span></div>` + (row.note === void 0 ? "" : `<div style="padding-left:16px;line-height:18px;font-size:12px;opacity:.7;font-variant-numeric:tabular-nums">${escapeHtml(row.note)}</div>`)
1495
+ (row) => `<div style="display:flex;align-items:center;gap:8px;line-height:20px"><span style="display:inline-block;width:8px;height:8px;border-radius:9999px;background:${escapeHtml(row.color)}"></span><span style="flex:1;opacity:.8">${escapeHtml(row.name)}</span><span style="font-weight:600;font-variant-numeric:tabular-nums;margin-left:12px">${row.value === null ? EMPTY_VALUE : escapeHtml(valueFormatter(row.value))}${row.share === void 0 ? "" : `<span style="opacity:.6;margin-left:4px">${escapeHtml(t.share(formatShare(row.share)))}</span>`}</span></div>` + (row.note === void 0 ? "" : `<div style="padding-left:16px;line-height:18px;font-size:12px;opacity:.7;font-variant-numeric:tabular-nums">${escapeHtml(row.note)}</div>`)
1350
1496
  );
1351
1497
  const noteLines = notes.map(
1352
1498
  (note) => `<div style="margin-top:4px;line-height:18px;font-size:12px;opacity:.7">${escapeHtml(note)}</div>`
1353
1499
  );
1354
1500
  return `<div style="font-weight:500;margin-bottom:4px">${escapeHtml(title)}</div>${lines.join("")}${noteLines.join("")}`;
1355
1501
  }
1356
- var BAR_TARGET_LABEL = "\u76EE\u6A19";
1357
1502
  var TARGET_MARKER_OVERHANG = 4;
1358
1503
  function targetMarkerRenderer(horizontalBars, barCategoryGap, color) {
1359
1504
  return (_params, api) => {
@@ -1379,10 +1524,10 @@ function achievementRate(value, target) {
1379
1524
  if (value === null || value === void 0 || target === null || target === void 0 || !(target > 0)) return null;
1380
1525
  return value / target * 100;
1381
1526
  }
1382
- function barTargetNote(label2, value, target, valueFormatter) {
1527
+ function barTargetNote(label2, value, target, valueFormatter, locale) {
1383
1528
  if (target === null) return null;
1384
1529
  const rate = achievementRate(value, target);
1385
- return `${label2} ${valueFormatter(target)}${rate === null ? "" : `\uFF08\u9054\u6210\u7387 ${formatShare(rate)}\uFF09`}`;
1530
+ return `${label2} ${valueFormatter(target)}${rate === null ? "" : chartText(locale).targetRate(formatShare(rate))}`;
1386
1531
  }
1387
1532
  function barHalfWidth(barCategoryGap) {
1388
1533
  const gap = typeof barCategoryGap === "string" && /^\d+(\.\d+)?%$/.test(barCategoryGap.trim()) ? parseFloat(barCategoryGap) / 100 : 0.2;
@@ -1430,9 +1575,8 @@ var OVERLAY_SERIES_ID = "__overlay";
1430
1575
  var TARGET_MARKER_SERIES_ID = "__target-marker";
1431
1576
  var TARGET_LEGEND_SERIES_ID = "__target-legend";
1432
1577
  var TARGET_LEGEND_ICON = "path://M0,0 L100,0 L100,24 L0,24 Z";
1433
- var DEFAULT_FORECAST_LABEL = "\u4E88\u6E2C";
1434
- function forecastBoundaryText(label2 = DEFAULT_FORECAST_LABEL) {
1435
- return `${label2} \u2192`;
1578
+ function forecastBoundaryText(label2, locale) {
1579
+ return `${label2 ?? chartText(locale).forecast} \u2192`;
1436
1580
  }
1437
1581
  var COMPARISON_LINE_WIDTH = 1.5;
1438
1582
  var COMPARISON_OPACITY = 0.6;
@@ -1458,7 +1602,6 @@ function isDarkSurface(color) {
1458
1602
  });
1459
1603
  return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.4;
1460
1604
  }
1461
- var STACK_TOTAL_LABEL = "\u5408\u8A08";
1462
1605
  function stackTotalsOf(values) {
1463
1606
  const length = Math.max(0, ...values.map((v) => v.length));
1464
1607
  return Array.from({ length }, (_, i) => {
@@ -1524,13 +1667,15 @@ function indexGrain(values) {
1524
1667
  const parsed = parseTimeIndex(values);
1525
1668
  return parsed ? parsed.granularity : null;
1526
1669
  }
1527
- function comparisonNote(current, previous, comparison, grain, format2, locale = DEFAULT_LOCALE) {
1670
+ function comparisonNote(current, previous, comparison, grain, format, localeArg) {
1671
+ const locale = resolveLocale(localeArg);
1528
1672
  const result = computeComparison(
1529
1673
  current,
1530
- comparison.vs === "custom" ? { previous, vs: "custom", label: comparison.label ?? "", grain } : { previous, vs: comparison.vs, label: comparison.label, grain }
1674
+ comparison.vs === "custom" ? { previous, vs: "custom", label: comparison.label ?? "", grain } : { previous, vs: comparison.vs, label: comparison.label, grain },
1675
+ { locale }
1531
1676
  );
1532
- const text = formatChange(result, defaultChangeDisplay(format2), locale, format2);
1533
- if (text === null) return `\u6BD4\u8F03\u306A\u3057 ${result.label}`;
1677
+ const text = formatChange(result, defaultChangeDisplay(format), locale, format);
1678
+ if (text === null) return `${chartText(locale).noComparison} ${result.label}`;
1534
1679
  const arrow = result.direction === "up" ? "\u2191" : result.direction === "down" ? "\u2193" : "\u2192";
1535
1680
  return `${arrow} ${text.replace(/^-/, "\u2212")} ${result.label}`;
1536
1681
  }
@@ -1555,7 +1700,6 @@ function buildCartesianOption(cfg) {
1555
1700
  toneColors,
1556
1701
  valueFormatter,
1557
1702
  axisFormatter = valueFormatter,
1558
- locale = DEFAULT_LOCALE,
1559
1703
  type = "default",
1560
1704
  layout = "horizontal",
1561
1705
  curveType = "linear",
@@ -1592,7 +1736,9 @@ function buildCartesianOption(cfg) {
1592
1736
  chartOptions,
1593
1737
  reserveActions = false
1594
1738
  } = cfg;
1595
- const provisionalLabel = cfg.provisionalLabel ?? DEFAULT_PROVISIONAL_LABEL;
1739
+ const locale = resolveLocale(cfg.locale);
1740
+ const text = chartText(locale);
1741
+ const provisionalLabel = cfg.provisionalLabel ?? text.provisional;
1596
1742
  const stacked = kind !== "line" && type !== "default";
1597
1743
  const percent = kind !== "line" && type === "percent";
1598
1744
  const horizontalBars = kind === "bar" && layout === "vertical";
@@ -1663,8 +1809,8 @@ function buildCartesianOption(cfg) {
1663
1809
  const edgeAlign = (i) => horizontalBars || labels.length < 2 ? void 0 : i === boundaryIndex && i !== last ? { align: "right", offset: [-6, 0] } : i === last ? { align: "right", ...kind === "bar" ? { offset: [8, 0] } : {} } : i === 0 ? { align: "left", ...kind === "bar" ? { offset: [-8, 0] } : {} } : void 0;
1664
1810
  const perBarTarget = kind === "bar" && Boolean(targetKey);
1665
1811
  const hasTarget = !perBarTarget && target !== void 0 && Number.isFinite(target);
1666
- const targetText = hasTarget ? targetLabel ?? `\u76EE\u6A19 ${axisFormatter(target)}` : "";
1667
- const highlightText = (value) => shareHighlight ? `${Math.round(value)}%` : `${stackTotals ? `${STACK_TOTAL_LABEL} ` : ""}${axisFormatter(value)}`;
1812
+ const targetText = hasTarget ? targetLabel ?? `${text.target} ${axisFormatter(target)}` : "";
1813
+ const highlightText = (value) => shareHighlight ? `${Math.round(value)}%` : `${stackTotals ? `${text.total} ` : ""}${axisFormatter(value)}`;
1668
1814
  const nearTargetLabel = (p, side) => {
1669
1815
  if (!hasTarget || !plotWidth || kind === "bar" || labels.length < 2) return false;
1670
1816
  if (side === "under" ? p.value > target : p.value <= target) return false;
@@ -1681,7 +1827,7 @@ function buildCartesianOption(cfg) {
1681
1827
  const below = (p) => !shareHighlight && !hideTargetLabel && nearTargetLabel(p, "under");
1682
1828
  const targetLabelBelow = !shareHighlight && !hideTargetLabel && highlightPoints.some((p) => nearTargetLabel(p, "over"));
1683
1829
  const barTargets = perBarTarget && targetKey && !percent && (stacked || categories.length === 1) ? barTargetValues(data, targetKey) : null;
1684
- const barTargetName = targetLabel ?? BAR_TARGET_LABEL;
1830
+ const barTargetName = targetLabel ?? text.target;
1685
1831
  const barTargetColor = labelColor ?? guideColor;
1686
1832
  const markPointFor = (c, color) => c === highlightSeries && highlightPoints.length > 0 ? {
1687
1833
  silent: true,
@@ -1860,7 +2006,7 @@ function buildCartesianOption(cfg) {
1860
2006
  data: []
1861
2007
  });
1862
2008
  }
1863
- const forecastLabel = forecast?.label ?? DEFAULT_FORECAST_LABEL;
2009
+ const forecastLabel = forecast?.label ?? text.forecast;
1864
2010
  const forecastBandAlpha = isDarkSurface(labelBackground) ? FORECAST_BAND_ALPHA_DARK : FORECAST_BAND_ALPHA_LIGHT;
1865
2011
  const forecastValues = [];
1866
2012
  if (forecast) {
@@ -2137,8 +2283,8 @@ function buildCartesianOption(cfg) {
2137
2283
  const top = percent ? 100 : maxValue ?? Math.max(0, ...(stacked ? stackTotalsOf(values) : values.flat()).map((v) => v ?? 0));
2138
2284
  const categoryColumn = showYAxis ? (yAxisWidth ?? Math.min(160, Math.max(0, ...labels.map(estimateTextWidth)))) + 8 : 0;
2139
2285
  const plot = plotWidth - categoryColumn - (highlightPoints.length > 0 ? 64 : 16) - 4;
2140
- const text = percent ? (v) => `${v}%` : (v) => axisFormatter(v);
2141
- return valueAxisSplitNumber(plot, [text(0), text(top)]);
2286
+ const text2 = percent ? (v) => `${v}%` : (v) => axisFormatter(v);
2287
+ return valueAxisSplitNumber(plot, [text2(0), text2(top)]);
2142
2288
  })();
2143
2289
  const limits = valueAxisLimits({ minValue, maxValue }, kind !== "line");
2144
2290
  const splitNumber = horizontalBars ? valueSplitNumber : valueAxisSplitCount(plotHeight);
@@ -2276,7 +2422,7 @@ function buildCartesianOption(cfg) {
2276
2422
  });
2277
2423
  }
2278
2424
  if (stackTotals && i <= lastActual && rows.length > 1) {
2279
- rows.push({ name: STACK_TOTAL_LABEL, color: "transparent", value: stackTotals[i] ?? null });
2425
+ rows.push({ name: text.total, color: "transparent", value: stackTotals[i] ?? null });
2280
2426
  }
2281
2427
  const provisional = provStart !== -1 && i >= provStart && i <= lastActual;
2282
2428
  if (provisional) {
@@ -2291,19 +2437,19 @@ function buildCartesianOption(cfg) {
2291
2437
  ...noteFor(at)
2292
2438
  });
2293
2439
  });
2294
- if (stackTotals && rows.length > 1) rows.push({ name: STACK_TOTAL_LABEL, color: "transparent", value: stackTotals[i] ?? null });
2440
+ if (stackTotals && rows.length > 1) rows.push({ name: text.total, color: "transparent", value: stackTotals[i] ?? null });
2295
2441
  }
2296
2442
  const title = tooltipTitles[i] ?? labels[i] ?? "";
2297
2443
  const lines = [];
2298
2444
  if (barTargets && i <= lastActual) {
2299
2445
  const total = stackTotals ? stackTotals[i] ?? null : values[0]?.[i] ?? null;
2300
- const note = barTargetNote(barTargetName, total, barTargets[i] ?? null, valueFormatter);
2446
+ const note = barTargetNote(barTargetName, total, barTargets[i] ?? null, valueFormatter, locale);
2301
2447
  if (note) lines.push(note);
2302
2448
  }
2303
2449
  for (const note of notes) {
2304
2450
  if (note.to === void 0 ? note.from === i : note.from <= i && i <= note.to) lines.push(note.label);
2305
2451
  }
2306
- return tooltipHtml(provisional ? `${title}(${provisionalLabel})` : title, rows, valueFormatter, lines);
2452
+ return tooltipHtml(provisional ? text.provisionalTitle(title, provisionalLabel) : title, rows, valueFormatter, lines, locale);
2307
2453
  }
2308
2454
  },
2309
2455
  xAxis: horizontalBars ? valueAxis : categoryAxis,
@@ -2332,7 +2478,6 @@ function donutTopText(slices, labels) {
2332
2478
  return top ? { label: labelOf(top.name, labels), amount: donutShareText(top.value, total) } : null;
2333
2479
  }
2334
2480
  var DONUT_OUTSIDE_LABELS = 2;
2335
- var DEFAULT_TOTAL_LABEL = "\u5408\u8A08";
2336
2481
  var sliceValue = (value) => Number.isFinite(value) && value > 0 ? value : 0;
2337
2482
  function donutShareText(value, total) {
2338
2483
  const v = sliceValue(value);
@@ -2344,7 +2489,8 @@ function donutLegendItems(slices) {
2344
2489
  const total = slices.reduce((sum, s) => sum + sliceValue(s.value), 0);
2345
2490
  return slices.map((s, slice) => ({ name: s.name, value: sliceValue(s.value), share: donutShareText(s.value, total), isOther: Boolean(s.isOther), slice })).sort((a, b) => Number(a.isOther) - Number(b.isOther) || b.value - a.value || a.slice - b.slice);
2346
2491
  }
2347
- function donutCenterText(total, valueFormatter, { totalLabel = DEFAULT_TOTAL_LABEL, unit } = {}) {
2492
+ function donutCenterText(total, valueFormatter, { totalLabel, unit, locale } = {}) {
2493
+ totalLabel ??= chartText(locale).total;
2348
2494
  const amount = valueFormatter(total);
2349
2495
  return { label: totalLabel, value: unit ? `${amount} ${unit}` : amount, amount, ...unit ? { unit } : {} };
2350
2496
  }
@@ -2464,7 +2610,6 @@ function labelRows(data, index, labels) {
2464
2610
  function hasLabel(labels, key) {
2465
2611
  return Boolean(labels) && Object.prototype.hasOwnProperty.call(labels, key);
2466
2612
  }
2467
- var DEFAULT_PROVISIONAL_LABEL = "\u901F\u5831";
2468
2613
  function provisionalStart(indexValues, from) {
2469
2614
  if (from === void 0 || from === null) return -1;
2470
2615
  const key = String(from);
@@ -2477,6 +2622,10 @@ function splitProvisional(values, start) {
2477
2622
  provisional: values.map((v, i) => i >= Math.max(0, start - 1) ? v : null)
2478
2623
  };
2479
2624
  }
2625
+ var TEXT4 = {
2626
+ ja: { item: "\u9805\u76EE", chart: (categories) => `${categories.join("\u30FB")}\u306E\u9762\u30B0\u30E9\u30D5` },
2627
+ en: { item: "Item", chart: (categories) => `Area chart of ${categories.join(", ")}` }
2628
+ };
2480
2629
  var NO_ROWS = [];
2481
2630
  function AreaChartImpl({
2482
2631
  data = NO_ROWS,
@@ -2485,7 +2634,7 @@ function AreaChartImpl({
2485
2634
  colors,
2486
2635
  labels,
2487
2636
  valueFormatter,
2488
- format: format2,
2637
+ format,
2489
2638
  title,
2490
2639
  summary,
2491
2640
  actions,
@@ -2525,12 +2674,17 @@ function AreaChartImpl({
2525
2674
  ...rest
2526
2675
  }, ref) {
2527
2676
  const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
2528
- const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format2), [valueFormatter, format2]);
2529
- const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format2), [valueFormatter, format2]);
2530
- const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format2), [valueFormatter, format2]);
2677
+ const locale = useLocale();
2678
+ const t = TEXT4[uiLanguage(locale)];
2679
+ const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
2680
+ const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
2681
+ const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
2531
2682
  const comparisonCategory = comparison && categories.includes(comparison.category) ? comparison.category : void 0;
2532
2683
  const comparisonConfig = comparisonCategory === void 0 ? void 0 : comparison;
2533
- const series = useMemo(() => aggregateSeriesKeeping(data, categories, comparisonCategory), [data, categories, comparisonCategory]);
2684
+ const series = useMemo(
2685
+ () => aggregateSeriesKeeping(data, categories, comparisonCategory, void 0, otherSeriesLabel(locale)),
2686
+ [data, categories, comparisonCategory, locale]
2687
+ );
2534
2688
  const palette = useMemo(
2535
2689
  () => resolveChartColors(
2536
2690
  seriesColorsWithComparison(series.categories, colors, CHART_OTHER_COLOR, series.otherCategory, categories, comparisonCategory),
@@ -2577,7 +2731,7 @@ function AreaChartImpl({
2577
2731
  annotations,
2578
2732
  forecast,
2579
2733
  comparison: comparisonConfig,
2580
- comparisonFormat: format2,
2734
+ comparisonFormat: format,
2581
2735
  provisionalFrom,
2582
2736
  provisionalLabel,
2583
2737
  reserveActions: Boolean(actions),
@@ -2586,7 +2740,8 @@ function AreaChartImpl({
2586
2740
  labelColor: tokens?.foreground ?? void 0,
2587
2741
  plotWidth,
2588
2742
  plotHeight: typeof height === "number" ? height : void 0,
2589
- chartOptions
2743
+ chartOptions,
2744
+ locale
2590
2745
  }),
2591
2746
  [
2592
2747
  series,
@@ -2622,23 +2777,24 @@ function AreaChartImpl({
2622
2777
  annotations,
2623
2778
  forecast,
2624
2779
  comparisonConfig,
2625
- format2,
2780
+ format,
2626
2781
  height,
2627
2782
  tokens,
2628
2783
  surface,
2629
2784
  plotWidth,
2630
- chartOptions
2785
+ chartOptions,
2786
+ locale
2631
2787
  ]
2632
2788
  );
2633
2789
  const dataTable = useMemo(() => {
2634
- const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, "\u9805\u76EE");
2635
- const times = timeTooltipLabels(series.data.map((row) => row[index]));
2790
+ const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, t.item);
2791
+ const times = timeTooltipLabels(series.data.map((row) => row[index]), locale);
2636
2792
  return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
2637
- }, [series, index, tooltipFormatter, labels]);
2638
- const label2 = ariaLabel ?? `${categories.join("\u30FB")}\u306E\u9762\u30B0\u30E9\u30D5`;
2793
+ }, [series, index, tooltipFormatter, labels, t, locale]);
2794
+ const label2 = ariaLabel ?? t.chart(categories);
2639
2795
  const resolvedSummary = useMemo(
2640
- () => summary === "auto" ? buildChartSummary({ data, index, categories, title, format: format2, valueFormatter }) : summary,
2641
- [summary, data, index, categories, title, format2, valueFormatter]
2796
+ () => summary === "auto" ? buildChartSummary({ data, index, categories, title, format, valueFormatter, locale }) : summary,
2797
+ [summary, data, index, categories, title, format, valueFormatter, locale]
2642
2798
  );
2643
2799
  return /* @__PURE__ */ jsx(
2644
2800
  ChartFrame,
@@ -2661,6 +2817,10 @@ function AreaChartImpl({
2661
2817
  }
2662
2818
  var AreaChart = forwardRef(AreaChartImpl);
2663
2819
  AreaChart.displayName = "AreaChart";
2820
+ var TEXT5 = {
2821
+ ja: { item: "\u9805\u76EE", chart: (categories) => `${categories.join("\u30FB")}\u306E\u68D2\u30B0\u30E9\u30D5` },
2822
+ en: { item: "Item", chart: (categories) => `Bar chart of ${categories.join(", ")}` }
2823
+ };
2664
2824
  var NO_ROWS2 = [];
2665
2825
  function BarChartImpl({
2666
2826
  data = NO_ROWS2,
@@ -2669,7 +2829,7 @@ function BarChartImpl({
2669
2829
  colors,
2670
2830
  labels,
2671
2831
  valueFormatter,
2672
- format: format2,
2832
+ format,
2673
2833
  title,
2674
2834
  summary,
2675
2835
  actions,
@@ -2707,10 +2867,12 @@ function BarChartImpl({
2707
2867
  ...rest
2708
2868
  }, ref) {
2709
2869
  const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
2710
- const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format2), [valueFormatter, format2]);
2711
- const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format2), [valueFormatter, format2]);
2712
- const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format2), [valueFormatter, format2]);
2713
- const series = useMemo(() => aggregateSeries(data, categories), [data, categories]);
2870
+ const locale = useLocale();
2871
+ const t = TEXT5[uiLanguage(locale)];
2872
+ const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
2873
+ const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
2874
+ const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
2875
+ const series = useMemo(() => aggregateSeries(data, categories, void 0, otherSeriesLabel(locale)), [data, categories, locale]);
2714
2876
  const palette = useMemo(
2715
2877
  () => resolveChartColors(
2716
2878
  // Meaning colours on bars are AREA colours (`warning` -> `--warning-fill`), the same as the thresholds' and a legend's.
@@ -2768,7 +2930,8 @@ function BarChartImpl({
2768
2930
  labelColor: tokens?.foreground ?? void 0,
2769
2931
  plotWidth,
2770
2932
  plotHeight: typeof height === "number" ? height : void 0,
2771
- chartOptions
2933
+ chartOptions,
2934
+ locale
2772
2935
  }),
2773
2936
  [
2774
2937
  series,
@@ -2809,18 +2972,19 @@ function BarChartImpl({
2809
2972
  tokens,
2810
2973
  surface,
2811
2974
  plotWidth,
2812
- chartOptions
2975
+ chartOptions,
2976
+ locale
2813
2977
  ]
2814
2978
  );
2815
2979
  const dataTable = useMemo(() => {
2816
- const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, "\u9805\u76EE");
2817
- const times = timeTooltipLabels(series.data.map((row) => row[index]));
2980
+ const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, t.item);
2981
+ const times = timeTooltipLabels(series.data.map((row) => row[index]), locale);
2818
2982
  return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
2819
- }, [series, index, tooltipFormatter, labels]);
2820
- const label2 = ariaLabel ?? `${categories.join("\u30FB")}\u306E\u68D2\u30B0\u30E9\u30D5`;
2983
+ }, [series, index, tooltipFormatter, labels, t, locale]);
2984
+ const label2 = ariaLabel ?? t.chart(categories);
2821
2985
  const resolvedSummary = useMemo(
2822
- () => summary === "auto" ? buildChartSummary({ data, index, categories, title, format: format2, valueFormatter }) : summary,
2823
- [summary, data, index, categories, title, format2, valueFormatter]
2986
+ () => summary === "auto" ? buildChartSummary({ data, index, categories, title, format, valueFormatter, locale }) : summary,
2987
+ [summary, data, index, categories, title, format, valueFormatter, locale]
2824
2988
  );
2825
2989
  return /* @__PURE__ */ jsx(
2826
2990
  ChartFrame,
@@ -2843,6 +3007,10 @@ function BarChartImpl({
2843
3007
  }
2844
3008
  var BarChart = forwardRef(BarChartImpl);
2845
3009
  BarChart.displayName = "BarChart";
3010
+ var TEXT6 = {
3011
+ ja: { item: "\u9805\u76EE", chart: (categories) => `${categories.join("\u30FB")}\u306E\u6298\u308C\u7DDA\u30B0\u30E9\u30D5` },
3012
+ en: { item: "Item", chart: (categories) => `Line chart of ${categories.join(", ")}` }
3013
+ };
2846
3014
  var NO_ROWS3 = [];
2847
3015
  function LineChartImpl({
2848
3016
  data = NO_ROWS3,
@@ -2851,7 +3019,7 @@ function LineChartImpl({
2851
3019
  colors,
2852
3020
  labels,
2853
3021
  valueFormatter,
2854
- format: format2,
3022
+ format,
2855
3023
  title,
2856
3024
  summary,
2857
3025
  actions,
@@ -2891,12 +3059,17 @@ function LineChartImpl({
2891
3059
  ...rest
2892
3060
  }, ref) {
2893
3061
  const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
2894
- const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format2), [valueFormatter, format2]);
2895
- const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format2), [valueFormatter, format2]);
2896
- const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format2), [valueFormatter, format2]);
3062
+ const locale = useLocale();
3063
+ const t = TEXT6[uiLanguage(locale)];
3064
+ const tooltipFormatter = useMemo(() => resolveValueFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
3065
+ const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
3066
+ const axisTicks = useMemo(() => resolveAxisTickFormatter(valueFormatter, format, locale), [valueFormatter, format, locale]);
2897
3067
  const comparisonCategory = comparison && categories.includes(comparison.category) ? comparison.category : void 0;
2898
3068
  const comparisonConfig = comparisonCategory === void 0 ? void 0 : comparison;
2899
- const series = useMemo(() => aggregateSeriesKeeping(data, categories, comparisonCategory), [data, categories, comparisonCategory]);
3069
+ const series = useMemo(
3070
+ () => aggregateSeriesKeeping(data, categories, comparisonCategory, void 0, otherSeriesLabel(locale)),
3071
+ [data, categories, comparisonCategory, locale]
3072
+ );
2900
3073
  const palette = useMemo(
2901
3074
  () => resolveChartColors(
2902
3075
  seriesColorsWithComparison(series.categories, colors, CHART_OTHER_COLOR, series.otherCategory, categories, comparisonCategory),
@@ -2944,7 +3117,7 @@ function LineChartImpl({
2944
3117
  annotations,
2945
3118
  forecast,
2946
3119
  comparison: comparisonConfig,
2947
- comparisonFormat: format2,
3120
+ comparisonFormat: format,
2948
3121
  provisionalFrom,
2949
3122
  provisionalLabel,
2950
3123
  reserveActions: Boolean(actions),
@@ -2953,7 +3126,8 @@ function LineChartImpl({
2953
3126
  labelColor: tokens?.foreground ?? void 0,
2954
3127
  plotWidth,
2955
3128
  plotHeight: typeof height === "number" ? height : void 0,
2956
- chartOptions
3129
+ chartOptions,
3130
+ locale
2957
3131
  }),
2958
3132
  [
2959
3133
  series,
@@ -2990,23 +3164,24 @@ function LineChartImpl({
2990
3164
  annotations,
2991
3165
  forecast,
2992
3166
  comparisonConfig,
2993
- format2,
3167
+ format,
2994
3168
  height,
2995
3169
  tokens,
2996
3170
  surface,
2997
3171
  plotWidth,
2998
- chartOptions
3172
+ chartOptions,
3173
+ locale
2999
3174
  ]
3000
3175
  );
3001
3176
  const dataTable = useMemo(() => {
3002
- const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, "\u9805\u76EE");
3003
- const times = timeTooltipLabels(series.data.map((row) => row[index]));
3177
+ const table = chartDataTable(labelRows(series.data, index, labels), index, series.categories, tooltipFormatter, labels, t.item);
3178
+ const times = timeTooltipLabels(series.data.map((row) => row[index]), locale);
3004
3179
  return times ? { ...table, rows: table.rows.map((row, i) => [times[i] ?? row[0] ?? "", ...row.slice(1)]) } : table;
3005
- }, [series, index, tooltipFormatter, labels]);
3006
- const label2 = ariaLabel ?? `${categories.join("\u30FB")}\u306E\u6298\u308C\u7DDA\u30B0\u30E9\u30D5`;
3180
+ }, [series, index, tooltipFormatter, labels, t, locale]);
3181
+ const label2 = ariaLabel ?? t.chart(categories);
3007
3182
  const resolvedSummary = useMemo(
3008
- () => summary === "auto" ? buildChartSummary({ data, index, categories, title, format: format2, valueFormatter }) : summary,
3009
- [summary, data, index, categories, title, format2, valueFormatter]
3183
+ () => summary === "auto" ? buildChartSummary({ data, index, categories, title, format, valueFormatter, locale }) : summary,
3184
+ [summary, data, index, categories, title, format, valueFormatter, locale]
3010
3185
  );
3011
3186
  return /* @__PURE__ */ jsx(
3012
3187
  ChartFrame,
@@ -3029,6 +3204,10 @@ function LineChartImpl({
3029
3204
  }
3030
3205
  var LineChart = forwardRef(LineChartImpl);
3031
3206
  LineChart.displayName = "LineChart";
3207
+ var TEXT7 = {
3208
+ ja: { item: "\u9805\u76EE", value: "\u5024", chart: (shares) => `\u69CB\u6210\u6BD4\u306E\u30C9\u30FC\u30CA\u30C4\u30B0\u30E9\u30D5\uFF08${shares.join("\u3001")}\uFF09` },
3209
+ en: { item: "Item", value: "Value", chart: (shares) => `Donut chart of shares (${shares.join(", ")})` }
3210
+ };
3032
3211
  function useElementWidth() {
3033
3212
  const [node, setNode] = useState(null);
3034
3213
  const [width, setWidth] = useState(null);
@@ -3048,7 +3227,7 @@ function DonutChartImpl({
3048
3227
  categories,
3049
3228
  colors,
3050
3229
  labels,
3051
- format: format2,
3230
+ format,
3052
3231
  valueFormatter: valueFormatterProp,
3053
3232
  title,
3054
3233
  summary,
@@ -3077,11 +3256,13 @@ function DonutChartImpl({
3077
3256
  const center = resolveDonutCenter(donutOptions?.centerLabel, { showLabel: donutOptions?.showLabel ?? showLabel, label: label2 });
3078
3257
  const maxSlices = donutOptions?.maxSlices;
3079
3258
  const showLegend = donutOptions?.showLegend ?? true;
3080
- const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp, format2), [valueFormatterProp, format2]);
3259
+ const locale = useLocale();
3260
+ const t = TEXT7[uiLanguage(locale)];
3261
+ const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
3081
3262
  const { ref: frameRef, tokens } = useChartSurface(ref);
3082
3263
  const slices = useMemo(
3083
- () => donutSlices(data, { index: labelKey, value: valueKey, colors, maxSlices, otherColor: CHART_OTHER_COLOR }),
3084
- [data, labelKey, valueKey, colors, maxSlices]
3264
+ () => donutSlices(data, { index: labelKey, value: valueKey, colors, maxSlices, otherColor: CHART_OTHER_COLOR, otherLabel: otherSeriesLabel(locale) }),
3265
+ [data, labelKey, valueKey, colors, maxSlices, locale]
3085
3266
  );
3086
3267
  const palette = useMemo(() => resolveChartColors(slices.map((s) => chartFillName(s.color)), tokens), [slices, tokens]);
3087
3268
  const rows = useMemo(() => slices.map((s) => s.row), [slices]);
@@ -3118,13 +3299,13 @@ function DonutChartImpl({
3118
3299
  let centerLabel = null;
3119
3300
  if (center.kind === "custom") centerLabel = center.node;
3120
3301
  else if (center.kind === "total") {
3121
- const text = donutCenterText(total, valueFormatter, { totalLabel: donutOptions?.totalLabel, unit: donutOptions?.unit });
3302
+ const text = donutCenterText(total, valueFormatter, { totalLabel: donutOptions?.totalLabel, unit: donutOptions?.unit, locale });
3122
3303
  centerLabel = caption(text.label, text.amount, text.unit);
3123
3304
  } else if (center.kind === "top") {
3124
3305
  const top = donutTopText(slices, labels);
3125
3306
  centerLabel = top && caption(top.label, top.amount);
3126
3307
  }
3127
- const a11yLabel = ariaLabel ?? `\u69CB\u6210\u6BD4\u306E\u30C9\u30FC\u30CA\u30C4\u30B0\u30E9\u30D5\uFF08${legend.map((item) => `${labelOf(item.name, labels)} ${item.share}`).join("\u3001")}\uFF09`;
3308
+ const a11yLabel = ariaLabel ?? t.chart(legend.map((item) => `${labelOf(item.name, labels)} ${item.share}`));
3128
3309
  const dataTable = useMemo(
3129
3310
  () => chartDataTable(
3130
3311
  // Fixed keys, so `labels` (which renames the rows) cannot collide with the column names.
@@ -3132,13 +3313,13 @@ function DonutChartImpl({
3132
3313
  "name",
3133
3314
  ["value"],
3134
3315
  valueFormatter,
3135
- { name: labels?.[labelKey] ?? "\u9805\u76EE", value: labels?.[valueKey] ?? "\u5024" }
3316
+ { name: labels?.[labelKey] ?? t.item, value: labels?.[valueKey] ?? t.value }
3136
3317
  ),
3137
- [rows, labelKey, valueKey, valueFormatter, labels]
3318
+ [rows, labelKey, valueKey, valueFormatter, labels, t]
3138
3319
  );
3139
3320
  const resolvedSummary = useMemo(
3140
- () => summary === "auto" ? buildShareSummary(slices, title) : summary,
3141
- [summary, slices, title]
3321
+ () => summary === "auto" ? buildShareSummary(slices, title, locale) : summary,
3322
+ [summary, slices, title, locale]
3142
3323
  );
3143
3324
  return /* @__PURE__ */ jsx(
3144
3325
  ChartFrame,
@@ -3193,6 +3374,10 @@ function DonutChartImpl({
3193
3374
  }
3194
3375
  var DonutChart = forwardRef(DonutChartImpl);
3195
3376
  DonutChart.displayName = "DonutChart";
3377
+ var TEXT8 = {
3378
+ ja: { item: "\u9805\u76EE", value: "\u5024" },
3379
+ en: { item: "Item", value: "Value" }
3380
+ };
3196
3381
  var listHeight = (n) => n * 32 + Math.max(0, n - 1) * 6;
3197
3382
  var isExternal = (href) => /^https?:\/\//.test(href);
3198
3383
  var NO_ROWS5 = [];
@@ -3204,7 +3389,7 @@ function BarListImpl({
3204
3389
  labels,
3205
3390
  thresholds,
3206
3391
  highlight,
3207
- format: format2,
3392
+ format,
3208
3393
  valueFormatter,
3209
3394
  formatValue: formatValue2,
3210
3395
  title,
@@ -3226,16 +3411,18 @@ function BarListImpl({
3226
3411
  const frame = requestAnimationFrame(() => setMounted(true));
3227
3412
  return () => cancelAnimationFrame(frame);
3228
3413
  }, [showAnimation]);
3414
+ const locale = useLocale();
3415
+ const t = TEXT8[uiLanguage(locale)];
3229
3416
  const maxItems = barListOptions?.maxItems ?? MAX_CHART_SERIES;
3230
3417
  const token = Array.isArray(colors) ? colors[0] : colors;
3231
3418
  const barColor = token ?? color ?? "chart-1";
3232
- const formatter = resolveValueFormatter(valueFormatter ?? formatValue2, format2);
3419
+ const formatter = resolveValueFormatter(valueFormatter ?? formatValue2, format, locale);
3233
3420
  const baseRows = barListRows(data, {
3234
3421
  index,
3235
3422
  category: categories?.[0],
3236
3423
  sortOrder: barListOptions?.sortOrder ?? sortOrder ?? "descending",
3237
3424
  maxItems,
3238
- otherLabel: barListOptions?.otherLabel,
3425
+ otherLabel: barListOptions?.otherLabel ?? otherSeriesLabel(locale),
3239
3426
  exclude: barListOptions?.exclude
3240
3427
  });
3241
3428
  const rows = baseRows.map((row) => {
@@ -3254,7 +3441,7 @@ function BarListImpl({
3254
3441
  "name",
3255
3442
  ["value"],
3256
3443
  formatter,
3257
- { name: index && labels?.[index] || "\u9805\u76EE", value: categories?.[0] && labels?.[categories[0]] || "\u5024" }
3444
+ { name: index && labels?.[index] || t.item, value: categories?.[0] && labels?.[categories[0]] || t.value }
3258
3445
  );
3259
3446
  const list = /* @__PURE__ */ jsxs("div", { "data-slot": "bar-list", className: "flex justify-between gap-6 text-sm", ...props, children: [
3260
3447
  /* @__PURE__ */ jsx("div", { className: "relative min-w-0 flex-1 space-y-1.5", children: rows.map((row, i) => {
@@ -3328,9 +3515,10 @@ function BarListImpl({
3328
3515
  var BarList = forwardRef(BarListImpl);
3329
3516
  BarList.displayName = "BarList";
3330
3517
  var NO_ROWS6 = [];
3331
- var CategoryBar = forwardRef(function CategoryBar2({ values = NO_ROWS6, colors, marker, showLabels = true, format: format2, valueFormatter: valueFormatterProp, className, ...props }, forwardedRef) {
3518
+ var CategoryBar = forwardRef(function CategoryBar2({ values = NO_ROWS6, colors, marker, showLabels = true, format, valueFormatter: valueFormatterProp, className, ...props }, forwardedRef) {
3332
3519
  const { ref, width } = useChartSurface(forwardedRef, null);
3333
- const valueFormatter = useMemo(() => resolveAxisFormatter(valueFormatterProp, format2), [valueFormatterProp, format2]);
3520
+ const locale = useLocale();
3521
+ const valueFormatter = useMemo(() => resolveAxisFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
3334
3522
  const segments = categoryBarSegments(values);
3335
3523
  const markerPosition = marker ? categoryBarMarkerPosition(marker.value, values) : 0;
3336
3524
  const allLabels = showLabels ? categoryBarLabels(values, void 0, marker ? markerPosition : void 0) : [];
@@ -3487,6 +3675,45 @@ var Tracker = forwardRef(function Tracker2({ data = NO_ROWS7, defaultColor, hove
3487
3675
  });
3488
3676
  Tracker.displayName = "Tracker";
3489
3677
  use([GraphicComponent]);
3678
+ var TEXT9 = {
3679
+ ja: {
3680
+ net: "\u7D14\u5897",
3681
+ total: "\u5408\u8A08",
3682
+ change: "\u5897\u6E1B",
3683
+ cumulative: "\u7D2F\u8A08",
3684
+ cumulativeChange: "\u7D2F\u8A08\u5897\u6E1B",
3685
+ item: "\u9805\u76EE",
3686
+ start: "\u958B\u59CB",
3687
+ end: "\u7D42\u4E86",
3688
+ fromTo: (from, to, net) => `${from} \u2192 ${to}\uFF08${net}\uFF09`,
3689
+ from: (from, net) => `${from} \u304B\u3089 ${net}`,
3690
+ to: (to, net) => `${to}\uFF08${net}\uFF09`,
3691
+ netOnly: (net) => `\u5897\u6E1B\u306E\u5408\u8A08 ${net}`,
3692
+ increase: (name, value) => `\u6700\u5927\u306E\u5897\u52A0\u306F ${name}\uFF08${value}\uFF09`,
3693
+ decrease: (name, value) => `\u6700\u5927\u306E\u6E1B\u5C11\u306F ${name}\uFF08${value}\uFF09`,
3694
+ sentenceJoin: "\u3002",
3695
+ chart: (label2) => `${label2}\u306E\u30A6\u30A9\u30FC\u30BF\u30FC\u30D5\u30A9\u30FC\u30EB\u30C1\u30E3\u30FC\u30C8`
3696
+ },
3697
+ en: {
3698
+ net: "Net change",
3699
+ total: "Total",
3700
+ change: "Change",
3701
+ cumulative: "Cumulative",
3702
+ cumulativeChange: "Cumulative change",
3703
+ item: "Item",
3704
+ start: "Start",
3705
+ end: "End",
3706
+ fromTo: (from, to, net) => `${from} \u2192 ${to} (${net})`,
3707
+ from: (from, net) => `${net} from ${from}`,
3708
+ to: (to, net) => `${to} (${net})`,
3709
+ netOnly: (net) => `Net change ${net}`,
3710
+ increase: (name, value) => `Largest increase: ${name} (${value})`,
3711
+ decrease: (name, value) => `Largest decrease: ${name} (${value})`,
3712
+ sentenceJoin: ". ",
3713
+ chart: (label2) => `Waterfall chart of ${label2}`
3714
+ }
3715
+ };
3716
+ var textOf = (locale) => TEXT9[uiLanguage(resolveLocale(locale))];
3490
3717
  function waterfallSteps(data, config) {
3491
3718
  const totals = new Set(config.totals ?? []);
3492
3719
  const delta = config.mode === "delta";
@@ -3505,11 +3732,13 @@ function waterfallSteps(data, config) {
3505
3732
  return { name, kind: n > 0 ? "increase" : n < 0 ? "decrease" : "flat", value: n, start, end: running, row };
3506
3733
  });
3507
3734
  if (delta && steps.some((s) => s.kind !== "gap")) {
3508
- steps.push({ name: DELTA_TOTAL_NAME, kind: "total", value: running, start: 0, end: running, row: {} });
3735
+ steps.push({ name: deltaTotalName(config.locale), kind: "total", value: running, start: 0, end: running, row: {} });
3509
3736
  }
3510
3737
  return steps;
3511
3738
  }
3512
- var DELTA_TOTAL_NAME = "\u7D14\u5897";
3739
+ function deltaTotalName(locale) {
3740
+ return textOf(locale).net;
3741
+ }
3513
3742
  function waterfallDeltaEnds(data, config) {
3514
3743
  const totals = new Set(config.totals ?? []);
3515
3744
  const kinds = data.map((row) => totals.has(String(row[config.index] ?? "")));
@@ -3525,16 +3754,17 @@ function waterfallDeltaEnds(data, config) {
3525
3754
  const closing = closingRow && closingRow.value === null && opening?.value != null ? { ...closingRow, value: opening.value + net } : closingRow;
3526
3755
  return { opening, closing, net };
3527
3756
  }
3528
- function waterfallDeltaNote(ends, formatter, labels) {
3757
+ function waterfallDeltaNote(ends, formatter, labels, locale) {
3758
+ const t = textOf(locale);
3529
3759
  const net = signedText(ends.net, formatter);
3530
3760
  const { opening, closing } = ends;
3531
3761
  const side = (e) => e && e.value !== null ? `${labelOf(e.name, labels)} ${formatter(e.value)}` : null;
3532
3762
  const from = side(opening);
3533
3763
  const to = side(closing);
3534
- if (from && to) return `${from} \u2192 ${to}\uFF08${net}\uFF09`;
3535
- if (from) return `${from} \u304B\u3089 ${net}`;
3536
- if (to) return `${to}\uFF08${net}\uFF09`;
3537
- return `\u5897\u6E1B\u306E\u5408\u8A08 ${net}`;
3764
+ if (from && to) return t.fromTo(from, to, net);
3765
+ if (from) return t.from(from, net);
3766
+ if (to) return t.to(to, net);
3767
+ return t.netOnly(net);
3538
3768
  }
3539
3769
  function waterfallStack(steps) {
3540
3770
  const base = [];
@@ -3586,7 +3816,8 @@ function waterfallStepText(step, formatter, delta = false) {
3586
3816
  if (step.value === null) return EMPTY_VALUE;
3587
3817
  return step.kind === "total" && !delta ? formatter(step.value) : signedText(step.value, formatter);
3588
3818
  }
3589
- function buildWaterfallSummary(steps, formatter, title, labels, delta) {
3819
+ function buildWaterfallSummary(steps, formatter, title, labels, delta, locale) {
3820
+ const t = textOf(locale);
3590
3821
  const real = steps.filter((s) => s.kind !== "gap");
3591
3822
  const first = real[0];
3592
3823
  const last = real[real.length - 1];
@@ -3594,7 +3825,7 @@ function buildWaterfallSummary(steps, formatter, title, labels, delta) {
3594
3825
  const name = (s) => labelOf(s.name, labels);
3595
3826
  const head = title ? `${title}: ` : "";
3596
3827
  const parts = [
3597
- delta ? waterfallDeltaNote(delta, formatter, labels) : real.length === 1 ? `${name(first)} ${formatter(first.end)}` : `${name(first)} ${formatter(first.end)} \u2192 ${name(last)} ${formatter(last.end)}`
3828
+ delta ? waterfallDeltaNote(delta, formatter, labels, locale) : real.length === 1 ? `${name(first)} ${formatter(first.end)}` : `${name(first)} ${formatter(first.end)} \u2192 ${name(last)} ${formatter(last.end)}`
3598
3829
  ];
3599
3830
  let up;
3600
3831
  let down;
@@ -3602,21 +3833,22 @@ function buildWaterfallSummary(steps, formatter, title, labels, delta) {
3602
3833
  if (s.kind === "increase" && (!up || s.value > up.value)) up = s;
3603
3834
  if (s.kind === "decrease" && (!down || s.value < down.value)) down = s;
3604
3835
  }
3605
- if (up) parts.push(`\u6700\u5927\u306E\u5897\u52A0\u306F ${name(up)}\uFF08${signedText(up.value, formatter)}\uFF09`);
3606
- if (down) parts.push(`\u6700\u5927\u306E\u6E1B\u5C11\u306F ${name(down)}\uFF08${signedText(down.value, formatter)}\uFF09`);
3607
- return `${head}${parts.join("\u3002")}`;
3836
+ if (up) parts.push(t.increase(name(up), signedText(up.value, formatter)));
3837
+ if (down) parts.push(t.decrease(name(down), signedText(down.value, formatter)));
3838
+ return `${head}${parts.join(t.sentenceJoin)}`;
3608
3839
  }
3609
- function waterfallDataTable(steps, names, formatter, labels, delta) {
3840
+ function waterfallDataTable(steps, names, formatter, labels, delta, locale) {
3841
+ const t = textOf(locale);
3610
3842
  const label2 = (key) => labelOf(key, labels);
3611
3843
  const rows = steps.map((s) => [
3612
3844
  label2(s.name),
3613
- s.kind === "total" ? delta ? DELTA_TOTAL_NAME : "\u5408\u8A08" : s.value === null ? EMPTY_VALUE : signedText(s.value, formatter),
3845
+ s.kind === "total" ? delta ? t.net : t.total : s.value === null ? EMPTY_VALUE : signedText(s.value, formatter),
3614
3846
  s.kind === "gap" ? EMPTY_VALUE : delta ? signedText(s.end, formatter) : formatter(s.end)
3615
3847
  ]);
3616
3848
  const end = (e, role) => e && e.value !== null ? [[label2(e.name), role, formatter(e.value)]] : [];
3617
3849
  return {
3618
- columns: [labels?.[names.index] ?? "\u9805\u76EE", "\u5897\u6E1B", delta ? "\u7D2F\u8A08\u5897\u6E1B" : "\u7D2F\u8A08"],
3619
- rows: delta ? [...end(delta.opening, "\u958B\u59CB"), ...rows, ...end(delta.closing, "\u7D42\u4E86")] : rows
3850
+ columns: [labels?.[names.index] ?? t.item, t.change, delta ? t.cumulativeChange : t.cumulative],
3851
+ rows: delta ? [...end(delta.opening, t.start), ...rows, ...end(delta.closing, t.end)] : rows
3620
3852
  };
3621
3853
  }
3622
3854
  var WATERFALL_BAR_SHARE = 0.45;
@@ -3698,6 +3930,7 @@ function waterfallConnectorRenderer(color) {
3698
3930
  var ROW_STYLE = "display:flex;align-items:center;gap:8px;line-height:20px";
3699
3931
  function buildWaterfallOption(config) {
3700
3932
  const { steps, colors, polarity, labels, valueFormatter, showValues = true, showTooltip = true } = config;
3933
+ const t = textOf(config.locale);
3701
3934
  const delta = config.mode === "delta";
3702
3935
  const axisFormatter = config.axisFormatter ?? valueFormatter;
3703
3936
  const noteWidth = config.plotWidth ? Math.max(120, config.plotWidth - 16) : void 0;
@@ -3768,7 +4001,7 @@ function buildWaterfallOption(config) {
3768
4001
  if (!step) return "";
3769
4002
  const color = escapeHtml(colorOf(step) ?? "currentColor");
3770
4003
  const line = (name, text) => `<div style="${ROW_STYLE}"><span style="display:inline-block;width:8px;height:8px;border-radius:9999px;background:${color}"></span><span style="flex:1;opacity:.8">${escapeHtml(name)}</span><span style="font-weight:500;font-variant-numeric:tabular-nums;margin-left:12px">${escapeHtml(text)}</span></div>`;
3771
- const rows = step.kind === "total" ? line(delta ? DELTA_TOTAL_NAME : "\u5408\u8A08", delta ? signedText(step.end, valueFormatter) : valueFormatter(step.end)) : line("\u5897\u6E1B", waterfallStepText(step, valueFormatter)) + (step.kind === "gap" ? "" : delta ? line("\u7D2F\u8A08\u5897\u6E1B", signedText(step.end, valueFormatter)) : line("\u7D2F\u8A08", valueFormatter(step.end)));
4004
+ const rows = step.kind === "total" ? line(delta ? t.net : t.total, delta ? signedText(step.end, valueFormatter) : valueFormatter(step.end)) : line(t.change, waterfallStepText(step, valueFormatter)) + (step.kind === "gap" ? "" : delta ? line(t.cumulativeChange, signedText(step.end, valueFormatter)) : line(t.cumulative, valueFormatter(step.end)));
3772
4005
  return `<div style="font-weight:500;margin-bottom:4px">${escapeHtml(labelOf(step.name, labels))}</div>${rows}`;
3773
4006
  }
3774
4007
  },
@@ -3838,7 +4071,7 @@ function WaterfallChartImpl({
3838
4071
  mode = "total",
3839
4072
  polarity = "higher-is-better",
3840
4073
  labels,
3841
- format: format2,
4074
+ format,
3842
4075
  valueFormatter: valueFormatterProp,
3843
4076
  showValues = true,
3844
4077
  showTooltip = true,
@@ -3859,11 +4092,15 @@ function WaterfallChartImpl({
3859
4092
  }, ref) {
3860
4093
  const valueKey = categories[0] ?? "";
3861
4094
  const { ref: frameRef, width: plotWidth, tokens } = useChartSurface(ref);
3862
- const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp, format2), [valueFormatterProp, format2]);
3863
- const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatterProp, format2), [valueFormatterProp, format2]);
3864
- const steps = useMemo(() => waterfallSteps(data, { index, value: valueKey, totals, mode }), [data, index, valueKey, totals, mode]);
4095
+ const locale = useLocale();
4096
+ const valueFormatter = useMemo(() => resolveValueFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
4097
+ const axisFormatter = useMemo(() => resolveAxisFormatter(valueFormatterProp, format, locale), [valueFormatterProp, format, locale]);
4098
+ const steps = useMemo(
4099
+ () => waterfallSteps(data, { index, value: valueKey, totals, mode, locale }),
4100
+ [data, index, valueKey, totals, mode, locale]
4101
+ );
3865
4102
  const ends = useMemo(() => mode === "delta" ? waterfallDeltaEnds(data, { index, value: valueKey, totals }) : void 0, [data, index, valueKey, totals, mode]);
3866
- const deltaNote = useMemo(() => ends ? waterfallDeltaNote(ends, valueFormatter, labels) : void 0, [ends, valueFormatter, labels]);
4103
+ const deltaNote = useMemo(() => ends ? waterfallDeltaNote(ends, valueFormatter, labels, locale) : void 0, [ends, valueFormatter, labels, locale]);
3867
4104
  const colors = useMemo(() => {
3868
4105
  const fills = resolveFillColors(tokens);
3869
4106
  const [total = ""] = resolveChartColors(["chart-1"], tokens);
@@ -3893,19 +4130,21 @@ function WaterfallChartImpl({
3893
4130
  chartOptions,
3894
4131
  minValue,
3895
4132
  maxValue,
3896
- yAxisWidth
4133
+ yAxisWidth,
4134
+ locale
3897
4135
  }),
3898
- [steps, colors, polarity, labels, valueFormatter, axisFormatter, showValues, showTooltip, tokens, mode, deltaNote, plotWidth, chartOptions, minValue, maxValue, yAxisWidth]
4136
+ [steps, colors, polarity, labels, valueFormatter, axisFormatter, showValues, showTooltip, tokens, mode, deltaNote, plotWidth, chartOptions, minValue, maxValue, yAxisWidth, locale]
3899
4137
  );
3900
4138
  const dataTable = useMemo(
3901
- () => waterfallDataTable(steps, { index}, valueFormatter, labels, ends),
3902
- [steps, index, valueKey, valueFormatter, labels, ends]
4139
+ () => waterfallDataTable(steps, { index}, valueFormatter, labels, ends, locale),
4140
+ [steps, index, valueKey, valueFormatter, labels, ends, locale]
3903
4141
  );
3904
4142
  const resolvedSummary = useMemo(
3905
- () => summary === "auto" ? buildWaterfallSummary(steps, valueFormatter, title, labels, ends) : summary,
3906
- [summary, steps, valueFormatter, title, labels, ends]
4143
+ () => summary === "auto" ? buildWaterfallSummary(steps, valueFormatter, title, labels, ends, locale) : summary,
4144
+ [summary, steps, valueFormatter, title, labels, ends, locale]
3907
4145
  );
3908
- const label2 = ariaLabel ?? `${labelOf(valueKey, labels) || "\u5897\u6E1B"}\u306E\u30A6\u30A9\u30FC\u30BF\u30FC\u30D5\u30A9\u30FC\u30EB\u30C1\u30E3\u30FC\u30C8`;
4146
+ const t = textOf(locale);
4147
+ const label2 = ariaLabel ?? t.chart(labelOf(valueKey, labels) || t.change.toLowerCase());
3909
4148
  return /* @__PURE__ */ jsx(
3910
4149
  ChartFrame,
3911
4150
  {
@@ -3947,7 +4186,38 @@ function scatterPoints(data, config) {
3947
4186
  }
3948
4187
  return points;
3949
4188
  }
3950
- function scatterSeries(points, max = MAX_CHART_SERIES) {
4189
+ var TEXT10 = {
4190
+ ja: {
4191
+ who: (name, value) => `${name}\uFF08${value}\uFF09`,
4192
+ summary: (count, y, who) => `${count}\u70B9\u3002${y}\u304C\u6700\u5927\u306A\u306E\u306F ${who}`,
4193
+ name: "\u540D\u524D",
4194
+ series: "\u7CFB\u5217",
4195
+ x: "\u6A2A\u8EF8",
4196
+ y: "\u7E26\u8EF8",
4197
+ size: "\u5927\u304D\u3055",
4198
+ pair: (y, x) => `${y}\xD7${x}`,
4199
+ first: (pair, count) => `${pair}\uFF08\u5148\u982D ${count} \u70B9\uFF09`,
4200
+ guide: (label2, axis, value) => `${label2}\uFF08${axis} ${value}\uFF09`,
4201
+ caption: (base, guides) => `${base}\u3002\u57FA\u6E96\u7DDA: ${guides.join("\u3001")}`,
4202
+ chart: (y, x) => `${y}\xD7${x}\u306E\u6563\u5E03\u56F3`
4203
+ },
4204
+ en: {
4205
+ who: (name, value) => `${name} (${value})`,
4206
+ summary: (count, y, who) => `${count === 1 ? "1 point" : `${count} points`}. Highest ${y}: ${who}`,
4207
+ name: "Name",
4208
+ series: "Series",
4209
+ x: "X",
4210
+ y: "Y",
4211
+ size: "Size",
4212
+ pair: (y, x) => `${y} \xD7 ${x}`,
4213
+ first: (pair, count) => `${pair} (first ${count} points)`,
4214
+ guide: (label2, axis, value) => `${label2} (${axis} ${value})`,
4215
+ caption: (base, guides) => `${base}. Reference lines: ${guides.join(", ")}`,
4216
+ chart: (y, x) => `Scatter plot of ${y} \xD7 ${x}`
4217
+ }
4218
+ };
4219
+ var textOf2 = (locale) => TEXT10[uiLanguage(resolveLocale(locale))];
4220
+ function scatterSeries(points, max = MAX_CHART_SERIES, otherLabel = otherSeriesLabel()) {
3951
4221
  const order = [];
3952
4222
  const counts = /* @__PURE__ */ new Map();
3953
4223
  for (const p of points) {
@@ -3960,7 +4230,7 @@ function scatterSeries(points, max = MAX_CHART_SERIES) {
3960
4230
  const ranked = order.map((name, at) => ({ name, at, n: counts.get(name) ?? 0 })).sort((a, b) => b.n - a.n || a.at - b.at);
3961
4231
  const kept = new Set(ranked.slice(0, Math.max(1, max)).map((r) => r.name));
3962
4232
  const result = order.filter((name) => kept.has(name)).map((name) => ({ name, isOther: false, points: points.filter((p) => p.series === name) }));
3963
- result.push({ name: OTHER_SERIES_LABEL, isOther: true, points: points.filter((p) => !kept.has(p.series)) });
4233
+ result.push({ name: otherLabel, isOther: true, points: points.filter((p) => !kept.has(p.series)) });
3964
4234
  return result;
3965
4235
  }
3966
4236
  var SCATTER_FADED_OPACITY = 0.2;
@@ -3974,24 +4244,26 @@ function scatterBubbleSize(value, max) {
3974
4244
  function pointTitle(point, labels) {
3975
4245
  return labelOf(point.name || point.series, labels);
3976
4246
  }
3977
- function buildScatterSummary(points, yName, yFormatter, title, labels) {
4247
+ function buildScatterSummary(points, yName, yFormatter, title, labels, locale) {
3978
4248
  if (points.length === 0) return void 0;
4249
+ const t = textOf2(locale);
3979
4250
  let best = points[0];
3980
4251
  for (const p of points) if (p.y > best.y) best = p;
3981
4252
  const head = title ? `${title}: ` : "";
3982
- const who = best.name ? `${labelOf(best.name, labels)}\uFF08${yFormatter(best.y)}\uFF09` : yFormatter(best.y);
3983
- return `${head}${points.length}\u70B9\u3002${labelOf(yName, labels)}\u304C\u6700\u5927\u306A\u306E\u306F ${who}`;
4253
+ const who = best.name ? t.who(labelOf(best.name, labels), yFormatter(best.y)) : yFormatter(best.y);
4254
+ return `${head}${t.summary(points.length, labelOf(yName, labels), who)}`;
3984
4255
  }
3985
4256
  var SCATTER_TABLE_MAX_ROWS = 100;
3986
4257
  function scatterDataTable(points, config) {
4258
+ const t = textOf2(config.locale);
3987
4259
  const label2 = (key) => labelOf(key, config.labels);
3988
4260
  const column = (key, fallback) => config.labels?.[key] ?? fallback;
3989
4261
  const columns = [
3990
- ...config.index ? [column(config.index, "\u540D\u524D")] : [],
3991
- ...config.series ? [column(config.series, "\u7CFB\u5217")] : [],
3992
- column(config.x, "\u6A2A\u8EF8"),
3993
- column(config.y, "\u7E26\u8EF8"),
3994
- ...config.size ? [column(config.size, "\u5927\u304D\u3055")] : []
4262
+ ...config.index ? [column(config.index, t.name)] : [],
4263
+ ...config.series ? [column(config.series, t.series)] : [],
4264
+ column(config.x, t.x),
4265
+ column(config.y, t.y),
4266
+ ...config.size ? [column(config.size, t.size)] : []
3995
4267
  ];
3996
4268
  const shown = points.slice(0, SCATTER_TABLE_MAX_ROWS);
3997
4269
  const rows = shown.map((p, i) => {
@@ -4004,14 +4276,15 @@ function scatterDataTable(points, config) {
4004
4276
  ];
4005
4277
  return config.index ? cells : [String(i + 1), ...cells];
4006
4278
  });
4007
- const base = points.length > shown.length ? `${label2(config.y)}\xD7${label2(config.x)}\uFF08\u5148\u982D ${shown.length} \u70B9\uFF09` : `${label2(config.y)}\xD7${label2(config.x)}`;
4279
+ const pair = t.pair(label2(config.y), label2(config.x));
4280
+ const base = points.length > shown.length ? t.first(pair, shown.length) : pair;
4008
4281
  const guides = (config.referenceLines ?? []).map((line) => {
4009
4282
  const key = line.axis === "x" ? config.x : config.y;
4010
4283
  const text = config.formatters[line.axis](line.value);
4011
- return line.label ? `${line.label}\uFF08${label2(key)} ${text}\uFF09` : `${label2(key)} ${text}`;
4284
+ return line.label ? t.guide(line.label, label2(key), text) : `${label2(key)} ${text}`;
4012
4285
  });
4013
4286
  return {
4014
- caption: guides.length > 0 ? `${base}\u3002\u57FA\u6E96\u7DDA: ${guides.join("\u3001")}` : base,
4287
+ caption: guides.length > 0 ? t.caption(base, guides) : base,
4015
4288
  columns: config.index ? columns : ["#", ...columns],
4016
4289
  rows
4017
4290
  };
@@ -4233,7 +4506,7 @@ function ScatterChartImpl({
4233
4506
  referenceLines,
4234
4507
  colors,
4235
4508
  labels,
4236
- format: format2,
4509
+ format,
4237
4510
  xFormat,
4238
4511
  yFormat,
4239
4512
  sizeFormat,
@@ -4258,26 +4531,27 @@ function ScatterChartImpl({
4258
4531
  ...rest
4259
4532
  }, ref) {
4260
4533
  const { ref: frameRef, width: plotWidth, tokens } = useChartSurface(ref);
4534
+ const locale = useLocale();
4261
4535
  const formatters = useMemo(
4262
4536
  () => ({
4263
- x: resolveValueFormatter(valueFormatter, xFormat ?? format2),
4264
- y: resolveValueFormatter(valueFormatter, yFormat ?? format2),
4265
- size: resolveValueFormatter(valueFormatter, sizeFormat ?? format2)
4537
+ x: resolveValueFormatter(valueFormatter, xFormat ?? format, locale),
4538
+ y: resolveValueFormatter(valueFormatter, yFormat ?? format, locale),
4539
+ size: resolveValueFormatter(valueFormatter, sizeFormat ?? format, locale)
4266
4540
  }),
4267
- [valueFormatter, xFormat, yFormat, sizeFormat, format2]
4541
+ [valueFormatter, xFormat, yFormat, sizeFormat, format, locale]
4268
4542
  );
4269
4543
  const axisFormatters = useMemo(
4270
4544
  () => ({
4271
- x: resolveAxisFormatter(valueFormatter, xFormat ?? format2),
4272
- y: resolveAxisFormatter(valueFormatter, yFormat ?? format2)
4545
+ x: resolveAxisFormatter(valueFormatter, xFormat ?? format, locale),
4546
+ y: resolveAxisFormatter(valueFormatter, yFormat ?? format, locale)
4273
4547
  }),
4274
- [valueFormatter, xFormat, yFormat, format2]
4548
+ [valueFormatter, xFormat, yFormat, format, locale]
4275
4549
  );
4276
4550
  const points = useMemo(
4277
4551
  () => scatterPoints(data, { x, y, size, index, series: seriesKey, labelKey }),
4278
4552
  [data, x, y, size, index, seriesKey, labelKey]
4279
4553
  );
4280
- const series = useMemo(() => scatterSeries(points), [points]);
4554
+ const series = useMemo(() => scatterSeries(points, void 0, otherSeriesLabel(locale)), [points, locale]);
4281
4555
  const palette = useMemo(
4282
4556
  () => resolveChartColors(scatterSeriesColors(series, colors).map(chartFillName), tokens),
4283
4557
  [series, colors, tokens]
@@ -4313,14 +4587,14 @@ function ScatterChartImpl({
4313
4587
  [series, palette, x, y, size, seriesKey, seriesLabel, highlightList, referenceLines, labelKey, tokens, labels, formatters, axisFormatters, fitToData, showLegend, showTooltip, actions, plotWidth, chartOptions, minValue, maxValue, xMinValue, xMaxValue]
4314
4588
  );
4315
4589
  const dataTable = useMemo(
4316
- () => scatterDataTable(points, { x, y, size, index: index ?? labelKey, series: seriesKey, formatters, labels, referenceLines }),
4317
- [points, x, y, size, index, labelKey, seriesKey, formatters, labels, referenceLines]
4590
+ () => scatterDataTable(points, { x, y, size, index: index ?? labelKey, series: seriesKey, formatters, labels, referenceLines, locale }),
4591
+ [points, x, y, size, index, labelKey, seriesKey, formatters, labels, referenceLines, locale]
4318
4592
  );
4319
4593
  const resolvedSummary = useMemo(
4320
- () => summary === "auto" ? buildScatterSummary(points, y, formatters.y, title, labels) : summary,
4321
- [summary, points, y, formatters, title, labels]
4594
+ () => summary === "auto" ? buildScatterSummary(points, y, formatters.y, title, labels, locale) : summary,
4595
+ [summary, points, y, formatters, title, labels, locale]
4322
4596
  );
4323
- const label2 = ariaLabel ?? `${labelOf(y, labels)}\xD7${labelOf(x, labels)}\u306E\u6563\u5E03\u56F3`;
4597
+ const label2 = ariaLabel ?? textOf2(locale).chart(labelOf(y, labels), labelOf(x, labels));
4324
4598
  return /* @__PURE__ */ jsx(
4325
4599
  ChartFrame,
4326
4600
  {
@@ -4345,7 +4619,12 @@ ScatterChart.displayName = "ScatterChart";
4345
4619
  function legendColors(categories, colors) {
4346
4620
  return seriesColorsFor(categories, colors, CHART_OTHER_COLOR).map((color) => chartFillToCss(color));
4347
4621
  }
4348
- var Legend = forwardRef(function Legend2({ categories, colors, labels, layout = "horizontal", ariaLabel = "\u51E1\u4F8B", className }, ref) {
4622
+ var TEXT11 = {
4623
+ ja: { legend: "\u51E1\u4F8B" },
4624
+ en: { legend: "Legend" }
4625
+ };
4626
+ var Legend = forwardRef(function Legend2({ categories, colors, labels, layout = "horizontal", ariaLabel, className }, ref) {
4627
+ const t = TEXT11[uiLanguage(useLocale())];
4349
4628
  if (categories.length === 0) return null;
4350
4629
  const swatches = legendColors(categories, colors);
4351
4630
  return /* @__PURE__ */ jsx(
@@ -4354,7 +4633,7 @@ var Legend = forwardRef(function Legend2({ categories, colors, labels, layout =
4354
4633
  ref,
4355
4634
  "data-slot": "legend",
4356
4635
  "data-layout": layout,
4357
- "aria-label": ariaLabel,
4636
+ "aria-label": ariaLabel ?? t.legend,
4358
4637
  className: cn("m-0 flex list-none gap-x-4 gap-y-1 p-0 text-xs", layout === "vertical" ? "flex-col" : "flex-row flex-wrap", className),
4359
4638
  children: categories.map((category, i) => /* @__PURE__ */ jsxs("li", { "data-slot": "legend-item", className: "flex min-w-0 items-center gap-1.5", children: [
4360
4639
  /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "size-2.5 shrink-0 rounded-[2px]", style: { background: swatches[i] } }),
@@ -4452,9 +4731,27 @@ var funnelConversionVariants = cva("flex items-center text-muted-foreground", {
4452
4731
  direction: "vertical"
4453
4732
  }
4454
4733
  });
4455
- function resolveFunnelFormatter(valueFormatter, formatValue2, format2) {
4456
- return resolveValueFormatter(valueFormatter ?? formatValue2, format2);
4734
+ function resolveFunnelFormatter(valueFormatter, formatValue2, format, locale) {
4735
+ return resolveValueFormatter(valueFormatter ?? formatValue2, format, locale);
4457
4736
  }
4737
+ var TEXT12 = {
4738
+ ja: {
4739
+ step: "\u30B9\u30C6\u30C3\u30D7",
4740
+ value: "\u5024",
4741
+ previous: "\u524D\u671F",
4742
+ previousHeader: "\u524D\u671F",
4743
+ change: (label2, points) => `(${label2}\u6BD4 ${points})`,
4744
+ funnel: "\u30D5\u30A1\u30CD\u30EB"
4745
+ },
4746
+ en: {
4747
+ step: "Step",
4748
+ value: "Value",
4749
+ previous: "prior period",
4750
+ previousHeader: "Prior period",
4751
+ change: (label2, points) => `(vs. ${label2} ${points})`,
4752
+ funnel: "Funnel"
4753
+ }
4754
+ };
4458
4755
  function lowestConversionStep(values) {
4459
4756
  if (values.length < 3) return -1;
4460
4757
  let lowest = -1;
@@ -4536,7 +4833,9 @@ function FunnelStepsImpl({
4536
4833
  }, ref) {
4537
4834
  const [mounted, setMounted] = useState(false);
4538
4835
  const isHorizontal = direction === "horizontal";
4539
- const format2 = resolveFunnelFormatter(valueFormatter, formatValue2, valueFormat);
4836
+ const locale = useLocale();
4837
+ const t = TEXT12[uiLanguage(locale)];
4838
+ const format = resolveFunnelFormatter(valueFormatter, formatValue2, valueFormat, locale);
4540
4839
  useEffect(() => {
4541
4840
  if (animate) setMounted(true);
4542
4841
  }, [animate]);
@@ -4548,15 +4847,19 @@ function FunnelStepsImpl({
4548
4847
  const maxValue = steps.length > 0 ? steps[0].value : 0;
4549
4848
  const values = steps.map((s) => s.value);
4550
4849
  const previous = comparison?.values;
4551
- const comparisonLabel2 = comparison?.label ?? "\u524D\u671F";
4850
+ const comparisonLabel2 = comparison?.label ?? t.previous;
4552
4851
  const showRates = showConversion || previous !== void 0;
4553
4852
  const focus = !showRates ? -1 : previous ? worstChangeStep(values, previous) : lowestConversionStep(values);
4554
4853
  const dataTable = chartDataTable(
4555
4854
  steps.map((step, i) => ({ label: step.label, value: step.value, previous: previous?.[i] ?? null })),
4556
4855
  "label",
4557
4856
  previous ? ["value", "previous"] : ["value"],
4558
- format2,
4559
- { label: labels?.[index] ?? "\u30B9\u30C6\u30C3\u30D7", value: categories?.[0] && labels?.[categories[0]] || "\u5024", previous: comparisonLabel2 }
4857
+ format,
4858
+ {
4859
+ label: labels?.[index] ?? t.step,
4860
+ value: categories?.[0] && labels?.[categories[0]] || t.value,
4861
+ previous: comparison?.label ?? t.previousHeader
4862
+ }
4560
4863
  );
4561
4864
  const list = /* @__PURE__ */ jsx("div", { "data-slot": "funnel-steps", role: "list", className: funnelStepsVariants({ size, direction }), ...props, children: steps.map((step, index2) => {
4562
4865
  const percentage = maxValue > 0 ? step.value / maxValue * 100 : 0;
@@ -4582,7 +4885,7 @@ function FunnelStepsImpl({
4582
4885
  {
4583
4886
  role: "listitem",
4584
4887
  className: "flex min-w-0 flex-1 flex-col items-center gap-1",
4585
- "aria-label": `${step.label}: ${format2(step.value)}`,
4888
+ "aria-label": `${step.label}: ${format(step.value)}`,
4586
4889
  children: [
4587
4890
  /* @__PURE__ */ jsx(
4588
4891
  "span",
@@ -4592,7 +4895,7 @@ function FunnelStepsImpl({
4592
4895
  "text-muted-foreground tabular-nums",
4593
4896
  size === "sm" ? "text-xs" : "text-sm"
4594
4897
  ),
4595
- children: format2(step.value)
4898
+ children: format(step.value)
4596
4899
  }
4597
4900
  ),
4598
4901
  /* @__PURE__ */ jsx("div", { className: funnelBarContainerHorizontalVariants({ size }), children: /* @__PURE__ */ jsx(
@@ -4624,10 +4927,10 @@ function FunnelStepsImpl({
4624
4927
  )
4625
4928
  ]
4626
4929
  }
4627
- ) : /* @__PURE__ */ jsxs("div", { role: "listitem", "aria-label": `${step.label}: ${format2(step.value)}`, children: [
4930
+ ) : /* @__PURE__ */ jsxs("div", { role: "listitem", "aria-label": `${step.label}: ${format(step.value)}`, children: [
4628
4931
  /* @__PURE__ */ jsxs("div", { className: funnelLabelVariants({ size }), children: [
4629
4932
  /* @__PURE__ */ jsx("span", { className: "truncate", children: step.label }),
4630
- /* @__PURE__ */ jsx("span", { "data-slot": "funnel-value", className: "tabular-nums", children: format2(step.value) })
4933
+ /* @__PURE__ */ jsx("span", { "data-slot": "funnel-value", className: "tabular-nums", children: format(step.value) })
4631
4934
  ] }),
4632
4935
  /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-hidden rounded-sm bg-muted", children: /* @__PURE__ */ jsx(
4633
4936
  "div",
@@ -4651,13 +4954,7 @@ function FunnelStepsImpl({
4651
4954
  children: [
4652
4955
  "\u2192 ",
4653
4956
  computeConversionRate(steps[index2 + 1].value, step.value),
4654
- previous && /* @__PURE__ */ jsxs("span", { "data-slot": "funnel-change", className: "ml-1 tabular-nums", children: [
4655
- "(",
4656
- comparisonLabel2,
4657
- "\u6BD4 ",
4658
- formatPoints(conversionChange(values, previous, index2 + 1)),
4659
- ")"
4660
- ] })
4957
+ previous && /* @__PURE__ */ jsx("span", { "data-slot": "funnel-change", className: "ml-1 tabular-nums", children: t.change(comparisonLabel2, formatPoints(conversionChange(values, previous, index2 + 1), locale)) })
4661
4958
  ]
4662
4959
  }
4663
4960
  ) })
@@ -4674,7 +4971,7 @@ function FunnelStepsImpl({
4674
4971
  emptyState,
4675
4972
  height: ready ? "auto" : FRAME_HEIGHT[size ?? "md"],
4676
4973
  variant: "list",
4677
- ariaLabel: ariaLabel ?? "\u30D5\u30A1\u30CD\u30EB",
4974
+ ariaLabel: ariaLabel ?? t.funnel,
4678
4975
  plotRole: "group",
4679
4976
  dataTable,
4680
4977
  className,
@@ -4791,8 +5088,26 @@ function heatmapCellFontSize(plotWidth, columns, rowNames, texts) {
4791
5088
  if (text + HEATMAP_CELL_PADDING <= cell) return 12;
4792
5089
  return text * 10 / 12 + HEATMAP_CELL_PADDING <= cell ? 10 : null;
4793
5090
  }
5091
+ var TEXT13 = {
5092
+ ja: {
5093
+ join: "\u30FB",
5094
+ flagged: "\u8981\u6CE8\u610F",
5095
+ item: "\u9805\u76EE",
5096
+ top: (y, x, value) => `\u6700\u5927\u306F ${y} ${x} \u306E ${value}`,
5097
+ chart: (y, x) => `${y}\xD7${x}\u306E\u30D2\u30FC\u30C8\u30DE\u30C3\u30D7`
5098
+ },
5099
+ en: {
5100
+ join: ", ",
5101
+ flagged: "Needs attention",
5102
+ item: "Item",
5103
+ top: (y, x, value) => `Highest: ${y} ${x} (${value})`,
5104
+ chart: (y, x) => `Heatmap of ${y} \xD7 ${x}`
5105
+ }
5106
+ };
5107
+ var textOf3 = (locale) => TEXT13[uiLanguage(resolveLocale(locale))];
4794
5108
  function buildHeatmapOption(config) {
4795
5109
  const { model, labels, valueFormatter } = config;
5110
+ const t = textOf3(config.locale);
4796
5111
  const label2 = (key) => labels?.[key] ?? key;
4797
5112
  const present = model.cells.filter((c) => c.value !== null);
4798
5113
  const missing = model.cells.filter((c) => c.value === null);
@@ -4806,9 +5121,9 @@ function buildHeatmapOption(config) {
4806
5121
  const extras = (config.details ?? []).map((key) => {
4807
5122
  const n = cell.row ? toChartNumber(cell.row[key]) : null;
4808
5123
  return `${escapeHtml2(label2(key))} ${n === null ? EMPTY_VALUE : escapeHtml2(valueFormatter(n))}`;
4809
- }).join("\u30FB");
4810
- const flag = cell.flagged ? "\u30FB\u8981\u6CE8\u610F" : "";
4811
- return `${head} ${main}${extras ? `\u30FB${extras}` : ""}${flag}`;
5124
+ }).join(t.join);
5125
+ const flag = cell.flagged ? `${t.join}${t.flagged}` : "";
5126
+ return `${head} ${main}${extras ? `${t.join}${extras}` : ""}${flag}`;
4812
5127
  };
4813
5128
  const cellFont = config.plotWidth ? heatmapCellFontSize(
4814
5129
  config.plotWidth,
@@ -4906,7 +5221,7 @@ function mergeDeep(a, b) {
4906
5221
  }
4907
5222
  return out;
4908
5223
  }
4909
- function heatmapDataTable(model, names, formatter, labels) {
5224
+ function heatmapDataTable(model, names, formatter, labels, locale) {
4910
5225
  const label2 = (key) => labels?.[key] ?? key;
4911
5226
  const rows = model.ys.map((yk, yi) => [
4912
5227
  label2(yk),
@@ -4915,15 +5230,15 @@ function heatmapDataTable(model, names, formatter, labels) {
4915
5230
  return v === null || v === void 0 ? EMPTY_VALUE : formatter(v);
4916
5231
  })
4917
5232
  ]);
4918
- return { caption: `${label2(names.y)}\xD7${label2(names.x)}`, columns: [labels?.[names.y] ?? "\u9805\u76EE", ...model.xs.map(label2)], rows };
5233
+ return { caption: `${label2(names.y)}\xD7${label2(names.x)}`, columns: [labels?.[names.y] ?? textOf3(locale).item, ...model.xs.map(label2)], rows };
4919
5234
  }
4920
- function buildHeatmapSummary(model, formatter, title, labels) {
5235
+ function buildHeatmapSummary(model, formatter, title, labels, locale) {
4921
5236
  let best;
4922
5237
  for (const cell of model.cells) if (cell.value !== null && (!best || cell.value > best.value)) best = cell;
4923
5238
  if (!best) return void 0;
4924
5239
  const label2 = (key) => labels?.[key] ?? key;
4925
5240
  const head = title ? `${title}: ` : "";
4926
- return `${head}\u6700\u5927\u306F ${label2(model.ys[best.yi])} ${label2(model.xs[best.xi])} \u306E ${formatter(best.value)}`;
5241
+ return `${head}${textOf3(locale).top(label2(model.ys[best.yi]), label2(model.xs[best.xi]), formatter(best.value))}`;
4927
5242
  }
4928
5243
  function colorsFor(tokens, tone) {
4929
5244
  const [color = "", flag = "", muted = ""] = resolveChartColors([tone, "negative", "var(--muted-foreground)"], tokens);
@@ -4938,7 +5253,7 @@ function HeatmapImpl({
4938
5253
  xLabels,
4939
5254
  yLabels,
4940
5255
  labels,
4941
- format: format2,
5256
+ format,
4942
5257
  valueFormatter,
4943
5258
  tone = "chart-1",
4944
5259
  scale,
@@ -4962,7 +5277,8 @@ function HeatmapImpl({
4962
5277
  ...rest
4963
5278
  }, ref) {
4964
5279
  const { ref: frameRef, surface, width: plotWidth, tokens } = useChartSurface(ref);
4965
- const formatter = useMemo(() => resolveValueFormatter(valueFormatter, format2 ?? "number"), [valueFormatter, format2]);
5280
+ const locale = useLocale();
5281
+ const formatter = useMemo(() => resolveValueFormatter(valueFormatter, format ?? "number", locale), [valueFormatter, format, locale]);
4966
5282
  const model = useMemo(
4967
5283
  () => buildHeatmapModel({ data, x, y, value, xLabels, yLabels, flag, scale, minValue, maxValue }),
4968
5284
  [data, x, y, value, xLabels, yLabels, flag, scale?.min, scale?.max, minValue, maxValue]
@@ -4983,16 +5299,17 @@ function HeatmapImpl({
4983
5299
  showValues,
4984
5300
  showTooltip,
4985
5301
  plotWidth,
4986
- chartOptions
5302
+ chartOptions,
5303
+ locale
4987
5304
  }),
4988
- [model, x, y, value, colors, surface, tokens, labels, formatter, details, showValues, showTooltip, plotWidth, chartOptions]
5305
+ [model, x, y, value, colors, surface, tokens, labels, formatter, details, showValues, showTooltip, plotWidth, chartOptions, locale]
4989
5306
  );
4990
- const dataTable = useMemo(() => heatmapDataTable(model, { x, y }, formatter, labels), [model, x, y, formatter, labels]);
5307
+ const dataTable = useMemo(() => heatmapDataTable(model, { x, y }, formatter, labels, locale), [model, x, y, formatter, labels, locale]);
4991
5308
  const resolvedSummary = useMemo(
4992
- () => summary === "auto" ? buildHeatmapSummary(model, formatter, title, labels) : summary,
4993
- [summary, model, formatter, title, labels]
5309
+ () => summary === "auto" ? buildHeatmapSummary(model, formatter, title, labels, locale) : summary,
5310
+ [summary, model, formatter, title, labels, locale]
4994
5311
  );
4995
- const label2 = ariaLabel ?? `${labels?.[y] ?? y}\xD7${labels?.[x] ?? x}\u306E\u30D2\u30FC\u30C8\u30DE\u30C3\u30D7`;
5312
+ const label2 = ariaLabel ?? textOf3(locale).chart(labels?.[y] ?? y, labels?.[x] ?? x);
4996
5313
  const legend = showLegend ? /* @__PURE__ */ jsx(HeatmapLegend, { model, formatter, tone }) : null;
4997
5314
  return /* @__PURE__ */ jsx(
4998
5315
  ChartFrame,
@@ -5030,31 +5347,68 @@ function HeatmapLegend({
5030
5347
  }
5031
5348
  var Heatmap = forwardRef(HeatmapImpl);
5032
5349
  Heatmap.displayName = "Heatmap";
5033
- function resolveFormat(format2, row) {
5034
- return typeof format2 === "function" ? format2(row) : format2;
5350
+ var TEXT14 = {
5351
+ ja: {
5352
+ tones: { positive: "\u826F\u597D", warning: "\u6CE8\u610F", negative: "\u8981\u5BFE\u5FDC", neutral: "\u4E2D\u7ACB" },
5353
+ toneNote: (label2) => `\uFF08${label2}\uFF09`,
5354
+ selectAll: "\u5168\u3066\u9078\u629E",
5355
+ selectRow: "\u884C\u3092\u9078\u629E",
5356
+ trend: (points, first, last, min, max) => `${points}\u70B9\u306E\u63A8\u79FB\u3001${first}\u304B\u3089${last}\u3001\u6700\u5C0F${min}\u3001\u6700\u5927${max}`,
5357
+ noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093",
5358
+ pageSize: (size) => `${size}\u4EF6`,
5359
+ range: (total, start, end) => `${total}\u4EF6\u4E2D ${start} - ${end} \u3092\u8868\u793A`,
5360
+ first: "\u6700\u521D",
5361
+ previous: "\u524D\u3078",
5362
+ next: "\u6B21\u3078",
5363
+ last: "\u6700\u5F8C",
5364
+ columns: "\u8868\u793A\u3059\u308B\u5217",
5365
+ exportCsv: "CSV \u3092\u66F8\u304D\u51FA\u3059"
5366
+ },
5367
+ en: {
5368
+ tones: { positive: "Good", warning: "Caution", negative: "Needs action", neutral: "Neutral" },
5369
+ toneNote: (label2) => ` (${label2})`,
5370
+ selectAll: "Select all",
5371
+ selectRow: "Select row",
5372
+ trend: (points, first, last, min, max) => `Trend over ${points} points: ${first} to ${last}, min ${min}, max ${max}`,
5373
+ noData: "No results.",
5374
+ pageSize: (size) => `${size} / page`,
5375
+ range: (total, start, end) => `Showing ${start}\u2013${end} of ${total}`,
5376
+ first: "First",
5377
+ previous: "Previous",
5378
+ next: "Next",
5379
+ last: "Last",
5380
+ columns: "Columns",
5381
+ exportCsv: "Export CSV"
5382
+ }
5383
+ };
5384
+ var useText = () => TEXT14[uiLanguage(useLocale())];
5385
+ function resolveFormat(format, row) {
5386
+ return typeof format === "function" ? format(row) : format;
5035
5387
  }
5036
5388
  function isMissingCell(value) {
5037
5389
  return value === null || value === void 0 || value === "" || typeof value === "number" && Number.isNaN(value);
5038
5390
  }
5039
- function formatCellText(value, row, meta) {
5391
+ function formatCellText(value, row, meta, locale) {
5040
5392
  if (isMissingCell(value)) return meta.nullLabel ?? EMPTY_VALUE;
5041
5393
  if (meta.dateFormat && (value instanceof Date || typeof value === "string" || typeof value === "number")) {
5042
- const text = formatDate(value, meta.dateFormat, void 0, { timeZone: meta.timeZone });
5394
+ const text = formatDate(value, meta.dateFormat, locale, { timeZone: meta.timeZone });
5043
5395
  return text === EMPTY_VALUE ? String(value) : text;
5044
5396
  }
5045
5397
  if (typeof value !== "number") return String(value);
5046
- return formatValue(value, resolveFormat(meta.format, row));
5398
+ return formatValue(value, resolveFormat(meta.format, row), locale);
5047
5399
  }
5048
5400
  var THRESHOLD_TONE_STYLES = {
5049
- positive: { Icon: CircleCheck, text: "text-positive", label: "\u826F\u597D" },
5050
- warning: { Icon: TriangleAlert, text: "text-warning", label: "\u6CE8\u610F" },
5051
- negative: { Icon: CircleX, text: "text-negative", label: "\u8981\u5BFE\u5FDC" },
5052
- neutral: { Icon: Minus, text: "text-neutral", label: "\u4E2D\u7ACB" }
5401
+ positive: { Icon: CircleCheck, text: "text-positive" },
5402
+ warning: { Icon: TriangleAlert, text: "text-warning" },
5403
+ negative: { Icon: CircleX, text: "text-negative" },
5404
+ neutral: { Icon: Minus, text: "text-neutral" }
5053
5405
  };
5054
5406
  function ThresholdCell({ value, text, thresholds }) {
5407
+ const t = useText();
5055
5408
  const tone = typeof value === "number" ? toneForValue(value, thresholds) : void 0;
5056
5409
  if (!tone) return /* @__PURE__ */ jsx("div", { className: "text-right tabular-nums", children: text });
5057
- const { Icon, text: toneClass, label: label2 } = THRESHOLD_TONE_STYLES[tone];
5410
+ const { Icon, text: toneClass } = THRESHOLD_TONE_STYLES[tone];
5411
+ const label2 = t.tones[tone];
5058
5412
  return /* @__PURE__ */ jsxs(
5059
5413
  "div",
5060
5414
  {
@@ -5064,11 +5418,7 @@ function ThresholdCell({ value, text, thresholds }) {
5064
5418
  children: [
5065
5419
  /* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0", "aria-hidden": "true" }),
5066
5420
  /* @__PURE__ */ jsx("span", { children: text }),
5067
- /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
5068
- "\uFF08",
5069
- label2,
5070
- "\uFF09"
5071
- ] })
5421
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: t.toneNote(label2) })
5072
5422
  ]
5073
5423
  }
5074
5424
  );
@@ -5123,6 +5473,8 @@ function DataTable({
5123
5473
  className,
5124
5474
  children
5125
5475
  }) {
5476
+ const locale = useLocale();
5477
+ const t = TEXT14[uiLanguage(locale)];
5126
5478
  const [sorting, setSorting] = useControlledState(sortingProp, [], onSortingChange);
5127
5479
  const [columnFilters, setColumnFilters] = useControlledState(
5128
5480
  columnFiltersProp,
@@ -5161,7 +5513,7 @@ function DataTable({
5161
5513
  ...column,
5162
5514
  cell: ({ row, getValue }) => {
5163
5515
  const value = getValue();
5164
- const text = formatCellText(value, row.original, meta2 ?? {});
5516
+ const text = formatCellText(value, row.original, meta2 ?? {}, locale);
5165
5517
  if (thresholds) return /* @__PURE__ */ jsx(ThresholdCell, { value, text, thresholds });
5166
5518
  if (aligned) return /* @__PURE__ */ jsx("div", { className: "text-right tabular-nums", children: text });
5167
5519
  if (meta2?.dateFormat) return /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: text });
@@ -5178,7 +5530,7 @@ function DataTable({
5178
5530
  checked: table2.getIsAllPageRowsSelected(),
5179
5531
  indeterminate: table2.getIsSomePageRowsSelected(),
5180
5532
  onCheckedChange: (checked) => table2.toggleAllPageRowsSelected(checked),
5181
- "aria-label": "\u5168\u3066\u9078\u629E"
5533
+ "aria-label": t.selectAll
5182
5534
  }
5183
5535
  ),
5184
5536
  cell: ({ row }) => /* @__PURE__ */ jsx(
@@ -5186,14 +5538,14 @@ function DataTable({
5186
5538
  {
5187
5539
  checked: row.getIsSelected(),
5188
5540
  onCheckedChange: (checked) => row.toggleSelected(checked),
5189
- "aria-label": "\u884C\u3092\u9078\u629E"
5541
+ "aria-label": t.selectRow
5190
5542
  }
5191
5543
  ),
5192
5544
  enableSorting: false,
5193
5545
  enableHiding: false
5194
5546
  };
5195
5547
  return [selectionColumn, ...formatted];
5196
- }, [columns, enableRowSelection]);
5548
+ }, [columns, enableRowSelection, locale, t]);
5197
5549
  const autoResetPage = enablePagination && pageCount === void 0 && rowCount === void 0;
5198
5550
  const resetKey = useRef(null);
5199
5551
  useEffect(() => {
@@ -5359,6 +5711,7 @@ function SortIcon({ sorted }) {
5359
5711
  var DataTableContent = forwardRef(
5360
5712
  ({ className, ...props }, ref) => {
5361
5713
  const { table, visibleColumnCount, isLoading, enablePagination } = useDataTable();
5714
+ const t = useText();
5362
5715
  const { comparisonOf, comparisonIds } = pairComparisons(table.getVisibleLeafColumns());
5363
5716
  return /* @__PURE__ */ jsx(
5364
5717
  "div",
@@ -5439,7 +5792,7 @@ var DataTableContent = forwardRef(
5439
5792
  {
5440
5793
  colSpan: visibleColumnCount,
5441
5794
  className: "h-24 text-center text-muted-foreground",
5442
- children: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093"
5795
+ children: t.noData
5443
5796
  }
5444
5797
  ) }) })
5445
5798
  ] })
@@ -5451,6 +5804,7 @@ DataTableContent.displayName = "DataTableContent";
5451
5804
  var DataTablePagination = forwardRef(
5452
5805
  ({ pageSizeOptions = [10, 20, 50], className, ...props }, ref) => {
5453
5806
  const { table, isLoading } = useDataTable();
5807
+ const t = useText();
5454
5808
  const totalRows = table.options.rowCount !== void 0 ? table.getRowCount() : table.getFilteredRowModel().rows.length;
5455
5809
  const currentPageSize = table.getState().pagination.pageSize;
5456
5810
  const currentPageIndex = table.getState().pagination.pageIndex;
@@ -5458,7 +5812,7 @@ var DataTablePagination = forwardRef(
5458
5812
  const rangeEnd = Math.min((currentPageIndex + 1) * currentPageSize, totalRows);
5459
5813
  const pageSizeItems = pageSizeOptions.map((size) => ({
5460
5814
  value: String(size),
5461
- label: `${size}\u4EF6`
5815
+ label: t.pageSize(size)
5462
5816
  }));
5463
5817
  return /* @__PURE__ */ jsxs(
5464
5818
  "div",
@@ -5470,14 +5824,7 @@ var DataTablePagination = forwardRef(
5470
5824
  ...props,
5471
5825
  children: [
5472
5826
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
5473
- /* @__PURE__ */ jsxs("span", { children: [
5474
- totalRows,
5475
- "\u4EF6\u4E2D ",
5476
- rangeStart,
5477
- " - ",
5478
- rangeEnd,
5479
- " \u3092\u8868\u793A"
5480
- ] }),
5827
+ /* @__PURE__ */ jsx("span", { children: t.range(totalRows, rangeStart, rangeEnd) }),
5481
5828
  /* @__PURE__ */ jsxs(
5482
5829
  Select,
5483
5830
  {
@@ -5485,7 +5832,7 @@ var DataTablePagination = forwardRef(
5485
5832
  value: String(currentPageSize),
5486
5833
  onValueChange: (value) => table.setPageSize(Number(value)),
5487
5834
  children: [
5488
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-[80px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
5835
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "min-w-[80px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
5489
5836
  /* @__PURE__ */ jsx(SelectContent, { children: pageSizeItems.map((item) => /* @__PURE__ */ jsx(SelectItem, { value: item.value, children: item.label }, item.value)) })
5490
5837
  ]
5491
5838
  }
@@ -5499,7 +5846,7 @@ var DataTablePagination = forwardRef(
5499
5846
  size: "sm",
5500
5847
  onClick: () => table.firstPage(),
5501
5848
  disabled: isLoading || !table.getCanPreviousPage(),
5502
- children: "\u6700\u521D"
5849
+ children: t.first
5503
5850
  }
5504
5851
  ),
5505
5852
  /* @__PURE__ */ jsx(
@@ -5509,7 +5856,7 @@ var DataTablePagination = forwardRef(
5509
5856
  size: "sm",
5510
5857
  onClick: () => table.previousPage(),
5511
5858
  disabled: isLoading || !table.getCanPreviousPage(),
5512
- children: "\u524D\u3078"
5859
+ children: t.previous
5513
5860
  }
5514
5861
  ),
5515
5862
  /* @__PURE__ */ jsx(
@@ -5519,7 +5866,7 @@ var DataTablePagination = forwardRef(
5519
5866
  size: "sm",
5520
5867
  onClick: () => table.nextPage(),
5521
5868
  disabled: isLoading || !table.getCanNextPage(),
5522
- children: "\u6B21\u3078"
5869
+ children: t.next
5523
5870
  }
5524
5871
  ),
5525
5872
  /* @__PURE__ */ jsx(
@@ -5529,7 +5876,7 @@ var DataTablePagination = forwardRef(
5529
5876
  size: "sm",
5530
5877
  onClick: () => table.lastPage(),
5531
5878
  disabled: isLoading || !table.getCanNextPage(),
5532
- children: "\u6700\u5F8C"
5879
+ children: t.last
5533
5880
  }
5534
5881
  )
5535
5882
  ] })
@@ -5541,6 +5888,7 @@ var DataTablePagination = forwardRef(
5541
5888
  DataTablePagination.displayName = "DataTablePagination";
5542
5889
  var DataTableColumnVisibility = forwardRef(({ columnLabels, className }, ref) => {
5543
5890
  const { table } = useDataTable();
5891
+ const t = useText();
5544
5892
  const hideableColumns = table.getAllColumns().filter((column) => column.getCanHide());
5545
5893
  if (hideableColumns.length === 0) return null;
5546
5894
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
@@ -5550,7 +5898,7 @@ var DataTableColumnVisibility = forwardRef(({ columnLabels, className }, ref) =>
5550
5898
  ref,
5551
5899
  render: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: cn(className) }),
5552
5900
  "data-slot": "data-table-column-visibility",
5553
- "aria-label": "\u8868\u793A\u3059\u308B\u5217",
5901
+ "aria-label": t.columns,
5554
5902
  children: /* @__PURE__ */ jsx(Columns3, { className: "size-4", "aria-hidden": "true" })
5555
5903
  }
5556
5904
  ),
@@ -5585,7 +5933,8 @@ function toCsv(header, rows, options = {}) {
5585
5933
  ];
5586
5934
  return (bom ? "\uFEFF" : "") + lines.join("\r\n");
5587
5935
  }
5588
- function tableToCsv(table, { values = "display", scope = "filtered" } = {}) {
5936
+ function tableToCsv(table, { values = "display", scope = "filtered", locale: localeArg } = {}) {
5937
+ const locale = resolveLocale(localeArg);
5589
5938
  const columns = table.getVisibleLeafColumns().filter((column) => column.id !== "_select");
5590
5939
  const rows = scope === "page" ? table.getRowModel().rows : table.getSortedRowModel().rows;
5591
5940
  const header = columns.map(
@@ -5595,7 +5944,7 @@ function tableToCsv(table, { values = "display", scope = "filtered" } = {}) {
5595
5944
  (row) => columns.map((column) => {
5596
5945
  const value = row.getValue(column.id);
5597
5946
  const meta = column.columnDef.meta;
5598
- if (values === "display" && (meta?.format || meta?.dateFormat)) return formatCellText(value, row.original, meta);
5947
+ if (values === "display" && (meta?.format || meta?.dateFormat)) return formatCellText(value, row.original, meta, locale);
5599
5948
  if (value === null || value === void 0) return "";
5600
5949
  if (typeof value === "number" || typeof value === "string") return value;
5601
5950
  if (value instanceof Date) return value.toISOString();
@@ -5608,12 +5957,13 @@ function DataTableExport({
5608
5957
  fileName = "export.csv",
5609
5958
  values = "display",
5610
5959
  scope = "filtered",
5611
- children = "CSV \u3092\u66F8\u304D\u51FA\u3059",
5960
+ children,
5612
5961
  className
5613
5962
  }) {
5614
5963
  const { table, isLoading } = useDataTable();
5964
+ const locale = useLocale();
5615
5965
  const onClick = () => {
5616
- const csv = tableToCsv(table, { values, scope });
5966
+ const csv = tableToCsv(table, { values, scope, locale });
5617
5967
  const url = URL.createObjectURL(new Blob([csv], { type: "text/csv;charset=utf-8" }));
5618
5968
  const a = document.createElement("a");
5619
5969
  a.href = url;
@@ -5633,7 +5983,7 @@ function DataTableExport({
5633
5983
  disabled: isLoading,
5634
5984
  children: [
5635
5985
  /* @__PURE__ */ jsx(Download, { className: "size-4", "aria-hidden": "true" }),
5636
- children
5986
+ children ?? TEXT14[uiLanguage(locale)].exportCsv
5637
5987
  ]
5638
5988
  }
5639
5989
  );
@@ -5668,24 +6018,44 @@ function DataTablePreset({
5668
6018
  }
5669
6019
  DataTablePreset.displayName = "DataTablePreset";
5670
6020
  var FilterBarContext = createContext(null);
6021
+ var TEXT15 = {
6022
+ ja: {
6023
+ filters: "\u30D5\u30A3\u30EB\u30BF\u30FC",
6024
+ selected: (count) => ` (${count}\u4EF6\u9078\u629E\u4E2D)`,
6025
+ remove: (filter, option) => `${filter}: ${option} \u3092\u524A\u9664`,
6026
+ clear: "\u30AF\u30EA\u30A2",
6027
+ clearAll: "\u3059\u3079\u3066\u306E\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u30AF\u30EA\u30A2"
6028
+ },
6029
+ en: {
6030
+ filters: "Filters",
6031
+ selected: (count) => ` (${count} selected)`,
6032
+ remove: (filter, option) => `Remove ${filter}: ${option}`,
6033
+ clear: "Clear",
6034
+ clearAll: "Clear all filters"
6035
+ }
6036
+ };
6037
+ var useText2 = () => TEXT15[uiLanguage(useLocale())];
5671
6038
  function useFilterBar() {
5672
6039
  const ctx = useContext(FilterBarContext);
5673
6040
  if (!ctx) throw new Error("useFilterBar must be used within <FilterBar>");
5674
6041
  return ctx;
5675
6042
  }
5676
6043
  var FilterBar = forwardRef(
5677
- ({ value, onChange, onClear, className, children, ...props }, ref) => /* @__PURE__ */ jsx(FilterBarContext.Provider, { value: { value, onChange, onClear }, children: /* @__PURE__ */ jsx(
5678
- "div",
5679
- {
5680
- ref,
5681
- role: "search",
5682
- "aria-label": "\u30D5\u30A3\u30EB\u30BF\u30FC",
5683
- "data-slot": "filter-bar",
5684
- className: cn("flex flex-wrap items-center gap-2", className),
5685
- ...props,
5686
- children
5687
- }
5688
- ) })
6044
+ ({ value, onChange, onClear, className, children, ...props }, ref) => {
6045
+ const t = useText2();
6046
+ return /* @__PURE__ */ jsx(FilterBarContext.Provider, { value: { value, onChange, onClear }, children: /* @__PURE__ */ jsx(
6047
+ "div",
6048
+ {
6049
+ ref,
6050
+ role: "search",
6051
+ "aria-label": t.filters,
6052
+ "data-slot": "filter-bar",
6053
+ className: cn("flex flex-wrap items-center gap-2", className),
6054
+ ...props,
6055
+ children
6056
+ }
6057
+ ) });
6058
+ }
5689
6059
  );
5690
6060
  FilterBar.displayName = "FilterBar";
5691
6061
  var ALL_VALUE = "__squadkit_all__";
@@ -5727,6 +6097,7 @@ function FilterBarMultiSelect({
5727
6097
  className
5728
6098
  }) {
5729
6099
  const { value, onChange } = useFilterBar();
6100
+ const t = useText2();
5730
6101
  const selected = value[filterKey] ?? [];
5731
6102
  const handleToggle = (option) => {
5732
6103
  const next = selected.includes(option) ? selected.filter((v) => v !== option) : [...selected, option];
@@ -5737,7 +6108,7 @@ function FilterBarMultiSelect({
5737
6108
  PopoverTrigger,
5738
6109
  {
5739
6110
  render: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: cn("h-8 gap-1", className) }),
5740
- "aria-label": `${placeholder ?? label2}${selected.length > 0 ? ` (${selected.length}\u4EF6\u9078\u629E\u4E2D)` : ""}`,
6111
+ "aria-label": `${placeholder ?? label2}${selected.length > 0 ? t.selected(selected.length) : ""}`,
5741
6112
  "data-slot": "filter-bar-multi-select",
5742
6113
  children: [
5743
6114
  placeholder ?? label2,
@@ -5769,6 +6140,7 @@ function FilterBarMultiSelect({
5769
6140
  FilterBarMultiSelect.displayName = "FilterBarMultiSelect";
5770
6141
  function FilterBarActiveChips({ filters, className }) {
5771
6142
  const { value, onChange } = useFilterBar();
6143
+ const t = useText2();
5772
6144
  const getActiveChips = () => {
5773
6145
  const chips = [];
5774
6146
  const pushRaw = (key, v) => {
@@ -5839,7 +6211,7 @@ function FilterBarActiveChips({ filters, className }) {
5839
6211
  type: "button",
5840
6212
  className: "ml-0.5 rounded-full p-0.5 hover:bg-muted-foreground/20",
5841
6213
  onClick: () => handleRemoveFilter(chip.key, chip.optionValue),
5842
- "aria-label": `${chip.filterLabel}: ${chip.optionLabel} \u3092\u524A\u9664`,
6214
+ "aria-label": t.remove(chip.filterLabel, chip.optionLabel),
5843
6215
  children: /* @__PURE__ */ jsx(X, { className: "size-3", "aria-hidden": "true" })
5844
6216
  }
5845
6217
  )
@@ -5849,8 +6221,9 @@ function FilterBarActiveChips({ filters, className }) {
5849
6221
  )) });
5850
6222
  }
5851
6223
  FilterBarActiveChips.displayName = "FilterBarActiveChips";
5852
- function FilterBarClearButton({ label: label2 = "\u30AF\u30EA\u30A2", className }) {
6224
+ function FilterBarClearButton({ label: label2, className }) {
5853
6225
  const { value, onClear } = useFilterBar();
6226
+ const t = useText2();
5854
6227
  const hasActiveFilters = Object.values(value).some(
5855
6228
  (v) => Array.isArray(v) ? v.length > 0 : v !== void 0 && v !== ""
5856
6229
  );
@@ -5862,9 +6235,9 @@ function FilterBarClearButton({ label: label2 = "\u30AF\u30EA\u30A2", className
5862
6235
  size: "sm",
5863
6236
  className: cn("h-7 px-2 text-xs", className),
5864
6237
  onClick: onClear,
5865
- "aria-label": "\u3059\u3079\u3066\u306E\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u30AF\u30EA\u30A2",
6238
+ "aria-label": t.clearAll,
5866
6239
  "data-slot": "filter-bar-clear-button",
5867
- children: label2
6240
+ children: label2 ?? t.clear
5868
6241
  }
5869
6242
  );
5870
6243
  }
@@ -5912,13 +6285,16 @@ function FilterBarPreset({
5912
6285
  ] });
5913
6286
  }
5914
6287
  FilterBarPreset.displayName = "FilterBarPreset";
5915
- var DEFAULT_FISCAL_YEAR_START_MONTH = 4;
5916
- var DEFAULT_DATE_PICKER_LOCALE = "en-US";
5917
- function normalizeFiscalYearStartMonth(month) {
5918
- return typeof month === "number" && Number.isInteger(month) && month >= 1 && month <= 12 ? month : DEFAULT_FISCAL_YEAR_START_MONTH;
5919
- }
5920
- function fiscalPeriodRange(date, { unit, fiscalYearStartMonth, offset = 0 }) {
5921
- const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth);
6288
+ function normalizeFiscalYearStartMonth(month, locale) {
6289
+ return typeof month === "number" && Number.isInteger(month) && month >= 1 && month <= 12 ? month : defaultFiscalYearStartMonth(locale);
6290
+ }
6291
+ function fiscalPeriodRange(date, {
6292
+ unit,
6293
+ fiscalYearStartMonth,
6294
+ offset = 0,
6295
+ locale
6296
+ }) {
6297
+ const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth, locale);
5922
6298
  const length = unit === "year" ? 12 : 3;
5923
6299
  const sinceYearStart = (date.getMonth() - (startMonth - 1) + 12) % 12;
5924
6300
  const into = unit === "year" ? sinceYearStart : sinceYearStart % 3;
@@ -5961,16 +6337,20 @@ var PRESET_LABELS = {
5961
6337
  lastFiscalYear: "Last fiscal year"
5962
6338
  }
5963
6339
  };
5964
- var isJapanese = (locale) => locale.toLowerCase().startsWith("ja");
5965
- var WEEK_OPTIONS = { weekStartsOn: 1 };
5966
- var calendarLocale = (locale) => isJapanese(locale) ? ja : void 0;
6340
+ var TEXT16 = {
6341
+ ja: { placeholder: "\u671F\u9593\u3092\u9078\u629E", rangeSeparator: " - " },
6342
+ en: { placeholder: "Pick a date range", rangeSeparator: " \u2013 " }
6343
+ };
6344
+ var calendarLocale = (locale) => uiLanguage(locale) === "ja" ? ja : void 0;
5967
6345
  function createDatePresets({
5968
- locale = DEFAULT_DATE_PICKER_LOCALE,
5969
- fiscalYearStartMonth = DEFAULT_FISCAL_YEAR_START_MONTH,
6346
+ locale: localeArg,
6347
+ fiscalYearStartMonth,
5970
6348
  now = () => /* @__PURE__ */ new Date()
5971
6349
  } = {}) {
5972
- const t = PRESET_LABELS[isJapanese(locale) ? "ja" : "en"];
5973
- const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth);
6350
+ const locale = resolveLocale(localeArg);
6351
+ const t = PRESET_LABELS[uiLanguage(locale)];
6352
+ const startMonth = normalizeFiscalYearStartMonth(fiscalYearStartMonth, locale);
6353
+ const WEEK_OPTIONS = { weekStartsOn: weekStartsOn(locale) };
5974
6354
  const lastDays = (days) => () => {
5975
6355
  const today = now();
5976
6356
  return { from: startOfDay(subDays(today, days - 1)), to: endOfDay(today) };
@@ -6039,24 +6419,26 @@ function findMatchingPreset(presets, value) {
6039
6419
  return range.from != null && range.to != null && isSameDay(range.from, from) && isSameDay(range.to, to);
6040
6420
  });
6041
6421
  }
6042
- var defaultPresets = createDatePresets();
6422
+ var defaultPresets = createDatePresets({ locale: FALLBACK_LOCALE });
6043
6423
  var DateRangePicker = forwardRef(
6044
6424
  function DateRangePicker2({
6045
6425
  value,
6046
6426
  onChange,
6047
6427
  presets: presetsProp,
6048
6428
  showPresets = true,
6049
- locale = DEFAULT_DATE_PICKER_LOCALE,
6050
- fiscalYearStartMonth = DEFAULT_FISCAL_YEAR_START_MONTH,
6429
+ locale: localeProp,
6430
+ fiscalYearStartMonth,
6051
6431
  maxDate,
6052
6432
  minDate,
6053
- placeholder = "\u671F\u9593\u3092\u9078\u629E",
6433
+ placeholder,
6054
6434
  disabled = false,
6055
6435
  className,
6056
6436
  align = "start"
6057
6437
  }, ref) {
6058
6438
  const [open, setOpen] = useState(false);
6059
6439
  const isMobile = useIsMobile();
6440
+ const locale = useLocale(localeProp);
6441
+ const t = TEXT16[uiLanguage(locale)];
6060
6442
  const presets = useMemo(
6061
6443
  () => presetsProp ?? createDatePresets({ locale, fiscalYearStartMonth }),
6062
6444
  [presetsProp, locale, fiscalYearStartMonth]
@@ -6075,9 +6457,9 @@ var DateRangePicker = forwardRef(
6075
6457
  [onChange]
6076
6458
  );
6077
6459
  const formatDateRange2 = () => {
6078
- if (!value?.from) return placeholder;
6079
- if (!value.to) return format(value.from, "yyyy/MM/dd");
6080
- return `${format(value.from, "yyyy/MM/dd")} - ${format(value.to, "yyyy/MM/dd")}`;
6460
+ if (!value?.from) return placeholder ?? t.placeholder;
6461
+ if (!value.to) return formatDate(value.from, "date", locale);
6462
+ return `${formatDate(value.from, "date", locale)}${t.rangeSeparator}${formatDate(value.to, "date", locale)}`;
6081
6463
  };
6082
6464
  const selectedPreset = findMatchingPreset(presets, value);
6083
6465
  const presetLabel = selectedPreset?.label;
@@ -6138,7 +6520,7 @@ var DateRangePicker = forwardRef(
6138
6520
  mode: "range",
6139
6521
  defaultMonth,
6140
6522
  locale: calendarLocale(locale),
6141
- weekStartsOn: isJapanese(locale) ? 1 : void 0,
6523
+ weekStartsOn: weekStartsOn(locale),
6142
6524
  numberOfMonths: isMobile ? 1 : 2,
6143
6525
  selected: calendarSelected,
6144
6526
  onSelect: handleCalendarSelect,
@@ -6273,6 +6655,10 @@ function RemoveButton({ label: label2, onRemove, iconClassName }) {
6273
6655
  }
6274
6656
  );
6275
6657
  }
6658
+ var TEXT17 = {
6659
+ ja: { placeholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044", search: "\u691C\u7D22...", empty: "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F", clear: "\u30AF\u30EA\u30A2" },
6660
+ en: { placeholder: "Select an option", search: "Search...", empty: "No results found.", clear: "Clear" }
6661
+ };
6276
6662
  var NO_OPTIONS2 = [];
6277
6663
  var SearchableSelect = forwardRef(
6278
6664
  function SearchableSelect2({
@@ -6280,15 +6666,16 @@ var SearchableSelect = forwardRef(
6280
6666
  value,
6281
6667
  onChange,
6282
6668
  onSearch,
6283
- placeholder = "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
6284
- searchPlaceholder = "\u691C\u7D22...",
6285
- emptyText = "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F",
6669
+ placeholder,
6670
+ searchPlaceholder,
6671
+ emptyText,
6286
6672
  isLoading = false,
6287
6673
  disabled = false,
6288
6674
  clearable = true,
6289
6675
  className
6290
6676
  }, ref) {
6291
6677
  const [open, setOpen] = useState(false);
6678
+ const t = TEXT17[uiLanguage(useLocale())];
6292
6679
  const allOptions = useMemo(() => flattenOptions(options), [options]);
6293
6680
  const selectedOption = useMemo(
6294
6681
  () => allOptions.find((opt) => opt.value === value),
@@ -6317,9 +6704,9 @@ var SearchableSelect = forwardRef(
6317
6704
  role: "combobox",
6318
6705
  "aria-expanded": open,
6319
6706
  children: [
6320
- /* @__PURE__ */ jsx("span", { className: "truncate", children: selectedOption ? selectedOption.label : placeholder }),
6707
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: selectedOption ? selectedOption.label : placeholder ?? t.placeholder }),
6321
6708
  /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
6322
- clearable && value && /* @__PURE__ */ jsx(RemoveButton, { label: "\u30AF\u30EA\u30A2", onRemove: () => onChange?.(void 0) }),
6709
+ clearable && value && /* @__PURE__ */ jsx(RemoveButton, { label: t.clear, onRemove: () => onChange?.(void 0) }),
6323
6710
  /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" })
6324
6711
  ] })
6325
6712
  ]
@@ -6333,14 +6720,30 @@ var SearchableSelect = forwardRef(
6333
6720
  onSelect: handleSelect,
6334
6721
  onSearch,
6335
6722
  isLoading,
6336
- searchPlaceholder,
6337
- emptyText
6723
+ searchPlaceholder: searchPlaceholder ?? t.search,
6724
+ emptyText: emptyText ?? t.empty
6338
6725
  }
6339
6726
  ) })
6340
6727
  ] }) });
6341
6728
  }
6342
6729
  );
6343
6730
  SearchableSelect.displayName = "SearchableSelect";
6731
+ var TEXT18 = {
6732
+ ja: {
6733
+ placeholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
6734
+ search: "\u691C\u7D22...",
6735
+ empty: "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F",
6736
+ remove: (label2) => `${label2}\u3092\u524A\u9664`,
6737
+ more: (count) => `+${count}\u4EF6`
6738
+ },
6739
+ en: {
6740
+ placeholder: "Select options",
6741
+ search: "Search...",
6742
+ empty: "No results found.",
6743
+ remove: (label2) => `Remove ${label2}`,
6744
+ more: (count) => `+${count} more`
6745
+ }
6746
+ };
6344
6747
  var NO_OPTIONS3 = [];
6345
6748
  var NO_VALUES = [];
6346
6749
  var MultiSelect = forwardRef(function MultiSelect2({
@@ -6349,15 +6752,16 @@ var MultiSelect = forwardRef(function MultiSelect2({
6349
6752
  onChange,
6350
6753
  onSearch,
6351
6754
  maxCount = 3,
6352
- placeholder = "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
6353
- searchPlaceholder = "\u691C\u7D22...",
6354
- emptyText = "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F",
6755
+ placeholder,
6756
+ searchPlaceholder,
6757
+ emptyText,
6355
6758
  isLoading = false,
6356
6759
  disabled = false,
6357
6760
  className
6358
6761
  }, ref) {
6359
6762
  const [open, setOpen] = useState(false);
6360
6763
  const listId = useId();
6764
+ const t = TEXT18[uiLanguage(useLocale())];
6361
6765
  const allOptions = useMemo(() => flattenOptions(options), [options]);
6362
6766
  const selectedOptions = useMemo(
6363
6767
  () => allOptions.filter((opt) => value.includes(opt.value)),
@@ -6385,23 +6789,19 @@ var MultiSelect = forwardRef(function MultiSelect2({
6385
6789
  className
6386
6790
  ),
6387
6791
  children: [
6388
- /* @__PURE__ */ jsx("span", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-1", children: selectedOptions.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
6792
+ /* @__PURE__ */ jsx("span", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-1", children: selectedOptions.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: placeholder ?? t.placeholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
6389
6793
  visibleBadges.map((option) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "shrink-0 gap-1 pr-1", children: [
6390
6794
  /* @__PURE__ */ jsx("span", { className: "max-w-[120px] truncate", children: option.label }),
6391
6795
  /* @__PURE__ */ jsx(
6392
6796
  RemoveButton,
6393
6797
  {
6394
- label: `${option.label}\u3092\u524A\u9664`,
6798
+ label: t.remove(option.label),
6395
6799
  onRemove: () => onChange?.(value.filter((v) => v !== option.value)),
6396
6800
  iconClassName: "size-3"
6397
6801
  }
6398
6802
  )
6399
6803
  ] }, option.value)),
6400
- overflowCount > 0 && /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "shrink-0", children: [
6401
- "+",
6402
- overflowCount,
6403
- "\u4EF6"
6404
- ] })
6804
+ overflowCount > 0 && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "shrink-0", children: t.more(overflowCount) })
6405
6805
  ] }) }),
6406
6806
  /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 shrink-0 opacity-50" })
6407
6807
  ]
@@ -6415,8 +6815,8 @@ var MultiSelect = forwardRef(function MultiSelect2({
6415
6815
  onSelect: handleSelect,
6416
6816
  onSearch,
6417
6817
  isLoading,
6418
- searchPlaceholder,
6419
- emptyText
6818
+ searchPlaceholder: searchPlaceholder ?? t.search,
6819
+ emptyText: emptyText ?? t.empty
6420
6820
  }
6421
6821
  ) })
6422
6822
  ] }) });
@@ -6505,14 +6905,17 @@ function inferPeriodGrain(period) {
6505
6905
  return void 0;
6506
6906
  }
6507
6907
  var RECORD_MIN_POINTS = 6;
6508
- var GRAIN_UNITS = {
6509
- day: "\u65E5",
6510
- week: "\u9031",
6511
- month: "\u304B\u6708",
6512
- quarter: "\u56DB\u534A\u671F",
6513
- year: "\u5E74"
6908
+ var RECORD_TEXT = {
6909
+ ja: (span, grain, lower) => {
6910
+ const units = { day: "\u65E5", week: "\u9031", month: "\u304B\u6708", quarter: "\u56DB\u534A\u671F", year: "\u5E74" };
6911
+ return `\u904E\u53BB ${span} ${units[grain]}\u3067${lower ? "\u6700\u4F4E" : "\u6700\u9AD8"}`;
6912
+ },
6913
+ en: (span, grain, lower) => {
6914
+ const units = { day: "days", week: "weeks", month: "months", quarter: "quarters", year: "years" };
6915
+ return `${lower ? "Lowest" : "Highest"} in ${span} ${units[grain]}`;
6916
+ }
6514
6917
  };
6515
- function detectRecord(history, grain = "month", polarity = "higher-is-better") {
6918
+ function detectRecord(history, grain = "month", polarity = "higher-is-better", locale) {
6516
6919
  if (!history) return null;
6517
6920
  const points = history.filter(isFiniteNumber);
6518
6921
  if (points.length < RECORD_MIN_POINTS) return null;
@@ -6525,7 +6928,7 @@ function detectRecord(history, grain = "month", polarity = "higher-is-better") {
6525
6928
  span,
6526
6929
  grain,
6527
6930
  kind: lower ? "lowest" : "highest",
6528
- label: `\u904E\u53BB ${span} ${GRAIN_UNITS[grain]}\u3067${lower ? "\u6700\u4F4E" : "\u6700\u9AD8"}`
6931
+ label: RECORD_TEXT[uiLanguage(resolveLocale(locale))](span, grain, lower)
6529
6932
  };
6530
6933
  }
6531
6934
  var deltaVariants = cva(
@@ -6554,13 +6957,29 @@ var deltaVariants = cva(
6554
6957
  }
6555
6958
  );
6556
6959
  var DELTA_NOT_COMPARABLE = EMPTY_VALUE;
6557
- function deltaAriaLabel(result, locale = DEFAULT_LOCALE, change = "relative", format2, digits) {
6960
+ var ARIA_TEXT = {
6961
+ ja: {
6962
+ none: (label2) => `${label2} \u6BD4\u8F03\u3067\u304D\u307E\u305B\u3093`,
6963
+ flat: (label2) => `${label2} \u6A2A\u3070\u3044`,
6964
+ points: " \u30DD\u30A4\u30F3\u30C8",
6965
+ change: (label2, amount, up) => `${label2} ${amount} ${up ? "\u5897\u52A0" : "\u6E1B\u5C11"}`
6966
+ },
6967
+ en: {
6968
+ none: (label2) => `${label2}: not comparable`,
6969
+ flat: (label2) => `Flat ${label2}`,
6970
+ points: " points",
6971
+ change: (label2, amount, up) => `${up ? "Up" : "Down"} ${amount} ${label2}`
6972
+ }
6973
+ };
6974
+ function deltaAriaLabel(result, locale, change = "relative", format, digits) {
6975
+ const resolved = resolveLocale(locale);
6976
+ const t = ARIA_TEXT[uiLanguage(resolved)];
6558
6977
  const { label: label2, direction, ratio } = result;
6559
- if (direction === "none" || ratio === null) return `${label2} \u6BD4\u8F03\u3067\u304D\u307E\u305B\u3093`;
6560
- if (direction === "flat") return `${label2} \u6A2A\u3070\u3044`;
6561
- const amount = formatChangeAmount(result, change, locale, format2, digits);
6562
- if (amount === null) return `${label2} \u6BD4\u8F03\u3067\u304D\u307E\u305B\u3093`;
6563
- return `${label2} ${change === "points" ? amount.replace(/pt$/, " \u30DD\u30A4\u30F3\u30C8") : amount} ${direction === "up" ? "\u5897\u52A0" : "\u6E1B\u5C11"}`;
6978
+ if (direction === "none" || ratio === null) return t.none(label2);
6979
+ if (direction === "flat") return t.flat(label2);
6980
+ const amount = formatChangeAmount(result, change, resolved, format, digits);
6981
+ if (amount === null) return t.none(label2);
6982
+ return t.change(label2, change === "points" ? amount.replace(/pt$/, t.points) : amount, direction === "up");
6564
6983
  }
6565
6984
  var Delta = forwardRef(
6566
6985
  ({
@@ -6569,23 +6988,28 @@ var Delta = forwardRef(
6569
6988
  betterWhen,
6570
6989
  polarity,
6571
6990
  neutralBand,
6572
- format: format2,
6991
+ format,
6573
6992
  change,
6574
6993
  digits,
6575
- locale = DEFAULT_LOCALE,
6994
+ locale: localeProp,
6576
6995
  showLabel = true,
6577
6996
  variant = "badge",
6578
6997
  className,
6579
6998
  ...props
6580
6999
  }, ref) => {
7000
+ const locale = useLocale(localeProp);
6581
7001
  if (!comparison) return null;
6582
- const result = computeComparison(value, comparison, { polarity: betterWhen ? betterWhen === "down" ? "lower-is-better" : "higher-is-better" : polarity, neutralBand });
6583
- const display = change ?? defaultChangeDisplay(format2);
6584
- const formatDigits = typeof format2 === "object" && format2 !== null && "digits" in format2 ? format2.digits : void 0;
7002
+ const result = computeComparison(value, comparison, {
7003
+ polarity: betterWhen ? betterWhen === "down" ? "lower-is-better" : "higher-is-better" : polarity,
7004
+ neutralBand,
7005
+ locale
7006
+ });
7007
+ const display = change ?? defaultChangeDisplay(format);
7008
+ const formatDigits = typeof format === "object" && format !== null && "digits" in format ? format.digits : void 0;
6585
7009
  const changeDigits = display === "points" ? digits ?? formatDigits : digits;
6586
7010
  const comparable = result.direction !== "none";
6587
7011
  const Icon = result.direction === "up" ? ArrowUp : result.direction === "down" ? ArrowDown : ArrowRight;
6588
- const text = formatChange(result, display, locale, format2, changeDigits);
7012
+ const text = formatChange(result, display, locale, format, changeDigits);
6589
7013
  return /* @__PURE__ */ jsxs(
6590
7014
  "span",
6591
7015
  {
@@ -6594,7 +7018,7 @@ var Delta = forwardRef(
6594
7018
  "data-slot": "delta",
6595
7019
  "data-direction": result.direction,
6596
7020
  "data-sentiment": result.sentiment,
6597
- "aria-label": deltaAriaLabel(result, locale, display, format2, changeDigits),
7021
+ "aria-label": deltaAriaLabel(result, locale, display, format, changeDigits),
6598
7022
  className: cn(
6599
7023
  deltaVariants({ variant, sentiment: result.sentiment }),
6600
7024
  !comparable && "text-muted-foreground",
@@ -6619,7 +7043,69 @@ var LONG_VALUE_CHARS = 10;
6619
7043
  var DELTA_UNDER_PLACEMENT = "col-start-1 row-span-1 row-start-3 justify-self-start";
6620
7044
  var KPI_FOOTER_CLASS = "flex-col items-start gap-2 rounded-none border-t-0 bg-transparent pt-0 text-sm";
6621
7045
  var PLACEHOLDER = /\{(\w+)\}/g;
6622
- var isJapanese2 = (locale) => locale.toLowerCase().startsWith("ja");
7046
+ var TEXT19 = {
7047
+ ja: {
7048
+ target: "\u76EE\u6A19",
7049
+ provisional: "\u901F\u5831",
7050
+ joiner: "\u30FB",
7051
+ countFrom: (count) => `${count}\u4EF6\u304B\u3089\u96C6\u8A08`,
7052
+ excluded: (count) => `${count}\u4EF6\u3092\u9664\u5916`,
7053
+ noBaseline: (baseline) => `${baseline}\u306E\u5B9F\u7E3E\u304C\u306A\u3044\u305F\u3081\u3001\u6BD4\u8F03\u3067\u304D\u307E\u305B\u3093\u3002`,
7054
+ previous: (baseline, value) => `${baseline} ${value}`,
7055
+ noPrevious: (baseline) => `${baseline}\u306E\u5B9F\u7E3E\u306A\u3057`,
7056
+ barLead: (tl, pct) => `${tl}\u306E ${pct}`,
7057
+ pace: (pct) => `\u3053\u306E\u30DA\u30FC\u30B9\u306A\u3089 ${pct}`,
7058
+ provisionalSuffix: "\uFF08\u78BA\u5B9A\u524D\uFF09",
7059
+ provisionalReached: (tl, target) => `${tl} ${target} \u306B\u5230\u9054\uFF08\u78BA\u5B9A\u524D\uFF09`,
7060
+ provisionalSoFar: (tl, target, pct) => `${tl} ${target} \u306B\u5BFE\u3057\u3066\u73FE\u6642\u70B9 ${pct}\uFF08\u78BA\u5B9A\u524D\uFF09`,
7061
+ provisionalToGo: (tl, target, distance) => `${tl} ${target} \u307E\u3067\u3042\u3068 ${distance}\uFF08\u78BA\u5B9A\u524D\uFF09`,
7062
+ provisionalToGoRate: (tl, distance, pct) => `${tl}\u307E\u3067\u3042\u3068 ${distance}\uFF08\u73FE\u6642\u70B9 ${pct}\u30FB\u78BA\u5B9A\u524D\uFF09`,
7063
+ met: (tl, target) => `${tl} ${target} \u3092\u9054\u6210`,
7064
+ toGo: (tl, target, distance) => `${tl} ${target} \u307E\u3067\u3042\u3068 ${distance}`,
7065
+ reached: (tl, target) => `${tl} ${target} \u306B\u5230\u9054`,
7066
+ reachedRate: (tl, target, pct) => `${tl} ${target} \u306B\u5230\u9054\uFF08${pct} \u9054\u6210\uFF09`,
7067
+ toGoRate: (tl, distance, pct) => `${tl}\u307E\u3067\u3042\u3068 ${distance}\uFF08${pct} \u9054\u6210\uFF09`,
7068
+ progressLabel: (tl) => `${tl}\u306B\u5BFE\u3059\u308B\u9032\u6357`,
7069
+ progressValue: (tl, target, value, pct) => `${tl} ${target} \u306B\u5BFE\u3057\u3066 ${value}\uFF08${pct}\uFF09`,
7070
+ history: (label2, points) => `${label2}\u306E\u63A8\u79FB\uFF08\u76F4\u8FD1 ${points} \u70B9\uFF09`,
7071
+ updatedRelative: (relative2) => `${relative2}\u306B\u66F4\u65B0`,
7072
+ updatedAbsolute: (absolute2) => `${absolute2} \u306B\u66F4\u65B0`,
7073
+ updatedBoth: (absolute2, relative2) => `${absolute2} \u306B\u66F4\u65B0\uFF08${relative2}\uFF09`,
7074
+ summaryExample: "{label}\u306F\u76EE\u6A19\u306E {achievement} \u307E\u3067\u6765\u3066\u3044\u307E\u3059\u3002"
7075
+ },
7076
+ en: {
7077
+ target: "Target",
7078
+ provisional: "Preliminary",
7079
+ joiner: " \xB7 ",
7080
+ countFrom: (count) => `Based on ${count} records`,
7081
+ excluded: (count) => `${count} excluded`,
7082
+ noBaseline: (baseline) => `No ${baseline} data to compare against.`,
7083
+ previous: (baseline, value) => `${capitalize(baseline)}: ${value}`,
7084
+ noPrevious: (baseline) => `No ${baseline} data`,
7085
+ barLead: (tl, pct) => `${tl}: ${pct}`,
7086
+ pace: (pct) => `On pace for ${pct}`,
7087
+ provisionalSuffix: " (preliminary)",
7088
+ provisionalReached: (tl, target) => `${tl} ${target}: reached (preliminary)`,
7089
+ provisionalSoFar: (tl, target, pct) => `${tl} ${target}: ${pct} so far (preliminary)`,
7090
+ provisionalToGo: (tl, target, distance) => `${tl} ${target}: ${distance} to go (preliminary)`,
7091
+ provisionalToGoRate: (tl, distance, pct) => `${tl}: ${distance} to go (${pct} so far, preliminary)`,
7092
+ met: (tl, target) => `${tl} ${target}: met`,
7093
+ toGo: (tl, target, distance) => `${tl} ${target}: ${distance} to go`,
7094
+ reached: (tl, target) => `${tl} ${target}: reached`,
7095
+ reachedRate: (tl, target, pct) => `${tl} ${target}: reached (${pct} achieved)`,
7096
+ toGoRate: (tl, distance, pct) => `${tl}: ${distance} to go (${pct} achieved)`,
7097
+ progressLabel: (tl) => `Progress toward ${tl}`,
7098
+ progressValue: (tl, target, value, pct) => `${value} of ${tl} ${target} (${pct})`,
7099
+ history: (label2, points) => `${label2} trend (last ${points} points)`,
7100
+ updatedRelative: (relative2) => `Updated ${relative2}`,
7101
+ updatedAbsolute: (absolute2) => `Updated ${absolute2}`,
7102
+ updatedBoth: (absolute2, relative2) => `Updated ${absolute2} (${relative2})`,
7103
+ summaryExample: "{label} is at {achievement} of target."
7104
+ }
7105
+ };
7106
+ function capitalize(text) {
7107
+ return text.charAt(0).toUpperCase() + text.slice(1);
7108
+ }
6623
7109
  var isMissing = (v) => v === null || v === void 0 || v === "";
6624
7110
  function fillKpiTemplate(template, values, fallback) {
6625
7111
  let missing = false;
@@ -6647,11 +7133,11 @@ function isProduction() {
6647
7133
  return true;
6648
7134
  }
6649
7135
  }
6650
- function warnShallowSummary(template) {
7136
+ function warnShallowSummary(template, t) {
6651
7137
  if (shallowSummaryWarned || isProduction() || !isShallowSummary(template)) return;
6652
7138
  shallowSummaryWarned = true;
6653
7139
  console.warn(
6654
- `[KpiCard] summary="${template}" only repeats the delta badge and the previous actual. Say one fact beyond the comparison \u2014 composition, target, record or rate (e.g. "{label}\u306F\u76EE\u6A19\u306E {achievement} \u307E\u3067\u6765\u3066\u3044\u307E\u3059\u3002").`
7140
+ `[KpiCard] summary="${template}" only repeats the delta badge and the previous actual. Say one fact beyond the comparison \u2014 composition, target, record or rate (e.g. "${t.summaryExample}").`
6655
7141
  );
6656
7142
  }
6657
7143
  function digitGroups(text) {
@@ -6660,8 +7146,8 @@ function digitGroups(text) {
6660
7146
  function KpiCard({
6661
7147
  label: label2,
6662
7148
  value,
6663
- format: format2,
6664
- locale = DEFAULT_LOCALE,
7149
+ format,
7150
+ locale: localeProp,
6665
7151
  comparison: comparisonProp,
6666
7152
  comparisons,
6667
7153
  provisional,
@@ -6672,7 +7158,7 @@ function KpiCard({
6672
7158
  showPrevious = true,
6673
7159
  summary,
6674
7160
  target,
6675
- targetLabel = "\u76EE\u6A19",
7161
+ targetLabel,
6676
7162
  targetDisplay,
6677
7163
  period,
6678
7164
  history,
@@ -6688,10 +7174,12 @@ function KpiCard({
6688
7174
  className,
6689
7175
  ...props
6690
7176
  }) {
7177
+ const locale = useLocale(localeProp);
7178
+ const t = TEXT19[uiLanguage(locale)];
6691
7179
  const allComparisons = [...comparisonProp ? [comparisonProp] : [], ...comparisons ?? []];
6692
7180
  const comparison = allComparisons[0];
6693
7181
  const isProvisional = provisional !== void 0 && provisional !== false;
6694
- const provisionalLabel = typeof provisional === "object" && provisional.label ? provisional.label : "\u901F\u5831";
7182
+ const provisionalLabel = typeof provisional === "object" && provisional.label ? provisional.label : t.provisional;
6695
7183
  const sample = useSampleMark();
6696
7184
  const polarity = betterWhen ? betterWhen === "down" ? "lower-is-better" : "higher-is-better" : polarityProp;
6697
7185
  const neutral = polarity === "neutral";
@@ -6699,11 +7187,11 @@ function KpiCard({
6699
7187
  const stacked = allComparisons.length > 1;
6700
7188
  const hasTarget = target !== void 0;
6701
7189
  const grain = comparison?.grain ?? historyGrain ?? inferPeriodGrain(period);
6702
- const record = isProvisional || neutral ? null : detectRecord(history, historyGrain ?? grain, polarity);
7190
+ const record = isProvisional || neutral ? null : detectRecord(history, historyGrain ?? grain, polarity, locale);
6703
7191
  const sourceParts = source ? [
6704
7192
  source.period !== void 0 ? formatDatesInText(source.period, locale) : void 0,
6705
- source.count !== void 0 ? `${formatValue(source.count, "number", locale)}\u4EF6\u304B\u3089\u96C6\u8A08` : void 0,
6706
- source.excluded !== void 0 && Number.isFinite(source.excluded) && source.excluded > 0 ? isJapanese2(locale) ? `${formatValue(source.excluded, "number", locale)}\u4EF6\u3092\u9664\u5916` : `${formatValue(source.excluded, "number", locale)} excluded` : void 0,
7193
+ source.count !== void 0 ? t.countFrom(formatValue(source.count, "number", locale)) : void 0,
7194
+ source.excluded !== void 0 && Number.isFinite(source.excluded) && source.excluded > 0 ? t.excluded(formatValue(source.excluded, "number", locale)) : void 0,
6707
7195
  source.name,
6708
7196
  source.note
6709
7197
  ].filter((p) => typeof p === "string" && p !== "") : [];
@@ -6711,11 +7199,11 @@ function KpiCard({
6711
7199
  const historyPoints = (history ?? []).filter((v) => typeof v === "number" && Number.isFinite(v));
6712
7200
  const small = size === "sm";
6713
7201
  const showSparkline = !small && showHistory && historyPoints.length >= SPARKLINE_MIN_POINTS;
6714
- const isRate = formatKind(format2) === "percent";
7202
+ const isRate = formatKind(format) === "percent";
6715
7203
  const byPoints = (targetDisplay ?? (isRate ? "points" : "achievement")) === "points";
6716
7204
  const lower = polarity === "lower-is-better";
6717
7205
  const targetBar = hasTarget && !neutral && !byPoints && !lower;
6718
- if (summary !== void 0) warnShallowSummary(summary);
7206
+ if (summary !== void 0) warnShallowSummary(summary, t);
6719
7207
  const cardClass = cn("row-span-2 grid content-start gap-y-0 grid-rows-subgrid", className);
6720
7208
  const valueSize = small ? "text-xl @[218px]/card:text-2xl" : "text-2xl @[218px]/card:text-4xl";
6721
7209
  if (isLoading) {
@@ -6757,15 +7245,15 @@ function KpiCard({
6757
7245
  }
6758
7246
  );
6759
7247
  }
6760
- const fmt = (v) => formatValue(v, format2, locale);
7248
+ const fmt = (v) => formatValue(v, format, locale);
6761
7249
  const fmtDistance = (v) => isRate ? formatPoints(v, locale, { signDisplay: "never" }) : fmt(v);
6762
7250
  const pct = (v) => formatValue(v, { type: "percent", digits: 0 }, locale);
6763
- const tl = targetLabel;
6764
- const display = change ?? defaultChangeDisplay(format2);
6765
- const digits = display === "points" && typeof format2 === "object" && format2 !== null && "digits" in format2 ? format2.digits : void 0;
7251
+ const tl = targetLabel ?? t.target;
7252
+ const display = change ?? defaultChangeDisplay(format);
7253
+ const digits = display === "points" && typeof format === "object" && format !== null && "digits" in format ? format.digits : void 0;
6766
7254
  const graded = comparison ? { ...comparison, grain } : void 0;
6767
- const result = graded ? computeComparison(value, graded, { polarity, neutralBand }) : null;
6768
- const baseline = graded ? comparisonBaseline(graded.vs, grain, graded.label, graded.toDate) : null;
7255
+ const result = graded ? computeComparison(value, graded, { polarity, neutralBand, locale }) : null;
7256
+ const baseline = graded ? comparisonBaseline(graded.vs, grain, graded.label, graded.toDate, locale) : null;
6769
7257
  const progress = hasTarget && !neutral ? computeTargetProgress(value, target, { period, now, polarity }) : null;
6770
7258
  const projectedValue = !isRate && !byPoints && progress?.projected != null && progress.elapsed ? value / progress.elapsed : null;
6771
7259
  const summaryText = summary ? fillKpiTemplate(
@@ -6773,14 +7261,14 @@ function KpiCard({
6773
7261
  {
6774
7262
  value: fmt(value),
6775
7263
  label: label2,
6776
- delta: result ? formatChange(result, display, locale, format2, digits) : null,
6777
- difference: result?.difference != null ? isRate ? formatPoints(result.difference, locale) : formatDelta(result.difference, format2, locale) : null,
7264
+ delta: result ? formatChange(result, display, locale, format, digits) : null,
7265
+ difference: result?.difference != null ? isRate ? formatPoints(result.difference, locale) : formatDelta(result.difference, format, locale) : null,
6778
7266
  previous: result?.previous != null ? fmt(result.previous) : null,
6779
7267
  target: hasTarget ? fmt(target) : null,
6780
7268
  achievement: progress ? byPoints ? formatPoints(value - target, locale) : pct(progress.achievement) : null,
6781
7269
  remaining: progress ? fmtDistance(progress.remaining) : null
6782
7270
  },
6783
- result && result.direction === "none" && baseline ? `${baseline}\u306E\u5B9F\u7E3E\u304C\u306A\u3044\u305F\u3081\u3001\u6BD4\u8F03\u3067\u304D\u307E\u305B\u3093\u3002` : null
7271
+ result && result.direction === "none" && baseline ? t.noBaseline(baseline) : null
6784
7272
  ) : null;
6785
7273
  const bar = targetBar && progress ? progressBar() : null;
6786
7274
  function progressBar() {
@@ -6788,9 +7276,9 @@ function KpiCard({
6788
7276
  const projected = projectedValue !== null && projectedValue > actual ? projectedValue : actual;
6789
7277
  const scale = Math.max(target, actual, projected);
6790
7278
  const at = (v) => scale > 0 ? v / scale * 100 : 0;
6791
- const parts = [`${tl}\u306E ${pct(progress.achievement)}`];
7279
+ const parts = [t.barLead(tl, pct(progress.achievement))];
6792
7280
  if (projectedValue !== null && progress.projected != null)
6793
- parts.push(`\u3053\u306E\u30DA\u30FC\u30B9\u306A\u3089 ${formatValue(progress.projected, { type: "percent", digits: 0 }, locale)}`);
7281
+ parts.push(t.pace(formatValue(progress.projected, { type: "percent", digits: 0 }, locale)));
6794
7282
  return {
6795
7283
  actualAt: at(actual),
6796
7284
  projectedAt: at(projected),
@@ -6803,13 +7291,13 @@ function KpiCard({
6803
7291
  if (hasTarget && !bar) {
6804
7292
  if (!progress) targetText = `${tl} ${fmt(target)}`;
6805
7293
  else if (isProvisional)
6806
- targetText = progress.achieved ? byPoints ? `${tl} ${fmt(target)} \u306B\u5230\u9054\uFF08\u78BA\u5B9A\u524D\uFF09` : `${tl} ${fmt(target)} \u306B\u5BFE\u3057\u3066\u73FE\u6642\u70B9 ${pct(progress.achievement)}\uFF08\u78BA\u5B9A\u524D\uFF09` : byPoints ? `${tl} ${fmt(target)} \u307E\u3067\u3042\u3068 ${fmtDistance(progress.remaining)}\uFF08\u78BA\u5B9A\u524D\uFF09` : `${tl}\u307E\u3067\u3042\u3068 ${fmtDistance(progress.remaining)}\uFF08\u73FE\u6642\u70B9 ${pct(progress.achievement)}\u30FB\u78BA\u5B9A\u524D\uFF09`;
7294
+ targetText = progress.achieved ? byPoints ? t.provisionalReached(tl, fmt(target)) : t.provisionalSoFar(tl, fmt(target), pct(progress.achievement)) : byPoints ? t.provisionalToGo(tl, fmt(target), fmtDistance(progress.remaining)) : t.provisionalToGoRate(tl, fmtDistance(progress.remaining), pct(progress.achievement));
6807
7295
  else if (lower)
6808
- targetText = progress.achieved ? `${tl} ${fmt(target)} \u3092\u9054\u6210` : `${tl} ${fmt(target)} \u307E\u3067\u3042\u3068 ${fmtDistance(progress.remaining)}`;
7296
+ targetText = progress.achieved ? t.met(tl, fmt(target)) : t.toGo(tl, fmt(target), fmtDistance(progress.remaining));
6809
7297
  else if (byPoints)
6810
- targetText = progress.achieved ? `${tl} ${fmt(target)} \u306B\u5230\u9054` : `${tl} ${fmt(target)} \u307E\u3067\u3042\u3068 ${fmtDistance(progress.remaining)}`;
7298
+ targetText = progress.achieved ? t.reached(tl, fmt(target)) : t.toGo(tl, fmt(target), fmtDistance(progress.remaining));
6811
7299
  else
6812
- targetText = progress.achieved ? `${tl} ${fmt(target)} \u306B\u5230\u9054\uFF08${pct(progress.achievement)} \u9054\u6210\uFF09` : `${tl}\u307E\u3067\u3042\u3068 ${fmtDistance(progress.remaining)}\uFF08${pct(progress.achievement)} \u9054\u6210\uFF09`;
7300
+ targetText = progress.achieved ? t.reachedRate(tl, fmt(target), pct(progress.achievement)) : t.toGoRate(tl, fmtDistance(progress.remaining), pct(progress.achievement));
6813
7301
  }
6814
7302
  const hasFooter = Boolean(summaryText) || record !== null || Boolean(targetText) || sourceParts.length > 0 || hasUpdated || showSparkline;
6815
7303
  const deltas = allComparisons.map((c, i) => /* @__PURE__ */ jsx(
@@ -6819,7 +7307,7 @@ function KpiCard({
6819
7307
  comparison: i === 0 ? graded ?? c : { ...c, grain: c.grain ?? grain },
6820
7308
  polarity,
6821
7309
  neutralBand,
6822
- format: format2,
7310
+ format,
6823
7311
  change: display,
6824
7312
  digits,
6825
7313
  locale
@@ -6852,18 +7340,18 @@ function KpiCard({
6852
7340
  }
6853
7341
  ),
6854
7342
  comparison && (stacked ? /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-comparisons", className: "flex flex-wrap items-center gap-1", children: deltas }) : /* @__PURE__ */ jsx(CardAction, { className: longValue ? DELTA_UNDER_PLACEMENT : DELTA_PLACEMENT, children: deltas })),
6855
- hasPrevious && comparison && /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-previous", className: "col-span-full text-sm text-muted-foreground tabular-nums", children: result?.previous != null ? `${baseline} ${fmt(result.previous)}` : `${baseline}\u306E\u5B9F\u7E3E\u306A\u3057` }),
7343
+ hasPrevious && comparison && /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-previous", className: "col-span-full text-sm text-muted-foreground tabular-nums", children: result?.previous != null ? t.previous(baseline ?? "", fmt(result.previous)) : t.noPrevious(baseline ?? "") }),
6856
7344
  bar && progress && /* @__PURE__ */ jsxs("div", { "data-slot": "kpi-card-target-progress", className: "col-span-full mt-1 flex min-w-0 flex-col gap-1.5", children: [
6857
7345
  /* @__PURE__ */ jsxs(
6858
7346
  "div",
6859
7347
  {
6860
7348
  "data-slot": "kpi-card-target-bar",
6861
7349
  role: "progressbar",
6862
- "aria-label": `${tl}\u306B\u5BFE\u3059\u308B\u9032\u6357`,
7350
+ "aria-label": t.progressLabel(tl),
6863
7351
  "aria-valuemin": 0,
6864
7352
  "aria-valuemax": target,
6865
7353
  "aria-valuenow": Math.min(Math.max(value, 0), target),
6866
- "aria-valuetext": `${tl} ${fmt(target)} \u306B\u5BFE\u3057\u3066 ${fmt(value)}\uFF08${pct(progress.achievement)}\uFF09`,
7354
+ "aria-valuetext": t.progressValue(tl, fmt(target), fmt(value), pct(progress.achievement)),
6867
7355
  className: "relative h-2 w-full overflow-hidden rounded-full bg-muted",
6868
7356
  children: [
6869
7357
  /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 bg-chart-1", style: { width: `${bar.actualAt}%` } }),
@@ -6890,15 +7378,15 @@ function KpiCard({
6890
7378
  "p",
6891
7379
  {
6892
7380
  "data-slot": "kpi-card-target",
6893
- title: [bar.lead, bar.pace].filter(Boolean).join("\u30FB"),
7381
+ title: [bar.lead, bar.pace].filter(Boolean).join(t.joiner),
6894
7382
  className: "truncate text-sm text-muted-foreground tabular-nums",
6895
7383
  children: [
6896
7384
  bar.lead,
6897
7385
  bar.pace && /* @__PURE__ */ jsxs(Fragment, { children: [
6898
- "\u30FB",
7386
+ t.joiner,
6899
7387
  /* @__PURE__ */ jsx("span", { "data-slot": "kpi-card-projection", "data-estimate": "", children: bar.pace })
6900
7388
  ] }),
6901
- isProvisional && "\uFF08\u78BA\u5B9A\u524D\uFF09"
7389
+ isProvisional && t.provisionalSuffix
6902
7390
  ]
6903
7391
  }
6904
7392
  )
@@ -6912,12 +7400,12 @@ function KpiCard({
6912
7400
  "p",
6913
7401
  {
6914
7402
  "data-slot": "kpi-card-source",
6915
- title: sourceParts.join("\u30FB"),
7403
+ title: sourceParts.join(t.joiner),
6916
7404
  className: "line-clamp-2 w-full text-xs leading-normal text-muted-foreground tabular-nums",
6917
- children: sourceParts.join("\u30FB")
7405
+ children: sourceParts.join(t.joiner)
6918
7406
  }
6919
7407
  ),
6920
- hasUpdated && /* @__PURE__ */ jsx("p", { "data-slot": "kpi-card-updated", className: "text-xs leading-normal text-muted-foreground", children: updatedAtText(updatedAt, updatedAtDisplay, locale, now, timeZone) }),
7408
+ hasUpdated && /* @__PURE__ */ jsx("p", { "data-slot": "kpi-card-updated", className: "text-xs leading-normal text-muted-foreground", children: updatedAtText(updatedAt, updatedAtDisplay, locale, t, now, timeZone) }),
6921
7409
  showSparkline && // mt-auto: the footers of a row are as tall as the tallest, so the sparklines share one bottom edge.
6922
7410
  /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-history", className: "mt-auto w-full pt-2 text-chart-1", children: /* @__PURE__ */ jsx(
6923
7411
  Sparkline,
@@ -6926,18 +7414,30 @@ function KpiCard({
6926
7414
  height: SPARKLINE_HEIGHT,
6927
7415
  color: "text-chart-1",
6928
7416
  highlight: "latest",
6929
- "aria-label": `${label2}\u306E\u63A8\u79FB\uFF08\u76F4\u8FD1 ${historyPoints.length} \u70B9\uFF09`
7417
+ "aria-label": t.history(label2, historyPoints.length)
6930
7418
  }
6931
7419
  ) })
6932
7420
  ] })
6933
7421
  ] });
6934
7422
  }
6935
- function updatedAtText(updatedAt, display, locale, now, timeZone) {
7423
+ function updatedAtText(updatedAt, display, locale, t, now, timeZone) {
6936
7424
  const relative2 = formatRelativeTime(updatedAt, { now, locale });
6937
- if (display === "relative") return `${relative2}\u306B\u66F4\u65B0`;
7425
+ if (display === "relative") return t.updatedRelative(relative2);
6938
7426
  const absolute2 = formatDate(updatedAt, "datetime", locale, { timeZone });
6939
- return display === "absolute" ? `${absolute2} \u306B\u66F4\u65B0` : `${absolute2} \u306B\u66F4\u65B0\uFF08${relative2}\uFF09`;
7427
+ return display === "absolute" ? t.updatedAbsolute(absolute2) : t.updatedBoth(absolute2, relative2);
6940
7428
  }
7429
+ var TEXT20 = {
7430
+ ja: {
7431
+ flat: (value) => `\u5909\u5316\u306A\u3057 ${value}%`,
7432
+ up: (value) => `${value}% \u5897\u52A0`,
7433
+ down: (value) => `${value}% \u6E1B\u5C11`
7434
+ },
7435
+ en: {
7436
+ flat: (value) => `No change ${value}%`,
7437
+ up: (value) => `Up ${value}%`,
7438
+ down: (value) => `Down ${value}%`
7439
+ }
7440
+ };
6941
7441
  var trendIndicatorVariants = cva("inline-flex items-center gap-0.5 text-sm font-medium", {
6942
7442
  variants: {
6943
7443
  sentiment: {
@@ -6955,7 +7455,8 @@ var TrendIndicator = forwardRef(
6955
7455
  const isGood = direction === "neutral" ? null : direction === "up" === positiveIsGood;
6956
7456
  const sentiment = isGood === null ? "neutral" : isGood ? "positive" : "negative";
6957
7457
  const Icon = direction === "up" ? ArrowUp : direction === "down" ? ArrowDown : Minus;
6958
- const ariaLabel = direction === "neutral" ? `\u5909\u5316\u306A\u3057 ${value}%` : direction === "up" ? `${value}% \u5897\u52A0` : `${value}% \u6E1B\u5C11`;
7458
+ const t = TEXT20[uiLanguage(useLocale())];
7459
+ const ariaLabel = direction === "neutral" ? t.flat(value) : direction === "up" ? t.up(value) : t.down(value);
6959
7460
  return /* @__PURE__ */ jsxs(
6960
7461
  "span",
6961
7462
  {
@@ -6975,21 +7476,49 @@ var TrendIndicator = forwardRef(
6975
7476
  }
6976
7477
  );
6977
7478
  TrendIndicator.displayName = "TrendIndicator";
7479
+ var STATUS_LABELS = {
7480
+ ja: {
7481
+ success: "\u6B63\u5E38",
7482
+ partial: "\u4E00\u90E8\u5931\u6557",
7483
+ failed: "\u5931\u6557",
7484
+ delayed: "\u9045\u5EF6",
7485
+ running: "\u5B9F\u884C\u4E2D",
7486
+ stopped: "\u505C\u6B62\u4E2D",
7487
+ active: "\u6709\u52B9",
7488
+ inactive: "\u7121\u52B9",
7489
+ warning: "\u8B66\u544A",
7490
+ error: "\u30A8\u30E9\u30FC",
7491
+ pending: "\u4FDD\u7559\u4E2D"
7492
+ },
7493
+ en: {
7494
+ success: "Healthy",
7495
+ partial: "Partially failed",
7496
+ failed: "Failed",
7497
+ delayed: "Delayed",
7498
+ running: "Running",
7499
+ stopped: "Stopped",
7500
+ active: "Active",
7501
+ inactive: "Inactive",
7502
+ warning: "Warning",
7503
+ error: "Error",
7504
+ pending: "Pending"
7505
+ }
7506
+ };
6978
7507
  var STATUS_VOCABULARY = {
6979
- success: { label: "\u6B63\u5E38", tone: "positive" },
6980
- partial: { label: "\u4E00\u90E8\u5931\u6557", tone: "warning" },
6981
- failed: { label: "\u5931\u6557", tone: "negative" },
6982
- delayed: { label: "\u9045\u5EF6", tone: "warning" },
6983
- running: { label: "\u5B9F\u884C\u4E2D", tone: "info" },
6984
- stopped: { label: "\u505C\u6B62\u4E2D", tone: "neutral" },
6985
- active: { label: "\u6709\u52B9", tone: "positive" },
6986
- inactive: { label: "\u7121\u52B9", tone: "neutral" },
6987
- warning: { label: "\u8B66\u544A", tone: "warning" },
6988
- error: { label: "\u30A8\u30E9\u30FC", tone: "negative" },
6989
- pending: { label: "\u4FDD\u7559\u4E2D", tone: "info" }
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" }
6990
7519
  };
6991
- function statusLabel(status) {
6992
- return Object.hasOwn(STATUS_VOCABULARY, status) ? STATUS_VOCABULARY[status].label : status;
7520
+ function statusLabel(status, locale) {
7521
+ return Object.hasOwn(STATUS_VOCABULARY, status) ? STATUS_LABELS[uiLanguage(resolveLocale(locale))][status] : status;
6993
7522
  }
6994
7523
  var defaultColorMap = Object.fromEntries(
6995
7524
  Object.entries(STATUS_VOCABULARY).map(([key, { tone }]) => [key, tone])
@@ -7014,9 +7543,10 @@ var resolveTone = (color) => {
7014
7543
  return legacyColorTones[color] ?? "neutral";
7015
7544
  };
7016
7545
  var StatusBadge = forwardRef(function StatusBadge2({ status, label: label2, colorMap, className }, ref) {
7546
+ const locale = useLocale();
7017
7547
  const mergedColorMap = { ...defaultColorMap, ...colorMap };
7018
7548
  const style = toneStyles[resolveTone(mergedColorMap[status])];
7019
- const displayLabel = label2 ?? statusLabel(status);
7549
+ const displayLabel = label2 ?? statusLabel(status, locale);
7020
7550
  return /* @__PURE__ */ jsxs(
7021
7551
  Badge,
7022
7552
  {
@@ -7047,5 +7577,5 @@ var Placeholder = forwardRef(function Placeholder2({ className, ...props }, ref)
7047
7577
  Placeholder.displayName = "Placeholder";
7048
7578
 
7049
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 };
7050
- //# sourceMappingURL=chunk-QOXXOFGL.js.map
7051
- //# sourceMappingURL=chunk-QOXXOFGL.js.map
7580
+ //# sourceMappingURL=chunk-77CISBMG.js.map
7581
+ //# sourceMappingURL=chunk-77CISBMG.js.map