@cardenelabs/cdl 0.113.0 → 0.115.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 +71 -1
- package/dist/index.cjs +67 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +67 -30
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +67 -30
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +67 -30
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/kinds/mind-map.tsx +113 -63
- package/src/kinds/tree.tsx +49 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,74 @@ CDL (Chainome Diagram Language) の主要変更履歴。
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.115.0] - 2026-09-30
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **木の兄弟どうしが遠くへ離れ、離れた 2 本の列に見えた** (#968)
|
|
13
|
+
|
|
14
|
+
葉は `canvasW / 葉の数` で等分した区画の中央に置かれていた。
|
|
15
|
+
区画は箱より広いので、葉が少ない図では兄弟が区画の幅だけ離れる。
|
|
16
|
+
見本帳の `配布物の構成` は葉が 2 枚で、箱の縁の間が 196 空いていた。
|
|
17
|
+
同じ図の段と段の隙間は 95 なので、横だけが縦の 2 倍になる。
|
|
18
|
+
|
|
19
|
+
横の隙間を **段と段の隙間に揃えた**。
|
|
20
|
+
木は根から下へ辿る図なので、間隔が 1 つの調子で揃っていないと系統が読めない。
|
|
21
|
+
|
|
22
|
+
| 図の形 | 横の隙間 (直す前 → 後) | 縦の隙間 |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| 葉 2 枚 | 196 → 95 | 95 |
|
|
25
|
+
| 葉 3 枚 | 84 → 84 (変わらない) | 95 |
|
|
26
|
+
|
|
27
|
+
**今より広げない**。 葉が多い図では区画の方が狭いので、そちらが効いて位置は動かない。
|
|
28
|
+
頭打ちを外すと間隔が区画の 3 倍になり、最後の一様縮小が効いて箱まで小さくなる
|
|
29
|
+
(実測 = 葉 10 枚の図で箱の幅が 57.1 から 19.5 に縮んだ)。
|
|
30
|
+
|
|
31
|
+
箱の幅を出す処理を置き場所より先に回した。
|
|
32
|
+
端の葉がどれだけ幅を取るかは、名前と段から決まるので位置より先に出せる。
|
|
33
|
+
|
|
34
|
+
見本帳 (`cardene777/dragon`) の `配布物の構成` は、札に対する中身の割合が
|
|
35
|
+
横 66% から 52% に **下がる**。 兄弟が近づいたぶん中身が小さくなるためで、
|
|
36
|
+
図が札の中で浮くのは札の大きさの話として別に扱う。
|
|
37
|
+
|
|
38
|
+
## [0.114.0] - 2026-09-30
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **左右で段数が違う放射の図が札の横を半分しか使わなかった** (#966)
|
|
43
|
+
|
|
44
|
+
枝を中心からどれだけ離すかが図で 1 つの値だった。
|
|
45
|
+
子を持つ枝は子の世代のぶんを内側に空ける必要があるので、その都合が子を持たない枝にも効く。
|
|
46
|
+
左が入れ子で右が葉 1 枚の図では右の枝も中心から 149 に留まり、
|
|
47
|
+
右には空ける相手が居ないのにその 171 を誰も使わない。
|
|
48
|
+
|
|
49
|
+
離す量を **枝ごとに** 出すようにした。
|
|
50
|
+
子を持つ枝は子を収める位置まで、末端の枝は名前が描画域の端に届く位置まで外へ出る。
|
|
51
|
+
|
|
52
|
+
| 枝 | 直す前 | 直した後 |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| 子を 1 段持つ枝 | 149 | 149 (変わらない) |
|
|
55
|
+
| 同じ側の末端の枝 | 149 | 296 |
|
|
56
|
+
| 反対側の末端の枝 | 149 | 338 |
|
|
57
|
+
|
|
58
|
+
あわせて末端の上限から「箱ごと描画域に収める」 という条件を外した。
|
|
59
|
+
末端は枠を持たない (#907) ので、収めるのは名前で箱ではない。
|
|
60
|
+
箱まで収めると、名前より 41 広い箱の都合で名前が描画域の内側で終わっていた。
|
|
61
|
+
|
|
62
|
+
名前を描く幅の見積りを、切る側 (`箱に積む` / `幅に収める`) と同じ `textWidth` に揃えた。
|
|
63
|
+
別の見積りで置き場所を決めていたため、ちょうど収まる位置に置いた名前が描く側で切られていた
|
|
64
|
+
(実測 = `Features` が `Featur…` になった)。
|
|
65
|
+
|
|
66
|
+
枝の離れは整数に落とす。
|
|
67
|
+
端数を持ったまま置くと枝の長さが座標の差から出るぶん丸め誤差が乗る
|
|
68
|
+
(実測 = 24 であるべき枝が 23.99999999999997 になった)。
|
|
69
|
+
|
|
70
|
+
中心の箱を横中央へ寄せる処理 (#913) は、両側が端まで届くようになったため
|
|
71
|
+
この形の図では働かなくなる。 片側にしか枝が無い図では引き続き働く。
|
|
72
|
+
|
|
73
|
+
見本帳 (`cardene777/dragon`) の 3 図を実際の画面で測ると、札の横を使う割合が
|
|
74
|
+
85% から 88%、52% から 88%、79% から 87% になった。
|
|
75
|
+
|
|
8
76
|
## [0.113.0] - 2026-09-30
|
|
9
77
|
|
|
10
78
|
### Fixed
|
|
@@ -4512,7 +4580,9 @@ Initial OSS release.
|
|
|
4512
4580
|
使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
|
|
4513
4581
|
行き止まりになる。
|
|
4514
4582
|
|
|
4515
|
-
[Unreleased]: https://github.com/cardene777/cdl/compare/v0.
|
|
4583
|
+
[Unreleased]: https://github.com/cardene777/cdl/compare/v0.115.0...HEAD
|
|
4584
|
+
[0.115.0]: https://github.com/cardene777/cdl/compare/v0.114.0...v0.115.0
|
|
4585
|
+
[0.114.0]: https://github.com/cardene777/cdl/compare/v0.113.0...v0.114.0
|
|
4516
4586
|
[0.113.0]: https://github.com/cardene777/cdl/compare/v0.112.0...v0.113.0
|
|
4517
4587
|
[0.112.0]: https://github.com/cardene777/cdl/compare/v0.111.0...v0.112.0
|
|
4518
4588
|
[0.111.0]: https://github.com/cardene777/cdl/compare/v0.110.0...v0.111.0
|
package/dist/index.cjs
CHANGED
|
@@ -15931,6 +15931,28 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
|
|
|
15931
15931
|
const \u8981\u308B = measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize}) + (nodeW - \u4F7F\u3048\u308B\u5E45(nodeW));
|
|
15932
15932
|
return Math.min(Math.max(\u8981\u308B, nodeW), slotW * 0.92);
|
|
15933
15933
|
};
|
|
15934
|
+
const \u8449\u306E\u4E26\u3073 = [];
|
|
15935
|
+
const \u6BB5\u306E\u8868 = /* @__PURE__ */ new Map();
|
|
15936
|
+
const \u5E45\u306E\u8868 = /* @__PURE__ */ new Map();
|
|
15937
|
+
{
|
|
15938
|
+
const \u898B\u305F = /* @__PURE__ */ new Set();
|
|
15939
|
+
const \u4E0B\u898B = (n, depth) => {
|
|
15940
|
+
\u898B\u305F.add(n.id);
|
|
15941
|
+
\u6BB5\u306E\u8868.set(n.id, depth);
|
|
15942
|
+
\u5E45\u306E\u8868.set(n.id, \u7BB1\u306E\u5E45(n, depth));
|
|
15943
|
+
const kids = (childrenOf.get(n.id) ?? []).filter((k) => !\u898B\u305F.has(k.id));
|
|
15944
|
+
if (kids.length === 0) {
|
|
15945
|
+
\u8449\u306E\u4E26\u3073.push(n.id);
|
|
15946
|
+
return;
|
|
15947
|
+
}
|
|
15948
|
+
for (const k of kids) \u4E0B\u898B(k, depth + 1);
|
|
15949
|
+
};
|
|
15950
|
+
for (const r of roots) if (!\u898B\u305F.has(r.id)) \u4E0B\u898B(r, 0);
|
|
15951
|
+
}
|
|
15952
|
+
const \u8449\u306E\u6570 = Math.max(\u8449\u306E\u4E26\u3073.length, 1);
|
|
15953
|
+
const \u6BB5\u306E\u9699\u9593 = depthGap - nodeH;
|
|
15954
|
+
const \u8449\u306E\u9593\u9694 = Math.min(slotW, nodeW + \u6BB5\u306E\u9699\u9593);
|
|
15955
|
+
const \u8449\u306Ex = (i) => canvasW / 2 - (\u8449\u306E\u6570 - 1) * \u8449\u306E\u9593\u9694 / 2 + i * \u8449\u306E\u9593\u9694;
|
|
15934
15956
|
const posOf = /* @__PURE__ */ new Map();
|
|
15935
15957
|
const nodes = [];
|
|
15936
15958
|
const placed = /* @__PURE__ */ new Set();
|
|
@@ -15940,7 +15962,7 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
|
|
|
15940
15962
|
const kids = (childrenOf.get(n.id) ?? []).filter((k) => !placed.has(k.id));
|
|
15941
15963
|
let x;
|
|
15942
15964
|
if (kids.length === 0) {
|
|
15943
|
-
x = leafCursor
|
|
15965
|
+
x = \u8449\u306Ex(leafCursor);
|
|
15944
15966
|
leafCursor += 1;
|
|
15945
15967
|
} else {
|
|
15946
15968
|
const xs = kids.map((k) => place(k, depth + 1));
|
|
@@ -15954,7 +15976,7 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
|
|
|
15954
15976
|
...n.subtitle !== void 0 ? { subtitle: n.subtitle } : {},
|
|
15955
15977
|
x,
|
|
15956
15978
|
y,
|
|
15957
|
-
w: \u7BB1\u306E\u5E45(n, depth),
|
|
15979
|
+
w: \u5E45\u306E\u8868.get(n.id) ?? \u7BB1\u306E\u5E45(n, depth),
|
|
15958
15980
|
h: nodeH,
|
|
15959
15981
|
depth,
|
|
15960
15982
|
...n.unresolved ? { unresolved: true } : {}
|
|
@@ -16141,7 +16163,7 @@ function \u63CF\u304F\u6A2A\u306E\u7AEF(n) {
|
|
|
16141
16163
|
if (n.isRoot || !n.isLeaf) return [n.x - n.w / 2, n.x + n.w / 2];
|
|
16142
16164
|
const \u8D77\u70B9 = n.x + (n.side === "right" ? -n.w / 2 : n.w / 2);
|
|
16143
16165
|
const \u540D\u524D = \u653E\u5C04\u306E\u884C(n)[0];
|
|
16144
|
-
const \u5E45 =
|
|
16166
|
+
const \u5E45 = textWidth(\u540D\u524D.text, \u540D\u524D.fontSize);
|
|
16145
16167
|
return n.side === "right" ? [\u8D77\u70B9, \u8D77\u70B9 + \u5E45] : [\u8D77\u70B9 - \u5E45, \u8D77\u70B9];
|
|
16146
16168
|
}
|
|
16147
16169
|
function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
|
|
@@ -16214,38 +16236,52 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
|
|
|
16214
16236
|
if (kids.length === 0) return 1;
|
|
16215
16237
|
return kids.reduce((sum, k) => sum + leafCountOf(k.id, seen), 0);
|
|
16216
16238
|
};
|
|
16217
|
-
const
|
|
16239
|
+
const leftBranches = firstLevel.slice(0, leftCount);
|
|
16240
|
+
const rightBranches = firstLevel.slice(leftCount);
|
|
16218
16241
|
const minLayer1XOffset = rootW / 2 + branchW / 2 + MIND_BOX_GAP;
|
|
16219
16242
|
const preferredSubDx = subBranchW + 20;
|
|
16220
|
-
const reserve = maxSubDepth > 0 ? branchW / 2 + maxSubDepth * preferredSubDx : 0;
|
|
16221
|
-
const maxLayer1XOffset = Math.max(minLayer1XOffset, canvasW / 2 - reserve);
|
|
16222
|
-
const \u8449\u306E\u540D\u524D\u306E\u6700\u5927\u5E45 = Math.max(
|
|
16223
|
-
0,
|
|
16224
|
-
...firstLevel.filter((br) => (childrenOf.get(br.id) ?? []).length === 0).map((br) => {
|
|
16225
|
-
const \u540D\u524D = \u653E\u5C04\u306E\u884C({ title: br.title, isRoot: false })[0];
|
|
16226
|
-
return measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize});
|
|
16227
|
-
})
|
|
16228
|
-
);
|
|
16229
|
-
const \u540D\u524D\u3067\u6C7A\u307E\u308B\u4E0A\u9650 = canvasW / 2 + branchW / 2 - \u8449\u306E\u540D\u524D\u306E\u6700\u5927\u5E45;
|
|
16230
|
-
const layer1XOffset = Math.max(minLayer1XOffset, Math.min(\u540D\u524D\u3067\u6C7A\u307E\u308B\u4E0A\u9650, maxLayer1XOffset));
|
|
16231
|
-
const room = canvasW / 2 - layer1XOffset;
|
|
16232
16243
|
const MIN_SUB_W = 56;
|
|
16233
16244
|
const PREFERRED_GAP = MIND_BOX_GAP;
|
|
16234
|
-
const
|
|
16235
|
-
|
|
16236
|
-
|
|
16237
|
-
|
|
16238
|
-
const
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
|
|
16245
|
+
const \u679D\u306E\u540D\u524D\u306E\u5E45 = (title) => {
|
|
16246
|
+
const \u540D\u524D = \u653E\u5C04\u306E\u884C({ title, isRoot: false })[0];
|
|
16247
|
+
return textWidth(\u540D\u524D.text, \u540D\u524D.fontSize);
|
|
16248
|
+
};
|
|
16249
|
+
const \u679D\u306E\u6A2A\u3092\u6C7A\u3081\u308B = (br) => {
|
|
16250
|
+
const maxSubDepth = subDepthOf(br.id, /* @__PURE__ */ new Set());
|
|
16251
|
+
const \u4E0A\u9650 = maxSubDepth > 0 ? canvasW / 2 - (branchW / 2 + maxSubDepth * preferredSubDx) : canvasW / 2 + branchW / 2 - \u679D\u306E\u540D\u524D\u306E\u5E45(br.title);
|
|
16252
|
+
const layer1XOffset = Math.floor(Math.max(minLayer1XOffset, \u4E0A\u9650));
|
|
16253
|
+
const room = canvasW / 2 - layer1XOffset;
|
|
16254
|
+
const gapRoom = maxSubDepth > 0 ? (room - branchW / 2 - maxSubDepth * MIN_SUB_W) / maxSubDepth : 0;
|
|
16255
|
+
const gap = Math.floor(Math.max(8, Math.min(PREFERRED_GAP, gapRoom)));
|
|
16256
|
+
const effSubW = maxSubDepth > 0 ? Math.floor(
|
|
16257
|
+
Math.max(1, Math.min(subBranchW, (room - branchW / 2 - maxSubDepth * gap) / maxSubDepth))
|
|
16258
|
+
) : subBranchW;
|
|
16259
|
+
const step1 = (branchW + effSubW) / 2 + gap;
|
|
16260
|
+
const stepN = effSubW + gap;
|
|
16261
|
+
return {
|
|
16262
|
+
layer1XOffset,
|
|
16263
|
+
effSubW,
|
|
16264
|
+
subOffset: (subDepth) => subDepth <= 0 ? 0 : step1 + (subDepth - 1) * stepN
|
|
16265
|
+
};
|
|
16266
|
+
};
|
|
16267
|
+
const \u6A2A\u306E\u5272\u4ED8\u8868 = new Map(
|
|
16268
|
+
firstLevel.map((br) => [br.id, \u679D\u306E\u6A2A\u3092\u6C7A\u3081\u308B(br)])
|
|
16269
|
+
);
|
|
16270
|
+
const \u4E00\u756A\u5185\u5074\u306E\u96E2\u308C = Math.min(
|
|
16271
|
+
...firstLevel.length > 0 ? firstLevel.map((br) => \u6A2A\u306E\u5272\u4ED8\u8868.get(br.id).layer1XOffset) : [minLayer1XOffset]
|
|
16272
|
+
);
|
|
16242
16273
|
const leavesOfSide = (brs) => Math.max(
|
|
16243
16274
|
1,
|
|
16244
16275
|
brs.reduce((sum, br) => sum + leafCountOf(br.id, /* @__PURE__ */ new Set()), 0)
|
|
16245
16276
|
);
|
|
16246
16277
|
const sideLaneCount = Math.max(leavesOfSide(leftBranches), leavesOfSide(rightBranches));
|
|
16247
16278
|
const laneBandH = Math.max(0, canvasH - BRANCH_BOX_H_MAX);
|
|
16248
|
-
const rowGap = sideLaneCount > 1 ? Math.min(
|
|
16279
|
+
const rowGap = sideLaneCount > 1 ? Math.min(
|
|
16280
|
+
laneBandH / (sideLaneCount - 1),
|
|
16281
|
+
// 帯は図で 1 つなので、**一番内側の枝** から上限を取る (#966)。
|
|
16282
|
+
// 外へ出た枝に合わせると、内側に残った枝の傾きが 45 度を超える
|
|
16283
|
+
\u7E26\u306E\u9593\u9694\u306E\u4E0A\u9650(\u4E00\u756A\u5185\u5074\u306E\u96E2\u308C)
|
|
16284
|
+
) : subBranchH + 14;
|
|
16249
16285
|
const effSubH = Math.min(SUB_BOX_H_MAX, rowGap * 0.7);
|
|
16250
16286
|
const effBranchH = Math.min(BRANCH_BOX_H_MAX, rowGap * 0.7);
|
|
16251
16287
|
const \u7AEF\u306E\u4F59\u308A = Math.max(effSubH, effBranchH) / 2;
|
|
@@ -16261,11 +16297,11 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
|
|
|
16261
16297
|
const half = nodeHalfW.get(mindData.rootId) ?? rootW / 2;
|
|
16262
16298
|
return \u4E2D\u5FC3\u306Ex + (isLeft ? -half : half);
|
|
16263
16299
|
};
|
|
16264
|
-
const placeSubtree = (node, subDepth, isLeft, tone, placed, laneRef) => {
|
|
16300
|
+
const placeSubtree = (node, subDepth, isLeft, tone, placed, laneRef, \u6A2A) => {
|
|
16265
16301
|
placed.add(node.id);
|
|
16266
16302
|
const dirX = isLeft ? -1 : 1;
|
|
16267
|
-
const x = cx + dirX * (layer1XOffset + subOffset(subDepth));
|
|
16268
|
-
const w = subDepth === 0 ? branchW : effSubW;
|
|
16303
|
+
const x = cx + dirX * (\u6A2A.layer1XOffset + \u6A2A.subOffset(subDepth));
|
|
16304
|
+
const w = subDepth === 0 ? branchW : \u6A2A.effSubW;
|
|
16269
16305
|
const h = subDepth === 0 ? effBranchH : effSubH;
|
|
16270
16306
|
const myTone = node.tone ?? tone;
|
|
16271
16307
|
const kids = (childrenOf.get(node.id) ?? []).filter((k) => !placed.has(k.id));
|
|
@@ -16281,7 +16317,8 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
|
|
|
16281
16317
|
isLeft,
|
|
16282
16318
|
myTone ?? MIND_TONES[i % MIND_TONES.length],
|
|
16283
16319
|
placed,
|
|
16284
|
-
laneRef
|
|
16320
|
+
laneRef,
|
|
16321
|
+
\u6A2A
|
|
16285
16322
|
)
|
|
16286
16323
|
);
|
|
16287
16324
|
y = (ys[0] + ys[ys.length - 1]) / 2;
|
|
@@ -16314,7 +16351,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
|
|
|
16314
16351
|
const placed = /* @__PURE__ */ new Set();
|
|
16315
16352
|
brs.forEach((br, i) => {
|
|
16316
16353
|
const tone = br.tone ?? MIND_TONES[(toneBase + i) % MIND_TONES.length];
|
|
16317
|
-
placeSubtree(br, 0, isLeft, tone, placed, laneRef);
|
|
16354
|
+
placeSubtree(br, 0, isLeft, tone, placed, laneRef, \u6A2A\u306E\u5272\u4ED8\u8868.get(br.id) ?? \u679D\u306E\u6A2A\u3092\u6C7A\u3081\u308B(br));
|
|
16318
16355
|
});
|
|
16319
16356
|
};
|
|
16320
16357
|
placeSide(leftBranches, true, 0);
|