@cardenelabs/cdl 0.6.1 → 0.9.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +401 -0
  2. package/SPEC.md +32 -17
  3. package/dist/index.cjs +820 -364
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +68 -14
  6. package/dist/index.d.ts +68 -14
  7. package/dist/index.js +820 -364
  8. package/dist/index.js.map +1 -1
  9. package/dist/react.cjs +692 -254
  10. package/dist/react.cjs.map +1 -1
  11. package/dist/react.d.cts +1 -1
  12. package/dist/react.d.ts +1 -1
  13. package/dist/react.js +692 -254
  14. package/dist/react.js.map +1 -1
  15. package/dist/{render-DquCvgOB.d.cts → render-hmFRAabt.d.cts} +33 -2
  16. package/dist/{render-DquCvgOB.d.ts → render-hmFRAabt.d.ts} +33 -2
  17. package/package.json +6 -3
  18. package/src/kinds/box-lines.ts +120 -0
  19. package/src/kinds/gantt.tsx +152 -24
  20. package/src/kinds/mind-map.tsx +77 -16
  21. package/src/kinds/quadrant.tsx +28 -2
  22. package/src/kinds/shape-blockchain.tsx +65 -12
  23. package/src/kinds/shape-region.tsx +152 -34
  24. package/src/kinds/tree.tsx +121 -24
  25. package/src/layout/collisions.ts +10 -2
  26. package/src/layout/footer-shape.ts +86 -24
  27. package/src/layout/lifeline.ts +80 -0
  28. package/src/layout/spec.ts +21 -2
  29. package/src/layout/text-width.ts +92 -4
  30. package/src/layout/viewbox.ts +0 -8
  31. package/src/layout.ts +8 -1
  32. package/src/presets.ts +120 -22
  33. package/src/render/header.tsx +3 -1
  34. package/src/render/nodes.tsx +6 -5
  35. package/src/render/payload-binding.ts +88 -3
  36. package/src/render/stage.tsx +17 -34
  37. package/src/render/template-fields.ts +212 -0
  38. package/src/render/utils.ts +32 -2
  39. package/src/render.tsx +2 -9
  40. package/src/types.ts +33 -2
  41. package/src/validate.ts +27 -9
  42. package/src/visual-validate.ts +34 -1
  43. package/src/layout/label-shift.ts +0 -28
package/dist/index.js CHANGED
@@ -11603,7 +11603,35 @@ function isCJK(code) {
11603
11603
  function isHalfwidthKana(code) {
11604
11604
  return code >= 65377 && code <= 65500;
11605
11605
  }
11606
+ var EMOJI_ADVANCE_EM = 1.05;
11607
+ var MONO_EMOJI_ADVANCE_EM = 1.16;
11608
+ var WIDE_SYMBOL_ADVANCE_EM = 0.95;
11609
+ function isEmoji(code) {
11610
+ return code >= 126976 && code <= 129791 || // 絵文字の主要面
11611
+ code >= 9728 && code <= 10175 || // 記号と絵文字 (♻ ✅ ❤ 等)
11612
+ code >= 127462 && code <= 127487;
11613
+ }
11614
+ function isEmojiGrapheme(grapheme, firstCode) {
11615
+ return isEmoji(firstCode) || grapheme.includes("\uFE0F");
11616
+ }
11617
+ function isWideSymbol(code) {
11618
+ return code >= 8592 && code <= 8703 || // 矢印
11619
+ code >= 9472 && code <= 9599 || // 罫線
11620
+ code >= 9632 && code <= 9727 || // 幾何図形
11621
+ code >= 11008 && code <= 11263;
11622
+ }
11623
+ var CLUSTER_JOINER_RE = /\u200d|\ufe0f|[\u{1f000}-\u{1faff}]|[\u{2600}-\u{27bf}]/u;
11624
+ var \u66F8\u8A18\u7D20\u3067\u5206\u3051\u308B;
11625
+ function segmentGraphemes(text) {
11626
+ if (typeof Intl === "undefined" || typeof Intl.Segmenter !== "function") {
11627
+ return [...text];
11628
+ }
11629
+ \u66F8\u8A18\u7D20\u3067\u5206\u3051\u308B ??= new Intl.Segmenter(void 0, { granularity: "grapheme" });
11630
+ return [...\u66F8\u8A18\u7D20\u3067\u5206\u3051\u308B.segment(text)].map((s) => s.segment);
11631
+ }
11606
11632
  function defaultAdvanceEm(ch, code) {
11633
+ if (isEmoji(code)) return EMOJI_ADVANCE_EM;
11634
+ if (isWideSymbol(code)) return WIDE_SYMBOL_ADVANCE_EM;
11607
11635
  if (isCJK(code)) return 1.08;
11608
11636
  if (isHalfwidthKana(code)) return 0.72;
11609
11637
  if (ch >= "a" && ch <= "z") return 0.73;
@@ -11617,19 +11645,23 @@ function measureTextWidth(text, opts = {}) {
11617
11645
  const fontFamily = opts.fontFamily ?? "sans";
11618
11646
  let advanceEmSum = 0;
11619
11647
  let charCount = 0;
11620
- for (const ch of text) {
11648
+ const \u6587\u5B57\u5217 = CLUSTER_JOINER_RE.test(text) ? segmentGraphemes(text) : [...text];
11649
+ for (const ch of \u6587\u5B57\u5217) {
11621
11650
  charCount++;
11651
+ const code = ch.codePointAt(0) ?? 0;
11652
+ if (isEmojiGrapheme(ch, code)) {
11653
+ advanceEmSum += fontFamily === "mono" ? MONO_EMOJI_ADVANCE_EM : EMOJI_ADVANCE_EM;
11654
+ continue;
11655
+ }
11622
11656
  if (fontFamily === "mono") {
11623
- const code2 = ch.codePointAt(0) ?? 0;
11624
- advanceEmSum += isCJK(code2) ? 1.08 : JETBRAINS_MONO_ADVANCE_EM;
11657
+ advanceEmSum += isCJK(code) ? 1.08 : JETBRAINS_MONO_ADVANCE_EM;
11625
11658
  continue;
11626
11659
  }
11627
- const code = ch.codePointAt(0) ?? 0;
11628
11660
  if (isCJK(code)) {
11629
11661
  advanceEmSum += 1.08;
11630
11662
  continue;
11631
11663
  }
11632
- const table = INTER_BOLD_ADVANCE_EM[ch];
11664
+ const table = ch.length === 1 ? INTER_BOLD_ADVANCE_EM[ch] : void 0;
11633
11665
  advanceEmSum += table !== void 0 ? table : defaultAdvanceEm(ch, code);
11634
11666
  }
11635
11667
  const w = advanceEmSum * fontSize + letterSpacing * charCount;
@@ -11685,13 +11717,15 @@ var KINDS_WITHOUT_TITLE_TEXT = /* @__PURE__ */ new Set([
11685
11717
  "funnel-stages",
11686
11718
  "quadrant-matrix",
11687
11719
  "tree-hierarchy",
11688
- "journey-map",
11689
- // 形の中に自前の文字を置く (title は使わない)
11690
- "shape-blockchain-block"
11720
+ "journey-map"
11691
11721
  ]);
11692
11722
  function rendersTitleText(kind) {
11693
11723
  return !KINDS_WITHOUT_TITLE_TEXT.has(kind ?? "");
11694
11724
  }
11725
+ var KINDS_FITTING_OWN_TITLE = /* @__PURE__ */ new Set(["shape-blockchain-block"]);
11726
+ function fitsOwnTitleWidth(kind) {
11727
+ return KINDS_FITTING_OWN_TITLE.has(kind ?? "");
11728
+ }
11695
11729
  var KINDS_WITH_ROW_TEXT = /* @__PURE__ */ new Set([
11696
11730
  // 専用の表組み (StorageNode)
11697
11731
  "storage",
@@ -11893,6 +11927,70 @@ function buildDiagramAltText(topic, phase) {
11893
11927
  return parts.join(" ");
11894
11928
  }
11895
11929
 
11930
+ // src/layout/footer-shape.ts
11931
+ var SHAPE_DRAW_UP_EXTENT = {
11932
+ "shape-robot-arm": 201,
11933
+ // 実測 上 129
11934
+ "shape-iot-sensor": 120,
11935
+ // 48
11936
+ "shape-credit-card": 113,
11937
+ // 40.8
11938
+ "shape-exchange": 107,
11939
+ // 35
11940
+ "shape-storefront": 104,
11941
+ // 32
11942
+ "shape-cdn-edge": 103,
11943
+ // 30.8
11944
+ "shape-payment-provider": 101,
11945
+ // 29
11946
+ "shape-gear": 96,
11947
+ // 23.9
11948
+ "shape-rpc-node": 94,
11949
+ // 22
11950
+ "shape-wallet": 84
11951
+ // 12.1
11952
+ };
11953
+ function lifelineFooterNodes(lanes, nodes) {
11954
+ const \u6570 = /* @__PURE__ */ new Map();
11955
+ for (const n of nodes) \u6570.set(n.lane, (\u6570.get(n.lane) ?? 0) + 1);
11956
+ const lifelineLanes = /* @__PURE__ */ new Set();
11957
+ for (const lane of lanes) {
11958
+ if (lane.lifeline) lifelineLanes.add(lane.id);
11959
+ }
11960
+ return nodes.filter(
11961
+ (n) => n.role === "lifeline-footer" && lifelineLanes.has(n.lane) && (\u6570.get(n.lane) ?? 0) >= 2
11962
+ );
11963
+ }
11964
+ function footerShapeDropY(kind, h) {
11965
+ const extent = SHAPE_DRAW_UP_EXTENT[kind];
11966
+ if (extent === void 0) return 0;
11967
+ if (!Number.isFinite(h) || h <= 0) return 0;
11968
+ return Math.max(0, extent - h);
11969
+ }
11970
+ function footerShapeDrops(lanes, nodes) {
11971
+ return footerShapeDropsOf(lifelineFooterNodes(lanes, nodes));
11972
+ }
11973
+ function footerShapeDropsOf(footers) {
11974
+ const drops = /* @__PURE__ */ new Map();
11975
+ for (const footer of footers) {
11976
+ const dy = footerShapeDropY(footer.kind, footer.h);
11977
+ if (dy > 0) drops.set(footer.id, dy);
11978
+ }
11979
+ return drops;
11980
+ }
11981
+ function applyFooterShapeDrops(lanes, nodes) {
11982
+ const drops = footerShapeDrops(lanes, nodes);
11983
+ if (drops.size === 0) return nodes;
11984
+ return nodes.map((n) => {
11985
+ if (n.posX !== void 0 && n.posY !== void 0) return n;
11986
+ const dy = drops.get(n.id);
11987
+ return dy === void 0 ? n : { ...n, cy: n.cy + dy };
11988
+ });
11989
+ }
11990
+ function footerShapeDrawTop(node) {
11991
+ return node.cy - node.h / 2 - footerShapeDropY(node.kind, node.h);
11992
+ }
11993
+
11896
11994
  // src/layout/collisions.ts
11897
11995
  var LANE_LABEL_CLEARANCE_MARGIN = 2;
11898
11996
  function collectBBoxes(lanes, nodes, edges) {
@@ -11908,14 +12006,16 @@ function collectBBoxes(lanes, nodes, edges) {
11908
12006
  h: 28
11909
12007
  });
11910
12008
  }
12009
+ const footerDraw = footerShapeDrops(lanes, nodes);
11911
12010
  for (const n of nodes) {
12011
+ const up = footerDraw.get(n.id) ?? 0;
11912
12012
  out.push({
11913
12013
  kind: "node",
11914
12014
  id: n.id,
11915
12015
  x: n.cx - n.w / 2,
11916
- y: n.cy - n.h / 2,
12016
+ y: n.cy - n.h / 2 - up,
11917
12017
  w: n.w,
11918
- h: n.h
12018
+ h: n.h + up
11919
12019
  });
11920
12020
  }
11921
12021
  for (const e of edges) {
@@ -14898,67 +14998,6 @@ function layoutNodes(diag, lanes) {
14898
14998
  return out;
14899
14999
  }
14900
15000
 
14901
- // src/layout/footer-shape.ts
14902
- var SHAPE_DRAW_UP_EXTENT = {
14903
- "shape-robot-arm": 201,
14904
- // 実測 上 129
14905
- "shape-iot-sensor": 120,
14906
- // 48
14907
- "shape-credit-card": 113,
14908
- // 40.8
14909
- "shape-exchange": 107,
14910
- // 35
14911
- "shape-storefront": 104,
14912
- // 32
14913
- "shape-cdn-edge": 103,
14914
- // 30.8
14915
- "shape-payment-provider": 101,
14916
- // 29
14917
- "shape-gear": 96,
14918
- // 23.9
14919
- "shape-rpc-node": 94,
14920
- // 22
14921
- "shape-wallet": 84
14922
- // 12.1
14923
- };
14924
- function lifelineFooterNodes(lanes, nodes) {
14925
- const byLane = /* @__PURE__ */ new Map();
14926
- for (const n of nodes) {
14927
- const inside = byLane.get(n.lane);
14928
- if (inside) inside.push(n);
14929
- else byLane.set(n.lane, [n]);
14930
- }
14931
- const footers = [];
14932
- for (const lane of lanes) {
14933
- if (!lane.lifeline) continue;
14934
- const inside = byLane.get(lane.id);
14935
- if (inside === void 0 || inside.length < 2) continue;
14936
- let footer = inside[0];
14937
- for (const n of inside) {
14938
- if (n.cy >= footer.cy) footer = n;
14939
- }
14940
- footers.push(footer);
14941
- }
14942
- return footers;
14943
- }
14944
- function footerShapeDropY(kind, h) {
14945
- const extent = SHAPE_DRAW_UP_EXTENT[kind];
14946
- if (extent === void 0) return 0;
14947
- if (!Number.isFinite(h) || h <= 0) return 0;
14948
- return Math.max(0, extent - h);
14949
- }
14950
- function footerShapeDrops(lanes, nodes) {
14951
- return footerShapeDropsOf(lifelineFooterNodes(lanes, nodes));
14952
- }
14953
- function footerShapeDropsOf(footers) {
14954
- const drops = /* @__PURE__ */ new Map();
14955
- for (const footer of footers) {
14956
- const dy = footerShapeDropY(footer.kind, footer.h);
14957
- if (dy > 0) drops.set(footer.id, dy);
14958
- }
14959
- return drops;
14960
- }
14961
-
14962
15001
  // src/layout/viewbox.ts
14963
15002
  function computeViewBox(lanes, nodes, edges, bboxes, viewport) {
14964
15003
  let maxX = 0;
@@ -14979,11 +15018,6 @@ function computeViewBox(lanes, nodes, edges, bboxes, viewport) {
14979
15018
  maxX = Math.max(maxX, n.cx + n.w / 2);
14980
15019
  maxY = Math.max(maxY, n.cy + n.h / 2);
14981
15020
  }
14982
- const footerDrops = footerShapeDrops(lanes, nodes);
14983
- for (const n of nodes) {
14984
- const dy = footerDrops.get(n.id);
14985
- if (dy !== void 0) maxY = Math.max(maxY, n.cy + n.h / 2 + dy);
14986
- }
14987
15021
  if (!Number.isFinite(minX)) minX = 0;
14988
15022
  if (!Number.isFinite(minY)) minY = 0;
14989
15023
  const x = minX - VIEW_PAD;
@@ -15061,7 +15095,7 @@ function applyRowLevelNodeShifts(nodes, lanes, nodeShifts) {
15061
15095
  }
15062
15096
  function layout(diag) {
15063
15097
  const lanes = layoutLanes(diag);
15064
- const rawNodes = layoutNodes(diag, lanes);
15098
+ const rawNodes = applyFooterShapeDrops(lanes, layoutNodes(diag, lanes));
15065
15099
  const expandedLanes = expandLanesForNodes(lanes, rawNodes);
15066
15100
  const gapExpandedLanes = expandLaneGapsForEdgeLabels(expandedLanes, rawNodes, diag.edges);
15067
15101
  const nodes = rawNodes.map((n) => {
@@ -15580,7 +15614,7 @@ function templateRefIds(text) {
15580
15614
  return out;
15581
15615
  }
15582
15616
  function computeStateValues(laid, phaseIdx, progress) {
15583
- const values = {};
15617
+ const values = /* @__PURE__ */ Object.create(null);
15584
15618
  for (const s of laid.states) values[s.id] = s.initial;
15585
15619
  for (let i = 0; i < laid.phases.length; i++) {
15586
15620
  const phase = laid.phases[i];
@@ -15598,10 +15632,20 @@ function computeStateValues(laid, phaseIdx, progress) {
15598
15632
  }
15599
15633
  }
15600
15634
  }
15601
- const out = {};
15635
+ const out = /* @__PURE__ */ Object.create(null);
15602
15636
  for (const [k, v] of Object.entries(values)) out[k] = String(v);
15603
15637
  return withDerivedValues(out, laid.derived);
15604
15638
  }
15639
+ function mergeStateValues(base, overrides) {
15640
+ const merged = Object.assign(/* @__PURE__ */ Object.create(null), base);
15641
+ for (const key of Object.keys(overrides)) {
15642
+ const v = overrides[key];
15643
+ if (typeof v === "number" || typeof v === "string" || typeof v === "boolean") {
15644
+ merged[key] = String(v);
15645
+ }
15646
+ }
15647
+ return merged;
15648
+ }
15605
15649
  function interpolate(template, values) {
15606
15650
  return template.replace(TEMPLATE_REF_RE, (_, id, accessor) => {
15607
15651
  const raw = Object.hasOwn(values, id) ? values[id] : void 0;
@@ -15751,6 +15795,65 @@ function pathSubpath(d, progress) {
15751
15795
  return d;
15752
15796
  }
15753
15797
 
15798
+ // src/render/template-fields.ts
15799
+ var TEXT_FIELDS = ["title", "eyebrow", "subtitle", "value", "wBind", "hBind", "visibleIf"];
15800
+ var LIST_FIELDS = ["rows"];
15801
+ var NUMERIC_FIELDS = ["opacity", "renderOffsetX", "renderOffsetY"];
15802
+ var SHAPE_TEMPLATE_FIELDS = ["source", "radius", "fillProgress", "angle", "level", "rotation", "fill"];
15803
+ function shapeTexts(shape) {
15804
+ if (!shape) return [];
15805
+ const out = [];
15806
+ const \u4E2D\u8EAB = shape;
15807
+ for (const f of SHAPE_TEMPLATE_FIELDS) {
15808
+ const v = \u4E2D\u8EAB[f];
15809
+ if (typeof v === "string" && v) out.push(v);
15810
+ }
15811
+ return out;
15812
+ }
15813
+ function payloadTexts(node) {
15814
+ const out = [];
15815
+ const \u8DB3\u3059 = (v) => {
15816
+ if (typeof v === "string" && v) out.push(v);
15817
+ };
15818
+ for (const d of node.chartData ?? []) \u8DB3\u3059(d.value);
15819
+ for (const s of node.funnelData ?? []) \u8DB3\u3059(s.count);
15820
+ for (const t of node.ganttData ?? []) {
15821
+ \u8DB3\u3059(t.startIdx);
15822
+ \u8DB3\u3059(t.endIdx);
15823
+ }
15824
+ for (const i of node.quadrantData?.items ?? []) \u8DB3\u3059(i.quadrant);
15825
+ for (const s of node.journeyData ?? []) \u8DB3\u3059(s.emotion);
15826
+ for (const n of node.treeData ?? []) {
15827
+ \u8DB3\u3059(n.title);
15828
+ \u8DB3\u3059(n.subtitle);
15829
+ }
15830
+ if (node.mindData) {
15831
+ \u8DB3\u3059(node.mindData.rootTitle);
15832
+ for (const b of node.mindData.branches) {
15833
+ \u8DB3\u3059(b.title);
15834
+ \u8DB3\u3059(b.subtitle);
15835
+ }
15836
+ }
15837
+ return out;
15838
+ }
15839
+ function nodeTemplateTexts(node) {
15840
+ const out = [];
15841
+ for (const f of TEXT_FIELDS) {
15842
+ const v = node[f];
15843
+ if (typeof v === "string" && v) out.push(v);
15844
+ }
15845
+ for (const f of LIST_FIELDS) {
15846
+ for (const v of node[f] ?? []) if (v) out.push(v);
15847
+ }
15848
+ for (const f of NUMERIC_FIELDS) {
15849
+ const v = node[f];
15850
+ if (typeof v === "string" && v) out.push(v);
15851
+ }
15852
+ out.push(...shapeTexts(node.shape));
15853
+ out.push(...payloadTexts(node));
15854
+ return out;
15855
+ }
15856
+
15754
15857
  // src/validate.ts
15755
15858
  var TONES2 = new Set(TONES);
15756
15859
  var KINDS = new Set(NODE_KINDS);
@@ -15809,7 +15912,13 @@ function validate(diag) {
15809
15912
  const nodeIds = new Set(diag.nodes.map((n) => n.id));
15810
15913
  const edgeIds = new Set(diag.edges.map((e) => e.id));
15811
15914
  const stateIds = new Set(diag.states.map((s) => s.id));
15812
- const readableIds = /* @__PURE__ */ new Set([...stateIds, ...(diag.derived ?? []).map((d) => d.id)]);
15915
+ const readableIds = /* @__PURE__ */ new Set([
15916
+ ...stateIds,
15917
+ ...(diag.derived ?? []).map((d) => d.id),
15918
+ ...(diag.inputs ?? []).map((i) => i.id),
15919
+ ...(diag.formulas ?? []).map((f) => f.id),
15920
+ ...(diag.scrollTriggers ?? []).map((t) => t.id)
15921
+ ]);
15813
15922
  const suggest = (target, candidates) => {
15814
15923
  const list = [...candidates];
15815
15924
  if (list.length === 0) return "";
@@ -15876,10 +15985,7 @@ function validate(diag) {
15876
15985
  }
15877
15986
  }
15878
15987
  for (const n of diag.nodes) {
15879
- const checks = [];
15880
- if (n.value) checks.push(n.value);
15881
- if (n.rows) checks.push(...n.rows);
15882
- for (const text of checks) {
15988
+ for (const text of nodeTemplateTexts(n)) {
15883
15989
  for (const id of templateRefIds(text)) {
15884
15990
  if (!readableIds.has(id)) {
15885
15991
  warnings.push(`node "${n.id}" \u304C\u672A\u5B9A\u7FA9 state "${id}" \u3092\u53C2\u7167`);
@@ -15907,8 +16013,7 @@ function validate(diag) {
15907
16013
  for (const s of p.sets) stateUsed.add(s.stateId);
15908
16014
  }
15909
16015
  for (const n of diag.nodes) {
15910
- const texts2 = [n.value, ...n.rows ?? []].filter(Boolean);
15911
- for (const text of texts2) {
16016
+ for (const text of nodeTemplateTexts(n)) {
15912
16017
  for (const id of templateRefIds(text)) stateUsed.add(id);
15913
16018
  }
15914
16019
  }
@@ -15988,6 +16093,187 @@ function compile(diag) {
15988
16093
  validate(diag);
15989
16094
  return layout(diag);
15990
16095
  }
16096
+ var TITLE_MAX = 18;
16097
+ var TITLE_MIN = 9;
16098
+ var TITLE_RATIO = 0.17;
16099
+ var SUB_RATIO = 0.72;
16100
+ var LINE_GAP = 3;
16101
+ var BOTTOM_PAD = 4;
16102
+ var ASCENT = 0.72;
16103
+ var DESCENT = 0.25;
16104
+ var ART_GAP = 4;
16105
+ var ART_MIN_BAND = 45;
16106
+ var \u843D\u3068\u3057\u3066\u3082\u63CF\u304F\u7A2E\u5225 = {
16107
+ \u80A9\u66F8: /* @__PURE__ */ new Set([
16108
+ // basement 系 = `commonLabel` が自前の帯に置く
16109
+ "shape-file",
16110
+ "shape-folder",
16111
+ "shape-cloud",
16112
+ "shape-cylinder",
16113
+ "shape-hexagon",
16114
+ "shape-diamond",
16115
+ "shape-stack",
16116
+ // software 系 = 固有 layout
16117
+ "shape-window",
16118
+ "shape-terminal",
16119
+ "shape-code-block",
16120
+ "shape-message-bubble",
16121
+ "shape-gear",
16122
+ // hardware 系のうち固有 layout を持つもの
16123
+ "shape-iot-sensor",
16124
+ "shape-robot-arm"
16125
+ ]),
16126
+ \u8AAC\u660E: /* @__PURE__ */ new Set([
16127
+ // basement 系 = `commonLabel` が自前の帯に置く
16128
+ "shape-file",
16129
+ "shape-folder",
16130
+ "shape-cloud",
16131
+ "shape-cylinder",
16132
+ "shape-hexagon",
16133
+ "shape-diamond",
16134
+ "shape-stack",
16135
+ // software 系 = 固有 layout
16136
+ "shape-window",
16137
+ "shape-message-bubble",
16138
+ "shape-gear",
16139
+ // hardware / blockchain 系のうち固有 layout を持つもの
16140
+ "shape-iot-sensor",
16141
+ "shape-robot-arm",
16142
+ "shape-blockchain-block"
16143
+ ])
16144
+ };
16145
+ function droppedLineIsHidden(kind, line) {
16146
+ return kind.startsWith("shape-") && !\u843D\u3068\u3057\u3066\u3082\u63CF\u304F\u7A2E\u5225[line].has(kind);
16147
+ }
16148
+ function labelPlan(node) {
16149
+ const \u9AD8\u3055 = Math.max(0, node.h);
16150
+ const \u5E95 = node.cy + \u9AD8\u3055 / 2;
16151
+ const \u5929 = node.cy - \u9AD8\u3055 / 2;
16152
+ const \u7A4D\u3080 = (\u540D\u524D\u5927, \u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2, \u4E0B\u4F59\u767D) => {
16153
+ const \u5C0F\u3055\u3044\u5B57 = Math.max(1, Math.round(\u540D\u524D\u5927 * SUB_RATIO));
16154
+ let y = \u5E95 - \u4E0B\u4F59\u767D;
16155
+ const \u8AAC\u660E = \u8AAC\u660E\u3042\u308A2 ? { y, size: \u5C0F\u3055\u3044\u5B57 } : null;
16156
+ if (\u8AAC\u660E !== null) y -= \u5C0F\u3055\u3044\u5B57 + LINE_GAP;
16157
+ const \u540D\u524D = { y, size: \u540D\u524D\u5927 };
16158
+ y -= \u540D\u524D\u5927 + LINE_GAP;
16159
+ const \u80A9\u66F8 = \u80A9\u66F8\u3042\u308A2 ? { y, size: \u5C0F\u3055\u3044\u5B57 } : null;
16160
+ const \u4E0A\u306E\u884C = \u80A9\u66F8 ?? \u540D\u524D;
16161
+ return { \u540D\u524D, \u8AAC\u660E, \u80A9\u66F8, \u4E0A\u7AEF: \u4E0A\u306E\u884C.y - \u4E0A\u306E\u884C.size * ASCENT };
16162
+ };
16163
+ const \u5165\u308B = (\u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2) => \u7A4D\u3080(1, \u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2, 1 * DESCENT).\u4E0A\u7AEF >= \u5929;
16164
+ let \u8AAC\u660E\u3042\u308A = Boolean(node.subtitle);
16165
+ let \u80A9\u66F8\u3042\u308A = Boolean(node.eyebrow);
16166
+ const \u843D\u3068\u3057\u305F = [];
16167
+ if (!\u5165\u308B(\u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A) && \u80A9\u66F8\u3042\u308A) {
16168
+ \u80A9\u66F8\u3042\u308A = false;
16169
+ \u843D\u3068\u3057\u305F.push("\u80A9\u66F8");
16170
+ }
16171
+ if (!\u5165\u308B(\u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A) && \u8AAC\u660E\u3042\u308A) {
16172
+ \u8AAC\u660E\u3042\u308A = false;
16173
+ \u843D\u3068\u3057\u305F.push("\u8AAC\u660E");
16174
+ }
16175
+ const \u7D44\u3080 = (\u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2) => {
16176
+ const \u4E0A\u9650 = Math.min(TITLE_MAX, Math.max(1, Math.round(\u9AD8\u3055 * TITLE_RATIO)));
16177
+ let \u540D\u524D\u5927 = 0;
16178
+ for (let size = \u4E0A\u9650; size >= 1; size--) {
16179
+ const \u5C0F\u3055\u3044\u5B572 = Math.max(1, Math.round(size * SUB_RATIO));
16180
+ const \u4E0B\u306E\u884C\u5927 = \u8AAC\u660E\u3042\u308A2 ? \u5C0F\u3055\u3044\u5B572 : size;
16181
+ if (\u7A4D\u3080(size, \u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2, \u4E0B\u306E\u884C\u5927 * DESCENT).\u4E0A\u7AEF >= \u5929) {
16182
+ \u540D\u524D\u5927 = size;
16183
+ break;
16184
+ }
16185
+ }
16186
+ if (\u540D\u524D\u5927 === 0) \u540D\u524D\u5927 = \u9AD8\u3055 / (ASCENT + DESCENT);
16187
+ const \u5C0F\u3055\u3044\u5B57 = Math.max(1, Math.round(\u540D\u524D\u5927 * SUB_RATIO));
16188
+ const \u5F35\u308A\u51FA\u3057 = (\u8AAC\u660E\u3042\u308A2 ? \u5C0F\u3055\u3044\u5B57 : \u540D\u524D\u5927) * DESCENT;
16189
+ const \u4F59\u308A = Math.max(0, \u7A4D\u3080(\u540D\u524D\u5927, \u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2, \u5F35\u308A\u51FA\u3057).\u4E0A\u7AEF - \u5929);
16190
+ const \u4E0B\u4F59\u767D = Math.min(Math.max(BOTTOM_PAD, \u5F35\u308A\u51FA\u3057), \u5F35\u308A\u51FA\u3057 + \u4F59\u308A);
16191
+ return \u7A4D\u3080(\u540D\u524D\u5927, \u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2, \u4E0B\u4F59\u767D);
16192
+ };
16193
+ const \u7D75\u306E\u5E2F = (\u7D442) => Math.max(0, \u7D442.\u4E0A\u7AEF - ART_GAP - \u5929);
16194
+ let \u7D44 = \u7D44\u3080(\u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A);
16195
+ if (\u7D75\u306E\u5E2F(\u7D44) < ART_MIN_BAND && \u80A9\u66F8\u3042\u308A) {
16196
+ \u80A9\u66F8\u3042\u308A = false;
16197
+ \u843D\u3068\u3057\u305F.push("\u80A9\u66F8");
16198
+ \u7D44 = \u7D44\u3080(\u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A);
16199
+ }
16200
+ if (\u7D75\u306E\u5E2F(\u7D44) < ART_MIN_BAND && \u8AAC\u660E\u3042\u308A) {
16201
+ \u8AAC\u660E\u3042\u308A = false;
16202
+ \u843D\u3068\u3057\u305F.push("\u8AAC\u660E");
16203
+ \u7D44 = \u7D44\u3080(\u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A);
16204
+ }
16205
+ const \u4E00\u756A\u5C0F\u3055\u3044\u884C = Math.min(
16206
+ ...[\u7D44.\u540D\u524D, \u7D44.\u8AAC\u660E, \u7D44.\u80A9\u66F8].filter((l) => l !== null).map((l) => l.size)
16207
+ );
16208
+ return {
16209
+ \u540D\u524D: \u7D44.\u540D\u524D,
16210
+ \u8AAC\u660E: \u7D44.\u8AAC\u660E,
16211
+ \u80A9\u66F8: \u7D44.\u80A9\u66F8,
16212
+ top: \u7D44.\u4E0A\u7AEF,
16213
+ \u8AAD\u3081\u308B: \u4E00\u756A\u5C0F\u3055\u3044\u884C >= TITLE_MIN,
16214
+ \u843D\u3068\u3057\u305F
16215
+ };
16216
+ }
16217
+ function shapeRegion(node) {
16218
+ const label = labelPlan(node);
16219
+ const \u5929 = node.cy - node.h / 2;
16220
+ const availH = Math.max(0, label.top - ART_GAP - \u5929);
16221
+ return {
16222
+ cx: node.cx,
16223
+ cy: \u5929 + availH / 2,
16224
+ availW: node.w,
16225
+ availH,
16226
+ labelY: label.\u540D\u524D.y,
16227
+ label
16228
+ };
16229
+ }
16230
+ var SHADOW_GAP = 8;
16231
+ var FRAME_HALF = 1.5;
16232
+ function bodyBand(node, opt) {
16233
+ const \u5F71 = Math.max(0, opt.\u5F71ry);
16234
+ const \u5916 = Math.max(0, opt.\u5916 ?? FRAME_HALF);
16235
+ const \u4E0B\u4F59\u767D = Math.max(SHADOW_GAP + \u5F71, \u5916);
16236
+ const \u7BB1w = Math.max(0, node.w);
16237
+ const \u7BB1h = Math.max(0, node.h);
16238
+ const \u7E26\u4F59\u767D = \u5916 + \u4E0B\u4F59\u767D;
16239
+ const ky = \u7E26\u4F59\u767D > \u7BB1h && \u7E26\u4F59\u767D > 0 ? \u7BB1h / \u7E26\u4F59\u767D : 1;
16240
+ const \u6A2A\u4F59\u767D = \u5916 * 2;
16241
+ const kx = \u6A2A\u4F59\u767D > \u7BB1w && \u6A2A\u4F59\u767D > 0 ? \u7BB1w / \u6A2A\u4F59\u767D : 1;
16242
+ const x = node.cx - \u7BB1w / 2 + \u5916 * kx;
16243
+ const y = node.cy - \u7BB1h / 2 + \u5916 * ky;
16244
+ const w = Math.max(0, \u7BB1w - \u6A2A\u4F59\u767D * kx);
16245
+ const h = Math.max(0, \u7BB1h - \u7E26\u4F59\u767D * ky);
16246
+ return { x, y, w, h, cx: x + w / 2, cy: y + h / 2, \u53F3: x + w, \u5E95: y + h };
16247
+ }
16248
+ function fitLabel(band, block, pos) {
16249
+ const \u7E26 = block.\u4E0A + block.\u4E0B;
16250
+ const \u6A2A = Math.max(0, block.\u5E45);
16251
+ if (!(\u7E26 > 0)) return { k: 1, x: pos.x, y: pos.y };
16252
+ if (!(band.h > 0) || !(band.w > 0)) return { k: 0, x: band.x + band.w / 2, y: band.y };
16253
+ const k = Math.min(1, band.h / \u7E26, \u6A2A > 0 ? band.w / \u6A2A : 1);
16254
+ const \u534A = \u6A2A * k / 2;
16255
+ return {
16256
+ k,
16257
+ x: Math.max(band.x + \u534A, Math.min(pos.x, band.x + band.w - \u534A)),
16258
+ y: Math.max(band.y + block.\u4E0A * k, Math.min(pos.y, band.y + band.h - block.\u4E0B * k))
16259
+ };
16260
+ }
16261
+ function fitArt(region, extent, art) {
16262
+ const \u7E26 = extent.\u4E0A + extent.\u4E0B;
16263
+ const \u6A2A = extent.\u5DE6 + extent.\u53F3;
16264
+ if (!Number.isFinite(\u7E26) || !Number.isFinite(\u6A2A) || \u7E26 <= 0 || \u6A2A <= 0) return art;
16265
+ if (!Number.isFinite(region.availH) || !Number.isFinite(region.availW) || region.availH <= 0 || region.availW <= 0) {
16266
+ return art;
16267
+ }
16268
+ const s = Math.min(1, region.availH / \u7E26, region.availW / \u6A2A);
16269
+ if (!Number.isFinite(s) || s <= 0) return art;
16270
+ const \u7D75cx = region.cx + (extent.\u53F3 - extent.\u5DE6) / 2;
16271
+ const \u7D75cy = region.cy + (extent.\u4E0B - extent.\u4E0A) / 2;
16272
+ const dx = region.cx - s * \u7D75cx;
16273
+ const dy = region.cy - s * \u7D75cy;
16274
+ if (s >= 1 && dx === 0 && dy === 0) return art;
16275
+ return /* @__PURE__ */ jsx("g", { transform: `translate(${dx} ${dy}) scale(${s})`, children: art });
16276
+ }
15991
16277
 
15992
16278
  // src/layout/geometry.ts
15993
16279
  function pointRectEdgeDistance(px, py, rect) {
@@ -16154,6 +16440,7 @@ function emptyCounts() {
16154
16440
  "validate-performance-budget": 0,
16155
16441
  "node-inside-viewbox": 0,
16156
16442
  "node-inside-lane": 0,
16443
+ "shape-label-dropped": 0,
16157
16444
  "edge-inside-viewbox": 0,
16158
16445
  "lane-label-inside-viewbox": 0,
16159
16446
  "lane-label-overlap": 0,
@@ -16844,6 +17131,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
16844
17131
  for (const n of laid.nodes) {
16845
17132
  if (n.id.endsWith("-spacer")) continue;
16846
17133
  if (!rendersTitleText(n.kind)) continue;
17134
+ if (fitsOwnTitleWidth(n.kind)) continue;
16847
17135
  if (!isRenderedNode(n)) continue;
16848
17136
  const titleTrimmed = n.title?.trim() ?? "";
16849
17137
  if (!titleTrimmed) continue;
@@ -17100,6 +17388,15 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
17100
17388
  );
17101
17389
  }
17102
17390
  }
17391
+ for (const n of laid.nodes) {
17392
+ const \u843D\u3068\u3057\u305F = labelPlan(n).\u843D\u3068\u3057\u305F.filter((line) => droppedLineIsHidden(n.kind, line));
17393
+ if (\u843D\u3068\u3057\u305F.length === 0) continue;
17394
+ push(
17395
+ "shape-label-dropped",
17396
+ `node "${n.id}" (${n.kind}, ${n.w.toFixed(0)}x${n.h.toFixed(0)}) \u306F\u66F8\u3044\u305F ${\u843D\u3068\u3057\u305F.join(" / ")} \u304C\u63CF\u304B\u308C\u306A\u3044\u3002 \u7BB1\u3092\u9AD8\u304F\u3059\u308B\u304B\u3001 \u305D\u306E\u884C\u3092\u6D88\u3059`,
17397
+ "warn"
17398
+ );
17399
+ }
17103
17400
  for (const e of laid.edges) {
17104
17401
  const segs = flattenPathSegments(extractPathSegments(e.d));
17105
17402
  if (segs.length === 0) continue;
@@ -18344,6 +18641,7 @@ function validateMetaAxes(totalCounts, diagrams = [], durations = [], reports =
18344
18641
  "validate-performance-budget",
18345
18642
  "node-inside-viewbox",
18346
18643
  "node-inside-lane",
18644
+ "shape-label-dropped",
18347
18645
  "edge-inside-viewbox",
18348
18646
  "lane-label-inside-viewbox",
18349
18647
  "lane-label-overlap",
@@ -18412,6 +18710,7 @@ function validateMetaAxes(totalCounts, diagrams = [], durations = [], reports =
18412
18710
  "validate-performance-budget",
18413
18711
  "node-inside-viewbox",
18414
18712
  "node-inside-lane",
18713
+ "shape-label-dropped",
18415
18714
  "edge-inside-viewbox",
18416
18715
  "lane-label-inside-viewbox",
18417
18716
  "lane-label-overlap",
@@ -18438,7 +18737,7 @@ function validateMetaAxes(totalCounts, diagrams = [], durations = [], reports =
18438
18737
  });
18439
18738
  }
18440
18739
  }
18441
- const EXPECTED_AXIS_COUNT = 66;
18740
+ const EXPECTED_AXIS_COUNT = 67;
18442
18741
  if (allAxes.length !== EXPECTED_AXIS_COUNT) {
18443
18742
  out.push({
18444
18743
  axis: "axis-documentation-completeness",
@@ -19650,7 +19949,7 @@ function StateDiffCard({
19650
19949
  ] }) }),
19651
19950
  /* @__PURE__ */ jsx("tbody", { style: { color: "var(--cdl-text, #1a1f2a)" }, children: states.map((s) => {
19652
19951
  const initial = String(s.initial);
19653
- const current = stateValues[s.id] ?? initial;
19952
+ const current = Object.hasOwn(stateValues, s.id) ? stateValues[s.id] : initial;
19654
19953
  const changed = initial !== current;
19655
19954
  return /* @__PURE__ */ jsxs("tr", { children: [
19656
19955
  /* @__PURE__ */ jsx("td", { className: "py-1 text-left text-[12px]", children: s.id }),
@@ -19939,14 +20238,14 @@ function fitTextSize(text, maxWidth, targetSize, minSize) {
19939
20238
  var COMPACT_MAX_H = 100;
19940
20239
  var COMPACT_PADDING_X = 16;
19941
20240
  var MIN_SIZE = 11;
19942
- var ASCENT = 0.72;
19943
- var DESCENT = 0.25;
19944
- var MIN_BAND_H = MIN_SIZE * (ASCENT + DESCENT);
20241
+ var ASCENT2 = 0.72;
20242
+ var DESCENT2 = 0.25;
20243
+ var MIN_BAND_H = MIN_SIZE * (ASCENT2 + DESCENT2);
19945
20244
  var EYEBROW_BASELINE = 38;
19946
20245
  var EYEBROW_SIZE = 18;
19947
20246
  var EYEBROW_GAP = 8;
19948
20247
  var BOTTOM_INSET = 4;
19949
- var eyebrowBottom = () => EYEBROW_BASELINE + EYEBROW_SIZE * DESCENT;
20248
+ var eyebrowBottom = () => EYEBROW_BASELINE + EYEBROW_SIZE * DESCENT2;
19950
20249
  var titleBandTop = (hasEyebrow) => eyebrowBottom() + EYEBROW_GAP ;
19951
20250
  var isCompactBox = (h) => h < COMPACT_MAX_H;
19952
20251
  function titlePlacement(node, \u901A\u5E38, opts = {}) {
@@ -19965,10 +20264,10 @@ function titlePlacement(node, \u901A\u5E38, opts = {}) {
19965
20264
  \u901A\u5E38.size,
19966
20265
  MIN_SIZE
19967
20266
  );
19968
- const \u5E2F\u3067 = Math.floor(\u5E2F / (ASCENT + DESCENT));
20267
+ const \u5E2F\u3067 = Math.floor(\u5E2F / (ASCENT2 + DESCENT2));
19969
20268
  const size = Math.max(MIN_SIZE, Math.min(\u5E45\u3067, \u5E2F\u3067));
19970
- const \u5B57\u9AD8 = size * (ASCENT + DESCENT);
19971
- const y = \u5B57\u9AD8 <= \u5E2F ? \u4E0A + \u5E2F / 2 + size * (ASCENT - DESCENT) / 2 : \u4E0A > 0 ? \u4E0A + size * ASCENT : (\u9AD8\u3055 - \u5B57\u9AD8) / 2 + size * ASCENT;
20269
+ const \u5B57\u9AD8 = size * (ASCENT2 + DESCENT2);
20270
+ const y = \u5B57\u9AD8 <= \u5E2F ? \u4E0A + \u5E2F / 2 + size * (ASCENT2 - DESCENT2) / 2 : \u4E0A > 0 ? \u4E0A + size * ASCENT2 : (\u9AD8\u3055 - \u5B57\u9AD8) / 2 + size * ASCENT2;
19972
20271
  return { x: node.w / 2, y, size, anchor: "middle" };
19973
20272
  }
19974
20273
  function ActorNode({ node, active, value }) {
@@ -20926,6 +21225,42 @@ function resolveJourneyData(steps, values) {
20926
21225
  return e.ok ? { ...s, emotion: e.value } : { ...s, emotion: e.value, unresolved: true };
20927
21226
  });
20928
21227
  }
21228
+ function resolveBoundText(raw, values) {
21229
+ if (!raw.includes("{")) return { value: raw, ok: true };
21230
+ const resolved = interpolate(raw, values);
21231
+ return hasUnresolvedRef(resolved) ? { value: resolved, ok: false } : { value: resolved, ok: true };
21232
+ }
21233
+ function resolveTreeData(nodes, values) {
21234
+ const \u8AAD\u3080 = nodes.some((n) => n.title.includes("{") || (n.subtitle?.includes("{") ?? false));
21235
+ if (!\u8AAD\u3080) return nodes;
21236
+ return nodes.map((n) => {
21237
+ const title = resolveBoundText(n.title, values);
21238
+ const subtitle = n.subtitle === void 0 ? void 0 : resolveBoundText(n.subtitle, values);
21239
+ const \u89E3\u6C7A\u5F8C = {
21240
+ ...n,
21241
+ title: title.value,
21242
+ ...subtitle ? { subtitle: subtitle.value } : {}
21243
+ };
21244
+ return title.ok && (subtitle?.ok ?? true) ? \u89E3\u6C7A\u5F8C : { ...\u89E3\u6C7A\u5F8C, unresolved: true };
21245
+ });
21246
+ }
21247
+ function resolveMindData(data, values) {
21248
+ const \u8AAD\u3080 = data.rootTitle.includes("{") || data.branches.some((b) => b.title.includes("{") || (b.subtitle?.includes("{") ?? false));
21249
+ if (!\u8AAD\u3080) return data;
21250
+ const root = resolveBoundText(data.rootTitle, values);
21251
+ const branches = data.branches.map((b) => {
21252
+ const title = resolveBoundText(b.title, values);
21253
+ const subtitle = b.subtitle === void 0 ? void 0 : resolveBoundText(b.subtitle, values);
21254
+ const \u89E3\u6C7A\u5F8C2 = {
21255
+ ...b,
21256
+ title: title.value,
21257
+ ...subtitle ? { subtitle: subtitle.value } : {}
21258
+ };
21259
+ return title.ok && (subtitle?.ok ?? true) ? \u89E3\u6C7A\u5F8C2 : { ...\u89E3\u6C7A\u5F8C2, unresolved: true };
21260
+ });
21261
+ const \u89E3\u6C7A\u5F8C = { ...data, rootTitle: root.value, branches };
21262
+ return root.ok ? \u89E3\u6C7A\u5F8C : { ...\u89E3\u6C7A\u5F8C, unresolved: true };
21263
+ }
20929
21264
  function ChartLineNode({
20930
21265
  node,
20931
21266
  active,
@@ -21332,16 +21667,53 @@ function GanttNode({
21332
21667
  const rowGap = 20;
21333
21668
  const rowCount = tasks.length || 1;
21334
21669
  const rowH = Math.max(28, (canvasH - rowGap * (rowCount + 1)) / rowCount);
21335
- const maxIdx = Math.max(1, Math.ceil(Math.max(...tasks.map((t) => t.endIdx + 1), 1)));
21670
+ const \u4F4D\u7F6E\u306E\u4E0A\u9650 = 1e6;
21671
+ const \u53CE\u3081\u305F = tasks.map((t) => {
21672
+ const \u59CB = Math.min(\u4F4D\u7F6E\u306E\u4E0A\u9650, Math.max(0, Number.isFinite(t.startIdx) ? t.startIdx : 0));
21673
+ const \u7D42 = Math.min(\u4F4D\u7F6E\u306E\u4E0A\u9650, Math.max(\u59CB, Number.isFinite(t.endIdx) ? t.endIdx : \u59CB));
21674
+ return { ...t, startIdx: \u59CB, endIdx: \u7D42 };
21675
+ });
21676
+ const \u5BA3\u8A00 = node.ganttAxisMax;
21677
+ const \u5BA3\u8A00\u3057\u305F\u5C3A = typeof \u5BA3\u8A00 === "number" && Number.isFinite(\u5BA3\u8A00) && \u5BA3\u8A00 > 0 ? Math.min(\u4F4D\u7F6E\u306E\u4E0A\u9650, Math.ceil(\u5BA3\u8A00)) : void 0;
21678
+ const maxIdx = \u5BA3\u8A00\u3057\u305F\u5C3A ?? Math.max(
21679
+ 1,
21680
+ Math.ceil(Math.max(...\u53CE\u3081\u305F.flatMap((t) => [t.startIdx + 1, t.endIdx + 1]), 1))
21681
+ );
21336
21682
  const cellW = canvasW / maxIdx;
21683
+ const \u6700\u5F8C\u306E\u76EE\u76DB\u308A = maxIdx - 1;
21684
+ const \u6574\u3048\u305F = \u5BA3\u8A00\u3057\u305F\u5C3A === void 0 ? \u53CE\u3081\u305F : \u53CE\u3081\u305F.map((t) => {
21685
+ const \u59CB = Math.min(t.startIdx, \u6700\u5F8C\u306E\u76EE\u76DB\u308A);
21686
+ const \u7D42 = Math.min(t.endIdx, \u6700\u5F8C\u306E\u76EE\u76DB\u308A);
21687
+ const \u5BC4\u305B\u305F = \u59CB !== t.startIdx || \u7D42 !== t.endIdx;
21688
+ return \u5BC4\u305B\u305F ? { ...t, startIdx: \u59CB, endIdx: \u7D42, clipped: true } : t;
21689
+ });
21690
+ const \u76EE\u76DB\u308A\u306E\u4E0A\u9650 = 200;
21691
+ const \u76EE\u76DB\u308A\u306E\u9593\u9694 = Math.max(1, Math.ceil(maxIdx / \u76EE\u76DB\u308A\u306E\u4E0A\u9650));
21692
+ const \u76EE\u76DB\u308A\u306E\u672C\u6570 = Math.ceil(maxIdx / \u76EE\u76DB\u308A\u306E\u9593\u9694);
21337
21693
  const xAt = (idx) => PAD_LEFT + idx * cellW;
21338
21694
  const yAt = (row) => PAD_TOP + rowGap + row * (rowH + rowGap);
21339
- const gridLabels = Array.from({ length: maxIdx }, (_, i) => {
21340
- const t = tasks.find((tt) => tt.startIdx === i);
21341
- return t?.startLabel ?? String(i);
21342
- });
21343
- const taskById = new Map(tasks.map((t) => [t.id, t]));
21344
- const rowOf = new Map(tasks.map((t, i) => [t.id, i]));
21695
+ const \u540D\u524D = { \u6574\u6570\u306E\u958B\u59CB: /* @__PURE__ */ new Map(), \u6574\u6570\u306E\u7D42\u4E86: /* @__PURE__ */ new Map(), \u7AEF\u6570\u306E\u958B\u59CB: /* @__PURE__ */ new Map(), \u7AEF\u6570\u306E\u7D42\u4E86: /* @__PURE__ */ new Map() };
21696
+ const \u7F6E\u304F = (\u8868, \u4F4D\u7F6E, label) => {
21697
+ if (label !== "" && Number.isFinite(\u4F4D\u7F6E) && !\u8868.has(\u4F4D\u7F6E)) \u8868.set(\u4F4D\u7F6E, label);
21698
+ };
21699
+ for (const t of \u53CE\u3081\u305F) {
21700
+ const \u6574\u6570\u306E\u958B\u59CB = Number.isInteger(t.startIdx);
21701
+ \u7F6E\u304F(\u6574\u6570\u306E\u958B\u59CB ? \u540D\u524D.\u6574\u6570\u306E\u958B\u59CB : \u540D\u524D.\u7AEF\u6570\u306E\u958B\u59CB, Math.round(t.startIdx), t.startLabel);
21702
+ const \u6574\u6570\u306E\u7D42\u4E86 = Number.isInteger(t.endIdx);
21703
+ \u7F6E\u304F(\u6574\u6570\u306E\u7D42\u4E86 ? \u540D\u524D.\u6574\u6570\u306E\u7D42\u4E86 : \u540D\u524D.\u7AEF\u6570\u306E\u7D42\u4E86, Math.round(t.endIdx), t.endLabel);
21704
+ }
21705
+ const \u540D\u524D\u3092\u5F15\u304F = (i) => \u540D\u524D.\u6574\u6570\u306E\u958B\u59CB.get(i) ?? \u540D\u524D.\u6574\u6570\u306E\u7D42\u4E86.get(i) ?? \u540D\u524D.\u7AEF\u6570\u306E\u958B\u59CB.get(i) ?? \u540D\u524D.\u7AEF\u6570\u306E\u7D42\u4E86.get(i) ?? "";
21706
+ const \u4F4D\u7F6E\u306E\u96C6\u5408 = /* @__PURE__ */ new Set();
21707
+ for (let n = 0; n < \u76EE\u76DB\u308A\u306E\u672C\u6570; n += 1) \u4F4D\u7F6E\u306E\u96C6\u5408.add(n * \u76EE\u76DB\u308A\u306E\u9593\u9694);
21708
+ for (const \u8868 of [\u540D\u524D.\u6574\u6570\u306E\u958B\u59CB, \u540D\u524D.\u6574\u6570\u306E\u7D42\u4E86, \u540D\u524D.\u7AEF\u6570\u306E\u958B\u59CB, \u540D\u524D.\u7AEF\u6570\u306E\u7D42\u4E86]) {
21709
+ for (const i of \u8868.keys()) if (i >= 0 && i < maxIdx) \u4F4D\u7F6E\u306E\u96C6\u5408.add(i);
21710
+ }
21711
+ const gridLabels = [...\u4F4D\u7F6E\u306E\u96C6\u5408].sort((a, b) => a - b).map((i) => ({ \u4F4D\u7F6E: i, label: \u540D\u524D\u3092\u5F15\u304F(i) }));
21712
+ const \u5E2F\u306E\u4F59\u767D = Math.min(6, cellW / 2);
21713
+ const \u5E2F\u306E\u5DE6 = (idx) => xAt(idx) + \u5E2F\u306E\u4F59\u767D / 2;
21714
+ const \u5E2F\u306E\u53F3 = (idx) => xAt(idx) + cellW - \u5E2F\u306E\u4F59\u767D / 2;
21715
+ const taskById = new Map(\u6574\u3048\u305F.map((t) => [t.id, t]));
21716
+ const rowOf = new Map(\u6574\u3048\u305F.map((t, i) => [t.id, i]));
21345
21717
  return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
21346
21718
  /* @__PURE__ */ jsx(
21347
21719
  "rect",
@@ -21357,10 +21729,11 @@ function GanttNode({
21357
21729
  strokeWidth: active ? 3 : 1.25
21358
21730
  }
21359
21731
  ),
21360
- gridLabels.map((label, i) => /* @__PURE__ */ jsxs("g", { children: [
21732
+ gridLabels.map(({ \u4F4D\u7F6E: i, label }) => /* @__PURE__ */ jsxs("g", { children: [
21361
21733
  /* @__PURE__ */ jsx(
21362
21734
  "line",
21363
21735
  {
21736
+ "data-cdl-role": "gantt-grid",
21364
21737
  x1: xAt(i),
21365
21738
  y1: PAD_TOP,
21366
21739
  x2: xAt(i),
@@ -21371,9 +21744,10 @@ function GanttNode({
21371
21744
  opacity: 0.5
21372
21745
  }
21373
21746
  ),
21374
- /* @__PURE__ */ jsx(
21747
+ label === "" ? null : /* @__PURE__ */ jsx(
21375
21748
  "text",
21376
21749
  {
21750
+ "data-cdl-role": "gantt-tick",
21377
21751
  x: xAt(i) + cellW / 2,
21378
21752
  y: PAD_TOP + canvasH + 18,
21379
21753
  fontSize: 11,
@@ -21395,7 +21769,7 @@ function GanttNode({
21395
21769
  opacity: 0.5
21396
21770
  }
21397
21771
  ),
21398
- tasks.map((t, row) => /* @__PURE__ */ jsx(
21772
+ \u6574\u3048\u305F.map((t, row) => /* @__PURE__ */ jsx(
21399
21773
  "text",
21400
21774
  {
21401
21775
  x: PAD_LEFT - 12,
@@ -21408,16 +21782,17 @@ function GanttNode({
21408
21782
  },
21409
21783
  `label-${t.id}`
21410
21784
  )),
21411
- tasks.map((t, row) => {
21412
- const bx = xAt(t.startIdx) + 3;
21785
+ \u6574\u3048\u305F.map((t, row) => {
21786
+ const bx = \u5E2F\u306E\u5DE6(t.startIdx);
21413
21787
  const by = yAt(row);
21414
- const bw = Math.max(cellW - 6, (t.endIdx - t.startIdx + 1) * cellW - 6);
21788
+ const bw = Math.max(0, \u5E2F\u306E\u53F3(t.endIdx) - bx);
21415
21789
  return /* @__PURE__ */ jsxs("g", { children: [
21416
21790
  /* @__PURE__ */ jsx(
21417
21791
  "rect",
21418
21792
  {
21419
21793
  "data-cdl-role": "gantt-bar",
21420
21794
  "data-cdl-unresolved": t.unresolved ? "true" : void 0,
21795
+ "data-cdl-clipped": "clipped" in t && t.clipped ? "true" : void 0,
21421
21796
  x: bx,
21422
21797
  y: by,
21423
21798
  width: bw,
@@ -21440,13 +21815,13 @@ function GanttNode({
21440
21815
  )
21441
21816
  ] }, `bar-${t.id}`);
21442
21817
  }),
21443
- tasks.filter((t) => t.dependsOn && taskById.has(t.dependsOn)).map((t) => {
21818
+ \u6574\u3048\u305F.filter((t) => t.dependsOn && taskById.has(t.dependsOn)).map((t) => {
21444
21819
  const parent = taskById.get(t.dependsOn);
21445
21820
  const parentRow = rowOf.get(parent.id);
21446
21821
  const childRow = rowOf.get(t.id);
21447
- const parentBarRight = xAt(parent.endIdx) + cellW - 3;
21822
+ const parentBarRight = \u5E2F\u306E\u53F3(parent.endIdx);
21448
21823
  const parentMidY = yAt(parentRow) + rowH / 2;
21449
- const childBarLeft = xAt(t.startIdx) + 3;
21824
+ const childBarLeft = \u5E2F\u306E\u5DE6(t.startIdx);
21450
21825
  const childMidY = yAt(childRow) + rowH / 2;
21451
21826
  const arrowHeadSize = 8;
21452
21827
  const arrowHeadTipGap = 10;
@@ -21488,12 +21863,59 @@ function toneColor3(tone) {
21488
21863
  if (!tone) return TONE.accent;
21489
21864
  return TONE[tone];
21490
21865
  }
21866
+
21867
+ // src/kinds/box-lines.ts
21868
+ var \u884C\u9001\u308A\u306E\u6BD4 = 1.15;
21869
+ var \u5B57\u306E\u9AD8\u3055\u306E\u6BD4 = 0.72;
21870
+ var \u4E0A\u4E0B\u306E\u4F59\u767D = 2;
21871
+ var \u5DE6\u53F3\u306E\u4F59\u767D = 8;
21872
+ function \u5E45\u3067\u5207\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E45, \u6E2C\u308B = textWidth) {
21873
+ if (\u4F7F\u3048\u308B\u5E45 <= 0) return "";
21874
+ if (\u6E2C\u308B(text, fontSize) <= \u4F7F\u3048\u308B\u5E45) return text;
21875
+ const \u7701\u7565 = "\u2026";
21876
+ const \u7701\u7565\u306E\u5E45 = \u6E2C\u308B(\u7701\u7565, fontSize);
21877
+ if (\u7701\u7565\u306E\u5E45 > \u4F7F\u3048\u308B\u5E45) return "";
21878
+ let \u51FA = "";
21879
+ let \u5E45 = 0;
21880
+ for (const c of \u66F8\u8A18\u7D20\u306B\u5206\u3051\u308B(text)) {
21881
+ const \u5B57\u306E\u5E452 = \u6E2C\u308B(c, fontSize);
21882
+ if (\u5E45 + \u5B57\u306E\u5E452 + \u7701\u7565\u306E\u5E45 > \u4F7F\u3048\u308B\u5E45) break;
21883
+ \u5E45 += \u5B57\u306E\u5E452;
21884
+ \u51FA += c;
21885
+ }
21886
+ return `${\u51FA}${\u7701\u7565}`;
21887
+ }
21888
+ function \u66F8\u8A18\u7D20\u306B\u5206\u3051\u308B(text) {
21889
+ const \u533A\u5207\u308A = Intl.Segmenter;
21890
+ if (typeof \u533A\u5207\u308A !== "function") return [...text];
21891
+ return [...new \u533A\u5207\u308A(void 0, { granularity: "grapheme" }).segment(text)].map((g) => g.segment);
21892
+ }
21893
+ function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u3055) {
21894
+ const \u5019\u88DC = \u884C.filter((r, i) => i === 0 || r.text.trim() !== "");
21895
+ if (\u5019\u88DC.length === 0) return [];
21896
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = \u7BB1\u306E\u9AD8\u3055 - \u4E0A\u4E0B\u306E\u4F59\u767D * 2;
21897
+ const \u9AD8\u3055 = (rs) => rs.reduce((a, r) => a + r.fontSize * \u884C\u9001\u308A\u306E\u6BD4, 0);
21898
+ const \u6B8B\u3059 = [...\u5019\u88DC];
21899
+ while (\u6B8B\u3059.length > 1 && \u9AD8\u3055(\u6B8B\u3059) > \u4F7F\u3048\u308B\u9AD8\u3055) \u6B8B\u3059.pop();
21900
+ const \u4F7F\u3048\u308B\u5E45 = \u7BB1\u306E\u5E45 - \u5DE6\u53F3\u306E\u4F59\u767D * 2;
21901
+ const \u7DCF\u9AD8 = \u9AD8\u3055(\u6B8B\u3059);
21902
+ let \u7A4D\u307F = -\u7DCF\u9AD8 / 2;
21903
+ return \u6B8B\u3059.map((r) => {
21904
+ const dy = \u7A4D\u307F + (\u884C\u9001\u308A\u306E\u6BD4 + \u5B57\u306E\u9AD8\u3055\u306E\u6BD4) / 2 * r.fontSize;
21905
+ \u7A4D\u307F += r.fontSize * \u884C\u9001\u308A\u306E\u6BD4;
21906
+ return { ...r, text: \u5E45\u3067\u5207\u308B(r.text, r.fontSize, \u4F7F\u3048\u308B\u5E45), dy };
21907
+ });
21908
+ }
21491
21909
  var MIND_TONES = ["accent", "teal", "success", "warning", "info", "error"];
21492
21910
  var MIND_BOX_GAP = 24;
21493
- function MindMapNode({ node, active }) {
21911
+ function MindMapNode({
21912
+ node,
21913
+ active,
21914
+ stateValues = {}
21915
+ }) {
21494
21916
  const x0 = node.cx - node.w / 2;
21495
21917
  const y0 = node.cy - node.h / 2;
21496
- const mindData = node.mindData;
21918
+ const mindData = node.mindData ? resolveMindData(node.mindData, stateValues) : void 0;
21497
21919
  if (!mindData) return /* @__PURE__ */ jsx("g", { transform: `translate(${x0} ${y0})` });
21498
21920
  const PAD = 40;
21499
21921
  const canvasCx = node.w / 2;
@@ -21529,33 +21951,59 @@ function MindMapNode({ node, active }) {
21529
21951
  },
21530
21952
  `edge-${i}`
21531
21953
  )),
21532
- layout2.nodes.map((n) => /* @__PURE__ */ jsxs("g", { children: [
21533
- /* @__PURE__ */ jsx(
21534
- "rect",
21535
- {
21536
- x: n.x - n.w / 2,
21537
- y: n.y - n.h / 2,
21538
- width: n.w,
21539
- height: n.h,
21540
- rx: n.isRoot ? 22 : 10,
21541
- fill: n.isRoot ? toneColor4(n.tone ?? "accent") : "var(--cdl-chip-fill, #f4f6fb)",
21542
- stroke: n.isRoot ? toneColor4(n.tone ?? "accent") : toneColor4(n.tone),
21543
- strokeWidth: n.isRoot ? 2 : 1.75
21544
- }
21545
- ),
21546
- /* @__PURE__ */ jsx(
21547
- "text",
21548
- {
21549
- x: n.x,
21550
- y: n.y + 5,
21551
- fontSize: n.isRoot ? 15 : 13,
21552
- fontWeight: n.isRoot ? 700 : 600,
21553
- textAnchor: "middle",
21554
- fill: n.isRoot ? "var(--cdl-text-on-tone, #ffffff)" : "var(--cdl-chip-text, #1a1f2a)",
21555
- children: n.title
21556
- }
21557
- )
21558
- ] }, `n-${n.id}`))
21954
+ layout2.nodes.map((n) => {
21955
+ const \u884C = \u7BB1\u306B\u7A4D\u3080(
21956
+ [
21957
+ { \u5F79\u5272: "title", text: n.title, fontSize: n.isRoot ? 15 : 13 },
21958
+ { \u5F79\u5272: "subtitle", text: n.subtitle ?? "", fontSize: 9 }
21959
+ ],
21960
+ n.w,
21961
+ n.h
21962
+ );
21963
+ const \u88DC\u8DB3\u3042\u308A = (n.subtitle ?? "").trim() !== "";
21964
+ const \u6587\u5B57\u306E\u8272 = n.isRoot ? "var(--cdl-text-on-tone, #ffffff)" : "var(--cdl-chip-text, #1a1f2a)";
21965
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-unresolved": n.unresolved ? "true" : void 0, children: [
21966
+ /* @__PURE__ */ jsx(
21967
+ "rect",
21968
+ {
21969
+ x: n.x - n.w / 2,
21970
+ y: n.y - n.h / 2,
21971
+ width: n.w,
21972
+ height: n.h,
21973
+ rx: n.isRoot ? 22 : 10,
21974
+ fill: n.isRoot ? toneColor4(n.tone ?? "accent") : "var(--cdl-chip-fill, #f4f6fb)",
21975
+ stroke: n.isRoot ? toneColor4(n.tone ?? "accent") : toneColor4(n.tone),
21976
+ strokeWidth: n.isRoot ? 2 : 1.75
21977
+ }
21978
+ ),
21979
+ \u88DC\u8DB3\u3042\u308A ? \u884C.map((r) => /* @__PURE__ */ jsx(
21980
+ "text",
21981
+ {
21982
+ "data-cdl-role": r.\u5F79\u5272 === "subtitle" ? "mind-node-subtitle" : void 0,
21983
+ x: n.x,
21984
+ y: n.y + r.dy,
21985
+ fontSize: r.fontSize,
21986
+ fontWeight: r.\u5F79\u5272 === "title" ? n.isRoot ? 700 : 600 : 500,
21987
+ textAnchor: "middle",
21988
+ fill: \u6587\u5B57\u306E\u8272,
21989
+ opacity: r.\u5F79\u5272 === "subtitle" ? 0.85 : void 0,
21990
+ children: r.text
21991
+ },
21992
+ r.\u5F79\u5272
21993
+ )) : /* @__PURE__ */ jsx(
21994
+ "text",
21995
+ {
21996
+ x: n.x,
21997
+ y: n.y + 5,
21998
+ fontSize: n.isRoot ? 15 : 13,
21999
+ fontWeight: n.isRoot ? 700 : 600,
22000
+ textAnchor: "middle",
22001
+ fill: \u6587\u5B57\u306E\u8272,
22002
+ children: n.title
22003
+ }
22004
+ )
22005
+ ] }, `n-${n.id}`);
22006
+ })
21559
22007
  ] });
21560
22008
  }
21561
22009
  function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
@@ -21570,7 +22018,8 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
21570
22018
  y: cy,
21571
22019
  w: rootW,
21572
22020
  h: rootH,
21573
- isRoot: true
22021
+ isRoot: true,
22022
+ ...mindData.unresolved ? { unresolved: true } : {}
21574
22023
  });
21575
22024
  const childrenOf = /* @__PURE__ */ new Map();
21576
22025
  for (const br of mindData.branches) {
@@ -21673,7 +22122,18 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
21673
22122
  );
21674
22123
  y = (ys[0] + ys[ys.length - 1]) / 2;
21675
22124
  }
21676
- nodes.push({ id: node.id, title: node.title, x, y, w, h, tone: myTone, isRoot: false });
22125
+ nodes.push({
22126
+ id: node.id,
22127
+ title: node.title,
22128
+ ...node.subtitle !== void 0 ? { subtitle: node.subtitle } : {},
22129
+ x,
22130
+ y,
22131
+ w,
22132
+ h,
22133
+ tone: myTone,
22134
+ isRoot: false,
22135
+ ...node.unresolved ? { unresolved: true } : {}
22136
+ });
21677
22137
  nodePos.set(node.id, { x, y });
21678
22138
  nodeSide.set(node.id, isLeft ? "left" : "right");
21679
22139
  nodeHalfW.set(node.id, w / 2);
@@ -21870,6 +22330,9 @@ function QuadrantNode({
21870
22330
  const PAD_BOTTOM = 56;
21871
22331
  const AXIS_LABEL_FONT = 12;
21872
22332
  const PAD_MIN = 60;
22333
+ const ITEM_FONT = 13;
22334
+ const ITEM_PAD_X = 12;
22335
+ const ITEM_MIN_W = 48;
21873
22336
  const axisLabelPad = (text) => Math.max(PAD_MIN, measureTextWidth(`\u2190 ${text}`, { fontSize: AXIS_LABEL_FONT}) + 12);
21874
22337
  const padBudget = Math.max(0, node.w * 0.5 - PAD_MIN * 2);
21875
22338
  const wantLeft = axisLabelPad(data.xAxis.left) - PAD_MIN;
@@ -21965,6 +22428,12 @@ function QuadrantNode({
21965
22428
  const qxStart = (isLeft ? PAD_LEFT : cx) + 18;
21966
22429
  const qyStart = (isTop ? PAD_TOP : cy) + 44;
21967
22430
  const qHalfW = halfW - 36;
22431
+ const \u67A0\u306E\u4F59\u5730 = qHalfW;
22432
+ if (\u67A0\u306E\u4F59\u5730 <= 0) return null;
22433
+ const \u67A0\u306E\u5E45 = (title) => Math.min(
22434
+ \u67A0\u306E\u4F59\u5730,
22435
+ Math.max(ITEM_MIN_W, measureTextWidth(title, { fontSize: ITEM_FONT}) + ITEM_PAD_X * 2)
22436
+ );
21968
22437
  const qHalfH = halfH - 60;
21969
22438
  const gap = 10;
21970
22439
  const rowH = 34;
@@ -21979,7 +22448,7 @@ function QuadrantNode({
21979
22448
  "data-cdl-unresolved": it.unresolved ? "true" : void 0,
21980
22449
  x: qxStart,
21981
22450
  y: py,
21982
- width: qHalfW,
22451
+ width: \u67A0\u306E\u5E45(it.title),
21983
22452
  height: rowH,
21984
22453
  rx: 6,
21985
22454
  fill: "var(--cdl-node-fill, #ffffff)",
@@ -21987,16 +22456,43 @@ function QuadrantNode({
21987
22456
  strokeWidth: 1.5
21988
22457
  }
21989
22458
  ),
21990
- /* @__PURE__ */ jsx("text", { x: qxStart + 12, y: py + rowH / 2 + 5, fontSize: 13, fontWeight: 600, fill: "var(--cdl-text, #1a1f2a)", children: it.title })
22459
+ /* @__PURE__ */ jsx("text", { x: qxStart + ITEM_PAD_X, y: py + rowH / 2 + 5, fontSize: ITEM_FONT, fontWeight: 600, letterSpacing: 0, fill: "var(--cdl-text, #1a1f2a)", children: it.title })
21991
22460
  ] }, `item-${it.id}`);
21992
22461
  });
21993
22462
  })
21994
22463
  ] });
21995
22464
  }
21996
- function TreeNode({ node, active }) {
22465
+ function \u7BB1\u306E\u6587\u5B57({
22466
+ \u884C,
22467
+ x,
22468
+ \u7BB1\u306E\u9AD8\u3055,
22469
+ fill,
22470
+ \u540D\u524D\u306E\u592A\u3055
22471
+ }) {
22472
+ return \u884C.map((r) => /* @__PURE__ */ jsx(
22473
+ "text",
22474
+ {
22475
+ "data-cdl-role": r.\u5F79\u5272 === "subtitle" ? "tree-node-subtitle" : void 0,
22476
+ x,
22477
+ y: \u7BB1\u306E\u9AD8\u3055 / 2 + r.dy,
22478
+ fontSize: r.fontSize,
22479
+ fontWeight: r.\u5F79\u5272 === "title" ? \u540D\u524D\u306E\u592A\u3055 : 500,
22480
+ textAnchor: "middle",
22481
+ fill,
22482
+ opacity: r.\u5F79\u5272 === "subtitle" ? 0.85 : void 0,
22483
+ children: r.text
22484
+ },
22485
+ r.\u5F79\u5272
22486
+ ));
22487
+ }
22488
+ function TreeNode({
22489
+ node,
22490
+ active,
22491
+ stateValues = {}
22492
+ }) {
21997
22493
  const x0 = node.cx - node.w / 2;
21998
22494
  const y0 = node.cy - node.h / 2;
21999
- const treeNodes = node.treeData ?? [];
22495
+ const treeNodes = resolveTreeData(node.treeData ?? [], stateValues);
22000
22496
  const gradientId = `tree-root-grad-${node.id}`;
22001
22497
  const PAD_TOP = 40;
22002
22498
  const PAD_RIGHT = 24;
@@ -22051,60 +22547,89 @@ function TreeNode({ node, active }) {
22051
22547
  layout2.nodes.map((n) => {
22052
22548
  const accent = depthColors[Math.min(n.depth, depthColors.length - 1)] ?? depthColors[0];
22053
22549
  const isRoot = n.depth === 0;
22054
- return /* @__PURE__ */ jsx("g", { transform: `translate(${PAD_LEFT + n.x - n.w / 2} ${PAD_TOP + n.y - n.h / 2})`, children: isRoot ? /* @__PURE__ */ jsxs(Fragment, { children: [
22055
- /* @__PURE__ */ jsx(
22056
- "rect",
22057
- {
22058
- "data-cdl-role": "tree-node",
22059
- x: 0,
22060
- y: 0,
22061
- width: n.w,
22062
- height: n.h,
22063
- rx: 12,
22064
- fill: `url(#${gradientId})`
22065
- }
22066
- ),
22067
- /* @__PURE__ */ jsx(
22068
- "text",
22069
- {
22070
- x: n.w / 2,
22071
- y: n.h / 2 + 5,
22072
- fontSize: 13,
22073
- fontWeight: 700,
22074
- textAnchor: "middle",
22075
- fill: "var(--cdl-text-on-tone, #ffffff)",
22076
- children: n.title
22077
- }
22078
- )
22079
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
22080
- /* @__PURE__ */ jsx(
22081
- "rect",
22082
- {
22083
- "data-cdl-role": "tree-node",
22084
- x: 0,
22085
- y: 0,
22086
- width: n.w,
22087
- height: n.h,
22088
- rx: 9,
22089
- fill: "var(--cdl-chip-fill, #f4f6fb)",
22090
- stroke: accent,
22091
- strokeWidth: 1.5
22092
- }
22093
- ),
22094
- /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: 4, height: n.h, rx: 2, fill: accent }),
22095
- /* @__PURE__ */ jsx(
22096
- "text",
22097
- {
22098
- x: n.w / 2 + 2,
22099
- y: n.h / 2 + 4,
22100
- fontSize: 12,
22101
- fontWeight: 600,
22102
- textAnchor: "middle",
22103
- fill: "var(--cdl-chip-text, #1a1f2a)",
22104
- children: n.title
22105
- }
22106
- )
22107
- ] }) }, `n-${n.id}`);
22550
+ const \u884C = \u7BB1\u306B\u7A4D\u3080(
22551
+ [
22552
+ { \u5F79\u5272: "title", text: n.title, fontSize: isRoot ? 13 : 12 },
22553
+ { \u5F79\u5272: "subtitle", text: n.subtitle ?? "", fontSize: 9 }
22554
+ ],
22555
+ n.w,
22556
+ n.h
22557
+ );
22558
+ const \u88DC\u8DB3\u3042\u308A = (n.subtitle ?? "").trim() !== "";
22559
+ return /* @__PURE__ */ jsx(
22560
+ "g",
22561
+ {
22562
+ "data-cdl-unresolved": n.unresolved ? "true" : void 0,
22563
+ transform: `translate(${PAD_LEFT + n.x - n.w / 2} ${PAD_TOP + n.y - n.h / 2})`,
22564
+ children: isRoot ? /* @__PURE__ */ jsxs(Fragment, { children: [
22565
+ /* @__PURE__ */ jsx(
22566
+ "rect",
22567
+ {
22568
+ "data-cdl-role": "tree-node",
22569
+ x: 0,
22570
+ y: 0,
22571
+ width: n.w,
22572
+ height: n.h,
22573
+ rx: 12,
22574
+ fill: `url(#${gradientId})`
22575
+ }
22576
+ ),
22577
+ \u88DC\u8DB3\u3042\u308A ? \u7BB1\u306E\u6587\u5B57({
22578
+ \u884C,
22579
+ x: n.w / 2,
22580
+ \u7BB1\u306E\u9AD8\u3055: n.h,
22581
+ fill: "var(--cdl-text-on-tone, #ffffff)",
22582
+ \u540D\u524D\u306E\u592A\u3055: 700
22583
+ }) : /* @__PURE__ */ jsx(
22584
+ "text",
22585
+ {
22586
+ x: n.w / 2,
22587
+ y: n.h / 2 + 5,
22588
+ fontSize: 13,
22589
+ fontWeight: 700,
22590
+ textAnchor: "middle",
22591
+ fill: "var(--cdl-text-on-tone, #ffffff)",
22592
+ children: n.title
22593
+ }
22594
+ )
22595
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
22596
+ /* @__PURE__ */ jsx(
22597
+ "rect",
22598
+ {
22599
+ "data-cdl-role": "tree-node",
22600
+ x: 0,
22601
+ y: 0,
22602
+ width: n.w,
22603
+ height: n.h,
22604
+ rx: 9,
22605
+ fill: "var(--cdl-chip-fill, #f4f6fb)",
22606
+ stroke: accent,
22607
+ strokeWidth: 1.5
22608
+ }
22609
+ ),
22610
+ /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: 4, height: n.h, rx: 2, fill: accent }),
22611
+ \u88DC\u8DB3\u3042\u308A ? \u7BB1\u306E\u6587\u5B57({
22612
+ \u884C,
22613
+ x: n.w / 2 + 2,
22614
+ \u7BB1\u306E\u9AD8\u3055: n.h,
22615
+ fill: "var(--cdl-chip-text, #1a1f2a)",
22616
+ \u540D\u524D\u306E\u592A\u3055: 600
22617
+ }) : /* @__PURE__ */ jsx(
22618
+ "text",
22619
+ {
22620
+ x: n.w / 2 + 2,
22621
+ y: n.h / 2 + 4,
22622
+ fontSize: 12,
22623
+ fontWeight: 600,
22624
+ textAnchor: "middle",
22625
+ fill: "var(--cdl-chip-text, #1a1f2a)",
22626
+ children: n.title
22627
+ }
22628
+ )
22629
+ ] })
22630
+ },
22631
+ `n-${n.id}`
22632
+ );
22108
22633
  })
22109
22634
  ] });
22110
22635
  }
@@ -22167,7 +22692,17 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
22167
22692
  }
22168
22693
  const y = depth * depthGap + depthGap / 2;
22169
22694
  posOf.set(n.id, { x, y });
22170
- nodes.push({ id: n.id, title: n.title, x, y, w: nodeW, h: nodeH, depth });
22695
+ nodes.push({
22696
+ id: n.id,
22697
+ title: n.title,
22698
+ ...n.subtitle !== void 0 ? { subtitle: n.subtitle } : {},
22699
+ x,
22700
+ y,
22701
+ w: nodeW,
22702
+ h: nodeH,
22703
+ depth,
22704
+ ...n.unresolved ? { unresolved: true } : {}
22705
+ });
22171
22706
  return x;
22172
22707
  };
22173
22708
  for (const r of roots) if (!placed.has(r.id)) place(r, 0);
@@ -22442,122 +22977,6 @@ function UserJourneyNode({
22442
22977
  ))
22443
22978
  ] });
22444
22979
  }
22445
- var TITLE_MAX = 18;
22446
- var TITLE_MIN = 9;
22447
- var TITLE_RATIO = 0.17;
22448
- var SUB_RATIO = 0.72;
22449
- var LINE_GAP = 3;
22450
- var BOTTOM_PAD = 4;
22451
- var ASCENT2 = 0.72;
22452
- var DESCENT2 = 0.25;
22453
- var ART_GAP = 4;
22454
- function labelPlan(node) {
22455
- const \u9AD8\u3055 = Math.max(0, node.h);
22456
- const \u5E95 = node.cy + \u9AD8\u3055 / 2;
22457
- const \u5929 = node.cy - \u9AD8\u3055 / 2;
22458
- const \u7A4D\u3080 = (\u540D\u524D\u59272, \u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2, \u4E0B\u4F59\u767D2) => {
22459
- const \u5C0F\u3055\u3044\u5B572 = Math.max(1, Math.round(\u540D\u524D\u59272 * SUB_RATIO));
22460
- let y = \u5E95 - \u4E0B\u4F59\u767D2;
22461
- const \u8AAC\u660E = \u8AAC\u660E\u3042\u308A2 ? { y, size: \u5C0F\u3055\u3044\u5B572 } : null;
22462
- if (\u8AAC\u660E !== null) y -= \u5C0F\u3055\u3044\u5B572 + LINE_GAP;
22463
- const \u540D\u524D = { y, size: \u540D\u524D\u59272 };
22464
- y -= \u540D\u524D\u59272 + LINE_GAP;
22465
- const \u80A9\u66F8 = \u80A9\u66F8\u3042\u308A2 ? { y, size: \u5C0F\u3055\u3044\u5B572 } : null;
22466
- const \u4E0A\u306E\u884C = \u80A9\u66F8 ?? \u540D\u524D;
22467
- return { \u540D\u524D, \u8AAC\u660E, \u80A9\u66F8, \u4E0A\u7AEF: \u4E0A\u306E\u884C.y - \u4E0A\u306E\u884C.size * ASCENT2 };
22468
- };
22469
- const \u5165\u308B = (\u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2) => \u7A4D\u3080(1, \u8AAC\u660E\u3042\u308A2, \u80A9\u66F8\u3042\u308A2, 1 * DESCENT2).\u4E0A\u7AEF >= \u5929;
22470
- let \u8AAC\u660E\u3042\u308A = Boolean(node.subtitle);
22471
- let \u80A9\u66F8\u3042\u308A = Boolean(node.eyebrow);
22472
- if (!\u5165\u308B(\u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A)) \u80A9\u66F8\u3042\u308A = false;
22473
- if (!\u5165\u308B(\u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A)) \u8AAC\u660E\u3042\u308A = false;
22474
- const \u4E0A\u9650 = Math.min(TITLE_MAX, Math.max(1, Math.round(\u9AD8\u3055 * TITLE_RATIO)));
22475
- let \u540D\u524D\u5927 = 0;
22476
- for (let size = \u4E0A\u9650; size >= 1; size--) {
22477
- const \u5C0F\u3055\u3044\u5B572 = Math.max(1, Math.round(size * SUB_RATIO));
22478
- const \u4E0B\u306E\u884C\u5927 = \u8AAC\u660E\u3042\u308A ? \u5C0F\u3055\u3044\u5B572 : size;
22479
- if (\u7A4D\u3080(size, \u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A, \u4E0B\u306E\u884C\u5927 * DESCENT2).\u4E0A\u7AEF >= \u5929) {
22480
- \u540D\u524D\u5927 = size;
22481
- break;
22482
- }
22483
- }
22484
- if (\u540D\u524D\u5927 === 0) \u540D\u524D\u5927 = \u9AD8\u3055 / (ASCENT2 + DESCENT2);
22485
- const \u5C0F\u3055\u3044\u5B57 = Math.max(1, Math.round(\u540D\u524D\u5927 * SUB_RATIO));
22486
- const \u5F35\u308A\u51FA\u3057 = (\u8AAC\u660E\u3042\u308A ? \u5C0F\u3055\u3044\u5B57 : \u540D\u524D\u5927) * DESCENT2;
22487
- const \u4F59\u308A = Math.max(0, \u7A4D\u3080(\u540D\u524D\u5927, \u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A, \u5F35\u308A\u51FA\u3057).\u4E0A\u7AEF - \u5929);
22488
- const \u4E0B\u4F59\u767D = Math.min(Math.max(BOTTOM_PAD, \u5F35\u308A\u51FA\u3057), \u5F35\u308A\u51FA\u3057 + \u4F59\u308A);
22489
- const \u7D44 = \u7A4D\u3080(\u540D\u524D\u5927, \u8AAC\u660E\u3042\u308A, \u80A9\u66F8\u3042\u308A, \u4E0B\u4F59\u767D);
22490
- const \u4E00\u756A\u5C0F\u3055\u3044\u884C = Math.min(
22491
- ...[\u7D44.\u540D\u524D, \u7D44.\u8AAC\u660E, \u7D44.\u80A9\u66F8].filter((l) => l !== null).map((l) => l.size)
22492
- );
22493
- return {
22494
- \u540D\u524D: \u7D44.\u540D\u524D,
22495
- \u8AAC\u660E: \u7D44.\u8AAC\u660E,
22496
- \u80A9\u66F8: \u7D44.\u80A9\u66F8,
22497
- top: \u7D44.\u4E0A\u7AEF,
22498
- \u8AAD\u3081\u308B: \u4E00\u756A\u5C0F\u3055\u3044\u884C >= TITLE_MIN
22499
- };
22500
- }
22501
- function shapeRegion(node) {
22502
- const label = labelPlan(node);
22503
- const \u5929 = node.cy - node.h / 2;
22504
- const availH = Math.max(0, label.top - ART_GAP - \u5929);
22505
- return {
22506
- cx: node.cx,
22507
- cy: \u5929 + availH / 2,
22508
- availW: node.w,
22509
- availH,
22510
- labelY: label.\u540D\u524D.y,
22511
- label
22512
- };
22513
- }
22514
- var SHADOW_GAP = 8;
22515
- var FRAME_HALF = 1.5;
22516
- function bodyBand(node, opt) {
22517
- const \u5F71 = Math.max(0, opt.\u5F71ry);
22518
- const \u5916 = Math.max(0, opt.\u5916 ?? FRAME_HALF);
22519
- const \u4E0B\u4F59\u767D = Math.max(SHADOW_GAP + \u5F71, \u5916);
22520
- const \u7BB1w = Math.max(0, node.w);
22521
- const \u7BB1h = Math.max(0, node.h);
22522
- const \u7E26\u4F59\u767D = \u5916 + \u4E0B\u4F59\u767D;
22523
- const ky = \u7E26\u4F59\u767D > \u7BB1h && \u7E26\u4F59\u767D > 0 ? \u7BB1h / \u7E26\u4F59\u767D : 1;
22524
- const \u6A2A\u4F59\u767D = \u5916 * 2;
22525
- const kx = \u6A2A\u4F59\u767D > \u7BB1w && \u6A2A\u4F59\u767D > 0 ? \u7BB1w / \u6A2A\u4F59\u767D : 1;
22526
- const x = node.cx - \u7BB1w / 2 + \u5916 * kx;
22527
- const y = node.cy - \u7BB1h / 2 + \u5916 * ky;
22528
- const w = Math.max(0, \u7BB1w - \u6A2A\u4F59\u767D * kx);
22529
- const h = Math.max(0, \u7BB1h - \u7E26\u4F59\u767D * ky);
22530
- return { x, y, w, h, cx: x + w / 2, cy: y + h / 2, \u53F3: x + w, \u5E95: y + h };
22531
- }
22532
- function fitLabel(band, block, pos) {
22533
- const \u7E26 = block.\u4E0A + block.\u4E0B;
22534
- const \u6A2A = Math.max(0, block.\u5E45);
22535
- if (!(\u7E26 > 0)) return { k: 1, x: pos.x, y: pos.y };
22536
- if (!(band.h > 0) || !(band.w > 0)) return { k: 0, x: band.x + band.w / 2, y: band.y };
22537
- const k = Math.min(1, band.h / \u7E26, \u6A2A > 0 ? band.w / \u6A2A : 1);
22538
- const \u534A = \u6A2A * k / 2;
22539
- return {
22540
- k,
22541
- x: Math.max(band.x + \u534A, Math.min(pos.x, band.x + band.w - \u534A)),
22542
- y: Math.max(band.y + block.\u4E0A * k, Math.min(pos.y, band.y + band.h - block.\u4E0B * k))
22543
- };
22544
- }
22545
- function fitArt(region, extent, art) {
22546
- const \u7E26 = extent.\u4E0A + extent.\u4E0B;
22547
- const \u6A2A = extent.\u5DE6 + extent.\u53F3;
22548
- if (!Number.isFinite(\u7E26) || !Number.isFinite(\u6A2A) || \u7E26 <= 0 || \u6A2A <= 0) return art;
22549
- if (!Number.isFinite(region.availH) || !Number.isFinite(region.availW) || region.availH <= 0 || region.availW <= 0) {
22550
- return art;
22551
- }
22552
- const s = Math.min(1, region.availH / \u7E26, region.availW / \u6A2A);
22553
- if (!Number.isFinite(s) || s <= 0) return art;
22554
- const \u7D75cx = region.cx + (extent.\u53F3 - extent.\u5DE6) / 2;
22555
- const \u7D75cy = region.cy + (extent.\u4E0B - extent.\u4E0A) / 2;
22556
- const dx = region.cx - s * \u7D75cx;
22557
- const dy = region.cy - s * \u7D75cy;
22558
- if (s >= 1 && dx === 0 && dy === 0) return art;
22559
- return /* @__PURE__ */ jsx("g", { transform: `translate(${dx} ${dy}) scale(${s})`, children: art });
22560
- }
22561
22980
  var BASEMENT_FILL = "#dde8f0";
22562
22981
  var commonFrame = (active) => ({
22563
22982
  fill: BASEMENT_FILL,
@@ -22572,8 +22991,8 @@ var EYEBROW_TRACKING = 2;
22572
22991
  var SUB_SIZE = 11;
22573
22992
  var SUB_GAP = 4;
22574
22993
  function labelBlock(node, pos, size, band) {
22575
- const \u4E0A = node.eyebrow ? size + EYEBROW_GAP2 + EYEBROW_SIZE2 * ASCENT2 : size * ASCENT2;
22576
- const \u4E0B = node.subtitle ? size + SUB_GAP + SUB_SIZE * DESCENT2 : size * DESCENT2;
22994
+ const \u4E0A = node.eyebrow ? size + EYEBROW_GAP2 + EYEBROW_SIZE2 * ASCENT : size * ASCENT;
22995
+ const \u4E0B = node.subtitle ? size + SUB_GAP + SUB_SIZE * DESCENT : size * DESCENT;
22577
22996
  const \u5E45 = Math.max(
22578
22997
  textWidth(node.title ?? "", size),
22579
22998
  node.eyebrow ? textWidth(node.eyebrow, EYEBROW_SIZE2, EYEBROW_TRACKING) : 0,
@@ -24763,6 +25182,15 @@ function ShapeSmartContractNode({ node, active }) {
24763
25182
  bottomLabel2(node, r.cx, r.label)
24764
25183
  ] });
24765
25184
  }
25185
+ var \u5B57\u306E\u5E45 = (text, size) => Math.max(displayWidth(text) * size * MONO_ADVANCE_RATIO, textWidth(text, size));
25186
+ var BLOCK_DEFAULT_FIELDS = [
25187
+ { label: "hash", value: "0xaf31c9d2..." },
25188
+ { label: "prev", value: "0x7b3f92c1..." },
25189
+ { label: "merkle", value: "0xc1892f4a..." },
25190
+ { label: "nonce", value: "82,914" },
25191
+ { label: "tx", value: "142 tx" }
25192
+ ];
25193
+ var BLOCK_DEFAULT_TITLE = "Block #421,873";
24766
25194
  function ShapeBlockchainBlockNode({ node, active }) {
24767
25195
  const frame = commonFrame4(active);
24768
25196
  const r = shapeRegion(node);
@@ -24772,21 +25200,22 @@ function ShapeBlockchainBlockNode({ node, active }) {
24772
25200
  const cy = r.cy;
24773
25201
  const x = cx - bw / 2;
24774
25202
  const y = cy - bh / 2;
25203
+ const \u6E21\u3055\u308C\u305F = (v) => (v ?? "").trim();
25204
+ const \u898B\u51FA\u3057 = \u6E21\u3055\u308C\u305F(node.title) || BLOCK_DEFAULT_TITLE;
25205
+ const fields = BLOCK_DEFAULT_FIELDS.map((f) => ({
25206
+ label: f.label,
25207
+ value: f.label === "hash" ? \u6E21\u3055\u308C\u305F(node.subtitle) || f.value : f.value
25208
+ }));
25209
+ const \u898B\u51FA\u3057\u306E\u5E45 = bw - 14 - 30;
24775
25210
  const art = /* @__PURE__ */ jsxs("g", { children: [
24776
25211
  /* @__PURE__ */ jsx("rect", { x: x + 6, y: y + 6, width: bw, height: bh, rx: 8, fill: frame.stroke, opacity: 0.2, stroke: "none" }),
24777
25212
  /* @__PURE__ */ jsx("rect", { "data-cdl-role": "node-body", x, y, width: bw, height: bh, rx: 8, ...frame }),
24778
25213
  /* @__PURE__ */ jsx("path", { d: `M ${x} ${y + 32} L ${x} ${y + 8} Q ${x} ${y}, ${x + 8} ${y} L ${x + bw - 8} ${y} Q ${x + bw} ${y}, ${x + bw} ${y + 8} L ${x + bw} ${y + 32} Z`, fill: "var(--cdl-tone-accent, #2d6a8f)", fillOpacity: 0.9, stroke: "none" }),
24779
- /* @__PURE__ */ jsx("text", { x: x + 14, y: y + 22, fontSize: 13, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "#ffffff", children: "Block #421,873" }),
25214
+ /* @__PURE__ */ jsx("text", { "data-cdl-role": "blockchain-block-title", x: x + 14, y: y + 22, fontSize: 13, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "#ffffff", children: \u5E45\u3067\u5207\u308B(\u898B\u51FA\u3057, 13, \u898B\u51FA\u3057\u306E\u5E45, \u5B57\u306E\u5E45) }),
24780
25215
  /* @__PURE__ */ jsx("circle", { cx: x + bw - 16, cy: y + 16, r: 5.5, fill: "#7cd88f", stroke: "#ffffff", strokeWidth: 1.5 }),
24781
- [
24782
- { label: "hash", value: "0xaf31c9d2..." },
24783
- { label: "prev", value: "0x7b3f92c1..." },
24784
- { label: "merkle", value: "0xc1892f4a..." },
24785
- { label: "nonce", value: "82,914" },
24786
- { label: "tx", value: "142 tx" }
24787
- ].map((f, i) => /* @__PURE__ */ jsxs("g", { children: [
25216
+ fields.map((f, i) => /* @__PURE__ */ jsxs("g", { children: [
24788
25217
  /* @__PURE__ */ jsx("text", { x: x + 14, y: y + 54 + i * 22, fontSize: 10.5, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "var(--cdl-text-dim, #5a6270)", children: f.label }),
24789
- /* @__PURE__ */ jsx("text", { x: x + bw - 14, y: y + 54 + i * 22, fontSize: 11, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontWeight: 600, textAnchor: "end", fill: "var(--cdl-text, #1a1f2a)", children: f.value }),
25218
+ /* @__PURE__ */ jsx("text", { "data-cdl-role": `blockchain-block-${f.label}`, x: x + bw - 14, y: y + 54 + i * 22, fontSize: 11, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontWeight: 600, textAnchor: "end", fill: "var(--cdl-text, #1a1f2a)", children: \u5E45\u3067\u5207\u308B(f.value, 11, bw - 28 - \u5B57\u306E\u5E45(f.label, 10.5) - 8, \u5B57\u306E\u5E45) }),
24790
25219
  /* @__PURE__ */ jsx("line", { x1: x + 14, y1: y + 60 + i * 22, x2: x + bw - 14, y2: y + 60 + i * 22, stroke: "var(--cdl-divider, #d4d4d8)", strokeWidth: 0.5, opacity: 0.5 })
24791
25220
  ] }, i)),
24792
25221
  /* @__PURE__ */ jsxs("g", { transform: `translate(${cx - 32}, ${y + bh - 26})`, children: [
@@ -26316,9 +26745,10 @@ function CdlNodeView({
26316
26745
  return /* @__PURE__ */ jsx(EventNode, { node: resolvedNode, active, progress });
26317
26746
  case "card":
26318
26747
  return /* @__PURE__ */ jsx(CardNode, { node: resolvedNode, active });
26319
- // 図表 7 種は payload の数と語が `{signal}` を取れるので stateValues を渡す
26320
- // (`render/payload-binding.ts` が描画直前に解決する)。 動かさない 2 種
26321
- // (mind-map / tree-hierarchy) は構造だけを持つため渡さない。
26748
+ // 図表 9 種は payload `{signal}` を取れるので stateValues を渡す
26749
+ // (`render/payload-binding.ts` が描画直前に解決する)。 取れる欄は種別で違い、
26750
+ // 数と語を取る 7 種に対し、mind-map / tree-hierarchy は **名前だけ** を取る (#467)
26751
+ // 親子の繋がりと、描かれない欄 (補足) は解決しない。
26322
26752
  case "chart-line":
26323
26753
  return /* @__PURE__ */ jsx(ChartLineNode, { node: resolvedNode, active, stateValues });
26324
26754
  case "chart-pie":
@@ -26328,13 +26758,13 @@ function CdlNodeView({
26328
26758
  case "gantt-timeline":
26329
26759
  return /* @__PURE__ */ jsx(GanttNode, { node: resolvedNode, active, stateValues });
26330
26760
  case "mind-map":
26331
- return /* @__PURE__ */ jsx(MindMapNode, { node: resolvedNode, active });
26761
+ return /* @__PURE__ */ jsx(MindMapNode, { node: resolvedNode, active, stateValues });
26332
26762
  case "funnel-stages":
26333
26763
  return /* @__PURE__ */ jsx(FunnelNode, { node: resolvedNode, active, stateValues });
26334
26764
  case "quadrant-matrix":
26335
26765
  return /* @__PURE__ */ jsx(QuadrantNode, { node: resolvedNode, active, stateValues });
26336
26766
  case "tree-hierarchy":
26337
- return /* @__PURE__ */ jsx(TreeNode, { node: resolvedNode, active });
26767
+ return /* @__PURE__ */ jsx(TreeNode, { node: resolvedNode, active, stateValues });
26338
26768
  case "journey-map":
26339
26769
  return /* @__PURE__ */ jsx(UserJourneyNode, { node: resolvedNode, active, stateValues });
26340
26770
  case "shape-file":
@@ -26481,6 +26911,29 @@ function CdlNodeView({
26481
26911
  }
26482
26912
  );
26483
26913
  }
26914
+
26915
+ // src/layout/lifeline.ts
26916
+ function lifelineStartYs(nodes) {
26917
+ const topmost = /* @__PURE__ */ new Map();
26918
+ for (const n of nodes) {
26919
+ const cur = topmost.get(n.lane);
26920
+ if (cur === void 0 || n.cy < cur.cy) topmost.set(n.lane, n);
26921
+ }
26922
+ const starts = /* @__PURE__ */ new Map();
26923
+ for (const [laneId, n] of topmost) starts.set(laneId, n.cy + n.h / 2);
26924
+ return starts;
26925
+ }
26926
+ function uniformLifelineEndY(lanes, nodes, starts = lifelineStartYs(nodes)) {
26927
+ const lifelineLanes = lanes.filter((l) => l.lifeline);
26928
+ let deepestStart = Number.NEGATIVE_INFINITY;
26929
+ for (const lane of lifelineLanes) {
26930
+ const start = starts.get(lane.id);
26931
+ if (start !== void 0) deepestStart = Math.max(deepestStart, start);
26932
+ }
26933
+ const footerTops = lifelineFooterNodes(lanes, nodes).map((f) => footerShapeDrawTop(f)).filter((top) => top > deepestStart);
26934
+ if (footerTops.length > 0) return Math.min(...footerTops);
26935
+ return lifelineLanes[0] ? lifelineLanes[0].y + lifelineLanes[0].height : 0;
26936
+ }
26484
26937
  function CdlStage({
26485
26938
  laid,
26486
26939
  currentPhase,
@@ -26491,15 +26944,13 @@ function CdlStage({
26491
26944
  svgRef
26492
26945
  }) {
26493
26946
  const activeSet = new Set(currentPhase?.activate ?? []);
26494
- const lifelineLanes = laid.lanes.filter((l) => l.lifeline);
26495
- const { footerTops, footerDropById } = useMemo(() => {
26496
- const footers = lifelineFooterNodes(laid.lanes, laid.nodes);
26947
+ const { lifelineStarts, uniformFooterTop } = useMemo(() => {
26948
+ const starts = lifelineStartYs(laid.nodes);
26497
26949
  return {
26498
- footerTops: footers.map((f) => f.cy - f.h / 2),
26499
- footerDropById: footerShapeDropsOf(footers)
26950
+ lifelineStarts: starts,
26951
+ uniformFooterTop: uniformLifelineEndY(laid.lanes, laid.nodes, starts)
26500
26952
  };
26501
26953
  }, [laid]);
26502
- const uniformFooterTop = footerTops.length > 0 ? Math.min(...footerTops) : lifelineLanes[0] ? lifelineLanes[0].y + lifelineLanes[0].height : 0;
26503
26954
  const diagramScale = laid.diagramScale ?? 1;
26504
26955
  return /* @__PURE__ */ jsxs("div", { className: compact ? "px-3 py-3" : "px-6 py-6", style: compact ? void 0 : { minHeight: 460 }, children: [
26505
26956
  /* @__PURE__ */ jsxs(
@@ -26586,11 +27037,8 @@ function CdlStage({
26586
27037
  }
26587
27038
  ),
26588
27039
  lane.lifeline && (() => {
26589
- const laneNodes = laid.nodes.filter((n) => n.lane === lane.id);
26590
- if (laneNodes.length === 0) return null;
26591
- const sortedByCy = laneNodes.slice().sort((a, b) => a.cy - b.cy);
26592
- const header = sortedByCy[0];
26593
- const y1 = header.cy + header.h / 2;
27040
+ const y1 = lifelineStarts.get(lane.id);
27041
+ if (y1 === void 0) return null;
26594
27042
  const y2 = uniformFooterTop;
26595
27043
  if (y2 <= y1) return null;
26596
27044
  return /* @__PURE__ */ jsx(
@@ -26637,8 +27085,7 @@ function CdlStage({
26637
27085
  currentPhaseId: currentPhase?.id
26638
27086
  }
26639
27087
  );
26640
- const dy = footerDropById.get(node.id);
26641
- return dy === void 0 ? /* @__PURE__ */ jsx("g", { children: view }, node.id) : /* @__PURE__ */ jsx("g", { transform: `translate(0, ${dy})`, children: view }, node.id);
27088
+ return /* @__PURE__ */ jsx("g", { children: view }, node.id);
26642
27089
  }),
26643
27090
  laid.edges.filter((edge) => Boolean(edge.dThrough)).map((edge) => /* @__PURE__ */ jsx(CdlEdgeGlowView, { edge, active: activeSet.has(edge.id) }, `glow-${edge.id}`)),
26644
27091
  laid.edges.map((edge) => /* @__PURE__ */ jsx(
@@ -26861,14 +27308,7 @@ function CdlDiagramView({ diagram: diagram2, laid: laidProp, hideHeader = false,
26861
27308
  );
26862
27309
  const stateValues = useMemo(() => {
26863
27310
  if (!isInteractive) return baseStateValues;
26864
- const merged = { ...baseStateValues };
26865
- for (const key of Object.keys(interactive.stateOverrides)) {
26866
- const v = interactive.stateOverrides[key];
26867
- if (typeof v === "number" || typeof v === "string" || typeof v === "boolean") {
26868
- merged[key] = String(v);
26869
- }
26870
- }
26871
- return merged;
27311
+ return mergeStateValues(baseStateValues, interactive.stateOverrides);
26872
27312
  }, [isInteractive, baseStateValues, interactive.stateOverrides]);
26873
27313
  return /* @__PURE__ */ jsxs(
26874
27314
  "div",
@@ -27110,6 +27550,7 @@ function bboxDiffWorld(predicted, actual) {
27110
27550
  }
27111
27551
 
27112
27552
  // src/presets.ts
27553
+ var \u53C2\u7167\u305D\u306E\u3082\u306E = (v) => /^\{[A-Za-z_][\s\S]*\}$/.test(v);
27113
27554
  var GRID_UNIT = 16;
27114
27555
  function gridAlignedLaneW(canvasW) {
27115
27556
  const padPerSide = Math.ceil(LANE_PAD_MIN / GRID_UNIT) * GRID_UNIT;
@@ -27177,6 +27618,7 @@ function flow(preset) {
27177
27618
  b.lane("flow", { width: w, ...preset.laneLabel ? { label: preset.laneLabel } : {} });
27178
27619
  const tone = preset.defaultTone ?? "accent";
27179
27620
  const style = preset.defaultStyle ?? "dotted-flow";
27621
+ const autoChain = preset.autoChain ?? true;
27180
27622
  let prevId = null;
27181
27623
  let stackIdx = 0;
27182
27624
  const phaseActivate = [];
@@ -27191,7 +27633,7 @@ function flow(preset) {
27191
27633
  ...node.subtitle ? { subtitle: node.subtitle } : {}
27192
27634
  });
27193
27635
  phaseActivate.push(node.id);
27194
- if (prevId !== null) {
27636
+ if (autoChain && prevId !== null) {
27195
27637
  const edgeId = `e-${prevId}-${node.id}`;
27196
27638
  b.edge(prevId, node.id, {
27197
27639
  id: edgeId,
@@ -27204,6 +27646,17 @@ function flow(preset) {
27204
27646
  prevId = node.id;
27205
27647
  return api;
27206
27648
  },
27649
+ edge(from, to, opts) {
27650
+ const edgeId = opts?.id ?? `e-${from}-${to}`;
27651
+ b.edge(from, to, {
27652
+ id: edgeId,
27653
+ label: opts?.label ?? "\u2192",
27654
+ tone: opts?.tone ?? tone,
27655
+ style: opts?.style ?? style
27656
+ });
27657
+ phaseActivate.push(edgeId);
27658
+ return api;
27659
+ },
27207
27660
  build() {
27208
27661
  b.phase(
27209
27662
  "flow",
@@ -27267,7 +27720,7 @@ function sequence(preset) {
27267
27720
  const laneId = actorIds.get(label) ?? slugify(label);
27268
27721
  const footerId = `${laneId}-footer`;
27269
27722
  const actorW = Math.max(140, label.length * 22 + 52);
27270
- b.node(footerId, { lane: laneId, stack: footerStack, kind: "card", title: label, w: actorW, h: 72 });
27723
+ b.node(footerId, { lane: laneId, stack: footerStack, kind: "card", title: label, w: actorW, h: 72, role: "lifeline-footer" });
27271
27724
  phaseActivate.push(footerId);
27272
27725
  });
27273
27726
  b.phase(
@@ -27590,8 +28043,7 @@ function tree(preset) {
27590
28043
  id: n.id,
27591
28044
  title: n.title,
27592
28045
  parent: n.parent,
27593
- subtitle: n.subtitle,
27594
- eyebrow: n.eyebrow
28046
+ subtitle: n.subtitle
27595
28047
  }))
27596
28048
  });
27597
28049
  b.phase(
@@ -27825,9 +28277,11 @@ function gantt(preset) {
27825
28277
  build() {
27826
28278
  const labelSeq = [];
27827
28279
  for (const t of tasks) {
27828
- if (!labelSeq.includes(t.start)) labelSeq.push(t.start);
27829
- if (!labelSeq.includes(t.end)) labelSeq.push(t.end);
28280
+ if (!\u53C2\u7167\u305D\u306E\u3082\u306E(t.start) && !labelSeq.includes(t.start)) labelSeq.push(t.start);
28281
+ if (!\u53C2\u7167\u305D\u306E\u3082\u306E(t.end) && !labelSeq.includes(t.end)) labelSeq.push(t.end);
27830
28282
  }
28283
+ const \u4F4D\u7F6E = (v) => \u53C2\u7167\u305D\u306E\u3082\u306E(v) ? v : labelSeq.indexOf(v);
28284
+ const \u540D\u672D = (v) => \u53C2\u7167\u305D\u306E\u3082\u306E(v) ? "" : v;
27831
28285
  b.lane("gantt", { width: canvasW });
27832
28286
  const nodeId = `${preset.id}-gantt`;
27833
28287
  b.node(nodeId, {
@@ -27838,13 +28292,15 @@ function gantt(preset) {
27838
28292
  eyebrow: "gantt",
27839
28293
  w: canvasW,
27840
28294
  h: canvasH,
28295
+ // 宣言していない図には欄自体を載せない = 自動で決める経路をそのまま通す
28296
+ ...preset.axisMax !== void 0 ? { ganttAxisMax: preset.axisMax } : {},
27841
28297
  ganttData: tasks.map((t) => ({
27842
28298
  id: t.id,
27843
28299
  title: t.title,
27844
- startIdx: labelSeq.indexOf(t.start),
27845
- endIdx: labelSeq.indexOf(t.end),
27846
- startLabel: t.start,
27847
- endLabel: t.end,
28300
+ startIdx: \u4F4D\u7F6E(t.start),
28301
+ endIdx: \u4F4D\u7F6E(t.end),
28302
+ startLabel: \u540D\u672D(t.start),
28303
+ endLabel: \u540D\u672D(t.end),
27848
28304
  owner: t.owner,
27849
28305
  dependsOn: t.dependsOn,
27850
28306
  tone