@squadbase/vantage 0.6.2-dev1.5aae04e → 0.6.2-dev1.5c79ef5

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 (228) hide show
  1. package/dist/{build-X5NVCQKT.js → build-U7GO26HR.js} +7 -7
  2. package/dist/{build-X5NVCQKT.js.map → build-U7GO26HR.js.map} +1 -1
  3. package/dist/{check-ZBIH422T.js → check-MRVAIHG5.js} +5 -5
  4. package/dist/{check-ZBIH422T.js.map → check-MRVAIHG5.js.map} +1 -1
  5. package/dist/chunk-2IAPIOPS.js +152 -0
  6. package/dist/chunk-2IAPIOPS.js.map +1 -0
  7. package/dist/chunk-3RJEOP3J.js +174 -0
  8. package/dist/chunk-3RJEOP3J.js.map +1 -0
  9. package/dist/{chunk-HKSVYMYJ.js → chunk-77CISBMG.js} +1049 -1387
  10. package/dist/chunk-77CISBMG.js.map +1 -0
  11. package/dist/{chunk-V3LF7BE7.js → chunk-ANZLVSEP.js} +4 -5
  12. package/dist/chunk-ANZLVSEP.js.map +1 -0
  13. package/dist/{chunk-XQUSGIDG.js → chunk-CKWPK4RO.js} +10 -3
  14. package/dist/chunk-CKWPK4RO.js.map +1 -0
  15. package/dist/chunk-EG4PX726.js +678 -0
  16. package/dist/chunk-EG4PX726.js.map +1 -0
  17. package/dist/{chunk-2N72FKLB.js → chunk-NZ5QIIG4.js} +33 -11
  18. package/dist/chunk-NZ5QIIG4.js.map +1 -0
  19. package/dist/{chunk-7DZGJQ3P.js → chunk-PJ4SPXHS.js} +23 -6
  20. package/dist/chunk-PJ4SPXHS.js.map +1 -0
  21. package/dist/{chunk-XPQSTZUU.js → chunk-QNOX7WLZ.js} +5 -4
  22. package/dist/chunk-QNOX7WLZ.js.map +1 -0
  23. package/dist/{chunk-PDOBHMUQ.js → chunk-ROHNXP7J.js} +72 -3
  24. package/dist/chunk-ROHNXP7J.js.map +1 -0
  25. package/dist/{chunk-CEXAQQ5W.js → chunk-S5MDTHH7.js} +180 -18
  26. package/dist/chunk-S5MDTHH7.js.map +1 -0
  27. package/dist/{chunk-2ICNHUG6.js → chunk-SDJTTMLK.js} +64 -7
  28. package/dist/chunk-SDJTTMLK.js.map +1 -0
  29. package/dist/{chunk-WAMZWZJB.js → chunk-SHZM3EXB.js} +19 -8
  30. package/dist/chunk-SHZM3EXB.js.map +1 -0
  31. package/dist/chunk-TRMHNMMZ.js +61 -0
  32. package/dist/chunk-TRMHNMMZ.js.map +1 -0
  33. package/dist/{chunk-JKLLFVEU.js → chunk-UWSQUHX6.js} +4 -99
  34. package/dist/chunk-UWSQUHX6.js.map +1 -0
  35. package/dist/cli.js +6 -6
  36. package/dist/client/index.d.ts +2 -0
  37. package/dist/client/index.js +8 -2
  38. package/dist/client/index.js.map +1 -1
  39. package/dist/components/index.d.ts +57 -273
  40. package/dist/components/index.js +6 -3
  41. package/dist/delta-text-CbrOaW83.d.ts +17 -0
  42. package/dist/{dev-4XEDTELV.js → dev-O42JFQ64.js} +7 -7
  43. package/dist/{dev-4XEDTELV.js.map → dev-O42JFQ64.js.map} +1 -1
  44. package/dist/doc/index.d.ts +215 -2
  45. package/dist/doc/index.js +422 -4
  46. package/dist/doc/index.js.map +1 -1
  47. package/dist/{doctor-5E2VEZPK.js → doctor-YD3XAAOT.js} +5 -5
  48. package/dist/{doctor-5E2VEZPK.js.map → doctor-YD3XAAOT.js.map} +1 -1
  49. package/dist/format-DihQkL1N.d.ts +249 -0
  50. package/dist/query/index.js +2 -2
  51. package/dist/{routes-3SGAFDMC.js → routes-PVKNT777.js} +4 -4
  52. package/dist/{routes-3SGAFDMC.js.map → routes-PVKNT777.js.map} +1 -1
  53. package/dist/slide/index.d.ts +272 -1
  54. package/dist/slide/index.js +1023 -2
  55. package/dist/slide/index.js.map +1 -1
  56. package/dist/table/index.js +9 -6
  57. package/dist/table/index.js.map +1 -1
  58. package/dist/ui/index.d.ts +5 -2
  59. package/dist/ui/index.js +6 -6
  60. package/dist/ui/index.js.map +1 -1
  61. package/dist/{upgrade-JHXZBGQS.js → upgrade-6DT7ADRP.js} +4 -4
  62. package/dist/{upgrade-JHXZBGQS.js.map → upgrade-6DT7ADRP.js.map} +1 -1
  63. package/dist/vite/index.js +3 -3
  64. package/docs/en/agent-skills.md +1 -1
  65. package/docs/en/changelog.md +2 -0
  66. package/docs/en/components.md +13 -2
  67. package/docs/en/doc/delta-text.md +40 -0
  68. package/docs/en/doc/doc-action-items.md +49 -0
  69. package/docs/en/doc/doc-callout.md +38 -0
  70. package/docs/en/doc/doc-data-table.md +60 -0
  71. package/docs/en/doc/doc-executive-summary.md +64 -0
  72. package/docs/en/doc/doc-figure.md +56 -0
  73. package/docs/en/doc/doc-key-findings.md +61 -0
  74. package/docs/en/doc/doc-kpi-scorecard.md +80 -0
  75. package/docs/en/doc/doc-notes-and-sources.md +43 -0
  76. package/docs/en/doc/doc-report-header.md +46 -0
  77. package/docs/en/pages-and-metadata.md +15 -0
  78. package/docs/en/parts/area-chart.md +99 -0
  79. package/docs/en/parts/bar-chart.md +91 -0
  80. package/docs/en/parts/bar-list.md +50 -0
  81. package/docs/en/parts/category-bar.md +37 -0
  82. package/docs/en/parts/chart-frame.md +39 -0
  83. package/docs/en/parts/delta.md +4 -3
  84. package/docs/en/parts/donut-chart.md +72 -0
  85. package/docs/en/parts/funnel-steps.md +2 -1
  86. package/docs/en/parts/heatmap.md +53 -0
  87. package/docs/en/parts/kpi-card.md +2 -1
  88. package/docs/en/parts/legend.md +35 -0
  89. package/docs/en/parts/line-chart.md +94 -0
  90. package/docs/en/parts/progress-circle.md +33 -0
  91. package/docs/en/parts/sample-data.md +39 -0
  92. package/docs/en/parts/scatter-chart.md +56 -0
  93. package/docs/en/parts/tracker.md +36 -0
  94. package/docs/en/parts/updated-at.md +30 -0
  95. package/docs/en/parts/waterfall-chart.md +56 -0
  96. package/docs/en/slide/slide-chart-full.md +48 -0
  97. package/docs/en/slide/slide-chart-insight.md +52 -0
  98. package/docs/en/slide/slide-columns.md +46 -0
  99. package/docs/en/slide/slide-comparison.md +68 -0
  100. package/docs/en/slide/slide-cover.md +39 -0
  101. package/docs/en/slide/slide-exec-summary.md +47 -0
  102. package/docs/en/slide/slide-heading.md +38 -0
  103. package/docs/en/slide/slide-kpi-grid.md +55 -0
  104. package/docs/en/slide/slide-kpi-hero.md +58 -0
  105. package/docs/en/slide/slide-next-actions.md +49 -0
  106. package/docs/en/slide/slide-scorecard-table.md +54 -0
  107. package/docs/en/slide/slide-section.md +44 -0
  108. package/docs/en/slide/slide-source-line.md +34 -0
  109. package/docs/en/ui/alert-dialog.md +42 -0
  110. package/docs/en/ui/avatar.md +31 -0
  111. package/docs/en/ui/combobox.md +74 -0
  112. package/docs/en/ui/drawer.md +41 -0
  113. package/docs/en/ui/empty.md +1 -1
  114. package/docs/en/ui/error-state.md +4 -3
  115. package/docs/en/ui/field.md +42 -0
  116. package/docs/en/ui/hover-card.md +21 -0
  117. package/docs/en/ui/kbd.md +17 -0
  118. package/docs/en/ui/loading.md +1 -1
  119. package/docs/en/ui/pagination.md +36 -0
  120. package/docs/en/ui/radio-group.md +21 -0
  121. package/docs/en/ui/toast.md +44 -0
  122. package/docs/en/ui/toggle-group.md +4 -3
  123. package/docs/index.json +857 -77
  124. package/docs/ja/agent-skills.md +1 -1
  125. package/docs/ja/changelog.md +2 -0
  126. package/docs/ja/components.md +12 -1
  127. package/docs/ja/doc/delta-text.md +40 -0
  128. package/docs/ja/doc/doc-action-items.md +49 -0
  129. package/docs/ja/doc/doc-callout.md +38 -0
  130. package/docs/ja/doc/doc-data-table.md +60 -0
  131. package/docs/ja/doc/doc-executive-summary.md +64 -0
  132. package/docs/ja/doc/doc-figure.md +56 -0
  133. package/docs/ja/doc/doc-key-findings.md +61 -0
  134. package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
  135. package/docs/ja/doc/doc-notes-and-sources.md +43 -0
  136. package/docs/ja/doc/doc-report-header.md +46 -0
  137. package/docs/ja/page-types/slide.md +1 -0
  138. package/docs/ja/pages-and-metadata.md +15 -0
  139. package/docs/ja/parts/area-chart.md +49 -25
  140. package/docs/ja/parts/bar-chart.md +50 -24
  141. package/docs/ja/parts/bar-list.md +31 -8
  142. package/docs/ja/parts/chart-frame.md +36 -0
  143. package/docs/ja/parts/delta.md +5 -4
  144. package/docs/ja/parts/donut-chart.md +45 -26
  145. package/docs/ja/parts/funnel-steps.md +27 -8
  146. package/docs/ja/parts/heatmap.md +45 -0
  147. package/docs/ja/parts/kpi-card.md +2 -1
  148. package/docs/ja/parts/legend.md +36 -0
  149. package/docs/ja/parts/line-chart.md +48 -22
  150. package/docs/ja/parts/sample-data.md +61 -0
  151. package/docs/ja/parts/scatter-chart.md +69 -0
  152. package/docs/ja/parts/updated-at.md +27 -0
  153. package/docs/ja/parts/waterfall-chart.md +61 -0
  154. package/docs/ja/slide/slide-chart-full.md +48 -0
  155. package/docs/ja/slide/slide-chart-insight.md +52 -0
  156. package/docs/ja/slide/slide-columns.md +46 -0
  157. package/docs/ja/slide/slide-comparison.md +68 -0
  158. package/docs/ja/slide/slide-cover.md +39 -0
  159. package/docs/ja/slide/slide-exec-summary.md +47 -0
  160. package/docs/ja/slide/slide-heading.md +38 -0
  161. package/docs/ja/slide/slide-kpi-grid.md +55 -0
  162. package/docs/ja/slide/slide-kpi-hero.md +58 -0
  163. package/docs/ja/slide/slide-next-actions.md +49 -0
  164. package/docs/ja/slide/slide-scorecard-table.md +54 -0
  165. package/docs/ja/slide/slide-section.md +44 -0
  166. package/docs/ja/slide/slide-source-line.md +34 -0
  167. package/docs/ja/ui/empty.md +1 -1
  168. package/docs/ja/ui/error-state.md +4 -3
  169. package/docs/ja/ui/loading.md +1 -1
  170. package/docs/ja/ui/toggle-group.md +4 -3
  171. package/package.json +2 -2
  172. package/registry/ui/app-shell.tsx +138 -1
  173. package/registry/ui/area-chart.tsx +389 -104
  174. package/registry/ui/attention-list.tsx +177 -15
  175. package/registry/ui/bar-chart.tsx +386 -104
  176. package/registry/ui/bar-list.tsx +376 -94
  177. package/registry/ui/box-plot-chart.tsx +450 -116
  178. package/registry/ui/category-bar.tsx +292 -57
  179. package/registry/ui/chart-frame.tsx +301 -63
  180. package/registry/ui/data-table.tsx +229 -37
  181. package/registry/ui/date-range-picker.tsx +190 -36
  182. package/registry/ui/delta.tsx +181 -19
  183. package/registry/ui/donut-chart.tsx +385 -103
  184. package/registry/ui/echart.tsx +313 -58
  185. package/registry/ui/filter-bar.tsx +179 -20
  186. package/registry/ui/funnel-steps.tsx +354 -80
  187. package/registry/ui/heatmap.tsx +338 -71
  188. package/registry/ui/histogram-chart.tsx +440 -116
  189. package/registry/ui/kpi-card.tsx +254 -48
  190. package/registry/ui/legend.tsx +374 -93
  191. package/registry/ui/line-chart.tsx +389 -104
  192. package/registry/ui/multi-select.tsx +159 -9
  193. package/registry/ui/page-shell.tsx +148 -10
  194. package/registry/ui/paired-chart.tsx +394 -109
  195. package/registry/ui/progress-circle.tsx +205 -39
  196. package/registry/ui/sample-data.tsx +154 -10
  197. package/registry/ui/scatter-chart.tsx +436 -119
  198. package/registry/ui/searchable-select.tsx +145 -7
  199. package/registry/ui/slider.tsx +1 -1
  200. package/registry/ui/states.tsx +170 -13
  201. package/registry/ui/status-badge.tsx +201 -36
  202. package/registry/ui/tooltip.tsx +6 -2
  203. package/registry/ui/tracker.tsx +214 -42
  204. package/registry/ui/trend-indicator.tsx +151 -8
  205. package/registry/ui/updated-at.tsx +170 -16
  206. package/registry/ui/waterfall-chart.tsx +460 -121
  207. package/skills/vantage-design/SKILL.md +54 -54
  208. package/skills/vantage-design/references/extract.md +26 -27
  209. package/skills/vantage-design/references/format.md +12 -172
  210. package/skills/vantage-design/references/presets.md +50 -110
  211. package/skills/vantage-pitfalls/SKILL.md +5 -0
  212. package/skills/vantage-slide/SKILL.md +54 -36
  213. package/templates/AGENTS.md +32 -16
  214. package/templates/agents/doc.md +48 -0
  215. package/templates/agents/page.md +23 -2
  216. package/templates/agents/slide.md +77 -3
  217. package/theme.css +23 -19
  218. package/dist/chunk-2ICNHUG6.js.map +0 -1
  219. package/dist/chunk-2N72FKLB.js.map +0 -1
  220. package/dist/chunk-7DZGJQ3P.js.map +0 -1
  221. package/dist/chunk-CEXAQQ5W.js.map +0 -1
  222. package/dist/chunk-HKSVYMYJ.js.map +0 -1
  223. package/dist/chunk-JKLLFVEU.js.map +0 -1
  224. package/dist/chunk-PDOBHMUQ.js.map +0 -1
  225. package/dist/chunk-V3LF7BE7.js.map +0 -1
  226. package/dist/chunk-WAMZWZJB.js.map +0 -1
  227. package/dist/chunk-XPQSTZUU.js.map +0 -1
  228. package/dist/chunk-XQUSGIDG.js.map +0 -1
@@ -37,6 +37,140 @@ import { formatDate } from "@squadbase/vantage/components"
37
37
  import { cn } from "@squadbase/vantage/ui"
38
38
  import { Empty } from "@squadbase/vantage/ui"
39
39
  import { StatusBadge } from "@squadbase/vantage/components"
40
+ import { useSyncExternalStore } from "react"
41
+
42
+ /* ---------- inlined from @squadbase/squadkit registry/lib/locale.ts (internal to @squadbase/vantage) ---------- */
43
+
44
+ /**
45
+ * The display language of the parts and the defaults that follow it.
46
+ *
47
+ * The language comes from `<html lang>`: a tag starting with `ja` reads Japanese, anything else English.
48
+ * Without a usable `lang` (missing, invalid, or no `document` — SSR, Node) the locale is `FALLBACK_LOCALE`
49
+ * (`en-US`). A `locale` passed explicitly (a prop, an argument) always wins.
50
+ *
51
+ * Parts read the locale through `useLocale` (`hooks/use-locale`) and pass it down; the pure helpers here
52
+ * and in `format` / `comparison` / `chart-*` take it as an argument and fall back to `documentLocale()`.
53
+ */
54
+
55
+ /** The language of the built-in wording: Japanese or English. */
56
+ type UiLanguage = "ja" | "en"
57
+
58
+ /** The locale used when `<html lang>` gives none (and on the server). */
59
+ const FALLBACK_LOCALE = "en-US"
60
+
61
+ /** `"ja"` when `locale` starts with `ja` (`ja`, `ja-JP`), else `"en"`. A missing locale is `"en"`. */
62
+ function uiLanguage(locale: string | null | undefined): UiLanguage {
63
+ return typeof locale === "string" && locale.trim().toLowerCase().startsWith("ja") ? "ja" : "en"
64
+ }
65
+
66
+ /** A BCP 47 tag in its canonical form (`en-gb` → `en-GB`), or `FALLBACK_LOCALE` when it is empty or invalid. */
67
+ function normalizeLocale(tag: string | null | undefined): string {
68
+ const value = tag?.trim()
69
+ if (!value) return FALLBACK_LOCALE
70
+ try {
71
+ return Intl.getCanonicalLocales(value)[0] ?? FALLBACK_LOCALE
72
+ } catch {
73
+ return FALLBACK_LOCALE
74
+ }
75
+ }
76
+
77
+ /**
78
+ * The locale of the page: `document.documentElement.lang`, canonicalized. `FALLBACK_LOCALE` when it is empty or
79
+ * invalid, or there is no `document`. Parts read it through `useLocale`, never while rendering.
80
+ */
81
+ function documentLocale(): string {
82
+ if (typeof document === "undefined") return FALLBACK_LOCALE
83
+ return normalizeLocale(document.documentElement?.getAttribute("lang"))
84
+ }
85
+
86
+ /** `locale` when given, else the page's locale (`documentLocale()`). */
87
+ function resolveLocale(locale?: string | null): string {
88
+ return locale || documentLocale()
89
+ }
90
+
91
+ /** Picks the wording table of the locale's language. */
92
+ function pickLocale<T>(table: { ja: T; en: T }, locale?: string | null): T {
93
+ return table[uiLanguage(resolveLocale(locale))]
94
+ }
95
+
96
+ /** The currency `format="currency"` uses without a `currency`: JPY for Japanese, USD otherwise. */
97
+ function defaultCurrency(locale?: string | null): string {
98
+ return uiLanguage(resolveLocale(locale)) === "ja" ? "JPY" : "USD"
99
+ }
100
+
101
+ /** The month a fiscal year starts in (1–12) when none is given: April for Japanese, January otherwise. */
102
+ function defaultFiscalYearStartMonth(locale?: string | null): number {
103
+ return uiLanguage(resolveLocale(locale)) === "ja" ? 4 : 1
104
+ }
105
+
106
+ /** A day of the week, 0 = Sunday … 6 = Saturday (the `Date#getDay` / date-fns numbering). */
107
+ type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6
108
+
109
+ /** Locales whose week starts on Sunday when the runtime has no week data. */
110
+ const SUNDAY_FIRST = new Set(["en", "en-US", "en-CA"])
111
+
112
+ /**
113
+ * The first day of the week: Monday for Japanese; otherwise the locale's convention from `Intl.Locale`
114
+ * (`en-US` Sunday, `en-GB` Monday). Without week data in the runtime: Sunday for `en` / `en-US` / `en-CA`,
115
+ * Monday for the rest.
116
+ */
117
+ function weekStartsOn(locale?: string | null): WeekDay {
118
+ const tag = normalizeLocale(resolveLocale(locale))
119
+ if (uiLanguage(tag) === "ja") return 1
120
+ try {
121
+ const info = new Intl.Locale(tag) as Intl.Locale & {
122
+ getWeekInfo?: () => { firstDay: number }
123
+ weekInfo?: { firstDay: number }
124
+ }
125
+ const firstDay = info.getWeekInfo?.().firstDay ?? info.weekInfo?.firstDay
126
+ if (typeof firstDay === "number" && firstDay >= 1 && firstDay <= 7) return (firstDay % 7) as WeekDay
127
+ } catch {
128
+ // Fall through to the table below.
129
+ }
130
+ return SUNDAY_FIRST.has(tag) ? 0 : 1
131
+ }
132
+
133
+ /* ---------- inlined from @squadbase/squadkit registry/hooks/use-locale.ts (internal to @squadbase/vantage) ---------- */
134
+
135
+ const listeners = new Set<() => void>()
136
+ let observer: MutationObserver | null = null
137
+
138
+ /** One observer on `<html lang>` for every subscribed part. */
139
+ function subscribe(onChange: () => void): () => void {
140
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") return () => {}
141
+ listeners.add(onChange)
142
+ if (!observer) {
143
+ observer = new MutationObserver(() => {
144
+ for (const listener of [...listeners]) listener()
145
+ })
146
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["lang"] })
147
+ }
148
+ return () => {
149
+ listeners.delete(onChange)
150
+ if (listeners.size === 0 && observer) {
151
+ observer.disconnect()
152
+ observer = null
153
+ }
154
+ }
155
+ }
156
+
157
+ const serverLocale = () => FALLBACK_LOCALE
158
+
159
+ /**
160
+ * The page's locale (`<html lang>`), following changes made while the page runs. On the server and during
161
+ * hydration it is `FALLBACK_LOCALE` (`en-US`), so the markup matches; it switches right after.
162
+ */
163
+ function useDocumentLocale(): string {
164
+ return useSyncExternalStore(subscribe, documentLocale, serverLocale)
165
+ }
166
+
167
+ /** The locale a part renders in: its `locale` prop when given, else the page's (`useDocumentLocale`). */
168
+ function useLocale(locale?: string | null): string {
169
+ const page = useDocumentLocale()
170
+ return locale || page
171
+ }
172
+
173
+ /* ---------- end of inlined code ---------- */
40
174
 
41
175
  export type AttentionKind = "overdue" | "risk" | "dueSoon" | "stale"
42
176
 
@@ -50,11 +184,37 @@ const KIND_TONES: Record<AttentionKind, string> = {
50
184
  stale: "info",
51
185
  }
52
186
 
53
- export const DEFAULT_ATTENTION_LABELS: Record<AttentionKind, string> = {
54
- overdue: "期日超過",
55
- risk: "リスク",
56
- dueSoon: "期限間近",
57
- stale: "滞留",
187
+ const daysEn = (n: number) => (n === 1 ? "1 day" : `${n} days`)
188
+
189
+ const TEXT = {
190
+ ja: {
191
+ labels: { overdue: "期日超過", risk: "リスク", dueSoon: "期限間近", stale: "滞留" } as Record<AttentionKind, string>,
192
+ overdue: (days: number) => `期日を ${days} 日過ぎています`,
193
+ dueToday: "期日は今日です",
194
+ dueIn: (days: number) => `期日まであと ${days} 日です`,
195
+ stale: (days: number) => `${days} 日間動きがありません`,
196
+ empty: "対応が必要な項目はありません",
197
+ due: "期日",
198
+ nextAction: "次の一手: ",
199
+ },
200
+ en: {
201
+ labels: { overdue: "Overdue", risk: "At risk", dueSoon: "Due soon", stale: "Stalled" } as Record<AttentionKind, string>,
202
+ overdue: (days: number) => `${daysEn(days)} overdue`,
203
+ dueToday: "Due today",
204
+ dueIn: (days: number) => `Due in ${daysEn(days)}`,
205
+ stale: (days: number) => `No activity for ${daysEn(days)}`,
206
+ empty: "Nothing needs attention",
207
+ due: "Due",
208
+ nextAction: "Next step: ",
209
+ },
210
+ } satisfies Record<UiLanguage, unknown>
211
+
212
+ /** The category names in English (the fallback language). The list picks the page's language (`<html lang>`); ja reads 期日超過 / リスク / 期限間近 / 滞留. */
213
+ export const DEFAULT_ATTENTION_LABELS: Record<AttentionKind, string> = TEXT.en.labels
214
+
215
+ /** The category names in `locale`'s language (default the page's, `<html lang>`). */
216
+ export function attentionLabels(locale?: string): Record<AttentionKind, string> {
217
+ return TEXT[uiLanguage(resolveLocale(locale))].labels
58
218
  }
59
219
 
60
220
  type DateInput = Date | string | null | undefined
@@ -124,14 +284,14 @@ export function compareAttention(a: AttentionJudgement | null, b: AttentionJudge
124
284
  return a.kind === "dueSoon" ? a.days - b.days : b.days - a.days
125
285
  }
126
286
 
127
- function defaultReason(j: AttentionJudgement, labels: Record<AttentionKind, string>): string {
287
+ function defaultReason(j: AttentionJudgement, labels: Record<AttentionKind, string>, t: (typeof TEXT)[UiLanguage]): string {
128
288
  switch (j.kind) {
129
289
  case "overdue":
130
- return `期日を ${j.days} 日過ぎています`
290
+ return t.overdue(j.days)
131
291
  case "dueSoon":
132
- return j.days === 0 ? "期日は今日です" : `期日まであと ${j.days} 日です`
292
+ return j.days === 0 ? t.dueToday : t.dueIn(j.days)
133
293
  case "stale":
134
- return `${j.days} 日間動きがありません`
294
+ return t.stale(j.days)
135
295
  case "risk":
136
296
  return labels.risk
137
297
  }
@@ -218,12 +378,14 @@ export function AttentionList<T>({
218
378
  getMeta,
219
379
  onRowClick,
220
380
  includeUnflagged = false,
221
- emptyTitle = "対応が必要な項目はありません",
381
+ emptyTitle,
222
382
  emptyDescription,
223
383
  className,
224
384
  ...rest
225
385
  }: AttentionListProps<T> & Omit<HTMLAttributes<HTMLUListElement>, keyof AttentionListProps<T>>) {
226
- const mergedLabels = useMemo(() => ({ ...DEFAULT_ATTENTION_LABELS, ...labels }), [labels])
386
+ const locale = useLocale()
387
+ const t = TEXT[uiLanguage(locale)]
388
+ const mergedLabels = useMemo(() => ({ ...t.labels, ...labels }), [t, labels])
227
389
  const colorMap = KIND_TONES
228
390
  const dueOf = (row: T) => (getDueDate ? getDueDate(row) : asDateInput(cell(row, dueDateKey)))
229
391
  const nextActionOf = (row: T, j: AttentionJudgement): ReactNode =>
@@ -247,7 +409,7 @@ export function AttentionList<T>({
247
409
  .sort((a, b) => compareAttention(a.judgement, b.judgement) || a.index - b.index)
248
410
 
249
411
  if (items.length === 0) {
250
- return <Empty title={emptyTitle} description={emptyDescription} className={className} />
412
+ return <Empty title={emptyTitle ?? t.empty} description={emptyDescription} className={className} />
251
413
  }
252
414
 
253
415
  return (
@@ -264,18 +426,18 @@ export function AttentionList<T>({
264
426
  {getMeta && <span className="text-sm tabular-nums text-muted-foreground">{getMeta(row)}</span>}
265
427
  {due ? (
266
428
  <span className="ml-auto text-sm tabular-nums text-muted-foreground">
267
- 期日 {formatDate(due)}
429
+ {t.due} {formatDate(due, "date", locale)}
268
430
  </span>
269
431
  ) : null}
270
432
  </div>
271
433
  {judgement && (
272
434
  <p className="mt-1 text-sm text-muted-foreground">
273
- {getReason ? getReason(row, judgement) : defaultReason(judgement, mergedLabels)}
435
+ {getReason ? getReason(row, judgement) : defaultReason(judgement, mergedLabels, t)}
274
436
  </p>
275
437
  )}
276
438
  {judgement && (getNextAction || nextActionKey) && nextActionOf(row, judgement) ? (
277
439
  <p className="mt-1 text-sm">
278
- <span className="text-muted-foreground">次の一手: </span>
440
+ <span className="text-muted-foreground">{t.nextAction}</span>
279
441
  {nextActionOf(row, judgement)}
280
442
  </p>
281
443
  ) : null}