@graphlearning/graphl-flow 0.0.0-stage → 0.2.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.
@@ -0,0 +1,189 @@
1
+ @import '@fontsource/ibm-plex-sans/400.css';
2
+ @import '@fontsource/ibm-plex-sans/600.css';
3
+ @import '@fontsource/ibm-plex-mono/400.css';
4
+ @import '@fontsource/ibm-plex-mono/600.css';
5
+
6
+ /* Colours come from theme.ts as --gf-* variables on .gf-scene; tones override
7
+ --gf-accent / --gf-tint on a node and every descendant inherits them. */
8
+
9
+ .gf-scene {
10
+ position: relative; width: 100%; height: 100%; overflow: hidden;
11
+ font: 16px/1.35 'IBM Plex Sans', system-ui, sans-serif;
12
+ background: var(--gf-bg); color: var(--gf-ink); user-select: text;
13
+ }
14
+ /* The natural box: laid out at max-content, then scaled by the fit (transform-origin 0 0). */
15
+ .gf-content { position: absolute; left: 0; top: 0; width: max-content; transform-origin: 0 0; }
16
+ .gf-scene *, .gf-scene *::before, .gf-scene *::after { box-sizing: border-box; }
17
+ .gf-scene-title { font-size: 32px; font-weight: 600; }
18
+ .gf-scene-sub { font-size: 20px; color: var(--gf-muted); margin-bottom: 16px; }
19
+
20
+ .gf-body { display: grid; align-items: stretch; }
21
+
22
+ /* A top-level group is a tinted column; a nested one is a card on it. */
23
+ .gf-group { border: 1px solid color-mix(in srgb, var(--gf-accent) 35%, transparent); border-radius: 8px; padding: 10px; background: var(--gf-tint); }
24
+ .gf-group .gf-group { background: var(--gf-surface); border-color: var(--gf-line); }
25
+ /* spread: the body takes the group's full (stretched) height and spaces its rows evenly over it. */
26
+ .gf-group[data-spread] { display: flex; flex-direction: column; }
27
+ .gf-group[data-spread] > .gf-body { flex: 1; align-content: space-evenly; }
28
+ /* ...unless it names its OWN tone: then it is a coloured column again (Spark's four columns). */
29
+ .gf-group .gf-group[data-toned] { background: var(--gf-tint); border-color: color-mix(in srgb, var(--gf-accent) 35%, transparent); }
30
+ /* A bare group only arranges: no frame, fill or padding, at any depth. */
31
+ .gf-group[data-bare], .gf-group .gf-group[data-bare] { border: 0; padding: 0; background: none; border-radius: 0; }
32
+ .gf-group-head { margin-bottom: 10px; }
33
+ .gf-group-title { display: flex; align-items: center; gap: 8px; font-size: 18px; font-weight: 600; }
34
+ .gf-group-sub { margin-top: 2px; font-size: 14px; color: var(--gf-muted); }
35
+ .gf-badge {
36
+ display: inline-grid; place-items: center; flex: none; width: 26px; height: 26px; border-radius: 50%;
37
+ background: var(--gf-accent); color: var(--gf-bg); font-size: 14px;
38
+ }
39
+
40
+ /* An item HUGS its content (no stretch): its box is what edges anchor to, and an unframed leaf
41
+ whose box ran to the cell edge would end every arrow short of nothing. Groups do stretch. */
42
+ .gf-item { display: flex; align-items: flex-start; gap: 10px; padding: 5px 2px; justify-self: start; align-self: start; }
43
+ .gf-icon { flex: none; color: var(--gf-accent); }
44
+ .gf-vendor { display: inline-flex; line-height: 0; }
45
+ .gf-aws { border-radius: 6px; overflow: hidden; }
46
+ /* A chip: a thing counted, not described — a small framed pill. */
47
+ .gf-item[data-chip] {
48
+ justify-self: stretch; justify-content: center; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 6px;
49
+ border: 1px solid color-mix(in srgb, var(--gf-accent) 45%, var(--gf-line)); background: var(--gf-surface);
50
+ }
51
+ .gf-item[data-chip] .gf-item-title { font-weight: 500; font-size: 15px; }
52
+ .gf-item[data-stack] { flex-direction: column; align-items: center; text-align: center; justify-self: center; }
53
+ .gf-item-title { font-weight: 600; }
54
+ /* The reading measure: an item's text WRAPS here instead of widening its column. The fit is set by
55
+ the scene's width, so an unwrapped subtitle shrinks every word in the frame (Barclays: 20px body
56
+ text at 4K before this). */
57
+ .gf-item > div { max-width: 15em; }
58
+ .gf-item-sub { font-size: 15px; color: var(--gf-muted); }
59
+ .gf-bullets { margin: 4px 0 0; padding-left: 18px; font-size: 15px; }
60
+
61
+ /* Edges live inside .gf-content, so they scale with it; pointer-events off keeps text selectable. */
62
+ .gf-edges { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
63
+ .gf-edge { fill: none; stroke: var(--gf-edge); stroke-width: 2; stroke-linejoin: round; }
64
+ .gf-arrowhead { fill: var(--gf-edge); }
65
+ .gf-pulse { fill: var(--gf-pulse); opacity: 0.9; }
66
+ .gf-edge-label {
67
+ position: absolute; white-space: nowrap; pointer-events: none;
68
+ padding: 1px 6px; border: 1px solid var(--gf-line); border-radius: 4px;
69
+ background: var(--gf-bg); color: var(--gf-muted); font-size: 14px;
70
+ }
71
+
72
+ /* A table hugs its content like an item: its box, and each row's, is what an edge anchors to. */
73
+ .gf-table {
74
+ justify-self: start; align-self: start; overflow: hidden;
75
+ border: 1px solid color-mix(in srgb, var(--gf-accent) 45%, var(--gf-line)); border-radius: 6px;
76
+ background: var(--gf-surface);
77
+ }
78
+ .gf-table-title {
79
+ padding: 5px 10px; font-weight: 600; font-size: 15px;
80
+ background: color-mix(in srgb, var(--gf-accent) 14%, var(--gf-surface));
81
+ border-bottom: 1px solid color-mix(in srgb, var(--gf-accent) 45%, var(--gf-line));
82
+ }
83
+ /* The inner table fills its frame: a title wider than the cells must not leave the rows — whose
84
+ faces edges anchor to — short of the border. */
85
+ .gf-table table { width: 100%; border-collapse: collapse; font: 15px/1.4 'IBM Plex Mono', ui-monospace, monospace; }
86
+ .gf-table th {
87
+ padding: 4px 10px; text-align: left; font: 600 12px/1.4 'IBM Plex Sans', system-ui, sans-serif;
88
+ letter-spacing: 0.04em; text-transform: uppercase; color: var(--gf-muted);
89
+ border-bottom: 1px solid var(--gf-line);
90
+ }
91
+ .gf-table td { padding: 4px 10px; white-space: nowrap; }
92
+ .gf-table tbody tr + tr td { border-top: 1px solid var(--gf-line); }
93
+ .gf-table tr[data-tone] td { background: var(--gf-tint); }
94
+ .gf-table td.gf-tag-cell { padding-right: 0; width: 1px; }
95
+ .gf-tag {
96
+ display: inline-block; padding: 0 5px; border-radius: 4px; font: 600 11px/1.6 'IBM Plex Sans', system-ui, sans-serif;
97
+ color: var(--gf-accent); border: 1px solid color-mix(in srgb, var(--gf-accent) 50%, transparent);
98
+ }
99
+
100
+ /* Code hugs its content like an item. Lines are BLOCKS spanning the full width: a line's box is
101
+ what an edge anchors to, and its faces must reach the frame (the table lesson). */
102
+ .gf-code {
103
+ justify-self: start; align-self: start; overflow: hidden; border-radius: 8px;
104
+ border: 1px solid color-mix(in srgb, var(--gf-accent) 35%, var(--gf-line));
105
+ background: var(--gf-code-bg); font: 15px/1.6 'IBM Plex Mono', ui-monospace, monospace;
106
+ }
107
+ .gf-code-bar {
108
+ display: flex; align-items: center; gap: 10px; padding: 6px 12px; background: var(--gf-code-bar);
109
+ border-bottom: 1px solid var(--gf-line); font: 13px/1.5 'IBM Plex Mono', ui-monospace, monospace; color: var(--gf-muted);
110
+ }
111
+ .gf-code[data-terminal] .gf-code-name { font: 600 12px/1.5 'IBM Plex Sans', system-ui, sans-serif; letter-spacing: 0.08em; text-transform: uppercase; }
112
+ .gf-dots { display: inline-flex; gap: 6px; }
113
+ .gf-dots i { width: 10px; height: 10px; border-radius: 50%; background: #ff5f56; }
114
+ .gf-dots i + i { background: #ffbd2e; }
115
+ .gf-dots i + i + i { background: #27c93f; }
116
+ .gf-code-body { padding-block: 8px; }
117
+ .gf-line { display: flex; white-space: pre; padding-right: 16px; color: var(--gf-code-var); }
118
+ .gf-code[data-terminal] .gf-line { padding-left: 14px; }
119
+ .gf-ln { flex: none; box-sizing: content-box; min-width: 3ch; padding: 0 12px 0 10px; text-align: right; color: var(--gf-code-gutter); user-select: none; }
120
+ .gf-line[data-lit] { background: color-mix(in srgb, var(--gf-accent) 16%, transparent); box-shadow: inset 3px 0 0 var(--gf-accent); }
121
+ .gf-line[data-lit] .gf-ln { color: var(--gf-accent); }
122
+ .gf-fold { color: var(--gf-code-gutter); font-style: italic; background: color-mix(in srgb, var(--gf-code-gutter) 10%, transparent); user-select: none; }
123
+ .gf-prompt { color: var(--gf-ok); user-select: none; }
124
+ .gf-line[data-kind='out'] { color: var(--gf-muted); }
125
+ .gf-line[data-kind='err'] { color: var(--gf-err); }
126
+ .tok-var { color: var(--gf-code-var); }
127
+ .tok-method { color: var(--gf-code-method); }
128
+ .tok-keyword { color: var(--gf-code-keyword); }
129
+ .tok-string { color: var(--gf-code-string); }
130
+ .tok-number { color: var(--gf-code-number); }
131
+ .tok-punct { color: var(--gf-code-punct); }
132
+ .tok-comment { color: var(--gf-code-comment); font-style: italic; }
133
+
134
+ /* A plot hugs its fixed-size SVG; it shares the table's title strip. */
135
+ .gf-plot {
136
+ justify-self: start; align-self: start; overflow: hidden; border-radius: 8px;
137
+ border: 1px solid color-mix(in srgb, var(--gf-accent) 35%, var(--gf-line)); background: var(--gf-surface);
138
+ }
139
+ .gf-plot svg { display: block; overflow: hidden; }
140
+ .gf-plot text { font: 15px 'IBM Plex Mono', ui-monospace, monospace; }
141
+ .gf-plot-grid line { stroke: var(--gf-line); stroke-width: 1; }
142
+ .gf-plot-axis line { stroke: var(--gf-muted); stroke-width: 1.5; }
143
+ .gf-plot-ticks text { fill: var(--gf-muted); }
144
+ .gf-plot-ticks .gf-plot-label { fill: var(--gf-ink); }
145
+ .gf-plot-labels text { font-weight: 600; }
146
+
147
+ /* A file explorer: the IDE's left pane. */
148
+ .gf-tree {
149
+ justify-self: start; align-self: start; overflow: hidden; border-radius: 8px;
150
+ border: 1px solid color-mix(in srgb, var(--gf-accent) 35%, var(--gf-line)); background: var(--gf-surface);
151
+ }
152
+ .gf-tree-title {
153
+ padding: 7px 12px; font: 600 12px/1.5 'IBM Plex Sans', system-ui, sans-serif; letter-spacing: 0.08em;
154
+ text-transform: uppercase; color: var(--gf-muted); border-bottom: 1px solid var(--gf-line); background: var(--gf-code-bar);
155
+ }
156
+ .gf-tree-body { padding-block: 6px; }
157
+ .gf-tree-row {
158
+ display: flex; align-items: center; gap: 6px; padding-right: 14px; white-space: nowrap;
159
+ font: 15px/1.75 'IBM Plex Sans', system-ui, sans-serif; color: var(--gf-ink);
160
+ }
161
+ .gf-tree-row svg { flex: none; color: var(--gf-muted); }
162
+ .gf-tree-chev { flex: none; width: 0.9em; }
163
+ .gf-tree-row[data-state='active'] { background: color-mix(in srgb, var(--gf-accent) 18%, transparent); box-shadow: inset 2px 0 0 var(--gf-accent); }
164
+ .gf-tree-row[data-state='active'] svg { color: var(--gf-accent); }
165
+ .gf-tree-row[data-state='new'] .gf-tree-name { color: var(--gf-ok); }
166
+ .gf-tree-row[data-state='muted'] { opacity: 0.5; }
167
+ .gf-tree-note { margin-left: auto; padding-left: 14px; font: 13px 'IBM Plex Mono', ui-monospace, monospace; color: var(--gf-muted); }
168
+ .gf-tree-row[data-state='new'] .gf-tree-note { color: var(--gf-ok); }
169
+ .gf-tree-row[data-state='muted'] .gf-tree-note { margin-left: 0; font: italic 14px 'IBM Plex Sans', system-ui, sans-serif; }
170
+ .gf-tree-icon { display: inline-flex; flex: none; line-height: 0; }
171
+
172
+ /* A note fills its column and wraps; capped so a note in an unbounded row stays a paragraph. */
173
+ .gf-note {
174
+ justify-self: stretch; align-self: start; max-width: 34em; padding: 12px 16px; border-radius: 8px;
175
+ border: 1.5px dashed var(--gf-accent); background: color-mix(in srgb, var(--gf-accent) 8%, transparent);
176
+ font: 17px/1.5 'IBM Plex Sans', system-ui, sans-serif; text-align: center; color: var(--gf-ink);
177
+ }
178
+ /* A plot never scales: in a narrow column use `compact`, the second fixed size. Too wide is overflow,
179
+ which check fails — scaling down silently shrank the text past reading in a 560px side pane. */
180
+
181
+ /* Focus: a ring and a glow in the node's own accent, by box-shadow — NO layout effect, so moving the
182
+ focus between sections never moves the scene. An unframed item gains a frame while focused. */
183
+ [data-focus] {
184
+ box-shadow: 0 0 0 2px var(--gf-accent), 0 0 24px 2px color-mix(in srgb, var(--gf-accent) 45%, transparent);
185
+ border-radius: 8px;
186
+ }
187
+ .gf-item[data-focus] { background: color-mix(in srgb, var(--gf-accent) 12%, var(--gf-surface)); }
188
+ tr[data-focus] td, .gf-line[data-focus], .gf-tree-row[data-focus] { background: color-mix(in srgb, var(--gf-accent) 18%, transparent); }
189
+ tr[data-focus], .gf-line[data-focus], .gf-tree-row[data-focus] { box-shadow: inset 3px 0 0 var(--gf-accent); border-radius: 0; }
@@ -0,0 +1,30 @@
1
+ import type { ThemeKey, Tone } from './types';
2
+ export interface ToneColors {
3
+ accent: string;
4
+ tint: string;
5
+ }
6
+ /** The code surface and its seven token colours — one set per theme, shared by every language. */
7
+ export interface CodeColors {
8
+ bg: string;
9
+ bar: string;
10
+ gutter: string;
11
+ var: string;
12
+ method: string;
13
+ keyword: string;
14
+ string: string;
15
+ number: string;
16
+ punct: string;
17
+ comment: string;
18
+ }
19
+ export interface Theme {
20
+ bg: string;
21
+ surface: string;
22
+ line: string;
23
+ ink: string;
24
+ muted: string;
25
+ edge: string;
26
+ pulse: string;
27
+ tones: Record<Tone, ToneColors>;
28
+ code: CodeColors;
29
+ }
30
+ export declare const THEMES: Record<ThemeKey, Theme>;
@@ -0,0 +1,184 @@
1
+ /** The scene model — the whole authoring contract. Scenes never carry x/y or sizes. */
2
+ export type ThemeKey = 'dark' | 'light';
3
+ /** What a box MEANS. A theme picks the shade; the tone picks the hue family. */
4
+ export type Tone = 'source' | 'ingest' | 'store' | 'serve' | 'consume' | 'infra' | 'neutral';
5
+ interface Base {
6
+ id: string;
7
+ /** Inherited: unset takes the nearest ancestor's tone. */
8
+ tone?: Tone;
9
+ /** Take a whole row of the parent (a rail under a row of columns). */
10
+ span?: 'all';
11
+ /**
12
+ * FLOORS in the scene's own pixels, applied after the natural size: a box never shrinks below
13
+ * them and content still grows it. Their job is consistency — frames whose boxes match get the same
14
+ * zoom, so a pane sits at the same pixels in every frame of a video.
15
+ */
16
+ minW?: number;
17
+ minH?: number;
18
+ /**
19
+ * CAPS: a box never grows past them. Content that does not fit overflows, and `check` fails it —
20
+ * a cap holds a column FIXED so nothing placed in it can move the rest of the frame.
21
+ */
22
+ maxW?: number;
23
+ maxH?: number;
24
+ /** Exact size: shorthand for min = max. A fixed column — the IDE's side pane, empty or not. */
25
+ w?: number;
26
+ h?: number;
27
+ /** A leaf stretches to fill its grid cell instead of hugging its content (IDE panes). */
28
+ fill?: boolean;
29
+ }
30
+ /** A leaf: one card. Every field is optional except `title`. */
31
+ export interface Item extends Base {
32
+ type: 'item';
33
+ title: string;
34
+ sub?: string;
35
+ /** An icon key — generic (`database`), Azure (`datafactory`), AWS (`s3`) or brand (`kafka`). */
36
+ icon?: string;
37
+ bullets?: string[];
38
+ /** Icon on top, text centred under it — a card in a column of peers. Default: icon left. */
39
+ stack?: boolean;
40
+ /** A small framed pill — a thing COUNTED, not described (`Task 1`, `Local disk`). */
41
+ chip?: boolean;
42
+ }
43
+ /** A container: lays its children out in a row, a column or a grid. */
44
+ export interface Group extends Base {
45
+ type: 'group';
46
+ title?: string;
47
+ /** A step number drawn as a badge before the title. */
48
+ badge?: number;
49
+ /** A line under the title: what the group is for. */
50
+ sub?: string;
51
+ /** An icon key drawn before the title. */
52
+ icon?: string;
53
+ dir?: 'row' | 'col' | 'grid';
54
+ /** Column count for `dir: 'grid'`. */
55
+ cols?: number;
56
+ /** No frame, fill or padding — a group that only arranges its children. */
57
+ bare?: boolean;
58
+ /** Distribute the children over the group's full height when it is stretched taller than them. */
59
+ spread?: boolean;
60
+ children: SceneNode[];
61
+ }
62
+ /** One table row: its cells, plus an optional id, a short tag in a leading gutter, and a tone. */
63
+ export interface TableRow {
64
+ /** Overrides the row's address. Default: its first cell, when that is a plain word. */
65
+ id?: string;
66
+ cells: (string | number)[];
67
+ /** A short marker drawn as a pill before the row: `PK`, `FK`, `sp`, `top`… */
68
+ tag?: string;
69
+ /** Tints the row — the changed value, the active frame. */
70
+ tone?: Tone;
71
+ }
72
+ /**
73
+ * A grid of cells — a DB table, a stack frame, a heap object, an array, a hash map's buckets.
74
+ * Each row is addressable by edges as `<table id>.<row id>`, which is how a pointer is drawn.
75
+ */
76
+ export interface Table extends Base {
77
+ type: 'table';
78
+ title?: string;
79
+ /** Header cells. Omit for a headerless table (a stack frame, a heap object). */
80
+ columns?: string[];
81
+ rows: ((string | number)[] | TableRow)[];
82
+ }
83
+ /**
84
+ * Source code or a terminal session. Lines are addressable by edges as `<code id>.L<n>` (the FILE's
85
+ * line number), which is how an arrow points from a line into a diagram.
86
+ */
87
+ export interface Code extends Base {
88
+ type: 'code';
89
+ /** The source. A template literal's common indent and outer blank lines are dropped. */
90
+ code: string;
91
+ lang?: 'python' | 'sql' | 'scala' | 'java' | 'js' | 'ts' | 'shell' | 'text';
92
+ /** The tab label; for a terminal, its title. */
93
+ filename?: string;
94
+ /** Only these 1-based, inclusive line ranges; each skipped run folds to `··· N lines`. */
95
+ show?: [number, number][];
96
+ /** Line numbers (the file's) to tint. */
97
+ highlight?: number[];
98
+ /** A terminal: `$ cmd` lines are commands, `! text` errors, the rest output. No line numbers. */
99
+ terminal?: boolean;
100
+ }
101
+ /** An axis in DATA units. `labels` makes it categorical: one slot per label (bar charts). */
102
+ export interface PlotAxis {
103
+ min?: number;
104
+ max?: number;
105
+ /** Tick spacing; default a "nice" step giving ~8 ticks. */
106
+ step?: number;
107
+ label?: string;
108
+ labels?: string[];
109
+ }
110
+ export interface PlotSeries {
111
+ kind: 'line' | 'scatter' | 'area' | 'bar' | 'segment';
112
+ /** Data points (line, scatter, area, bar). Curves are sampled in the scene file. */
113
+ points?: [number, number][];
114
+ /** A segment's two ends. */
115
+ from?: [number, number];
116
+ to?: [number, number];
117
+ /** Drawn at the last point, a segment's midpoint, or an arrow's tip. */
118
+ label?: string;
119
+ /** Default: the next colour of the plot ramp. */
120
+ tone?: Tone;
121
+ /** A line drawn dashed. A segment is dashed UNLESS `dashed: false`. */
122
+ dashed?: boolean;
123
+ /** A segment with a head at `to` — a vector. */
124
+ arrow?: boolean;
125
+ }
126
+ /** A chart. Every plot's drawing area is the same fixed size, whatever its data. */
127
+ export interface Plot extends Base {
128
+ type: 'plot';
129
+ title?: string;
130
+ x: PlotAxis;
131
+ y: PlotAxis;
132
+ series: PlotSeries[];
133
+ /** Default: through the origin when both numeric ranges span zero, else along the corner. */
134
+ axes?: 'origin' | 'corner';
135
+ /** Gridlines at the ticks. Default true. */
136
+ grid?: boolean;
137
+ /** The second fixed size (420×280 drawing area) — a chart in a side pane, at full text size. */
138
+ compact?: boolean;
139
+ }
140
+ export interface TreeEntry {
141
+ name: string;
142
+ children?: TreeEntry[];
143
+ /** Draw as a folder even with no children listed. */
144
+ folder?: boolean;
145
+ /** `active` — the open file; `new` — added in this step; `muted` — not relevant here. */
146
+ state?: 'active' | 'new' | 'muted';
147
+ /** A short note after the name (`M`, `U`); on a `muted` entry it reads as an italic aside. */
148
+ note?: string;
149
+ /** An icon key. Default: by extension (`.py` → the Python mark), else a plain file or folder. */
150
+ icon?: string;
151
+ }
152
+ /** A file explorer. Each entry is addressable by edges as `<tree id>.<path>` (`ide.src/jobs/orders.py`). */
153
+ export interface Tree extends Base {
154
+ type: 'tree';
155
+ /** The panel heading. Default `Explorer`. */
156
+ title?: string;
157
+ entries: TreeEntry[];
158
+ }
159
+ /** A callout: wrapping prose in a dashed frame of its tone. Fills its column's width. */
160
+ export interface Note extends Base {
161
+ type: 'note';
162
+ text: string;
163
+ }
164
+ export type SceneNode = Item | Group | Table | Code | Plot | Tree | Note;
165
+ export interface Edge {
166
+ /** A node id, or a table row as `<table>.<row>`. */
167
+ from: string;
168
+ to: string;
169
+ label?: string;
170
+ dashed?: boolean;
171
+ /** A head at both ends (and a pulse each way) — a read/write, a request/response. */
172
+ bidirectional?: boolean;
173
+ }
174
+ export interface Scene {
175
+ title?: string;
176
+ sub?: string;
177
+ /** Direction of the top-level nodes. Default `'col'`. */
178
+ dir?: 'row' | 'col';
179
+ nodes: SceneNode[];
180
+ edges?: Edge[];
181
+ /** A dot travels every edge once per 2.4 s (the recorder's loop). Default true. */
182
+ pulse?: boolean;
183
+ }
184
+ export {};
package/package.json CHANGED
@@ -1,6 +1,58 @@
1
1
  {
2
2
  "name": "@graphlearning/graphl-flow",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Declarative diagram engine — authors describe groups, items and edges; the browser lays them out and the engine draws the edges.",
5
+ "license": "UNLICENSED",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/schemabotview/graphl-flow.git"
9
+ },
10
+ "type": "module",
11
+ "sideEffects": [
12
+ "**/*.css"
13
+ ],
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ },
25
+ "./styles.css": "./dist/styles.css"
26
+ },
27
+ "scripts": {
28
+ "dev": "vite",
29
+ "build": "vite build && tsc --emitDeclarationOnly && cp src/styles.css dist/styles.css",
30
+ "watch": "vite build --watch",
31
+ "prepublishOnly": "npm run build",
32
+ "capture": "node scripts/capture.mjs",
33
+ "check": "node scripts/check.mjs"
34
+ },
35
+ "peerDependencies": {
36
+ "lucide-react": "^1.28.0",
37
+ "react": "^19.2.0",
38
+ "react-dom": "^19.2.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/react": "^19.2.0",
42
+ "@types/react-dom": "^19.2.0",
43
+ "@vitejs/plugin-react": "^4.3.4",
44
+ "lucide-react": "^1.28.0",
45
+ "playwright": "1.63.0",
46
+ "react": "^19.2.0",
47
+ "react-dom": "^19.2.0",
48
+ "typescript": "~5.7.2",
49
+ "vite": "^6.0.5"
50
+ },
51
+ "dependencies": {
52
+ "@fontsource/ibm-plex-mono": "^5.3.0",
53
+ "@fontsource/ibm-plex-sans": "^5.3.0",
54
+ "@threeveloper/azure-react-icons": "^1.1.1",
55
+ "aws-react-icons": "^3.3.0",
56
+ "simple-icons": "^16.36.0"
57
+ }
58
+ }