@cardenelabs/cdl 0.51.0 → 0.53.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-BoBEyCu-.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-BoBEyCu-.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;
@@ -1048,6 +1048,8 @@ type DiagramBuilder = {
1048
1048
  cardinality?: string;
1049
1049
  /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1050
1050
  headLabel?: string;
1051
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1052
+ tailLabel?: string;
1051
1053
  labelOffsetX?: number;
1052
1054
  labelOffsetY?: number;
1053
1055
  routing?: "default" | "back-detour";
@@ -1140,6 +1142,8 @@ type DiagramBuilder = {
1140
1142
  cardinality?: string;
1141
1143
  /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1142
1144
  headLabel?: string;
1145
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1146
+ tailLabel?: string;
1143
1147
  labelOffsetX?: number;
1144
1148
  labelOffsetY?: number;
1145
1149
  routing?: "default" | "back-detour";
@@ -3412,6 +3416,8 @@ type UmlRelation = {
3412
3416
  label?: string;
3413
3417
  /** 多重度 (例 "1..*" / "0..1")。 行き先 (`to`) の端に添える (#821) */
3414
3418
  cardinality?: string;
3419
+ /** 出どころ (`from`) 側の多重度 (例 "1")。 出どころの端に添える (#825) */
3420
+ tailCardinality?: string;
3415
3421
  tone?: Tone;
3416
3422
  /**
3417
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-BoBEyCu-.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-BoBEyCu-.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;
@@ -1048,6 +1048,8 @@ type DiagramBuilder = {
1048
1048
  cardinality?: string;
1049
1049
  /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1050
1050
  headLabel?: string;
1051
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1052
+ tailLabel?: string;
1051
1053
  labelOffsetX?: number;
1052
1054
  labelOffsetY?: number;
1053
1055
  routing?: "default" | "back-detour";
@@ -1140,6 +1142,8 @@ type DiagramBuilder = {
1140
1142
  cardinality?: string;
1141
1143
  /** 行き先の端に添える字 (#821)。 クラス図の多重度に使う */
1142
1144
  headLabel?: string;
1145
+ /** 出どころの端に添える字 (#825)。 クラス図の出どころ側の多重度に使う */
1146
+ tailLabel?: string;
1143
1147
  labelOffsetX?: number;
1144
1148
  labelOffsetY?: number;
1145
1149
  routing?: "default" | "back-detour";
@@ -3412,6 +3416,8 @@ type UmlRelation = {
3412
3416
  label?: string;
3413
3417
  /** 多重度 (例 "1..*" / "0..1")。 行き先 (`to`) の端に添える (#821) */
3414
3418
  cardinality?: string;
3419
+ /** 出どころ (`from`) 側の多重度 (例 "1")。 出どころの端に添える (#825) */
3420
+ tailCardinality?: string;
3415
3421
  tone?: Tone;
3416
3422
  /**
3417
3423
  * 矢印の先の形 (cdl#574)。 書かなければ種類から決まる (`CLASS_RELATION_LOOK`)。
package/dist/index.js CHANGED
@@ -9500,6 +9500,7 @@ function diagram(id, options) {
9500
9500
  guard: opts.guard,
9501
9501
  cardinality: opts.cardinality,
9502
9502
  headLabel: opts.headLabel,
9503
+ tailLabel: opts.tailLabel,
9503
9504
  labelOffsetX: opts.labelOffsetX,
9504
9505
  labelOffsetY: opts.labelOffsetY,
9505
9506
  routing: opts.routing,
@@ -9627,6 +9628,7 @@ function diagram(id, options) {
9627
9628
  guard: d.guard,
9628
9629
  cardinality: d.cardinality,
9629
9630
  headLabel: d.headLabel,
9631
+ tailLabel: d.tailLabel,
9630
9632
  labelOffsetX: d.labelOffsetX,
9631
9633
  labelOffsetY: d.labelOffsetY,
9632
9634
  routing: d.routing,
@@ -20528,6 +20530,87 @@ function requiredRowsWidth(rows, kind) {
20528
20530
  return Math.ceil(kind === "storage" ? storage : generic);
20529
20531
  }
20530
20532
 
20533
+ // src/layout/head-label.ts
20534
+ var \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 = 22;
20535
+ var \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 = 8;
20536
+ var \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 = EDGE_LABEL_TEXT.sub.fontSize;
20537
+ var \u7BB1\u306E\u9AD8\u3055 = Math.round(\u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * 1.2);
20538
+ var BASELINE_RATIO = 0.8;
20539
+ var \u4E21\u7AEF\u306E\u5B57\u306E\u9593 = \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 * 2;
20540
+ function \u7AEF\u306E\u5B57\u306B\u8981\u308B\u7DDA\u306E\u9577\u3055(edge) {
20541
+ const \u4E00\u3064\u5206 = \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 + \u7BB1\u306E\u9AD8\u3055;
20542
+ const \u6570 = [edge.headLabel, edge.tailLabel].filter((t) => t?.trim()).length;
20543
+ if (\u6570 === 0) return 0;
20544
+ if (\u6570 === 1) return \u4E00\u3064\u5206;
20545
+ return \u4E00\u3064\u5206 * 2 + \u4E21\u7AEF\u306E\u5B57\u306E\u9593;
20546
+ }
20547
+ function \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC) {
20548
+ for (const p of \u5019\u88DC) {
20549
+ if (!p) continue;
20550
+ const dx = end.x - p.x;
20551
+ const dy = end.y - p.y;
20552
+ const len = Math.hypot(dx, dy);
20553
+ if (len > 1e-6) return { end, ux: dx / len, uy: dy / len };
20554
+ }
20555
+ return null;
20556
+ }
20557
+ function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
20558
+ const segs = extractPathSegments(d);
20559
+ if (segs.length === 0) return null;
20560
+ if (\u7AEF === "head") {
20561
+ const last = segs[segs.length - 1];
20562
+ const end2 = { x: last.x2, y: last.y2 };
20563
+ 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 }]);
20564
+ return \u5411\u304D\u3092\u53D6\u308B(end2, \u5019\u88DC2);
20565
+ }
20566
+ const first = segs[0];
20567
+ const end = { x: first.x1, y: first.y1 };
20568
+ const \u5019\u88DC = segs.flatMap((s) => [...s.ctrl ?? [], { x: s.x2, y: s.y2 }]);
20569
+ return \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC);
20570
+ }
20571
+ function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
20572
+ const text = (\u7AEF === "head" ? edge.headLabel : edge.tailLabel)?.trim();
20573
+ if (!text) return null;
20574
+ const \u5411\u304D = \u7AEF\u3067\u306E\u5411\u304D(edge.d, \u7AEF);
20575
+ if (!\u5411\u304D) return null;
20576
+ const { end, ux, uy } = \u5411\u304D;
20577
+ const bx = end.x - ux * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
20578
+ const by = end.y - uy * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
20579
+ const w = measureTextWidth(text, {
20580
+ fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
20581
+ fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
20582
+ fontFamily: "mono"
20583
+ });
20584
+ const h = \u7BB1\u306E\u9AD8\u3055;
20585
+ const \u672D = hasRenderedLabel(edge) && edge.labelX !== void 0 && edge.labelY !== void 0 ? { x: edge.labelX, y: edge.labelY } : null;
20586
+ let anchor;
20587
+ let box;
20588
+ if (Math.abs(ux) >= Math.abs(uy)) {
20589
+ const \u53F3\u3078\u9032\u3080 = ux > 0;
20590
+ const \u4E0A\u306B\u7F6E\u304F = \u672D !== null && \u672D.y > by;
20591
+ anchor = \u53F3\u3078\u9032\u3080 ? "end" : "start";
20592
+ box = {
20593
+ x: \u53F3\u3078\u9032\u3080 ? bx - w : bx,
20594
+ y: \u4E0A\u306B\u7F6E\u304F ? by - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - h : by + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593,
20595
+ w,
20596
+ h
20597
+ };
20598
+ } else {
20599
+ const \u4E0B\u3078\u9032\u3080 = uy > 0;
20600
+ const \u53F3\u306B\u7F6E\u304F = \u672D !== null && \u672D.x < bx;
20601
+ anchor = \u53F3\u306B\u7F6E\u304F ? "start" : "end";
20602
+ box = {
20603
+ x: \u53F3\u306B\u7F6E\u304F ? bx + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 : bx - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - w,
20604
+ y: \u4E0B\u3078\u9032\u3080 ? by - h : by,
20605
+ w,
20606
+ h
20607
+ };
20608
+ }
20609
+ const x = anchor === "start" ? box.x : box.x + box.w;
20610
+ const y = box.y + (h - \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055) / 2 + \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * BASELINE_RATIO;
20611
+ return { x, y, anchor, box };
20612
+ }
20613
+
20531
20614
  // src/layout/nodes.ts
20532
20615
  function autoStorageHeight(n, defaultH) {
20533
20616
  if (n.kind !== "storage") return n.h ?? defaultH;
@@ -20549,7 +20632,7 @@ function autoRowsWidth(n, defaultW) {
20549
20632
  const required = requiredRowsWidth(n.rows, n.kind);
20550
20633
  return Math.max(defaultW, required);
20551
20634
  }
20552
- function \u7BB1\u306E\u9AD8\u3055(n, \u65E2\u5B9Ah) {
20635
+ function \u7BB1\u306E\u9AD8\u30552(n, \u65E2\u5B9Ah) {
20553
20636
  if (n.h != null) return n.h;
20554
20637
  if (n.kind === "storage") return autoStorageHeight(n, \u65E2\u5B9Ah);
20555
20638
  return \u4E2D\u8EAB\u304B\u3089\u51FA\u3059\u9AD8\u3055(n.kind, \u65E2\u5B9Ah, {
@@ -20563,8 +20646,8 @@ function requiredStackGapForEdgeLabels(diag, allStacks) {
20563
20646
  const byId = new Map(diag.nodes.map((n) => [n.id, n]));
20564
20647
  const rankOf = new Map(allStacks.map((stack, i) => [stack, i]));
20565
20648
  const pillHsByGap = /* @__PURE__ */ new Map();
20649
+ let \u7AEF\u306E\u5B57\u306E\u8981\u6C42 = 0;
20566
20650
  for (const e of diag.edges) {
20567
- if (!hasRenderedLabel(e)) continue;
20568
20651
  const from = byId.get(e.from);
20569
20652
  const to = byId.get(e.to);
20570
20653
  if (!from || !to) continue;
@@ -20573,10 +20656,12 @@ function requiredStackGapForEdgeLabels(diag, allStacks) {
20573
20656
  const toRank = rankOf.get(to.stack);
20574
20657
  if (fromRank === void 0 || toRank === void 0) continue;
20575
20658
  if (Math.abs(fromRank - toRank) !== 1) continue;
20659
+ \u7AEF\u306E\u5B57\u306E\u8981\u6C42 = Math.max(\u7AEF\u306E\u5B57\u306E\u8981\u6C42, \u7AEF\u306E\u5B57\u306B\u8981\u308B\u7DDA\u306E\u9577\u3055(e));
20660
+ if (!hasRenderedLabel(e)) continue;
20576
20661
  const key = `${from.lane}::${Math.min(fromRank, toRank)}`;
20577
20662
  pillHsByGap.set(key, [...pillHsByGap.get(key) ?? [], labelPillH(e.sub)]);
20578
20663
  }
20579
- let required = 0;
20664
+ let required = \u7AEF\u306E\u5B57\u306E\u8981\u6C42;
20580
20665
  for (const pillHs of pillHsByGap.values()) {
20581
20666
  required = Math.max(required, requiredVerticalLabelGap(pillHs));
20582
20667
  }
@@ -20588,7 +20673,7 @@ function layoutNodes(diag, lanes) {
20588
20673
  const rowH = /* @__PURE__ */ new Map();
20589
20674
  for (const stack of allStacks) {
20590
20675
  const nodesAtStack = diag.nodes.filter((n) => n.stack === stack);
20591
- const h = Math.max(...nodesAtStack.map((n) => \u7BB1\u306E\u9AD8\u3055(n, NODE_SIZE[n.kind].h)));
20676
+ const h = Math.max(...nodesAtStack.map((n) => \u7BB1\u306E\u9AD8\u30552(n, NODE_SIZE[n.kind].h)));
20592
20677
  rowH.set(stack, h);
20593
20678
  }
20594
20679
  const rowCy = /* @__PURE__ */ new Map();
@@ -20642,7 +20727,7 @@ function layoutNodes(diag, lanes) {
20642
20727
  const \u6BB5\u306E\u82AF = rowCy.get(n.stack);
20643
20728
  const \u6BB5\u306E\u9AD8\u3055 = rowH.get(n.stack);
20644
20729
  const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0;
20645
- const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? \u7BB1\u306E\u9AD8\u3055(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
20730
+ const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? \u7BB1\u306E\u9AD8\u30552(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
20646
20731
  const cy = \u6BB5\u306E\u82AF;
20647
20732
  const w = autoRowsWidth(n, size.w);
20648
20733
  out.push({
@@ -22931,73 +23016,6 @@ function \u7B49\u5E45\u306E\u5B57(text, fontSize) {
22931
23016
  });
22932
23017
  return out;
22933
23018
  }
22934
-
22935
- // src/layout/head-label.ts
22936
- var \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 = 22;
22937
- var \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 = 8;
22938
- var \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 = EDGE_LABEL_TEXT.sub.fontSize;
22939
- var \u7BB1\u306E\u9AD8\u30552 = Math.round(\u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * 1.2);
22940
- var BASELINE_RATIO = 0.8;
22941
- function \u6700\u5F8C\u306E\u5411\u304D(d) {
22942
- const segs = extractPathSegments(d);
22943
- const last = segs[segs.length - 1];
22944
- if (!last) return null;
22945
- const end = { x: last.x2, y: last.y2 };
22946
- for (let i = segs.length - 1; i >= 0; i--) {
22947
- const s = segs[i];
22948
- const \u5236\u5FA1\u70B9 = s.cmd === "Q" ? s.ctrl?.[0] : s.cmd === "C" ? s.ctrl?.[1] : void 0;
22949
- for (const p of [\u5236\u5FA1\u70B9, { x: s.x1, y: s.y1 }]) {
22950
- if (!p) continue;
22951
- const dx = end.x - p.x;
22952
- const dy = end.y - p.y;
22953
- const len = Math.hypot(dx, dy);
22954
- if (len > 1e-6) return { end, ux: dx / len, uy: dy / len };
22955
- }
22956
- }
22957
- return null;
22958
- }
22959
- function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge) {
22960
- const text = edge.headLabel?.trim();
22961
- if (!text) return null;
22962
- const \u5411\u304D = \u6700\u5F8C\u306E\u5411\u304D(edge.d);
22963
- if (!\u5411\u304D) return null;
22964
- const { end, ux, uy } = \u5411\u304D;
22965
- const bx = end.x - ux * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
22966
- const by = end.y - uy * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
22967
- const w = measureTextWidth(text, {
22968
- fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
22969
- fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
22970
- fontFamily: "mono"
22971
- });
22972
- const h = \u7BB1\u306E\u9AD8\u30552;
22973
- const \u672D = hasRenderedLabel(edge) && edge.labelX !== void 0 && edge.labelY !== void 0 ? { x: edge.labelX, y: edge.labelY } : null;
22974
- let anchor;
22975
- let box;
22976
- if (Math.abs(ux) >= Math.abs(uy)) {
22977
- const \u53F3\u3078\u9032\u3080 = ux > 0;
22978
- const \u4E0A\u306B\u7F6E\u304F = \u672D !== null && \u672D.y > by;
22979
- anchor = \u53F3\u3078\u9032\u3080 ? "end" : "start";
22980
- box = {
22981
- x: \u53F3\u3078\u9032\u3080 ? bx - w : bx,
22982
- y: \u4E0A\u306B\u7F6E\u304F ? by - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - h : by + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593,
22983
- w,
22984
- h
22985
- };
22986
- } else {
22987
- const \u4E0B\u3078\u9032\u3080 = uy > 0;
22988
- const \u53F3\u306B\u7F6E\u304F = \u672D !== null && \u672D.x < bx;
22989
- anchor = \u53F3\u306B\u7F6E\u304F ? "start" : "end";
22990
- box = {
22991
- x: \u53F3\u306B\u7F6E\u304F ? bx + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 : bx - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - w,
22992
- y: \u4E0B\u3078\u9032\u3080 ? by - h : by,
22993
- w,
22994
- h
22995
- };
22996
- }
22997
- const x = anchor === "start" ? box.x : box.x + box.w;
22998
- const y = box.y + (h - \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055) / 2 + \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * BASELINE_RATIO;
22999
- return { x, y, anchor, box };
23000
- }
23001
23019
  function defaultEdgeWidth(active) {
23002
23020
  return active ? 2.5 : 1.25;
23003
23021
  }
@@ -23260,11 +23278,12 @@ function CdlEdgeLabelView({
23260
23278
  }
23261
23279
  );
23262
23280
  }
23263
- function CdlEdgeHeadLabelView({
23281
+ function CdlEdgeEndLabelView({
23264
23282
  edge,
23265
- active
23283
+ active,
23284
+ \u7AEF
23266
23285
  }) {
23267
- const \u7F6E\u304D\u5834\u6240 = \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge);
23286
+ const \u7F6E\u304D\u5834\u6240 = \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF);
23268
23287
  if (!\u7F6E\u304D\u5834\u6240) return null;
23269
23288
  const color = edgeColor(edge);
23270
23289
  return /* @__PURE__ */ jsx(
@@ -23272,6 +23291,7 @@ function CdlEdgeHeadLabelView({
23272
23291
  {
23273
23292
  "data-cdl-role": "edge-end-label",
23274
23293
  "data-cdl-edge-end-label-for": edge.id,
23294
+ "data-cdl-edge-end": \u7AEF,
23275
23295
  x: \u7F6E\u304D\u5834\u6240.x,
23276
23296
  y: \u7F6E\u304D\u5834\u6240.y,
23277
23297
  fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
@@ -23283,7 +23303,7 @@ function CdlEdgeHeadLabelView({
23283
23303
  strokeLinejoin: "round",
23284
23304
  paintOrder: "stroke",
23285
23305
  style: { fontFamily: fontFamilyAttr("sub") },
23286
- children: \u7B49\u5E45\u306E\u5B57(edge.headLabel, \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055)
23306
+ children: \u7B49\u5E45\u306E\u5B57(\u7AEF === "head" ? edge.headLabel : edge.tailLabel, \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055)
23287
23307
  }
23288
23308
  );
23289
23309
  }
@@ -31571,14 +31591,17 @@ function CdlStage({
31571
31591
  },
31572
31592
  `label-${edge.id}`
31573
31593
  )),
31574
- laid.edges.filter((edge) => edge.headLabel && \u77E2\u5370\u306E\u51FA\u756A.\u51FA\u308B\u304B(edge.id)).map((edge) => /* @__PURE__ */ jsx(
31575
- CdlEdgeHeadLabelView,
31576
- {
31577
- edge,
31578
- active: activeSet.has(edge.id)
31579
- },
31580
- `head-label-${edge.id}`
31581
- )),
31594
+ laid.edges.filter((edge) => (edge.headLabel || edge.tailLabel) && \u77E2\u5370\u306E\u51FA\u756A.\u51FA\u308B\u304B(edge.id)).flatMap(
31595
+ (edge) => ["head", "tail"].map((\u7AEF) => /* @__PURE__ */ jsx(
31596
+ CdlEdgeEndLabelView,
31597
+ {
31598
+ edge,
31599
+ active: activeSet.has(edge.id),
31600
+ \u7AEF
31601
+ },
31602
+ `${\u7AEF}-label-${edge.id}`
31603
+ ))
31604
+ ),
31582
31605
  debug && /* @__PURE__ */ jsxs("g", { pointerEvents: "none", children: [
31583
31606
  laid.bboxes.map((bbox, idx) => {
31584
31607
  const color = bbox.kind === "node" ? "#3b82f6" : bbox.kind === "lane-label" ? "#a855f7" : bbox.kind === "edge-label" ? "#10b981" : "#f59e0b";
@@ -32626,6 +32649,7 @@ function classDiagram(preset) {
32626
32649
  // 多重度は行き先の端に添える (#821)。 札の下の行に入れると語と続けて読まれ
32627
32650
  // (英字の頃は「HAS 1..*」 が「HAS1」)、 どちらの端の数かも読めない
32628
32651
  ...r.cardinality ? { headLabel: r.cardinality } : {},
32652
+ ...r.tailCardinality ? { tailLabel: r.tailCardinality } : {},
32629
32653
  tone: r.tone ?? \u56F3\u306E\u65E2\u5B9A ?? CLASS_RELATION_TONE[r.type],
32630
32654
  // 関係の種類から線と端の形を決める (cdl#574 / #578)。 書いた値が勝つ
32631
32655
  style: r.style ?? \u898B\u305F\u76EE.style,