@cardenelabs/cdl 0.34.0 → 0.36.0

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.
@@ -423,6 +423,21 @@ type CdlNode = {
423
423
  * `previous` (cdl#680) が効くのは `ring` だけ。 他の形は内側の輪を描かない。
424
424
  */
425
425
  chartPieForm?: ChartPieForm;
426
+ /**
427
+ * chart-slope の見せ方 (cdl#702)。 右の列に何の数を出すかを決める。
428
+ *
429
+ * - `values` ... 今の値
430
+ * - `delta` ... 増減 (`+40` / `-90`)
431
+ *
432
+ * 左の列は どちらでも前の値。 `前 + 増減 = 今` なので、 `delta` でも今の値は足せば戻る。
433
+ * 3 つ目の数を足さないので、 名札の高さも線を引く幅も変わらない。
434
+ *
435
+ * 型の外の値は `values` として描く = 見せ方が決まらないより、既定の形が出る方がよい。
436
+ *
437
+ * 前の時点を持たない図 (`previous` が 1 件も無い) は右の列そのものが無いため、
438
+ * この欄を書いても絵は変わらない。
439
+ */
440
+ chartSlopeForm?: ChartSlopeForm;
426
441
  /**
427
442
  * gantt-timeline 専用の task payload。 task 全件を 1 node に格納し、
428
443
  * kinds/gantt.tsx が縦軸 task lane + 横軸日付 rect bar で SVG 描画する。
@@ -478,6 +493,8 @@ type BoundEnum<T extends string> = T | (string & {});
478
493
  /** Chart 系 kind の 1 datum payload。 label + value + optional tone (color) */
479
494
  /** chart-pie の見せ方 (cdl#684)。 SSOT は `kinds/chart-pie.tsx` */
480
495
  type ChartPieForm = "ring" | "arcs" | "table";
496
+ /** chart-slope の見せ方 (cdl#702)。 SSOT は `kinds/chart-slope.tsx` */
497
+ type ChartSlopeForm = "values" | "delta";
481
498
  type ChartDatumPayload = {
482
499
  label: string;
483
500
  /** 棒 / 折れ線 / 扇の大きさ。 `{signal}` で状態に追随する */
@@ -2883,4 +2900,4 @@ type CdlDiagramViewProps = {
2883
2900
  };
2884
2901
  declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
2885
2902
 
2886
- export { createScrollProgressSignals as $, EDGE_REVEALS as A, type BBox as B, type CdlDiagram as C, EDGE_REVEAL_DEFAULT as D, type EdgeStyle as E, EDGE_STYLES as F, type EdgeReveal as G, type InteractiveSignalsAccessor as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, type LaidLane as K, type LaidDiagram as L, NODE_KINDS as M, type NodeKind as N, type ScrollProgressHandle as O, TONES as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, computeEventBindingKey as U, computeFormulaKey as V, computeInputSignalKey as W, computeScrollTriggerKey as X, computed as Y, createInteractiveSignalsAccessor as Z, createScrollProgressHandle as _, type CdlInput as a, hasInteractivePrimitives as a0, sequenceBoardMetrics as a1, sequenceStepId as a2, signal as a3, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeRole as e, type EdgeHead as f, type EdgeHeadFill as g, type CdlState as h, type CdlEventTarget as i, type Computed as j, type CdlDerivedValue as k, type CdlScrollTrigger as l, type CdlDiagramViewProps as m, type LaidEdge as n, type LaidNode as o, type CdlEdge as p, CdlDiagramView as q, type CdlEventBinding as r, type CdlEventKind as s, type CdlFormula as t, type CdlPhase as u, type ChartPieForm as v, EDGE_HEADS as w, EDGE_HEAD_DEFAULT as x, EDGE_HEAD_FILLS as y, EDGE_HEAD_FILL_DEFAULT as z };
2903
+ export { createScrollProgressHandle as $, EDGE_HEAD_FILL_DEFAULT as A, type BBox as B, type CdlDiagram as C, EDGE_REVEALS as D, type EdgeStyle as E, EDGE_REVEAL_DEFAULT as F, EDGE_STYLES as G, type EdgeReveal as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, type InteractiveSignalsAccessor as K, type LaidDiagram as L, type LaidLane as M, type NodeKind as N, NODE_KINDS as O, type ScrollProgressHandle as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, TONES as U, computeEventBindingKey as V, computeFormulaKey as W, computeInputSignalKey as X, computeScrollTriggerKey as Y, computed as Z, createInteractiveSignalsAccessor as _, type CdlInput as a, createScrollProgressSignals as a0, hasInteractivePrimitives as a1, sequenceBoardMetrics as a2, sequenceStepId as a3, signal as a4, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeRole as e, type EdgeHead as f, type EdgeHeadFill as g, type CdlState as h, type CdlEventTarget as i, type Computed as j, type CdlDerivedValue as k, type CdlScrollTrigger as l, type CdlDiagramViewProps as m, type LaidEdge as n, type LaidNode as o, type CdlEdge as p, CdlDiagramView as q, type CdlEventBinding as r, type CdlEventKind as s, type CdlFormula as t, type CdlPhase as u, type ChartPieForm as v, type ChartSlopeForm as w, EDGE_HEADS as x, EDGE_HEAD_DEFAULT as y, EDGE_HEAD_FILLS as z };
@@ -423,6 +423,21 @@ type CdlNode = {
423
423
  * `previous` (cdl#680) が効くのは `ring` だけ。 他の形は内側の輪を描かない。
424
424
  */
425
425
  chartPieForm?: ChartPieForm;
426
+ /**
427
+ * chart-slope の見せ方 (cdl#702)。 右の列に何の数を出すかを決める。
428
+ *
429
+ * - `values` ... 今の値
430
+ * - `delta` ... 増減 (`+40` / `-90`)
431
+ *
432
+ * 左の列は どちらでも前の値。 `前 + 増減 = 今` なので、 `delta` でも今の値は足せば戻る。
433
+ * 3 つ目の数を足さないので、 名札の高さも線を引く幅も変わらない。
434
+ *
435
+ * 型の外の値は `values` として描く = 見せ方が決まらないより、既定の形が出る方がよい。
436
+ *
437
+ * 前の時点を持たない図 (`previous` が 1 件も無い) は右の列そのものが無いため、
438
+ * この欄を書いても絵は変わらない。
439
+ */
440
+ chartSlopeForm?: ChartSlopeForm;
426
441
  /**
427
442
  * gantt-timeline 専用の task payload。 task 全件を 1 node に格納し、
428
443
  * kinds/gantt.tsx が縦軸 task lane + 横軸日付 rect bar で SVG 描画する。
@@ -478,6 +493,8 @@ type BoundEnum<T extends string> = T | (string & {});
478
493
  /** Chart 系 kind の 1 datum payload。 label + value + optional tone (color) */
479
494
  /** chart-pie の見せ方 (cdl#684)。 SSOT は `kinds/chart-pie.tsx` */
480
495
  type ChartPieForm = "ring" | "arcs" | "table";
496
+ /** chart-slope の見せ方 (cdl#702)。 SSOT は `kinds/chart-slope.tsx` */
497
+ type ChartSlopeForm = "values" | "delta";
481
498
  type ChartDatumPayload = {
482
499
  label: string;
483
500
  /** 棒 / 折れ線 / 扇の大きさ。 `{signal}` で状態に追随する */
@@ -2883,4 +2900,4 @@ type CdlDiagramViewProps = {
2883
2900
  };
2884
2901
  declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
2885
2902
 
2886
- export { createScrollProgressSignals as $, EDGE_REVEALS as A, type BBox as B, type CdlDiagram as C, EDGE_REVEAL_DEFAULT as D, type EdgeStyle as E, EDGE_STYLES as F, type EdgeReveal as G, type InteractiveSignalsAccessor as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, type LaidLane as K, type LaidDiagram as L, NODE_KINDS as M, type NodeKind as N, type ScrollProgressHandle as O, TONES as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, computeEventBindingKey as U, computeFormulaKey as V, computeInputSignalKey as W, computeScrollTriggerKey as X, computed as Y, createInteractiveSignalsAccessor as Z, createScrollProgressHandle as _, type CdlInput as a, hasInteractivePrimitives as a0, sequenceBoardMetrics as a1, sequenceStepId as a2, signal as a3, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeRole as e, type EdgeHead as f, type EdgeHeadFill as g, type CdlState as h, type CdlEventTarget as i, type Computed as j, type CdlDerivedValue as k, type CdlScrollTrigger as l, type CdlDiagramViewProps as m, type LaidEdge as n, type LaidNode as o, type CdlEdge as p, CdlDiagramView as q, type CdlEventBinding as r, type CdlEventKind as s, type CdlFormula as t, type CdlPhase as u, type ChartPieForm as v, EDGE_HEADS as w, EDGE_HEAD_DEFAULT as x, EDGE_HEAD_FILLS as y, EDGE_HEAD_FILL_DEFAULT as z };
2903
+ export { createScrollProgressHandle as $, EDGE_HEAD_FILL_DEFAULT as A, type BBox as B, type CdlDiagram as C, EDGE_REVEALS as D, type EdgeStyle as E, EDGE_REVEAL_DEFAULT as F, EDGE_STYLES as G, type EdgeReveal as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, type InteractiveSignalsAccessor as K, type LaidDiagram as L, type LaidLane as M, type NodeKind as N, NODE_KINDS as O, type ScrollProgressHandle as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, TONES as U, computeEventBindingKey as V, computeFormulaKey as W, computeInputSignalKey as X, computeScrollTriggerKey as Y, computed as Z, createInteractiveSignalsAccessor as _, type CdlInput as a, createScrollProgressSignals as a0, hasInteractivePrimitives as a1, sequenceBoardMetrics as a2, sequenceStepId as a3, signal as a4, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeRole as e, type EdgeHead as f, type EdgeHeadFill as g, type CdlState as h, type CdlEventTarget as i, type Computed as j, type CdlDerivedValue as k, type CdlScrollTrigger as l, type CdlDiagramViewProps as m, type LaidEdge as n, type LaidNode as o, type CdlEdge as p, CdlDiagramView as q, type CdlEventBinding as r, type CdlEventKind as s, type CdlFormula as t, type CdlPhase as u, type ChartPieForm as v, type ChartSlopeForm as w, EDGE_HEADS as x, EDGE_HEAD_DEFAULT as y, EDGE_HEAD_FILLS as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/cdl",
3
- "version": "0.34.0",
3
+ "version": "0.36.0",
4
4
  "description": "CDL (Chainome Diagram Language). Mermaid-like declarative DSL that compiles to animated SVG diagrams. Built for blockchain / Solidity flows, generic enough for sequence / flow / state / ER / topology diagrams.",
5
5
  "license": "MIT",
6
6
  "author": "cardene777",
package/src/index.ts CHANGED
@@ -284,6 +284,7 @@ export type {
284
284
  CdlDiagram,
285
285
  CdlEdge,
286
286
  ChartPieForm,
287
+ ChartSlopeForm,
287
288
  CdlLane,
288
289
  CdlNode,
289
290
  CdlPhase,
@@ -3,6 +3,7 @@ import type { LaidNode, Tone } from "../types";
3
3
  import { TONE, chartSeriesColor } from "../render/tone";
4
4
  import { resolveChartData } from "../render/payload-binding";
5
5
  import { textWidth } from "./text-width";
6
+ import { 実値表記, 割合表記 } from "./chart-number";
6
7
 
7
8
  /**
8
9
  * chart-gauge kind ... 上半分の弧で内訳を示し、 合計を主役に置く図 (cdl#549)。
@@ -217,23 +218,6 @@ function 切り詰める(s: string, 上限: number, 級: number): string {
217
218
  return `${out}…`;
218
219
  }
219
220
 
220
- /**
221
- * 実値の表記。 桁区切りを入れる (`chart-pie` と揃える)。
222
- *
223
- * 小数は 1 桁までに丸める。 図に置く数なので、 桁を尽くすより並びが揃う方が読みやすい。
224
- */
225
- function 実値表記(v: number): string {
226
- return Number.isInteger(v)
227
- ? v.toLocaleString("en-US")
228
- : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
229
- }
230
-
231
- /** 取り分の表記。 整数のとき小数を出さない (`chart-pie` と揃える) */
232
- function 割合表記(frac: number): string {
233
- const v = Math.round(frac * 1000) / 10;
234
- return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
235
- }
236
-
237
221
  /** 弧の色。 明示した色が優先され、 無ければ図表の系列の色を順に配る */
238
222
  function arcColor(tone: Tone | undefined, idx: number): string {
239
223
  if (tone) return TONE[tone];
@@ -1,11 +1,11 @@
1
1
  /**
2
- * 図表に置く数の表記 (cdl#688)。
2
+ * 図表に置く数の表記 (cdl#688 / cdl#689)。
3
3
  *
4
- * **同じ表記を種別ごとに書き写さない**。 いま `実値表記` は 7 つの種別に同じ本体で置かれて
5
- * おり、片方だけ直せば図によって桁区切りの有無が変わる。 新しい種別はここから取る。
4
+ * **同じ表記を種別ごとに書き写さない**。 書き写すと片方だけ直した時に、図によって桁区切りの
5
+ * 有無や小数の桁が変わる。 数を字にする種別はここから取る。
6
6
  *
7
- * 既存の 7 つをここへ寄せるのは #689 で行う = 種別を新設する変更と、既にある種別の
8
- * 内部を組み替える変更を 1 つの取り込みに混ぜない。
7
+ * 寄せる前は各種別が私物の写しを持ち、「`chart-pie` と揃える」 というコメントで揃いを人の目に
8
+ * 委ねていた。 揃っているかは目で確かめるものではなく、1 つしか無いことで保証する。
9
9
  */
10
10
 
11
11
  /**
@@ -18,3 +18,16 @@ export function 実値表記(v: number): string {
18
18
  ? v.toLocaleString("en-US")
19
19
  : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
20
20
  }
21
+
22
+ /**
23
+ * 取り分の表記 (cdl#542)。
24
+ *
25
+ * **整数のとき小数を出さない**。 `toFixed(1)` 固定だと 3 件とも `45.0%` のように無駄な
26
+ * `.0` が付き、桁が増えて読みにくい。 小数を持つ時だけ 1 桁出す。
27
+ *
28
+ * 丸めた結果が整数になる形 (`0.4499` → `45.0`) も整数として出す = 丸めた後の値で判定する。
29
+ */
30
+ export function 割合表記(frac: number): string {
31
+ const v = Math.round(frac * 1000) / 10;
32
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
33
+ }
@@ -4,6 +4,7 @@ import { TONE, chartSeriesColor } from "../render/tone";
4
4
  import { resolveChartData, type ResolvedChartDatum } from "../render/payload-binding";
5
5
  import { 進みを畳む } from "./draw-progress";
6
6
  import { textWidth } from "./text-width";
7
+ import { 実値表記, 割合表記 } from "./chart-number";
7
8
 
8
9
  /**
9
10
  * chart-pie kind ... 1 node に datum 配列 (chartData) を保持し、 SVG path arc で円グラフ描画する。
@@ -702,33 +703,6 @@ function 扇形の切り抜き(cx: number, cy: number, r: number, 開き: number
702
703
  return <path d={d} />;
703
704
  }
704
705
 
705
- /**
706
- * 実値の表記 (cdl#548)。
707
- *
708
- * **桁区切りを入れる**。 同じ repo の折れ線が各点の値を `1,342` の形で置いており、そちらと
709
- * 揃える。 4 桁を超えると区切りの有無で読む速さが変わる。
710
- *
711
- * 小数は 1 桁までに丸める。 図に置く数なので、桁を尽くすより並びが揃う方が読みやすい。
712
- */
713
- function 実値表記(v: number): string {
714
- return Number.isInteger(v)
715
- ? v.toLocaleString("en-US")
716
- : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
717
- }
718
-
719
- /**
720
- * 取り分の表記 (cdl#542)。
721
- *
722
- * **整数のとき小数を出さない**。 `toFixed(1)` 固定だと 3 件とも `45.0%` のように無駄な
723
- * `.0` が付き、桁が増えて読みにくい。 小数を持つ時だけ 1 桁出す。
724
- *
725
- * 丸めた結果が整数になる形 (`0.4499` → `45.0`) も整数として出す = 丸めた後の値で判定する。
726
- */
727
- function 割合表記(frac: number): string {
728
- const v = Math.round(frac * 1000) / 10;
729
- return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
730
- }
731
-
732
706
  /**
733
707
  * 扇の色 (cdl#546)。
734
708
  *
@@ -3,6 +3,7 @@ import type { LaidNode, Tone } from "../types";
3
3
  import { TONE, chartSeriesColor } from "../render/tone";
4
4
  import { resolveChartData } from "../render/payload-binding";
5
5
  import { textWidth } from "./text-width";
6
+ import { 実値表記, 割合表記 } from "./chart-number";
6
7
 
7
8
  /**
8
9
  * chart-radial kind ... 1 件を 1 本の弧にして内側から重ね、 長さで比べる図 (cdl#550)。
@@ -190,19 +191,6 @@ function 弧の道(cx: number, cy: number, 中心半径: number, 幅: number,
190
191
  );
191
192
  }
192
193
 
193
- /** 実値の表記。 桁区切りを入れる (`chart-pie` と揃える) */
194
- function 実値表記(v: number): string {
195
- return Number.isInteger(v)
196
- ? v.toLocaleString("en-US")
197
- : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
198
- }
199
-
200
- /** 取り分の表記。 整数のとき小数を出さない (`chart-pie` と揃える) */
201
- function 割合表記(frac: number): string {
202
- const v = Math.round(frac * 1000) / 10;
203
- return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
204
- }
205
-
206
194
  /** 弧の色。 明示した色が優先され、 無ければ図表の系列の色を順に配る */
207
195
  function arcColor(tone: Tone | undefined, idx: number): string {
208
196
  if (tone) return TONE[tone];
@@ -1,5 +1,5 @@
1
1
  import { type JSX } from "react";
2
- import type { LaidNode, Tone } from "../types";
2
+ import type { ChartSlopeForm, LaidNode, Tone } from "../types";
3
3
  import { TONE, chartSeriesColor } from "../render/tone";
4
4
  import { resolveChartData } from "../render/payload-binding";
5
5
  import { textWidth } from "./text-width";
@@ -42,6 +42,14 @@ import { 進みを畳む, 伸ばすdash } from "./draw-progress";
42
42
  * 値と名前は **別の役割** で出す (`chart-slope-value` / `chart-slope-name`、cdl#693)。
43
43
  * 1 つにまとめると使う側が値だけに字体を当てられず、寸法を記録する側も 2 つの大きさを
44
44
  * 1 行に潰す。 他の図表 (`chart-stat` / `chart-stacked-bar`) も字を役割で分けている。
45
+ *
46
+ * ## 名前は線と同じ色で描く (cdl#698)
47
+ *
48
+ * 名前も値も同じ淡い色にすると、名前と線を突き合わせるのに線を目で辿ることになる。
49
+ * 交差を読ませる図なので、交差した先を追う作業が読み手に残ってしまう。
50
+ *
51
+ * 色を持たせるのは **名前だけ**。 値は太字の濃い色のままにして、数の読み比べを保つ。
52
+ * identity は色が、量は字が担う。
45
53
  */
46
54
 
47
55
  /** 線を引くのに最低限要る横幅。 名札が長い図でもこれだけは残す */
@@ -104,8 +112,32 @@ export function ChartSlopeNode({
104
112
  const yを取る = (v: number): number =>
105
113
  尺の幅 > 0 ? 下端 - ((v - 最小) / 尺の幅) * (下端 - 上端) : (上端 + 下端) / 2;
106
114
 
115
+ /**
116
+ * 見せ方 (cdl#702)。 **型の外の値は `values` に落とす** = 見せ方が決まらないより、
117
+ * 既定の形が出る方がよい (円グラフと同じ判断)。
118
+ *
119
+ * **前の時点を持たない図では `values` に落とす**。 引く相手がいないので、増減を出すと
120
+ * 「0 から増えた」 という書いていない主張になる (前を持たない件を 0 から立ち上げるのは
121
+ * 線を引くための扱いで、前が 0 だったという意味ではない)。
122
+ */
123
+ const 形: ChartSlopeForm = 前あり && node.chartSlopeForm === "delta" ? "delta" : "values";
124
+
125
+ /**
126
+ * 増減の表記。 符号を前に付ける。
127
+ *
128
+ * `0` は `+0` にしない = 動いていないことを「増えた」 と読ませない。
129
+ * 負は `実値表記` が `-` を付けるのでそのまま。
130
+ */
131
+ const 増減表記 = (前: number, 今: number): string => {
132
+ const 差 = 今 - 前;
133
+ return 差 > 0 ? `+${実値表記(差)}` : 実値表記(差);
134
+ };
135
+
107
136
  const 左の字 = 系列たち.map((s) => 実値表記(s.前));
108
- const 右の字 = 系列たち.map((s) => 実値表記(s.今));
137
+ // `delta` は今の値の代わりに増減を出す。 3 つ目の数を足さないので列は 2 つのまま
138
+ const 右の字 = 系列たち.map((s) =>
139
+ 形 === "delta" ? 増減表記(s.前, s.今) : 実値表記(s.今),
140
+ );
109
141
  const 左値幅 = Math.max(0, ...左の字.map((t) => textWidth(t, 値の級)));
110
142
  const 右値幅 = Math.max(0, ...右の字.map((t) => textWidth(t, 値の級)));
111
143
 
@@ -166,7 +198,9 @@ export function ChartSlopeNode({
166
198
  x2={x}
167
199
  y2={下端 + 6}
168
200
  stroke="var(--cdl-divider, #d4d4d8)"
169
- strokeWidth={1}
201
+ // 太さ 1 の罫では柱に見えず、時点の見出しだけが宙に浮く。
202
+ // 系列の線 (2.5) より細いまま、柱として立つ太さにする
203
+ strokeWidth={2}
170
204
  />
171
205
  ))}
172
206
 
@@ -257,7 +291,7 @@ export function ChartSlopeNode({
257
291
  y={左y + 5}
258
292
  textAnchor="end"
259
293
  fontSize={名前の級}
260
- fill="var(--cdl-text-dim, #5a6270)"
294
+ fill={s.色}
261
295
  >
262
296
  {s.名前}
263
297
  </text>
@@ -269,7 +303,7 @@ export function ChartSlopeNode({
269
303
  y={右y + 5}
270
304
  textAnchor="end"
271
305
  fontSize={名前の級}
272
- fill="var(--cdl-text-dim, #5a6270)"
306
+ fill={s.色}
273
307
  >
274
308
  {s.名前}
275
309
  </text>
@@ -278,7 +312,9 @@ export function ChartSlopeNode({
278
312
  {右を出す && (
279
313
  <>
280
314
  <text
281
- data-cdl-role="chart-slope-value"
315
+ // 増減は今の値と意味が違うので役割を分ける (cdl#702)。
316
+ // 消費側が増減だけに色を当てたくなる経路がある
317
+ data-cdl-role={形 === "delta" ? "chart-slope-delta" : "chart-slope-value"}
282
318
  x={右軸x + 軸から値まで}
283
319
  y={右y + 5}
284
320
  fontSize={値の級}
@@ -293,7 +329,7 @@ export function ChartSlopeNode({
293
329
  x={右軸x + 軸から値まで + 右値幅 + 値から名前まで}
294
330
  y={右y + 5}
295
331
  fontSize={名前の級}
296
- fill="var(--cdl-text-dim, #5a6270)"
332
+ fill={s.色}
297
333
  >
298
334
  {s.名前}
299
335
  </text>
@@ -3,6 +3,7 @@ import type { LaidNode, Tone } from "../types";
3
3
  import { TONE, chartSeriesColor } from "../render/tone";
4
4
  import { resolveChartData, type ResolvedChartDatum } from "../render/payload-binding";
5
5
  import { textWidth } from "./text-width";
6
+ import { 実値表記, 割合表記 } from "./chart-number";
6
7
 
7
8
  /**
8
9
  * chart-stacked-bar kind ... 1 本の帯を割合で区切り、時点を並べて変化を見せる図 (cdl#551)。
@@ -214,19 +215,6 @@ function 帯を組む(
214
215
  };
215
216
  }
216
217
 
217
- /** 実値の表記。 桁区切りを入れる (他の図表と揃える) */
218
- function 実値表記(v: number): string {
219
- return Number.isInteger(v)
220
- ? v.toLocaleString("en-US")
221
- : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
222
- }
223
-
224
- /** 取り分の表記。 整数のとき小数を出さない (他の図表と揃える) */
225
- function 割合表記(frac: number): string {
226
- const v = Math.round(frac * 1000) / 10;
227
- return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
228
- }
229
-
230
218
  /** 区画の色。 明示した色が優先され、無ければ図表の系列の色を順に配る */
231
219
  function 印の色(tone: Tone | undefined, idx: number): string {
232
220
  if (tone) return TONE[tone];
@@ -3,6 +3,7 @@ import type { LaidNode, Tone } from "../types";
3
3
  import { TONE, chartSeriesColor } from "../render/tone";
4
4
  import { resolveChartData } from "../render/payload-binding";
5
5
  import { textWidth } from "./text-width";
6
+ import { 実値表記, 割合表記 } from "./chart-number";
6
7
 
7
8
  /**
8
9
  * chart-stat kind ... 数値そのものを主役にする図 (cdl#553)。
@@ -211,19 +212,6 @@ function 弧の道(cx: number, cy: number, r: number, 割合: number): string {
211
212
  return `M ${p(a0)} A ${r} ${r} 0 ${large} 1 ${p(a1)}`;
212
213
  }
213
214
 
214
- /** 実値の表記。 桁区切りを入れる (`chart-pie` / `chart-radial` と揃える) */
215
- export function 実値表記(v: number): string {
216
- return Number.isInteger(v)
217
- ? v.toLocaleString("en-US")
218
- : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
219
- }
220
-
221
- /** 取り分の表記。 整数のとき小数を出さない (`chart-pie` / `chart-radial` と揃える) */
222
- function 割合表記(frac: number): string {
223
- const v = Math.round(frac * 1000) / 10;
224
- return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
225
- }
226
-
227
215
  /** 印の色。 明示した色が優先され、無ければ図表の系列の色を順に配る */
228
216
  function 印の色(tone: Tone | undefined, idx: number): string {
229
217
  if (tone) return TONE[tone];
@@ -3,6 +3,7 @@ import type { LaidNode, Tone } from "../types";
3
3
  import { TONE, chartSeriesColor } from "../render/tone";
4
4
  import { resolveChartData } from "../render/payload-binding";
5
5
  import { textWidth } from "./text-width";
6
+ import { 実値表記 } from "./chart-number";
6
7
 
7
8
  /**
8
9
  * chart-waffle kind ... 100 個の印で割合を **数えて確かめられる** 図 (cdl#552)。
@@ -183,13 +184,6 @@ export function ChartWaffleNode({
183
184
  );
184
185
  }
185
186
 
186
- /** 実値の表記。 桁区切りを入れる (他の図表と揃える) */
187
- function 実値表記(v: number): string {
188
- return Number.isInteger(v)
189
- ? v.toLocaleString("en-US")
190
- : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
191
- }
192
-
193
187
  /** 印の色。 明示した色が優先され、無ければ図表の系列の色を順に配る */
194
188
  function 印の色(tone: Tone | undefined, idx: number): string {
195
189
  if (tone) return TONE[tone];
@@ -58,6 +58,8 @@ type 読まない欄 =
58
58
  | "chartTrace"
59
59
  // 円グラフの見せ方 (#684)。 決まった値のどれかで、字を差し込む先が無い
60
60
  | "chartPieForm"
61
+ // 傾き図の見せ方 (#702)。 同上
62
+ | "chartSlopeForm"
61
63
  | "ganttData"
62
64
  | "ganttAxisMax"
63
65
  | "mindData"
package/src/types.ts CHANGED
@@ -482,6 +482,21 @@ export type CdlNode = {
482
482
  * `previous` (cdl#680) が効くのは `ring` だけ。 他の形は内側の輪を描かない。
483
483
  */
484
484
  chartPieForm?: ChartPieForm;
485
+ /**
486
+ * chart-slope の見せ方 (cdl#702)。 右の列に何の数を出すかを決める。
487
+ *
488
+ * - `values` ... 今の値
489
+ * - `delta` ... 増減 (`+40` / `-90`)
490
+ *
491
+ * 左の列は どちらでも前の値。 `前 + 増減 = 今` なので、 `delta` でも今の値は足せば戻る。
492
+ * 3 つ目の数を足さないので、 名札の高さも線を引く幅も変わらない。
493
+ *
494
+ * 型の外の値は `values` として描く = 見せ方が決まらないより、既定の形が出る方がよい。
495
+ *
496
+ * 前の時点を持たない図 (`previous` が 1 件も無い) は右の列そのものが無いため、
497
+ * この欄を書いても絵は変わらない。
498
+ */
499
+ chartSlopeForm?: ChartSlopeForm;
485
500
  /**
486
501
  * gantt-timeline 専用の task payload。 task 全件を 1 node に格納し、
487
502
  * kinds/gantt.tsx が縦軸 task lane + 横軸日付 rect bar で SVG 描画する。
@@ -541,6 +556,9 @@ export type BoundEnum<T extends string> = T | (string & {});
541
556
  /** chart-pie の見せ方 (cdl#684)。 SSOT は `kinds/chart-pie.tsx` */
542
557
  export type ChartPieForm = "ring" | "arcs" | "table";
543
558
 
559
+ /** chart-slope の見せ方 (cdl#702)。 SSOT は `kinds/chart-slope.tsx` */
560
+ export type ChartSlopeForm = "values" | "delta";
561
+
544
562
  export type ChartDatumPayload = {
545
563
  label: string;
546
564
  /** 棒 / 折れ線 / 扇の大きさ。 `{signal}` で状態に追随する */