@cardenelabs/cdl 0.30.3 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -1
- package/dist/index.cjs +397 -278
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +397 -278
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +397 -278
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +397 -278
- package/dist/react.js.map +1 -1
- package/dist/{render-CabTMeao.d.cts → render-D6wVFGfI.d.cts} +6 -0
- package/dist/{render-CabTMeao.d.ts → render-D6wVFGfI.d.ts} +6 -0
- package/package.json +1 -1
- package/src/kinds/chart-line.tsx +178 -89
- package/src/render/edge-head.ts +23 -1
- package/src/render/edges.tsx +8 -14
- package/src/render/nodes.tsx +4 -1
- package/src/render/stage.tsx +100 -50
- package/src/render/template-fields.ts +4 -0
- package/src/types.ts +6 -0
|
@@ -405,6 +405,12 @@ type CdlNode = {
|
|
|
405
405
|
* 数値 chart の全 datum を 1 node に格納し、 kinds/chart-*.tsx が自己完結で SVG 描画する。
|
|
406
406
|
*/
|
|
407
407
|
chartData?: ChartDatumPayload[];
|
|
408
|
+
/** chart-line の線から下を、上端 0.22 から下端 0 へ薄く塗る */
|
|
409
|
+
chartFillUnder?: boolean;
|
|
410
|
+
/** chart-line の値を、点への到着直後だけ下からせり上げる */
|
|
411
|
+
chartValueRise?: boolean;
|
|
412
|
+
/** chart-line を描き切った後、粒で経路をなぞって点を順に出す */
|
|
413
|
+
chartTrace?: boolean;
|
|
408
414
|
/**
|
|
409
415
|
* gantt-timeline 専用の task payload。 task 全件を 1 node に格納し、
|
|
410
416
|
* kinds/gantt.tsx が縦軸 task lane + 横軸日付 rect bar で SVG 描画する。
|
|
@@ -405,6 +405,12 @@ type CdlNode = {
|
|
|
405
405
|
* 数値 chart の全 datum を 1 node に格納し、 kinds/chart-*.tsx が自己完結で SVG 描画する。
|
|
406
406
|
*/
|
|
407
407
|
chartData?: ChartDatumPayload[];
|
|
408
|
+
/** chart-line の線から下を、上端 0.22 から下端 0 へ薄く塗る */
|
|
409
|
+
chartFillUnder?: boolean;
|
|
410
|
+
/** chart-line の値を、点への到着直後だけ下からせり上げる */
|
|
411
|
+
chartValueRise?: boolean;
|
|
412
|
+
/** chart-line を描き切った後、粒で経路をなぞって点を順に出す */
|
|
413
|
+
chartTrace?: boolean;
|
|
408
414
|
/**
|
|
409
415
|
* gantt-timeline 専用の task payload。 task 全件を 1 node に格納し、
|
|
410
416
|
* kinds/gantt.tsx が縦軸 task lane + 横軸日付 rect bar で SVG 描画する。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/cdl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.1",
|
|
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/kinds/chart-line.tsx
CHANGED
|
@@ -3,6 +3,36 @@ import type { LaidNode } from "../types";
|
|
|
3
3
|
import { resolveChartData } from "../render/payload-binding";
|
|
4
4
|
import { 進みを畳む, 伸ばすdash } from "./draw-progress";
|
|
5
5
|
|
|
6
|
+
export type ChartLineScale = { min: number; max: number; ticks: number[] };
|
|
7
|
+
|
|
8
|
+
const 数を書く = (value: number): string =>
|
|
9
|
+
value.toLocaleString("en-US", { maximumFractionDigits: 12 });
|
|
10
|
+
|
|
11
|
+
export function 折れ線の目盛(values: readonly number[]): ChartLineScale {
|
|
12
|
+
let rawMin = values.length > 0 ? Math.min(...values) : 0;
|
|
13
|
+
let rawMax = values.length > 0 ? Math.max(...values) : 1;
|
|
14
|
+
if (rawMin === rawMax) {
|
|
15
|
+
const room = 10 ** Math.floor(Math.log10(Math.abs(rawMin) || 1) - 1);
|
|
16
|
+
rawMin -= room;
|
|
17
|
+
rawMax += room;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const roughStep = (rawMax - rawMin) / 4;
|
|
21
|
+
const power = 10 ** Math.floor(Math.log10(roughStep));
|
|
22
|
+
const fraction = roughStep / power;
|
|
23
|
+
const niceFraction =
|
|
24
|
+
fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10;
|
|
25
|
+
const step = niceFraction * power;
|
|
26
|
+
const min = Math.floor(rawMin / step) * step;
|
|
27
|
+
const max = Math.ceil(rawMax / step) * step;
|
|
28
|
+
const tickCount = Math.round((max - min) / step);
|
|
29
|
+
const ticks = Array.from({ length: tickCount + 1 }, (_, i) => {
|
|
30
|
+
const value = min + step * i;
|
|
31
|
+
return Math.abs(value) < step * 1e-12 ? 0 : value;
|
|
32
|
+
});
|
|
33
|
+
return { min, max, ticks };
|
|
34
|
+
}
|
|
35
|
+
|
|
6
36
|
/**
|
|
7
37
|
* chart-line kind ... 1 node に datum 配列 (chartData) を保持し、 SVG polyline で折れ線描画する。
|
|
8
38
|
* layout は node bbox (node.w × node.h) 内側に padding (top/right/bottom/left) を確保し、
|
|
@@ -18,12 +48,15 @@ export function ChartLineNode({
|
|
|
18
48
|
node,
|
|
19
49
|
active,
|
|
20
50
|
stateValues = {},
|
|
51
|
+
scale: fixedScale,
|
|
21
52
|
drawing = false,
|
|
22
53
|
progress = 1,
|
|
23
54
|
}: {
|
|
24
55
|
node: LaidNode;
|
|
25
56
|
active: boolean;
|
|
26
57
|
stateValues?: Record<string, string>;
|
|
58
|
+
/** 全 phase を通して固定する目盛。 単独描画では現在の系列から決める */
|
|
59
|
+
scale?: ChartLineScale;
|
|
27
60
|
/**
|
|
28
61
|
* この phase の `draw` に載っているか (cdl#512)。 true の間だけ折れ線が左の起点から
|
|
29
62
|
* 伸び、 点と値の数字は線の先が自分の位置に届いた時に現れる。
|
|
@@ -43,10 +76,8 @@ export function ChartLineNode({
|
|
|
43
76
|
const canvasW = node.w - PAD_LEFT - PAD_RIGHT;
|
|
44
77
|
const canvasH = node.h - PAD_TOP - PAD_BOTTOM;
|
|
45
78
|
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
const vMax = values.length > 0 ? Math.max(...values) : 1;
|
|
49
|
-
const vRange = vMax - vMin || 1;
|
|
79
|
+
const scale = fixedScale ?? 折れ線の目盛(data.map((d) => d.value));
|
|
80
|
+
const vRange = scale.max - scale.min;
|
|
50
81
|
|
|
51
82
|
// 最大値 / 最小値の点が描画領域の上下端に張り付くと、 値 label が線に重なる。
|
|
52
83
|
// 上下に label 1 行ぶんの余白を確保して、 その内側に折れ線を描く。
|
|
@@ -54,50 +85,59 @@ export function ChartLineNode({
|
|
|
54
85
|
const plotTop = PAD_TOP + LABEL_ROOM;
|
|
55
86
|
const plotH = Math.max(canvasH - LABEL_ROOM * 2, 1);
|
|
56
87
|
|
|
88
|
+
const POINT_EDGE_ROOM = 24;
|
|
89
|
+
const plotW = Math.max(canvasW - POINT_EDGE_ROOM * 2, 1);
|
|
57
90
|
const xAt = (idx: number) =>
|
|
58
|
-
PAD_LEFT + (data.length <= 1 ?
|
|
59
|
-
const yAt = (v: number) => plotTop + plotH - ((v -
|
|
91
|
+
PAD_LEFT + POINT_EDGE_ROOM + (data.length <= 1 ? plotW / 2 : (plotW * idx) / (data.length - 1));
|
|
92
|
+
const yAt = (v: number) => plotTop + plotH - ((v - scale.min) / vRange) * plotH;
|
|
60
93
|
|
|
61
|
-
const
|
|
94
|
+
const plotBottom = PAD_TOP + canvasH;
|
|
62
95
|
|
|
63
96
|
// dash は polyline の実際の経路長で進むため、 点の表示判定も同じ経路長に揃える。
|
|
64
97
|
// 点番号の比率では、 急傾斜と平坦な区間が混ざる線で先端と点がずれる。
|
|
65
|
-
const 点までの長さ: number[] = [];
|
|
66
98
|
let 線の全長 = 0;
|
|
67
99
|
let 前の点: { x: number; y: number } | undefined;
|
|
68
|
-
|
|
69
|
-
const 今の点 = { x: xAt(idx), y: yAt(datum.value) };
|
|
100
|
+
const 描画点 = data.map((datum, idx) => {
|
|
101
|
+
const 今の点 = { datum, x: xAt(idx), y: yAt(datum.value), ここまでの長さ: 0 };
|
|
70
102
|
if (前の点) {
|
|
71
103
|
線の全長 += Math.hypot(今の点.x - 前の点.x, 今の点.y - 前の点.y);
|
|
72
104
|
}
|
|
73
|
-
|
|
105
|
+
今の点.ここまでの長さ = 線の全長;
|
|
74
106
|
前の点 = 今の点;
|
|
75
|
-
|
|
107
|
+
return 今の点;
|
|
108
|
+
});
|
|
109
|
+
const points = 描画点.map((点) => `${点.x},${点.y}`).join(" ");
|
|
76
110
|
|
|
77
|
-
/**
|
|
78
|
-
const
|
|
111
|
+
/** phase がどこまで進んだか (0..1、 cdl#512)。 畳み方は `draw-progress.ts` が持つ */
|
|
112
|
+
const 段の進み = 進みを畳む(drawing, progress);
|
|
113
|
+
const 粒を走らせる = drawing && node.chartTrace === true;
|
|
114
|
+
// 0.5 で線を完成させてから 0.55 まで間を置くため、線と粒の順が混ざらない。
|
|
115
|
+
const 伸び = 粒を走らせる ? Math.min(1, 段の進み / 0.5) : 段の進み;
|
|
116
|
+
const 粒の進み = 粒を走らせる ? Math.min(1, Math.max(0, (段の進み - 0.55) / 0.45)) : 伸び;
|
|
117
|
+
const 粒が出る = 粒を走らせる && 段の進み >= 0.55 && 段の進み < 1;
|
|
118
|
+
const 到着窓 = 0.12;
|
|
79
119
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
});
|
|
120
|
+
let 粒の位置: { x: number; y: number } | undefined;
|
|
121
|
+
const 最初の点 = 描画点[0];
|
|
122
|
+
if (粒が出る && 最初の点) {
|
|
123
|
+
const 粒までの長さ = 粒の進み * 線の全長;
|
|
124
|
+
let 区間の前 = 最初の点;
|
|
125
|
+
let 区間の後 = 最初の点;
|
|
126
|
+
for (const 点 of 描画点.slice(1)) {
|
|
127
|
+
区間の後 = 点;
|
|
128
|
+
if (点.ここまでの長さ >= 粒までの長さ) break;
|
|
129
|
+
区間の前 = 点;
|
|
130
|
+
}
|
|
131
|
+
const 区間の始め = 区間の前.ここまでの長さ;
|
|
132
|
+
const 区間の長さ = 区間の後.ここまでの長さ - 区間の始め;
|
|
133
|
+
const 区間の進み = 区間の長さ === 0 ? 0 : (粒までの長さ - 区間の始め) / 区間の長さ;
|
|
134
|
+
粒の位置 = {
|
|
135
|
+
x: 区間の前.x + (区間の後.x - 区間の前.x) * 区間の進み,
|
|
136
|
+
y: 区間の前.y + (区間の後.y - 区間の前.y) * 区間の進み,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const gridTicks = scale.ticks.map((value) => ({ y: yAt(value), value }));
|
|
101
141
|
|
|
102
142
|
return (
|
|
103
143
|
<g transform={`translate(${x0} ${y0})`}>
|
|
@@ -109,8 +149,8 @@ export function ChartLineNode({
|
|
|
109
149
|
height={node.h}
|
|
110
150
|
rx={16}
|
|
111
151
|
fill="var(--cdl-node-fill, #ffffff)"
|
|
112
|
-
stroke=
|
|
113
|
-
strokeWidth={active ?
|
|
152
|
+
stroke="var(--cdl-divider, #d4d4d8)"
|
|
153
|
+
strokeWidth={active ? 1.5 : 1}
|
|
114
154
|
/>
|
|
115
155
|
{gridTicks.map((t, i) => (
|
|
116
156
|
<g key={`grid-${i}`}>
|
|
@@ -131,35 +171,41 @@ export function ChartLineNode({
|
|
|
131
171
|
textAnchor="end"
|
|
132
172
|
fill="var(--cdl-text-dim, #5a6270)"
|
|
133
173
|
>
|
|
134
|
-
{
|
|
174
|
+
{数を書く(t.value)}
|
|
135
175
|
</text>
|
|
136
176
|
</g>
|
|
137
177
|
))}
|
|
138
178
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
179
|
+
{node.chartFillUnder && data.length > 1 && (
|
|
180
|
+
<>
|
|
181
|
+
<defs>
|
|
182
|
+
<linearGradient
|
|
183
|
+
id={`chart-line-fill-${node.id}`}
|
|
184
|
+
gradientUnits="userSpaceOnUse"
|
|
185
|
+
x1={0}
|
|
186
|
+
y1={plotTop}
|
|
187
|
+
x2={0}
|
|
188
|
+
y2={plotBottom}
|
|
189
|
+
>
|
|
190
|
+
<stop offset="0%" stopColor="var(--cdl-tone-accent, #2d6a8f)" stopOpacity={0.22} />
|
|
191
|
+
<stop offset="100%" stopColor="var(--cdl-tone-accent, #2d6a8f)" stopOpacity={0} />
|
|
192
|
+
</linearGradient>
|
|
193
|
+
</defs>
|
|
194
|
+
<path
|
|
195
|
+
data-cdl-role="chart-line-fill-under"
|
|
196
|
+
d={`M ${xAt(0)} ${plotBottom} L ${points.replaceAll(",", " ")} L ${xAt(data.length - 1)} ${plotBottom} Z`}
|
|
197
|
+
fill={`url(#chart-line-fill-${node.id})`}
|
|
198
|
+
stroke="none"
|
|
199
|
+
/>
|
|
200
|
+
</>
|
|
201
|
+
)}
|
|
156
202
|
{data.length > 1 && (
|
|
157
203
|
<polyline
|
|
158
204
|
data-cdl-role="chart-line"
|
|
159
205
|
points={points}
|
|
160
206
|
fill="none"
|
|
161
207
|
stroke="var(--cdl-tone-accent, #2d6a8f)"
|
|
162
|
-
strokeWidth={2
|
|
208
|
+
strokeWidth={active ? 3 : 2}
|
|
163
209
|
strokeLinejoin="round"
|
|
164
210
|
strokeLinecap="round"
|
|
165
211
|
// 伸ばすのは dash で行い、 **`points` は触らない** (cdl#512)。 点を削る形にすると
|
|
@@ -172,53 +218,96 @@ export function ChartLineNode({
|
|
|
172
218
|
{...伸ばすdash(drawing, 伸び)}
|
|
173
219
|
/>
|
|
174
220
|
)}
|
|
175
|
-
{
|
|
176
|
-
|
|
177
|
-
|
|
221
|
+
{粒の位置 && (
|
|
222
|
+
<circle
|
|
223
|
+
data-cdl-role="chart-line-trace"
|
|
224
|
+
cx={粒の位置.x}
|
|
225
|
+
cy={粒の位置.y}
|
|
226
|
+
r={4.5}
|
|
227
|
+
fill="var(--cdl-now)"
|
|
228
|
+
/>
|
|
229
|
+
)}
|
|
230
|
+
{描画点.map(({ datum: d, x: cx, y: cy, ここまでの長さ }, idx) => {
|
|
178
231
|
// value label は marker の上に置くのが基本、 canvas 上端 6px より内側になる場合は
|
|
179
232
|
// 下に反転して他要素と重ならないようにする
|
|
180
233
|
// 折れ線に重ならない側へ置く。 山 (両隣より高い) なら上、 谷なら下。
|
|
181
234
|
// 単調な区間では上に置く。 上下端には LABEL_ROOM を確保してあるので反転は不要。
|
|
182
|
-
const prev =
|
|
183
|
-
const next =
|
|
235
|
+
const prev = data[idx - 1]?.value;
|
|
236
|
+
const next = data[idx + 1]?.value;
|
|
184
237
|
const isValley =
|
|
185
238
|
(prev === undefined || d.value <= prev) && (next === undefined || d.value <= next);
|
|
186
239
|
const labelAbove = !isValley;
|
|
187
240
|
const labelY = labelAbove ? cy - 12 : cy + 18;
|
|
188
241
|
// 点と値の数字は線の先に合わせて現れる。 **横軸の名前は最初から出す** =
|
|
189
242
|
// 名前は図の枠 (軸 / 格子) の側で、 これが順に増えると軸そのものが伸びて見える
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
243
|
+
const 到着後 = 線の全長 === 0 ? 粒の進み : 粒の進み - ここまでの長さ / 線の全長;
|
|
244
|
+
// 粒を使う図は線を描き切ってから点を出す。 左端は粒の開始と同時に出す。
|
|
245
|
+
const 出す = !drawing || ((!粒を走らせる || 段の進み >= 0.55) && 到着後 >= 0);
|
|
246
|
+
// ちょうど 0.12 は窓の外に含め、輪と到着色を残さない。
|
|
247
|
+
const 光る = drawing && 出す && 到着後 < 到着窓;
|
|
248
|
+
const 光の進み = 光る ? 到着後 / 到着窓 : 1;
|
|
249
|
+
let 点と値: JSX.Element | undefined;
|
|
250
|
+
if (出す) {
|
|
251
|
+
const 光の半径 = 6 + 16 * 光の進み;
|
|
252
|
+
const 値 = (
|
|
253
|
+
<text
|
|
254
|
+
data-cdl-role="chart-line-value"
|
|
255
|
+
x={cx}
|
|
256
|
+
y={labelY}
|
|
257
|
+
fontSize={11}
|
|
258
|
+
fontWeight={600}
|
|
259
|
+
textAnchor="middle"
|
|
260
|
+
fill="var(--cdl-text, #1a1f2a)"
|
|
261
|
+
>
|
|
262
|
+
{数を書く(d.value)}
|
|
263
|
+
</text>
|
|
264
|
+
);
|
|
265
|
+
点と値 = (
|
|
266
|
+
<>
|
|
267
|
+
{光る && (
|
|
268
|
+
// marker の `circle` を数える利用側へ混ぜず、専用 role の等径 ellipse として輪を出す。
|
|
269
|
+
<ellipse
|
|
270
|
+
data-cdl-role="chart-line-arrival-ring"
|
|
204
271
|
cx={cx}
|
|
205
272
|
cy={cy}
|
|
206
|
-
|
|
207
|
-
|
|
273
|
+
rx={光の半径}
|
|
274
|
+
ry={光の半径}
|
|
275
|
+
fill="none"
|
|
276
|
+
stroke="var(--cdl-now)"
|
|
277
|
+
strokeWidth={2}
|
|
278
|
+
opacity={0.85 * (1 - 光の進み)}
|
|
208
279
|
/>
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
280
|
+
)}
|
|
281
|
+
<circle
|
|
282
|
+
cx={cx}
|
|
283
|
+
cy={cy}
|
|
284
|
+
r={5}
|
|
285
|
+
fill="var(--cdl-node-fill, #ffffff)"
|
|
286
|
+
stroke={光る ? "var(--cdl-now)" : "var(--cdl-tone-accent, #2d6a8f)"}
|
|
287
|
+
strokeWidth={2.5}
|
|
288
|
+
/>
|
|
289
|
+
<circle
|
|
290
|
+
cx={cx}
|
|
291
|
+
cy={cy}
|
|
292
|
+
r={2.5}
|
|
293
|
+
fill={光る ? "var(--cdl-now)" : "var(--cdl-tone-accent, #2d6a8f)"}
|
|
294
|
+
/>
|
|
295
|
+
{node.chartValueRise && 光る ? (
|
|
296
|
+
<g
|
|
297
|
+
data-cdl-role="chart-line-value-rise"
|
|
298
|
+
transform={`translate(0 ${8 * (1 - 光の進み)})`}
|
|
217
299
|
>
|
|
218
|
-
{
|
|
219
|
-
</
|
|
220
|
-
|
|
221
|
-
|
|
300
|
+
{値}
|
|
301
|
+
</g>
|
|
302
|
+
) : (
|
|
303
|
+
値
|
|
304
|
+
)}
|
|
305
|
+
</>
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
return (
|
|
309
|
+
<g key={`pt-${idx}`} data-cdl-unresolved={d.unresolved ? "true" : undefined}>
|
|
310
|
+
{点と値}
|
|
222
311
|
<text
|
|
223
312
|
x={cx}
|
|
224
313
|
y={PAD_TOP + canvasH + 20}
|
package/src/render/edge-head.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
EDGE_HEAD_DEFAULT,
|
|
3
|
+
EDGE_HEAD_FILL_DEFAULT,
|
|
4
|
+
type EdgeHead,
|
|
5
|
+
type EdgeHeadFill,
|
|
6
|
+
} from "../types";
|
|
7
|
+
import { hasTone } from "./tone";
|
|
8
|
+
|
|
9
|
+
export const EDGE_HEAD_MUTED_MARKER_ID = "cdl-arrow-muted";
|
|
2
10
|
|
|
3
11
|
/**
|
|
4
12
|
* 関係の端の形の **描き方と marker の名前** (SSOT、 #560)。
|
|
@@ -88,6 +96,20 @@ export function edgeHeadMarkerId(
|
|
|
88
96
|
: `cdl-arrow-${tone}-${head}${塗}${小}`;
|
|
89
97
|
}
|
|
90
98
|
|
|
99
|
+
/** 辺の端が実際に参照する marker 名。定義側と描画側で同じ判定を使う。 */
|
|
100
|
+
export function edgeHeadMarkerName(
|
|
101
|
+
tone: string,
|
|
102
|
+
head: EdgeHead | undefined,
|
|
103
|
+
small: boolean,
|
|
104
|
+
fill: EdgeHeadFill | undefined,
|
|
105
|
+
): string | undefined {
|
|
106
|
+
const 実際の形 = head ?? EDGE_HEAD_DEFAULT;
|
|
107
|
+
if (実際の形 === "none") return undefined;
|
|
108
|
+
return hasTone(tone)
|
|
109
|
+
? edgeHeadMarkerId(tone, 実際の形, small, fill ?? EDGE_HEAD_FILL_DEFAULT)
|
|
110
|
+
: EDGE_HEAD_MUTED_MARKER_ID;
|
|
111
|
+
}
|
|
112
|
+
|
|
91
113
|
/**
|
|
92
114
|
* marker を 1 つ描くのに要る 4 つ。 定義側 (`render/stage.tsx`) が引く。
|
|
93
115
|
*
|
package/src/render/edges.tsx
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { JSX } from "react";
|
|
2
|
-
import { EDGE_HEAD_DEFAULT, EDGE_HEAD_FILL_DEFAULT, type LaidEdge } from "../types";
|
|
3
|
-
import { edgeHeadMarkerId } from "./edge-head";
|
|
4
2
|
import { computeLabelBBoxWorld, hasRenderedLabel, LABEL_PILL_PAD_X } from "../layout/spec";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
3
|
+
import type { EdgeRole, LaidEdge, Tone } from "../types";
|
|
4
|
+
import { edgeHeadMarkerName } from "./edge-head";
|
|
5
|
+
import { toneColor } from "./tone";
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* 辺の色 (#618)。 役目を書いた辺だけ「いま」 の色で引く。
|
|
@@ -75,18 +74,13 @@ export function CdlEdgeView({
|
|
|
75
74
|
// その色なら 0.9 で 4.51-4.92 と 4.5:1 を満たす (0.8 では 3.69-4.04 で届かない)。
|
|
76
75
|
// 実線と点線で同じ組を使い、 光らせた側が薄くなる逆転を作らない。
|
|
77
76
|
// 端の形は線の種類と別の軸 (#560)。 書かなければ既定の塗った三角で、名前も従来のまま
|
|
78
|
-
const
|
|
79
|
-
const 形 = h ?? EDGE_HEAD_DEFAULT;
|
|
80
|
-
// 何も描かない端は marker を持たない (#578)。 参照すると解決できない url が残る
|
|
81
|
-
if (形 === "none") return undefined;
|
|
82
|
-
return hasTone(edge.tone)
|
|
83
|
-
? edgeHeadMarkerId(edge.tone, 形, !active, f ?? EDGE_HEAD_FILL_DEFAULT)
|
|
84
|
-
: "cdl-arrow-muted";
|
|
85
|
-
};
|
|
86
|
-
const marker = 端の名前(edge.head, edge.headFill);
|
|
77
|
+
const marker = edgeHeadMarkerName(edge.tone, edge.head, !active, edge.headFill);
|
|
87
78
|
// 出どころ側の印 (#578)。 marker は経路の向きに従って回るので、始点に置いた印は
|
|
88
79
|
// 自動で外向きになる (`orient="auto-start-reverse"`)。 書かない図では端が無い
|
|
89
|
-
const tailMarker =
|
|
80
|
+
const tailMarker =
|
|
81
|
+
edge.tailHead === undefined
|
|
82
|
+
? undefined
|
|
83
|
+
: edgeHeadMarkerName(edge.tone, edge.tailHead, !active, edge.tailHeadFill);
|
|
90
84
|
|
|
91
85
|
const style = edge.style ?? "solid";
|
|
92
86
|
const isDotted = style === "dotted-flow";
|
package/src/render/nodes.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import { StorageNode } from "../kinds/storage";
|
|
|
8
8
|
import { GenericNode } from "../kinds/generic";
|
|
9
9
|
import { MarkStartNode, MarkEndNode } from "../kinds/terminal-mark";
|
|
10
10
|
import { DynShapeNode } from "../kinds/dyn-shape";
|
|
11
|
-
import { ChartLineNode } from "../kinds/chart-line";
|
|
11
|
+
import { ChartLineNode, type ChartLineScale } from "../kinds/chart-line";
|
|
12
12
|
import { ChartPieNode } from "../kinds/chart-pie";
|
|
13
13
|
import { ChartGaugeNode } from "../kinds/chart-gauge";
|
|
14
14
|
import { ChartRadialNode } from "../kinds/chart-radial";
|
|
@@ -95,6 +95,7 @@ export function CdlNodeView({
|
|
|
95
95
|
progress,
|
|
96
96
|
stateValues,
|
|
97
97
|
currentPhaseId,
|
|
98
|
+
chartLineScale,
|
|
98
99
|
}: {
|
|
99
100
|
node: LaidNode;
|
|
100
101
|
active: boolean;
|
|
@@ -106,6 +107,7 @@ export function CdlNodeView({
|
|
|
106
107
|
progress: number;
|
|
107
108
|
stateValues: Record<string, string>;
|
|
108
109
|
currentPhaseId: string | undefined;
|
|
110
|
+
chartLineScale?: ChartLineScale;
|
|
109
111
|
}): JSX.Element {
|
|
110
112
|
const value = node.value ? interpolate(node.value, stateValues) : undefined;
|
|
111
113
|
const rows = (node.rows ?? []).map((r) => interpolate(r, stateValues));
|
|
@@ -175,6 +177,7 @@ export function CdlNodeView({
|
|
|
175
177
|
node={resolvedNode}
|
|
176
178
|
active={active}
|
|
177
179
|
stateValues={stateValues}
|
|
180
|
+
scale={chartLineScale}
|
|
178
181
|
drawing={drawing}
|
|
179
182
|
progress={progress}
|
|
180
183
|
/>
|