@cardenelabs/cdl 0.83.0 → 0.103.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 (44) hide show
  1. package/CHANGELOG.md +874 -1
  2. package/dist/index.cjs +879 -186
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +20 -4
  5. package/dist/index.d.ts +20 -4
  6. package/dist/index.js +879 -187
  7. package/dist/index.js.map +1 -1
  8. package/dist/react.cjs +869 -178
  9. package/dist/react.cjs.map +1 -1
  10. package/dist/react.d.cts +1 -1
  11. package/dist/react.d.ts +1 -1
  12. package/dist/react.js +869 -178
  13. package/dist/react.js.map +1 -1
  14. package/dist/{render-DfXCs3Eh.d.cts → render-oEmwYN-q.d.cts} +21 -3
  15. package/dist/{render-DfXCs3Eh.d.ts → render-oEmwYN-q.d.ts} +21 -3
  16. package/package.json +1 -1
  17. package/src/index.ts +5 -0
  18. package/src/kinds/chart-gauge.tsx +20 -3
  19. package/src/kinds/chart-legend-number.tsx +33 -0
  20. package/src/kinds/chart-number.ts +33 -0
  21. package/src/kinds/chart-radial.tsx +24 -7
  22. package/src/kinds/chart-stat.tsx +35 -5
  23. package/src/kinds/chart-waffle.tsx +25 -7
  24. package/src/kinds/dyn-shape.tsx +72 -12
  25. package/src/kinds/funnel.tsx +50 -2
  26. package/src/kinds/mind-map.tsx +206 -64
  27. package/src/kinds/quadrant.tsx +318 -45
  28. package/src/kinds/shape-blockchain.tsx +50 -18
  29. package/src/kinds/shape-commerce.tsx +27 -4
  30. package/src/kinds/shape-region.tsx +42 -1
  31. package/src/kinds/shape-software.tsx +51 -12
  32. package/src/kinds/storage.tsx +16 -8
  33. package/src/kinds/tree.tsx +46 -10
  34. package/src/lang.ts +5 -5
  35. package/src/layout/nodes.ts +3 -1
  36. package/src/layout/spec.ts +154 -25
  37. package/src/layout/text-width.ts +25 -0
  38. package/src/layout/viewbox.ts +32 -0
  39. package/src/presets.ts +21 -7
  40. package/src/render/nodes.tsx +77 -0
  41. package/src/render/payload-binding.ts +108 -25
  42. package/src/render/stage.tsx +24 -2
  43. package/src/types.ts +117 -38
  44. package/src/visual-validate.ts +61 -1
package/dist/react.cjs CHANGED
@@ -363,22 +363,22 @@ function resolveLang(value) {
363
363
  return value === "ja" ? "ja" : "en";
364
364
  }
365
365
  var en = {
366
- /** `shape-terminal` の 2 行目 (命令の出力) */
367
366
  /*
368
- * `shape-terminal` の出力の行。
367
+ * `shape-terminal` の出力の行を **書かない時** の控え (#927)。
369
368
  *
370
369
  * **いちばん長い行が絵の倍率を決める** (#891)。 端末の中身は自分の座標で組んでから箱へ
371
370
  * 収めるので、この行が長いほど全部の字が小さくなる。 120x110 の箱では 20 字の版で
372
- * 7.71 world まで落ちていた。
371
+ * 7.71 world まで落ちていた。 書いた説明を通すようになったので、長い説明を渡した図でも
372
+ * 同じことが起きる。
373
373
  */
374
374
  "terminal.output": "\u2192 12 chunks",
375
- /** `shape-code-block` の札の file 名 */
375
+ /** `shape-code-block` の札の file 名を **書かない時** の控え (#927) */
376
376
  "codeBlock.fileName": "utils.ts",
377
377
  /** `shape-kanban-card` の課題の番号 */
378
378
  "kanbanCard.id": "CAR-1111",
379
379
  /** `shape-kanban-card` の状態の札 */
380
380
  "kanbanCard.status": "IN PROG",
381
- /** `shape-kanban-card` の題の下の説明 */
381
+ /** `shape-kanban-card` の題の下の説明を **書かない時** の控え (#927) */
382
382
  "kanbanCard.task": "shape-driven kind \u5B9F\u88C5",
383
383
  /** `shape-kanban-card` の期日 */
384
384
  "kanbanCard.due": "Jul 10",
@@ -901,6 +901,11 @@ function measureTextWidth(text, opts = {}) {
901
901
  const w = advanceEmSum * fontSize + letterSpacing * charCount;
902
902
  return Math.max(w, fontSize * 1.2);
903
903
  }
904
+ function \u53CE\u3081\u308B\u500D\u7387(text, opts, \u5E45) {
905
+ if (!(\u5E45 > 0) || !(opts.fontSize > 0)) return 1;
906
+ const \u5B9F\u5E45 = measureTextWidth(text, { ...opts, letterSpacing: 0 });
907
+ return \u5B9F\u5E45 > \u5E45 ? \u5E45 / \u5B9F\u5E45 : 1;
908
+ }
904
909
 
905
910
  // src/label-text.ts
906
911
  var EDGE_LABEL_TEXT = {
@@ -935,17 +940,7 @@ var LABEL_PILL_PAD_X = 18;
935
940
  function hasRenderedLabel(e) {
936
941
  return Boolean(e.label?.trim() || e.sub?.trim());
937
942
  }
938
- var KINDS_WITHOUT_TITLE_TEXT = /* @__PURE__ */ new Set([
939
- // 時系列のやり取り (#578)。 図を丸ごと描く種別で、描くのは面々の名前と言づての語。
940
- // 箱の `title` は使わない
941
- "sequence-board",
942
- // 形だけを描く (DynShapeNode)
943
- "dyn-rect",
944
- "dyn-circle",
945
- "dyn-arc",
946
- "dyn-wave",
947
- "dyn-polygon",
948
- // payload を自前 layout して描く (label は payload 側が持つ)
943
+ var KINDS_DRAWING_OWN_PAYLOAD = /* @__PURE__ */ new Set([
949
944
  "chart-pie",
950
945
  "chart-line",
951
946
  "chart-bar",
@@ -960,22 +955,27 @@ var KINDS_WITHOUT_TITLE_TEXT = /* @__PURE__ */ new Set([
960
955
  "funnel-stages",
961
956
  "quadrant-matrix",
962
957
  "tree-hierarchy",
963
- "journey-map",
964
- // 印そのものが意味を持つ (#560)
958
+ "journey-map"
959
+ ]);
960
+ function drawsFigureTitle(kind) {
961
+ return KINDS_DRAWING_OWN_PAYLOAD.has(kind ?? "");
962
+ }
963
+ var KINDS_WITHOUT_TITLE_TEXT = /* @__PURE__ */ new Set([
964
+ "sequence-board",
965
965
  "mark-start",
966
966
  "mark-end"
967
967
  ]);
968
968
  function rendersTitleText(kind) {
969
969
  return !KINDS_WITHOUT_TITLE_TEXT.has(kind ?? "");
970
970
  }
971
- var KINDS_FITTING_OWN_TITLE = /* @__PURE__ */ new Set(["shape-blockchain-block"]);
971
+ var KINDS_FITTING_OWN_TITLE = /* @__PURE__ */ new Set([
972
+ "shape-blockchain-block",
973
+ ...KINDS_DRAWING_OWN_PAYLOAD
974
+ ]);
972
975
  function fitsOwnTitleWidth(kind) {
973
976
  return KINDS_FITTING_OWN_TITLE.has(kind ?? "");
974
977
  }
975
- var KINDS_WITH_ROW_TEXT = /* @__PURE__ */ new Set([
976
- // 専用の表組み (StorageNode)
977
- "storage",
978
- // 汎用描画 (GenericNode)
978
+ var KINDS_DRAWN_BY_GENERIC = [
979
979
  "person",
980
980
  "user-group",
981
981
  "admin",
@@ -997,10 +997,44 @@ var KINDS_WITH_ROW_TEXT = /* @__PURE__ */ new Set([
997
997
  "oracle",
998
998
  "merkle-tree",
999
999
  "decision"
1000
+ ];
1001
+ var KINDS_WITH_ROW_TEXT = /* @__PURE__ */ new Set([
1002
+ // 専用の表組み (StorageNode)
1003
+ "storage",
1004
+ ...KINDS_DRAWN_BY_GENERIC
1000
1005
  ]);
1001
1006
  function rendersRows(kind) {
1002
1007
  return KINDS_WITH_ROW_TEXT.has(kind ?? "");
1003
1008
  }
1009
+ var KINDS_DRAWING_ONLY_SHAPE = [
1010
+ "dyn-rect",
1011
+ "dyn-circle",
1012
+ "dyn-arc",
1013
+ "dyn-wave",
1014
+ "dyn-polygon"
1015
+ ];
1016
+ var KINDS_WITHOUT_EYEBROW_TEXT = /* @__PURE__ */ new Set([
1017
+ ...KINDS_DRAWING_ONLY_SHAPE,
1018
+ ...KINDS_WITHOUT_TITLE_TEXT
1019
+ ]);
1020
+ function rendersEyebrow(kind) {
1021
+ return !KINDS_WITHOUT_EYEBROW_TEXT.has(kind ?? "");
1022
+ }
1023
+ var KINDS_WITHOUT_SUBTITLE_TEXT = /* @__PURE__ */ new Set([
1024
+ ...KINDS_DRAWING_OWN_PAYLOAD,
1025
+ ...KINDS_WITHOUT_TITLE_TEXT
1026
+ ]);
1027
+ function rendersSubtitle(kind) {
1028
+ return !KINDS_WITHOUT_SUBTITLE_TEXT.has(kind ?? "");
1029
+ }
1030
+ var KINDS_WITH_VALUE_TEXT = /* @__PURE__ */ new Set([
1031
+ // 面々の絵 (ActorNode)
1032
+ "actor",
1033
+ ...KINDS_DRAWN_BY_GENERIC
1034
+ ]);
1035
+ function rendersValue(kind) {
1036
+ return KINDS_WITH_VALUE_TEXT.has(kind ?? "");
1037
+ }
1004
1038
  function rowBaselineY(kind, index) {
1005
1039
  if (!rendersRows(kind)) return null;
1006
1040
  return kind === "storage" ? ROW_TOP_STORAGE + index * ROW_PITCH_STORAGE : ROW_TOP_GENERIC + genericTextShift(kind) + index * ROW_PITCH_GENERIC;
@@ -3043,6 +3077,15 @@ function requiredRowsWidth(rows, kind) {
3043
3077
  if (kind === void 0) return Math.ceil(Math.max(storage, generic));
3044
3078
  return Math.ceil(kind === "storage" ? storage : generic);
3045
3079
  }
3080
+ function \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(\u66F8\u3044\u305F, \u63A7\u3048) {
3081
+ const v = (\u66F8\u3044\u305F ?? "").trim();
3082
+ return v === "" ? \u63A7\u3048 : v;
3083
+ }
3084
+ function \u5E45\u306E\u500D\u7387(text, size, letterSpacing, \u5E45) {
3085
+ if (!(\u5E45 > 0) || !(size > 0)) return 1;
3086
+ const \u5B9F\u5E45 = textWidth(text, size, letterSpacing);
3087
+ return \u5B9F\u5E45 > \u5E45 ? \u5E45 / \u5B9F\u5E45 : 1;
3088
+ }
3046
3089
  var TITLE_MAX = 18;
3047
3090
  var TITLE_MIN = 9;
3048
3091
  var TITLE_RATIO = 0.17;
@@ -3069,7 +3112,10 @@ var \u843D\u3068\u3057\u3066\u3082\u63CF\u304F\u7A2E\u5225 = {
3069
3112
  "shape-code-block",
3070
3113
  "shape-message-bubble",
3071
3114
  "shape-gear",
3072
- // hardware 系のうち固有 layout を持つもの
3115
+ // 絵の中の字の口に肩書を通す 2 種別 (#941)。 状態の札 / 見出しの帯の右 に描く
3116
+ "shape-kanban-card",
3117
+ "shape-blockchain-block",
3118
+ // hardware / blockchain 系のうち固有 layout を持つもの
3073
3119
  "shape-iot-sensor",
3074
3120
  "shape-robot-arm"
3075
3121
  ]),
@@ -3086,6 +3132,10 @@ var \u843D\u3068\u3057\u3066\u3082\u63CF\u304F\u7A2E\u5225 = {
3086
3132
  "shape-window",
3087
3133
  "shape-message-bubble",
3088
3134
  "shape-gear",
3135
+ // 絵の中の字の口に説明を通す 3 種別 (#927)。 札の file 名 / 出力の行 / 課題の 1 行 に描く
3136
+ "shape-terminal",
3137
+ "shape-code-block",
3138
+ "shape-kanban-card",
3089
3139
  // hardware / blockchain 系のうち固有 layout を持つもの
3090
3140
  "shape-iot-sensor",
3091
3141
  "shape-robot-arm",
@@ -4320,7 +4370,9 @@ function needsResolve(raw) {
4320
4370
  return typeof raw !== "number" || !Number.isFinite(raw);
4321
4371
  }
4322
4372
  function resolveChartData(data, values) {
4323
- if (!data.some((d) => needsResolve(d.value) || d.previous !== void 0 && needsResolve(d.previous)))
4373
+ if (!data.some(
4374
+ (d) => needsResolve(d.value) || d.previous !== void 0 && needsResolve(d.previous)
4375
+ ))
4324
4376
  return data;
4325
4377
  return data.map((d) => {
4326
4378
  const v = resolveBoundNumber(d.value, values, 0);
@@ -4331,14 +4383,24 @@ function resolveChartData(data, values) {
4331
4383
  });
4332
4384
  }
4333
4385
  function resolveFunnelData(stages, values) {
4334
- if (!stages.some((s) => needsResolve(s.count))) return stages;
4386
+ const \u8AAD\u3080 = stages.some(
4387
+ (s) => needsResolve(s.count) || (s.subtitle?.includes("{") ?? false)
4388
+ );
4389
+ if (!\u8AAD\u3080) return stages;
4335
4390
  return stages.map((s) => {
4336
4391
  const c = resolveBoundNumber(s.count, values, 0);
4337
- return c.ok ? { ...s, count: c.value } : { ...s, count: c.value, unresolved: true };
4392
+ const sub = s.subtitle === void 0 ? void 0 : resolveBoundText(s.subtitle, values);
4393
+ const \u7D20 = {
4394
+ ...s,
4395
+ count: c.value,
4396
+ ...sub ? { subtitle: sub.value } : {}
4397
+ };
4398
+ return c.ok && (sub?.ok ?? true) ? \u7D20 : { ...\u7D20, unresolved: true };
4338
4399
  });
4339
4400
  }
4340
4401
  function resolveGanttData(tasks, values) {
4341
- if (!tasks.some((t) => needsResolve(t.startIdx) || needsResolve(t.endIdx))) return tasks;
4402
+ if (!tasks.some((t) => needsResolve(t.startIdx) || needsResolve(t.endIdx)))
4403
+ return tasks;
4342
4404
  return tasks.map((t) => {
4343
4405
  const start = resolveBoundNumber(t.startIdx, values, 0);
4344
4406
  const end = resolveBoundNumber(t.endIdx, values, start.value);
@@ -4346,16 +4408,48 @@ function resolveGanttData(tasks, values) {
4346
4408
  return start.ok && end.ok ? next : { ...next, unresolved: true };
4347
4409
  });
4348
4410
  }
4411
+ function \u5EA7\u6A19\u306E\u8C61\u9650(x, y) {
4412
+ const \u53F3 = x >= 0.5;
4413
+ const \u4E0A = y >= 0.5;
4414
+ if (\u4E0A) return \u53F3 ? "topRight" : "topLeft";
4415
+ return \u53F3 ? "bottomRight" : "bottomLeft";
4416
+ }
4417
+ var \u57DF\u306B\u53CE\u3081\u308B = (v) => Math.min(1, Math.max(0, v));
4349
4418
  function resolveQuadrantData(data, values) {
4350
4419
  const items = data.items;
4351
- if (items.every((i) => QUADRANT_KEYS.includes(i.quadrant))) {
4352
- return data;
4353
- }
4420
+ const \u8FD1\u9053 = !items.some((i) => i.at !== void 0) && !items.some((i) => i.subtitle?.includes("{") ?? false) && items.every((i) => QUADRANT_KEYS.includes(i.quadrant ?? ""));
4421
+ if (\u8FD1\u9053) return data;
4354
4422
  return {
4355
4423
  ...data,
4356
4424
  items: items.map((i) => {
4357
- const q = resolveBoundEnum(i.quadrant, values, QUADRANT_KEYS, QUADRANT_FALLBACK);
4358
- return q.ok ? { ...i, quadrant: q.value } : { ...i, quadrant: q.value, unresolved: true };
4425
+ if (i.at !== void 0) {
4426
+ const x = resolveBoundNumber(i.at.x, values, 0.5);
4427
+ const y = resolveBoundNumber(i.at.y, values, 0.5);
4428
+ const \u7F6E\u304F = { x: \u57DF\u306B\u53CE\u3081\u308B(x.value), y: \u57DF\u306B\u53CE\u3081\u308B(y.value) };
4429
+ const sub2 = i.subtitle === void 0 ? void 0 : resolveBoundText(i.subtitle, values);
4430
+ const \u7D202 = {
4431
+ id: i.id,
4432
+ title: i.title,
4433
+ at: \u7F6E\u304F,
4434
+ quadrant: \u5EA7\u6A19\u306E\u8C61\u9650(\u7F6E\u304F.x, \u7F6E\u304F.y),
4435
+ ...sub2 ? { subtitle: sub2.value } : {}
4436
+ };
4437
+ return x.ok && y.ok && (sub2?.ok ?? true) ? \u7D202 : { ...\u7D202, unresolved: true };
4438
+ }
4439
+ const q = resolveBoundEnum(
4440
+ i.quadrant ?? "",
4441
+ values,
4442
+ QUADRANT_KEYS,
4443
+ QUADRANT_FALLBACK
4444
+ );
4445
+ const sub = i.subtitle === void 0 ? void 0 : resolveBoundText(i.subtitle, values);
4446
+ const \u7D20 = {
4447
+ id: i.id,
4448
+ title: i.title,
4449
+ quadrant: q.value,
4450
+ ...sub ? { subtitle: sub.value } : {}
4451
+ };
4452
+ return q.ok && (sub?.ok ?? true) ? \u7D20 : { ...\u7D20, unresolved: true };
4359
4453
  })
4360
4454
  };
4361
4455
  }
@@ -4475,13 +4569,10 @@ var PAD_TOP = 40;
4475
4569
  var PAD_RIGHT = 24;
4476
4570
  var PAD_BOTTOM = 40;
4477
4571
  var PAD_LEFT = 24;
4572
+ var \u6728\u306E\u679D\u306E\u592A\u3055 = (\u6BB5) => Math.max(1.1, 2.6 - \u6BB5 * 0.45);
4478
4573
  function \u6728\u306E\u4E2D\u8EAB(node, stateValues = {}) {
4479
4574
  const treeNodes = resolveTreeData(node.treeData ?? [], stateValues);
4480
- return computeTreeLayout(
4481
- treeNodes,
4482
- node.w - PAD_LEFT - PAD_RIGHT,
4483
- node.h - PAD_TOP - PAD_BOTTOM
4484
- );
4575
+ return computeTreeLayout(treeNodes, node.w - PAD_LEFT - PAD_RIGHT, node.h - PAD_TOP - PAD_BOTTOM);
4485
4576
  }
4486
4577
  function \u6728\u306E\u884C(n) {
4487
4578
  return [
@@ -4540,7 +4631,7 @@ function TreeNode({
4540
4631
  fill: "none",
4541
4632
  stroke: TONE.accent,
4542
4633
  strokeOpacity: 0.55,
4543
- strokeWidth: 1.5,
4634
+ strokeWidth: \u6728\u306E\u679D\u306E\u592A\u3055(e.depth),
4544
4635
  strokeLinejoin: "round",
4545
4636
  ...\u4F38\u3070\u3059dash(drawing, \u679D\u306E\u4F38\u3073)
4546
4637
  }
@@ -4675,11 +4766,20 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
4675
4766
  if (kids.length === 0) return 1;
4676
4767
  return kids.reduce((sum, k) => sum + leafCount(k.id, seen), 0);
4677
4768
  };
4678
- const totalLeaves = Math.max(roots.reduce((sum, r) => sum + leafCount(r.id, /* @__PURE__ */ new Set()), 0), 1);
4769
+ const totalLeaves = Math.max(
4770
+ roots.reduce((sum, r) => sum + leafCount(r.id, /* @__PURE__ */ new Set()), 0),
4771
+ 1
4772
+ );
4679
4773
  const depthGap = canvasH / Math.max(maxDepth + 1, 1);
4680
4774
  const slotW = canvasW / totalLeaves;
4681
4775
  const nodeH = Math.min(38, depthGap * 0.7);
4682
4776
  const nodeW = Math.min(140, slotW * 0.85);
4777
+ const \u7BB1\u306E\u5E45 = (n, depth) => {
4778
+ const \u6750\u6599 = \u6728\u306E\u884C({ ...n, depth });
4779
+ const \u540D\u524D = \u6750\u6599[0];
4780
+ const \u8981\u308B = measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize}) + (nodeW - \u4F7F\u3048\u308B\u5E45(nodeW));
4781
+ return Math.min(Math.max(\u8981\u308B, nodeW), slotW * 0.92);
4782
+ };
4683
4783
  const posOf = /* @__PURE__ */ new Map();
4684
4784
  const nodes = [];
4685
4785
  const placed = /* @__PURE__ */ new Set();
@@ -4703,7 +4803,7 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
4703
4803
  ...n.subtitle !== void 0 ? { subtitle: n.subtitle } : {},
4704
4804
  x,
4705
4805
  y,
4706
- w: nodeW,
4806
+ w: \u7BB1\u306E\u5E45(n, depth),
4707
4807
  h: nodeH,
4708
4808
  depth,
4709
4809
  ...n.unresolved ? { unresolved: true } : {}
@@ -4754,6 +4854,10 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
4754
4854
  }
4755
4855
  var MIND_TONES = ["accent", "teal", "success", "warning", "info", "error"];
4756
4856
  var MIND_BOX_GAP = 24;
4857
+ var \u679D\u306E\u592A\u3055 = (\u6BB5) => Math.max(1.2, 3.2 - \u6BB5 * 0.7);
4858
+ var BRANCH_BOX_H_MAX = 48;
4859
+ var SUB_BOX_H_MAX = 40;
4860
+ var ROW_GAP_MAX = 96;
4757
4861
  var MIND_PAD = 40;
4758
4862
  function \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues = {}) {
4759
4863
  const mindData = node.mindData ? resolveMindData(node.mindData, stateValues) : void 0;
@@ -4810,7 +4914,7 @@ function MindMapNode({
4810
4914
  d: e.d,
4811
4915
  fill: "none",
4812
4916
  stroke: toneColor2(e.tone),
4813
- strokeWidth: 2.5,
4917
+ strokeWidth: \u679D\u306E\u592A\u3055(e.depth),
4814
4918
  strokeOpacity: 0.55,
4815
4919
  strokeLinecap: "round",
4816
4920
  ...\u4F38\u3070\u3059dash(drawing, \u679D\u306E\u4F38\u3073)
@@ -4821,13 +4925,19 @@ function MindMapNode({
4821
4925
  layout2.nodes.map((n) => {
4822
4926
  if (!\u7BB1\u304C\u51FA\u308B(n.depth)) return null;
4823
4927
  const \u6750\u6599 = \u653E\u5C04\u306E\u884C(n);
4824
- const \u884C = \u7BB1\u306B\u7A4D\u3080(\u6750\u6599, n.w, n.h);
4825
4928
  const \u88DC\u8DB3\u3042\u308A = (n.subtitle ?? "").trim() !== "";
4826
4929
  const \u540D\u524D = \u6750\u6599[0];
4827
- const \u53CE\u3081\u305F\u540D\u524D = \u88DC\u8DB3\u3042\u308A ? void 0 : \u5E45\u306B\u53CE\u3081\u308B(\u540D\u524D.text, \u540D\u524D.fontSize, \u4F7F\u3048\u308B\u5E45(n.w));
4930
+ const \u67A0\u306A\u3057 = !n.isRoot && n.isLeaf;
4931
+ const \u5916\u3078 = n.side === "right";
4932
+ const \u6587\u5B57\u306Ex = \u67A0\u306A\u3057 ? n.x + (\u5916\u3078 ? -n.w / 2 : n.w / 2) : n.x;
4933
+ const \u6587\u5B57\u306E\u5BC4\u305B = \u67A0\u306A\u3057 ? \u5916\u3078 ? "start" : "end" : "middle";
4934
+ const \u63CF\u753B\u57DF\u306E\u7AEF = \u5916\u3078 ? node.w - MIND_PAD : MIND_PAD;
4935
+ const \u4F7F\u3048\u308B = \u67A0\u306A\u3057 ? Math.abs(\u63CF\u753B\u57DF\u306E\u7AEF - \u6587\u5B57\u306Ex) : \u4F7F\u3048\u308B\u5E45(n.w);
4936
+ const \u53CE\u3081\u305F\u540D\u524D = \u88DC\u8DB3\u3042\u308A ? void 0 : \u5E45\u306B\u53CE\u3081\u308B(\u540D\u524D.text, \u540D\u524D.fontSize, \u4F7F\u3048\u308B);
4937
+ const \u884C = \u7BB1\u306B\u7A4D\u3080(\u6750\u6599, \u67A0\u306A\u3057 ? \u4F7F\u3048\u308B + (n.w - \u4F7F\u3048\u308B\u5E45(n.w)) : n.w, n.h);
4828
4938
  const \u6587\u5B57\u306E\u8272 = n.isRoot ? "var(--cdl-text-on-tone, #ffffff)" : "var(--cdl-chip-text, #1a1f2a)";
4829
4939
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-unresolved": n.unresolved ? "true" : void 0, children: [
4830
- /* @__PURE__ */ jsxRuntime.jsx(
4940
+ \u67A0\u306A\u3057 ? null : /* @__PURE__ */ jsxRuntime.jsx(
4831
4941
  "rect",
4832
4942
  {
4833
4943
  x: n.x - n.w / 2,
@@ -4844,11 +4954,11 @@ function MindMapNode({
4844
4954
  "text",
4845
4955
  {
4846
4956
  "data-cdl-role": r.\u5F79\u5272 === "subtitle" ? "mind-node-subtitle" : void 0,
4847
- x: n.x,
4957
+ x: \u6587\u5B57\u306Ex,
4848
4958
  y: n.y + r.dy,
4849
4959
  fontSize: r.fontSize,
4850
4960
  fontWeight: r.\u5F79\u5272 === "title" ? n.isRoot ? 700 : 600 : 500,
4851
- textAnchor: "middle",
4961
+ textAnchor: \u6587\u5B57\u306E\u5BC4\u305B,
4852
4962
  fill: \u6587\u5B57\u306E\u8272,
4853
4963
  opacity: r.\u5F79\u5272 === "subtitle" ? 0.85 : void 0,
4854
4964
  children: r.text
@@ -4862,11 +4972,11 @@ function MindMapNode({
4862
4972
  /* @__PURE__ */ jsxRuntime.jsx(
4863
4973
  "text",
4864
4974
  {
4865
- x: n.x,
4975
+ x: \u6587\u5B57\u306Ex,
4866
4976
  y: n.y + 5,
4867
4977
  fontSize: \u53CE\u3081\u305F\u540D\u524D.fontSize,
4868
4978
  fontWeight: n.isRoot ? 700 : 600,
4869
- textAnchor: "middle",
4979
+ textAnchor: \u6587\u5B57\u306E\u5BC4\u305B,
4870
4980
  fill: \u6587\u5B57\u306E\u8272,
4871
4981
  children: \u53CE\u3081\u305F\u540D\u524D.text
4872
4982
  }
@@ -4876,6 +4986,13 @@ function MindMapNode({
4876
4986
  })
4877
4987
  ] });
4878
4988
  }
4989
+ function \u63CF\u304F\u6A2A\u306E\u7AEF(n) {
4990
+ if (n.isRoot || !n.isLeaf) return [n.x - n.w / 2, n.x + n.w / 2];
4991
+ const \u8D77\u70B9 = n.x + (n.side === "right" ? -n.w / 2 : n.w / 2);
4992
+ const \u540D\u524D = \u653E\u5C04\u306E\u884C(n)[0];
4993
+ const \u5E45 = measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize});
4994
+ return n.side === "right" ? [\u8D77\u70B9, \u8D77\u70B9 + \u5E45] : [\u8D77\u70B9 - \u5E45, \u8D77\u70B9];
4995
+ }
4879
4996
  function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
4880
4997
  const nodes = [];
4881
4998
  const edges = [];
@@ -4891,6 +5008,9 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
4891
5008
  w: rootW,
4892
5009
  h: rootH,
4893
5010
  isRoot: true,
5011
+ // 中心は枝を持たなくても枠を描く = 図の起点なので、無いと何から広がるのかが読めない
5012
+ isLeaf: false,
5013
+ side: "right",
4894
5014
  // 中心は起点なので段数 0 (cdl#520)
4895
5015
  depth: 0,
4896
5016
  ...mindData.unresolved ? { unresolved: true } : {}
@@ -4927,7 +5047,6 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
4927
5047
  const firstCount = firstLevel.length;
4928
5048
  const leftCount = Math.ceil(firstCount / 2);
4929
5049
  const branchW = 130;
4930
- const branchH = 38;
4931
5050
  const subBranchW = 100;
4932
5051
  const subBranchH = 30;
4933
5052
  const subDepthOf = (id, seen) => {
@@ -4961,22 +5080,27 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
4961
5080
  const subOffset = (subDepth) => subDepth <= 0 ? 0 : step1 + (subDepth - 1) * stepN;
4962
5081
  const leftBranches = firstLevel.slice(0, leftCount);
4963
5082
  const rightBranches = firstLevel.slice(leftCount);
4964
- const leavesOfSide = (brs) => Math.max(1, brs.reduce((sum, br) => sum + leafCountOf(br.id, /* @__PURE__ */ new Set()), 0));
5083
+ const leavesOfSide = (brs) => Math.max(
5084
+ 1,
5085
+ brs.reduce((sum, br) => sum + leafCountOf(br.id, /* @__PURE__ */ new Set()), 0)
5086
+ );
4965
5087
  const sideLaneCount = Math.max(leavesOfSide(leftBranches), leavesOfSide(rightBranches));
4966
- const laneBandH = Math.min(canvasH * 0.9, sideLaneCount * (subBranchH + 14));
4967
- const rowGap = sideLaneCount > 1 ? laneBandH / (sideLaneCount - 1) : subBranchH + 14;
4968
- const effSubH = Math.min(subBranchH, rowGap * 0.7);
4969
- const effBranchH = Math.min(branchH, rowGap * 0.7);
4970
- const laneTop = cy - canvasH / 2 + effSubH / 2;
4971
- const laneBottom = cy + canvasH / 2 - effSubH / 2;
5088
+ const laneBandH = Math.max(0, canvasH - BRANCH_BOX_H_MAX);
5089
+ const rowGap = sideLaneCount > 1 ? Math.min(laneBandH / (sideLaneCount - 1), ROW_GAP_MAX) : subBranchH + 14;
5090
+ const effSubH = Math.min(SUB_BOX_H_MAX, rowGap * 0.7);
5091
+ const effBranchH = Math.min(BRANCH_BOX_H_MAX, rowGap * 0.7);
5092
+ const \u7AEF\u306E\u4F59\u308A = Math.max(effSubH, effBranchH) / 2;
5093
+ const laneTop = cy - canvasH / 2 + \u7AEF\u306E\u4F59\u308A;
5094
+ const laneBottom = cy + canvasH / 2 - \u7AEF\u306E\u4F59\u308A;
5095
+ const \u4F7F\u3046\u9AD8\u3055 = (sideLaneCount - 1) * rowGap;
4972
5096
  const laneY = (lane) => {
4973
5097
  if (sideLaneCount <= 1) return cy;
4974
- const y = cy - laneBandH / 2 + lane * rowGap;
5098
+ const y = cy - \u4F7F\u3046\u9AD8\u3055 / 2 + lane * rowGap;
4975
5099
  return Math.max(laneTop, Math.min(laneBottom, y));
4976
5100
  };
4977
- const rootEdgeXFor = (isLeft) => {
5101
+ const rootEdgeXFor = (isLeft, \u4E2D\u5FC3\u306Ex) => {
4978
5102
  const half = nodeHalfW.get(mindData.rootId) ?? rootW / 2;
4979
- return cx + (isLeft ? -half : half);
5103
+ return \u4E2D\u5FC3\u306Ex + (isLeft ? -half : half);
4980
5104
  };
4981
5105
  const placeSubtree = (node, subDepth, isLeft, tone, placed, laneRef) => {
4982
5106
  placed.add(node.id);
@@ -4992,7 +5116,14 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
4992
5116
  laneRef.cursor += 1;
4993
5117
  } else {
4994
5118
  const ys = kids.map(
4995
- (k, i) => placeSubtree(k, subDepth + 1, isLeft, myTone ?? MIND_TONES[i % MIND_TONES.length], placed, laneRef)
5119
+ (k, i) => placeSubtree(
5120
+ k,
5121
+ subDepth + 1,
5122
+ isLeft,
5123
+ myTone ?? MIND_TONES[i % MIND_TONES.length],
5124
+ placed,
5125
+ laneRef
5126
+ )
4996
5127
  );
4997
5128
  y = (ys[0] + ys[ys.length - 1]) / 2;
4998
5129
  }
@@ -5008,6 +5139,8 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5008
5139
  depth: subDepth + 1,
5009
5140
  tone: myTone,
5010
5141
  isRoot: false,
5142
+ isLeaf: kids.length === 0,
5143
+ side: isLeft ? "left" : "right",
5011
5144
  ...node.unresolved ? { unresolved: true } : {}
5012
5145
  });
5013
5146
  nodePos.set(node.id, { x, y });
@@ -5017,7 +5150,8 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5017
5150
  return y;
5018
5151
  };
5019
5152
  const placeSide = (brs, isLeft, toneBase) => {
5020
- const laneRef = { cursor: 0 };
5153
+ const \u8449\u6570 = brs.reduce((sum, br) => sum + leafCountOf(br.id, /* @__PURE__ */ new Set()), 0);
5154
+ const laneRef = { cursor: Math.max(0, (sideLaneCount - \u8449\u6570) / 2) };
5021
5155
  const placed = /* @__PURE__ */ new Set();
5022
5156
  brs.forEach((br, i) => {
5023
5157
  const tone = br.tone ?? MIND_TONES[(toneBase + i) % MIND_TONES.length];
@@ -5047,6 +5181,23 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5047
5181
  }
5048
5182
  }
5049
5183
  }
5184
+ {
5185
+ let \u5DE6\u7AEF = Number.POSITIVE_INFINITY;
5186
+ let \u53F3\u7AEF = Number.NEGATIVE_INFINITY;
5187
+ for (const n of nodes) {
5188
+ const [l, r] = \u63CF\u304F\u6A2A\u306E\u7AEF(n);
5189
+ \u5DE6\u7AEF = Math.min(\u5DE6\u7AEF, l);
5190
+ \u53F3\u7AEF = Math.max(\u53F3\u7AEF, r);
5191
+ }
5192
+ const \u5BC4\u305B = Math.round((cx - \u5DE6\u7AEF - (\u53F3\u7AEF - cx)) / 2);
5193
+ if (Number.isFinite(\u5BC4\u305B) && \u5BC4\u305B !== 0) {
5194
+ for (const n of nodes) {
5195
+ n.x += \u5BC4\u305B;
5196
+ nodePos.set(n.id, { x: n.x, y: n.y });
5197
+ }
5198
+ }
5199
+ }
5200
+ const rootX = nodePos.get(mindData.rootId)?.x ?? cx;
5050
5201
  const \u6BB5\u6570 = new Map(nodes.map((n) => [n.id, n.depth]));
5051
5202
  for (const br of mindData.branches) {
5052
5203
  const childPos = nodePos.get(br.id);
@@ -5057,7 +5208,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5057
5208
  const childDepth = \u6BB5\u6570.get(br.id) ?? 1;
5058
5209
  const parentDepth = \u6BB5\u6570.get(br.parent) ?? 0;
5059
5210
  if (br.parent === mindData.rootId) {
5060
- const startX = rootEdgeXFor(isLeft);
5211
+ const startX = rootEdgeXFor(isLeft, rootX);
5061
5212
  const endX = childPos.x + (isLeft ? childHalfW : -childHalfW);
5062
5213
  edges.push({
5063
5214
  d: makeCurve(startX, cy, endX, childPos.y),
@@ -5237,6 +5388,7 @@ function emptyCounts() {
5237
5388
  "node-inside-lane": 0,
5238
5389
  "shape-label-dropped": 0,
5239
5390
  "box-line-dropped": 0,
5391
+ "node-field-unsupported": 0,
5240
5392
  "edge-inside-viewbox": 0,
5241
5393
  "lane-label-inside-viewbox": 0,
5242
5394
  "lane-label-overlap": 0,
@@ -6406,6 +6558,28 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6406
6558
  `node "${n.id}" (kind=${n.kind ?? "\u672A\u6307\u5B9A"}) \u304C rows ${n.rows.length} \u884C\u3092\u6301\u3064\u304C\u3001 \u3053\u306E\u7A2E\u5225\u306F\u884C\u3092\u63CF\u304B\u306A\u3044 (\u66F8\u3044\u305F\u5185\u5BB9\u304C\u753B\u9762\u306B\u51FA\u306A\u3044)`
6407
6559
  );
6408
6560
  }
6561
+ const \u6B04\u306E\u63CF\u304D\u5206\u3051 = [
6562
+ { \u6B04: "eyebrow", \u8A9E: "\u80A9\u66F8", \u63CF\u304F\u304B: rendersEyebrow },
6563
+ { \u6B04: "subtitle", \u8A9E: "\u8AAC\u660E", \u63CF\u304F\u304B: rendersSubtitle },
6564
+ { \u6B04: "value", \u8A9E: "\u5024", \u63CF\u304F\u304B: rendersValue }
6565
+ ];
6566
+ for (const n of diag.nodes) {
6567
+ if (!isRenderedNode(n)) continue;
6568
+ for (const { \u6B04, \u8A9E, \u63CF\u304F\u304B } of \u6B04\u306E\u63CF\u304D\u5206\u3051) {
6569
+ const \u66F8\u3044\u305F = (n[\u6B04] ?? "").trim();
6570
+ if (\u66F8\u3044\u305F === "") continue;
6571
+ if (\u63CF\u304F\u304B(n.kind)) continue;
6572
+ push(
6573
+ "node-field-unsupported",
6574
+ `node "${n.id}" (kind=${n.kind ?? "\u672A\u6307\u5B9A"}) \u304C ${\u6B04} (${\u8A9E}) \u306B "${\u66F8\u3044\u305F}" \u3092\u6301\u3064\u304C\u3001 \u3053\u306E\u7A2E\u5225\u306F\u305D\u306E\u6B04\u3092\u63CF\u304B\u306A\u3044 (\u66F8\u3044\u305F\u8A9E\u304C\u753B\u9762\u306B\u51FA\u306A\u3044)`,
6575
+ // 図そのものは正しく描かれており、効かない語が書かれているだけなので警告にする。
6576
+ // 誤り扱いにすると、既に書いている図が 1 枚も通らなくなる (実測 = engine の検査
6577
+ // だけで 8 file が落ちた)。 `rows-not-rendered` は誤り扱いだが、あちらは行が
6578
+ // 箱の主な中身になる種別を相手にしており、落ちた時の図の壊れ方が違う
6579
+ "warn"
6580
+ );
6581
+ }
6582
+ }
6409
6583
  for (const n of diag.nodes) {
6410
6584
  if (!n.rows || n.rows.length === 0) continue;
6411
6585
  if (!rendersRows(n.kind)) continue;
@@ -9895,7 +10069,7 @@ function autoStorageHeight(n, defaultH) {
9895
10069
  if (n.kind !== "storage") return n.h ?? defaultH;
9896
10070
  if (n.h != null) return n.h;
9897
10071
  const \u5370\u3042\u308A = n.rowMarks !== void 0;
9898
- const \u547C\u3073\u540D\u306E\u5206 = \u5370\u3042\u308A && n.subtitle ? SUBTITLE_ROW_SHIFT : 0;
10072
+ const \u547C\u3073\u540D\u306E\u5206 = n.subtitle ? SUBTITLE_ROW_SHIFT : 0;
9899
10073
  const \u7E70\u308A\u4E0A\u3052 = n.eyebrow ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052("storage");
9900
10074
  if (!n.rows || n.rows.length === 0) return 115 + \u547C\u3073\u540D\u306E\u5206 - \u7E70\u308A\u4E0A\u3052;
9901
10075
  const \u5FC5\u8981 = requiredRowsHeight("storage", n.rows.length) ?? defaultH;
@@ -10022,22 +10196,33 @@ function layoutNodes(diag, lanes) {
10022
10196
  }
10023
10197
 
10024
10198
  // src/layout/viewbox.ts
10199
+ function \u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F(lane) {
10200
+ return lane.contain === true || lane.lifeline === true;
10201
+ }
10025
10202
  function computeViewBox(lanes, nodes, edges, bboxes, viewport) {
10203
+ const \u5E38\u306B\u96A0\u308C\u308B\u7BC0 = new Set(nodes.filter((n) => !isRenderedNode(n)).map((n) => n.id));
10026
10204
  let maxX = 0;
10027
10205
  let maxY = 0;
10028
10206
  let minX = Number.POSITIVE_INFINITY;
10029
10207
  let minY = Number.POSITIVE_INFINITY;
10030
10208
  for (const bbox of bboxes) {
10209
+ if (bbox.kind === "node" && \u5E38\u306B\u96A0\u308C\u308B\u7BC0.has(bbox.id)) continue;
10031
10210
  maxX = Math.max(maxX, bbox.x + bbox.w);
10032
10211
  maxY = Math.max(maxY, bbox.y + bbox.h);
10033
10212
  minX = Math.min(minX, bbox.x);
10034
10213
  minY = Math.min(minY, bbox.y);
10035
10214
  }
10036
10215
  for (const lane of lanes) {
10216
+ if (!\u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F(lane)) continue;
10217
+ minX = Math.min(minX, lane.x);
10218
+ minY = Math.min(minY, lane.y);
10037
10219
  maxX = Math.max(maxX, lane.x + lane.width);
10038
10220
  maxY = Math.max(maxY, lane.y + lane.height);
10039
10221
  }
10040
10222
  for (const n of nodes) {
10223
+ if (\u5E38\u306B\u96A0\u308C\u308B\u7BC0.has(n.id)) continue;
10224
+ minX = Math.min(minX, n.cx - n.w / 2);
10225
+ minY = Math.min(minY, n.cy - n.h / 2);
10041
10226
  maxX = Math.max(maxX, n.cx + n.w / 2);
10042
10227
  maxY = Math.max(maxY, n.cy + n.h / 2);
10043
10228
  }
@@ -11983,7 +12168,7 @@ function StorageNode({
11983
12168
  const columnDividerX = (leftEndDrawn + rightColX) / 2;
11984
12169
  const columnDividerFits = columnDividerX <= node.w - ROW_PAD_X_PX;
11985
12170
  const \u5370\u3067\u5206\u3051\u308B = node.rowMarks !== void 0;
11986
- const \u884C\u306E\u4E0B\u3052 = \u5370\u3067\u5206\u3051\u308B && node.subtitle ? SUBTITLE_ROW_SHIFT : 0;
12171
+ const \u884C\u306E\u4E0B\u3052 = node.subtitle ? SUBTITLE_ROW_SHIFT : 0;
11987
12172
  const lastRowBottom = Math.min(
11988
12173
  ROW_TOP_STORAGE + (rows.length - 1) * ROW_PITCH_STORAGE + (rowGlyphDepth("storage") ?? 0),
11989
12174
  node.h - ROW_PAD_X_PX
@@ -12023,8 +12208,7 @@ function StorageNode({
12023
12208
  );
12024
12209
  }),
12025
12210
  node.eyebrow && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 38, fontSize: 18, fontWeight: 700, letterSpacing: 2, fill: accent, children: node.eyebrow }),
12026
- \u5370\u3067\u5206\u3051\u308B && node.subtitle && // 呼び名は **印で分ける箱でだけ** 出す (#578)。 従来の箱は題の下に区切り線が来るので
12027
- // 置き場が無い
12211
+ node.subtitle && // 呼び名は書き方によらず出す (#937)。 区切り線を同じ分だけ下げて置き場を作る
12028
12212
  /* @__PURE__ */ jsxRuntime.jsx(
12029
12213
  "text",
12030
12214
  {
@@ -12055,9 +12239,9 @@ function StorageNode({
12055
12239
  {
12056
12240
  "data-cdl-role": "node-row-divider",
12057
12241
  x1: 26,
12058
- y1: STORAGE_ROW_DIVIDER_Y,
12242
+ y1: STORAGE_ROW_DIVIDER_Y + \u884C\u306E\u4E0B\u3052,
12059
12243
  x2: node.w - 26,
12060
- y2: STORAGE_ROW_DIVIDER_Y,
12244
+ y2: STORAGE_ROW_DIVIDER_Y + \u884C\u306E\u4E0B\u3052,
12061
12245
  stroke: "var(--cdl-row-divider, #7e848e)",
12062
12246
  strokeWidth: 1.25
12063
12247
  }
@@ -12067,7 +12251,7 @@ function StorageNode({
12067
12251
  {
12068
12252
  "data-cdl-role": "node-column-divider",
12069
12253
  x1: columnDividerX,
12070
- y1: STORAGE_ROW_DIVIDER_Y,
12254
+ y1: STORAGE_ROW_DIVIDER_Y + \u884C\u306E\u4E0B\u3052,
12071
12255
  x2: columnDividerX,
12072
12256
  y2: lastRowBottom,
12073
12257
  stroke: "var(--cdl-row-divider, #7e848e)",
@@ -12528,18 +12712,57 @@ function DynShapeNode({
12528
12712
  const strokeColor = shape.stroke ?? "var(--cdl-line, #a89d8f)";
12529
12713
  const fillColor = shape.fill ?? "var(--cdl-fill, #e0e6ef)";
12530
12714
  const activeOpacity = active ? 1 : 0.85;
12531
- switch (shape.kind) {
12532
- case "rect":
12533
- return renderRect(shape, x, y, w, h, stateValues, fillColor, strokeColor, activeOpacity, node);
12534
- case "circle":
12535
- return renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, activeOpacity);
12536
- case "arc":
12537
- return renderArc(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, activeOpacity);
12538
- case "wave":
12539
- return /* @__PURE__ */ jsxRuntime.jsx(WaveShape, { shape, x, y, w, h, stateValues, fillColor, strokeColor, opacity: activeOpacity, node });
12540
- case "polygon":
12541
- return renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, activeOpacity);
12542
- }
12715
+ const \u5F62 = (() => {
12716
+ switch (shape.kind) {
12717
+ case "rect":
12718
+ return renderRect(shape, x, y, w, h, stateValues, fillColor, strokeColor, activeOpacity, node);
12719
+ case "circle":
12720
+ return renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, activeOpacity);
12721
+ case "arc":
12722
+ return renderArc(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, activeOpacity);
12723
+ case "wave":
12724
+ return /* @__PURE__ */ jsxRuntime.jsx(WaveShape, { shape, x, y, w, h, stateValues, fillColor, strokeColor, opacity: activeOpacity, node });
12725
+ case "polygon":
12726
+ return renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, activeOpacity);
12727
+ }
12728
+ })();
12729
+ const \u540D\u524D = (node.title ?? "").trim();
12730
+ const \u5024 = (node.subtitle ?? "").trim();
12731
+ if (\u540D\u524D === "" && \u5024 === "") return \u5F62;
12732
+ const \u63C3\u3048 = \u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F2(shape.kind) ? "start" : "middle";
12733
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
12734
+ \u5F62,
12735
+ \u540D\u524D !== "" && /* @__PURE__ */ jsxRuntime.jsx(
12736
+ "text",
12737
+ {
12738
+ "data-cdl-role": "shape-name",
12739
+ x: \u63C3\u3048 === "start" ? x : cx,
12740
+ y: y - NAME_GAP,
12741
+ textAnchor: \u63C3\u3048,
12742
+ fontSize: 13,
12743
+ fontWeight: 600,
12744
+ fill: "var(--cdl-text, #23201b)",
12745
+ children: \u540D\u524D
12746
+ }
12747
+ ),
12748
+ \u5024 !== "" && /* @__PURE__ */ jsxRuntime.jsx(
12749
+ "text",
12750
+ {
12751
+ "data-cdl-role": "shape-value",
12752
+ x: cx,
12753
+ y: y + h + VALUE_GAP,
12754
+ textAnchor: "middle",
12755
+ fontSize: 12,
12756
+ fill: "var(--cdl-text-dim, #5a6270)",
12757
+ children: \u5024
12758
+ }
12759
+ )
12760
+ ] });
12761
+ }
12762
+ var NAME_GAP = 6;
12763
+ var VALUE_GAP = 18;
12764
+ function \u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F2(kind) {
12765
+ return kind === "rect" || kind === "wave";
12543
12766
  }
12544
12767
  function renderRect(shape, x, y, w, h, stateValues, fillColor, strokeColor, opacity, node) {
12545
12768
  const value = resolveNumericAttr(shape.source, stateValues, 0);
@@ -12827,6 +13050,13 @@ function \u5272\u5408\u8868\u8A18(frac) {
12827
13050
  const v = Math.round(frac * 1e3) / 10;
12828
13051
  return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
12829
13052
  }
13053
+ function \u5024\u3068\u5272\u5408\u306E\u7D44(\u5024, \u5272\u5408, \u5408\u8A08) {
13054
+ return Math.abs(\u5408\u8A08 - 100) < 1e-9 ? { \u5024: null, \u5272\u5408 } : { \u5024, \u5272\u5408 };
13055
+ }
13056
+ function \u5024\u3068\u5272\u5408\u306E\u6587\u5B57(\u5024, \u5272\u5408, \u5408\u8A08) {
13057
+ const \u7D44 = \u5024\u3068\u5272\u5408\u306E\u7D44(\u5024, \u5272\u5408, \u5408\u8A08);
13058
+ return \u7D44.\u5024 === null ? \u7D44.\u5272\u5408 : `${\u7D44.\u5024} ${\u7D44.\u5272\u5408}`;
13059
+ }
12830
13060
  var \u7A74\u306B\u5BFE\u3059\u308B\u4E0A\u9650 = 0.8;
12831
13061
  function \u4E2D\u592E\u306E\u5B57(\u6BD4\u4F8B\u3057\u305F\u5927\u304D\u3055, \u7A74\u306E\u534A\u5F84, \u6587) {
12832
13062
  const \u5165\u308B\u5927\u304D\u3055 = \u7A74\u306E\u534A\u5F84 * 2 * \u7A74\u306B\u5BFE\u3059\u308B\u4E0A\u9650 / Math.max(textWidth(\u6587, 1), 1e-6);
@@ -13303,6 +13533,18 @@ function sliceColor(tone, idx) {
13303
13533
  if (tone) return TONE[tone];
13304
13534
  return chartSeriesColor(idx);
13305
13535
  }
13536
+ function \u5024\u3068\u5272\u5408\u306E\u5B57({
13537
+ \u5024,
13538
+ \u5272\u5408,
13539
+ \u5408\u8A08
13540
+ }) {
13541
+ const \u7D44 = \u5024\u3068\u5272\u5408\u306E\u7D44(\u5024, \u5272\u5408, \u5408\u8A08);
13542
+ if (\u7D44.\u5024 === null) return /* @__PURE__ */ jsxRuntime.jsx("tspan", { "data-cdl-role": "chart-legend-share", children: \u7D44.\u5272\u5408 });
13543
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13544
+ /* @__PURE__ */ jsxRuntime.jsx("tspan", { "data-cdl-role": "chart-legend-value", fill: "var(--cdl-text, #1a1f2a)", children: `${\u7D44.\u5024} ` }),
13545
+ /* @__PURE__ */ jsxRuntime.jsx("tspan", { "data-cdl-role": "chart-legend-share", children: \u7D44.\u5272\u5408 })
13546
+ ] });
13547
+ }
13306
13548
  function ChartGaugeNode({
13307
13549
  node,
13308
13550
  active,
@@ -13325,7 +13567,7 @@ function ChartGaugeNode({
13325
13567
  const \u5F27\u3068\u5185\u8A33\u306E\u9593 = 16;
13326
13568
  const \u5370\u306E\u5E452 = 30;
13327
13569
  const \u533A\u753B\u306E\u9593 = 12;
13328
- const \u6570\u5024\u306E\u884C = (d) => `${\u5B9F\u5024\u8868\u8A18(d.value)} ${\u5272\u5408\u8868\u8A18(d.value / total)}`;
13570
+ const \u6570\u5024\u306E\u884C = (d) => \u5024\u3068\u5272\u5408\u306E\u6587\u5B57(\u5B9F\u5024\u8868\u8A18(d.value), \u5272\u5408\u8868\u8A18(d.value / total), total);
13329
13571
  const \u5272\u308A\u4ED8\u3051\u308B = (\u4EF6\u305F\u3061) => {
13330
13572
  const \u5E45 = Math.max(\u5370\u306E\u5E452, ...\u4EF6\u305F\u3061.map((d) => textWidth(\u6570\u5024\u306E\u884C(d), \u6570\u5024\u306E\u7D1A))) + \u533A\u753B\u306E\u9593;
13331
13573
  const \u884C\u306E\u4EF6\u65702 = Math.min(
@@ -13494,6 +13736,8 @@ function ChartGaugeNode({
13494
13736
  const x = PAD_SIDE + \u5185\u8A33\u306E\u5E45 * \u5217;
13495
13737
  const y = \u5185\u8A33\u306Ey + \u6BB5\u306E\u9AD8\u3055 * \u6BB5;
13496
13738
  const \u53CE\u307E\u308B\u5E45 = \u5185\u8A33\u306E\u5E45 - \u533A\u753B\u306E\u9593;
13739
+ const \u6570\u306E\u884C = \u5185\u8A33\u306E\u6570\u5024[idx] ?? "";
13740
+ const \u5207\u3063\u305F\u6570\u306E\u884C = \u5207\u308A\u8A70\u3081\u308B(\u6570\u306E\u884C, \u53CE\u307E\u308B\u5E45, \u6570\u5024\u306E\u7D1A);
13497
13741
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "chart-gauge-item", children: [
13498
13742
  /* @__PURE__ */ jsxRuntime.jsx(
13499
13743
  "rect",
@@ -13517,7 +13761,14 @@ function ChartGaugeNode({
13517
13761
  children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u53CE\u307E\u308B\u5E45, \u540D\u524D\u306E\u7D1A)
13518
13762
  }
13519
13763
  ),
13520
- /* @__PURE__ */ jsxRuntime.jsx("text", { x, y: y + 46, fontSize: \u6570\u5024\u306E\u7D1A, fill: "var(--cdl-text-dim, #5a6270)", children: \u5207\u308A\u8A70\u3081\u308B(\u5185\u8A33\u306E\u6570\u5024[idx] ?? "", \u53CE\u307E\u308B\u5E45, \u6570\u5024\u306E\u7D1A) })
13764
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x, y: y + 46, fontSize: \u6570\u5024\u306E\u7D1A, fill: "var(--cdl-text-dim, #5a6270)", children: \u5207\u3063\u305F\u6570\u306E\u884C === \u6570\u306E\u884C ? /* @__PURE__ */ jsxRuntime.jsx(
13765
+ \u5024\u3068\u5272\u5408\u306E\u5B57,
13766
+ {
13767
+ \u5024: \u5B9F\u5024\u8868\u8A18(d.value),
13768
+ \u5272\u5408: \u5272\u5408\u8868\u8A18(d.value / total),
13769
+ \u5408\u8A08: total
13770
+ }
13771
+ ) : \u5207\u3063\u305F\u6570\u306E\u884C })
13521
13772
  ] }, `legend-${idx}`);
13522
13773
  })
13523
13774
  ] });
@@ -13556,7 +13807,9 @@ function ChartRadialNode({
13556
13807
  const \u6570\u5024\u306E\u7D1A = 13;
13557
13808
  const \u884C\u306E\u9AD8\u3055 = 42;
13558
13809
  const \u4E00\u89A7\u3068\u5F27\u306E\u9593 = 28;
13559
- const \u6570\u5024\u306E\u6587\u5B57 = data.map((d) => `${\u5B9F\u5024\u8868\u8A18(d.value)} ${\u5272\u5408\u8868\u8A18(d.value / total)}`);
13810
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map(
13811
+ (d) => \u5024\u3068\u5272\u5408\u306E\u6587\u5B57(\u5B9F\u5024\u8868\u8A18(d.value), \u5272\u5408\u8868\u8A18(d.value / total), total)
13812
+ );
13560
13813
  const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E45 + Math.max(
13561
13814
  0,
13562
13815
  ...data.map(
@@ -13568,7 +13821,9 @@ function ChartRadialNode({
13568
13821
  const \u4F7F\u3048\u308B\u539A\u307F = \u5916\u534A\u5F84 * 0.7;
13569
13822
  const \u5E2F1\u672C = \u4F7F\u3048\u308B\u539A\u307F / Math.max(data.length, 1);
13570
13823
  const \u5E2F\u306E\u5E45 = \u5E2F1\u672C * 0.66;
13571
- const \u5F27\u306Ecx = PAD + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u5F27\u306E\u9593 + \u5916\u534A\u5F84;
13824
+ const \u4E2D\u8EAB\u306E\u5E45 = \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u5F27\u306E\u9593 + \u5916\u534A\u5F84 * 2;
13825
+ const \u4E00\u89A7\u306E\u5DE6 = Math.max(PAD, (node.w - \u4E2D\u8EAB\u306E\u5E45) / 2);
13826
+ const \u5F27\u306Ecx = \u4E00\u89A7\u306E\u5DE6 + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u5F27\u306E\u9593 + \u5916\u534A\u5F84;
13572
13827
  const cy = PAD + \u4F7F\u3048\u308B\u9AD8\u3055 / 2;
13573
13828
  const rings = data.map((d, idx) => {
13574
13829
  const frac = d.value / total;
@@ -13643,11 +13898,11 @@ function ChartRadialNode({
13643
13898
  data.map((d, idx) => {
13644
13899
  const y = \u4E00\u89A7\u306E\u59CB\u307E\u308A + \u884C\u306E\u9AD8\u3055 * idx;
13645
13900
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "chart-radial-item", children: [
13646
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: PAD, y: y - 11, width: 4, height: 22, rx: 2, fill: arcColor2(d.tone, idx) }),
13901
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: \u4E00\u89A7\u306E\u5DE6, y: y - 11, width: 4, height: 22, rx: 2, fill: arcColor2(d.tone, idx) }),
13647
13902
  /* @__PURE__ */ jsxRuntime.jsx(
13648
13903
  "text",
13649
13904
  {
13650
- x: PAD + \u5370\u306E\u5E45,
13905
+ x: \u4E00\u89A7\u306E\u5DE6 + \u5370\u306E\u5E45,
13651
13906
  y: y + 1,
13652
13907
  fontSize: \u540D\u524D\u306E\u7D1A,
13653
13908
  fontWeight: 700,
@@ -13658,11 +13913,18 @@ function ChartRadialNode({
13658
13913
  /* @__PURE__ */ jsxRuntime.jsx(
13659
13914
  "text",
13660
13915
  {
13661
- x: PAD + \u5370\u306E\u5E45,
13916
+ x: \u4E00\u89A7\u306E\u5DE6 + \u5370\u306E\u5E45,
13662
13917
  y: y + 20,
13663
13918
  fontSize: \u6570\u5024\u306E\u7D1A,
13664
13919
  fill: "var(--cdl-text-dim, #5a6270)",
13665
- children: \u6570\u5024\u306E\u6587\u5B57[idx]
13920
+ children: /* @__PURE__ */ jsxRuntime.jsx(
13921
+ \u5024\u3068\u5272\u5408\u306E\u5B57,
13922
+ {
13923
+ \u5024: \u5B9F\u5024\u8868\u8A18(d.value),
13924
+ \u5272\u5408: \u5272\u5408\u8868\u8A18(d.value / total),
13925
+ \u5408\u8A08: total
13926
+ }
13927
+ )
13666
13928
  }
13667
13929
  )
13668
13930
  ] }, `item-${idx}`);
@@ -13705,7 +13967,7 @@ function ChartStatNode({
13705
13967
  const data = resolveChartData(node.chartData ?? [], stateValues);
13706
13968
  const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
13707
13969
  const \u524D\u3092\u51FA\u3059 = data.some((d) => d.previous !== void 0);
13708
- const \u533A\u753B = \u533A\u753B\u306E\u5272\u4ED8(node.w, node.h, data.length, \u524D\u3092\u51FA\u3059);
13970
+ const \u533A\u753B = \u533A\u753B\u306E\u5272\u4ED8(node.w, node.h, data.length, \u524D\u3092\u51FA\u3059, data.length > 1);
13709
13971
  const \u5272\u5408\u3092\u51FA\u3059 = data.length > 1;
13710
13972
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
13711
13973
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -13834,17 +14096,23 @@ function ChartStatNode({
13834
14096
  })
13835
14097
  ] });
13836
14098
  }
13837
- function \u533A\u753B\u306E\u5272\u4ED8(w, h, \u4EF6\u6570, \u524D\u3092\u51FA\u3059) {
14099
+ function \u533A\u753B\u306E\u5272\u4ED8(w, h, \u4EF6\u6570, \u524D\u3092\u51FA\u3059, \u5272\u5408\u3092\u51FA\u3059) {
13838
14100
  const \u4F59\u767D = 20;
13839
14101
  const \u5E45 = \u4EF6\u6570 > 0 ? w / \u4EF6\u6570 : w;
13840
14102
  const \u540D\u524D\u306E\u7D1A = 14;
13841
- const \u6570\u5024\u306E\u7D1A = 40;
13842
14103
  const \u524D\u306E\u7D1A = \u540D\u524D\u306E\u7D1A;
13843
14104
  const \u5272\u5408\u306E\u7D1A = 12;
13844
14105
  const \u5F27\u306E\u534A\u5F84 = 20;
13845
14106
  const \u5F27\u306E\u592A\u3055 = 4;
14107
+ const \u6570\u5024\u306E\u7D1A\u306E\u4E0B\u9650 = 40;
14108
+ const \u6570\u5024\u306E\u7D1A\u306E\u4E0A\u9650 = 112;
13846
14109
  const \u524D\u306E\u9AD8\u3055 = \u524D\u3092\u51FA\u3059 ? 8 + \u524D\u306E\u7D1A : 0;
13847
- const \u4E2D\u8EAB\u306E\u9AD8\u3055 = \u540D\u524D\u306E\u7D1A + 12 + \u6570\u5024\u306E\u7D1A + \u524D\u306E\u9AD8\u3055 + 16 + \u5F27\u306E\u534A\u5F84 * 2 + 8 + \u5272\u5408\u306E\u7D1A;
14110
+ const \u5F27\u3068\u5272\u5408\u306E\u9AD8\u3055 = \u5272\u5408\u3092\u51FA\u3059 ? 16 + \u5F27\u306E\u534A\u5F84 * 2 + 8 + \u5272\u5408\u306E\u7D1A : 0;
14111
+ const \u6570\u5024\u306E\u7D1A = \u5272\u5408\u3092\u51FA\u3059 ? \u6570\u5024\u306E\u7D1A\u306E\u4E0B\u9650 : Math.max(
14112
+ \u6570\u5024\u306E\u7D1A\u306E\u4E0B\u9650,
14113
+ Math.min(\u6570\u5024\u306E\u7D1A\u306E\u4E0A\u9650, Math.floor(h - \u4F59\u767D * 2 - \u540D\u524D\u306E\u7D1A - 12 - \u524D\u306E\u9AD8\u3055))
14114
+ );
14115
+ const \u4E2D\u8EAB\u306E\u9AD8\u3055 = \u540D\u524D\u306E\u7D1A + 12 + \u6570\u5024\u306E\u7D1A + \u524D\u306E\u9AD8\u3055 + \u5F27\u3068\u5272\u5408\u306E\u9AD8\u3055;
13848
14116
  const \u4E0A\u7AEF = Math.max(\u4F59\u767D, (h - \u4E2D\u8EAB\u306E\u9AD8\u3055) / 2);
13849
14117
  const \u540D\u524D\u306Ey = \u4E0A\u7AEF + \u540D\u524D\u306E\u7D1A;
13850
14118
  const \u6570\u5024\u306Ey = \u540D\u524D\u306Ey + 12 + \u6570\u5024\u306E\u7D1A * 0.78;
@@ -13916,7 +14184,10 @@ function ChartWaffleNode({
13916
14184
  const \u884C\u306E\u9AD8\u3055 = 40;
13917
14185
  const \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593 = 28;
13918
14186
  const \u5370\u306E\u5E452 = 18;
13919
- const \u6570\u5024\u306E\u6587\u5B57 = data.map((d, i) => `${\u5B9F\u5024\u8868\u8A18(d.value)} ${\u914D\u5206[i] ?? 0}%`);
14187
+ const \u5B9F\u5024\u306E\u5408\u8A08 = data.reduce((acc, d) => acc + d.value, 0);
14188
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map(
14189
+ (d, i) => \u5024\u3068\u5272\u5408\u306E\u6587\u5B57(\u5B9F\u5024\u8868\u8A18(d.value), `${\u914D\u5206[i] ?? 0}%`, \u5B9F\u5024\u306E\u5408\u8A08)
14190
+ );
13920
14191
  const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E452 + Math.max(
13921
14192
  0,
13922
14193
  ...data.map(
@@ -13927,7 +14198,9 @@ function ChartWaffleNode({
13927
14198
  const \u683C\u5B50\u306B\u4F7F\u3048\u308B\u5E45 = node.w - PAD * 2 - \u4E00\u89A7\u306E\u5E45 - \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593;
13928
14199
  const \u5347 = Math.max(4, Math.min(\u4F7F\u3048\u308B\u9AD8\u3055, \u683C\u5B50\u306B\u4F7F\u3048\u308B\u5E45) / WAFFLE_COLS);
13929
14200
  const \u5370 = \u5347 * 0.78;
13930
- const \u683C\u5B50\u306E\u5DE6 = PAD + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593;
14201
+ const \u4E2D\u8EAB\u306E\u5E45 = \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593 + \u5347 * WAFFLE_COLS;
14202
+ const \u4E00\u89A7\u306E\u5DE6 = Math.max(PAD, (node.w - \u4E2D\u8EAB\u306E\u5E45) / 2);
14203
+ const \u683C\u5B50\u306E\u5DE6 = \u4E00\u89A7\u306E\u5DE6 + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593;
13931
14204
  const \u683C\u5B50\u306E\u4E0A = PAD + (\u4F7F\u3048\u308B\u9AD8\u3055 - \u5347 * WAFFLE_COLS) / 2;
13932
14205
  const \u6301\u3061\u4E3B = [];
13933
14206
  \u914D\u5206.forEach((n, idx) => {
@@ -13974,11 +14247,11 @@ function ChartWaffleNode({
13974
14247
  data.map((d, idx) => {
13975
14248
  const y = \u4E00\u89A7\u306E\u59CB\u307E\u308A + \u884C\u306E\u9AD8\u3055 * idx;
13976
14249
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "chart-waffle-item", children: [
13977
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: PAD, y: y - 11, width: 4, height: 22, rx: 2, fill: \u5370\u306E\u82722(d.tone, idx) }),
14250
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: \u4E00\u89A7\u306E\u5DE6, y: y - 11, width: 4, height: 22, rx: 2, fill: \u5370\u306E\u82722(d.tone, idx) }),
13978
14251
  /* @__PURE__ */ jsxRuntime.jsx(
13979
14252
  "text",
13980
14253
  {
13981
- x: PAD + \u5370\u306E\u5E452,
14254
+ x: \u4E00\u89A7\u306E\u5DE6 + \u5370\u306E\u5E452,
13982
14255
  y: y + 1,
13983
14256
  fontSize: \u540D\u524D\u306E\u7D1A,
13984
14257
  fontWeight: 700,
@@ -13991,11 +14264,18 @@ function ChartWaffleNode({
13991
14264
  {
13992
14265
  "data-cdl-role": "chart-waffle-count",
13993
14266
  "data-cdl-unresolved": d.unresolved ? "true" : void 0,
13994
- x: PAD + \u5370\u306E\u5E452,
14267
+ x: \u4E00\u89A7\u306E\u5DE6 + \u5370\u306E\u5E452,
13995
14268
  y: y + 20,
13996
14269
  fontSize: \u6570\u5024\u306E\u7D1A,
13997
14270
  fill: "var(--cdl-text-dim, #5a6270)",
13998
- children: \u6570\u5024\u306E\u6587\u5B57[idx]
14271
+ children: /* @__PURE__ */ jsxRuntime.jsx(
14272
+ \u5024\u3068\u5272\u5408\u306E\u5B57,
14273
+ {
14274
+ \u5024: \u5B9F\u5024\u8868\u8A18(d.value),
14275
+ \u5272\u5408: `${\u914D\u5206[idx] ?? 0}%`,
14276
+ \u5408\u8A08: \u5B9F\u5024\u306E\u5408\u8A08
14277
+ }
14278
+ )
13999
14279
  }
14000
14280
  )
14001
14281
  ] }, `item-${idx}`);
@@ -14901,6 +15181,8 @@ function FunnelNode({
14901
15181
  const t = step / stageCount;
14902
15182
  return canvasW * (topRatio + (bottomRatio - topRatio) * t);
14903
15183
  };
15184
+ const \u540D\u524D\u306E\u5B57 = 14;
15185
+ const \u88DC\u8DB3\u306E\u5B57 = 10.5;
14904
15186
  const \u6BB5 = stages.map((s, idx) => {
14905
15187
  const prev = idx > 0 ? stages[idx - 1] : null;
14906
15188
  const dropRate = prev && prev.count > 0 ? (prev.count - s.count) / prev.count * 100 : 0;
@@ -14913,6 +15195,17 @@ function FunnelNode({
14913
15195
  const points = `${topX},${y} ${topX + topW},${y} ${bottomX + bottomW},${y + stageH} ${bottomX},${y + stageH}`;
14914
15196
  const tone = toneByIndex(idx);
14915
15197
  const legendX = PAD_LEFT2 + canvasW + 24;
15198
+ const \u88DC\u8DB3 = (s.subtitle ?? "").trim();
15199
+ const \u88DC\u8DB3\u3042\u308A = \u88DC\u8DB3 !== "";
15200
+ const \u4E8C\u884C\u306E\u9AD8\u3055 = \u540D\u524D\u306E\u5B57 * 1.2 + \u88DC\u8DB3\u306E\u5B57 * 1.25;
15201
+ const \u7E26\u500D = \u88DC\u8DB3\u3042\u308A ? Math.min(1, Math.max(0, stageH - 8) / \u4E8C\u884C\u306E\u9AD8\u3055) : 1;
15202
+ const \u540D\u524D\u306E\u5B9F\u5B57 = \u540D\u524D\u306E\u5B57 * \u7E26\u500D;
15203
+ const \u88DC\u8DB3\u306E\u67A0\u5B57 = \u88DC\u8DB3\u306E\u5B57 * \u7E26\u500D;
15204
+ const \u53CE\u307E\u308B\u5E45 = Math.max(0, bottomW - 16);
15205
+ const \u88DC\u8DB3\u306E\u5B9F\u5B57 = \u88DC\u8DB3\u306E\u67A0\u5B57 * \u53CE\u3081\u308B\u500D\u7387(\u88DC\u8DB3, { fontSize: \u88DC\u8DB3\u306E\u67A0\u5B57, fontWeight: 500 }, \u53CE\u307E\u308B\u5E45);
15206
+ const \u584A\u306E\u4E0A = y + stageH / 2 - (\u540D\u524D\u306E\u5B9F\u5B57 * 1.2 + \u88DC\u8DB3\u306E\u67A0\u5B57 * 1.25) / 2;
15207
+ const \u540D\u524D\u306Ey = \u88DC\u8DB3\u3042\u308A ? \u584A\u306E\u4E0A + \u540D\u524D\u306E\u5B9F\u5B57 * 0.95 : y + stageH / 2 + 5;
15208
+ const \u88DC\u8DB3\u306Ey = \u584A\u306E\u4E0A + \u540D\u524D\u306E\u5B9F\u5B57 * 1.2 + \u88DC\u8DB3\u306E\u67A0\u5B57 * 0.95;
14916
15209
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
14917
15210
  /* @__PURE__ */ jsxRuntime.jsx(
14918
15211
  "polygon",
@@ -14930,14 +15223,29 @@ function FunnelNode({
14930
15223
  "text",
14931
15224
  {
14932
15225
  x: cx,
14933
- y: y + stageH / 2 + 5,
14934
- fontSize: 14,
15226
+ y: \u540D\u524D\u306Ey,
15227
+ fontSize: \u540D\u524D\u306E\u5B9F\u5B57,
14935
15228
  fontWeight: 700,
14936
15229
  textAnchor: "middle",
14937
15230
  fill: "var(--cdl-node-fill, #ffffff)",
14938
15231
  children: s.title
14939
15232
  }
14940
15233
  ),
15234
+ \u88DC\u8DB3\u3042\u308A && /* @__PURE__ */ jsxRuntime.jsx(
15235
+ "text",
15236
+ {
15237
+ "data-cdl-role": "funnel-stage-subtitle",
15238
+ x: cx,
15239
+ y: \u88DC\u8DB3\u306Ey,
15240
+ fontSize: \u88DC\u8DB3\u306E\u5B9F\u5B57,
15241
+ fontWeight: 500,
15242
+ letterSpacing: 0,
15243
+ textAnchor: "middle",
15244
+ fill: "var(--cdl-node-fill, #ffffff)",
15245
+ fillOpacity: 0.82,
15246
+ children: \u88DC\u8DB3
15247
+ }
15248
+ ),
14941
15249
  \u6BB5\u304C\u51FA\u5207\u3063\u305F(idx) && /* @__PURE__ */ jsxRuntime.jsx(
14942
15250
  "text",
14943
15251
  {
@@ -14991,6 +15299,9 @@ var TONE_ORDER = [
14991
15299
  function toneByIndex(idx) {
14992
15300
  return TONE_ORDER[idx % TONE_ORDER.length];
14993
15301
  }
15302
+ function \u7573\u3093\u3060\u6587(\u4EF6\u6570) {
15303
+ return `\u307B\u304B ${\u4EF6\u6570} \u4EF6`;
15304
+ }
14994
15305
  function QuadrantNode({
14995
15306
  node,
14996
15307
  active,
@@ -15008,7 +15319,13 @@ function QuadrantNode({
15008
15319
  const ITEM_FONT = 13;
15009
15320
  const ITEM_PAD_X = 12;
15010
15321
  const ITEM_MIN_W = 48;
15011
- const axisLabelPad = (text) => Math.max(PAD_MIN, measureTextWidth(`\u2190 ${text}`, { fontSize: AXIS_LABEL_FONT}) + 12);
15322
+ const POINT_R = 5;
15323
+ const POINT_GAP = 6;
15324
+ const SUB_FONT = 10;
15325
+ const axisLabelPad = (text) => Math.max(
15326
+ PAD_MIN,
15327
+ measureTextWidth(`\u2190 ${text}`, { fontSize: AXIS_LABEL_FONT}) + 12
15328
+ );
15012
15329
  const padBudget = Math.max(0, node.w * 0.5 - PAD_MIN * 2);
15013
15330
  const wantLeft = axisLabelPad(data.xAxis.left) - PAD_MIN;
15014
15331
  const wantRight = axisLabelPad(data.xAxis.right) - PAD_MIN;
@@ -15022,11 +15339,13 @@ function QuadrantNode({
15022
15339
  const cy = PAD_TOP2 + canvasH / 2;
15023
15340
  const halfW = canvasW / 2;
15024
15341
  const halfH = canvasH / 2;
15342
+ const \u70B9\u3067\u7F6E\u304F = data.items.filter((i) => i.at !== void 0);
15343
+ const \u7A4D\u3080 = data.items.filter((i) => i.at === void 0);
15025
15344
  const itemsBy = {
15026
- topLeft: data.items.filter((i) => i.quadrant === "topLeft"),
15027
- topRight: data.items.filter((i) => i.quadrant === "topRight"),
15028
- bottomLeft: data.items.filter((i) => i.quadrant === "bottomLeft"),
15029
- bottomRight: data.items.filter((i) => i.quadrant === "bottomRight")
15345
+ topLeft: \u7A4D\u3080.filter((i) => i.quadrant === "topLeft"),
15346
+ topRight: \u7A4D\u3080.filter((i) => i.quadrant === "topRight"),
15347
+ bottomLeft: \u7A4D\u3080.filter((i) => i.quadrant === "bottomLeft"),
15348
+ bottomRight: \u7A4D\u3080.filter((i) => i.quadrant === "bottomRight")
15030
15349
  };
15031
15350
  const quadrantColor = {
15032
15351
  topLeft: toneFill("success", 0.06),
@@ -15055,10 +15374,50 @@ function QuadrantNode({
15055
15374
  strokeWidth: active ? 3 : 1.25
15056
15375
  }
15057
15376
  ),
15058
- /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "quadrant-bg", x: PAD_LEFT2, y: PAD_TOP2, width: halfW, height: halfH, ...quadrantColor.topLeft }),
15059
- /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "quadrant-bg", x: cx, y: PAD_TOP2, width: halfW, height: halfH, ...quadrantColor.topRight }),
15060
- /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "quadrant-bg", x: PAD_LEFT2, y: cy, width: halfW, height: halfH, ...quadrantColor.bottomLeft }),
15061
- /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "quadrant-bg", x: cx, y: cy, width: halfW, height: halfH, ...quadrantColor.bottomRight }),
15377
+ /* @__PURE__ */ jsxRuntime.jsx(
15378
+ "rect",
15379
+ {
15380
+ "data-cdl-role": "quadrant-bg",
15381
+ x: PAD_LEFT2,
15382
+ y: PAD_TOP2,
15383
+ width: halfW,
15384
+ height: halfH,
15385
+ ...quadrantColor.topLeft
15386
+ }
15387
+ ),
15388
+ /* @__PURE__ */ jsxRuntime.jsx(
15389
+ "rect",
15390
+ {
15391
+ "data-cdl-role": "quadrant-bg",
15392
+ x: cx,
15393
+ y: PAD_TOP2,
15394
+ width: halfW,
15395
+ height: halfH,
15396
+ ...quadrantColor.topRight
15397
+ }
15398
+ ),
15399
+ /* @__PURE__ */ jsxRuntime.jsx(
15400
+ "rect",
15401
+ {
15402
+ "data-cdl-role": "quadrant-bg",
15403
+ x: PAD_LEFT2,
15404
+ y: cy,
15405
+ width: halfW,
15406
+ height: halfH,
15407
+ ...quadrantColor.bottomLeft
15408
+ }
15409
+ ),
15410
+ /* @__PURE__ */ jsxRuntime.jsx(
15411
+ "rect",
15412
+ {
15413
+ "data-cdl-role": "quadrant-bg",
15414
+ x: cx,
15415
+ y: cy,
15416
+ width: halfW,
15417
+ height: halfH,
15418
+ ...quadrantColor.bottomRight
15419
+ }
15420
+ ),
15062
15421
  /* @__PURE__ */ jsxRuntime.jsx(
15063
15422
  "rect",
15064
15423
  {
@@ -15073,28 +15432,136 @@ function QuadrantNode({
15073
15432
  rx: 8
15074
15433
  }
15075
15434
  ),
15076
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: cx, y1: PAD_TOP2, x2: cx, y2: PAD_TOP2 + canvasH, stroke: "var(--cdl-text-mute, #8a8678)", strokeWidth: 1.5 }),
15077
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: PAD_LEFT2, y1: cy, x2: PAD_LEFT2 + canvasW, y2: cy, stroke: "var(--cdl-text-mute, #8a8678)", strokeWidth: 1.5 }),
15078
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: PAD_LEFT2 + halfW / 2, y: PAD_TOP2 + 22, fontSize: 13, fontWeight: 700, textAnchor: "middle", fill: quadrantAccent.topLeft, children: data.quadrantLabels.topLeft }),
15079
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx + halfW / 2, y: PAD_TOP2 + 22, fontSize: 13, fontWeight: 700, textAnchor: "middle", fill: quadrantAccent.topRight, children: data.quadrantLabels.topRight }),
15080
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: PAD_LEFT2 + halfW / 2, y: PAD_TOP2 + canvasH - 12, fontSize: 13, fontWeight: 700, textAnchor: "middle", fill: quadrantAccent.bottomLeft, children: data.quadrantLabels.bottomLeft }),
15081
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx + halfW / 2, y: PAD_TOP2 + canvasH - 12, fontSize: 13, fontWeight: 700, textAnchor: "middle", fill: quadrantAccent.bottomRight, children: data.quadrantLabels.bottomRight }),
15082
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: cx, y: PAD_TOP2 - 12, fontSize: 12, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: [
15083
- "\u2191 ",
15084
- data.yAxis.top
15085
- ] }),
15086
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: cx, y: PAD_TOP2 + canvasH + 24, fontSize: 12, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: [
15087
- "\u2193 ",
15088
- data.yAxis.bottom
15089
- ] }),
15090
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: PAD_LEFT2 - 12, y: cy + 4, fontSize: AXIS_LABEL_FONT, fontWeight: 700, textAnchor: "end", fill: "var(--cdl-text-dim, #5a6270)", children: [
15091
- "\u2190 ",
15092
- data.xAxis.left
15093
- ] }),
15094
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: PAD_LEFT2 + canvasW + 12, y: cy + 4, fontSize: AXIS_LABEL_FONT, fontWeight: 700, textAnchor: "start", fill: "var(--cdl-text-dim, #5a6270)", children: [
15095
- data.xAxis.right,
15096
- " \u2192"
15097
- ] }),
15435
+ /* @__PURE__ */ jsxRuntime.jsx(
15436
+ "line",
15437
+ {
15438
+ x1: cx,
15439
+ y1: PAD_TOP2,
15440
+ x2: cx,
15441
+ y2: PAD_TOP2 + canvasH,
15442
+ stroke: "var(--cdl-text-mute, #8a8678)",
15443
+ strokeWidth: 1.5
15444
+ }
15445
+ ),
15446
+ /* @__PURE__ */ jsxRuntime.jsx(
15447
+ "line",
15448
+ {
15449
+ x1: PAD_LEFT2,
15450
+ y1: cy,
15451
+ x2: PAD_LEFT2 + canvasW,
15452
+ y2: cy,
15453
+ stroke: "var(--cdl-text-mute, #8a8678)",
15454
+ strokeWidth: 1.5
15455
+ }
15456
+ ),
15457
+ /* @__PURE__ */ jsxRuntime.jsx(
15458
+ "text",
15459
+ {
15460
+ x: PAD_LEFT2 + halfW / 2,
15461
+ y: PAD_TOP2 + 22,
15462
+ fontSize: 13,
15463
+ fontWeight: 700,
15464
+ textAnchor: "middle",
15465
+ fill: quadrantAccent.topLeft,
15466
+ children: data.quadrantLabels.topLeft
15467
+ }
15468
+ ),
15469
+ /* @__PURE__ */ jsxRuntime.jsx(
15470
+ "text",
15471
+ {
15472
+ x: cx + halfW / 2,
15473
+ y: PAD_TOP2 + 22,
15474
+ fontSize: 13,
15475
+ fontWeight: 700,
15476
+ textAnchor: "middle",
15477
+ fill: quadrantAccent.topRight,
15478
+ children: data.quadrantLabels.topRight
15479
+ }
15480
+ ),
15481
+ /* @__PURE__ */ jsxRuntime.jsx(
15482
+ "text",
15483
+ {
15484
+ x: PAD_LEFT2 + halfW / 2,
15485
+ y: PAD_TOP2 + canvasH - 12,
15486
+ fontSize: 13,
15487
+ fontWeight: 700,
15488
+ textAnchor: "middle",
15489
+ fill: quadrantAccent.bottomLeft,
15490
+ children: data.quadrantLabels.bottomLeft
15491
+ }
15492
+ ),
15493
+ /* @__PURE__ */ jsxRuntime.jsx(
15494
+ "text",
15495
+ {
15496
+ x: cx + halfW / 2,
15497
+ y: PAD_TOP2 + canvasH - 12,
15498
+ fontSize: 13,
15499
+ fontWeight: 700,
15500
+ textAnchor: "middle",
15501
+ fill: quadrantAccent.bottomRight,
15502
+ children: data.quadrantLabels.bottomRight
15503
+ }
15504
+ ),
15505
+ /* @__PURE__ */ jsxRuntime.jsxs(
15506
+ "text",
15507
+ {
15508
+ x: cx,
15509
+ y: PAD_TOP2 - 12,
15510
+ fontSize: 12,
15511
+ fontWeight: 700,
15512
+ textAnchor: "middle",
15513
+ fill: "var(--cdl-text-dim, #5a6270)",
15514
+ children: [
15515
+ "\u2191 ",
15516
+ data.yAxis.top
15517
+ ]
15518
+ }
15519
+ ),
15520
+ /* @__PURE__ */ jsxRuntime.jsxs(
15521
+ "text",
15522
+ {
15523
+ x: cx,
15524
+ y: PAD_TOP2 + canvasH + 24,
15525
+ fontSize: 12,
15526
+ fontWeight: 700,
15527
+ textAnchor: "middle",
15528
+ fill: "var(--cdl-text-dim, #5a6270)",
15529
+ children: [
15530
+ "\u2193 ",
15531
+ data.yAxis.bottom
15532
+ ]
15533
+ }
15534
+ ),
15535
+ /* @__PURE__ */ jsxRuntime.jsxs(
15536
+ "text",
15537
+ {
15538
+ x: PAD_LEFT2 - 12,
15539
+ y: cy + 4,
15540
+ fontSize: AXIS_LABEL_FONT,
15541
+ fontWeight: 700,
15542
+ textAnchor: "end",
15543
+ fill: "var(--cdl-text-dim, #5a6270)",
15544
+ children: [
15545
+ "\u2190 ",
15546
+ data.xAxis.left
15547
+ ]
15548
+ }
15549
+ ),
15550
+ /* @__PURE__ */ jsxRuntime.jsxs(
15551
+ "text",
15552
+ {
15553
+ x: PAD_LEFT2 + canvasW + 12,
15554
+ y: cy + 4,
15555
+ fontSize: AXIS_LABEL_FONT,
15556
+ fontWeight: 700,
15557
+ textAnchor: "start",
15558
+ fill: "var(--cdl-text-dim, #5a6270)",
15559
+ children: [
15560
+ data.xAxis.right,
15561
+ " \u2192"
15562
+ ]
15563
+ }
15564
+ ),
15098
15565
  Object.keys(itemsBy).map((q) => {
15099
15566
  const items = itemsBy[q];
15100
15567
  if (items.length === 0) return null;
@@ -15105,35 +15572,169 @@ function QuadrantNode({
15105
15572
  const qHalfW = halfW - 36;
15106
15573
  const \u67A0\u306E\u4F59\u5730 = qHalfW;
15107
15574
  if (\u67A0\u306E\u4F59\u5730 <= 0) return null;
15108
- const \u67A0\u306E\u5E45 = (title) => Math.min(
15575
+ const \u67A0\u306E\u5E45 = (\u884C\u30892) => Math.min(
15109
15576
  \u67A0\u306E\u4F59\u5730,
15110
- Math.max(ITEM_MIN_W, measureTextWidth(title, { fontSize: ITEM_FONT}) + ITEM_PAD_X * 2)
15577
+ Math.max(
15578
+ ITEM_MIN_W,
15579
+ Math.max(
15580
+ ...\u884C\u30892.map(
15581
+ (r) => measureTextWidth(r.text, { fontSize: r.size, fontWeight: r.weight })
15582
+ )
15583
+ ) + ITEM_PAD_X * 2
15584
+ )
15111
15585
  );
15586
+ const \u884C\u3089 = (it) => {
15587
+ const \u88DC\u8DB3 = (it.subtitle ?? "").trim();
15588
+ return [
15589
+ { text: it.title, size: ITEM_FONT, weight: 600 },
15590
+ ...\u88DC\u8DB3 === "" ? [] : [{ text: \u88DC\u8DB3, size: SUB_FONT, weight: 500 }]
15591
+ ];
15592
+ };
15112
15593
  const qHalfH = halfH - 60;
15113
15594
  const gap = 10;
15114
15595
  const rowH = 34;
15115
15596
  const maxRows = Math.max(1, Math.floor(qHalfH / (rowH + gap)));
15116
- return items.slice(0, maxRows).map((it, idx) => {
15117
- const py = qyStart + idx * (rowH + gap);
15118
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
15119
- /* @__PURE__ */ jsxRuntime.jsx(
15120
- "rect",
15121
- {
15122
- "data-cdl-role": "quadrant-item",
15123
- "data-cdl-unresolved": it.unresolved ? "true" : void 0,
15124
- x: qxStart,
15125
- y: py,
15126
- width: \u67A0\u306E\u5E45(it.title),
15127
- height: rowH,
15128
- rx: 6,
15129
- fill: "var(--cdl-node-fill, #ffffff)",
15130
- stroke: quadrantAccent[q],
15131
- strokeWidth: 1.5
15132
- }
15133
- ),
15134
- /* @__PURE__ */ jsxRuntime.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 })
15135
- ] }, `item-${it.id}`);
15136
- });
15597
+ const \u7573\u3080 = items.length > maxRows;
15598
+ const \u540D\u524D\u3092\u51FA\u3059 = \u7573\u3080 ? items.slice(0, maxRows - 1) : items;
15599
+ const \u7573\u3093\u3060\u4EF6\u6570 = items.length - \u540D\u524D\u3092\u51FA\u3059.length;
15600
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
15601
+ \u540D\u524D\u3092\u51FA\u3059.map((it, idx) => {
15602
+ const py = qyStart + idx * (rowH + gap);
15603
+ const \u5E45 = \u67A0\u306E\u5E45(\u884C\u3089(it));
15604
+ const \u88DC\u8DB3 = (it.subtitle ?? "").trim();
15605
+ const \u88DC\u8DB3\u306E\u5B57 = SUB_FONT * \u53CE\u3081\u308B\u500D\u7387(
15606
+ \u88DC\u8DB3,
15607
+ { fontSize: SUB_FONT, fontWeight: 500 },
15608
+ Math.max(0, \u5E45 - ITEM_PAD_X * 2)
15609
+ );
15610
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
15611
+ /* @__PURE__ */ jsxRuntime.jsx(
15612
+ "rect",
15613
+ {
15614
+ "data-cdl-role": "quadrant-item",
15615
+ "data-cdl-unresolved": it.unresolved ? "true" : void 0,
15616
+ x: qxStart,
15617
+ y: py,
15618
+ width: \u5E45,
15619
+ height: rowH,
15620
+ rx: 6,
15621
+ fill: "var(--cdl-node-fill, #ffffff)",
15622
+ stroke: quadrantAccent[q],
15623
+ strokeWidth: 1.5
15624
+ }
15625
+ ),
15626
+ /* @__PURE__ */ jsxRuntime.jsx(
15627
+ "text",
15628
+ {
15629
+ x: qxStart + ITEM_PAD_X,
15630
+ y: \u88DC\u8DB3 === "" ? py + rowH / 2 + 5 : py + rowH / 2 - 2,
15631
+ fontSize: ITEM_FONT,
15632
+ fontWeight: 600,
15633
+ letterSpacing: 0,
15634
+ fill: "var(--cdl-text, #1a1f2a)",
15635
+ children: it.title
15636
+ }
15637
+ ),
15638
+ \u88DC\u8DB3 !== "" && /* @__PURE__ */ jsxRuntime.jsx(
15639
+ "text",
15640
+ {
15641
+ "data-cdl-role": "quadrant-item-subtitle",
15642
+ x: qxStart + ITEM_PAD_X,
15643
+ y: py + rowH / 2 + 11,
15644
+ fontSize: \u88DC\u8DB3\u306E\u5B57,
15645
+ fontWeight: 500,
15646
+ letterSpacing: 0,
15647
+ fill: "var(--cdl-text-dim, #5a6270)",
15648
+ children: \u88DC\u8DB3
15649
+ }
15650
+ )
15651
+ ] }, `item-${it.id}`);
15652
+ }),
15653
+ \u7573\u3080 ? (
15654
+ /*
15655
+ 畳んだ段は名前の段と見た目を分ける。 同じにすると「ほか 3 件」 という名前の
15656
+ 項目があるように読める。 枠を持たず、点線の下線と薄い字で「続きがある」 ことを表す。
15657
+ */
15658
+ /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
15659
+ /* @__PURE__ */ jsxRuntime.jsx(
15660
+ "line",
15661
+ {
15662
+ "data-cdl-role": "quadrant-more-rule",
15663
+ x1: qxStart,
15664
+ y1: qyStart + \u540D\u524D\u3092\u51FA\u3059.length * (rowH + gap) + rowH / 2 + 9,
15665
+ x2: qxStart + \u67A0\u306E\u5E45([{ text: \u7573\u3093\u3060\u6587(\u7573\u3093\u3060\u4EF6\u6570), size: ITEM_FONT, weight: 600 }]),
15666
+ y2: qyStart + \u540D\u524D\u3092\u51FA\u3059.length * (rowH + gap) + rowH / 2 + 9,
15667
+ stroke: quadrantAccent[q],
15668
+ strokeWidth: 1,
15669
+ strokeDasharray: "3 3",
15670
+ strokeOpacity: 0.6
15671
+ }
15672
+ ),
15673
+ /* @__PURE__ */ jsxRuntime.jsx(
15674
+ "text",
15675
+ {
15676
+ "data-cdl-role": "quadrant-more",
15677
+ x: qxStart + ITEM_PAD_X,
15678
+ y: qyStart + \u540D\u524D\u3092\u51FA\u3059.length * (rowH + gap) + rowH / 2 + 5,
15679
+ fontSize: ITEM_FONT,
15680
+ fontWeight: 600,
15681
+ letterSpacing: 0,
15682
+ fill: quadrantAccent[q],
15683
+ children: \u7573\u3093\u3060\u6587(\u7573\u3093\u3060\u4EF6\u6570)
15684
+ }
15685
+ )
15686
+ ] }, `more-${q}`)
15687
+ ) : null
15688
+ ] }, `q-${q}`);
15689
+ }),
15690
+ \u70B9\u3067\u7F6E\u304F.map((it) => {
15691
+ const at = it.at;
15692
+ const px = PAD_LEFT2 + at.x * canvasW;
15693
+ const py = PAD_TOP2 + (1 - at.y) * canvasH;
15694
+ const \u53F3\u5BC4\u308A = at.x >= 0.5;
15695
+ const \u540D\u524D\u306Ex = px + (\u53F3\u5BC4\u308A ? -11 : POINT_R + POINT_GAP);
15696
+ const \u5BC4\u305B = \u53F3\u5BC4\u308A ? "end" : "start";
15697
+ const \u88DC\u8DB3 = (it.subtitle ?? "").trim();
15698
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-unresolved": it.unresolved ? "true" : void 0, children: [
15699
+ /* @__PURE__ */ jsxRuntime.jsx(
15700
+ "circle",
15701
+ {
15702
+ "data-cdl-role": "quadrant-point",
15703
+ cx: px,
15704
+ cy: py,
15705
+ r: POINT_R,
15706
+ fill: quadrantAccent[it.quadrant]
15707
+ }
15708
+ ),
15709
+ /* @__PURE__ */ jsxRuntime.jsx(
15710
+ "text",
15711
+ {
15712
+ "data-cdl-role": "quadrant-point-label",
15713
+ x: \u540D\u524D\u306Ex,
15714
+ y: \u88DC\u8DB3 === "" ? py + 4 : py - 1,
15715
+ fontSize: ITEM_FONT,
15716
+ fontWeight: 600,
15717
+ letterSpacing: 0,
15718
+ textAnchor: \u5BC4\u305B,
15719
+ fill: "var(--cdl-text, #1a1f2a)",
15720
+ children: it.title
15721
+ }
15722
+ ),
15723
+ \u88DC\u8DB3 !== "" && /* @__PURE__ */ jsxRuntime.jsx(
15724
+ "text",
15725
+ {
15726
+ "data-cdl-role": "quadrant-point-subtitle",
15727
+ x: \u540D\u524D\u306Ex,
15728
+ y: py + 11,
15729
+ fontSize: SUB_FONT,
15730
+ fontWeight: 500,
15731
+ letterSpacing: 0,
15732
+ textAnchor: \u5BC4\u305B,
15733
+ fill: "var(--cdl-text-dim, #5a6270)",
15734
+ children: \u88DC\u8DB3
15735
+ }
15736
+ )
15737
+ ] }, `at-${it.id}`);
15137
15738
  })
15138
15739
  ] });
15139
15740
  }
@@ -16026,12 +16627,13 @@ function ShapeTerminalNode({ node, active, lang }) {
16026
16627
  const \u5148\u982D = 26;
16027
16628
  const \u884C\u9593 = 22;
16028
16629
  const \u30AB\u30FC\u30BD\u30EB = { \u5DE6: 30, \u5E45: 9, \u9AD8: 14, \u4E0A: 11, \u4E0B: 3 };
16630
+ const \u51FA\u529B = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.subtitle, \u5B57\u5F15("terminal.output"));
16029
16631
  const \u884C = [
16030
16632
  [
16031
16633
  { \u5DE6: 16, \u5B57: 12.5, \u8272: "#7cd88f", \u6587: "$" },
16032
16634
  { \u5DE6: 30, \u5B57: 12.5, \u8272: "#e6edf3", \u6587: "pnpm build" }
16033
16635
  ],
16034
- [{ \u5DE6: 16, \u5B57: 12.5, \u8272: "#8b95a5", \u6587: \u5B57\u5F15("terminal.output") }],
16636
+ [{ \u5DE6: 16, \u5B57: 12.5, \u8272: "#8b95a5", \u6587: \u51FA\u529B }],
16035
16637
  [{ \u5DE6: 16, \u5B57: 12.5, \u8272: "#7cd88f", \u6587: "$" }]
16036
16638
  ];
16037
16639
  const \u81EA\u7136\u5E45 = Math.max(...\u884C.flat().map((c) => c.\u5DE6 + \u7B49\u5E45\u306E\u6841(c.\u6587) * MONO_ADVANCE * c.\u5B57)) + \u4F59\u767D;
@@ -16153,7 +16755,9 @@ function ShapeCodeBlockNode({ node, active, lang }) {
16153
16755
  const w = Math.max(0, node.w - \u7DDA * 2);
16154
16756
  const bodyH = Math.max(0, node.h - 42 - \u7DDA * 2);
16155
16757
  const lineFont = "ui-monospace, SFMono-Regular, Menlo, monospace";
16156
- const \u30BF\u30D6\u5E45 = 100;
16758
+ const \u672D = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.subtitle, \u5B57\u5F15("codeBlock.fileName"));
16759
+ const \u672D\u306E\u5B57 = 11;
16760
+ const \u30BF\u30D6\u5E45 = Math.min(Math.max(100, textWidth(\u672D, \u672D\u306E\u5B57, 0) + 24), Math.max(0, w));
16157
16761
  const \u30BF\u30D6\u9AD8 = 24;
16158
16762
  const \u89D2 = 10;
16159
16763
  const \u6E9D = 32;
@@ -16190,7 +16794,7 @@ function ShapeCodeBlockNode({ node, active, lang }) {
16190
16794
  const \u81EA\u7136\u9AD8 = \u30BF\u30D6\u9AD8 + \u884C\u982D + \u884C\u9593 * (lines.length - 1) + Math.max(\u592A\u3055 - \u6301\u3061\u4E0A\u3052, \u884C\u756A\u53F7\u306E\u5B57 * DESCENT3);
16191
16795
  const \u500D = Math.min(1, bodyH / \u81EA\u7136\u9AD8);
16192
16796
  const \u6253\u3061\u6D88\u3059\u5B57\u3089 = [
16193
- { text: \u5B57\u5F15("codeBlock.fileName"), size: 11, \u5E2F: { \u5E45: \u30BF\u30D6\u5E45, \u9AD8\u3055: \u30BF\u30D6\u9AD8 } },
16797
+ { text: \u672D, size: \u672D\u306E\u5B57, \u5E2F: { \u5E45: \u30BF\u30D6\u5E45, \u9AD8\u3055: \u30BF\u30D6\u9AD8 } },
16194
16798
  { text: "1", size: \u884C\u756A\u53F7\u306E\u5B57, \u5E2F: { \u5E45: \u6E9D - \u6301\u3061\u4E0A\u3052, \u9AD8\u3055: \u884C\u9593 } }
16195
16799
  ];
16196
16800
  const \u500D\u8FD4\u3057 = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D, \u6253\u3061\u6D88\u3059\u5B57\u3089);
@@ -16232,11 +16836,11 @@ function ShapeCodeBlockNode({ node, active, lang }) {
16232
16836
  "data-cdl-counter-scaled": "1",
16233
16837
  x: x + tabW / 2,
16234
16838
  y: y + tabH / 2 + 4 * \u500D,
16235
- fontSize: 11 * \u500D * \u500D\u8FD4\u3057,
16839
+ fontSize: \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057 * \u5E45\u306E\u500D\u7387(\u672D, \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057, 0, tabW),
16236
16840
  fontFamily: lineFont,
16237
16841
  textAnchor: "middle",
16238
16842
  fill: "#e6edf3",
16239
- children: \u5B57\u5F15("codeBlock.fileName")
16843
+ children: \u672D
16240
16844
  }
16241
16845
  ),
16242
16846
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x + tabW - \u4E38, cy: y + tabH / 2, r: 3 * \u500D, fill: "#7cd88f", stroke: "none" }),
@@ -16336,6 +16940,7 @@ function ShapeKanbanCardNode({ node, active, lang }) {
16336
16940
  const PILL\u9AD8 = 16;
16337
16941
  const PILL\u5B57 = 11;
16338
16942
  const PILL\u5B57\u9593 = 0;
16943
+ const PILL\u5B57\u5E45 = PILL\u5E45 - 6;
16339
16944
  const FOOTER\u4E0B = 22;
16340
16945
  const AVATAR\u4E2D\u5FC3Y = 4;
16341
16946
  const AVATAR\u534A\u5F84 = 9;
@@ -16365,6 +16970,11 @@ function ShapeKanbanCardNode({ node, active, lang }) {
16365
16970
  \u4E0B: size * \u8AAC\u660E\u57FA\u6E96\u6BD4 + size * \u8AAC\u660E\u5B57\u6BD4 * DESCENT3
16366
16971
  })
16367
16972
  );
16973
+ const \u8AAC\u660E = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.subtitle, \u5B57\u5F15("kanbanCard.task"));
16974
+ const \u72B6\u614B = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.eyebrow, \u5B57\u5F15("kanbanCard.status"));
16975
+ const \u72B6\u614B\u306E\u500D\u7387 = \u5E45\u306E\u500D\u7387(\u72B6\u614B, PILL\u5B57, PILL\u5B57\u9593, PILL\u5B57\u5E45);
16976
+ const \u8AAC\u660E\u306E\u5B57 = \u540D\u524D.size * \u8AAC\u660E\u5B57\u6BD4;
16977
+ const \u4F7F\u3048\u308B\u5E452 = Math.max(0, w - \u5DE6\u53F3\u4F59\u767D * \u500D * 2);
16368
16978
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
16369
16979
  /* @__PURE__ */ jsxRuntime.jsx(
16370
16980
  "rect",
@@ -16419,15 +17029,16 @@ function ShapeKanbanCardNode({ node, active, lang }) {
16419
17029
  /* @__PURE__ */ jsxRuntime.jsx(
16420
17030
  "text",
16421
17031
  {
17032
+ "data-cdl-role": "kanban-status",
16422
17033
  x: x + w - (\u5DE6\u53F3\u4F59\u767D + PILL\u5E45 / 2) * \u500D,
16423
17034
  y: pillY + 12 * \u500D,
16424
- fontSize: PILL\u5B57 * \u500D,
17035
+ fontSize: PILL\u5B57 * \u500D * \u72B6\u614B\u306E\u500D\u7387,
16425
17036
  fontWeight: 700,
16426
- letterSpacing: PILL\u5B57\u9593 * \u500D,
17037
+ letterSpacing: PILL\u5B57\u9593 * \u500D * \u72B6\u614B\u306E\u500D\u7387,
16427
17038
  textAnchor: "middle",
16428
17039
  fill: "#5a4a1a",
16429
17040
  fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
16430
- children: \u5B57\u5F15("kanbanCard.status")
17041
+ children: \u72B6\u614B
16431
17042
  }
16432
17043
  ),
16433
17044
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -16448,10 +17059,10 @@ function ShapeKanbanCardNode({ node, active, lang }) {
16448
17059
  {
16449
17060
  x: x + w / 2,
16450
17061
  y: \u540D\u524D.y + \u540D\u524D.size * \u8AAC\u660E\u57FA\u6E96\u6BD4,
16451
- fontSize: \u540D\u524D.size * \u8AAC\u660E\u5B57\u6BD4,
17062
+ fontSize: \u8AAC\u660E\u306E\u5B57 * \u5E45\u306E\u500D\u7387(\u8AAC\u660E, \u8AAC\u660E\u306E\u5B57, 0, \u4F7F\u3048\u308B\u5E452),
16452
17063
  textAnchor: "middle",
16453
17064
  fill: "var(--cdl-text-dim, #5a6270)",
16454
- children: \u5B57\u5F15("kanbanCard.task")
17065
+ children: \u8AAC\u660E
16455
17066
  }
16456
17067
  ),
16457
17068
  /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x + \u5DE6\u53F3\u4F59\u767D * \u500D}, ${footY})`, children: [
@@ -17469,6 +18080,7 @@ var SMART_CONTRACT_H = 220;
17469
18080
  var BLOCK_W = 240;
17470
18081
  var BLOCK_H = 220;
17471
18082
  var \u898B\u51FA\u3057\u306E\u5B57 = 13;
18083
+ var \u80A9\u66F8\u306E\u5B57 = 10;
17472
18084
  var \u540D\u306E\u5B57 = 11;
17473
18085
  var \u5024\u306E\u5B57 = 11;
17474
18086
  var \u884C\u306E\u9593\u9694 = 22;
@@ -17544,11 +18156,6 @@ function blockchainNodeExtent(strokeWidth) {
17544
18156
  const \u6A2A = (NODE_PEER_DIST + NODE_PEER_R) * Math.cos(Math.PI / 6) + \u7DDA;
17545
18157
  return { \u4E0A: \u7E26, \u4E0B: \u7E26, \u5DE6: \u6A2A, \u53F3: \u6A2A };
17546
18158
  }
17547
- function \u5E45\u306E\u500D\u7387(text, size, letterSpacing, \u5E45) {
17548
- if (!(\u5E45 > 0) || !(size > 0)) return 1;
17549
- const \u5B9F\u5E45 = textWidth(text, size, letterSpacing);
17550
- return \u5B9F\u5E45 > \u5E45 ? \u5E45 / \u5B9F\u5E45 : 1;
17551
- }
17552
18159
  function bottomLabel2(node, cx, plan) {
17553
18160
  const \u80A9\u66F8\u500D\u7387 = node.eyebrow && plan.\u80A9\u66F8 ? \u5E45\u306E\u500D\u7387(node.eyebrow, plan.\u80A9\u66F8.size, 2, node.w) : 1;
17554
18161
  const \u540D\u524D\u500D\u7387 = \u5E45\u306E\u500D\u7387(node.title, plan.\u540D\u524D.size, 0, node.w);
@@ -17666,9 +18273,18 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
17666
18273
  value: f.key === "hash" ? \u6E21\u3055\u308C\u305F(node.subtitle) || \u65E2\u5B9A\u5024 : \u65E2\u5B9A\u5024
17667
18274
  };
17668
18275
  });
17669
- const \u898B\u51FA\u3057\u306E\u5E45 = bw - 14 - 30;
18276
+ const \u80A9\u66F8 = \u6E21\u3055\u308C\u305F(node.eyebrow);
18277
+ const \u5E2F\u306E\u6B8B\u308A = bw - 14 - 30;
18278
+ const \u80A9\u66F8\u306E\u9699\u9593 = 8;
18279
+ const \u80A9\u66F8\u306E\u4E0A\u9650 = (\u5E2F\u306E\u6B8B\u308A - \u80A9\u66F8\u306E\u9699\u9593) / 2;
18280
+ const \u80A9\u66F8\u306E\u500D\u7387 = \u80A9\u66F8 === "" ? 1 : \u5E45\u306E\u500D\u7387(\u80A9\u66F8, \u80A9\u66F8\u306E\u5B57, 0, \u80A9\u66F8\u306E\u4E0A\u9650);
18281
+ const \u80A9\u66F8\u306E\u6307\u5B9A = \u80A9\u66F8\u306E\u5B57 * \u80A9\u66F8\u306E\u500D\u7387;
18282
+ const \u80A9\u66F8\u306E\u5E45 = \u80A9\u66F8 === "" ? 0 : \u5B57\u306E\u5E45(\u80A9\u66F8, \u80A9\u66F8\u306E\u6307\u5B9A);
18283
+ const \u898B\u51FA\u3057\u306E\u5E45 = \u5E2F\u306E\u6B8B\u308A - (\u80A9\u66F8 === "" ? 0 : \u80A9\u66F8\u306E\u5E45 + \u80A9\u66F8\u306E\u9699\u9593);
17670
18284
  const \u6253\u3061\u6D88\u3059\u5B57\u3089 = [
17671
18285
  { text: \u898B\u51FA\u3057, size: \u898B\u51FA\u3057\u306E\u5B57, \u5E2F: { \u5E45: \u898B\u51FA\u3057\u306E\u5E45, \u9AD8\u3055: \u898B\u51FA\u3057\u306E\u5E2F } },
18286
+ // 肩書も帯に入れる = 入れないと打ち消しの倍率が肩書を見ずに決まり、帯から横へ出る
18287
+ ...\u80A9\u66F8 === "" ? [] : [{ text: \u80A9\u66F8, size: \u80A9\u66F8\u306E\u6307\u5B9A, \u5E2F: { \u5E45: \u80A9\u66F8\u306E\u5E45, \u9AD8\u3055: \u898B\u51FA\u3057\u306E\u5E2F } }],
17672
18288
  ...fields.flatMap((f) => [
17673
18289
  { text: f.label, size: \u540D\u306E\u5B57, \u5E2F: { \u5E45: bw - 28, \u9AD8\u3055: \u884C\u306E\u9593\u9694 } },
17674
18290
  {
@@ -17681,6 +18297,7 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
17681
18297
  const art = (\u500D\u7387) => {
17682
18298
  const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
17683
18299
  const \u984C\u306E\u5927\u304D\u3055 = \u898B\u51FA\u3057\u306E\u5B57 * \u500D;
18300
+ const \u80A9\u66F8\u306E\u5927\u304D\u3055 = \u80A9\u66F8\u306E\u6307\u5B9A * \u500D;
17684
18301
  const \u540D\u306E\u5927\u304D\u3055 = \u540D\u306E\u5B57 * \u500D;
17685
18302
  const \u5024\u306E\u5927\u304D\u3055 = \u5024\u306E\u5B57 * \u500D;
17686
18303
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
@@ -17688,6 +18305,22 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
17688
18305
  /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "node-body", x, y, width: bw, height: bh, rx: 8, ...frame }),
17689
18306
  /* @__PURE__ */ jsxRuntime.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" }),
17690
18307
  /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "blockchain-block-title", "data-cdl-counter-scaled": "1", x: x + 14, y: y + 22, fontSize: \u984C\u306E\u5927\u304D\u3055, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "#ffffff", children: \u5E45\u3067\u5207\u308B(\u898B\u51FA\u3057, \u984C\u306E\u5927\u304D\u3055, \u898B\u51FA\u3057\u306E\u5E45, \u5B57\u306E\u5E45) }),
18308
+ \u80A9\u66F8 !== "" && /* @__PURE__ */ jsxRuntime.jsx(
18309
+ "text",
18310
+ {
18311
+ "data-cdl-role": "blockchain-block-eyebrow",
18312
+ "data-cdl-counter-scaled": "1",
18313
+ x: x + bw - 30,
18314
+ y: y + 21,
18315
+ fontSize: \u80A9\u66F8\u306E\u5927\u304D\u3055,
18316
+ fontWeight: 600,
18317
+ textAnchor: "end",
18318
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
18319
+ fill: "#ffffff",
18320
+ fillOpacity: 0.78,
18321
+ children: \u80A9\u66F8
18322
+ }
18323
+ ),
17691
18324
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x + bw - 16, cy: y + 16, r: 5.5, fill: "#7cd88f", stroke: "#ffffff", strokeWidth: 1.5 }),
17692
18325
  fields.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
17693
18326
  /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-counter-scaled": "1", x: x + 14, y: y + 54 + i * \u884C\u306E\u9593\u9694, fontSize: \u540D\u306E\u5927\u304D\u3055, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "var(--cdl-text-dim, #5a6270)", children: f.label }),
@@ -17749,7 +18382,7 @@ function ShapeBlockchainNode({ node, active }) {
17749
18382
  420 + i
17750
18383
  ] }),
17751
18384
  /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-counter-scaled": "0", x: bx + blockW / 2, y: cy + 8, fontSize: 14, fontWeight: 700, textAnchor: "middle", fill: isCurrent ? "#ffffff" : "var(--cdl-tone-accent, #2d6a8f)", fontFamily: "Georgia, serif", children: "#" }),
17752
- /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-counter-scaled": "1", x: bx + blockW / 2, y: cy + 22, fontSize: CHAIN_HASH_SIZE * \u500D, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", textAnchor: "middle", fill: isCurrent ? "#ffffff" : "var(--cdl-text-dim, #5a6270)", opacity: 0.9, children: "0x\u2026" })
18385
+ /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-ellipsis": "written", "data-cdl-counter-scaled": "1", x: bx + blockW / 2, y: cy + 22, fontSize: CHAIN_HASH_SIZE * \u500D, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", textAnchor: "middle", fill: isCurrent ? "#ffffff" : "var(--cdl-text-dim, #5a6270)", opacity: 0.9, children: "0x\u2026" })
17753
18386
  ] }, i);
17754
18387
  }) });
17755
18388
  };
@@ -18784,13 +19417,18 @@ function ShapeWarehouseNode({ node, active, lang }) {
18784
19417
  bottomLabel4(node, r.cx, r.label)
18785
19418
  ] });
18786
19419
  }
19420
+ var HANDLE_GRIP_X = 118;
19421
+ var HANDLE_GRIP_R = 4;
19422
+ var CART_SHADOW_RX = 80;
18787
19423
  function ShapeOnlineShopNode({ node, active }) {
18788
19424
  const frame = commonFrame6(active);
18789
19425
  const r = shapeRegion(node);
18790
- const cx = r.cx;
18791
19426
  const cy = r.cy + 10;
18792
19427
  const scale = Math.min(r.availW / 260, r.availH / 320);
18793
19428
  const s = scale * 0.9;
19429
+ const \u5DE6\u3078\u51FA\u308B = HANDLE_GRIP_X + HANDLE_GRIP_R;
19430
+ const \u53F3\u3078\u51FA\u308B = CART_SHADOW_RX;
19431
+ const cx = r.cx + (\u5DE6\u3078\u51FA\u308B - \u53F3\u3078\u51FA\u308B) / 2 * s;
18794
19432
  const accent = "var(--cdl-tone-accent, #2d6a8f)";
18795
19433
  const accentDark = "#1a4a68";
18796
19434
  const accentDarker = "#0f3450";
@@ -18804,9 +19442,9 @@ function ShapeOnlineShopNode({ node, active }) {
18804
19442
  const wheelL = cx - 42 * s;
18805
19443
  const wheelR = cx + 42 * s;
18806
19444
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18807
- /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx, cy: wheelY + 22 * s, rx: 80 * s, ry: 5 * s, fill: frame.stroke, opacity: 0.25, stroke: "none" }),
18808
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: `M ${cx - 118 * s} ${basketTopY - 60 * s} L ${cx - 90 * s} ${basketTopY - 60 * s} L ${cx - 80 * s} ${basketTopY - 30 * s} L ${basketTopL} ${basketTopY}`, fill: "none", stroke: accent, strokeWidth: 6 * s, strokeLinecap: "round", strokeLinejoin: "round" }),
18809
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: cx - 118 * s, cy: basketTopY - 60 * s, r: 4 * s, fill: accent, stroke: accentDark, strokeWidth: 1.5 }),
19445
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx, cy: wheelY + 22 * s, rx: CART_SHADOW_RX * s, ry: 5 * s, fill: frame.stroke, opacity: 0.25, stroke: "none" }),
19446
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: `M ${cx - HANDLE_GRIP_X * s} ${basketTopY - 60 * s} L ${cx - 90 * s} ${basketTopY - 60 * s} L ${cx - 80 * s} ${basketTopY - 30 * s} L ${basketTopL} ${basketTopY}`, fill: "none", stroke: accent, strokeWidth: 6 * s, strokeLinecap: "round", strokeLinejoin: "round" }),
19447
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: cx - HANDLE_GRIP_X * s, cy: basketTopY - 60 * s, r: HANDLE_GRIP_R * s, fill: accent, stroke: accentDark, strokeWidth: 1.5 }),
18810
19448
  /* @__PURE__ */ jsxRuntime.jsx(
18811
19449
  "path",
18812
19450
  {
@@ -19624,11 +20262,58 @@ function CdlNodeView({
19624
20262
  pointerEvents: "none"
19625
20263
  }
19626
20264
  ),
19627
- inner
20265
+ inner,
20266
+ \u7BB1\u306E\u4E0A\u306E\u8A9E(resolvedNode)
19628
20267
  ]
19629
20268
  }
19630
20269
  );
19631
20270
  }
20271
+ var FIGURE_TITLE_GAP = 10;
20272
+ var FIGURE_TITLE_SIZE = 15;
20273
+ var FIGURE_EYEBROW_SIZE = 11;
20274
+ var FIGURE_EYEBROW_LIFT = 1.1;
20275
+ function \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, \u5E45) {
20276
+ const \u5B9F\u5E45 = textWidth(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, 0);
20277
+ return \u5B9F\u5E45 > \u5E45 ? \u7D20\u306E\u5927\u304D\u3055 * \u5E45 / \u5B9F\u5E45 : \u7D20\u306E\u5927\u304D\u3055;
20278
+ }
20279
+ function \u7BB1\u306E\u4E0A\u306E\u8A9E(node) {
20280
+ if (!drawsFigureTitle(node.kind)) return null;
20281
+ const \u540D\u524D = (node.title ?? "").trim();
20282
+ const \u5C0F\u898B\u51FA\u3057 = (node.eyebrow ?? "").trim();
20283
+ if (\u540D\u524D === "" && \u5C0F\u898B\u51FA\u3057 === "") return null;
20284
+ const \u984C\u306Ey = node.cy - node.h / 2 - FIGURE_TITLE_GAP;
20285
+ const \u984C\u306E\u5927\u304D\u3055 = \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u540D\u524D, FIGURE_TITLE_SIZE, node.w);
20286
+ const \u5C0F\u898B\u51FA\u3057\u306Ey = \u540D\u524D === "" ? \u984C\u306Ey : \u984C\u306Ey - \u984C\u306E\u5927\u304D\u3055 * FIGURE_EYEBROW_LIFT;
20287
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20288
+ \u5C0F\u898B\u51FA\u3057 !== "" && /* @__PURE__ */ jsxRuntime.jsx(
20289
+ "text",
20290
+ {
20291
+ "data-cdl-role": "figure-eyebrow",
20292
+ x: node.cx,
20293
+ y: \u5C0F\u898B\u51FA\u3057\u306Ey,
20294
+ textAnchor: "middle",
20295
+ fontSize: \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u5C0F\u898B\u51FA\u3057, FIGURE_EYEBROW_SIZE, node.w),
20296
+ fontWeight: 600,
20297
+ letterSpacing: 0.6,
20298
+ fill: "var(--cdl-text-dim, #5a6270)",
20299
+ children: \u5C0F\u898B\u51FA\u3057
20300
+ }
20301
+ ),
20302
+ \u540D\u524D !== "" && /* @__PURE__ */ jsxRuntime.jsx(
20303
+ "text",
20304
+ {
20305
+ "data-cdl-role": "figure-title",
20306
+ x: node.cx,
20307
+ y: \u984C\u306Ey,
20308
+ textAnchor: "middle",
20309
+ fontSize: \u984C\u306E\u5927\u304D\u3055,
20310
+ fontWeight: 600,
20311
+ fill: "var(--cdl-text, #23201b)",
20312
+ children: \u540D\u524D
20313
+ }
20314
+ )
20315
+ ] });
20316
+ }
19632
20317
 
19633
20318
  // src/render/relation-focus.ts
19634
20319
  function relatedFocusSet(edges, nodeId) {
@@ -19641,6 +20326,11 @@ function relatedFocusSet(edges, nodeId) {
19641
20326
  }
19642
20327
  return \u96C6\u5408;
19643
20328
  }
20329
+ function \u63CF\u304F\u3082\u306E\u304C\u3042\u308B(laid) {
20330
+ if (laid.edges.length > 0) return true;
20331
+ if (laid.nodes.some((n) => isRenderedNode(n))) return true;
20332
+ return laid.lanes.some((l) => l.contain === true || l.lifeline === true || Boolean(l.label));
20333
+ }
19644
20334
  function CdlStage({
19645
20335
  laid,
19646
20336
  currentPhase,
@@ -19799,6 +20489,7 @@ function CdlStage({
19799
20489
  );
19800
20490
  }, [laid]);
19801
20491
  const diagramScale = laid.diagramScale ?? 1;
20492
+ if (!\u63CF\u304F\u3082\u306E\u304C\u3042\u308B(laid)) return null;
19802
20493
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: compact ? "px-3 py-3" : "px-6 py-6", style: compact ? void 0 : { minHeight: 460 }, children: [
19803
20494
  /* @__PURE__ */ jsxRuntime.jsxs(
19804
20495
  "svg",