@cardenelabs/cdl 0.5.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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +343 -0
  3. package/SPEC.md +374 -0
  4. package/dist/index.cjs +28085 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.cts +3415 -0
  7. package/dist/index.d.ts +3415 -0
  8. package/dist/index.js +27962 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/react.cjs +23043 -0
  11. package/dist/react.cjs.map +1 -0
  12. package/dist/react.d.cts +2 -0
  13. package/dist/react.d.ts +2 -0
  14. package/dist/react.js +23041 -0
  15. package/dist/react.js.map +1 -0
  16. package/dist/render-C78lIXeC.d.cts +2449 -0
  17. package/dist/render-C78lIXeC.d.ts +2449 -0
  18. package/examples/quick-start.md +88 -0
  19. package/package.json +79 -0
  20. package/src/anim/core/easing.ts +77 -0
  21. package/src/anim/core/timeline.ts +335 -0
  22. package/src/anim/core/types.ts +42 -0
  23. package/src/anim/index.ts +20 -0
  24. package/src/anim/react/index.ts +3 -0
  25. package/src/anim/react/useReducedMotion.ts +27 -0
  26. package/src/anim/react/useTimeline.ts +48 -0
  27. package/src/assert-never.ts +16 -0
  28. package/src/author-intent-verify.ts +587 -0
  29. package/src/builder.ts +3740 -0
  30. package/src/compile.ts +12 -0
  31. package/src/dom-verify-core.ts +121 -0
  32. package/src/dom-verify-types.ts +21 -0
  33. package/src/dom-verify.ts +948 -0
  34. package/src/event-handler/index.ts +184 -0
  35. package/src/formula/ast.ts +46 -0
  36. package/src/formula/evaluator.ts +163 -0
  37. package/src/formula/formula-computeds.ts +83 -0
  38. package/src/formula/index.ts +5 -0
  39. package/src/formula/parser.ts +399 -0
  40. package/src/index.ts +284 -0
  41. package/src/input-signals.ts +74 -0
  42. package/src/kinds/actor.tsx +79 -0
  43. package/src/kinds/card.tsx +61 -0
  44. package/src/kinds/chart-bar.tsx +121 -0
  45. package/src/kinds/chart-line.tsx +163 -0
  46. package/src/kinds/chart-pie.tsx +107 -0
  47. package/src/kinds/compact-title.ts +164 -0
  48. package/src/kinds/dyn-shape.tsx +394 -0
  49. package/src/kinds/event.tsx +70 -0
  50. package/src/kinds/function.tsx +53 -0
  51. package/src/kinds/funnel.tsx +122 -0
  52. package/src/kinds/gantt.tsx +193 -0
  53. package/src/kinds/generic.tsx +368 -0
  54. package/src/kinds/mind-map.tsx +367 -0
  55. package/src/kinds/mind-radial.tsx +209 -0
  56. package/src/kinds/node-tone.ts +18 -0
  57. package/src/kinds/quadrant.tsx +164 -0
  58. package/src/kinds/row-align.ts +179 -0
  59. package/src/kinds/shape-basement.tsx +683 -0
  60. package/src/kinds/shape-blockchain.tsx +750 -0
  61. package/src/kinds/shape-commerce.tsx +553 -0
  62. package/src/kinds/shape-finance.tsx +706 -0
  63. package/src/kinds/shape-hardware.tsx +862 -0
  64. package/src/kinds/shape-people.tsx +439 -0
  65. package/src/kinds/shape-region.tsx +383 -0
  66. package/src/kinds/shape-software.tsx +859 -0
  67. package/src/kinds/storage.tsx +180 -0
  68. package/src/kinds/text-width.ts +73 -0
  69. package/src/kinds/tree.tsx +275 -0
  70. package/src/kinds/user-journey.tsx +240 -0
  71. package/src/label-text.ts +71 -0
  72. package/src/layout/clearance-constants.ts +47 -0
  73. package/src/layout/collisions.ts +2078 -0
  74. package/src/layout/edges.ts +2498 -0
  75. package/src/layout/footer-shape.ts +97 -0
  76. package/src/layout/geometry.ts +135 -0
  77. package/src/layout/label-shift.ts +28 -0
  78. package/src/layout/lanes.ts +328 -0
  79. package/src/layout/nodes.ts +190 -0
  80. package/src/layout/predict-bbox.ts +76 -0
  81. package/src/layout/px-projection.ts +176 -0
  82. package/src/layout/spec.ts +872 -0
  83. package/src/layout/text-width.ts +133 -0
  84. package/src/layout/tokens.ts +181 -0
  85. package/src/layout/viewbox.ts +47 -0
  86. package/src/layout-with-validation.ts +175 -0
  87. package/src/layout.ts +381 -0
  88. package/src/presets.ts +2108 -0
  89. package/src/reactive/batch.ts +48 -0
  90. package/src/reactive/computed.ts +85 -0
  91. package/src/reactive/effect.ts +145 -0
  92. package/src/reactive/index.ts +6 -0
  93. package/src/reactive/internal.ts +109 -0
  94. package/src/reactive/signal.ts +113 -0
  95. package/src/render/edges.tsx +318 -0
  96. package/src/render/header.tsx +146 -0
  97. package/src/render/interactive-panel.tsx +9620 -0
  98. package/src/render/nodes.tsx +319 -0
  99. package/src/render/stage.tsx +377 -0
  100. package/src/render/tone.ts +64 -0
  101. package/src/render/utils.ts +238 -0
  102. package/src/render.tsx +221 -0
  103. package/src/scroll-trigger/index.ts +109 -0
  104. package/src/scroll-trigger/progress.ts +49 -0
  105. package/src/thumbnail.tsx +114 -0
  106. package/src/types.ts +2371 -0
  107. package/src/validate.ts +268 -0
  108. package/src/visual-validate.ts +4381 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cardene777
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,343 @@
1
+ # @cardenelabs/cdl
2
+
3
+ > Declarative TypeScript DSL for animated React + SVG diagrams. UML / ER / state machine / topology / sequence / flow を 1 行で書く OSS library。
4
+
5
+ [![npm](https://img.shields.io/npm/v/@cardenelabs/cdl.svg)](https://www.npmjs.com/package/@cardenelabs/cdl)
6
+ [![license](https://img.shields.io/npm/l/@cardenelabs/cdl.svg)](LICENSE)
7
+
8
+ ## Documentation
9
+
10
+ | 目的 | リンク |
11
+ |---|---|
12
+ | **repo root** | [github.com/cardene777/cdl](https://github.com/cardene777/cdl) |
13
+ | **5 分で動かす** | [README quickstart](#quickstart) (本 file 下部) |
14
+ | **playground demo** | `pnpm dev` → http://localhost:4321 ([apps/playground](../../apps/playground/README.md)) |
15
+ | **全 API + preset 一覧** | playground `/docs/reference` |
16
+ | **Text DSL spec** | `apps/playground/src/content/cdl-docs/text-dsl-spec.md` |
17
+ | **LLM prompt guide** | `apps/playground/src/content/cdl-docs/text-dsl-llm-guide.md` |
18
+ | **contribute** | [CONTRIBUTING.md](../../CONTRIBUTING.md) |
19
+
20
+ ## なぜ cdl
21
+
22
+ mermaid / PlantUML はテキストから静止画像を生成する。 cdl は **TypeScript → animated React + SVG component** で、 phase / state / tween / progress glow 等の動きを宣言的に書ける。
23
+
24
+ | 形式 | mermaid | cdl |
25
+ |---|---|---|
26
+ | sequence | 静止 | animated + phase 切替 |
27
+ | ER 図 | 静止 | animated + cardinality + sub label |
28
+ | state diagram | 静止 | animated + initial/final marker + guard |
29
+ | flow | 静止 | animated + dotted-flow 進行点 glow |
30
+ | 構成図 / deployment | 限定的 | animated + container group + connection |
31
+ | 自由レイアウト | 限定的 | lane + node + edge で自由構成 |
32
+
33
+ ## Quickstart
34
+
35
+ ```bash
36
+ pnpm add @cardenelabs/cdl react react-dom
37
+ ```
38
+
39
+ ### diagram declare
40
+
41
+ ```ts
42
+ import { sequence } from "@cardenelabs/cdl";
43
+
44
+ export const authSeq = sequence({
45
+ id: "auth",
46
+ topic: "User Login",
47
+ actors: ["User", "API", "DB"],
48
+ })
49
+ .step({ from: "User", to: "API", label: "POST /login", sub: "email + password" })
50
+ .step({ from: "API", to: "DB", label: "SELECT credentials" })
51
+ .step({ from: "DB", to: "API", label: "rows", tone: "success", style: "dotted-flow" })
52
+ .step({ from: "API", to: "User", label: "200 OK", sub: "JWT token", tone: "success" })
53
+ .build();
54
+ ```
55
+
56
+ ### React で render
57
+
58
+ ```tsx
59
+ import { CdlDiagramView } from "@cardenelabs/cdl";
60
+ import { authSeq } from "./auth-seq";
61
+
62
+ export function AuthSequenceDemo() {
63
+ return <CdlDiagramView diagram={authSeq} />;
64
+ }
65
+ ```
66
+
67
+ これで UML sequence diagram が phase 切替 + state diff + 進行点 glow で animated に表示。
68
+
69
+ ## 6 つの preset
70
+
71
+ 低位 API (lane / node / edge 個別宣言) + 高位 preset (1 行で典型図生成)。
72
+
73
+ ### swimlane
74
+
75
+ 横並び 3 lane 自動配置 + slug 自動。
76
+
77
+ ```ts
78
+ swimlane({ id, topic, lanes: ["送信元", "Contract", "出力"] })
79
+ .node("alice", { lane: "送信元", stack: 0, kind: "actor", title: "Alice" })
80
+ .node("fn", { lane: "Contract", stack: 0, kind: "function", title: "transfer(...)" })
81
+ .edge("alice", "fn", { id: "call", label: "call", tone: "accent", style: "dotted-flow" })
82
+ .build()
83
+ ```
84
+
85
+ ### flow
86
+
87
+ 1 lane 縦 stack、 前 step → 次 step 自動 edge。
88
+
89
+ ```ts
90
+ flow({ id, topic, laneLabel: "Auth Flow", defaultTone: "teal" })
91
+ .step({ id: "user", kind: "person", title: "User" })
92
+ .step({ id: "api", kind: "api", title: "POST /login" }, "ログイン要求")
93
+ .step({ id: "db", kind: "database", title: "users 表" }, "credential 検証")
94
+ .build()
95
+ ```
96
+
97
+ ### sequence
98
+
99
+ UML sequence diagram (actor lifeline + 時系列 message)。
100
+
101
+ ```ts
102
+ sequence({ id, topic, actors: ["User", "API", "DB"] })
103
+ .step({ from: "User", to: "API", label: "POST /login" })
104
+ .step({ from: "API", to: "DB", label: "SELECT" })
105
+ .step({ from: "API", to: "User", label: "200 OK", tone: "success" })
106
+ .build()
107
+ ```
108
+
109
+ ### topology
110
+
111
+ 構成図 / deployment diagram (group + container + connection)。
112
+
113
+ ```ts
114
+ topology({ id, topic })
115
+ .group("aws", { label: "AWS" })
116
+ .add({ id: "alb", kind: "service", title: "ALB" })
117
+ .add({ id: "ecs", kind: "service", title: "ECS Task" })
118
+ .add({ id: "rds", kind: "database", title: "RDS" })
119
+ .group("client", { label: "Client" })
120
+ .add({ id: "browser", kind: "frontend", title: "Browser" })
121
+ .connect("browser", "alb", { label: "HTTPS" })
122
+ .connect("ecs", "rds", { label: "TCP 5432", tone: "success" })
123
+ .build()
124
+ ```
125
+
126
+ ### er
127
+
128
+ ER 図 (entity + cardinality)。
129
+
130
+ ```ts
131
+ er({ id, topic })
132
+ .entity({ id: "user", title: "User", rows: ["id: PK", "email: string", "createdAt: timestamp"] })
133
+ .entity({ id: "order", title: "Order", rows: ["id: PK", "userId: FK", "total: number"] })
134
+ .relation({ from: "user", to: "order", cardinality: "1:N", label: "places" })
135
+ .build()
136
+ ```
137
+
138
+ cardinality 6 種 ... `"1:1" | "1:N" | "N:1" | "N:M" | "0..1" | "1..*"`。
139
+
140
+ ### stateMachine
141
+
142
+ FSM / workflow (state + transition trigger + guard)。
143
+
144
+ ```ts
145
+ stateMachine({ id, topic })
146
+ .state({ id: "idle", title: "Idle", initial: true })
147
+ .state({ id: "loading", title: "Loading" })
148
+ .state({ id: "done", title: "Done", final: true })
149
+ .state({ id: "error", title: "Error" })
150
+ .transition({ from: "idle", to: "loading", trigger: "submit" })
151
+ .transition({ from: "loading", to: "done", trigger: "success", tone: "success" })
152
+ .transition({ from: "loading", to: "error", trigger: "fail", tone: "error" })
153
+ .transition({ from: "error", to: "idle", trigger: "retry", guard: "if attempts < 3" })
154
+ .build()
155
+ ```
156
+
157
+ ## 低位 API
158
+
159
+ preset で表現しきれない自由レイアウトは低位 API で。
160
+
161
+ ```ts
162
+ import { diagram } from "@cardenelabs/cdl";
163
+
164
+ export const custom = diagram("custom", { topic: "Custom" })
165
+ .lane("left", { x: 0, width: 400 })
166
+ .lane("right", { x: 500, width: 400 })
167
+ .node("a", { lane: "left", stack: 0, kind: "actor", title: "Alice" })
168
+ .node("b", { lane: "right", stack: 0, kind: "function", title: "Bob" })
169
+ .edge("a", "b", { id: "e", label: "msg", tone: "accent", style: "solid" })
170
+ .state("counter", { initial: 0 })
171
+ .phase("p1", { duration: 1500, title: "Phase 1", body: "tween counter" },
172
+ (p) => p.activate("a", "b", "e").tween("counter", 0, 100).badge("running"))
173
+ .build();
174
+ ```
175
+
176
+ ## NodeKind 29 種
177
+
178
+ | 系統 | kinds |
179
+ |---|---|
180
+ | 基本 5 | `actor` / `function` / `storage` / `event` / `card` |
181
+ | 人系 5 | `person` / `user-group` / `admin` / `developer` / `external-user` |
182
+ | インフラ 6 | `database` / `cache` / `queue` / `message-bus` / `cloud` / `cdn` |
183
+ | アプリ系 6 | `service` / `api` / `frontend` / `backend` / `webhook` / `microservice` |
184
+ | blockchain 8 | `wallet` / `validator` / `miner` / `blockchain-node` / `mempool` / `block` / `bridge-node` / `relayer` |
185
+ | 暗号 / データ 4 | `signer` / `oracle` / `merkle-tree` / `decision` |
186
+
187
+ 各 kind は shape / color / icon が異なる。 基本 5 は専用 component、 残り 24 種は `GenericNode` で汎用描画。
188
+
189
+ ## EdgeStyle + Tone
190
+
191
+ | EdgeStyle | 動き |
192
+ |---|---|
193
+ | `solid` | 実線 + 矢頭 marker、 progress 連動で path が伸びる |
194
+ | `dotted-flow` | 点線 + 進行点 glow (3 重円) が path 上を流れる、 node 貫通自動判定 |
195
+
196
+ | Tone | 色 (hex) | 用途 |
197
+ |---|---|---|
198
+ | `accent` | `#c17f3e` | default |
199
+ | `teal` | `#4a8b7f` | 補助動作 |
200
+ | `success` | `#6b9e5a` | 成功 path |
201
+ | `error` | `#c15a4a` | 失敗 path |
202
+ | `warning` | `#c9a23e` | 警告 |
203
+ | `info` | `#5a8ec1` | 情報 |
204
+
205
+ ## phase / state / tween / set / badge
206
+
207
+ phase 内で state を tween / set し、 badge を出す。
208
+
209
+ ```ts
210
+ .state("amount", { initial: 0 })
211
+ .state("status", { initial: "idle" })
212
+ .phase("p1", { duration: 1800, title: "Phase 1", body: "tween + set" },
213
+ (p) => p
214
+ .activate("a", "b")
215
+ .tween("amount", 0, 100) // 数値の線形補間
216
+ .set("status", "running") // 文字列の即時切替
217
+ .badge("processing")) // header に badge 表示
218
+ ```
219
+
220
+ state placeholder は node の `title` / `subtitle` / `eyebrow` / `value` 内で `{stateId}` 記法で参照。
221
+
222
+ ```ts
223
+ .node("a", { lane: "l", stack: 0, kind: "function", title: "Process", subtitle: "status: {status}" })
224
+ ```
225
+
226
+ phase 切替に連動して `status: idle` → `status: running` のように描画される。
227
+
228
+ ## CdlDiagramView props
229
+
230
+ ```ts
231
+ <CdlDiagramView
232
+ diagram={d}
233
+ hideHeader={false} // header (phase indicator + state diff) 表示
234
+ focusPhaseId="p1" // 特定 phase に固定 (autoplay は維持)
235
+ debug={false} // bbox + collision を半透明で重ね描き (開発用)
236
+ />
237
+ ```
238
+
239
+ ## 見た目を当てる (role selector)
240
+
241
+ cdl は形だけを描き、 色や影は持たない (geometry only、 style 不干渉、 CAR-643 SSOT)。
242
+ 描かれる各部品には `data-cdl-role` が付くので、 consumer app 側が selector で見た目を当てる。
243
+
244
+ ```css
245
+ [data-cdl-role="node-body"] {
246
+ fill: #ffffff;
247
+ stroke: #57534b;
248
+ stroke-width: 1.75;
249
+ }
250
+ ```
251
+
252
+ 明暗の切替は consumer 側の仕組み (`html` の class 等) で行う = cdl は明暗の概念を持たない。
253
+
254
+ **`CdlRole` 型は実装にある role の全部ではない**。 実装には 33 種の role があり、
255
+ 型に載っているのは 13 種。 残り 20 種 (`chart-line` / `tree-edge` / `funnel-stage` /
256
+ `edge-glow` 等) は型を持たないが、 属性は付くので selector は書ける。
257
+
258
+ 型の内外は「共通か kind 固有か」 では分かれていない (共通の描画で使う `edge-glow` が型の外に
259
+ あり、 放射状の図でしか使わない `mind-radial-halo` が型の中にある)。 **型に載っているかどうかは
260
+ selector を書けるかとは無関係**なので、 一覧が要る時は source を `data-cdl-role=` で検索する。
261
+
262
+ role が付かない小さな部品もある (kind が自前で描く目盛や軸など)。 それらは CSS 変数で色を渡す。
263
+
264
+ ```css
265
+ :root {
266
+ --cdl-node-fill: #f2f1ec;
267
+ --cdl-text: #191714;
268
+ --cdl-tone-accent: #2c68ae;
269
+ }
270
+ ```
271
+
272
+ ## CdlDiagramThumbnail
273
+
274
+ thumbnail として表示、 click で viewport いっぱい (94vw x 94vh) のモーダルで拡大。
275
+
276
+ ```tsx
277
+ import { CdlDiagramThumbnail } from "@cardenelabs/cdl";
278
+
279
+ <CdlDiagramThumbnail diagram={d} hideHeader />
280
+ ```
281
+
282
+ close は Escape / 背景クリック / × の 3 経路。
283
+
284
+ ## Architecture
285
+
286
+ ```
287
+ src/
288
+ ├── builder.ts — DSL builder
289
+ ├── compile.ts — DSL → CdlDiagram normalization
290
+ ├── validate.ts — schema validation
291
+ ├── layout/ — layout engine (6 file)
292
+ │ ├── tokens.ts — DESIGN TOKENS SSOT
293
+ │ ├── lanes.ts — lane 配置 + auto width
294
+ │ ├── nodes.ts — node cy/cx/w/h 確定
295
+ │ ├── edges.ts — orthogonal routing + label
296
+ │ ├── collisions.ts — bbox + clearance + Liang-Barsky
297
+ │ └── viewbox.ts — auto viewBox 計算
298
+ ├── render/ — React + SVG (7 file)
299
+ │ ├── stage.tsx — SVG defs + 3 pass
300
+ │ ├── nodes.tsx — NodeKind 別 switch
301
+ │ ├── edges.tsx — solid / dotted-flow
302
+ │ ├── header.tsx — phase indicator + state diff
303
+ │ ├── utils.ts — interpolate / pathSubpath / shrinkPathEnd
304
+ │ └── tone.ts — TONE 6 色
305
+ ├── kinds/ — 専用 component (actor/function/storage/event/card/generic)
306
+ ├── presets.ts — 6 preset
307
+ ├── thumbnail.tsx — モーダル拡大
308
+ └── types.ts — public types
309
+ ```
310
+
311
+ ## Testing
312
+
313
+ ```sh
314
+ pnpm test
315
+ ```
316
+
317
+ vitest で 36 test (builder / compile / layout / sequence preset / snapshot) を実行、 全 pass 確認。
318
+
319
+ ## Performance baseline
320
+
321
+ `packages/cdl/test/bench.test.ts` の vitest bench で 5 case (small / medium / large / huge / animation-heavy) × 3 stage (parse / compile / layout) を計測する。
322
+
323
+ ```sh
324
+ pnpm --filter @cardenelabs/cdl exec vitest bench --run
325
+ ```
326
+
327
+ baseline (mean ms、 Apple Silicon / node 24)。
328
+
329
+ | case (node / edge / phase) | parse | compile | layout (旧) | layout (最適化後) |
330
+ | --- | --- | --- | --- | --- |
331
+ | small (10 / 5 / 0) | 0.002 | 0.020 | 0.260 | **0.192** |
332
+ | medium (100 / 50 / 5) | 0.022 | 1.488 | 25.014 | **0.807** |
333
+ | large (500 / 200 / 20) | 0.092 | 29.953 | 492.96 | **11.63** |
334
+ | huge (1000 / 500 / 50) | 0.200 | 129.88 | 2424.39 | **53.74** |
335
+ | animation-heavy (100 node / 100 phase / 50 tween) | 0.105 | 1.582 | 24.586 | **0.819** |
336
+
337
+ 最適化内容 ... `detectCollisions` / `detectNearCollisions` を全 pair O(n²) から spatial hash (cell size 200px、 max clearance 70px margin) に変更。 巨大 bbox (edge-path 等) は fallback 経路で全件比較。 huge case で約 46x 高速化、 1000 node でも 60ms 以下で完了。
338
+
339
+ stage 内訳。 parse = `parseTextDslV05` (Text DSL → DslDocument)、 compile = `compileToCdl` (DslDocument → CdlDiagram)、 layout = `layout` (CdlDiagram → LaidDiagram)。 raw 出力は `.context/scratch/bench-baseline.{txt,json}` (vitest `--outputJson` 形式)。
340
+
341
+ ## License
342
+
343
+ MIT