@eventcatalog/visualiser 5.0.0-beta.4 → 5.0.0-beta.6
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/dist/chunk-Q3OM5AL5.mjs +1 -0
- package/dist/chunk-Q3OM5AL5.mjs.map +1 -0
- package/dist/chunk-R3QHQ7LF.mjs +427 -0
- package/dist/chunk-R3QHQ7LF.mjs.map +1 -0
- package/dist/chunk-T4UBHBKL.mjs +15698 -0
- package/dist/chunk-T4UBHBKL.mjs.map +1 -0
- package/dist/chunk-Z3G354GF.mjs +464 -0
- package/dist/chunk-Z3G354GF.mjs.map +1 -0
- package/dist/elk-layout-BVUJjv6i.d.mts +47 -0
- package/dist/elk-layout-BVUJjv6i.d.ts +47 -0
- package/dist/fonts/Excalifont-Regular.woff2 +0 -0
- package/dist/fonts/OFL.txt +93 -0
- package/dist/fonts/README.md +2 -0
- package/dist/index.d.mts +178 -9
- package/dist/index.d.ts +178 -9
- package/dist/index.js +5545 -5167
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +129 -15691
- package/dist/index.mjs.map +1 -1
- package/dist/layout.d.mts +2 -45
- package/dist/layout.d.ts +2 -45
- package/dist/layout.mjs +10 -374
- package/dist/layout.mjs.map +1 -1
- package/dist/model.d.mts +18 -0
- package/dist/model.mjs +51 -0
- package/dist/model.mjs.map +1 -0
- package/dist/schema-DKA0EQ_H.d.mts +484 -0
- package/dist/studio-fonts.css +10 -0
- package/dist/studio.css +509 -0
- package/dist/studio.d.mts +1312 -0
- package/dist/studio.mjs +6719 -0
- package/dist/studio.mjs.map +1 -0
- package/dist/styles-core.css +591 -1
- package/dist/styles.css +591 -1
- package/package.json +26 -8
package/dist/studio.css
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The visualiser hides node handles (it is read only), here they are the connection points,
|
|
3
|
+
* so show them on hover, on selection and while connecting.
|
|
4
|
+
*/
|
|
5
|
+
.studio-canvas .react-flow__handle {
|
|
6
|
+
opacity: 0 !important;
|
|
7
|
+
width: 11px;
|
|
8
|
+
height: 11px;
|
|
9
|
+
background: rgb(var(--ec-card-bg));
|
|
10
|
+
border: 2px solid rgb(var(--ec-accent));
|
|
11
|
+
transition: opacity 0.15s ease;
|
|
12
|
+
z-index: 30;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.studio-canvas .react-flow__node:hover .react-flow__handle,
|
|
16
|
+
.studio-canvas .react-flow__node.selected .react-flow__handle,
|
|
17
|
+
.studio-canvas .react-flow__pane.connecting ~ * .react-flow__handle,
|
|
18
|
+
.studio-canvas .react-flow__handle.connectingto {
|
|
19
|
+
opacity: 1 !important;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.studio-canvas .react-flow__handle:hover,
|
|
23
|
+
.studio-canvas .react-flow__handle.connectingto {
|
|
24
|
+
background: rgb(var(--ec-accent));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.studio-canvas .react-flow__handle.connectingto.valid {
|
|
28
|
+
background: rgb(var(--ec-badge-color-green-text));
|
|
29
|
+
border-color: rgb(var(--ec-badge-color-green-text));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.studio-canvas .react-flow__edge.selected .react-flow__edge-path,
|
|
33
|
+
.studio-canvas .react-flow__edge:hover .react-flow__edge-path {
|
|
34
|
+
stroke: rgb(var(--ec-accent)) !important;
|
|
35
|
+
stroke-width: 2px !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* A connection being dragged (a new one, or an end moved to another node): once it's on a node it can connect
|
|
40
|
+
* to, it turns the hover colour, so you know letting go will connect it
|
|
41
|
+
*/
|
|
42
|
+
.studio-canvas .react-flow__connection-path {
|
|
43
|
+
stroke-width: 2px;
|
|
44
|
+
transition: stroke 100ms ease;
|
|
45
|
+
}
|
|
46
|
+
/* Like a hovered edge in the visualiser: glowing, with the dashes flowing (ec-edge-dash, from its styles) */
|
|
47
|
+
.studio-canvas .react-flow__connection.valid .react-flow__connection-path {
|
|
48
|
+
stroke: #2563eb;
|
|
49
|
+
stroke-width: 4px;
|
|
50
|
+
filter: drop-shadow(0 0 8px #2563eb);
|
|
51
|
+
stroke-dasharray: 5 5;
|
|
52
|
+
animation: ec-edge-dash 0.5s linear infinite;
|
|
53
|
+
}
|
|
54
|
+
[data-theme='dark'] .studio-canvas .react-flow__connection.valid .react-flow__connection-path {
|
|
55
|
+
stroke: #00d9ff;
|
|
56
|
+
filter: drop-shadow(0 0 8px #00d9ff);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Comment mode (C): click anywhere to drop a comment */
|
|
60
|
+
.studio-canvas.comment-mode .react-flow__pane,
|
|
61
|
+
.studio-canvas.comment-mode .react-flow__node {
|
|
62
|
+
cursor: crosshair !important;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* After a layout or a level change, nodes glide to their new place */
|
|
66
|
+
.studio-canvas.is-layout-transition .react-flow__node {
|
|
67
|
+
transition: transform 450ms ease;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Edges are drawn where the nodes end up, so they wait for the glide to finish */
|
|
71
|
+
.studio-canvas .react-flow__edges {
|
|
72
|
+
transition: opacity 200ms ease;
|
|
73
|
+
}
|
|
74
|
+
.studio-canvas.is-layout-transition .react-flow__edges {
|
|
75
|
+
opacity: 0;
|
|
76
|
+
transition: none;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Containers grow smoothly when they're fitted to what's in them, or someone else resizes them */
|
|
80
|
+
.studio-canvas.is-container-resize :is(.react-flow__node-domain-group, .react-flow__node-system-group) {
|
|
81
|
+
transition:
|
|
82
|
+
width 300ms ease,
|
|
83
|
+
height 300ms ease,
|
|
84
|
+
transform 300ms ease;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Nodes pop in when they're added (by anyone, people or agents) */
|
|
88
|
+
@keyframes studio-node-in {
|
|
89
|
+
from {
|
|
90
|
+
opacity: 0;
|
|
91
|
+
scale: 0.85;
|
|
92
|
+
}
|
|
93
|
+
to {
|
|
94
|
+
opacity: 1;
|
|
95
|
+
scale: 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
.studio-canvas .react-flow__node {
|
|
99
|
+
animation: studio-node-in 220ms ease-out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* No React Flow attribution on the canvas */
|
|
103
|
+
.studio-canvas .react-flow__attribution {
|
|
104
|
+
display: none;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* Containers let the pointer through their body to the canvas (so dragging inside one draws a selection box),
|
|
109
|
+
* and are moved, selected and resized by their header and resize handles. React Flow sets pointer-events inline.
|
|
110
|
+
*/
|
|
111
|
+
.studio-canvas .react-flow__node-domain-group,
|
|
112
|
+
.studio-canvas .react-flow__node-system-group {
|
|
113
|
+
pointer-events: none !important;
|
|
114
|
+
}
|
|
115
|
+
.studio-canvas .react-flow__node-domain-group :is(.ec-group-grip, .react-flow__resize-control),
|
|
116
|
+
.studio-canvas .react-flow__node-system-group :is(.ec-group-grip, .react-flow__resize-control) {
|
|
117
|
+
pointer-events: auto;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* Selected nodes get an accent outline and glow around them, and hovered ones a faint outline (like Figma and
|
|
122
|
+
* Miro). Drawn by the node's wrapper, so it fits every kind of node. Containers draw their own.
|
|
123
|
+
*/
|
|
124
|
+
.studio-canvas .react-flow__node:not(.react-flow__node-domain-group, .react-flow__node-system-group, .react-flow__node-text)::after {
|
|
125
|
+
content: '';
|
|
126
|
+
position: absolute;
|
|
127
|
+
inset: -6px;
|
|
128
|
+
border-radius: 12px;
|
|
129
|
+
border: 2px solid transparent;
|
|
130
|
+
pointer-events: none;
|
|
131
|
+
transition:
|
|
132
|
+
border-color 120ms ease,
|
|
133
|
+
box-shadow 120ms ease;
|
|
134
|
+
}
|
|
135
|
+
.studio-canvas .react-flow__node:not(.react-flow__node-domain-group, .react-flow__node-system-group, .react-flow__node-text):hover::after {
|
|
136
|
+
border-color: color-mix(in srgb, rgb(var(--ec-accent)) 35%, transparent);
|
|
137
|
+
}
|
|
138
|
+
.studio-canvas .react-flow__node.selected:not(.react-flow__node-domain-group, .react-flow__node-system-group, .react-flow__node-text)::after {
|
|
139
|
+
border-color: rgb(var(--ec-accent));
|
|
140
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, rgb(var(--ec-accent)) 15%, transparent);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* A selected or hovered connection shows the ends you can drag to another node. (Tints of the accent are mixed:
|
|
144
|
+
on the canvas it's written with commas, which rgb(... / alpha) can't take) */
|
|
145
|
+
.studio-canvas .react-flow__edge .react-flow__edgeupdater {
|
|
146
|
+
cursor: grab;
|
|
147
|
+
}
|
|
148
|
+
.studio-canvas .react-flow__edge:is(.selected, :hover) .react-flow__edgeupdater {
|
|
149
|
+
fill: color-mix(in srgb, rgb(var(--ec-accent)) 20%, transparent);
|
|
150
|
+
stroke: rgb(var(--ec-accent));
|
|
151
|
+
stroke-width: 1.5;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* A selected container */
|
|
155
|
+
.studio-canvas .ec-group-selected {
|
|
156
|
+
position: absolute;
|
|
157
|
+
inset: 0;
|
|
158
|
+
border-radius: 14px;
|
|
159
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, rgb(var(--ec-accent)) 70%, transparent);
|
|
160
|
+
pointer-events: none;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* A container something's dragged over: it goes in it when it's dropped (in the theme's button colours, which stay
|
|
164
|
+
strong in light and dark themes) */
|
|
165
|
+
.studio-canvas .ec-drop-target {
|
|
166
|
+
position: absolute;
|
|
167
|
+
inset: -5px;
|
|
168
|
+
border-radius: 17px;
|
|
169
|
+
border: 3px solid rgb(var(--ec-button-bg));
|
|
170
|
+
background: rgb(var(--ec-button-bg) / 0.1);
|
|
171
|
+
box-shadow: 0 0 0 6px rgb(var(--ec-button-bg) / 0.2);
|
|
172
|
+
pointer-events: none;
|
|
173
|
+
animation: ec-drop-target-in 150ms ease-out;
|
|
174
|
+
}
|
|
175
|
+
.studio-canvas .ec-drop-target-label {
|
|
176
|
+
position: absolute;
|
|
177
|
+
top: -16px;
|
|
178
|
+
left: 50%;
|
|
179
|
+
translate: -50% 0;
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
border-radius: 9999px;
|
|
182
|
+
padding: 4px 12px;
|
|
183
|
+
font-size: 12px;
|
|
184
|
+
font-weight: 600;
|
|
185
|
+
color: rgb(var(--ec-button-text));
|
|
186
|
+
background: rgb(var(--ec-button-bg));
|
|
187
|
+
box-shadow: 0 2px 8px rgb(0 0 0 / 0.25);
|
|
188
|
+
}
|
|
189
|
+
@keyframes ec-drop-target-in {
|
|
190
|
+
from {
|
|
191
|
+
opacity: 0;
|
|
192
|
+
scale: 0.98;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
* What's dragged from the left panel (DragGhost): just the node, on nothing. The visualiser's class gives it the page
|
|
198
|
+
* background, and its handles are hidden on the canvas only.
|
|
199
|
+
*/
|
|
200
|
+
.studio-drag-preview,
|
|
201
|
+
.studio-drag-preview .react-flow,
|
|
202
|
+
.studio-drag-preview .react-flow__renderer,
|
|
203
|
+
.studio-drag-preview .react-flow__pane,
|
|
204
|
+
/* (over the visualiser's own, which give its diagrams the page background, the dark theme's more specifically) */
|
|
205
|
+
html[data-theme] .studio-drag-preview.eventcatalog-visualizer .react-flow,
|
|
206
|
+
html[data-theme] .studio-drag-preview.eventcatalog-visualizer .react-flow__renderer,
|
|
207
|
+
html[data-theme] .studio-drag-preview.eventcatalog-visualizer .react-flow__pane,
|
|
208
|
+
html .studio-drag-preview.eventcatalog-visualizer .react-flow {
|
|
209
|
+
background: transparent !important;
|
|
210
|
+
}
|
|
211
|
+
.studio-drag-preview .react-flow__handle {
|
|
212
|
+
display: none !important;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* Text written on the canvas: no card around it, in the page's text colour */
|
|
216
|
+
.studio-canvas .studio-text,
|
|
217
|
+
.studio-drag-preview .studio-text {
|
|
218
|
+
position: relative;
|
|
219
|
+
width: max-content;
|
|
220
|
+
min-width: 24px;
|
|
221
|
+
padding: 4px 8px;
|
|
222
|
+
transform-origin: center;
|
|
223
|
+
}
|
|
224
|
+
.studio-text .studio-text-body {
|
|
225
|
+
margin: 0;
|
|
226
|
+
/* Handwritten, as text typed on Excalidraw's canvas (Excalifont, bundled in view.css) */
|
|
227
|
+
font-family: 'Excalifont', 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
228
|
+
font-size: 22px;
|
|
229
|
+
line-height: 1.3;
|
|
230
|
+
color: rgb(var(--ec-page-text));
|
|
231
|
+
white-space: pre;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.studio-canvas .studio-width-handle {
|
|
235
|
+
border-color: rgb(var(--ec-accent)) !important;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* A sticky note: about square like a post-it, taller if more is written on it (dark text: the paper is light in
|
|
239
|
+
every theme) */
|
|
240
|
+
.studio-note {
|
|
241
|
+
position: relative;
|
|
242
|
+
display: flex;
|
|
243
|
+
flex-direction: column;
|
|
244
|
+
justify-content: center;
|
|
245
|
+
min-height: 176px;
|
|
246
|
+
height: 100%;
|
|
247
|
+
padding: 20px 18px 30px;
|
|
248
|
+
border: 1px solid;
|
|
249
|
+
border-radius: 6px;
|
|
250
|
+
box-shadow:
|
|
251
|
+
0 1px 2px rgb(0 0 0 / 0.06),
|
|
252
|
+
0 6px 16px -6px rgb(0 0 0 / 0.18);
|
|
253
|
+
color: #1f2937;
|
|
254
|
+
}
|
|
255
|
+
.studio-note .studio-note-body {
|
|
256
|
+
margin: 0;
|
|
257
|
+
/* Handwritten, as Excalidraw's notes are (Excalifont, bundled in view.css) */
|
|
258
|
+
font-family: 'Excalifont', 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
259
|
+
font-size: 22px;
|
|
260
|
+
line-height: 1.3;
|
|
261
|
+
text-align: center;
|
|
262
|
+
color: inherit;
|
|
263
|
+
white-space: pre-wrap;
|
|
264
|
+
overflow-wrap: anywhere;
|
|
265
|
+
}
|
|
266
|
+
/* The level it's on, and when it was written, in its corners */
|
|
267
|
+
.studio-note .studio-note-level,
|
|
268
|
+
.studio-note .studio-note-date {
|
|
269
|
+
position: absolute;
|
|
270
|
+
right: 14px;
|
|
271
|
+
bottom: 10px;
|
|
272
|
+
font-family: 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
273
|
+
font-size: 12px;
|
|
274
|
+
color: inherit;
|
|
275
|
+
opacity: 0.75;
|
|
276
|
+
pointer-events: none;
|
|
277
|
+
}
|
|
278
|
+
.studio-note .studio-note-level {
|
|
279
|
+
right: auto;
|
|
280
|
+
left: 14px;
|
|
281
|
+
font-weight: 600;
|
|
282
|
+
font-size: 11px;
|
|
283
|
+
letter-spacing: 0.02em;
|
|
284
|
+
opacity: 0.6;
|
|
285
|
+
}
|
|
286
|
+
.studio-note .studio-note-body::placeholder {
|
|
287
|
+
color: inherit;
|
|
288
|
+
opacity: 0.5;
|
|
289
|
+
}
|
|
290
|
+
/* Its colours, above it while it's selected */
|
|
291
|
+
.studio-note .studio-note-colors {
|
|
292
|
+
position: absolute;
|
|
293
|
+
bottom: calc(100% + 8px);
|
|
294
|
+
left: 0;
|
|
295
|
+
display: flex;
|
|
296
|
+
gap: 4px;
|
|
297
|
+
padding: 4px;
|
|
298
|
+
border-radius: 9999px;
|
|
299
|
+
border: 1px solid rgb(var(--ec-page-border));
|
|
300
|
+
background: rgb(var(--ec-card-bg));
|
|
301
|
+
box-shadow: 0 2px 8px rgb(0 0 0 / 0.15);
|
|
302
|
+
}
|
|
303
|
+
.studio-note .studio-note-color {
|
|
304
|
+
width: 16px;
|
|
305
|
+
height: 16px;
|
|
306
|
+
border-radius: 9999px;
|
|
307
|
+
border: 2px solid;
|
|
308
|
+
cursor: pointer;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* The hand: everything on the canvas is grabbed to move around it */
|
|
312
|
+
.studio-canvas.is-panning .react-flow__pane,
|
|
313
|
+
.studio-canvas.is-panning .react-flow__node,
|
|
314
|
+
.studio-canvas.is-panning .react-flow__edge { cursor: grab !important; }
|
|
315
|
+
.studio-canvas.is-panning .react-flow__pane.dragging { cursor: grabbing !important; }
|
|
316
|
+
|
|
317
|
+
/* The text tool: click anywhere on the canvas to write there */
|
|
318
|
+
.studio-canvas.is-placing .react-flow__pane,
|
|
319
|
+
.studio-canvas.is-placing .react-flow__node { cursor: crosshair !important; }
|
|
320
|
+
/* Text being written has no box around it, like Excalidraw's */
|
|
321
|
+
.studio-text textarea.studio-text-body { display: block; width: 100%; border: 0; outline: none; padding: 0; resize: none; overflow: hidden; background: transparent; }
|
|
322
|
+
|
|
323
|
+
/* Text selected: a box, with corners that scale it and a handle above that turns it, as Excalidraw's */
|
|
324
|
+
.studio-text.is-framed { outline: 1px solid rgb(var(--ec-accent)); }
|
|
325
|
+
.studio-text .studio-text-corner,
|
|
326
|
+
.studio-text .studio-text-turn {
|
|
327
|
+
position: absolute;
|
|
328
|
+
width: 10px;
|
|
329
|
+
height: 10px;
|
|
330
|
+
border: 1px solid rgb(var(--ec-accent));
|
|
331
|
+
border-radius: 3px;
|
|
332
|
+
background: rgb(var(--ec-card-bg));
|
|
333
|
+
z-index: 1;
|
|
334
|
+
}
|
|
335
|
+
.studio-text .studio-text-corner.is-top-left { left: -5px; top: -5px; cursor: nwse-resize; }
|
|
336
|
+
.studio-text .studio-text-corner.is-top-right { right: -5px; top: -5px; cursor: nesw-resize; }
|
|
337
|
+
.studio-text .studio-text-corner.is-bottom-left { left: -5px; bottom: -5px; cursor: nesw-resize; }
|
|
338
|
+
.studio-text .studio-text-corner.is-bottom-right { right: -5px; bottom: -5px; cursor: nwse-resize; }
|
|
339
|
+
.studio-text .studio-text-turn { left: calc(50% - 5px); top: -26px; border-radius: 9999px; cursor: grab; }
|
|
340
|
+
.studio-text .studio-text-turn:active { cursor: grabbing; }
|
|
341
|
+
|
|
342
|
+
/* A selected node's Edit button, above its top right corner (hidden while things move) */
|
|
343
|
+
.studio-edit-button {
|
|
344
|
+
display: inline-flex;
|
|
345
|
+
align-items: center;
|
|
346
|
+
gap: 5px;
|
|
347
|
+
height: 26px;
|
|
348
|
+
padding: 0 10px 0 8px;
|
|
349
|
+
border: 1px solid rgb(var(--ec-page-border));
|
|
350
|
+
border-radius: 7px;
|
|
351
|
+
background: rgb(var(--ec-card-bg));
|
|
352
|
+
color: rgb(var(--ec-page-text));
|
|
353
|
+
font: 600 12px/1 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
354
|
+
box-shadow: 0 2px 6px rgb(0 0 0 / 0.1);
|
|
355
|
+
cursor: pointer;
|
|
356
|
+
}
|
|
357
|
+
.studio-edit-button:hover { background: rgb(var(--ec-content-hover)); border-color: rgb(var(--ec-accent)); }
|
|
358
|
+
.studio-edit-button svg { width: 12px; height: 12px; }
|
|
359
|
+
.ec-interaction-active .react-flow__node-toolbar { visibility: hidden; }
|
|
360
|
+
|
|
361
|
+
/* Each kind's icon colour (the visualiser's -600s) is too dark on the dark theme's cards: a lighter shade there, as
|
|
362
|
+
EventCatalog's dark theme uses (on the canvas and what's dragged onto it: not the rest of the page it's on) */
|
|
363
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-pink-600 { color: #f472b6; }
|
|
364
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-orange-600 { color: #fb923c; }
|
|
365
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-blue-600 { color: #60a5fa; }
|
|
366
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-green-600 { color: #4ade80; }
|
|
367
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-gray-600 { color: #9ca3af; }
|
|
368
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-violet-600 { color: #a78bfa; }
|
|
369
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-purple-600 { color: #c084fc; }
|
|
370
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-sky-600 { color: #38bdf8; }
|
|
371
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-emerald-600 { color: #34d399; }
|
|
372
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-indigo-600 { color: #818cf8; }
|
|
373
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-teal-600 { color: #2dd4bf; }
|
|
374
|
+
:root[data-theme='dark'] :is(.studio-canvas, .studio-drag-preview) svg.text-cyan-600 { color: #22d3ee; }
|
|
375
|
+
|
|
376
|
+
/* An entity's whole-entity source, on its header's right (level with the visualiser's target on the left) */
|
|
377
|
+
.studio-canvas .react-flow__handle.studio-entity-source { top: 29px !important; }
|
|
378
|
+
|
|
379
|
+
/* The other people in a live room: their cursor and name, in their colour */
|
|
380
|
+
.studio-live-cursor {
|
|
381
|
+
position: absolute;
|
|
382
|
+
left: 0;
|
|
383
|
+
top: 0;
|
|
384
|
+
transform-origin: 0 0;
|
|
385
|
+
pointer-events: none;
|
|
386
|
+
z-index: 1000;
|
|
387
|
+
/* (no transition: it glides a step a frame, see smooth.ts) */
|
|
388
|
+
}
|
|
389
|
+
.studio-live-cursor span {
|
|
390
|
+
position: absolute;
|
|
391
|
+
left: 14px;
|
|
392
|
+
top: 16px;
|
|
393
|
+
padding: 2px 7px;
|
|
394
|
+
border-radius: 6px;
|
|
395
|
+
color: white;
|
|
396
|
+
font: 600 11px/1.4 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
397
|
+
white-space: nowrap;
|
|
398
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 0.2);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/* The canvas's dots on the dark theme: the visualiser's are bright enough to busy the page, so a quieter grey, as
|
|
402
|
+
Excalidraw's are */
|
|
403
|
+
[data-theme='dark'] .eventcatalog-visualizer.studio-canvas { --ec-bg-dots: #353b46; }
|
|
404
|
+
|
|
405
|
+
/* A picked tool or level on the dark theme: the accent's -600 on its own tint is hard to read there, so a lighter
|
|
406
|
+
indigo on a slightly stronger tint (the canvas's own buttons, not the page's) */
|
|
407
|
+
:root[data-theme='dark'] .studio-canvas button[aria-pressed='true'] { color: #a5b4fc; background-color: rgb(99 102 241 / 0.24); }
|
|
408
|
+
:root[data-theme='dark'] .studio-canvas button[aria-pressed='true']:hover { background-color: rgb(99 102 241 / 0.32); }
|
|
409
|
+
|
|
410
|
+
/* Hotspots: a node with any glows in the colour of the most important (critical red, warning amber, info blue), so
|
|
411
|
+
it's found at a glance; their markers sit on its top right corner (Hotspots.tsx). The glow is still: an animated
|
|
412
|
+
one cost every frame for every hotspot, idle (10 hotspots: ~200 ms of every 3 seconds, against ~2 ms) */
|
|
413
|
+
.studio-canvas .react-flow__node.studio-hotspot { --studio-hotspot: 217 119 6; border-radius: 14px; }
|
|
414
|
+
.studio-canvas .react-flow__node.studio-hotspot-critical { --studio-hotspot: 220 38 38; }
|
|
415
|
+
.studio-canvas .react-flow__node.studio-hotspot-info { --studio-hotspot: 37 99 235; }
|
|
416
|
+
.studio-canvas .react-flow__node.studio-hotspot::before {
|
|
417
|
+
content: '';
|
|
418
|
+
position: absolute;
|
|
419
|
+
inset: -7px;
|
|
420
|
+
border-radius: 16px;
|
|
421
|
+
border: 2px solid rgb(var(--studio-hotspot) / 0.85);
|
|
422
|
+
box-shadow: 0 0 0 4px rgb(var(--studio-hotspot) / 0.12), 0 0 22px 2px rgb(var(--studio-hotspot) / 0.35);
|
|
423
|
+
pointer-events: none;
|
|
424
|
+
}
|
|
425
|
+
.studio-hotspot-marker {
|
|
426
|
+
box-shadow: 0 0 0 2px rgb(var(--ec-card-bg)), 0 4px 12px rgb(0 0 0 / 0.25);
|
|
427
|
+
transition: transform 120ms;
|
|
428
|
+
}
|
|
429
|
+
.studio-hotspot-marker:hover { transform: scale(1.05); }
|
|
430
|
+
/* Zoomed well out: just each marker's icon (its title is in the list, and on hover) */
|
|
431
|
+
.is-icons-only .studio-hotspot-label { display: none; }
|
|
432
|
+
.is-icons-only .studio-hotspot-marker { padding-right: 4px; }
|
|
433
|
+
/* An open marker's panel (or the form adding one): its full size on screen however far out the canvas is */
|
|
434
|
+
.studio-hotspot-panel { transform: scale(var(--studio-hotspot-panel-scale, 1)); transform-origin: 0 -34px; }
|
|
435
|
+
|
|
436
|
+
/* A hotspot being dragged over a node: the node lights up in its colour, to show it'll go on it when dropped */
|
|
437
|
+
.studio-canvas .react-flow__node.studio-hotspot-drop { --studio-hotspot-drop: 217 119 6; border-radius: 14px; }
|
|
438
|
+
.studio-canvas .react-flow__node.studio-hotspot-drop-critical { --studio-hotspot-drop: 220 38 38; }
|
|
439
|
+
.studio-canvas .react-flow__node.studio-hotspot-drop-info { --studio-hotspot-drop: 37 99 235; }
|
|
440
|
+
.studio-canvas .react-flow__node.studio-hotspot-drop::before {
|
|
441
|
+
content: '';
|
|
442
|
+
position: absolute;
|
|
443
|
+
inset: -8px;
|
|
444
|
+
border-radius: 16px;
|
|
445
|
+
border: 2.5px dashed rgb(var(--studio-hotspot-drop));
|
|
446
|
+
background: rgb(var(--studio-hotspot-drop) / 0.08);
|
|
447
|
+
box-shadow: 0 0 0 6px rgb(var(--studio-hotspot-drop) / 0.15), 0 0 32px 6px rgb(var(--studio-hotspot-drop) / 0.45);
|
|
448
|
+
pointer-events: none;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/*
|
|
452
|
+
* A node's card (NodeCard.tsx), next to it on the canvas: its header, and the form that edits it, its fields saved as
|
|
453
|
+
* they're typed.
|
|
454
|
+
*/
|
|
455
|
+
/* Icon buttons, as EventCatalog's (Studio's Dialog.tsx and CanvasHeader.tsx) */
|
|
456
|
+
.ec-icon-button {
|
|
457
|
+
display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; flex-shrink: 0; border: 0;
|
|
458
|
+
border-radius: 6px; background: transparent; color: rgb(var(--ec-page-text-muted)); cursor: pointer;
|
|
459
|
+
}
|
|
460
|
+
.ec-icon-button:hover:not(:disabled) { color: rgb(var(--ec-page-text)); background: rgb(var(--ec-page-border) / 0.4); }
|
|
461
|
+
.ec-icon-button:disabled { opacity: 0.35; cursor: default; }
|
|
462
|
+
.ec-icon-button svg { width: 15px; height: 15px; }
|
|
463
|
+
/* A node's page: a small docs page (the catalog's resource header, badges, toolbar and Sends / Receives lists) */
|
|
464
|
+
.ec-doc-card {
|
|
465
|
+
position: absolute; z-index: 30; max-height: calc(100% - 110px); overflow-y: auto; border: 1px solid rgb(var(--ec-page-border));
|
|
466
|
+
border-radius: 12px; background: rgb(var(--ec-card-bg)); color: rgb(var(--ec-page-text)); box-shadow: 0 24px 48px rgb(0 0 0 / 0.16), 0 2px 6px rgb(0 0 0 / 0.06);
|
|
467
|
+
font-family: 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
468
|
+
}
|
|
469
|
+
/* The card's arrow, to the node it's about: a square turned on its corner, over the card's edge */
|
|
470
|
+
.ec-doc-card-arrow {
|
|
471
|
+
position: absolute; z-index: 31; width: 14px; height: 14px; background: rgb(var(--ec-card-bg)); transform: rotate(45deg);
|
|
472
|
+
border: 1px solid rgb(var(--ec-page-border)); pointer-events: none;
|
|
473
|
+
}
|
|
474
|
+
.ec-doc-card-arrow.is-right { border-top-color: transparent; border-right-color: transparent; }
|
|
475
|
+
.ec-doc-card-arrow.is-left { border-bottom-color: transparent; border-left-color: transparent; }
|
|
476
|
+
/* Nothing under the header: no line under it either */
|
|
477
|
+
.ec-doc-card-header:last-child { border-bottom: 0; }
|
|
478
|
+
.ec-doc-card-header { padding: 14px 16px 12px; border-bottom: 1px solid rgb(var(--ec-page-border)); }
|
|
479
|
+
.ec-doc-card-kicker { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
480
|
+
.ec-doc-card-breadcrumb { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: rgb(var(--ec-page-text-muted)); font-size: 12px; }
|
|
481
|
+
.ec-doc-card-close { margin-left: auto; margin-right: -6px; }
|
|
482
|
+
.ec-doc-card-title { margin: 10px 0 0; font-size: 20px; font-weight: 700; line-height: 1.25; letter-spacing: -0.01em; }
|
|
483
|
+
.ec-doc-card-version { margin-left: 8px; font-size: 12px; font-weight: 500; color: rgb(var(--ec-page-text-muted)); letter-spacing: 0; }
|
|
484
|
+
.ec-doc-card-summary { margin: 8px 0 0; font-size: 13px; font-weight: 300; line-height: 1.55; color: rgb(var(--ec-page-text-muted)); }
|
|
485
|
+
/* Editing it: a small form, its fields plainly fields (a border, a focus ring), saved as they're typed */
|
|
486
|
+
.ec-edit-form { display: flex; flex-wrap: wrap; gap: 12px 10px; margin-top: 14px; }
|
|
487
|
+
.ec-field { display: flex; flex: 1 1 100%; flex-direction: column; gap: 5px; min-width: 0; }
|
|
488
|
+
.ec-field-version { flex: 0 0 120px; }
|
|
489
|
+
.ec-field-label { font-size: 11px; font-weight: 600; letter-spacing: 0.02em; color: rgb(var(--ec-page-text-muted)); }
|
|
490
|
+
.ec-editable {
|
|
491
|
+
box-sizing: border-box; display: block; width: 100%; padding: 7px 10px; border: 1px solid rgb(var(--ec-page-border)); border-radius: 8px;
|
|
492
|
+
background: rgb(var(--ec-page-bg)); color: rgb(var(--ec-page-text)); font: inherit; font-size: 13px; line-height: 1.4; outline: none; resize: none;
|
|
493
|
+
transition: border-color 120ms, box-shadow 120ms, background 120ms;
|
|
494
|
+
}
|
|
495
|
+
.ec-editable:hover { border-color: color-mix(in srgb, rgb(var(--ec-page-text-muted)) 55%, transparent); }
|
|
496
|
+
.ec-editable:focus {
|
|
497
|
+
border-color: rgb(var(--ec-accent)); background: rgb(var(--ec-card-bg));
|
|
498
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, rgb(var(--ec-accent)) 18%, transparent);
|
|
499
|
+
}
|
|
500
|
+
.ec-editable::placeholder { color: rgb(var(--ec-page-text-muted)); opacity: 0.7; }
|
|
501
|
+
.ec-editable-title { font-size: 15px; font-weight: 600; }
|
|
502
|
+
.ec-editable-summary { min-height: 60px; overflow: hidden; line-height: 1.5; }
|
|
503
|
+
.ec-edit-status {
|
|
504
|
+
display: inline-flex; flex: 1 1 100%; align-items: center; gap: 4px; margin: -4px 0 0; font-size: 11px;
|
|
505
|
+
color: rgb(var(--ec-page-text-muted)); opacity: 0.8; transition: color 150ms;
|
|
506
|
+
}
|
|
507
|
+
.ec-edit-status.is-saved { color: #16a34a; opacity: 1; }
|
|
508
|
+
.ec-edit-status svg { width: 12px; height: 12px; }
|
|
509
|
+
.ec-doc-card-header:has(+ .ec-doc-card-body:empty) { border-bottom: 0; }
|