@cardenelabs/cdl 0.50.0 → 0.52.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.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CdlDiagram, S as Signal, a as CdlInput, b as CdlLane, c as CdlNode, T as Tone, d as Side, E as EdgeStyle, e as EdgeRole, f as EdgeHead, g as EdgeHeadFill, h as CdlState, i as CdlEventTarget, j as Computed, k as CdlDerivedValue, l as CdlScrollTrigger, L as LaidDiagram, m as CdlDiagramViewProps, n as LaidEdge, o as LaidNode, p as CdlEdge, B as BBox, R as RowMark, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-C53-PeJZ.cjs';
2
- export { q as CdlDiagramView, r as CdlEventBinding, s as CdlEventKind, t as CdlFormula, u as CdlPhase, v as ChartPieForm, w as ChartSlopeForm, x as EDGE_HEADS, y as EDGE_HEAD_DEFAULT, z as EDGE_HEAD_FILLS, A as EDGE_HEAD_FILL_DEFAULT, D as EDGE_REVEALS, F as EDGE_REVEAL_DEFAULT, G as EDGE_STYLES, H as EdgeReveal, I as InteractiveHandlerMap, K as InteractiveSignalsAccessor, M as LaidLane, O as NODE_KINDS, P as RELATION_FOCUSES, U as RELATION_FOCUS_DEFAULT, V as RelationFocus, W as ScrollProgressHandle, X as TONES, Y as computeEventBindingKey, Z as computeFormulaKey, _ as computeInputSignalKey, $ as computeScrollTriggerKey, a0 as computed, a1 as createInteractiveSignalsAccessor, a2 as createScrollProgressHandle, a3 as createScrollProgressSignals, a4 as hasInteractivePrimitives, a5 as sequenceBoardMetrics, a6 as sequenceStepId, a7 as signal } from './render-C53-PeJZ.cjs';
1
+ import { C as CdlDiagram, S as Signal, a as CdlInput, b as CdlLane, c as CdlNode, T as Tone, d as Side, E as EdgeStyle, e as EdgeRole, f as EdgeHead, g as EdgeHeadFill, h as CdlState, i as CdlEventTarget, j as Computed, k as CdlDerivedValue, l as CdlScrollTrigger, L as LaidDiagram, m as CdlDiagramViewProps, n as LaidEdge, o as LaidNode, p as CdlEdge, B as BBox, R as RowMark, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-C0PJ2weJ.cjs';
2
+ export { q as CdlDiagramView, r as CdlEventBinding, s as CdlEventKind, t as CdlFormula, u as CdlPhase, v as ChartPieForm, w as ChartSlopeForm, x as EDGE_HEADS, y as EDGE_HEAD_DEFAULT, z as EDGE_HEAD_FILLS, A as EDGE_HEAD_FILL_DEFAULT, D as EDGE_REVEALS, F as EDGE_REVEAL_DEFAULT, G as EDGE_STYLES, H as EdgeReveal, I as InteractiveHandlerMap, K as InteractiveSignalsAccessor, M as LaidLane, O as NODE_KINDS, P as RELATION_FOCUSES, U as RELATION_FOCUS_DEFAULT, V as RelationFocus, W as ScrollProgressHandle, X as TONES, Y as computeEventBindingKey, Z as computeFormulaKey, _ as computeInputSignalKey, $ as computeScrollTriggerKey, a0 as computed, a1 as createInteractiveSignalsAccessor, a2 as createScrollProgressHandle, a3 as createScrollProgressSignals, a4 as hasInteractivePrimitives, a5 as sequenceBoardMetrics, a6 as sequenceStepId, a7 as signal } from './render-C0PJ2weJ.cjs';
3
3
  import { JSX } from 'react';
4
4
 
5
5
  declare function effect(fn: () => void | (() => void)): () => void;
@@ -1046,6 +1046,10 @@ type DiagramBuilder = {
1046
1046
  guard?: string;
1047
1047
  /** ER 関係 cardinality、 text-dsl v0.5 inline option (`cardinality: "1:N"`) を CdlEdge.cardinality へ透過 */
1048
1048
  cardinality?: string;
1049
+ /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1050
+ headLabel?: string;
1051
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1052
+ tailLabel?: string;
1049
1053
  labelOffsetX?: number;
1050
1054
  labelOffsetY?: number;
1051
1055
  routing?: "default" | "back-detour";
@@ -1136,6 +1140,10 @@ type DiagramBuilder = {
1136
1140
  tailHeadFill?: EdgeHeadFill;
1137
1141
  guard?: string;
1138
1142
  cardinality?: string;
1143
+ /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1144
+ headLabel?: string;
1145
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1146
+ tailLabel?: string;
1139
1147
  labelOffsetX?: number;
1140
1148
  labelOffsetY?: number;
1141
1149
  routing?: "default" | "back-detour";
@@ -3406,8 +3414,10 @@ type UmlRelation = {
3406
3414
  type: ClassRelationType;
3407
3415
  /** 関係 label (default は type 名) */
3408
3416
  label?: string;
3409
- /** 多重度 (例 "1..*" / "0..1") */
3417
+ /** 多重度 (例 "1..*" / "0..1")。 行き先 (`to`) の端に添える (#821) */
3410
3418
  cardinality?: string;
3419
+ /** 出どころ (`from`) 側の多重度 (例 "1")。 出どころの端に添える (#825) */
3420
+ tailCardinality?: string;
3411
3421
  tone?: Tone;
3412
3422
  /**
3413
3423
  * 矢印の先の形 (cdl#574)。 書かなければ種類から決まる (`CLASS_RELATION_LOOK`)。
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CdlDiagram, S as Signal, a as CdlInput, b as CdlLane, c as CdlNode, T as Tone, d as Side, E as EdgeStyle, e as EdgeRole, f as EdgeHead, g as EdgeHeadFill, h as CdlState, i as CdlEventTarget, j as Computed, k as CdlDerivedValue, l as CdlScrollTrigger, L as LaidDiagram, m as CdlDiagramViewProps, n as LaidEdge, o as LaidNode, p as CdlEdge, B as BBox, R as RowMark, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-C53-PeJZ.js';
2
- export { q as CdlDiagramView, r as CdlEventBinding, s as CdlEventKind, t as CdlFormula, u as CdlPhase, v as ChartPieForm, w as ChartSlopeForm, x as EDGE_HEADS, y as EDGE_HEAD_DEFAULT, z as EDGE_HEAD_FILLS, A as EDGE_HEAD_FILL_DEFAULT, D as EDGE_REVEALS, F as EDGE_REVEAL_DEFAULT, G as EDGE_STYLES, H as EdgeReveal, I as InteractiveHandlerMap, K as InteractiveSignalsAccessor, M as LaidLane, O as NODE_KINDS, P as RELATION_FOCUSES, U as RELATION_FOCUS_DEFAULT, V as RelationFocus, W as ScrollProgressHandle, X as TONES, Y as computeEventBindingKey, Z as computeFormulaKey, _ as computeInputSignalKey, $ as computeScrollTriggerKey, a0 as computed, a1 as createInteractiveSignalsAccessor, a2 as createScrollProgressHandle, a3 as createScrollProgressSignals, a4 as hasInteractivePrimitives, a5 as sequenceBoardMetrics, a6 as sequenceStepId, a7 as signal } from './render-C53-PeJZ.js';
1
+ import { C as CdlDiagram, S as Signal, a as CdlInput, b as CdlLane, c as CdlNode, T as Tone, d as Side, E as EdgeStyle, e as EdgeRole, f as EdgeHead, g as EdgeHeadFill, h as CdlState, i as CdlEventTarget, j as Computed, k as CdlDerivedValue, l as CdlScrollTrigger, L as LaidDiagram, m as CdlDiagramViewProps, n as LaidEdge, o as LaidNode, p as CdlEdge, B as BBox, R as RowMark, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-C0PJ2weJ.js';
2
+ export { q as CdlDiagramView, r as CdlEventBinding, s as CdlEventKind, t as CdlFormula, u as CdlPhase, v as ChartPieForm, w as ChartSlopeForm, x as EDGE_HEADS, y as EDGE_HEAD_DEFAULT, z as EDGE_HEAD_FILLS, A as EDGE_HEAD_FILL_DEFAULT, D as EDGE_REVEALS, F as EDGE_REVEAL_DEFAULT, G as EDGE_STYLES, H as EdgeReveal, I as InteractiveHandlerMap, K as InteractiveSignalsAccessor, M as LaidLane, O as NODE_KINDS, P as RELATION_FOCUSES, U as RELATION_FOCUS_DEFAULT, V as RelationFocus, W as ScrollProgressHandle, X as TONES, Y as computeEventBindingKey, Z as computeFormulaKey, _ as computeInputSignalKey, $ as computeScrollTriggerKey, a0 as computed, a1 as createInteractiveSignalsAccessor, a2 as createScrollProgressHandle, a3 as createScrollProgressSignals, a4 as hasInteractivePrimitives, a5 as sequenceBoardMetrics, a6 as sequenceStepId, a7 as signal } from './render-C0PJ2weJ.js';
3
3
  import { JSX } from 'react';
4
4
 
5
5
  declare function effect(fn: () => void | (() => void)): () => void;
@@ -1046,6 +1046,10 @@ type DiagramBuilder = {
1046
1046
  guard?: string;
1047
1047
  /** ER 関係 cardinality、 text-dsl v0.5 inline option (`cardinality: "1:N"`) を CdlEdge.cardinality へ透過 */
1048
1048
  cardinality?: string;
1049
+ /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1050
+ headLabel?: string;
1051
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1052
+ tailLabel?: string;
1049
1053
  labelOffsetX?: number;
1050
1054
  labelOffsetY?: number;
1051
1055
  routing?: "default" | "back-detour";
@@ -1136,6 +1140,10 @@ type DiagramBuilder = {
1136
1140
  tailHeadFill?: EdgeHeadFill;
1137
1141
  guard?: string;
1138
1142
  cardinality?: string;
1143
+ /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1144
+ headLabel?: string;
1145
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1146
+ tailLabel?: string;
1139
1147
  labelOffsetX?: number;
1140
1148
  labelOffsetY?: number;
1141
1149
  routing?: "default" | "back-detour";
@@ -3406,8 +3414,10 @@ type UmlRelation = {
3406
3414
  type: ClassRelationType;
3407
3415
  /** 関係 label (default は type 名) */
3408
3416
  label?: string;
3409
- /** 多重度 (例 "1..*" / "0..1") */
3417
+ /** 多重度 (例 "1..*" / "0..1")。 行き先 (`to`) の端に添える (#821) */
3410
3418
  cardinality?: string;
3419
+ /** 出どころ (`from`) 側の多重度 (例 "1")。 出どころの端に添える (#825) */
3420
+ tailCardinality?: string;
3411
3421
  tone?: Tone;
3412
3422
  /**
3413
3423
  * 矢印の先の形 (cdl#574)。 書かなければ種類から決まる (`CLASS_RELATION_LOOK`)。
package/dist/index.js CHANGED
@@ -9499,6 +9499,8 @@ function diagram(id, options) {
9499
9499
  tailHeadFill: opts.tailHeadFill,
9500
9500
  guard: opts.guard,
9501
9501
  cardinality: opts.cardinality,
9502
+ headLabel: opts.headLabel,
9503
+ tailLabel: opts.tailLabel,
9502
9504
  labelOffsetX: opts.labelOffsetX,
9503
9505
  labelOffsetY: opts.labelOffsetY,
9504
9506
  routing: opts.routing,
@@ -9625,6 +9627,8 @@ function diagram(id, options) {
9625
9627
  tailHeadFill: d.tailHeadFill,
9626
9628
  guard: d.guard,
9627
9629
  cardinality: d.cardinality,
9630
+ headLabel: d.headLabel,
9631
+ tailLabel: d.tailLabel,
9628
9632
  labelOffsetX: d.labelOffsetX,
9629
9633
  labelOffsetY: d.labelOffsetY,
9630
9634
  routing: d.routing,
@@ -14103,10 +14107,10 @@ function \u66F8\u8A18\u7D20\u306B\u5206\u3051\u308B(text) {
14103
14107
  if (typeof \u533A\u5207\u308A !== "function") return [...text];
14104
14108
  return [...new \u533A\u5207\u308A(void 0, { granularity: "grapheme" }).segment(text)].map((g) => g.segment);
14105
14109
  }
14106
- function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u30552) {
14110
+ function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u30553) {
14107
14111
  const \u5019\u88DC = \u884C.filter((r, i) => i === 0 || r.text.trim() !== "");
14108
14112
  if (\u5019\u88DC.length === 0) return [];
14109
- const \u4F7F\u3048\u308B\u9AD8\u3055 = \u7BB1\u306E\u9AD8\u30552 - \u4E0A\u4E0B\u306E\u4F59\u767D * 2;
14113
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = \u7BB1\u306E\u9AD8\u30553 - \u4E0A\u4E0B\u306E\u4F59\u767D * 2;
14110
14114
  const \u9AD8\u3055 = (rs) => rs.reduce((a, r) => a + r.fontSize * \u884C\u9001\u308A\u306E\u6BD4, 0);
14111
14115
  const \u6B8B\u3059 = [...\u5019\u88DC];
14112
14116
  while (\u6B8B\u3059.length > 1 && \u9AD8\u3055(\u6B8B\u3059) > \u4F7F\u3048\u308B\u9AD8\u3055) \u6B8B\u3059.pop();
@@ -14833,7 +14837,7 @@ function \u30D9\u30B8\u30A8\u306E\u7D2F\u7A4D\u5272\u5408(\u70B9, \u5236\u5FA1\u
14833
14837
  function \u7BB1\u306E\u6587\u5B57({
14834
14838
  \u884C,
14835
14839
  x,
14836
- \u7BB1\u306E\u9AD8\u3055: \u7BB1\u306E\u9AD8\u30552,
14840
+ \u7BB1\u306E\u9AD8\u3055: \u7BB1\u306E\u9AD8\u30553,
14837
14841
  fill,
14838
14842
  \u540D\u524D\u306E\u592A\u3055
14839
14843
  }) {
@@ -14842,7 +14846,7 @@ function \u7BB1\u306E\u6587\u5B57({
14842
14846
  {
14843
14847
  "data-cdl-role": r.\u5F79\u5272 === "subtitle" ? "tree-node-subtitle" : void 0,
14844
14848
  x,
14845
- y: \u7BB1\u306E\u9AD8\u30552 / 2 + r.dy,
14849
+ y: \u7BB1\u306E\u9AD8\u30553 / 2 + r.dy,
14846
14850
  fontSize: r.fontSize,
14847
14851
  fontWeight: r.\u5F79\u5272 === "title" ? \u540D\u524D\u306E\u592A\u3055 : 500,
14848
14852
  textAnchor: "middle",
@@ -22929,6 +22933,79 @@ function \u7B49\u5E45\u306E\u5B57(text, fontSize) {
22929
22933
  });
22930
22934
  return out;
22931
22935
  }
22936
+
22937
+ // src/layout/head-label.ts
22938
+ var \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 = 22;
22939
+ var \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 = 8;
22940
+ var \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 = EDGE_LABEL_TEXT.sub.fontSize;
22941
+ var \u7BB1\u306E\u9AD8\u30552 = Math.round(\u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * 1.2);
22942
+ var BASELINE_RATIO = 0.8;
22943
+ function \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC) {
22944
+ for (const p of \u5019\u88DC) {
22945
+ if (!p) continue;
22946
+ const dx = end.x - p.x;
22947
+ const dy = end.y - p.y;
22948
+ const len = Math.hypot(dx, dy);
22949
+ if (len > 1e-6) return { end, ux: dx / len, uy: dy / len };
22950
+ }
22951
+ return null;
22952
+ }
22953
+ function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
22954
+ const segs = extractPathSegments(d);
22955
+ if (segs.length === 0) return null;
22956
+ if (\u7AEF === "head") {
22957
+ const last = segs[segs.length - 1];
22958
+ const end2 = { x: last.x2, y: last.y2 };
22959
+ const \u5019\u88DC2 = segs.slice().reverse().flatMap((s) => [s.cmd === "Q" ? s.ctrl?.[0] : s.cmd === "C" ? s.ctrl?.[1] : void 0, { x: s.x1, y: s.y1 }]);
22960
+ return \u5411\u304D\u3092\u53D6\u308B(end2, \u5019\u88DC2);
22961
+ }
22962
+ const first = segs[0];
22963
+ const end = { x: first.x1, y: first.y1 };
22964
+ const \u5019\u88DC = segs.flatMap((s) => [...s.ctrl ?? [], { x: s.x2, y: s.y2 }]);
22965
+ return \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC);
22966
+ }
22967
+ function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
22968
+ const text = (\u7AEF === "head" ? edge.headLabel : edge.tailLabel)?.trim();
22969
+ if (!text) return null;
22970
+ const \u5411\u304D = \u7AEF\u3067\u306E\u5411\u304D(edge.d, \u7AEF);
22971
+ if (!\u5411\u304D) return null;
22972
+ const { end, ux, uy } = \u5411\u304D;
22973
+ const bx = end.x - ux * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
22974
+ const by = end.y - uy * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
22975
+ const w = measureTextWidth(text, {
22976
+ fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
22977
+ fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
22978
+ fontFamily: "mono"
22979
+ });
22980
+ const h = \u7BB1\u306E\u9AD8\u30552;
22981
+ const \u672D = hasRenderedLabel(edge) && edge.labelX !== void 0 && edge.labelY !== void 0 ? { x: edge.labelX, y: edge.labelY } : null;
22982
+ let anchor;
22983
+ let box;
22984
+ if (Math.abs(ux) >= Math.abs(uy)) {
22985
+ const \u53F3\u3078\u9032\u3080 = ux > 0;
22986
+ const \u4E0A\u306B\u7F6E\u304F = \u672D !== null && \u672D.y > by;
22987
+ anchor = \u53F3\u3078\u9032\u3080 ? "end" : "start";
22988
+ box = {
22989
+ x: \u53F3\u3078\u9032\u3080 ? bx - w : bx,
22990
+ y: \u4E0A\u306B\u7F6E\u304F ? by - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - h : by + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593,
22991
+ w,
22992
+ h
22993
+ };
22994
+ } else {
22995
+ const \u4E0B\u3078\u9032\u3080 = uy > 0;
22996
+ const \u53F3\u306B\u7F6E\u304F = \u672D !== null && \u672D.x < bx;
22997
+ anchor = \u53F3\u306B\u7F6E\u304F ? "start" : "end";
22998
+ box = {
22999
+ x: \u53F3\u306B\u7F6E\u304F ? bx + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 : bx - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - w,
23000
+ y: \u4E0B\u3078\u9032\u3080 ? by - h : by,
23001
+ w,
23002
+ h
23003
+ };
23004
+ }
23005
+ const x = anchor === "start" ? box.x : box.x + box.w;
23006
+ const y = box.y + (h - \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055) / 2 + \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * BASELINE_RATIO;
23007
+ return { x, y, anchor, box };
23008
+ }
22932
23009
  function defaultEdgeWidth(active) {
22933
23010
  return active ? 2.5 : 1.25;
22934
23011
  }
@@ -23191,6 +23268,35 @@ function CdlEdgeLabelView({
23191
23268
  }
23192
23269
  );
23193
23270
  }
23271
+ function CdlEdgeEndLabelView({
23272
+ edge,
23273
+ active,
23274
+ \u7AEF
23275
+ }) {
23276
+ const \u7F6E\u304D\u5834\u6240 = \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF);
23277
+ if (!\u7F6E\u304D\u5834\u6240) return null;
23278
+ const color = edgeColor(edge);
23279
+ return /* @__PURE__ */ jsx(
23280
+ "text",
23281
+ {
23282
+ "data-cdl-role": "edge-end-label",
23283
+ "data-cdl-edge-end-label-for": edge.id,
23284
+ "data-cdl-edge-end": \u7AEF,
23285
+ x: \u7F6E\u304D\u5834\u6240.x,
23286
+ y: \u7F6E\u304D\u5834\u6240.y,
23287
+ fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
23288
+ fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
23289
+ textAnchor: \u7F6E\u304D\u5834\u6240.anchor,
23290
+ fill: active ? color : "var(--cdl-text-dim, #5a6270)",
23291
+ stroke: "var(--cdl-label-bg, #ffffff)",
23292
+ strokeWidth: 4,
23293
+ strokeLinejoin: "round",
23294
+ paintOrder: "stroke",
23295
+ style: { fontFamily: fontFamilyAttr("sub") },
23296
+ children: \u7B49\u5E45\u306E\u5B57(\u7AEF === "head" ? edge.headLabel : edge.tailLabel, \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055)
23297
+ }
23298
+ );
23299
+ }
23194
23300
 
23195
23301
  // src/kinds/node-tone.ts
23196
23302
  function nodeAccent(node, fallback) {
@@ -31475,6 +31581,17 @@ function CdlStage({
31475
31581
  },
31476
31582
  `label-${edge.id}`
31477
31583
  )),
31584
+ laid.edges.filter((edge) => (edge.headLabel || edge.tailLabel) && \u77E2\u5370\u306E\u51FA\u756A.\u51FA\u308B\u304B(edge.id)).flatMap(
31585
+ (edge) => ["head", "tail"].map((\u7AEF) => /* @__PURE__ */ jsx(
31586
+ CdlEdgeEndLabelView,
31587
+ {
31588
+ edge,
31589
+ active: activeSet.has(edge.id),
31590
+ \u7AEF
31591
+ },
31592
+ `${\u7AEF}-label-${edge.id}`
31593
+ ))
31594
+ ),
31478
31595
  debug && /* @__PURE__ */ jsxs("g", { pointerEvents: "none", children: [
31479
31596
  laid.bboxes.map((bbox, idx) => {
31480
31597
  const color = bbox.kind === "node" ? "#3b82f6" : bbox.kind === "lane-label" ? "#a855f7" : bbox.kind === "edge-label" ? "#10b981" : "#f59e0b";
@@ -32519,7 +32636,10 @@ function classDiagram(preset) {
32519
32636
  b.edge(r.from, r.to, {
32520
32637
  id: edgeId,
32521
32638
  label: r.label ?? r.type,
32522
- ...r.cardinality ? { sub: r.cardinality } : {},
32639
+ // 多重度は行き先の端に添える (#821)。 札の下の行に入れると語と続けて読まれ
32640
+ // (英字の頃は「HAS 1..*」 が「HAS1」)、 どちらの端の数かも読めない
32641
+ ...r.cardinality ? { headLabel: r.cardinality } : {},
32642
+ ...r.tailCardinality ? { tailLabel: r.tailCardinality } : {},
32523
32643
  tone: r.tone ?? \u56F3\u306E\u65E2\u5B9A ?? CLASS_RELATION_TONE[r.type],
32524
32644
  // 関係の種類から線と端の形を決める (cdl#574 / #578)。 書いた値が勝つ
32525
32645
  style: r.style ?? \u898B\u305F\u76EE.style,