@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
@@ -112,6 +112,11 @@ if (q.isError) return <ErrorState message={q.error.message} /> // HttpError の
112
112
  const rows = useApiQuery<Row[]>("/api/customers", { search: { segment } })
113
113
  ```
114
114
 
115
+ 絞り込み(期間・セグメント)を持つページでは、この `ErrorState` の早期 return をデータを描く
116
+ 子コンポーネントの中に置く。ページの先頭に置くと、失敗したときに絞り込みの欄ごと消えて条件を
117
+ 直せなくなる。期間は `DateRangePicker` で選ばせる(→ `agents/page.md` の「絞り込みの欄は、
118
+ 読み込み中も失敗したときも出し続ける」)。
119
+
115
120
  書き込みは `useApiMutation(path, { method: "POST" })` — 変数がそのまま JSON ボディになる。
116
121
 
117
122
  ## UI コンポーネント / ブロックを追加する
@@ -47,8 +47,9 @@ UI キット・開発サーバー・API サーバー・ビルドはすべて Van
47
47
  - **`definePage` の値はリテラルで書く。** title/description/navLabel はビルド時に静的抽出される
48
48
  ため、変数・関数呼び出し・テンプレート補間は使わない。`page` エクスポートはランタイムでは
49
49
  読まれない。
50
- - **アプリの表示言語は、ルート `_layout.tsx` の `export const lang = "ja"`(リテラル)で指定する。**
50
+ - **アプリの表示言語は、ルート `_layout.tsx` の `export const lang = "en"`(リテラル。BCP 47)で指定する。**
51
51
  `<html lang>` になり、日本語の文節改行とスライドの文言切り替えに効く。未指定は `"en"`。
52
+ 画面の文言・docs・コメントは、ユーザーが使う言語に合わせる(`lang` もその言語にする)。
52
53
 
53
54
  ## ディレクトリ構造(ページをどこに置くか)
54
55
 
@@ -103,8 +104,8 @@ root/
103
104
  | `@squadbase/vantage/server` | `ApiContext`・`ApiHandler`・`HttpError`・`isHttpError`・`json`(server/ 側でのみ使う) |
104
105
 
105
106
  **KPI は `KpiCard`、増減は `Delta`(`comparison` を渡し、下がって良い指標は `betterWhen="down"`)。** 向き・率・色は値から計算
106
- されるので手で渡さない。`TrendIndicator` は非推奨(`direction` を手で渡すので値と食い違いうる)。props は
107
- `vantage docs kpi-card` / `vantage docs delta` を引く。
107
+ されるので手で渡さない。KPI カードを自作しない。`TrendIndicator` は非推奨(`direction` を手で渡すので値と食い違いうる)。props は
108
+ `vantage docs kpi-card` / `vantage docs delta`、数値の書式は `vantage docs format` を引く。
108
109
 
109
110
  ```tsx
110
111
  import { KpiCard, Delta } from "@squadbase/vantage/components";
@@ -135,7 +136,8 @@ import { KpiCard, Delta } from "@squadbase/vantage/components";
135
136
  中立 = `neutral`。系列色は `chart-1`〜`chart-5` を番号順に使う(5 系列まで。超えるなら「その他」に
136
137
  まとめる)。増減の良否は指標の性質(コスト減・解約率減は良い)で決めて
137
138
  positive / negative に分け(`KpiCard` / `Delta` の `betterWhen`。下がって良い指標は `betterWhen="down"`)、向きは ▲▼ や符号で表す。
138
- - **レイアウト:** 内容はカードで包む。順序は KPI → チャート → 表。値が 1 つなら KPI にする
139
+ - **レイアウト:** 内容はカードで包む(ページのチャートはタイトル付きの `DashboardCardPreset` に入れる。
140
+ `EChart` は親の幅に追従する)。順序は KPI → チャート → 表。値が 1 つなら KPI にする
139
141
  (1 本の棒グラフにしない)。強調は 1 画面(スライドは 1 枚)に 1 か所。数値には単位と比較対象を添える。
140
142
  - **Do:** トークンで色を指定する / 色の意味をアプリ全体でそろえる / チャートのタイトルに結論を書く。
141
143
  - **Don't:** 色コードや素のパレットクラスを書く / `dark:` を並べる / 3D・装飾目的のグラデーション・
@@ -146,9 +148,9 @@ import { KpiCard, Delta } from "@squadbase/vantage/components";
146
148
  ブランド素材などユーザー固有の意図)。AGENTS.md の規則に加えて従うが、**色の割り当てはテーマを優先**
147
149
  する。新規には作らない。ユーザーの持ち物で、`vantage upgrade` は書き換えも削除もしない。
148
150
 
149
- **デザイン変更の依頼**(「もっと落ち着いた色に」「ブランドに合わせて」など)は、ファイルごとに
150
- 直さず、テーマの切り替えかスタイルシートの上書きで完結させる。`DESIGN.md` には記録しない。今のテーマ名は
151
- `styles.css` の `/* theme: <name> */` マーカーから読む。手順は Skill `vantage-design`。
151
+ **サイト全体のデザイン変更の依頼**(「もっと落ち着いた色に」「ブランドに合わせて」、配色・フォントの変更など)は、
152
+ ファイルごとに直さず、テーマの切り替えかスタイルシートの上書きで完結させる。`DESIGN.md` には記録しない。今のテーマ名は
153
+ `styles.css` の `/* theme: <name> */` マーカーから読む。手順は Skill `vantage-design` に従う。
152
154
 
153
155
  ## 何を書くか → どのファイルを読むか
154
156
 
@@ -187,7 +189,7 @@ vantage docs button # 1 ページ表示(短縮名。ui/button に解
187
189
  vantage docs parts/data-table # 完全な slug でも引ける
188
190
  vantage docs data-table --json # { slug, title, description, section, content }
189
191
  vantage docs --all # 全ページを連結(まとめて読み込む用)
190
- vantage docs routing --lang en # 英語版(既定は ja)
192
+ vantage docs routing --lang en # 英語版(`--lang` 省略時は ja。アプリの文言の言語とは無関係)
191
193
  ```
192
194
 
193
195
  props の表・使用例・落とし穴はコンポーネントのページに載っている。**推測で props を書く前に
@@ -32,6 +32,9 @@ export async function GET({ params, env }: ApiContext) {
32
32
  (`!` で黙らせない)。
33
33
  - **クライアントに見せたいエラーは `HttpError(status, msg)` を throw する。** それ以外の throw は
34
34
  ログに記録され汎用の 500 に丸められる。
35
+ - **入力の誤りは 400 で返し、`msg` には何がどう誤りかを書く。** `msg` はそのまま `ErrorState` に
36
+ 出る。「開始日(10/20)が終了日(10/01)より後です」のように、利用者が条件を直せる文にする。
37
+ 許す範囲だけを並べた文(「最大366日で指定」)では、どこを直せばよいか伝わらない。
35
38
  - **シークレットは `ApiContext.env` にだけ届く**(クライアントには決して届かない)。
36
39
 
37
40
  クライアント側からは `useApiQuery` で `/api/*` を叩く。ベース URL の解決・JSON パース・
@@ -74,5 +77,9 @@ return <Chart sessions={sessions.data} metrics={metrics.data} />
74
77
  カードごとに別々に読み込み中・エラーを出すなら、`data` を渡す側で `q.data ?? []` にするか、
75
78
  カードのコンポーネントの中で上と同じ判定をする。
76
79
 
80
+ 期間などの絞り込みを持つページでは、上の早期 return をページの先頭に置かない。失敗したときに
81
+ 絞り込みの欄まで消え、条件を直せなくなる。判定はデータを描く子コンポーネントの中で行う
82
+ (→ `agents/page.md` の「絞り込みの欄は、読み込み中も失敗したときも出し続ける」)。
83
+
77
84
  `ApiError` は `message`・`status`・`body`・`requestId` を持つ。hook が使えない場所では
78
85
  `apiJson(path, init)`、生の `Response` が要るときは `apiFetch`。
@@ -147,6 +147,42 @@ const [segments, setSegments] = useSearchState<string[]>("segments", []) // JSON
147
147
  デフォルト値(または `null`)を書くとキーは URL から消える。履歴は既定で `replace`
148
148
  (`{ replace: false }` で push)。
149
149
 
150
+ ### 絞り込みの欄は、読み込み中も失敗したときも出し続ける
151
+
152
+ ページの先頭で `if (q.isError) return <ErrorState …/>` と書くと、取得に失敗したときに
153
+ 期間などの絞り込みの欄まで消える。利用者は条件を直せず、初期値に戻すしかなくなる。
154
+ 絞り込みの欄はページに置いたままにし、取得と `Loading` / `ErrorState` はデータを描く
155
+ 子コンポーネントに入れる:
156
+
157
+ ```tsx
158
+ export default function Traffic() {
159
+ const [from, setFrom] = useSearchParam("from", DEFAULT_FROM)
160
+ const [to, setTo] = useSearchParam("to", DEFAULT_TO)
161
+ return (
162
+ <>
163
+ {/* 失敗しても消えない。ここから条件を直せる */}
164
+ <PeriodFilter from={from} to={to} onChange={…} />
165
+ <TrafficBody from={from} to={to} />
166
+ </>
167
+ )
168
+ }
169
+
170
+ function TrafficBody({ from, to }: { from: string; to: string }) {
171
+ const q = useApiQuery<Row[]>("/api/traffic", { search: { from, to } })
172
+ if (q.isPending) return <Loading />
173
+ if (q.isError) return <ErrorState message={q.error.message} />
174
+ return <BarChart data={q.data} index="channel" categories={["sessions"]} />
175
+ }
176
+ ```
177
+
178
+ - **期間は `DateRangePicker`(`@squadbase/vantage/components`)で選ばせる。** カレンダーで
179
+ 範囲を選ぶので開始と終了が逆にならず、選べる日を `minDate` / `maxDate` で絞れる。
180
+ `<input type="date">` を 2 つ並べて自前で組まない。
181
+ - 値をそのまま打ち込める欄を置くなら、開始が終了より後・選べる範囲の外といった誤りは、
182
+ API へ送る前に欄のそばで理由を出す。誤りがあるあいだはデータの子コンポーネントを描かない
183
+ (送れば失敗するだけで、`ErrorState` には直し方が出ない)。
184
+ - サーバー側の検証で弾くときも、`HttpError(400, …)` の文で何がどう誤りかを言う(→ `agents/api.md`)。
185
+
150
186
  ### 動的パラメータの「3 つの綴り」を同期させる
151
187
 
152
188
  崩すと静かにマッチしなくなる不変条件:
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../squadkit/registry/ui/states.tsx"],"names":[],"mappings":";;;;AAsBO,SAAS,OAAA,CAAQ,EAAE,KAAA,GAAQ,wDAAA,EAAa,WAAU,EAA2C;AAClG,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,iDAAiD,SAAS,CAAA,EAAG,IAAA,EAAK,QAAA,EAAS,WAAA,EAAU,QAAA,EACtG,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uDAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,gFAAA,EAAiF,CAAA;AAAA,IAChG;AAAA,GAAA,EACH,CAAA,EACF,CAAA;AAEJ;AAEO,SAAS,KAAA,CAAM;AAAA,EACpB,KAAA,GAAQ,sFAAA;AAAA,EACR,WAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAMG;AACD,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,kEAAA,EAAoE,SAAS,CAAA,EAC7F,QAAA,EAAA;AAAA,IAAA,IAAA,mBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gCAAA,EAAkC,gBAAK,CAAA,GAAS,IAAA;AAAA,oBACvE,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,aAAA,EAAe,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IACjC,8BAAc,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wCAAA,EAA0C,uBAAY,CAAA,GAAO,IAAA;AAAA,IACxF,yBAAS,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAQ,kBAAO,CAAA,GAAS;AAAA,GAAA,EACnD,CAAA;AAEJ;AAEO,SAAS,UAAA,CAAW;AAAA,EACzB,KAAA,GAAQ,sFAAA;AAAA,EACR,OAAA,GAAU,4OAAA;AAAA,EACV,OAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAQG;AACD,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,8DAAA,EAAgE,SAAS,CAAA;AAAA,MACvF,IAAA,EAAK,OAAA;AAAA,MAEL,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gCAAA,EAAkC,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,QACpD,0BAAU,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,oCAAA,EAAsC,mBAAQ,CAAA,GAAO,IAAA;AAAA,QAC5E,OAAA,mBACC,IAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,oCAAA,EACjB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,4BAAA,EAA6B,QAAA,EAAA,gCAAA,EAAK,CAAA;AAAA,0BACrD,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,OAAA,EAAQ;AAAA,SAAA,EACrD,CAAA,GACE,IAAA;AAAA,QACH,yBAAS,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAQ,kBAAO,CAAA,GAAS;AAAA;AAAA;AAAA,GACnD;AAEJ","file":"chunk-2N72FKLB.js","sourcesContent":["\"use client\"\n\n/**\n * Loading / Empty / ErrorState — the three non-data states of a panel, worded for\n * business users. Defaults are Japanese and say what is happening, not why the\n * system failed: keep raw errors (\"upstream timeout after 30s\") in `details`,\n * which stays folded behind \"詳細を表示\".\n *\n * @example\n * import { ErrorState } from \"@/components/ui/states\"\n * // Vantage: import { ErrorState } from \"@squadbase/vantage/ui\"\n *\n * <ErrorState\n * title=\"売上を読み込めませんでした\"\n * message=\"データソースから時間内に応答がありませんでした。しばらくしてから再試行してください。\"\n * details={error.message}\n * action={<Button variant=\"outline\" onClick={retry}>再試行する</Button>}\n * />\n */\nimport type { ReactNode } from \"react\"\nimport { cn } from \"../lib/utils\"\n\nexport function Loading({ label = \"読み込んでいます…\", className }: { label?: string; className?: string }) {\n return (\n <div className={cn(\"flex min-h-[30vh] items-center justify-center\", className)} role=\"status\" aria-live=\"polite\">\n <div className=\"flex items-center gap-3 text-sm text-muted-foreground\">\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n {label}\n </div>\n </div>\n )\n}\n\nexport function Empty({\n title = \"表示できるデータがありません\",\n description,\n icon,\n action,\n className,\n}: {\n title?: string\n description?: string\n icon?: ReactNode\n action?: ReactNode\n className?: string\n}) {\n return (\n <div className={cn(\"flex flex-col items-center justify-center gap-2 p-10 text-center\", className)}>\n {icon ? <div className=\"text-3xl text-muted-foreground\">{icon}</div> : null}\n <p className=\"font-medium\">{title}</p>\n {description ? <p className=\"max-w-sm text-sm text-muted-foreground\">{description}</p> : null}\n {action ? <div className=\"mt-2\">{action}</div> : null}\n </div>\n )\n}\n\nexport function ErrorState({\n title = \"データを読み込めませんでした\",\n message = \"時間をおいて再試行してください。解決しない場合は管理者にお問い合わせください。\",\n details,\n action,\n className,\n}: {\n title?: string\n /** What happened and what to do next, in plain words. */\n message?: ReactNode\n /** Technical detail (error message, status code), folded behind \"詳細を表示\". */\n details?: ReactNode\n action?: ReactNode\n className?: string\n}) {\n return (\n <div\n className={cn(\"rounded-xl border border-destructive/30 bg-destructive/5 p-6\", className)}\n role=\"alert\"\n >\n <p className=\"font-semibold text-destructive\">{title}</p>\n {message ? <p className=\"mt-1 text-sm text-muted-foreground\">{message}</p> : null}\n {details ? (\n <details className=\"mt-2 text-xs text-muted-foreground\">\n <summary className=\"cursor-pointer select-none\">詳細を表示</summary>\n <div className=\"mt-1 font-mono break-all\">{details}</div>\n </details>\n ) : null}\n {action ? <div className=\"mt-3\">{action}</div> : null}\n </div>\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../squadkit/registry/lib/format.ts"],"names":[],"mappings":"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","file":"chunk-57GHR5LN.js","sourcesContent":["/**\n * Locale-aware number formatting shared by KPI cards, tables and charts. All\n * shortening is delegated to `Intl.NumberFormat` (`notation: \"compact\"`); this\n * module never hard-codes unit thresholds or unit strings.\n *\n * | `format` | input | ja-JP output |\n * |--------------------------------------------|--------------|----------------|\n * | `\"compact\"` (default) | `48_200_000` | `4,820万` |\n * | `\"number\"` | `1234.567` | `1,234.57` |\n * | `\"currency\"` (JPY, compact) | `48_200_000` | `¥4,820万` |\n * | `{ type: \"currency\", notation: \"standard\" }` | `48_200_000` | `¥48,200,000` |\n * | `{ type: \"currency\", currency: \"USD\" }` | `1234.5` | `$1,234.5` |\n * | `\"percent\"` — pass a **ratio** | `0.124` | `12.4%` |\n * | `{ type: \"percent\", digits: 0 }` | `0.124` | `12%` |\n * | `\"multiple\"` | `1.5` | `1.5×` |\n * | `{ type: \"number\", unit: \"件\" }` | `48_210` | `48,210件` |\n * | `{ type: \"compact\", unit: \"人\" }` | `12_345` | `1.2万人` |\n * | `\"duration\"` — pass **seconds** | `12_000` | `3時間20分` |\n * | `{ type: \"duration\", durationUnit: \"minute\" }` | `2160` | `1.5日` |\n *\n * - `percent` takes a ratio (0.124 → 12.4%). Passing 12.4 renders 1,240%. The fraction\n * digits are **fixed**, never trimmed (`PERCENT_DIGITS` = 1: 0.14 → \"14.0%\", never \"14%\"\n * beside \"11.9%\"). Pass `digits` in the format to share another count across cards.\n * - A minus sign is always U+2212 (`MINUS_SIGN`, \"−1,234\" / \"−5.0%\"), never the hyphen-minus.\n * - `currency` defaults to JPY and to compact notation (万・億 in ja); pass\n * `notation: \"standard\"` for every digit (tables, invoices). In ja-JP the yen\n * sign is the half-width `¥`.\n * - `unit` is a counter appended right after the number, with no space\n * (\"48,210件\", \"1.2万人\"), for `number` / `compact` / `currency`. It is\n * ignored for `percent` and `duration`, and for `multiple` it replaces the\n * default `×` (\"2.7倍\"). Do not write it into a `valueFormatter` by hand.\n * - Charts take the same `format` a KpiCard takes (`format=\"currency\"`).\n * `toValueFormatter(format)` turns it into a function for places that need\n * one (a `valueFormatter`, table cells).\n * - Missing values (null / undefined / NaN) render as `—` (`EMPTY_VALUE`).\n * - Dates go through `formatDate` (`Intl.DateTimeFormat`): `\"date\"` → `2026/10/20`,\n * `\"datetime\"` → `2026/10/20 14:30`, `\"year-month\"` → `2026年10月`, `\"month\"` → `10月`,\n * `\"year\"` → `2026年`.\n * - A period goes through `formatDateRange`: `2026/9/23〜10/20` (same year drops the end year),\n * `2025/12/20〜2026/1/18` across years; month and day are not zero-padded.\n */\n\n/**\n * The kind of number a value is. Pick by what the number means, not by how\n * long it is: `currency` for money, `percent` for a ratio, `multiple` for a\n * factor (\"1.5×\"), `duration` for a length of time (\"3時間20分\"), `number` for\n * exact counts in tables, `compact` (default) for large headline counts (万・億).\n */\nexport type FormatKind = \"number\" | \"compact\" | \"currency\" | \"percent\" | \"multiple\" | \"duration\"\n\n/** The unit a `duration` value is measured in. */\nexport type DurationUnit = \"second\" | \"minute\" | \"hour\" | \"day\"\n\n/**\n * How to display a number: a `FormatKind` alone, or an object for digits,\n * currency, notation and a counter. The same value is accepted by KpiCard,\n * Delta, the charts (`format`) and `formatValue`.\n *\n * @example\n * \"currency\" // ¥4,820万\n * { type: \"currency\", notation: \"standard\" } // ¥48,200,000\n * { type: \"percent\", digits: 1 } // 2.0%\n * { type: \"number\", unit: \"件\" } // 48,210件\n */\nexport type ValueFormat =\n | FormatKind\n | {\n type: FormatKind\n /** Fixed number of fraction digits. */\n digits?: number\n /** ISO 4217 code for `currency`. Default `\"JPY\"`. */\n currency?: string\n /** `currency` only: `\"compact\"` (default, 万・億) or `\"standard\"` (every digit). */\n notation?: \"compact\" | \"standard\"\n /** Counter appended after the number, e.g. `\"件\"`, `\"人\"`. Ignored for `percent` and `duration`. For `multiple` it replaces the default `×` (`\"倍\"` → `2.7倍`). */\n unit?: string\n /** 値をこの数で割ってから整形する。例: `divisor: 100`(セント → ドル)。0 と非有限は無視。 */\n divisor?: number\n /** `duration` only: the unit the value is in. Default `\"second\"`. Reads as \"45秒\" / \"12分\" / \"3時間20分\" / \"1.5日\" (`digits` sets the fraction digits of days). */\n durationUnit?: DurationUnit\n }\n\n/** Locale used when none is passed. Every function here takes a `locale` to override it. */\nexport const DEFAULT_LOCALE = \"ja-JP\"\n\n/** Shown in place of a missing value (null / undefined / NaN). */\nexport const EMPTY_VALUE = \"—\"\n\n/** The minus sign every formatter writes (U+2212), so a negative never mixes with a hyphen-minus. */\nexport const MINUS_SIGN = \"\\u2212\"\n\n/** Fraction digits of a `percent` value (and of the points in `formatPoints`) when `digits` is not given. Fixed, never trimmed. */\nexport const PERCENT_DIGITS = 1\n\nconst DEFAULT_CURRENCY = \"JPY\"\nconst MULTIPLE_SUFFIX = \"×\"\n/** Suffix for a difference between two rates, in percentage points. */\nconst POINTS_SUFFIX = \"pt\"\n\n/** Extra options for `formatValue`. */\nexport interface FormatValueOptions {\n /** `\"auto\"` (default) signs negatives only; `\"exceptZero\"` also writes `+` on positives (for differences). */\n signDisplay?: \"auto\" | \"exceptZero\"\n /** Round to this many significant digits (e.g. 3 for an estimate: 79,653,985 → 7,970万). */\n significantDigits?: number\n}\n\ntype NormalizedFormat = Exclude<ValueFormat, FormatKind>\n\nfunction normalize(format: ValueFormat | undefined): NormalizedFormat {\n if (format === undefined) return { type: \"compact\" }\n return typeof format === \"string\" ? { type: format } : format\n}\n\n/**\n * The kind of a format, whether it was given as a string or an object. Use it\n * to branch on the meaning of a metric (e.g. a `percent` metric compares in\n * points) without unpacking `ValueFormat` yourself.\n *\n * @param format - The format as a KpiCard / chart takes it. `undefined` means the default.\n * @returns The `FormatKind`; `\"compact\"` when `format` is omitted.\n *\n * @example\n * formatKind(\"percent\") // \"percent\"\n * formatKind({ type: \"currency\", notation: \"standard\" }) // \"currency\"\n * formatKind(undefined) // \"compact\"\n */\nexport function formatKind(format: ValueFormat | undefined): FormatKind {\n return normalize(format).type\n}\n\nfunction digitOptions(\n digits: number | undefined,\n defaultMax: number | undefined,\n significantDigits: number | undefined,\n): Intl.NumberFormatOptions {\n if (significantDigits !== undefined) return { maximumSignificantDigits: significantDigits }\n if (digits !== undefined) return { minimumFractionDigits: digits, maximumFractionDigits: digits }\n return defaultMax === undefined ? {} : { maximumFractionDigits: defaultMax }\n}\n\n/**\n * Format through Intl, letting Intl decide whether the number is large enough to\n * shorten. Shortened numbers keep digit grouping (\"7,965万\"), and the full-width\n * currency sign some locales emit (\"¥\") is folded to its half-width form (\"¥\").\n */\nfunction formatParts(locale: string, options: Intl.NumberFormatOptions, value: number): string {\n if (options.notation === \"compact\") {\n const compact = new Intl.NumberFormat(locale, {\n ...options,\n useGrouping: \"always\" as unknown as boolean,\n }).formatToParts(value)\n if (!compact.some((p) => p.type === \"compact\")) return formatParts(locale, { ...options, notation: \"standard\" }, value)\n return joinParts(compact)\n }\n return joinParts(new Intl.NumberFormat(locale, options).formatToParts(value))\n}\n\nconst joinParts = (parts: Intl.NumberFormatPart[]): string =>\n parts\n .map((p) => (p.type === \"currency\" ? p.value.normalize(\"NFKC\") : p.type === \"minusSign\" ? MINUS_SIGN : p.value))\n .join(\"\")\n\n/**\n * Format a number for display — KPI values, table cells, chart labels and\n * sentences built from data (titles, summaries). See the table at the top of\n * this module.\n *\n * @param value - The number. `null` / `undefined` / `NaN` render as `—`.\n * For `percent`, a ratio (0.124 means 12.4%).\n * @param format - How to display it. Default `\"compact\"`.\n * @param locale - BCP 47 locale. Default `\"ja-JP\"`.\n * @param options - `signDisplay` and `significantDigits` (rounding for estimates).\n * @returns The display string. In ja-JP the yen sign is the half-width `¥`.\n *\n * @example\n * formatValue(48_200_000, \"currency\") // \"¥4,820万\"\n * formatValue(48_200_000, { type: \"currency\", notation: \"standard\" }) // \"¥48,200,000\"\n * formatValue(0.021, \"percent\") // \"2.1%\"\n * formatValue(0.124, \"percent\", \"ja-JP\", { signDisplay: \"exceptZero\" }) // \"+12.4%\"\n * formatValue(79_653_985, \"currency\", \"ja-JP\", { significantDigits: 3 }) // \"¥7,970万\"\n * formatValue(48_210, { type: \"number\", unit: \"件\" }) // \"48,210件\"\n * formatValue(1.5, \"multiple\") // \"1.5×\"\n * formatValue(null) // \"—\"\n */\nexport function formatValue(\n value: number | null | undefined,\n format?: ValueFormat,\n locale: string = DEFAULT_LOCALE,\n options?: FormatValueOptions,\n): string {\n if (value === null || value === undefined || Number.isNaN(value)) return EMPTY_VALUE\n const { type, digits, currency, notation, unit, divisor, durationUnit } = normalize(format)\n if (divisor !== undefined && Number.isFinite(divisor) && divisor !== 0) value = value / divisor\n const signDisplay = options?.signDisplay ?? \"auto\"\n const sig = options?.significantDigits\n const withUnit = (s: string) => (unit ? `${s}${unit}` : s)\n\n switch (type) {\n case \"number\":\n return withUnit(formatParts(locale, { ...digitOptions(digits, 2, sig), signDisplay }, value))\n case \"percent\":\n return formatParts(locale, { style: \"percent\", ...digitOptions(digits ?? PERCENT_DIGITS, undefined, sig), signDisplay }, value)\n case \"currency\":\n return withUnit(\n formatParts(\n locale,\n {\n style: \"currency\",\n currency: currency ?? DEFAULT_CURRENCY,\n notation: notation ?? \"compact\",\n ...digitOptions(digits, notation === \"standard\" ? undefined : 1, sig),\n signDisplay,\n },\n value,\n ),\n )\n case \"multiple\":\n return `${formatParts(locale, { ...digitOptions(digits, 2, sig), signDisplay }, value)}${unit || MULTIPLE_SUFFIX}`\n case \"compact\":\n return withUnit(formatParts(locale, { ...digitOptions(digits, 1, sig), signDisplay, notation: \"compact\" }, value))\n case \"duration\":\n return formatDuration(value, durationUnit ?? \"second\", locale, digits, signDisplay)\n }\n}\n\nconst SECONDS_PER: Record<DurationUnit, number> = { second: 1, minute: 60, hour: 3600, day: 86_400 }\n\n/**\n * Unit words and spacing: Japanese reads \"3時間20分\" (no space, like \"48,210件\"),\n * other locales \"3 h 20 min\".\n */\nfunction durationWords(locale: string) {\n return locale.toLowerCase().startsWith(\"ja\")\n ? { day: \"日\", hour: \"時間\", minute: \"分\", second: \"秒\", sep: \"\" }\n : { day: \"d\", hour: \"h\", minute: \"min\", second: \"s\", sep: \" \" }\n}\n\n/**\n * A length of time in the largest sensible unit: under a minute in seconds, under\n * an hour in minutes (+ seconds), under a day in hours + minutes, from a day on\n * in days with a decimal (\"1.5日\"). Rounded before splitting, so 59.6 minutes\n * never reads \"59分60秒\".\n */\nfunction formatDuration(\n value: number,\n unit: DurationUnit,\n locale: string,\n digits: number | undefined,\n signDisplay: \"auto\" | \"exceptZero\",\n): string {\n const w = durationWords(locale)\n const abs = Math.round(Math.abs(value) * SECONDS_PER[unit])\n const join = (...parts: Array<[number, string]>) =>\n parts\n .filter(([n]) => n !== 0)\n .map(([n, u]) => `${n}${w.sep}${u}`)\n .join(w.sep) || `0${w.sep}${parts.at(-1)?.[1] ?? w.second}`\n let body: string\n let zero = false\n if (abs >= 86_400) {\n const days = new Intl.NumberFormat(locale, { maximumFractionDigits: digits ?? 1, minimumFractionDigits: digits ?? 0 })\n body = `${days.format(abs / 86_400)}${w.sep}${w.day}`\n } else if (abs >= 3600) {\n const minutes = Math.round(abs / 60)\n body = join([Math.floor(minutes / 60), w.hour], [minutes % 60, w.minute])\n } else if (abs >= 60) {\n body = join([Math.floor(abs / 60), w.minute], [abs % 60, w.second])\n } else {\n zero = abs === 0\n body = `${abs}${w.sep}${w.second}`\n }\n const sign = zero ? \"\" : value < 0 ? MINUS_SIGN : signDisplay === \"exceptZero\" ? \"+\" : \"\"\n return `${sign}${body}`\n}\n\n/**\n * Like `formatValue`, but always signed (except zero) — for a difference\n * between two values (\"+¥530万\", \"−120件\"). Use `formatPoints` instead for a\n * difference between two rates.\n *\n * @param value - The difference (current − previous). Missing values render as `—`.\n * @param format - Format of the metric itself. Default `\"compact\"`.\n * @param locale - BCP 47 locale. Default `\"ja-JP\"`.\n * @returns The signed display string; zero has no sign.\n *\n * @example\n * formatDelta(5_300_000, \"currency\") // \"+¥530万\"\n * formatDelta(-120, { type: \"number\", unit: \"件\" }) // \"−120件\"\n * formatDelta(0.031, \"percent\") // \"+3.1%\"\n * formatDelta(0, \"currency\") // \"¥0\"\n */\nexport function formatDelta(value: number | null | undefined, format?: ValueFormat, locale: string = DEFAULT_LOCALE): string {\n return formatValue(value, format, locale, { signDisplay: \"exceptZero\" })\n}\n\n/**\n * A difference between two rates in percentage points, always signed:\n * `formatPoints(0.021 - 0.026)` → `\"−0.5pt\"`. Use it instead of a relative\n * change for rate metrics (churn, conversion), where \"−19.2%\" reads as a drop\n * of nineteen points. `signDisplay: \"never\"` drops the sign (\"あと 0.5pt\").\n *\n * @param difference - The difference of two **ratios** (0.021 − 0.026). Missing values render as `—`.\n * @param locale - BCP 47 locale. Default `\"ja-JP\"`.\n * @param options - `digits`: fixed fraction digits (default `PERCENT_DIGITS` = 1, so \"0.0pt\" / \"+0.5pt\"); `signDisplay`:\n * `\"exceptZero\"` (default) or `\"never\"` when the sentence already says the direction.\n * @returns The difference in points with the `pt` suffix.\n *\n * @example\n * formatPoints(0.021 - 0.026) // \"−0.5pt\"\n * formatPoints(0.031 - 0.026) // \"+0.5pt\"\n * formatPoints(0.02 - 0.015, \"ja-JP\", { signDisplay: \"never\" }) // \"0.5pt\"(「目標まであと 0.5pt」)\n */\nexport function formatPoints(\n difference: number | null | undefined,\n locale: string = DEFAULT_LOCALE,\n options?: { digits?: number; signDisplay?: \"exceptZero\" | \"never\" },\n): string {\n if (difference === null || difference === undefined || Number.isNaN(difference)) return EMPTY_VALUE\n const digits = options?.digits ?? PERCENT_DIGITS\n const number = formatParts(\n locale,\n { minimumFractionDigits: digits, maximumFractionDigits: digits, signDisplay: options?.signDisplay ?? \"exceptZero\" },\n difference * 100,\n )\n return `${number}${POINTS_SUFFIX}`\n}\n\n/**\n * Binds a format and locale into a single-argument formatter, for a chart\n * `valueFormatter` or a table cell: `valueFormatter={toValueFormatter(\"currency\")}`.\n * Prefer passing `format` to the chart directly; this is for APIs that only\n * take a function.\n *\n * @param format - How to display each value. Default `\"compact\"`.\n * @param locale - BCP 47 locale. Default `\"ja-JP\"`.\n * @returns `(value) => string`, rendering missing values as `—`.\n *\n * @example\n * const yen = toValueFormatter(\"currency\")\n * yen(48_200_000) // \"¥4,820万\"\n * yen(null) // \"—\"\n * const count = toValueFormatter({ type: \"number\", unit: \"件\" })\n * count(48_210) // \"48,210件\"(表のセル)\n */\nexport function toValueFormatter(\n format?: ValueFormat,\n locale: string = DEFAULT_LOCALE,\n): (value: number | null | undefined) => string {\n return (value) => formatValue(value, format, locale)\n}\n\n/**\n * 日付の書式。何を表す日付かで選ぶ: 日単位は `\"date\"`、時刻まで要るなら `\"datetime\"`、\n * 月次の集計は `\"year-month\"`(年をまたぐ軸)か `\"month\"`(同じ年の中の軸)、年次は `\"year\"`。\n */\nexport type DateStyle = \"date\" | \"datetime\" | \"month\" | \"year-month\" | \"year\"\n\n/** `formatDate` の追加オプション。 */\nexport interface FormatDateOptions {\n /**\n * IANA のタイムゾーン名(例: `\"Asia/Tokyo\"`)。既定は実行環境のタイムゾーン。\n * サーバーとブラウザで描画が食い違う(SSR)なら固定する。日付だけの文字列(`\"2026-10-20\"`)には効かず、常にその暦日のまま出す。\n */\n timeZone?: string\n}\n\nconst DATE_STYLE_OPTIONS: Record<DateStyle, Intl.DateTimeFormatOptions> = {\n date: { year: \"numeric\", month: \"2-digit\", day: \"2-digit\" },\n datetime: { year: \"numeric\", month: \"2-digit\", day: \"2-digit\", hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" },\n month: { month: \"short\" },\n \"year-month\": { year: \"numeric\", month: \"long\" },\n year: { year: \"numeric\" },\n}\n\n/** `\"2026-10-20\"` / `\"2026-10\"` はタイムゾーンを持たない暦日。UTC で解釈して UTC で出し、ずれを防ぐ。 */\nconst CALENDAR_DATE = /^\\d{4}-\\d{2}(-\\d{2})?$/\n\n/**\n * 日付を表示用の文字列にする。表のセル・タイトル・文に埋める日付に使い、`toLocaleString` や手組みの\n * `getMonth() + 1` は使わない。\n *\n * @param value - `Date`、エポックミリ秒、または日付文字列(`\"2026-10-20\"`、ISO 8601)。`null` / `undefined` / 解釈できない値は `—`。\n * @param style - 何を表す日付か。既定 `\"date\"`。\n * @param locale - BCP 47 ロケール。既定 `\"ja-JP\"`。\n * @param options - `timeZone`。\n * @returns 表示文字列。\n *\n * @example\n * formatDate(\"2026-10-20\") // \"2026/10/20\"\n * formatDate(new Date(\"2026-10-20T05:30:00Z\"), \"datetime\", \"ja-JP\", { timeZone: \"Asia/Tokyo\" }) // \"2026/10/20 14:30\"\n * formatDate(\"2026-10-01\", \"year-month\") // \"2026年10月\"\n * formatDate(\"2026-10-01\", \"month\") // \"10月\"\n * formatDate(null) // \"—\"\n */\nexport function formatDate(\n value: Date | string | number | null | undefined,\n style: DateStyle = \"date\",\n locale: string = DEFAULT_LOCALE,\n options?: FormatDateOptions,\n): string {\n if (value === null || value === undefined || value === \"\") return EMPTY_VALUE\n const calendar = typeof value === \"string\" && CALENDAR_DATE.test(value)\n const date = value instanceof Date ? value : new Date(value)\n if (!Number.isFinite(date.getTime())) return EMPTY_VALUE\n return new Intl.DateTimeFormat(locale, {\n ...DATE_STYLE_OPTIONS[style],\n timeZone: calendar ? \"UTC\" : options?.timeZone,\n }).format(date)\n}\n\n/** `formatDateRange` のオプション。 */\nexport interface FormatDateRangeOptions extends FormatDateOptions {\n /** BCP 47 ロケール。既定 `\"ja-JP\"`。 */\n locale?: string\n}\n\n/**\n * 期間を「2026/9/23〜10/20」の形にする。同じ年なら終了側の年を省き、年をまたぐときは両方に付ける。\n * 月日はゼロ詰めしない。区切りは日本語で「〜」、それ以外のロケールでは「 – 」。始まりと終わりが同じ日なら 1 日だけ出す。\n *\n * @param start - 期間の最初の日(`Date`、エポックミリ秒、日付文字列)。`\"2026-09-23\"` のような日付だけの文字列はその暦日のまま出す。\n * @param end - 期間の最後の日。\n * @param options - `locale` と `timeZone`。\n * @returns 表示文字列。どちらかが解釈できなければ `—`。\n *\n * @example\n * formatDateRange(\"2026-09-23\", \"2026-10-20\") // \"2026/9/23〜10/20\"\n * formatDateRange(\"2025-12-20\", \"2026-01-18\") // \"2025/12/20〜2026/1/18\"\n */\nexport function formatDateRange(\n start: Date | string | number | null | undefined,\n end: Date | string | number | null | undefined,\n options?: FormatDateRangeOptions,\n): string {\n const locale = options?.locale ?? DEFAULT_LOCALE\n const parse = (value: Date | string | number | null | undefined) => {\n if (value === null || value === undefined || value === \"\") return null\n const calendar = typeof value === \"string\" && CALENDAR_DATE.test(value)\n const date = value instanceof Date ? value : new Date(value)\n if (!Number.isFinite(date.getTime())) return null\n return { date, timeZone: calendar ? \"UTC\" : options?.timeZone }\n }\n const a = parse(start)\n const b = parse(end)\n if (!a || !b) return EMPTY_VALUE\n const full = (x: NonNullable<typeof a>, withYear: boolean) =>\n new Intl.DateTimeFormat(locale, {\n ...(withYear ? { year: \"numeric\" } : {}),\n month: \"numeric\",\n day: \"numeric\",\n timeZone: x.timeZone,\n } as Intl.DateTimeFormatOptions).format(x.date)\n const year = (x: NonNullable<typeof a>) =>\n new Intl.DateTimeFormat(\"en-US\", { year: \"numeric\", timeZone: x.timeZone }).format(x.date)\n const startText = full(a, true)\n const sameYear = year(a) === year(b)\n const endFull = full(b, true)\n if (startText === endFull) return startText\n const separator = locale.toLowerCase().startsWith(\"ja\") ? \"〜\" : \" – \"\n return `${startText}${separator}${sameYear ? full(b, false) : endFull}`\n}\n\n/**\n * 文中の ISO の年月・日付(`2023-04`、`2026-10-20`)を `formatDate` の書式に置き換える。期間や出典の注記のように、\n * 利用者が文字列で渡す文に日付が混ざるときの表示用(`\"2023-04 以降\"` → `\"2023年4月 以降\"`)。日付でない数字は触らない。\n *\n * @param text - 日付を含みうる文。\n * @param locale - BCP 47 ロケール。既定 `\"ja-JP\"`。\n * @returns ISO の年月は `\"year-month\"`、年月日は `\"date\"` で整形した文。\n */\nexport function formatDatesInText(text: string, locale: string = DEFAULT_LOCALE): string {\n return text.replace(/(?<![\\d-])(\\d{4})-(0[1-9]|1[0-2])(-(0[1-9]|[12]\\d|3[01]))?(?![\\d-])/g, (match, _y, _m, day) =>\n formatDate(match, day ? \"date\" : \"year-month\", locale),\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../squadkit/registry/blocks/delta-text/delta-text.tsx"],"names":[],"mappings":";;;;AA4BA,IAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,kBAAA,EAAmB;AAEnC,SAAS,UAAU,EAAE,KAAA,EAAO,QAAQ,UAAA,GAAa,IAAA,EAAM,iBAAgB,EAAmB;AAC/F,EAAA,MAAM,KAAA,GAAQ,eAAA,mBAAkB,IAAA,CAAC,MAAA,EAAA,EAAK,OAAO,KAAA,EAAQ,QAAA,EAAA;AAAA,IAAA,eAAA;AAAA,IAAgB;AAAA,GAAA,EAAC,CAAA,GAAU,IAAA;AAChF,EAAA,IAAI,UAAU,IAAA,EAAM;AAClB,IAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,MAAA,KAAA;AAAA,0BACA,MAAA,EAAA,EAAK,WAAA,EAAU,YAAA,EAAa,KAAA,EAAO,OAAO,QAAA,EAAA,QAAA,EAE3C;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AACA,EAAA,MAAM,MAAM,KAAA,GAAQ,CAAA,GAAI,IAAA,GAAO,KAAA,GAAQ,IAAI,MAAA,GAAS,MAAA;AACpD,EAAA,MAAM,OAAO,GAAA,KAAQ,IAAA,GAAO,QAAA,GAAM,GAAA,KAAQ,SAAS,QAAA,GAAM,QAAA;AACzD,EAAA,MAAM,OAAO,GAAA,KAAQ,IAAA,GAAO,QAAA,GAAM,GAAA,KAAQ,SAAS,QAAA,GAAM,oBAAA;AACzD,EAAA,MAAM,OAAO,GAAA,KAAQ,MAAA,GAAS,MAAA,GAAa,GAAA,KAAQ,UAAW,UAAA,KAAe,IAAA,CAAA;AAC7E,EAAA,MAAM,IAAA,GAAO,IAAA,KAAS,MAAA,GAAY,MAAA,GAAY,OAAO,eAAA,GAAkB,eAAA;AACvE,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,KAAA,EAAO,MAAM,CAAA;AACtC,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,KAAA;AAAA,oBACD,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,YAAA;AAAA,QACV,SAAA,EAAW,IAAA;AAAA,QACX,KAAA,EAAO,OAAO,MAAA,GAAY,KAAA;AAAA,QAC1B,YAAA,EAAY,CAAA,EAAG,IAAI,CAAA,MAAA,EAAI,IAAI,CAAA,EAAG,IAAA,KAAS,MAAA,GAAY,EAAA,GAAK,IAAA,GAAO,oBAAA,GAAQ,oBAAK,CAAA,CAAA;AAAA,QAE3E,QAAA,EAAA;AAAA,UAAA,IAAA;AAAA,UAAK,GAAA;AAAA,UAAE;AAAA;AAAA;AAAA;AACV,GAAA,EACF,CAAA;AAEJ","file":"chunk-6OTTGAPO.js","sourcesContent":["\"use client\"\n\n/**\n * delta-text — a change as a bare inline `span`: mark + signed value (\"▲ +3.2%\"), so print and\n * colour-blind readers get the direction; colour only adds good / bad. It sets no text size, so it\n * takes the size of the line it sits in (doc blocks, slide text).\n *\n * - The direction comes from the sign of `value`; `betterWhen` (\"up\" by default; `\"down\"` for churn,\n * cost) decides good / bad. Zero is \"→\" in the muted colour; `null` is \"—\".\n * - `value` is the change itself, formatted by `format` with an explicit sign.\n * - `comparisonLabel` (\"前月比\") is printed in front, muted.\n *\n * @example\n * import { DeltaText } from \"@/blocks/delta-text/delta-text\"\n * <DeltaText value={0.032} format=\"percent\" comparisonLabel=\"前月比\" />\n */\nimport { formatDelta, type ValueFormat } from \"../../lib/format\"\n\nexport interface DeltaTextProps {\n /** The change itself; its direction comes from the sign. `null` shows \"—\". */\n value: number | null\n format?: ValueFormat\n /** Which way is good. Default `\"up\"`. */\n betterWhen?: \"up\" | \"down\"\n /** Name of the comparison, e.g. \"前月比\". Printed before the change; omit to print only the change. */\n comparisonLabel?: string\n}\n\nconst MUTED = { color: \"var(--doc-muted)\" } as const\n\nexport function DeltaText({ value, format, betterWhen = \"up\", comparisonLabel }: DeltaTextProps) {\n const label = comparisonLabel ? <span style={MUTED}>{comparisonLabel} </span> : null\n if (value === null) {\n return (\n <>\n {label}\n <span data-slot=\"delta-text\" style={MUTED}>\n —\n </span>\n </>\n )\n }\n const dir = value > 0 ? \"up\" : value < 0 ? \"down\" : \"flat\"\n const mark = dir === \"up\" ? \"▲\" : dir === \"down\" ? \"▼\" : \"→\"\n const word = dir === \"up\" ? \"増\" : dir === \"down\" ? \"減\" : \"横ばい\"\n const good = dir === \"flat\" ? undefined : (dir === \"up\") === (betterWhen === \"up\")\n const tone = good === undefined ? undefined : good ? \"text-positive\" : \"text-negative\"\n const text = formatDelta(value, format)\n return (\n <>\n {label}\n <span\n data-slot=\"delta-text\"\n className={tone}\n style={tone ? undefined : MUTED}\n aria-label={`${word}、${text}${good === undefined ? \"\" : good ? \"、改善\" : \"、悪化\"}`}\n >\n {mark} {text}\n </span>\n </>\n )\n}\n\nexport default DeltaText\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../squadkit/registry/lib/chart-theme.ts","../../squadkit/registry/charts/echart.tsx"],"names":["useState","useEffect","EChart","useRef","useCallback"],"mappings":"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","file":"chunk-JXFCSF3K.js","sourcesContent":["/**\n * Chart theming — reads the design tokens off the document and turns them into\n * an ECharts theme object.\n *\n * Canvas can't resolve CSS variables *while painting*, which is why series\n * colours can't just be `var(--chart-1)`. It can resolve them once, up front:\n * `getComputedStyle` returns the substituted value, and that value is handed to\n * `echarts.init` as a theme. Every colour is normalized to `rgb()`/`#rrggbb`\n * first — zrender's own colour parser only understands hex/`rgb()`/`hsl()`.\n * Canvas still paints an `oklch()` series, but every colour zrender derives from\n * it comes out empty: the hover emphasis lifts the fill, can't parse it, and the\n * hovered bar disappears. A `fillStyle` round-trip is not enough on its own —\n * current Chrome serializes `oklch()` back as `oklch()` — so a colour that comes\n * back in any other form is painted onto the canvas and read back as a pixel.\n */\nimport { createContext, useCallback, useEffect, useRef, useState, type ForwardedRef, type RefObject } from \"react\"\n\nimport type { ChartTone } from \"./types\"\n\n/**\n * The colour of the folded「その他」series / slice / row. The ONLY place this\n * grey is defined — every chart takes it from here. It is the most subdued\n * colour in a chart, not the darkest: the theme's `--neutral` mixed halfway into\n * `--background`, so it recedes in light and dark alike (and brand themes follow\n * it). `--neutral-subtle` alone sits too close to the background to read as a\n * slice. Canvas charts resolve it through `resolveChartColors`.\n */\nexport const CHART_OTHER_COLOR = \"color-mix(in oklab, var(--neutral) 50%, var(--background))\"\n\n/**\n * True inside `ChartFrame`. The frame's plot area carries the chart's single\n * `role=\"img\"` and label, so `EChart` drops its own when it sees this.\n */\nexport const ChartFrameContext = createContext(false)\n\n/** Series palette, in order. Missing tokens are skipped, not defaulted. */\nconst SERIES_TOKENS = [\"--chart-1\", \"--chart-2\", \"--chart-3\", \"--chart-4\", \"--chart-5\"] as const\n\nexport interface ChartTokens {\n /** Resolved `--chart-1..5`, in order. */\n series: string[]\n /** Computed `font-family` of the container, so canvas text matches the DOM. Optional. */\n fontFamily?: string\n /** Body text: titles and the default `textStyle`. */\n foreground: string | null\n /** Secondary text: axis labels, legend, subtitles. */\n mutedForeground: string | null\n /** Axis lines, ticks, split lines, tooltip border. */\n border: string | null\n /** Tooltip surface. */\n popover: string | null\n /** Semantic and surface dependencies used by typed chart options. Optional for hand-built tokens. */\n colors?: Record<string, string>\n /** Actual inherited painting surface (may change without a token changing). */\n surface?: string | null\n /** Tooltip text. */\n popoverForeground: string | null\n}\n\n// Keep scope out of the public token shape. A resolved snapshot remembers where arbitrary\n// var(--token) expressions must be read, without retaining unmounted charts globally.\nconst tokenScopes = new WeakMap<ChartTokens, Element>()\nconst OPTION_COLOR_TOKENS = [\n \"--background\", \"--card\", \"--muted\", \"--primary\", \"--destructive\",\n ...[\"positive\", \"negative\", \"warning\", \"neutral\", \"info\"].flatMap((tone) =>\n [\"\", \"-fill\", \"-subtle\"].map((suffix) => `--${tone}${suffix}`)),\n]\n\nlet normalizeContext: CanvasRenderingContext2D | null | undefined\n\n/** The forms `fillStyle` serializes legacy colours to, and zrender can parse. */\nconst ZRENDER_COLOR_RE = /^(?:#[0-9a-f]{6}|rgba?\\()/i\n\n/**\n * Serialize a CSS colour into a canvas-safe form, or `null` if the browser\n * rejects it. Assigning an invalid value to `fillStyle` is a no-op, so the same\n * input is written over two different known colours: agreeing results mean the\n * value parsed, differing ones mean it was dropped.\n */\nfunction toCanvasColor(value: string): string | null {\n const raw = value.trim()\n if (!raw) return null\n if (normalizeContext === undefined) {\n const canvas = document.createElement(\"canvas\")\n canvas.width = 1\n canvas.height = 1\n normalizeContext = canvas.getContext(\"2d\", { willReadFrequently: true })\n }\n const ctx = normalizeContext\n if (!ctx) return raw\n ctx.fillStyle = \"#000000\"\n ctx.fillStyle = raw\n const onBlack = ctx.fillStyle\n ctx.fillStyle = \"#ffffff\"\n ctx.fillStyle = raw\n if (onBlack !== ctx.fillStyle || typeof onBlack !== \"string\") return null\n if (ZRENDER_COLOR_RE.test(onBlack)) return onBlack\n // Still `oklch()` / `lab()` / `color(...)`: paint it and read the pixel back.\n // Wide-gamut colours clip to sRGB, which is all zrender can express anyway.\n ctx.clearRect(0, 0, 1, 1)\n ctx.fillRect(0, 0, 1, 1)\n const [r = 0, g = 0, b = 0, a = 0] = ctx.getImageData(0, 0, 1, 1).data\n return a === 255\n ? `rgb(${r}, ${g}, ${b})`\n : `rgba(${r}, ${g}, ${b}, ${Math.round((a / 255) * 1000) / 1000})`\n}\n\n/**\n * Read the chart tokens off `el` (the document root by default — tokens live on\n * `:root` and inherit). Returns `null` outside the browser so callers fall back\n * to plain ECharts defaults.\n */\nexport function readChartTokens(el?: Element | null): ChartTokens | null {\n if (typeof document === \"undefined\") return null\n const target = el ?? document.documentElement\n if (!target) return null\n const styles = getComputedStyle(target)\n const read = (name: string) => toCanvasColor(styles.getPropertyValue(name))\n const series: string[] = []\n for (const token of SERIES_TOKENS) {\n const color = read(token)\n if (color) series.push(color)\n }\n const tokens: ChartTokens = {\n series,\n colors: Object.fromEntries(OPTION_COLOR_TOKENS.map((name) => [name, styles.getPropertyValue(name).trim()])),\n surface: readChartSurface(target),\n ...(styles.fontFamily ? { fontFamily: styles.fontFamily } : {}),\n foreground: read(\"--foreground\"),\n mutedForeground: read(\"--muted-foreground\"),\n border: read(\"--border\"),\n popover: read(\"--popover\"),\n popoverForeground: read(\"--popover-foreground\"),\n }\n tokenScopes.set(tokens, target)\n return tokens\n}\n\n/** Structural equality, so a theme toggle that changes nothing doesn't re-init. */\nexport function sameChartTokens(a: ChartTokens | null, b: ChartTokens | null): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return (\n tokenScopes.get(a) === tokenScopes.get(b) &&\n a.surface === b.surface &&\n Object.keys(a.colors ?? {}).length === Object.keys(b.colors ?? {}).length &&\n Object.entries(a.colors ?? {}).every(([name, value]) => b.colors?.[name] === value) &&\n a.series.length === b.series.length &&\n a.series.every((color, i) => color === b.series[i]) &&\n a.fontFamily === b.fontFamily &&\n a.foreground === b.foreground &&\n a.mutedForeground === b.mutedForeground &&\n a.border === b.border &&\n a.popover === b.popover &&\n a.popoverForeground === b.popoverForeground\n )\n}\n\n/**\n * Watch everything that can change the resolved tokens and call `onChange` when\n * something might have. It only ever says \"re-read\" — the caller compares with\n * `sameChartTokens` and decides whether anything actually moved. Returns a\n * disposer.\n *\n * Two sources, not one:\n * - light/dark flips, which land as `class` / `data-theme` (or an inline\n * `style`) on `<html>`/`<body>`, or as an OS preference change\n * - stylesheet changes. In dev, editing `styles.css` rewrites the injected\n * `<style>` in `<head>` and touches nothing else, so watching the theme\n * attributes alone leaves the chart painted in the previous palette until a\n * reload — the tokens in the DOM are new, the canvas is not.\n */\nexport function watchChartTokens(onChange: () => void, scope?: Element | null): () => void {\n if (typeof document === \"undefined\") return () => {}\n // Style edits arrive as bursts of mutations; coalesce them into one read, and\n // take it after the next frame so a swapped stylesheet has been applied.\n let frame = 0\n const schedule = () => {\n if (frame) return\n frame = requestAnimationFrame(() => {\n frame = 0\n onChange()\n })\n }\n\n const themeObserver = new MutationObserver(schedule)\n const attributeFilter = [\"class\", \"style\", \"data-theme\"]\n // Only the chart and its ancestors can change its inherited theme. Never observe\n // the document subtree: canvas/tooltip/rendering mutations would trigger every chart.\n for (let node: Element | null = scope ?? document.body ?? document.documentElement; node; node = node.parentElement) {\n themeObserver.observe(node, { attributes: true, attributeFilter })\n }\n\n const styleObserver = new MutationObserver(schedule)\n if (document.head) {\n styleObserver.observe(document.head, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"href\", \"media\", \"disabled\"],\n })\n }\n\n // A swapped `<link>` only applies once the sheet has loaded, after its mutation.\n const onLoad = (event: Event) => {\n if (event.target instanceof HTMLLinkElement) schedule()\n }\n document.addEventListener(\"load\", onLoad, true)\n\n const media = window.matchMedia(\"(prefers-color-scheme: dark)\")\n media.addEventListener(\"change\", schedule)\n\n return () => {\n if (frame) cancelAnimationFrame(frame)\n themeObserver.disconnect()\n styleObserver.disconnect()\n document.removeEventListener(\"load\", onLoad, true)\n media.removeEventListener(\"change\", schedule)\n }\n}\n\n/** Shared shape for the four axis types ECharts themes address separately. */\nfunction axisTheme(tokens: ChartTokens, splitLine: boolean) {\n const line = tokens.border ?? undefined\n return {\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: { show: true, color: tokens.mutedForeground ?? undefined, fontSize: 12 },\n // Faint horizontal rules only: the border colour at low opacity.\n splitLine: { show: splitLine, lineStyle: { color: line ? [line] : undefined, opacity: 0.5, width: 1 } },\n splitArea: { show: false },\n }\n}\n\n/**\n * Build the ECharts theme. `option.color` still wins over `theme.color`, so an\n * app that sets its own palette keeps it.\n */\nexport function buildChartTheme(tokens: ChartTokens): Record<string, unknown> {\n const text = tokens.foreground ?? undefined\n const muted = tokens.mutedForeground ?? undefined\n const line = tokens.border ?? undefined\n return {\n // Let the page background show through: charts sit on cards, not on a canvas.\n backgroundColor: \"transparent\",\n ...(tokens.series.length > 0 ? { color: tokens.series } : {}),\n textStyle: { color: text, ...(tokens.fontFamily ? { fontFamily: tokens.fontFamily } : {}) },\n title: { textStyle: { color: text }, subtextStyle: { color: muted } },\n legend: { textStyle: { color: muted } },\n categoryAxis: axisTheme(tokens, false),\n valueAxis: axisTheme(tokens, true),\n logAxis: axisTheme(tokens, true),\n timeAxis: axisTheme(tokens, true),\n tooltip: {\n // ECharts' default 0.4s transform lags the tooltip ~300ms behind the cursor.\n transitionDuration: 0,\n backgroundColor: tokens.popover ?? undefined,\n borderColor: line,\n borderWidth: 1,\n padding: [8, 12],\n // Rounded card with a soft shadow; in dark mode the shadow barely shows, so the border carries the edge.\n extraCssText: \"border-radius:8px;box-shadow:var(--shadow-card, 0 4px 12px rgb(0 0 0 / 0.08));\",\n textStyle: {\n color: tokens.popoverForeground ?? undefined,\n fontSize: 12,\n ...(tokens.fontFamily ? { fontFamily: tokens.fontFamily } : {}),\n },\n axisPointer: { lineStyle: { color: line }, crossStyle: { color: line } },\n },\n }\n}\n\n/**\n * The resolved tokens, kept current: re-read whenever `watchChartTokens` says\n * they may have moved, and only replaced when a value actually changed. For\n * components that build an ECharts option from token colours themselves (the\n * typed charts), so their palette follows light/dark like `EChart`'s theme.\n */\nexport function useChartTokens(scope?: Element | null | RefObject<Element | null>): ChartTokens | null {\n const [tokens, setTokens] = useState<ChartTokens | null>(() => readChartTokens())\n // Compared here, not inside a `setTokens` updater: an updater that reads the DOM is\n // replayed by React on every rebase and returns a fresh object each time, so the state\n // never settles (\"Maximum update depth exceeded\" once the tokens change after mount).\n const tokensRef = useRef(tokens)\n useEffect(() => {\n const target = scope && \"current\" in scope ? scope.current : scope\n const sync = () => {\n const next = readChartTokens(target)\n if (sameChartTokens(tokensRef.current, next)) return\n tokensRef.current = next\n setTokens(next)\n }\n sync()\n return watchChartTokens(sync, target)\n }, [scope])\n return tokens\n}\n\nconst SERIES_TOKEN_NAME_RE = /^chart-([1-5])$/\nconst TONE_NAME_RE = /^(?:positive|warning|negative|neutral|info)(?:-fill)?$/\nconst CSS_VAR_RE = /^var\\(\\s*(--[\\w-]+)\\s*(?:,\\s*(.+))?\\)$/\nconst EMBEDDED_VAR_RE = /var\\(\\s*(--[\\w-]+)\\s*\\)/g\n\n/**\n * Turn chart colours into canvas-safe strings. `\"chart-1\"`〜`\"chart-5\"` come from\n * the resolved series tokens; `\"positive\"` / `\"warning\"` / `\"negative\"` / `\"neutral\"` (and the area\n * variants `\"positive-fill\"`, …) are read in the snapshot's inherited scope (`--positive`, …); `var(--token)` uses the same scope; any\n * other CSS colour is normalized like the tokens are. A colour that can't be\n * resolved comes back as `\"\"`, which ECharts treats as \"use the palette\".\n */\nexport function resolveChartColors(colors: readonly string[], tokens: ChartTokens | null): string[] {\n return colors.map((color) => {\n const token = SERIES_TOKEN_NAME_RE.exec(color.trim())\n if (token) return tokens?.series[Number(token[1]) - 1] ?? \"\"\n // Meaning colours are the theme tokens of the same name: same path as `var(--positive)`.\n if (TONE_NAME_RE.test(color.trim())) {\n if (typeof document === \"undefined\") return \"\"\n const target = (tokens && tokenScopes.get(tokens)) ?? document.documentElement\n return toCanvasColor(getComputedStyle(target).getPropertyValue(`--${color.trim()}`)) ?? \"\"\n }\n if (typeof document === \"undefined\") return color\n let value = color.trim()\n const cssVar = CSS_VAR_RE.exec(value)\n const styles = getComputedStyle((tokens && tokenScopes.get(tokens)) ?? document.documentElement)\n if (cssVar) {\n value = styles.getPropertyValue(cssVar[1]!).trim() || (cssVar[2] ?? \"\").trim()\n } else if (value.includes(\"var(\")) {\n // A colour function over tokens (`color-mix(… var(--muted-foreground) …)`):\n // substitute the tokens, then let the canvas resolve the rest.\n value = value.replace(EMBEDDED_VAR_RE, (_, name: string) => styles.getPropertyValue(name).trim())\n }\n return toCanvasColor(value) ?? \"\"\n })\n}\n\n/** Every meaning colour resolved for the canvas (`\"\"` when it can't be resolved). */\nexport function resolveToneColors(tokens: ChartTokens | null): Record<ChartTone, string> {\n const [positive = \"\", warning = \"\", negative = \"\", neutral = \"\"] = resolveChartColors(\n [\"positive\", \"warning\", \"negative\", \"neutral\"],\n tokens,\n )\n return { positive, warning, negative, neutral }\n}\n\n/** The area (`--<tone>-fill`) colours of every meaning tone, resolved for the canvas (`\"\"` when it can't be resolved). */\nexport function resolveFillColors(tokens: ChartTokens | null): Record<ChartTone, string> {\n const [positive = \"\", warning = \"\", negative = \"\", neutral = \"\"] = resolveChartColors(\n [\"positive-fill\", \"warning-fill\", \"negative-fill\", \"neutral-fill\"],\n tokens,\n )\n return { positive, warning, negative, neutral }\n}\n\nconst TRANSPARENT_RE = /^(?:transparent|rgba\\([^)]*,\\s*0(?:\\.0+)?\\))$/i\n\n/**\n * The colour the chart is painted on: the first opaque `background-color` up\n * from `el` (a card, the page), else `--background`. Canvas-safe, or `null`\n * outside the browser.\n */\nexport function readChartSurface(el: Element | null): string | null {\n if (typeof document === \"undefined\") return null\n for (let node: Element | null = el; node; node = node.parentElement) {\n const bg = getComputedStyle(node).backgroundColor.trim()\n if (bg && !TRANSPARENT_RE.test(bg)) {\n const color = toCanvasColor(bg)\n if (color) return color\n }\n }\n return toCanvasColor(getComputedStyle(el ?? document.documentElement).getPropertyValue(\"--background\"))\n}\n\n/** Widths are bucketed so a resize only rebuilds the option when the label budget can change. */\nconst WIDTH_BUCKET = 40\n\n/**\n * The surface colour behind a chart (see `readChartSurface`), re-read when the\n * tokens move (light/dark), and the plot's width (rounded down to 40px;\n * `undefined` until measured). Returns a ref for the plot that also feeds the\n * component's forwarded ref.\n */\nexport function useChartSurface<E extends Element>(\n forwarded: ForwardedRef<E>,\n tokens?: ChartTokens | null,\n): { ref: (el: E | null) => void; surface: string | undefined; width: number | undefined; tokens: ChartTokens | null } {\n const [node, setNode] = useState<E | null>(null)\n const scopedTokens = useChartTokens(node)\n const [surface, setSurface] = useState<string | undefined>(undefined)\n const [width, setWidth] = useState<number | undefined>(undefined)\n const ref = useCallback(\n (el: E | null) => {\n setNode(el)\n if (typeof forwarded === \"function\") forwarded(el)\n else if (forwarded) forwarded.current = el\n },\n [forwarded],\n )\n useEffect(() => {\n if (!node) return\n setSurface(readChartSurface(node) ?? undefined)\n }, [node, tokens, scopedTokens])\n useEffect(() => {\n if (!node || typeof ResizeObserver === \"undefined\") return\n const update = (w: number) => setWidth(Math.floor(w / WIDTH_BUCKET) * WIDTH_BUCKET)\n update(node.getBoundingClientRect().width)\n const observer = new ResizeObserver((entries) => update(entries[0]?.contentRect.width ?? 0))\n observer.observe(node)\n return () => observer.disconnect()\n }, [node])\n return { ref, surface, width, tokens: scopedTokens }\n}\n","\"use client\"\n\n/**\n * EChart — a thin Apache ECharts wrapper. It owns the canvas lifecycle (init,\n * resize, dispose), forwards `option` and event handlers, drives the loading\n * spinner, and can copy/download the chart as a PNG.\n *\n * Colours follow the design tokens: `--chart-1..5` become the series palette,\n * and the text/border/popover tokens style axes, legend and tooltip. They're\n * resolved once at init (see `chart-theme.ts`) and re-read whenever they can\n * have changed — a light/dark flip, or a stylesheet swap such as editing\n * `styles.css` while the dev server is running. `theme` opts out entirely;\n * `option.color` overrides just the palette and keeps the rest.\n *\n * Pitfall: the canvas can't read CSS. A colour written into the option as\n * `\"var(--chart-1)\"`, `\"chart-1\"` or `\"oklch(…)\"` paints black (or nothing).\n * Leave colours out and the tokens apply; when you must set one yourself, pass\n * it through `useResolvedChartColors` and use the result:\n *\n * @example\n * const [accent] = useResolvedChartColors([\"chart-2\"])\n * const option = { series: [{ type: \"line\", data, lineStyle: { color: accent } }] }\n * return <EChart option={option} />\n *\n * Updates merge instead of replacing (`replaceMerge` on every component type in\n * play), so series with a stable `id` transition to their new values while\n * anything dropped from the option is still removed. With\n * `prefers-reduced-motion: reduce` every animation is off.\n *\n * ECharts is loaded modularly (`echarts/core`): only the bar / line / pie series (and `custom`, which draws\n * the per-bar target marker),\n * the components the typed charts emit and the canvas renderer are registered\n * below. To draw anything else with `<EChart>` (scatter, funnel, dataZoom, …),\n * register it once in your own code:\n *\n * @example\n * import { use } from \"echarts/core\"\n * import { ScatterChart } from \"echarts/charts\"\n * use([ScatterChart])\n */\nimport { forwardRef, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\"\nimport { init, use } from \"echarts/core\"\nimport { BarChart, CustomChart, LineChart, PieChart } from \"echarts/charts\"\nimport {\n GridComponent,\n LegendComponent,\n MarkAreaComponent,\n MarkLineComponent,\n MarkPointComponent,\n TooltipComponent,\n} from \"echarts/components\"\nimport { CanvasRenderer } from \"echarts/renderers\"\nimport type { ECharts, EChartsOption } from \"echarts\"\nimport { Check, Copy, Download } from \"lucide-react\"\n\nimport { cn } from \"../lib/utils\"\nimport { Button } from \"../ui/button\"\nimport type { ChartActionsOptions } from \"../lib/types\"\nimport {\n buildChartTheme,\n ChartFrameContext,\n resolveChartColors,\n useChartTokens,\n} from \"../lib/chart-theme\"\n\n// What the typed charts (Bar / Line / Area / Donut) emit. Other series and\n// components are the consumer's to `use()` — see the note at the top.\nuse([\n BarChart,\n CustomChart,\n LineChart,\n PieChart,\n GridComponent,\n LegendComponent,\n MarkAreaComponent,\n MarkLineComponent,\n MarkPointComponent,\n TooltipComponent,\n CanvasRenderer,\n])\n\nexport interface EChartProps {\n /**\n * ECharts のオプション。\n *\n * 型推論を効かせるため、必ず `EChartsOption` を annotation するか\n * `satisfies EChartsOption` を付けること。付けないと `type: \"category\"` などの\n * literal が `string` に拡張され、ビルドが失敗する。\n *\n * @example\n * import type { EChartsOption } from \"@/components/echart\"\n *\n * const option: EChartsOption = {\n * xAxis: { type: \"category\", data: [\"A\", \"B\"] },\n * yAxis: { type: \"value\" },\n * series: [{ type: \"bar\", data: [1, 2] }],\n * }\n * <EChart option={option} />\n */\n option: EChartsOption\n /**\n * チャートの高さ。数値は px、文字列は CSS 値(例: `\"50vh\"`)として扱う。\n *\n * 省略した場合は外側ラッパーに `h-[400px]` がデフォルトで当たるが、`className` に\n * `h-full` や `h-[360px]` などの高さクラスを渡せばそちらが優先される\n * (`h-full` を使う場合は親要素に確定した高さが必要)。\n * `height` と `className` の高さを両方指定した場合は `height`(インライン style)が勝つ。\n */\n height?: string | number\n loading?: boolean\n /**\n * `echarts.init` にそのまま渡すテーマ(名前または登録済みテーマオブジェクト)。\n *\n * 渡すとデザイントークン追従は**完全に無効**になり、明暗の切り替えにも追従しなく\n * なる。系列色だけ変えたいなら `option.color` を使う ― option はテーマより優先\n * されるので、軸・凡例・ツールチップのトークン追従は残る。\n */\n theme?: string | object\n onEvents?: Record<string, (params: unknown) => void>\n ariaLabel?: string\n className?: string\n /**\n * true にするとチャート右上に PNG コピー / ダウンロードボタンを表示する。\n * `exportHeader` があれば PNG の上にその見出しを含める(`{ includeTitle: false }` で含めない)。\n */\n actions?: boolean | ChartActionsOptions\n /** ダウンロード時のファイル名(拡張子含む)。省略時は \"chart.png\" */\n fileName?: string\n /**\n * PNG の上に含める見出しと要約。型付きグラフは自分の `title` / `summary` を渡す。\n * 自分で `ChartFrame` を組むときも同じものを渡すと、保存した画像だけで何のグラフか分かる。\n */\n exportHeader?: ChartExportHeader\n}\n\n/** The heading a saved PNG carries above the plot. */\nexport interface ChartExportHeader {\n title?: string\n summary?: string\n}\n\nconst HEADER_PAD_X = 16\nconst HEADER_PAD_TOP = 16\nconst HEADER_PAD_BOTTOM = 12\nconst HEADER_LINE_HEIGHT = 20\nconst HEADER_GAP = 4\nconst HEADER_FONT_SIZE = 14\n\nexport interface ChartExportHeaderLine {\n text: string\n kind: \"title\" | \"summary\"\n}\n\n/**\n * Break `text` into lines no wider than `maxWidth` (px, via `measure`), character\n * by character so Japanese wraps without spaces. Always at least one line for\n * non-empty text; a single over-wide character still gets its own line.\n */\nexport function wrapChartText(text: string, maxWidth: number, measure: (text: string) => number): string[] {\n const lines: string[] = []\n let line = \"\"\n for (const ch of text) {\n if (ch === \"\\n\") {\n lines.push(line)\n line = \"\"\n continue\n }\n if (line !== \"\" && measure(line + ch) > maxWidth) {\n lines.push(line)\n line = ch.trim() === \"\" ? \"\" : ch\n } else {\n line += ch\n }\n }\n if (line !== \"\" || lines.length === 0) lines.push(line)\n return lines.filter((l, i) => l !== \"\" || i < lines.length - 1)\n}\n\n/**\n * The lines and total height (CSS px) of the PNG's heading band for a plot\n * `width` px wide. `measure` takes (text, kind) and returns its width in px.\n * No title and no summary → no band (`height` 0).\n */\nexport function chartExportHeaderLayout(\n header: ChartExportHeader | undefined,\n width: number,\n measure: (text: string, kind: \"title\" | \"summary\") => number,\n): { lines: ChartExportHeaderLine[]; height: number } {\n const title = header?.title?.trim()\n const summary = header?.summary?.trim()\n if (!title && !summary) return { lines: [], height: 0 }\n const room = Math.max(40, width - HEADER_PAD_X * 2)\n const lines: ChartExportHeaderLine[] = [\n ...(title ? wrapChartText(title, room, (t) => measure(t, \"title\")).map((text) => ({ text, kind: \"title\" as const })) : []),\n ...(summary ? wrapChartText(summary, room, (t) => measure(t, \"summary\")).map((text) => ({ text, kind: \"summary\" as const })) : []),\n ]\n const gap = title && summary ? HEADER_GAP : 0\n return { lines, height: HEADER_PAD_TOP + lines.length * HEADER_LINE_HEIGHT + gap + HEADER_PAD_BOTTOM }\n}\n\nfunction loadImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const image = new Image()\n image.onload = () => resolve(image)\n image.onerror = () => reject(new Error(\"PNG の読み込みに失敗しました\"))\n image.src = src\n })\n}\n\n/** Draw a heading band (title in foreground, summary muted) above the exported plot and return the new PNG. */\nasync function pngWithHeader(\n dataUrl: string,\n header: ChartExportHeader,\n look: { background: string; color: string; mutedColor: string; fontFamily: string },\n pixelRatio: number,\n): Promise<string> {\n const image = await loadImage(dataUrl)\n const width = image.width / pixelRatio\n const plotHeight = image.height / pixelRatio\n const canvas = document.createElement(\"canvas\")\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return dataUrl\n const font = (kind: \"title\" | \"summary\") => `${kind === \"title\" ? 500 : 400} ${HEADER_FONT_SIZE}px ${look.fontFamily}`\n ctx.font = font(\"title\")\n const layout = chartExportHeaderLayout(header, width, (text, kind) => {\n ctx.font = font(kind)\n return ctx.measureText(text).width\n })\n if (layout.height === 0) return dataUrl\n canvas.width = Math.round(image.width)\n canvas.height = Math.round((layout.height + plotHeight) * pixelRatio)\n ctx.scale(pixelRatio, pixelRatio)\n ctx.fillStyle = look.background\n ctx.fillRect(0, 0, width, layout.height + plotHeight)\n ctx.textBaseline = \"middle\"\n let y = HEADER_PAD_TOP\n let previous: \"title\" | \"summary\" | null = null\n for (const line of layout.lines) {\n if (previous === \"title\" && line.kind === \"summary\") y += HEADER_GAP\n ctx.font = font(line.kind)\n ctx.fillStyle = line.kind === \"title\" ? look.color : look.mutedColor\n ctx.fillText(line.text, HEADER_PAD_X, y + HEADER_LINE_HEIGHT / 2)\n y += HEADER_LINE_HEIGHT\n previous = line.kind\n }\n ctx.drawImage(image, 0, layout.height, width, plotHeight)\n return canvas.toDataURL(\"image/png\")\n}\n\n/**\n * Canvas-safe versions of theme colours, kept current across light/dark.\n * Takes `\"chart-1\"`〜`\"chart-5\"`, `\"var(--token)\"` or any CSS colour; one that\n * can't be resolved comes back as `\"\"` (ECharts then uses the palette).\n * Use it whenever a colour goes into a raw `EChart` option by hand.\n *\n * @example\n * const [line, band] = useResolvedChartColors([\"chart-1\", \"var(--muted-foreground)\"])\n */\nexport function useResolvedChartColors(colors: readonly string[]): string[] {\n const tokens = useChartTokens()\n const key = colors.join(\"\\u0000\")\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `key` stands for the array's contents\n return useMemo(() => resolveChartColors(colors, tokens), [key, tokens])\n}\n\ntype EChartsEventHandler = (params: unknown) => void\n\n/**\n * ECharts component main types. Listed in `replaceMerge`, a type keeps only the\n * components whose `id` matches (merged, so they can transition) and drops the\n * rest — including every one of them when the new option no longer has the type.\n */\nconst COMPONENT_MAIN_TYPES = new Set([\n \"title\", \"legend\", \"grid\", \"xAxis\", \"yAxis\", \"polar\", \"radiusAxis\", \"angleAxis\", \"radar\",\n \"dataZoom\", \"visualMap\", \"tooltip\", \"axisPointer\", \"toolbox\", \"brush\", \"geo\", \"parallel\",\n \"parallelAxis\", \"singleAxis\", \"graphic\", \"calendar\", \"dataset\", \"series\", \"matrix\", \"thumbnail\",\n])\n\nexport interface EChartSetOptionOpts {\n notMerge: boolean\n replaceMerge?: string[]\n lazyUpdate: boolean\n}\n\n/**\n * How to apply `next` after `prev`: the first option and timeline / media\n * options replace everything; otherwise merge, replacing every component type\n * either option uses so nothing stale survives.\n */\nexport function echartSetOptionOpts(prev: EChartsOption | null, next: EChartsOption): EChartSetOptionOpts {\n const special = (o: EChartsOption) => \"timeline\" in o || \"baseOption\" in o || \"options\" in o || \"media\" in o\n if (!prev || special(prev) || special(next)) return { notMerge: true, lazyUpdate: true }\n const types = new Set<string>()\n for (const key of [...Object.keys(prev), ...Object.keys(next)]) if (COMPONENT_MAIN_TYPES.has(key)) types.add(key)\n return { notMerge: false, replaceMerge: [...types], lazyUpdate: true }\n}\n\n/**\n * Component types that get a generated `id` when the option has none, so replaceMerge can match them across updates.\n * Not `dataset` / `graphic` / `tooltip`: they are rebuilt on every update (there is nothing to transition).\n */\nconst ID_TYPES = [\n \"title\", \"legend\", \"grid\", \"xAxis\", \"yAxis\", \"polar\", \"radiusAxis\", \"angleAxis\", \"radar\",\n \"dataZoom\", \"visualMap\", \"geo\", \"singleAxis\", \"calendar\",\n] as const\n\n/**\n * What `withStableIds` remembers between updates: per generated id, the shape last applied and how many\n * times it changed (the id's `~v<n>` suffix); per component type, the order of its ids.\n */\nexport interface StableIdState {\n ids: Map<string, { shape: string; version: number }>\n order: Map<string, string[]>\n}\nexport const createStableIdState = (): StableIdState => ({ ids: new Map(), order: new Map() })\n\n/**\n * Shape of a component: which keys it has, recursively (arrays only as \"array\", values not at all —\n * except `type`). A merge keeps keys the new option dropped, so a changed shape must not be merged.\n */\nfunction shapeOf(v: unknown): string {\n if (Array.isArray(v)) return \"[]\"\n if (!v || typeof v !== \"object\" || Object.getPrototypeOf(v) !== Object.prototype) return \".\"\n const o = v as Record<string, unknown>\n return `{${Object.keys(o)\n .filter((k) => o[k] !== undefined)\n .sort()\n .map((k) => (k === \"type\" || k === \"id\" ? `${k}=${String(o[k])}` : `${k}:${shapeOf(o[k])}`))\n .join(\",\")}}`\n}\n\n/**\n * Gives every series (and the common components) an `id` it does not have yet —\n * series: `series:<name ?? index>`, others `<type>:<index>` — so an update that\n * only changes values is matched to the existing component and transitions\n * instead of being rebuilt. If the component's shape changed since `state` last\n * saw it (a key was removed or added, the type changed), the id gets a new\n * `~v<n>` suffix so replaceMerge builds it from scratch: the result then always\n * equals applying the option with `notMerge`. Explicit ids are kept; the input is not mutated.\n */\nexport function withStableIds(option: EChartsOption, state: StableIdState = createStableIdState()): EChartsOption {\n const out: Record<string, unknown> = { ...(option as Record<string, unknown>) }\n const taken = new Set<string>()\n const list = (v: unknown): Record<string, unknown>[] | null =>\n Array.isArray(v) ? (v as Record<string, unknown>[]) : v && typeof v === \"object\" ? [v as Record<string, unknown>] : null\n const give = (key: string, pick: (c: Record<string, unknown>, i: number) => string) => {\n const items = list(out[key])\n if (!items) return\n const used = new Set<string>(items.flatMap((c) => (c && c.id != null ? [String(c.id)] : [])))\n const bases = items.map((c, i) => {\n if (!c || typeof c !== \"object\" || c.id != null) return null\n let base = pick(c, i)\n for (let n = 2; used.has(base) || taken.has(`${key}\\u0000${base}`); n++) base = `${pick(c, i)}#${n}`\n used.add(base)\n taken.add(`${key}\\u0000${base}`)\n return base\n })\n // A merge fills the empty slots a removal left and keeps the slot order of what exists, so after any\n // change in which components there are (or their order) it would not match a fresh render: rebuild them all.\n const prevOrder = state.order.get(key) ?? []\n const cur = bases.filter((b): b is string => b !== null)\n const inOrder = cur.length === prevOrder.length && cur.every((b, i) => b === prevOrder[i])\n state.order.set(key, cur)\n out[key] = items.map((c, i) => {\n const base = bases[i]\n if (base == null) return c\n const shape = shapeOf(c)\n const prev = state.ids.get(base)\n const version = !prev ? 0 : prev.shape === shape && inOrder ? prev.version : prev.version + 1\n state.ids.set(base, { shape, version })\n return { ...c, id: version ? `${base}~v${version}` : base }\n })\n }\n give(\"series\", (c, i) => `series:${typeof c.name === \"string\" && c.name ? c.name : i}`)\n for (const key of ID_TYPES) give(key, (_c, i) => `${key}:${i}`)\n return out as EChartsOption\n}\n\n/** Copy of the plain objects / arrays of an option (functions, class instances, Dates stay shared), to compare against later in-place edits. */\nexport function snapshotOption<T>(v: T): T {\n if (Array.isArray(v)) return v.map(snapshotOption) as T\n if (v && typeof v === \"object\") {\n const proto = Object.getPrototypeOf(v)\n if (proto === Object.prototype || proto === null) {\n return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, snapshotOption(x)])) as T\n }\n }\n return v\n}\n\n/** Structural equality for option trees; functions and other non-plain objects compare by reference. */\nexport function optionEquals(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (typeof a !== \"object\" || typeof b !== \"object\" || !a || !b) return false\n if (Array.isArray(a) !== Array.isArray(b)) return false\n if (Array.isArray(a)) {\n const bb = b as unknown[]\n return a.length === bb.length && a.every((v, i) => optionEquals(v, bb[i]))\n }\n if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime()\n const pa = Object.getPrototypeOf(a)\n if ((pa !== Object.prototype && pa !== null) || Object.getPrototypeOf(b) !== pa) return false\n const ka = Object.keys(a)\n const kb = Object.keys(b)\n return ka.length === kb.length && ka.every((k) => Object.hasOwn(b, k) && optionEquals((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]))\n}\n\n/** `graphic` text doesn't inherit the global `textStyle`, so give it the inherited font unless it sets its own. */\nfunction withGraphicFont(option: EChartsOption, fontFamily: string | undefined): EChartsOption {\n const graphic = (option as { graphic?: unknown }).graphic\n if (!fontFamily || !Array.isArray(graphic)) return option\n return {\n ...option,\n graphic: graphic.map((g: { type?: string; style?: Record<string, unknown> }) =>\n g && g.type === \"text\" && g.style && !g.style.fontFamily ? { ...g, style: { ...g.style, fontFamily } } : g,\n ),\n } as EChartsOption\n}\n\n/** `option` as applied: reduced motion forces `animation: false`; otherwise animation stays explicit so it can flip back. */\nexport function withMotionPreference(option: EChartsOption, reducedMotion: boolean): EChartsOption {\n return { ...option, animation: reducedMotion ? false : (option.animation ?? true) }\n}\n\nconst REDUCED_MOTION_QUERY = \"(prefers-reduced-motion: reduce)\"\n\n/** `prefers-reduced-motion: reduce`, kept current. `false` on the server. */\nexport function usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(\n () => typeof window !== \"undefined\" && typeof window.matchMedia === \"function\" && window.matchMedia(REDUCED_MOTION_QUERY).matches,\n )\n useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return\n const media = window.matchMedia(REDUCED_MOTION_QUERY)\n const sync = () => setReduced(media.matches)\n sync()\n media.addEventListener(\"change\", sync)\n return () => media.removeEventListener(\"change\", sync)\n }, [])\n return reduced\n}\n\nexport const EChart = forwardRef<HTMLDivElement, EChartProps>(function EChart(\n {\n option,\n height,\n loading = false,\n theme,\n onEvents,\n ariaLabel,\n className,\n actions = false,\n fileName = \"chart.png\",\n exportHeader,\n },\n ref,\n) {\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [instance, setInstance] = useState<ECharts | null>(null)\n const [copied, setCopied] = useState(false)\n const tokens = useChartTokens(containerRef)\n const reducedMotion = usePrefersReducedMotion()\n // What the current instance last received, to pick the merge mode of the next update.\n const appliedRef = useRef<EChartsOption | null>(null)\n // The option (before ids) as it was when applied, deep-copied; and the shape history behind the generated ids.\n const snapshotRef = useRef<EChartsOption | null>(null)\n const idStateRef = useRef<StableIdState>(createStableIdState())\n\n const autoTheme = useMemo(() => (tokens ? buildChartTheme(tokens) : undefined), [tokens])\n const resolvedTheme = theme ?? autoTheme\n\n // init / re-init: ECharts はテーマの差し替えに対応しないので、テーマが変わったら\n // インスタンスを破棄して作り直す(トークンが実際に変わったときだけここに来る)\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n const inst = init(container, resolvedTheme, { renderer: \"canvas\" })\n appliedRef.current = null\n snapshotRef.current = null\n // `data-rendering` stays on until the (animated) paint is done, so anything\n // capturing the page — printing a document — can wait for real pixels.\n container.dataset.rendering = \"\"\n inst.on(\"finished\", () => {\n delete container.dataset.rendering\n })\n setInstance(inst)\n\n // At most one resize per frame (the sidebar animates the width).\n let frame = 0\n const observer = new ResizeObserver(() => {\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(() => {\n if (!inst.isDisposed()) inst.resize()\n })\n })\n observer.observe(container)\n\n return () => {\n observer.disconnect()\n cancelAnimationFrame(frame)\n inst.dispose()\n }\n }, [resolvedTheme])\n\n useEffect(() => {\n if (!instance || instance.isDisposed()) return\n const prepared = withGraphicFont(\n withMotionPreference(option, reducedMotion),\n theme === undefined ? tokens?.fontFamily : undefined,\n )\n // Same content as last time (a re-render that built an equal option): nothing to redraw.\n // Compared with a snapshot, so an in-place edit of a nested array of the caller's option still counts as a change.\n if (snapshotRef.current && optionEquals(snapshotRef.current, prepared)) return\n if (containerRef.current) containerRef.current.dataset.rendering = \"\"\n const next = withStableIds(prepared, idStateRef.current)\n instance.setOption(next, echartSetOptionOpts(appliedRef.current, next))\n appliedRef.current = next\n snapshotRef.current = snapshotOption(prepared)\n }, [instance, option, reducedMotion, theme, tokens?.fontFamily])\n\n useEffect(() => {\n if (!instance || instance.isDisposed()) return\n if (loading) instance.showLoading()\n else instance.hideLoading()\n }, [instance, loading])\n\n useEffect(() => {\n if (!instance || instance.isDisposed() || !onEvents) return\n const entries = Object.entries(onEvents)\n for (const [event, handler] of entries) {\n instance.on(event, handler as EChartsEventHandler)\n }\n return () => {\n if (instance.isDisposed()) return\n for (const [event, handler] of entries) {\n instance.off(event, handler as EChartsEventHandler)\n }\n }\n }, [instance, onEvents])\n\n const includeTitle = typeof actions === \"object\" ? (actions.includeTitle ?? true) : true\n const getPngDataUrl = useCallback(async (): Promise<string | null> => {\n if (!instance) return null\n // Export over the nearest opaque background (card, then page) so the PNG\n // matches what is on screen in dark too. Computed styles resolve to rgb(a),\n // so this stays canvas-safe whatever the token.\n let backgroundColor = \"#ffffff\"\n for (let el: HTMLElement | null = containerRef.current; el; el = el.parentElement) {\n const bg = getComputedStyle(el).backgroundColor\n if (bg && bg !== \"rgba(0, 0, 0, 0)\" && bg !== \"transparent\") {\n backgroundColor = bg\n break\n }\n }\n const pixelRatio = 2\n const dataUrl = instance.getDataURL({ type: \"png\", pixelRatio, backgroundColor })\n if (!includeTitle || !exportHeader || !(exportHeader.title || exportHeader.summary) || !containerRef.current) return dataUrl\n try {\n const style = getComputedStyle(containerRef.current)\n return await pngWithHeader(\n dataUrl,\n exportHeader,\n { background: backgroundColor, color: style.color, mutedColor: tokens?.mutedForeground ?? style.color, fontFamily: style.fontFamily },\n pixelRatio,\n )\n } catch {\n return dataUrl\n }\n }, [instance, includeTitle, exportHeader, tokens])\n\n const handleCopy = useCallback(async () => {\n const dataUrl = await getPngDataUrl()\n if (!dataUrl) return\n try {\n const blob = await (await fetch(dataUrl)).blob()\n await navigator.clipboard.write([new ClipboardItem({ \"image/png\": blob })])\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch {\n // ClipboardItem 未対応ブラウザでは silent fail\n }\n }, [getPngDataUrl])\n\n const handleDownload = useCallback(async () => {\n const dataUrl = await getPngDataUrl()\n if (!dataUrl) return\n const link = document.createElement(\"a\")\n link.href = dataUrl\n link.download = fileName\n link.click()\n }, [getPngDataUrl, fileName])\n\n // 高さの解決: height prop を渡した場合はインライン style が勝つ。未指定なら\n // h-[400px] をデフォルトで当て、className の高さクラスに後勝ちさせる。\n const inFrame = useContext(ChartFrameContext)\n const styleHeight =\n height == null ? undefined : typeof height === \"number\" ? `${height}px` : height\n\n return (\n <div\n ref={ref}\n data-slot=\"echart\"\n className={cn(\"group relative w-full\", height == null && \"h-[400px]\", className)}\n style={styleHeight != null ? { height: styleHeight } : undefined}\n >\n {/* `role=\"img\"` wraps the canvas only, so the action buttons stay reachable. Inside a ChartFrame the plot area is the one image. */}\n <div\n ref={containerRef}\n data-slot=\"echart-canvas\"\n className=\"h-full w-full\"\n role={inFrame ? undefined : \"img\"}\n aria-label={inFrame ? undefined : (ariaLabel ?? \"チャート\")}\n />\n {actions && (\n <div\n data-slot=\"echart-actions\"\n className=\"absolute top-2 right-2 z-10 flex gap-1 pointer-events-none opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100 [@media(hover:none)]:pointer-events-auto [@media(hover:none)]:opacity-100\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={handleCopy}\n aria-label={copied ? \"コピーしました\" : \"PNG をクリップボードにコピー\"}\n >\n {copied ? <Check className=\"size-4\" /> : <Copy className=\"size-4\" />}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={handleDownload}\n aria-label=\"PNG をダウンロード\"\n >\n <Download className=\"size-4\" />\n </Button>\n </div>\n )}\n </div>\n )\n})\nEChart.displayName = \"EChart\"\n\nexport type { EChartsOption } from \"echarts\"\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../squadkit/registry/ui/button.tsx"],"names":["ButtonPrimitive"],"mappings":";;;;;;AAOA,IAAM,cAAA,GAAiB,GAAA;AAAA,EACrB,4lBAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,wDAAA;AAAA,QACT,OAAA,EACE,iLAAA;AAAA,QACF,SAAA,EACE,gLAAA;AAAA,QACF,KAAA,EACE,kHAAA;AAAA,QACF,WAAA,EACE,6NAAA;AAAA,QACF,IAAA,EAAM;AAAA,OACR;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,OAAA,EACE,sFAAA;AAAA,QACF,EAAA,EAAI,+MAAA;AAAA,QACJ,EAAA,EAAI,yNAAA;AAAA,QACJ,EAAA,EAAI,sFAAA;AAAA,QACJ,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EACE,yHAAA;AAAA,QACF,SAAA,EACE,oFAAA;AAAA,QACF,SAAA,EAAW;AAAA;AACb,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM;AAAA;AACR;AAEJ;AAEA,SAAS,MAAA,CAAO;AAAA,EACd,SAAA;AAAA,EACA,OAAA,GAAU,SAAA;AAAA,EACV,IAAA,GAAO,SAAA;AAAA,EACP,GAAG;AACL,CAAA,EAAgE;AAC9D,EAAA,uBACE,GAAA;AAAA,IAACA,QAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,QAAA;AAAA,MACV,SAAA,EAAW,GAAG,cAAA,CAAe,EAAE,SAAS,IAAA,EAAM,SAAA,EAAW,CAAC,CAAA;AAAA,MACzD,GAAG;AAAA;AAAA,GACN;AAEJ","file":"chunk-PDOBHMUQ.js","sourcesContent":["\"use client\"\n\nimport { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n"]}