@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.
- package/dist/{build-X5NVCQKT.js → build-U7GO26HR.js} +7 -7
- package/dist/{build-X5NVCQKT.js.map → build-U7GO26HR.js.map} +1 -1
- package/dist/{check-ZBIH422T.js → check-MRVAIHG5.js} +5 -5
- package/dist/{check-ZBIH422T.js.map → check-MRVAIHG5.js.map} +1 -1
- package/dist/chunk-2IAPIOPS.js +152 -0
- package/dist/chunk-2IAPIOPS.js.map +1 -0
- package/dist/chunk-3RJEOP3J.js +174 -0
- package/dist/chunk-3RJEOP3J.js.map +1 -0
- package/dist/{chunk-HKSVYMYJ.js → chunk-77CISBMG.js} +1049 -1387
- package/dist/chunk-77CISBMG.js.map +1 -0
- package/dist/{chunk-V3LF7BE7.js → chunk-ANZLVSEP.js} +4 -5
- package/dist/chunk-ANZLVSEP.js.map +1 -0
- package/dist/{chunk-XQUSGIDG.js → chunk-CKWPK4RO.js} +10 -3
- package/dist/chunk-CKWPK4RO.js.map +1 -0
- package/dist/chunk-EG4PX726.js +678 -0
- package/dist/chunk-EG4PX726.js.map +1 -0
- package/dist/{chunk-2N72FKLB.js → chunk-NZ5QIIG4.js} +33 -11
- package/dist/chunk-NZ5QIIG4.js.map +1 -0
- package/dist/{chunk-7DZGJQ3P.js → chunk-PJ4SPXHS.js} +23 -6
- package/dist/chunk-PJ4SPXHS.js.map +1 -0
- package/dist/{chunk-XPQSTZUU.js → chunk-QNOX7WLZ.js} +5 -4
- package/dist/chunk-QNOX7WLZ.js.map +1 -0
- package/dist/{chunk-PDOBHMUQ.js → chunk-ROHNXP7J.js} +72 -3
- package/dist/chunk-ROHNXP7J.js.map +1 -0
- package/dist/{chunk-CEXAQQ5W.js → chunk-S5MDTHH7.js} +180 -18
- package/dist/chunk-S5MDTHH7.js.map +1 -0
- package/dist/{chunk-2ICNHUG6.js → chunk-SDJTTMLK.js} +64 -7
- package/dist/chunk-SDJTTMLK.js.map +1 -0
- package/dist/{chunk-WAMZWZJB.js → chunk-SHZM3EXB.js} +19 -8
- package/dist/chunk-SHZM3EXB.js.map +1 -0
- package/dist/chunk-TRMHNMMZ.js +61 -0
- package/dist/chunk-TRMHNMMZ.js.map +1 -0
- package/dist/{chunk-JKLLFVEU.js → chunk-UWSQUHX6.js} +4 -99
- package/dist/chunk-UWSQUHX6.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +8 -2
- package/dist/client/index.js.map +1 -1
- package/dist/components/index.d.ts +57 -273
- package/dist/components/index.js +6 -3
- package/dist/delta-text-CbrOaW83.d.ts +17 -0
- package/dist/{dev-4XEDTELV.js → dev-O42JFQ64.js} +7 -7
- package/dist/{dev-4XEDTELV.js.map → dev-O42JFQ64.js.map} +1 -1
- package/dist/doc/index.d.ts +215 -2
- package/dist/doc/index.js +422 -4
- package/dist/doc/index.js.map +1 -1
- package/dist/{doctor-5E2VEZPK.js → doctor-YD3XAAOT.js} +5 -5
- package/dist/{doctor-5E2VEZPK.js.map → doctor-YD3XAAOT.js.map} +1 -1
- package/dist/format-DihQkL1N.d.ts +249 -0
- package/dist/query/index.js +2 -2
- package/dist/{routes-3SGAFDMC.js → routes-PVKNT777.js} +4 -4
- package/dist/{routes-3SGAFDMC.js.map → routes-PVKNT777.js.map} +1 -1
- package/dist/slide/index.d.ts +272 -1
- package/dist/slide/index.js +1023 -2
- package/dist/slide/index.js.map +1 -1
- package/dist/table/index.js +9 -6
- package/dist/table/index.js.map +1 -1
- package/dist/ui/index.d.ts +5 -2
- package/dist/ui/index.js +6 -6
- package/dist/ui/index.js.map +1 -1
- package/dist/{upgrade-JHXZBGQS.js → upgrade-6DT7ADRP.js} +4 -4
- package/dist/{upgrade-JHXZBGQS.js.map → upgrade-6DT7ADRP.js.map} +1 -1
- package/dist/vite/index.js +3 -3
- package/docs/en/agent-skills.md +1 -1
- package/docs/en/changelog.md +2 -0
- package/docs/en/components.md +13 -2
- package/docs/en/doc/delta-text.md +40 -0
- package/docs/en/doc/doc-action-items.md +49 -0
- package/docs/en/doc/doc-callout.md +38 -0
- package/docs/en/doc/doc-data-table.md +60 -0
- package/docs/en/doc/doc-executive-summary.md +64 -0
- package/docs/en/doc/doc-figure.md +56 -0
- package/docs/en/doc/doc-key-findings.md +61 -0
- package/docs/en/doc/doc-kpi-scorecard.md +80 -0
- package/docs/en/doc/doc-notes-and-sources.md +43 -0
- package/docs/en/doc/doc-report-header.md +46 -0
- package/docs/en/pages-and-metadata.md +15 -0
- package/docs/en/parts/area-chart.md +99 -0
- package/docs/en/parts/bar-chart.md +91 -0
- package/docs/en/parts/bar-list.md +50 -0
- package/docs/en/parts/category-bar.md +37 -0
- package/docs/en/parts/chart-frame.md +39 -0
- package/docs/en/parts/delta.md +4 -3
- package/docs/en/parts/donut-chart.md +72 -0
- package/docs/en/parts/funnel-steps.md +2 -1
- package/docs/en/parts/heatmap.md +53 -0
- package/docs/en/parts/kpi-card.md +2 -1
- package/docs/en/parts/legend.md +35 -0
- package/docs/en/parts/line-chart.md +94 -0
- package/docs/en/parts/progress-circle.md +33 -0
- package/docs/en/parts/sample-data.md +39 -0
- package/docs/en/parts/scatter-chart.md +56 -0
- package/docs/en/parts/tracker.md +36 -0
- package/docs/en/parts/updated-at.md +30 -0
- package/docs/en/parts/waterfall-chart.md +56 -0
- package/docs/en/slide/slide-chart-full.md +48 -0
- package/docs/en/slide/slide-chart-insight.md +52 -0
- package/docs/en/slide/slide-columns.md +46 -0
- package/docs/en/slide/slide-comparison.md +68 -0
- package/docs/en/slide/slide-cover.md +39 -0
- package/docs/en/slide/slide-exec-summary.md +47 -0
- package/docs/en/slide/slide-heading.md +38 -0
- package/docs/en/slide/slide-kpi-grid.md +55 -0
- package/docs/en/slide/slide-kpi-hero.md +58 -0
- package/docs/en/slide/slide-next-actions.md +49 -0
- package/docs/en/slide/slide-scorecard-table.md +54 -0
- package/docs/en/slide/slide-section.md +44 -0
- package/docs/en/slide/slide-source-line.md +34 -0
- package/docs/en/ui/alert-dialog.md +42 -0
- package/docs/en/ui/avatar.md +31 -0
- package/docs/en/ui/combobox.md +74 -0
- package/docs/en/ui/drawer.md +41 -0
- package/docs/en/ui/empty.md +1 -1
- package/docs/en/ui/error-state.md +4 -3
- package/docs/en/ui/field.md +42 -0
- package/docs/en/ui/hover-card.md +21 -0
- package/docs/en/ui/kbd.md +17 -0
- package/docs/en/ui/loading.md +1 -1
- package/docs/en/ui/pagination.md +36 -0
- package/docs/en/ui/radio-group.md +21 -0
- package/docs/en/ui/toast.md +44 -0
- package/docs/en/ui/toggle-group.md +4 -3
- package/docs/index.json +857 -77
- package/docs/ja/agent-skills.md +1 -1
- package/docs/ja/changelog.md +2 -0
- package/docs/ja/components.md +12 -1
- package/docs/ja/doc/delta-text.md +40 -0
- package/docs/ja/doc/doc-action-items.md +49 -0
- package/docs/ja/doc/doc-callout.md +38 -0
- package/docs/ja/doc/doc-data-table.md +60 -0
- package/docs/ja/doc/doc-executive-summary.md +64 -0
- package/docs/ja/doc/doc-figure.md +56 -0
- package/docs/ja/doc/doc-key-findings.md +61 -0
- package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
- package/docs/ja/doc/doc-notes-and-sources.md +43 -0
- package/docs/ja/doc/doc-report-header.md +46 -0
- package/docs/ja/page-types/slide.md +1 -0
- package/docs/ja/pages-and-metadata.md +15 -0
- package/docs/ja/parts/area-chart.md +49 -25
- package/docs/ja/parts/bar-chart.md +50 -24
- package/docs/ja/parts/bar-list.md +31 -8
- package/docs/ja/parts/chart-frame.md +36 -0
- package/docs/ja/parts/delta.md +5 -4
- package/docs/ja/parts/donut-chart.md +45 -26
- package/docs/ja/parts/funnel-steps.md +27 -8
- package/docs/ja/parts/heatmap.md +45 -0
- package/docs/ja/parts/kpi-card.md +2 -1
- package/docs/ja/parts/legend.md +36 -0
- package/docs/ja/parts/line-chart.md +48 -22
- package/docs/ja/parts/sample-data.md +61 -0
- package/docs/ja/parts/scatter-chart.md +69 -0
- package/docs/ja/parts/updated-at.md +27 -0
- package/docs/ja/parts/waterfall-chart.md +61 -0
- package/docs/ja/slide/slide-chart-full.md +48 -0
- package/docs/ja/slide/slide-chart-insight.md +52 -0
- package/docs/ja/slide/slide-columns.md +46 -0
- package/docs/ja/slide/slide-comparison.md +68 -0
- package/docs/ja/slide/slide-cover.md +39 -0
- package/docs/ja/slide/slide-exec-summary.md +47 -0
- package/docs/ja/slide/slide-heading.md +38 -0
- package/docs/ja/slide/slide-kpi-grid.md +55 -0
- package/docs/ja/slide/slide-kpi-hero.md +58 -0
- package/docs/ja/slide/slide-next-actions.md +49 -0
- package/docs/ja/slide/slide-scorecard-table.md +54 -0
- package/docs/ja/slide/slide-section.md +44 -0
- package/docs/ja/slide/slide-source-line.md +34 -0
- package/docs/ja/ui/empty.md +1 -1
- package/docs/ja/ui/error-state.md +4 -3
- package/docs/ja/ui/loading.md +1 -1
- package/docs/ja/ui/toggle-group.md +4 -3
- package/package.json +2 -2
- package/registry/ui/app-shell.tsx +138 -1
- package/registry/ui/area-chart.tsx +389 -104
- package/registry/ui/attention-list.tsx +177 -15
- package/registry/ui/bar-chart.tsx +386 -104
- package/registry/ui/bar-list.tsx +376 -94
- package/registry/ui/box-plot-chart.tsx +450 -116
- package/registry/ui/category-bar.tsx +292 -57
- package/registry/ui/chart-frame.tsx +301 -63
- package/registry/ui/data-table.tsx +229 -37
- package/registry/ui/date-range-picker.tsx +190 -36
- package/registry/ui/delta.tsx +181 -19
- package/registry/ui/donut-chart.tsx +385 -103
- package/registry/ui/echart.tsx +313 -58
- package/registry/ui/filter-bar.tsx +179 -20
- package/registry/ui/funnel-steps.tsx +354 -80
- package/registry/ui/heatmap.tsx +338 -71
- package/registry/ui/histogram-chart.tsx +440 -116
- package/registry/ui/kpi-card.tsx +254 -48
- package/registry/ui/legend.tsx +374 -93
- package/registry/ui/line-chart.tsx +389 -104
- package/registry/ui/multi-select.tsx +159 -9
- package/registry/ui/page-shell.tsx +148 -10
- package/registry/ui/paired-chart.tsx +394 -109
- package/registry/ui/progress-circle.tsx +205 -39
- package/registry/ui/sample-data.tsx +154 -10
- package/registry/ui/scatter-chart.tsx +436 -119
- package/registry/ui/searchable-select.tsx +145 -7
- package/registry/ui/slider.tsx +1 -1
- package/registry/ui/states.tsx +170 -13
- package/registry/ui/status-badge.tsx +201 -36
- package/registry/ui/tooltip.tsx +6 -2
- package/registry/ui/tracker.tsx +214 -42
- package/registry/ui/trend-indicator.tsx +151 -8
- package/registry/ui/updated-at.tsx +170 -16
- package/registry/ui/waterfall-chart.tsx +460 -121
- package/skills/vantage-design/SKILL.md +54 -54
- package/skills/vantage-design/references/extract.md +26 -27
- package/skills/vantage-design/references/format.md +12 -172
- package/skills/vantage-design/references/presets.md +50 -110
- package/skills/vantage-pitfalls/SKILL.md +5 -0
- package/skills/vantage-slide/SKILL.md +54 -36
- package/templates/AGENTS.md +32 -16
- package/templates/agents/doc.md +48 -0
- package/templates/agents/page.md +23 -2
- package/templates/agents/slide.md +77 -3
- package/theme.css +23 -19
- package/dist/chunk-2ICNHUG6.js.map +0 -1
- package/dist/chunk-2N72FKLB.js.map +0 -1
- package/dist/chunk-7DZGJQ3P.js.map +0 -1
- package/dist/chunk-CEXAQQ5W.js.map +0 -1
- package/dist/chunk-HKSVYMYJ.js.map +0 -1
- package/dist/chunk-JKLLFVEU.js.map +0 -1
- package/dist/chunk-PDOBHMUQ.js.map +0 -1
- package/dist/chunk-V3LF7BE7.js.map +0 -1
- package/dist/chunk-WAMZWZJB.js.map +0 -1
- package/dist/chunk-XPQSTZUU.js.map +0 -1
- 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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
|
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
|
|
290
|
+
return t.overdue(j.days)
|
|
131
291
|
case "dueSoon":
|
|
132
|
-
return j.days === 0 ?
|
|
292
|
+
return j.days === 0 ? t.dueToday : t.dueIn(j.days)
|
|
133
293
|
case "stale":
|
|
134
|
-
return
|
|
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
|
|
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
|
-
|
|
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"
|
|
440
|
+
<span className="text-muted-foreground">{t.nextAction}</span>
|
|
279
441
|
{nextActionOf(row, judgement)}
|
|
280
442
|
</p>
|
|
281
443
|
) : null}
|