@cardenelabs/cdl 0.14.0 → 0.16.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 +249 -1
  2. package/README.md +20 -1
  3. package/dist/index.cjs +1243 -92
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +27 -5
  6. package/dist/index.d.ts +27 -5
  7. package/dist/index.js +1242 -93
  8. package/dist/index.js.map +1 -1
  9. package/dist/react.cjs +1208 -88
  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 +1208 -88
  14. package/dist/react.js.map +1 -1
  15. package/dist/{render-B5JHcUrb.d.cts → render-BS1E6Mlo.d.cts} +55 -2
  16. package/dist/{render-B5JHcUrb.d.ts → render-BS1E6Mlo.d.ts} +55 -2
  17. package/package.json +1 -1
  18. package/src/builder.ts +24 -0
  19. package/src/index.ts +2 -1
  20. package/src/kinds/chart-gauge.tsx +241 -0
  21. package/src/kinds/chart-pie.tsx +214 -53
  22. package/src/kinds/chart-radial.tsx +210 -0
  23. package/src/kinds/chart-stacked-bar.tsx +272 -0
  24. package/src/kinds/chart-stat.tsx +231 -0
  25. package/src/kinds/chart-waffle.tsx +197 -0
  26. package/src/kinds/draw-ratio.ts +44 -0
  27. package/src/kinds/dyn-shape.tsx +3 -6
  28. package/src/kinds/generic.tsx +18 -6
  29. package/src/kinds/terminal-mark.tsx +96 -0
  30. package/src/layout/edges.ts +30 -1
  31. package/src/layout/self-loop.ts +217 -0
  32. package/src/layout/spec.ts +81 -4
  33. package/src/layout/tokens.ts +15 -0
  34. package/src/presets.ts +68 -4
  35. package/src/render/edge-head.ts +45 -0
  36. package/src/render/edges.tsx +4 -2
  37. package/src/render/interactive-panel.tsx +2 -2
  38. package/src/render/nodes.tsx +25 -0
  39. package/src/render/payload-binding.ts +14 -3
  40. package/src/render/stage.tsx +41 -18
  41. package/src/render/tone.ts +52 -0
  42. package/src/types.ts +66 -2
  43. package/src/validate.ts +13 -5
  44. package/src/visual-validate.ts +48 -1
package/dist/react.js CHANGED
@@ -569,12 +569,20 @@ var KINDS_WITHOUT_TITLE_TEXT = /* @__PURE__ */ new Set([
569
569
  "chart-pie",
570
570
  "chart-line",
571
571
  "chart-bar",
572
+ "chart-gauge",
573
+ "chart-radial",
574
+ "chart-stat",
575
+ "chart-waffle",
576
+ "chart-stacked-bar",
572
577
  "gantt-timeline",
573
578
  "mind-map",
574
579
  "funnel-stages",
575
580
  "quadrant-matrix",
576
581
  "tree-hierarchy",
577
- "journey-map"
582
+ "journey-map",
583
+ // 印そのものが意味を持つ (#560)
584
+ "mark-start",
585
+ "mark-end"
578
586
  ]);
579
587
  function rendersTitleText(kind) {
580
588
  return !KINDS_WITHOUT_TITLE_TEXT.has(kind ?? "");
@@ -614,19 +622,36 @@ function rendersRows(kind) {
614
622
  }
615
623
  function rowBaselineY(kind, index) {
616
624
  if (!rendersRows(kind)) return null;
617
- return kind === "storage" ? ROW_TOP_STORAGE + index * ROW_PITCH_STORAGE : ROW_TOP_GENERIC + index * ROW_PITCH_GENERIC;
625
+ return kind === "storage" ? ROW_TOP_STORAGE + index * ROW_PITCH_STORAGE : ROW_TOP_GENERIC + genericTextShift(kind) + index * ROW_PITCH_GENERIC;
626
+ }
627
+ function genericTextShift(kind) {
628
+ return KINDS_SHAPE_CYLINDER.has(kind ?? "") ? GENERIC_TEXT_SHIFT_CYLINDER : 0;
629
+ }
630
+ var KINDS_SHAPE_CYLINDER = /* @__PURE__ */ new Set(["database"]);
631
+ var KINDS_TEXT_CENTERED = /* @__PURE__ */ new Set(["cloud", "decision"]);
632
+ function genericTextCentered(kind, hasRows) {
633
+ return !hasRows && KINDS_TEXT_CENTERED.has(kind ?? "");
634
+ }
635
+ function genericTitleBaselineY(kind, h, hasRows) {
636
+ return genericTextCentered(kind, hasRows) ? h / 2 + GENERIC_TITLE_CENTER_OFFSET : GENERIC_TITLE_TOP + genericTextShift(kind);
618
637
  }
619
638
  var ROW_TOP_STORAGE = 130;
620
639
  var ROW_PITCH_STORAGE = 56;
621
640
  var ROW_TOP_GENERIC = 100;
622
641
  var ROW_PITCH_GENERIC = 28;
642
+ var GENERIC_TEXT_SHIFT_CYLINDER = 28;
643
+ var GENERIC_TITLE_TOP = 68;
644
+ var GENERIC_TITLE_CENTER_OFFSET = 4;
645
+ var GENERIC_TITLE_FONT = 20;
646
+ var GLYPH_CAP_RATIO = 0.72;
623
647
  var ROW_FONT_STORAGE = 26;
624
648
  var ROW_FONT_GENERIC = 21;
625
649
  var STORAGE_TITLE_BASELINE = 78;
626
650
  var STORAGE_ROW_DIVIDER_Y = Math.round(
627
- (STORAGE_TITLE_BASELINE + (ROW_TOP_STORAGE - ROW_FONT_STORAGE * 0.72)) / 2
651
+ (STORAGE_TITLE_BASELINE + (ROW_TOP_STORAGE - ROW_FONT_STORAGE * GLYPH_CAP_RATIO)) / 2
628
652
  );
629
653
  var ROW_GLYPH_DEPTH_RATIO = 0.4;
654
+ var TITLE_ROW_MIN_GAP = GENERIC_TITLE_FONT * ROW_GLYPH_DEPTH_RATIO + ROW_FONT_GENERIC * GLYPH_CAP_RATIO;
630
655
  function rowGlyphDepth(kind) {
631
656
  if (!rendersRows(kind)) return null;
632
657
  const font = kind === "storage" ? ROW_FONT_STORAGE : ROW_FONT_GENERIC;
@@ -1820,6 +1845,108 @@ function applyEdgeLabelAndPathShifts(edges, labelShiftMap, edgePathShiftMap) {
1820
1845
  });
1821
1846
  }
1822
1847
 
1848
+ // src/layout/self-loop.ts
1849
+ var SELF_LOOP_OUT = 72;
1850
+ var SELF_LOOP_SPAN = 64;
1851
+ var SELF_LOOP_STAGGER = 45;
1852
+ var SELF_LOOP_SIDE_ORDER = ["right", "top", "left", "bottom"];
1853
+ var SELF_LOOP_SIDE_FALLBACK = "right";
1854
+ var CUBIC_APEX_RATIO = 0.75;
1855
+ var ENDPOINT_CENTER_MARGIN = 8;
1856
+ var SPAN_MIN = 8;
1857
+ function controlOffset(out) {
1858
+ return out / CUBIC_APEX_RATIO;
1859
+ }
1860
+ function sideGeometry(n, side) {
1861
+ switch (side) {
1862
+ case "right":
1863
+ return { x: n.cx + n.w / 2, y: n.cy, ux: 1, uy: 0 };
1864
+ case "left":
1865
+ return { x: n.cx - n.w / 2, y: n.cy, ux: -1, uy: 0 };
1866
+ case "top":
1867
+ return { x: n.cx, y: n.cy - n.h / 2, ux: 0, uy: -1 };
1868
+ case "bottom":
1869
+ return { x: n.cx, y: n.cy + n.h / 2, ux: 0, uy: 1 };
1870
+ }
1871
+ }
1872
+ function fitSpan(sideLength, wanted) {
1873
+ const \u9650\u5EA6 = sideLength - 2 * ENDPOINT_CENTER_MARGIN;
1874
+ return Math.max(SPAN_MIN, Math.min(wanted, \u9650\u5EA6));
1875
+ }
1876
+ function pickFreeSides(occupied, count) {
1877
+ const \u7A7A\u304D = SELF_LOOP_SIDE_ORDER.filter((s) => !occupied?.has(s));
1878
+ const \u4F7F\u3046 = \u7A7A\u304D.length > 0 ? \u7A7A\u304D : [SELF_LOOP_SIDE_FALLBACK];
1879
+ return Array.from({ length: count }, (_, i) => \u4F7F\u3046[i % \u4F7F\u3046.length]);
1880
+ }
1881
+ function routeSelfLoopGroup(edges, node, side) {
1882
+ const horizontal = side === "left" || side === "right";
1883
+ const g = sideGeometry(node, side);
1884
+ const span = fitSpan(horizontal ? node.h : node.w, SELF_LOOP_SPAN);
1885
+ const half = span / 2;
1886
+ const \u6CBF = horizontal ? { x: 0, y: 1 } : { x: 1, y: 0 };
1887
+ const \u6700\u5916 = controlOffset(SELF_LOOP_OUT + (edges.length - 1) * SELF_LOOP_STAGGER);
1888
+ const \u8A9E\u307E\u3067 = \u6700\u5916 + LABEL_TO_PATH_CLEARANCE;
1889
+ const \u8A9E\u5E45 = edges.map(
1890
+ (e) => horizontal ? labelPillH(e.sub) : computeLabelBoxW(e.label, e.sub)
1891
+ );
1892
+ const \u4F4D\u7F6E = [];
1893
+ let \u7A4D = 0;
1894
+ for (const w of \u8A9E\u5E45) {
1895
+ \u4F4D\u7F6E.push(\u7A4D + w / 2);
1896
+ \u7A4D += w + CLEARANCE_LABEL_LABEL;
1897
+ }
1898
+ const \u5168\u9577 = Math.max(0, \u7A4D - CLEARANCE_LABEL_LABEL);
1899
+ return edges.map((edge, index) => {
1900
+ const c = controlOffset(SELF_LOOP_OUT + index * SELF_LOOP_STAGGER);
1901
+ const x1 = g.x - \u6CBF.x * half;
1902
+ const y1 = g.y - \u6CBF.y * half;
1903
+ const x2 = g.x + \u6CBF.x * half;
1904
+ const y2 = g.y + \u6CBF.y * half;
1905
+ const \u305A\u308C = \u4F4D\u7F6E[index] - \u5168\u9577 / 2;
1906
+ return {
1907
+ ...edge,
1908
+ d: `M ${x1} ${y1} C ${x1 + g.ux * c} ${y1 + g.uy * c} ${x2 + g.ux * c} ${y2 + g.uy * c} ${x2} ${y2}`,
1909
+ fromSide: side,
1910
+ toSide: side,
1911
+ labelX: g.x + g.ux * \u8A9E\u307E\u3067 + \u6CBF.x * \u305A\u308C + (edge.labelOffsetX ?? 0),
1912
+ labelY: g.y + g.uy * \u8A9E\u307E\u3067 + \u6CBF.y * \u305A\u308C + (edge.labelOffsetY ?? 0),
1913
+ labelAnchor: side === "left" ? "end" : side === "right" ? "start" : "middle"
1914
+ };
1915
+ });
1916
+ }
1917
+ function isSelfLoop(e) {
1918
+ return e.from === e.to;
1919
+ }
1920
+ function layoutSelfLoops(edges, nodes, occupiedBySide) {
1921
+ const \u5272\u5F53 = /* @__PURE__ */ new Map();
1922
+ for (const edge of edges) {
1923
+ if (edge.side) continue;
1924
+ const list = \u5272\u5F53.get(edge.from) ?? [];
1925
+ list.push("right");
1926
+ \u5272\u5F53.set(edge.from, list);
1927
+ }
1928
+ for (const [nodeId, list] of \u5272\u5F53) {
1929
+ \u5272\u5F53.set(nodeId, pickFreeSides(occupiedBySide.get(nodeId), list.length));
1930
+ }
1931
+ const \u6D88\u8CBB = /* @__PURE__ */ new Map();
1932
+ const \u675F = /* @__PURE__ */ new Map();
1933
+ for (const edge of edges) {
1934
+ const node = nodes.get(edge.from);
1935
+ if (!node) throw new Error(`cdl layout: edge "${edge.id}" \u306E from "${edge.from}" \u304C node \u306B\u7121\u3044`);
1936
+ let side = edge.side;
1937
+ if (!side) {
1938
+ const i = \u6D88\u8CBB.get(edge.from) ?? 0;
1939
+ \u6D88\u8CBB.set(edge.from, i + 1);
1940
+ side = \u5272\u5F53.get(edge.from)[i];
1941
+ }
1942
+ const key = `${edge.from}::${side}`;
1943
+ const \u65E2 = \u675F.get(key);
1944
+ if (\u65E2) \u65E2.edges.push(edge);
1945
+ else \u675F.set(key, { node, side, edges: [edge] });
1946
+ }
1947
+ return [...\u675F.values()].flatMap((b) => routeSelfLoopGroup(b.edges, b.node, b.side));
1948
+ }
1949
+
1823
1950
  // src/layout/tokens.ts
1824
1951
  var TOKENS = {
1825
1952
  // viewBox / lane margins
@@ -1865,6 +1992,16 @@ var TOKENS = {
1865
1992
  "chart-line": { w: 640, h: 360 },
1866
1993
  "chart-pie": { w: 640, h: 320 },
1867
1994
  "chart-bar": { w: 640, h: 360 },
1995
+ // 上半分の弧 + 下段の内訳。 弧が浅いぶん pie より低くて済む (cdl#549)
1996
+ "chart-gauge": { w: 640, h: 320 },
1997
+ // 左に一覧 + 右に同心の弧。 件数ぶん内側へ重なるので pie と同じ高さを取る (cdl#550)
1998
+ "chart-radial": { w: 640, h: 320 },
1999
+ // 件ごとに区画を割り、名前 / 数値 / 弧 / 割合 を縦に積む。 数値を大きく組むので縦が要る (cdl#553)
2000
+ "chart-stat": { w: 640, h: 320 },
2001
+ // 左に一覧 + 右に 10x10 の格子。 格子が正方形なので pie と同じ高さで足りる (cdl#552)
2002
+ "chart-waffle": { w: 640, h: 320 },
2003
+ // 帯を最大 2 本 + 下に一覧。 縦は帯 2 本ぶんで足りる (cdl#551)
2004
+ "chart-stacked-bar": { w: 640, h: 320 },
1868
2005
  // Timeline / Mind 系 (CAR-994 Phase B)
1869
2006
  "gantt-timeline": { w: 720, h: 360 },
1870
2007
  "mind-map": { w: 720, h: 480 },
@@ -1935,7 +2072,12 @@ var TOKENS = {
1935
2072
  "shape-notary": { w: 280, h: 320 },
1936
2073
  "shape-lawyer": { w: 280, h: 300 },
1937
2074
  "shape-trader": { w: 300, h: 300 },
1938
- "shape-customer-service": { w: 320, h: 300 }
2075
+ "shape-customer-service": { w: 320, h: 300 },
2076
+ // 流れの始まりと終わりの印 2 種 (#560) ... 正方形にして丸が縦横どちらにも歪まないようにする。
2077
+ // 印は箱いっぱいに描く (線が箱の縁で止まるため) ので、この値が丸の直径になる。
2078
+ // 箱としての最小 (80x40) より大きく、名前を持つ箱 (card 320x150) よりは明らかに小さい
2079
+ "mark-start": { w: 96, h: 96 },
2080
+ "mark-end": { w: 96, h: 96 }
1939
2081
  },
1940
2082
  // row gap (stack 間の vertical gap、 lane 内 / 跨ぎ共通)
1941
2083
  // edge label が node の上 36 px に配置されるため、 boxH 68 + 36 + 余裕 = 100 必要。
@@ -2008,6 +2150,7 @@ function layoutEdges(diag, nodes, lanes = []) {
2008
2150
  const lmap = new Map(lanes.map((l) => [l.id, l]));
2009
2151
  const positionedEdges = [];
2010
2152
  const autoEdges = [];
2153
+ const selfLoopEdges = [];
2011
2154
  for (const e of diag.edges) {
2012
2155
  if (e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0) {
2013
2156
  const from = nmap.get(e.from);
@@ -2026,6 +2169,8 @@ function layoutEdges(diag, nodes, lanes = []) {
2026
2169
  labelY: midY + (e.labelOffsetY ?? 0),
2027
2170
  labelAnchor: "middle"
2028
2171
  });
2172
+ } else if (isSelfLoop(e)) {
2173
+ selfLoopEdges.push(e);
2029
2174
  } else {
2030
2175
  autoEdges.push(e);
2031
2176
  }
@@ -2049,6 +2194,22 @@ function layoutEdges(diag, nodes, lanes = []) {
2049
2194
  if (list.length <= 1) continue;
2050
2195
  distributeBySides(list);
2051
2196
  }
2197
+ const occupiedBySide = /* @__PURE__ */ new Map();
2198
+ const \u4F7F\u3046 = (nodeId, side) => {
2199
+ const s = occupiedBySide.get(nodeId) ?? /* @__PURE__ */ new Set();
2200
+ s.add(side);
2201
+ occupiedBySide.set(nodeId, s);
2202
+ };
2203
+ for (const p of prepared) {
2204
+ const backDetour = p.e.routing === "back-detour";
2205
+ \u4F7F\u3046(p.e.from, backDetour ? "top" : p.fromSide);
2206
+ \u4F7F\u3046(p.e.to, backDetour ? "top" : p.toSide);
2207
+ }
2208
+ for (const le of positionedEdges) {
2209
+ \u4F7F\u3046(le.from, le.fromSide);
2210
+ \u4F7F\u3046(le.to, le.toSide);
2211
+ }
2212
+ const loopEdges = layoutSelfLoops(selfLoopEdges, nmap, occupiedBySide);
2052
2213
  const labelOffsetsByEdgeId = /* @__PURE__ */ new Map();
2053
2214
  const parallelKey = (p) => p.e.from < p.e.to ? `${p.e.from}::${p.e.to}` : `${p.e.to}::${p.e.from}`;
2054
2215
  const byParallel = /* @__PURE__ */ new Map();
@@ -2547,6 +2708,7 @@ function layoutEdges(diag, nodes, lanes = []) {
2547
2708
  });
2548
2709
  const laidById = /* @__PURE__ */ new Map();
2549
2710
  for (const le of autoResults) laidById.set(le.id, le);
2711
+ for (const le of loopEdges) laidById.set(le.id, le);
2550
2712
  for (const le of positionedEdges) laidById.set(le.id, le);
2551
2713
  return diag.edges.map((e) => laidById.get(e.id)).filter((e) => e !== void 0);
2552
2714
  }
@@ -3914,10 +4076,19 @@ var NODE_KINDS = [
3914
4076
  "oracle",
3915
4077
  "merkle-tree",
3916
4078
  "decision",
3917
- // Chart 系 (3) ... 1 node に datum 配列を持ち、 kind 内で全 datum を SVG 描画
4079
+ // Chart 系 (5) ... 1 node に datum 配列を持ち、 kind 内で全 datum を SVG 描画。
4080
+ // chart-gauge は合計を主役に置く形 (cdl#549)、 chart-radial は弧の長さで比べる形 (cdl#550)、
4081
+ // chart-stat は数値そのものを主役に置く形 (cdl#553)
4082
+ // chart-waffle は 100 個の印で割合を数えて確かめる形 (cdl#552)
3918
4083
  "chart-pie",
3919
4084
  "chart-line",
3920
4085
  "chart-bar",
4086
+ "chart-gauge",
4087
+ "chart-radial",
4088
+ "chart-stat",
4089
+ // chart-stacked-bar は帯を割合で区切り時点を並べる形 (cdl#551)
4090
+ "chart-waffle",
4091
+ "chart-stacked-bar",
3921
4092
  // Timeline / Mind 系 (2、 CAR-994 Phase B) ... 1 node に payload 配列、 SVG geometry render
3922
4093
  "gantt-timeline",
3923
4094
  "mind-map",
@@ -3984,8 +4155,14 @@ var NODE_KINDS = [
3984
4155
  "shape-notary",
3985
4156
  "shape-lawyer",
3986
4157
  "shape-trader",
3987
- "shape-customer-service"
4158
+ "shape-customer-service",
4159
+ // 流れの始まりと終わりの印 2 種 (#560) ... 塗った丸と輪で囲んだ丸。
4160
+ // 状態遷移図が使う。 印そのものが意味を持つので文字は描かない
4161
+ "mark-start",
4162
+ "mark-end"
3988
4163
  ];
4164
+ var EDGE_HEAD_DEFAULT = "triangle";
4165
+ var EDGE_HEADS = ["triangle", "diamond", "open", "crow"];
3989
4166
 
3990
4167
  // src/formula/evaluator.ts
3991
4168
  function evaluate(ast, ctxOrResolver) {
@@ -4993,12 +5170,6 @@ function validate(diag) {
4993
5170
  \u2192 \u4FEE\u6B63\u4F8B: .node("${e.to}", { lane: "...", stack: 0, kind: "...", title: "..." }) \u3092 edge \u5BA3\u8A00\u524D\u306B\u8FFD\u52A0`
4994
5171
  );
4995
5172
  }
4996
- if (e.from === e.to) {
4997
- errors.push(
4998
- `[cdl] self-loop: edge "${e.id}" \u306E from \u3068 to \u304C\u540C\u3058 node "${e.from}" \u3067\u3059 (self-loop \u306F\u73FE\u72B6\u672A\u5BFE\u5FDC)
4999
- \u2192 \u5225 node \u3092\u4F5C\u3063\u3066 2 \u6BB5\u306B\u5206\u3051\u308B\u304B\u3001 \u5F8C\u7D9A PR \u306E self-loop support \u3092\u5F85\u3063\u3066\u304F\u3060\u3055\u3044`
5000
- );
5001
- }
5002
5173
  }
5003
5174
  for (const p of diag.phases) {
5004
5175
  for (const id of p.activate) {
@@ -5018,6 +5189,17 @@ function validate(diag) {
5018
5189
  );
5019
5190
  }
5020
5191
  }
5192
+ if (p.drawRatio !== void 0) {
5193
+ if (!Number.isFinite(p.drawRatio) || p.drawRatio <= 0 || p.drawRatio > 1) {
5194
+ warnings.push(
5195
+ `phase "${p.id}" \u306E drawRatio ${p.drawRatio} \u306F\u7BC4\u56F2\u5916 (0 \u3088\u308A\u5927\u304D\u304F 1 \u4EE5\u4E0B)\u3002 1 \u3068\u3057\u3066\u6271\u3046`
5196
+ );
5197
+ } else if ((p.draw ?? []).length === 0) {
5198
+ warnings.push(
5199
+ `phase "${p.id}" \u306F drawRatio \u3092\u6301\u3064\u304C draw \u304C\u7A7A\u3002 \u63CF\u304F\u5BFE\u8C61\u304C\u7121\u3044\u306E\u3067\u4F55\u3082\u5909\u308F\u3089\u306A\u3044`
5200
+ );
5201
+ }
5202
+ }
5021
5203
  for (const t of p.tweens) {
5022
5204
  if (!stateIds.has(t.stateId)) {
5023
5205
  errors.push(`[cdl] unknown-ref: phase "${p.id}" tween \u5BFE\u8C61 state "${t.stateId}" \u672A\u5B9A\u7FA9`);
@@ -5273,6 +5455,18 @@ function StateDiffCard({
5273
5455
  );
5274
5456
  }
5275
5457
 
5458
+ // src/render/edge-head.ts
5459
+ var EDGE_HEAD_SHAPE = {
5460
+ triangle: { d: "M 0 0 L 10 5 L 0 10 z", refX: 9, filled: true },
5461
+ diamond: { d: "M 0 5 L 5 0 L 10 5 L 5 10 z", refX: 9, filled: true },
5462
+ open: { d: "M 1 0 L 9 5 L 1 10", refX: 9, filled: false },
5463
+ crow: { d: "M 10 0 L 0 5 M 10 5 L 0 5 M 10 10 L 0 5", refX: 10, filled: false }
5464
+ };
5465
+ function edgeHeadMarkerId(tone, head, small) {
5466
+ const \u5C0F = small ? "-sm" : "";
5467
+ return head === EDGE_HEAD_DEFAULT ? `cdl-arrow-${tone}${\u5C0F}` : `cdl-arrow-${tone}-${head}${\u5C0F}`;
5468
+ }
5469
+
5276
5470
  // src/render/tone.ts
5277
5471
  var TONE = {
5278
5472
  accent: "var(--cdl-tone-accent, #2d6a8f)",
@@ -5290,6 +5484,17 @@ var TONE_HEX = {
5290
5484
  warning: "#a67a2e",
5291
5485
  info: "#5a8ec1"
5292
5486
  };
5487
+ var CHART_SERIES = [
5488
+ "var(--cdl-chart-1, #4338ca)",
5489
+ "var(--cdl-chart-2, #0d9488)",
5490
+ "var(--cdl-chart-3, #f59e0b)",
5491
+ "var(--cdl-chart-4, #be185d)",
5492
+ "var(--cdl-chart-5, #4d7c0f)",
5493
+ "var(--cdl-chart-6, #0369a1)"
5494
+ ];
5495
+ function chartSeriesColor(idx) {
5496
+ return CHART_SERIES[(idx % CHART_SERIES.length + CHART_SERIES.length) % CHART_SERIES.length];
5497
+ }
5293
5498
  var TONE_FALLBACK = "#2d6a8f";
5294
5499
  function hasTone(tone) {
5295
5500
  return Object.hasOwn(TONE, tone);
@@ -5313,7 +5518,7 @@ function CdlEdgeView({
5313
5518
  stateValues
5314
5519
  }) {
5315
5520
  const color = toneColor(edge.tone);
5316
- const marker = hasTone(edge.tone) ? `cdl-arrow-${edge.tone}${active ? "" : "-sm"}` : "cdl-arrow-muted";
5521
+ const marker = hasTone(edge.tone) ? edgeHeadMarkerId(edge.tone, edge.head ?? EDGE_HEAD_DEFAULT, !active) : "cdl-arrow-muted";
5317
5522
  const style = edge.style ?? "solid";
5318
5523
  const isDotted = style === "dotted-flow";
5319
5524
  const isPassThrough = isDotted && Boolean(edge.dThrough);
@@ -6133,12 +6338,13 @@ function GenericNode({
6133
6338
  );
6134
6339
  })();
6135
6340
  const resolvedValue = value !== void 0 ? interpolate(value, stateValues) : void 0;
6136
- const centered = shape === "diamond" || shape === "cloud";
6341
+ const hasRows = (node.rows?.length ?? 0) > 0;
6342
+ const centered = genericTextCentered(node.kind, hasRows);
6137
6343
  const textAnchor = centered ? "middle" : "start";
6138
6344
  const textX = centered ? w / 2 : 20;
6139
- const cylinderShift = shape === "cylinder" ? 28 : 0;
6345
+ const cylinderShift = genericTextShift(node.kind);
6140
6346
  const eyebrowY = centered ? h / 2 - 26 : 32 + cylinderShift;
6141
- const titleY = centered ? h / 2 + 4 : 68 + cylinderShift;
6347
+ const titleY = genericTitleBaselineY(node.kind, h, hasRows);
6142
6348
  const subtitleY = centered ? h / 2 + 28 : 96 + cylinderShift;
6143
6349
  const iconX = centered ? w / 2 + 40 : w - 48;
6144
6350
  const iconY = centered ? h / 2 - 44 : 18 + cylinderShift;
@@ -6194,6 +6400,57 @@ function GenericNode({
6194
6400
  })()
6195
6401
  ] });
6196
6402
  }
6403
+ var MARK_INNER_RATIO = 0.56;
6404
+ var RING_WIDTH_ACTIVE = 6;
6405
+ var RING_WIDTH_IDLE = 4;
6406
+ var MARK_DEFAULT = "var(--cdl-tone-accent, #2d6a8f)";
6407
+ function markRadius(node) {
6408
+ return Math.min(node.w, node.h) / 2;
6409
+ }
6410
+ function MarkStartNode({ node }) {
6411
+ const \u8272 = nodeAccent(node, MARK_DEFAULT);
6412
+ return /* @__PURE__ */ jsx("g", { transform: `translate(${node.cx - node.w / 2} ${node.cy - node.h / 2})`, children: /* @__PURE__ */ jsx(
6413
+ "circle",
6414
+ {
6415
+ "data-cdl-role": "node-body",
6416
+ "data-cdl-mark": "start",
6417
+ cx: node.w / 2,
6418
+ cy: node.h / 2,
6419
+ r: markRadius(node),
6420
+ fill: \u8272
6421
+ }
6422
+ ) });
6423
+ }
6424
+ function MarkEndNode({ node, active }) {
6425
+ const \u8272 = nodeAccent(node, MARK_DEFAULT);
6426
+ const r = markRadius(node);
6427
+ const \u8F2A\u306E\u592A\u3055 = active ? RING_WIDTH_ACTIVE : RING_WIDTH_IDLE;
6428
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${node.cx - node.w / 2} ${node.cy - node.h / 2})`, children: [
6429
+ /* @__PURE__ */ jsx(
6430
+ "circle",
6431
+ {
6432
+ "data-cdl-role": "node-body",
6433
+ "data-cdl-mark": "end",
6434
+ cx: node.w / 2,
6435
+ cy: node.h / 2,
6436
+ r: Math.max(0, r - \u8F2A\u306E\u592A\u3055 / 2),
6437
+ fill: "var(--cdl-node-fill, #ffffff)",
6438
+ stroke: \u8272,
6439
+ strokeWidth: \u8F2A\u306E\u592A\u3055
6440
+ }
6441
+ ),
6442
+ /* @__PURE__ */ jsx(
6443
+ "circle",
6444
+ {
6445
+ "data-cdl-role": "node-inner",
6446
+ cx: node.w / 2,
6447
+ cy: node.h / 2,
6448
+ r: Math.max(0, r * MARK_INNER_RATIO),
6449
+ fill: \u8272
6450
+ }
6451
+ )
6452
+ ] });
6453
+ }
6197
6454
  function useTimeTick() {
6198
6455
  const [t, setT] = useState(() => typeof performance !== "undefined" ? performance.now() : 0);
6199
6456
  useEffect(() => {
@@ -6311,7 +6568,7 @@ function renderRect(shape, x, y, w, h, stateValues, fillColor, strokeColor, opac
6311
6568
  )
6312
6569
  ] });
6313
6570
  }
6314
- function renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity, node) {
6571
+ function renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity) {
6315
6572
  const maxR = Math.min(w, h) / 2;
6316
6573
  const r = shape.radius !== void 0 ? resolveNumericAttr(shape.radius, stateValues, maxR) : maxR;
6317
6574
  const progress = shape.fillProgress !== void 0 ? Math.min(1, Math.max(0, resolveNumericAttr(shape.fillProgress, stateValues, 0))) : 1;
@@ -6332,7 +6589,7 @@ function renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor,
6332
6589
  )
6333
6590
  ] });
6334
6591
  }
6335
- function renderArc(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity, node) {
6592
+ function renderArc(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity) {
6336
6593
  const maxR = Math.min(w, h) / 2;
6337
6594
  const outerR = shape.outerRadius ?? maxR;
6338
6595
  const innerR = shape.innerRadius ?? outerR * 0.7;
@@ -6432,7 +6689,7 @@ function WaveShape({
6432
6689
  )
6433
6690
  ] });
6434
6691
  }
6435
- function renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, opacity, node) {
6692
+ function renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, opacity) {
6436
6693
  const sides = Math.min(12, Math.max(3, shape.sides));
6437
6694
  const r = shape.radius !== void 0 ? resolveNumericAttr(shape.radius, stateValues, 40) : 40;
6438
6695
  const rotation = shape.rotation !== void 0 ? resolveNumericAttr(shape.rotation, stateValues, 0) : 0;
@@ -6512,10 +6769,14 @@ function needsResolve(raw) {
6512
6769
  return typeof raw !== "number" || !Number.isFinite(raw);
6513
6770
  }
6514
6771
  function resolveChartData(data, values) {
6515
- if (!data.some((d) => needsResolve(d.value))) return data;
6772
+ if (!data.some((d) => needsResolve(d.value) || d.previous !== void 0 && needsResolve(d.previous)))
6773
+ return data;
6516
6774
  return data.map((d) => {
6517
6775
  const v = resolveBoundNumber(d.value, values, 0);
6518
- return v.ok ? { ...d, value: v.value } : { ...d, value: v.value, unresolved: true };
6776
+ const \u524D = d.previous === void 0 ? void 0 : resolveBoundNumber(d.previous, values, 0);
6777
+ const \u89E3\u3051\u305F = v.ok && (\u524D === void 0 || \u524D.ok);
6778
+ const \u7D20 = { ...d, value: v.value, previous: \u524D?.value };
6779
+ return \u89E3\u3051\u305F ? \u7D20 : { ...\u7D20, unresolved: true };
6519
6780
  });
6520
6781
  }
6521
6782
  function resolveFunnelData(stages, values) {
@@ -6835,10 +7096,26 @@ function ChartPieNode({
6835
7096
  const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
6836
7097
  const PAD_TOP2 = 20;
6837
7098
  const PAD_BOTTOM2 = 20;
7099
+ const PAD_SIDE = 20;
6838
7100
  const chartAreaH = node.h - PAD_TOP2 - PAD_BOTTOM2;
6839
- const pieAreaW = node.w * 0.5;
6840
- const radius = Math.min(pieAreaW, chartAreaH) / 2 - 12;
6841
- const cx = pieAreaW / 2;
7101
+ const \u540D\u672D\u306E\u7D1A = 14;
7102
+ const \u6570\u5024\u306E\u7D1A = 13;
7103
+ const \u5F15\u304D\u51FA\u3057 = 18;
7104
+ const \u5B57\u307E\u3067\u306E\u9593 = 26;
7105
+ const \u540D\u672D\u306E\u7E26\u306E\u5F35\u308A\u51FA\u3057 = 20;
7106
+ const \u5272\u5408\u306E\u6587\u5B57 = data.map((d) => \u5272\u5408\u8868\u8A18(d.value / total));
7107
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map((d, i) => `${\u5B9F\u5024\u8868\u8A18(d.value)} ${\u5272\u5408\u306E\u6587\u5B57[i]}`);
7108
+ const \u540D\u672D\u5E45 = Math.max(
7109
+ 0,
7110
+ ...data.map(
7111
+ (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u672D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
7112
+ )
7113
+ );
7114
+ const \u7E26\u304B\u3089 = chartAreaH / 2 - \u5F15\u304D\u51FA\u3057 - \u540D\u672D\u306E\u7E26\u306E\u5F35\u308A\u51FA\u3057;
7115
+ const \u6A2A\u304B\u3089 = (node.w - PAD_SIDE * 2) / 2 - \u5F15\u304D\u51FA\u3057 - \u5B57\u307E\u3067\u306E\u9593 - \u540D\u672D\u5E45;
7116
+ const radius = Math.max(24, Math.min(\u7E26\u304B\u3089, \u6A2A\u304B\u3089));
7117
+ const \u5185\u534A\u5F84 = radius * 0.58;
7118
+ const cx = node.w / 2;
6842
7119
  const cy = PAD_TOP2 + chartAreaH / 2;
6843
7120
  let cumAngle = -Math.PI / 2;
6844
7121
  let cumFrac = 0;
@@ -6854,16 +7131,19 @@ function ChartPieNode({
6854
7131
  const y1 = cy + radius * Math.sin(a0);
6855
7132
  const x2 = cx + radius * Math.cos(a1);
6856
7133
  const y2 = cy + radius * Math.sin(a1);
7134
+ const x3 = cx + \u5185\u534A\u5F84 * Math.cos(a1);
7135
+ const y3 = cy + \u5185\u534A\u5F84 * Math.sin(a1);
7136
+ const x4 = cx + \u5185\u534A\u5F84 * Math.cos(a0);
7137
+ const y4 = cy + \u5185\u534A\u5F84 * Math.sin(a0);
6857
7138
  const large = angle > Math.PI ? 1 : 0;
6858
- const path = `M ${cx} ${cy} L ${x1} ${y1} A ${radius} ${radius} 0 ${large} 1 ${x2} ${y2} Z`;
6859
- return { d, frac, path, startFrac };
7139
+ const path = `M ${x1} ${y1} A ${radius} ${radius} 0 ${large} 1 ${x2} ${y2} L ${x3} ${y3} A ${\u5185\u534A\u5F84} ${\u5185\u534A\u5F84} 0 ${large} 0 ${x4} ${y4} Z`;
7140
+ const \u4E2D\u592E\u89D2 = (a0 + a1) / 2;
7141
+ return { d, frac, path, startFrac, \u4E2D\u592E\u89D2 };
6860
7142
  });
6861
7143
  const \u958B\u304D = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
6862
7144
  const \u5207\u308A\u629C\u304Did = `cdl-pie-draw-${instanceId}`;
7145
+ const \u5F71id = `cdl-pie-shadow-${instanceId}`;
6863
7146
  const \u958B\u304D\u59CB\u3081\u305F = (startFrac) => !drawing || \u958B\u304D > startFrac;
6864
- const legendX = pieAreaW + 8;
6865
- const legendGap = Math.min(28, chartAreaH / Math.max(data.length, 1));
6866
- const legendStartY = PAD_TOP2 + (chartAreaH - legendGap * data.length) / 2 + legendGap / 2;
6867
7147
  return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
6868
7148
  /* @__PURE__ */ jsx(
6869
7149
  "rect",
@@ -6879,56 +7159,90 @@ function ChartPieNode({
6879
7159
  strokeWidth: active ? 3 : 1.25
6880
7160
  }
6881
7161
  ),
6882
- drawing && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: \u5207\u308A\u629C\u304Did, children: \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, radius + 2, \u958B\u304D) }) }),
6883
- /* @__PURE__ */ jsx("g", { ...drawing ? { clipPath: `url(#${\u5207\u308A\u629C\u304Did})` } : {}, children: slices.map((s, idx) => /* @__PURE__ */ jsx(
7162
+ /* @__PURE__ */ jsxs("defs", { children: [
7163
+ drawing && /* @__PURE__ */ jsx("clipPath", { id: \u5207\u308A\u629C\u304Did, children: \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, radius + 2, \u958B\u304D) }),
7164
+ /* @__PURE__ */ jsx("filter", { id: \u5F71id, x: "-20%", y: "-20%", width: "140%", height: "140%", children: /* @__PURE__ */ jsx("feDropShadow", { dx: "0", dy: "6", stdDeviation: "10", floodColor: "#0b1220", floodOpacity: "0.16" }) })
7165
+ ] }),
7166
+ /* @__PURE__ */ jsx("g", { ...drawing ? { clipPath: `url(#${\u5207\u308A\u629C\u304Did})` } : {}, filter: `url(#${\u5F71id})`, children: slices.map((s, idx) => /* @__PURE__ */ jsx(
6884
7167
  "path",
6885
7168
  {
6886
7169
  "data-cdl-role": "chart-pie-slice",
6887
7170
  "data-cdl-unresolved": s.d.unresolved ? "true" : void 0,
6888
7171
  d: s.path,
6889
7172
  fill: sliceColor(s.d.tone, idx),
6890
- fillOpacity: active ? 0.95 : 0.85,
6891
7173
  stroke: "var(--cdl-node-fill, #ffffff)",
6892
- strokeWidth: 1.5
7174
+ strokeWidth: 3,
7175
+ strokeLinejoin: "round"
6893
7176
  },
6894
7177
  `slice-${idx}`
6895
7178
  )) }),
6896
- slices.map((s, idx) => !\u958B\u304D\u59CB\u3081\u305F(s.startFrac) ? null : /* @__PURE__ */ jsxs("g", { transform: `translate(${legendX} ${legendStartY + idx * legendGap})`, children: [
6897
- /* @__PURE__ */ jsx(
6898
- "rect",
6899
- {
6900
- x: 0,
6901
- y: -8,
6902
- width: 14,
6903
- height: 14,
6904
- rx: 3,
6905
- fill: sliceColor(s.d.tone, idx)
6906
- }
6907
- ),
6908
- /* @__PURE__ */ jsx(
6909
- "text",
6910
- {
6911
- x: 20,
6912
- y: 2,
6913
- fontSize: 12,
6914
- fill: "var(--cdl-text, #1a1f2a)",
6915
- children: s.d.label
6916
- }
6917
- ),
6918
- /* @__PURE__ */ jsxs(
6919
- "text",
6920
- {
6921
- x: 20,
6922
- y: 16,
6923
- fontSize: 11,
6924
- fill: "var(--cdl-text-dim, #5a6270)",
6925
- children: [
6926
- (s.frac * 100).toFixed(1),
6927
- "%"
6928
- ]
6929
- }
6930
- )
6931
- ] }, `legend-${idx}`))
7179
+ /* @__PURE__ */ jsx(
7180
+ "text",
7181
+ {
7182
+ x: cx,
7183
+ y: cy - 2,
7184
+ textAnchor: "middle",
7185
+ fontSize: Math.round(radius * 0.26),
7186
+ fontWeight: 600,
7187
+ fill: "var(--cdl-text, #1a1f2a)",
7188
+ children: \u5B9F\u5024\u8868\u8A18(Math.round(total))
7189
+ }
7190
+ ),
7191
+ /* @__PURE__ */ jsx(
7192
+ "text",
7193
+ {
7194
+ x: cx,
7195
+ y: cy + Math.round(radius * 0.2),
7196
+ textAnchor: "middle",
7197
+ fontSize: Math.round(radius * 0.12),
7198
+ fill: "var(--cdl-text-dim, #5a6270)",
7199
+ children: "\u5408\u8A08"
7200
+ }
7201
+ ),
7202
+ slices.map((s, idx) => {
7203
+ if (!\u958B\u304D\u59CB\u3081\u305F(s.startFrac)) return null;
7204
+ const \u53F3 = Math.cos(s.\u4E2D\u592E\u89D2) >= 0;
7205
+ const \u7E01x = cx + radius * Math.cos(s.\u4E2D\u592E\u89D2);
7206
+ const \u7E01y = cy + radius * Math.sin(s.\u4E2D\u592E\u89D2);
7207
+ const \u6298\u308Cx = cx + (radius + \u5F15\u304D\u51FA\u3057) * Math.cos(s.\u4E2D\u592E\u89D2);
7208
+ const \u6298\u308Cy = cy + (radius + \u5F15\u304D\u51FA\u3057) * Math.sin(s.\u4E2D\u592E\u89D2);
7209
+ const \u5B57x = \u6298\u308Cx + (\u53F3 ? \u5B57\u307E\u3067\u306E\u9593 : -\u5B57\u307E\u3067\u306E\u9593);
7210
+ return /* @__PURE__ */ jsxs("g", { children: [
7211
+ /* @__PURE__ */ jsx(
7212
+ "path",
7213
+ {
7214
+ d: `M ${\u7E01x} ${\u7E01y} L ${\u6298\u308Cx} ${\u6298\u308Cy} L ${\u5B57x - (\u53F3 ? 6 : -6)} ${\u6298\u308Cy}`,
7215
+ fill: "none",
7216
+ stroke: "var(--cdl-divider, #d4d4d8)",
7217
+ strokeWidth: 1
7218
+ }
7219
+ ),
7220
+ /* @__PURE__ */ jsx("circle", { cx: \u7E01x, cy: \u7E01y, r: 3, fill: sliceColor(s.d.tone, idx) }),
7221
+ /* @__PURE__ */ jsx(
7222
+ "text",
7223
+ {
7224
+ x: \u5B57x,
7225
+ y: \u6298\u308Cy - 3,
7226
+ textAnchor: \u53F3 ? "start" : "end",
7227
+ fontSize: \u540D\u672D\u306E\u7D1A,
7228
+ fontWeight: 600,
7229
+ fill: "var(--cdl-text, #1a1f2a)",
7230
+ children: s.d.label
7231
+ }
7232
+ ),
7233
+ /* @__PURE__ */ jsx(
7234
+ "text",
7235
+ {
7236
+ x: \u5B57x,
7237
+ y: \u6298\u308Cy + 15,
7238
+ textAnchor: \u53F3 ? "start" : "end",
7239
+ fontSize: \u6570\u5024\u306E\u7D1A,
7240
+ fill: "var(--cdl-text-dim, #5a6270)",
7241
+ children: \u6570\u5024\u306E\u6587\u5B57[idx]
7242
+ }
7243
+ )
7244
+ ] }, `callout-${idx}`);
7245
+ })
6932
7246
  ] });
6933
7247
  }
6934
7248
  function \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, r, \u958B\u304D) {
@@ -6940,10 +7254,741 @@ function \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, r, \u958B\u304D) {
6940
7254
  const d = `M ${cx} ${cy} L ${cx + r * Math.cos(a0)} ${cy + r * Math.sin(a0)} A ${r} ${r} 0 ${large} 1 ${cx + r * Math.cos(a1)} ${cy + r * Math.sin(a1)} Z`;
6941
7255
  return /* @__PURE__ */ jsx("path", { d });
6942
7256
  }
6943
- var FALLBACK_ORDER = ["accent", "teal", "warning", "success", "info", "error"];
7257
+ function \u5B9F\u5024\u8868\u8A18(v) {
7258
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
7259
+ }
7260
+ function \u5272\u5408\u8868\u8A18(frac) {
7261
+ const v = Math.round(frac * 1e3) / 10;
7262
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
7263
+ }
6944
7264
  function sliceColor(tone, idx) {
6945
7265
  if (tone) return TONE[tone];
6946
- return TONE[FALLBACK_ORDER[idx % FALLBACK_ORDER.length]];
7266
+ return chartSeriesColor(idx);
7267
+ }
7268
+ function ChartGaugeNode({
7269
+ node,
7270
+ active,
7271
+ stateValues = {}
7272
+ }) {
7273
+ const x0 = node.cx - node.w / 2;
7274
+ const y0 = node.cy - node.h / 2;
7275
+ const data = resolveChartData(node.chartData ?? [], stateValues);
7276
+ const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
7277
+ const PAD_TOP2 = 20;
7278
+ const PAD_BOTTOM2 = 20;
7279
+ const PAD_SIDE = 20;
7280
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD_TOP2 - PAD_BOTTOM2;
7281
+ const \u4F7F\u3048\u308B\u5E452 = node.w - PAD_SIDE * 2;
7282
+ const \u540D\u524D\u306E\u7D1A = 14;
7283
+ const \u6570\u5024\u306E\u7D1A = 13;
7284
+ const \u5185\u8A33\u306E\u9AD8\u3055 = 56;
7285
+ const \u5F27\u3068\u5185\u8A33\u306E\u9593 = 16;
7286
+ const \u5F27\u306B\u4F7F\u3048\u308B\u9AD8\u3055 = \u4F7F\u3048\u308B\u9AD8\u3055 - \u5185\u8A33\u306E\u9AD8\u3055 - \u5F27\u3068\u5185\u8A33\u306E\u9593;
7287
+ const radius = Math.max(24, Math.min(\u5F27\u306B\u4F7F\u3048\u308B\u9AD8\u3055, \u4F7F\u3048\u308B\u5E452 / 2));
7288
+ const \u5185\u534A\u5F84 = radius * 0.62;
7289
+ const cx = node.w / 2;
7290
+ const cy = PAD_TOP2 + radius;
7291
+ let cumFrac = 0;
7292
+ const slices = data.map((d) => {
7293
+ const frac = d.value / total;
7294
+ const a0 = Math.PI + cumFrac * Math.PI;
7295
+ const a1 = a0 + frac * Math.PI;
7296
+ cumFrac += frac;
7297
+ const \u59161 = \u6975(cx, cy, radius, a0);
7298
+ const \u59162 = \u6975(cx, cy, radius, a1);
7299
+ const \u51852 = \u6975(cx, cy, \u5185\u534A\u5F84, a1);
7300
+ const \u51851 = \u6975(cx, cy, \u5185\u534A\u5F84, a0);
7301
+ const path = `M ${\u59161.x} ${\u59161.y} A ${radius} ${radius} 0 0 1 ${\u59162.x} ${\u59162.y} L ${\u51852.x} ${\u51852.y} A ${\u5185\u534A\u5F84} ${\u5185\u534A\u5F84} 0 0 0 ${\u51851.x} ${\u51851.y} Z`;
7302
+ return { d, frac, path };
7303
+ });
7304
+ const \u5408\u8A08\u306E\u6587\u5B57 = \u5B9F\u5024\u8868\u8A182(Math.round(total));
7305
+ const \u6A2A\u306E\u4E0A\u9650 = \u5185\u534A\u5F84 * 2 * 0.86;
7306
+ const \u7D1A\u306E\u5019\u88DC = Math.min(
7307
+ // 横 = 実際の字幅から逆算する
7308
+ \u6A2A\u306E\u4E0A\u9650 / Math.max(textWidth(\u5408\u8A08\u306E\u6587\u5B57, 100), 1) * 100,
7309
+ // 縦 = 合計 1 行 + 見出し 1 行が内側の高さに収まる比
7310
+ \u5185\u534A\u5F84 * 0.52
7311
+ );
7312
+ const \u5408\u8A08\u306E\u7D1A = Math.max(11, Math.round(\u7D1A\u306E\u5019\u88DC));
7313
+ const \u898B\u51FA\u3057\u306E\u7D1A = Math.max(9, Math.round(\u5408\u8A08\u306E\u7D1A * 0.38));
7314
+ const \u5185\u8A33\u306E\u5E45 = \u4F7F\u3048\u308B\u5E452 / Math.max(data.length, 1);
7315
+ const \u5185\u8A33\u306Ey = cy + \u5F27\u3068\u5185\u8A33\u306E\u9593;
7316
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
7317
+ /* @__PURE__ */ jsx(
7318
+ "rect",
7319
+ {
7320
+ "data-cdl-role": "node-body",
7321
+ x: 0,
7322
+ y: 0,
7323
+ width: node.w,
7324
+ height: node.h,
7325
+ rx: 16,
7326
+ fill: "var(--cdl-node-fill, #ffffff)",
7327
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
7328
+ strokeWidth: active ? 3 : 1.25
7329
+ }
7330
+ ),
7331
+ slices.map((s, idx) => /* @__PURE__ */ jsx(
7332
+ "path",
7333
+ {
7334
+ "data-cdl-role": "chart-gauge-arc",
7335
+ "data-cdl-unresolved": s.d.unresolved ? "true" : void 0,
7336
+ d: s.path,
7337
+ fill: arcColor(s.d.tone, idx),
7338
+ stroke: "var(--cdl-node-fill, #ffffff)",
7339
+ strokeWidth: 3,
7340
+ strokeLinejoin: "round"
7341
+ },
7342
+ `arc-${idx}`
7343
+ )),
7344
+ /* @__PURE__ */ jsx(
7345
+ "text",
7346
+ {
7347
+ x: cx,
7348
+ y: cy - \u5408\u8A08\u306E\u7D1A * 0.5,
7349
+ textAnchor: "middle",
7350
+ fontSize: \u5408\u8A08\u306E\u7D1A,
7351
+ fontWeight: 600,
7352
+ fill: "var(--cdl-text, #1a1f2a)",
7353
+ children: \u5408\u8A08\u306E\u6587\u5B57
7354
+ }
7355
+ ),
7356
+ /* @__PURE__ */ jsx(
7357
+ "text",
7358
+ {
7359
+ x: cx,
7360
+ y: cy - \u5408\u8A08\u306E\u7D1A * 0.5 + \u898B\u51FA\u3057\u306E\u7D1A * 1.5,
7361
+ textAnchor: "middle",
7362
+ fontSize: \u898B\u51FA\u3057\u306E\u7D1A,
7363
+ fill: "var(--cdl-text-dim, #5a6270)",
7364
+ children: "\u5408\u8A08"
7365
+ }
7366
+ ),
7367
+ data.map((d, idx) => {
7368
+ const x = PAD_SIDE + \u5185\u8A33\u306E\u5E45 * idx;
7369
+ const \u6570\u5024 = `${\u5B9F\u5024\u8868\u8A182(d.value)} ${\u5272\u5408\u8868\u8A182(d.value / total)}`;
7370
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-gauge-item", children: [
7371
+ /* @__PURE__ */ jsx("rect", { x, y: \u5185\u8A33\u306Ey, width: 30, height: 4, rx: 2, fill: arcColor(d.tone, idx) }),
7372
+ /* @__PURE__ */ jsx(
7373
+ "text",
7374
+ {
7375
+ x,
7376
+ y: \u5185\u8A33\u306Ey + 26,
7377
+ fontSize: \u540D\u524D\u306E\u7D1A,
7378
+ fontWeight: 700,
7379
+ fill: "var(--cdl-text, #1a1f2a)",
7380
+ children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u5185\u8A33\u306E\u5E45 - 12, \u540D\u524D\u306E\u7D1A)
7381
+ }
7382
+ ),
7383
+ /* @__PURE__ */ jsx("text", { x, y: \u5185\u8A33\u306Ey + 46, fontSize: \u6570\u5024\u306E\u7D1A, fill: "var(--cdl-text-dim, #5a6270)", children: \u6570\u5024 })
7384
+ ] }, `legend-${idx}`);
7385
+ })
7386
+ ] });
7387
+ }
7388
+ function \u6975(cx, cy, r, a) {
7389
+ return { x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) };
7390
+ }
7391
+ function \u5207\u308A\u8A70\u3081\u308B(s, \u4E0A\u9650, \u7D1A) {
7392
+ if (\u4E0A\u9650 <= 0 || textWidth(s, \u7D1A) <= \u4E0A\u9650) return s;
7393
+ const \u8A18\u53F7\u5E45 = textWidth("\u2026", \u7D1A);
7394
+ let out = "";
7395
+ for (const c of s) {
7396
+ if (textWidth(out + c, \u7D1A) + \u8A18\u53F7\u5E45 > \u4E0A\u9650) break;
7397
+ out += c;
7398
+ }
7399
+ return `${out}\u2026`;
7400
+ }
7401
+ function \u5B9F\u5024\u8868\u8A182(v) {
7402
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
7403
+ }
7404
+ function \u5272\u5408\u8868\u8A182(frac) {
7405
+ const v = Math.round(frac * 1e3) / 10;
7406
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
7407
+ }
7408
+ function arcColor(tone, idx) {
7409
+ if (tone) return TONE[tone];
7410
+ return chartSeriesColor(idx);
7411
+ }
7412
+ function ChartRadialNode({
7413
+ node,
7414
+ active,
7415
+ stateValues = {}
7416
+ }) {
7417
+ const x0 = node.cx - node.w / 2;
7418
+ const y0 = node.cy - node.h / 2;
7419
+ const data = resolveChartData(node.chartData ?? [], stateValues);
7420
+ const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
7421
+ const PAD = 20;
7422
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD * 2;
7423
+ const \u540D\u524D\u306E\u7D1A = 14;
7424
+ const \u6570\u5024\u306E\u7D1A = 13;
7425
+ const \u884C\u306E\u9AD8\u3055 = 42;
7426
+ const \u4E00\u89A7\u3068\u5F27\u306E\u9593 = 28;
7427
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map((d) => `${\u5B9F\u5024\u8868\u8A183(d.value)} ${\u5272\u5408\u8868\u8A183(d.value / total)}`);
7428
+ const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E45 + Math.max(
7429
+ 0,
7430
+ ...data.map(
7431
+ (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
7432
+ )
7433
+ );
7434
+ const \u5F27\u306B\u4F7F\u3048\u308B\u5E45 = node.w - PAD * 2 - \u4E00\u89A7\u306E\u5E45 - \u4E00\u89A7\u3068\u5F27\u306E\u9593;
7435
+ const \u5916\u534A\u5F84 = Math.max(24, Math.min(\u4F7F\u3048\u308B\u9AD8\u3055 / 2, \u5F27\u306B\u4F7F\u3048\u308B\u5E45 / 2));
7436
+ const \u4F7F\u3048\u308B\u539A\u307F = \u5916\u534A\u5F84 * 0.7;
7437
+ const \u5E2F1\u672C = \u4F7F\u3048\u308B\u539A\u307F / Math.max(data.length, 1);
7438
+ const \u5E2F\u306E\u5E45 = \u5E2F1\u672C * 0.66;
7439
+ const \u5F27\u306Ecx = PAD + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u5F27\u306E\u9593 + \u5916\u534A\u5F84;
7440
+ const cy = PAD + \u4F7F\u3048\u308B\u9AD8\u3055 / 2;
7441
+ const rings = data.map((d, idx) => {
7442
+ const frac = d.value / total;
7443
+ const \u4E2D\u5FC3\u534A\u5F84 = \u5916\u534A\u5F84 - \u5E2F1\u672C * idx - \u5E2F1\u672C / 2;
7444
+ return {
7445
+ d,
7446
+ frac,
7447
+ \u4E2D\u5FC3\u534A\u5F84,
7448
+ // 軌道は全周。 1 周ちょうどは弧で表せないので、 わずかに欠かして描く
7449
+ \u8ECC\u9053: \u5F27\u306E\u9053(\u5F27\u306Ecx, cy, \u4E2D\u5FC3\u534A\u5F84, \u5E2F\u306E\u5E45, 0.9999),
7450
+ \u53D6\u308A\u5206: frac <= 0 ? null : \u5F27\u306E\u9053(\u5F27\u306Ecx, cy, \u4E2D\u5FC3\u534A\u5F84, \u5E2F\u306E\u5E45, Math.min(frac, 0.9999))
7451
+ };
7452
+ });
7453
+ const \u4E00\u89A7\u306E\u59CB\u307E\u308A = PAD + (\u4F7F\u3048\u308B\u9AD8\u3055 - \u884C\u306E\u9AD8\u3055 * data.length) / 2 + \u884C\u306E\u9AD8\u3055 / 2;
7454
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
7455
+ /* @__PURE__ */ jsx(
7456
+ "rect",
7457
+ {
7458
+ "data-cdl-role": "node-body",
7459
+ x: 0,
7460
+ y: 0,
7461
+ width: node.w,
7462
+ height: node.h,
7463
+ rx: 16,
7464
+ fill: "var(--cdl-node-fill, #ffffff)",
7465
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
7466
+ strokeWidth: active ? 3 : 1.25
7467
+ }
7468
+ ),
7469
+ rings.map((r, idx) => /* @__PURE__ */ jsx(
7470
+ "path",
7471
+ {
7472
+ "data-cdl-role": "chart-radial-track",
7473
+ d: r.\u8ECC\u9053,
7474
+ fill: "var(--cdl-divider, #d4d4d8)",
7475
+ fillOpacity: 0.28
7476
+ },
7477
+ `track-${idx}`
7478
+ )),
7479
+ rings.map(
7480
+ (r, idx) => r.\u53D6\u308A\u5206 === null ? null : /* @__PURE__ */ jsx(
7481
+ "path",
7482
+ {
7483
+ "data-cdl-role": "chart-radial-arc",
7484
+ "data-cdl-unresolved": r.d.unresolved ? "true" : void 0,
7485
+ d: r.\u53D6\u308A\u5206,
7486
+ fill: arcColor2(r.d.tone, idx)
7487
+ },
7488
+ `arc-${idx}`
7489
+ )
7490
+ ),
7491
+ data.map((d, idx) => {
7492
+ const y = \u4E00\u89A7\u306E\u59CB\u307E\u308A + \u884C\u306E\u9AD8\u3055 * idx;
7493
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-radial-item", children: [
7494
+ /* @__PURE__ */ jsx("rect", { x: PAD, y: y - 11, width: 4, height: 22, rx: 2, fill: arcColor2(d.tone, idx) }),
7495
+ /* @__PURE__ */ jsx(
7496
+ "text",
7497
+ {
7498
+ x: PAD + \u5370\u306E\u5E45,
7499
+ y: y + 1,
7500
+ fontSize: \u540D\u524D\u306E\u7D1A,
7501
+ fontWeight: 700,
7502
+ fill: "var(--cdl-text, #1a1f2a)",
7503
+ children: d.label
7504
+ }
7505
+ ),
7506
+ /* @__PURE__ */ jsx(
7507
+ "text",
7508
+ {
7509
+ x: PAD + \u5370\u306E\u5E45,
7510
+ y: y + 20,
7511
+ fontSize: \u6570\u5024\u306E\u7D1A,
7512
+ fill: "var(--cdl-text-dim, #5a6270)",
7513
+ children: \u6570\u5024\u306E\u6587\u5B57[idx]
7514
+ }
7515
+ )
7516
+ ] }, `item-${idx}`);
7517
+ })
7518
+ ] });
7519
+ }
7520
+ var \u5370\u306E\u5E45 = 18;
7521
+ function \u5F27\u306E\u9053(cx, cy, \u4E2D\u5FC3\u534A\u5F84, \u5E45, \u5272\u5408) {
7522
+ const \u5916 = \u4E2D\u5FC3\u534A\u5F84 + \u5E45 / 2;
7523
+ const \u5185 = Math.max(0.5, \u4E2D\u5FC3\u534A\u5F84 - \u5E45 / 2);
7524
+ const a0 = -Math.PI / 2;
7525
+ const a1 = a0 + \u5272\u5408 * Math.PI * 2;
7526
+ const large = \u5272\u5408 > 0.5 ? 1 : 0;
7527
+ const p = (r, a) => `${cx + r * Math.cos(a)} ${cy + r * Math.sin(a)}`;
7528
+ return `M ${p(\u5916, a0)} A ${\u5916} ${\u5916} 0 ${large} 1 ${p(\u5916, a1)} L ${p(\u5185, a1)} A ${\u5185} ${\u5185} 0 ${large} 0 ${p(\u5185, a0)} Z`;
7529
+ }
7530
+ function \u5B9F\u5024\u8868\u8A183(v) {
7531
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
7532
+ }
7533
+ function \u5272\u5408\u8868\u8A183(frac) {
7534
+ const v = Math.round(frac * 1e3) / 10;
7535
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
7536
+ }
7537
+ function arcColor2(tone, idx) {
7538
+ if (tone) return TONE[tone];
7539
+ return chartSeriesColor(idx);
7540
+ }
7541
+ function ChartStatNode({
7542
+ node,
7543
+ active,
7544
+ stateValues = {}
7545
+ }) {
7546
+ const x0 = node.cx - node.w / 2;
7547
+ const y0 = node.cy - node.h / 2;
7548
+ const data = resolveChartData(node.chartData ?? [], stateValues);
7549
+ const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
7550
+ const \u533A\u753B = \u533A\u753B\u306E\u5272\u4ED8(node.w, node.h, data.length);
7551
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
7552
+ /* @__PURE__ */ jsx(
7553
+ "rect",
7554
+ {
7555
+ "data-cdl-role": "node-body",
7556
+ x: 0,
7557
+ y: 0,
7558
+ width: node.w,
7559
+ height: node.h,
7560
+ rx: 16,
7561
+ fill: "var(--cdl-node-fill, #ffffff)",
7562
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
7563
+ strokeWidth: active ? 3 : 1.25
7564
+ }
7565
+ ),
7566
+ data.map((d, idx) => {
7567
+ const \u67A0 = \u533A\u753B.\u67A0(idx);
7568
+ const frac = total > 0 ? d.value / total : 0;
7569
+ const \u8272 = \u5370\u306E\u8272(d.tone, idx);
7570
+ const \u6570\u5024 = \u5B9F\u5024\u8868\u8A184(d.value);
7571
+ const \u6570\u5024\u306E\u7D1A = \u53CE\u3081\u308B\u7D1A(\u6570\u5024, \u67A0.w - \u533A\u753B.\u4F59\u767D * 2, \u533A\u753B.\u6570\u5024\u306E\u7D1A, \u533A\u753B.\u540D\u524D\u306E\u7D1A + 1);
7572
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-stat-item", transform: `translate(${\u67A0.x} ${\u67A0.y})`, children: [
7573
+ idx > 0 && /* @__PURE__ */ jsx(
7574
+ "line",
7575
+ {
7576
+ "data-cdl-role": "chart-stat-divider",
7577
+ x1: 0,
7578
+ y1: \u533A\u753B.\u4F59\u767D,
7579
+ x2: 0,
7580
+ y2: \u67A0.h - \u533A\u753B.\u4F59\u767D,
7581
+ stroke: "var(--cdl-divider, #d4d4d8)",
7582
+ strokeWidth: 1
7583
+ }
7584
+ ),
7585
+ /* @__PURE__ */ jsx(
7586
+ "text",
7587
+ {
7588
+ "data-cdl-role": "chart-stat-label",
7589
+ x: \u67A0.w / 2,
7590
+ y: \u533A\u753B.\u540D\u524D\u306Ey,
7591
+ fontSize: \u533A\u753B.\u540D\u524D\u306E\u7D1A,
7592
+ fontWeight: 700,
7593
+ textAnchor: "middle",
7594
+ fill: "var(--cdl-text-dim, #5a6270)",
7595
+ children: d.label
7596
+ }
7597
+ ),
7598
+ /* @__PURE__ */ jsx(
7599
+ "text",
7600
+ {
7601
+ "data-cdl-role": "chart-stat-value",
7602
+ "data-cdl-unresolved": d.unresolved ? "true" : void 0,
7603
+ x: \u67A0.w / 2,
7604
+ y: \u533A\u753B.\u6570\u5024\u306Ey,
7605
+ fontSize: \u6570\u5024\u306E\u7D1A,
7606
+ fontWeight: 700,
7607
+ textAnchor: "middle",
7608
+ fill: \u8272,
7609
+ children: \u6570\u5024
7610
+ }
7611
+ ),
7612
+ /* @__PURE__ */ jsx(
7613
+ "circle",
7614
+ {
7615
+ "data-cdl-role": "chart-stat-track",
7616
+ cx: \u67A0.w / 2,
7617
+ cy: \u533A\u753B.\u5F27\u306Ey,
7618
+ r: \u533A\u753B.\u5F27\u306E\u534A\u5F84,
7619
+ fill: "none",
7620
+ stroke: "var(--cdl-divider, #d4d4d8)",
7621
+ strokeWidth: \u533A\u753B.\u5F27\u306E\u592A\u3055,
7622
+ strokeOpacity: 0.5
7623
+ }
7624
+ ),
7625
+ frac > 0 && /* @__PURE__ */ jsx(
7626
+ "path",
7627
+ {
7628
+ "data-cdl-role": "chart-stat-arc",
7629
+ d: \u5F27\u306E\u90532(\u67A0.w / 2, \u533A\u753B.\u5F27\u306Ey, \u533A\u753B.\u5F27\u306E\u534A\u5F84, Math.min(frac, 0.9999)),
7630
+ fill: "none",
7631
+ stroke: \u8272,
7632
+ strokeWidth: \u533A\u753B.\u5F27\u306E\u592A\u3055,
7633
+ strokeLinecap: "round"
7634
+ }
7635
+ ),
7636
+ /* @__PURE__ */ jsx(
7637
+ "text",
7638
+ {
7639
+ "data-cdl-role": "chart-stat-share",
7640
+ x: \u67A0.w / 2,
7641
+ y: \u533A\u753B.\u5272\u5408\u306Ey,
7642
+ fontSize: \u533A\u753B.\u5272\u5408\u306E\u7D1A,
7643
+ textAnchor: "middle",
7644
+ fill: "var(--cdl-text-dim, #5a6270)",
7645
+ children: \u5272\u5408\u8868\u8A184(frac)
7646
+ }
7647
+ )
7648
+ ] }, `stat-${idx}`);
7649
+ })
7650
+ ] });
7651
+ }
7652
+ function \u533A\u753B\u306E\u5272\u4ED8(w, h, \u4EF6\u6570) {
7653
+ const \u4F59\u767D = 20;
7654
+ const \u5E45 = \u4EF6\u6570 > 0 ? w / \u4EF6\u6570 : w;
7655
+ const \u540D\u524D\u306E\u7D1A = 14;
7656
+ const \u6570\u5024\u306E\u7D1A = 40;
7657
+ const \u5272\u5408\u306E\u7D1A = 12;
7658
+ const \u5F27\u306E\u534A\u5F84 = 20;
7659
+ const \u5F27\u306E\u592A\u3055 = 4;
7660
+ const \u4E2D\u8EAB\u306E\u9AD8\u3055 = \u540D\u524D\u306E\u7D1A + 12 + \u6570\u5024\u306E\u7D1A + 16 + \u5F27\u306E\u534A\u5F84 * 2 + 8 + \u5272\u5408\u306E\u7D1A;
7661
+ const \u4E0A\u7AEF = Math.max(\u4F59\u767D, (h - \u4E2D\u8EAB\u306E\u9AD8\u3055) / 2);
7662
+ const \u540D\u524D\u306Ey = \u4E0A\u7AEF + \u540D\u524D\u306E\u7D1A;
7663
+ const \u6570\u5024\u306Ey = \u540D\u524D\u306Ey + 12 + \u6570\u5024\u306E\u7D1A * 0.78;
7664
+ const \u5F27\u306Ey = \u6570\u5024\u306Ey + 16 + \u5F27\u306E\u534A\u5F84;
7665
+ const \u5272\u5408\u306Ey = \u5F27\u306Ey + \u5F27\u306E\u534A\u5F84 + 8 + \u5272\u5408\u306E\u7D1A;
7666
+ return {
7667
+ \u4F59\u767D,
7668
+ \u540D\u524D\u306E\u7D1A,
7669
+ \u6570\u5024\u306E\u7D1A,
7670
+ \u5272\u5408\u306E\u7D1A,
7671
+ \u5F27\u306E\u534A\u5F84,
7672
+ \u5F27\u306E\u592A\u3055,
7673
+ \u540D\u524D\u306Ey,
7674
+ \u6570\u5024\u306Ey,
7675
+ \u5F27\u306Ey,
7676
+ \u5272\u5408\u306Ey,
7677
+ \u67A0: (idx) => ({ x: \u5E45 * idx, y: 0, w: \u5E45, h })
7678
+ };
7679
+ }
7680
+ function \u53CE\u3081\u308B\u7D1A(\u5B57, \u4F7F\u3048\u308B\u5E452, \u521D\u671F, \u4E0B\u9650) {
7681
+ let \u7D1A = \u521D\u671F;
7682
+ while (\u7D1A > \u4E0B\u9650 && textWidth(\u5B57, \u7D1A) > \u4F7F\u3048\u308B\u5E452) \u7D1A -= 1;
7683
+ return \u7D1A;
7684
+ }
7685
+ function \u5F27\u306E\u90532(cx, cy, r, \u5272\u5408) {
7686
+ const a0 = -Math.PI / 2;
7687
+ const a1 = a0 + \u5272\u5408 * Math.PI * 2;
7688
+ const large = \u5272\u5408 > 0.5 ? 1 : 0;
7689
+ const p = (a) => `${cx + r * Math.cos(a)} ${cy + r * Math.sin(a)}`;
7690
+ return `M ${p(a0)} A ${r} ${r} 0 ${large} 1 ${p(a1)}`;
7691
+ }
7692
+ function \u5B9F\u5024\u8868\u8A184(v) {
7693
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
7694
+ }
7695
+ function \u5272\u5408\u8868\u8A184(frac) {
7696
+ const v = Math.round(frac * 1e3) / 10;
7697
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
7698
+ }
7699
+ function \u5370\u306E\u8272(tone, idx) {
7700
+ if (tone) return TONE[tone];
7701
+ return chartSeriesColor(idx);
7702
+ }
7703
+ var WAFFLE_TOTAL = 100;
7704
+ var WAFFLE_COLS = 10;
7705
+ function \u5370\u306E\u5272\u4ED8(\u5024) {
7706
+ const \u5408\u8A08 = \u5024.reduce((a, v) => a + Math.max(0, v), 0);
7707
+ if (\u5408\u8A08 <= 0) return \u5024.map(() => 0);
7708
+ const \u751F = \u5024.map((v) => Math.max(0, v) / \u5408\u8A08 * WAFFLE_TOTAL);
7709
+ const \u914D\u5206 = \u751F.map((v) => Math.floor(v));
7710
+ let \u4F59\u308A = WAFFLE_TOTAL - \u914D\u5206.reduce((a, v) => a + v, 0);
7711
+ const \u9806 = \u751F.map((v, i) => ({ i, \u5C0F\u6570\u90E8: v - Math.floor(v) })).sort((a, b) => b.\u5C0F\u6570\u90E8 - a.\u5C0F\u6570\u90E8 || a.i - b.i);
7712
+ for (let k = 0; \u4F59\u308A > 0; k = (k + 1) % \u9806.length) {
7713
+ const i = \u9806[k].i;
7714
+ \u914D\u5206[i] = (\u914D\u5206[i] ?? 0) + 1;
7715
+ \u4F59\u308A -= 1;
7716
+ }
7717
+ return \u914D\u5206;
7718
+ }
7719
+ function ChartWaffleNode({
7720
+ node,
7721
+ active,
7722
+ stateValues = {}
7723
+ }) {
7724
+ const x0 = node.cx - node.w / 2;
7725
+ const y0 = node.cy - node.h / 2;
7726
+ const data = resolveChartData(node.chartData ?? [], stateValues);
7727
+ const \u914D\u5206 = \u5370\u306E\u5272\u4ED8(data.map((d) => d.value));
7728
+ const PAD = 20;
7729
+ const \u540D\u524D\u306E\u7D1A = 14;
7730
+ const \u6570\u5024\u306E\u7D1A = 13;
7731
+ const \u884C\u306E\u9AD8\u3055 = 40;
7732
+ const \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593 = 28;
7733
+ const \u5370\u306E\u5E452 = 18;
7734
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map((d, i) => `${\u5B9F\u5024\u8868\u8A185(d.value)} ${\u914D\u5206[i] ?? 0}%`);
7735
+ const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E452 + Math.max(
7736
+ 0,
7737
+ ...data.map(
7738
+ (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
7739
+ )
7740
+ );
7741
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD * 2;
7742
+ const \u683C\u5B50\u306B\u4F7F\u3048\u308B\u5E45 = node.w - PAD * 2 - \u4E00\u89A7\u306E\u5E45 - \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593;
7743
+ const \u5347 = Math.max(4, Math.min(\u4F7F\u3048\u308B\u9AD8\u3055, \u683C\u5B50\u306B\u4F7F\u3048\u308B\u5E45) / WAFFLE_COLS);
7744
+ const \u5370 = \u5347 * 0.78;
7745
+ const \u683C\u5B50\u306E\u5DE6 = PAD + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593;
7746
+ const \u683C\u5B50\u306E\u4E0A = PAD + (\u4F7F\u3048\u308B\u9AD8\u3055 - \u5347 * WAFFLE_COLS) / 2;
7747
+ const \u6301\u3061\u4E3B = [];
7748
+ \u914D\u5206.forEach((n, idx) => {
7749
+ for (let k = 0; k < n; k++) \u6301\u3061\u4E3B.push(idx);
7750
+ });
7751
+ const \u4E00\u89A7\u306E\u59CB\u307E\u308A = PAD + (\u4F7F\u3048\u308B\u9AD8\u3055 - \u884C\u306E\u9AD8\u3055 * data.length) / 2 + \u884C\u306E\u9AD8\u3055 / 2;
7752
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
7753
+ /* @__PURE__ */ jsx(
7754
+ "rect",
7755
+ {
7756
+ "data-cdl-role": "node-body",
7757
+ x: 0,
7758
+ y: 0,
7759
+ width: node.w,
7760
+ height: node.h,
7761
+ rx: 16,
7762
+ fill: "var(--cdl-node-fill, #ffffff)",
7763
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
7764
+ strokeWidth: active ? 3 : 1.25
7765
+ }
7766
+ ),
7767
+ Array.from({ length: WAFFLE_TOTAL }, (_, k) => {
7768
+ const \u884C = Math.floor(k / WAFFLE_COLS);
7769
+ const \u5217 = k % WAFFLE_COLS;
7770
+ const owner = \u6301\u3061\u4E3B[k];
7771
+ return /* @__PURE__ */ jsx(
7772
+ "rect",
7773
+ {
7774
+ "data-cdl-role": "chart-waffle-cell",
7775
+ "data-cdl-waffle-owner": owner === void 0 ? "" : String(owner),
7776
+ x: \u683C\u5B50\u306E\u5DE6 + \u5347 * \u5217 + (\u5347 - \u5370) / 2,
7777
+ y: \u683C\u5B50\u306E\u4E0A + \u5347 * \u884C + (\u5347 - \u5370) / 2,
7778
+ width: \u5370,
7779
+ height: \u5370,
7780
+ rx: 2,
7781
+ fill: owner === void 0 ? "var(--cdl-divider, #d4d4d8)" : \u5370\u306E\u82722(data[owner].tone, owner),
7782
+ fillOpacity: owner === void 0 ? 0.35 : 1
7783
+ },
7784
+ `cell-${k}`
7785
+ );
7786
+ }),
7787
+ data.map((d, idx) => {
7788
+ const y = \u4E00\u89A7\u306E\u59CB\u307E\u308A + \u884C\u306E\u9AD8\u3055 * idx;
7789
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-waffle-item", children: [
7790
+ /* @__PURE__ */ jsx("rect", { x: PAD, y: y - 11, width: 4, height: 22, rx: 2, fill: \u5370\u306E\u82722(d.tone, idx) }),
7791
+ /* @__PURE__ */ jsx(
7792
+ "text",
7793
+ {
7794
+ x: PAD + \u5370\u306E\u5E452,
7795
+ y: y + 1,
7796
+ fontSize: \u540D\u524D\u306E\u7D1A,
7797
+ fontWeight: 700,
7798
+ fill: "var(--cdl-text, #1a1f2a)",
7799
+ children: d.label
7800
+ }
7801
+ ),
7802
+ /* @__PURE__ */ jsx(
7803
+ "text",
7804
+ {
7805
+ "data-cdl-role": "chart-waffle-count",
7806
+ "data-cdl-unresolved": d.unresolved ? "true" : void 0,
7807
+ x: PAD + \u5370\u306E\u5E452,
7808
+ y: y + 20,
7809
+ fontSize: \u6570\u5024\u306E\u7D1A,
7810
+ fill: "var(--cdl-text-dim, #5a6270)",
7811
+ children: \u6570\u5024\u306E\u6587\u5B57[idx]
7812
+ }
7813
+ )
7814
+ ] }, `item-${idx}`);
7815
+ })
7816
+ ] });
7817
+ }
7818
+ function \u5B9F\u5024\u8868\u8A185(v) {
7819
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
7820
+ }
7821
+ function \u5370\u306E\u82722(tone, idx) {
7822
+ if (tone) return TONE[tone];
7823
+ return chartSeriesColor(idx);
7824
+ }
7825
+ var SLICE_MIN_W_FOR_TEXT = 44;
7826
+ var SLICE_MIN_W_FOR_VALUE = 84;
7827
+ function ChartStackedBarNode({
7828
+ node,
7829
+ active,
7830
+ stateValues = {}
7831
+ }) {
7832
+ const x0 = node.cx - node.w / 2;
7833
+ const y0 = node.cy - node.h / 2;
7834
+ const data = resolveChartData(node.chartData ?? [], stateValues);
7835
+ const \u5E2F\u305F\u3061 = \u5E2F\u306E\u4E26\u3073(data);
7836
+ const PAD = 24;
7837
+ const \u540D\u524D\u306E\u7D1A = 13;
7838
+ const \u533A\u753B\u306E\u7D1A = 12;
7839
+ const \u6642\u70B9\u306E\u7D1A = 13;
7840
+ const \u6642\u70B9\u306E\u5E45 = Math.max(0, ...\u5E2F\u305F\u3061.map((b) => textWidth(b.\u540D\u524D, \u6642\u70B9\u306E\u7D1A))) + (\u5E2F\u305F\u3061.length > 1 ? 16 : 0);
7841
+ const \u5E2F\u306E\u5DE6 = PAD + \u6642\u70B9\u306E\u5E45;
7842
+ const \u5E2F\u306E\u5E45 = Math.max(40, node.w - \u5E2F\u306E\u5DE6 - PAD);
7843
+ const \u5E2F\u306E\u9AD8\u3055 = 44;
7844
+ const \u5E2F\u306E\u9593 = 20;
7845
+ const \u4E00\u89A7\u306E\u9AD8\u3055 = 26;
7846
+ const \u5168\u4F53\u306E\u9AD8\u3055 = \u5E2F\u305F\u3061.length * \u5E2F\u306E\u9AD8\u3055 + (\u5E2F\u305F\u3061.length - 1) * \u5E2F\u306E\u9593 + 16 + \u4E00\u89A7\u306E\u9AD8\u3055;
7847
+ const \u4E0A\u7AEF = Math.max(PAD, (node.h - \u5168\u4F53\u306E\u9AD8\u3055) / 2);
7848
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
7849
+ /* @__PURE__ */ jsx(
7850
+ "rect",
7851
+ {
7852
+ "data-cdl-role": "node-body",
7853
+ x: 0,
7854
+ y: 0,
7855
+ width: node.w,
7856
+ height: node.h,
7857
+ rx: 16,
7858
+ fill: "var(--cdl-node-fill, #ffffff)",
7859
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
7860
+ strokeWidth: active ? 3 : 1.25
7861
+ }
7862
+ ),
7863
+ \u5E2F\u305F\u3061.map((\u5E2F, \u6BB5) => {
7864
+ const y = \u4E0A\u7AEF + \u6BB5 * (\u5E2F\u306E\u9AD8\u3055 + \u5E2F\u306E\u9593);
7865
+ let \u5DE6 = \u5E2F\u306E\u5DE6;
7866
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-stacked-bar-row", children: [
7867
+ \u5E2F\u305F\u3061.length > 1 && /* @__PURE__ */ jsx(
7868
+ "text",
7869
+ {
7870
+ "data-cdl-role": "chart-stacked-bar-period",
7871
+ x: PAD,
7872
+ y: y + \u5E2F\u306E\u9AD8\u3055 / 2 + 4,
7873
+ fontSize: \u6642\u70B9\u306E\u7D1A,
7874
+ fontWeight: 700,
7875
+ fill: "var(--cdl-text-dim, #5a6270)",
7876
+ children: \u5E2F.\u540D\u524D
7877
+ }
7878
+ ),
7879
+ \u5E2F.\u533A\u753B.map((s, idx) => {
7880
+ const w = \u5E2F\u306E\u5E45 * s.\u5272\u5408;
7881
+ const x = \u5DE6;
7882
+ \u5DE6 += w;
7883
+ const \u8272 = \u5370\u306E\u82723(s.tone, idx);
7884
+ return /* @__PURE__ */ jsxs("g", { children: [
7885
+ /* @__PURE__ */ jsx(
7886
+ "rect",
7887
+ {
7888
+ "data-cdl-role": "chart-stacked-bar-slice",
7889
+ "data-cdl-unresolved": s.unresolved ? "true" : void 0,
7890
+ x,
7891
+ y,
7892
+ width: Math.max(0, w),
7893
+ height: \u5E2F\u306E\u9AD8\u3055,
7894
+ fill: \u8272
7895
+ }
7896
+ ),
7897
+ w >= SLICE_MIN_W_FOR_TEXT && /* @__PURE__ */ jsx(
7898
+ "text",
7899
+ {
7900
+ "data-cdl-role": "chart-stacked-bar-slice-text",
7901
+ x: x + w / 2,
7902
+ y: y + \u5E2F\u306E\u9AD8\u3055 / 2 + (w >= SLICE_MIN_W_FOR_VALUE ? -2 : 4),
7903
+ fontSize: \u533A\u753B\u306E\u7D1A,
7904
+ fontWeight: 700,
7905
+ textAnchor: "middle",
7906
+ fill: "#ffffff",
7907
+ children: \u5272\u5408\u8868\u8A185(s.\u5272\u5408)
7908
+ }
7909
+ ),
7910
+ w >= SLICE_MIN_W_FOR_VALUE && /* @__PURE__ */ jsx(
7911
+ "text",
7912
+ {
7913
+ "data-cdl-role": "chart-stacked-bar-slice-value",
7914
+ x: x + w / 2,
7915
+ y: y + \u5E2F\u306E\u9AD8\u3055 / 2 + 13,
7916
+ fontSize: \u533A\u753B\u306E\u7D1A - 1,
7917
+ textAnchor: "middle",
7918
+ fill: "#ffffff",
7919
+ fillOpacity: 0.85,
7920
+ children: \u5B9F\u5024\u8868\u8A186(s.\u5B9F\u5024)
7921
+ }
7922
+ )
7923
+ ] }, `slice-${idx}`);
7924
+ })
7925
+ ] }, `bar-${\u6BB5}`);
7926
+ }),
7927
+ \u4E00\u89A7\u306E\u4E26\u3073(data, \u5E2F\u306E\u5DE6, node.w - PAD, \u540D\u524D\u306E\u7D1A).map(({ d, idx, x, \u884C }) => {
7928
+ const y = \u4E0A\u7AEF + \u5E2F\u305F\u3061.length * (\u5E2F\u306E\u9AD8\u3055 + \u5E2F\u306E\u9593) - \u5E2F\u306E\u9593 + 16 + \u4E00\u89A7\u306E\u9AD8\u3055 / 2 + \u884C * \u4E00\u89A7\u306E\u9AD8\u3055;
7929
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-stacked-bar-legend", children: [
7930
+ /* @__PURE__ */ jsx("rect", { x, y: y - 5, width: 10, height: 10, rx: 2, fill: \u5370\u306E\u82723(d.tone, idx) }),
7931
+ /* @__PURE__ */ jsx(
7932
+ "text",
7933
+ {
7934
+ x: x + 16,
7935
+ y: y + 4,
7936
+ fontSize: \u540D\u524D\u306E\u7D1A,
7937
+ fill: "var(--cdl-text, #1a1f2a)",
7938
+ children: d.label
7939
+ }
7940
+ )
7941
+ ] }, `legend-${idx}`);
7942
+ })
7943
+ ] });
7944
+ }
7945
+ function \u5E2F\u306E\u4E26\u3073(data) {
7946
+ const \u524D\u3042\u308A = data.some((d) => d.previous !== void 0);
7947
+ const \u4ECA = \u5E2F\u3092\u7D44\u3080("\u4ECA", data, (d) => d.value);
7948
+ if (!\u524D\u3042\u308A) return [\u4ECA];
7949
+ return [\u5E2F\u3092\u7D44\u3080("\u524D", data, (d) => d.previous ?? 0), \u4ECA];
7950
+ }
7951
+ function \u5E2F\u3092\u7D44\u3080(\u540D\u524D, data, \u53D6\u308B) {
7952
+ const \u5024 = data.map((d) => Math.max(0, \u53D6\u308B(d)));
7953
+ const \u5408\u8A08 = \u5024.reduce((a, v) => a + v, 0);
7954
+ return {
7955
+ \u540D\u524D,
7956
+ \u533A\u753B: data.map((d, i) => ({
7957
+ // 合計 0 の帯は区画を持たない (0 で割らない)。 幅 0 の区画として並べる
7958
+ \u5272\u5408: \u5408\u8A08 > 0 ? \u5024[i] / \u5408\u8A08 : 0,
7959
+ \u5B9F\u5024: \u5024[i],
7960
+ tone: d.tone,
7961
+ ...d.unresolved ? { unresolved: true } : {}
7962
+ }))
7963
+ };
7964
+ }
7965
+ function \u5B9F\u5024\u8868\u8A186(v) {
7966
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
7967
+ }
7968
+ function \u5272\u5408\u8868\u8A185(frac) {
7969
+ const v = Math.round(frac * 1e3) / 10;
7970
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
7971
+ }
7972
+ function \u5370\u306E\u82723(tone, idx) {
7973
+ if (tone) return TONE[tone];
7974
+ return chartSeriesColor(idx);
7975
+ }
7976
+ var \u5370\u304B\u3089\u540D\u524D\u307E\u3067 = 16;
7977
+ var \u4EF6\u306E\u9593 = 10;
7978
+ function \u4E00\u89A7\u306E\u4E26\u3073(data, \u5DE6, \u53F3\u7AEF, \u7D1A) {
7979
+ const out = [];
7980
+ let x = \u5DE6;
7981
+ let \u884C = 0;
7982
+ data.forEach((d, idx) => {
7983
+ const \u5E45 = \u5370\u304B\u3089\u540D\u524D\u307E\u3067 + textWidth(d.label ?? "", \u7D1A);
7984
+ if (x > \u5DE6 && x + \u5E45 > \u53F3\u7AEF) {
7985
+ \u884C += 1;
7986
+ x = \u5DE6;
7987
+ }
7988
+ out.push({ d, idx, x, \u884C });
7989
+ x += \u5E45 + \u4EF6\u306E\u9593;
7990
+ });
7991
+ return out;
6947
7992
  }
6948
7993
  function ChartBarNode({
6949
7994
  node,
@@ -12494,6 +13539,16 @@ function CdlNodeView({
12494
13539
  progress
12495
13540
  }
12496
13541
  );
13542
+ case "chart-gauge":
13543
+ return /* @__PURE__ */ jsx(ChartGaugeNode, { node: resolvedNode, active, stateValues });
13544
+ case "chart-stacked-bar":
13545
+ return /* @__PURE__ */ jsx(ChartStackedBarNode, { node: resolvedNode, active, stateValues });
13546
+ case "chart-waffle":
13547
+ return /* @__PURE__ */ jsx(ChartWaffleNode, { node: resolvedNode, active, stateValues });
13548
+ case "chart-stat":
13549
+ return /* @__PURE__ */ jsx(ChartStatNode, { node: resolvedNode, active, stateValues });
13550
+ case "chart-radial":
13551
+ return /* @__PURE__ */ jsx(ChartRadialNode, { node: resolvedNode, active, stateValues });
12497
13552
  case "chart-bar":
12498
13553
  return /* @__PURE__ */ jsx(
12499
13554
  ChartBarNode,
@@ -12660,6 +13715,10 @@ function CdlNodeView({
12660
13715
  return /* @__PURE__ */ jsx(ShapeTraderNode, { node: resolvedNode, active });
12661
13716
  case "shape-customer-service":
12662
13717
  return /* @__PURE__ */ jsx(ShapeCustomerServiceNode, { node: resolvedNode, active });
13718
+ case "mark-start":
13719
+ return /* @__PURE__ */ jsx(MarkStartNode, { node: resolvedNode, active });
13720
+ case "mark-end":
13721
+ return /* @__PURE__ */ jsx(MarkEndNode, { node: resolvedNode, active });
12663
13722
  default:
12664
13723
  return /* @__PURE__ */ jsx(GenericNode, { node: resolvedNode, active, value: node.value, stateValues });
12665
13724
  }
@@ -12729,6 +13788,21 @@ function uniformLifelineEndY(lanes, nodes, starts = lifelineStartYs(nodes)) {
12729
13788
  if (footerTops.length > 0) return Math.min(...footerTops);
12730
13789
  return lifelineLanes[0] ? lifelineLanes[0].y + lifelineLanes[0].height : 0;
12731
13790
  }
13791
+
13792
+ // src/kinds/draw-ratio.ts
13793
+ var DRAW_RATIO_DEFAULT = 1;
13794
+ function \u63CF\u304F\u5272\u5408\u3092\u6B63\u3059(ratio) {
13795
+ if (ratio === void 0) return DRAW_RATIO_DEFAULT;
13796
+ if (!Number.isFinite(ratio)) return DRAW_RATIO_DEFAULT;
13797
+ if (ratio <= 0 || ratio > 1) return DRAW_RATIO_DEFAULT;
13798
+ return ratio;
13799
+ }
13800
+ function \u63CF\u304F\u9032\u307F\u306B\u76F4\u3059(progress, ratio) {
13801
+ const \u5272\u5408 = \u63CF\u304F\u5272\u5408\u3092\u6B63\u3059(ratio);
13802
+ if (\u5272\u5408 === DRAW_RATIO_DEFAULT) return progress;
13803
+ if (!Number.isFinite(progress)) return progress;
13804
+ return Math.min(1, progress / \u5272\u5408);
13805
+ }
12732
13806
  function CdlStage({
12733
13807
  laid,
12734
13808
  currentPhase,
@@ -12740,6 +13814,7 @@ function CdlStage({
12740
13814
  }) {
12741
13815
  const activeSet = new Set(currentPhase?.activate ?? []);
12742
13816
  const drawSet = new Set(currentPhase?.draw ?? []);
13817
+ const \u63CF\u304F\u9032\u307F = \u63CF\u304F\u9032\u307F\u306B\u76F4\u3059(progress, currentPhase?.drawRatio);
12743
13818
  const { lifelineStarts, uniformFooterTop } = useMemo(() => {
12744
13819
  const starts = lifelineStartYs(laid.nodes);
12745
13820
  return {
@@ -12764,21 +13839,38 @@ function CdlStage({
12764
13839
  children: [
12765
13840
  /* @__PURE__ */ jsxs("defs", { children: [
12766
13841
  Object.entries(TONE).flatMap(
12767
- ([tone, color]) => [["", 14], ["-sm", 10]].map(([suffix, size]) => /* @__PURE__ */ jsx(
12768
- "marker",
12769
- {
12770
- id: `cdl-arrow-${tone}${suffix}`,
12771
- viewBox: "0 0 10 10",
12772
- refX: "9",
12773
- refY: "5",
12774
- markerWidth: size,
12775
- markerHeight: size,
12776
- markerUnits: "userSpaceOnUse",
12777
- orient: "auto-start-reverse",
12778
- children: /* @__PURE__ */ jsx("path", { "data-cdl-role": "edge-arrowhead", d: "M 0 0 L 10 5 L 0 10 z", fill: color })
12779
- },
12780
- `${tone}${suffix}`
12781
- ))
13842
+ ([tone, color]) => [["", 14], ["-sm", 10]].flatMap(
13843
+ ([suffix, size]) => EDGE_HEADS.map((head) => {
13844
+ const \u5F62 = EDGE_HEAD_SHAPE[head];
13845
+ return /* @__PURE__ */ jsx(
13846
+ "marker",
13847
+ {
13848
+ id: edgeHeadMarkerId(tone, head, suffix === "-sm"),
13849
+ viewBox: "0 0 10 10",
13850
+ refX: \u5F62.refX,
13851
+ refY: "5",
13852
+ markerWidth: size,
13853
+ markerHeight: size,
13854
+ markerUnits: "userSpaceOnUse",
13855
+ orient: "auto-start-reverse",
13856
+ children: /* @__PURE__ */ jsx(
13857
+ "path",
13858
+ {
13859
+ "data-cdl-role": "edge-arrowhead",
13860
+ "data-cdl-edge-head": head,
13861
+ d: \u5F62.d,
13862
+ fill: \u5F62.filled ? color : "none",
13863
+ stroke: \u5F62.filled ? "none" : color,
13864
+ strokeWidth: \u5F62.filled ? void 0 : 1.6,
13865
+ strokeLinecap: \u5F62.filled ? void 0 : "round",
13866
+ strokeLinejoin: \u5F62.filled ? void 0 : "round"
13867
+ }
13868
+ )
13869
+ },
13870
+ `${tone}${suffix}-${head}`
13871
+ );
13872
+ })
13873
+ )
12782
13874
  ),
12783
13875
  /* @__PURE__ */ jsx(
12784
13876
  "marker",
@@ -12871,13 +13963,14 @@ function CdlStage({
12871
13963
  )),
12872
13964
  laid.edges.map((edge) => /* @__PURE__ */ jsx(CdlEdgeView, { edge, active: activeSet.has(edge.id), progress, stateValues }, edge.id)),
12873
13965
  laid.nodes.map((node) => {
13966
+ const \u63CF\u304F = drawSet.has(node.id);
12874
13967
  const view = /* @__PURE__ */ jsx(
12875
13968
  CdlNodeView,
12876
13969
  {
12877
13970
  node,
12878
13971
  active: activeSet.has(node.id),
12879
- drawing: drawSet.has(node.id),
12880
- progress,
13972
+ drawing: \u63CF\u304F,
13973
+ progress: \u63CF\u304F ? \u63CF\u304F\u9032\u307F : progress,
12881
13974
  stateValues,
12882
13975
  currentPhaseId: currentPhase?.id
12883
13976
  }
@@ -21690,6 +22783,11 @@ var GRID_ALIGNED_KINDS = /* @__PURE__ */ new Set([
21690
22783
  "chart-pie",
21691
22784
  "chart-line",
21692
22785
  "chart-bar",
22786
+ "chart-gauge",
22787
+ "chart-radial",
22788
+ "chart-stat",
22789
+ "chart-waffle",
22790
+ "chart-stacked-bar",
21693
22791
  "funnel-stages",
21694
22792
  "quadrant-matrix"
21695
22793
  ]);
@@ -21779,6 +22877,7 @@ function emptyCounts() {
21779
22877
  "row-gap-uniform": 0,
21780
22878
  "column-gap-uniform": 0,
21781
22879
  "rows-not-rendered": 0,
22880
+ "title-row-overlap": 0,
21782
22881
  "malformed-input": 0,
21783
22882
  "validation-interrupted": 0
21784
22883
  };
@@ -22909,6 +24008,21 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
22909
24008
  `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)`
22910
24009
  );
22911
24010
  }
24011
+ for (const n of diag.nodes) {
24012
+ if (!n.rows || n.rows.length === 0) continue;
24013
+ if (!rendersRows(n.kind)) continue;
24014
+ if (n.kind === "storage") continue;
24015
+ if (typeof n.h !== "number") continue;
24016
+ const \u984C = genericTitleBaselineY(n.kind, n.h, true);
24017
+ const \u884C = rowBaselineY(n.kind, 0);
24018
+ if (\u884C === null) continue;
24019
+ const \u9593 = \u884C - \u984C;
24020
+ if (\u9593 >= TITLE_ROW_MIN_GAP) continue;
24021
+ push(
24022
+ "title-row-overlap",
24023
+ `node "${n.id}" (kind=${n.kind ?? "\u672A\u6307\u5B9A"}) \u306E\u984C baseline y=${\u984C.toFixed(0)} \u3068 1 \u884C\u76EE baseline y=${\u884C.toFixed(0)} \u306E\u9593\u304C ${\u9593.toFixed(0)} world \u3067\u3001 \u898B\u8FBC\u3080\u5B57\u5F62\u306E\u9AD8\u3055 ${TITLE_ROW_MIN_GAP.toFixed(0)} \u306B\u5C4A\u304B\u306A\u3044 (\u5B57\u304C\u91CD\u306A\u308B)`
24024
+ );
24025
+ }
22912
24026
  const GROUP_INTERNAL_PAD = 20;
22913
24027
  const GROUP_EXTERNAL_CLEAR = 16;
22914
24028
  for (const lane of laid.lanes) {
@@ -23266,6 +24380,12 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
23266
24380
  `edge "${e.id}" tone "${e.tone}" \u304C TONE_COLORS \u5B9A\u7FA9\u306B\u5B58\u5728\u3057\u306A\u3044\u3001 marker "cdl-arrow-${e.tone}" dead ref`
23267
24381
  );
23268
24382
  }
24383
+ if (e.head !== void 0 && !EDGE_HEADS.includes(e.head)) {
24384
+ push(
24385
+ "marker-gradient-def-integrity",
24386
+ `edge "${e.id}" head "${e.head}" \u304C EDGE_HEADS \u5B9A\u7FA9\u306B\u5B58\u5728\u3057\u306A\u3044\u3001 marker "cdl-arrow-${e.tone}-${e.head}" dead ref`
24387
+ );
24388
+ }
23269
24389
  }
23270
24390
  const SUBPIXEL_TOL = 0.5;
23271
24391
  function isSubpixel(v) {