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