@cardenelabs/cdl 0.115.0 → 0.116.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 +40 -1
- package/dist/index.cjs +41 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -3
- package/dist/index.d.ts +23 -3
- package/dist/index.js +41 -4
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +4 -2
- 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 +4 -2
- package/dist/react.js.map +1 -1
- package/dist/{render-oEmwYN-q.d.cts → render-A5AKjNuy.d.cts} +1 -1
- package/dist/{render-oEmwYN-q.d.ts → render-A5AKjNuy.d.ts} +1 -1
- package/package.json +1 -1
- package/src/index.ts +3 -0
- package/src/kinds/tree.tsx +78 -2
- package/src/presets.ts +5 -1
|
@@ -3035,4 +3035,4 @@ type CdlDiagramViewProps = {
|
|
|
3035
3035
|
};
|
|
3036
3036
|
declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
|
|
3037
3037
|
|
|
3038
|
-
export {
|
|
3038
|
+
export { computeEventBindingKey as $, EDGE_HEADS as A, type BBox as B, type CdlDiagram as C, EDGE_HEAD_DEFAULT as D, type EdgeStyle as E, EDGE_HEAD_FILLS as F, EDGE_HEAD_FILL_DEFAULT as G, EDGE_REVEALS as H, EDGE_REVEAL_DEFAULT as I, type JourneyEmotion as J, EDGE_STYLES as K, type LaidDiagram as L, type EdgeReveal as M, type NodeKind as N, type InteractiveHandlerMap as O, type InteractiveSignalsAccessor as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, type LaidLane as U, NODE_KINDS as V, RELATION_FOCUSES as W, RELATION_FOCUS_DEFAULT as X, type RelationFocus as Y, type ScrollProgressHandle as Z, TONES as _, type CdlInput as a, computeFormulaKey as a0, computeInputSignalKey as a1, computeScrollTriggerKey as a2, computed as a3, createInteractiveSignalsAccessor as a4, createScrollProgressHandle as a5, createScrollProgressSignals as a6, hasInteractivePrimitives as a7, resolveLang as a8, sequenceBoardMetrics as a9, sequenceStepId as aa, signal as ab, 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 CdlInputOption as i, type CdlEventTarget as j, type CdlLang as k, type Computed as l, type CdlDerivedValue as m, type CdlScrollTrigger as n, type CdlDiagramViewProps as o, type LaidEdge as p, type LaidNode as q, type CdlEdge as r, type TreeNodePayload as s, CdlDiagramView as t, type CdlEventBinding as u, type CdlEventKind as v, type CdlFormula as w, type CdlPhase as x, type ChartPieForm as y, type ChartSlopeForm as z };
|
|
@@ -3035,4 +3035,4 @@ type CdlDiagramViewProps = {
|
|
|
3035
3035
|
};
|
|
3036
3036
|
declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
|
|
3037
3037
|
|
|
3038
|
-
export {
|
|
3038
|
+
export { computeEventBindingKey as $, EDGE_HEADS as A, type BBox as B, type CdlDiagram as C, EDGE_HEAD_DEFAULT as D, type EdgeStyle as E, EDGE_HEAD_FILLS as F, EDGE_HEAD_FILL_DEFAULT as G, EDGE_REVEALS as H, EDGE_REVEAL_DEFAULT as I, type JourneyEmotion as J, EDGE_STYLES as K, type LaidDiagram as L, type EdgeReveal as M, type NodeKind as N, type InteractiveHandlerMap as O, type InteractiveSignalsAccessor as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, type LaidLane as U, NODE_KINDS as V, RELATION_FOCUSES as W, RELATION_FOCUS_DEFAULT as X, type RelationFocus as Y, type ScrollProgressHandle as Z, TONES as _, type CdlInput as a, computeFormulaKey as a0, computeInputSignalKey as a1, computeScrollTriggerKey as a2, computed as a3, createInteractiveSignalsAccessor as a4, createScrollProgressHandle as a5, createScrollProgressSignals as a6, hasInteractivePrimitives as a7, resolveLang as a8, sequenceBoardMetrics as a9, sequenceStepId as aa, signal as ab, 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 CdlInputOption as i, type CdlEventTarget as j, type CdlLang as k, type Computed as l, type CdlDerivedValue as m, type CdlScrollTrigger as n, type CdlDiagramViewProps as o, type LaidEdge as p, type LaidNode as q, type CdlEdge as r, type TreeNodePayload as s, CdlDiagramView as t, type CdlEventBinding as u, type CdlEventKind as v, type CdlFormula as w, type CdlPhase as x, type ChartPieForm as y, type ChartSlopeForm as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/cdl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.116.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
|
@@ -220,6 +220,9 @@ export { CLASS_RELATION_LOOK, ER_CARDINALITY_HEAD, FSM_ACTION_MARK, SEQUENCE_MES
|
|
|
220
220
|
// 時系列のやり取りの図が引く名前と寸法 (#578)。 **組み立て器ではない** ので presets からは出さない
|
|
221
221
|
// (`mermaid-parity` が presets の公開関数を組み立て器として数える)
|
|
222
222
|
export { sequenceStepId, sequenceBoardMetrics } from "./kinds/sequence-board-metrics";
|
|
223
|
+
// 木の札の幅 (#970)。 葉の数で必要な幅が変わるので、組み立てる側が札を作る前に引く。
|
|
224
|
+
// **組み立て器ではない** ので presets からは出さない (`mermaid-parity` の数え方に合わせる)
|
|
225
|
+
export { 木の札の幅 } from "./kinds/tree";
|
|
223
226
|
// Text DSL は @cardenelabs/dragon に切出済 (cdl は engine only)
|
|
224
227
|
export type {
|
|
225
228
|
SwimlanePreset,
|
package/src/kinds/tree.tsx
CHANGED
|
@@ -62,6 +62,82 @@ const PAD_RIGHT = 24;
|
|
|
62
62
|
const PAD_BOTTOM = 40;
|
|
63
63
|
const PAD_LEFT = 24;
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* 箱の上限 (#970)。 割付の中で `Math.min` の相手として使う値を module に出した。
|
|
67
|
+
*
|
|
68
|
+
* 札の大きさを中身から出すには、置く前に「箱がどれだけ取るか」 を知る必要がある。
|
|
69
|
+
* 割付の中に閉じていると、呼ぶ側は同じ数を書き写すしかない。
|
|
70
|
+
*/
|
|
71
|
+
const 箱の最大幅 = 140;
|
|
72
|
+
const 箱の最大高さ = 38;
|
|
73
|
+
|
|
74
|
+
/** 札の既定の大きさ。 中身から出した値がこれを超える時の頭打ちになる (#970) */
|
|
75
|
+
const 札の既定幅 = 720;
|
|
76
|
+
const 札の既定高さ = 480;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 木を描くのに要る札の幅を、葉の数から出す (#970)。
|
|
80
|
+
*
|
|
81
|
+
* 木の札は種別ごとに 1 つの値 (720) で固定されていた。 必要な幅は葉の数で変わるので、
|
|
82
|
+
* 葉が少ない図は札の中で浮く (実測 = 葉 2 枚の図が 720 の札に 476 で、左右に 122 ずつ余る)。
|
|
83
|
+
*
|
|
84
|
+
* **縦が既に持っている規則を、横にも当てる**。
|
|
85
|
+
* 段は `canvasH / 段数` で等分した区画の中央に置かれるので、縦の余白は隙間の半分ずつになる。
|
|
86
|
+
* 同じ形を横に当てると `葉の数 × (箱の幅 + 隙間)` で、中身の左右にも隙間の半分ずつが残る。
|
|
87
|
+
* 実際 3 段の木では この式が今の高さ (480) をそのまま返す = 縦は既にこの値で描かれている。
|
|
88
|
+
*
|
|
89
|
+
* **広げる向きには使わない** (`Math.min(札の既定幅, ...)`)。 葉が多い図では式の値が
|
|
90
|
+
* 既定を超えるが、札を広げると見本帳の並びが崩れる。 超える図は今までどおり区画が狭まり、
|
|
91
|
+
* 箱が小さくなる側で吸収する。
|
|
92
|
+
*
|
|
93
|
+
* **葉が 1 枚の図は 2 枚として扱う**。 1 枚の木は縦 1 本の鎖で、式のまま出すと
|
|
94
|
+
* 箱 1 つぶんの幅 (188) になる。 縦に長く横に細い札は、木ではなく縦書きの字列に見える。
|
|
95
|
+
*/
|
|
96
|
+
export function 木の札の幅(treeNodes: TreeNodePayload[]): number {
|
|
97
|
+
const { 葉の数, 段数 } = 木の形(treeNodes);
|
|
98
|
+
// 隙間は段の隙間と同じ値を使う。 段の高さは札の高さを段数で割った値から出る
|
|
99
|
+
const 段の高さ = (札の既定高さ - PAD_TOP - PAD_BOTTOM) / Math.max(段数, 1);
|
|
100
|
+
const 箱の高さ = Math.min(箱の最大高さ, 段の高さ * 0.7);
|
|
101
|
+
const 隙間 = 段の高さ - 箱の高さ;
|
|
102
|
+
const 要る幅 = Math.max(葉の数, 2) * (箱の最大幅 + 隙間);
|
|
103
|
+
// 切り上げる。 切り下げると区画が要る間隔よりわずかに狭くなり、頭打ちが効いて
|
|
104
|
+
// 葉の隙間が段の隙間より詰まる (割付は `canvasW / 葉の数` を上限に持つ)
|
|
105
|
+
return Math.ceil(Math.min(札の既定幅, 要る幅 + PAD_LEFT + PAD_RIGHT));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 木の形 (葉の数と段数) を出す (#970)。
|
|
110
|
+
*
|
|
111
|
+
* 走査の順と打ち切りは `computeTreeLayout` と同じにする。 親が実在しない項目を根として拾い、
|
|
112
|
+
* 既に見た項目で打ち切るので、循環参照のある入力でも止まる。
|
|
113
|
+
*/
|
|
114
|
+
function 木の形(treeNodes: TreeNodePayload[]): { 葉の数: number; 段数: number } {
|
|
115
|
+
const ids = new Set(treeNodes.map((n) => n.id));
|
|
116
|
+
const childrenOf = new Map<string, TreeNodePayload[]>();
|
|
117
|
+
for (const n of treeNodes) {
|
|
118
|
+
const p = n.parent && ids.has(n.parent) ? n.parent : "__root__";
|
|
119
|
+
if (!childrenOf.has(p)) childrenOf.set(p, []);
|
|
120
|
+
childrenOf.get(p)!.push(n);
|
|
121
|
+
}
|
|
122
|
+
const 見た = new Set<string>();
|
|
123
|
+
let 葉の数 = 0;
|
|
124
|
+
let 段数 = 0;
|
|
125
|
+
const 下見 = (n: TreeNodePayload, depth: number): void => {
|
|
126
|
+
見た.add(n.id);
|
|
127
|
+
段数 = Math.max(段数, depth + 1);
|
|
128
|
+
const kids = (childrenOf.get(n.id) ?? []).filter((k) => !見た.has(k.id));
|
|
129
|
+
if (kids.length === 0) {
|
|
130
|
+
葉の数 += 1;
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
for (const k of kids) 下見(k, depth + 1);
|
|
134
|
+
};
|
|
135
|
+
for (const r of childrenOf.get("__root__") ?? []) if (!見た.has(r.id)) 下見(r, 0);
|
|
136
|
+
// 循環参照で根から辿れない項目は、宣言順で最初に現れたものを根として拾う
|
|
137
|
+
for (const n of treeNodes) if (!見た.has(n.id)) 下見(n, 0);
|
|
138
|
+
return { 葉の数, 段数 };
|
|
139
|
+
}
|
|
140
|
+
|
|
65
141
|
/**
|
|
66
142
|
* 枝の太さ。 根に近いほど太く、葉へ行くほど細い (#909)。
|
|
67
143
|
*
|
|
@@ -383,8 +459,8 @@ export function computeTreeLayout(
|
|
|
383
459
|
// box は必ず slot の一定割合に収める。 加算的な floor (min 12 / min 8 等) を置くと、 深い / 多い
|
|
384
460
|
// 入力で floor が slot を超えて隣と重なる。 slot の割合にすれば規模によらず必ず gap が残る。
|
|
385
461
|
// 深い / 多い入力では box が小さくなるが、 位置のはみ出しは末尾の最終スケールが捌く。
|
|
386
|
-
const nodeH = Math.min(
|
|
387
|
-
const nodeW = Math.min(
|
|
462
|
+
const nodeH = Math.min(箱の最大高さ, depthGap * 0.7);
|
|
463
|
+
const nodeW = Math.min(箱の最大幅, slotW * 0.85);
|
|
388
464
|
|
|
389
465
|
/**
|
|
390
466
|
* 箱の幅を名前から出す (#909)。
|
package/src/presets.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { diagram } from "./builder";
|
|
|
2
2
|
import type { DiagramBuilder } from "./builder";
|
|
3
3
|
import { LANE_PAD_MIN, NODE_SIZE } from "./layout/tokens";
|
|
4
4
|
import { requiredRowsWidth } from "./kinds/row-align";
|
|
5
|
+
import { 木の札の幅 } from "./kinds/tree";
|
|
5
6
|
import {
|
|
6
7
|
sequenceBoardMetrics,
|
|
7
8
|
sequenceStepId,
|
|
@@ -1647,7 +1648,6 @@ export type TreeBuilder = {
|
|
|
1647
1648
|
* .build();
|
|
1648
1649
|
*/
|
|
1649
1650
|
export function tree(preset: TreePreset): TreeBuilder {
|
|
1650
|
-
const canvasW = preset.nodeWidth ? preset.nodeWidth * 2 : 720;
|
|
1651
1651
|
const canvasH = 480;
|
|
1652
1652
|
const b = diagram(preset.id, { topic: preset.topic, type: "tree" });
|
|
1653
1653
|
const treeNodes: TreeNode[] = [];
|
|
@@ -1658,6 +1658,10 @@ export function tree(preset: TreePreset): TreeBuilder {
|
|
|
1658
1658
|
return api;
|
|
1659
1659
|
},
|
|
1660
1660
|
build() {
|
|
1661
|
+
// 札の幅は葉の数で変わる (#970)。 項目が出揃う `build` まで待たないと出せない
|
|
1662
|
+
const canvasW = preset.nodeWidth
|
|
1663
|
+
? preset.nodeWidth * 2
|
|
1664
|
+
: 木の札の幅(treeNodes.map((n) => ({ id: n.id, title: n.title, parent: n.parent })));
|
|
1661
1665
|
b.lane("tree", { width: canvasW });
|
|
1662
1666
|
const nodeId = `${preset.id}-tree`;
|
|
1663
1667
|
b.node(nodeId, {
|