@squadbase/vantage 0.6.2-dev1.d7c0911 → 0.6.2-dev1.e85faec

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 (221) hide show
  1. package/dist/chunk-2IAPIOPS.js +152 -0
  2. package/dist/chunk-2IAPIOPS.js.map +1 -0
  3. package/dist/chunk-57GHR5LN.js +163 -0
  4. package/dist/chunk-57GHR5LN.js.map +1 -0
  5. package/dist/chunk-6OTTGAPO.js +44 -0
  6. package/dist/chunk-6OTTGAPO.js.map +1 -0
  7. package/dist/{chunk-XPQSTZUU.js → chunk-7S52M2SL.js} +4 -3
  8. package/dist/chunk-7S52M2SL.js.map +1 -0
  9. package/dist/chunk-JXFCSF3K.js +673 -0
  10. package/dist/chunk-JXFCSF3K.js.map +1 -0
  11. package/dist/{chunk-WRSX2MDK.js → chunk-QOXXOFGL.js} +115 -930
  12. package/dist/chunk-QOXXOFGL.js.map +1 -0
  13. package/dist/components/index.d.ts +13 -249
  14. package/dist/components/index.js +5 -2
  15. package/dist/delta-text-CvwBGJ95.d.ts +15 -0
  16. package/dist/doc/index.d.ts +215 -2
  17. package/dist/doc/index.js +300 -3
  18. package/dist/doc/index.js.map +1 -1
  19. package/dist/format-U0cQl069.d.ts +243 -0
  20. package/dist/slide/index.d.ts +272 -1
  21. package/dist/slide/index.js +968 -3
  22. package/dist/slide/index.js.map +1 -1
  23. package/dist/table/index.js +6 -3
  24. package/dist/table/index.js.map +1 -1
  25. package/dist/ui/index.d.ts +4 -1
  26. package/dist/ui/index.js +3 -3
  27. package/dist/ui/index.js.map +1 -1
  28. package/docs/en/components.md +13 -2
  29. package/docs/en/doc/delta-text.md +40 -0
  30. package/docs/en/doc/doc-action-items.md +49 -0
  31. package/docs/en/doc/doc-callout.md +38 -0
  32. package/docs/en/doc/doc-data-table.md +60 -0
  33. package/docs/en/doc/doc-executive-summary.md +64 -0
  34. package/docs/en/doc/doc-figure.md +56 -0
  35. package/docs/en/doc/doc-key-findings.md +61 -0
  36. package/docs/en/doc/doc-kpi-scorecard.md +80 -0
  37. package/docs/en/doc/doc-notes-and-sources.md +43 -0
  38. package/docs/en/doc/doc-report-header.md +46 -0
  39. package/docs/en/parts/area-chart.md +99 -0
  40. package/docs/en/parts/bar-chart.md +91 -0
  41. package/docs/en/parts/bar-list.md +50 -0
  42. package/docs/en/parts/category-bar.md +37 -0
  43. package/docs/en/parts/chart-frame.md +39 -0
  44. package/docs/en/parts/delta.md +4 -3
  45. package/docs/en/parts/donut-chart.md +72 -0
  46. package/docs/en/parts/funnel-steps.md +2 -1
  47. package/docs/en/parts/heatmap.md +53 -0
  48. package/docs/en/parts/kpi-card.md +2 -1
  49. package/docs/en/parts/legend.md +35 -0
  50. package/docs/en/parts/line-chart.md +94 -0
  51. package/docs/en/parts/progress-circle.md +33 -0
  52. package/docs/en/parts/sample-data.md +39 -0
  53. package/docs/en/parts/scatter-chart.md +56 -0
  54. package/docs/en/parts/tracker.md +36 -0
  55. package/docs/en/parts/updated-at.md +30 -0
  56. package/docs/en/parts/waterfall-chart.md +56 -0
  57. package/docs/en/slide/slide-chart-full.md +48 -0
  58. package/docs/en/slide/slide-chart-insight.md +52 -0
  59. package/docs/en/slide/slide-columns.md +46 -0
  60. package/docs/en/slide/slide-comparison.md +68 -0
  61. package/docs/en/slide/slide-cover.md +39 -0
  62. package/docs/en/slide/slide-exec-summary.md +47 -0
  63. package/docs/en/slide/slide-heading.md +38 -0
  64. package/docs/en/slide/slide-kpi-grid.md +55 -0
  65. package/docs/en/slide/slide-kpi-hero.md +58 -0
  66. package/docs/en/slide/slide-next-actions.md +49 -0
  67. package/docs/en/slide/slide-scorecard-table.md +54 -0
  68. package/docs/en/slide/slide-section.md +44 -0
  69. package/docs/en/slide/slide-source-line.md +34 -0
  70. package/docs/en/ui/alert-dialog.md +42 -0
  71. package/docs/en/ui/avatar.md +31 -0
  72. package/docs/en/ui/combobox.md +74 -0
  73. package/docs/en/ui/drawer.md +41 -0
  74. package/docs/en/ui/empty.md +1 -1
  75. package/docs/en/ui/error-state.md +4 -3
  76. package/docs/en/ui/field.md +42 -0
  77. package/docs/en/ui/hover-card.md +21 -0
  78. package/docs/en/ui/kbd.md +17 -0
  79. package/docs/en/ui/loading.md +1 -1
  80. package/docs/en/ui/pagination.md +36 -0
  81. package/docs/en/ui/radio-group.md +21 -0
  82. package/docs/en/ui/toast.md +44 -0
  83. package/docs/en/ui/toggle-group.md +4 -3
  84. package/docs/index.json +857 -77
  85. package/docs/ja/components.md +12 -1
  86. package/docs/ja/doc/delta-text.md +40 -0
  87. package/docs/ja/doc/doc-action-items.md +49 -0
  88. package/docs/ja/doc/doc-callout.md +38 -0
  89. package/docs/ja/doc/doc-data-table.md +60 -0
  90. package/docs/ja/doc/doc-executive-summary.md +64 -0
  91. package/docs/ja/doc/doc-figure.md +56 -0
  92. package/docs/ja/doc/doc-key-findings.md +61 -0
  93. package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
  94. package/docs/ja/doc/doc-notes-and-sources.md +43 -0
  95. package/docs/ja/doc/doc-report-header.md +46 -0
  96. package/docs/ja/parts/area-chart.md +49 -25
  97. package/docs/ja/parts/bar-chart.md +50 -24
  98. package/docs/ja/parts/bar-list.md +31 -8
  99. package/docs/ja/parts/chart-frame.md +36 -0
  100. package/docs/ja/parts/delta.md +5 -4
  101. package/docs/ja/parts/donut-chart.md +45 -26
  102. package/docs/ja/parts/funnel-steps.md +27 -8
  103. package/docs/ja/parts/heatmap.md +45 -0
  104. package/docs/ja/parts/kpi-card.md +2 -1
  105. package/docs/ja/parts/legend.md +36 -0
  106. package/docs/ja/parts/line-chart.md +48 -22
  107. package/docs/ja/parts/sample-data.md +61 -0
  108. package/docs/ja/parts/scatter-chart.md +69 -0
  109. package/docs/ja/parts/updated-at.md +27 -0
  110. package/docs/ja/parts/waterfall-chart.md +61 -0
  111. package/docs/ja/slide/slide-chart-full.md +48 -0
  112. package/docs/ja/slide/slide-chart-insight.md +52 -0
  113. package/docs/ja/slide/slide-columns.md +46 -0
  114. package/docs/ja/slide/slide-comparison.md +68 -0
  115. package/docs/ja/slide/slide-cover.md +39 -0
  116. package/docs/ja/slide/slide-exec-summary.md +47 -0
  117. package/docs/ja/slide/slide-heading.md +38 -0
  118. package/docs/ja/slide/slide-kpi-grid.md +55 -0
  119. package/docs/ja/slide/slide-kpi-hero.md +58 -0
  120. package/docs/ja/slide/slide-next-actions.md +49 -0
  121. package/docs/ja/slide/slide-scorecard-table.md +54 -0
  122. package/docs/ja/slide/slide-section.md +44 -0
  123. package/docs/ja/slide/slide-source-line.md +34 -0
  124. package/docs/ja/ui/empty.md +1 -1
  125. package/docs/ja/ui/error-state.md +4 -3
  126. package/docs/ja/ui/loading.md +1 -1
  127. package/docs/ja/ui/toggle-group.md +4 -3
  128. package/package.json +26 -25
  129. package/registry/ui/accordion.tsx +1 -1
  130. package/registry/ui/alert-dialog.tsx +1 -1
  131. package/registry/ui/alert.tsx +1 -1
  132. package/registry/ui/app-shell.tsx +1 -1
  133. package/registry/ui/area-chart.tsx +89 -27
  134. package/registry/ui/attention-list.tsx +303 -0
  135. package/registry/ui/avatar.tsx +1 -1
  136. package/registry/ui/badge.tsx +1 -1
  137. package/registry/ui/bar-chart.tsx +89 -27
  138. package/registry/ui/bar-list.tsx +88 -25
  139. package/registry/ui/box-plot-chart.tsx +3906 -0
  140. package/registry/ui/breadcrumb.tsx +1 -1
  141. package/registry/ui/button.tsx +1 -1
  142. package/registry/ui/calendar.tsx +1 -1
  143. package/registry/ui/card.tsx +1 -1
  144. package/registry/ui/category-bar.tsx +55 -20
  145. package/registry/ui/chart-frame.tsx +57 -22
  146. package/registry/ui/checkbox.tsx +1 -1
  147. package/registry/ui/collapsible.tsx +1 -1
  148. package/registry/ui/combobox.tsx +1 -1
  149. package/registry/ui/command.tsx +1 -1
  150. package/registry/ui/dashboard-card.tsx +5 -5
  151. package/registry/ui/data-table.tsx +1 -1
  152. package/registry/ui/date-range-picker.tsx +1 -1
  153. package/registry/ui/delta.tsx +12 -9
  154. package/registry/ui/dialog.tsx +1 -1
  155. package/registry/ui/donut-chart.tsx +90 -27
  156. package/registry/ui/drawer.tsx +1 -1
  157. package/registry/ui/dropdown-menu.tsx +1 -1
  158. package/registry/ui/echart.tsx +195 -45
  159. package/registry/ui/field.tsx +1 -1
  160. package/registry/ui/filter-bar.tsx +1 -1
  161. package/registry/ui/funnel-steps.tsx +34 -6
  162. package/registry/ui/heatmap.tsx +56 -22
  163. package/registry/ui/histogram-chart.tsx +3986 -0
  164. package/registry/ui/hover-card.tsx +1 -1
  165. package/registry/ui/input-group.tsx +1 -1
  166. package/registry/ui/input.tsx +1 -1
  167. package/registry/ui/kbd.tsx +1 -1
  168. package/registry/ui/kpi-card.tsx +42 -15
  169. package/registry/ui/label.tsx +1 -1
  170. package/registry/ui/legend.tsx +88 -25
  171. package/registry/ui/line-chart.tsx +89 -27
  172. package/registry/ui/metric-value.tsx +1 -1
  173. package/registry/ui/multi-select.tsx +1 -1
  174. package/registry/ui/page-shell.tsx +11 -11
  175. package/registry/ui/pagination.tsx +1 -1
  176. package/registry/ui/paired-chart.tsx +3827 -0
  177. package/registry/ui/placeholder.tsx +1 -1
  178. package/registry/ui/popover.tsx +1 -1
  179. package/registry/ui/progress-circle.tsx +1 -1
  180. package/registry/ui/progress.tsx +1 -1
  181. package/registry/ui/radio-group.tsx +1 -1
  182. package/registry/ui/sample-data.tsx +2 -2
  183. package/registry/ui/scatter-chart.tsx +89 -27
  184. package/registry/ui/scroll-area.tsx +1 -1
  185. package/registry/ui/searchable-select.tsx +1 -1
  186. package/registry/ui/section-header.tsx +3 -3
  187. package/registry/ui/segmented-control.tsx +1 -1
  188. package/registry/ui/select.tsx +1 -1
  189. package/registry/ui/separator.tsx +1 -1
  190. package/registry/ui/sheet.tsx +1 -1
  191. package/registry/ui/sidebar.tsx +1 -1
  192. package/registry/ui/skeleton.tsx +1 -1
  193. package/registry/ui/slider.tsx +2 -2
  194. package/registry/ui/sparkline.tsx +1 -1
  195. package/registry/ui/spinner.tsx +1 -1
  196. package/registry/ui/states.tsx +1 -1
  197. package/registry/ui/status-badge.tsx +9 -9
  198. package/registry/ui/switch.tsx +1 -1
  199. package/registry/ui/table.tsx +1 -1
  200. package/registry/ui/tabs.tsx +1 -1
  201. package/registry/ui/textarea.tsx +1 -1
  202. package/registry/ui/toast.tsx +1 -1
  203. package/registry/ui/toggle-group.tsx +1 -1
  204. package/registry/ui/toggle.tsx +1 -1
  205. package/registry/ui/tooltip.tsx +7 -3
  206. package/registry/ui/tracker.tsx +10 -4
  207. package/registry/ui/trend-indicator.tsx +3 -3
  208. package/registry/ui/updated-at.tsx +1 -1
  209. package/registry/ui/waterfall-chart.tsx +89 -27
  210. package/skills/vantage-design/SKILL.md +34 -24
  211. package/skills/vantage-design/references/extract.md +16 -14
  212. package/skills/vantage-design/references/format.md +6 -5
  213. package/skills/vantage-design/references/presets.md +60 -110
  214. package/skills/vantage-slide/SKILL.md +54 -36
  215. package/templates/AGENTS.md +2 -2
  216. package/templates/agents/doc.md +48 -0
  217. package/templates/agents/page.md +32 -1
  218. package/templates/agents/slide.md +70 -2
  219. package/theme.css +25 -20
  220. package/dist/chunk-WRSX2MDK.js.map +0 -1
  221. package/dist/chunk-XPQSTZUU.js.map +0 -1
package/dist/doc/index.js CHANGED
@@ -1,6 +1,10 @@
1
+ import { DeltaText } from '../chunk-6OTTGAPO.js';
2
+ export { DeltaText } from '../chunk-6OTTGAPO.js';
3
+ import { Sparkline } from '../chunk-2IAPIOPS.js';
4
+ import { formatValue } from '../chunk-57GHR5LN.js';
1
5
  import { Button } from '../chunk-PDOBHMUQ.js';
2
6
  import '../chunk-U736PVHY.js';
3
- import { forwardRef, useEffect } from 'react';
7
+ import { forwardRef, useEffect, useId } from 'react';
4
8
  import { PrinterIcon } from 'lucide-react';
5
9
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
6
10
 
@@ -105,7 +109,7 @@ var Document = forwardRef(function Document2({ theme, style, ...props }, ref) {
105
109
  {
106
110
  ref,
107
111
  "data-slot": "document",
108
- style: themeVars || style ? { ...themeVars, ...style } : void 0,
112
+ style: { width: "100%", ...themeVars, ...style },
109
113
  ...props
110
114
  }
111
115
  ),
@@ -128,7 +132,300 @@ var Document = forwardRef(function Document2({ theme, style, ...props }, ref) {
128
132
  ] });
129
133
  });
130
134
  Document.displayName = "Document";
135
+ var PRIORITY = { high: "\u9AD8", medium: "\u4E2D", low: "\u4F4E" };
136
+ var MUTED = { color: "var(--doc-muted)" };
137
+ function Priority({ value }) {
138
+ if (!value) return /* @__PURE__ */ jsx(Fragment, { children: "\u2014" });
139
+ return /* @__PURE__ */ jsx("span", { className: value === "high" ? "font-semibold" : void 0, children: PRIORITY[value] });
140
+ }
141
+ function DocActionItems({ title = "\u63A8\u5968\u3059\u308B\u5BFE\u5FDC", headingLevel = 2, items, variant = "table" }) {
142
+ const Heading = headingLevel === 3 ? "h3" : "h2";
143
+ return /* @__PURE__ */ jsxs("section", { "data-slot": "doc-action-items", children: [
144
+ /* @__PURE__ */ jsx(Heading, { children: title }),
145
+ variant === "asks" ? /* @__PURE__ */ jsx("ul", { children: items.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "break-inside-avoid", children: [
146
+ item.action,
147
+ item.owner || item.due ? /* @__PURE__ */ jsxs("span", { style: MUTED, children: [
148
+ "\uFF08",
149
+ [item.owner, item.due ? `${item.due} \u307E\u3067` : void 0].filter(Boolean).join("\u30FB"),
150
+ "\uFF09"
151
+ ] }) : null
152
+ ] }, i)) }) : /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "table w-full", children: [
153
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
154
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "\u5BFE\u5FDC" }),
155
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "\u62C5\u5F53" }),
156
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "\u671F\u9650" }),
157
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "\u671F\u5F85\u3059\u308B\u52B9\u679C" }),
158
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "\u512A\u5148\u5EA6" })
159
+ ] }) }),
160
+ /* @__PURE__ */ jsx("tbody", { children: items.map((item, i) => /* @__PURE__ */ jsxs("tr", { children: [
161
+ /* @__PURE__ */ jsx("td", { children: item.action }),
162
+ /* @__PURE__ */ jsx("td", { children: item.owner ?? "\u2014" }),
163
+ /* @__PURE__ */ jsx("td", { className: "whitespace-nowrap tabular-nums", children: item.due ?? "\u2014" }),
164
+ /* @__PURE__ */ jsx("td", { children: item.impact ?? "\u2014" }),
165
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Priority, { value: item.priority }) })
166
+ ] }, i)) })
167
+ ] }) })
168
+ ] });
169
+ }
170
+ var KINDS = {
171
+ note: { word: "\u88DC\u8DB3", rule: "border-info", tint: "bg-info-subtle", text: "text-info" },
172
+ insight: { word: "\u793A\u5506", rule: "border-positive", tint: "bg-positive-subtle", text: "text-positive" },
173
+ warning: { word: "\u6CE8\u610F", rule: "border-warning", tint: "bg-warning-subtle", text: "text-warning" },
174
+ decision: { word: "\u6C7A\u5B9A\u4E8B\u9805", rule: "border-foreground", tint: "bg-muted", text: "text-foreground" }
175
+ };
176
+ function DocCallout({ kind = "note", title, children }) {
177
+ const k = KINDS[kind];
178
+ const titleId = useId();
179
+ const heading = title && title !== k.word ? `${k.word}: ${title}` : k.word;
180
+ return /* @__PURE__ */ jsxs(
181
+ "div",
182
+ {
183
+ role: "note",
184
+ "aria-labelledby": titleId,
185
+ "data-slot": "doc-callout",
186
+ "data-kind": kind,
187
+ className: `break-inside-avoid border-l-4 px-4 py-2 ${k.rule} ${k.tint}`,
188
+ children: [
189
+ /* @__PURE__ */ jsx("p", { id: titleId, className: `m-0 font-semibold ${k.text}`, children: heading }),
190
+ /* @__PURE__ */ jsx("div", { children: typeof children === "string" ? /* @__PURE__ */ jsx("p", { className: "m-0", children }) : children })
191
+ ]
192
+ }
193
+ );
194
+ }
195
+ var ALIGN = { left: "text-left", right: "text-right", center: "text-center" };
196
+ function DocDataTable({ title, unit, columns, rows, total, highlightRows, footnotes, source, asOf }) {
197
+ const isNumeric = (col) => rows.some((r) => typeof r[col.key] === "number");
198
+ const cls = (col) => {
199
+ const numeric = isNumeric(col);
200
+ return `${ALIGN[col.align ?? (numeric ? "right" : "left")]}${numeric ? " tabular-nums" : ""}`;
201
+ };
202
+ const text = (col, v) => typeof v === "number" ? formatValue(v, col.format ?? "number") : v === null || v === void 0 || v === "" ? "\u2014" : v;
203
+ const origin = [source ? `\u51FA\u5178: ${source}` : void 0, asOf ? `\u30C7\u30FC\u30BF\u6642\u70B9 ${asOf}` : void 0].filter(Boolean).join(" \uFF0F ");
204
+ const highlighted = new Set(highlightRows);
205
+ return /* @__PURE__ */ jsxs("figure", { "data-slot": "doc-data-table", className: "m-0 w-full break-inside-auto", children: [
206
+ /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "table w-full", children: [
207
+ title || unit ? /* @__PURE__ */ jsxs("caption", { className: "text-left", children: [
208
+ title ? /* @__PURE__ */ jsx("span", { className: "font-semibold", children: title }) : null,
209
+ unit ? /* @__PURE__ */ jsx("span", { style: { color: "var(--doc-muted)" }, children: title ? `\uFF08${unit}\uFF09` : unit }) : null
210
+ ] }) : null,
211
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsx("th", { scope: "col", className: cls(col), children: col.label }, col.key)) }) }),
212
+ /* @__PURE__ */ jsx("tbody", { children: rows.map((row, i) => /* @__PURE__ */ jsx("tr", { className: highlighted.has(i) ? "font-semibold" : void 0, children: columns.map((col) => /* @__PURE__ */ jsx("td", { className: cls(col), children: text(col, row[col.key]) }, col.key)) }, i)) }),
213
+ total ? /* @__PURE__ */ jsx("tfoot", { children: /* @__PURE__ */ jsx("tr", { className: "font-semibold", children: columns.map((col) => /* @__PURE__ */ jsx("td", { className: cls(col), children: text(col, total[col.key]) }, col.key)) }) }) : null
214
+ ] }) }),
215
+ footnotes?.length || origin ? /* @__PURE__ */ jsxs("figcaption", { className: "flex flex-col gap-0.5 break-inside-avoid text-left", children: [
216
+ footnotes?.map((f) => /* @__PURE__ */ jsxs("span", { children: [
217
+ f.mark,
218
+ " ",
219
+ f.text
220
+ ] }, f.mark)),
221
+ origin ? /* @__PURE__ */ jsx("span", { children: origin }) : null
222
+ ] }) : null
223
+ ] });
224
+ }
225
+ function DocExecutiveSummary({
226
+ title = "\u8981\u65E8",
227
+ headingLevel = 2,
228
+ conclusion,
229
+ points,
230
+ metrics
231
+ }) {
232
+ const Heading = headingLevel === 3 ? "h3" : "h2";
233
+ const shown2 = (metrics ?? []).slice(0, 3);
234
+ return /* @__PURE__ */ jsxs("section", { "data-slot": "doc-executive-summary", children: [
235
+ /* @__PURE__ */ jsx(Heading, { children: title }),
236
+ /* @__PURE__ */ jsx("p", { className: "font-semibold", children: conclusion }),
237
+ /* @__PURE__ */ jsx("ol", { children: points.map((point, i) => /* @__PURE__ */ jsx("li", { className: "break-inside-avoid", children: point }, i)) }),
238
+ shown2.length > 0 ? /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-1 gap-4 sm:grid-cols-3 print:grid-cols-3", children: shown2.map((m) => /* @__PURE__ */ jsxs(
239
+ "div",
240
+ {
241
+ className: "break-inside-avoid border-l-2 pl-3",
242
+ style: { borderColor: "var(--doc-border)" },
243
+ children: [
244
+ /* @__PURE__ */ jsx("dt", { style: { color: "var(--doc-muted)" }, children: m.label }),
245
+ /* @__PURE__ */ jsx("dd", { className: "m-0 font-semibold tabular-nums", children: m.display ?? formatValue(m.value, m.format) }),
246
+ m.delta ? /* @__PURE__ */ jsxs("dd", { className: "m-0", children: [
247
+ /* @__PURE__ */ jsxs("span", { style: { color: "var(--doc-muted)" }, children: [
248
+ m.comparisonLabel ?? "\u524D\u671F\u6BD4",
249
+ " "
250
+ ] }),
251
+ /* @__PURE__ */ jsx(DeltaText, { value: m.delta.value, format: m.delta.format ?? m.format, betterWhen: m.betterWhen })
252
+ ] }) : null
253
+ ]
254
+ },
255
+ m.label
256
+ )) }) : null
257
+ ] });
258
+ }
259
+ function DocFigure({ title, unit, number, source, asOf, notes, children }) {
260
+ const titleId = useId();
261
+ const origin = [source ? `\u51FA\u5178: ${source}` : void 0, asOf ? `\u30C7\u30FC\u30BF\u6642\u70B9 ${asOf}` : void 0].filter(Boolean).join(" \uFF0F ");
262
+ const hasCaption = number !== void 0 || origin || notes && notes.length > 0;
263
+ return /* @__PURE__ */ jsxs("figure", { "data-slot": "doc-figure", "aria-labelledby": titleId, className: "w-full break-inside-avoid", children: [
264
+ /* @__PURE__ */ jsx("p", { id: titleId, className: "m-0 font-semibold", children: title }),
265
+ unit ? /* @__PURE__ */ jsx("p", { className: "m-0", style: { color: "var(--doc-muted)" }, children: unit }) : null,
266
+ /* @__PURE__ */ jsx("div", { className: "w-full", children }),
267
+ hasCaption ? /* @__PURE__ */ jsxs("figcaption", { className: "flex flex-col gap-0.5 text-left", children: [
268
+ number !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
269
+ "\u56F3 ",
270
+ number
271
+ ] }) : null,
272
+ origin ? /* @__PURE__ */ jsx("span", { children: origin }) : null,
273
+ notes?.map((note, i) => /* @__PURE__ */ jsx("span", { children: note }, i))
274
+ ] }) : null
275
+ ] });
276
+ }
277
+ function DocKeyFindings({ title = "\u4E3B\u8981\u306A\u767A\u898B", headingLevel = 2, findings }) {
278
+ const Heading = headingLevel === 3 ? "h3" : "h2";
279
+ const Item = headingLevel === 3 ? "h4" : "h3";
280
+ return /* @__PURE__ */ jsxs("section", { "data-slot": "doc-key-findings", children: [
281
+ /* @__PURE__ */ jsx(Heading, { children: title }),
282
+ findings.map((f, i) => /* @__PURE__ */ jsxs("article", { className: "break-inside-avoid", children: [
283
+ /* @__PURE__ */ jsxs(Item, { children: [
284
+ i + 1,
285
+ ". ",
286
+ f.headline
287
+ ] }),
288
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between print:flex-row print:justify-between", children: [
289
+ /* @__PURE__ */ jsx("div", { children: typeof f.evidence === "string" ? /* @__PURE__ */ jsx("p", { className: "m-0", children: f.evidence }) : f.evidence }),
290
+ f.metric ? /* @__PURE__ */ jsxs("dl", { className: "m-0 shrink-0 sm:text-right print:text-right", children: [
291
+ /* @__PURE__ */ jsx("dt", { style: { color: "var(--doc-muted)" }, children: f.metric.label }),
292
+ /* @__PURE__ */ jsx("dd", { className: "m-0 font-semibold tabular-nums", children: f.metric.display ?? formatValue(f.metric.value, f.metric.format) }),
293
+ f.metric.delta ? /* @__PURE__ */ jsxs("dd", { className: "m-0", children: [
294
+ /* @__PURE__ */ jsxs("span", { style: { color: "var(--doc-muted)" }, children: [
295
+ f.metric.comparisonLabel ?? "\u524D\u671F\u6BD4",
296
+ " "
297
+ ] }),
298
+ /* @__PURE__ */ jsx(DeltaText, { value: f.metric.delta.value, format: f.metric.delta.format ?? f.metric.format, betterWhen: f.metric.betterWhen })
299
+ ] }) : null
300
+ ] }) : null
301
+ ] })
302
+ ] }, i))
303
+ ] });
304
+ }
305
+ var MUTED2 = { color: "var(--doc-muted)" };
306
+ var ACHIEVEMENT = { type: "percent", digits: 1 };
307
+ var shown = (m) => m.display ?? formatValue(m.value, m.format);
308
+ var achievement = (m) => m.target === void 0 || m.target === 0 || m.value === null ? "\u2014" : formatValue(m.value / m.target, ACHIEVEMENT);
309
+ var change = (m) => m.delta ? /* @__PURE__ */ jsx(DeltaText, { value: m.delta.value, format: m.delta.format ?? m.format, betterWhen: m.betterWhen }) : "\u2014";
310
+ var trendOf = (m) => (m.trend ?? []).map(({ y }) => ({ value: y }));
311
+ function DocKpiScorecard({
312
+ title = "\u4E3B\u8981\u6307\u6A19",
313
+ headingLevel = 2,
314
+ metrics,
315
+ variant = "table",
316
+ asOf,
317
+ source
318
+ }) {
319
+ const Heading = headingLevel === 3 ? "h3" : "h2";
320
+ const caption = [source ? `\u51FA\u5178: ${source}` : void 0, asOf ? `\u30C7\u30FC\u30BF\u6642\u70B9 ${asOf}` : void 0].filter(Boolean).join(" \uFF0F ");
321
+ const columnLabel = metrics.find((m) => m.comparisonLabel)?.comparisonLabel ?? "\u524D\u671F\u6BD4";
322
+ return /* @__PURE__ */ jsxs("section", { "data-slot": "doc-kpi-scorecard", children: [
323
+ /* @__PURE__ */ jsx(Heading, { children: title }),
324
+ variant === "grid" ? /* @__PURE__ */ jsx("dl", { className: "m-0 grid grid-cols-1 gap-4 sm:grid-cols-3 print:grid-cols-3", children: metrics.map((m) => /* @__PURE__ */ jsxs(
325
+ "div",
326
+ {
327
+ className: "break-inside-avoid rounded-md border p-3",
328
+ style: { borderColor: "var(--doc-border)", background: "var(--doc-subtle)" },
329
+ children: [
330
+ /* @__PURE__ */ jsx("dt", { style: MUTED2, children: m.label }),
331
+ /* @__PURE__ */ jsx("dd", { className: "m-0 font-semibold tabular-nums", children: shown(m) }),
332
+ /* @__PURE__ */ jsxs("dd", { className: "m-0 flex flex-col gap-0.5", children: [
333
+ m.delta ? /* @__PURE__ */ jsxs("span", { children: [
334
+ /* @__PURE__ */ jsxs("span", { style: MUTED2, children: [
335
+ m.comparisonLabel ?? "\u524D\u671F\u6BD4",
336
+ " "
337
+ ] }),
338
+ change(m)
339
+ ] }) : null,
340
+ m.target !== void 0 ? /* @__PURE__ */ jsxs("span", { children: [
341
+ /* @__PURE__ */ jsx("span", { style: MUTED2, children: "\u9054\u6210\u7387 " }),
342
+ achievement(m),
343
+ /* @__PURE__ */ jsxs("span", { style: MUTED2, children: [
344
+ "\uFF08\u76EE\u6A19 ",
345
+ formatValue(m.target, m.format),
346
+ "\uFF09"
347
+ ] })
348
+ ] }) : null
349
+ ] }),
350
+ m.trend && m.trend.length > 1 ? /* @__PURE__ */ jsx("dd", { className: "m-0", children: /* @__PURE__ */ jsx(Sparkline, { data: trendOf(m), height: 28, "aria-label": `${m.label}\u306E\u63A8\u79FB` }) }) : null
351
+ ]
352
+ },
353
+ m.label
354
+ )) }) : /* @__PURE__ */ jsx("div", { className: "w-full overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "table w-full", children: [
355
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
356
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "\u6307\u6A19" }),
357
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "text-right", children: "\u5B9F\u7E3E" }),
358
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "text-right", children: columnLabel }),
359
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "text-right", children: "\u76EE\u6A19" }),
360
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "text-right", children: "\u9054\u6210\u7387" }),
361
+ /* @__PURE__ */ jsx("th", { scope: "col", children: "\u63A8\u79FB" })
362
+ ] }) }),
363
+ /* @__PURE__ */ jsx("tbody", { children: metrics.map((m) => /* @__PURE__ */ jsxs("tr", { children: [
364
+ /* @__PURE__ */ jsx("th", { scope: "row", className: "font-medium", children: m.label }),
365
+ /* @__PURE__ */ jsx("td", { className: "text-right font-semibold tabular-nums", children: shown(m) }),
366
+ /* @__PURE__ */ jsx("td", { className: "text-right whitespace-nowrap", children: change(m) }),
367
+ /* @__PURE__ */ jsx("td", { className: "text-right tabular-nums", children: m.target === void 0 ? "\u2014" : formatValue(m.target, m.format) }),
368
+ /* @__PURE__ */ jsx("td", { className: "text-right tabular-nums", children: achievement(m) }),
369
+ /* @__PURE__ */ jsx("td", { children: m.trend && m.trend.length > 1 ? /* @__PURE__ */ jsx(Sparkline, { data: trendOf(m), height: 24, "aria-label": `${m.label}\u306E\u63A8\u79FB` }) : "\u2014" })
370
+ ] }, m.label)) })
371
+ ] }) }),
372
+ caption ? /* @__PURE__ */ jsx("p", { style: MUTED2, children: caption }) : null
373
+ ] });
374
+ }
375
+ function DocReportHeader({ title, subtitle, period, asOf, author, source }) {
376
+ const facts = [
377
+ ...period ? [{ label: "\u5BFE\u8C61\u671F\u9593", value: period }] : [],
378
+ ...asOf ? [{ label: "\u30C7\u30FC\u30BF\u6642\u70B9", value: asOf }] : [],
379
+ ...author ? [{ label: "\u4F5C\u6210\u8005", value: author }] : [],
380
+ ...source ? [{ label: "\u51FA\u5178", value: source }] : []
381
+ ];
382
+ return /* @__PURE__ */ jsxs("header", { "data-slot": "doc-report-header", className: "break-inside-avoid", children: [
383
+ /* @__PURE__ */ jsx("h1", { children: title }),
384
+ subtitle ? typeof subtitle === "string" ? /* @__PURE__ */ jsx("p", { style: { color: "var(--doc-muted)" }, children: subtitle }) : /* @__PURE__ */ jsx("div", { style: { color: "var(--doc-muted)" }, children: subtitle }) : null,
385
+ facts.length > 0 ? /* @__PURE__ */ jsx(
386
+ "dl",
387
+ {
388
+ className: "grid grid-cols-1 gap-x-8 gap-y-2 border-y py-3 sm:grid-cols-2 print:grid-cols-2",
389
+ style: { borderColor: "var(--doc-border)" },
390
+ children: facts.map((fact) => /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
391
+ /* @__PURE__ */ jsx("dt", { className: "shrink-0", style: { color: "var(--doc-muted)" }, children: fact.label }),
392
+ /* @__PURE__ */ jsx("dd", { className: "m-0 font-medium", children: fact.value })
393
+ ] }, fact.label))
394
+ }
395
+ ) : null
396
+ ] });
397
+ }
398
+ function DocNotesAndSources({ title = "\u6CE8\u8A18\u30FB\u51FA\u5178", headingLevel = 2, notes = [], definitions = [], sources = [] }) {
399
+ if (notes.length === 0 && definitions.length === 0 && sources.length === 0) return null;
400
+ const Heading = headingLevel === 3 ? "h3" : "h2";
401
+ const Sub = headingLevel === 3 ? "h4" : "h3";
402
+ return /* @__PURE__ */ jsxs("section", { "data-slot": "doc-notes-and-sources", children: [
403
+ /* @__PURE__ */ jsx(Heading, { children: title }),
404
+ notes.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "break-inside-avoid", children: [
405
+ /* @__PURE__ */ jsx(Sub, { children: "\u6CE8\u8A18" }),
406
+ /* @__PURE__ */ jsx("ol", { children: notes.map((n, i) => /* @__PURE__ */ jsx("li", { children: n }, i)) })
407
+ ] }) : null,
408
+ definitions.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "break-inside-avoid", children: [
409
+ /* @__PURE__ */ jsx(Sub, { children: "\u7528\u8A9E\u306E\u5B9A\u7FA9" }),
410
+ /* @__PURE__ */ jsx("dl", { className: "m-0", children: definitions.map((d, i) => /* @__PURE__ */ jsxs("div", { className: "break-inside-avoid", children: [
411
+ /* @__PURE__ */ jsx("dt", { className: "font-semibold", children: d.term }),
412
+ /* @__PURE__ */ jsx("dd", { className: "m-0", children: d.description })
413
+ ] }, i)) })
414
+ ] }) : null,
415
+ sources.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "break-inside-avoid", children: [
416
+ /* @__PURE__ */ jsx(Sub, { children: "\u51FA\u5178" }),
417
+ /* @__PURE__ */ jsx("ul", { children: sources.map((s, i) => /* @__PURE__ */ jsxs("li", { children: [
418
+ s.name,
419
+ s.asOf ? /* @__PURE__ */ jsxs("span", { style: { color: "var(--doc-muted)" }, children: [
420
+ "\uFF08\u30C7\u30FC\u30BF\u6642\u70B9 ",
421
+ s.asOf,
422
+ "\uFF09"
423
+ ] }) : null
424
+ ] }, i)) })
425
+ ] }) : null
426
+ ] });
427
+ }
131
428
 
132
- export { Document };
429
+ export { DocActionItems, DocCallout, DocDataTable, DocExecutiveSummary, DocFigure, DocKeyFindings, DocKpiScorecard, DocNotesAndSources, DocReportHeader, Document };
133
430
  //# sourceMappingURL=index.js.map
134
431
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/doc/print.ts","../../src/doc/document.tsx"],"names":["Document"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Printing a document — the browser's own print dialog, where \"Save as PDF\"\n * is the download. Paper is white and backgrounds are dropped by default, so a\n * dark theme would print pale text on nothing: the page is switched to light\n * for the duration and put back afterwards.\n */\n\nconst DARK_CLASS = \"dark\"\nconst THEME_ATTR = \"data-theme\"\n\ntype Restore = () => void\n\nlet restore: Restore | null = null\n\n/** Drop every dark marker on `<html>`/`<body>`, remembering exactly what was there. */\nfunction forceLight(): void {\n if (restore) return\n const undo: Restore[] = []\n for (const el of [document.documentElement, document.body]) {\n if (!el) continue\n if (el.classList.contains(DARK_CLASS)) {\n el.classList.remove(DARK_CLASS)\n undo.push(() => el.classList.add(DARK_CLASS))\n }\n if (el.getAttribute(THEME_ATTR) === \"dark\") {\n el.setAttribute(THEME_ATTR, \"light\")\n undo.push(() => el.setAttribute(THEME_ATTR, \"dark\"))\n }\n }\n restore = () => {\n for (const fn of undo) fn()\n }\n}\n\nfunction restoreTheme(): void {\n restore?.()\n restore = null\n}\n\nfunction nextFrame(): Promise<void> {\n return new Promise((resolve) => {\n let settled = false\n const settle = () => {\n if (settled) return\n settled = true\n resolve()\n }\n requestAnimationFrame(settle)\n setTimeout(settle, 50)\n })\n}\n\n/**\n * Canvas charts keep the colours they were painted with, and a CSS switch at\n * print time does not repaint them. Their tokens are re-read a frame after the\n * theme flips, then React re-inits the chart, which animates in from empty —\n * printed mid-way, the bars are missing. So wait a few frames for the re-init\n * to start, then for every chart to report its paint done.\n */\nconst REPAINT_FRAMES = 4\nconst CHART_TIMEOUT_MS = 3000\n\nasync function waitForCharts(): Promise<void> {\n const deadline = performance.now() + CHART_TIMEOUT_MS\n while (performance.now() < deadline) {\n if (!document.querySelector('[data-slot=\"echart-canvas\"][data-rendering]')) return\n await nextFrame()\n }\n}\n\n/**\n * The theme comes back on `afterprint` (see `watchPrintEvents`), not after\n * `window.print()` returns — not every browser blocks on the dialog.\n */\nexport async function printDocument(): Promise<void> {\n const wasForced = restore !== null\n forceLight()\n try {\n if (!wasForced && restore) {\n for (let i = 0; i < REPAINT_FRAMES; i++) await nextFrame()\n }\n await waitForCharts()\n window.print()\n } catch (error) {\n restoreTheme()\n throw error\n }\n}\n\n/**\n * Must be mounted while a document is on screen. It also covers the browser's\n * own Print command, which skips the button: flipping the theme in\n * `beforeprint` still gets the text and rules right, though canvas charts\n * cannot repaint in time on that path.\n */\nexport function watchPrintEvents(): () => void {\n window.addEventListener(\"beforeprint\", forceLight)\n window.addEventListener(\"afterprint\", restoreTheme)\n return () => {\n window.removeEventListener(\"beforeprint\", forceLight)\n window.removeEventListener(\"afterprint\", restoreTheme)\n }\n}\n","import { forwardRef, useEffect } from \"react\"\nimport type { CSSProperties, HTMLAttributes } from \"react\"\nimport { PrinterIcon } from \"lucide-react\"\n\nimport { Button } from \"@squadbase/squadkit/ui/button\"\nimport { printDocument, watchPrintEvents } from \"./print\"\nimport type { DocumentTheme } from \"./types\"\n\nexport interface DocumentProps extends HTMLAttributes<HTMLElement> {\n /** Token overrides for this document; anything omitted follows the app's theme. */\n theme?: DocumentTheme\n}\n\n/**\n * Only the keys the document set are emitted — the rest resolve up the\n * cascade to `--doc-*` in theme.css. Writing defaults here would freeze every\n * document to light.\n */\nfunction themeToCssVars(theme: DocumentTheme | undefined): CSSProperties | undefined {\n if (!theme) return undefined\n const vars: Record<string, string> = {}\n if (theme.fg) vars[\"--doc-fg\"] = theme.fg\n if (theme.muted) vars[\"--doc-muted\"] = theme.muted\n if (theme.accent) vars[\"--doc-accent\"] = theme.accent\n if (theme.border) vars[\"--doc-border\"] = theme.border\n if (theme.subtle) vars[\"--doc-subtle\"] = theme.subtle\n if (theme.fontBody) vars[\"--doc-font-body\"] = theme.fontBody\n if (theme.fontHeading) vars[\"--doc-font-heading\"] = theme.fontHeading\n if (theme.fontMono) vars[\"--doc-font-mono\"] = theme.fontMono\n if (theme.sizeBody) vars[\"--doc-size-body\"] = theme.sizeBody\n if (theme.lineHeight) vars[\"--doc-line-height\"] = theme.lineHeight\n if (theme.maxWidth) vars[\"--doc-max-width\"] = theme.maxWidth\n return Object.keys(vars).length > 0 ? (vars as CSSProperties) : undefined\n}\n\n/**\n * With no page margin the browser has nowhere to print its date / URL header\n * and footer. Rendered by `<Document>` rather than put in theme.css because an\n * `@page` rule cannot be scoped — there it would reach every dashboard too.\n */\nconst PRINT_PAGE_CSS = \"@media print { @page { margin: 0 } }\"\n\n/** The one piece of chrome a document shows: English, Japanese for a Japanese browser. */\nfunction printLabel(): string {\n return navigator.language.toLowerCase().startsWith(\"ja\") ? \"PDF として保存\" : \"Save as PDF\"\n}\n\n/**\n * The container of a document page. Plain elements written inside it —\n * headings, paragraphs, lists, tables, quotes, code, figures — are typeset by\n * the `[data-slot=\"document\"]` rules in theme.css, so the page body needs no\n * classes. Those rules sit in `@layer components`, below Tailwind utilities, so\n * a `className` on any element still wins.\n *\n * It also carries its own way out: a button that opens the print dialog, where\n * \"Save as PDF\" is the download. The print rules in theme.css leave only the\n * document on paper.\n */\nexport const Document = forwardRef<HTMLElement, DocumentProps>(function Document(\n { theme, style, ...props },\n ref,\n) {\n const themeVars = themeToCssVars(theme)\n const label = printLabel()\n useEffect(() => watchPrintEvents(), [])\n return (\n <>\n <article\n ref={ref}\n data-slot=\"document\"\n style={themeVars || style ? { ...themeVars, ...style } : undefined}\n {...props}\n />\n <style>{PRINT_PAGE_CSS}</style>\n <Button\n data-slot=\"document-print\"\n variant=\"outline\"\n size=\"sm\"\n className=\"fixed right-4 bottom-4 z-10 shadow-sm\"\n onClick={() => void printDocument()}\n title={label}\n >\n <PrinterIcon aria-hidden=\"true\" />\n {label}\n </Button>\n </>\n )\n})\nDocument.displayName = \"Document\"\n"]}
1
+ {"version":3,"sources":["../../src/doc/print.ts","../../src/doc/document.tsx","../../../squadkit/registry/blocks/doc-action-items/doc-action-items.tsx","../../../squadkit/registry/blocks/doc-callout/doc-callout.tsx","../../../squadkit/registry/blocks/doc-data-table/doc-data-table.tsx","../../../squadkit/registry/blocks/doc-executive-summary/doc-executive-summary.tsx","../../../squadkit/registry/blocks/doc-figure/doc-figure.tsx","../../../squadkit/registry/blocks/doc-key-findings/doc-key-findings.tsx","../../../squadkit/registry/blocks/doc-kpi-scorecard/doc-kpi-scorecard.tsx","../../../squadkit/registry/blocks/doc-report-header/doc-report-header.tsx","../../../squadkit/registry/blocks/doc-notes-and-sources/doc-notes-and-sources.tsx"],"names":["Document","jsx","Fragment","jsxs","shown","useId","MUTED"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Printing a document — the browser's own print dialog, where \"Save as PDF\"\n * is the download. Paper is white and backgrounds are dropped by default, so a\n * dark theme would print pale text on nothing: the page is switched to light\n * for the duration and put back afterwards.\n */\n\nconst DARK_CLASS = \"dark\"\nconst THEME_ATTR = \"data-theme\"\n\ntype Restore = () => void\n\nlet restore: Restore | null = null\n\n/** Drop every dark marker on `<html>`/`<body>`, remembering exactly what was there. */\nfunction forceLight(): void {\n if (restore) return\n const undo: Restore[] = []\n for (const el of [document.documentElement, document.body]) {\n if (!el) continue\n if (el.classList.contains(DARK_CLASS)) {\n el.classList.remove(DARK_CLASS)\n undo.push(() => el.classList.add(DARK_CLASS))\n }\n if (el.getAttribute(THEME_ATTR) === \"dark\") {\n el.setAttribute(THEME_ATTR, \"light\")\n undo.push(() => el.setAttribute(THEME_ATTR, \"dark\"))\n }\n }\n restore = () => {\n for (const fn of undo) fn()\n }\n}\n\nfunction restoreTheme(): void {\n restore?.()\n restore = null\n}\n\nfunction nextFrame(): Promise<void> {\n return new Promise((resolve) => {\n let settled = false\n const settle = () => {\n if (settled) return\n settled = true\n resolve()\n }\n requestAnimationFrame(settle)\n setTimeout(settle, 50)\n })\n}\n\n/**\n * Canvas charts keep the colours they were painted with, and a CSS switch at\n * print time does not repaint them. Their tokens are re-read a frame after the\n * theme flips, then React re-inits the chart, which animates in from empty —\n * printed mid-way, the bars are missing. So wait a few frames for the re-init\n * to start, then for every chart to report its paint done.\n */\nconst REPAINT_FRAMES = 4\nconst CHART_TIMEOUT_MS = 3000\n\nasync function waitForCharts(): Promise<void> {\n const deadline = performance.now() + CHART_TIMEOUT_MS\n while (performance.now() < deadline) {\n if (!document.querySelector('[data-slot=\"echart-canvas\"][data-rendering]')) return\n await nextFrame()\n }\n}\n\n/**\n * The theme comes back on `afterprint` (see `watchPrintEvents`), not after\n * `window.print()` returns — not every browser blocks on the dialog.\n */\nexport async function printDocument(): Promise<void> {\n const wasForced = restore !== null\n forceLight()\n try {\n if (!wasForced && restore) {\n for (let i = 0; i < REPAINT_FRAMES; i++) await nextFrame()\n }\n await waitForCharts()\n window.print()\n } catch (error) {\n restoreTheme()\n throw error\n }\n}\n\n/**\n * Must be mounted while a document is on screen. It also covers the browser's\n * own Print command, which skips the button: flipping the theme in\n * `beforeprint` still gets the text and rules right, though canvas charts\n * cannot repaint in time on that path.\n */\nexport function watchPrintEvents(): () => void {\n window.addEventListener(\"beforeprint\", forceLight)\n window.addEventListener(\"afterprint\", restoreTheme)\n return () => {\n window.removeEventListener(\"beforeprint\", forceLight)\n window.removeEventListener(\"afterprint\", restoreTheme)\n }\n}\n","import { forwardRef, useEffect } from \"react\"\nimport type { CSSProperties, HTMLAttributes } from \"react\"\nimport { PrinterIcon } from \"lucide-react\"\n\nimport { Button } from \"@squadbase/squadkit/ui/button\"\nimport { printDocument, watchPrintEvents } from \"./print\"\nimport type { DocumentTheme } from \"./types\"\n\nexport interface DocumentProps extends HTMLAttributes<HTMLElement> {\n /** Token overrides for this document; anything omitted follows the app's theme. */\n theme?: DocumentTheme\n}\n\n/**\n * Only the keys the document set are emitted — the rest resolve up the\n * cascade to `--doc-*` in theme.css. Writing defaults here would freeze every\n * document to light.\n */\nfunction themeToCssVars(theme: DocumentTheme | undefined): CSSProperties | undefined {\n if (!theme) return undefined\n const vars: Record<string, string> = {}\n if (theme.fg) vars[\"--doc-fg\"] = theme.fg\n if (theme.muted) vars[\"--doc-muted\"] = theme.muted\n if (theme.accent) vars[\"--doc-accent\"] = theme.accent\n if (theme.border) vars[\"--doc-border\"] = theme.border\n if (theme.subtle) vars[\"--doc-subtle\"] = theme.subtle\n if (theme.fontBody) vars[\"--doc-font-body\"] = theme.fontBody\n if (theme.fontHeading) vars[\"--doc-font-heading\"] = theme.fontHeading\n if (theme.fontMono) vars[\"--doc-font-mono\"] = theme.fontMono\n if (theme.sizeBody) vars[\"--doc-size-body\"] = theme.sizeBody\n if (theme.lineHeight) vars[\"--doc-line-height\"] = theme.lineHeight\n if (theme.maxWidth) vars[\"--doc-max-width\"] = theme.maxWidth\n return Object.keys(vars).length > 0 ? (vars as CSSProperties) : undefined\n}\n\n/**\n * With no page margin the browser has nowhere to print its date / URL header\n * and footer. Rendered by `<Document>` rather than put in theme.css because an\n * `@page` rule cannot be scoped — there it would reach every dashboard too.\n */\nconst PRINT_PAGE_CSS = \"@media print { @page { margin: 0 } }\"\n\n/** The one piece of chrome a document shows: English, Japanese for a Japanese browser. */\nfunction printLabel(): string {\n return navigator.language.toLowerCase().startsWith(\"ja\") ? \"PDF として保存\" : \"Save as PDF\"\n}\n\n/**\n * The container of a document page. Plain elements written inside it —\n * headings, paragraphs, lists, tables, quotes, code, figures — are typeset by\n * the `[data-slot=\"document\"]` rules in theme.css, so the page body needs no\n * classes. Those rules sit in `@layer components`, below Tailwind utilities, so\n * a `className` on any element still wins.\n *\n * It also carries its own way out: a button that opens the print dialog, where\n * \"Save as PDF\" is the download. The print rules in theme.css leave only the\n * document on paper.\n */\nexport const Document = forwardRef<HTMLElement, DocumentProps>(function Document(\n { theme, style, ...props },\n ref,\n) {\n const themeVars = themeToCssVars(theme)\n const label = printLabel()\n useEffect(() => watchPrintEvents(), [])\n return (\n <>\n <article\n ref={ref}\n data-slot=\"document\"\n // `margin-inline: auto` shrinks an article to its content inside a flex column parent;\n // 100% keeps the column (max-width from the theme still caps it).\n style={{ width: \"100%\", ...themeVars, ...style }}\n {...props}\n />\n <style>{PRINT_PAGE_CSS}</style>\n <Button\n data-slot=\"document-print\"\n variant=\"outline\"\n size=\"sm\"\n className=\"fixed right-4 bottom-4 z-10 shadow-sm\"\n onClick={() => void printDocument()}\n title={label}\n >\n <PrinterIcon aria-hidden=\"true\" />\n {label}\n </Button>\n </>\n )\n})\nDocument.displayName = \"Document\"\n","\"use client\"\n\n/**\n * doc-action-items — what to do next: action, owner, due date, expected effect, priority.\n * For the recommendation section of a report, a QBR or a board paper.\n *\n * - `variant=\"table\"` (default) is a plain `table`. `variant=\"asks\"` is a short bulleted list of\n * requests to the reader (introductions, a decision, a hire): owner and due are shown inline.\n * - `priority` is an enum (`high` | `medium` | `low`), printed as a plain word (高 / 中 / 低; 高 in\n * semibold) with no badge and no colour. A missing owner / due / impact shows \"—\".\n * - Rows are listed in the order given; put the most important first.\n * - The heading is a bare `h2` / `h3`; the document sets its size. No width is set anywhere.\n *\n * @example\n * import { DocActionItems } from \"@/blocks/doc-action-items/doc-action-items\"\n * <DocActionItems items={[{ action: \"法人プランの導入支援を増員する\", owner: \"CS 部\", due: \"2026-11-15\", priority: \"high\" }]} />\n */\nimport type { ReactNode } from \"react\"\n\nexport type DocActionPriority = \"high\" | \"medium\" | \"low\"\n\nexport interface DocActionItem {\n action: ReactNode\n owner?: string\n /** Due date as written, e.g. \"2026-11-15\" or \"11 月末\". */\n due?: string\n /** What we expect to change, e.g. \"解約率 −0.5pt\". */\n impact?: string\n priority?: DocActionPriority\n}\n\nexport interface DocActionItemsProps {\n /** Heading text. Default \"推奨する対応\". */\n title?: string\n /** `2` directly under the document, `3` inside another section. Default 2. */\n headingLevel?: 2 | 3\n items: DocActionItem[]\n variant?: \"table\" | \"asks\"\n}\n\nconst PRIORITY = { high: \"高\", medium: \"中\", low: \"低\" } as const\n\nconst MUTED = { color: \"var(--doc-muted)\" } as const\n\nfunction Priority({ value }: { value: DocActionPriority | undefined }) {\n if (!value) return <>—</>\n return <span className={value === \"high\" ? \"font-semibold\" : undefined}>{PRIORITY[value]}</span>\n}\n\nexport function DocActionItems({ title = \"推奨する対応\", headingLevel = 2, items, variant = \"table\" }: DocActionItemsProps) {\n const Heading = headingLevel === 3 ? \"h3\" : \"h2\"\n\n return (\n <section data-slot=\"doc-action-items\">\n <Heading>{title}</Heading>\n {variant === \"asks\" ? (\n <ul>\n {items.map((item, i) => (\n <li key={i} className=\"break-inside-avoid\">\n {item.action}\n {item.owner || item.due ? (\n <span style={MUTED}>\n ({[item.owner, item.due ? `${item.due} まで` : undefined].filter(Boolean).join(\"・\")})\n </span>\n ) : null}\n </li>\n ))}\n </ul>\n ) : (\n <div className=\"w-full overflow-x-auto\">\n <table className=\"table w-full\">\n <thead>\n <tr>\n <th scope=\"col\">対応</th>\n <th scope=\"col\">担当</th>\n <th scope=\"col\">期限</th>\n <th scope=\"col\">期待する効果</th>\n <th scope=\"col\">優先度</th>\n </tr>\n </thead>\n <tbody>\n {items.map((item, i) => (\n <tr key={i}>\n <td>{item.action}</td>\n <td>{item.owner ?? \"—\"}</td>\n <td className=\"whitespace-nowrap tabular-nums\">{item.due ?? \"—\"}</td>\n <td>{item.impact ?? \"—\"}</td>\n <td>\n <Priority value={item.priority} />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </section>\n )\n}\n\nexport default DocActionItems\n","\"use client\"\n\n/**\n * doc-callout — a boxed remark inside the running text: a note, an insight, a warning, or a\n * decision that was made. Use it for the one thing a reader must not miss; not for decoration.\n *\n * - A `div role=\"note\"` named by its heading, with a left rule in the kind's colour (`decision` is\n * neutral: a decision is not bad news). The kind also prints as a word (\"注意\", \"示唆\"), so colour\n * is never the only signal. When `title` equals the kind's word, it is shown once.\n * - `children` is a `string` or a `ReactNode`; Markdown strings are not parsed. Paragraphs\n * inside take the document's body size.\n * - `break-inside-avoid` keeps it on one page when printed.\n *\n * @example\n * import { DocCallout } from \"@/blocks/doc-callout/doc-callout\"\n * <DocCallout kind=\"warning\" title=\"9 月の数値は速報値\">10 月 10 日の確定で変わることがあります。</DocCallout>\n */\nimport { useId, type ReactNode } from \"react\"\n\nexport type DocCalloutKind = \"note\" | \"insight\" | \"warning\" | \"decision\"\n\nexport interface DocCalloutProps {\n kind?: DocCalloutKind\n /** Heading of the box, one short line. Default: the kind's word. */\n title?: string\n children: ReactNode\n}\n\nconst KINDS: Record<DocCalloutKind, { word: string; rule: string; tint: string; text: string }> = {\n note: { word: \"補足\", rule: \"border-info\", tint: \"bg-info-subtle\", text: \"text-info\" },\n insight: { word: \"示唆\", rule: \"border-positive\", tint: \"bg-positive-subtle\", text: \"text-positive\" },\n warning: { word: \"注意\", rule: \"border-warning\", tint: \"bg-warning-subtle\", text: \"text-warning\" },\n decision: { word: \"決定事項\", rule: \"border-foreground\", tint: \"bg-muted\", text: \"text-foreground\" },\n}\n\nexport function DocCallout({ kind = \"note\", title, children }: DocCalloutProps) {\n const k = KINDS[kind]\n const titleId = useId()\n const heading = title && title !== k.word ? `${k.word}: ${title}` : k.word\n return (\n <div\n role=\"note\"\n aria-labelledby={titleId}\n data-slot=\"doc-callout\"\n data-kind={kind}\n className={`break-inside-avoid border-l-4 px-4 py-2 ${k.rule} ${k.tint}`}\n >\n <p id={titleId} className={`m-0 font-semibold ${k.text}`}>\n {heading}\n </p>\n <div>{typeof children === \"string\" ? <p className=\"m-0\">{children}</p> : children}</div>\n </div>\n )\n}\n\nexport default DocCallout\n","\"use client\"\n\n/**\n * doc-data-table — a table with the notes a printed table needs: title, unit, right-aligned\n * numbers, a total row, highlighted rows, footnote marks, and a source line.\n *\n * - A plain `table`: the document styles it and keeps each row on one page when printed; a long\n * table may break between rows (the figure is allowed to split, the caption stays whole).\n * (`ui/table` and `DataTable` are for screens — sorting, scrolling — and are not used here.)\n * - Numbers are formatted from `format` (default: a plain number) and right-aligned with\n * `tabular-nums`; a missing value shows \"—\". Text columns align left.\n * - `total` is a row of values keyed like the rows, shown in a `tfoot`.\n * - `footnotes` are `{ mark, text }`; put the same `mark` (\"※1\") in a cell string to point at it.\n * - A column is `w-full` in a table that fills the column; no width is set on cells.\n *\n * @example\n * import { DocDataTable } from \"@/blocks/doc-data-table/doc-data-table\"\n * <DocDataTable title=\"部門別の売上\" unit=\"単位: 百万円\" columns={[{ key: \"dept\", label: \"部門\" }, { key: \"sales\", label: \"売上\", format: \"number\" }]} rows={[{ dept: \"法人営業\", sales: 312 }]} />\n */\nimport { formatValue, type ValueFormat } from \"../../lib/format\"\n\nexport type DocTableCell = string | number | null | undefined\nexport type DocTableRow = Record<string, DocTableCell>\n\nexport interface DocTableColumn {\n key: string\n label: string\n /** Format of a numeric column. Without it, numbers use a plain thousands format. */\n format?: ValueFormat\n /** Default: right for a column of numbers, left otherwise. */\n align?: \"left\" | \"right\" | \"center\"\n}\n\nexport interface DocDataTableProps {\n /** Table title, as a caption above the table. */\n title?: string\n /** Unit or scale, e.g. \"単位: 百万円\". */\n unit?: string\n columns: DocTableColumn[]\n rows: DocTableRow[]\n /** The total row, keyed like `rows`. */\n total?: DocTableRow\n /** Row indexes to set in semibold. */\n highlightRows?: number[]\n footnotes?: { mark: string; text: string }[]\n source?: string\n /** When the data was taken: a date only, e.g. \"2026-10-03\". \"データ時点\" is added here. */\n asOf?: string\n}\n\nconst ALIGN = { left: \"text-left\", right: \"text-right\", center: \"text-center\" } as const\n\nexport function DocDataTable({ title, unit, columns, rows, total, highlightRows, footnotes, source, asOf }: DocDataTableProps) {\n const isNumeric = (col: DocTableColumn) => rows.some((r) => typeof r[col.key] === \"number\")\n const cls = (col: DocTableColumn) => {\n const numeric = isNumeric(col)\n return `${ALIGN[col.align ?? (numeric ? \"right\" : \"left\")]}${numeric ? \" tabular-nums\" : \"\"}`\n }\n const text = (col: DocTableColumn, v: DocTableCell) =>\n typeof v === \"number\" ? formatValue(v, col.format ?? \"number\") : v === null || v === undefined || v === \"\" ? \"—\" : v\n const origin = [source ? `出典: ${source}` : undefined, asOf ? `データ時点 ${asOf}` : undefined].filter(Boolean).join(\" / \")\n const highlighted = new Set(highlightRows)\n\n return (\n <figure data-slot=\"doc-data-table\" className=\"m-0 w-full break-inside-auto\">\n <div className=\"w-full overflow-x-auto\">\n <table className=\"table w-full\">\n {title || unit ? (\n <caption className=\"text-left\">\n {title ? <span className=\"font-semibold\">{title}</span> : null}\n {unit ? <span style={{ color: \"var(--doc-muted)\" }}>{title ? `(${unit})` : unit}</span> : null}\n </caption>\n ) : null}\n <thead>\n <tr>\n {columns.map((col) => (\n <th key={col.key} scope=\"col\" className={cls(col)}>\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, i) => (\n <tr key={i} className={highlighted.has(i) ? \"font-semibold\" : undefined}>\n {columns.map((col) => (\n <td key={col.key} className={cls(col)}>\n {text(col, row[col.key])}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n {total ? (\n <tfoot>\n <tr className=\"font-semibold\">\n {columns.map((col) => (\n <td key={col.key} className={cls(col)}>\n {text(col, total[col.key])}\n </td>\n ))}\n </tr>\n </tfoot>\n ) : null}\n </table>\n </div>\n {footnotes?.length || origin ? (\n <figcaption className=\"flex flex-col gap-0.5 break-inside-avoid text-left\">\n {footnotes?.map((f) => (\n <span key={f.mark}>\n {f.mark} {f.text}\n </span>\n ))}\n {origin ? <span>{origin}</span> : null}\n </figcaption>\n ) : null}\n </figure>\n )\n}\n\nexport default DocDataTable\n","\"use client\"\n\n/**\n * doc-executive-summary — the answer first (BLUF): one conclusion sentence, 3–5 supporting\n * points, and optionally up to 3 headline numbers. One section to put right after the header.\n *\n * - `conclusion` is a sentence that carries the verdict, set in semibold at body size.\n * - `points` is a numbered list. Each is a `string` or a `ReactNode`; Markdown strings are not parsed.\n * - `metrics` (at most 3) are a `dl`. `value` is formatted by `format` (or shown as `display`; null is \"—\").\n * `delta` is the change itself; its direction comes from the sign, and `betterWhen` (\"up\" by default)\n * decides good / bad. The mark ▲▼ and the sign are always printed, so colour is never the only signal.\n * - Only the points and the metric tiles keep together when printed; the section itself may split.\n * - The heading is a bare `h2` / `h3` (`headingLevel`), so the document sets its size.\n *\n * @example\n * import { DocExecutiveSummary } from \"@/blocks/doc-executive-summary/doc-executive-summary\"\n * <DocExecutiveSummary conclusion=\"9 月の売上は計画を上回った。\" points={[\"…\", \"…\", \"…\"]} />\n */\nimport type { ReactNode } from \"react\"\n\nimport { formatValue, type ValueFormat } from \"../../lib/format\"\nimport { DeltaText } from \"../delta-text/delta-text\"\n\nexport interface DocSummaryMetric {\n label: string\n value: number | null\n format?: ValueFormat\n /** Overrides the shown value (e.g. \"約 5,400 万円\"). */\n display?: string\n /** The change from the comparison; direction comes from its sign. Omit for no comparison. */\n delta?: { value: number; format?: ValueFormat }\n /** Name of the comparison, e.g. \"前月比\". Default \"前期比\". */\n comparisonLabel?: string\n /** Which way is good. Default `\"up\"`. */\n betterWhen?: \"up\" | \"down\"\n}\n\nexport interface DocExecutiveSummaryProps {\n /** Heading text. Default \"要旨\". */\n title?: string\n /** `2` directly under the document, `3` inside another section. Default 2. */\n headingLevel?: 2 | 3\n /** The verdict in one sentence. */\n conclusion: ReactNode\n /** 3–5 supporting points, most important first. */\n points: ReactNode[]\n /** Up to 3 headline numbers; any beyond are ignored. */\n metrics?: DocSummaryMetric[]\n}\n\nexport function DocExecutiveSummary({\n title = \"要旨\",\n headingLevel = 2,\n conclusion,\n points,\n metrics,\n}: DocExecutiveSummaryProps) {\n const Heading = headingLevel === 3 ? \"h3\" : \"h2\"\n const shown = (metrics ?? []).slice(0, 3)\n\n return (\n <section data-slot=\"doc-executive-summary\">\n <Heading>{title}</Heading>\n <p className=\"font-semibold\">{conclusion}</p>\n <ol>\n {points.map((point, i) => (\n <li key={i} className=\"break-inside-avoid\">\n {point}\n </li>\n ))}\n </ol>\n {shown.length > 0 ? (\n <dl className=\"grid grid-cols-1 gap-4 sm:grid-cols-3 print:grid-cols-3\">\n {shown.map((m) => (\n <div\n key={m.label}\n className=\"break-inside-avoid border-l-2 pl-3\"\n style={{ borderColor: \"var(--doc-border)\" }}\n >\n <dt style={{ color: \"var(--doc-muted)\" }}>{m.label}</dt>\n <dd className=\"m-0 font-semibold tabular-nums\">{m.display ?? formatValue(m.value, m.format)}</dd>\n {m.delta ? (\n <dd className=\"m-0\">\n <span style={{ color: \"var(--doc-muted)\" }}>{m.comparisonLabel ?? \"前期比\"} </span>\n <DeltaText value={m.delta.value} format={m.delta.format ?? m.format} betterWhen={m.betterWhen} />\n </dd>\n ) : null}\n </div>\n ))}\n </dl>\n ) : null}\n </section>\n )\n}\n\nexport default DocExecutiveSummary\n","\"use client\"\n\n/**\n * doc-figure — the figure convention in one place: a title that states the finding, the unit,\n * the chart (passed as `children`), and a caption with source and notes. The block owns the\n * convention; the chart is yours (any typed chart, an `EChart`, an image).\n *\n * - A real `figure` + `figcaption`, named by its title (`aria-labelledby`); the document's print\n * rule keeps it on one page. Do not give the chart its own `title`: the title is here.\n * - `title` is a sentence that says what the chart shows (\"解約率は 3 か月連続で低下\"), not its\n * subject (\"解約率の推移\"). `unit` goes right under it. `number` prefixes the caption (\"図 1\").\n * - The chart gets the full column (`w-full`); no width is set here.\n * - `source` and `asOf` are first-class: a number without a source and a date is not finished.\n * `asOf` is a date only (\"2026-10-03\"); \"データ時点\" is added here.\n *\n * @example\n * import { DocFigure } from \"@/blocks/doc-figure/doc-figure\"\n * <DocFigure number={1} title=\"解約率は 3 か月連続で低下\" unit=\"単位: %\" source=\"課金システム\" asOf=\"2026-10-03\"><LineChart … /></DocFigure>\n */\nimport { useId, type ReactNode } from \"react\"\n\nexport interface DocFigureProps {\n /** The finding, as a sentence. */\n title: string\n /** Unit or scale, e.g. \"単位: 百万円\". */\n unit?: string\n /** Figure number; shown as \"図 N\" in the caption. */\n number?: number\n /** Where the data comes from. */\n source?: string\n /** When the data was taken: a date only, e.g. \"2026-10-03\". */\n asOf?: string\n /** Footnotes, one per line. */\n notes?: string[]\n /** The chart. */\n children: ReactNode\n}\n\nexport function DocFigure({ title, unit, number, source, asOf, notes, children }: DocFigureProps) {\n const titleId = useId()\n const origin = [source ? `出典: ${source}` : undefined, asOf ? `データ時点 ${asOf}` : undefined].filter(Boolean).join(\" / \")\n const hasCaption = number !== undefined || origin || (notes && notes.length > 0)\n\n return (\n <figure data-slot=\"doc-figure\" aria-labelledby={titleId} className=\"w-full break-inside-avoid\">\n <p id={titleId} className=\"m-0 font-semibold\">{title}</p>\n {unit ? (\n <p className=\"m-0\" style={{ color: \"var(--doc-muted)\" }}>\n {unit}\n </p>\n ) : null}\n <div className=\"w-full\">{children}</div>\n {hasCaption ? (\n <figcaption className=\"flex flex-col gap-0.5 text-left\">\n {number !== undefined ? <span className=\"font-medium\">図 {number}</span> : null}\n {origin ? <span>{origin}</span> : null}\n {notes?.map((note, i) => <span key={i}>{note}</span>)}\n </figcaption>\n ) : null}\n </figure>\n )\n}\n\nexport default DocFigure\n","\"use client\"\n\n/**\n * doc-key-findings — 3–5 findings, each a headline that states the conclusion, the evidence\n * under it, and optionally one number. For the \"what we learned\" section of an analysis.\n *\n * - Each finding is a numbered `h3` (the section heading is `h2`, or `h3` with `headingLevel={3}`\n * when the block sits inside another section — then the findings drop to `h4`).\n * - `headline` is a sentence with a verdict (\"解約は法人プランに集中している\"), not a topic.\n * - `evidence` is a `string` or a `ReactNode`; Markdown strings are not parsed.\n * - The optional `metric` is a number with a change: `delta` is the change itself, its direction comes\n * from the sign, `betterWhen` (\"up\" by default) decides good / bad. The mark ▲▼ and the sign are\n * always printed, so colour is never the only signal.\n *\n * @example\n * import { DocKeyFindings } from \"@/blocks/doc-key-findings/doc-key-findings\"\n * <DocKeyFindings findings={[{ headline: \"新規契約は法人プランが牽引した\", evidence: \"法人プランの新規が前月比 +18%。\" }]} />\n */\nimport type { ReactNode } from \"react\"\n\nimport { formatValue, type ValueFormat } from \"../../lib/format\"\nimport { DeltaText } from \"../delta-text/delta-text\"\n\nexport interface DocFindingMetric {\n label: string\n value: number | null\n format?: ValueFormat\n /** Overrides the shown value. */\n display?: string\n /** The change from the comparison; direction comes from its sign. */\n delta?: { value: number; format?: ValueFormat }\n /** Name of the comparison, e.g. \"前月比\". Default \"前期比\". */\n comparisonLabel?: string\n /** Which way is good. Default `\"up\"`. */\n betterWhen?: \"up\" | \"down\"\n}\n\nexport interface DocFinding {\n /** The conclusion, as a sentence. */\n headline: string\n evidence: ReactNode\n metric?: DocFindingMetric\n}\n\nexport interface DocKeyFindingsProps {\n /** Heading text. Default \"主要な発見\". */\n title?: string\n /** `2` directly under the document, `3` inside another section. Default 2. */\n headingLevel?: 2 | 3\n /** 3–5 findings, most important first. */\n findings: DocFinding[]\n}\n\nexport function DocKeyFindings({ title = \"主要な発見\", headingLevel = 2, findings }: DocKeyFindingsProps) {\n const Heading = headingLevel === 3 ? \"h3\" : \"h2\"\n const Item = headingLevel === 3 ? \"h4\" : \"h3\"\n\n return (\n <section data-slot=\"doc-key-findings\">\n <Heading>{title}</Heading>\n {findings.map((f, i) => (\n <article key={i} className=\"break-inside-avoid\">\n <Item>\n {i + 1}. {f.headline}\n </Item>\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between print:flex-row print:justify-between\">\n <div>{typeof f.evidence === \"string\" ? <p className=\"m-0\">{f.evidence}</p> : f.evidence}</div>\n {f.metric ? (\n <dl className=\"m-0 shrink-0 sm:text-right print:text-right\">\n <dt style={{ color: \"var(--doc-muted)\" }}>{f.metric.label}</dt>\n <dd className=\"m-0 font-semibold tabular-nums\">{f.metric.display ?? formatValue(f.metric.value, f.metric.format)}</dd>\n {f.metric.delta ? (\n <dd className=\"m-0\">\n <span style={{ color: \"var(--doc-muted)\" }}>{f.metric.comparisonLabel ?? \"前期比\"} </span>\n <DeltaText value={f.metric.delta.value} format={f.metric.delta.format ?? f.metric.format} betterWhen={f.metric.betterWhen} />\n </dd>\n ) : null}\n </dl>\n ) : null}\n </div>\n </article>\n ))}\n </section>\n )\n}\n\nexport default DocKeyFindings\n","\"use client\"\n\n/**\n * doc-kpi-scorecard — the key metrics in one place: actual, change from the previous period,\n * progress to target, and a small trend. One section for a monthly report, a QBR or an investor update.\n *\n * - `variant=\"table\"` (default) is a plain `table`: it prints well and each row stays together.\n * `variant=\"grid\"` is a 3-column `dl` of metric tiles for a short list (3–6 metrics).\n * - `value` is formatted by `format` (or shown as `display`); null shows \"—\".\n * - `delta` is the change itself: its direction comes from the sign, `betterWhen` (\"up\" by default;\n * `\"down\"` for churn, cost) decides good / bad. The mark ▲▼ and the sign are always printed, so\n * colour is never the only signal. `comparisonLabel` names it (\"前年同期比\"; default \"前期比\").\n * - `target` is shown in the metric's `format`; the achievement rate (value ÷ target) is computed here.\n * - `trend` is a single series `{ x, y }[]`, drawn as a `Sparkline`; leave it out and the column shows \"—\".\n * - `asOf` (a date only, e.g. \"2026-10-03\") and `source` go in a caption line under the block.\n * - The heading is a bare `h2` / `h3`; the document sets its size. The table fills the column\n * (`w-full`) and scrolls sideways inside its own wrapper when it is too wide.\n *\n * @example\n * import { DocKpiScorecard } from \"@/blocks/doc-kpi-scorecard/doc-kpi-scorecard\"\n * <DocKpiScorecard title=\"主要指標\" asOf=\"2026-10-03\" metrics={[{ label: \"売上\", value: 53_900_000, format: \"currency\", delta: { value: 3_700_000 }, comparisonLabel: \"前月比\", target: 52_000_000 }]} />\n */\nimport { Sparkline } from \"../../charts/sparkline\"\nimport { formatValue, type ValueFormat } from \"../../lib/format\"\nimport { DeltaText } from \"../delta-text/delta-text\"\n\nexport interface DocScorecardMetric {\n label: string\n value: number | null\n format?: ValueFormat\n /** Overrides the shown value. */\n display?: string\n /** The change from the comparison; direction comes from its sign. */\n delta?: { value: number; format?: ValueFormat }\n /** Name of the comparison, e.g. \"前年同期比\". Default \"前期比\". */\n comparisonLabel?: string\n /** Which way is good. Default `\"up\"`. */\n betterWhen?: \"up\" | \"down\"\n /** The target for the period, in the same `format` as `value`. */\n target?: number\n /** One series over time, oldest first; the last one is the current value. */\n trend?: { x: string; y: number }[]\n}\n\nexport interface DocKpiScorecardProps {\n /** Heading text. Default \"主要指標\". */\n title?: string\n /** `2` directly under the document, `3` inside another section. Default 2. */\n headingLevel?: 2 | 3\n metrics: DocScorecardMetric[]\n variant?: \"table\" | \"grid\"\n /** When the numbers were taken: a date only, e.g. \"2026-10-03\". \"データ時点\" is added here. */\n asOf?: string\n source?: string\n}\n\nconst MUTED = { color: \"var(--doc-muted)\" } as const\nconst ACHIEVEMENT: ValueFormat = { type: \"percent\", digits: 1 }\n\nconst shown = (m: DocScorecardMetric) => m.display ?? formatValue(m.value, m.format)\nconst achievement = (m: DocScorecardMetric) =>\n m.target === undefined || m.target === 0 || m.value === null ? \"—\" : formatValue(m.value / m.target, ACHIEVEMENT)\nconst change = (m: DocScorecardMetric) => (m.delta ? <DeltaText value={m.delta.value} format={m.delta.format ?? m.format} betterWhen={m.betterWhen} /> : \"—\")\nconst trendOf = (m: DocScorecardMetric) => (m.trend ?? []).map(({ y }) => ({ value: y }))\n\nexport function DocKpiScorecard({\n title = \"主要指標\",\n headingLevel = 2,\n metrics,\n variant = \"table\",\n asOf,\n source,\n}: DocKpiScorecardProps) {\n const Heading = headingLevel === 3 ? \"h3\" : \"h2\"\n const caption = [source ? `出典: ${source}` : undefined, asOf ? `データ時点 ${asOf}` : undefined].filter(Boolean).join(\" / \")\n const columnLabel = metrics.find((m) => m.comparisonLabel)?.comparisonLabel ?? \"前期比\"\n\n return (\n <section data-slot=\"doc-kpi-scorecard\">\n <Heading>{title}</Heading>\n {variant === \"grid\" ? (\n <dl className=\"m-0 grid grid-cols-1 gap-4 sm:grid-cols-3 print:grid-cols-3\">\n {metrics.map((m) => (\n <div\n key={m.label}\n className=\"break-inside-avoid rounded-md border p-3\"\n style={{ borderColor: \"var(--doc-border)\", background: \"var(--doc-subtle)\" }}\n >\n <dt style={MUTED}>{m.label}</dt>\n <dd className=\"m-0 font-semibold tabular-nums\">{shown(m)}</dd>\n <dd className=\"m-0 flex flex-col gap-0.5\">\n {m.delta ? (\n <span>\n <span style={MUTED}>{m.comparisonLabel ?? \"前期比\"} </span>\n {change(m)}\n </span>\n ) : null}\n {m.target !== undefined ? (\n <span>\n <span style={MUTED}>達成率 </span>\n {achievement(m)}\n <span style={MUTED}>(目標 {formatValue(m.target, m.format)})</span>\n </span>\n ) : null}\n </dd>\n {m.trend && m.trend.length > 1 ? (\n <dd className=\"m-0\">\n <Sparkline data={trendOf(m)} height={28} aria-label={`${m.label}の推移`} />\n </dd>\n ) : null}\n </div>\n ))}\n </dl>\n ) : (\n <div className=\"w-full overflow-x-auto\">\n <table className=\"table w-full\">\n <thead>\n <tr>\n <th scope=\"col\">指標</th>\n <th scope=\"col\" className=\"text-right\">実績</th>\n <th scope=\"col\" className=\"text-right\">{columnLabel}</th>\n <th scope=\"col\" className=\"text-right\">目標</th>\n <th scope=\"col\" className=\"text-right\">達成率</th>\n <th scope=\"col\">推移</th>\n </tr>\n </thead>\n <tbody>\n {metrics.map((m) => (\n <tr key={m.label}>\n <th scope=\"row\" className=\"font-medium\">\n {m.label}\n </th>\n <td className=\"text-right font-semibold tabular-nums\">{shown(m)}</td>\n <td className=\"text-right whitespace-nowrap\">{change(m)}</td>\n <td className=\"text-right tabular-nums\">{m.target === undefined ? \"—\" : formatValue(m.target, m.format)}</td>\n <td className=\"text-right tabular-nums\">{achievement(m)}</td>\n <td>\n {m.trend && m.trend.length > 1 ? (\n <Sparkline data={trendOf(m)} height={24} aria-label={`${m.label}の推移`} />\n ) : (\n \"—\"\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n {caption ? <p style={MUTED}>{caption}</p> : null}\n </section>\n )\n}\n\nexport default DocKpiScorecard\n","\"use client\"\n\n/**\n * doc-report-header — the opening of a document: title, subtitle, and a short fact sheet\n * (period, data as-of, author, source). One section to put directly under `<Document>`.\n *\n * - The only block that owns the `h1`. The rest of the document starts at `h2`.\n * - Typography comes from the document (`h1` / `p`); this block sets no text size and no width.\n * - The fact sheet is a `dl`, so a screen reader reads each label with its value. An empty\n * fact is left out instead of showing \"—\".\n * - `break-inside-avoid` keeps the header on one page when printed.\n *\n * @example\n * import { DocReportHeader } from \"@/blocks/doc-report-header/doc-report-header\"\n * <DocReportHeader title=\"2026 年 9 月 月次事業報告\" period=\"2026-09-01 〜 2026-09-30\" asOf=\"2026-10-03\" />\n */\nimport type { ReactNode } from \"react\"\n\nexport interface DocReportHeaderProps {\n /** The document title (h1). State the subject and the period, not a slogan. */\n title: string\n /** One line under the title, e.g. who the report is for. */\n subtitle?: ReactNode\n /** The period the numbers cover, e.g. \"2026 年 9 月\" or \"2026-07-01 〜 2026-09-30\". */\n period?: string\n /** When the data was taken: a date only, e.g. \"2026-10-03\". Shown under \"データ時点\". */\n asOf?: string\n author?: string\n /** Where the numbers come from, e.g. \"受注管理システム、会計システム\". */\n source?: string\n}\n\nexport function DocReportHeader({ title, subtitle, period, asOf, author, source }: DocReportHeaderProps) {\n const facts: { label: string; value: string }[] = [\n ...(period ? [{ label: \"対象期間\", value: period }] : []),\n ...(asOf ? [{ label: \"データ時点\", value: asOf }] : []),\n ...(author ? [{ label: \"作成者\", value: author }] : []),\n ...(source ? [{ label: \"出典\", value: source }] : []),\n ]\n\n return (\n <header data-slot=\"doc-report-header\" className=\"break-inside-avoid\">\n <h1>{title}</h1>\n {subtitle ? (\n typeof subtitle === \"string\" ? (\n <p style={{ color: \"var(--doc-muted)\" }}>{subtitle}</p>\n ) : (\n <div style={{ color: \"var(--doc-muted)\" }}>{subtitle}</div>\n )\n ) : null}\n {facts.length > 0 ? <dl\n className=\"grid grid-cols-1 gap-x-8 gap-y-2 border-y py-3 sm:grid-cols-2 print:grid-cols-2\"\n style={{ borderColor: \"var(--doc-border)\" }}\n >\n {facts.map((fact) => (\n <div key={fact.label} className=\"flex gap-3\">\n <dt className=\"shrink-0\" style={{ color: \"var(--doc-muted)\" }}>\n {fact.label}\n </dt>\n <dd className=\"m-0 font-medium\">{fact.value}</dd>\n </div>\n ))}\n </dl> : null}\n </header>\n )\n}\n\nexport default DocReportHeader\n","\"use client\"\n\n/**\n * doc-notes-and-sources — the end matter of a document: notes, definitions of terms, and the\n * data sources. One section to put last.\n *\n * - `notes` is a numbered `ol` (\"※\" style notes: provisional figures, exclusions). Each is a\n * `string` or a `ReactNode`; Markdown strings are not parsed.\n * - `definitions` is a `dl` of term / description pairs (\"解約率: 月初契約数に対する…\").\n * - `sources` is a `ul` of \"name(データ時点 asOf)\"; `asOf` is a date only, e.g. \"2026-10-03\".\n * - A part with nothing in it is not drawn; with all three empty the block renders nothing.\n * - The headings are bare (`headingLevel` 2 or 3, the sub-parts one level lower); the document sets\n * their size, and no size is set here.\n *\n * @example\n * import { DocNotesAndSources } from \"@/blocks/doc-notes-and-sources/doc-notes-and-sources\"\n * <DocNotesAndSources notes={[\"9 月の数値は速報値です。\"]} definitions={[{ term: \"解約率\", description: \"月初契約数に対する当月解約数の割合。\" }]} sources={[{ name: \"契約管理 DB\", asOf: \"2026-10-03\" }]} />\n */\nimport type { ReactNode } from \"react\"\n\nexport interface DocDefinition {\n term: string\n description: ReactNode\n}\n\nexport interface DocSource {\n name: string\n /** Data as-of date, e.g. \"2026-10-03\". */\n asOf?: string\n}\n\nexport interface DocNotesAndSourcesProps {\n /** Heading text. Default \"注記・出典\". */\n title?: string\n /** `2` directly under the document, `3` inside another section. Default 2. */\n headingLevel?: 2 | 3\n notes?: ReactNode[]\n definitions?: DocDefinition[]\n sources?: DocSource[]\n}\n\nexport function DocNotesAndSources({ title = \"注記・出典\", headingLevel = 2, notes = [], definitions = [], sources = [] }: DocNotesAndSourcesProps) {\n if (notes.length === 0 && definitions.length === 0 && sources.length === 0) return null\n const Heading = headingLevel === 3 ? \"h3\" : \"h2\"\n const Sub = headingLevel === 3 ? \"h4\" : \"h3\"\n\n return (\n <section data-slot=\"doc-notes-and-sources\">\n <Heading>{title}</Heading>\n {notes.length > 0 ? (\n <div className=\"break-inside-avoid\">\n <Sub>注記</Sub>\n <ol>\n {notes.map((n, i) => (\n <li key={i}>{n}</li>\n ))}\n </ol>\n </div>\n ) : null}\n {definitions.length > 0 ? (\n <div className=\"break-inside-avoid\">\n <Sub>用語の定義</Sub>\n <dl className=\"m-0\">\n {definitions.map((d, i) => (\n <div key={i} className=\"break-inside-avoid\">\n <dt className=\"font-semibold\">{d.term}</dt>\n <dd className=\"m-0\">{d.description}</dd>\n </div>\n ))}\n </dl>\n </div>\n ) : null}\n {sources.length > 0 ? (\n <div className=\"break-inside-avoid\">\n <Sub>出典</Sub>\n <ul>\n {sources.map((s, i) => (\n <li key={i}>\n {s.name}\n {s.asOf ? <span style={{ color: \"var(--doc-muted)\" }}>(データ時点 {s.asOf})</span> : null}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n </section>\n )\n}\n\nexport default DocNotesAndSources\n"]}