@stealthscale/component-graphs 0.1.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/LICENSE +21 -0
- package/README.md +636 -0
- package/dist/cyclonedx/bom.json +1 -0
- package/dist/index.d.ts +1175 -0
- package/dist/index.js +3808 -0
- package/dist/recipe-BkmwNoaQ.js +632 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/theme.d.ts +11 -0
- package/dist/theme.js +16 -0
- package/package.json +86 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
import { defineSlotRecipe, dense, onSlots, ratioVariants, truncate } from "@stealthscale/theme/authoring";
|
|
2
|
+
//#region src/graph/disc.ts
|
|
3
|
+
/**
|
|
4
|
+
* Styles a network's node for the graph recipe: a disc with the node's icon, and its name under
|
|
5
|
+
* it.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The disc is as wide as its `--graph-disc`, which the preset writes from the node's weight, and
|
|
9
|
+
* is a circle from the theme's panel with a hairline edge. The name is one line on a pill in the
|
|
10
|
+
* panel's color, so an edge under it does not cross the letters. The node's box is the disc and
|
|
11
|
+
* the name, so the view's fit and the overview map include the name. The node's handles are in a
|
|
12
|
+
* hub, a line of no height half a handle below the disc's middle, so the top of each handle, the
|
|
13
|
+
* point React Flow starts a top handle's edges at, is the disc's centre. The hub is hidden, and
|
|
14
|
+
* React Flow still measures the handles in it. A selected disc takes the focus ink on its edge,
|
|
15
|
+
* and a dimmed node, `data-dimmed`, recedes by a dashed edge and a muted name, not by opacity on
|
|
16
|
+
* its words.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Styles of the node's box: the disc above its name, centred.
|
|
20
|
+
*/
|
|
21
|
+
const DISC_NODE = {
|
|
22
|
+
alignItems: "center",
|
|
23
|
+
display: "flex",
|
|
24
|
+
flexDirection: "column",
|
|
25
|
+
gap: "1",
|
|
26
|
+
position: "relative"
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Styles of the disc: a circle as wide as `--graph-disc` with the node's icon in its middle.
|
|
30
|
+
*/
|
|
31
|
+
const DISC = {
|
|
32
|
+
".react-flow__node.selected &": {
|
|
33
|
+
_highContrast: { borderColor: "Highlight" },
|
|
34
|
+
borderColor: "border.focus",
|
|
35
|
+
boxShadow: "0 0 0 {borderWidths.hairline} {colors.border.focus}"
|
|
36
|
+
},
|
|
37
|
+
"[data-dimmed] > &": {
|
|
38
|
+
borderStyle: "dashed",
|
|
39
|
+
boxShadow: "none"
|
|
40
|
+
},
|
|
41
|
+
"& > svg": { boxSize: "icon.sm" },
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
background: "bg.panel",
|
|
44
|
+
borderColor: "border",
|
|
45
|
+
borderRadius: "full",
|
|
46
|
+
borderStyle: "solid",
|
|
47
|
+
borderWidth: "hairline",
|
|
48
|
+
boxShadow: "xs",
|
|
49
|
+
boxSize: "var(--graph-disc)",
|
|
50
|
+
color: "fg.muted",
|
|
51
|
+
display: "flex",
|
|
52
|
+
justifyContent: "center",
|
|
53
|
+
position: "relative"
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Styles of the hub the handles are in: a hidden line of no height, half a handle below the disc's
|
|
57
|
+
* middle.
|
|
58
|
+
*/
|
|
59
|
+
const DISC_HUB = {
|
|
60
|
+
blockSize: "0",
|
|
61
|
+
insetBlockStart: "calc(50% + {sizes.2.5} / 2)",
|
|
62
|
+
insetInline: "0",
|
|
63
|
+
position: "absolute",
|
|
64
|
+
visibility: "hidden"
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Styles of the name under the disc: one line on a pill in the panel's color.
|
|
68
|
+
*/
|
|
69
|
+
const DISC_LABEL = {
|
|
70
|
+
"[data-dimmed] > &": {
|
|
71
|
+
color: "fg.muted",
|
|
72
|
+
fontWeight: "normal"
|
|
73
|
+
},
|
|
74
|
+
background: "bg.panel",
|
|
75
|
+
borderRadius: "l1",
|
|
76
|
+
color: "fg",
|
|
77
|
+
fontWeight: "medium",
|
|
78
|
+
paddingInline: "1",
|
|
79
|
+
textStyle: "body.xs",
|
|
80
|
+
whiteSpace: "nowrap"
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/graph/flow.ts
|
|
84
|
+
/**
|
|
85
|
+
* Restyles the classes React Flow writes, for the graph recipe's canvas.
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* React Flow places its layers by these rules and ships them as `base.css`. A component imports
|
|
89
|
+
* no stylesheet, so the canvas states the rules the kit needs, with the theme's tokens for every
|
|
90
|
+
* color: the pane under the viewport, the nodes and edges above it, the label layer the edges'
|
|
91
|
+
* controls render in, the corner panels, and the attribution link. The layers keep React Flow's
|
|
92
|
+
* own order inside the canvas, which isolates them from the page. An edge is the muted ink, and a
|
|
93
|
+
* selected or focused edge is the focus ink twice as wide. An edge on a traced path,
|
|
94
|
+
* `data-trace="on"`, is the ink twice as wide, and an edge off it fades to the theme's backdrop
|
|
95
|
+
* opacity. An added edge, `data-change="added"`, is the success ink twice as wide, a removed edge
|
|
96
|
+
* the error ink dashed and twice as wide, and an unchanged edge fades, so the dash tells a
|
|
97
|
+
* removed edge apart under forced colors too. An edge's `--graph-strength` multiplies both
|
|
98
|
+
* widths, 1 unless set, so a network's stronger link renders wider. A handle is a dot in the
|
|
99
|
+
* muted ink inside a ring in the panel's color, and a handle no edge meets, `data-unused`, is
|
|
100
|
+
* invisible and still measured. Under forced colors the edges and the handles take `CanvasText`,
|
|
101
|
+
* and a selected edge and a handle that takes connections `Highlight`. The viewport is hidden
|
|
102
|
+
* while React Flow's element has `data-placing`, which a preset sets until its nodes are laid out
|
|
103
|
+
* by their measured sizes.
|
|
104
|
+
*/
|
|
105
|
+
/**
|
|
106
|
+
* Rules of React Flow's own layers: where each is placed, what takes the pointer, and in which
|
|
107
|
+
* order.
|
|
108
|
+
*/
|
|
109
|
+
const LAYERS = {
|
|
110
|
+
"& .react-flow": {
|
|
111
|
+
direction: "ltr",
|
|
112
|
+
inlineSize: "full",
|
|
113
|
+
position: "relative"
|
|
114
|
+
},
|
|
115
|
+
"& .react-flow__background": {
|
|
116
|
+
pointerEvents: "none",
|
|
117
|
+
zIndex: "-1"
|
|
118
|
+
},
|
|
119
|
+
"& .react-flow__background-pattern.dots": {
|
|
120
|
+
_highContrast: { fill: "GrayText" },
|
|
121
|
+
fill: "border"
|
|
122
|
+
},
|
|
123
|
+
"& .react-flow__container": {
|
|
124
|
+
blockSize: "full",
|
|
125
|
+
inlineSize: "full",
|
|
126
|
+
insetBlockStart: "0",
|
|
127
|
+
insetInlineStart: "0",
|
|
128
|
+
position: "absolute"
|
|
129
|
+
},
|
|
130
|
+
"& .react-flow__edgelabel-renderer": {
|
|
131
|
+
blockSize: "full",
|
|
132
|
+
inlineSize: "full",
|
|
133
|
+
insetBlockStart: "0",
|
|
134
|
+
insetInlineStart: "0",
|
|
135
|
+
pointerEvents: "none",
|
|
136
|
+
position: "absolute",
|
|
137
|
+
userSelect: "none"
|
|
138
|
+
},
|
|
139
|
+
"& .react-flow__nodes": {
|
|
140
|
+
pointerEvents: "none",
|
|
141
|
+
transformOrigin: "0 0"
|
|
142
|
+
},
|
|
143
|
+
"& .react-flow__pane": {
|
|
144
|
+
touchAction: "none",
|
|
145
|
+
zIndex: "1"
|
|
146
|
+
},
|
|
147
|
+
"& .react-flow__pane.draggable": { cursor: "pan" },
|
|
148
|
+
"& .react-flow__pane.dragging": { cursor: "dragging" },
|
|
149
|
+
"& .react-flow__renderer": { zIndex: "4" },
|
|
150
|
+
"& .react-flow__selection": { zIndex: "6" },
|
|
151
|
+
"& .react-flow__viewport": {
|
|
152
|
+
pointerEvents: "none",
|
|
153
|
+
transformOrigin: "0 0",
|
|
154
|
+
zIndex: "2"
|
|
155
|
+
},
|
|
156
|
+
"& .react-flow[data-placing] .react-flow__viewport": { visibility: "hidden" }
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Rules of the nodes: React Flow's wrapper places each node, takes the pointer and the focus ring.
|
|
160
|
+
*/
|
|
161
|
+
const NODES = {
|
|
162
|
+
"& .react-flow__node": {
|
|
163
|
+
boxSizing: "border-box",
|
|
164
|
+
focusRingColor: "border.focus",
|
|
165
|
+
focusVisibleRing: "outside",
|
|
166
|
+
pointerEvents: "all",
|
|
167
|
+
position: "absolute",
|
|
168
|
+
transformOrigin: "0 0",
|
|
169
|
+
userSelect: "none"
|
|
170
|
+
},
|
|
171
|
+
"& .react-flow__node.draggable": { cursor: "drag" },
|
|
172
|
+
"& .react-flow__node.draggable.dragging": { cursor: "dragging" },
|
|
173
|
+
"& .react-flow__node.selectable": { cursor: "button" }
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Rules of the edges and of the line a connection in progress renders.
|
|
177
|
+
*/
|
|
178
|
+
const EDGES = {
|
|
179
|
+
"& .react-flow__arrowhead polyline": {
|
|
180
|
+
_highContrast: { stroke: "CanvasText" },
|
|
181
|
+
stroke: "fg.muted"
|
|
182
|
+
},
|
|
183
|
+
"& .react-flow__arrowhead polyline.arrowclosed": {
|
|
184
|
+
_highContrast: { fill: "CanvasText" },
|
|
185
|
+
fill: "fg.muted"
|
|
186
|
+
},
|
|
187
|
+
"& .react-flow__connection": { pointerEvents: "none" },
|
|
188
|
+
"& .react-flow__connection-path": {
|
|
189
|
+
_highContrast: { stroke: "Highlight" },
|
|
190
|
+
fill: "none",
|
|
191
|
+
stroke: "border.focus",
|
|
192
|
+
strokeWidth: "ring"
|
|
193
|
+
},
|
|
194
|
+
"& .react-flow__connectionline": {
|
|
195
|
+
overflow: "visible",
|
|
196
|
+
position: "absolute",
|
|
197
|
+
zIndex: "1001"
|
|
198
|
+
},
|
|
199
|
+
"& .react-flow__edge": {
|
|
200
|
+
outline: "none",
|
|
201
|
+
pointerEvents: "visibleStroke"
|
|
202
|
+
},
|
|
203
|
+
"& .react-flow__edge-path": {
|
|
204
|
+
_highContrast: { stroke: "CanvasText" },
|
|
205
|
+
fill: "none",
|
|
206
|
+
stroke: "fg.muted",
|
|
207
|
+
strokeWidth: "calc({borderWidths.hairline} * var(--graph-strength, 1))",
|
|
208
|
+
transition: "stroke {durations.fast} {easings.out}, opacity {durations.fast} {easings.out}"
|
|
209
|
+
},
|
|
210
|
+
"& .react-flow__edge:is(.selected, :focus-visible) .react-flow__edge-path": {
|
|
211
|
+
_highContrast: { stroke: "Highlight" },
|
|
212
|
+
stroke: "border.focus",
|
|
213
|
+
strokeWidth: "ring"
|
|
214
|
+
},
|
|
215
|
+
"& .react-flow__edge.inactive": { pointerEvents: "none" },
|
|
216
|
+
"& .react-flow__edge.selectable": { cursor: "button" },
|
|
217
|
+
"& .react-flow__edge[data-change=added] .react-flow__edge-path": {
|
|
218
|
+
_highContrast: { stroke: "CanvasText" },
|
|
219
|
+
stroke: "border.success",
|
|
220
|
+
strokeWidth: "calc({borderWidths.ring} * var(--graph-strength, 1))"
|
|
221
|
+
},
|
|
222
|
+
"& .react-flow__edge[data-change=removed] .react-flow__edge-path": {
|
|
223
|
+
_highContrast: { stroke: "CanvasText" },
|
|
224
|
+
stroke: "border.error",
|
|
225
|
+
strokeDasharray: "{spacing.1.5} {spacing.1}",
|
|
226
|
+
strokeWidth: "calc({borderWidths.ring} * var(--graph-strength, 1))"
|
|
227
|
+
},
|
|
228
|
+
"& .react-flow__edge[data-change=unchanged]": { opacity: "backdrop" },
|
|
229
|
+
"& .react-flow__edge[data-trace=off]": { opacity: "backdrop" },
|
|
230
|
+
"& .react-flow__edge[data-trace=on] .react-flow__edge-path": {
|
|
231
|
+
_highContrast: { stroke: "CanvasText" },
|
|
232
|
+
stroke: "fg",
|
|
233
|
+
strokeWidth: "calc({borderWidths.ring} * var(--graph-strength, 1))"
|
|
234
|
+
},
|
|
235
|
+
"& .react-flow .react-flow__edges": { position: "absolute" },
|
|
236
|
+
"& .react-flow .react-flow__edges svg": {
|
|
237
|
+
overflow: "visible",
|
|
238
|
+
pointerEvents: "none",
|
|
239
|
+
position: "absolute"
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Rules of a handle, which React Flow places on the side of its node that `position` names.
|
|
244
|
+
*/
|
|
245
|
+
const HANDLES = {
|
|
246
|
+
"& .react-flow__handle": {
|
|
247
|
+
_highContrast: {
|
|
248
|
+
background: "CanvasText",
|
|
249
|
+
borderColor: "Canvas"
|
|
250
|
+
},
|
|
251
|
+
background: "fg.muted",
|
|
252
|
+
borderColor: "bg.panel",
|
|
253
|
+
borderRadius: "full",
|
|
254
|
+
borderStyle: "solid",
|
|
255
|
+
borderWidth: "ring",
|
|
256
|
+
boxSize: "2.5",
|
|
257
|
+
pointerEvents: "none",
|
|
258
|
+
position: "absolute"
|
|
259
|
+
},
|
|
260
|
+
"& .react-flow__handle-bottom": {
|
|
261
|
+
insetBlockEnd: "0",
|
|
262
|
+
left: "var(--graph-port-along, 50%)",
|
|
263
|
+
transform: "translate(-50%, 50%)"
|
|
264
|
+
},
|
|
265
|
+
"& .react-flow__handle-left": {
|
|
266
|
+
left: "0",
|
|
267
|
+
top: "var(--graph-port-along, 50%)",
|
|
268
|
+
transform: "translate(-50%, -50%)"
|
|
269
|
+
},
|
|
270
|
+
"& .react-flow__handle-right": {
|
|
271
|
+
right: "0",
|
|
272
|
+
top: "var(--graph-port-along, 50%)",
|
|
273
|
+
transform: "translate(50%, -50%)"
|
|
274
|
+
},
|
|
275
|
+
"& .react-flow__handle-top": {
|
|
276
|
+
insetBlockStart: "0",
|
|
277
|
+
left: "var(--graph-port-along, 50%)",
|
|
278
|
+
transform: "translate(-50%, -50%)"
|
|
279
|
+
},
|
|
280
|
+
"& .react-flow__handle.connectable": {
|
|
281
|
+
_highContrast: { background: "Highlight" },
|
|
282
|
+
background: "border.focus",
|
|
283
|
+
pointerEvents: "all"
|
|
284
|
+
},
|
|
285
|
+
"& .react-flow__handle.connectionindicator": { cursor: "connect" },
|
|
286
|
+
"& .react-flow__handle[data-unused]": { visibility: "hidden" }
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* Rules of the corner panels: the attribution and any panel of the caller's.
|
|
290
|
+
*/
|
|
291
|
+
const PANELS = {
|
|
292
|
+
"& .react-flow__attribution": {
|
|
293
|
+
background: "bg.panel",
|
|
294
|
+
color: "fg.muted",
|
|
295
|
+
margin: "0",
|
|
296
|
+
paddingInline: "1",
|
|
297
|
+
textStyle: "body.xs"
|
|
298
|
+
},
|
|
299
|
+
"& .react-flow__attribution a": {
|
|
300
|
+
color: "fg.muted",
|
|
301
|
+
textDecoration: "none"
|
|
302
|
+
},
|
|
303
|
+
"& .react-flow__panel": {
|
|
304
|
+
margin: "3",
|
|
305
|
+
position: "absolute",
|
|
306
|
+
zIndex: "5"
|
|
307
|
+
},
|
|
308
|
+
"& .react-flow__panel.bottom": { insetBlockEnd: "0" },
|
|
309
|
+
"& .react-flow__panel.left": { left: "0" },
|
|
310
|
+
"& .react-flow__panel.right": { right: "0" },
|
|
311
|
+
"& .react-flow__panel.top": { insetBlockStart: "0" }
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* Rules the canvas slot takes: React Flow's layers, nodes, edges, handles and panels.
|
|
315
|
+
*/
|
|
316
|
+
const FLOW = {
|
|
317
|
+
...LAYERS,
|
|
318
|
+
...NODES,
|
|
319
|
+
...EDGES,
|
|
320
|
+
...HANDLES,
|
|
321
|
+
...PANELS
|
|
322
|
+
};
|
|
323
|
+
//#endregion
|
|
324
|
+
//#region src/graph/recipe.ts
|
|
325
|
+
/**
|
|
326
|
+
* Styles a graph's figure, canvas, controls, overview map, summary, empty state and nodes, and
|
|
327
|
+
* restyles the classes React Flow writes with the theme's tokens.
|
|
328
|
+
*
|
|
329
|
+
* @remarks
|
|
330
|
+
* The canvas is a panel as wide as the figure and as tall as its ratio, because React Flow
|
|
331
|
+
* measures its box after the first render and renders nothing in a box 0 pixels high. The empty
|
|
332
|
+
* state takes the canvas's place at the same ratio. The controls are a row at the figure's start
|
|
333
|
+
* above the canvas, and the overview map a panel at its end below the canvas, so neither covers a
|
|
334
|
+
* node. A node is a card 256px wide, the width `layoutGraph` places a node by, with a header of
|
|
335
|
+
* an icon, a title, a subtitle, a status and actions, a body, and a problem line in the error
|
|
336
|
+
* ink. A tag renders above the card's top edge at its end, and a branch control straddles the
|
|
337
|
+
* middle of its bottom edge, where the card keeps half the control's height free. A network's
|
|
338
|
+
* node is a disc with its name under it instead of a card. A selected node takes the focus ink
|
|
339
|
+
* on its edge, and a node the canvas dims recedes by a dashed edge and a muted title, not by
|
|
340
|
+
* opacity on its words. A port's name is written beside its handle, outside
|
|
341
|
+
* the node, on the side the handle is on. The recipe has no `palette` axis, because a graph is
|
|
342
|
+
* not a control and its colors are the theme's roles.
|
|
343
|
+
*/
|
|
344
|
+
/**
|
|
345
|
+
* Styles of the overview map's box: a panel 176 by 112 pixels at the end of the figure, the map's
|
|
346
|
+
* nodes in the muted ink and the part out of view behind a wash.
|
|
347
|
+
*/
|
|
348
|
+
const OVERVIEW = {
|
|
349
|
+
"& .react-flow__minimap-mask": {
|
|
350
|
+
fill: "bg.muted",
|
|
351
|
+
fillOpacity: "{opacity.muted}",
|
|
352
|
+
stroke: "none"
|
|
353
|
+
},
|
|
354
|
+
"& .react-flow__minimap-node": {
|
|
355
|
+
_highContrast: { fill: "CanvasText" },
|
|
356
|
+
fill: "fg.muted"
|
|
357
|
+
},
|
|
358
|
+
"& .react-flow__minimap-svg": {
|
|
359
|
+
blockSize: "28",
|
|
360
|
+
display: "block",
|
|
361
|
+
inlineSize: "44"
|
|
362
|
+
},
|
|
363
|
+
background: "bg.panel",
|
|
364
|
+
borderColor: "border",
|
|
365
|
+
borderRadius: "l2",
|
|
366
|
+
borderStyle: "solid",
|
|
367
|
+
borderWidth: "hairline",
|
|
368
|
+
marginInlineStart: "auto",
|
|
369
|
+
overflow: "hidden"
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* Rule of the hairline that parts a node's body and problem line from its header.
|
|
373
|
+
*/
|
|
374
|
+
const RULED = {
|
|
375
|
+
borderBlockStartColor: "border",
|
|
376
|
+
borderBlockStartStyle: "solid",
|
|
377
|
+
borderBlockStartWidth: "hairline",
|
|
378
|
+
paddingBlock: dense("{spacing.inset.xs}"),
|
|
379
|
+
paddingInline: dense("{spacing.inset.sm}"),
|
|
380
|
+
textStyle: "body.xs"
|
|
381
|
+
};
|
|
382
|
+
/**
|
|
383
|
+
* Defines the graph recipe: a figure whose canvas is as wide as the figure and as tall as its
|
|
384
|
+
* ratio, by default the video ratio.
|
|
385
|
+
*/
|
|
386
|
+
const recipe = defineSlotRecipe({
|
|
387
|
+
base: {
|
|
388
|
+
canvas: {
|
|
389
|
+
...FLOW,
|
|
390
|
+
background: "bg.panel",
|
|
391
|
+
borderColor: "border",
|
|
392
|
+
borderRadius: "l2",
|
|
393
|
+
borderStyle: "solid",
|
|
394
|
+
borderWidth: "hairline",
|
|
395
|
+
inlineSize: "full",
|
|
396
|
+
isolation: "isolate",
|
|
397
|
+
minInlineSize: "0",
|
|
398
|
+
overflow: "hidden",
|
|
399
|
+
position: "relative"
|
|
400
|
+
},
|
|
401
|
+
caption: {
|
|
402
|
+
color: "fg.muted",
|
|
403
|
+
textStyle: "body.sm"
|
|
404
|
+
},
|
|
405
|
+
controls: {
|
|
406
|
+
alignItems: "center",
|
|
407
|
+
alignSelf: "flex-start",
|
|
408
|
+
display: "flex",
|
|
409
|
+
gap: dense("{spacing.gap.xs}"),
|
|
410
|
+
maxInlineSize: "full"
|
|
411
|
+
},
|
|
412
|
+
disc: DISC,
|
|
413
|
+
discHub: DISC_HUB,
|
|
414
|
+
discLabel: DISC_LABEL,
|
|
415
|
+
discNode: DISC_NODE,
|
|
416
|
+
empty: {
|
|
417
|
+
alignItems: "center",
|
|
418
|
+
background: "bg.panel",
|
|
419
|
+
borderColor: "border",
|
|
420
|
+
borderRadius: "l2",
|
|
421
|
+
borderStyle: "dashed",
|
|
422
|
+
borderWidth: "hairline",
|
|
423
|
+
color: "fg.muted",
|
|
424
|
+
display: "flex",
|
|
425
|
+
inlineSize: "full",
|
|
426
|
+
justifyContent: "center",
|
|
427
|
+
padding: dense("{spacing.inset.md}"),
|
|
428
|
+
textAlign: "center",
|
|
429
|
+
textStyle: "body.sm"
|
|
430
|
+
},
|
|
431
|
+
level: {
|
|
432
|
+
color: "fg.muted",
|
|
433
|
+
fontVariantNumeric: "tabular-nums",
|
|
434
|
+
minInlineSize: "10",
|
|
435
|
+
paddingInline: dense("{spacing.inset.xs}"),
|
|
436
|
+
textAlign: "center",
|
|
437
|
+
textStyle: "body.xs"
|
|
438
|
+
},
|
|
439
|
+
node: {
|
|
440
|
+
".react-flow__node.selected > &": {
|
|
441
|
+
_highContrast: { borderColor: "Highlight" },
|
|
442
|
+
borderColor: "border.focus",
|
|
443
|
+
boxShadow: "0 0 0 {borderWidths.hairline} {colors.border.focus}"
|
|
444
|
+
},
|
|
445
|
+
"&:has(> .graph__nodeBranch)": { paddingBlockEnd: `calc(${dense("{sizes.control.xs}")} / 2)` },
|
|
446
|
+
"&[data-dimmed]": {
|
|
447
|
+
borderStyle: "dashed",
|
|
448
|
+
boxShadow: "none"
|
|
449
|
+
},
|
|
450
|
+
"&[data-invalid]": { borderColor: "border.error" },
|
|
451
|
+
background: "bg.panel",
|
|
452
|
+
borderColor: "border",
|
|
453
|
+
borderRadius: "l2",
|
|
454
|
+
borderStyle: "solid",
|
|
455
|
+
borderWidth: "hairline",
|
|
456
|
+
boxShadow: "xs",
|
|
457
|
+
color: "fg",
|
|
458
|
+
display: "flex",
|
|
459
|
+
flexDirection: "column",
|
|
460
|
+
inlineSize: "64",
|
|
461
|
+
position: "relative",
|
|
462
|
+
textAlign: "start",
|
|
463
|
+
textStyle: "body.sm"
|
|
464
|
+
},
|
|
465
|
+
nodeActions: {
|
|
466
|
+
alignItems: "center",
|
|
467
|
+
display: "flex",
|
|
468
|
+
flexShrink: "0"
|
|
469
|
+
},
|
|
470
|
+
nodeBody: {
|
|
471
|
+
...RULED,
|
|
472
|
+
color: "fg.muted"
|
|
473
|
+
},
|
|
474
|
+
nodeBranch: {
|
|
475
|
+
display: "inline-flex",
|
|
476
|
+
insetBlockEnd: "0",
|
|
477
|
+
left: "50%",
|
|
478
|
+
position: "absolute",
|
|
479
|
+
translate: "-50% 50%"
|
|
480
|
+
},
|
|
481
|
+
nodeHeader: {
|
|
482
|
+
alignItems: "flex-start",
|
|
483
|
+
display: "flex",
|
|
484
|
+
gap: dense("{spacing.gap.sm}"),
|
|
485
|
+
paddingBlock: dense("{spacing.inset.xs}"),
|
|
486
|
+
paddingInline: dense("{spacing.inset.sm}")
|
|
487
|
+
},
|
|
488
|
+
nodeIcon: {
|
|
489
|
+
"& > svg": { boxSize: "icon.sm" },
|
|
490
|
+
color: "fg.muted",
|
|
491
|
+
display: "inline-flex",
|
|
492
|
+
flexShrink: "0",
|
|
493
|
+
marginBlockStart: "0.5"
|
|
494
|
+
},
|
|
495
|
+
nodeProblem: {
|
|
496
|
+
...RULED,
|
|
497
|
+
color: "fg.error"
|
|
498
|
+
},
|
|
499
|
+
nodeSubtitle: {
|
|
500
|
+
...truncate(),
|
|
501
|
+
color: "fg.muted",
|
|
502
|
+
textStyle: "body.xs"
|
|
503
|
+
},
|
|
504
|
+
nodeTag: {
|
|
505
|
+
display: "inline-flex",
|
|
506
|
+
insetBlockEnd: "100%",
|
|
507
|
+
insetInlineEnd: dense("{spacing.inset.sm}"),
|
|
508
|
+
marginBlockEnd: "1",
|
|
509
|
+
pointerEvents: "none",
|
|
510
|
+
position: "absolute"
|
|
511
|
+
},
|
|
512
|
+
nodeText: {
|
|
513
|
+
display: "flex",
|
|
514
|
+
flex: "1",
|
|
515
|
+
flexDirection: "column",
|
|
516
|
+
minInlineSize: "0"
|
|
517
|
+
},
|
|
518
|
+
nodeTitle: {
|
|
519
|
+
...truncate(),
|
|
520
|
+
"[data-dimmed] &": {
|
|
521
|
+
color: "fg.muted",
|
|
522
|
+
fontWeight: "normal"
|
|
523
|
+
},
|
|
524
|
+
fontWeight: "medium"
|
|
525
|
+
},
|
|
526
|
+
overview: OVERVIEW,
|
|
527
|
+
portName: {
|
|
528
|
+
".react-flow__handle-bottom > &": {
|
|
529
|
+
insetBlockStart: "100%",
|
|
530
|
+
left: "50%",
|
|
531
|
+
marginBlockStart: "1",
|
|
532
|
+
translate: "-50% 0"
|
|
533
|
+
},
|
|
534
|
+
".react-flow__handle-left > &": {
|
|
535
|
+
marginInlineEnd: "1.5",
|
|
536
|
+
right: "100%",
|
|
537
|
+
top: "50%",
|
|
538
|
+
translate: "0 -50%"
|
|
539
|
+
},
|
|
540
|
+
".react-flow__handle-right > &": {
|
|
541
|
+
left: "100%",
|
|
542
|
+
marginInlineStart: "1.5",
|
|
543
|
+
top: "50%",
|
|
544
|
+
translate: "0 -50%"
|
|
545
|
+
},
|
|
546
|
+
".react-flow__handle-top > &": {
|
|
547
|
+
insetBlockEnd: "100%",
|
|
548
|
+
left: "50%",
|
|
549
|
+
marginBlockEnd: "1",
|
|
550
|
+
translate: "-50% 0"
|
|
551
|
+
},
|
|
552
|
+
"&[data-hidden]": { srOnly: true },
|
|
553
|
+
background: "bg.panel",
|
|
554
|
+
borderRadius: "l1",
|
|
555
|
+
color: "fg.muted",
|
|
556
|
+
paddingInline: "1",
|
|
557
|
+
pointerEvents: "none",
|
|
558
|
+
position: "absolute",
|
|
559
|
+
textStyle: "body.xs",
|
|
560
|
+
whiteSpace: "nowrap"
|
|
561
|
+
},
|
|
562
|
+
remove: {
|
|
563
|
+
display: "inline-flex",
|
|
564
|
+
left: "0",
|
|
565
|
+
pointerEvents: "all",
|
|
566
|
+
position: "absolute",
|
|
567
|
+
top: "0",
|
|
568
|
+
transform: "translate(-50%, -50%) translate(var(--graph-edge-x), var(--graph-edge-y))"
|
|
569
|
+
},
|
|
570
|
+
root: {
|
|
571
|
+
display: "flex",
|
|
572
|
+
flexDirection: "column",
|
|
573
|
+
gap: dense("{spacing.gap.md}"),
|
|
574
|
+
inlineSize: "full",
|
|
575
|
+
margin: "0",
|
|
576
|
+
minInlineSize: "0"
|
|
577
|
+
},
|
|
578
|
+
summary: {
|
|
579
|
+
alignItems: "center",
|
|
580
|
+
color: "fg.muted",
|
|
581
|
+
display: "flex",
|
|
582
|
+
flexWrap: "wrap",
|
|
583
|
+
gap: dense("{spacing.gap.sm}"),
|
|
584
|
+
textStyle: "body.sm"
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
className: "graph",
|
|
588
|
+
defaultVariants: { ratio: "video" },
|
|
589
|
+
jsx: [/^Graph(\.\w+)?$/u],
|
|
590
|
+
slots: [
|
|
591
|
+
"root",
|
|
592
|
+
"canvas",
|
|
593
|
+
"controls",
|
|
594
|
+
"level",
|
|
595
|
+
"caption",
|
|
596
|
+
"node",
|
|
597
|
+
"nodeHeader",
|
|
598
|
+
"nodeIcon",
|
|
599
|
+
"nodeText",
|
|
600
|
+
"nodeTitle",
|
|
601
|
+
"nodeSubtitle",
|
|
602
|
+
"nodeActions",
|
|
603
|
+
"nodeBody",
|
|
604
|
+
"nodeProblem",
|
|
605
|
+
"nodeTag",
|
|
606
|
+
"nodeBranch",
|
|
607
|
+
"discNode",
|
|
608
|
+
"disc",
|
|
609
|
+
"discHub",
|
|
610
|
+
"discLabel",
|
|
611
|
+
"portName",
|
|
612
|
+
"remove",
|
|
613
|
+
"overview",
|
|
614
|
+
"summary",
|
|
615
|
+
"empty"
|
|
616
|
+
],
|
|
617
|
+
variants: {
|
|
618
|
+
/**
|
|
619
|
+
* Aspect ratio of the canvas, one of the theme's ratios, which the empty state takes in the
|
|
620
|
+
* canvas's place.
|
|
621
|
+
*
|
|
622
|
+
* @remarks
|
|
623
|
+
* React Flow measures the canvas's box after the first render and renders nothing in a box 0
|
|
624
|
+
* pixels high. The ratio gives the box its height before that measurement.
|
|
625
|
+
*/
|
|
626
|
+
ratio: onSlots({
|
|
627
|
+
canvas: ratioVariants(),
|
|
628
|
+
empty: ratioVariants()
|
|
629
|
+
}) }
|
|
630
|
+
});
|
|
631
|
+
//#endregion
|
|
632
|
+
export { recipe as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll as t };
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/theme.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Registers every recipe in the package in the preset an application's style compiler installs.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* The list is written by hand. `theme.spec.ts` fails when a recipe file is missing from it, so no
|
|
7
|
+
* generator writes it.
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: import("@stealthscale/theme/authoring").Preset;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { _default as default };
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { t as recipe } from "./recipe-BkmwNoaQ.js";
|
|
2
|
+
import { definePreset } from "@stealthscale/theme/authoring";
|
|
3
|
+
//#region src/theme.ts
|
|
4
|
+
/**
|
|
5
|
+
* Registers every recipe in the package in the preset an application's style compiler installs.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The list is written by hand. `theme.spec.ts` fails when a recipe file is missing from it, so no
|
|
9
|
+
* generator writes it.
|
|
10
|
+
*/
|
|
11
|
+
var theme_default = definePreset({
|
|
12
|
+
name: "@stealthscale/component-graphs",
|
|
13
|
+
theme: { extend: { slotRecipes: { graph: recipe } } }
|
|
14
|
+
});
|
|
15
|
+
//#endregion
|
|
16
|
+
export { theme_default as default };
|