@cardenelabs/cdl 0.30.2 → 0.31.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.
- package/CHANGELOG.md +63 -1
- package/dist/index.cjs +438 -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 +438 -278
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +438 -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 +438 -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 +176 -98
- package/src/layout/edges.ts +108 -0
- 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
package/src/render/stage.tsx
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { useMemo, type JSX } from "react";
|
|
2
|
+
import { 折れ線の目盛, type ChartLineScale } from "../kinds/chart-line";
|
|
3
|
+
import { 描く進みに直す } from "../kinds/draw-ratio";
|
|
4
|
+
import { lifelineStartYs, uniformLifelineEndY } from "../layout/lifeline";
|
|
5
|
+
import { buildDiagramAltText } from "../layout/spec";
|
|
2
6
|
import {
|
|
3
7
|
EDGE_HEADS,
|
|
4
8
|
EDGE_HEAD_FILLS,
|
|
@@ -7,13 +11,18 @@ import {
|
|
|
7
11
|
type CdlPhase,
|
|
8
12
|
type LaidDiagram,
|
|
9
13
|
} from "../types";
|
|
14
|
+
import {
|
|
15
|
+
EDGE_HEAD_MUTED_MARKER_ID,
|
|
16
|
+
EDGE_HEAD_SHAPE,
|
|
17
|
+
edgeHeadMarkerId,
|
|
18
|
+
edgeHeadMarkerName,
|
|
19
|
+
edgeHeadPaint,
|
|
20
|
+
} from "./edge-head";
|
|
10
21
|
import { CdlEdgeView, CdlEdgeGlowView, CdlEdgeLabelView } from "./edges";
|
|
11
22
|
import { CdlNodeView } from "./nodes";
|
|
23
|
+
import { resolveChartData } from "./payload-binding";
|
|
12
24
|
import { TONE, TONE_HEX } from "./tone";
|
|
13
|
-
import {
|
|
14
|
-
import { buildDiagramAltText } from "../layout/spec";
|
|
15
|
-
import { lifelineStartYs, uniformLifelineEndY } from "../layout/lifeline";
|
|
16
|
-
import { 描く進みに直す } from "../kinds/draw-ratio";
|
|
25
|
+
import { computeStateValues } from "./utils";
|
|
17
26
|
|
|
18
27
|
export function CdlStage({
|
|
19
28
|
laid,
|
|
@@ -81,6 +90,28 @@ export function CdlStage({
|
|
|
81
90
|
// この phase で左の起点から描き始める node (cdl#512)。 `activate` とは別集合で持つ =
|
|
82
91
|
// 焦点が当たり続ける図で毎 phase 引き直すことになるため、 光っているかを引き金にしない
|
|
83
92
|
const drawSet = new Set(currentPhase?.draw ?? []);
|
|
93
|
+
// 目盛は全 phase を見渡せる stage で一度だけ決める。 node 内で現在値から測ると段ごとに軸が動く。
|
|
94
|
+
const chartLineScales = useMemo(() => {
|
|
95
|
+
const nodes = laid.nodes.filter((node) => node.kind === "chart-line");
|
|
96
|
+
if (nodes.length === 0) return new Map<string, ChartLineScale>();
|
|
97
|
+
|
|
98
|
+
const frames = [
|
|
99
|
+
// phase index -1 はどの段にも入る前の初期値。
|
|
100
|
+
computeStateValues(laid, -1, 0),
|
|
101
|
+
...laid.phases.flatMap((_, phaseIndex) => [
|
|
102
|
+
computeStateValues(laid, phaseIndex, 0),
|
|
103
|
+
computeStateValues(laid, phaseIndex, 1),
|
|
104
|
+
]),
|
|
105
|
+
];
|
|
106
|
+
const scales = new Map<string, ChartLineScale>();
|
|
107
|
+
for (const node of nodes) {
|
|
108
|
+
const values = frames.flatMap((stateValues) =>
|
|
109
|
+
resolveChartData(node.chartData ?? [], stateValues).map((datum) => datum.value),
|
|
110
|
+
);
|
|
111
|
+
scales.set(node.id, 折れ線の目盛(values));
|
|
112
|
+
}
|
|
113
|
+
return scales;
|
|
114
|
+
}, [laid]);
|
|
84
115
|
// 描く対象から見た進み (cdl#570)。 `drawRatio` を書かない phase では `progress` と同値で、
|
|
85
116
|
// 描く速さを phase の長さから切り離すためだけに使う
|
|
86
117
|
const 描く進み = 描く進みに直す(progress, currentPhase?.drawRatio);
|
|
@@ -100,6 +131,67 @@ export function CdlStage({
|
|
|
100
131
|
uniformFooterTop: uniformLifelineEndY(laid.lanes, laid.nodes, starts),
|
|
101
132
|
};
|
|
102
133
|
}, [laid]);
|
|
134
|
+
const edgeHeadMarkers = useMemo(() => {
|
|
135
|
+
const referenced = new Set<string>();
|
|
136
|
+
const add = (
|
|
137
|
+
tone: string,
|
|
138
|
+
head: (typeof laid.edges)[number]["head"],
|
|
139
|
+
fill: (typeof laid.edges)[number]["headFill"],
|
|
140
|
+
): void => {
|
|
141
|
+
for (const small of [false, true]) {
|
|
142
|
+
const id = edgeHeadMarkerName(tone, head, small, fill);
|
|
143
|
+
if (id !== undefined) referenced.add(id);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
for (const edge of laid.edges) {
|
|
147
|
+
add(edge.tone, edge.head, edge.headFill);
|
|
148
|
+
if (edge.tailHead !== undefined) add(edge.tone, edge.tailHead, edge.tailHeadFill);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return Object.entries(TONE).flatMap(([tone, color]) =>
|
|
152
|
+
(
|
|
153
|
+
[
|
|
154
|
+
[false, 14],
|
|
155
|
+
[true, 10],
|
|
156
|
+
] as const
|
|
157
|
+
).flatMap(([small, size]) =>
|
|
158
|
+
EDGE_HEADS.flatMap((head) =>
|
|
159
|
+
EDGE_HEAD_FILLS.map((fill) => {
|
|
160
|
+
const 形 = EDGE_HEAD_SHAPE[head];
|
|
161
|
+
const id = edgeHeadMarkerId(tone, head, small, fill);
|
|
162
|
+
if (!referenced.has(id) || 形.d === "") return null;
|
|
163
|
+
if (fill !== EDGE_HEAD_FILL_DEFAULT && !形.filled) return null;
|
|
164
|
+
const 塗 = edgeHeadPaint(head, fill, color);
|
|
165
|
+
return (
|
|
166
|
+
<marker
|
|
167
|
+
key={id}
|
|
168
|
+
id={id}
|
|
169
|
+
viewBox={`0 0 ${形.w} ${形.h}`}
|
|
170
|
+
refX={形.refX}
|
|
171
|
+
refY={形.h / 2}
|
|
172
|
+
markerWidth={(size * (形.scale ?? 1) * 形.w) / 形.h}
|
|
173
|
+
markerHeight={size * (形.scale ?? 1)}
|
|
174
|
+
markerUnits="userSpaceOnUse"
|
|
175
|
+
orient="auto-start-reverse"
|
|
176
|
+
>
|
|
177
|
+
<path
|
|
178
|
+
data-cdl-role="edge-arrowhead"
|
|
179
|
+
data-cdl-edge-head={head}
|
|
180
|
+
data-cdl-edge-head-fill={fill}
|
|
181
|
+
d={形.d}
|
|
182
|
+
fill={塗.fill}
|
|
183
|
+
stroke={塗.stroke}
|
|
184
|
+
strokeWidth={塗.strokeWidth}
|
|
185
|
+
strokeLinecap={塗.strokeWidth === undefined ? undefined : "round"}
|
|
186
|
+
strokeLinejoin={塗.strokeWidth === undefined ? undefined : "round"}
|
|
187
|
+
/>
|
|
188
|
+
</marker>
|
|
189
|
+
);
|
|
190
|
+
}),
|
|
191
|
+
),
|
|
192
|
+
),
|
|
193
|
+
);
|
|
194
|
+
}, [laid]);
|
|
103
195
|
const diagramScale = laid.diagramScale ?? 1;
|
|
104
196
|
return (
|
|
105
197
|
<div className={compact ? "px-3 py-3" : "px-6 py-6"} style={compact ? undefined : { minHeight: 460 }}>
|
|
@@ -157,55 +249,12 @@ export function CdlStage({
|
|
|
157
249
|
{/* CAR-643 = cdl は geometry only。 shadow / border effect の filter は cdl SVG 内に
|
|
158
250
|
持たず、 consumer app (dragon 等) が独自 filter を CSS 経由で data-cdl-role selector
|
|
159
251
|
に適用する。 marker (cdl-arrow-*) は edge routing の SSOT なので cdl 内に維持。 */}
|
|
160
|
-
{/*
|
|
161
|
-
|
|
162
|
-
(Issue の制約 = 色だけを足す)。 */}
|
|
163
|
-
{Object.entries(TONE).flatMap(([tone, color]) =>
|
|
164
|
-
([["", 14], ["-sm", 10]] as const).flatMap(([suffix, size]) =>
|
|
165
|
-
EDGE_HEADS.flatMap((head) =>
|
|
166
|
-
// 塗り方は形と別の軸 (#578)。 塗らない形では 2 つが同じ名前に畳まれるので、
|
|
167
|
-
// `edgeHeadMarkerId` が返す名前で重複を外す
|
|
168
|
-
EDGE_HEAD_FILLS.map((fill) => {
|
|
169
|
-
const 形 = EDGE_HEAD_SHAPE[head];
|
|
170
|
-
const id = edgeHeadMarkerId(tone, head, suffix === "-sm", fill);
|
|
171
|
-
// 何も描かない端は marker を定義しない (#578)。 線側も参照しない
|
|
172
|
-
if (形.d === "") return null;
|
|
173
|
-
if (fill !== EDGE_HEAD_FILL_DEFAULT && !形.filled) return null;
|
|
174
|
-
const 塗 = edgeHeadPaint(head, fill, color);
|
|
175
|
-
return (
|
|
176
|
-
<marker
|
|
177
|
-
key={id}
|
|
178
|
-
id={id}
|
|
179
|
-
viewBox={`0 0 ${形.w} ${形.h}`}
|
|
180
|
-
refX={形.refX}
|
|
181
|
-
refY={形.h / 2}
|
|
182
|
-
// 枠の縦を 10 に揃えてあるので、横だけが形の比で伸びる
|
|
183
|
-
markerWidth={(size * (形.scale ?? 1) * 形.w) / 形.h}
|
|
184
|
-
markerHeight={size * (形.scale ?? 1)}
|
|
185
|
-
markerUnits="userSpaceOnUse"
|
|
186
|
-
orient="auto-start-reverse"
|
|
187
|
-
>
|
|
188
|
-
<path
|
|
189
|
-
data-cdl-role="edge-arrowhead"
|
|
190
|
-
data-cdl-edge-head={head}
|
|
191
|
-
data-cdl-edge-head-fill={fill}
|
|
192
|
-
d={形.d}
|
|
193
|
-
fill={塗.fill}
|
|
194
|
-
stroke={塗.stroke}
|
|
195
|
-
strokeWidth={塗.strokeWidth}
|
|
196
|
-
strokeLinecap={塗.strokeWidth === undefined ? undefined : "round"}
|
|
197
|
-
strokeLinejoin={塗.strokeWidth === undefined ? undefined : "round"}
|
|
198
|
-
/>
|
|
199
|
-
</marker>
|
|
200
|
-
);
|
|
201
|
-
}),
|
|
202
|
-
),
|
|
203
|
-
),
|
|
204
|
-
)}
|
|
252
|
+
{/* 大小は phase ごとに入れ替わるため、配置が参照する両方を保持する。 */}
|
|
253
|
+
{edgeHeadMarkers}
|
|
205
254
|
{/* tone が TONE 定義に無い edge の受け皿。 visual-validate の tone-marker-ref 軸が
|
|
206
255
|
dead ref を検知するが、 検知するまでの間に矢頭が消えないようにする。 */}
|
|
207
256
|
<marker
|
|
208
|
-
id=
|
|
257
|
+
id={EDGE_HEAD_MUTED_MARKER_ID}
|
|
209
258
|
viewBox="0 0 10 10"
|
|
210
259
|
refX="9"
|
|
211
260
|
refY="5"
|
|
@@ -315,6 +364,7 @@ export function CdlStage({
|
|
|
315
364
|
progress={描く ? 描く進み : progress}
|
|
316
365
|
stateValues={stateValues}
|
|
317
366
|
currentPhaseId={currentPhase?.id}
|
|
367
|
+
chartLineScale={chartLineScales.get(node.id)}
|
|
318
368
|
/>
|
|
319
369
|
);
|
|
320
370
|
return <g key={node.id}>{view}</g>;
|
|
@@ -34,6 +34,7 @@ const NUMERIC_FIELDS = ["opacity", "renderOffsetX", "renderOffsetY"] as const;
|
|
|
34
34
|
* |---|---|
|
|
35
35
|
* | `id` / `lane` / `kind` / `role` / `tone` | 名前や区分で、 描画側が置換に掛けない |
|
|
36
36
|
* | `stack` / `w` / `h` / `pos*` / `ganttAxisMax` | 数のみ。 型が `number` で文字を受けない |
|
|
37
|
+
* | `chartFillUnder` / `chartValueRise` / `chartTrace` | 動きを選ぶ真偽値で、文字を受けない |
|
|
37
38
|
* | `shape` | 入れ子の構造。 下の `shapeTexts` が中の文字を全部拾う |
|
|
38
39
|
* | `*Data` | 図表 payload。 入れ子の構造で、 下の `payloadTexts` が中の文字を拾う |
|
|
39
40
|
*/
|
|
@@ -52,6 +53,9 @@ type 読まない欄 =
|
|
|
52
53
|
| "tone"
|
|
53
54
|
| "shape"
|
|
54
55
|
| "chartData"
|
|
56
|
+
| "chartFillUnder"
|
|
57
|
+
| "chartValueRise"
|
|
58
|
+
| "chartTrace"
|
|
55
59
|
| "ganttData"
|
|
56
60
|
| "ganttAxisMax"
|
|
57
61
|
| "mindData"
|
package/src/types.ts
CHANGED
|
@@ -463,6 +463,12 @@ export type CdlNode = {
|
|
|
463
463
|
* 数値 chart の全 datum を 1 node に格納し、 kinds/chart-*.tsx が自己完結で SVG 描画する。
|
|
464
464
|
*/
|
|
465
465
|
chartData?: ChartDatumPayload[];
|
|
466
|
+
/** chart-line の線から下を、上端 0.22 から下端 0 へ薄く塗る */
|
|
467
|
+
chartFillUnder?: boolean;
|
|
468
|
+
/** chart-line の値を、点への到着直後だけ下からせり上げる */
|
|
469
|
+
chartValueRise?: boolean;
|
|
470
|
+
/** chart-line を描き切った後、粒で経路をなぞって点を順に出す */
|
|
471
|
+
chartTrace?: boolean;
|
|
466
472
|
/**
|
|
467
473
|
* gantt-timeline 専用の task payload。 task 全件を 1 node に格納し、
|
|
468
474
|
* kinds/gantt.tsx が縦軸 task lane + 横軸日付 rect bar で SVG 描画する。
|