@zukhruf/diagram 0.0.0-stage → 0.3.27

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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +325 -2
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +6 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/compiler/diagram-compile.d.ts +16 -0
  8. package/dist/lib/compiler/diagram-compile.d.ts.map +1 -0
  9. package/dist/lib/compiler/diagram-compile.js +711 -0
  10. package/dist/lib/compiler/diagram-compile.js.map +1 -0
  11. package/dist/lib/layouts/graph/graph-layout.d.ts +153 -0
  12. package/dist/lib/layouts/graph/graph-layout.d.ts.map +1 -0
  13. package/dist/lib/layouts/graph/graph-layout.js +2345 -0
  14. package/dist/lib/layouts/graph/graph-layout.js.map +1 -0
  15. package/dist/lib/layouts/text-metrics.d.ts +7 -0
  16. package/dist/lib/layouts/text-metrics.d.ts.map +1 -0
  17. package/dist/lib/layouts/text-metrics.js +40 -0
  18. package/dist/lib/layouts/text-metrics.js.map +1 -0
  19. package/dist/lib/layouts/timeline/timeline-layout.d.ts +110 -0
  20. package/dist/lib/layouts/timeline/timeline-layout.d.ts.map +1 -0
  21. package/dist/lib/layouts/timeline/timeline-layout.js +226 -0
  22. package/dist/lib/layouts/timeline/timeline-layout.js.map +1 -0
  23. package/dist/lib/model/diagram-ir.d.ts +288 -0
  24. package/dist/lib/model/diagram-ir.d.ts.map +1 -0
  25. package/dist/lib/model/diagram-ir.js +2 -0
  26. package/dist/lib/model/diagram-ir.js.map +1 -0
  27. package/dist/lib/react/Diagram.d.ts +34 -0
  28. package/dist/lib/react/Diagram.d.ts.map +1 -0
  29. package/dist/lib/react/Diagram.js +56 -0
  30. package/dist/lib/react/Diagram.js.map +1 -0
  31. package/dist/lib/react/chrome/control-panel.d.ts +7 -0
  32. package/dist/lib/react/chrome/control-panel.d.ts.map +1 -0
  33. package/dist/lib/react/chrome/control-panel.js +63 -0
  34. package/dist/lib/react/chrome/control-panel.js.map +1 -0
  35. package/dist/lib/react/chrome/frame.d.ts +18 -0
  36. package/dist/lib/react/chrome/frame.d.ts.map +1 -0
  37. package/dist/lib/react/chrome/frame.js +432 -0
  38. package/dist/lib/react/chrome/frame.js.map +1 -0
  39. package/dist/lib/react/chrome/header.d.ts +6 -0
  40. package/dist/lib/react/chrome/header.d.ts.map +1 -0
  41. package/dist/lib/react/chrome/header.js +58 -0
  42. package/dist/lib/react/chrome/header.js.map +1 -0
  43. package/dist/lib/react/chrome/index.d.ts +5 -0
  44. package/dist/lib/react/chrome/index.d.ts.map +1 -0
  45. package/dist/lib/react/chrome/index.js +5 -0
  46. package/dist/lib/react/chrome/index.js.map +1 -0
  47. package/dist/lib/react/chrome/theme.d.ts +37 -0
  48. package/dist/lib/react/chrome/theme.d.ts.map +1 -0
  49. package/dist/lib/react/chrome/theme.js +66 -0
  50. package/dist/lib/react/chrome/theme.js.map +1 -0
  51. package/dist/lib/react/diagram-types.d.ts +87 -0
  52. package/dist/lib/react/diagram-types.d.ts.map +1 -0
  53. package/dist/lib/react/diagram-types.js +2 -0
  54. package/dist/lib/react/diagram-types.js.map +1 -0
  55. package/dist/lib/renderers/canvas/canvas-viewport.d.ts +11 -0
  56. package/dist/lib/renderers/canvas/canvas-viewport.d.ts.map +1 -0
  57. package/dist/lib/renderers/canvas/canvas-viewport.js +57 -0
  58. package/dist/lib/renderers/canvas/canvas-viewport.js.map +1 -0
  59. package/dist/lib/renderers/canvas/graph-canvas.d.ts +7 -0
  60. package/dist/lib/renderers/canvas/graph-canvas.d.ts.map +1 -0
  61. package/dist/lib/renderers/canvas/graph-canvas.js +397 -0
  62. package/dist/lib/renderers/canvas/graph-canvas.js.map +1 -0
  63. package/dist/lib/renderers/html/graph-html.d.ts +8 -0
  64. package/dist/lib/renderers/html/graph-html.d.ts.map +1 -0
  65. package/dist/lib/renderers/html/graph-html.js +1069 -0
  66. package/dist/lib/renderers/html/graph-html.js.map +1 -0
  67. package/dist/lib/renderers/shared/defs.d.ts +2 -0
  68. package/dist/lib/renderers/shared/defs.d.ts.map +1 -0
  69. package/dist/lib/renderers/shared/defs.js +158 -0
  70. package/dist/lib/renderers/shared/defs.js.map +1 -0
  71. package/dist/lib/renderers/shared/graph-parts.d.ts +53 -0
  72. package/dist/lib/renderers/shared/graph-parts.d.ts.map +1 -0
  73. package/dist/lib/renderers/shared/graph-parts.js +1601 -0
  74. package/dist/lib/renderers/shared/graph-parts.js.map +1 -0
  75. package/dist/lib/renderers/shared/node-content.d.ts +3 -0
  76. package/dist/lib/renderers/shared/node-content.d.ts.map +1 -0
  77. package/dist/lib/renderers/shared/node-content.js +6 -0
  78. package/dist/lib/renderers/shared/node-content.js.map +1 -0
  79. package/dist/lib/renderers/shared/node-parts.d.ts +36 -0
  80. package/dist/lib/renderers/shared/node-parts.d.ts.map +1 -0
  81. package/dist/lib/renderers/shared/node-parts.js +1206 -0
  82. package/dist/lib/renderers/shared/node-parts.js.map +1 -0
  83. package/dist/lib/renderers/shared/paper.d.ts +10 -0
  84. package/dist/lib/renderers/shared/paper.d.ts.map +1 -0
  85. package/dist/lib/renderers/shared/paper.js +131 -0
  86. package/dist/lib/renderers/shared/paper.js.map +1 -0
  87. package/dist/lib/renderers/shared/viewport-zoom.d.ts +4 -0
  88. package/dist/lib/renderers/shared/viewport-zoom.d.ts.map +1 -0
  89. package/dist/lib/renderers/shared/viewport-zoom.js +14 -0
  90. package/dist/lib/renderers/shared/viewport-zoom.js.map +1 -0
  91. package/dist/lib/renderers/svg/graph-svg.d.ts +10 -0
  92. package/dist/lib/renderers/svg/graph-svg.d.ts.map +1 -0
  93. package/dist/lib/renderers/svg/graph-svg.js +860 -0
  94. package/dist/lib/renderers/svg/graph-svg.js.map +1 -0
  95. package/dist/lib/renderers/svg/timeline-svg.d.ts +4 -0
  96. package/dist/lib/renderers/svg/timeline-svg.d.ts.map +1 -0
  97. package/dist/lib/renderers/svg/timeline-svg.js +1071 -0
  98. package/dist/lib/renderers/svg/timeline-svg.js.map +1 -0
  99. package/dist/lib/renderers/svg/viewport.d.ts +13 -0
  100. package/dist/lib/renderers/svg/viewport.d.ts.map +1 -0
  101. package/dist/lib/renderers/svg/viewport.js +48 -0
  102. package/dist/lib/renderers/svg/viewport.js.map +1 -0
  103. package/dist/lib/renderers/types.d.ts +18 -0
  104. package/dist/lib/renderers/types.d.ts.map +1 -0
  105. package/dist/lib/renderers/types.js +2 -0
  106. package/dist/lib/renderers/types.js.map +1 -0
  107. package/dist/lib/renderers/webgpu/flow-shader.d.ts +2 -0
  108. package/dist/lib/renderers/webgpu/flow-shader.d.ts.map +1 -0
  109. package/dist/lib/renderers/webgpu/flow-shader.js +67 -0
  110. package/dist/lib/renderers/webgpu/flow-shader.js.map +1 -0
  111. package/dist/lib/renderers/webgpu/graph-flow-effects.d.ts +22 -0
  112. package/dist/lib/renderers/webgpu/graph-flow-effects.d.ts.map +1 -0
  113. package/dist/lib/renderers/webgpu/graph-flow-effects.js +274 -0
  114. package/dist/lib/renderers/webgpu/graph-flow-effects.js.map +1 -0
  115. package/package.json +53 -4
  116. package/styles.css +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ezzabuzaid
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 CHANGED
@@ -1,3 +1,326 @@
1
- # Temporary Holding Version
1
+ # @zukhruf/diagram
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ React components that draw technical diagrams: the graph of a system, or the timeline of a protocol. You write a diagram as a tree of primitives, for example `Diagram.Box` and `Diagram.Arrow`. A renderer compiles the tree, calculates the layout, and draws it as SVG, on a canvas, or as HTML. The theme is a set of CSS variables, and the diagram can animate its parts and the flow on its edges.
4
+
5
+ The words in these documents have one meaning each. See the glossary in [CONTEXT.md](./CONTEXT.md).
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ npm i @zukhruf/diagram
11
+ ```
12
+
13
+ The peer dependencies are `react` 19, `motion` 12 and `tailwindcss` 4. The other dependencies, for example `vgpu` for the effects, install with the package.
14
+
15
+ ## Use it
16
+
17
+ Import the stylesheet in the Tailwind CSS file of the app, after Tailwind:
18
+
19
+ ```css
20
+ @import 'tailwindcss';
21
+ @import '@zukhruf/diagram/styles.css';
22
+ ```
23
+
24
+ Obey two rules:
25
+
26
+ - **Use a plain `@import`.** Do not write `@import '@zukhruf/diagram/styles.css' layer(components);`. A `layer()` puts all of the stylesheet into a layer, also its `@source` rule. Tailwind CSS refuses these rules in a layer.
27
+ - **Do not add an `@source` for the package.** The stylesheet registers its own `dist` folder. Tailwind CSS then finds the classes of the diagrams. See [ADR 0001](./docs/adr/0001-the-diagram-is-a-zukhruf-package.md).
28
+
29
+ Write the diagram with the primitives of `Diagram`, and give it to a renderer:
30
+
31
+ ```tsx
32
+ import { Diagram, SvgGraphDiagram } from '@zukhruf/diagram';
33
+
34
+ export function Checkout() {
35
+ return (
36
+ <SvgGraphDiagram title="Checkout" defaultMode="static">
37
+ <Diagram.Box id="web" row={0} col={0}>
38
+ Web app
39
+ </Diagram.Box>
40
+ <Diagram.Box id="api" row={0} col={1}>
41
+ API
42
+ </Diagram.Box>
43
+ <Diagram.Arrow from="web" to="api">
44
+ POST /orders
45
+ </Diagram.Arrow>
46
+ </SvgGraphDiagram>
47
+ );
48
+ }
49
+ ```
50
+
51
+ A timeline uses lanes and signals:
52
+
53
+ ```tsx
54
+ import { Diagram, SvgTimelineDiagram } from '@zukhruf/diagram';
55
+
56
+ export function Handshake() {
57
+ return (
58
+ <SvgTimelineDiagram title="Handshake" defaultMode="static">
59
+ <Diagram.Lane id="client">Client</Diagram.Lane>
60
+ <Diagram.Lane id="server">Server</Diagram.Lane>
61
+ <Diagram.Signal from="client" to="server">
62
+ hello
63
+ </Diagram.Signal>
64
+ <Diagram.Signal from="server" to="client" boxed>
65
+ session id
66
+ </Diagram.Signal>
67
+ </SvgTimelineDiagram>
68
+ );
69
+ }
70
+ ```
71
+
72
+ ## Renderers
73
+
74
+ Each renderer draws one layout to one output. The compiler of a renderer throws when it gets a primitive of the other layout.
75
+
76
+ | Renderer | Layout | Output | Notes |
77
+ | -------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
78
+ | `SvgGraphDiagram` | Graph | SVG | The only renderer that takes `effects`. |
79
+ | `SvgTimelineDiagram` | Timeline | SVG | One frame at most. |
80
+ | `CanvasGraphDiagram` | Graph | A canvas | The same props as `SvgGraphDiagram`, without `effects`. |
81
+ | `HtmlGraphDiagram` | Graph | HTML | The only renderer that draws `Diagram.Content`. It draws at natural size (one layout unit is one CSS pixel), and scrolls when the page is too narrow. |
82
+
83
+ ## Theme
84
+
85
+ The theme is the values of the `--dgm-*` CSS variables. The wrapper element of each diagram sets a light set of values, and a dark set with the `dark:` variant of Tailwind CSS. Thus the dark values follow the dark variant of the app. By default, that is the `prefers-color-scheme` media query. An app that sets `@custom-variant dark` uses its own rule, for example a `.dark` class.
86
+
87
+ | Variable | What it colors |
88
+ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
89
+ | `--dgm-bg` | The background of the diagram |
90
+ | `--dgm-surface-muted` | A muted surface, for example the `surface` paper |
91
+ | `--dgm-text` | The text |
92
+ | `--dgm-neutral` | Lines and text with no accent |
93
+ | `--dgm-dim` | Dim lines and dim text, and the status of the effects |
94
+ | `--dgm-lifeline` | The line of a lane |
95
+ | `--dgm-border` | The border of the paper |
96
+ | `--dgm-divider` | The lines of the control panel |
97
+ | `--dgm-hover` | The hover state of the control panel |
98
+ | `--dgm-dot` | The `dots` texture |
99
+ | `--dgm-hatch` | The `hatch` texture |
100
+ | `--dgm-accent-green` | The `green` accent |
101
+ | `--dgm-accent-primary` | The `primary` accent |
102
+ | `--dgm-accent-neutral` | The `neutral` accent |
103
+ | `--dgm-on-accent` | Text on an accent fill |
104
+ | `--dgm-tone-<tone>-fill`, `--dgm-tone-<tone>-stroke` | The fill and the border of each tone: `neutral`, `green`, `blue`, `amber`, `rose`, `purple`, `slate` |
105
+
106
+ The theme classes are utilities, so they are in `@layer utilities`. A rule outside of a layer wins over each rule in a layer (MDN, `@layer`). To change the theme, write a rule outside of a layer that selects the diagram:
107
+
108
+ ```css
109
+ @import 'tailwindcss';
110
+ @import '@zukhruf/diagram/styles.css';
111
+
112
+ [data-diagram-style-preset] {
113
+ --dgm-accent-primary: oklch(0.55 0.2 260);
114
+ }
115
+
116
+ .dark [data-diagram-style-preset] {
117
+ --dgm-accent-primary: oklch(0.7 0.15 260);
118
+ }
119
+ ```
120
+
121
+ Do not set the variables only on `:root`. The wrapper element sets its own values, and a value on an element wins over the value that it gets from `:root`.
122
+
123
+ Two props also change the look:
124
+
125
+ - `accent`: the highlight color. It is `green` (the default), `primary`, `neutral`, or a CSS color.
126
+ - `stylePreset`: `default`, or `sketch`. The `sketch` preset draws black ink on white, and makes each tone the same gray.
127
+
128
+ The SVG text uses the font `ui-monospace, 'Geist Mono', monospace`. The layout calculates the width of a label from the widths of a monospace font.
129
+
130
+ ## Effects
131
+
132
+ `SvgGraphDiagram` can draw pulses that move along its edges. Give it the `effects` prop:
133
+
134
+ - `effects="flow"`: the mode controls the pulses. In `reveal`, they move all the time. In `static`, they draw one time and do not move. In `scrub`, the scroll position moves them.
135
+ - `effects={{ flow }}`: `flow` is a `MotionValue<number>` that you control. From 0 to 1, a pulse goes along the first edge. From 1 to 2, a pulse goes along the second edge, and so on, in the order of the edges in the tree. An integer value clears the pulses. You control the timing, the pauses and the stops.
136
+
137
+ An edge with no arrowhead (`Wire`, `headless`, or `direction="none"`) gets no pulse.
138
+
139
+ The effects draw with WebGPU, on a canvas above the SVG. The package loads `vgpu` with a dynamic `import()` only when a diagram has `effects`. Thus a diagram with no `effects` adds no WebGPU code to the bundle.
140
+
141
+ The SVG drawing is always there. The effects only add to it:
142
+
143
+ - When the browser has no WebGPU, or the GPU device fails, the canvas hides. A status line shows the text "Flow animation is unavailable in this browser."
144
+ - When the user prefers reduced motion, the canvas hides, and the effects do not draw.
145
+ - When the diagram is not in view, or the page is hidden, the effects pause.
146
+
147
+ The canvas has the attribute `data-diagram-effects-status`. Its value is `initializing`, `empty`, `paused`, `controlled`, `static`, `reveal`, `scrub`, `reduced-motion` or `unavailable`. A test or a debug tool can read it.
148
+
149
+ ## API
150
+
151
+ The source of truth is `src/lib/react/Diagram.tsx`, `src/lib/react/diagram-types.ts` and `src/lib/model/diagram-ir.ts`. Read the types when a prop seems to be missing.
152
+
153
+ ### Layouts
154
+
155
+ The renderer sets the layout. `SvgGraphDiagram`, `CanvasGraphDiagram` and `HtmlGraphDiagram` draw a **graph**. `SvgTimelineDiagram` draws a **timeline**.
156
+
157
+ - **Graph primitives:** `Node`, `Box`, `Card`, `Port`, `Label`, `Float`, `Phantom`, `Marker`, `Appliance`, `Connector`, `Junction`, `Edge`, `Arrow`, `Wire`, `Group`, `Guide`, `Text`, `Note`.
158
+ - **Timeline primitives:** `Lane`, `Signal`, `Frame`.
159
+
160
+ `Line` makes a label with more than one line, in both layouts. `Content` goes into a `Box`, a `Card` or a `Node`, one time. `Waypoint`, `Entry` and `Exit` go into an edge.
161
+
162
+ ### Timeline primitives
163
+
164
+ | Primitive | What it is | Required props | Optional props |
165
+ | ---------------- | ------------------------------------------------ | -------------- | -------------------------------------------------------------------------------------- |
166
+ | `Diagram.Lane` | The vertical line of one actor | `id` | `accent` |
167
+ | `Diagram.Signal` | A horizontal arrow from one lane to another lane | `from`, `to` | `accent`, `dim`, `boxed`, `stub`, `bordered`, `filled` |
168
+ | `Diagram.Frame` | A labeled rectangle around some signals | `label` | Its children must be signals. A timeline has one frame at most; a second frame throws. |
169
+
170
+ The label of a lane or a signal is its text children.
171
+
172
+ #### `Signal.boxed`
173
+
174
+ A boxed signal puts its label in a box on the line.
175
+
176
+ - `boxed` is `true`, or the position of the box: `'source'`, `'center'` or `'target'`. `true` is `'source'`.
177
+ - `stub` is the gap between the line of the lane and the edge of the box. The default is 12.
178
+ - `bordered` draws the border of the box in the color of the signal. The default is `true`.
179
+ - `filled` fills the box. The default is `true`. With `false`, the box is transparent, and it has no dots.
180
+
181
+ The layout splits the line into two stubs. The stub at the source has no arrowhead. The stub at the target has the arrowhead. When the box is wider than the distance between the lanes, the layout throws.
182
+
183
+ ### Graph primitives
184
+
185
+ Each node has an `id`, and a `row` and a `col` in the grid. `colSpan`, `width` and `height` change its size.
186
+
187
+ | Primitive | What it is | Default frame | Notes |
188
+ | ------------------- | ----------------------------------------------------------- | ------------- | --------------------------------------------------------------------- |
189
+ | `Diagram.Node` | The general node | `solid` | Prefer `Box` or `Card`. |
190
+ | `Diagram.Box` | A node with a solid border and centered text | `solid` | The usual node. |
191
+ | `Diagram.Card` | A node with a solid border and text that starts at the left | `solid` | For a node with a `description` or `items`. |
192
+ | `Diagram.Port` | A node with no header | `transparent` | Often holds a set of labels under a box. |
193
+ | `Diagram.Label` | Text at a grid position | `none` | For a section title or the label of an axis. |
194
+ | `Diagram.Float` | A flat node | `flat` | An edge cannot attach to it. |
195
+ | `Diagram.Phantom` | A node that is not visible | `none` | An edge can attach to it. Use it to make an edge go through one cell. |
196
+ | `Diagram.Marker` | A node with an `icon`, for example `server` or `user` | `none` | The icon is required. |
197
+ | `Diagram.Appliance` | A hardware device | `none` | `appliancePorts`, `antenna` and `slant` change the drawing. |
198
+ | `Diagram.Connector` | A small node with round corners and an optional `icon` | `solid` | The default size is 148 × 40. |
199
+ | `Diagram.Junction` | A small circle where edges meet | `none` | The default size is 16 × 16. |
200
+
201
+ Other props of a node:
202
+
203
+ - `tone`, `texture` and `accent` set its colors.
204
+ - `caption` puts text next to the node, on the side that `captionSide` sets.
205
+ - `ports` gives node ports: named points on a side, where an edge can attach.
206
+ - `stack` draws copies of the frame behind the node, for a set of equal items.
207
+
208
+ ### Edges
209
+
210
+ | Primitive | What it is | Arrowhead | Use it |
211
+ | --------------- | ----------------------------------------- | ------------- | -------------------------------------------------- |
212
+ | `Diagram.Arrow` | An edge with an arrowhead at the target | Yes | For "X calls Y" and "X depends on Y". |
213
+ | `Diagram.Wire` | An edge with no arrowhead | No | When the direction is clear or the same both ways. |
214
+ | `Diagram.Edge` | The general edge; set `headless` yourself | You select it | Prefer `Arrow` or `Wire`. |
215
+
216
+ The required props are `from` and `to`. Other props: `lineStyle` (`solid`, `dashed`, `dotted`), `direction` (`forward`, `both`, `none`), `route` (`orthogonal`, `straight`), `dim`, `accent`, the `label*` props, and the `badge*` props for an icon on the edge.
217
+
218
+ An edge accepts these children: text and `Diagram.Line` for its label, and `Diagram.Entry`, `Diagram.Exit` and `Diagram.Waypoint`.
219
+
220
+ ### Groups
221
+
222
+ `Diagram.Group` draws a rectangle around a set of nodes. Put the nodes in it as children, or give each node a `group` prop.
223
+
224
+ The required prop is `id`. The optional props are `label`, `accent`, `tone`, `texture`, `rx` (the corner radius), `tight` (bounds that fit the nodes closely), `padding`, `dividers`, `frame` (`solid`, `dashed`, `none`), and `rowStart`, `rowEnd`, `colStart`, `colEnd` (the bounds). When you do not give the bounds, the compiler calculates them from the rows and columns of the nodes.
225
+
226
+ ### Edge routing
227
+
228
+ | Primitive | What it does |
229
+ | ------------------ | --------------------------------------------------------------------------------------- |
230
+ | `Diagram.Entry` | Sets the side of the target where the edge goes in: `top`, `right`, `bottom` or `left`. |
231
+ | `Diagram.Exit` | Sets the side of the source where the edge goes out. |
232
+ | `Diagram.Waypoint` | Gives a point that the edge goes through: `{ x, y }`, a grid cell, a guide, or a node. |
233
+
234
+ Use them when the router draws a crossing, or draws an edge around a node.
235
+
236
+ The router in `src/lib/layouts/graph/graph-layout.ts` does these things:
237
+
238
+ - A self-edge (`from` is the same as `to`) is a loop around the node. The default loop is above the node. `Exit` and `Entry` can select a different side.
239
+ - Two edges in the same row that go in opposite directions get two lanes. For example, `running → paused` stays direct, and `paused → running` goes below the nodes.
240
+ - An edge in the same row that goes from right to left goes below the row, not across the top of the row.
241
+ - Return edges from the same source to the same side get different corridors. A longer return, for example `paused → idle`, goes deeper than a shorter return, for example `paused → running`.
242
+ - The router puts each edge label from the geometry of its path.
243
+
244
+ When the default paths still cross, use `Entry`, `Exit` and `Waypoint`. When the problem is general, fix the router instead. See [the internals](./docs/internals.md).
245
+
246
+ ### Primitives for both layouts
247
+
248
+ | Primitive | What it is |
249
+ | ----------------- | ---------------------------------------------------------------------------------------------- |
250
+ | `Diagram.Text` | A free annotation: `{ x, y }`, or next to a `target` node, with an optional leader line. |
251
+ | `Diagram.Note` | The same as `Diagram.Text`. |
252
+ | `Diagram.Line` | One line of a label with more than one line. It goes into a lane, a signal, a node or an edge. |
253
+ | `Diagram.Guide` | A vertical or horizontal line that helps to align things. |
254
+ | `Diagram.Content` | Real React content in a `Box`, a `Card` or a `Node`. Only `HtmlGraphDiagram` draws it. |
255
+
256
+ ### Labels
257
+
258
+ A label has one of two shapes:
259
+
260
+ - A text child: a label with one line.
261
+ - One or more `Diagram.Line` children: a label with more than one line.
262
+
263
+ `Diagram.Line` accepts `textColor` (`accent`, `neutral`, `dim`) and `fontWeight`, so each line can have its own look. The compiler removes text that is only white space.
264
+
265
+ ### The rules for children
266
+
267
+ The compiler checks the children, and it throws with a clear message:
268
+
269
+ - A renderer accepts only primitives as children.
270
+ - A React fragment (`<>…</>`) throws. Write the primitives directly, or give an array of primitives.
271
+ - A different component, for example `<MyHelper />`, throws with the name of the component.
272
+ - A lane, a signal, an edge and a frame accept only their own children: text, `Line`, `Entry`, `Exit` and `Waypoint`, and `Signal` in a frame.
273
+ - A duplicate `id` of a node, a group, a guide or a lane throws, with the id in the message.
274
+ - An edge to a missing `from` or `to` throws, with both ends in the message.
275
+
276
+ ### Renderer props
277
+
278
+ Each renderer takes these props:
279
+
280
+ | Prop | Type | Default | What it does |
281
+ | ------------- | ------------------------------------ | -------------- | -------------------------------------------------------------------------------------- |
282
+ | `title` | `string \| string[]` | Required | The title. Each string is one line. |
283
+ | `children` | Primitives | Required | The diagram. |
284
+ | `defaultMode` | `'static' \| 'reveal' \| 'scrub'` | `'reveal'` | The first mode. A user that prefers reduced motion always gets `static`. |
285
+ | `controls` | `boolean` | `false` | Shows the control panel, in which the user selects the mode. |
286
+ | `showHeader` | `boolean` | `true` | Shows the header with the title and the corner. |
287
+ | `corner` | `ReactNode` | | A slot at the corner of the header, for example a logo. |
288
+ | `accent` | `DiagramAccent` | `'green'` | The highlight color. |
289
+ | `stylePreset` | `'default' \| 'sketch'` | `'default'` | The style preset. |
290
+ | `className` | `string` | | Classes for the wrapper element, for example the width in the grid of a page. |
291
+ | `viewport` | `{ fit?, zoom? }` | `fit: 'width'` | How the drawing fits its container: `width`, `contain` or `natural`. `zoom` scales it. |
292
+ | `paper` | `boolean \| { fill?, stroke?, rx? }` | | A rectangle behind the drawing. `fill` is `background` or `surface`. |
293
+
294
+ The graph renderers also take `graph`: the size of the columns and rows, and the padding. `HtmlGraphDiagram` takes `viewport.zoom`, but not `viewport.fit`. Only `SvgGraphDiagram` takes `effects`.
295
+
296
+ The package does not set the width of a diagram on a page. Give the classes of your page layout with `className`.
297
+
298
+ ## Documentation
299
+
300
+ - **Internals**: [docs/internals.md](./docs/internals.md) tells how the compiler, the layouts and the renderers divide the work, and which mistakes the code had before.
301
+ - **Copied code**: [docs/copied-code.md](./docs/copied-code.md) lists the code that is in two places, and where each fix must go.
302
+ - **Decisions**: the [architecture decision records](./docs/adr) tell why the design is as it is.
303
+ 1. [The diagram is a zukhruf package](./docs/adr/0001-the-diagram-is-a-zukhruf-package.md)
304
+
305
+ ## Development
306
+
307
+ This package is part of the [zukhruf](../../README.md) workspace. Run the commands from the workspace root.
308
+
309
+ ```sh
310
+ npm install
311
+ npx nx run diagram:test # builds, then runs the tests
312
+ npx nx run diagram:typecheck # formats, lints, then type checks
313
+ npx nx run diagram:build # compiles src/ to dist/ with the React Compiler
314
+ npx nx run diagram:lint # lints the code
315
+ ```
316
+
317
+ ```
318
+ src/
319
+ lib/model/ the IR types
320
+ lib/compiler/ reads the primitives, and makes the IR
321
+ lib/layouts/ the pure geometry of the graph and the timeline
322
+ lib/renderers/ svg/, canvas/, html/ and webgpu/ draw the layouts; shared/ holds the parts that they share
323
+ lib/react/ the Diagram primitives and the chrome
324
+ index.ts the entry
325
+ styles.css registers dist with @source
326
+ ```
@@ -0,0 +1,8 @@
1
+ export { Diagram, type DiagramAccent, type DiagramApplianceProps, type DiagramConnectorProps, type DiagramContentProps, type DiagramEdgeProps, type DiagramEffects, type DiagramEntryProps, type DiagramExitProps, type DiagramFrameProps, type DiagramGroupProps, type DiagramGuideProps, type DiagramJunctionProps, type DiagramLaneProps, type DiagramLineProps, type DiagramMarkerProps, type DiagramMode, type DiagramNodeProps, type DiagramPaper, type DiagramPhantomProps, type DiagramProps, type DiagramSignalProps, type DiagramStackDirection, type DiagramStylePreset, type DiagramTextProps, type DiagramViewport, type DiagramWaypointProps, } from './lib/react/Diagram.tsx';
2
+ export { SvgGraphDiagram, type SvgGraphDiagramProps, } from './lib/renderers/svg/graph-svg.tsx';
3
+ export { SvgTimelineDiagram, type SvgTimelineDiagramProps, } from './lib/renderers/svg/timeline-svg.tsx';
4
+ export { CanvasGraphDiagram, type CanvasGraphDiagramProps, } from './lib/renderers/canvas/graph-canvas.tsx';
5
+ export { HtmlGraphDiagram, type HtmlGraphDiagramProps, } from './lib/renderers/html/graph-html.tsx';
6
+ export type { Box, DiagramAnchor, DiagramAnnotation, DiagramEdge, DiagramEdgeDirection, DiagramEdgeLabelSide, DiagramEdgeLineStyle, DiagramFrameElement, DiagramGraphIR, DiagramGraphLayout, DiagramGroup, DiagramGuide, DiagramLabelLine, DiagramLane, DiagramMarker, DiagramNode, DiagramNodeIcon, DiagramNodePort, DiagramSide, DiagramSignal, DiagramTextColor, DiagramTextAlign, DiagramTexture, DiagramTimelineSpec, DiagramTone, DiagramViewportFit, Point, } from './lib/model/diagram-ir.ts';
7
+ export type { DiagramFontFace } from './lib/layouts/text-metrics.ts';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,oBAAoB,GAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,GAAG,EACH,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,WAAW,EACX,eAAe,EACf,eAAe,EACf,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,KAAK,GACN,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { Diagram } from "./lib/react/Diagram.js";
2
+ export { SvgGraphDiagram } from "./lib/renderers/svg/graph-svg.js";
3
+ export { SvgTimelineDiagram } from "./lib/renderers/svg/timeline-svg.js";
4
+ export { CanvasGraphDiagram } from "./lib/renderers/canvas/graph-canvas.js";
5
+ export { HtmlGraphDiagram } from "./lib/renderers/html/graph-html.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["Diagram","SvgGraphDiagram","SvgTimelineDiagram","CanvasGraphDiagram","HtmlGraphDiagram"],"sources":["../src/index.ts"],"sourcesContent":["export {\n Diagram,\n type DiagramAccent,\n type DiagramApplianceProps,\n type DiagramConnectorProps,\n type DiagramContentProps,\n type DiagramEdgeProps,\n type DiagramEffects,\n type DiagramEntryProps,\n type DiagramExitProps,\n type DiagramFrameProps,\n type DiagramGroupProps,\n type DiagramGuideProps,\n type DiagramJunctionProps,\n type DiagramLaneProps,\n type DiagramLineProps,\n type DiagramMarkerProps,\n type DiagramMode,\n type DiagramNodeProps,\n type DiagramPaper,\n type DiagramPhantomProps,\n type DiagramProps,\n type DiagramSignalProps,\n type DiagramStackDirection,\n type DiagramStylePreset,\n type DiagramTextProps,\n type DiagramViewport,\n type DiagramWaypointProps,\n} from './lib/react/Diagram.tsx';\nexport {\n SvgGraphDiagram,\n type SvgGraphDiagramProps,\n} from './lib/renderers/svg/graph-svg.tsx';\nexport {\n SvgTimelineDiagram,\n type SvgTimelineDiagramProps,\n} from './lib/renderers/svg/timeline-svg.tsx';\nexport {\n CanvasGraphDiagram,\n type CanvasGraphDiagramProps,\n} from './lib/renderers/canvas/graph-canvas.tsx';\nexport {\n HtmlGraphDiagram,\n type HtmlGraphDiagramProps,\n} from './lib/renderers/html/graph-html.tsx';\nexport type {\n Box,\n DiagramAnchor,\n DiagramAnnotation,\n DiagramEdge,\n DiagramEdgeDirection,\n DiagramEdgeLabelSide,\n DiagramEdgeLineStyle,\n DiagramFrameElement,\n DiagramGraphIR,\n DiagramGraphLayout,\n DiagramGroup,\n DiagramGuide,\n DiagramLabelLine,\n DiagramLane,\n DiagramMarker,\n DiagramNode,\n DiagramNodeIcon,\n DiagramNodePort,\n DiagramSide,\n DiagramSignal,\n DiagramTextColor,\n DiagramTextAlign,\n DiagramTexture,\n DiagramTimelineSpec,\n DiagramTone,\n DiagramViewportFit,\n Point,\n} from './lib/model/diagram-ir.ts';\nexport type { DiagramFontFace } from './lib/layouts/text-metrics.ts';\n"],"mappings":"AAAA,SACEA,OAAO,QA2BF,wBAAyB;AAChC,SACEC,eAAe,QAEV,kCAAmC;AAC1C,SACEC,kBAAkB,QAEb,qCAAsC;AAC7C,SACEC,kBAAkB,QAEb,wCAAyC;AAChD,SACEC,gBAAgB,QAEX,oCAAqC","ignoreList":[]}
@@ -0,0 +1,16 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { DiagramGraphIR, DiagramGraphLayout, DiagramTimelineSpec } from '../model/diagram-ir.ts';
3
+ export declare const DIAGRAM_PRIMITIVE: unique symbol;
4
+ declare const PRIMITIVE_KINDS: readonly ["node", "box", "card", "port", "label", "float", "phantom", "appliance", "connector", "junction", "edge", "arrow", "wire", "group", "text", "line", "lane", "signal", "frame", "marker", "guide", "waypoint", "entry", "exit", "content"];
5
+ export type PrimitiveKind = (typeof PRIMITIVE_KINDS)[number];
6
+ export type PrimitiveComponent<P> = ((props: P) => null) & {
7
+ [DIAGRAM_PRIMITIVE]: PrimitiveKind;
8
+ };
9
+ export declare function primitive<P>(kind: PrimitiveKind): PrimitiveComponent<P>;
10
+ export declare function primitiveKind(node: ReactNode): PrimitiveKind | null;
11
+ export declare function compileGraph(children: ReactNode, layout: DiagramGraphLayout | undefined): DiagramGraphIR;
12
+ export declare function compileTimeline(children: ReactNode): DiagramTimelineSpec;
13
+ export declare function validateGraph(ir: DiagramGraphIR): void;
14
+ export declare function validateTimeline(ir: DiagramTimelineSpec): void;
15
+ export {};
16
+ //# sourceMappingURL=diagram-compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagram-compile.d.ts","sourceRoot":"","sources":["../../../src/lib/compiler/diagram-compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAIV,cAAc,EACd,kBAAkB,EAOlB,mBAAmB,EAEpB,MAAM,wBAAwB,CAAC;AAsBhC,eAAO,MAAM,iBAAiB,eAA2C,CAAC;AAE1E,QAAA,MAAM,eAAe,qPA0BX,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG;IACzD,CAAC,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACpC,CAAC;AAEF,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAEvE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,aAAa,GAAG,IAAI,CAMnE;AA6CD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,kBAAkB,GAAG,SAAS,GACrC,cAAc,CAmBhB;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,GAAG,mBAAmB,CAkBxE;AA0mBD,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,QA4I/C;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,mBAAmB,QAoBvD"}