@graphlearning/graphl-flow 0.8.0 → 0.10.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/README.md CHANGED
@@ -3,8 +3,9 @@
3
3
  Declarative architecture diagrams for React. Describe **groups**, **items** and **edges**; the
4
4
  browser lays them out and the engine draws the arrows. Scenes never contain x/y.
5
5
 
6
- > 0.1.0 — seven node types (`group`, `item`, `table`, `code`, `plot`, `tree`, `note`), edges,
6
+ > 0.9.0 — eight node types (`group`, `item`, `table`, `code`, `plot`, `tree`, `note`, `tty`), edges,
7
7
  > two themes, fit-to-frame for 4K recording. Content repos pin a version and upgrade deliberately.
8
+ > Maintainer rules: `CLAUDE.md`; their history: `docs/DECISIONS.md`; workspace: `../CLAUDE.md`.
8
9
 
9
10
  ## Install
10
11
 
@@ -35,6 +36,62 @@ const scene: SceneModel = {
35
36
  </div>
36
37
  ```
37
38
 
39
+ ## Model
40
+
41
+ | Type | Fields |
42
+ |---------|--------|
43
+ | `item` | `id`, `title`, `muted?`, `sub?`, `icon?`, `bullets?`, `stack?`, `chip?`, `tone?`, `span?` |
44
+ | `group` | `id`, `children`, `title?`, `sub?`, `icon?`, `badge?`, `dir?: 'row' \| 'col' \| 'grid'`, `cols?`, `bare?`, `dashed?`, `muted?`, `spread?`, `cell?: number \| true`, `tone?`, `span?` |
45
+ | `table` | `id`, `rows`, `columns?`, `title?`, `tone?`, `span?` — a row is `[cells…]` or `{ cells, id?, tag?, tone? }` |
46
+ | `code` | `id`, `code`, `lang?`, `filename?`, `show?: [from, to][]`, `highlight?: number[]`, `terminal?`, `output?`, `console?`, `cols?`, `wrap?`, `tone?`, `span?` — `wrap` soft-wraps a long editor line under its own text |
47
+ | `tty` | `id`, `screen: string[]`, `title?`, `cols?`, `inverse?`, `bold?` (`[row, from, to][]`) — a full-screen program's grid |
48
+ | `plot` | `id`, `x`, `y` (axes: `min`, `max`, `step?`, `label?`, or `labels` for categories), `series`, `title?`, `axes?`, `grid?`, `compact?` — with `w`, the plot is that wide and its drawing area takes what the gutters leave |
49
+ | `tree` | `id`, `entries` (`name`, `children?`, `folder?`, `state?: active \| new \| muted`, `note?`, `icon?`), `title?`, `compact?` (13px rows: a sidebar beside a code pane) |
50
+ | `note` | `id`, `text`, `tone?` — a dashed callout of wrapping prose |
51
+ | any node | `minW?`/`minH?` (floors), `maxW?`/`maxH?` (caps), `w?`/`h?` (exact), `fill?`, `span?`, `tone?`; groups also `bare?` |
52
+ | `Edge` | `from`, `to` (a node id; a table row `table.row`; a code line `code.L12`; a tree entry `tree.src/a.py`; a tty row `top.R7`), `label?`, `dashed?`, `bidirectional?` |
53
+ | `Scene` | `nodes`, `edges?`, `title?`, `sub?`, `dir?`, `pulse?`, `padding?` (the fit's margin per side, 0–0.2, default 0.04) |
54
+
55
+ **Layout.** A group lays its children out as `dir: 'col'` (default), `'row'` (one column per child)
56
+ or `'grid'` (`cols`, default 2). `span: 'all'` gives a child a full row — a rail under columns.
57
+ Siblings in a row stretch to equal height.
58
+
59
+ **Tone** sets what a box means and is inherited by everything inside it:
60
+
61
+ | tone | hue | | tone | hue |
62
+ |---|---|---|---|---|
63
+ | `neutral` | grey | | `serve` | violet |
64
+ | `source` | slate | | `consume` | red |
65
+ | `ingest` | blue | | `infra` | orange |
66
+ | `store` | green | | | |
67
+
68
+ The theme (`dark` | `light`) picks the shade; repos cannot recolour.
69
+
70
+ ## Group and item looks
71
+
72
+ **`dashed: true`** draws a group's frame dashed — a boundary that is a PLACE, not a thing (an AWS
73
+ Region or Availability Zone, as AWS's own diagrams draw them). Only the line style changes, so
74
+ dashing a group never moves anything.
75
+
76
+ **`spread: true`** on a group spaces its children evenly over its full height when the group is
77
+ stretched taller than them (a short column beside a tall one).
78
+
79
+ **`muted: true`** draws an item greyed, or a group as a plain grey outline — a part the system does
80
+ not have yet, at its full size and place (paint only, so muting moves nothing; a muted group does not
81
+ dim its children). An architecture that grows course by course draws its
82
+ whole final shape from the start.
83
+
84
+ **`chip: true`** draws an item as a small framed pill — a thing counted, not described (`Task 1`,
85
+ `Local disk`); chips fill their grid cell, so a row of them lines up.
86
+
87
+ A nested group is a plain card, unless it names its OWN `tone` — then it is a coloured column again
88
+ (the Spark study's four columns, and its green worker nodes inside the orange Worker column).
89
+
90
+ **`stack: true`** puts an item's icon on top with the text centred under it — a card in a column of
91
+ peers (the Business Consumers column).
92
+
93
+ ## Edges
94
+
38
95
  **Edges** connect any two nodes by id — items or groups, at any depth — as right-angle arrows.
39
96
  An edge leaves across the larger gap between the two columns (or rows) it connects, so it stays in
40
97
  the gaps rather than cutting through a neighbour; ends that face each other connect straight. A face with several edges gives each its
@@ -47,14 +104,11 @@ That period is the recorder's loop (`PULSE_S` in `@graphlearning/shell`'s record
47
104
  video has no jump at the join. `pulse: false` on a scene turns it off. `npm run capture` freezes the
48
105
  animation at t = 0, so stills are reproducible.
49
106
 
50
- **`dashed: true`** draws a group's frame dashed — a boundary that is a PLACE, not a thing (an AWS
51
- Region or Availability Zone, as AWS's own diagrams draw them). Only the line style changes, so
52
- dashing a group never moves anything.
107
+ An edge to an id the scene doesn't have logs a console error naming it.
53
108
 
54
- **`spread: true`** on a group spaces its children evenly over its full height when the group is
55
- stretched taller than them (a short column beside a tall one).
109
+ ## Tables and memory
56
110
 
57
- **Tables and memory.** A `table` is a DB schema, a stack frame, a heap object, an array or a hash
111
+ A `table` is a DB schema, a stack frame, a heap object, an array or a hash
58
112
  map's buckets. Every row is addressable as `<table id>.<first cell>` (or `.<id>` when you set one), so
59
113
  a pointer is just an edge: `{ from: 'main.nums', to: 'list' }`. There is no memory node type —
60
114
  stack and heap are groups of tables:
@@ -71,6 +125,8 @@ A row connects through its left or right end only. Lay a pointer's target BESIDE
71
125
  column), not below it — an edge is routed in the gap between two siblings, never around a third.
72
126
  `tag` draws a short pill before a row (`PK`, `FK`, `sp`); `tone` on a row tints it.
73
127
 
128
+ ## Code, consoles and screens
129
+
74
130
  **Code.** `code` takes the source as a (template-literal) string; its common indent is dropped.
75
131
  `lang` is `python | sql | scala | java | js | ts | shell | hcl | ini | nginx | nft | text` — one small highlighter with seven
76
132
  token colours per theme, sharing one keyword set (Java's primitive types, `record`, `sealed` and
@@ -103,37 +159,49 @@ A full-screen program is a **`tty`**: `screen` (its rows), `cols?` (80), `invers
103
159
  as `[row, from, to)` — a fixed grid, padded to `cols`, so two captures of `top` are the same box.
104
160
  Its rows are `tty.R<n>`.
105
161
 
106
- **Console frames (0.7).** Two columns, both FIXED: the console (or a `tty` in its slot, same `w`/`h`) |
107
- the PICTURE of what it just showed — a `bare` group of the rest of 16:9. No edges between them; ring
108
- the console line with `focus`. See `dev/fixtures/studies/console-frame.ts`.
162
+ ## Charts
109
163
 
110
- **IDE frames.** Three columns: `tree` | (editor `code` over terminal `code`, in a `bare` group) |
111
- a SIDE PANE — a `bare` group with a fixed width `w`. The IDE alone is narrower than 16:9; the side
112
- pane fills the frame and holds whatever the moment needs (a `note`, a `compact` plot, a small memory
113
- diagram) or nothing. See `dev/fixtures/studies/ide-frame.ts`.
164
+ A `plot`'s x/y values are DATA in the axes' own units — sample curves in the scene
165
+ file. A series is `line | scatter | area | bar | segment`. Every plot's drawing area is the same
166
+ fixed size, so charts line up across a deck. Series take the next colour of a fixed ramp
167
+ (blue, orange, violet, green) unless given a `tone`. A `segment` is a dashed construction or threshold
168
+ line — muted grey unless toned, solid with `dashed: false`, a vector with `arrow: true`. Bars label
169
+ themselves in a legend; other series label their last point.
170
+
171
+ ## Frames
172
+
173
+ Recipes for whole video frames; each has a study fixture.
174
+
175
+ **One grid (0.10).** Every IDE, notebook and console frame is 1344×756 (16:9) with
176
+ `padding: 0.01`, every column a fixed `w` with a full-height floor, so they all land on ONE fit
177
+ (about 42px code in the 4K frame) and `check` asserts it (`SAME_FIT`).
114
178
 
115
- **Notebook frames.** The same three columns with a notebook in the middle: `tree` | a group (the
116
- notebook: `title: 'explore.ipynb'`, `icon: 'jupyter'`) of CELLS | the fixed side pane. A cell is a
179
+ **IDE frames.** `tree` (`compact`, 175) | editor `code` (`wrap`) over terminal `code`, in a `bare`
180
+ group (715: 72 columns) | a SIDE PANE (434): a group titled with the moment's mental model, `spread`,
181
+ holding a diagram (a memory diagram, a plot with `w`, a result table). Two variants of one height: a
182
+ tall editor over a short terminal, or the reverse. Without the explorer the side pane takes its
183
+ column (619), so the frame still fills 16:9. See `dev/fixtures/studies/ide-frame.ts`.
184
+
185
+ **Notebook frames.** The same columns with a notebook in the middle: `tree` | a group (the
186
+ notebook: `title: 'explore.ipynb'`, `icon: 'jupyter'`) of CELLS | the side pane. A cell is a
117
187
  `group` with `cell: n`, the execution count drawn as `[n]` in a gutter (`cell: true` draws `[ ]`, not
118
188
  run yet). Its first child is the input `code` (drawn without a tab bar, stretched to the cell),
119
189
  followed by its outputs: `{ type: 'code', output: true }` for printed text (`! ` lines are errors), a
120
190
  `table` for a DataFrame, or a `plot`. See `dev/fixtures/studies/notebook-frame.ts`.
121
191
 
192
+ **Console frames.** Two columns: the console (760: 80 columns, 29 rows; or a `tty` in its slot, same
193
+ `w`/`h`) | the PICTURE of what it just showed — a `bare`, `spread` group of the rest (574). No edges
194
+ between them; ring the console line with `focus`. See `dev/fixtures/studies/console-frame.ts`.
195
+
122
196
  `minW`/`minH` are FLOORS and `maxW`/`maxH` CAPS, in the scene's own pixels; `w`/`h` set both. Give
123
197
  every frame of a video the same floors and a fixed side pane, and they get the same zoom: no pane
124
198
  moves between cuts, whatever the side pane holds. Prose wraps to the pane; tables and code do not,
125
- so keep them narrow. A plot never scales — use `compact: true` (a 420×280 area) in a side pane.
199
+ so keep them narrow. A plot never scales — use `compact: true` (a 420×280 area) in a side pane, or
200
+ `compact` with a `w` to fit a narrower column.
126
201
  Don't draw an edge between the IDE's columns: an arrow widens the gap it crosses and moves every
127
202
  pane. Point at code with `highlight` and the narration; edges INSIDE the side pane are fine.
128
203
 
129
- **Charts.** A `plot`'s x/y values are DATA in the axes' own units — sample curves in the scene
130
- file. A series is `line | scatter | area | bar | segment`. Every plot's drawing area is the same
131
- fixed size, so charts line up across a deck. Series take the next colour of a fixed ramp
132
- (blue, orange, violet, green) unless given a `tone`. A `segment` is a dashed construction or threshold
133
- line — muted grey unless toned, solid with `dashed: false`, a vector with `arrow: true`. Bars label
134
- themselves in a legend; other series label their last point.
135
-
136
- An edge to an id the scene doesn't have logs a console error naming it.
204
+ ## Rendering: legibility, focus, fit, recording
137
205
 
138
206
  **Legibility on video.** The fit scales the whole scene to the frame, so what decides how big text
139
207
  looks is how WIDE the scene is for the text it holds — not the font size. Item text wraps at a
@@ -146,7 +214,9 @@ diagram hits that, split the slide or trim bullets — a denser scene can only g
146
214
  line included — with a ring and a glow in its own tone. It is drawn with box-shadow, so it moves
147
215
  nothing: every section of a course can focus a different node on the same scene without a jump.
148
216
 
149
- **Fit.** `Scene` fills its parent and scales the scene to fit, centred, with a 4% margin. The scale
217
+ **Fit.** `Scene` fills its parent and scales the scene to fit, centred, with a 4% margin per side —
218
+ or the scene's own `padding` (a fraction, 0–0.2): a fixed frame template already shaped to the pane
219
+ sets `padding: 0.01` to fill the recording. The scale
150
220
  depends only on the parent's size and the scene's natural size, so the same scene in the same frame
151
221
  always lands on the same pixels. The view is locked (no zoom/pan); page scroll passes through and text
152
222
  stays selectable. The root carries `data-fit="ready"` once fonts have loaded, edges are routed and the fit is applied —
@@ -156,38 +226,9 @@ wait on it before recording.
156
226
  `@graphlearning/shell`'s recorders use. In this repo: `npm run capture -- <fixtureId> --theme dark`
157
227
  writes `captures/<id>-<theme>.png`.
158
228
 
159
- ## Model
160
-
161
- | Type | Fields |
162
- |---------|--------|
163
- | `item` | `id`, `title`, `muted?`, `sub?`, `icon?`, `bullets?`, `stack?`, `chip?`, `tone?`, `span?` |
164
- | `group` | `id`, `children`, `title?`, `sub?`, `icon?`, `badge?`, `dir?: 'row' \| 'col' \| 'grid'`, `cols?`, `bare?`, `dashed?`, `muted?`, `spread?`, `cell?: number \| true`, `tone?`, `span?` |
165
- | `table` | `id`, `rows`, `columns?`, `title?`, `tone?`, `span?` — a row is `[cells…]` or `{ cells, id?, tag?, tone? }` |
166
- | `code` | `id`, `code`, `lang?`, `filename?`, `show?: [from, to][]`, `highlight?: number[]`, `terminal?`, `output?`, `console?`, `cols?`, `tone?`, `span?` |
167
- | `tty` | `id`, `screen: string[]`, `title?`, `cols?`, `inverse?`, `bold?` (`[row, from, to][]`) — a full-screen program's grid |
168
- | `plot` | `id`, `x`, `y` (axes: `min`, `max`, `step?`, `label?`, or `labels` for categories), `series`, `title?`, `axes?`, `grid?` |
169
- | `tree` | `id`, `entries` (`name`, `children?`, `folder?`, `state?: active \| new \| muted`, `note?`, `icon?`), `title?` |
170
- | `note` | `id`, `text`, `tone?` — a dashed callout of wrapping prose |
171
- | any node | `minW?`/`minH?` (floors), `maxW?`/`maxH?` (caps), `w?`/`h?` (exact), `fill?`, `span?`, `tone?`; groups also `bare?` |
172
- | `Edge` | `from`, `to` (a node id; a table row `table.row`; a code line `code.L12`; a tree entry `tree.src/a.py`; a tty row `top.R7`), `label?`, `dashed?`, `bidirectional?` |
173
- | `Scene` | `nodes`, `edges?`, `title?`, `sub?`, `dir?`, `pulse?` |
229
+ ## Icons
174
230
 
175
- **Layout.** A group lays its children out as `dir: 'col'` (default), `'row'` (one column per child)
176
- or `'grid'` (`cols`, default 2). `span: 'all'` gives a child a full row — a rail under columns.
177
- Siblings in a row stretch to equal height.
178
-
179
- **Tone** sets what a box means and is inherited by everything inside it:
180
-
181
- | tone | hue | | tone | hue |
182
- |---|---|---|---|---|
183
- | `neutral` | grey | | `serve` | violet |
184
- | `source` | slate | | `consume` | red |
185
- | `ingest` | blue | | `infra` | orange |
186
- | `store` | green | | | |
187
-
188
- The theme (`dark` | `light`) picks the shade; repos cannot recolour.
189
-
190
- **Icons** share one key space across five sets; an unknown key draws no icon. Keys match
231
+ **Icons** share one key space across six sets; an unknown key draws no icon. Keys match
191
232
  `@graphlearning/flow`'s where both have the icon, so scenes port without renaming.
192
233
 
193
234
  | set | drawn in | keys |
@@ -197,18 +238,5 @@ The theme (`dark` | `light`) picks the shade; repos cannot recolour.
197
238
  | AWS service | its own tile | `acm apigateway athena aurora backup budgets cloudformation cloudfront cloudtrail cloudwatch costexplorer dms dynamodb ec2 ecr ecs eks elasticache elb emr eventbridge fargate firehose glue iam identitycenter kinesis kms lakeformation lambda msk mwaa organizations rds redshift route53 s3 sagemaker secretsmanager sns sqs ssm stepfunctions vpc waf xray` |
198
239
  | AWS group mark | its own tile (for a group's `icon`) | `account autoscaling privatesubnet publicsubnet region` |
199
240
  | AWS resource | a single-colour glyph, no tile | `alb bucket container ecsservice ecstask hostedzone iamrole igw message natgateway permissions queue router sts topic vpcendpoint` |
200
- | brand | its own colour (ink if it would vanish) | `airflow almalinux apple arch bash debian docker duckdb fedora flink git github githubactions grafana java junit jupyter kafka kubernetes letsencrypt linux macos maven mongodb nginx pandas postgresql prometheus python redhat rocky snowflakedb spark terraform ubuntu zsh` |
201
-
202
- **`muted: true`** draws an item greyed, or a group as a plain grey outline — a part the system does
203
- not have yet, at its full size and place (paint only, so muting moves nothing; a muted group does not
204
- dim its children). An architecture that grows course by course draws its
205
- whole final shape from the start.
206
-
207
- **`chip: true`** draws an item as a small framed pill — a thing counted, not described (`Task 1`,
208
- `Local disk`); chips fill their grid cell, so a row of them lines up.
209
-
210
- A nested group is a plain card, unless it names its OWN `tone` — then it is a coloured column again
211
- (the Spark study's four columns, and its green worker nodes inside the orange Worker column).
212
-
213
- **`stack: true`** puts an item's icon on top with the text centred under it — a card in a column of
214
- peers (the Business Consumers column).
241
+ | Google Cloud | its own colours (Google Cloud Icons, Apache-2.0) | `bigquery cloudbuild cloudkms cloudlogging cloudmonitoring composer dataflow dataplex dataproc dlp gcpbilling gcpiam gcpproject gcs pubsub secretmanager` |
242
+ | brand | its own colour (ink if it would vanish) | `airflow almalinux apple arch bash debian docker duckdb fedora flink git github gcp githubactions grafana java junit jupyter kafka kubernetes letsencrypt linux looker macos maven mongodb nginx pandas postgresql prometheus python redhat rocky snowflakedb spark terraform ubuntu zsh` |
package/dist/fit.d.ts CHANGED
@@ -17,4 +17,4 @@ export declare const MAX_SCALE = 4;
17
17
  * That is what makes recordings reproducible: two frames whose scenes have the same natural box get
18
18
  * the same scale and put every panel at the same pixels.
19
19
  */
20
- export declare function fitTransform(pane: Size, content: Size): Fit;
20
+ export declare function fitTransform(pane: Size, content: Size, padding?: number): Fit;
@@ -0,0 +1,5 @@
1
+ /** Google Cloud product icons in their own colours: 24×24 SVG bodies, keyed as scenes name them. */
2
+ export declare const GCP: Record<string, {
3
+ title: string;
4
+ body: string;
5
+ }>;
package/dist/icons.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ComponentType, ReactElement } from 'react';
2
2
  import { type LucideIcon } from 'lucide-react';
3
+ import { GCP } from './gcp-icons';
3
4
  /** Generic glyphs, drawn in the node's tone accent. */
4
5
  export declare const LUCIDE: Record<string, LucideIcon>;
5
6
  /** Azure service tiles, in their own colours. The package ships no viewBox; 0 0 18 18 fits all. */
@@ -22,9 +23,9 @@ export declare const BRAND: Record<string, {
22
23
  hex: string;
23
24
  path: string;
24
25
  }>;
26
+ export { GCP };
25
27
  /** `size` is a CSS length — in em, so an icon scales WITH its text and the ratio stays designed. */
26
28
  type Draw = (size: string, surface: string, ink: string) => ReactElement;
27
29
  /** A brand mark under this contrast against the surface draws in ink (Kafka's black on dark). */
28
30
  export declare const BRAND_MIN_CONTRAST = 2.2;
29
31
  export declare const ICONS: Record<string, Draw>;
30
- export {};