@cardenelabs/cdl 0.7.0 → 0.9.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 (42) hide show
  1. package/CHANGELOG.md +401 -0
  2. package/SPEC.md +32 -17
  3. package/dist/index.cjs +700 -306
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +68 -14
  6. package/dist/index.d.ts +68 -14
  7. package/dist/index.js +700 -306
  8. package/dist/index.js.map +1 -1
  9. package/dist/react.cjs +572 -196
  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 +572 -196
  14. package/dist/react.js.map +1 -1
  15. package/dist/{render-DquCvgOB.d.cts → render-hmFRAabt.d.cts} +33 -2
  16. package/dist/{render-DquCvgOB.d.ts → render-hmFRAabt.d.ts} +33 -2
  17. package/package.json +6 -3
  18. package/src/kinds/box-lines.ts +120 -0
  19. package/src/kinds/gantt.tsx +152 -24
  20. package/src/kinds/mind-map.tsx +50 -12
  21. package/src/kinds/quadrant.tsx +28 -2
  22. package/src/kinds/shape-blockchain.tsx +65 -12
  23. package/src/kinds/shape-region.tsx +152 -34
  24. package/src/kinds/tree.tsx +92 -20
  25. package/src/layout/collisions.ts +10 -2
  26. package/src/layout/footer-shape.ts +86 -24
  27. package/src/layout/lifeline.ts +80 -0
  28. package/src/layout/spec.ts +21 -2
  29. package/src/layout/text-width.ts +92 -4
  30. package/src/layout/viewbox.ts +0 -8
  31. package/src/layout.ts +8 -1
  32. package/src/presets.ts +120 -22
  33. package/src/render/header.tsx +3 -1
  34. package/src/render/payload-binding.ts +31 -8
  35. package/src/render/stage.tsx +17 -34
  36. package/src/render/template-fields.ts +212 -0
  37. package/src/render/utils.ts +32 -2
  38. package/src/render.tsx +2 -9
  39. package/src/types.ts +33 -2
  40. package/src/validate.ts +27 -9
  41. package/src/visual-validate.ts +34 -1
  42. package/src/layout/label-shift.ts +0 -28
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 CdlState, f as CdlEventTarget, g as Computed, h as CdlDerivedValue, i as CdlScrollTrigger, L as LaidDiagram, j as CdlDiagramViewProps, k as LaidEdge, l as LaidNode, m as CdlEdge, B as BBox, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-DquCvgOB.cjs';
2
- export { n as CdlDiagramView, o as CdlEventBinding, p as CdlEventKind, q as CdlFormula, r as CdlPhase, I as InteractiveHandlerMap, s as InteractiveSignalsAccessor, t as LaidLane, u as NODE_KINDS, v as ScrollProgressHandle, w as TONES, x as computeEventBindingKey, y as computeFormulaKey, z as computeInputSignalKey, A as computeScrollTriggerKey, D as computed, F as createInteractiveSignalsAccessor, G as createScrollProgressHandle, H as createScrollProgressSignals, K as hasInteractivePrimitives, M as signal } from './render-DquCvgOB.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 CdlState, f as CdlEventTarget, g as Computed, h as CdlDerivedValue, i as CdlScrollTrigger, L as LaidDiagram, j as CdlDiagramViewProps, k as LaidEdge, l as LaidNode, m as CdlEdge, B as BBox, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-hmFRAabt.cjs';
2
+ export { n as CdlDiagramView, o as CdlEventBinding, p as CdlEventKind, q as CdlFormula, r as CdlPhase, I as InteractiveHandlerMap, s as InteractiveSignalsAccessor, t as LaidLane, u as NODE_KINDS, v as ScrollProgressHandle, w as TONES, x as computeEventBindingKey, y as computeFormulaKey, z as computeInputSignalKey, A as computeScrollTriggerKey, D as computed, F as createInteractiveSignalsAccessor, G as createScrollProgressHandle, H as createScrollProgressSignals, K as hasInteractivePrimitives, M as signal } from './render-hmFRAabt.cjs';
3
3
  import { JSX } from 'react';
4
4
 
5
5
  declare function effect(fn: () => void | (() => void)): () => void;
@@ -1535,7 +1535,7 @@ interface Violation {
1535
1535
  detail: string;
1536
1536
  severity: "error" | "warn";
1537
1537
  }
1538
- type VisualAxis = "node-visibility" | "edge-label-overlap" | "edge-label-proximity" | "text-readability" | "row-format" | "alignment" | "clearance" | "arrow-endpoint-anchoring" | "label-char-range" | "node-overlap" | "edge-crossing" | "edge-node-cross" | "edge-segment-orthogonality" | "label-inside-viewbox" | "lane-cx-consistency" | "row-vertical-spacing" | "group-boundary-clearance" | "node-vertical-clearance" | "lane-lane-gap" | "arrow-marker-clearance" | "grid-alignment" | "phase-layout-stability" | "responsive-viewport" | "accessibility-basics" | "animation-frame-integrity" | "i18n-cjk-detection" | "contrast-basics" | "print-media-compat" | "color-blind-safety" | "marker-gradient-def-integrity" | "subpixel-precision" | "dom-complexity-budget" | "reduced-motion-compat" | "touch-target-size" | "row-content-typing" | "terminal-safe-text" | "gpu-layer-efficiency" | "memory-budget" | "svg-injection-safety" | "seo-metadata-quality" | "bidi-hyphenation" | "structured-data-extraction" | "diagram-version-semver" | "migration-path-consistency" | "axis-coverage-meta" | "axis-documentation-completeness" | "fixture-drift-detection" | "locale-parity" | "validate-performance-budget" | "node-inside-viewbox" | "node-inside-lane" | "edge-inside-viewbox" | "lane-label-inside-viewbox" | "lane-label-overlap" | "row-alignment" | "column-alignment" | "edge-stubout-min" | "fan-origin-single-point" | "detour-slot-distinct" | "arrow-endpoint-center" | "lane-border-clearance" | "row-gap-uniform" | "column-gap-uniform" | "rows-not-rendered" | "malformed-input" | "validation-interrupted";
1538
+ type VisualAxis = "node-visibility" | "edge-label-overlap" | "edge-label-proximity" | "text-readability" | "row-format" | "alignment" | "clearance" | "arrow-endpoint-anchoring" | "label-char-range" | "node-overlap" | "edge-crossing" | "edge-node-cross" | "edge-segment-orthogonality" | "label-inside-viewbox" | "lane-cx-consistency" | "row-vertical-spacing" | "group-boundary-clearance" | "node-vertical-clearance" | "lane-lane-gap" | "arrow-marker-clearance" | "grid-alignment" | "phase-layout-stability" | "responsive-viewport" | "accessibility-basics" | "animation-frame-integrity" | "i18n-cjk-detection" | "contrast-basics" | "print-media-compat" | "color-blind-safety" | "marker-gradient-def-integrity" | "subpixel-precision" | "dom-complexity-budget" | "reduced-motion-compat" | "touch-target-size" | "row-content-typing" | "terminal-safe-text" | "gpu-layer-efficiency" | "memory-budget" | "svg-injection-safety" | "seo-metadata-quality" | "bidi-hyphenation" | "structured-data-extraction" | "diagram-version-semver" | "migration-path-consistency" | "axis-coverage-meta" | "axis-documentation-completeness" | "fixture-drift-detection" | "locale-parity" | "validate-performance-budget" | "node-inside-viewbox" | "shape-label-dropped" | "node-inside-lane" | "edge-inside-viewbox" | "lane-label-inside-viewbox" | "lane-label-overlap" | "row-alignment" | "column-alignment" | "edge-stubout-min" | "fan-origin-single-point" | "detour-slot-distinct" | "arrow-endpoint-center" | "lane-border-clearance" | "row-gap-uniform" | "column-gap-uniform" | "rows-not-rendered" | "malformed-input" | "validation-interrupted";
1539
1539
  /**
1540
1540
  * 検査の用途。 用途によって見るべき軸が違う。
1541
1541
  *
@@ -2643,6 +2643,16 @@ declare function bboxDiffWorld(predicted: {
2643
2643
  max: number;
2644
2644
  };
2645
2645
 
2646
+ /**
2647
+ * 状態を読む書き方 (`{名前}`)。
2648
+ *
2649
+ * 中身の型 (`BoundNumber` / `BoundEnum`) は任意の文字列を受けるが、 **入口はこの形だけに
2650
+ * 限る** (#468 Round 1)。 広いままだと `value: "abc"` や `quadrant: "topLfet"` のような
2651
+ * 書き間違いが、 これまで組み立ての時点で止まっていたのに実行時まで進み、 解決側の既定値
2652
+ * (0 / 左下 / 普通) に落ちた図が出る。
2653
+ */
2654
+ type 名前の頭 = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "_";
2655
+ type BindingRef = `{${名前の頭}${string}}`;
2646
2656
  /**
2647
2657
  * 高位 API ... 著者が「lane / node / edge を 1 件ずつ宣言」 する低位 API を簡略化。
2648
2658
  *
@@ -2690,10 +2700,32 @@ type FlowPreset = {
2690
2700
  /** edge tone / style の default (各 step → next step の edge) */
2691
2701
  defaultTone?: Tone;
2692
2702
  defaultStyle?: EdgeStyle;
2703
+ /**
2704
+ * step 間の edge を自動生成するか (既定 true)。
2705
+ *
2706
+ * `false` にすると `step()` は node だけを置き、矢印は呼び手が `edge()` で宣言する。
2707
+ * **並び順と違う流れ** (`alpha` から `gamma` へ直接繋いで `beta` を経由しない等) を
2708
+ * 書きたい時に使う。 自動生成しか無かった間、その形は本 preset では作れなかった (#474)。
2709
+ *
2710
+ * 既定を `true` にしているので、既存の呼び出しは 1 行も変えずに同じ図になる。
2711
+ */
2712
+ autoChain?: boolean;
2693
2713
  };
2694
2714
  type FlowBuilder = {
2695
- /** step を順番に追加、 自動で前 step から edge 接続 */
2715
+ /** step を順番に追加、 自動で前 step から edge 接続 (`autoChain: false` なら node だけ) */
2696
2716
  step: (node: FlowStepInput, edgeLabel?: string) => FlowBuilder;
2717
+ /**
2718
+ * 矢印を宣言する (#474)。 tone / style は preset の既定を引き継ぐ。
2719
+ *
2720
+ * ここで作った矢印も `build()` の phase の `activate` に載る (自動生成分と同じ扱い)。
2721
+ * 載せないと animation で光らず、自動生成と見た目が揃わない。
2722
+ */
2723
+ edge: (from: string, to: string, opts?: {
2724
+ id?: string;
2725
+ label?: string;
2726
+ tone?: Tone;
2727
+ style?: EdgeStyle;
2728
+ }) => FlowBuilder;
2697
2729
  build: () => ReturnType<DiagramBuilder["build"]>;
2698
2730
  };
2699
2731
  /**
@@ -3023,8 +3055,8 @@ type TreeNode = {
3023
3055
  parent?: string;
3024
3056
  /** 表示 kind (default "card") */
3025
3057
  kind?: NodeKind;
3058
+ /** 箱の 2 行目に出す補足。 上の小ラベルは木では受けない (#471、 `TreeNodePayload` 参照) */
3026
3059
  subtitle?: string;
3027
- eyebrow?: string;
3028
3060
  };
3029
3061
  type TreePreset = {
3030
3062
  id: string;
@@ -3055,7 +3087,8 @@ declare function tree(preset: TreePreset): TreeBuilder;
3055
3087
  type JourneyStep = {
3056
3088
  id: string;
3057
3089
  title: string;
3058
- emotion: JourneyEmotion;
3090
+ /** 起伏の段階。 `{名前}` を書くと状態から読む (#468) */
3091
+ emotion: JourneyEmotion | BindingRef;
3059
3092
  /** どの touchpoint (例 "Website", "Email", "Support") */
3060
3093
  touchpoint?: string;
3061
3094
  /** opportunity (改善余地のメモ) */
@@ -3121,8 +3154,8 @@ declare function mindMap(preset: MindMapPreset): MindMapBuilder;
3121
3154
  type FunnelStage = {
3122
3155
  id: string;
3123
3156
  title: string;
3124
- /** この stage の人数 / 件数 */
3125
- count: number;
3157
+ /** この stage の人数 / 件数。 `{名前}` を書くと状態から読む (#468) */
3158
+ count: number | BindingRef;
3126
3159
  /** stage 詳細 */
3127
3160
  subtitle?: string;
3128
3161
  };
@@ -3153,8 +3186,8 @@ type QuadrantQuadrantLabel = QuadrantKey;
3153
3186
  type QuadrantItem = {
3154
3187
  id: string;
3155
3188
  title: string;
3156
- /** どの象限 (4 象限) */
3157
- quadrant: QuadrantQuadrantLabel;
3189
+ /** どの象限 (4 象限) `{名前}` を書くと状態から読む (#468) */
3190
+ quadrant: QuadrantQuadrantLabel | BindingRef;
3158
3191
  subtitle?: string;
3159
3192
  };
3160
3193
  type QuadrantPreset = {
@@ -3198,7 +3231,8 @@ type ChartType = "pie" | "bar" | "line";
3198
3231
  type ChartDatum = {
3199
3232
  id: string;
3200
3233
  label: string;
3201
- value: number;
3234
+ /** 棒 / 折れ線 / 扇の大きさ。 `{名前}` を書くと状態から読む (#468) */
3235
+ value: number | BindingRef;
3202
3236
  /** 個別 tone (default は preset の defaultTone) */
3203
3237
  tone?: Tone;
3204
3238
  };
@@ -3231,9 +3265,15 @@ declare function chart(preset: ChartPreset): ChartBuilder;
3231
3265
  type GanttTask = {
3232
3266
  id: string;
3233
3267
  title: string;
3234
- /** 開始 (例 "2026-Q1" / "Day 1") */
3268
+ /**
3269
+ * 開始の目盛りの名前 (例 "2026-Q1" / "Day 1")。
3270
+ *
3271
+ * `{名前}` を書くと **位置そのもの** を状態から読む (#468)。 目盛りの名前の対応付けは
3272
+ * 飛ばす = 名前の並びに `{名前}` が混ざると、 位置が状態で動くたびに目盛りの並びが
3273
+ * 変わってしまう。
3274
+ */
3235
3275
  start: string;
3236
- /** 終了 (例 "2026-Q2") */
3276
+ /** 終了の目盛りの名前。 `{名前}` の扱いは `start` と同じ (#468) */
3237
3277
  end: string;
3238
3278
  /** owner / assignee */
3239
3279
  owner?: string;
@@ -3245,6 +3285,17 @@ type GanttPreset = {
3245
3285
  topic: string;
3246
3286
  defaultTone?: Tone;
3247
3287
  laneWidth?: number;
3288
+ /**
3289
+ * 横軸を何目盛り分にするか (`#483`)。
3290
+ *
3291
+ * 書かないと今までどおり全 task の最大値から自動で決まるため、 `{名前}` で動く task が
3292
+ * 1 つあると **動かしていない task の帯まで伸び縮みする** (実測 = 端を 3 から 9 に動かすと
3293
+ * 静的な task の帯が 252 から 97.2 になった)。
3294
+ *
3295
+ * 書くと尺がその値で固定され、 他の task の帯の位置と幅が変わらない。 範囲から外れる task の
3296
+ * 帯は右端の目盛りに寄せて描く (`kinds/gantt.tsx` SSOT)。
3297
+ */
3298
+ axisMax?: number;
3248
3299
  };
3249
3300
  type GanttBuilder = {
3250
3301
  task: (t: GanttTask) => GanttBuilder;
@@ -3254,8 +3305,11 @@ type GanttBuilder = {
3254
3305
  * gantt preset ... Gantt chart / sprint planning / release timeline。
3255
3306
  * task ごとに 1 lane を作り、 start - end + owner を subtitle、 dependsOn で前 task → 次 task の edge を auto 生成。
3256
3307
  *
3308
+ * 横軸の範囲は既定では全 task の最大値から自動で決まる。 `axisMax` を書くと尺がその値で
3309
+ * 固定され、 `{名前}` で動く task があっても他の task の帯が動かない (`#483`)。
3310
+ *
3257
3311
  * @example
3258
- * gantt({ id: "release", topic: "Release timeline" })
3312
+ * gantt({ id: "release", topic: "Release timeline", axisMax: 4 })
3259
3313
  * .task({ id: "design", title: "Design", start: "Q1", end: "Q1" })
3260
3314
  * .task({ id: "build", title: "Build", start: "Q2", end: "Q2", dependsOn: "design" })
3261
3315
  * .task({ id: "test", title: "Test", start: "Q3", end: "Q3", dependsOn: "build" })
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 CdlState, f as CdlEventTarget, g as Computed, h as CdlDerivedValue, i as CdlScrollTrigger, L as LaidDiagram, j as CdlDiagramViewProps, k as LaidEdge, l as LaidNode, m as CdlEdge, B as BBox, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-DquCvgOB.js';
2
- export { n as CdlDiagramView, o as CdlEventBinding, p as CdlEventKind, q as CdlFormula, r as CdlPhase, I as InteractiveHandlerMap, s as InteractiveSignalsAccessor, t as LaidLane, u as NODE_KINDS, v as ScrollProgressHandle, w as TONES, x as computeEventBindingKey, y as computeFormulaKey, z as computeInputSignalKey, A as computeScrollTriggerKey, D as computed, F as createInteractiveSignalsAccessor, G as createScrollProgressHandle, H as createScrollProgressSignals, K as hasInteractivePrimitives, M as signal } from './render-DquCvgOB.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 CdlState, f as CdlEventTarget, g as Computed, h as CdlDerivedValue, i as CdlScrollTrigger, L as LaidDiagram, j as CdlDiagramViewProps, k as LaidEdge, l as LaidNode, m as CdlEdge, B as BBox, N as NodeKind, J as JourneyEmotion, Q as QuadrantKey } from './render-hmFRAabt.js';
2
+ export { n as CdlDiagramView, o as CdlEventBinding, p as CdlEventKind, q as CdlFormula, r as CdlPhase, I as InteractiveHandlerMap, s as InteractiveSignalsAccessor, t as LaidLane, u as NODE_KINDS, v as ScrollProgressHandle, w as TONES, x as computeEventBindingKey, y as computeFormulaKey, z as computeInputSignalKey, A as computeScrollTriggerKey, D as computed, F as createInteractiveSignalsAccessor, G as createScrollProgressHandle, H as createScrollProgressSignals, K as hasInteractivePrimitives, M as signal } from './render-hmFRAabt.js';
3
3
  import { JSX } from 'react';
4
4
 
5
5
  declare function effect(fn: () => void | (() => void)): () => void;
@@ -1535,7 +1535,7 @@ interface Violation {
1535
1535
  detail: string;
1536
1536
  severity: "error" | "warn";
1537
1537
  }
1538
- type VisualAxis = "node-visibility" | "edge-label-overlap" | "edge-label-proximity" | "text-readability" | "row-format" | "alignment" | "clearance" | "arrow-endpoint-anchoring" | "label-char-range" | "node-overlap" | "edge-crossing" | "edge-node-cross" | "edge-segment-orthogonality" | "label-inside-viewbox" | "lane-cx-consistency" | "row-vertical-spacing" | "group-boundary-clearance" | "node-vertical-clearance" | "lane-lane-gap" | "arrow-marker-clearance" | "grid-alignment" | "phase-layout-stability" | "responsive-viewport" | "accessibility-basics" | "animation-frame-integrity" | "i18n-cjk-detection" | "contrast-basics" | "print-media-compat" | "color-blind-safety" | "marker-gradient-def-integrity" | "subpixel-precision" | "dom-complexity-budget" | "reduced-motion-compat" | "touch-target-size" | "row-content-typing" | "terminal-safe-text" | "gpu-layer-efficiency" | "memory-budget" | "svg-injection-safety" | "seo-metadata-quality" | "bidi-hyphenation" | "structured-data-extraction" | "diagram-version-semver" | "migration-path-consistency" | "axis-coverage-meta" | "axis-documentation-completeness" | "fixture-drift-detection" | "locale-parity" | "validate-performance-budget" | "node-inside-viewbox" | "node-inside-lane" | "edge-inside-viewbox" | "lane-label-inside-viewbox" | "lane-label-overlap" | "row-alignment" | "column-alignment" | "edge-stubout-min" | "fan-origin-single-point" | "detour-slot-distinct" | "arrow-endpoint-center" | "lane-border-clearance" | "row-gap-uniform" | "column-gap-uniform" | "rows-not-rendered" | "malformed-input" | "validation-interrupted";
1538
+ type VisualAxis = "node-visibility" | "edge-label-overlap" | "edge-label-proximity" | "text-readability" | "row-format" | "alignment" | "clearance" | "arrow-endpoint-anchoring" | "label-char-range" | "node-overlap" | "edge-crossing" | "edge-node-cross" | "edge-segment-orthogonality" | "label-inside-viewbox" | "lane-cx-consistency" | "row-vertical-spacing" | "group-boundary-clearance" | "node-vertical-clearance" | "lane-lane-gap" | "arrow-marker-clearance" | "grid-alignment" | "phase-layout-stability" | "responsive-viewport" | "accessibility-basics" | "animation-frame-integrity" | "i18n-cjk-detection" | "contrast-basics" | "print-media-compat" | "color-blind-safety" | "marker-gradient-def-integrity" | "subpixel-precision" | "dom-complexity-budget" | "reduced-motion-compat" | "touch-target-size" | "row-content-typing" | "terminal-safe-text" | "gpu-layer-efficiency" | "memory-budget" | "svg-injection-safety" | "seo-metadata-quality" | "bidi-hyphenation" | "structured-data-extraction" | "diagram-version-semver" | "migration-path-consistency" | "axis-coverage-meta" | "axis-documentation-completeness" | "fixture-drift-detection" | "locale-parity" | "validate-performance-budget" | "node-inside-viewbox" | "shape-label-dropped" | "node-inside-lane" | "edge-inside-viewbox" | "lane-label-inside-viewbox" | "lane-label-overlap" | "row-alignment" | "column-alignment" | "edge-stubout-min" | "fan-origin-single-point" | "detour-slot-distinct" | "arrow-endpoint-center" | "lane-border-clearance" | "row-gap-uniform" | "column-gap-uniform" | "rows-not-rendered" | "malformed-input" | "validation-interrupted";
1539
1539
  /**
1540
1540
  * 検査の用途。 用途によって見るべき軸が違う。
1541
1541
  *
@@ -2643,6 +2643,16 @@ declare function bboxDiffWorld(predicted: {
2643
2643
  max: number;
2644
2644
  };
2645
2645
 
2646
+ /**
2647
+ * 状態を読む書き方 (`{名前}`)。
2648
+ *
2649
+ * 中身の型 (`BoundNumber` / `BoundEnum`) は任意の文字列を受けるが、 **入口はこの形だけに
2650
+ * 限る** (#468 Round 1)。 広いままだと `value: "abc"` や `quadrant: "topLfet"` のような
2651
+ * 書き間違いが、 これまで組み立ての時点で止まっていたのに実行時まで進み、 解決側の既定値
2652
+ * (0 / 左下 / 普通) に落ちた図が出る。
2653
+ */
2654
+ type 名前の頭 = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "_";
2655
+ type BindingRef = `{${名前の頭}${string}}`;
2646
2656
  /**
2647
2657
  * 高位 API ... 著者が「lane / node / edge を 1 件ずつ宣言」 する低位 API を簡略化。
2648
2658
  *
@@ -2690,10 +2700,32 @@ type FlowPreset = {
2690
2700
  /** edge tone / style の default (各 step → next step の edge) */
2691
2701
  defaultTone?: Tone;
2692
2702
  defaultStyle?: EdgeStyle;
2703
+ /**
2704
+ * step 間の edge を自動生成するか (既定 true)。
2705
+ *
2706
+ * `false` にすると `step()` は node だけを置き、矢印は呼び手が `edge()` で宣言する。
2707
+ * **並び順と違う流れ** (`alpha` から `gamma` へ直接繋いで `beta` を経由しない等) を
2708
+ * 書きたい時に使う。 自動生成しか無かった間、その形は本 preset では作れなかった (#474)。
2709
+ *
2710
+ * 既定を `true` にしているので、既存の呼び出しは 1 行も変えずに同じ図になる。
2711
+ */
2712
+ autoChain?: boolean;
2693
2713
  };
2694
2714
  type FlowBuilder = {
2695
- /** step を順番に追加、 自動で前 step から edge 接続 */
2715
+ /** step を順番に追加、 自動で前 step から edge 接続 (`autoChain: false` なら node だけ) */
2696
2716
  step: (node: FlowStepInput, edgeLabel?: string) => FlowBuilder;
2717
+ /**
2718
+ * 矢印を宣言する (#474)。 tone / style は preset の既定を引き継ぐ。
2719
+ *
2720
+ * ここで作った矢印も `build()` の phase の `activate` に載る (自動生成分と同じ扱い)。
2721
+ * 載せないと animation で光らず、自動生成と見た目が揃わない。
2722
+ */
2723
+ edge: (from: string, to: string, opts?: {
2724
+ id?: string;
2725
+ label?: string;
2726
+ tone?: Tone;
2727
+ style?: EdgeStyle;
2728
+ }) => FlowBuilder;
2697
2729
  build: () => ReturnType<DiagramBuilder["build"]>;
2698
2730
  };
2699
2731
  /**
@@ -3023,8 +3055,8 @@ type TreeNode = {
3023
3055
  parent?: string;
3024
3056
  /** 表示 kind (default "card") */
3025
3057
  kind?: NodeKind;
3058
+ /** 箱の 2 行目に出す補足。 上の小ラベルは木では受けない (#471、 `TreeNodePayload` 参照) */
3026
3059
  subtitle?: string;
3027
- eyebrow?: string;
3028
3060
  };
3029
3061
  type TreePreset = {
3030
3062
  id: string;
@@ -3055,7 +3087,8 @@ declare function tree(preset: TreePreset): TreeBuilder;
3055
3087
  type JourneyStep = {
3056
3088
  id: string;
3057
3089
  title: string;
3058
- emotion: JourneyEmotion;
3090
+ /** 起伏の段階。 `{名前}` を書くと状態から読む (#468) */
3091
+ emotion: JourneyEmotion | BindingRef;
3059
3092
  /** どの touchpoint (例 "Website", "Email", "Support") */
3060
3093
  touchpoint?: string;
3061
3094
  /** opportunity (改善余地のメモ) */
@@ -3121,8 +3154,8 @@ declare function mindMap(preset: MindMapPreset): MindMapBuilder;
3121
3154
  type FunnelStage = {
3122
3155
  id: string;
3123
3156
  title: string;
3124
- /** この stage の人数 / 件数 */
3125
- count: number;
3157
+ /** この stage の人数 / 件数。 `{名前}` を書くと状態から読む (#468) */
3158
+ count: number | BindingRef;
3126
3159
  /** stage 詳細 */
3127
3160
  subtitle?: string;
3128
3161
  };
@@ -3153,8 +3186,8 @@ type QuadrantQuadrantLabel = QuadrantKey;
3153
3186
  type QuadrantItem = {
3154
3187
  id: string;
3155
3188
  title: string;
3156
- /** どの象限 (4 象限) */
3157
- quadrant: QuadrantQuadrantLabel;
3189
+ /** どの象限 (4 象限) `{名前}` を書くと状態から読む (#468) */
3190
+ quadrant: QuadrantQuadrantLabel | BindingRef;
3158
3191
  subtitle?: string;
3159
3192
  };
3160
3193
  type QuadrantPreset = {
@@ -3198,7 +3231,8 @@ type ChartType = "pie" | "bar" | "line";
3198
3231
  type ChartDatum = {
3199
3232
  id: string;
3200
3233
  label: string;
3201
- value: number;
3234
+ /** 棒 / 折れ線 / 扇の大きさ。 `{名前}` を書くと状態から読む (#468) */
3235
+ value: number | BindingRef;
3202
3236
  /** 個別 tone (default は preset の defaultTone) */
3203
3237
  tone?: Tone;
3204
3238
  };
@@ -3231,9 +3265,15 @@ declare function chart(preset: ChartPreset): ChartBuilder;
3231
3265
  type GanttTask = {
3232
3266
  id: string;
3233
3267
  title: string;
3234
- /** 開始 (例 "2026-Q1" / "Day 1") */
3268
+ /**
3269
+ * 開始の目盛りの名前 (例 "2026-Q1" / "Day 1")。
3270
+ *
3271
+ * `{名前}` を書くと **位置そのもの** を状態から読む (#468)。 目盛りの名前の対応付けは
3272
+ * 飛ばす = 名前の並びに `{名前}` が混ざると、 位置が状態で動くたびに目盛りの並びが
3273
+ * 変わってしまう。
3274
+ */
3235
3275
  start: string;
3236
- /** 終了 (例 "2026-Q2") */
3276
+ /** 終了の目盛りの名前。 `{名前}` の扱いは `start` と同じ (#468) */
3237
3277
  end: string;
3238
3278
  /** owner / assignee */
3239
3279
  owner?: string;
@@ -3245,6 +3285,17 @@ type GanttPreset = {
3245
3285
  topic: string;
3246
3286
  defaultTone?: Tone;
3247
3287
  laneWidth?: number;
3288
+ /**
3289
+ * 横軸を何目盛り分にするか (`#483`)。
3290
+ *
3291
+ * 書かないと今までどおり全 task の最大値から自動で決まるため、 `{名前}` で動く task が
3292
+ * 1 つあると **動かしていない task の帯まで伸び縮みする** (実測 = 端を 3 から 9 に動かすと
3293
+ * 静的な task の帯が 252 から 97.2 になった)。
3294
+ *
3295
+ * 書くと尺がその値で固定され、 他の task の帯の位置と幅が変わらない。 範囲から外れる task の
3296
+ * 帯は右端の目盛りに寄せて描く (`kinds/gantt.tsx` SSOT)。
3297
+ */
3298
+ axisMax?: number;
3248
3299
  };
3249
3300
  type GanttBuilder = {
3250
3301
  task: (t: GanttTask) => GanttBuilder;
@@ -3254,8 +3305,11 @@ type GanttBuilder = {
3254
3305
  * gantt preset ... Gantt chart / sprint planning / release timeline。
3255
3306
  * task ごとに 1 lane を作り、 start - end + owner を subtitle、 dependsOn で前 task → 次 task の edge を auto 生成。
3256
3307
  *
3308
+ * 横軸の範囲は既定では全 task の最大値から自動で決まる。 `axisMax` を書くと尺がその値で
3309
+ * 固定され、 `{名前}` で動く task があっても他の task の帯が動かない (`#483`)。
3310
+ *
3257
3311
  * @example
3258
- * gantt({ id: "release", topic: "Release timeline" })
3312
+ * gantt({ id: "release", topic: "Release timeline", axisMax: 4 })
3259
3313
  * .task({ id: "design", title: "Design", start: "Q1", end: "Q1" })
3260
3314
  * .task({ id: "build", title: "Build", start: "Q2", end: "Q2", dependsOn: "design" })
3261
3315
  * .task({ id: "test", title: "Test", start: "Q3", end: "Q3", dependsOn: "build" })