@cardenelabs/cdl 0.22.0 → 0.24.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.
@@ -109,6 +109,8 @@ type Side = "top" | "right" | "bottom" | "left";
109
109
  * ER の「識別しない」 のように **刻みが意味を持つ関係** はこちらを使う。
110
110
  */
111
111
  type EdgeStyle = "solid" | "dotted-flow" | "dashed";
112
+ /** 辺の役目 (#618)。 `main` = 図の主となる道 */
113
+ type EdgeRole = "main";
112
114
  /**
113
115
  * 線の種類の全種 (#578)。 **型だけでなく実体を持つ**。
114
116
  *
@@ -572,6 +574,21 @@ type CdlEdge = {
572
574
  side?: Side;
573
575
  /** visual style、 default "solid" */
574
576
  style?: EdgeStyle;
577
+ /**
578
+ * 辺の役目 (#618)。 書かなければ従来どおり tone の色で引く。
579
+ *
580
+ * `main` を書いた辺だけ「いま」 の色 (`--cdl-now`) で引く。 図の中で 1 本の道を
581
+ * 目立たせ、 どこから読むかを決めるための口。 すべての辺に書くと差が消えるので、
582
+ * 主となる 1 本 (または 1 続き) にだけ書く。
583
+ */
584
+ role?: EdgeRole;
585
+ /**
586
+ * 名前の下地を敷くか (#618)。 書かなければ敷く (従来どおり)。
587
+ *
588
+ * 丸い下地は箱と同じ形なので、 名前が小さな箱に見える。 罫の細い図では外したほうが
589
+ * 線と名前の区別が付く。
590
+ */
591
+ labelPlate?: boolean;
575
592
  /** 端の形、 default "triangle" (#560)。 線の種類とは別の軸 */
576
593
  head?: EdgeHead;
577
594
  /**
@@ -2810,4 +2827,4 @@ type CdlDiagramViewProps = {
2810
2827
  };
2811
2828
  declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
2812
2829
 
2813
- export { sequenceBoardMetrics as $, EDGE_STYLES as A, type BBox as B, type CdlDiagram as C, type EdgeReveal as D, type EdgeStyle as E, type InteractiveSignalsAccessor as F, type LaidLane as G, NODE_KINDS as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, type ScrollProgressHandle as K, type LaidDiagram as L, TONES as M, type NodeKind as N, computeEventBindingKey as O, computeFormulaKey as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, computeInputSignalKey as U, computeScrollTriggerKey as V, computed as W, createInteractiveSignalsAccessor as X, createScrollProgressHandle as Y, createScrollProgressSignals as Z, hasInteractivePrimitives as _, type CdlInput as a, sequenceStepId as a0, signal as a1, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeHead as e, type EdgeHeadFill as f, type CdlState as g, type CdlEventTarget as h, type Computed as i, type CdlDerivedValue as j, type CdlScrollTrigger as k, type CdlDiagramViewProps as l, type LaidEdge as m, type LaidNode as n, type CdlEdge as o, CdlDiagramView as p, type CdlEventBinding as q, type CdlEventKind as r, type CdlFormula as s, type CdlPhase as t, EDGE_HEADS as u, EDGE_HEAD_DEFAULT as v, EDGE_HEAD_FILLS as w, EDGE_HEAD_FILL_DEFAULT as x, EDGE_REVEALS as y, EDGE_REVEAL_DEFAULT as z };
2830
+ export { hasInteractivePrimitives as $, EDGE_REVEAL_DEFAULT as A, type BBox as B, type CdlDiagram as C, EDGE_STYLES as D, type EdgeStyle as E, type EdgeReveal as F, type InteractiveSignalsAccessor as G, type LaidLane as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, NODE_KINDS as K, type LaidDiagram as L, type ScrollProgressHandle as M, type NodeKind as N, TONES as O, computeEventBindingKey as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, computeFormulaKey as U, computeInputSignalKey as V, computeScrollTriggerKey as W, computed as X, createInteractiveSignalsAccessor as Y, createScrollProgressHandle as Z, createScrollProgressSignals as _, type CdlInput as a, sequenceBoardMetrics as a0, sequenceStepId as a1, signal as a2, 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, EDGE_HEADS as v, EDGE_HEAD_DEFAULT as w, EDGE_HEAD_FILLS as x, EDGE_HEAD_FILL_DEFAULT as y, EDGE_REVEALS as z };
@@ -109,6 +109,8 @@ type Side = "top" | "right" | "bottom" | "left";
109
109
  * ER の「識別しない」 のように **刻みが意味を持つ関係** はこちらを使う。
110
110
  */
111
111
  type EdgeStyle = "solid" | "dotted-flow" | "dashed";
112
+ /** 辺の役目 (#618)。 `main` = 図の主となる道 */
113
+ type EdgeRole = "main";
112
114
  /**
113
115
  * 線の種類の全種 (#578)。 **型だけでなく実体を持つ**。
114
116
  *
@@ -572,6 +574,21 @@ type CdlEdge = {
572
574
  side?: Side;
573
575
  /** visual style、 default "solid" */
574
576
  style?: EdgeStyle;
577
+ /**
578
+ * 辺の役目 (#618)。 書かなければ従来どおり tone の色で引く。
579
+ *
580
+ * `main` を書いた辺だけ「いま」 の色 (`--cdl-now`) で引く。 図の中で 1 本の道を
581
+ * 目立たせ、 どこから読むかを決めるための口。 すべての辺に書くと差が消えるので、
582
+ * 主となる 1 本 (または 1 続き) にだけ書く。
583
+ */
584
+ role?: EdgeRole;
585
+ /**
586
+ * 名前の下地を敷くか (#618)。 書かなければ敷く (従来どおり)。
587
+ *
588
+ * 丸い下地は箱と同じ形なので、 名前が小さな箱に見える。 罫の細い図では外したほうが
589
+ * 線と名前の区別が付く。
590
+ */
591
+ labelPlate?: boolean;
575
592
  /** 端の形、 default "triangle" (#560)。 線の種類とは別の軸 */
576
593
  head?: EdgeHead;
577
594
  /**
@@ -2810,4 +2827,4 @@ type CdlDiagramViewProps = {
2810
2827
  };
2811
2828
  declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
2812
2829
 
2813
- export { sequenceBoardMetrics as $, EDGE_STYLES as A, type BBox as B, type CdlDiagram as C, type EdgeReveal as D, type EdgeStyle as E, type InteractiveSignalsAccessor as F, type LaidLane as G, NODE_KINDS as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, type ScrollProgressHandle as K, type LaidDiagram as L, TONES as M, type NodeKind as N, computeEventBindingKey as O, computeFormulaKey as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, computeInputSignalKey as U, computeScrollTriggerKey as V, computed as W, createInteractiveSignalsAccessor as X, createScrollProgressHandle as Y, createScrollProgressSignals as Z, hasInteractivePrimitives as _, type CdlInput as a, sequenceStepId as a0, signal as a1, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeHead as e, type EdgeHeadFill as f, type CdlState as g, type CdlEventTarget as h, type Computed as i, type CdlDerivedValue as j, type CdlScrollTrigger as k, type CdlDiagramViewProps as l, type LaidEdge as m, type LaidNode as n, type CdlEdge as o, CdlDiagramView as p, type CdlEventBinding as q, type CdlEventKind as r, type CdlFormula as s, type CdlPhase as t, EDGE_HEADS as u, EDGE_HEAD_DEFAULT as v, EDGE_HEAD_FILLS as w, EDGE_HEAD_FILL_DEFAULT as x, EDGE_REVEALS as y, EDGE_REVEAL_DEFAULT as z };
2830
+ export { hasInteractivePrimitives as $, EDGE_REVEAL_DEFAULT as A, type BBox as B, type CdlDiagram as C, EDGE_STYLES as D, type EdgeStyle as E, type EdgeReveal as F, type InteractiveSignalsAccessor as G, type LaidLane as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, NODE_KINDS as K, type LaidDiagram as L, type ScrollProgressHandle as M, type NodeKind as N, TONES as O, computeEventBindingKey as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, computeFormulaKey as U, computeInputSignalKey as V, computeScrollTriggerKey as W, computed as X, createInteractiveSignalsAccessor as Y, createScrollProgressHandle as Z, createScrollProgressSignals as _, type CdlInput as a, sequenceBoardMetrics as a0, sequenceStepId as a1, signal as a2, 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, EDGE_HEADS as v, EDGE_HEAD_DEFAULT as w, EDGE_HEAD_FILLS as x, EDGE_HEAD_FILL_DEFAULT as y, EDGE_REVEALS as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/cdl",
3
- "version": "0.22.0",
3
+ "version": "0.24.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/builder.ts CHANGED
@@ -15,6 +15,7 @@ import type {
15
15
  EdgeHead,
16
16
  EdgeHeadFill,
17
17
  EdgeStyle,
18
+ EdgeRole,
18
19
  NodeKind,
19
20
  Side,
20
21
  Tone,
@@ -1435,6 +1436,10 @@ export type DiagramBuilder = {
1435
1436
  tone?: Tone;
1436
1437
  side?: Side;
1437
1438
  style?: EdgeStyle;
1439
+ /** 辺の役目 (#618)。 `main` を書いた辺だけ「いま」 の色で引く */
1440
+ role?: EdgeRole;
1441
+ /** 名前の下地を敷くか (#618)。 書かなければ敷く */
1442
+ labelPlate?: boolean;
1438
1443
  /** 端の形 (#560)、 既定は塗った三角。 線の種類とは別の軸 */
1439
1444
  head?: EdgeHead;
1440
1445
  /** 端の印の塗り (#578)。 書かなければ形ごとの既定 */
@@ -1755,6 +1760,8 @@ export function diagram(
1755
1760
  tone: opts.tone ?? "accent",
1756
1761
  side: opts.side,
1757
1762
  style: opts.style,
1763
+ role: opts.role,
1764
+ labelPlate: opts.labelPlate,
1758
1765
  head: opts.head,
1759
1766
  headFill: opts.headFill,
1760
1767
  tailHead: opts.tailHead,
package/src/index.ts CHANGED
@@ -65,6 +65,10 @@ export { compile } from "./compile";
65
65
  export { layout } from "./layout";
66
66
  export { validate } from "./validate";
67
67
  export { countEdgeCrossings, visualValidate, visualValidateLaid, visualValidateAll } from "./visual-validate";
68
+ // 並べ替え (#599)。 関係から lane / stack を決める純関数。 `compile` からは呼ばない =
69
+ // 書き手が明示した配置を engine が黙って動かすと既存の全図が変わるため、呼ぶ判断は上流に置く
70
+ export { orderNodes, countOrderCrossings } from "./layout/order";
71
+ export type { OrderNode, OrderEdge, OrderResult } from "./layout/order";
68
72
  export type {
69
73
  Violation,
70
74
  VisualAxis,
@@ -39,12 +39,71 @@ type KindStyle = {
39
39
  icon: string;
40
40
  /** shape: rect (default) / cylinder / cloud / diamond / hexagon */
41
41
  shape?: "rect" | "cylinder" | "cloud" | "diamond" | "hexagon";
42
+ /**
43
+ * 面と枠の描き方 (#616)。 未指定は従来どおり。
44
+ *
45
+ * 色で kind を分ける形は、 消費側の配色によっては読めない。 dragon の茶墨は
46
+ * kind の色が 4 つとも暗く彩度が低く、 枠線や細い帯の面積では差が出ない
47
+ * (隔たりは 18.6 以上あるが、 面積が小さいと効かない)。 形で分ける口を用意する。
48
+ */
49
+ look?: NodeLook;
42
50
  };
43
51
 
52
+ /** 箱の見せ方。 何を示すかは値の名前が持つ */
53
+ export type NodeLook =
54
+ /** 図の外にある = 面を塗らず枠だけ */
55
+ | "outline"
56
+ /** 通り道 = 薄い面。 止まらず抜ける */
57
+ | "tint"
58
+ /** ここが働く = ベタ塗り。 図で最も重い */
59
+ | "solid"
60
+ /** 消えては困る = 底を二重の罫で締める */
61
+ | "ledger"
62
+ /** 失っても作り直せる = 破線の枠 */
63
+ | "dashed";
64
+
65
+ /** 薄い面の濃さ。 `color-mix` を読めない環境では第 2 引数の色に落ちる */
66
+ const TINT_FILL = "color-mix(in srgb, var(--cdl-text, #1a1f2a) 6%, transparent)";
67
+
68
+ /**
69
+ * `look` から面と枠を決める。
70
+ *
71
+ * 未指定は従来どおり (面 = node-fill、 枠 = 光れば kind の色 / 光らなければ divider)。
72
+ * ここを通らない kind の出力は 1 文字も変わらない。
73
+ */
74
+ export function lookPaint(look: NodeLook | undefined, accent: string, active: boolean): {
75
+ fill: string;
76
+ stroke: string;
77
+ strokeWidth: number;
78
+ dash?: string;
79
+ /** ベタ塗りの上では字を紙の色で抜く */
80
+ onSolid: boolean;
81
+ } {
82
+ const 既定枠 = active ? accent : "var(--cdl-divider, #d4d4d8)";
83
+ const 既定太さ = active ? 3 : 1.25;
84
+ switch (look) {
85
+ case "outline":
86
+ return { fill: "none", stroke: 既定枠, strokeWidth: 既定太さ, onSolid: false };
87
+ case "tint":
88
+ return { fill: TINT_FILL, stroke: 既定枠, strokeWidth: 既定太さ, onSolid: false };
89
+ case "solid":
90
+ // 枠は従来どおり (光れば kind の色)。 面だけを墨で塗る = 「光っている節の枠は kind の色」
91
+ // は既存の契約で、 `node-styling` が守っている
92
+ return { fill: "var(--cdl-text, #1a1f2a)", stroke: 既定枠, strokeWidth: 既定太さ, onSolid: true };
93
+ case "ledger":
94
+ return { fill: "var(--cdl-node-fill, #ffffff)", stroke: 既定枠, strokeWidth: 既定太さ, onSolid: false };
95
+ case "dashed":
96
+ return { fill: "none", stroke: 既定枠, strokeWidth: 既定太さ, dash: "6 4", onSolid: false };
97
+ default:
98
+ return { fill: "var(--cdl-node-fill, #ffffff)", stroke: 既定枠, strokeWidth: 既定太さ, onSolid: false };
99
+ }
100
+ }
101
+
44
102
  // 各 kind の visual style (icon は heroicons / lucide 風の minimal SVG path)
45
103
  const STYLES: Partial<Record<NodeKind, KindStyle>> = {
46
104
  // 人系
47
105
  person: {
106
+ look: "outline",
48
107
  accent: "var(--cdl-tone-accent, #2d6a8f)",
49
108
  eyebrowColor: "var(--cdl-tone-accent, #2d6a8f)",
50
109
  icon: "M12 12c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4zm0 2c-2.7 0-8 1.3-8 4v2h16v-2c0-2.7-5.3-4-8-4z",
@@ -78,11 +137,13 @@ const STYLES: Partial<Record<NodeKind, KindStyle>> = {
78
137
  shape: "cylinder",
79
138
  },
80
139
  cache: {
140
+ look: "dashed",
81
141
  accent: "var(--cdl-tone-warning, #a67a2e)",
82
142
  eyebrowColor: "var(--cdl-tone-warning, #a67a2e)",
83
143
  icon: "M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z",
84
144
  },
85
145
  queue: {
146
+ look: "ledger",
86
147
  accent: "var(--cdl-tone-warning, #a67a2e)",
87
148
  eyebrowColor: "var(--cdl-tone-warning, #a67a2e)",
88
149
  icon: "M4 6h16v2H4zm0 5h16v2H4zm0 5h16v2H4z",
@@ -99,6 +160,7 @@ const STYLES: Partial<Record<NodeKind, KindStyle>> = {
99
160
  shape: "cloud",
100
161
  },
101
162
  cdn: {
163
+ look: "tint",
102
164
  accent: "var(--cdl-tone-info, #5a8ec1)",
103
165
  eyebrowColor: "var(--cdl-tone-info, #5a8ec1)",
104
166
  icon: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z",
@@ -106,6 +168,7 @@ const STYLES: Partial<Record<NodeKind, KindStyle>> = {
106
168
 
107
169
  // アプリ系
108
170
  service: {
171
+ look: "solid",
109
172
  accent: "var(--cdl-tone-teal, #2f8770)",
110
173
  eyebrowColor: "var(--cdl-tone-teal, #2f8770)",
111
174
  icon: "M19.43 12.98c.04-.32.07-.64.07-.98 0-.34-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98 0 .33.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z",
@@ -188,6 +251,7 @@ export function GenericNode({
188
251
 
189
252
  // shape 別 path
190
253
  const shape = style.shape ?? "rect";
254
+ const paint = lookPaint(style.look, style.accent, active);
191
255
  const shapeEl = (() => {
192
256
  if (shape === "cylinder") {
193
257
  // 円柱 (top ellipse + side + bottom ellipse)
@@ -267,16 +331,23 @@ export function GenericNode({
267
331
  }
268
332
  // default rect
269
333
  return (
270
- <rect
271
- x={0}
272
- y={0}
273
- width={w}
274
- height={h}
275
- rx={18}
276
- fill="var(--cdl-node-fill, #ffffff)"
277
- stroke={active ? style.accent : "var(--cdl-divider, #d4d4d8)"}
278
- strokeWidth={active ? 3 : 1.25}
279
- />
334
+ <>
335
+ <rect
336
+ x={0}
337
+ y={0}
338
+ width={w}
339
+ height={h}
340
+ rx={18}
341
+ fill={paint.fill}
342
+ stroke={paint.stroke}
343
+ strokeWidth={paint.strokeWidth}
344
+ strokeDasharray={paint.dash}
345
+ />
346
+ {/* 台帳 = 底を二重の罫で締める。 消えては困る物という約束を形で示す (#616) */}
347
+ {style.look === "ledger" && (
348
+ <line x1={1} y1={h - 7} x2={w - 1} y2={h - 7} stroke={paint.stroke} strokeWidth={1} />
349
+ )}
350
+ </>
280
351
  );
281
352
  })();
282
353
 
@@ -332,7 +403,14 @@ export function GenericNode({
332
403
  const dominantBaseline = centered ? ("middle" as const) : undefined;
333
404
 
334
405
  return (
335
- <g transform={`translate(${x} ${y})`} data-cdl-role="node-body">
406
+ <g
407
+ transform={`translate(${x} ${y})`}
408
+ data-cdl-role="node-body"
409
+ /* 見せ方を持つ箱だけに出す目印 (#620)。 消費側が `:not([data-cdl-look])` で
410
+ 従来どおりの箱だけを上書きの対象にできる。 持たない kind には出さない
411
+ = 空文字を出すと選択子が効かなくなる */
412
+ data-cdl-look={style.look}
413
+ >
336
414
  {shapeEl}
337
415
  {/* icon */}
338
416
  <g transform={`translate(${iconX} ${iconY}) scale(1)`} data-cdl-role="node-kind-icon">
@@ -340,15 +418,15 @@ export function GenericNode({
340
418
  <path d={style.icon} fill={style.eyebrowColor} opacity={0.7} transform="scale(1)" />
341
419
  </g>
342
420
  {node.eyebrow && (
343
- <text x={textX} y={eyebrowY} fontSize={17} fontWeight={700} letterSpacing={1.5} fill={style.eyebrowColor} textAnchor={textAnchor} dominantBaseline={dominantBaseline}>
421
+ <text x={textX} y={eyebrowY} fontSize={17} fontWeight={700} letterSpacing={1.5} fill={paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : style.eyebrowColor} textAnchor={textAnchor} dominantBaseline={dominantBaseline}>
344
422
  {node.eyebrow}
345
423
  </text>
346
424
  )}
347
- <text data-cdl-role="node-label" x={textX} y={titleY} fontSize={20} fontWeight={700} fill="var(--cdl-text, #1a1f2a)" textAnchor={textAnchor} dominantBaseline={dominantBaseline} style={node.kind === "function" || node.kind === "api" ? { fontFamily: "'JetBrains Mono', monospace" } : undefined}>
425
+ <text data-cdl-role="node-label" x={textX} y={titleY} fontSize={20} fontWeight={700} fill={paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text, #1a1f2a)"} textAnchor={textAnchor} dominantBaseline={dominantBaseline} style={node.kind === "function" || node.kind === "api" ? { fontFamily: "'JetBrains Mono', monospace" } : undefined}>
348
426
  {node.title}
349
427
  </text>
350
428
  {node.subtitle && (
351
- <text x={textX} y={subtitleY} fontSize={17} fill="var(--cdl-text-dim, #5a6270)" textAnchor={textAnchor} dominantBaseline={dominantBaseline} style={{ fontFamily: "'JetBrains Mono', monospace" }}>
429
+ <text x={textX} y={subtitleY} fontSize={17} fill={paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text-dim, #5a6270)"} textAnchor={textAnchor} dominantBaseline={dominantBaseline} style={{ fontFamily: "'JetBrains Mono', monospace" }}>
352
430
  {node.subtitle}
353
431
  </text>
354
432
  )}