@squadbase/vantage 0.6.2-dev1.d594c56 → 0.6.2-dev1.e333781

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 (202) hide show
  1. package/dist/{build-X5NVCQKT.js → build-YOPOGPQB.js} +7 -7
  2. package/dist/{build-X5NVCQKT.js.map → build-YOPOGPQB.js.map} +1 -1
  3. package/dist/{check-ZBIH422T.js → check-FBHT6W6J.js} +5 -5
  4. package/dist/{check-ZBIH422T.js.map → check-FBHT6W6J.js.map} +1 -1
  5. package/dist/chunk-2IAPIOPS.js +152 -0
  6. package/dist/chunk-2IAPIOPS.js.map +1 -0
  7. package/dist/chunk-57GHR5LN.js +163 -0
  8. package/dist/chunk-57GHR5LN.js.map +1 -0
  9. package/dist/{chunk-7DZGJQ3P.js → chunk-5C2SEDPH.js} +21 -4
  10. package/dist/chunk-5C2SEDPH.js.map +1 -0
  11. package/dist/chunk-6OTTGAPO.js +44 -0
  12. package/dist/chunk-6OTTGAPO.js.map +1 -0
  13. package/dist/{chunk-2ICNHUG6.js → chunk-7652CGJJ.js} +10 -3
  14. package/dist/{chunk-2ICNHUG6.js.map → chunk-7652CGJJ.js.map} +1 -1
  15. package/dist/{chunk-XPQSTZUU.js → chunk-7S52M2SL.js} +4 -3
  16. package/dist/chunk-7S52M2SL.js.map +1 -0
  17. package/dist/chunk-JXFCSF3K.js +673 -0
  18. package/dist/chunk-JXFCSF3K.js.map +1 -0
  19. package/dist/{chunk-HKSVYMYJ.js → chunk-QOXXOFGL.js} +61 -929
  20. package/dist/chunk-QOXXOFGL.js.map +1 -0
  21. package/dist/{chunk-WAMZWZJB.js → chunk-R6MTJAHX.js} +6 -6
  22. package/dist/chunk-R6MTJAHX.js.map +1 -0
  23. package/dist/{chunk-CEXAQQ5W.js → chunk-S5MDTHH7.js} +180 -18
  24. package/dist/chunk-S5MDTHH7.js.map +1 -0
  25. package/dist/{chunk-JKLLFVEU.js → chunk-UWSQUHX6.js} +4 -99
  26. package/dist/chunk-UWSQUHX6.js.map +1 -0
  27. package/dist/cli.js +6 -6
  28. package/dist/components/index.d.ts +11 -247
  29. package/dist/components/index.js +5 -2
  30. package/dist/delta-text-CvwBGJ95.d.ts +15 -0
  31. package/dist/{dev-4XEDTELV.js → dev-GUKQT6U6.js} +7 -7
  32. package/dist/{dev-4XEDTELV.js.map → dev-GUKQT6U6.js.map} +1 -1
  33. package/dist/doc/index.d.ts +215 -2
  34. package/dist/doc/index.js +307 -3
  35. package/dist/doc/index.js.map +1 -1
  36. package/dist/{doctor-5E2VEZPK.js → doctor-B2O3GJDU.js} +5 -5
  37. package/dist/{doctor-5E2VEZPK.js.map → doctor-B2O3GJDU.js.map} +1 -1
  38. package/dist/format-U0cQl069.d.ts +243 -0
  39. package/dist/{routes-3SGAFDMC.js → routes-PVKNT777.js} +4 -4
  40. package/dist/{routes-3SGAFDMC.js.map → routes-PVKNT777.js.map} +1 -1
  41. package/dist/slide/index.d.ts +272 -1
  42. package/dist/slide/index.js +972 -2
  43. package/dist/slide/index.js.map +1 -1
  44. package/dist/table/index.js +5 -2
  45. package/dist/table/index.js.map +1 -1
  46. package/dist/ui/index.d.ts +4 -1
  47. package/dist/ui/index.js +3 -3
  48. package/dist/ui/index.js.map +1 -1
  49. package/dist/{upgrade-JHXZBGQS.js → upgrade-7ZXMCTTR.js} +4 -4
  50. package/dist/{upgrade-JHXZBGQS.js.map → upgrade-7ZXMCTTR.js.map} +1 -1
  51. package/dist/vite/index.js +3 -3
  52. package/docs/en/changelog.md +2 -0
  53. package/docs/en/components.md +13 -2
  54. package/docs/en/doc/delta-text.md +40 -0
  55. package/docs/en/doc/doc-action-items.md +49 -0
  56. package/docs/en/doc/doc-callout.md +38 -0
  57. package/docs/en/doc/doc-data-table.md +60 -0
  58. package/docs/en/doc/doc-executive-summary.md +64 -0
  59. package/docs/en/doc/doc-figure.md +56 -0
  60. package/docs/en/doc/doc-key-findings.md +61 -0
  61. package/docs/en/doc/doc-kpi-scorecard.md +80 -0
  62. package/docs/en/doc/doc-notes-and-sources.md +43 -0
  63. package/docs/en/doc/doc-report-header.md +46 -0
  64. package/docs/en/pages-and-metadata.md +15 -0
  65. package/docs/en/parts/area-chart.md +99 -0
  66. package/docs/en/parts/bar-chart.md +91 -0
  67. package/docs/en/parts/bar-list.md +50 -0
  68. package/docs/en/parts/category-bar.md +37 -0
  69. package/docs/en/parts/chart-frame.md +39 -0
  70. package/docs/en/parts/delta.md +4 -3
  71. package/docs/en/parts/donut-chart.md +72 -0
  72. package/docs/en/parts/funnel-steps.md +2 -1
  73. package/docs/en/parts/heatmap.md +53 -0
  74. package/docs/en/parts/kpi-card.md +2 -1
  75. package/docs/en/parts/legend.md +35 -0
  76. package/docs/en/parts/line-chart.md +94 -0
  77. package/docs/en/parts/progress-circle.md +33 -0
  78. package/docs/en/parts/sample-data.md +39 -0
  79. package/docs/en/parts/scatter-chart.md +56 -0
  80. package/docs/en/parts/tracker.md +36 -0
  81. package/docs/en/parts/updated-at.md +30 -0
  82. package/docs/en/parts/waterfall-chart.md +56 -0
  83. package/docs/en/slide/slide-chart-full.md +48 -0
  84. package/docs/en/slide/slide-chart-insight.md +52 -0
  85. package/docs/en/slide/slide-columns.md +46 -0
  86. package/docs/en/slide/slide-comparison.md +68 -0
  87. package/docs/en/slide/slide-cover.md +39 -0
  88. package/docs/en/slide/slide-exec-summary.md +47 -0
  89. package/docs/en/slide/slide-heading.md +38 -0
  90. package/docs/en/slide/slide-kpi-grid.md +55 -0
  91. package/docs/en/slide/slide-kpi-hero.md +58 -0
  92. package/docs/en/slide/slide-next-actions.md +49 -0
  93. package/docs/en/slide/slide-scorecard-table.md +54 -0
  94. package/docs/en/slide/slide-section.md +44 -0
  95. package/docs/en/slide/slide-source-line.md +34 -0
  96. package/docs/en/ui/alert-dialog.md +42 -0
  97. package/docs/en/ui/avatar.md +31 -0
  98. package/docs/en/ui/combobox.md +74 -0
  99. package/docs/en/ui/drawer.md +41 -0
  100. package/docs/en/ui/empty.md +1 -1
  101. package/docs/en/ui/error-state.md +4 -3
  102. package/docs/en/ui/field.md +42 -0
  103. package/docs/en/ui/hover-card.md +21 -0
  104. package/docs/en/ui/kbd.md +17 -0
  105. package/docs/en/ui/loading.md +1 -1
  106. package/docs/en/ui/pagination.md +36 -0
  107. package/docs/en/ui/radio-group.md +21 -0
  108. package/docs/en/ui/toast.md +44 -0
  109. package/docs/en/ui/toggle-group.md +4 -3
  110. package/docs/index.json +857 -77
  111. package/docs/ja/changelog.md +2 -0
  112. package/docs/ja/components.md +12 -1
  113. package/docs/ja/doc/delta-text.md +40 -0
  114. package/docs/ja/doc/doc-action-items.md +49 -0
  115. package/docs/ja/doc/doc-callout.md +38 -0
  116. package/docs/ja/doc/doc-data-table.md +60 -0
  117. package/docs/ja/doc/doc-executive-summary.md +64 -0
  118. package/docs/ja/doc/doc-figure.md +56 -0
  119. package/docs/ja/doc/doc-key-findings.md +61 -0
  120. package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
  121. package/docs/ja/doc/doc-notes-and-sources.md +43 -0
  122. package/docs/ja/doc/doc-report-header.md +46 -0
  123. package/docs/ja/page-types/slide.md +1 -0
  124. package/docs/ja/pages-and-metadata.md +15 -0
  125. package/docs/ja/parts/area-chart.md +49 -25
  126. package/docs/ja/parts/bar-chart.md +50 -24
  127. package/docs/ja/parts/bar-list.md +31 -8
  128. package/docs/ja/parts/chart-frame.md +36 -0
  129. package/docs/ja/parts/delta.md +5 -4
  130. package/docs/ja/parts/donut-chart.md +45 -26
  131. package/docs/ja/parts/funnel-steps.md +27 -8
  132. package/docs/ja/parts/heatmap.md +45 -0
  133. package/docs/ja/parts/kpi-card.md +2 -1
  134. package/docs/ja/parts/legend.md +36 -0
  135. package/docs/ja/parts/line-chart.md +48 -22
  136. package/docs/ja/parts/sample-data.md +61 -0
  137. package/docs/ja/parts/scatter-chart.md +69 -0
  138. package/docs/ja/parts/updated-at.md +27 -0
  139. package/docs/ja/parts/waterfall-chart.md +61 -0
  140. package/docs/ja/slide/slide-chart-full.md +48 -0
  141. package/docs/ja/slide/slide-chart-insight.md +52 -0
  142. package/docs/ja/slide/slide-columns.md +46 -0
  143. package/docs/ja/slide/slide-comparison.md +68 -0
  144. package/docs/ja/slide/slide-cover.md +39 -0
  145. package/docs/ja/slide/slide-exec-summary.md +47 -0
  146. package/docs/ja/slide/slide-heading.md +38 -0
  147. package/docs/ja/slide/slide-kpi-grid.md +55 -0
  148. package/docs/ja/slide/slide-kpi-hero.md +58 -0
  149. package/docs/ja/slide/slide-next-actions.md +49 -0
  150. package/docs/ja/slide/slide-scorecard-table.md +54 -0
  151. package/docs/ja/slide/slide-section.md +44 -0
  152. package/docs/ja/slide/slide-source-line.md +34 -0
  153. package/docs/ja/ui/empty.md +1 -1
  154. package/docs/ja/ui/error-state.md +4 -3
  155. package/docs/ja/ui/loading.md +1 -1
  156. package/docs/ja/ui/toggle-group.md +4 -3
  157. package/package.json +2 -2
  158. package/registry/ui/area-chart.tsx +88 -26
  159. package/registry/ui/attention-list.tsx +303 -0
  160. package/registry/ui/bar-chart.tsx +88 -26
  161. package/registry/ui/bar-list.tsx +87 -24
  162. package/registry/ui/box-plot-chart.tsx +3906 -0
  163. package/registry/ui/category-bar.tsx +54 -19
  164. package/registry/ui/chart-frame.tsx +56 -21
  165. package/registry/ui/dashboard-card.tsx +2 -2
  166. package/registry/ui/delta.tsx +11 -8
  167. package/registry/ui/donut-chart.tsx +89 -26
  168. package/registry/ui/echart.tsx +194 -44
  169. package/registry/ui/funnel-steps.tsx +33 -5
  170. package/registry/ui/heatmap.tsx +55 -21
  171. package/registry/ui/histogram-chart.tsx +3986 -0
  172. package/registry/ui/kpi-card.tsx +41 -14
  173. package/registry/ui/legend.tsx +87 -24
  174. package/registry/ui/line-chart.tsx +88 -26
  175. package/registry/ui/page-shell.tsx +9 -9
  176. package/registry/ui/paired-chart.tsx +3827 -0
  177. package/registry/ui/sample-data.tsx +1 -1
  178. package/registry/ui/scatter-chart.tsx +88 -26
  179. package/registry/ui/section-header.tsx +2 -2
  180. package/registry/ui/slider.tsx +1 -1
  181. package/registry/ui/status-badge.tsx +8 -8
  182. package/registry/ui/tooltip.tsx +6 -2
  183. package/registry/ui/tracker.tsx +9 -3
  184. package/registry/ui/trend-indicator.tsx +2 -2
  185. package/registry/ui/waterfall-chart.tsx +88 -26
  186. package/skills/vantage-design/SKILL.md +27 -25
  187. package/skills/vantage-design/references/extract.md +16 -14
  188. package/skills/vantage-design/references/format.md +6 -5
  189. package/skills/vantage-design/references/presets.md +60 -110
  190. package/skills/vantage-pitfalls/SKILL.md +5 -0
  191. package/skills/vantage-slide/SKILL.md +54 -36
  192. package/templates/AGENTS.md +4 -2
  193. package/templates/agents/doc.md +48 -0
  194. package/templates/agents/page.md +22 -1
  195. package/templates/agents/slide.md +70 -2
  196. package/theme.css +16 -15
  197. package/dist/chunk-7DZGJQ3P.js.map +0 -1
  198. package/dist/chunk-CEXAQQ5W.js.map +0 -1
  199. package/dist/chunk-HKSVYMYJ.js.map +0 -1
  200. package/dist/chunk-JKLLFVEU.js.map +0 -1
  201. package/dist/chunk-WAMZWZJB.js.map +0 -1
  202. package/dist/chunk-XPQSTZUU.js.map +0 -1
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Locale-aware number formatting shared by KPI cards, tables and charts. All
3
+ * shortening is delegated to `Intl.NumberFormat` (`notation: "compact"`); this
4
+ * module never hard-codes unit thresholds or unit strings.
5
+ *
6
+ * | `format` | input | ja-JP output |
7
+ * |--------------------------------------------|--------------|----------------|
8
+ * | `"compact"` (default) | `48_200_000` | `4,820万` |
9
+ * | `"number"` | `1234.567` | `1,234.57` |
10
+ * | `"currency"` (JPY, compact) | `48_200_000` | `¥4,820万` |
11
+ * | `{ type: "currency", notation: "standard" }` | `48_200_000` | `¥48,200,000` |
12
+ * | `{ type: "currency", currency: "USD" }` | `1234.5` | `$1,234.5` |
13
+ * | `"percent"` — pass a **ratio** | `0.124` | `12.4%` |
14
+ * | `{ type: "percent", digits: 0 }` | `0.124` | `12%` |
15
+ * | `"multiple"` | `1.5` | `1.5×` |
16
+ * | `{ type: "number", unit: "件" }` | `48_210` | `48,210件` |
17
+ * | `{ type: "compact", unit: "人" }` | `12_345` | `1.2万人` |
18
+ * | `"duration"` — pass **seconds** | `12_000` | `3時間20分` |
19
+ * | `{ type: "duration", durationUnit: "minute" }` | `2160` | `1.5日` |
20
+ *
21
+ * - `percent` takes a ratio (0.124 → 12.4%). Passing 12.4 renders 1,240%. The fraction
22
+ * digits are **fixed**, never trimmed (`PERCENT_DIGITS` = 1: 0.14 → "14.0%", never "14%"
23
+ * beside "11.9%"). Pass `digits` in the format to share another count across cards.
24
+ * - A minus sign is always U+2212 (`MINUS_SIGN`, "−1,234" / "−5.0%"), never the hyphen-minus.
25
+ * - `currency` defaults to JPY and to compact notation (万・億 in ja); pass
26
+ * `notation: "standard"` for every digit (tables, invoices). In ja-JP the yen
27
+ * sign is the half-width `¥`.
28
+ * - `unit` is a counter appended right after the number, with no space
29
+ * ("48,210件", "1.2万人"), for `number` / `compact` / `currency`. It is
30
+ * ignored for `percent` and `duration`, and for `multiple` it replaces the
31
+ * default `×` ("2.7倍"). Do not write it into a `valueFormatter` by hand.
32
+ * - Charts take the same `format` a KpiCard takes (`format="currency"`).
33
+ * `toValueFormatter(format)` turns it into a function for places that need
34
+ * one (a `valueFormatter`, table cells).
35
+ * - Missing values (null / undefined / NaN) render as `—` (`EMPTY_VALUE`).
36
+ * - Dates go through `formatDate` (`Intl.DateTimeFormat`): `"date"` → `2026/10/20`,
37
+ * `"datetime"` → `2026/10/20 14:30`, `"year-month"` → `2026年10月`, `"month"` → `10月`,
38
+ * `"year"` → `2026年`.
39
+ * - A period goes through `formatDateRange`: `2026/9/23〜10/20` (same year drops the end year),
40
+ * `2025/12/20〜2026/1/18` across years; month and day are not zero-padded.
41
+ */
42
+ /**
43
+ * The kind of number a value is. Pick by what the number means, not by how
44
+ * long it is: `currency` for money, `percent` for a ratio, `multiple` for a
45
+ * factor ("1.5×"), `duration` for a length of time ("3時間20分"), `number` for
46
+ * exact counts in tables, `compact` (default) for large headline counts (万・億).
47
+ */
48
+ type FormatKind = "number" | "compact" | "currency" | "percent" | "multiple" | "duration";
49
+ /** The unit a `duration` value is measured in. */
50
+ type DurationUnit = "second" | "minute" | "hour" | "day";
51
+ /**
52
+ * How to display a number: a `FormatKind` alone, or an object for digits,
53
+ * currency, notation and a counter. The same value is accepted by KpiCard,
54
+ * Delta, the charts (`format`) and `formatValue`.
55
+ *
56
+ * @example
57
+ * "currency" // ¥4,820万
58
+ * { type: "currency", notation: "standard" } // ¥48,200,000
59
+ * { type: "percent", digits: 1 } // 2.0%
60
+ * { type: "number", unit: "件" } // 48,210件
61
+ */
62
+ type ValueFormat = FormatKind | {
63
+ type: FormatKind;
64
+ /** Fixed number of fraction digits. */
65
+ digits?: number;
66
+ /** ISO 4217 code for `currency`. Default `"JPY"`. */
67
+ currency?: string;
68
+ /** `currency` only: `"compact"` (default, 万・億) or `"standard"` (every digit). */
69
+ notation?: "compact" | "standard";
70
+ /** Counter appended after the number, e.g. `"件"`, `"人"`. Ignored for `percent` and `duration`. For `multiple` it replaces the default `×` (`"倍"` → `2.7倍`). */
71
+ unit?: string;
72
+ /** 値をこの数で割ってから整形する。例: `divisor: 100`(セント → ドル)。0 と非有限は無視。 */
73
+ divisor?: number;
74
+ /** `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). */
75
+ durationUnit?: DurationUnit;
76
+ };
77
+ /** Locale used when none is passed. Every function here takes a `locale` to override it. */
78
+ declare const DEFAULT_LOCALE = "ja-JP";
79
+ /** Shown in place of a missing value (null / undefined / NaN). */
80
+ declare const EMPTY_VALUE = "\u2014";
81
+ /** The minus sign every formatter writes (U+2212), so a negative never mixes with a hyphen-minus. */
82
+ declare const MINUS_SIGN = "\u2212";
83
+ /** Extra options for `formatValue`. */
84
+ interface FormatValueOptions {
85
+ /** `"auto"` (default) signs negatives only; `"exceptZero"` also writes `+` on positives (for differences). */
86
+ signDisplay?: "auto" | "exceptZero";
87
+ /** Round to this many significant digits (e.g. 3 for an estimate: 79,653,985 → 7,970万). */
88
+ significantDigits?: number;
89
+ }
90
+ /**
91
+ * The kind of a format, whether it was given as a string or an object. Use it
92
+ * to branch on the meaning of a metric (e.g. a `percent` metric compares in
93
+ * points) without unpacking `ValueFormat` yourself.
94
+ *
95
+ * @param format - The format as a KpiCard / chart takes it. `undefined` means the default.
96
+ * @returns The `FormatKind`; `"compact"` when `format` is omitted.
97
+ *
98
+ * @example
99
+ * formatKind("percent") // "percent"
100
+ * formatKind({ type: "currency", notation: "standard" }) // "currency"
101
+ * formatKind(undefined) // "compact"
102
+ */
103
+ declare function formatKind(format: ValueFormat | undefined): FormatKind;
104
+ /**
105
+ * Format a number for display — KPI values, table cells, chart labels and
106
+ * sentences built from data (titles, summaries). See the table at the top of
107
+ * this module.
108
+ *
109
+ * @param value - The number. `null` / `undefined` / `NaN` render as `—`.
110
+ * For `percent`, a ratio (0.124 means 12.4%).
111
+ * @param format - How to display it. Default `"compact"`.
112
+ * @param locale - BCP 47 locale. Default `"ja-JP"`.
113
+ * @param options - `signDisplay` and `significantDigits` (rounding for estimates).
114
+ * @returns The display string. In ja-JP the yen sign is the half-width `¥`.
115
+ *
116
+ * @example
117
+ * formatValue(48_200_000, "currency") // "¥4,820万"
118
+ * formatValue(48_200_000, { type: "currency", notation: "standard" }) // "¥48,200,000"
119
+ * formatValue(0.021, "percent") // "2.1%"
120
+ * formatValue(0.124, "percent", "ja-JP", { signDisplay: "exceptZero" }) // "+12.4%"
121
+ * formatValue(79_653_985, "currency", "ja-JP", { significantDigits: 3 }) // "¥7,970万"
122
+ * formatValue(48_210, { type: "number", unit: "件" }) // "48,210件"
123
+ * formatValue(1.5, "multiple") // "1.5×"
124
+ * formatValue(null) // "—"
125
+ */
126
+ declare function formatValue(value: number | null | undefined, format?: ValueFormat, locale?: string, options?: FormatValueOptions): string;
127
+ /**
128
+ * Like `formatValue`, but always signed (except zero) — for a difference
129
+ * between two values ("+¥530万", "−120件"). Use `formatPoints` instead for a
130
+ * difference between two rates.
131
+ *
132
+ * @param value - The difference (current − previous). Missing values render as `—`.
133
+ * @param format - Format of the metric itself. Default `"compact"`.
134
+ * @param locale - BCP 47 locale. Default `"ja-JP"`.
135
+ * @returns The signed display string; zero has no sign.
136
+ *
137
+ * @example
138
+ * formatDelta(5_300_000, "currency") // "+¥530万"
139
+ * formatDelta(-120, { type: "number", unit: "件" }) // "−120件"
140
+ * formatDelta(0.031, "percent") // "+3.1%"
141
+ * formatDelta(0, "currency") // "¥0"
142
+ */
143
+ declare function formatDelta(value: number | null | undefined, format?: ValueFormat, locale?: string): string;
144
+ /**
145
+ * A difference between two rates in percentage points, always signed:
146
+ * `formatPoints(0.021 - 0.026)` → `"−0.5pt"`. Use it instead of a relative
147
+ * change for rate metrics (churn, conversion), where "−19.2%" reads as a drop
148
+ * of nineteen points. `signDisplay: "never"` drops the sign ("あと 0.5pt").
149
+ *
150
+ * @param difference - The difference of two **ratios** (0.021 − 0.026). Missing values render as `—`.
151
+ * @param locale - BCP 47 locale. Default `"ja-JP"`.
152
+ * @param options - `digits`: fixed fraction digits (default `PERCENT_DIGITS` = 1, so "0.0pt" / "+0.5pt"); `signDisplay`:
153
+ * `"exceptZero"` (default) or `"never"` when the sentence already says the direction.
154
+ * @returns The difference in points with the `pt` suffix.
155
+ *
156
+ * @example
157
+ * formatPoints(0.021 - 0.026) // "−0.5pt"
158
+ * formatPoints(0.031 - 0.026) // "+0.5pt"
159
+ * formatPoints(0.02 - 0.015, "ja-JP", { signDisplay: "never" }) // "0.5pt"(「目標まであと 0.5pt」)
160
+ */
161
+ declare function formatPoints(difference: number | null | undefined, locale?: string, options?: {
162
+ digits?: number;
163
+ signDisplay?: "exceptZero" | "never";
164
+ }): string;
165
+ /**
166
+ * Binds a format and locale into a single-argument formatter, for a chart
167
+ * `valueFormatter` or a table cell: `valueFormatter={toValueFormatter("currency")}`.
168
+ * Prefer passing `format` to the chart directly; this is for APIs that only
169
+ * take a function.
170
+ *
171
+ * @param format - How to display each value. Default `"compact"`.
172
+ * @param locale - BCP 47 locale. Default `"ja-JP"`.
173
+ * @returns `(value) => string`, rendering missing values as `—`.
174
+ *
175
+ * @example
176
+ * const yen = toValueFormatter("currency")
177
+ * yen(48_200_000) // "¥4,820万"
178
+ * yen(null) // "—"
179
+ * const count = toValueFormatter({ type: "number", unit: "件" })
180
+ * count(48_210) // "48,210件"(表のセル)
181
+ */
182
+ declare function toValueFormatter(format?: ValueFormat, locale?: string): (value: number | null | undefined) => string;
183
+ /**
184
+ * 日付の書式。何を表す日付かで選ぶ: 日単位は `"date"`、時刻まで要るなら `"datetime"`、
185
+ * 月次の集計は `"year-month"`(年をまたぐ軸)か `"month"`(同じ年の中の軸)、年次は `"year"`。
186
+ */
187
+ type DateStyle = "date" | "datetime" | "month" | "year-month" | "year";
188
+ /** `formatDate` の追加オプション。 */
189
+ interface FormatDateOptions {
190
+ /**
191
+ * IANA のタイムゾーン名(例: `"Asia/Tokyo"`)。既定は実行環境のタイムゾーン。
192
+ * サーバーとブラウザで描画が食い違う(SSR)なら固定する。日付だけの文字列(`"2026-10-20"`)には効かず、常にその暦日のまま出す。
193
+ */
194
+ timeZone?: string;
195
+ }
196
+ /**
197
+ * 日付を表示用の文字列にする。表のセル・タイトル・文に埋める日付に使い、`toLocaleString` や手組みの
198
+ * `getMonth() + 1` は使わない。
199
+ *
200
+ * @param value - `Date`、エポックミリ秒、または日付文字列(`"2026-10-20"`、ISO 8601)。`null` / `undefined` / 解釈できない値は `—`。
201
+ * @param style - 何を表す日付か。既定 `"date"`。
202
+ * @param locale - BCP 47 ロケール。既定 `"ja-JP"`。
203
+ * @param options - `timeZone`。
204
+ * @returns 表示文字列。
205
+ *
206
+ * @example
207
+ * formatDate("2026-10-20") // "2026/10/20"
208
+ * formatDate(new Date("2026-10-20T05:30:00Z"), "datetime", "ja-JP", { timeZone: "Asia/Tokyo" }) // "2026/10/20 14:30"
209
+ * formatDate("2026-10-01", "year-month") // "2026年10月"
210
+ * formatDate("2026-10-01", "month") // "10月"
211
+ * formatDate(null) // "—"
212
+ */
213
+ declare function formatDate(value: Date | string | number | null | undefined, style?: DateStyle, locale?: string, options?: FormatDateOptions): string;
214
+ /** `formatDateRange` のオプション。 */
215
+ interface FormatDateRangeOptions extends FormatDateOptions {
216
+ /** BCP 47 ロケール。既定 `"ja-JP"`。 */
217
+ locale?: string;
218
+ }
219
+ /**
220
+ * 期間を「2026/9/23〜10/20」の形にする。同じ年なら終了側の年を省き、年をまたぐときは両方に付ける。
221
+ * 月日はゼロ詰めしない。区切りは日本語で「〜」、それ以外のロケールでは「 – 」。始まりと終わりが同じ日なら 1 日だけ出す。
222
+ *
223
+ * @param start - 期間の最初の日(`Date`、エポックミリ秒、日付文字列)。`"2026-09-23"` のような日付だけの文字列はその暦日のまま出す。
224
+ * @param end - 期間の最後の日。
225
+ * @param options - `locale` と `timeZone`。
226
+ * @returns 表示文字列。どちらかが解釈できなければ `—`。
227
+ *
228
+ * @example
229
+ * formatDateRange("2026-09-23", "2026-10-20") // "2026/9/23〜10/20"
230
+ * formatDateRange("2025-12-20", "2026-01-18") // "2025/12/20〜2026/1/18"
231
+ */
232
+ declare function formatDateRange(start: Date | string | number | null | undefined, end: Date | string | number | null | undefined, options?: FormatDateRangeOptions): string;
233
+ /**
234
+ * 文中の ISO の年月・日付(`2023-04`、`2026-10-20`)を `formatDate` の書式に置き換える。期間や出典の注記のように、
235
+ * 利用者が文字列で渡す文に日付が混ざるときの表示用(`"2023-04 以降"` → `"2023年4月 以降"`)。日付でない数字は触らない。
236
+ *
237
+ * @param text - 日付を含みうる文。
238
+ * @param locale - BCP 47 ロケール。既定 `"ja-JP"`。
239
+ * @returns ISO の年月は `"year-month"`、年月日は `"date"` で整形した文。
240
+ */
241
+ declare function formatDatesInText(text: string, locale?: string): string;
242
+
243
+ export { DEFAULT_LOCALE as D, EMPTY_VALUE as E, type FormatDateOptions as F, MINUS_SIGN as M, type ValueFormat as V, type DateStyle as a, type FormatKind as b, type FormatValueOptions as c, formatDateRange as d, formatDatesInText as e, formatDate as f, formatDelta as g, formatKind as h, formatPoints as i, formatValue as j, toValueFormatter as t };
@@ -1,5 +1,5 @@
1
- import { extractPageSpec, extractApiSpec } from './chunk-JKLLFVEU.js';
2
- import './chunk-CEXAQQ5W.js';
1
+ import { extractPageSpec, extractApiSpec } from './chunk-UWSQUHX6.js';
2
+ import './chunk-S5MDTHH7.js';
3
3
  import { scanProject } from './chunk-RNTDBX6S.js';
4
4
  import { printJson } from './chunk-GNXCX4WE.js';
5
5
  import './chunk-C2CX6GLX.js';
@@ -124,5 +124,5 @@ async function routes(root, args) {
124
124
  }
125
125
 
126
126
  export { routes };
127
- //# sourceMappingURL=routes-3SGAFDMC.js.map
128
- //# sourceMappingURL=routes-3SGAFDMC.js.map
127
+ //# sourceMappingURL=routes-PVKNT777.js.map
128
+ //# sourceMappingURL=routes-PVKNT777.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/routes.ts"],"names":[],"mappings":";;;;;;;;AAYA,IAAM,YAAA,GAAe,EAAA;AACrB,IAAM,YAAA,GAAe,CAAA;AAGrB,SAAS,UAAA,CAAW,MAAA,EAAgB,KAAA,EAAe,KAAA,EAAqB;AACtE,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,EAAA,CAAG,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,YAAY,CAAC,CAAC,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AACtE;AAGA,SAAS,aAAa,MAAA,EAA8B;AAClD,EAAA,OAAO,OAAO,GAAA,CAAI,CAAC,CAAA,KAAO,CAAA,CAAE,SAAS,UAAA,GAAa,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,KAAK,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,CAAA,CAAG,CAAA,CAAE,KAAK,IAAI,CAAA;AAC3F;AAEA,SAAS,WAAW,IAAA,EAAoC;AACtD,EAAA,OAAO,MAAM,MAAA,GAAS,CAAA,GAAA,EAAM,KAAK,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,CAAA,GAAO,EAAA;AACpD;AAEA,SAAS,cAAc,IAAA,EAAsB;AAC3C,EAAA,MAAM,MAAA,GAAS,QAAA;AACf,EAAA,IAAI,KAAK,KAAA,EAAO,UAAA,CAAW,MAAA,EAAQ,OAAA,EAAS,KAAK,KAAK,CAAA;AACtD,EAAA,IAAI,KAAK,QAAA,EAAU,UAAA,CAAW,MAAA,EAAQ,KAAA,EAAO,KAAK,QAAQ,CAAA;AAC1D,EAAA,IAAI,KAAK,WAAA,EAAa,UAAA,CAAW,MAAA,EAAQ,MAAA,EAAQ,KAAK,WAAW,CAAA;AACjE,EAAA,IAAI,IAAA,CAAK,OAAO,MAAA,EAAQ,UAAA,CAAW,QAAQ,QAAA,EAAU,YAAA,CAAa,IAAA,CAAK,MAAM,CAAC,CAAA;AAChF;AAEA,SAAS,kBAAA,CAAmB,QAAuB,MAAA,EAA4B;AAC7E,EAAA,MAAM,MAAA,GAAS,UAAA;AACf,EAAA,OAAA,CAAQ,IAAI,CAAA,MAAA,EAAS,EAAA,CAAG,KAAK,MAAA,CAAO,MAAM,CAAC,CAAA,CAAE,CAAA;AAC7C,EAAA,IAAI,OAAO,MAAA,EAAQ,UAAA,CAAW,QAAQ,MAAA,EAAQ,YAAA,CAAa,MAAM,CAAC,CAAA;AAClE,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,SAAS,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA;AAC5E,EAAA,IAAI,MAAA,CAAO,IAAA,EAAM,UAAA,CAAW,MAAA,EAAQ,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,MAAA,GAAS,UAAA,CAAW,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA;AAC7F,EAAA,KAAA,MAAW,GAAA,IAAO,OAAO,SAAA,EAAW;AAClC,IAAA,MAAM,KAAA,GAAQ,CAAC,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA,EAAG,GAAA,CAAI,WAAW,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AAC5E,IAAA,UAAA,CAAW,QAAQ,UAAA,EAAY,KAAA,GAAQ,UAAA,CAAW,GAAA,CAAI,IAAI,CAAC,CAAA;AAAA,EAC7D;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,OAAO,MAAA,EAAQ;AAC/B,IAAA,UAAA,CAAW,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAG,GAAA,CAAI,MAAM,CAAA,EAAG,GAAA,CAAI,OAAA,GAAU,CAAA,EAAA,EAAK,GAAA,CAAI,OAAO,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA,CAAE,CAAA;AAAA,EACtF;AACF;AAOA,SAAS,UAAU,IAAA,EAAyB;AAC1C,EAAA,IAAI,IAAA,CAAK,IAAA,KAAS,MAAA,EAAQ,OAAO,EAAA,CAAG,OAAA,CAAQ,CAAA,EAAA,EAAA,CAAM,IAAA,CAAK,OAAA,IAAW,EAAA,EAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AACjF,EAAA,IAAI,IAAA,CAAK,SAAS,OAAO,EAAA,CAAG,QAAQ,CAAA,EAAA,EAAK,IAAA,CAAK,OAAO,CAAA,CAAA,CAAG,CAAA;AACxD,EAAA,OAAO,EAAA;AACT;AAEA,SAAS,UAAA,CAAW,OAAmB,MAAA,EAAuB;AAC5D,EAAA,OAAA,CAAQ,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,SAAS,CAAC,CAAA;AAC9B,EAAA,IAAI,KAAA,CAAM,MAAM,MAAA,KAAW,CAAA,UAAW,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,UAAU,CAAC,CAAA;AAC5D,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,EAAA,CAAG,KAAA,CAAM,EAAE,SAAA,CAAU,MAAA,CAAO,YAAY,CAAC,CAAC,IAAI,EAAA,CAAG,GAAA,CAAI,EAAE,IAAI,CAAC,GAAG,SAAA,CAAU,CAAC,CAAC,CAAA,CAAE,CAAA;AAC9F,IAAA,IAAI,MAAA,EAAQ,aAAA,CAAc,eAAA,CAAgB,CAAC,CAAC,CAAA;AAAA,EAC9C;AAEA,EAAA,IAAI,MAAM,OAAA,CAAQ,MAAA,IAAU,KAAA,CAAM,QAAA,IAAY,MAAM,KAAA,EAAO;AACzD,IAAA,OAAA,CAAQ,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,WAAW,CAAC,CAAA;AAChC,IAAA,KAAA,MAAW,CAAA,IAAK,MAAM,OAAA,EAAS;AAC7B,MAAA,MAAM,QAAQ,SAAA,IAAa,CAAA,CAAE,QAAQ,EAAA,GAAK,GAAA,GAAM,MAAM,CAAA,CAAE,GAAA,CAAA;AACxD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAA,EAAK,EAAA,CAAG,IAAA,CAAK,MAAM,MAAA,CAAO,YAAY,CAAC,CAAC,IAAI,EAAA,CAAG,GAAA,CAAI,CAAA,CAAE,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,IAC1E;AACA,IAAA,IAAI,MAAM,QAAA,EAAU,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,EAAA,CAAG,KAAK,KAAA,CAAM,MAAA,CAAO,YAAY,CAAC,CAAC,CAAA,CAAA,EAAI,EAAA,CAAG,IAAI,KAAA,CAAM,QAAQ,CAAC,CAAA,CAAE,CAAA;AACpG,IAAA,IAAI,MAAM,KAAA,EAAO,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,EAAA,CAAG,KAAK,OAAA,CAAQ,MAAA,CAAO,YAAY,CAAC,CAAC,CAAA,CAAA,EAAI,EAAA,CAAG,IAAI,KAAA,CAAM,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,EAClG;AACF;AAEA,SAAS,SAAA,CAAU,OAAmB,MAAA,EAAuB;AAC3D,EAAA,OAAA,CAAQ,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,OAAO,CAAC,CAAA;AAC5B,EAAA,IAAI,CAAC,MAAM,SAAA,EAAW;AACpB,IAAA,OAAA,CAAQ,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,uDAAkD,CAAC,CAAA;AACtE,IAAA;AAAA,EACF;AACA,EAAA,IAAI,KAAA,CAAM,KAAK,MAAA,KAAW,CAAA,UAAW,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,UAAU,CAAC,CAAA;AAC3D,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,IAAA,EAAM;AAC1B,IAAA,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,EAAA,CAAG,MAAA,CAAO,CAAA,CAAE,UAAU,MAAA,CAAO,YAAY,CAAC,CAAC,IAAI,EAAA,CAAG,GAAA,CAAI,CAAA,CAAE,IAAI,CAAC,CAAA,CAAE,CAAA;AAChF,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,MAAM,IAAA,GAAO,eAAe,CAAC,CAAA;AAC7B,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAA,CAAQ,GAAA,CAAI,CAAA,MAAA,EAAS,EAAA,CAAG,GAAA,CAAI,mCAAmC,CAAC,CAAA,CAAE,CAAA;AACjG,IAAA,KAAA,MAAW,UAAU,IAAA,CAAK,OAAA,EAAS,kBAAA,CAAmB,MAAA,EAAQ,KAAK,MAAM,CAAA;AAAA,EAC3E;AACF;AAEA,SAAS,QAAA,CAAS,GAAc,MAAA,EAAiB;AAC/C,EAAA,OAAO;AAAA,IACL,OAAO,CAAA,CAAE,SAAA;AAAA,IACT,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,GAAI,EAAE,OAAA,GAAU,EAAE,SAAS,CAAA,CAAE,OAAA,KAAY,EAAC;AAAA,IAC1C,GAAI,EAAE,OAAA,GAAU,EAAE,SAAS,CAAA,CAAE,OAAA,KAAY,EAAC;AAAA,IAC1C,GAAI,SAAS,EAAE,IAAA,EAAM,gBAAgB,CAAC,CAAA,KAAM;AAAC,GAC/C;AACF;AAEA,SAAS,OAAA,CAAQ,GAAa,MAAA,EAAiB;AAC7C,EAAA,OAAO;AAAA,IACL,OAAO,CAAA,CAAE,SAAA;AAAA,IACT,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,QAAQ,CAAA,CAAE,MAAA;AAAA,IACV,GAAI,SAAS,EAAE,IAAA,EAAM,eAAe,CAAC,CAAA,KAAM;AAAC,GAC9C;AACF;AAQA,eAAsB,MAAA,CAAO,MAAc,IAAA,EAAmC;AAC5E,EAAA,MAAM,KAAA,GAAQ,YAAY,IAAI,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC1C,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAExC,EAAA,MAAM,SAAA,GAAY,aAAa,CAAC,QAAA;AAChC,EAAA,MAAM,QAAA,GAAW,YAAY,CAAC,SAAA;AAC9B,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAExC,EAAA,IAAI,IAAA,CAAK,MAAM,IAAA,EAAM;AACnB,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,OAAA,CAAQ,KAAA,GAAQ,MAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,QAAA,CAAS,CAAA,EAAG,MAAM,CAAC,CAAA;AAC1D,MAAA,OAAA,CAAQ,UAAU,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,OAAO,EAAE,GAAA,EAAK,CAAA,CAAE,GAAA,KAAQ,KAAK,GAAA,GAAM,CAAA,CAAE,KAAK,IAAA,EAAM,CAAA,CAAE,MAAK,CAAE,CAAA;AAC9F,MAAA,OAAA,CAAQ,WAAW,KAAA,CAAM,QAAA;AACzB,MAAA,OAAA,CAAQ,QAAQ,KAAA,CAAM,KAAA;AAGtB,MAAA,OAAA,CAAQ,WAAW,KAAA,CAAM,QAAA;AAAA,IAC3B;AACA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAA,CAAQ,IAAA,GAAO,MAAM,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,EAAG,MAAM,CAAC,CAAA;AACvD,MAAA,OAAA,CAAQ,YAAY,KAAA,CAAM,SAAA;AAAA,IAC5B;AACA,IAAA,SAAA,CAAU,OAAO,CAAA;AACjB,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,IAAI,SAAA,EAAW,UAAA,CAAW,KAAA,EAAO,MAAM,CAAA;AAEvC,EAAA,IAAI,aAAa,KAAA,CAAM,SAAA,IAAa,QAAA,CAAA,EAAW,SAAA,CAAU,OAAO,MAAM,CAAA;AACtE,EAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,EAAA,OAAO,CAAA;AACT","file":"routes-3SGAFDMC.js","sourcesContent":["import pc from \"picocolors\"\nimport {\n extractApiSpec,\n extractPageSpec,\n type ApiMethodSpec,\n type PageSpec,\n type RouteParam,\n} from \"../core/route-spec\"\nimport { scanProject } from \"../core/scan\"\nimport type { ApiRoute, PageRoute, RouteModel } from \"../core/types\"\nimport { printJson, type ParsedArgs } from \"./util\"\n\nconst ROUTE_COLUMN = 28\nconst LABEL_COLUMN = 9\n\n/** Print an indented `label value` line under a route. */\nfunction detailLine(indent: string, label: string, value: string): void {\n console.log(`${indent}${pc.dim(label.padEnd(LABEL_COLUMN))}${value}`)\n}\n\n/** Render params as `:id`, `*rest`. */\nfunction formatParams(params: RouteParam[]): string {\n return params.map((p) => (p.kind === \"catchall\" ? `*${p.name}` : `:${p.name}`)).join(\", \")\n}\n\nfunction formatKeys(keys: string[] | undefined): string {\n return keys?.length ? ` { ${keys.join(\", \")} }` : \"\"\n}\n\nfunction printPageSpec(spec: PageSpec): void {\n const indent = \" \"\n if (spec.title) detailLine(indent, \"title\", spec.title)\n if (spec.navLabel) detailLine(indent, \"nav\", spec.navLabel)\n if (spec.description) detailLine(indent, \"desc\", spec.description)\n if (spec.params.length) detailLine(indent, \"params\", formatParams(spec.params))\n}\n\nfunction printApiMethodSpec(method: ApiMethodSpec, params: RouteParam[]): void {\n const indent = \" \"\n console.log(` ${pc.bold(method.method)}`)\n if (params.length) detailLine(indent, \"path\", formatParams(params))\n if (method.query.length) detailLine(indent, \"query\", method.query.join(\", \"))\n if (method.body) detailLine(indent, \"body\", method.body.format + formatKeys(method.body.keys))\n for (const res of method.responses) {\n const parts = [String(res.status), res.contentType].filter(Boolean).join(\" \")\n detailLine(indent, \"response\", parts + formatKeys(res.keys))\n }\n for (const err of method.errors) {\n detailLine(indent, \"error\", `${err.status}${err.message ? ` \"${err.message}\"` : \"\"}`)\n }\n}\n\n/**\n * How a page is rendered, when it is not the plain case. Without this a\n * `.slide.tsx` and a `.tsx` that resolve to the same URL look identical here,\n * and the whole point of `routes` is to show what the scan understood.\n */\nfunction pageBadge(page: PageRoute): string {\n if (page.kind === \"file\") return pc.magenta(` (${(page.fileExt ?? \"\").slice(1)})`)\n if (page.variant) return pc.magenta(` (${page.variant})`)\n return \"\"\n}\n\nfunction printPages(model: RouteModel, detail: boolean): void {\n console.log(pc.bold(\"\\nPages\"))\n if (model.pages.length === 0) console.log(pc.dim(\" (none)\"))\n for (const p of model.pages) {\n console.log(` ${pc.green(p.routePath.padEnd(ROUTE_COLUMN))} ${pc.dim(p.file)}${pageBadge(p)}`)\n if (detail) printPageSpec(extractPageSpec(p))\n }\n\n if (model.layouts.length || model.notFound || model.error) {\n console.log(pc.bold(\"\\nSpecial\"))\n for (const l of model.layouts) {\n const label = \"layout \" + (l.dir === \"\" ? \"/\" : \"/\" + l.dir)\n console.log(` ${pc.cyan(label.padEnd(ROUTE_COLUMN))} ${pc.dim(l.file)}`)\n }\n if (model.notFound) console.log(` ${pc.cyan(\"404\".padEnd(ROUTE_COLUMN))} ${pc.dim(model.notFound)}`)\n if (model.error) console.log(` ${pc.cyan(\"error\".padEnd(ROUTE_COLUMN))} ${pc.dim(model.error)}`)\n }\n}\n\nfunction printApis(model: RouteModel, detail: boolean): void {\n console.log(pc.bold(\"\\nAPI\"))\n if (!model.hasServer) {\n console.log(pc.dim(\" (none — this project has no server/ directory)\"))\n return\n }\n if (model.apis.length === 0) console.log(pc.dim(\" (none)\"))\n for (const a of model.apis) {\n console.log(` ${pc.yellow(a.routePath.padEnd(ROUTE_COLUMN))} ${pc.dim(a.file)}`)\n if (!detail) continue\n const spec = extractApiSpec(a)\n if (spec.methods.length === 0) console.log(` ${pc.dim(\"(no HTTP method handler exported)\")}`)\n for (const method of spec.methods) printApiMethodSpec(method, spec.params)\n }\n}\n\nfunction pageJson(p: PageRoute, detail: boolean) {\n return {\n route: p.routePath,\n file: p.file,\n dynamic: p.dynamic,\n kind: p.kind,\n ...(p.fileExt ? { fileExt: p.fileExt } : {}),\n ...(p.variant ? { variant: p.variant } : {}),\n ...(detail ? { spec: extractPageSpec(p) } : {}),\n }\n}\n\nfunction apiJson(a: ApiRoute, detail: boolean) {\n return {\n route: a.routePath,\n file: a.file,\n params: a.params,\n ...(detail ? { spec: extractApiSpec(a) } : {}),\n }\n}\n\n/**\n * `vantage routes` — show the page and API URL map.\n * `--pages` / `--apis` narrow the map to one side; `--detail` adds the static\n * spec of each route (page path params + definePage meta, API methods with\n * their request input and response shape).\n */\nexport async function routes(root: string, args: ParsedArgs): Promise<number> {\n const model = scanProject(root)\n const onlyPages = Boolean(args.flags.pages)\n const onlyApis = Boolean(args.flags.apis)\n // Neither flag (or both) means \"everything\", so the two are never exclusive.\n const showPages = onlyPages || !onlyApis\n const showApis = onlyApis || !onlyPages\n const detail = Boolean(args.flags.detail)\n\n if (args.flags.json) {\n const payload: Record<string, unknown> = {}\n if (showPages) {\n payload.pages = model.pages.map((p) => pageJson(p, detail))\n payload.layouts = model.layouts.map((l) => ({ dir: l.dir === \"\" ? \"/\" : l.dir, file: l.file }))\n payload.notFound = model.notFound\n payload.error = model.error\n // Files the scan skipped. `check` explains them; listing them here means\n // an agent reading `routes --json` sees them without a second command.\n payload.unrouted = model.unrouted\n }\n if (showApis) {\n payload.apis = model.apis.map((a) => apiJson(a, detail))\n payload.hasServer = model.hasServer\n }\n printJson(payload)\n return 0\n }\n\n if (showPages) printPages(model, detail)\n // Without --apis, an API-less project stays silent (nothing to say about it).\n if (showApis && (model.hasServer || onlyApis)) printApis(model, detail)\n console.log(\"\")\n return 0\n}\n"]}
1
+ {"version":3,"sources":["../src/cli/routes.ts"],"names":[],"mappings":"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","file":"routes-PVKNT777.js","sourcesContent":["import pc from \"picocolors\"\nimport {\n extractApiSpec,\n extractPageSpec,\n type ApiMethodSpec,\n type PageSpec,\n type RouteParam,\n} from \"../core/route-spec\"\nimport { scanProject } from \"../core/scan\"\nimport type { ApiRoute, PageRoute, RouteModel } from \"../core/types\"\nimport { printJson, type ParsedArgs } from \"./util\"\n\nconst ROUTE_COLUMN = 28\nconst LABEL_COLUMN = 9\n\n/** Print an indented `label value` line under a route. */\nfunction detailLine(indent: string, label: string, value: string): void {\n console.log(`${indent}${pc.dim(label.padEnd(LABEL_COLUMN))}${value}`)\n}\n\n/** Render params as `:id`, `*rest`. */\nfunction formatParams(params: RouteParam[]): string {\n return params.map((p) => (p.kind === \"catchall\" ? `*${p.name}` : `:${p.name}`)).join(\", \")\n}\n\nfunction formatKeys(keys: string[] | undefined): string {\n return keys?.length ? ` { ${keys.join(\", \")} }` : \"\"\n}\n\nfunction printPageSpec(spec: PageSpec): void {\n const indent = \" \"\n if (spec.title) detailLine(indent, \"title\", spec.title)\n if (spec.navLabel) detailLine(indent, \"nav\", spec.navLabel)\n if (spec.description) detailLine(indent, \"desc\", spec.description)\n if (spec.params.length) detailLine(indent, \"params\", formatParams(spec.params))\n}\n\nfunction printApiMethodSpec(method: ApiMethodSpec, params: RouteParam[]): void {\n const indent = \" \"\n console.log(` ${pc.bold(method.method)}`)\n if (params.length) detailLine(indent, \"path\", formatParams(params))\n if (method.query.length) detailLine(indent, \"query\", method.query.join(\", \"))\n if (method.body) detailLine(indent, \"body\", method.body.format + formatKeys(method.body.keys))\n for (const res of method.responses) {\n const parts = [String(res.status), res.contentType].filter(Boolean).join(\" \")\n detailLine(indent, \"response\", parts + formatKeys(res.keys))\n }\n for (const err of method.errors) {\n detailLine(indent, \"error\", `${err.status}${err.message ? ` \"${err.message}\"` : \"\"}`)\n }\n}\n\n/**\n * How a page is rendered, when it is not the plain case. Without this a\n * `.slide.tsx` and a `.tsx` that resolve to the same URL look identical here,\n * and the whole point of `routes` is to show what the scan understood.\n */\nfunction pageBadge(page: PageRoute): string {\n if (page.kind === \"file\") return pc.magenta(` (${(page.fileExt ?? \"\").slice(1)})`)\n if (page.variant) return pc.magenta(` (${page.variant})`)\n return \"\"\n}\n\nfunction printPages(model: RouteModel, detail: boolean): void {\n console.log(pc.bold(\"\\nPages\"))\n if (model.pages.length === 0) console.log(pc.dim(\" (none)\"))\n for (const p of model.pages) {\n console.log(` ${pc.green(p.routePath.padEnd(ROUTE_COLUMN))} ${pc.dim(p.file)}${pageBadge(p)}`)\n if (detail) printPageSpec(extractPageSpec(p))\n }\n\n if (model.layouts.length || model.notFound || model.error) {\n console.log(pc.bold(\"\\nSpecial\"))\n for (const l of model.layouts) {\n const label = \"layout \" + (l.dir === \"\" ? \"/\" : \"/\" + l.dir)\n console.log(` ${pc.cyan(label.padEnd(ROUTE_COLUMN))} ${pc.dim(l.file)}`)\n }\n if (model.notFound) console.log(` ${pc.cyan(\"404\".padEnd(ROUTE_COLUMN))} ${pc.dim(model.notFound)}`)\n if (model.error) console.log(` ${pc.cyan(\"error\".padEnd(ROUTE_COLUMN))} ${pc.dim(model.error)}`)\n }\n}\n\nfunction printApis(model: RouteModel, detail: boolean): void {\n console.log(pc.bold(\"\\nAPI\"))\n if (!model.hasServer) {\n console.log(pc.dim(\" (none — this project has no server/ directory)\"))\n return\n }\n if (model.apis.length === 0) console.log(pc.dim(\" (none)\"))\n for (const a of model.apis) {\n console.log(` ${pc.yellow(a.routePath.padEnd(ROUTE_COLUMN))} ${pc.dim(a.file)}`)\n if (!detail) continue\n const spec = extractApiSpec(a)\n if (spec.methods.length === 0) console.log(` ${pc.dim(\"(no HTTP method handler exported)\")}`)\n for (const method of spec.methods) printApiMethodSpec(method, spec.params)\n }\n}\n\nfunction pageJson(p: PageRoute, detail: boolean) {\n return {\n route: p.routePath,\n file: p.file,\n dynamic: p.dynamic,\n kind: p.kind,\n ...(p.fileExt ? { fileExt: p.fileExt } : {}),\n ...(p.variant ? { variant: p.variant } : {}),\n ...(detail ? { spec: extractPageSpec(p) } : {}),\n }\n}\n\nfunction apiJson(a: ApiRoute, detail: boolean) {\n return {\n route: a.routePath,\n file: a.file,\n params: a.params,\n ...(detail ? { spec: extractApiSpec(a) } : {}),\n }\n}\n\n/**\n * `vantage routes` — show the page and API URL map.\n * `--pages` / `--apis` narrow the map to one side; `--detail` adds the static\n * spec of each route (page path params + definePage meta, API methods with\n * their request input and response shape).\n */\nexport async function routes(root: string, args: ParsedArgs): Promise<number> {\n const model = scanProject(root)\n const onlyPages = Boolean(args.flags.pages)\n const onlyApis = Boolean(args.flags.apis)\n // Neither flag (or both) means \"everything\", so the two are never exclusive.\n const showPages = onlyPages || !onlyApis\n const showApis = onlyApis || !onlyPages\n const detail = Boolean(args.flags.detail)\n\n if (args.flags.json) {\n const payload: Record<string, unknown> = {}\n if (showPages) {\n payload.pages = model.pages.map((p) => pageJson(p, detail))\n payload.layouts = model.layouts.map((l) => ({ dir: l.dir === \"\" ? \"/\" : l.dir, file: l.file }))\n payload.notFound = model.notFound\n payload.error = model.error\n // Files the scan skipped. `check` explains them; listing them here means\n // an agent reading `routes --json` sees them without a second command.\n payload.unrouted = model.unrouted\n }\n if (showApis) {\n payload.apis = model.apis.map((a) => apiJson(a, detail))\n payload.hasServer = model.hasServer\n }\n printJson(payload)\n return 0\n }\n\n if (showPages) printPages(model, detail)\n // Without --apis, an API-less project stays silent (nothing to say about it).\n if (showApis && (model.hasServer || onlyApis)) printApis(model, detail)\n console.log(\"\")\n return 0\n}\n"]}
@@ -1,5 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ReactNode, PropsWithChildren, CSSProperties, ReactElement } from 'react';
3
+ import { V as ValueFormat } from '../format-U0cQl069.js';
4
+ export { D as DeltaText, a as DeltaTextProps } from '../delta-text-CvwBGJ95.js';
3
5
 
4
6
  /**
5
7
  * Ported from open-slide (MIT) — https://github.com/1weiho/open-slide
@@ -227,4 +229,273 @@ declare function exportDeckAsPptx({ slides, fileName, theme, onProgress, }: Expo
227
229
  declare const CANVAS_WIDTH = 1920;
228
230
  declare const CANVAS_HEIGHT = 1080;
229
231
 
230
- export { CANVAS_HEIGHT, CANVAS_WIDTH, type EntryDirection, type ExportDeckOptions, MorphElement, type MorphElementProps, type MorphTransition, type PptxExportProgress, Slide, SlideCanvas, type SlideCanvasProps, SlideDeck, type SlideDeckProps, type SlideProps, type SlideTheme, type SlideTransition, Step, type StepController, type StepProps, Steps, type TransitionPhase, exportDeckAsPptx, useIsActiveSlide, useSlideNumber };
232
+ interface SlideChartInsightChart {
233
+ type: "line" | "bar" | "area";
234
+ /** The x-axis labels, one per value of each series. */
235
+ categories: string[];
236
+ series: {
237
+ name: string;
238
+ data: number[];
239
+ }[];
240
+ }
241
+ interface SlideChartInsightProps {
242
+ /** The conclusion as a sentence (an action title). */
243
+ title: string;
244
+ chart: SlideChartInsightChart;
245
+ /** 2–3 points that read the chart. */
246
+ insights: string[];
247
+ /** Which side the chart takes. Default `"left"`. */
248
+ chartSide?: "left" | "right";
249
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
250
+ asOf?: string;
251
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
252
+ source?: string;
253
+ }
254
+ declare function SlideChartInsight({ title, chart, insights, chartSide, asOf, source }: SlideChartInsightProps): React.JSX.Element;
255
+
256
+ interface SlideCoverProps {
257
+ /** The name of the deck. */
258
+ title: string;
259
+ subtitle?: string;
260
+ /** The period the deck covers, e.g.「2026 年 7 月〜9 月」. */
261
+ period?: string;
262
+ author?: string;
263
+ /** The date the numbers were taken, date only, e.g. `"2026-10-20"`. Shown as「2026-10-20 時点」(the block adds「時点」once). */
264
+ asOf?: string;
265
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
266
+ source?: string;
267
+ }
268
+ declare function SlideCover({ title, subtitle, period, author, asOf, source }: SlideCoverProps): React.JSX.Element;
269
+
270
+ interface SlideExecSummaryPoint {
271
+ /** The point in one line. */
272
+ headline: string;
273
+ /** One supporting line (a number, a cause). */
274
+ detail?: string;
275
+ }
276
+ interface SlideExecSummaryProps {
277
+ /** The conclusion as a sentence (an action title), not a topic. */
278
+ title: string;
279
+ /** 3–5 points. */
280
+ points: SlideExecSummaryPoint[];
281
+ layout?: "rows" | "columns";
282
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
283
+ asOf?: string;
284
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
285
+ source?: string;
286
+ }
287
+ declare function SlideExecSummary({ title, points, layout, asOf, source }: SlideExecSummaryProps): React.JSX.Element;
288
+
289
+ /** A change: its size in the metric's units, signed. The direction is read from the sign. */
290
+ interface SlideKpiGridDelta {
291
+ /** e.g. `0.074` with `format: "percent"` →「+7.4%」. */
292
+ value: number;
293
+ /** Default: the item's `format`. */
294
+ format?: ValueFormat;
295
+ }
296
+ interface SlideKpiGridItem {
297
+ label: string;
298
+ /** The number; `null` shows「—」. */
299
+ value: number | null;
300
+ format?: ValueFormat;
301
+ /** Replaces the shown text only (the number behind it stays `value`). */
302
+ display?: string;
303
+ delta?: SlideKpiGridDelta;
304
+ /** Which direction of `delta` is good. Default `"up"`. */
305
+ betterWhen?: "up" | "down";
306
+ /** What `delta` is against, e.g.「前月比」. */
307
+ comparisonLabel?: string;
308
+ /** The target, in the same `format` as `value`. The attainment rate is worked out here. */
309
+ target?: number;
310
+ }
311
+ interface SlideKpiGridProps {
312
+ /** The conclusion as a sentence (an action title). */
313
+ title: string;
314
+ /** 2–4 KPIs. */
315
+ items: SlideKpiGridItem[];
316
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
317
+ asOf?: string;
318
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
319
+ source?: string;
320
+ }
321
+ declare function SlideKpiGrid({ title, items, asOf, source }: SlideKpiGridProps): React.JSX.Element;
322
+
323
+ /** A change: its size in the metric's units, signed. The direction is read from the sign. */
324
+ interface SlideKpiHeroDelta {
325
+ /** e.g. `0.074` with `format: "percent"` →「+7.4%」. */
326
+ value: number;
327
+ /** Default: the metric's `format`. */
328
+ format?: ValueFormat;
329
+ }
330
+ interface SlideKpiHeroProps {
331
+ /** The conclusion as a sentence (an action title). */
332
+ title: string;
333
+ /** What the number is, e.g.「月次売上」. */
334
+ label: string;
335
+ /** The number; `null` shows「—」. */
336
+ value: number | null;
337
+ format?: ValueFormat;
338
+ /** Replaces the shown text only (the number behind it stays `value`). */
339
+ display?: string;
340
+ delta?: SlideKpiHeroDelta;
341
+ /** Which direction of `delta` is good. Default `"up"`. */
342
+ betterWhen?: "up" | "down";
343
+ /** What `delta` is against, e.g.「前月比」. */
344
+ comparisonLabel?: string;
345
+ /** Points of the line on the right; leave out for a number alone. */
346
+ trend?: {
347
+ x: string;
348
+ y: number;
349
+ }[];
350
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
351
+ asOf?: string;
352
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
353
+ source?: string;
354
+ }
355
+ declare function SlideKpiHero({ title, label, value, format, display, delta, betterWhen, comparisonLabel, trend, asOf, source }: SlideKpiHeroProps): React.JSX.Element;
356
+
357
+ interface SlideNextActionsItem {
358
+ /** What to do, as one sentence starting from the verb's object. */
359
+ action: string;
360
+ owner?: string;
361
+ /** As written, e.g. `"10/31"`. */
362
+ due?: string;
363
+ /** What to look at to know it worked. */
364
+ metric?: string;
365
+ }
366
+ interface SlideNextActionsProps {
367
+ /** The decision or the plan as a sentence (an action title). */
368
+ title: string;
369
+ /** 3–5 actions. */
370
+ items: SlideNextActionsItem[];
371
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
372
+ asOf?: string;
373
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
374
+ source?: string;
375
+ }
376
+ declare function SlideNextActions({ title, items, asOf, source }: SlideNextActionsProps): React.JSX.Element;
377
+
378
+ type SlideScorecardStatus = "on" | "risk" | "off";
379
+ interface SlideScorecardRow {
380
+ metric: string;
381
+ /** The actual; `null` shows「—」. */
382
+ value: number | null;
383
+ format?: ValueFormat;
384
+ /** Replaces the shown actual only (the number behind it stays `value`). */
385
+ display?: string;
386
+ /** The target, in the same `format` as `value`. */
387
+ target?: number;
388
+ /** Which direction is good. Default `"up"`; it flips the attainment rate. */
389
+ betterWhen?: "up" | "down";
390
+ /** `on` = on track, `risk` = at risk, `off` = off track. */
391
+ status: SlideScorecardStatus;
392
+ }
393
+ interface SlideScorecardTableProps {
394
+ /** The conclusion as a sentence (an action title). */
395
+ title: string;
396
+ /** Up to 8 rows. */
397
+ rows: SlideScorecardRow[];
398
+ /** Header words; leave out what you do not rename. */
399
+ columns?: Partial<Record<"metric" | "target" | "actual" | "attainment" | "status", string>>;
400
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
401
+ asOf?: string;
402
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
403
+ source?: string;
404
+ }
405
+ declare function SlideScorecardTable({ title, rows, columns, asOf, source }: SlideScorecardTableProps): React.JSX.Element;
406
+
407
+ interface SlideChartFullProps {
408
+ /** The conclusion as a sentence (an action title). */
409
+ title: string;
410
+ chart: SlideChartInsightChart;
411
+ /** One line under the chart. */
412
+ note?: string;
413
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
414
+ asOf?: string;
415
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
416
+ source?: string;
417
+ }
418
+ declare function SlideChartFull({ title, chart, note, asOf, source }: SlideChartFullProps): React.JSX.Element;
419
+
420
+ interface SlideComparisonColumn {
421
+ /** What this column is, e.g.「旧プラン」「施策前」. */
422
+ heading: string;
423
+ /** The main number. `null` shows「—」. */
424
+ value?: number | null;
425
+ format?: ValueFormat;
426
+ /** The main number as a string you already formatted; wins over `value`. */
427
+ display?: string;
428
+ /** The change of the main number against the other side or the previous period. `format` falls back to the column's `format`. */
429
+ delta?: {
430
+ value: number | null;
431
+ format?: ValueFormat;
432
+ };
433
+ /** Name of what `delta` is measured against, e.g.「前月比」「旧プラン比」. Printed before the change. */
434
+ comparisonLabel?: string;
435
+ /** Which way is good for the main number. Default `"up"`. */
436
+ betterWhen?: "up" | "down";
437
+ /** 1–3 short points about this column. */
438
+ points: string[];
439
+ }
440
+ interface SlideComparisonProps {
441
+ /** The conclusion as a sentence (an action title). */
442
+ title: string;
443
+ /** 2–3 columns. */
444
+ columns: SlideComparisonColumn[];
445
+ /** One line that says which side wins or what follows. */
446
+ verdict?: string;
447
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(the block adds「時点」once). */
448
+ asOf?: string;
449
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
450
+ source?: string;
451
+ }
452
+ declare function SlideComparison({ title, columns, verdict, asOf, source }: SlideComparisonProps): React.JSX.Element;
453
+
454
+ interface SlideSectionProps {
455
+ /** The chapter number, shown as「02」above the title. */
456
+ index?: number;
457
+ title: string;
458
+ /** One line under the title saying what the chapter answers. */
459
+ lead?: string;
460
+ /** The chapters of the deck, shown as a numbered agenda at the right. */
461
+ items?: string[];
462
+ /** The chapter in `items` to emphasise, 1-based. */
463
+ current?: number;
464
+ }
465
+ declare function SlideSection({ index, title, lead, items, current }: SlideSectionProps): React.JSX.Element;
466
+
467
+ interface SlideHeadingProps {
468
+ /** The conclusion as a sentence (an action title). Clamped to 2 lines. */
469
+ title: string;
470
+ /** A short label above the title, e.g.「第 2 章 解約」. */
471
+ eyebrow?: string;
472
+ }
473
+ declare function SlideHeading({ title, eyebrow }: SlideHeadingProps): React.JSX.Element;
474
+
475
+ interface SlideSourceLineProps {
476
+ /** The date the numbers were taken, date only, e.g. `"2026-10-01"`. Shown as「2026-10-01 時点」(this part adds「時点」once). */
477
+ asOf?: string;
478
+ /** Where the numbers come from, e.g.「社内 BI」. Shown as「出典: 社内 BI」. */
479
+ source?: string;
480
+ /** The page number, shown at the right as「3 / 12」. */
481
+ page?: {
482
+ current: number;
483
+ total: number;
484
+ };
485
+ }
486
+ declare function SlideSourceLine({ asOf, source, page }: SlideSourceLineProps): React.JSX.Element | null;
487
+
488
+ interface SlideColumnsProps {
489
+ children: ReactNode;
490
+ /** Vertical alignment of the columns in the row. Default `"stretch"`. */
491
+ align?: "start" | "center" | "stretch";
492
+ }
493
+ declare function SlideColumns({ children, align }: SlideColumnsProps): React.JSX.Element;
494
+ interface SlideColumnProps {
495
+ /** How many of the 12 columns it takes, 1–12. */
496
+ span: number;
497
+ children: ReactNode;
498
+ }
499
+ declare function SlideColumn({ span, children }: SlideColumnProps): React.JSX.Element;
500
+
501
+ export { CANVAS_HEIGHT, CANVAS_WIDTH, type EntryDirection, type ExportDeckOptions, MorphElement, type MorphElementProps, type MorphTransition, type PptxExportProgress, Slide, SlideCanvas, type SlideCanvasProps, SlideChartFull, type SlideChartFullProps, SlideChartInsight, type SlideChartInsightChart, type SlideChartInsightProps, SlideColumn, type SlideColumnProps, SlideColumns, type SlideColumnsProps, SlideComparison, type SlideComparisonColumn, type SlideComparisonProps, SlideCover, type SlideCoverProps, SlideDeck, type SlideDeckProps, SlideExecSummary, type SlideExecSummaryPoint, type SlideExecSummaryProps, SlideHeading, type SlideHeadingProps, SlideKpiGrid, type SlideKpiGridDelta, type SlideKpiGridItem, type SlideKpiGridProps, SlideKpiHero, type SlideKpiHeroDelta, type SlideKpiHeroProps, SlideNextActions, type SlideNextActionsItem, type SlideNextActionsProps, type SlideProps, type SlideScorecardRow, type SlideScorecardStatus, SlideScorecardTable, type SlideScorecardTableProps, SlideSection, type SlideSectionProps, SlideSourceLine, type SlideSourceLineProps, type SlideTheme, type SlideTransition, Step, type StepController, type StepProps, Steps, type TransitionPhase, exportDeckAsPptx, useIsActiveSlide, useSlideNumber };