@cardenelabs/cdl 0.69.0 → 0.71.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/cdl",
3
- "version": "0.69.0",
3
+ "version": "0.71.0",
4
4
  "description": "CDL (Chainome Diagram Language). Mermaid-like declarative DSL that compiles to animated SVG diagrams. Built for blockchain / Solidity flows, generic enough for sequence / flow / state / ER / topology diagrams.",
5
5
  "license": "MIT",
6
6
  "author": "cardene777",
package/src/index.ts CHANGED
@@ -277,6 +277,7 @@ export type {
277
277
  FlowchartNode,
278
278
  FlowchartEdge,
279
279
  FlowchartNodeShape,
280
+ FlowchartDirection,
280
281
  NetworkPreset,
281
282
  NetworkBuilder,
282
283
  NetworkDevice,
@@ -137,11 +137,23 @@ function renderRect(
137
137
  clipPath={`url(#dyn-rect-clip-${node.id})`}
138
138
  style={{ transition: "all 200ms ease-out" }}
139
139
  />
140
- {/* value label */}
140
+ {/*
141
+ 読み取り値。 **箱の右端に揃える** (#870)。
142
+
143
+ 中央に置くと、同じ帯の上下を繋ぐ矢印と必ず重なる。 矢印は受け手の上端の中央へ
144
+ 真下から入り、読み取り値は上端の中央の真上に出るので、置き場所が同じになる。
145
+ 利用側の 4 枚が 4 枚とも、矢印の先が数字の区切りに刺さって `10 ⯆ 10` に見えていた。
146
+
147
+ 右端へ寄せると、中央の縦の通り道が空く。 矢印の側ではなく数字の側を動かすのは、
148
+ 矢印の取り付き点が 2 本並んだ時の振り分けを既に持っており、そこへ別の理由で
149
+ ずらす条件を足すと両方が効いた時の位置が読めなくなるため。
150
+
151
+ 揃える先を右にしたのは、箱の右上が空いている図が多いから (左上には枠の題が来る)。
152
+ */}
141
153
  <text
142
- x={x + w / 2}
154
+ x={x + w}
143
155
  y={y - 6}
144
- textAnchor="middle"
156
+ textAnchor="end"
145
157
  fontSize={11}
146
158
  fontFamily="monospace"
147
159
  fill="var(--cdl-text-dim, #5a6270)"
package/src/presets.ts CHANGED
@@ -2289,6 +2289,18 @@ export type FlowchartEdge = {
2289
2289
  tone?: Tone;
2290
2290
  };
2291
2291
 
2292
+ /**
2293
+ * 分かれ道の図を並べる向き (#880)。
2294
+ *
2295
+ * - `"horizontal"` (既定) ... 縦列を横に並べ、箱をその中に上から積む。 役割は縦列の見出しに出る
2296
+ * - `"vertical"` ... 縦列 1 本に全部の箱を書いた順で積む。 役割は箱の上の小さな字に移す
2297
+ *
2298
+ * **縦列を横の帯にして縦に積む形は持たない**。 配置は格子で、縦列が横の位置を、段が縦の
2299
+ * 位置を決める (`layout/nodes.ts`)。 帯にするには軸の入れ替えが要り、入口の option では
2300
+ * 足りない。
2301
+ */
2302
+ export type FlowchartDirection = "horizontal" | "vertical";
2303
+
2292
2304
  export type FlowchartPreset = {
2293
2305
  id: string;
2294
2306
  topic: string;
@@ -2296,6 +2308,8 @@ export type FlowchartPreset = {
2296
2308
  lanes: string[];
2297
2309
  defaultTone?: Tone;
2298
2310
  laneWidth?: number;
2311
+ /** 並べる向き (既定 = `"horizontal"`、 今までの並び) */
2312
+ direction?: FlowchartDirection;
2299
2313
  };
2300
2314
 
2301
2315
  export type FlowchartBuilder = {
@@ -2339,32 +2353,57 @@ const SHAPE_EYEBROW: Record<FlowchartNodeShape, string> = {
2339
2353
  * .edge({ from: "review", to: "revise", label: "false" })
2340
2354
  * .build();
2341
2355
  */
2356
+ /** 縦に積む時に使う 1 本だけの縦列の id (#880) */
2357
+ const VERTICAL_LANE_ID = "flowchart-main";
2358
+
2342
2359
  export function flowchart(preset: FlowchartPreset): FlowchartBuilder {
2343
2360
  const laneW = preset.laneWidth ?? 380;
2344
2361
  const tone: Tone = preset.defaultTone ?? "accent";
2362
+ const 縦に積む = (preset.direction ?? "horizontal") === "vertical";
2345
2363
  const b = diagram(preset.id, { topic: preset.topic, type: "flowchart" });
2346
2364
 
2347
2365
  const laneToId = new Map<string, string>();
2348
2366
  const laneStackCount = new Map<string, number>();
2349
- for (const label of preset.lanes) {
2350
- const id = slugify(label) || `lane-${laneToId.size}`;
2351
- laneToId.set(label, id);
2352
- laneStackCount.set(id, 0);
2353
- b.lane(id, { width: laneW, label });
2367
+ if (縦に積む) {
2368
+ /*
2369
+ * 縦列を 1 本だけ置く (#880)。
2370
+ *
2371
+ * 見出しは付けない = 役割が 1 つに畳まれるので、どれか 1 つの名前を見出しにすると
2372
+ * 他の役割の箱にもその名前が掛かって読める。 役割は箱ごとの小さな字が持つ。
2373
+ */
2374
+ b.lane(VERTICAL_LANE_ID, { width: laneW });
2375
+ laneStackCount.set(VERTICAL_LANE_ID, 0);
2376
+ } else {
2377
+ for (const label of preset.lanes) {
2378
+ const id = slugify(label) || `lane-${laneToId.size}`;
2379
+ laneToId.set(label, id);
2380
+ laneStackCount.set(id, 0);
2381
+ b.lane(id, { width: laneW, label });
2382
+ }
2354
2383
  }
2355
2384
  const phaseActivate: string[] = [];
2356
2385
  let edgeIdx = 0;
2357
2386
 
2387
+ /*
2388
+ * 箱の上に出す字。
2389
+ *
2390
+ * 縦に積む図で役割を 2 つ以上書いた時だけ、形の名前の前に役割を足す。
2391
+ * 1 つしか書いていない図は足さない = 全部の箱に同じ字が並ぶだけで、読む材料が増えない。
2392
+ */
2393
+ const 役割を足す = 縦に積む && preset.lanes.length >= 2;
2394
+ const 箱の上の字 = (n: FlowchartNode): string =>
2395
+ 役割を足す ? `${n.lane} · ${SHAPE_EYEBROW[n.shape]}` : SHAPE_EYEBROW[n.shape];
2396
+
2358
2397
  const api: FlowchartBuilder = {
2359
2398
  node(n) {
2360
- const laneId = laneToId.get(n.lane) ?? n.lane;
2399
+ const laneId = 縦に積む ? VERTICAL_LANE_ID : (laneToId.get(n.lane) ?? n.lane);
2361
2400
  const stack = laneStackCount.get(laneId) ?? 0;
2362
2401
  b.node(n.id, {
2363
2402
  lane: laneId,
2364
2403
  stack,
2365
2404
  kind: SHAPE_KIND[n.shape],
2366
2405
  title: n.title,
2367
- eyebrow: SHAPE_EYEBROW[n.shape],
2406
+ eyebrow: 箱の上の字(n),
2368
2407
  });
2369
2408
  laneStackCount.set(laneId, stack + 1);
2370
2409
  phaseActivate.push(n.id);