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