@cardenelabs/cdl 0.46.0 → 0.48.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 +64 -1
- package/dist/index.cjs +135 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +133 -24
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +131 -23
- 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 +131 -23
- package/dist/react.js.map +1 -1
- package/dist/{render-UGswDfAh.d.cts → render-C53-PeJZ.d.cts} +25 -1
- package/dist/{render-UGswDfAh.d.ts → render-C53-PeJZ.d.ts} +25 -1
- package/package.json +1 -1
- package/src/index.ts +6 -0
- package/src/layout/edges.ts +95 -23
- package/src/layout.ts +1 -0
- package/src/render/edges.tsx +19 -0
- package/src/render/nodes.tsx +40 -1
- package/src/render/relation-focus.ts +40 -0
- package/src/render/stage.tsx +55 -2
- package/src/types.ts +27 -0
package/dist/react.cjs
CHANGED
|
@@ -2423,6 +2423,7 @@ var EDGE_HEADS = [
|
|
|
2423
2423
|
];
|
|
2424
2424
|
var EDGE_HEAD_FILL_DEFAULT = "solid";
|
|
2425
2425
|
var EDGE_HEAD_FILLS = ["solid", "hollow"];
|
|
2426
|
+
var RELATION_FOCUS_DEFAULT = "off";
|
|
2426
2427
|
var EDGE_REVEAL_DEFAULT = "phase";
|
|
2427
2428
|
|
|
2428
2429
|
// src/kinds/text-width.ts
|
|
@@ -8281,33 +8282,73 @@ function placeAvoidingSiblingPaths(args) {
|
|
|
8281
8282
|
}
|
|
8282
8283
|
};
|
|
8283
8284
|
consider([...wants]);
|
|
8285
|
+
const \u62BC\u3059\u91CF = (idx, side, pos) => {
|
|
8286
|
+
let \u8981\u308B = 0;
|
|
8287
|
+
for (const i of idx) {
|
|
8288
|
+
const box = boxes[i];
|
|
8289
|
+
const rect = { x: box.x, y: pos[i] - box.h / 2, w: box.w, h: box.h };
|
|
8290
|
+
for (const probe of probeSegs[i]) {
|
|
8291
|
+
if (measurePathLabelGapSegs(probe.segs, rect) >= CLEARANCE_PATH_LABEL) continue;
|
|
8292
|
+
let lo = Infinity;
|
|
8293
|
+
let hi = -Infinity;
|
|
8294
|
+
for (const seg of probe.segs) {
|
|
8295
|
+
const c = clipY(seg, box.x, box.x + box.w);
|
|
8296
|
+
if (!c) continue;
|
|
8297
|
+
lo = Math.min(lo, c.lo);
|
|
8298
|
+
hi = Math.max(hi, c.hi);
|
|
8299
|
+
}
|
|
8300
|
+
if (lo > hi) continue;
|
|
8301
|
+
const \u884C\u304D\u5148 = side === "above" ? lo - box.h / 2 - CLEARANCE_PATH_LABEL : hi + box.h / 2 + CLEARANCE_PATH_LABEL;
|
|
8302
|
+
\u8981\u308B = Math.max(\u8981\u308B, side === "above" ? pos[i] - \u884C\u304D\u5148 : \u884C\u304D\u5148 - pos[i]);
|
|
8303
|
+
}
|
|
8304
|
+
}
|
|
8305
|
+
return Math.max(0, \u8981\u308B);
|
|
8306
|
+
};
|
|
8284
8307
|
if (bands.some((b) => b !== null)) {
|
|
8285
8308
|
for (let split = 0; split <= order.length; split++) {
|
|
8286
8309
|
const above = order.slice(0, split);
|
|
8287
8310
|
const below = order.slice(split);
|
|
8288
|
-
const
|
|
8289
|
-
|
|
8290
|
-
[above, "above"],
|
|
8291
|
-
[below, "below"]
|
|
8292
|
-
]) {
|
|
8293
|
-
if (idx.length === 0) continue;
|
|
8294
|
-
const ys = spread(idx);
|
|
8295
|
-
let shift = 0;
|
|
8296
|
-
for (let k = 0; k < idx.length; k++) {
|
|
8297
|
-
const band = bands[idx[k]];
|
|
8298
|
-
if (!band) continue;
|
|
8299
|
-
shift = side === "above" ? Math.min(shift, band.lo - ys[k]) : Math.max(shift, band.hi - ys[k]);
|
|
8300
|
-
}
|
|
8301
|
-
for (let k = 0; k < idx.length; k++) out[idx[k]] = ys[k] + shift;
|
|
8302
|
-
}
|
|
8303
|
-
if (above.length > 0 && below.length > 0) {
|
|
8311
|
+
const \u9593\u3092\u7A7A\u3051\u308B = (out) => {
|
|
8312
|
+
if (above.length === 0 || below.length === 0) return;
|
|
8304
8313
|
const lastIdx = above[above.length - 1];
|
|
8305
8314
|
const firstIdx = below[0];
|
|
8306
8315
|
const need = (sizes[lastIdx] + sizes[firstIdx]) / 2 + CLEARANCE_LABEL_LABEL;
|
|
8307
8316
|
const deficit = need - (out[firstIdx] - out[lastIdx]);
|
|
8308
|
-
if (deficit > 0) for (const i of below) out[i]
|
|
8309
|
-
}
|
|
8310
|
-
|
|
8317
|
+
if (deficit > 0) for (const i of below) out[i] = out[i] + deficit;
|
|
8318
|
+
};
|
|
8319
|
+
const \u5E2F\u3092\u8D8A\u3048\u308B = () => {
|
|
8320
|
+
const out = new Array(members.length);
|
|
8321
|
+
for (const [idx, side] of [
|
|
8322
|
+
[above, "above"],
|
|
8323
|
+
[below, "below"]
|
|
8324
|
+
]) {
|
|
8325
|
+
if (idx.length === 0) continue;
|
|
8326
|
+
const ys = spread(idx);
|
|
8327
|
+
let shift = 0;
|
|
8328
|
+
for (let k = 0; k < idx.length; k++) {
|
|
8329
|
+
const band = bands[idx[k]];
|
|
8330
|
+
if (!band) continue;
|
|
8331
|
+
shift = side === "above" ? Math.min(shift, band.lo - ys[k]) : Math.max(shift, band.hi - ys[k]);
|
|
8332
|
+
}
|
|
8333
|
+
for (let k = 0; k < idx.length; k++) out[idx[k]] = ys[k] + shift;
|
|
8334
|
+
}
|
|
8335
|
+
\u9593\u3092\u7A7A\u3051\u308B(out);
|
|
8336
|
+
return out;
|
|
8337
|
+
};
|
|
8338
|
+
const \u62BC\u3057\u3066\u8D8A\u3048\u308B = () => {
|
|
8339
|
+
const out = \u5E2F\u3092\u8D8A\u3048\u308B();
|
|
8340
|
+
for (let round = 0; round < 4; round += 1) {
|
|
8341
|
+
const a = \u62BC\u3059\u91CF(above, "above", out);
|
|
8342
|
+
const b = \u62BC\u3059\u91CF(below, "below", out);
|
|
8343
|
+
if (a === 0 && b === 0) return out;
|
|
8344
|
+
for (const i of above) out[i] = out[i] - a;
|
|
8345
|
+
for (const i of below) out[i] = out[i] + b;
|
|
8346
|
+
}
|
|
8347
|
+
return \u62BC\u3059\u91CF(above, "above", out) === 0 && \u62BC\u3059\u91CF(below, "below", out) === 0 ? out : null;
|
|
8348
|
+
};
|
|
8349
|
+
consider(\u5E2F\u3092\u8D8A\u3048\u308B());
|
|
8350
|
+
const \u62BC\u3057\u305F = \u62BC\u3057\u3066\u8D8A\u3048\u308B();
|
|
8351
|
+
if (\u62BC\u3057\u305F) consider(\u62BC\u3057\u305F);
|
|
8311
8352
|
}
|
|
8312
8353
|
}
|
|
8313
8354
|
const plain = spread(all);
|
|
@@ -9427,6 +9468,7 @@ function layout(diag) {
|
|
|
9427
9468
|
...diag.derived ? { derived: diag.derived } : {},
|
|
9428
9469
|
// 矢印をいつ出すか (#582)。 描き手が読む欄なので、そのまま持ち越す
|
|
9429
9470
|
...diag.edgeReveal ? { edgeReveal: diag.edgeReveal } : {},
|
|
9471
|
+
...diag.relationFocus ? { relationFocus: diag.relationFocus } : {},
|
|
9430
9472
|
// どの配色で描くか (#1553)。 空文字は書かなかった扱いにする = 空の目印を出すと、
|
|
9431
9473
|
// 消費側の `[data-cdl-palette]` が配色を書いていない図にも当たる。
|
|
9432
9474
|
//
|
|
@@ -10300,7 +10342,8 @@ function CdlEdgeView({
|
|
|
10300
10342
|
active,
|
|
10301
10343
|
drawing,
|
|
10302
10344
|
progress,
|
|
10303
|
-
stateValues
|
|
10345
|
+
stateValues,
|
|
10346
|
+
flowing = false
|
|
10304
10347
|
}) {
|
|
10305
10348
|
const color = edgeColor(edge);
|
|
10306
10349
|
const marker = edgeHeadMarkerName(edge.tone, edge.head, !active, edge.headFill);
|
|
@@ -10318,6 +10361,7 @@ function CdlEdgeView({
|
|
|
10318
10361
|
"data-cdl-from": edge.from,
|
|
10319
10362
|
"data-cdl-to": edge.to,
|
|
10320
10363
|
"data-cdl-active": active ? "true" : "false",
|
|
10364
|
+
"data-cdl-flowing": flowing ? "true" : "false",
|
|
10321
10365
|
"data-cdl-drawing": drawing ? "true" : "false",
|
|
10322
10366
|
"data-cdl-path-d": edge.d,
|
|
10323
10367
|
"data-cdl-label-x": edge.labelX,
|
|
@@ -10370,7 +10414,11 @@ function CdlEdgeView({
|
|
|
10370
10414
|
strokeWidth: 14,
|
|
10371
10415
|
strokeLinecap: "round"
|
|
10372
10416
|
}
|
|
10373
|
-
)
|
|
10417
|
+
),
|
|
10418
|
+
flowing && !isDotted && /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "edge-flow", children: [
|
|
10419
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { id: glowPathId, d: edge.d, fill: "none", stroke: "none" }),
|
|
10420
|
+
/* @__PURE__ */ jsxRuntime.jsx(EdgeGlowCircles, { color, edgeId: edge.id })
|
|
10421
|
+
] })
|
|
10374
10422
|
]
|
|
10375
10423
|
}
|
|
10376
10424
|
);
|
|
@@ -18143,7 +18191,8 @@ function CdlNodeView({
|
|
|
18143
18191
|
progress,
|
|
18144
18192
|
stateValues,
|
|
18145
18193
|
currentPhaseId,
|
|
18146
|
-
chartLineScale
|
|
18194
|
+
chartLineScale,
|
|
18195
|
+
\u95A2\u4FC2\u306E\u53D7\u3051\u53E3
|
|
18147
18196
|
}) {
|
|
18148
18197
|
const value = node.value ? interpolate(node.value, stateValues) : void 0;
|
|
18149
18198
|
const rows = (node.rows ?? []).map((r) => interpolate(r, stateValues));
|
|
@@ -18465,6 +18514,23 @@ function CdlNodeView({
|
|
|
18465
18514
|
"data-cdl-eyebrow": resolvedNode.eyebrow ?? "",
|
|
18466
18515
|
"data-cdl-offset-x": offsetX || void 0,
|
|
18467
18516
|
"data-cdl-offset-y": offsetY || void 0,
|
|
18517
|
+
...\u95A2\u4FC2\u306E\u53D7\u3051\u53E3 === void 0 ? {} : {
|
|
18518
|
+
// 読み上げに「押せる」 ことを伝え、 tab でも辿れるようにする。
|
|
18519
|
+
role: "button",
|
|
18520
|
+
tabIndex: 0,
|
|
18521
|
+
"aria-pressed": \u95A2\u4FC2\u306E\u53D7\u3051\u53E3.\u7126\u70B9 === node.id,
|
|
18522
|
+
style: { cursor: "pointer" },
|
|
18523
|
+
onPointerEnter: () => \u95A2\u4FC2\u306E\u53D7\u3051\u53E3.\u89E6\u308C\u305F(node.id),
|
|
18524
|
+
onPointerLeave: () => \u95A2\u4FC2\u306E\u53D7\u3051\u53E3.\u96E2\u308C\u305F(),
|
|
18525
|
+
onFocus: () => \u95A2\u4FC2\u306E\u53D7\u3051\u53E3.\u89E6\u308C\u305F(node.id),
|
|
18526
|
+
onBlur: () => \u95A2\u4FC2\u306E\u53D7\u3051\u53E3.\u96E2\u308C\u305F(),
|
|
18527
|
+
onClick: () => \u95A2\u4FC2\u306E\u53D7\u3051\u53E3.\u62BC\u3057\u305F(node.id),
|
|
18528
|
+
onKeyDown: (e) => {
|
|
18529
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
18530
|
+
e.preventDefault();
|
|
18531
|
+
\u95A2\u4FC2\u306E\u53D7\u3051\u53E3.\u62BC\u3057\u305F(node.id);
|
|
18532
|
+
}
|
|
18533
|
+
},
|
|
18468
18534
|
transform: hasOffset ? `translate(${offsetX}, ${offsetY})` : void 0,
|
|
18469
18535
|
opacity: boundOpacity,
|
|
18470
18536
|
"data-cdl-tone": node.tone,
|
|
@@ -18488,6 +18554,18 @@ function CdlNodeView({
|
|
|
18488
18554
|
}
|
|
18489
18555
|
);
|
|
18490
18556
|
}
|
|
18557
|
+
|
|
18558
|
+
// src/render/relation-focus.ts
|
|
18559
|
+
function relatedFocusSet(edges, nodeId) {
|
|
18560
|
+
const \u96C6\u5408 = /* @__PURE__ */ new Set([nodeId]);
|
|
18561
|
+
for (const e of edges) {
|
|
18562
|
+
if (e.from !== nodeId && e.to !== nodeId) continue;
|
|
18563
|
+
\u96C6\u5408.add(e.id);
|
|
18564
|
+
\u96C6\u5408.add(e.from);
|
|
18565
|
+
\u96C6\u5408.add(e.to);
|
|
18566
|
+
}
|
|
18567
|
+
return \u96C6\u5408;
|
|
18568
|
+
}
|
|
18491
18569
|
function CdlStage({
|
|
18492
18570
|
laid,
|
|
18493
18571
|
currentPhase,
|
|
@@ -18498,7 +18576,35 @@ function CdlStage({
|
|
|
18498
18576
|
compact = false,
|
|
18499
18577
|
svgRef
|
|
18500
18578
|
}) {
|
|
18501
|
-
const
|
|
18579
|
+
const [\u7126\u70B9, set\u7126\u70B9] = react.useState(null);
|
|
18580
|
+
const \u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B = (laid.relationFocus ?? RELATION_FOCUS_DEFAULT) === "hover";
|
|
18581
|
+
const \u52D5\u304D\u3092\u63A7\u3048\u308B = useReducedMotion();
|
|
18582
|
+
react.useEffect(() => {
|
|
18583
|
+
if (!\u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B) set\u7126\u70B9(null);
|
|
18584
|
+
}, [\u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B]);
|
|
18585
|
+
react.useEffect(() => {
|
|
18586
|
+
if (!\u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B || \u7126\u70B9?.\u7559\u3081\u305F !== true) return;
|
|
18587
|
+
const \u62BC\u3057\u305F2 = (e) => {
|
|
18588
|
+
if (e.key === "Escape") set\u7126\u70B9(null);
|
|
18589
|
+
};
|
|
18590
|
+
window.addEventListener("keydown", \u62BC\u3057\u305F2);
|
|
18591
|
+
return () => window.removeEventListener("keydown", \u62BC\u3057\u305F2);
|
|
18592
|
+
}, [\u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B, \u7126\u70B9?.\u7559\u3081\u305F]);
|
|
18593
|
+
const \u89E6\u308C\u305F = react.useCallback((id) => {
|
|
18594
|
+
set\u7126\u70B9((\u524D) => \u524D?.\u7559\u3081\u305F === true ? \u524D : { id, \u7559\u3081\u305F: false });
|
|
18595
|
+
}, []);
|
|
18596
|
+
const \u96E2\u308C\u305F = react.useCallback(() => {
|
|
18597
|
+
set\u7126\u70B9((\u524D) => \u524D?.\u7559\u3081\u305F === true ? \u524D : null);
|
|
18598
|
+
}, []);
|
|
18599
|
+
const \u62BC\u3057\u305F = react.useCallback((id) => {
|
|
18600
|
+
set\u7126\u70B9((\u524D) => \u524D?.id === id && \u524D.\u7559\u3081\u305F ? null : { id, \u7559\u3081\u305F: true });
|
|
18601
|
+
}, []);
|
|
18602
|
+
const \u7126\u70B9\u306E\u96C6\u5408 = react.useMemo(
|
|
18603
|
+
() => \u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B && \u7126\u70B9 !== null ? relatedFocusSet(laid.edges, \u7126\u70B9.id) : null,
|
|
18604
|
+
[\u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B, \u7126\u70B9, laid.edges]
|
|
18605
|
+
);
|
|
18606
|
+
const activeSet = \u7126\u70B9\u306E\u96C6\u5408 ?? new Set(currentPhase?.activate ?? []);
|
|
18607
|
+
const \u7BB1\u306E\u53D7\u3051\u53E3 = \u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B ? { \u89E6\u308C\u305F, \u96E2\u308C\u305F, \u62BC\u3057\u305F, \u7126\u70B9: \u7126\u70B9?.id ?? null } : void 0;
|
|
18502
18608
|
const \u77E2\u5370\u306E\u51FA\u756A = react.useMemo(() => {
|
|
18503
18609
|
const \u521D\u51FA = /* @__PURE__ */ new Map();
|
|
18504
18610
|
laid.phases.forEach((p, i) => {
|
|
@@ -18729,6 +18835,7 @@ function CdlStage({
|
|
|
18729
18835
|
{
|
|
18730
18836
|
edge,
|
|
18731
18837
|
active: activeSet.has(edge.id),
|
|
18838
|
+
flowing: \u7126\u70B9\u306E\u96C6\u5408?.has(edge.id) === true && !\u52D5\u304D\u3092\u63A7\u3048\u308B,
|
|
18732
18839
|
drawing: \u77E2\u5370\u306E\u51FA\u756A.\u4F38\u3070\u3059\u304B(edge.id),
|
|
18733
18840
|
progress: \u77E2\u5370\u306E\u51FA\u756A.\u4F38\u3070\u3059\u304B(edge.id) ? \u63CF\u304F\u9032\u307F : progress,
|
|
18734
18841
|
stateValues
|
|
@@ -18742,6 +18849,7 @@ function CdlStage({
|
|
|
18742
18849
|
{
|
|
18743
18850
|
node,
|
|
18744
18851
|
active: activeSet.has(node.id),
|
|
18852
|
+
\u95A2\u4FC2\u306E\u53D7\u3051\u53E3: \u7BB1\u306E\u53D7\u3051\u53E3,
|
|
18745
18853
|
drawing: \u63CF\u304F,
|
|
18746
18854
|
progress: \u63CF\u304F ? \u63CF\u304F\u9032\u307F : progress,
|
|
18747
18855
|
stateValues,
|