@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/index.js CHANGED
@@ -9365,6 +9365,10 @@ function makePhaseBuilder(acc) {
9365
9365
  acc.draw.push(...ids);
9366
9366
  return api;
9367
9367
  },
9368
+ drawRatio(ratio) {
9369
+ acc.drawRatio = ratio;
9370
+ return api;
9371
+ },
9368
9372
  tween(stateId, from, to) {
9369
9373
  acc.tweens.push({ stateId, from, to });
9370
9374
  return api;
@@ -9487,6 +9491,7 @@ function diagram(id, options) {
9487
9491
  tone: opts.tone ?? "accent",
9488
9492
  side: opts.side,
9489
9493
  style: opts.style,
9494
+ head: opts.head,
9490
9495
  guard: opts.guard,
9491
9496
  cardinality: opts.cardinality,
9492
9497
  labelOffsetX: opts.labelOffsetX,
@@ -9609,6 +9614,7 @@ function diagram(id, options) {
9609
9614
  tone: d.tone ?? "accent",
9610
9615
  side: d.side,
9611
9616
  style: d.style,
9617
+ head: d.head,
9612
9618
  guard: d.guard,
9613
9619
  cardinality: d.cardinality,
9614
9620
  labelOffsetX: d.labelOffsetX,
@@ -11454,6 +11460,8 @@ function diagram(id, options) {
11454
11460
  activate: acc.activate,
11455
11461
  // 空なら欄ごと置かない。 置くと `draw` を使わない図の JSON の形が変わる
11456
11462
  ...acc.draw.length > 0 ? { draw: acc.draw } : {},
11463
+ // 書かない phase では欄ごと出さない = 従来の図の JSON が 1 byte も変わらない
11464
+ ...acc.drawRatio === void 0 ? {} : { drawRatio: acc.drawRatio },
11457
11465
  tweens: acc.tweens,
11458
11466
  sets: acc.sets,
11459
11467
  badge: acc.badge
@@ -11718,12 +11726,20 @@ var KINDS_WITHOUT_TITLE_TEXT = /* @__PURE__ */ new Set([
11718
11726
  "chart-pie",
11719
11727
  "chart-line",
11720
11728
  "chart-bar",
11729
+ "chart-gauge",
11730
+ "chart-radial",
11731
+ "chart-stat",
11732
+ "chart-waffle",
11733
+ "chart-stacked-bar",
11721
11734
  "gantt-timeline",
11722
11735
  "mind-map",
11723
11736
  "funnel-stages",
11724
11737
  "quadrant-matrix",
11725
11738
  "tree-hierarchy",
11726
- "journey-map"
11739
+ "journey-map",
11740
+ // 印そのものが意味を持つ (#560)
11741
+ "mark-start",
11742
+ "mark-end"
11727
11743
  ]);
11728
11744
  function rendersTitleText(kind) {
11729
11745
  return !KINDS_WITHOUT_TITLE_TEXT.has(kind ?? "");
@@ -11763,19 +11779,36 @@ function rendersRows(kind) {
11763
11779
  }
11764
11780
  function rowBaselineY(kind, index) {
11765
11781
  if (!rendersRows(kind)) return null;
11766
- return kind === "storage" ? ROW_TOP_STORAGE + index * ROW_PITCH_STORAGE : ROW_TOP_GENERIC + index * ROW_PITCH_GENERIC;
11782
+ return kind === "storage" ? ROW_TOP_STORAGE + index * ROW_PITCH_STORAGE : ROW_TOP_GENERIC + genericTextShift(kind) + index * ROW_PITCH_GENERIC;
11783
+ }
11784
+ function genericTextShift(kind) {
11785
+ return KINDS_SHAPE_CYLINDER.has(kind ?? "") ? GENERIC_TEXT_SHIFT_CYLINDER : 0;
11786
+ }
11787
+ var KINDS_SHAPE_CYLINDER = /* @__PURE__ */ new Set(["database"]);
11788
+ var KINDS_TEXT_CENTERED = /* @__PURE__ */ new Set(["cloud", "decision"]);
11789
+ function genericTextCentered(kind, hasRows) {
11790
+ return !hasRows && KINDS_TEXT_CENTERED.has(kind ?? "");
11791
+ }
11792
+ function genericTitleBaselineY(kind, h, hasRows) {
11793
+ return genericTextCentered(kind, hasRows) ? h / 2 + GENERIC_TITLE_CENTER_OFFSET : GENERIC_TITLE_TOP + genericTextShift(kind);
11767
11794
  }
11768
11795
  var ROW_TOP_STORAGE = 130;
11769
11796
  var ROW_PITCH_STORAGE = 56;
11770
11797
  var ROW_TOP_GENERIC = 100;
11771
11798
  var ROW_PITCH_GENERIC = 28;
11799
+ var GENERIC_TEXT_SHIFT_CYLINDER = 28;
11800
+ var GENERIC_TITLE_TOP = 68;
11801
+ var GENERIC_TITLE_CENTER_OFFSET = 4;
11802
+ var GENERIC_TITLE_FONT = 20;
11803
+ var GLYPH_CAP_RATIO = 0.72;
11772
11804
  var ROW_FONT_STORAGE = 26;
11773
11805
  var ROW_FONT_GENERIC = 21;
11774
11806
  var STORAGE_TITLE_BASELINE = 78;
11775
11807
  var STORAGE_ROW_DIVIDER_Y = Math.round(
11776
- (STORAGE_TITLE_BASELINE + (ROW_TOP_STORAGE - ROW_FONT_STORAGE * 0.72)) / 2
11808
+ (STORAGE_TITLE_BASELINE + (ROW_TOP_STORAGE - ROW_FONT_STORAGE * GLYPH_CAP_RATIO)) / 2
11777
11809
  );
11778
11810
  var ROW_GLYPH_DEPTH_RATIO = 0.4;
11811
+ var TITLE_ROW_MIN_GAP = GENERIC_TITLE_FONT * ROW_GLYPH_DEPTH_RATIO + ROW_FONT_GENERIC * GLYPH_CAP_RATIO;
11779
11812
  function rowGlyphDepth(kind) {
11780
11813
  if (!rendersRows(kind)) return null;
11781
11814
  const font = kind === "storage" ? ROW_FONT_STORAGE : ROW_FONT_GENERIC;
@@ -13142,6 +13175,108 @@ function applyEdgeLabelAndPathShifts(edges, labelShiftMap, edgePathShiftMap) {
13142
13175
  });
13143
13176
  }
13144
13177
 
13178
+ // src/layout/self-loop.ts
13179
+ var SELF_LOOP_OUT = 72;
13180
+ var SELF_LOOP_SPAN = 64;
13181
+ var SELF_LOOP_STAGGER = 45;
13182
+ var SELF_LOOP_SIDE_ORDER = ["right", "top", "left", "bottom"];
13183
+ var SELF_LOOP_SIDE_FALLBACK = "right";
13184
+ var CUBIC_APEX_RATIO = 0.75;
13185
+ var ENDPOINT_CENTER_MARGIN = 8;
13186
+ var SPAN_MIN = 8;
13187
+ function controlOffset(out) {
13188
+ return out / CUBIC_APEX_RATIO;
13189
+ }
13190
+ function sideGeometry(n, side) {
13191
+ switch (side) {
13192
+ case "right":
13193
+ return { x: n.cx + n.w / 2, y: n.cy, ux: 1, uy: 0 };
13194
+ case "left":
13195
+ return { x: n.cx - n.w / 2, y: n.cy, ux: -1, uy: 0 };
13196
+ case "top":
13197
+ return { x: n.cx, y: n.cy - n.h / 2, ux: 0, uy: -1 };
13198
+ case "bottom":
13199
+ return { x: n.cx, y: n.cy + n.h / 2, ux: 0, uy: 1 };
13200
+ }
13201
+ }
13202
+ function fitSpan(sideLength, wanted) {
13203
+ const \u9650\u5EA6 = sideLength - 2 * ENDPOINT_CENTER_MARGIN;
13204
+ return Math.max(SPAN_MIN, Math.min(wanted, \u9650\u5EA6));
13205
+ }
13206
+ function pickFreeSides(occupied, count) {
13207
+ const \u7A7A\u304D = SELF_LOOP_SIDE_ORDER.filter((s) => !occupied?.has(s));
13208
+ const \u4F7F\u3046 = \u7A7A\u304D.length > 0 ? \u7A7A\u304D : [SELF_LOOP_SIDE_FALLBACK];
13209
+ return Array.from({ length: count }, (_, i) => \u4F7F\u3046[i % \u4F7F\u3046.length]);
13210
+ }
13211
+ function routeSelfLoopGroup(edges, node, side) {
13212
+ const horizontal = side === "left" || side === "right";
13213
+ const g = sideGeometry(node, side);
13214
+ const span = fitSpan(horizontal ? node.h : node.w, SELF_LOOP_SPAN);
13215
+ const half = span / 2;
13216
+ const \u6CBF = horizontal ? { x: 0, y: 1 } : { x: 1, y: 0 };
13217
+ const \u6700\u5916 = controlOffset(SELF_LOOP_OUT + (edges.length - 1) * SELF_LOOP_STAGGER);
13218
+ const \u8A9E\u307E\u3067 = \u6700\u5916 + LABEL_TO_PATH_CLEARANCE;
13219
+ const \u8A9E\u5E45 = edges.map(
13220
+ (e) => horizontal ? labelPillH(e.sub) : computeLabelBoxW(e.label, e.sub)
13221
+ );
13222
+ const \u4F4D\u7F6E = [];
13223
+ let \u7A4D = 0;
13224
+ for (const w of \u8A9E\u5E45) {
13225
+ \u4F4D\u7F6E.push(\u7A4D + w / 2);
13226
+ \u7A4D += w + CLEARANCE_LABEL_LABEL;
13227
+ }
13228
+ const \u5168\u9577 = Math.max(0, \u7A4D - CLEARANCE_LABEL_LABEL);
13229
+ return edges.map((edge, index) => {
13230
+ const c = controlOffset(SELF_LOOP_OUT + index * SELF_LOOP_STAGGER);
13231
+ const x1 = g.x - \u6CBF.x * half;
13232
+ const y1 = g.y - \u6CBF.y * half;
13233
+ const x2 = g.x + \u6CBF.x * half;
13234
+ const y2 = g.y + \u6CBF.y * half;
13235
+ const \u305A\u308C = \u4F4D\u7F6E[index] - \u5168\u9577 / 2;
13236
+ return {
13237
+ ...edge,
13238
+ d: `M ${x1} ${y1} C ${x1 + g.ux * c} ${y1 + g.uy * c} ${x2 + g.ux * c} ${y2 + g.uy * c} ${x2} ${y2}`,
13239
+ fromSide: side,
13240
+ toSide: side,
13241
+ labelX: g.x + g.ux * \u8A9E\u307E\u3067 + \u6CBF.x * \u305A\u308C + (edge.labelOffsetX ?? 0),
13242
+ labelY: g.y + g.uy * \u8A9E\u307E\u3067 + \u6CBF.y * \u305A\u308C + (edge.labelOffsetY ?? 0),
13243
+ labelAnchor: side === "left" ? "end" : side === "right" ? "start" : "middle"
13244
+ };
13245
+ });
13246
+ }
13247
+ function isSelfLoop(e) {
13248
+ return e.from === e.to;
13249
+ }
13250
+ function layoutSelfLoops(edges, nodes, occupiedBySide) {
13251
+ const \u5272\u5F53 = /* @__PURE__ */ new Map();
13252
+ for (const edge of edges) {
13253
+ if (edge.side) continue;
13254
+ const list = \u5272\u5F53.get(edge.from) ?? [];
13255
+ list.push("right");
13256
+ \u5272\u5F53.set(edge.from, list);
13257
+ }
13258
+ for (const [nodeId, list] of \u5272\u5F53) {
13259
+ \u5272\u5F53.set(nodeId, pickFreeSides(occupiedBySide.get(nodeId), list.length));
13260
+ }
13261
+ const \u6D88\u8CBB = /* @__PURE__ */ new Map();
13262
+ const \u675F = /* @__PURE__ */ new Map();
13263
+ for (const edge of edges) {
13264
+ const node = nodes.get(edge.from);
13265
+ if (!node) throw new Error(`cdl layout: edge "${edge.id}" \u306E from "${edge.from}" \u304C node \u306B\u7121\u3044`);
13266
+ let side = edge.side;
13267
+ if (!side) {
13268
+ const i = \u6D88\u8CBB.get(edge.from) ?? 0;
13269
+ \u6D88\u8CBB.set(edge.from, i + 1);
13270
+ side = \u5272\u5F53.get(edge.from)[i];
13271
+ }
13272
+ const key = `${edge.from}::${side}`;
13273
+ const \u65E2 = \u675F.get(key);
13274
+ if (\u65E2) \u65E2.edges.push(edge);
13275
+ else \u675F.set(key, { node, side, edges: [edge] });
13276
+ }
13277
+ return [...\u675F.values()].flatMap((b) => routeSelfLoopGroup(b.edges, b.node, b.side));
13278
+ }
13279
+
13145
13280
  // src/layout/tokens.ts
13146
13281
  var TOKENS = {
13147
13282
  // viewBox / lane margins
@@ -13187,6 +13322,16 @@ var TOKENS = {
13187
13322
  "chart-line": { w: 640, h: 360 },
13188
13323
  "chart-pie": { w: 640, h: 320 },
13189
13324
  "chart-bar": { w: 640, h: 360 },
13325
+ // 上半分の弧 + 下段の内訳。 弧が浅いぶん pie より低くて済む (cdl#549)
13326
+ "chart-gauge": { w: 640, h: 320 },
13327
+ // 左に一覧 + 右に同心の弧。 件数ぶん内側へ重なるので pie と同じ高さを取る (cdl#550)
13328
+ "chart-radial": { w: 640, h: 320 },
13329
+ // 件ごとに区画を割り、名前 / 数値 / 弧 / 割合 を縦に積む。 数値を大きく組むので縦が要る (cdl#553)
13330
+ "chart-stat": { w: 640, h: 320 },
13331
+ // 左に一覧 + 右に 10x10 の格子。 格子が正方形なので pie と同じ高さで足りる (cdl#552)
13332
+ "chart-waffle": { w: 640, h: 320 },
13333
+ // 帯を最大 2 本 + 下に一覧。 縦は帯 2 本ぶんで足りる (cdl#551)
13334
+ "chart-stacked-bar": { w: 640, h: 320 },
13190
13335
  // Timeline / Mind 系 (CAR-994 Phase B)
13191
13336
  "gantt-timeline": { w: 720, h: 360 },
13192
13337
  "mind-map": { w: 720, h: 480 },
@@ -13257,7 +13402,12 @@ var TOKENS = {
13257
13402
  "shape-notary": { w: 280, h: 320 },
13258
13403
  "shape-lawyer": { w: 280, h: 300 },
13259
13404
  "shape-trader": { w: 300, h: 300 },
13260
- "shape-customer-service": { w: 320, h: 300 }
13405
+ "shape-customer-service": { w: 320, h: 300 },
13406
+ // 流れの始まりと終わりの印 2 種 (#560) ... 正方形にして丸が縦横どちらにも歪まないようにする。
13407
+ // 印は箱いっぱいに描く (線が箱の縁で止まるため) ので、この値が丸の直径になる。
13408
+ // 箱としての最小 (80x40) より大きく、名前を持つ箱 (card 320x150) よりは明らかに小さい
13409
+ "mark-start": { w: 96, h: 96 },
13410
+ "mark-end": { w: 96, h: 96 }
13261
13411
  },
13262
13412
  // row gap (stack 間の vertical gap、 lane 内 / 跨ぎ共通)
13263
13413
  // edge label が node の上 36 px に配置されるため、 boxH 68 + 36 + 余裕 = 100 必要。
@@ -13330,6 +13480,7 @@ function layoutEdges(diag, nodes, lanes = []) {
13330
13480
  const lmap = new Map(lanes.map((l) => [l.id, l]));
13331
13481
  const positionedEdges = [];
13332
13482
  const autoEdges = [];
13483
+ const selfLoopEdges = [];
13333
13484
  for (const e of diag.edges) {
13334
13485
  if (e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0) {
13335
13486
  const from = nmap.get(e.from);
@@ -13348,6 +13499,8 @@ function layoutEdges(diag, nodes, lanes = []) {
13348
13499
  labelY: midY + (e.labelOffsetY ?? 0),
13349
13500
  labelAnchor: "middle"
13350
13501
  });
13502
+ } else if (isSelfLoop(e)) {
13503
+ selfLoopEdges.push(e);
13351
13504
  } else {
13352
13505
  autoEdges.push(e);
13353
13506
  }
@@ -13371,6 +13524,22 @@ function layoutEdges(diag, nodes, lanes = []) {
13371
13524
  if (list.length <= 1) continue;
13372
13525
  distributeBySides(list);
13373
13526
  }
13527
+ const occupiedBySide = /* @__PURE__ */ new Map();
13528
+ const \u4F7F\u3046 = (nodeId, side) => {
13529
+ const s = occupiedBySide.get(nodeId) ?? /* @__PURE__ */ new Set();
13530
+ s.add(side);
13531
+ occupiedBySide.set(nodeId, s);
13532
+ };
13533
+ for (const p of prepared) {
13534
+ const backDetour = p.e.routing === "back-detour";
13535
+ \u4F7F\u3046(p.e.from, backDetour ? "top" : p.fromSide);
13536
+ \u4F7F\u3046(p.e.to, backDetour ? "top" : p.toSide);
13537
+ }
13538
+ for (const le of positionedEdges) {
13539
+ \u4F7F\u3046(le.from, le.fromSide);
13540
+ \u4F7F\u3046(le.to, le.toSide);
13541
+ }
13542
+ const loopEdges = layoutSelfLoops(selfLoopEdges, nmap, occupiedBySide);
13374
13543
  const labelOffsetsByEdgeId = /* @__PURE__ */ new Map();
13375
13544
  const parallelKey = (p) => p.e.from < p.e.to ? `${p.e.from}::${p.e.to}` : `${p.e.to}::${p.e.from}`;
13376
13545
  const byParallel = /* @__PURE__ */ new Map();
@@ -13869,6 +14038,7 @@ function layoutEdges(diag, nodes, lanes = []) {
13869
14038
  });
13870
14039
  const laidById = /* @__PURE__ */ new Map();
13871
14040
  for (const le of autoResults) laidById.set(le.id, le);
14041
+ for (const le of loopEdges) laidById.set(le.id, le);
13872
14042
  for (const le of positionedEdges) laidById.set(le.id, le);
13873
14043
  return diag.edges.map((e) => laidById.get(e.id)).filter((e) => e !== void 0);
13874
14044
  }
@@ -15236,10 +15406,19 @@ var NODE_KINDS = [
15236
15406
  "oracle",
15237
15407
  "merkle-tree",
15238
15408
  "decision",
15239
- // Chart 系 (3) ... 1 node に datum 配列を持ち、 kind 内で全 datum を SVG 描画
15409
+ // Chart 系 (5) ... 1 node に datum 配列を持ち、 kind 内で全 datum を SVG 描画。
15410
+ // chart-gauge は合計を主役に置く形 (cdl#549)、 chart-radial は弧の長さで比べる形 (cdl#550)、
15411
+ // chart-stat は数値そのものを主役に置く形 (cdl#553)
15412
+ // chart-waffle は 100 個の印で割合を数えて確かめる形 (cdl#552)
15240
15413
  "chart-pie",
15241
15414
  "chart-line",
15242
15415
  "chart-bar",
15416
+ "chart-gauge",
15417
+ "chart-radial",
15418
+ "chart-stat",
15419
+ // chart-stacked-bar は帯を割合で区切り時点を並べる形 (cdl#551)
15420
+ "chart-waffle",
15421
+ "chart-stacked-bar",
15243
15422
  // Timeline / Mind 系 (2、 CAR-994 Phase B) ... 1 node に payload 配列、 SVG geometry render
15244
15423
  "gantt-timeline",
15245
15424
  "mind-map",
@@ -15306,8 +15485,14 @@ var NODE_KINDS = [
15306
15485
  "shape-notary",
15307
15486
  "shape-lawyer",
15308
15487
  "shape-trader",
15309
- "shape-customer-service"
15488
+ "shape-customer-service",
15489
+ // 流れの始まりと終わりの印 2 種 (#560) ... 塗った丸と輪で囲んだ丸。
15490
+ // 状態遷移図が使う。 印そのものが意味を持つので文字は描かない
15491
+ "mark-start",
15492
+ "mark-end"
15310
15493
  ];
15494
+ var EDGE_HEAD_DEFAULT = "triangle";
15495
+ var EDGE_HEADS = ["triangle", "diamond", "open", "crow"];
15311
15496
 
15312
15497
  // src/anim/core/easing.ts
15313
15498
  function cubicBezier(x1, y1, x2, y2) {
@@ -15971,12 +16156,6 @@ function validate(diag) {
15971
16156
  \u2192 \u4FEE\u6B63\u4F8B: .node("${e.to}", { lane: "...", stack: 0, kind: "...", title: "..." }) \u3092 edge \u5BA3\u8A00\u524D\u306B\u8FFD\u52A0`
15972
16157
  );
15973
16158
  }
15974
- if (e.from === e.to) {
15975
- errors.push(
15976
- `[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)
15977
- \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`
15978
- );
15979
- }
15980
16159
  }
15981
16160
  for (const p of diag.phases) {
15982
16161
  for (const id of p.activate) {
@@ -15996,6 +16175,17 @@ function validate(diag) {
15996
16175
  );
15997
16176
  }
15998
16177
  }
16178
+ if (p.drawRatio !== void 0) {
16179
+ if (!Number.isFinite(p.drawRatio) || p.drawRatio <= 0 || p.drawRatio > 1) {
16180
+ warnings.push(
16181
+ `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`
16182
+ );
16183
+ } else if ((p.draw ?? []).length === 0) {
16184
+ warnings.push(
16185
+ `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`
16186
+ );
16187
+ }
16188
+ }
15999
16189
  for (const t of p.tweens) {
16000
16190
  if (!stateIds.has(t.stateId)) {
16001
16191
  errors.push(`[cdl] unknown-ref: phase "${p.id}" tween \u5BFE\u8C61 state "${t.stateId}" \u672A\u5B9A\u7FA9`);
@@ -16426,6 +16616,17 @@ var TONE_HEX = {
16426
16616
  warning: "#a67a2e",
16427
16617
  info: "#5a8ec1"
16428
16618
  };
16619
+ var CHART_SERIES = [
16620
+ "var(--cdl-chart-1, #4338ca)",
16621
+ "var(--cdl-chart-2, #0d9488)",
16622
+ "var(--cdl-chart-3, #f59e0b)",
16623
+ "var(--cdl-chart-4, #be185d)",
16624
+ "var(--cdl-chart-5, #4d7c0f)",
16625
+ "var(--cdl-chart-6, #0369a1)"
16626
+ ];
16627
+ function chartSeriesColor(idx) {
16628
+ return CHART_SERIES[(idx % CHART_SERIES.length + CHART_SERIES.length) % CHART_SERIES.length];
16629
+ }
16429
16630
  var TONE_FALLBACK = "#2d6a8f";
16430
16631
  function hasTone(tone) {
16431
16632
  return Object.hasOwn(TONE, tone);
@@ -16471,10 +16672,14 @@ function needsResolve(raw) {
16471
16672
  return typeof raw !== "number" || !Number.isFinite(raw);
16472
16673
  }
16473
16674
  function resolveChartData(data, values) {
16474
- if (!data.some((d) => needsResolve(d.value))) return data;
16675
+ if (!data.some((d) => needsResolve(d.value) || d.previous !== void 0 && needsResolve(d.previous)))
16676
+ return data;
16475
16677
  return data.map((d) => {
16476
16678
  const v = resolveBoundNumber(d.value, values, 0);
16477
- return v.ok ? { ...d, value: v.value } : { ...d, value: v.value, unresolved: true };
16679
+ const \u524D = d.previous === void 0 ? void 0 : resolveBoundNumber(d.previous, values, 0);
16680
+ const \u89E3\u3051\u305F = v.ok && (\u524D === void 0 || \u524D.ok);
16681
+ const \u7D20 = { ...d, value: v.value, previous: \u524D?.value };
16682
+ return \u89E3\u3051\u305F ? \u7D20 : { ...\u7D20, unresolved: true };
16478
16683
  });
16479
16684
  }
16480
16685
  function resolveFunnelData(stages, values) {
@@ -17304,6 +17509,11 @@ var GRID_ALIGNED_KINDS = /* @__PURE__ */ new Set([
17304
17509
  "chart-pie",
17305
17510
  "chart-line",
17306
17511
  "chart-bar",
17512
+ "chart-gauge",
17513
+ "chart-radial",
17514
+ "chart-stat",
17515
+ "chart-waffle",
17516
+ "chart-stacked-bar",
17307
17517
  "funnel-stages",
17308
17518
  "quadrant-matrix"
17309
17519
  ]);
@@ -17393,6 +17603,7 @@ function emptyCounts() {
17393
17603
  "row-gap-uniform": 0,
17394
17604
  "column-gap-uniform": 0,
17395
17605
  "rows-not-rendered": 0,
17606
+ "title-row-overlap": 0,
17396
17607
  "malformed-input": 0,
17397
17608
  "validation-interrupted": 0
17398
17609
  };
@@ -18560,6 +18771,21 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
18560
18771
  `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)`
18561
18772
  );
18562
18773
  }
18774
+ for (const n of diag.nodes) {
18775
+ if (!n.rows || n.rows.length === 0) continue;
18776
+ if (!rendersRows(n.kind)) continue;
18777
+ if (n.kind === "storage") continue;
18778
+ if (typeof n.h !== "number") continue;
18779
+ const \u984C = genericTitleBaselineY(n.kind, n.h, true);
18780
+ const \u884C = rowBaselineY(n.kind, 0);
18781
+ if (\u884C === null) continue;
18782
+ const \u9593 = \u884C - \u984C;
18783
+ if (\u9593 >= TITLE_ROW_MIN_GAP) continue;
18784
+ push(
18785
+ "title-row-overlap",
18786
+ `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)`
18787
+ );
18788
+ }
18563
18789
  const GROUP_INTERNAL_PAD = 20;
18564
18790
  const GROUP_EXTERNAL_CLEAR = 16;
18565
18791
  for (const lane of laid.lanes) {
@@ -18917,6 +19143,12 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
18917
19143
  `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`
18918
19144
  );
18919
19145
  }
19146
+ if (e.head !== void 0 && !EDGE_HEADS.includes(e.head)) {
19147
+ push(
19148
+ "marker-gradient-def-integrity",
19149
+ `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`
19150
+ );
19151
+ }
18920
19152
  }
18921
19153
  const SUBPIXEL_TOL = 0.5;
18922
19154
  function isSubpixel(v) {
@@ -20941,6 +21173,18 @@ function StateDiffCard({
20941
21173
  }
20942
21174
  );
20943
21175
  }
21176
+
21177
+ // src/render/edge-head.ts
21178
+ var EDGE_HEAD_SHAPE = {
21179
+ triangle: { d: "M 0 0 L 10 5 L 0 10 z", refX: 9, filled: true },
21180
+ diamond: { d: "M 0 5 L 5 0 L 10 5 L 5 10 z", refX: 9, filled: true },
21181
+ open: { d: "M 1 0 L 9 5 L 1 10", refX: 9, filled: false },
21182
+ crow: { d: "M 10 0 L 0 5 M 10 5 L 0 5 M 10 10 L 0 5", refX: 10, filled: false }
21183
+ };
21184
+ function edgeHeadMarkerId(tone, head, small) {
21185
+ const \u5C0F = small ? "-sm" : "";
21186
+ return head === EDGE_HEAD_DEFAULT ? `cdl-arrow-${tone}${\u5C0F}` : `cdl-arrow-${tone}-${head}${\u5C0F}`;
21187
+ }
20944
21188
  function opacityAttr(opacity) {
20945
21189
  return opacity < 1 ? opacity : void 0;
20946
21190
  }
@@ -20954,7 +21198,7 @@ function CdlEdgeView({
20954
21198
  stateValues
20955
21199
  }) {
20956
21200
  const color = toneColor(edge.tone);
20957
- const marker = hasTone(edge.tone) ? `cdl-arrow-${edge.tone}${active ? "" : "-sm"}` : "cdl-arrow-muted";
21201
+ const marker = hasTone(edge.tone) ? edgeHeadMarkerId(edge.tone, edge.head ?? EDGE_HEAD_DEFAULT, !active) : "cdl-arrow-muted";
20958
21202
  const style = edge.style ?? "solid";
20959
21203
  const isDotted = style === "dotted-flow";
20960
21204
  const isPassThrough = isDotted && Boolean(edge.dThrough);
@@ -21722,12 +21966,13 @@ function GenericNode({
21722
21966
  );
21723
21967
  })();
21724
21968
  const resolvedValue = value !== void 0 ? interpolate(value, stateValues) : void 0;
21725
- const centered = shape === "diamond" || shape === "cloud";
21969
+ const hasRows = (node.rows?.length ?? 0) > 0;
21970
+ const centered = genericTextCentered(node.kind, hasRows);
21726
21971
  const textAnchor = centered ? "middle" : "start";
21727
21972
  const textX = centered ? w / 2 : 20;
21728
- const cylinderShift = shape === "cylinder" ? 28 : 0;
21973
+ const cylinderShift = genericTextShift(node.kind);
21729
21974
  const eyebrowY = centered ? h / 2 - 26 : 32 + cylinderShift;
21730
- const titleY = centered ? h / 2 + 4 : 68 + cylinderShift;
21975
+ const titleY = genericTitleBaselineY(node.kind, h, hasRows);
21731
21976
  const subtitleY = centered ? h / 2 + 28 : 96 + cylinderShift;
21732
21977
  const iconX = centered ? w / 2 + 40 : w - 48;
21733
21978
  const iconY = centered ? h / 2 - 44 : 18 + cylinderShift;
@@ -21783,6 +22028,57 @@ function GenericNode({
21783
22028
  })()
21784
22029
  ] });
21785
22030
  }
22031
+ var MARK_INNER_RATIO = 0.56;
22032
+ var RING_WIDTH_ACTIVE = 6;
22033
+ var RING_WIDTH_IDLE = 4;
22034
+ var MARK_DEFAULT = "var(--cdl-tone-accent, #2d6a8f)";
22035
+ function markRadius(node) {
22036
+ return Math.min(node.w, node.h) / 2;
22037
+ }
22038
+ function MarkStartNode({ node }) {
22039
+ const \u8272 = nodeAccent(node, MARK_DEFAULT);
22040
+ return /* @__PURE__ */ jsx("g", { transform: `translate(${node.cx - node.w / 2} ${node.cy - node.h / 2})`, children: /* @__PURE__ */ jsx(
22041
+ "circle",
22042
+ {
22043
+ "data-cdl-role": "node-body",
22044
+ "data-cdl-mark": "start",
22045
+ cx: node.w / 2,
22046
+ cy: node.h / 2,
22047
+ r: markRadius(node),
22048
+ fill: \u8272
22049
+ }
22050
+ ) });
22051
+ }
22052
+ function MarkEndNode({ node, active }) {
22053
+ const \u8272 = nodeAccent(node, MARK_DEFAULT);
22054
+ const r = markRadius(node);
22055
+ const \u8F2A\u306E\u592A\u3055 = active ? RING_WIDTH_ACTIVE : RING_WIDTH_IDLE;
22056
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${node.cx - node.w / 2} ${node.cy - node.h / 2})`, children: [
22057
+ /* @__PURE__ */ jsx(
22058
+ "circle",
22059
+ {
22060
+ "data-cdl-role": "node-body",
22061
+ "data-cdl-mark": "end",
22062
+ cx: node.w / 2,
22063
+ cy: node.h / 2,
22064
+ r: Math.max(0, r - \u8F2A\u306E\u592A\u3055 / 2),
22065
+ fill: "var(--cdl-node-fill, #ffffff)",
22066
+ stroke: \u8272,
22067
+ strokeWidth: \u8F2A\u306E\u592A\u3055
22068
+ }
22069
+ ),
22070
+ /* @__PURE__ */ jsx(
22071
+ "circle",
22072
+ {
22073
+ "data-cdl-role": "node-inner",
22074
+ cx: node.w / 2,
22075
+ cy: node.h / 2,
22076
+ r: Math.max(0, r * MARK_INNER_RATIO),
22077
+ fill: \u8272
22078
+ }
22079
+ )
22080
+ ] });
22081
+ }
21786
22082
  function useTimeTick() {
21787
22083
  const [t, setT] = useState(() => typeof performance !== "undefined" ? performance.now() : 0);
21788
22084
  useEffect(() => {
@@ -21900,7 +22196,7 @@ function renderRect(shape, x, y, w, h, stateValues, fillColor, strokeColor, opac
21900
22196
  )
21901
22197
  ] });
21902
22198
  }
21903
- function renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity, node) {
22199
+ function renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity) {
21904
22200
  const maxR = Math.min(w, h) / 2;
21905
22201
  const r = shape.radius !== void 0 ? resolveNumericAttr(shape.radius, stateValues, maxR) : maxR;
21906
22202
  const progress = shape.fillProgress !== void 0 ? Math.min(1, Math.max(0, resolveNumericAttr(shape.fillProgress, stateValues, 0))) : 1;
@@ -21921,7 +22217,7 @@ function renderCircle(shape, cx, cy, w, h, stateValues, fillColor, strokeColor,
21921
22217
  )
21922
22218
  ] });
21923
22219
  }
21924
- function renderArc(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity, node) {
22220
+ function renderArc(shape, cx, cy, w, h, stateValues, fillColor, strokeColor, opacity) {
21925
22221
  const maxR = Math.min(w, h) / 2;
21926
22222
  const outerR = shape.outerRadius ?? maxR;
21927
22223
  const innerR = shape.innerRadius ?? outerR * 0.7;
@@ -22021,7 +22317,7 @@ function WaveShape({
22021
22317
  )
22022
22318
  ] });
22023
22319
  }
22024
- function renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, opacity, node) {
22320
+ function renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, opacity) {
22025
22321
  const sides = Math.min(12, Math.max(3, shape.sides));
22026
22322
  const r = shape.radius !== void 0 ? resolveNumericAttr(shape.radius, stateValues, 40) : 40;
22027
22323
  const rotation = shape.rotation !== void 0 ? resolveNumericAttr(shape.rotation, stateValues, 0) : 0;
@@ -22265,10 +22561,26 @@ function ChartPieNode({
22265
22561
  const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
22266
22562
  const PAD_TOP2 = 20;
22267
22563
  const PAD_BOTTOM2 = 20;
22564
+ const PAD_SIDE = 20;
22268
22565
  const chartAreaH = node.h - PAD_TOP2 - PAD_BOTTOM2;
22269
- const pieAreaW = node.w * 0.5;
22270
- const radius = Math.min(pieAreaW, chartAreaH) / 2 - 12;
22271
- const cx = pieAreaW / 2;
22566
+ const \u540D\u672D\u306E\u7D1A = 14;
22567
+ const \u6570\u5024\u306E\u7D1A = 13;
22568
+ const \u5F15\u304D\u51FA\u3057 = 18;
22569
+ const \u5B57\u307E\u3067\u306E\u9593 = 26;
22570
+ const \u540D\u672D\u306E\u7E26\u306E\u5F35\u308A\u51FA\u3057 = 20;
22571
+ const \u5272\u5408\u306E\u6587\u5B57 = data.map((d) => \u5272\u5408\u8868\u8A18(d.value / total));
22572
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map((d, i) => `${\u5B9F\u5024\u8868\u8A18(d.value)} ${\u5272\u5408\u306E\u6587\u5B57[i]}`);
22573
+ const \u540D\u672D\u5E45 = Math.max(
22574
+ 0,
22575
+ ...data.map(
22576
+ (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u672D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
22577
+ )
22578
+ );
22579
+ const \u7E26\u304B\u3089 = chartAreaH / 2 - \u5F15\u304D\u51FA\u3057 - \u540D\u672D\u306E\u7E26\u306E\u5F35\u308A\u51FA\u3057;
22580
+ const \u6A2A\u304B\u3089 = (node.w - PAD_SIDE * 2) / 2 - \u5F15\u304D\u51FA\u3057 - \u5B57\u307E\u3067\u306E\u9593 - \u540D\u672D\u5E45;
22581
+ const radius = Math.max(24, Math.min(\u7E26\u304B\u3089, \u6A2A\u304B\u3089));
22582
+ const \u5185\u534A\u5F84 = radius * 0.58;
22583
+ const cx = node.w / 2;
22272
22584
  const cy = PAD_TOP2 + chartAreaH / 2;
22273
22585
  let cumAngle = -Math.PI / 2;
22274
22586
  let cumFrac = 0;
@@ -22284,16 +22596,19 @@ function ChartPieNode({
22284
22596
  const y1 = cy + radius * Math.sin(a0);
22285
22597
  const x2 = cx + radius * Math.cos(a1);
22286
22598
  const y2 = cy + radius * Math.sin(a1);
22599
+ const x3 = cx + \u5185\u534A\u5F84 * Math.cos(a1);
22600
+ const y3 = cy + \u5185\u534A\u5F84 * Math.sin(a1);
22601
+ const x4 = cx + \u5185\u534A\u5F84 * Math.cos(a0);
22602
+ const y4 = cy + \u5185\u534A\u5F84 * Math.sin(a0);
22287
22603
  const large = angle > Math.PI ? 1 : 0;
22288
- const path = `M ${cx} ${cy} L ${x1} ${y1} A ${radius} ${radius} 0 ${large} 1 ${x2} ${y2} Z`;
22289
- return { d, frac, path, startFrac };
22604
+ 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`;
22605
+ const \u4E2D\u592E\u89D2 = (a0 + a1) / 2;
22606
+ return { d, frac, path, startFrac, \u4E2D\u592E\u89D2 };
22290
22607
  });
22291
22608
  const \u958B\u304D = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
22292
22609
  const \u5207\u308A\u629C\u304Did = `cdl-pie-draw-${instanceId}`;
22610
+ const \u5F71id = `cdl-pie-shadow-${instanceId}`;
22293
22611
  const \u958B\u304D\u59CB\u3081\u305F = (startFrac) => !drawing || \u958B\u304D > startFrac;
22294
- const legendX = pieAreaW + 8;
22295
- const legendGap = Math.min(28, chartAreaH / Math.max(data.length, 1));
22296
- const legendStartY = PAD_TOP2 + (chartAreaH - legendGap * data.length) / 2 + legendGap / 2;
22297
22612
  return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
22298
22613
  /* @__PURE__ */ jsx(
22299
22614
  "rect",
@@ -22309,56 +22624,90 @@ function ChartPieNode({
22309
22624
  strokeWidth: active ? 3 : 1.25
22310
22625
  }
22311
22626
  ),
22312
- 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) }) }),
22313
- /* @__PURE__ */ jsx("g", { ...drawing ? { clipPath: `url(#${\u5207\u308A\u629C\u304Did})` } : {}, children: slices.map((s, idx) => /* @__PURE__ */ jsx(
22627
+ /* @__PURE__ */ jsxs("defs", { children: [
22628
+ drawing && /* @__PURE__ */ jsx("clipPath", { id: \u5207\u308A\u629C\u304Did, children: \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, radius + 2, \u958B\u304D) }),
22629
+ /* @__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" }) })
22630
+ ] }),
22631
+ /* @__PURE__ */ jsx("g", { ...drawing ? { clipPath: `url(#${\u5207\u308A\u629C\u304Did})` } : {}, filter: `url(#${\u5F71id})`, children: slices.map((s, idx) => /* @__PURE__ */ jsx(
22314
22632
  "path",
22315
22633
  {
22316
22634
  "data-cdl-role": "chart-pie-slice",
22317
22635
  "data-cdl-unresolved": s.d.unresolved ? "true" : void 0,
22318
22636
  d: s.path,
22319
22637
  fill: sliceColor(s.d.tone, idx),
22320
- fillOpacity: active ? 0.95 : 0.85,
22321
22638
  stroke: "var(--cdl-node-fill, #ffffff)",
22322
- strokeWidth: 1.5
22639
+ strokeWidth: 3,
22640
+ strokeLinejoin: "round"
22323
22641
  },
22324
22642
  `slice-${idx}`
22325
22643
  )) }),
22326
- slices.map((s, idx) => !\u958B\u304D\u59CB\u3081\u305F(s.startFrac) ? null : /* @__PURE__ */ jsxs("g", { transform: `translate(${legendX} ${legendStartY + idx * legendGap})`, children: [
22327
- /* @__PURE__ */ jsx(
22328
- "rect",
22329
- {
22330
- x: 0,
22331
- y: -8,
22332
- width: 14,
22333
- height: 14,
22334
- rx: 3,
22335
- fill: sliceColor(s.d.tone, idx)
22336
- }
22337
- ),
22338
- /* @__PURE__ */ jsx(
22339
- "text",
22340
- {
22341
- x: 20,
22342
- y: 2,
22343
- fontSize: 12,
22344
- fill: "var(--cdl-text, #1a1f2a)",
22345
- children: s.d.label
22346
- }
22347
- ),
22348
- /* @__PURE__ */ jsxs(
22349
- "text",
22350
- {
22351
- x: 20,
22352
- y: 16,
22353
- fontSize: 11,
22354
- fill: "var(--cdl-text-dim, #5a6270)",
22355
- children: [
22356
- (s.frac * 100).toFixed(1),
22357
- "%"
22358
- ]
22359
- }
22360
- )
22361
- ] }, `legend-${idx}`))
22644
+ /* @__PURE__ */ jsx(
22645
+ "text",
22646
+ {
22647
+ x: cx,
22648
+ y: cy - 2,
22649
+ textAnchor: "middle",
22650
+ fontSize: Math.round(radius * 0.26),
22651
+ fontWeight: 600,
22652
+ fill: "var(--cdl-text, #1a1f2a)",
22653
+ children: \u5B9F\u5024\u8868\u8A18(Math.round(total))
22654
+ }
22655
+ ),
22656
+ /* @__PURE__ */ jsx(
22657
+ "text",
22658
+ {
22659
+ x: cx,
22660
+ y: cy + Math.round(radius * 0.2),
22661
+ textAnchor: "middle",
22662
+ fontSize: Math.round(radius * 0.12),
22663
+ fill: "var(--cdl-text-dim, #5a6270)",
22664
+ children: "\u5408\u8A08"
22665
+ }
22666
+ ),
22667
+ slices.map((s, idx) => {
22668
+ if (!\u958B\u304D\u59CB\u3081\u305F(s.startFrac)) return null;
22669
+ const \u53F3 = Math.cos(s.\u4E2D\u592E\u89D2) >= 0;
22670
+ const \u7E01x = cx + radius * Math.cos(s.\u4E2D\u592E\u89D2);
22671
+ const \u7E01y = cy + radius * Math.sin(s.\u4E2D\u592E\u89D2);
22672
+ const \u6298\u308Cx = cx + (radius + \u5F15\u304D\u51FA\u3057) * Math.cos(s.\u4E2D\u592E\u89D2);
22673
+ const \u6298\u308Cy = cy + (radius + \u5F15\u304D\u51FA\u3057) * Math.sin(s.\u4E2D\u592E\u89D2);
22674
+ const \u5B57x = \u6298\u308Cx + (\u53F3 ? \u5B57\u307E\u3067\u306E\u9593 : -\u5B57\u307E\u3067\u306E\u9593);
22675
+ return /* @__PURE__ */ jsxs("g", { children: [
22676
+ /* @__PURE__ */ jsx(
22677
+ "path",
22678
+ {
22679
+ d: `M ${\u7E01x} ${\u7E01y} L ${\u6298\u308Cx} ${\u6298\u308Cy} L ${\u5B57x - (\u53F3 ? 6 : -6)} ${\u6298\u308Cy}`,
22680
+ fill: "none",
22681
+ stroke: "var(--cdl-divider, #d4d4d8)",
22682
+ strokeWidth: 1
22683
+ }
22684
+ ),
22685
+ /* @__PURE__ */ jsx("circle", { cx: \u7E01x, cy: \u7E01y, r: 3, fill: sliceColor(s.d.tone, idx) }),
22686
+ /* @__PURE__ */ jsx(
22687
+ "text",
22688
+ {
22689
+ x: \u5B57x,
22690
+ y: \u6298\u308Cy - 3,
22691
+ textAnchor: \u53F3 ? "start" : "end",
22692
+ fontSize: \u540D\u672D\u306E\u7D1A,
22693
+ fontWeight: 600,
22694
+ fill: "var(--cdl-text, #1a1f2a)",
22695
+ children: s.d.label
22696
+ }
22697
+ ),
22698
+ /* @__PURE__ */ jsx(
22699
+ "text",
22700
+ {
22701
+ x: \u5B57x,
22702
+ y: \u6298\u308Cy + 15,
22703
+ textAnchor: \u53F3 ? "start" : "end",
22704
+ fontSize: \u6570\u5024\u306E\u7D1A,
22705
+ fill: "var(--cdl-text-dim, #5a6270)",
22706
+ children: \u6570\u5024\u306E\u6587\u5B57[idx]
22707
+ }
22708
+ )
22709
+ ] }, `callout-${idx}`);
22710
+ })
22362
22711
  ] });
22363
22712
  }
22364
22713
  function \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, r, \u958B\u304D) {
@@ -22370,10 +22719,741 @@ function \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, r, \u958B\u304D) {
22370
22719
  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`;
22371
22720
  return /* @__PURE__ */ jsx("path", { d });
22372
22721
  }
22373
- var FALLBACK_ORDER = ["accent", "teal", "warning", "success", "info", "error"];
22722
+ function \u5B9F\u5024\u8868\u8A18(v) {
22723
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
22724
+ }
22725
+ function \u5272\u5408\u8868\u8A18(frac) {
22726
+ const v = Math.round(frac * 1e3) / 10;
22727
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
22728
+ }
22374
22729
  function sliceColor(tone, idx) {
22375
22730
  if (tone) return TONE[tone];
22376
- return TONE[FALLBACK_ORDER[idx % FALLBACK_ORDER.length]];
22731
+ return chartSeriesColor(idx);
22732
+ }
22733
+ function ChartGaugeNode({
22734
+ node,
22735
+ active,
22736
+ stateValues = {}
22737
+ }) {
22738
+ const x0 = node.cx - node.w / 2;
22739
+ const y0 = node.cy - node.h / 2;
22740
+ const data = resolveChartData(node.chartData ?? [], stateValues);
22741
+ const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
22742
+ const PAD_TOP2 = 20;
22743
+ const PAD_BOTTOM2 = 20;
22744
+ const PAD_SIDE = 20;
22745
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD_TOP2 - PAD_BOTTOM2;
22746
+ const \u4F7F\u3048\u308B\u5E452 = node.w - PAD_SIDE * 2;
22747
+ const \u540D\u524D\u306E\u7D1A = 14;
22748
+ const \u6570\u5024\u306E\u7D1A = 13;
22749
+ const \u5185\u8A33\u306E\u9AD8\u3055 = 56;
22750
+ const \u5F27\u3068\u5185\u8A33\u306E\u9593 = 16;
22751
+ const \u5F27\u306B\u4F7F\u3048\u308B\u9AD8\u3055 = \u4F7F\u3048\u308B\u9AD8\u3055 - \u5185\u8A33\u306E\u9AD8\u3055 - \u5F27\u3068\u5185\u8A33\u306E\u9593;
22752
+ const radius = Math.max(24, Math.min(\u5F27\u306B\u4F7F\u3048\u308B\u9AD8\u3055, \u4F7F\u3048\u308B\u5E452 / 2));
22753
+ const \u5185\u534A\u5F84 = radius * 0.62;
22754
+ const cx = node.w / 2;
22755
+ const cy = PAD_TOP2 + radius;
22756
+ let cumFrac = 0;
22757
+ const slices = data.map((d) => {
22758
+ const frac = d.value / total;
22759
+ const a0 = Math.PI + cumFrac * Math.PI;
22760
+ const a1 = a0 + frac * Math.PI;
22761
+ cumFrac += frac;
22762
+ const \u59161 = \u6975(cx, cy, radius, a0);
22763
+ const \u59162 = \u6975(cx, cy, radius, a1);
22764
+ const \u51852 = \u6975(cx, cy, \u5185\u534A\u5F84, a1);
22765
+ const \u51851 = \u6975(cx, cy, \u5185\u534A\u5F84, a0);
22766
+ 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`;
22767
+ return { d, frac, path };
22768
+ });
22769
+ const \u5408\u8A08\u306E\u6587\u5B57 = \u5B9F\u5024\u8868\u8A182(Math.round(total));
22770
+ const \u6A2A\u306E\u4E0A\u9650 = \u5185\u534A\u5F84 * 2 * 0.86;
22771
+ const \u7D1A\u306E\u5019\u88DC = Math.min(
22772
+ // 横 = 実際の字幅から逆算する
22773
+ \u6A2A\u306E\u4E0A\u9650 / Math.max(textWidth(\u5408\u8A08\u306E\u6587\u5B57, 100), 1) * 100,
22774
+ // 縦 = 合計 1 行 + 見出し 1 行が内側の高さに収まる比
22775
+ \u5185\u534A\u5F84 * 0.52
22776
+ );
22777
+ const \u5408\u8A08\u306E\u7D1A = Math.max(11, Math.round(\u7D1A\u306E\u5019\u88DC));
22778
+ const \u898B\u51FA\u3057\u306E\u7D1A = Math.max(9, Math.round(\u5408\u8A08\u306E\u7D1A * 0.38));
22779
+ const \u5185\u8A33\u306E\u5E45 = \u4F7F\u3048\u308B\u5E452 / Math.max(data.length, 1);
22780
+ const \u5185\u8A33\u306Ey = cy + \u5F27\u3068\u5185\u8A33\u306E\u9593;
22781
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
22782
+ /* @__PURE__ */ jsx(
22783
+ "rect",
22784
+ {
22785
+ "data-cdl-role": "node-body",
22786
+ x: 0,
22787
+ y: 0,
22788
+ width: node.w,
22789
+ height: node.h,
22790
+ rx: 16,
22791
+ fill: "var(--cdl-node-fill, #ffffff)",
22792
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
22793
+ strokeWidth: active ? 3 : 1.25
22794
+ }
22795
+ ),
22796
+ slices.map((s, idx) => /* @__PURE__ */ jsx(
22797
+ "path",
22798
+ {
22799
+ "data-cdl-role": "chart-gauge-arc",
22800
+ "data-cdl-unresolved": s.d.unresolved ? "true" : void 0,
22801
+ d: s.path,
22802
+ fill: arcColor(s.d.tone, idx),
22803
+ stroke: "var(--cdl-node-fill, #ffffff)",
22804
+ strokeWidth: 3,
22805
+ strokeLinejoin: "round"
22806
+ },
22807
+ `arc-${idx}`
22808
+ )),
22809
+ /* @__PURE__ */ jsx(
22810
+ "text",
22811
+ {
22812
+ x: cx,
22813
+ y: cy - \u5408\u8A08\u306E\u7D1A * 0.5,
22814
+ textAnchor: "middle",
22815
+ fontSize: \u5408\u8A08\u306E\u7D1A,
22816
+ fontWeight: 600,
22817
+ fill: "var(--cdl-text, #1a1f2a)",
22818
+ children: \u5408\u8A08\u306E\u6587\u5B57
22819
+ }
22820
+ ),
22821
+ /* @__PURE__ */ jsx(
22822
+ "text",
22823
+ {
22824
+ x: cx,
22825
+ y: cy - \u5408\u8A08\u306E\u7D1A * 0.5 + \u898B\u51FA\u3057\u306E\u7D1A * 1.5,
22826
+ textAnchor: "middle",
22827
+ fontSize: \u898B\u51FA\u3057\u306E\u7D1A,
22828
+ fill: "var(--cdl-text-dim, #5a6270)",
22829
+ children: "\u5408\u8A08"
22830
+ }
22831
+ ),
22832
+ data.map((d, idx) => {
22833
+ const x = PAD_SIDE + \u5185\u8A33\u306E\u5E45 * idx;
22834
+ const \u6570\u5024 = `${\u5B9F\u5024\u8868\u8A182(d.value)} ${\u5272\u5408\u8868\u8A182(d.value / total)}`;
22835
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-gauge-item", children: [
22836
+ /* @__PURE__ */ jsx("rect", { x, y: \u5185\u8A33\u306Ey, width: 30, height: 4, rx: 2, fill: arcColor(d.tone, idx) }),
22837
+ /* @__PURE__ */ jsx(
22838
+ "text",
22839
+ {
22840
+ x,
22841
+ y: \u5185\u8A33\u306Ey + 26,
22842
+ fontSize: \u540D\u524D\u306E\u7D1A,
22843
+ fontWeight: 700,
22844
+ fill: "var(--cdl-text, #1a1f2a)",
22845
+ children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u5185\u8A33\u306E\u5E45 - 12, \u540D\u524D\u306E\u7D1A)
22846
+ }
22847
+ ),
22848
+ /* @__PURE__ */ jsx("text", { x, y: \u5185\u8A33\u306Ey + 46, fontSize: \u6570\u5024\u306E\u7D1A, fill: "var(--cdl-text-dim, #5a6270)", children: \u6570\u5024 })
22849
+ ] }, `legend-${idx}`);
22850
+ })
22851
+ ] });
22852
+ }
22853
+ function \u6975(cx, cy, r, a) {
22854
+ return { x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) };
22855
+ }
22856
+ function \u5207\u308A\u8A70\u3081\u308B(s, \u4E0A\u9650, \u7D1A) {
22857
+ if (\u4E0A\u9650 <= 0 || textWidth(s, \u7D1A) <= \u4E0A\u9650) return s;
22858
+ const \u8A18\u53F7\u5E45 = textWidth("\u2026", \u7D1A);
22859
+ let out = "";
22860
+ for (const c of s) {
22861
+ if (textWidth(out + c, \u7D1A) + \u8A18\u53F7\u5E45 > \u4E0A\u9650) break;
22862
+ out += c;
22863
+ }
22864
+ return `${out}\u2026`;
22865
+ }
22866
+ function \u5B9F\u5024\u8868\u8A182(v) {
22867
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
22868
+ }
22869
+ function \u5272\u5408\u8868\u8A182(frac) {
22870
+ const v = Math.round(frac * 1e3) / 10;
22871
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
22872
+ }
22873
+ function arcColor(tone, idx) {
22874
+ if (tone) return TONE[tone];
22875
+ return chartSeriesColor(idx);
22876
+ }
22877
+ function ChartRadialNode({
22878
+ node,
22879
+ active,
22880
+ stateValues = {}
22881
+ }) {
22882
+ const x0 = node.cx - node.w / 2;
22883
+ const y0 = node.cy - node.h / 2;
22884
+ const data = resolveChartData(node.chartData ?? [], stateValues);
22885
+ const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
22886
+ const PAD = 20;
22887
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD * 2;
22888
+ const \u540D\u524D\u306E\u7D1A = 14;
22889
+ const \u6570\u5024\u306E\u7D1A = 13;
22890
+ const \u884C\u306E\u9AD8\u3055 = 42;
22891
+ const \u4E00\u89A7\u3068\u5F27\u306E\u9593 = 28;
22892
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map((d) => `${\u5B9F\u5024\u8868\u8A183(d.value)} ${\u5272\u5408\u8868\u8A183(d.value / total)}`);
22893
+ const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E45 + Math.max(
22894
+ 0,
22895
+ ...data.map(
22896
+ (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
22897
+ )
22898
+ );
22899
+ const \u5F27\u306B\u4F7F\u3048\u308B\u5E45 = node.w - PAD * 2 - \u4E00\u89A7\u306E\u5E45 - \u4E00\u89A7\u3068\u5F27\u306E\u9593;
22900
+ const \u5916\u534A\u5F84 = Math.max(24, Math.min(\u4F7F\u3048\u308B\u9AD8\u3055 / 2, \u5F27\u306B\u4F7F\u3048\u308B\u5E45 / 2));
22901
+ const \u4F7F\u3048\u308B\u539A\u307F = \u5916\u534A\u5F84 * 0.7;
22902
+ const \u5E2F1\u672C = \u4F7F\u3048\u308B\u539A\u307F / Math.max(data.length, 1);
22903
+ const \u5E2F\u306E\u5E45 = \u5E2F1\u672C * 0.66;
22904
+ const \u5F27\u306Ecx = PAD + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u5F27\u306E\u9593 + \u5916\u534A\u5F84;
22905
+ const cy = PAD + \u4F7F\u3048\u308B\u9AD8\u3055 / 2;
22906
+ const rings = data.map((d, idx) => {
22907
+ const frac = d.value / total;
22908
+ const \u4E2D\u5FC3\u534A\u5F84 = \u5916\u534A\u5F84 - \u5E2F1\u672C * idx - \u5E2F1\u672C / 2;
22909
+ return {
22910
+ d,
22911
+ frac,
22912
+ \u4E2D\u5FC3\u534A\u5F84,
22913
+ // 軌道は全周。 1 周ちょうどは弧で表せないので、 わずかに欠かして描く
22914
+ \u8ECC\u9053: \u5F27\u306E\u9053(\u5F27\u306Ecx, cy, \u4E2D\u5FC3\u534A\u5F84, \u5E2F\u306E\u5E45, 0.9999),
22915
+ \u53D6\u308A\u5206: frac <= 0 ? null : \u5F27\u306E\u9053(\u5F27\u306Ecx, cy, \u4E2D\u5FC3\u534A\u5F84, \u5E2F\u306E\u5E45, Math.min(frac, 0.9999))
22916
+ };
22917
+ });
22918
+ 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;
22919
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
22920
+ /* @__PURE__ */ jsx(
22921
+ "rect",
22922
+ {
22923
+ "data-cdl-role": "node-body",
22924
+ x: 0,
22925
+ y: 0,
22926
+ width: node.w,
22927
+ height: node.h,
22928
+ rx: 16,
22929
+ fill: "var(--cdl-node-fill, #ffffff)",
22930
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
22931
+ strokeWidth: active ? 3 : 1.25
22932
+ }
22933
+ ),
22934
+ rings.map((r, idx) => /* @__PURE__ */ jsx(
22935
+ "path",
22936
+ {
22937
+ "data-cdl-role": "chart-radial-track",
22938
+ d: r.\u8ECC\u9053,
22939
+ fill: "var(--cdl-divider, #d4d4d8)",
22940
+ fillOpacity: 0.28
22941
+ },
22942
+ `track-${idx}`
22943
+ )),
22944
+ rings.map(
22945
+ (r, idx) => r.\u53D6\u308A\u5206 === null ? null : /* @__PURE__ */ jsx(
22946
+ "path",
22947
+ {
22948
+ "data-cdl-role": "chart-radial-arc",
22949
+ "data-cdl-unresolved": r.d.unresolved ? "true" : void 0,
22950
+ d: r.\u53D6\u308A\u5206,
22951
+ fill: arcColor2(r.d.tone, idx)
22952
+ },
22953
+ `arc-${idx}`
22954
+ )
22955
+ ),
22956
+ data.map((d, idx) => {
22957
+ const y = \u4E00\u89A7\u306E\u59CB\u307E\u308A + \u884C\u306E\u9AD8\u3055 * idx;
22958
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-radial-item", children: [
22959
+ /* @__PURE__ */ jsx("rect", { x: PAD, y: y - 11, width: 4, height: 22, rx: 2, fill: arcColor2(d.tone, idx) }),
22960
+ /* @__PURE__ */ jsx(
22961
+ "text",
22962
+ {
22963
+ x: PAD + \u5370\u306E\u5E45,
22964
+ y: y + 1,
22965
+ fontSize: \u540D\u524D\u306E\u7D1A,
22966
+ fontWeight: 700,
22967
+ fill: "var(--cdl-text, #1a1f2a)",
22968
+ children: d.label
22969
+ }
22970
+ ),
22971
+ /* @__PURE__ */ jsx(
22972
+ "text",
22973
+ {
22974
+ x: PAD + \u5370\u306E\u5E45,
22975
+ y: y + 20,
22976
+ fontSize: \u6570\u5024\u306E\u7D1A,
22977
+ fill: "var(--cdl-text-dim, #5a6270)",
22978
+ children: \u6570\u5024\u306E\u6587\u5B57[idx]
22979
+ }
22980
+ )
22981
+ ] }, `item-${idx}`);
22982
+ })
22983
+ ] });
22984
+ }
22985
+ var \u5370\u306E\u5E45 = 18;
22986
+ function \u5F27\u306E\u9053(cx, cy, \u4E2D\u5FC3\u534A\u5F84, \u5E45, \u5272\u5408) {
22987
+ const \u5916 = \u4E2D\u5FC3\u534A\u5F84 + \u5E45 / 2;
22988
+ const \u5185 = Math.max(0.5, \u4E2D\u5FC3\u534A\u5F84 - \u5E45 / 2);
22989
+ const a0 = -Math.PI / 2;
22990
+ const a1 = a0 + \u5272\u5408 * Math.PI * 2;
22991
+ const large = \u5272\u5408 > 0.5 ? 1 : 0;
22992
+ const p = (r, a) => `${cx + r * Math.cos(a)} ${cy + r * Math.sin(a)}`;
22993
+ 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`;
22994
+ }
22995
+ function \u5B9F\u5024\u8868\u8A183(v) {
22996
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
22997
+ }
22998
+ function \u5272\u5408\u8868\u8A183(frac) {
22999
+ const v = Math.round(frac * 1e3) / 10;
23000
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
23001
+ }
23002
+ function arcColor2(tone, idx) {
23003
+ if (tone) return TONE[tone];
23004
+ return chartSeriesColor(idx);
23005
+ }
23006
+ function ChartStatNode({
23007
+ node,
23008
+ active,
23009
+ stateValues = {}
23010
+ }) {
23011
+ const x0 = node.cx - node.w / 2;
23012
+ const y0 = node.cy - node.h / 2;
23013
+ const data = resolveChartData(node.chartData ?? [], stateValues);
23014
+ const total = data.reduce((acc, d) => acc + d.value, 0) || 1;
23015
+ const \u533A\u753B = \u533A\u753B\u306E\u5272\u4ED8(node.w, node.h, data.length);
23016
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
23017
+ /* @__PURE__ */ jsx(
23018
+ "rect",
23019
+ {
23020
+ "data-cdl-role": "node-body",
23021
+ x: 0,
23022
+ y: 0,
23023
+ width: node.w,
23024
+ height: node.h,
23025
+ rx: 16,
23026
+ fill: "var(--cdl-node-fill, #ffffff)",
23027
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
23028
+ strokeWidth: active ? 3 : 1.25
23029
+ }
23030
+ ),
23031
+ data.map((d, idx) => {
23032
+ const \u67A0 = \u533A\u753B.\u67A0(idx);
23033
+ const frac = total > 0 ? d.value / total : 0;
23034
+ const \u8272 = \u5370\u306E\u8272(d.tone, idx);
23035
+ const \u6570\u5024 = \u5B9F\u5024\u8868\u8A184(d.value);
23036
+ 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);
23037
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-stat-item", transform: `translate(${\u67A0.x} ${\u67A0.y})`, children: [
23038
+ idx > 0 && /* @__PURE__ */ jsx(
23039
+ "line",
23040
+ {
23041
+ "data-cdl-role": "chart-stat-divider",
23042
+ x1: 0,
23043
+ y1: \u533A\u753B.\u4F59\u767D,
23044
+ x2: 0,
23045
+ y2: \u67A0.h - \u533A\u753B.\u4F59\u767D,
23046
+ stroke: "var(--cdl-divider, #d4d4d8)",
23047
+ strokeWidth: 1
23048
+ }
23049
+ ),
23050
+ /* @__PURE__ */ jsx(
23051
+ "text",
23052
+ {
23053
+ "data-cdl-role": "chart-stat-label",
23054
+ x: \u67A0.w / 2,
23055
+ y: \u533A\u753B.\u540D\u524D\u306Ey,
23056
+ fontSize: \u533A\u753B.\u540D\u524D\u306E\u7D1A,
23057
+ fontWeight: 700,
23058
+ textAnchor: "middle",
23059
+ fill: "var(--cdl-text-dim, #5a6270)",
23060
+ children: d.label
23061
+ }
23062
+ ),
23063
+ /* @__PURE__ */ jsx(
23064
+ "text",
23065
+ {
23066
+ "data-cdl-role": "chart-stat-value",
23067
+ "data-cdl-unresolved": d.unresolved ? "true" : void 0,
23068
+ x: \u67A0.w / 2,
23069
+ y: \u533A\u753B.\u6570\u5024\u306Ey,
23070
+ fontSize: \u6570\u5024\u306E\u7D1A,
23071
+ fontWeight: 700,
23072
+ textAnchor: "middle",
23073
+ fill: \u8272,
23074
+ children: \u6570\u5024
23075
+ }
23076
+ ),
23077
+ /* @__PURE__ */ jsx(
23078
+ "circle",
23079
+ {
23080
+ "data-cdl-role": "chart-stat-track",
23081
+ cx: \u67A0.w / 2,
23082
+ cy: \u533A\u753B.\u5F27\u306Ey,
23083
+ r: \u533A\u753B.\u5F27\u306E\u534A\u5F84,
23084
+ fill: "none",
23085
+ stroke: "var(--cdl-divider, #d4d4d8)",
23086
+ strokeWidth: \u533A\u753B.\u5F27\u306E\u592A\u3055,
23087
+ strokeOpacity: 0.5
23088
+ }
23089
+ ),
23090
+ frac > 0 && /* @__PURE__ */ jsx(
23091
+ "path",
23092
+ {
23093
+ "data-cdl-role": "chart-stat-arc",
23094
+ d: \u5F27\u306E\u90532(\u67A0.w / 2, \u533A\u753B.\u5F27\u306Ey, \u533A\u753B.\u5F27\u306E\u534A\u5F84, Math.min(frac, 0.9999)),
23095
+ fill: "none",
23096
+ stroke: \u8272,
23097
+ strokeWidth: \u533A\u753B.\u5F27\u306E\u592A\u3055,
23098
+ strokeLinecap: "round"
23099
+ }
23100
+ ),
23101
+ /* @__PURE__ */ jsx(
23102
+ "text",
23103
+ {
23104
+ "data-cdl-role": "chart-stat-share",
23105
+ x: \u67A0.w / 2,
23106
+ y: \u533A\u753B.\u5272\u5408\u306Ey,
23107
+ fontSize: \u533A\u753B.\u5272\u5408\u306E\u7D1A,
23108
+ textAnchor: "middle",
23109
+ fill: "var(--cdl-text-dim, #5a6270)",
23110
+ children: \u5272\u5408\u8868\u8A184(frac)
23111
+ }
23112
+ )
23113
+ ] }, `stat-${idx}`);
23114
+ })
23115
+ ] });
23116
+ }
23117
+ function \u533A\u753B\u306E\u5272\u4ED8(w, h, \u4EF6\u6570) {
23118
+ const \u4F59\u767D = 20;
23119
+ const \u5E45 = \u4EF6\u6570 > 0 ? w / \u4EF6\u6570 : w;
23120
+ const \u540D\u524D\u306E\u7D1A = 14;
23121
+ const \u6570\u5024\u306E\u7D1A = 40;
23122
+ const \u5272\u5408\u306E\u7D1A = 12;
23123
+ const \u5F27\u306E\u534A\u5F84 = 20;
23124
+ const \u5F27\u306E\u592A\u3055 = 4;
23125
+ 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;
23126
+ const \u4E0A\u7AEF = Math.max(\u4F59\u767D, (h - \u4E2D\u8EAB\u306E\u9AD8\u3055) / 2);
23127
+ const \u540D\u524D\u306Ey = \u4E0A\u7AEF + \u540D\u524D\u306E\u7D1A;
23128
+ const \u6570\u5024\u306Ey = \u540D\u524D\u306Ey + 12 + \u6570\u5024\u306E\u7D1A * 0.78;
23129
+ const \u5F27\u306Ey = \u6570\u5024\u306Ey + 16 + \u5F27\u306E\u534A\u5F84;
23130
+ const \u5272\u5408\u306Ey = \u5F27\u306Ey + \u5F27\u306E\u534A\u5F84 + 8 + \u5272\u5408\u306E\u7D1A;
23131
+ return {
23132
+ \u4F59\u767D,
23133
+ \u540D\u524D\u306E\u7D1A,
23134
+ \u6570\u5024\u306E\u7D1A,
23135
+ \u5272\u5408\u306E\u7D1A,
23136
+ \u5F27\u306E\u534A\u5F84,
23137
+ \u5F27\u306E\u592A\u3055,
23138
+ \u540D\u524D\u306Ey,
23139
+ \u6570\u5024\u306Ey,
23140
+ \u5F27\u306Ey,
23141
+ \u5272\u5408\u306Ey,
23142
+ \u67A0: (idx) => ({ x: \u5E45 * idx, y: 0, w: \u5E45, h })
23143
+ };
23144
+ }
23145
+ function \u53CE\u3081\u308B\u7D1A(\u5B57, \u4F7F\u3048\u308B\u5E452, \u521D\u671F, \u4E0B\u9650) {
23146
+ let \u7D1A = \u521D\u671F;
23147
+ while (\u7D1A > \u4E0B\u9650 && textWidth(\u5B57, \u7D1A) > \u4F7F\u3048\u308B\u5E452) \u7D1A -= 1;
23148
+ return \u7D1A;
23149
+ }
23150
+ function \u5F27\u306E\u90532(cx, cy, r, \u5272\u5408) {
23151
+ const a0 = -Math.PI / 2;
23152
+ const a1 = a0 + \u5272\u5408 * Math.PI * 2;
23153
+ const large = \u5272\u5408 > 0.5 ? 1 : 0;
23154
+ const p = (a) => `${cx + r * Math.cos(a)} ${cy + r * Math.sin(a)}`;
23155
+ return `M ${p(a0)} A ${r} ${r} 0 ${large} 1 ${p(a1)}`;
23156
+ }
23157
+ function \u5B9F\u5024\u8868\u8A184(v) {
23158
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
23159
+ }
23160
+ function \u5272\u5408\u8868\u8A184(frac) {
23161
+ const v = Math.round(frac * 1e3) / 10;
23162
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
23163
+ }
23164
+ function \u5370\u306E\u8272(tone, idx) {
23165
+ if (tone) return TONE[tone];
23166
+ return chartSeriesColor(idx);
23167
+ }
23168
+ var WAFFLE_TOTAL = 100;
23169
+ var WAFFLE_COLS = 10;
23170
+ function \u5370\u306E\u5272\u4ED8(\u5024) {
23171
+ const \u5408\u8A08 = \u5024.reduce((a, v) => a + Math.max(0, v), 0);
23172
+ if (\u5408\u8A08 <= 0) return \u5024.map(() => 0);
23173
+ const \u751F = \u5024.map((v) => Math.max(0, v) / \u5408\u8A08 * WAFFLE_TOTAL);
23174
+ const \u914D\u5206 = \u751F.map((v) => Math.floor(v));
23175
+ let \u4F59\u308A = WAFFLE_TOTAL - \u914D\u5206.reduce((a, v) => a + v, 0);
23176
+ 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);
23177
+ for (let k = 0; \u4F59\u308A > 0; k = (k + 1) % \u9806.length) {
23178
+ const i = \u9806[k].i;
23179
+ \u914D\u5206[i] = (\u914D\u5206[i] ?? 0) + 1;
23180
+ \u4F59\u308A -= 1;
23181
+ }
23182
+ return \u914D\u5206;
23183
+ }
23184
+ function ChartWaffleNode({
23185
+ node,
23186
+ active,
23187
+ stateValues = {}
23188
+ }) {
23189
+ const x0 = node.cx - node.w / 2;
23190
+ const y0 = node.cy - node.h / 2;
23191
+ const data = resolveChartData(node.chartData ?? [], stateValues);
23192
+ const \u914D\u5206 = \u5370\u306E\u5272\u4ED8(data.map((d) => d.value));
23193
+ const PAD = 20;
23194
+ const \u540D\u524D\u306E\u7D1A = 14;
23195
+ const \u6570\u5024\u306E\u7D1A = 13;
23196
+ const \u884C\u306E\u9AD8\u3055 = 40;
23197
+ const \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593 = 28;
23198
+ const \u5370\u306E\u5E452 = 18;
23199
+ const \u6570\u5024\u306E\u6587\u5B57 = data.map((d, i) => `${\u5B9F\u5024\u8868\u8A185(d.value)} ${\u914D\u5206[i] ?? 0}%`);
23200
+ const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E452 + Math.max(
23201
+ 0,
23202
+ ...data.map(
23203
+ (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
23204
+ )
23205
+ );
23206
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD * 2;
23207
+ const \u683C\u5B50\u306B\u4F7F\u3048\u308B\u5E45 = node.w - PAD * 2 - \u4E00\u89A7\u306E\u5E45 - \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593;
23208
+ const \u5347 = Math.max(4, Math.min(\u4F7F\u3048\u308B\u9AD8\u3055, \u683C\u5B50\u306B\u4F7F\u3048\u308B\u5E45) / WAFFLE_COLS);
23209
+ const \u5370 = \u5347 * 0.78;
23210
+ const \u683C\u5B50\u306E\u5DE6 = PAD + \u4E00\u89A7\u306E\u5E45 + \u4E00\u89A7\u3068\u683C\u5B50\u306E\u9593;
23211
+ const \u683C\u5B50\u306E\u4E0A = PAD + (\u4F7F\u3048\u308B\u9AD8\u3055 - \u5347 * WAFFLE_COLS) / 2;
23212
+ const \u6301\u3061\u4E3B = [];
23213
+ \u914D\u5206.forEach((n, idx) => {
23214
+ for (let k = 0; k < n; k++) \u6301\u3061\u4E3B.push(idx);
23215
+ });
23216
+ 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;
23217
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
23218
+ /* @__PURE__ */ jsx(
23219
+ "rect",
23220
+ {
23221
+ "data-cdl-role": "node-body",
23222
+ x: 0,
23223
+ y: 0,
23224
+ width: node.w,
23225
+ height: node.h,
23226
+ rx: 16,
23227
+ fill: "var(--cdl-node-fill, #ffffff)",
23228
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
23229
+ strokeWidth: active ? 3 : 1.25
23230
+ }
23231
+ ),
23232
+ Array.from({ length: WAFFLE_TOTAL }, (_, k) => {
23233
+ const \u884C = Math.floor(k / WAFFLE_COLS);
23234
+ const \u5217 = k % WAFFLE_COLS;
23235
+ const owner = \u6301\u3061\u4E3B[k];
23236
+ return /* @__PURE__ */ jsx(
23237
+ "rect",
23238
+ {
23239
+ "data-cdl-role": "chart-waffle-cell",
23240
+ "data-cdl-waffle-owner": owner === void 0 ? "" : String(owner),
23241
+ x: \u683C\u5B50\u306E\u5DE6 + \u5347 * \u5217 + (\u5347 - \u5370) / 2,
23242
+ y: \u683C\u5B50\u306E\u4E0A + \u5347 * \u884C + (\u5347 - \u5370) / 2,
23243
+ width: \u5370,
23244
+ height: \u5370,
23245
+ rx: 2,
23246
+ fill: owner === void 0 ? "var(--cdl-divider, #d4d4d8)" : \u5370\u306E\u82722(data[owner].tone, owner),
23247
+ fillOpacity: owner === void 0 ? 0.35 : 1
23248
+ },
23249
+ `cell-${k}`
23250
+ );
23251
+ }),
23252
+ data.map((d, idx) => {
23253
+ const y = \u4E00\u89A7\u306E\u59CB\u307E\u308A + \u884C\u306E\u9AD8\u3055 * idx;
23254
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-waffle-item", children: [
23255
+ /* @__PURE__ */ jsx("rect", { x: PAD, y: y - 11, width: 4, height: 22, rx: 2, fill: \u5370\u306E\u82722(d.tone, idx) }),
23256
+ /* @__PURE__ */ jsx(
23257
+ "text",
23258
+ {
23259
+ x: PAD + \u5370\u306E\u5E452,
23260
+ y: y + 1,
23261
+ fontSize: \u540D\u524D\u306E\u7D1A,
23262
+ fontWeight: 700,
23263
+ fill: "var(--cdl-text, #1a1f2a)",
23264
+ children: d.label
23265
+ }
23266
+ ),
23267
+ /* @__PURE__ */ jsx(
23268
+ "text",
23269
+ {
23270
+ "data-cdl-role": "chart-waffle-count",
23271
+ "data-cdl-unresolved": d.unresolved ? "true" : void 0,
23272
+ x: PAD + \u5370\u306E\u5E452,
23273
+ y: y + 20,
23274
+ fontSize: \u6570\u5024\u306E\u7D1A,
23275
+ fill: "var(--cdl-text-dim, #5a6270)",
23276
+ children: \u6570\u5024\u306E\u6587\u5B57[idx]
23277
+ }
23278
+ )
23279
+ ] }, `item-${idx}`);
23280
+ })
23281
+ ] });
23282
+ }
23283
+ function \u5B9F\u5024\u8868\u8A185(v) {
23284
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
23285
+ }
23286
+ function \u5370\u306E\u82722(tone, idx) {
23287
+ if (tone) return TONE[tone];
23288
+ return chartSeriesColor(idx);
23289
+ }
23290
+ var SLICE_MIN_W_FOR_TEXT = 44;
23291
+ var SLICE_MIN_W_FOR_VALUE = 84;
23292
+ function ChartStackedBarNode({
23293
+ node,
23294
+ active,
23295
+ stateValues = {}
23296
+ }) {
23297
+ const x0 = node.cx - node.w / 2;
23298
+ const y0 = node.cy - node.h / 2;
23299
+ const data = resolveChartData(node.chartData ?? [], stateValues);
23300
+ const \u5E2F\u305F\u3061 = \u5E2F\u306E\u4E26\u3073(data);
23301
+ const PAD = 24;
23302
+ const \u540D\u524D\u306E\u7D1A = 13;
23303
+ const \u533A\u753B\u306E\u7D1A = 12;
23304
+ const \u6642\u70B9\u306E\u7D1A = 13;
23305
+ 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);
23306
+ const \u5E2F\u306E\u5DE6 = PAD + \u6642\u70B9\u306E\u5E45;
23307
+ const \u5E2F\u306E\u5E45 = Math.max(40, node.w - \u5E2F\u306E\u5DE6 - PAD);
23308
+ const \u5E2F\u306E\u9AD8\u3055 = 44;
23309
+ const \u5E2F\u306E\u9593 = 20;
23310
+ const \u4E00\u89A7\u306E\u9AD8\u3055 = 26;
23311
+ 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;
23312
+ const \u4E0A\u7AEF = Math.max(PAD, (node.h - \u5168\u4F53\u306E\u9AD8\u3055) / 2);
23313
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
23314
+ /* @__PURE__ */ jsx(
23315
+ "rect",
23316
+ {
23317
+ "data-cdl-role": "node-body",
23318
+ x: 0,
23319
+ y: 0,
23320
+ width: node.w,
23321
+ height: node.h,
23322
+ rx: 16,
23323
+ fill: "var(--cdl-node-fill, #ffffff)",
23324
+ stroke: active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)",
23325
+ strokeWidth: active ? 3 : 1.25
23326
+ }
23327
+ ),
23328
+ \u5E2F\u305F\u3061.map((\u5E2F, \u6BB5) => {
23329
+ const y = \u4E0A\u7AEF + \u6BB5 * (\u5E2F\u306E\u9AD8\u3055 + \u5E2F\u306E\u9593);
23330
+ let \u5DE6 = \u5E2F\u306E\u5DE6;
23331
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-stacked-bar-row", children: [
23332
+ \u5E2F\u305F\u3061.length > 1 && /* @__PURE__ */ jsx(
23333
+ "text",
23334
+ {
23335
+ "data-cdl-role": "chart-stacked-bar-period",
23336
+ x: PAD,
23337
+ y: y + \u5E2F\u306E\u9AD8\u3055 / 2 + 4,
23338
+ fontSize: \u6642\u70B9\u306E\u7D1A,
23339
+ fontWeight: 700,
23340
+ fill: "var(--cdl-text-dim, #5a6270)",
23341
+ children: \u5E2F.\u540D\u524D
23342
+ }
23343
+ ),
23344
+ \u5E2F.\u533A\u753B.map((s, idx) => {
23345
+ const w = \u5E2F\u306E\u5E45 * s.\u5272\u5408;
23346
+ const x = \u5DE6;
23347
+ \u5DE6 += w;
23348
+ const \u8272 = \u5370\u306E\u82723(s.tone, idx);
23349
+ return /* @__PURE__ */ jsxs("g", { children: [
23350
+ /* @__PURE__ */ jsx(
23351
+ "rect",
23352
+ {
23353
+ "data-cdl-role": "chart-stacked-bar-slice",
23354
+ "data-cdl-unresolved": s.unresolved ? "true" : void 0,
23355
+ x,
23356
+ y,
23357
+ width: Math.max(0, w),
23358
+ height: \u5E2F\u306E\u9AD8\u3055,
23359
+ fill: \u8272
23360
+ }
23361
+ ),
23362
+ w >= SLICE_MIN_W_FOR_TEXT && /* @__PURE__ */ jsx(
23363
+ "text",
23364
+ {
23365
+ "data-cdl-role": "chart-stacked-bar-slice-text",
23366
+ x: x + w / 2,
23367
+ y: y + \u5E2F\u306E\u9AD8\u3055 / 2 + (w >= SLICE_MIN_W_FOR_VALUE ? -2 : 4),
23368
+ fontSize: \u533A\u753B\u306E\u7D1A,
23369
+ fontWeight: 700,
23370
+ textAnchor: "middle",
23371
+ fill: "#ffffff",
23372
+ children: \u5272\u5408\u8868\u8A185(s.\u5272\u5408)
23373
+ }
23374
+ ),
23375
+ w >= SLICE_MIN_W_FOR_VALUE && /* @__PURE__ */ jsx(
23376
+ "text",
23377
+ {
23378
+ "data-cdl-role": "chart-stacked-bar-slice-value",
23379
+ x: x + w / 2,
23380
+ y: y + \u5E2F\u306E\u9AD8\u3055 / 2 + 13,
23381
+ fontSize: \u533A\u753B\u306E\u7D1A - 1,
23382
+ textAnchor: "middle",
23383
+ fill: "#ffffff",
23384
+ fillOpacity: 0.85,
23385
+ children: \u5B9F\u5024\u8868\u8A186(s.\u5B9F\u5024)
23386
+ }
23387
+ )
23388
+ ] }, `slice-${idx}`);
23389
+ })
23390
+ ] }, `bar-${\u6BB5}`);
23391
+ }),
23392
+ \u4E00\u89A7\u306E\u4E26\u3073(data, \u5E2F\u306E\u5DE6, node.w - PAD, \u540D\u524D\u306E\u7D1A).map(({ d, idx, x, \u884C }) => {
23393
+ 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;
23394
+ return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-stacked-bar-legend", children: [
23395
+ /* @__PURE__ */ jsx("rect", { x, y: y - 5, width: 10, height: 10, rx: 2, fill: \u5370\u306E\u82723(d.tone, idx) }),
23396
+ /* @__PURE__ */ jsx(
23397
+ "text",
23398
+ {
23399
+ x: x + 16,
23400
+ y: y + 4,
23401
+ fontSize: \u540D\u524D\u306E\u7D1A,
23402
+ fill: "var(--cdl-text, #1a1f2a)",
23403
+ children: d.label
23404
+ }
23405
+ )
23406
+ ] }, `legend-${idx}`);
23407
+ })
23408
+ ] });
23409
+ }
23410
+ function \u5E2F\u306E\u4E26\u3073(data) {
23411
+ const \u524D\u3042\u308A = data.some((d) => d.previous !== void 0);
23412
+ const \u4ECA = \u5E2F\u3092\u7D44\u3080("\u4ECA", data, (d) => d.value);
23413
+ if (!\u524D\u3042\u308A) return [\u4ECA];
23414
+ return [\u5E2F\u3092\u7D44\u3080("\u524D", data, (d) => d.previous ?? 0), \u4ECA];
23415
+ }
23416
+ function \u5E2F\u3092\u7D44\u3080(\u540D\u524D, data, \u53D6\u308B) {
23417
+ const \u5024 = data.map((d) => Math.max(0, \u53D6\u308B(d)));
23418
+ const \u5408\u8A08 = \u5024.reduce((a, v) => a + v, 0);
23419
+ return {
23420
+ \u540D\u524D,
23421
+ \u533A\u753B: data.map((d, i) => ({
23422
+ // 合計 0 の帯は区画を持たない (0 で割らない)。 幅 0 の区画として並べる
23423
+ \u5272\u5408: \u5408\u8A08 > 0 ? \u5024[i] / \u5408\u8A08 : 0,
23424
+ \u5B9F\u5024: \u5024[i],
23425
+ tone: d.tone,
23426
+ ...d.unresolved ? { unresolved: true } : {}
23427
+ }))
23428
+ };
23429
+ }
23430
+ function \u5B9F\u5024\u8868\u8A186(v) {
23431
+ return Number.isInteger(v) ? v.toLocaleString("en-US") : v.toLocaleString("en-US", { maximumFractionDigits: 1 });
23432
+ }
23433
+ function \u5272\u5408\u8868\u8A185(frac) {
23434
+ const v = Math.round(frac * 1e3) / 10;
23435
+ return `${Number.isInteger(v) ? v : v.toFixed(1)}%`;
23436
+ }
23437
+ function \u5370\u306E\u82723(tone, idx) {
23438
+ if (tone) return TONE[tone];
23439
+ return chartSeriesColor(idx);
23440
+ }
23441
+ var \u5370\u304B\u3089\u540D\u524D\u307E\u3067 = 16;
23442
+ var \u4EF6\u306E\u9593 = 10;
23443
+ function \u4E00\u89A7\u306E\u4E26\u3073(data, \u5DE6, \u53F3\u7AEF, \u7D1A) {
23444
+ const out = [];
23445
+ let x = \u5DE6;
23446
+ let \u884C = 0;
23447
+ data.forEach((d, idx) => {
23448
+ const \u5E45 = \u5370\u304B\u3089\u540D\u524D\u307E\u3067 + textWidth(d.label ?? "", \u7D1A);
23449
+ if (x > \u5DE6 && x + \u5E45 > \u53F3\u7AEF) {
23450
+ \u884C += 1;
23451
+ x = \u5DE6;
23452
+ }
23453
+ out.push({ d, idx, x, \u884C });
23454
+ x += \u5E45 + \u4EF6\u306E\u9593;
23455
+ });
23456
+ return out;
22377
23457
  }
22378
23458
  function ChartBarNode({
22379
23459
  node,
@@ -27045,6 +28125,16 @@ function CdlNodeView({
27045
28125
  progress
27046
28126
  }
27047
28127
  );
28128
+ case "chart-gauge":
28129
+ return /* @__PURE__ */ jsx(ChartGaugeNode, { node: resolvedNode, active, stateValues });
28130
+ case "chart-stacked-bar":
28131
+ return /* @__PURE__ */ jsx(ChartStackedBarNode, { node: resolvedNode, active, stateValues });
28132
+ case "chart-waffle":
28133
+ return /* @__PURE__ */ jsx(ChartWaffleNode, { node: resolvedNode, active, stateValues });
28134
+ case "chart-stat":
28135
+ return /* @__PURE__ */ jsx(ChartStatNode, { node: resolvedNode, active, stateValues });
28136
+ case "chart-radial":
28137
+ return /* @__PURE__ */ jsx(ChartRadialNode, { node: resolvedNode, active, stateValues });
27048
28138
  case "chart-bar":
27049
28139
  return /* @__PURE__ */ jsx(
27050
28140
  ChartBarNode,
@@ -27211,6 +28301,10 @@ function CdlNodeView({
27211
28301
  return /* @__PURE__ */ jsx(ShapeTraderNode, { node: resolvedNode, active });
27212
28302
  case "shape-customer-service":
27213
28303
  return /* @__PURE__ */ jsx(ShapeCustomerServiceNode, { node: resolvedNode, active });
28304
+ case "mark-start":
28305
+ return /* @__PURE__ */ jsx(MarkStartNode, { node: resolvedNode, active });
28306
+ case "mark-end":
28307
+ return /* @__PURE__ */ jsx(MarkEndNode, { node: resolvedNode, active });
27214
28308
  default:
27215
28309
  return /* @__PURE__ */ jsx(GenericNode, { node: resolvedNode, active, value: node.value, stateValues });
27216
28310
  }
@@ -27280,6 +28374,21 @@ function uniformLifelineEndY(lanes, nodes, starts = lifelineStartYs(nodes)) {
27280
28374
  if (footerTops.length > 0) return Math.min(...footerTops);
27281
28375
  return lifelineLanes[0] ? lifelineLanes[0].y + lifelineLanes[0].height : 0;
27282
28376
  }
28377
+
28378
+ // src/kinds/draw-ratio.ts
28379
+ var DRAW_RATIO_DEFAULT = 1;
28380
+ function \u63CF\u304F\u5272\u5408\u3092\u6B63\u3059(ratio) {
28381
+ if (ratio === void 0) return DRAW_RATIO_DEFAULT;
28382
+ if (!Number.isFinite(ratio)) return DRAW_RATIO_DEFAULT;
28383
+ if (ratio <= 0 || ratio > 1) return DRAW_RATIO_DEFAULT;
28384
+ return ratio;
28385
+ }
28386
+ function \u63CF\u304F\u9032\u307F\u306B\u76F4\u3059(progress, ratio) {
28387
+ const \u5272\u5408 = \u63CF\u304F\u5272\u5408\u3092\u6B63\u3059(ratio);
28388
+ if (\u5272\u5408 === DRAW_RATIO_DEFAULT) return progress;
28389
+ if (!Number.isFinite(progress)) return progress;
28390
+ return Math.min(1, progress / \u5272\u5408);
28391
+ }
27283
28392
  function CdlStage({
27284
28393
  laid,
27285
28394
  currentPhase,
@@ -27291,6 +28400,7 @@ function CdlStage({
27291
28400
  }) {
27292
28401
  const activeSet = new Set(currentPhase?.activate ?? []);
27293
28402
  const drawSet = new Set(currentPhase?.draw ?? []);
28403
+ const \u63CF\u304F\u9032\u307F = \u63CF\u304F\u9032\u307F\u306B\u76F4\u3059(progress, currentPhase?.drawRatio);
27294
28404
  const { lifelineStarts, uniformFooterTop } = useMemo(() => {
27295
28405
  const starts = lifelineStartYs(laid.nodes);
27296
28406
  return {
@@ -27315,21 +28425,38 @@ function CdlStage({
27315
28425
  children: [
27316
28426
  /* @__PURE__ */ jsxs("defs", { children: [
27317
28427
  Object.entries(TONE).flatMap(
27318
- ([tone, color]) => [["", 14], ["-sm", 10]].map(([suffix, size]) => /* @__PURE__ */ jsx(
27319
- "marker",
27320
- {
27321
- id: `cdl-arrow-${tone}${suffix}`,
27322
- viewBox: "0 0 10 10",
27323
- refX: "9",
27324
- refY: "5",
27325
- markerWidth: size,
27326
- markerHeight: size,
27327
- markerUnits: "userSpaceOnUse",
27328
- orient: "auto-start-reverse",
27329
- children: /* @__PURE__ */ jsx("path", { "data-cdl-role": "edge-arrowhead", d: "M 0 0 L 10 5 L 0 10 z", fill: color })
27330
- },
27331
- `${tone}${suffix}`
27332
- ))
28428
+ ([tone, color]) => [["", 14], ["-sm", 10]].flatMap(
28429
+ ([suffix, size]) => EDGE_HEADS.map((head) => {
28430
+ const \u5F62 = EDGE_HEAD_SHAPE[head];
28431
+ return /* @__PURE__ */ jsx(
28432
+ "marker",
28433
+ {
28434
+ id: edgeHeadMarkerId(tone, head, suffix === "-sm"),
28435
+ viewBox: "0 0 10 10",
28436
+ refX: \u5F62.refX,
28437
+ refY: "5",
28438
+ markerWidth: size,
28439
+ markerHeight: size,
28440
+ markerUnits: "userSpaceOnUse",
28441
+ orient: "auto-start-reverse",
28442
+ children: /* @__PURE__ */ jsx(
28443
+ "path",
28444
+ {
28445
+ "data-cdl-role": "edge-arrowhead",
28446
+ "data-cdl-edge-head": head,
28447
+ d: \u5F62.d,
28448
+ fill: \u5F62.filled ? color : "none",
28449
+ stroke: \u5F62.filled ? "none" : color,
28450
+ strokeWidth: \u5F62.filled ? void 0 : 1.6,
28451
+ strokeLinecap: \u5F62.filled ? void 0 : "round",
28452
+ strokeLinejoin: \u5F62.filled ? void 0 : "round"
28453
+ }
28454
+ )
28455
+ },
28456
+ `${tone}${suffix}-${head}`
28457
+ );
28458
+ })
28459
+ )
27333
28460
  ),
27334
28461
  /* @__PURE__ */ jsx(
27335
28462
  "marker",
@@ -27422,13 +28549,14 @@ function CdlStage({
27422
28549
  )),
27423
28550
  laid.edges.map((edge) => /* @__PURE__ */ jsx(CdlEdgeView, { edge, active: activeSet.has(edge.id), progress, stateValues }, edge.id)),
27424
28551
  laid.nodes.map((node) => {
28552
+ const \u63CF\u304F = drawSet.has(node.id);
27425
28553
  const view = /* @__PURE__ */ jsx(
27426
28554
  CdlNodeView,
27427
28555
  {
27428
28556
  node,
27429
28557
  active: activeSet.has(node.id),
27430
- drawing: drawSet.has(node.id),
27431
- progress,
28558
+ drawing: \u63CF\u304F,
28559
+ progress: \u63CF\u304F ? \u63CF\u304F\u9032\u307F : progress,
27432
28560
  stateValues,
27433
28561
  currentPhaseId: currentPhase?.id
27434
28562
  }
@@ -28299,6 +29427,13 @@ function infrastructure(preset) {
28299
29427
  };
28300
29428
  return api;
28301
29429
  }
29430
+ var CLASS_RELATION_HEAD = {
29431
+ extends: "triangle",
29432
+ implements: "triangle",
29433
+ uses: "open",
29434
+ aggregates: "diamond",
29435
+ composes: "diamond"
29436
+ };
28302
29437
  function classDiagram(preset) {
28303
29438
  const classW = resolveStorageBoxW(preset.classWidth, "classDiagram", "classWidth");
28304
29439
  const tone = preset.defaultTone ?? "info";
@@ -28342,7 +29477,9 @@ function classDiagram(preset) {
28342
29477
  label,
28343
29478
  ...sub ? { sub } : {},
28344
29479
  tone: r.tone ?? tone,
28345
- style: "solid"
29480
+ style: "solid",
29481
+ // 関係の種類から端の形を決める (cdl#574)。 書いた形が勝つ
29482
+ head: r.head ?? CLASS_RELATION_HEAD[r.type]
28346
29483
  // CAR-531 SSOT ... 旧実装は `labelOffsetY: currentIdx % 2 === 0 ? -60 : 60` で
28347
29484
  // 複数 relation label の path 沿い集中を強制分散していた。 CAR-430 で導入した
28348
29485
  // engine 側 fan offset (FAN_STEP 40 world) が同 from / to 群を自動分散する現在、
@@ -28576,13 +29713,20 @@ function quadrant(preset) {
28576
29713
  }
28577
29714
  function chart(preset) {
28578
29715
  const canvasW = toGridSize(preset.itemWidth ?? 640);
28579
- const canvasH = toGridSize(preset.type === "pie" ? 320 : 360);
29716
+ const canvasH = toGridSize(
29717
+ preset.type === "pie" || preset.type === "gauge" || preset.type === "radial" || preset.type === "stat" || preset.type === "waffle" || preset.type === "stacked-bar" ? 320 : 360
29718
+ );
28580
29719
  const b = diagram(preset.id, { topic: preset.topic });
28581
29720
  const data = [];
28582
29721
  const kindMap = {
28583
29722
  line: "chart-line",
28584
29723
  pie: "chart-pie",
28585
- bar: "chart-bar"
29724
+ bar: "chart-bar",
29725
+ gauge: "chart-gauge",
29726
+ radial: "chart-radial",
29727
+ stat: "chart-stat",
29728
+ waffle: "chart-waffle",
29729
+ "stacked-bar": "chart-stacked-bar"
28586
29730
  };
28587
29731
  const api = {
28588
29732
  datum(d) {
@@ -28600,7 +29744,12 @@ function chart(preset) {
28600
29744
  eyebrow: preset.type,
28601
29745
  w: canvasW,
28602
29746
  h: canvasH,
28603
- chartData: data.map((d) => ({ label: d.label, value: d.value, tone: d.tone }))
29747
+ chartData: data.map((d) => ({
29748
+ label: d.label,
29749
+ value: d.value,
29750
+ ...d.previous === void 0 ? {} : { previous: d.previous },
29751
+ tone: d.tone
29752
+ }))
28604
29753
  });
28605
29754
  b.phase(
28606
29755
  "chart",
@@ -28853,6 +30002,6 @@ function slugify(s) {
28853
30002
  return s.toLowerCase().replace(/[^a-z0-9぀-ゟ゠-ヿ一-龯]+/g, "-").replace(/^-|-$/g, "");
28854
30003
  }
28855
30004
 
28856
- export { ARROW_ANGLE_MAX_DEG, ARROW_ENDPOINT_CENTER_TOL, CHAIN_MIN_CLEARANCE, CHAIN_SHIFT_MAX_ACCUMULATED, CHAIN_SHIFT_MAX_ITER, CLEARANCE_LABEL_LABEL, CLEARANCE_LANE_LABEL, CLEARANCE_NODE_LABEL, CLEARANCE_PATH_LABEL, COLUMN_GAP_VARIANCE_TOL, CdlDiagramThumbnail, CdlDiagramView, DETOUR_GAP, DETOUR_SLOT_GAP, DIST_LABEL_PATH_MAX, DIST_LABEL_PATH_MIN, EDGE_LABEL_TEXT, EDGE_STUB_OUT, FAN_GAP, FONT_RENDER_TOLERANCE_WORLD, LABEL_INIT_CLEARANCE, LABEL_INIT_CLEARANCE_DOTTED_FLOW, LABEL_SIZE_TOLERANCE_WORLD, LABEL_TO_PATH_CLEARANCE, LANE_BORDER_CLEARANCE_TOL, MARKER_GLOW_RADIUS, MIN_COLUMN_ALIGNMENT_TOLERANCE, MIN_ROW_ALIGNMENT_TOLERANCE, NEAR_COLLISION_DEFAULT_MIN, NEAR_COLLISION_POLICY, NODE_FRAME_SELECTOR, NODE_KINDS, ROW_GAP_VARIANCE_TOL, SPEC_CLEARANCE_POLICY, STAGE_SVG_SELECTOR, TARGET_LABEL_PATH_DIST, TONES, WCAG_AA_LARGE, WCAG_AA_NORMAL, applyDerivedValues, assertNever, attachEventHandlers, batch, bboxClearance, bboxDiffWorld, cdlAdapter, chart, classDiagram, compile, computeEventBindingKey, computeFormulaKey, computeInputSignalKey, computeScrollProgress, computeScrollTriggerKey, computeStateValues, computeViewportScale, computed, countEdgeCrossings, createFormulaComputeds, createInputSignals, createInteractiveSignalsAccessor, createScrollProgressHandle, createScrollProgressSignals, diagram, effect, er, evaluate as evaluateFormula, extractIdentifiers, flow, flowchart, funnel, gantt, hasInteractivePrimitives, infrastructure, inputDefaultValue, interpolate, isLargeText, labelInitClearance, layout, layoutWithValidation, mindMap, network, parseFormula, pointRectEdgeDistance, pointToSegmentDistance2 as pointToSegmentDistance, predictLabelBBoxWorld, predictNodeBBoxWorld, projectEdgeLabel, projectNode, projectPathSegment, pxToWorld, quadrant, rectRectClearance, rectRectOverlapArea, rendersRows, requiredContrastRatio, requiredNearClearance, requiredRowsHeight, requiredRowsWidth, requiredSpecClearance, resolveEdgeLabelOverlapsWithChain, resolveEdgeLabelOverlapsWithChainAndPropagate, resolveOverlapsWithChain, resolveTarget, resolveTargetAll, segmentsIntersect2 as segmentsIntersect, sequence, signal, stateMachine, stateMachine2, swimlane, topology, tree, untrack, userJourney, validate, verifyAllDiagramsDom, verifyAuthorIntent, verifyAuthorIntentAll, verifyDiagramDom, visualValidate, visualValidateAll, visualValidateLaid, withDerivedValues, worldToPx };
30005
+ export { ARROW_ANGLE_MAX_DEG, ARROW_ENDPOINT_CENTER_TOL, CHAIN_MIN_CLEARANCE, CHAIN_SHIFT_MAX_ACCUMULATED, CHAIN_SHIFT_MAX_ITER, CLEARANCE_LABEL_LABEL, CLEARANCE_LANE_LABEL, CLEARANCE_NODE_LABEL, CLEARANCE_PATH_LABEL, COLUMN_GAP_VARIANCE_TOL, CdlDiagramThumbnail, CdlDiagramView, DETOUR_GAP, DETOUR_SLOT_GAP, DIST_LABEL_PATH_MAX, DIST_LABEL_PATH_MIN, EDGE_HEADS, EDGE_HEAD_DEFAULT, EDGE_LABEL_TEXT, EDGE_STUB_OUT, FAN_GAP, FONT_RENDER_TOLERANCE_WORLD, LABEL_INIT_CLEARANCE, LABEL_INIT_CLEARANCE_DOTTED_FLOW, LABEL_SIZE_TOLERANCE_WORLD, LABEL_TO_PATH_CLEARANCE, LANE_BORDER_CLEARANCE_TOL, MARKER_GLOW_RADIUS, MIN_COLUMN_ALIGNMENT_TOLERANCE, MIN_ROW_ALIGNMENT_TOLERANCE, NEAR_COLLISION_DEFAULT_MIN, NEAR_COLLISION_POLICY, NODE_FRAME_SELECTOR, NODE_KINDS, ROW_GAP_VARIANCE_TOL, SPEC_CLEARANCE_POLICY, STAGE_SVG_SELECTOR, TARGET_LABEL_PATH_DIST, TONES, WCAG_AA_LARGE, WCAG_AA_NORMAL, applyDerivedValues, assertNever, attachEventHandlers, batch, bboxClearance, bboxDiffWorld, cdlAdapter, chart, classDiagram, compile, computeEventBindingKey, computeFormulaKey, computeInputSignalKey, computeScrollProgress, computeScrollTriggerKey, computeStateValues, computeViewportScale, computed, countEdgeCrossings, createFormulaComputeds, createInputSignals, createInteractiveSignalsAccessor, createScrollProgressHandle, createScrollProgressSignals, diagram, effect, er, evaluate as evaluateFormula, extractIdentifiers, flow, flowchart, funnel, gantt, hasInteractivePrimitives, infrastructure, inputDefaultValue, interpolate, isLargeText, labelInitClearance, layout, layoutWithValidation, mindMap, network, parseFormula, pointRectEdgeDistance, pointToSegmentDistance2 as pointToSegmentDistance, predictLabelBBoxWorld, predictNodeBBoxWorld, projectEdgeLabel, projectNode, projectPathSegment, pxToWorld, quadrant, rectRectClearance, rectRectOverlapArea, rendersRows, requiredContrastRatio, requiredNearClearance, requiredRowsHeight, requiredRowsWidth, requiredSpecClearance, resolveEdgeLabelOverlapsWithChain, resolveEdgeLabelOverlapsWithChainAndPropagate, resolveOverlapsWithChain, resolveTarget, resolveTargetAll, segmentsIntersect2 as segmentsIntersect, sequence, signal, stateMachine, stateMachine2, swimlane, topology, tree, untrack, userJourney, validate, verifyAllDiagramsDom, verifyAuthorIntent, verifyAuthorIntentAll, verifyDiagramDom, visualValidate, visualValidateAll, visualValidateLaid, withDerivedValues, worldToPx };
28857
30006
  //# sourceMappingURL=index.js.map
28858
30007
  //# sourceMappingURL=index.js.map