@eventcatalog/visualiser 5.1.1 → 5.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.
- package/dist/{chunk-ZHXUMAPK.mjs → chunk-QQUJTD6O.mjs} +1864 -1327
- package/dist/chunk-QQUJTD6O.mjs.map +1 -0
- package/dist/index.d.mts +5 -14
- package/dist/index.d.ts +5 -14
- package/dist/index.js +1709 -1418
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -3
- package/dist/node-card.css +262 -0
- package/dist/studio.css +3 -31
- package/dist/studio.d.mts +263 -127
- package/dist/studio.mjs +1016 -1192
- package/dist/studio.mjs.map +1 -1
- package/dist/styles-core.css +283 -9
- package/dist/styles.css +283 -9
- package/package.json +2 -2
- package/dist/chunk-ZHXUMAPK.mjs.map +0 -1
package/dist/studio.mjs
CHANGED
|
@@ -1,22 +1,52 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CATALOG_COLLECTIONS,
|
|
3
|
+
CATALOG_GROUPS,
|
|
4
|
+
COMPONENT_TYPES,
|
|
2
5
|
CanvasPortal,
|
|
6
|
+
DEFAULT_NODE_SIZE,
|
|
3
7
|
DIAGRAM_FIT_VIEW_OPTIONS,
|
|
4
8
|
DomainCard_default,
|
|
5
9
|
ENTITY_TARGET_HANDLE_ID,
|
|
6
10
|
EdgeLabelPortal,
|
|
11
|
+
EditStatus,
|
|
12
|
+
EditableText,
|
|
7
13
|
Entity_default,
|
|
14
|
+
Field,
|
|
15
|
+
GROUP_TYPES,
|
|
16
|
+
NODE_CATEGORIES,
|
|
17
|
+
NODE_ICONS,
|
|
18
|
+
NodeCard,
|
|
8
19
|
SystemGroupNode_default,
|
|
9
20
|
Toolbar,
|
|
10
21
|
ToolbarButton,
|
|
11
22
|
ToolbarDivider,
|
|
12
23
|
ZoomLevel,
|
|
13
24
|
addExportBranding,
|
|
25
|
+
canGoInContainer,
|
|
26
|
+
canHold,
|
|
27
|
+
componentKey,
|
|
14
28
|
diagramNodeComponents,
|
|
15
29
|
eventcatalog_logo_default,
|
|
16
30
|
getExportImageDimensions,
|
|
31
|
+
getNodeDefinition,
|
|
32
|
+
getNodeLabel,
|
|
33
|
+
getNodeName,
|
|
34
|
+
getNodeSize as getNodeSize2,
|
|
35
|
+
getNoteLevel,
|
|
36
|
+
getResource,
|
|
17
37
|
injectExportStyles,
|
|
18
|
-
|
|
19
|
-
|
|
38
|
+
isCatalogCollection,
|
|
39
|
+
isGroupType,
|
|
40
|
+
isOnLevel,
|
|
41
|
+
isShownOnLevel,
|
|
42
|
+
isVersioned,
|
|
43
|
+
isWrittenOnCanvas,
|
|
44
|
+
memoNode,
|
|
45
|
+
nodeDefinitions,
|
|
46
|
+
updateResource,
|
|
47
|
+
useNodeAnchor,
|
|
48
|
+
useSavedFlash
|
|
49
|
+
} from "./chunk-QQUJTD6O.mjs";
|
|
20
50
|
import "./chunk-STJQWGKW.mjs";
|
|
21
51
|
import {
|
|
22
52
|
getMessagesLabel,
|
|
@@ -105,317 +135,6 @@ var createEdge = (connection, sourceType, targetType) => {
|
|
|
105
135
|
};
|
|
106
136
|
};
|
|
107
137
|
|
|
108
|
-
// src/studio/node-types.ts
|
|
109
|
-
var NODE_CATEGORIES = [
|
|
110
|
-
{ id: "boundaries", label: "Boundaries" },
|
|
111
|
-
// What's deployed (services, UIs, agents) and what's outside it: drawn first, then what flows between them
|
|
112
|
-
{ id: "architecture", label: "Services" },
|
|
113
|
-
{ id: "messages", label: "Messages" },
|
|
114
|
-
// Where data lives: all data nodes, of EventCatalog's kinds (container_type)
|
|
115
|
-
{ id: "data", label: "Data" },
|
|
116
|
-
// Who's involved: who uses the architecture (actors) and who owns it (teams)
|
|
117
|
-
{ id: "people", label: "People" },
|
|
118
|
-
{ id: "other", label: "Other" }
|
|
119
|
-
];
|
|
120
|
-
var CATALOG_COLLECTIONS = [
|
|
121
|
-
"domains",
|
|
122
|
-
"systems",
|
|
123
|
-
"services",
|
|
124
|
-
"events",
|
|
125
|
-
"commands",
|
|
126
|
-
"queries",
|
|
127
|
-
"channels",
|
|
128
|
-
"containers"
|
|
129
|
-
];
|
|
130
|
-
var isCatalogCollection = (collection) => CATALOG_COLLECTIONS.includes(collection);
|
|
131
|
-
var GROUP_TYPES = {
|
|
132
|
-
domain: "domain-group",
|
|
133
|
-
system: "system-group"
|
|
134
|
-
};
|
|
135
|
-
var isGroupType = (type) => type === GROUP_TYPES.domain || type === GROUP_TYPES.system;
|
|
136
|
-
var resource = (name, summary) => ({
|
|
137
|
-
name,
|
|
138
|
-
version: "0.0.1",
|
|
139
|
-
summary,
|
|
140
|
-
owners: []
|
|
141
|
-
});
|
|
142
|
-
var DATA_KINDS = [
|
|
143
|
-
{
|
|
144
|
-
containerType: "database",
|
|
145
|
-
label: "Database",
|
|
146
|
-
name: "New Database",
|
|
147
|
-
summary: "Tables, e.g. PostgreSQL"
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
containerType: "cache",
|
|
151
|
-
label: "Cache",
|
|
152
|
-
name: "New Cache",
|
|
153
|
-
summary: "Fast data, e.g. Redis"
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
containerType: "searchIndex",
|
|
157
|
-
label: "Search index",
|
|
158
|
-
name: "New Search Index",
|
|
159
|
-
summary: "Search, e.g. Elasticsearch"
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
containerType: "objectStore",
|
|
163
|
-
label: "Object store",
|
|
164
|
-
name: "New Object Store",
|
|
165
|
-
summary: "Files and blobs, e.g. S3"
|
|
166
|
-
}
|
|
167
|
-
];
|
|
168
|
-
var nodeDefinitions = [
|
|
169
|
-
{
|
|
170
|
-
type: GROUP_TYPES.domain,
|
|
171
|
-
firstLevel: 1,
|
|
172
|
-
label: "Domain",
|
|
173
|
-
summary: "A business area, e.g. Sales",
|
|
174
|
-
category: "boundaries",
|
|
175
|
-
resourceKey: "domain",
|
|
176
|
-
defaultSize: { width: 720, height: 460 },
|
|
177
|
-
createData: () => ({ domain: { name: "New Domain", version: "0.0.1" } })
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
type: GROUP_TYPES.system,
|
|
181
|
-
firstLevel: 1,
|
|
182
|
-
label: "System",
|
|
183
|
-
summary: "Services doing one job",
|
|
184
|
-
category: "boundaries",
|
|
185
|
-
resourceKey: "system",
|
|
186
|
-
defaultSize: { width: 560, height: 360 },
|
|
187
|
-
createData: () => ({ system: { name: "New System", version: "0.0.1" } })
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
type: "service",
|
|
191
|
-
firstLevel: 2,
|
|
192
|
-
category: "architecture",
|
|
193
|
-
label: "Service",
|
|
194
|
-
summary: "An API, worker or function",
|
|
195
|
-
resourceKey: "service",
|
|
196
|
-
createData: () => ({
|
|
197
|
-
mode: "full",
|
|
198
|
-
service: {
|
|
199
|
-
...resource("New Service", "Describe what this service does."),
|
|
200
|
-
sends: [],
|
|
201
|
-
receives: []
|
|
202
|
-
}
|
|
203
|
-
})
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
type: "event",
|
|
207
|
-
firstLevel: 3,
|
|
208
|
-
category: "messages",
|
|
209
|
-
label: "Event",
|
|
210
|
-
summary: "Something that happened",
|
|
211
|
-
resourceKey: "message",
|
|
212
|
-
createData: () => ({
|
|
213
|
-
mode: "full",
|
|
214
|
-
message: resource("NewEvent", "Something happened.")
|
|
215
|
-
})
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
type: "command",
|
|
219
|
-
firstLevel: 3,
|
|
220
|
-
category: "messages",
|
|
221
|
-
label: "Command",
|
|
222
|
-
summary: "A request to do something",
|
|
223
|
-
resourceKey: "message",
|
|
224
|
-
createData: () => ({
|
|
225
|
-
mode: "full",
|
|
226
|
-
message: resource("NewCommand", "Asks a service to do something.")
|
|
227
|
-
})
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
type: "query",
|
|
231
|
-
firstLevel: 3,
|
|
232
|
-
category: "messages",
|
|
233
|
-
label: "Query",
|
|
234
|
-
summary: "A request for data",
|
|
235
|
-
resourceKey: "message",
|
|
236
|
-
createData: () => ({
|
|
237
|
-
mode: "full",
|
|
238
|
-
message: resource("NewQuery", "Asks for some information.")
|
|
239
|
-
})
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
type: "channel",
|
|
243
|
-
firstLevel: 3,
|
|
244
|
-
// With the messages it carries
|
|
245
|
-
category: "messages",
|
|
246
|
-
label: "Channel",
|
|
247
|
-
summary: "A topic, queue or bus",
|
|
248
|
-
resourceKey: "channel",
|
|
249
|
-
createData: () => ({
|
|
250
|
-
mode: "full",
|
|
251
|
-
channel: {
|
|
252
|
-
...resource("new.channel", "Where messages are routed."),
|
|
253
|
-
protocols: []
|
|
254
|
-
}
|
|
255
|
-
})
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
type: "view",
|
|
259
|
-
firstLevel: 2,
|
|
260
|
-
category: "architecture",
|
|
261
|
-
label: "View",
|
|
262
|
-
summary: "A screen or app people use",
|
|
263
|
-
resourceKey: "view",
|
|
264
|
-
createData: () => ({
|
|
265
|
-
mode: "full",
|
|
266
|
-
view: resource("New View", "What the user sees.")
|
|
267
|
-
})
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
type: "externalSystem",
|
|
271
|
-
firstLevel: 1,
|
|
272
|
-
category: "architecture",
|
|
273
|
-
label: "External System",
|
|
274
|
-
summary: "A third party you use",
|
|
275
|
-
resourceKey: "externalSystem",
|
|
276
|
-
createData: () => ({
|
|
277
|
-
mode: "full",
|
|
278
|
-
externalSystem: resource("External System", "A third party system.")
|
|
279
|
-
})
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
type: "agent",
|
|
283
|
-
// The detail of how things work, like messages: shown on L3 (L1 and L2 draw past it)
|
|
284
|
-
firstLevel: 3,
|
|
285
|
-
category: "architecture",
|
|
286
|
-
label: "Agent",
|
|
287
|
-
summary: "An AI agent at work",
|
|
288
|
-
resourceKey: "agent",
|
|
289
|
-
createData: () => ({
|
|
290
|
-
mode: "full",
|
|
291
|
-
agent: {
|
|
292
|
-
...resource("New Agent", "What this agent does."),
|
|
293
|
-
sends: [],
|
|
294
|
-
receives: []
|
|
295
|
-
}
|
|
296
|
-
})
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
type: "actor",
|
|
300
|
-
firstLevel: 1,
|
|
301
|
-
// Who uses the architecture: customers, operators, partners (Studio's actors)
|
|
302
|
-
category: "people",
|
|
303
|
-
label: "Actor",
|
|
304
|
-
summary: "Someone who uses it",
|
|
305
|
-
// Drawn like the visualiser's actors (by name only); the summary is for agents and the properties panel
|
|
306
|
-
createData: () => ({ mode: "full", name: "Customer", summary: "" })
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
type: "team",
|
|
310
|
-
firstLevel: 1,
|
|
311
|
-
// Who owns what: connected to a domain, system or service, it's its owner (EventCatalog's owners)
|
|
312
|
-
category: "people",
|
|
313
|
-
label: "Team",
|
|
314
|
-
summary: "Who owns what",
|
|
315
|
-
resourceKey: "team",
|
|
316
|
-
createData: () => ({
|
|
317
|
-
mode: "full",
|
|
318
|
-
team: resource("New Team", "What this team looks after.")
|
|
319
|
-
})
|
|
320
|
-
},
|
|
321
|
-
{
|
|
322
|
-
type: "text",
|
|
323
|
-
// On the bar at the top (T, N), not in the palette
|
|
324
|
-
unlisted: true,
|
|
325
|
-
firstLevel: 2,
|
|
326
|
-
category: "other",
|
|
327
|
-
label: "Text",
|
|
328
|
-
defaultSize: { width: 240, height: 40 },
|
|
329
|
-
autoSize: true,
|
|
330
|
-
createData: () => ({ text: "Add some text" })
|
|
331
|
-
},
|
|
332
|
-
{
|
|
333
|
-
type: "note",
|
|
334
|
-
// On the bar at the top (T, N), not in the palette
|
|
335
|
-
unlisted: true,
|
|
336
|
-
firstLevel: 1,
|
|
337
|
-
category: "other",
|
|
338
|
-
label: "Sticky Note",
|
|
339
|
-
// About square, like a post-it (taller if more is written on it)
|
|
340
|
-
defaultSize: { width: 200, height: 176 },
|
|
341
|
-
autoHeight: true,
|
|
342
|
-
createData: () => ({ text: "", color: "yellow" })
|
|
343
|
-
},
|
|
344
|
-
// The kinds of data store: all data nodes (EventCatalog's containers), told apart by their container_type
|
|
345
|
-
...DATA_KINDS.map(
|
|
346
|
-
({ containerType, label, name, summary }) => ({
|
|
347
|
-
type: "data",
|
|
348
|
-
...containerType !== "database" && { id: `data:${containerType}` },
|
|
349
|
-
firstLevel: 2,
|
|
350
|
-
category: "data",
|
|
351
|
-
label,
|
|
352
|
-
summary,
|
|
353
|
-
resourceKey: "data",
|
|
354
|
-
createData: () => ({
|
|
355
|
-
mode: "full",
|
|
356
|
-
data: {
|
|
357
|
-
...resource(name, "Stores data."),
|
|
358
|
-
container_type: containerType
|
|
359
|
-
}
|
|
360
|
-
})
|
|
361
|
-
})
|
|
362
|
-
),
|
|
363
|
-
{
|
|
364
|
-
type: "entity",
|
|
365
|
-
// The domain model: detail, like messages (L3)
|
|
366
|
-
firstLevel: 3,
|
|
367
|
-
// The domain's data model, with the stores it's kept in
|
|
368
|
-
category: "data",
|
|
369
|
-
label: "Entity",
|
|
370
|
-
summary: "Part of the domain model",
|
|
371
|
-
resourceKey: "entity",
|
|
372
|
-
createData: () => ({
|
|
373
|
-
mode: "full",
|
|
374
|
-
entity: {
|
|
375
|
-
...resource("NewEntity", "Something the domain keeps track of."),
|
|
376
|
-
properties: [
|
|
377
|
-
{ name: "id", type: "string", required: true },
|
|
378
|
-
{ name: "createdAt", type: "string" }
|
|
379
|
-
]
|
|
380
|
-
}
|
|
381
|
-
})
|
|
382
|
-
}
|
|
383
|
-
];
|
|
384
|
-
var componentKey = (definition) => definition.id ?? definition.type;
|
|
385
|
-
var COMPONENT_TYPES = [
|
|
386
|
-
...new Set(
|
|
387
|
-
nodeDefinitions.filter((definition) => !definition.unlisted).map((definition) => definition.type)
|
|
388
|
-
)
|
|
389
|
-
];
|
|
390
|
-
var definitionsByType = new Map(
|
|
391
|
-
nodeDefinitions.map((definition) => [componentKey(definition), definition])
|
|
392
|
-
);
|
|
393
|
-
var catalogNodeTypes = {
|
|
394
|
-
system: { label: "System", resourceKey: "system", firstLevel: 1 },
|
|
395
|
-
"context-domain": { label: "Domain", resourceKey: "domain", firstLevel: 1 }
|
|
396
|
-
};
|
|
397
|
-
var getNodeDefinition = (type) => type ? definitionsByType.get(type) : void 0;
|
|
398
|
-
var getNodeLabel = (type) => getNodeDefinition(type)?.label ?? catalogNodeTypes[type ?? ""]?.label ?? "Node";
|
|
399
|
-
var DEFAULT_NODE_SIZE = { width: 240, height: 112 };
|
|
400
|
-
var getNodeSize2 = (type) => getNodeDefinition(type)?.defaultSize ?? DEFAULT_NODE_SIZE;
|
|
401
|
-
var getResourceKey = (type) => getNodeDefinition(type)?.resourceKey ?? catalogNodeTypes[type ?? ""]?.resourceKey;
|
|
402
|
-
var getResource = (type, data) => {
|
|
403
|
-
const key = getResourceKey(type);
|
|
404
|
-
return key ? data[key] ?? {} : data;
|
|
405
|
-
};
|
|
406
|
-
var canGoInContainer = (type) => !isWrittenOnCanvas(type);
|
|
407
|
-
var canHold = (containerType, type) => canGoInContainer(type) && (containerType === GROUP_TYPES.domain || containerType === GROUP_TYPES.system && type !== GROUP_TYPES.domain && type !== "context-domain");
|
|
408
|
-
var getNoteLevel = (node) => isWrittenOnCanvas(node.type) ? node.data.level ?? 3 : void 0;
|
|
409
|
-
var isOnLevel = (node, level) => !isWrittenOnCanvas(node.type) || getNoteLevel(node) === level;
|
|
410
|
-
var isShownOnLevel = (type, level) => level >= (getNodeDefinition(type)?.firstLevel ?? catalogNodeTypes[type ?? ""]?.firstLevel ?? 3);
|
|
411
|
-
var isVersioned = (type) => !!getResourceKey(type);
|
|
412
|
-
var isWrittenOnCanvas = (type) => type === "note" || type === "text";
|
|
413
|
-
var updateResource = (type, data, fields) => {
|
|
414
|
-
const key = getResourceKey(type);
|
|
415
|
-
return key ? { ...data, [key]: { ...getResource(type, data), ...fields } } : { ...data, ...fields };
|
|
416
|
-
};
|
|
417
|
-
var getNodeName = (type, data, fallback = "node") => String(getResource(type, data).name ?? data.text ?? fallback);
|
|
418
|
-
|
|
419
138
|
// src/studio/grouping.ts
|
|
420
139
|
var GROUP_PADDING = { top: 80, right: 40, bottom: 40, left: 40 };
|
|
421
140
|
var byId = (nodes) => new Map(nodes.map((node) => [node.id, node]));
|
|
@@ -1350,6 +1069,228 @@ var offsetToCentre = (roots, at) => {
|
|
|
1350
1069
|
return { x: at.x - (left + right) / 2, y: at.y - (top + bottom) / 2 };
|
|
1351
1070
|
};
|
|
1352
1071
|
|
|
1072
|
+
// src/studio/connect-new.ts
|
|
1073
|
+
var CONNECT_PLACEHOLDER = "connect-placeholder";
|
|
1074
|
+
var CONNECT_PLACEHOLDER_EDGE = "connect-placeholder-edge";
|
|
1075
|
+
var CONNECT_PLACEHOLDER_SIZE = { width: 200, height: 66 };
|
|
1076
|
+
var notPlaceholder = (change) => change.type === "add" || change.id !== CONNECT_PLACEHOLDER;
|
|
1077
|
+
var linkConnection = (newId, link) => link.newIs === "target" ? {
|
|
1078
|
+
source: link.nodeId,
|
|
1079
|
+
sourceHandle: link.handleId,
|
|
1080
|
+
target: newId,
|
|
1081
|
+
targetHandle: null
|
|
1082
|
+
} : {
|
|
1083
|
+
source: newId,
|
|
1084
|
+
sourceHandle: null,
|
|
1085
|
+
target: link.nodeId,
|
|
1086
|
+
targetHandle: link.handleId
|
|
1087
|
+
};
|
|
1088
|
+
var DOMAIN_CARD = "context-domain";
|
|
1089
|
+
var SYSTEM_CARD = "system";
|
|
1090
|
+
var connectedType = (type) => type === GROUP_TYPES.domain ? DOMAIN_CARD : type === GROUP_TYPES.system ? SYSTEM_CARD : type;
|
|
1091
|
+
var isCardType = (type) => type === DOMAIN_CARD || type === SYSTEM_CARD;
|
|
1092
|
+
var newCardData = (type) => ({
|
|
1093
|
+
mode: "full",
|
|
1094
|
+
navigable: false,
|
|
1095
|
+
...getNodeDefinition(
|
|
1096
|
+
type === DOMAIN_CARD ? GROUP_TYPES.domain : GROUP_TYPES.system
|
|
1097
|
+
).createData()
|
|
1098
|
+
});
|
|
1099
|
+
var categoryOrder = new Map(
|
|
1100
|
+
NODE_CATEGORIES.map((category, index) => [category.id, index])
|
|
1101
|
+
);
|
|
1102
|
+
var getConnectOptions = (fromType, newIs, level) => nodeDefinitions.filter(
|
|
1103
|
+
(definition) => !definition.unlisted && !isWrittenOnCanvas(definition.type) && isShownOnLevel(definition.type, level)
|
|
1104
|
+
).map((definition) => {
|
|
1105
|
+
const type = connectedType(definition.type);
|
|
1106
|
+
const says = newIs === "target" ? getEdgeLabel(fromType, type) : getEdgeLabel(type, fromType);
|
|
1107
|
+
return {
|
|
1108
|
+
key: componentKey(definition),
|
|
1109
|
+
type,
|
|
1110
|
+
label: definition.label,
|
|
1111
|
+
summary: definition.summary,
|
|
1112
|
+
category: definition.category,
|
|
1113
|
+
says: says.replace(/\s+/g, " ").trim()
|
|
1114
|
+
};
|
|
1115
|
+
}).sort(
|
|
1116
|
+
(a, b) => Number(!a.says) - Number(!b.says) || (categoryOrder.get(a.category) ?? 0) - (categoryOrder.get(b.category) ?? 0)
|
|
1117
|
+
);
|
|
1118
|
+
var filterConnectOptions = (options, query) => {
|
|
1119
|
+
const words = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
1120
|
+
if (!words.length) return options;
|
|
1121
|
+
return options.filter((option) => {
|
|
1122
|
+
const text = `${option.label} ${option.summary ?? ""} ${option.says}`.toLowerCase();
|
|
1123
|
+
return words.every((word) => text.includes(word));
|
|
1124
|
+
});
|
|
1125
|
+
};
|
|
1126
|
+
var CONNECT_MIN_DISTANCE = 40;
|
|
1127
|
+
var isAwayFrom = (from, to) => Math.hypot(to.x - from.x, to.y - from.y) >= CONNECT_MIN_DISTANCE;
|
|
1128
|
+
var isEmptyCanvasAt = (point, canvas) => {
|
|
1129
|
+
const under = document.elementFromPoint(point.x, point.y);
|
|
1130
|
+
return !!under?.closest(".react-flow__pane") && !under.closest(".react-flow__node") && !!canvas?.contains(under);
|
|
1131
|
+
};
|
|
1132
|
+
var centreBeyond = (from, to, size) => {
|
|
1133
|
+
const dx = to.x - from.x;
|
|
1134
|
+
const dy = to.y - from.y;
|
|
1135
|
+
if (Math.abs(dx) >= Math.abs(dy))
|
|
1136
|
+
return { x: to.x + Math.sign(dx || 1) * (size.width / 2), y: to.y };
|
|
1137
|
+
return { x: to.x, y: to.y + Math.sign(dy) * (size.height / 2) };
|
|
1138
|
+
};
|
|
1139
|
+
|
|
1140
|
+
// src/studio/use-connect-new.ts
|
|
1141
|
+
import {
|
|
1142
|
+
useCallback,
|
|
1143
|
+
useEffect,
|
|
1144
|
+
useMemo,
|
|
1145
|
+
useRef,
|
|
1146
|
+
useState
|
|
1147
|
+
} from "react";
|
|
1148
|
+
import {
|
|
1149
|
+
useReactFlow
|
|
1150
|
+
} from "@xyflow/react";
|
|
1151
|
+
var PLACEHOLDER_EDGE_STYLE = {
|
|
1152
|
+
stroke: "rgb(var(--ec-accent))",
|
|
1153
|
+
strokeWidth: 1.5,
|
|
1154
|
+
strokeDasharray: "6 4"
|
|
1155
|
+
};
|
|
1156
|
+
var placeholderPosition = ({ from, to }) => {
|
|
1157
|
+
const center = centreBeyond(from, to, CONNECT_PLACEHOLDER_SIZE);
|
|
1158
|
+
return {
|
|
1159
|
+
x: center.x - CONNECT_PLACEHOLDER_SIZE.width / 2,
|
|
1160
|
+
y: center.y - CONNECT_PLACEHOLDER_SIZE.height / 2
|
|
1161
|
+
};
|
|
1162
|
+
};
|
|
1163
|
+
function useConnectNew({
|
|
1164
|
+
canvasRef,
|
|
1165
|
+
getNode,
|
|
1166
|
+
getLevel,
|
|
1167
|
+
locked,
|
|
1168
|
+
onMake
|
|
1169
|
+
}) {
|
|
1170
|
+
const { screenToFlowPosition, flowToScreenPosition } = useReactFlow();
|
|
1171
|
+
const [connecting, setConnecting] = useState(null);
|
|
1172
|
+
const latest = useRef({ getNode, getLevel, locked, onMake, connecting });
|
|
1173
|
+
latest.current = { getNode, getLevel, locked, onMake, connecting };
|
|
1174
|
+
const reconnecting = useRef(false);
|
|
1175
|
+
const onReconnectStart = useCallback(() => {
|
|
1176
|
+
reconnecting.current = true;
|
|
1177
|
+
}, []);
|
|
1178
|
+
const onReconnectEnd = useCallback(() => {
|
|
1179
|
+
reconnecting.current = false;
|
|
1180
|
+
}, []);
|
|
1181
|
+
const onConnectEnd = useCallback(
|
|
1182
|
+
(event, state) => {
|
|
1183
|
+
const { fromNode, fromHandle } = state;
|
|
1184
|
+
if (latest.current.locked || reconnecting.current || state.isValid || state.toNode || !fromNode || !fromHandle)
|
|
1185
|
+
return;
|
|
1186
|
+
const from = latest.current.getNode(fromNode.id);
|
|
1187
|
+
if (!from) return;
|
|
1188
|
+
const { clientX, clientY } = "changedTouches" in event ? event.changedTouches[0] : event;
|
|
1189
|
+
const to = screenToFlowPosition({ x: clientX, y: clientY });
|
|
1190
|
+
if (!isAwayFrom(state.from, to) || !isEmptyCanvasAt({ x: clientX, y: clientY }, canvasRef.current))
|
|
1191
|
+
return;
|
|
1192
|
+
const newIs = fromHandle.type === "source" ? "target" : "source";
|
|
1193
|
+
const options = getConnectOptions(
|
|
1194
|
+
from.type,
|
|
1195
|
+
newIs,
|
|
1196
|
+
latest.current.getLevel()
|
|
1197
|
+
);
|
|
1198
|
+
if (!options.length) return;
|
|
1199
|
+
setConnecting({
|
|
1200
|
+
link: { nodeId: from.id, handleId: fromHandle.id ?? null, newIs },
|
|
1201
|
+
fromName: getNodeName(from.type, from.data),
|
|
1202
|
+
options,
|
|
1203
|
+
from: state.from,
|
|
1204
|
+
to
|
|
1205
|
+
});
|
|
1206
|
+
},
|
|
1207
|
+
[screenToFlowPosition, canvasRef]
|
|
1208
|
+
);
|
|
1209
|
+
const placeholder = useMemo(() => {
|
|
1210
|
+
if (!connecting) return null;
|
|
1211
|
+
const { choice } = connecting;
|
|
1212
|
+
const data = {
|
|
1213
|
+
choice: choice && {
|
|
1214
|
+
key: choice.key,
|
|
1215
|
+
label: choice.label,
|
|
1216
|
+
summary: choice.summary
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
const node = {
|
|
1220
|
+
id: CONNECT_PLACEHOLDER,
|
|
1221
|
+
type: CONNECT_PLACEHOLDER,
|
|
1222
|
+
position: placeholderPosition(connecting),
|
|
1223
|
+
data,
|
|
1224
|
+
draggable: false,
|
|
1225
|
+
selectable: false,
|
|
1226
|
+
connectable: false,
|
|
1227
|
+
focusable: false,
|
|
1228
|
+
deletable: false,
|
|
1229
|
+
zIndex: 1e3
|
|
1230
|
+
};
|
|
1231
|
+
const edge = {
|
|
1232
|
+
id: CONNECT_PLACEHOLDER_EDGE,
|
|
1233
|
+
...linkConnection(CONNECT_PLACEHOLDER, connecting.link),
|
|
1234
|
+
type: "smoothstep",
|
|
1235
|
+
style: PLACEHOLDER_EDGE_STYLE,
|
|
1236
|
+
selectable: false,
|
|
1237
|
+
focusable: false,
|
|
1238
|
+
deletable: false
|
|
1239
|
+
};
|
|
1240
|
+
return { node, edge };
|
|
1241
|
+
}, [connecting]);
|
|
1242
|
+
const highlight = useCallback(
|
|
1243
|
+
(choice) => setConnecting(
|
|
1244
|
+
(current) => current && current.choice?.key !== choice?.key ? { ...current, choice } : current
|
|
1245
|
+
),
|
|
1246
|
+
[]
|
|
1247
|
+
);
|
|
1248
|
+
const cancel = useCallback(() => setConnecting(null), []);
|
|
1249
|
+
const choose = useCallback((option) => {
|
|
1250
|
+
const { connecting: at, locked: isLocked, onMake: make } = latest.current;
|
|
1251
|
+
setConnecting(null);
|
|
1252
|
+
if (!at || isLocked) return;
|
|
1253
|
+
make(
|
|
1254
|
+
option,
|
|
1255
|
+
centreBeyond(at.from, at.to, getNodeSize2(option.type)),
|
|
1256
|
+
at.link
|
|
1257
|
+
);
|
|
1258
|
+
}, []);
|
|
1259
|
+
useEffect(() => {
|
|
1260
|
+
if (locked) setConnecting(null);
|
|
1261
|
+
}, [locked]);
|
|
1262
|
+
let chooser = null;
|
|
1263
|
+
if (connecting && placeholder) {
|
|
1264
|
+
const { x, y } = placeholder.node.position;
|
|
1265
|
+
const start = flowToScreenPosition({ x, y });
|
|
1266
|
+
const end = flowToScreenPosition({
|
|
1267
|
+
x: x + CONNECT_PLACEHOLDER_SIZE.width,
|
|
1268
|
+
y: y + CONNECT_PLACEHOLDER_SIZE.height
|
|
1269
|
+
});
|
|
1270
|
+
chooser = {
|
|
1271
|
+
options: connecting.options,
|
|
1272
|
+
fromName: connecting.fromName,
|
|
1273
|
+
anchor: {
|
|
1274
|
+
x: start.x,
|
|
1275
|
+
y: start.y,
|
|
1276
|
+
width: end.x - start.x,
|
|
1277
|
+
height: end.y - start.y
|
|
1278
|
+
},
|
|
1279
|
+
onHighlight: highlight,
|
|
1280
|
+
onChoose: choose,
|
|
1281
|
+
onCancel: cancel
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
return {
|
|
1285
|
+
placeholder,
|
|
1286
|
+
chooser,
|
|
1287
|
+
onConnectEnd,
|
|
1288
|
+
onReconnectStart,
|
|
1289
|
+
onReconnectEnd,
|
|
1290
|
+
cancel
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1353
1294
|
// src/studio/entity-handles.ts
|
|
1354
1295
|
var ENTITY_SOURCE_HANDLE = "__entity-source";
|
|
1355
1296
|
|
|
@@ -2081,7 +2022,7 @@ var getLevelUnavailableReason = (nodes, level) => {
|
|
|
2081
2022
|
};
|
|
2082
2023
|
|
|
2083
2024
|
// src/studio/live-moves.ts
|
|
2084
|
-
import { useEffect, useState } from "react";
|
|
2025
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
2085
2026
|
|
|
2086
2027
|
// src/studio/smooth.ts
|
|
2087
2028
|
var EASE_MS = 45;
|
|
@@ -2157,10 +2098,10 @@ var sendMove = (live, kind, id, at) => live?.send(
|
|
|
2157
2098
|
);
|
|
2158
2099
|
var NONE = /* @__PURE__ */ new Map();
|
|
2159
2100
|
function useRemoteMoves(live, kind) {
|
|
2160
|
-
const [moves, setMoves] =
|
|
2101
|
+
const [moves, setMoves] = useState2(NONE);
|
|
2161
2102
|
const source = live?.source;
|
|
2162
2103
|
const level = live?.level;
|
|
2163
|
-
|
|
2104
|
+
useEffect2(() => {
|
|
2164
2105
|
if (!source) return;
|
|
2165
2106
|
let shown = "";
|
|
2166
2107
|
const glide = createSmoother((at) => setMoves(at.size ? at : NONE));
|
|
@@ -2222,9 +2163,9 @@ var NODE_TYPE = {
|
|
|
2222
2163
|
};
|
|
2223
2164
|
var RESOURCE_TYPE = {
|
|
2224
2165
|
...Object.fromEntries(
|
|
2225
|
-
Object.entries(NODE_TYPE).map(([
|
|
2166
|
+
Object.entries(NODE_TYPE).map(([resource, node]) => [
|
|
2226
2167
|
node,
|
|
2227
|
-
|
|
2168
|
+
resource
|
|
2228
2169
|
])
|
|
2229
2170
|
),
|
|
2230
2171
|
// Catalog domains and systems as cards (Studio's catalog adds them; kept if a canvas has them)
|
|
@@ -2247,42 +2188,42 @@ var toCanvasHotspots = (hotspots) => hotspots.map((hotspot) => ({
|
|
|
2247
2188
|
author: hotspot.author ?? AGENT_AUTHOR,
|
|
2248
2189
|
createdAt: hotspot.createdAt ?? Date.now()
|
|
2249
2190
|
}));
|
|
2250
|
-
function resourceNodeData(
|
|
2251
|
-
const type = NODE_TYPE[
|
|
2191
|
+
function resourceNodeData(resource) {
|
|
2192
|
+
const type = NODE_TYPE[resource.type];
|
|
2252
2193
|
const fields = {
|
|
2253
|
-
name:
|
|
2254
|
-
version:
|
|
2255
|
-
summary:
|
|
2256
|
-
owners:
|
|
2194
|
+
name: resource.name,
|
|
2195
|
+
version: resource.version ?? "0.0.1",
|
|
2196
|
+
summary: resource.summary ?? "",
|
|
2197
|
+
owners: resource.owners ?? []
|
|
2257
2198
|
};
|
|
2258
2199
|
const defaults = getNodeDefinition(type)?.createData() ?? {};
|
|
2259
|
-
const shared = { resource
|
|
2260
|
-
switch (
|
|
2200
|
+
const shared = { resource };
|
|
2201
|
+
switch (resource.type) {
|
|
2261
2202
|
case "domain":
|
|
2262
|
-
return
|
|
2203
|
+
return resource.card ? {
|
|
2263
2204
|
...shared,
|
|
2264
2205
|
mode: "full",
|
|
2265
2206
|
navigable: false,
|
|
2266
|
-
domain: { id:
|
|
2207
|
+
domain: { id: resource.id, ...fields }
|
|
2267
2208
|
} : {
|
|
2268
2209
|
...shared,
|
|
2269
2210
|
domain: {
|
|
2270
|
-
id:
|
|
2271
|
-
name:
|
|
2211
|
+
id: resource.id,
|
|
2212
|
+
name: resource.name,
|
|
2272
2213
|
version: fields.version
|
|
2273
2214
|
}
|
|
2274
2215
|
};
|
|
2275
2216
|
case "system":
|
|
2276
|
-
return
|
|
2217
|
+
return resource.card ? {
|
|
2277
2218
|
...shared,
|
|
2278
2219
|
mode: "full",
|
|
2279
2220
|
navigable: false,
|
|
2280
|
-
system: { id:
|
|
2221
|
+
system: { id: resource.id, ...fields }
|
|
2281
2222
|
} : {
|
|
2282
2223
|
...shared,
|
|
2283
2224
|
system: {
|
|
2284
|
-
id:
|
|
2285
|
-
name:
|
|
2225
|
+
id: resource.id,
|
|
2226
|
+
name: resource.name,
|
|
2286
2227
|
version: fields.version
|
|
2287
2228
|
}
|
|
2288
2229
|
};
|
|
@@ -2290,8 +2231,8 @@ function resourceNodeData(resource2) {
|
|
|
2290
2231
|
return {
|
|
2291
2232
|
...defaults,
|
|
2292
2233
|
...shared,
|
|
2293
|
-
name:
|
|
2294
|
-
summary:
|
|
2234
|
+
name: resource.name,
|
|
2235
|
+
summary: resource.summary ?? ""
|
|
2295
2236
|
};
|
|
2296
2237
|
case "channel":
|
|
2297
2238
|
return {
|
|
@@ -2299,7 +2240,7 @@ function resourceNodeData(resource2) {
|
|
|
2299
2240
|
...shared,
|
|
2300
2241
|
channel: {
|
|
2301
2242
|
...fields,
|
|
2302
|
-
protocols:
|
|
2243
|
+
protocols: resource.technology ? [resource.technology] : []
|
|
2303
2244
|
}
|
|
2304
2245
|
};
|
|
2305
2246
|
case "container":
|
|
@@ -2308,15 +2249,15 @@ function resourceNodeData(resource2) {
|
|
|
2308
2249
|
...shared,
|
|
2309
2250
|
data: {
|
|
2310
2251
|
...fields,
|
|
2311
|
-
container_type:
|
|
2312
|
-
technology:
|
|
2252
|
+
container_type: resource.containerType ?? "database",
|
|
2253
|
+
technology: resource.technology
|
|
2313
2254
|
}
|
|
2314
2255
|
};
|
|
2315
2256
|
case "entity":
|
|
2316
2257
|
return {
|
|
2317
2258
|
...defaults,
|
|
2318
2259
|
...shared,
|
|
2319
|
-
entity: { ...fields, properties:
|
|
2260
|
+
entity: { ...fields, properties: resource.properties ?? [] }
|
|
2320
2261
|
};
|
|
2321
2262
|
default: {
|
|
2322
2263
|
const key = getNodeDefinition(type)?.resourceKey ?? type;
|
|
@@ -2400,22 +2341,22 @@ var placeOf2 = (place) => ({
|
|
|
2400
2341
|
x: place.x,
|
|
2401
2342
|
y: place.y
|
|
2402
2343
|
});
|
|
2403
|
-
var nodeTypeOf = (
|
|
2404
|
-
var
|
|
2344
|
+
var nodeTypeOf = (resource) => resource.card && resource.type === "domain" ? "context-domain" : resource.card && resource.type === "system" ? "system" : NODE_TYPE[resource.type];
|
|
2345
|
+
var isCardType2 = (type) => type === "context-domain" || type === "system";
|
|
2405
2346
|
async function modelToCanvas(model, seed) {
|
|
2406
2347
|
const byId2 = new Map(model.resources.map((r) => [r.id, r]));
|
|
2407
2348
|
const saved = model.layout?.messages ?? {};
|
|
2408
2349
|
let nodes = sortByHierarchy(
|
|
2409
|
-
model.resources.map((
|
|
2410
|
-
const parent =
|
|
2411
|
-
const place = saved[
|
|
2412
|
-
const group = !
|
|
2413
|
-
const size = group ? place?.width && place.height ? { width: place.width, height: place.height } : getNodeDefinition(NODE_TYPE[
|
|
2350
|
+
model.resources.map((resource) => {
|
|
2351
|
+
const parent = resource.parent ? byId2.get(resource.parent) : void 0;
|
|
2352
|
+
const place = saved[resource.id];
|
|
2353
|
+
const group = !resource.card && (resource.type === "domain" || resource.type === "system");
|
|
2354
|
+
const size = group ? place?.width && place.height ? { width: place.width, height: place.height } : getNodeDefinition(NODE_TYPE[resource.type])?.defaultSize : void 0;
|
|
2414
2355
|
return {
|
|
2415
|
-
id:
|
|
2416
|
-
type: nodeTypeOf(
|
|
2356
|
+
id: resource.id,
|
|
2357
|
+
type: nodeTypeOf(resource),
|
|
2417
2358
|
position: place ? placeOf2(place) : { x: 0, y: 0 },
|
|
2418
|
-
data: resourceNodeData(
|
|
2359
|
+
data: resourceNodeData(resource),
|
|
2419
2360
|
...size && { width: size.width, height: size.height },
|
|
2420
2361
|
...parent && !parent.card && (parent.type === "domain" || parent.type === "system") && {
|
|
2421
2362
|
parentId: parent.id
|
|
@@ -2641,7 +2582,7 @@ function canvasToModel(nodes, edges, levelLayouts, base, threads = [], hotspots
|
|
|
2641
2582
|
...type === "container" && {
|
|
2642
2583
|
containerType: fields.container_type && fields.container_type !== "database" ? fields.container_type : void 0
|
|
2643
2584
|
},
|
|
2644
|
-
...
|
|
2585
|
+
...isCardType2(node.type) && { card: true },
|
|
2645
2586
|
...parent && resourceTypeOf(parent.type) && { parent: parent.id }
|
|
2646
2587
|
};
|
|
2647
2588
|
});
|
|
@@ -2692,12 +2633,12 @@ function canvasToModel(nodes, edges, levelLayouts, base, threads = [], hotspots
|
|
|
2692
2633
|
const notes = nodes.filter((node) => isWrittenOnCanvas(node.type)).map((node) => {
|
|
2693
2634
|
const at = getAbsolutePosition(node, lookup);
|
|
2694
2635
|
const level = node.data.level ?? void 0;
|
|
2695
|
-
const
|
|
2636
|
+
const resource = typeof node.data.resource === "string" && byId2.has(node.data.resource) ? node.data.resource : void 0;
|
|
2696
2637
|
return {
|
|
2697
2638
|
text: String(node.data.text ?? "").slice(0, 1e3),
|
|
2698
2639
|
...node.type === "text" && { kind: "text" },
|
|
2699
2640
|
...node.type === "note" && node.data.color ? { color: node.data.color } : {},
|
|
2700
|
-
...
|
|
2641
|
+
...resource && { resource },
|
|
2701
2642
|
...typeof node.data.author === "string" && {
|
|
2702
2643
|
author: node.data.author
|
|
2703
2644
|
},
|
|
@@ -2728,16 +2669,16 @@ function canvasToModel(nodes, edges, levelLayouts, base, threads = [], hotspots
|
|
|
2728
2669
|
team.name
|
|
2729
2670
|
]);
|
|
2730
2671
|
}
|
|
2731
|
-
for (const
|
|
2732
|
-
if (
|
|
2672
|
+
for (const resource of resources) {
|
|
2673
|
+
if (resource.type === "team") continue;
|
|
2733
2674
|
const owners = [
|
|
2734
2675
|
.../* @__PURE__ */ new Set([
|
|
2735
|
-
...(
|
|
2736
|
-
...ownedBy.get(
|
|
2676
|
+
...(resource.owners ?? []).filter((owner) => !teamNames.has(owner)),
|
|
2677
|
+
...ownedBy.get(resource.id) ?? []
|
|
2737
2678
|
])
|
|
2738
2679
|
];
|
|
2739
|
-
if (owners.length)
|
|
2740
|
-
else delete
|
|
2680
|
+
if (owners.length) resource.owners = owners;
|
|
2681
|
+
else delete resource.owners;
|
|
2741
2682
|
}
|
|
2742
2683
|
}
|
|
2743
2684
|
const ids = new Set(resources.map((r) => r.id));
|
|
@@ -2937,21 +2878,21 @@ async function canvasImage(container) {
|
|
|
2937
2878
|
// src/studio/components/canvas-nodes.tsx
|
|
2938
2879
|
import {
|
|
2939
2880
|
createContext,
|
|
2940
|
-
memo as
|
|
2941
|
-
useCallback,
|
|
2881
|
+
memo as memo3,
|
|
2882
|
+
useCallback as useCallback2,
|
|
2942
2883
|
useContext,
|
|
2943
|
-
useEffect as
|
|
2944
|
-
useMemo,
|
|
2945
|
-
useRef,
|
|
2946
|
-
useState as
|
|
2884
|
+
useEffect as useEffect4,
|
|
2885
|
+
useMemo as useMemo3,
|
|
2886
|
+
useRef as useRef3,
|
|
2887
|
+
useState as useState4
|
|
2947
2888
|
} from "react";
|
|
2948
2889
|
import {
|
|
2949
|
-
Handle as
|
|
2890
|
+
Handle as Handle3,
|
|
2950
2891
|
NodeResizeControl,
|
|
2951
2892
|
NodeResizer,
|
|
2952
|
-
Position as
|
|
2893
|
+
Position as Position3,
|
|
2953
2894
|
ResizeControlVariant,
|
|
2954
|
-
useReactFlow,
|
|
2895
|
+
useReactFlow as useReactFlow2,
|
|
2955
2896
|
useStoreApi as useStoreApi2,
|
|
2956
2897
|
useUpdateNodeInternals
|
|
2957
2898
|
} from "@xyflow/react";
|
|
@@ -3006,8 +2947,232 @@ var TeamNode = memo(function TeamNode2({ data, selected }) {
|
|
|
3006
2947
|
});
|
|
3007
2948
|
var TeamNode_default = TeamNode;
|
|
3008
2949
|
|
|
2950
|
+
// src/studio/components/ConnectChooser.tsx
|
|
2951
|
+
import {
|
|
2952
|
+
Fragment,
|
|
2953
|
+
memo as memo2,
|
|
2954
|
+
useEffect as useEffect3,
|
|
2955
|
+
useMemo as useMemo2,
|
|
2956
|
+
useRef as useRef2,
|
|
2957
|
+
useState as useState3
|
|
2958
|
+
} from "react";
|
|
2959
|
+
import { Handle as Handle2, Position as Position2 } from "@xyflow/react";
|
|
2960
|
+
import { Plus, X } from "lucide-react";
|
|
2961
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2962
|
+
var HIDDEN_HANDLE = {
|
|
2963
|
+
opacity: 0,
|
|
2964
|
+
pointerEvents: "none"
|
|
2965
|
+
};
|
|
2966
|
+
var PLACEHOLDER_CLASS = "relative rounded-xl border-2 border-dashed border-current bg-[rgb(var(--ec-card-bg))] px-3 pt-3.5 pb-2.5 opacity-50";
|
|
2967
|
+
var DEFAULT_COLOUR = "text-[rgb(var(--ec-accent))]";
|
|
2968
|
+
function PlaceholderContent({ choice }) {
|
|
2969
|
+
const icon = choice ? NODE_ICONS[choice.key] : void 0;
|
|
2970
|
+
const Icon = icon?.icon ?? Plus;
|
|
2971
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2972
|
+
/* @__PURE__ */ jsx2("span", { className: "absolute -top-2.5 left-2.5 rounded bg-current px-1.5 py-0.5 shadow-sm", children: /* @__PURE__ */ jsxs2("span", { className: "flex items-center gap-1 text-[7px] font-bold uppercase tracking-widest text-white", children: [
|
|
2973
|
+
/* @__PURE__ */ jsx2(Icon, { className: "h-2.5 w-2.5", strokeWidth: 2.5 }),
|
|
2974
|
+
choice?.label ?? "New"
|
|
2975
|
+
] }) }),
|
|
2976
|
+
/* @__PURE__ */ jsx2("div", { className: "truncate text-[13px] font-semibold leading-snug text-[rgb(var(--ec-page-text))]", children: choice ? `New ${choice.label}` : "New node" }),
|
|
2977
|
+
/* @__PURE__ */ jsx2("div", { className: "mt-1.5 truncate text-[9px] leading-relaxed text-[rgb(var(--ec-page-text-muted))]", children: choice ? choice.summary : "Choose what it is from the list" })
|
|
2978
|
+
] });
|
|
2979
|
+
}
|
|
2980
|
+
var ConnectPlaceholderNode = memo2(function ConnectPlaceholderNode2({
|
|
2981
|
+
data
|
|
2982
|
+
}) {
|
|
2983
|
+
const { choice } = data;
|
|
2984
|
+
const colour = choice && NODE_ICONS[choice.key]?.className || DEFAULT_COLOUR;
|
|
2985
|
+
return /* @__PURE__ */ jsxs2(
|
|
2986
|
+
"div",
|
|
2987
|
+
{
|
|
2988
|
+
className: `${PLACEHOLDER_CLASS} ${colour}`,
|
|
2989
|
+
style: CONNECT_PLACEHOLDER_SIZE,
|
|
2990
|
+
children: [
|
|
2991
|
+
/* @__PURE__ */ jsx2(
|
|
2992
|
+
Handle2,
|
|
2993
|
+
{
|
|
2994
|
+
type: "target",
|
|
2995
|
+
position: Position2.Left,
|
|
2996
|
+
isConnectable: false,
|
|
2997
|
+
style: HIDDEN_HANDLE
|
|
2998
|
+
}
|
|
2999
|
+
),
|
|
3000
|
+
/* @__PURE__ */ jsx2(PlaceholderContent, { choice }),
|
|
3001
|
+
/* @__PURE__ */ jsx2(
|
|
3002
|
+
Handle2,
|
|
3003
|
+
{
|
|
3004
|
+
type: "source",
|
|
3005
|
+
position: Position2.Right,
|
|
3006
|
+
isConnectable: false,
|
|
3007
|
+
style: HIDDEN_HANDLE
|
|
3008
|
+
}
|
|
3009
|
+
)
|
|
3010
|
+
]
|
|
3011
|
+
}
|
|
3012
|
+
);
|
|
3013
|
+
});
|
|
3014
|
+
var LIST_WIDTH = 288;
|
|
3015
|
+
var LIST_HEIGHT = 360;
|
|
3016
|
+
function ConnectChooser({
|
|
3017
|
+
options,
|
|
3018
|
+
fromName,
|
|
3019
|
+
anchor,
|
|
3020
|
+
onHighlight,
|
|
3021
|
+
onChoose,
|
|
3022
|
+
onCancel
|
|
3023
|
+
}) {
|
|
3024
|
+
const [query, setQuery] = useState3("");
|
|
3025
|
+
const [index, setIndex] = useState3(0);
|
|
3026
|
+
const [picking, setPicking] = useState3(false);
|
|
3027
|
+
const shown = useMemo2(
|
|
3028
|
+
() => filterConnectOptions(options, query),
|
|
3029
|
+
[options, query]
|
|
3030
|
+
);
|
|
3031
|
+
const highlighted = shown[Math.min(index, shown.length - 1)];
|
|
3032
|
+
const listRef = useRef2(null);
|
|
3033
|
+
useEffect3(() => setIndex(0), [query]);
|
|
3034
|
+
useEffect3(
|
|
3035
|
+
() => onHighlight(picking ? highlighted : void 0),
|
|
3036
|
+
[picking, highlighted?.key]
|
|
3037
|
+
);
|
|
3038
|
+
useEffect3(() => {
|
|
3039
|
+
if (!highlighted) return;
|
|
3040
|
+
listRef.current?.querySelector(`[data-key="${CSS.escape(highlighted.key)}"]`)?.scrollIntoView({ block: "nearest" });
|
|
3041
|
+
}, [highlighted?.key]);
|
|
3042
|
+
const onKeyDown = (event) => {
|
|
3043
|
+
if (event.key === "Escape") {
|
|
3044
|
+
event.preventDefault();
|
|
3045
|
+
event.stopPropagation();
|
|
3046
|
+
return onCancel();
|
|
3047
|
+
}
|
|
3048
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
3049
|
+
event.preventDefault();
|
|
3050
|
+
setPicking(true);
|
|
3051
|
+
if (!shown.length) return;
|
|
3052
|
+
const step = event.key === "ArrowDown" ? 1 : -1;
|
|
3053
|
+
setIndex(
|
|
3054
|
+
(current) => (Math.min(current, shown.length - 1) + step + shown.length) % shown.length
|
|
3055
|
+
);
|
|
3056
|
+
}
|
|
3057
|
+
if (event.key === "Enter" && highlighted) {
|
|
3058
|
+
event.preventDefault();
|
|
3059
|
+
onChoose(highlighted);
|
|
3060
|
+
}
|
|
3061
|
+
};
|
|
3062
|
+
const left = Math.min(
|
|
3063
|
+
Math.max(anchor.x, 12),
|
|
3064
|
+
window.innerWidth - LIST_WIDTH - 12
|
|
3065
|
+
);
|
|
3066
|
+
const below2 = anchor.y + anchor.height + 8;
|
|
3067
|
+
const top = below2 + LIST_HEIGHT > window.innerHeight - 12 ? Math.max(anchor.y - LIST_HEIGHT - 8, 12) : below2;
|
|
3068
|
+
const suggested = shown.filter((option) => option.says);
|
|
3069
|
+
const others = shown.filter((option) => !option.says);
|
|
3070
|
+
const row = (option) => {
|
|
3071
|
+
const { icon: Icon, className } = NODE_ICONS[option.key] ?? NODE_ICONS[option.type] ?? { icon: Plus, className: "" };
|
|
3072
|
+
const active = option.key === highlighted?.key;
|
|
3073
|
+
return /* @__PURE__ */ jsxs2(
|
|
3074
|
+
"button",
|
|
3075
|
+
{
|
|
3076
|
+
type: "button",
|
|
3077
|
+
role: "option",
|
|
3078
|
+
tabIndex: -1,
|
|
3079
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
3080
|
+
"aria-selected": active,
|
|
3081
|
+
"data-key": option.key,
|
|
3082
|
+
onPointerMove: () => {
|
|
3083
|
+
setPicking(true);
|
|
3084
|
+
if (!active) setIndex(shown.indexOf(option));
|
|
3085
|
+
},
|
|
3086
|
+
onClick: () => onChoose(option),
|
|
3087
|
+
className: `flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-left ${active ? "bg-[rgb(var(--ec-accent)/0.1)]" : ""}`,
|
|
3088
|
+
children: [
|
|
3089
|
+
/* @__PURE__ */ jsx2("span", { className: "flex h-7 w-7 flex-none items-center justify-center rounded-md bg-[rgb(var(--ec-content-hover))]", children: /* @__PURE__ */ jsx2(Icon, { size: 15, className }) }),
|
|
3090
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0 flex-1", children: [
|
|
3091
|
+
/* @__PURE__ */ jsx2("span", { className: "block truncate text-[13px] font-medium leading-tight", children: option.label }),
|
|
3092
|
+
/* @__PURE__ */ jsx2("span", { className: "block truncate text-[11px] leading-snug text-[rgb(var(--ec-page-text-muted))]", children: option.says || option.summary })
|
|
3093
|
+
] })
|
|
3094
|
+
]
|
|
3095
|
+
},
|
|
3096
|
+
option.key
|
|
3097
|
+
);
|
|
3098
|
+
};
|
|
3099
|
+
const section = (title, list) => list.length > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
3100
|
+
/* @__PURE__ */ jsx2(
|
|
3101
|
+
"p",
|
|
3102
|
+
{
|
|
3103
|
+
role: "presentation",
|
|
3104
|
+
className: "px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wider text-[rgb(var(--ec-page-text-muted))]",
|
|
3105
|
+
children: title
|
|
3106
|
+
}
|
|
3107
|
+
),
|
|
3108
|
+
list.map(row)
|
|
3109
|
+
] }, title);
|
|
3110
|
+
return /* @__PURE__ */ jsx2("div", { className: "fixed inset-0 z-50", onPointerDown: onCancel, children: /* @__PURE__ */ jsxs2(
|
|
3111
|
+
"div",
|
|
3112
|
+
{
|
|
3113
|
+
role: "dialog",
|
|
3114
|
+
"aria-label": "Connect to something new",
|
|
3115
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
3116
|
+
className: "absolute flex flex-col rounded-lg border shadow-xl bg-[rgb(var(--ec-card-bg))] border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text))]",
|
|
3117
|
+
style: { left, top, width: LIST_WIDTH, maxHeight: LIST_HEIGHT },
|
|
3118
|
+
children: [
|
|
3119
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-none items-center gap-1 border-b border-[rgb(var(--ec-page-border))] p-1.5", children: [
|
|
3120
|
+
/* @__PURE__ */ jsx2(
|
|
3121
|
+
"input",
|
|
3122
|
+
{
|
|
3123
|
+
autoFocus: true,
|
|
3124
|
+
value: query,
|
|
3125
|
+
onChange: (event) => {
|
|
3126
|
+
setPicking(true);
|
|
3127
|
+
setQuery(event.target.value);
|
|
3128
|
+
},
|
|
3129
|
+
onKeyDown,
|
|
3130
|
+
placeholder: fromName ? `Connect ${fromName} to\u2026` : "Connect to\u2026",
|
|
3131
|
+
"aria-label": "What to connect to",
|
|
3132
|
+
role: "combobox",
|
|
3133
|
+
"aria-expanded": true,
|
|
3134
|
+
"aria-controls": "studio-connect-options",
|
|
3135
|
+
className: "min-w-0 flex-1 rounded-md bg-transparent px-2 py-1 text-[13px] outline-none placeholder:text-[rgb(var(--ec-page-text-muted))]"
|
|
3136
|
+
}
|
|
3137
|
+
),
|
|
3138
|
+
/* @__PURE__ */ jsx2(
|
|
3139
|
+
"button",
|
|
3140
|
+
{
|
|
3141
|
+
type: "button",
|
|
3142
|
+
onClick: onCancel,
|
|
3143
|
+
"aria-label": "Cancel",
|
|
3144
|
+
className: "rounded p-1 text-[rgb(var(--ec-icon-color))] hover:bg-[rgb(var(--ec-page-border)/0.5)]",
|
|
3145
|
+
children: /* @__PURE__ */ jsx2(X, { size: 14 })
|
|
3146
|
+
}
|
|
3147
|
+
)
|
|
3148
|
+
] }),
|
|
3149
|
+
/* @__PURE__ */ jsx2(
|
|
3150
|
+
"div",
|
|
3151
|
+
{
|
|
3152
|
+
ref: listRef,
|
|
3153
|
+
id: "studio-connect-options",
|
|
3154
|
+
role: "listbox",
|
|
3155
|
+
className: "min-h-0 flex-1 overflow-y-auto p-1",
|
|
3156
|
+
children: shown.length ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
3157
|
+
section("Suggested", suggested),
|
|
3158
|
+
section(
|
|
3159
|
+
suggested.length ? "Everything else" : "Components",
|
|
3160
|
+
others
|
|
3161
|
+
)
|
|
3162
|
+
] }) : /* @__PURE__ */ jsxs2("p", { className: "px-2 py-3 text-center text-xs text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
3163
|
+
"Nothing called \u201C",
|
|
3164
|
+
query,
|
|
3165
|
+
"\u201D"
|
|
3166
|
+
] })
|
|
3167
|
+
}
|
|
3168
|
+
)
|
|
3169
|
+
]
|
|
3170
|
+
}
|
|
3171
|
+
) });
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3009
3174
|
// src/studio/components/canvas-nodes.tsx
|
|
3010
|
-
import { Fragment, jsx as
|
|
3175
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3011
3176
|
var UpdateNodeDataContext = createContext(() => {
|
|
3012
3177
|
});
|
|
3013
3178
|
var EditingContext = createContext(
|
|
@@ -3019,8 +3184,8 @@ var StartWritingContext = createContext(null);
|
|
|
3019
3184
|
var LockedContext = createContext(false);
|
|
3020
3185
|
var SystemGroupComponent = SystemGroupNode_default;
|
|
3021
3186
|
function WidthHandles() {
|
|
3022
|
-
return /* @__PURE__ */
|
|
3023
|
-
/* @__PURE__ */
|
|
3187
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3188
|
+
/* @__PURE__ */ jsx3(
|
|
3024
3189
|
NodeResizeControl,
|
|
3025
3190
|
{
|
|
3026
3191
|
position: "left",
|
|
@@ -3030,7 +3195,7 @@ function WidthHandles() {
|
|
|
3030
3195
|
className: "studio-width-handle"
|
|
3031
3196
|
}
|
|
3032
3197
|
),
|
|
3033
|
-
/* @__PURE__ */
|
|
3198
|
+
/* @__PURE__ */ jsx3(
|
|
3034
3199
|
NodeResizeControl,
|
|
3035
3200
|
{
|
|
3036
3201
|
position: "right",
|
|
@@ -3054,8 +3219,8 @@ function Writing({
|
|
|
3054
3219
|
}) {
|
|
3055
3220
|
const updateNodeData2 = useContext(UpdateNodeDataContext);
|
|
3056
3221
|
const liveEdit = useContext(EditingContext);
|
|
3057
|
-
const areaRef =
|
|
3058
|
-
|
|
3222
|
+
const areaRef = useRef3(null);
|
|
3223
|
+
useEffect4(() => {
|
|
3059
3224
|
if (!editing) return;
|
|
3060
3225
|
let frame = 0;
|
|
3061
3226
|
let tries = 0;
|
|
@@ -3078,8 +3243,8 @@ function Writing({
|
|
|
3078
3243
|
area.style.height = `${area.scrollHeight}px`;
|
|
3079
3244
|
};
|
|
3080
3245
|
if (!editing)
|
|
3081
|
-
return /* @__PURE__ */
|
|
3082
|
-
return /* @__PURE__ */
|
|
3246
|
+
return /* @__PURE__ */ jsx3("p", { className, style, children: text || placeholder && /* @__PURE__ */ jsx3("span", { className: "opacity-50", children: placeholder }) });
|
|
3247
|
+
return /* @__PURE__ */ jsx3(
|
|
3083
3248
|
"textarea",
|
|
3084
3249
|
{
|
|
3085
3250
|
ref: (area) => {
|
|
@@ -3118,30 +3283,30 @@ var NOTE_COLORS = {
|
|
|
3118
3283
|
purple: { fill: "#ede9fe", border: "#c4b5fd" },
|
|
3119
3284
|
gray: { fill: "#f3f4f6", border: "#d1d5db" }
|
|
3120
3285
|
};
|
|
3121
|
-
var StickyNote =
|
|
3286
|
+
var StickyNote = memo3(function StickyNote2({ id, data, selected }) {
|
|
3122
3287
|
const updateNodeData2 = useContext(UpdateNodeDataContext);
|
|
3123
|
-
const [editing, setEditing] =
|
|
3288
|
+
const [editing, setEditing] = useState4(
|
|
3124
3289
|
useContext(StartWritingContext) === id
|
|
3125
3290
|
);
|
|
3126
3291
|
const locked = useContext(LockedContext);
|
|
3127
3292
|
const colorName = typeof data.color === "string" && NOTE_COLORS[data.color] ? data.color : "yellow";
|
|
3128
3293
|
const color = NOTE_COLORS[colorName];
|
|
3129
|
-
return /* @__PURE__ */
|
|
3294
|
+
return /* @__PURE__ */ jsxs3(
|
|
3130
3295
|
"div",
|
|
3131
3296
|
{
|
|
3132
3297
|
className: "studio-note",
|
|
3133
3298
|
style: { background: color.fill, borderColor: color.border },
|
|
3134
3299
|
onDoubleClick: () => !locked && setEditing(true),
|
|
3135
3300
|
children: [
|
|
3136
|
-
selected && !editing && !locked && /* @__PURE__ */
|
|
3137
|
-
/* @__PURE__ */
|
|
3138
|
-
/* @__PURE__ */
|
|
3301
|
+
selected && !editing && !locked && /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3302
|
+
/* @__PURE__ */ jsx3(WidthHandles, {}),
|
|
3303
|
+
/* @__PURE__ */ jsx3(
|
|
3139
3304
|
"div",
|
|
3140
3305
|
{
|
|
3141
3306
|
className: "nodrag nopan studio-note-colors",
|
|
3142
3307
|
role: "radiogroup",
|
|
3143
3308
|
"aria-label": "Note colour",
|
|
3144
|
-
children: Object.entries(NOTE_COLORS).map(([name, { fill, border }]) => /* @__PURE__ */
|
|
3309
|
+
children: Object.entries(NOTE_COLORS).map(([name, { fill, border }]) => /* @__PURE__ */ jsx3(
|
|
3145
3310
|
"button",
|
|
3146
3311
|
{
|
|
3147
3312
|
role: "radio",
|
|
@@ -3159,7 +3324,7 @@ var StickyNote = memo2(function StickyNote2({ id, data, selected }) {
|
|
|
3159
3324
|
}
|
|
3160
3325
|
)
|
|
3161
3326
|
] }),
|
|
3162
|
-
/* @__PURE__ */
|
|
3327
|
+
/* @__PURE__ */ jsx3(
|
|
3163
3328
|
Writing,
|
|
3164
3329
|
{
|
|
3165
3330
|
id,
|
|
@@ -3170,12 +3335,12 @@ var StickyNote = memo2(function StickyNote2({ id, data, selected }) {
|
|
|
3170
3335
|
className: "studio-note-body"
|
|
3171
3336
|
}
|
|
3172
3337
|
),
|
|
3173
|
-
/* @__PURE__ */
|
|
3338
|
+
/* @__PURE__ */ jsxs3("span", { className: "studio-note-level", children: [
|
|
3174
3339
|
"L",
|
|
3175
3340
|
getNoteLevel({ type: "note", data }),
|
|
3176
3341
|
" note"
|
|
3177
3342
|
] }),
|
|
3178
|
-
typeof data.createdAt === "number" && /* @__PURE__ */
|
|
3343
|
+
typeof data.createdAt === "number" && /* @__PURE__ */ jsx3("span", { className: "studio-note-date", children: new Date(data.createdAt).toLocaleDateString(void 0, {
|
|
3179
3344
|
day: "numeric",
|
|
3180
3345
|
month: "short"
|
|
3181
3346
|
}) })
|
|
@@ -3203,18 +3368,18 @@ var followPointer = (onMove, onEnd) => {
|
|
|
3203
3368
|
window.addEventListener("pointerup", end);
|
|
3204
3369
|
window.addEventListener("pointercancel", end);
|
|
3205
3370
|
};
|
|
3206
|
-
var TextNode =
|
|
3207
|
-
const [editing, setEditing] =
|
|
3371
|
+
var TextNode = memo3(function TextNode2({ id, data, selected }) {
|
|
3372
|
+
const [editing, setEditing] = useState4(
|
|
3208
3373
|
useContext(StartWritingContext) === id
|
|
3209
3374
|
);
|
|
3210
|
-
const { deleteElements } =
|
|
3375
|
+
const { deleteElements } = useReactFlow2();
|
|
3211
3376
|
const updateNodeData2 = useContext(UpdateNodeDataContext);
|
|
3212
3377
|
const liveEdit = useContext(EditingContext);
|
|
3213
|
-
const boxRef =
|
|
3378
|
+
const boxRef = useRef3(null);
|
|
3214
3379
|
const savedFont = typeof data.fontSize === "number" ? data.fontSize : TEXT_FONT_SIZE;
|
|
3215
3380
|
const savedAngle = typeof data.angle === "number" ? data.angle : 0;
|
|
3216
|
-
const [scaling, setScaling] =
|
|
3217
|
-
const [turning, setTurning] =
|
|
3381
|
+
const [scaling, setScaling] = useState4(null);
|
|
3382
|
+
const [turning, setTurning] = useState4(null);
|
|
3218
3383
|
const fontSize = scaling ?? savedFont;
|
|
3219
3384
|
const angle = turning ?? savedAngle;
|
|
3220
3385
|
const startScaling = (corner) => (event) => {
|
|
@@ -3280,7 +3445,7 @@ var TextNode = memo2(function TextNode2({ id, data, selected }) {
|
|
|
3280
3445
|
};
|
|
3281
3446
|
const locked = useContext(LockedContext);
|
|
3282
3447
|
const framed = (selected || scaling !== null || turning !== null) && !editing && !locked;
|
|
3283
|
-
return /* @__PURE__ */
|
|
3448
|
+
return /* @__PURE__ */ jsxs3(
|
|
3284
3449
|
"div",
|
|
3285
3450
|
{
|
|
3286
3451
|
ref: boxRef,
|
|
@@ -3288,8 +3453,8 @@ var TextNode = memo2(function TextNode2({ id, data, selected }) {
|
|
|
3288
3453
|
style: angle ? { transform: `rotate(${angle}deg)` } : void 0,
|
|
3289
3454
|
onDoubleClick: () => !locked && setEditing(true),
|
|
3290
3455
|
children: [
|
|
3291
|
-
framed && /* @__PURE__ */
|
|
3292
|
-
TEXT_CORNERS.map((corner) => /* @__PURE__ */
|
|
3456
|
+
framed && /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3457
|
+
TEXT_CORNERS.map((corner) => /* @__PURE__ */ jsx3(
|
|
3293
3458
|
"span",
|
|
3294
3459
|
{
|
|
3295
3460
|
className: `nodrag nopan studio-text-corner is-${corner}`,
|
|
@@ -3297,7 +3462,7 @@ var TextNode = memo2(function TextNode2({ id, data, selected }) {
|
|
|
3297
3462
|
},
|
|
3298
3463
|
corner
|
|
3299
3464
|
)),
|
|
3300
|
-
/* @__PURE__ */
|
|
3465
|
+
/* @__PURE__ */ jsx3(
|
|
3301
3466
|
"span",
|
|
3302
3467
|
{
|
|
3303
3468
|
className: "nodrag nopan studio-text-turn",
|
|
@@ -3306,7 +3471,7 @@ var TextNode = memo2(function TextNode2({ id, data, selected }) {
|
|
|
3306
3471
|
}
|
|
3307
3472
|
)
|
|
3308
3473
|
] }),
|
|
3309
|
-
/* @__PURE__ */
|
|
3474
|
+
/* @__PURE__ */ jsx3(
|
|
3310
3475
|
Writing,
|
|
3311
3476
|
{
|
|
3312
3477
|
id,
|
|
@@ -3327,42 +3492,42 @@ var useDomainData = ({
|
|
|
3327
3492
|
type,
|
|
3328
3493
|
data,
|
|
3329
3494
|
parentId
|
|
3330
|
-
}) =>
|
|
3495
|
+
}) => useMemo3(() => {
|
|
3331
3496
|
const isDomain2 = type === GROUP_TYPES.domain || type === "context-domain";
|
|
3332
3497
|
return isDomain2 && parentId && data.subdomain === void 0 ? { ...data, subdomain: true } : data;
|
|
3333
3498
|
}, [type, data, parentId]);
|
|
3334
|
-
var EntityCard =
|
|
3335
|
-
const data =
|
|
3499
|
+
var EntityCard = memo3(function EntityCard2(props) {
|
|
3500
|
+
const data = useMemo3(
|
|
3336
3501
|
() => ({ ...props.data, entity: { data: props.data.entity ?? {} } }),
|
|
3337
3502
|
[props.data]
|
|
3338
3503
|
);
|
|
3339
|
-
return /* @__PURE__ */
|
|
3340
|
-
/* @__PURE__ */
|
|
3341
|
-
/* @__PURE__ */
|
|
3342
|
-
|
|
3504
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3505
|
+
/* @__PURE__ */ jsx3(Entity_default, { ...props, data }),
|
|
3506
|
+
/* @__PURE__ */ jsx3(
|
|
3507
|
+
Handle3,
|
|
3343
3508
|
{
|
|
3344
3509
|
type: "source",
|
|
3345
|
-
position:
|
|
3510
|
+
position: Position3.Right,
|
|
3346
3511
|
id: ENTITY_SOURCE_HANDLE,
|
|
3347
3512
|
className: "studio-entity-source"
|
|
3348
3513
|
}
|
|
3349
3514
|
)
|
|
3350
3515
|
] });
|
|
3351
3516
|
});
|
|
3352
|
-
var DomainCard =
|
|
3353
|
-
return /* @__PURE__ */
|
|
3517
|
+
var DomainCard = memo3(function DomainCard2(props) {
|
|
3518
|
+
return /* @__PURE__ */ jsx3(DomainCard_default, { ...props, data: useDomainData(props) });
|
|
3354
3519
|
});
|
|
3355
|
-
var GroupNode =
|
|
3520
|
+
var GroupNode = memo3(function GroupNode2(props) {
|
|
3356
3521
|
const isDropTarget = useContext(DropTargetContext) === props.id;
|
|
3357
3522
|
const locked = useContext(LockedContext);
|
|
3358
3523
|
const data = useDomainData(props);
|
|
3359
3524
|
const store = useStoreApi2();
|
|
3360
3525
|
const updateNodeInternals = useUpdateNodeInternals();
|
|
3361
|
-
|
|
3526
|
+
useEffect4(() => {
|
|
3362
3527
|
updateNodeInternals(props.id);
|
|
3363
3528
|
}, [updateNodeInternals, props.id, props.width, props.height]);
|
|
3364
|
-
const contents =
|
|
3365
|
-
const onResizeStart =
|
|
3529
|
+
const contents = useRef3(null);
|
|
3530
|
+
const onResizeStart = useCallback2(() => {
|
|
3366
3531
|
const { nodeLookup } = store.getState();
|
|
3367
3532
|
const container = nodeLookup.get(props.id);
|
|
3368
3533
|
const children = [...nodeLookup.values()].filter(
|
|
@@ -3401,7 +3566,7 @@ var GroupNode = memo2(function GroupNode2(props) {
|
|
|
3401
3566
|
)
|
|
3402
3567
|
};
|
|
3403
3568
|
}, [store, props.id]);
|
|
3404
|
-
const shouldResize =
|
|
3569
|
+
const shouldResize = useCallback2(
|
|
3405
3570
|
(_, {
|
|
3406
3571
|
x,
|
|
3407
3572
|
y,
|
|
@@ -3413,8 +3578,8 @@ var GroupNode = memo2(function GroupNode2(props) {
|
|
|
3413
3578
|
},
|
|
3414
3579
|
[]
|
|
3415
3580
|
);
|
|
3416
|
-
return /* @__PURE__ */
|
|
3417
|
-
/* @__PURE__ */
|
|
3581
|
+
return /* @__PURE__ */ jsxs3("div", { style: { width: "100%", height: "100%", position: "relative" }, children: [
|
|
3582
|
+
/* @__PURE__ */ jsx3(
|
|
3418
3583
|
NodeResizer,
|
|
3419
3584
|
{
|
|
3420
3585
|
isVisible: props.selected && !locked,
|
|
@@ -3426,16 +3591,16 @@ var GroupNode = memo2(function GroupNode2(props) {
|
|
|
3426
3591
|
handleClassName: "!h-2.5 !w-2.5 !rounded-sm !border-2 !bg-[rgb(var(--ec-card-bg))] !border-[rgb(var(--ec-accent))]"
|
|
3427
3592
|
}
|
|
3428
3593
|
),
|
|
3429
|
-
/* @__PURE__ */
|
|
3430
|
-
/* @__PURE__ */
|
|
3594
|
+
/* @__PURE__ */ jsx3(SystemGroupComponent, { ...props, data }),
|
|
3595
|
+
/* @__PURE__ */ jsx3("div", { className: "ec-group-grip absolute inset-x-0 -top-3 h-[60px] cursor-grab" }),
|
|
3431
3596
|
isDropTarget ? (
|
|
3432
3597
|
// What's dragged over it goes in it when it's dropped
|
|
3433
|
-
/* @__PURE__ */
|
|
3598
|
+
/* @__PURE__ */ jsx3("div", { className: "ec-drop-target", children: /* @__PURE__ */ jsxs3("span", { className: "ec-drop-target-label", children: [
|
|
3434
3599
|
"Drop to add to",
|
|
3435
3600
|
" ",
|
|
3436
3601
|
getNodeName(props.type, props.data, "this container")
|
|
3437
3602
|
] }) })
|
|
3438
|
-
) : props.selected && /* @__PURE__ */
|
|
3603
|
+
) : props.selected && /* @__PURE__ */ jsx3("div", { className: "ec-group-selected" })
|
|
3439
3604
|
] });
|
|
3440
3605
|
});
|
|
3441
3606
|
var components = {
|
|
@@ -3453,7 +3618,9 @@ var components = {
|
|
|
3453
3618
|
team: TeamNode,
|
|
3454
3619
|
// Domains and systems as containers
|
|
3455
3620
|
[GROUP_TYPES.domain]: GroupNode,
|
|
3456
|
-
[GROUP_TYPES.system]: GroupNode
|
|
3621
|
+
[GROUP_TYPES.system]: GroupNode,
|
|
3622
|
+
// Where a connection let go of on empty canvas makes something new, until what it is is chosen
|
|
3623
|
+
[CONNECT_PLACEHOLDER]: ConnectPlaceholderNode
|
|
3457
3624
|
};
|
|
3458
3625
|
var nodeTypes = Object.fromEntries(
|
|
3459
3626
|
Object.entries(components).map(([type, component]) => [
|
|
@@ -3465,17 +3632,17 @@ var nodeTypes = Object.fromEntries(
|
|
|
3465
3632
|
// src/studio/components/Comments.tsx
|
|
3466
3633
|
import {
|
|
3467
3634
|
createContext as createContext2,
|
|
3468
|
-
memo as
|
|
3469
|
-
useCallback as
|
|
3635
|
+
memo as memo4,
|
|
3636
|
+
useCallback as useCallback3,
|
|
3470
3637
|
useContext as useContext2,
|
|
3471
|
-
useEffect as
|
|
3472
|
-
useRef as
|
|
3473
|
-
useState as
|
|
3638
|
+
useEffect as useEffect5,
|
|
3639
|
+
useRef as useRef4,
|
|
3640
|
+
useState as useState6
|
|
3474
3641
|
} from "react";
|
|
3475
3642
|
import { createPortal } from "react-dom";
|
|
3476
3643
|
import {
|
|
3477
3644
|
useInternalNode,
|
|
3478
|
-
useReactFlow as
|
|
3645
|
+
useReactFlow as useReactFlow3
|
|
3479
3646
|
} from "@xyflow/react";
|
|
3480
3647
|
import {
|
|
3481
3648
|
Check,
|
|
@@ -3483,7 +3650,7 @@ import {
|
|
|
3483
3650
|
Maximize2,
|
|
3484
3651
|
RotateCcw,
|
|
3485
3652
|
Trash2,
|
|
3486
|
-
X
|
|
3653
|
+
X as X2
|
|
3487
3654
|
} from "lucide-react";
|
|
3488
3655
|
|
|
3489
3656
|
// src/studio/components/status.ts
|
|
@@ -3532,15 +3699,15 @@ var CANVAS_STATUS_LOOK = {
|
|
|
3532
3699
|
};
|
|
3533
3700
|
|
|
3534
3701
|
// src/studio/components/Picture.tsx
|
|
3535
|
-
import { useState as
|
|
3536
|
-
import { jsx as
|
|
3702
|
+
import { useState as useState5 } from "react";
|
|
3703
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
3537
3704
|
function Picture({
|
|
3538
3705
|
src,
|
|
3539
3706
|
className = "absolute inset-0 h-full w-full"
|
|
3540
3707
|
}) {
|
|
3541
|
-
const [failed, setFailed] =
|
|
3708
|
+
const [failed, setFailed] = useState5();
|
|
3542
3709
|
if (!src || failed === src) return null;
|
|
3543
|
-
return /* @__PURE__ */
|
|
3710
|
+
return /* @__PURE__ */ jsx4(
|
|
3544
3711
|
"img",
|
|
3545
3712
|
{
|
|
3546
3713
|
src,
|
|
@@ -3555,15 +3722,15 @@ function Picture({
|
|
|
3555
3722
|
|
|
3556
3723
|
// src/studio/components/ClientLogos.tsx
|
|
3557
3724
|
import { Bot } from "lucide-react";
|
|
3558
|
-
import { jsx as
|
|
3559
|
-
var ClaudeLogo = (props) => /* @__PURE__ */
|
|
3725
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
3726
|
+
var ClaudeLogo = (props) => /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", "aria-hidden": true, ...props, children: /* @__PURE__ */ jsx5(
|
|
3560
3727
|
"path",
|
|
3561
3728
|
{
|
|
3562
3729
|
fill: "#D97757",
|
|
3563
3730
|
d: "M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"
|
|
3564
3731
|
}
|
|
3565
3732
|
) });
|
|
3566
|
-
var ClaudeCodeLogo = (props) => /* @__PURE__ */
|
|
3733
|
+
var ClaudeCodeLogo = (props) => /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", "aria-hidden": true, ...props, children: /* @__PURE__ */ jsx5(
|
|
3567
3734
|
"path",
|
|
3568
3735
|
{
|
|
3569
3736
|
fill: "#D97757",
|
|
@@ -3572,14 +3739,14 @@ var ClaudeCodeLogo = (props) => /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 2
|
|
|
3572
3739
|
d: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z"
|
|
3573
3740
|
}
|
|
3574
3741
|
) });
|
|
3575
|
-
var OpenAILogo = (props) => /* @__PURE__ */
|
|
3742
|
+
var OpenAILogo = (props) => /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", "aria-hidden": true, ...props, children: /* @__PURE__ */ jsx5(
|
|
3576
3743
|
"path",
|
|
3577
3744
|
{
|
|
3578
3745
|
fill: "currentColor",
|
|
3579
3746
|
d: "M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"
|
|
3580
3747
|
}
|
|
3581
3748
|
) });
|
|
3582
|
-
var CursorLogo = (props) => /* @__PURE__ */
|
|
3749
|
+
var CursorLogo = (props) => /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", "aria-hidden": true, ...props, children: /* @__PURE__ */ jsx5(
|
|
3583
3750
|
"path",
|
|
3584
3751
|
{
|
|
3585
3752
|
fill: "currentColor",
|
|
@@ -3599,18 +3766,18 @@ function AgentMark({
|
|
|
3599
3766
|
size = 14
|
|
3600
3767
|
}) {
|
|
3601
3768
|
const Logo = agentLogoFor(name);
|
|
3602
|
-
return Logo ? /* @__PURE__ */
|
|
3769
|
+
return Logo ? /* @__PURE__ */ jsx5(
|
|
3603
3770
|
"span",
|
|
3604
3771
|
{
|
|
3605
3772
|
className: "flex flex-none items-center justify-center rounded-full bg-white",
|
|
3606
3773
|
style: { width: size + 4, height: size + 4, color: "#111827" },
|
|
3607
|
-
children: /* @__PURE__ */
|
|
3774
|
+
children: /* @__PURE__ */ jsx5(Logo, { width: size - 2, height: size - 2 })
|
|
3608
3775
|
}
|
|
3609
|
-
) : /* @__PURE__ */
|
|
3776
|
+
) : /* @__PURE__ */ jsx5(Bot, { size });
|
|
3610
3777
|
}
|
|
3611
3778
|
|
|
3612
3779
|
// src/studio/components/Comments.tsx
|
|
3613
|
-
import { Fragment as
|
|
3780
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3614
3781
|
var initials = (name) => {
|
|
3615
3782
|
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
3616
3783
|
return (words.length > 1 ? words.map((word) => word[0]).join("") : name.trim()).slice(0, 2).toUpperCase();
|
|
@@ -3659,7 +3826,7 @@ function Avatar({
|
|
|
3659
3826
|
muted,
|
|
3660
3827
|
size = "h-6 w-6"
|
|
3661
3828
|
}) {
|
|
3662
|
-
return /* @__PURE__ */
|
|
3829
|
+
return /* @__PURE__ */ jsxs4(
|
|
3663
3830
|
"span",
|
|
3664
3831
|
{
|
|
3665
3832
|
title: author.name,
|
|
@@ -3668,8 +3835,8 @@ function Avatar({
|
|
|
3668
3835
|
backgroundColor: muted ? "rgb(var(--ec-page-text-muted))" : author.color
|
|
3669
3836
|
},
|
|
3670
3837
|
children: [
|
|
3671
|
-
author.agent ? /* @__PURE__ */
|
|
3672
|
-
/* @__PURE__ */
|
|
3838
|
+
author.agent ? /* @__PURE__ */ jsx6(AgentMark, { name: author.name, size: 13 }) : initials(author.name),
|
|
3839
|
+
/* @__PURE__ */ jsx6(
|
|
3673
3840
|
Picture,
|
|
3674
3841
|
{
|
|
3675
3842
|
src: author.picture,
|
|
@@ -3689,11 +3856,11 @@ function Pin({
|
|
|
3689
3856
|
onClick,
|
|
3690
3857
|
onDrag
|
|
3691
3858
|
}) {
|
|
3692
|
-
const drag =
|
|
3693
|
-
const [hovered, setHovered] =
|
|
3694
|
-
const hoverTimer =
|
|
3695
|
-
|
|
3696
|
-
const [pressed, setPressed] =
|
|
3859
|
+
const drag = useRef4(null);
|
|
3860
|
+
const [hovered, setHovered] = useState6(false);
|
|
3861
|
+
const hoverTimer = useRef4(void 0);
|
|
3862
|
+
useEffect5(() => () => clearTimeout(hoverTimer.current), []);
|
|
3863
|
+
const [pressed, setPressed] = useState6(false);
|
|
3697
3864
|
const tipOf = (event) => ({
|
|
3698
3865
|
x: event.clientX - drag.current.grab.x,
|
|
3699
3866
|
y: event.clientY - drag.current.grab.y
|
|
@@ -3701,7 +3868,7 @@ function Pin({
|
|
|
3701
3868
|
const people = thread ? participantsOf(thread) : [author];
|
|
3702
3869
|
const [first, ...rest] = thread?.messages ?? [];
|
|
3703
3870
|
const expanded = !!thread && !!first && hovered && !active && !pressed;
|
|
3704
|
-
return /* @__PURE__ */
|
|
3871
|
+
return /* @__PURE__ */ jsx6(
|
|
3705
3872
|
"button",
|
|
3706
3873
|
{
|
|
3707
3874
|
onPointerEnter: () => {
|
|
@@ -3761,9 +3928,9 @@ function Pin({
|
|
|
3761
3928
|
style: selected ? {
|
|
3762
3929
|
boxShadow: "0 0 0 2px rgb(var(--ec-card-bg)), 0 0 0 4px rgb(var(--ec-button-bg))"
|
|
3763
3930
|
} : void 0,
|
|
3764
|
-
children: expanded ? /* @__PURE__ */
|
|
3765
|
-
/* @__PURE__ */
|
|
3766
|
-
/* @__PURE__ */
|
|
3931
|
+
children: expanded ? /* @__PURE__ */ jsxs4("span", { className: "block space-y-1 px-1.5 py-1", children: [
|
|
3932
|
+
/* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-2", children: [
|
|
3933
|
+
/* @__PURE__ */ jsx6("span", { className: "flex -space-x-0.5", children: people.slice(0, MAX_PIN_AVATARS).map((person) => /* @__PURE__ */ jsx6(
|
|
3767
3934
|
Avatar,
|
|
3768
3935
|
{
|
|
3769
3936
|
author: person,
|
|
@@ -3772,26 +3939,26 @@ function Pin({
|
|
|
3772
3939
|
},
|
|
3773
3940
|
person.name
|
|
3774
3941
|
)) }),
|
|
3775
|
-
/* @__PURE__ */
|
|
3776
|
-
/* @__PURE__ */
|
|
3942
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate text-xs font-semibold", children: thread.author.name }),
|
|
3943
|
+
/* @__PURE__ */ jsx6("span", { className: "shrink-0 text-[11px] text-[rgb(var(--ec-page-text-muted))]", children: timeAgo(first.createdAt) })
|
|
3777
3944
|
] }),
|
|
3778
|
-
/* @__PURE__ */
|
|
3779
|
-
(rest.length > 0 || resolved) && /* @__PURE__ */
|
|
3780
|
-
rest.length > 0 && /* @__PURE__ */
|
|
3781
|
-
resolved && /* @__PURE__ */
|
|
3945
|
+
/* @__PURE__ */ jsx6("span", { className: "line-clamp-3 block whitespace-pre-wrap break-words text-xs", children: first.text }),
|
|
3946
|
+
(rest.length > 0 || resolved) && /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-2 text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
3947
|
+
rest.length > 0 && /* @__PURE__ */ jsx6("span", { children: repliesLabel(rest.length) }),
|
|
3948
|
+
resolved && /* @__PURE__ */ jsxs4(
|
|
3782
3949
|
"span",
|
|
3783
3950
|
{
|
|
3784
3951
|
className: `flex items-center gap-0.5 ${STATUS.success.text}`,
|
|
3785
3952
|
children: [
|
|
3786
|
-
/* @__PURE__ */
|
|
3953
|
+
/* @__PURE__ */ jsx6(Check, { size: 11 }),
|
|
3787
3954
|
" Resolved"
|
|
3788
3955
|
]
|
|
3789
3956
|
}
|
|
3790
3957
|
)
|
|
3791
3958
|
] })
|
|
3792
|
-
] }) : /* @__PURE__ */
|
|
3793
|
-
people.slice(0, MAX_PIN_AVATARS).map((person) => /* @__PURE__ */
|
|
3794
|
-
people.length > MAX_PIN_AVATARS && /* @__PURE__ */
|
|
3959
|
+
] }) : /* @__PURE__ */ jsxs4("span", { className: "flex -space-x-1", children: [
|
|
3960
|
+
people.slice(0, MAX_PIN_AVATARS).map((person) => /* @__PURE__ */ jsx6(Avatar, { author: person, muted: resolved }, person.name)),
|
|
3961
|
+
people.length > MAX_PIN_AVATARS && /* @__PURE__ */ jsxs4("span", { className: "flex h-6 w-6 items-center justify-center rounded-full text-[10px] font-semibold ring-2 ring-[rgb(var(--ec-card-bg))] bg-[rgb(var(--ec-page-border))]", children: [
|
|
3795
3962
|
"+",
|
|
3796
3963
|
people.length - MAX_PIN_AVATARS
|
|
3797
3964
|
] })
|
|
@@ -3804,14 +3971,14 @@ function Composer({
|
|
|
3804
3971
|
onSubmit,
|
|
3805
3972
|
onCancel
|
|
3806
3973
|
}) {
|
|
3807
|
-
const [text, setText] =
|
|
3974
|
+
const [text, setText] = useState6("");
|
|
3808
3975
|
const submit = () => {
|
|
3809
3976
|
if (!text.trim()) return;
|
|
3810
3977
|
onSubmit(text.trim());
|
|
3811
3978
|
setText("");
|
|
3812
3979
|
};
|
|
3813
|
-
return /* @__PURE__ */
|
|
3814
|
-
/* @__PURE__ */
|
|
3980
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-end gap-2 p-2", children: [
|
|
3981
|
+
/* @__PURE__ */ jsx6(
|
|
3815
3982
|
"textarea",
|
|
3816
3983
|
{
|
|
3817
3984
|
autoFocus: true,
|
|
@@ -3829,7 +3996,7 @@ function Composer({
|
|
|
3829
3996
|
className: "max-h-32 min-h-[34px] flex-1 resize-none rounded-md border px-2 py-1.5 text-sm bg-[rgb(var(--ec-input-bg))] border-[rgb(var(--ec-input-border))] text-[rgb(var(--ec-input-text))]"
|
|
3830
3997
|
}
|
|
3831
3998
|
),
|
|
3832
|
-
/* @__PURE__ */
|
|
3999
|
+
/* @__PURE__ */ jsx6(
|
|
3833
4000
|
"button",
|
|
3834
4001
|
{
|
|
3835
4002
|
onClick: submit,
|
|
@@ -3845,7 +4012,7 @@ function IconButton({
|
|
|
3845
4012
|
onClick,
|
|
3846
4013
|
children
|
|
3847
4014
|
}) {
|
|
3848
|
-
return /* @__PURE__ */
|
|
4015
|
+
return /* @__PURE__ */ jsx6(
|
|
3849
4016
|
"button",
|
|
3850
4017
|
{
|
|
3851
4018
|
title,
|
|
@@ -3862,14 +4029,14 @@ function FloatingPanel({
|
|
|
3862
4029
|
children,
|
|
3863
4030
|
onClickOutside
|
|
3864
4031
|
}) {
|
|
3865
|
-
const ref =
|
|
3866
|
-
const [offset, setOffset] =
|
|
3867
|
-
const offsetRef =
|
|
4032
|
+
const ref = useRef4(null);
|
|
4033
|
+
const [offset, setOffset] = useState6({ x: 0, y: 0 });
|
|
4034
|
+
const offsetRef = useRef4(offset);
|
|
3868
4035
|
offsetRef.current = offset;
|
|
3869
|
-
const clickedOutside =
|
|
4036
|
+
const clickedOutside = useRef4(onClickOutside);
|
|
3870
4037
|
clickedOutside.current = onClickOutside;
|
|
3871
4038
|
const closesOnClickOutside = !!onClickOutside;
|
|
3872
|
-
|
|
4039
|
+
useEffect5(() => {
|
|
3873
4040
|
if (!closesOnClickOutside) return;
|
|
3874
4041
|
const onPointerDown = (event) => {
|
|
3875
4042
|
const element = ref.current;
|
|
@@ -3882,7 +4049,7 @@ function FloatingPanel({
|
|
|
3882
4049
|
document.addEventListener("pointerdown", onPointerDown, true);
|
|
3883
4050
|
return () => document.removeEventListener("pointerdown", onPointerDown, true);
|
|
3884
4051
|
}, [closesOnClickOutside]);
|
|
3885
|
-
|
|
4052
|
+
useEffect5(() => {
|
|
3886
4053
|
const element = ref.current;
|
|
3887
4054
|
if (!element) return;
|
|
3888
4055
|
const fit = () => {
|
|
@@ -3898,7 +4065,7 @@ function FloatingPanel({
|
|
|
3898
4065
|
observer.observe(element);
|
|
3899
4066
|
return () => observer.disconnect();
|
|
3900
4067
|
}, []);
|
|
3901
|
-
const startDrag =
|
|
4068
|
+
const startDrag = useCallback3((event) => {
|
|
3902
4069
|
if (event.button !== 0 || event.target.closest("button"))
|
|
3903
4070
|
return;
|
|
3904
4071
|
event.preventDefault();
|
|
@@ -3919,7 +4086,7 @@ function FloatingPanel({
|
|
|
3919
4086
|
element.addEventListener("pointerup", end);
|
|
3920
4087
|
element.addEventListener("pointercancel", end);
|
|
3921
4088
|
}, []);
|
|
3922
|
-
return /* @__PURE__ */
|
|
4089
|
+
return /* @__PURE__ */ jsx6(
|
|
3923
4090
|
"div",
|
|
3924
4091
|
{
|
|
3925
4092
|
ref,
|
|
@@ -3929,7 +4096,7 @@ function FloatingPanel({
|
|
|
3929
4096
|
top: offset.y,
|
|
3930
4097
|
maxHeight: PANEL_MAX_HEIGHT_PX
|
|
3931
4098
|
},
|
|
3932
|
-
children: /* @__PURE__ */
|
|
4099
|
+
children: /* @__PURE__ */ jsx6(DragPanelContext.Provider, { value: startDrag, children })
|
|
3933
4100
|
}
|
|
3934
4101
|
);
|
|
3935
4102
|
}
|
|
@@ -3941,21 +4108,21 @@ function ThreadPopover({
|
|
|
3941
4108
|
onClose,
|
|
3942
4109
|
onExpand
|
|
3943
4110
|
}) {
|
|
3944
|
-
const listRef =
|
|
4111
|
+
const listRef = useRef4(null);
|
|
3945
4112
|
const startDrag = useContext2(DragPanelContext);
|
|
3946
|
-
|
|
4113
|
+
useEffect5(() => {
|
|
3947
4114
|
listRef.current?.scrollTo({ top: listRef.current.scrollHeight });
|
|
3948
4115
|
}, [thread.messages.length]);
|
|
3949
|
-
return /* @__PURE__ */
|
|
3950
|
-
/* @__PURE__ */
|
|
4116
|
+
return /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
4117
|
+
/* @__PURE__ */ jsxs4(
|
|
3951
4118
|
"div",
|
|
3952
4119
|
{
|
|
3953
4120
|
onPointerDown: startDrag ?? void 0,
|
|
3954
4121
|
title: startDrag ? "Drag to move" : void 0,
|
|
3955
4122
|
className: `flex shrink-0 select-none items-center justify-between border-b px-3 py-2 border-[rgb(var(--ec-page-border))] ${startDrag ? "cursor-move" : ""}`,
|
|
3956
4123
|
children: [
|
|
3957
|
-
/* @__PURE__ */
|
|
3958
|
-
startDrag && /* @__PURE__ */
|
|
4124
|
+
/* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1 text-xs font-semibold", children: [
|
|
4125
|
+
startDrag && /* @__PURE__ */ jsx6(
|
|
3959
4126
|
GripVertical,
|
|
3960
4127
|
{
|
|
3961
4128
|
size: 14,
|
|
@@ -3965,51 +4132,51 @@ function ThreadPopover({
|
|
|
3965
4132
|
),
|
|
3966
4133
|
thread.resolved ? "Resolved thread" : "Thread"
|
|
3967
4134
|
] }),
|
|
3968
|
-
/* @__PURE__ */
|
|
3969
|
-
/* @__PURE__ */
|
|
4135
|
+
/* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-0.5", children: [
|
|
4136
|
+
/* @__PURE__ */ jsx6(
|
|
3970
4137
|
IconButton,
|
|
3971
4138
|
{
|
|
3972
4139
|
title: thread.resolved ? "Reopen" : "Resolve",
|
|
3973
4140
|
onClick: () => onResolve(!thread.resolved),
|
|
3974
|
-
children: thread.resolved ? /* @__PURE__ */
|
|
4141
|
+
children: thread.resolved ? /* @__PURE__ */ jsx6(RotateCcw, { size: 14 }) : /* @__PURE__ */ jsx6(Check, { size: 14 })
|
|
3975
4142
|
}
|
|
3976
4143
|
),
|
|
3977
|
-
/* @__PURE__ */
|
|
3978
|
-
onExpand && /* @__PURE__ */
|
|
3979
|
-
/* @__PURE__ */
|
|
4144
|
+
/* @__PURE__ */ jsx6(IconButton, { title: "Delete thread", onClick: onDelete, children: /* @__PURE__ */ jsx6(Trash2, { size: 14 }) }),
|
|
4145
|
+
onExpand && /* @__PURE__ */ jsx6(IconButton, { title: "Open bigger", onClick: onExpand, children: /* @__PURE__ */ jsx6(Maximize2, { size: 14 }) }),
|
|
4146
|
+
/* @__PURE__ */ jsx6(IconButton, { title: "Close", onClick: onClose, children: /* @__PURE__ */ jsx6(X2, { size: 14 }) })
|
|
3980
4147
|
] })
|
|
3981
4148
|
]
|
|
3982
4149
|
}
|
|
3983
4150
|
),
|
|
3984
|
-
/* @__PURE__ */
|
|
4151
|
+
/* @__PURE__ */ jsx6(
|
|
3985
4152
|
"div",
|
|
3986
4153
|
{
|
|
3987
4154
|
ref: listRef,
|
|
3988
4155
|
className: "min-h-0 flex-1 space-y-3 overflow-y-auto px-3 py-3",
|
|
3989
|
-
children: thread.messages.map((message) => /* @__PURE__ */
|
|
3990
|
-
/* @__PURE__ */
|
|
4156
|
+
children: thread.messages.map((message) => /* @__PURE__ */ jsxs4("div", { className: "flex gap-2", children: [
|
|
4157
|
+
/* @__PURE__ */ jsxs4(
|
|
3991
4158
|
"span",
|
|
3992
4159
|
{
|
|
3993
4160
|
className: "relative flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[10px] font-semibold text-white",
|
|
3994
4161
|
style: { backgroundColor: message.author.color },
|
|
3995
4162
|
children: [
|
|
3996
|
-
message.author.agent ? /* @__PURE__ */
|
|
3997
|
-
/* @__PURE__ */
|
|
4163
|
+
message.author.agent ? /* @__PURE__ */ jsx6(AgentMark, { name: message.author.name, size: 13 }) : initials(message.author.name),
|
|
4164
|
+
/* @__PURE__ */ jsx6(Picture, { src: message.author.picture })
|
|
3998
4165
|
]
|
|
3999
4166
|
}
|
|
4000
4167
|
),
|
|
4001
|
-
/* @__PURE__ */
|
|
4002
|
-
/* @__PURE__ */
|
|
4003
|
-
/* @__PURE__ */
|
|
4168
|
+
/* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
|
|
4169
|
+
/* @__PURE__ */ jsxs4("p", { className: "text-xs", children: [
|
|
4170
|
+
/* @__PURE__ */ jsx6("span", { className: "font-semibold", children: message.author.name }),
|
|
4004
4171
|
" ",
|
|
4005
|
-
/* @__PURE__ */
|
|
4172
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[rgb(var(--ec-page-text-muted))]", children: timeAgo(message.createdAt) })
|
|
4006
4173
|
] }),
|
|
4007
|
-
/* @__PURE__ */
|
|
4174
|
+
/* @__PURE__ */ jsx6("p", { className: "whitespace-pre-wrap break-words text-sm", children: message.text })
|
|
4008
4175
|
] })
|
|
4009
4176
|
] }, message.id))
|
|
4010
4177
|
}
|
|
4011
4178
|
),
|
|
4012
|
-
/* @__PURE__ */
|
|
4179
|
+
/* @__PURE__ */ jsx6("div", { className: "shrink-0 border-t border-[rgb(var(--ec-page-border))]", children: /* @__PURE__ */ jsx6(Composer, { placeholder: "Reply", onSubmit: onReply, onCancel: onClose }) })
|
|
4013
4180
|
] });
|
|
4014
4181
|
}
|
|
4015
4182
|
function ThreadDialog({
|
|
@@ -4020,12 +4187,12 @@ function ThreadDialog({
|
|
|
4020
4187
|
onShrink,
|
|
4021
4188
|
onClose
|
|
4022
4189
|
}) {
|
|
4023
|
-
|
|
4190
|
+
useEffect5(() => {
|
|
4024
4191
|
const onKeyDown = (event) => event.key === "Escape" && onShrink();
|
|
4025
4192
|
window.addEventListener("keydown", onKeyDown);
|
|
4026
4193
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
4027
4194
|
}, [onShrink]);
|
|
4028
|
-
return /* @__PURE__ */
|
|
4195
|
+
return /* @__PURE__ */ jsx6(
|
|
4029
4196
|
"div",
|
|
4030
4197
|
{
|
|
4031
4198
|
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
|
|
@@ -4038,14 +4205,14 @@ function ThreadDialog({
|
|
|
4038
4205
|
onDoubleClick: (event) => event.stopPropagation(),
|
|
4039
4206
|
onContextMenu: (event) => event.stopPropagation(),
|
|
4040
4207
|
onWheel: (event) => event.stopPropagation(),
|
|
4041
|
-
children: /* @__PURE__ */
|
|
4208
|
+
children: /* @__PURE__ */ jsx6(
|
|
4042
4209
|
"div",
|
|
4043
4210
|
{
|
|
4044
4211
|
role: "dialog",
|
|
4045
4212
|
"aria-label": "Comment thread",
|
|
4046
4213
|
onClick: (event) => event.stopPropagation(),
|
|
4047
4214
|
className: "flex max-h-[80vh] w-full max-w-xl flex-col rounded-xl border shadow-2xl bg-[rgb(var(--ec-card-bg))] border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text))]",
|
|
4048
|
-
children: /* @__PURE__ */
|
|
4215
|
+
children: /* @__PURE__ */ jsx6(
|
|
4049
4216
|
ThreadPopover,
|
|
4050
4217
|
{
|
|
4051
4218
|
thread,
|
|
@@ -4068,7 +4235,7 @@ function PinAt({
|
|
|
4068
4235
|
const node = useInternalNode(anchor.nodeId ?? "");
|
|
4069
4236
|
const origin = anchor.nodeId && anchor.offset ? node?.internals.positionAbsolute : void 0;
|
|
4070
4237
|
const { x, y } = origin && anchor.offset ? { x: origin.x + anchor.offset.x, y: origin.y + anchor.offset.y } : anchor.position;
|
|
4071
|
-
return /* @__PURE__ */
|
|
4238
|
+
return /* @__PURE__ */ jsx6(
|
|
4072
4239
|
"div",
|
|
4073
4240
|
{
|
|
4074
4241
|
className: "absolute",
|
|
@@ -4079,11 +4246,11 @@ function PinAt({
|
|
|
4079
4246
|
transformOrigin: "0 0",
|
|
4080
4247
|
zIndex
|
|
4081
4248
|
},
|
|
4082
|
-
children: /* @__PURE__ */
|
|
4249
|
+
children: /* @__PURE__ */ jsx6("div", { className: "nopan nodrag nowheel pointer-events-auto absolute bottom-0 left-0", children })
|
|
4083
4250
|
}
|
|
4084
4251
|
);
|
|
4085
4252
|
}
|
|
4086
|
-
var CommentLayer =
|
|
4253
|
+
var CommentLayer = memo4(function CommentLayer2({
|
|
4087
4254
|
threads,
|
|
4088
4255
|
author,
|
|
4089
4256
|
openThreadId,
|
|
@@ -4101,12 +4268,12 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4101
4268
|
selectionOffset,
|
|
4102
4269
|
live
|
|
4103
4270
|
}) {
|
|
4104
|
-
const layer =
|
|
4271
|
+
const layer = useRef4(null);
|
|
4105
4272
|
useCounterScale(layer);
|
|
4106
|
-
const { screenToFlowPosition, getInternalNode } =
|
|
4107
|
-
const [moving, setMoving] =
|
|
4273
|
+
const { screenToFlowPosition, getInternalNode } = useReactFlow3();
|
|
4274
|
+
const [moving, setMoving] = useState6(null);
|
|
4108
4275
|
const remote = useRemoteMoves(live, "comment");
|
|
4109
|
-
const [expandedId, setExpandedId] =
|
|
4276
|
+
const [expandedId, setExpandedId] = useState6(null);
|
|
4110
4277
|
const expanded = expandedId && expandedId === openThreadId ? threads.find((thread) => thread.id === expandedId) : void 0;
|
|
4111
4278
|
const nodeUnder = (point) => {
|
|
4112
4279
|
for (const element of document.elementsFromPoint(point.x, point.y)) {
|
|
@@ -4131,7 +4298,7 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4131
4298
|
const visible = threads.filter(
|
|
4132
4299
|
(thread) => showResolved || !thread.resolved || thread.id === openThreadId
|
|
4133
4300
|
);
|
|
4134
|
-
return /* @__PURE__ */
|
|
4301
|
+
return /* @__PURE__ */ jsx6(CanvasPortal, { children: /* @__PURE__ */ jsxs4(
|
|
4135
4302
|
"div",
|
|
4136
4303
|
{
|
|
4137
4304
|
ref: layer,
|
|
@@ -4140,7 +4307,7 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4140
4307
|
children: [
|
|
4141
4308
|
visible.map((thread) => {
|
|
4142
4309
|
const isOpen = thread.id === openThreadId;
|
|
4143
|
-
return /* @__PURE__ */
|
|
4310
|
+
return /* @__PURE__ */ jsxs4(
|
|
4144
4311
|
PinAt,
|
|
4145
4312
|
{
|
|
4146
4313
|
anchor: moving?.threadId === thread.id ? moving.anchor : remote.has(thread.id) ? { position: remote.get(thread.id) } : selectionOffset && !thread.nodeId && selectedIds.has(thread.id) ? {
|
|
@@ -4151,7 +4318,7 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4151
4318
|
} : thread,
|
|
4152
4319
|
zIndex: isOpen ? 2 : 1,
|
|
4153
4320
|
children: [
|
|
4154
|
-
/* @__PURE__ */
|
|
4321
|
+
/* @__PURE__ */ jsx6(
|
|
4155
4322
|
Pin,
|
|
4156
4323
|
{
|
|
4157
4324
|
author: thread.author,
|
|
@@ -4172,7 +4339,7 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4172
4339
|
}
|
|
4173
4340
|
}
|
|
4174
4341
|
),
|
|
4175
|
-
isOpen && expanded?.id !== thread.id && /* @__PURE__ */
|
|
4342
|
+
isOpen && expanded?.id !== thread.id && /* @__PURE__ */ jsx6(FloatingPanel, { onClickOutside: () => onOpen(null), children: /* @__PURE__ */ jsx6(
|
|
4176
4343
|
ThreadPopover,
|
|
4177
4344
|
{
|
|
4178
4345
|
thread,
|
|
@@ -4189,7 +4356,7 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4189
4356
|
);
|
|
4190
4357
|
}),
|
|
4191
4358
|
expanded && createPortal(
|
|
4192
|
-
/* @__PURE__ */
|
|
4359
|
+
/* @__PURE__ */ jsx6(
|
|
4193
4360
|
ThreadDialog,
|
|
4194
4361
|
{
|
|
4195
4362
|
thread: expanded,
|
|
@@ -4208,8 +4375,8 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4208
4375
|
),
|
|
4209
4376
|
document.body
|
|
4210
4377
|
),
|
|
4211
|
-
draft && /* @__PURE__ */
|
|
4212
|
-
/* @__PURE__ */
|
|
4378
|
+
draft && /* @__PURE__ */ jsxs4(PinAt, { anchor: draft, zIndex: 3, children: [
|
|
4379
|
+
/* @__PURE__ */ jsx6(
|
|
4213
4380
|
Pin,
|
|
4214
4381
|
{
|
|
4215
4382
|
author,
|
|
@@ -4217,7 +4384,7 @@ var CommentLayer = memo3(function CommentLayer2({
|
|
|
4217
4384
|
onDrag: (tip, phase) => onMoveDraft(anchorFor(tip, phase))
|
|
4218
4385
|
}
|
|
4219
4386
|
),
|
|
4220
|
-
/* @__PURE__ */
|
|
4387
|
+
/* @__PURE__ */ jsx6(FloatingPanel, { children: /* @__PURE__ */ jsx6(
|
|
4221
4388
|
Composer,
|
|
4222
4389
|
{
|
|
4223
4390
|
placeholder: "Add a comment",
|
|
@@ -4237,9 +4404,9 @@ function CommentList({
|
|
|
4237
4404
|
onOpen
|
|
4238
4405
|
}) {
|
|
4239
4406
|
const shown = threads.filter((thread) => showResolved || !thread.resolved).reverse();
|
|
4240
|
-
return /* @__PURE__ */
|
|
4241
|
-
/* @__PURE__ */
|
|
4242
|
-
/* @__PURE__ */
|
|
4407
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
4408
|
+
/* @__PURE__ */ jsxs4("label", { className: "mx-3 mb-2 flex items-center gap-2 text-xs text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
4409
|
+
/* @__PURE__ */ jsx6(
|
|
4243
4410
|
"input",
|
|
4244
4411
|
{
|
|
4245
4412
|
type: "checkbox",
|
|
@@ -4249,27 +4416,27 @@ function CommentList({
|
|
|
4249
4416
|
),
|
|
4250
4417
|
"Show resolved"
|
|
4251
4418
|
] }),
|
|
4252
|
-
/* @__PURE__ */
|
|
4253
|
-
shown.length === 0 && /* @__PURE__ */
|
|
4419
|
+
/* @__PURE__ */ jsxs4("div", { className: "min-h-0 flex-1 space-y-1.5 overflow-y-auto px-3 pb-3", children: [
|
|
4420
|
+
shown.length === 0 && /* @__PURE__ */ jsx6("p", { className: "py-6 text-center text-xs text-[rgb(var(--ec-page-text-muted))]", children: "No comments yet. Right click the canvas, or press C, to add one." }),
|
|
4254
4421
|
shown.map((thread) => {
|
|
4255
4422
|
const [first, ...replies] = thread.messages;
|
|
4256
|
-
return /* @__PURE__ */
|
|
4423
|
+
return /* @__PURE__ */ jsxs4(
|
|
4257
4424
|
"button",
|
|
4258
4425
|
{
|
|
4259
4426
|
onClick: () => onOpen(thread),
|
|
4260
4427
|
className: `w-full space-y-1 rounded-md border px-2.5 py-2 text-left bg-[rgb(var(--ec-page-bg))] border-[rgb(var(--ec-page-border))] hover:border-[rgb(var(--ec-accent))] ${thread.resolved ? "opacity-60" : ""}`,
|
|
4261
4428
|
children: [
|
|
4262
|
-
/* @__PURE__ */
|
|
4263
|
-
/* @__PURE__ */
|
|
4429
|
+
/* @__PURE__ */ jsxs4("p", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
4430
|
+
/* @__PURE__ */ jsx6(
|
|
4264
4431
|
"span",
|
|
4265
4432
|
{
|
|
4266
4433
|
className: "h-2 w-2 shrink-0 rounded-full",
|
|
4267
4434
|
style: { backgroundColor: thread.author.color }
|
|
4268
4435
|
}
|
|
4269
4436
|
),
|
|
4270
|
-
/* @__PURE__ */
|
|
4271
|
-
/* @__PURE__ */
|
|
4272
|
-
thread.resolved && /* @__PURE__ */
|
|
4437
|
+
/* @__PURE__ */ jsx6("span", { className: "font-semibold", children: thread.author.name }),
|
|
4438
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[rgb(var(--ec-page-text-muted))]", children: timeAgo(thread.createdAt) }),
|
|
4439
|
+
thread.resolved && /* @__PURE__ */ jsx6(
|
|
4273
4440
|
Check,
|
|
4274
4441
|
{
|
|
4275
4442
|
size: 12,
|
|
@@ -4277,8 +4444,8 @@ function CommentList({
|
|
|
4277
4444
|
}
|
|
4278
4445
|
)
|
|
4279
4446
|
] }),
|
|
4280
|
-
/* @__PURE__ */
|
|
4281
|
-
replies.length > 0 && /* @__PURE__ */
|
|
4447
|
+
/* @__PURE__ */ jsx6("p", { className: "line-clamp-2 text-xs", children: first?.text }),
|
|
4448
|
+
replies.length > 0 && /* @__PURE__ */ jsxs4("p", { className: "text-[11px] text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
4282
4449
|
replies.length,
|
|
4283
4450
|
" ",
|
|
4284
4451
|
replies.length === 1 ? "reply" : "replies"
|
|
@@ -4294,11 +4461,11 @@ function CommentList({
|
|
|
4294
4461
|
|
|
4295
4462
|
// src/studio/components/ContextMenu.tsx
|
|
4296
4463
|
import {
|
|
4297
|
-
memo as
|
|
4298
|
-
useEffect as
|
|
4464
|
+
memo as memo5,
|
|
4465
|
+
useEffect as useEffect6,
|
|
4299
4466
|
useLayoutEffect as useLayoutEffect2,
|
|
4300
|
-
useRef as
|
|
4301
|
-
useState as
|
|
4467
|
+
useRef as useRef5,
|
|
4468
|
+
useState as useState7
|
|
4302
4469
|
} from "react";
|
|
4303
4470
|
import {
|
|
4304
4471
|
ClipboardPaste,
|
|
@@ -4312,9 +4479,9 @@ import {
|
|
|
4312
4479
|
Trash2 as Trash22,
|
|
4313
4480
|
TriangleAlert
|
|
4314
4481
|
} from "lucide-react";
|
|
4315
|
-
import { Fragment as
|
|
4482
|
+
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4316
4483
|
var EDGE = 8;
|
|
4317
|
-
var ContextMenu =
|
|
4484
|
+
var ContextMenu = memo5(function ContextMenu2({
|
|
4318
4485
|
menu,
|
|
4319
4486
|
questions,
|
|
4320
4487
|
onCopy,
|
|
@@ -4328,7 +4495,7 @@ var ContextMenu = memo4(function ContextMenu2({
|
|
|
4328
4495
|
onDeleteNode,
|
|
4329
4496
|
onClose
|
|
4330
4497
|
}) {
|
|
4331
|
-
|
|
4498
|
+
useEffect6(() => {
|
|
4332
4499
|
if (!menu) return;
|
|
4333
4500
|
const close = (event) => {
|
|
4334
4501
|
if (event instanceof KeyboardEvent && event.key !== "Escape") return;
|
|
@@ -4343,8 +4510,8 @@ var ContextMenu = memo4(function ContextMenu2({
|
|
|
4343
4510
|
window.removeEventListener("wheel", close);
|
|
4344
4511
|
};
|
|
4345
4512
|
}, [menu, onClose]);
|
|
4346
|
-
const menuRef =
|
|
4347
|
-
const [placed, setPlaced] =
|
|
4513
|
+
const menuRef = useRef5(null);
|
|
4514
|
+
const [placed, setPlaced] = useState7(
|
|
4348
4515
|
null
|
|
4349
4516
|
);
|
|
4350
4517
|
useLayoutEffect2(() => {
|
|
@@ -4360,13 +4527,13 @@ var ContextMenu = memo4(function ContextMenu2({
|
|
|
4360
4527
|
if (!menu) return null;
|
|
4361
4528
|
const itemClass = "flex w-full items-center gap-2 rounded px-2.5 py-1.5 text-left text-xs hover:bg-[rgb(var(--ec-page-border)/0.5)]";
|
|
4362
4529
|
const shortcutClass = "ml-auto text-[rgb(var(--ec-page-text-muted))]";
|
|
4363
|
-
const item = (icon, label, onClick, shortcut, className = "") => /* @__PURE__ */
|
|
4530
|
+
const item = (icon, label, onClick, shortcut, className = "") => /* @__PURE__ */ jsxs5("button", { className: `${itemClass} ${className}`, onClick, children: [
|
|
4364
4531
|
icon,
|
|
4365
4532
|
label,
|
|
4366
|
-
shortcut && /* @__PURE__ */
|
|
4533
|
+
shortcut && /* @__PURE__ */ jsx7("span", { className: shortcutClass, children: shortcut })
|
|
4367
4534
|
] });
|
|
4368
|
-
const separator = /* @__PURE__ */
|
|
4369
|
-
return /* @__PURE__ */
|
|
4535
|
+
const separator = /* @__PURE__ */ jsx7("div", { className: "my-1 h-px bg-[rgb(var(--ec-page-border))]" });
|
|
4536
|
+
return /* @__PURE__ */ jsxs5(
|
|
4370
4537
|
"div",
|
|
4371
4538
|
{
|
|
4372
4539
|
onPointerDown: (event) => event.stopPropagation(),
|
|
@@ -4380,14 +4547,14 @@ var ContextMenu = memo4(function ContextMenu2({
|
|
|
4380
4547
|
visibility: placed ? "visible" : "hidden"
|
|
4381
4548
|
},
|
|
4382
4549
|
children: [
|
|
4383
|
-
menu.node && questions?.length ? /* @__PURE__ */
|
|
4384
|
-
questions.map((question) => /* @__PURE__ */
|
|
4550
|
+
menu.node && questions?.length ? /* @__PURE__ */ jsxs5(Fragment5, { children: [
|
|
4551
|
+
questions.map((question) => /* @__PURE__ */ jsxs5(
|
|
4385
4552
|
"button",
|
|
4386
4553
|
{
|
|
4387
4554
|
className: itemClass,
|
|
4388
4555
|
onClick: question.onSelect,
|
|
4389
4556
|
children: [
|
|
4390
|
-
/* @__PURE__ */
|
|
4557
|
+
/* @__PURE__ */ jsx7(MessageCircleQuestion, { size: 14 }),
|
|
4391
4558
|
question.label
|
|
4392
4559
|
]
|
|
4393
4560
|
},
|
|
@@ -4395,30 +4562,30 @@ var ContextMenu = memo4(function ContextMenu2({
|
|
|
4395
4562
|
)),
|
|
4396
4563
|
separator
|
|
4397
4564
|
] }) : null,
|
|
4398
|
-
menu.node && /* @__PURE__ */
|
|
4399
|
-
onAddComment && item(/* @__PURE__ */
|
|
4400
|
-
onAddHotspot && !isWrittenOnCanvas(menu.node.type) && item(/* @__PURE__ */
|
|
4401
|
-
!isWrittenOnCanvas(menu.node.type) && item(/* @__PURE__ */
|
|
4402
|
-
onEditDetails && !isWrittenOnCanvas(menu.node.type) && item(/* @__PURE__ */
|
|
4403
|
-
item(/* @__PURE__ */
|
|
4404
|
-
item(/* @__PURE__ */
|
|
4565
|
+
menu.node && /* @__PURE__ */ jsxs5(Fragment5, { children: [
|
|
4566
|
+
onAddComment && item(/* @__PURE__ */ jsx7(MessageCircle, { size: 14 }), "Add comment", onAddComment, "C"),
|
|
4567
|
+
onAddHotspot && !isWrittenOnCanvas(menu.node.type) && item(/* @__PURE__ */ jsx7(TriangleAlert, { size: 14 }), "Add hotspot", onAddHotspot, "A"),
|
|
4568
|
+
!isWrittenOnCanvas(menu.node.type) && item(/* @__PURE__ */ jsx7(StickyNote3, { size: 14 }), "Add a note", onAddNote),
|
|
4569
|
+
onEditDetails && !isWrittenOnCanvas(menu.node.type) && item(/* @__PURE__ */ jsx7(Pencil, { size: 14 }), "Edit details", onEditDetails),
|
|
4570
|
+
item(/* @__PURE__ */ jsx7(Copy, { size: 14 }), "Copy", onCopy, "\u2318C"),
|
|
4571
|
+
item(/* @__PURE__ */ jsx7(CopyPlus, { size: 14 }), "Duplicate", onDuplicate, "\u2318D"),
|
|
4405
4572
|
separator,
|
|
4406
4573
|
item(
|
|
4407
|
-
/* @__PURE__ */
|
|
4574
|
+
/* @__PURE__ */ jsx7(Trash22, { size: 14 }),
|
|
4408
4575
|
"Delete",
|
|
4409
4576
|
onDeleteNode,
|
|
4410
4577
|
"\u232B",
|
|
4411
4578
|
STATUS.danger.text
|
|
4412
4579
|
)
|
|
4413
4580
|
] }),
|
|
4414
|
-
!menu.node && /* @__PURE__ */
|
|
4415
|
-
onAddComment && item(/* @__PURE__ */
|
|
4416
|
-
onAddHotspot && item(/* @__PURE__ */
|
|
4417
|
-
item(/* @__PURE__ */
|
|
4418
|
-
onPaste && item(/* @__PURE__ */
|
|
4419
|
-
onReorder && /* @__PURE__ */
|
|
4581
|
+
!menu.node && /* @__PURE__ */ jsxs5(Fragment5, { children: [
|
|
4582
|
+
onAddComment && item(/* @__PURE__ */ jsx7(MessageCircle, { size: 14 }), "Add comment", onAddComment, "C"),
|
|
4583
|
+
onAddHotspot && item(/* @__PURE__ */ jsx7(TriangleAlert, { size: 14 }), "Add hotspot", onAddHotspot, "A"),
|
|
4584
|
+
item(/* @__PURE__ */ jsx7(StickyNote3, { size: 14 }), "Add a sticky note", onAddNote, "N"),
|
|
4585
|
+
onPaste && item(/* @__PURE__ */ jsx7(ClipboardPaste, { size: 14 }), "Paste here", onPaste, "\u2318V"),
|
|
4586
|
+
onReorder && /* @__PURE__ */ jsxs5(Fragment5, { children: [
|
|
4420
4587
|
separator,
|
|
4421
|
-
item(/* @__PURE__ */
|
|
4588
|
+
item(/* @__PURE__ */ jsx7(SendToBack, { size: 14 }), "Reorder diagram", onReorder)
|
|
4422
4589
|
] })
|
|
4423
4590
|
] })
|
|
4424
4591
|
]
|
|
@@ -4428,18 +4595,18 @@ var ContextMenu = memo4(function ContextMenu2({
|
|
|
4428
4595
|
|
|
4429
4596
|
// src/studio/components/DragGhost.tsx
|
|
4430
4597
|
import {
|
|
4431
|
-
useCallback as
|
|
4432
|
-
useEffect as
|
|
4433
|
-
useMemo as
|
|
4434
|
-
useRef as
|
|
4435
|
-
useState as
|
|
4598
|
+
useCallback as useCallback4,
|
|
4599
|
+
useEffect as useEffect7,
|
|
4600
|
+
useMemo as useMemo4,
|
|
4601
|
+
useRef as useRef6,
|
|
4602
|
+
useState as useState8
|
|
4436
4603
|
} from "react";
|
|
4437
4604
|
import {
|
|
4438
4605
|
ReactFlow,
|
|
4439
4606
|
ReactFlowProvider,
|
|
4440
4607
|
useStoreApi as useStoreApi3
|
|
4441
4608
|
} from "@xyflow/react";
|
|
4442
|
-
import { jsx as
|
|
4609
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
4443
4610
|
var NO_DRAG_IMAGE = typeof Image === "undefined" ? void 0 : Object.assign(new Image(), {
|
|
4444
4611
|
src: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
|
4445
4612
|
});
|
|
@@ -4447,8 +4614,8 @@ var MARGIN = 16;
|
|
|
4447
4614
|
var PRO_OPTIONS = { hideAttribution: true };
|
|
4448
4615
|
function useDragGhost() {
|
|
4449
4616
|
const store = useStoreApi3();
|
|
4450
|
-
const [ghost, setGhost] =
|
|
4451
|
-
const startDrag =
|
|
4617
|
+
const [ghost, setGhost] = useState8(null);
|
|
4618
|
+
const startDrag = useCallback4(
|
|
4452
4619
|
(dragType, value, preview) => (event) => {
|
|
4453
4620
|
event.dataTransfer.setData(dragType, value);
|
|
4454
4621
|
event.dataTransfer.effectAllowed = "move";
|
|
@@ -4461,11 +4628,11 @@ function useDragGhost() {
|
|
|
4461
4628
|
},
|
|
4462
4629
|
[store]
|
|
4463
4630
|
);
|
|
4464
|
-
const element = ghost && /* @__PURE__ */
|
|
4631
|
+
const element = ghost && /* @__PURE__ */ jsx8(DragGhost, { ghost, onEnd: () => setGhost(null) });
|
|
4465
4632
|
return { startDrag, ghost: element };
|
|
4466
4633
|
}
|
|
4467
4634
|
function DragGhost({ ghost, onEnd }) {
|
|
4468
|
-
const ref =
|
|
4635
|
+
const ref = useRef6(null);
|
|
4469
4636
|
const { preview, zoom } = ghost;
|
|
4470
4637
|
const container = isGroupType(preview.type);
|
|
4471
4638
|
const size = getNodeSize2(preview.type);
|
|
@@ -4473,7 +4640,7 @@ function DragGhost({ ghost, onEnd }) {
|
|
|
4473
4640
|
x: size.width / 2 * zoom + MARGIN,
|
|
4474
4641
|
y: size.height / 2 * zoom + MARGIN
|
|
4475
4642
|
};
|
|
4476
|
-
|
|
4643
|
+
useEffect7(() => {
|
|
4477
4644
|
const move = (x, y) => {
|
|
4478
4645
|
if (ref.current)
|
|
4479
4646
|
ref.current.style.transform = `translate(${x - offset.x}px, ${y - offset.y}px)`;
|
|
@@ -4491,7 +4658,7 @@ function DragGhost({ ghost, onEnd }) {
|
|
|
4491
4658
|
document.removeEventListener("dragend", onEnd);
|
|
4492
4659
|
};
|
|
4493
4660
|
}, [ghost]);
|
|
4494
|
-
const nodes =
|
|
4661
|
+
const nodes = useMemo4(
|
|
4495
4662
|
() => [
|
|
4496
4663
|
{
|
|
4497
4664
|
id: "drag-ghost",
|
|
@@ -4503,8 +4670,8 @@ function DragGhost({ ghost, onEnd }) {
|
|
|
4503
4670
|
],
|
|
4504
4671
|
[preview, container, size]
|
|
4505
4672
|
);
|
|
4506
|
-
const viewport =
|
|
4507
|
-
return /* @__PURE__ */
|
|
4673
|
+
const viewport = useMemo4(() => ({ x: MARGIN, y: MARGIN, zoom }), [zoom]);
|
|
4674
|
+
return /* @__PURE__ */ jsx8(
|
|
4508
4675
|
"div",
|
|
4509
4676
|
{
|
|
4510
4677
|
ref,
|
|
@@ -4514,7 +4681,7 @@ function DragGhost({ ghost, onEnd }) {
|
|
|
4514
4681
|
width: size.width * zoom + MARGIN * 2,
|
|
4515
4682
|
height: size.height * zoom + MARGIN * 2
|
|
4516
4683
|
},
|
|
4517
|
-
children: /* @__PURE__ */
|
|
4684
|
+
children: /* @__PURE__ */ jsx8(ReactFlowProvider, { children: /* @__PURE__ */ jsx8(
|
|
4518
4685
|
ReactFlow,
|
|
4519
4686
|
{
|
|
4520
4687
|
nodes,
|
|
@@ -4536,14 +4703,14 @@ function DragGhost({ ghost, onEnd }) {
|
|
|
4536
4703
|
|
|
4537
4704
|
// src/studio/components/Hotspots.tsx
|
|
4538
4705
|
import {
|
|
4539
|
-
memo as
|
|
4706
|
+
memo as memo6,
|
|
4540
4707
|
useLayoutEffect as useLayoutEffect3,
|
|
4541
|
-
useRef as
|
|
4542
|
-
useState as
|
|
4708
|
+
useRef as useRef7,
|
|
4709
|
+
useState as useState9
|
|
4543
4710
|
} from "react";
|
|
4544
4711
|
import {
|
|
4545
4712
|
useInternalNode as useInternalNode2,
|
|
4546
|
-
useReactFlow as
|
|
4713
|
+
useReactFlow as useReactFlow4,
|
|
4547
4714
|
useStoreApi as useStoreApi4
|
|
4548
4715
|
} from "@xyflow/react";
|
|
4549
4716
|
import {
|
|
@@ -4552,9 +4719,9 @@ import {
|
|
|
4552
4719
|
Pencil as Pencil2,
|
|
4553
4720
|
Trash2 as Trash23,
|
|
4554
4721
|
TriangleAlert as TriangleAlert2,
|
|
4555
|
-
X as
|
|
4722
|
+
X as X3
|
|
4556
4723
|
} from "lucide-react";
|
|
4557
|
-
import { Fragment as
|
|
4724
|
+
import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4558
4725
|
var SEVERITIES = {
|
|
4559
4726
|
critical: {
|
|
4560
4727
|
label: "Critical",
|
|
@@ -4604,7 +4771,7 @@ function SpotAt({
|
|
|
4604
4771
|
at = { x: x + (node.measured.width ?? node.width ?? 0), y };
|
|
4605
4772
|
}
|
|
4606
4773
|
if (!at) return null;
|
|
4607
|
-
return /* @__PURE__ */
|
|
4774
|
+
return /* @__PURE__ */ jsx9(
|
|
4608
4775
|
"div",
|
|
4609
4776
|
{
|
|
4610
4777
|
className: "absolute",
|
|
@@ -4615,7 +4782,7 @@ function SpotAt({
|
|
|
4615
4782
|
transformOrigin: "0 0",
|
|
4616
4783
|
zIndex
|
|
4617
4784
|
},
|
|
4618
|
-
children: /* @__PURE__ */
|
|
4785
|
+
children: /* @__PURE__ */ jsx9("div", { className: "nopan nodrag nowheel pointer-events-auto absolute left-[-14px] top-[-14px]", children })
|
|
4619
4786
|
}
|
|
4620
4787
|
);
|
|
4621
4788
|
}
|
|
@@ -4624,7 +4791,7 @@ function SeverityIcon({
|
|
|
4624
4791
|
size = 13
|
|
4625
4792
|
}) {
|
|
4626
4793
|
const { icon: Icon } = SEVERITIES[severity];
|
|
4627
|
-
return /* @__PURE__ */
|
|
4794
|
+
return /* @__PURE__ */ jsx9(Icon, { size, strokeWidth: 2.5, "aria-hidden": true });
|
|
4628
4795
|
}
|
|
4629
4796
|
var DRAG_THRESHOLD_PX2 = 4;
|
|
4630
4797
|
var ICON_CENTRE_PX = 14;
|
|
@@ -4635,7 +4802,7 @@ function Marker({
|
|
|
4635
4802
|
onClick,
|
|
4636
4803
|
onDrag
|
|
4637
4804
|
}) {
|
|
4638
|
-
const drag =
|
|
4805
|
+
const drag = useRef7(null);
|
|
4639
4806
|
const pointOf = (event) => ({
|
|
4640
4807
|
x: event.clientX - drag.current.grab.x,
|
|
4641
4808
|
y: event.clientY - drag.current.grab.y
|
|
@@ -4644,7 +4811,7 @@ function Marker({
|
|
|
4644
4811
|
const severity = sorted[0].severity;
|
|
4645
4812
|
const count = sorted.length;
|
|
4646
4813
|
const label = spot.inside ? `${count} hotspot${count === 1 ? "" : "s"}` : count > 1 ? `${sorted[0].title} +${count - 1}` : sorted[0].title;
|
|
4647
|
-
return /* @__PURE__ */
|
|
4814
|
+
return /* @__PURE__ */ jsxs6(
|
|
4648
4815
|
"button",
|
|
4649
4816
|
{
|
|
4650
4817
|
type: "button",
|
|
@@ -4704,8 +4871,8 @@ function Marker({
|
|
|
4704
4871
|
}
|
|
4705
4872
|
},
|
|
4706
4873
|
children: [
|
|
4707
|
-
/* @__PURE__ */
|
|
4708
|
-
/* @__PURE__ */
|
|
4874
|
+
/* @__PURE__ */ jsx9("span", { className: "flex h-5 w-5 flex-none items-center justify-center rounded-full bg-white/20", children: /* @__PURE__ */ jsx9(SeverityIcon, { severity }) }),
|
|
4875
|
+
/* @__PURE__ */ jsx9("span", { className: "studio-hotspot-label truncate", children: label })
|
|
4709
4876
|
]
|
|
4710
4877
|
}
|
|
4711
4878
|
);
|
|
@@ -4718,11 +4885,11 @@ function HotspotForm({
|
|
|
4718
4885
|
onSubmit,
|
|
4719
4886
|
onCancel
|
|
4720
4887
|
}) {
|
|
4721
|
-
const [severity, setSeverity] =
|
|
4888
|
+
const [severity, setSeverity] = useState9(
|
|
4722
4889
|
initial?.severity ?? "warning"
|
|
4723
4890
|
);
|
|
4724
|
-
const [title, setTitle] =
|
|
4725
|
-
const [description, setDescription] =
|
|
4891
|
+
const [title, setTitle] = useState9(initial?.title ?? "");
|
|
4892
|
+
const [description, setDescription] = useState9(initial?.description ?? "");
|
|
4726
4893
|
const submit = (event) => {
|
|
4727
4894
|
event?.preventDefault();
|
|
4728
4895
|
if (!title.trim()) return;
|
|
@@ -4732,7 +4899,7 @@ function HotspotForm({
|
|
|
4732
4899
|
...description.trim() && { description: description.trim() }
|
|
4733
4900
|
});
|
|
4734
4901
|
};
|
|
4735
|
-
return /* @__PURE__ */
|
|
4902
|
+
return /* @__PURE__ */ jsxs6(
|
|
4736
4903
|
"form",
|
|
4737
4904
|
{
|
|
4738
4905
|
onSubmit: submit,
|
|
@@ -4744,9 +4911,9 @@ function HotspotForm({
|
|
|
4744
4911
|
},
|
|
4745
4912
|
className: "space-y-2.5 p-3",
|
|
4746
4913
|
children: [
|
|
4747
|
-
/* @__PURE__ */
|
|
4914
|
+
/* @__PURE__ */ jsx9("div", { role: "radiogroup", "aria-label": "How important", className: "flex gap-1", children: SEVERITY_ORDER.map((value) => {
|
|
4748
4915
|
const picked = value === severity;
|
|
4749
|
-
return /* @__PURE__ */
|
|
4916
|
+
return /* @__PURE__ */ jsxs6(
|
|
4750
4917
|
"button",
|
|
4751
4918
|
{
|
|
4752
4919
|
type: "button",
|
|
@@ -4763,14 +4930,14 @@ function HotspotForm({
|
|
|
4763
4930
|
color: SEVERITIES[value].color
|
|
4764
4931
|
},
|
|
4765
4932
|
children: [
|
|
4766
|
-
/* @__PURE__ */
|
|
4933
|
+
/* @__PURE__ */ jsx9(SeverityIcon, { severity: value, size: 12 }),
|
|
4767
4934
|
SEVERITIES[value].label
|
|
4768
4935
|
]
|
|
4769
4936
|
},
|
|
4770
4937
|
value
|
|
4771
4938
|
);
|
|
4772
4939
|
}) }),
|
|
4773
|
-
/* @__PURE__ */
|
|
4940
|
+
/* @__PURE__ */ jsx9(
|
|
4774
4941
|
"input",
|
|
4775
4942
|
{
|
|
4776
4943
|
autoFocus: true,
|
|
@@ -4781,7 +4948,7 @@ function HotspotForm({
|
|
|
4781
4948
|
className: inputClass
|
|
4782
4949
|
}
|
|
4783
4950
|
),
|
|
4784
|
-
/* @__PURE__ */
|
|
4951
|
+
/* @__PURE__ */ jsx9(
|
|
4785
4952
|
"textarea",
|
|
4786
4953
|
{
|
|
4787
4954
|
value: description,
|
|
@@ -4796,8 +4963,8 @@ function HotspotForm({
|
|
|
4796
4963
|
className: `${inputClass} resize-none`
|
|
4797
4964
|
}
|
|
4798
4965
|
),
|
|
4799
|
-
/* @__PURE__ */
|
|
4800
|
-
/* @__PURE__ */
|
|
4966
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex justify-end gap-2", children: [
|
|
4967
|
+
/* @__PURE__ */ jsx9(
|
|
4801
4968
|
"button",
|
|
4802
4969
|
{
|
|
4803
4970
|
type: "button",
|
|
@@ -4806,7 +4973,7 @@ function HotspotForm({
|
|
|
4806
4973
|
children: "Cancel"
|
|
4807
4974
|
}
|
|
4808
4975
|
),
|
|
4809
|
-
/* @__PURE__ */
|
|
4976
|
+
/* @__PURE__ */ jsx9(
|
|
4810
4977
|
"button",
|
|
4811
4978
|
{
|
|
4812
4979
|
type: "submit",
|
|
@@ -4821,13 +4988,13 @@ function HotspotForm({
|
|
|
4821
4988
|
);
|
|
4822
4989
|
}
|
|
4823
4990
|
function SeverityTag({ severity }) {
|
|
4824
|
-
return /* @__PURE__ */
|
|
4991
|
+
return /* @__PURE__ */ jsxs6(
|
|
4825
4992
|
"span",
|
|
4826
4993
|
{
|
|
4827
4994
|
className: "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-white",
|
|
4828
4995
|
style: { background: SEVERITIES[severity].color },
|
|
4829
4996
|
children: [
|
|
4830
|
-
/* @__PURE__ */
|
|
4997
|
+
/* @__PURE__ */ jsx9(SeverityIcon, { severity, size: 10 }),
|
|
4831
4998
|
SEVERITIES[severity].label
|
|
4832
4999
|
]
|
|
4833
5000
|
}
|
|
@@ -4837,24 +5004,24 @@ function HotspotItem({
|
|
|
4837
5004
|
hotspot,
|
|
4838
5005
|
actions
|
|
4839
5006
|
}) {
|
|
4840
|
-
return /* @__PURE__ */
|
|
5007
|
+
return /* @__PURE__ */ jsxs6(
|
|
4841
5008
|
"div",
|
|
4842
5009
|
{
|
|
4843
5010
|
className: "border-l-[3px] pl-2.5",
|
|
4844
5011
|
style: { borderColor: SEVERITIES[hotspot.severity].color },
|
|
4845
5012
|
children: [
|
|
4846
|
-
/* @__PURE__ */
|
|
4847
|
-
/* @__PURE__ */
|
|
4848
|
-
/* @__PURE__ */
|
|
4849
|
-
hotspot.author.agent && /* @__PURE__ */
|
|
5013
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
5014
|
+
/* @__PURE__ */ jsx9(SeverityTag, { severity: hotspot.severity }),
|
|
5015
|
+
/* @__PURE__ */ jsxs6("span", { className: "flex min-w-0 items-center gap-1 truncate text-[11px] text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
5016
|
+
hotspot.author.agent && /* @__PURE__ */ jsx9(AgentMark, { name: hotspot.author.name, size: 11 }),
|
|
4850
5017
|
hotspot.author.name,
|
|
4851
5018
|
" \xB7 ",
|
|
4852
5019
|
timeAgo(hotspot.createdAt)
|
|
4853
5020
|
] }),
|
|
4854
|
-
actions && /* @__PURE__ */
|
|
5021
|
+
actions && /* @__PURE__ */ jsx9("span", { className: "ml-auto flex flex-none items-center gap-0.5", children: actions })
|
|
4855
5022
|
] }),
|
|
4856
|
-
/* @__PURE__ */
|
|
4857
|
-
hotspot.description && /* @__PURE__ */
|
|
5023
|
+
/* @__PURE__ */ jsx9("p", { className: "mt-1.5 text-sm font-semibold leading-snug", children: hotspot.title }),
|
|
5024
|
+
hotspot.description && /* @__PURE__ */ jsx9("p", { className: "mt-1 whitespace-pre-wrap text-xs leading-relaxed text-[rgb(var(--ec-page-text-muted))]", children: hotspot.description })
|
|
4858
5025
|
]
|
|
4859
5026
|
}
|
|
4860
5027
|
);
|
|
@@ -4864,7 +5031,7 @@ function IconButton2({
|
|
|
4864
5031
|
onClick,
|
|
4865
5032
|
children
|
|
4866
5033
|
}) {
|
|
4867
|
-
return /* @__PURE__ */
|
|
5034
|
+
return /* @__PURE__ */ jsx9(
|
|
4868
5035
|
"button",
|
|
4869
5036
|
{
|
|
4870
5037
|
type: "button",
|
|
@@ -4884,15 +5051,15 @@ function SpotPanel({
|
|
|
4884
5051
|
onDelete,
|
|
4885
5052
|
onGo
|
|
4886
5053
|
}) {
|
|
4887
|
-
const [editing, setEditing] =
|
|
5054
|
+
const [editing, setEditing] = useState9(null);
|
|
4888
5055
|
const sorted = [...spot.hotspots].sort(bySeverity);
|
|
4889
|
-
return /* @__PURE__ */
|
|
4890
|
-
/* @__PURE__ */
|
|
4891
|
-
/* @__PURE__ */
|
|
4892
|
-
/* @__PURE__ */
|
|
5056
|
+
return /* @__PURE__ */ jsxs6("div", { className: panelClass2, children: [
|
|
5057
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between border-b border-[rgb(var(--ec-page-border))] px-3 py-2", children: [
|
|
5058
|
+
/* @__PURE__ */ jsx9("span", { className: "text-xs font-semibold", children: sorted.length === 1 ? "Hotspot" : `${sorted.length} hotspots` }),
|
|
5059
|
+
/* @__PURE__ */ jsx9(IconButton2, { label: "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(X3, { size: 14 }) })
|
|
4893
5060
|
] }),
|
|
4894
|
-
/* @__PURE__ */
|
|
4895
|
-
(hotspot) => editing === hotspot.id ? /* @__PURE__ */
|
|
5061
|
+
/* @__PURE__ */ jsx9("div", { className: "max-h-80 space-y-3 overflow-y-auto p-3", children: sorted.map(
|
|
5062
|
+
(hotspot) => editing === hotspot.id ? /* @__PURE__ */ jsx9("div", { className: "-m-3", children: /* @__PURE__ */ jsx9(
|
|
4896
5063
|
HotspotForm,
|
|
4897
5064
|
{
|
|
4898
5065
|
initial: hotspot,
|
|
@@ -4905,35 +5072,35 @@ function SpotPanel({
|
|
|
4905
5072
|
}
|
|
4906
5073
|
) }, hotspot.id) : spot.inside ? (
|
|
4907
5074
|
// Inside a node on L1 or L2: goes to it on L3, where it is
|
|
4908
|
-
/* @__PURE__ */
|
|
5075
|
+
/* @__PURE__ */ jsx9(
|
|
4909
5076
|
"button",
|
|
4910
5077
|
{
|
|
4911
5078
|
type: "button",
|
|
4912
5079
|
onClick: () => onGo(hotspot),
|
|
4913
5080
|
className: "block w-full rounded-md text-left hover:bg-[rgb(var(--ec-content-hover))]!",
|
|
4914
|
-
children: /* @__PURE__ */
|
|
5081
|
+
children: /* @__PURE__ */ jsx9(HotspotItem, { hotspot })
|
|
4915
5082
|
},
|
|
4916
5083
|
hotspot.id
|
|
4917
5084
|
)
|
|
4918
|
-
) : /* @__PURE__ */
|
|
5085
|
+
) : /* @__PURE__ */ jsx9(
|
|
4919
5086
|
HotspotItem,
|
|
4920
5087
|
{
|
|
4921
5088
|
hotspot,
|
|
4922
|
-
actions: !locked && /* @__PURE__ */
|
|
4923
|
-
/* @__PURE__ */
|
|
5089
|
+
actions: !locked && /* @__PURE__ */ jsxs6(Fragment6, { children: [
|
|
5090
|
+
/* @__PURE__ */ jsx9(
|
|
4924
5091
|
IconButton2,
|
|
4925
5092
|
{
|
|
4926
5093
|
label: "Edit",
|
|
4927
5094
|
onClick: () => setEditing(hotspot.id),
|
|
4928
|
-
children: /* @__PURE__ */
|
|
5095
|
+
children: /* @__PURE__ */ jsx9(Pencil2, { size: 13 })
|
|
4929
5096
|
}
|
|
4930
5097
|
),
|
|
4931
|
-
/* @__PURE__ */
|
|
5098
|
+
/* @__PURE__ */ jsx9(
|
|
4932
5099
|
IconButton2,
|
|
4933
5100
|
{
|
|
4934
5101
|
label: "Remove",
|
|
4935
5102
|
onClick: () => onDelete(hotspot.id),
|
|
4936
|
-
children: /* @__PURE__ */
|
|
5103
|
+
children: /* @__PURE__ */ jsx9(Trash23, { size: 13 })
|
|
4937
5104
|
}
|
|
4938
5105
|
)
|
|
4939
5106
|
] })
|
|
@@ -4941,10 +5108,10 @@ function SpotPanel({
|
|
|
4941
5108
|
hotspot.id
|
|
4942
5109
|
)
|
|
4943
5110
|
) }),
|
|
4944
|
-
spot.inside && /* @__PURE__ */
|
|
5111
|
+
spot.inside && /* @__PURE__ */ jsx9("p", { className: "border-t border-[rgb(var(--ec-page-border))] px-3 py-2 text-[11px] text-[rgb(var(--ec-page-text-muted))]", children: "Inside this: click one to go to it." })
|
|
4945
5112
|
] });
|
|
4946
5113
|
}
|
|
4947
|
-
var HotspotLayer =
|
|
5114
|
+
var HotspotLayer = memo6(function HotspotLayer2({
|
|
4948
5115
|
spots,
|
|
4949
5116
|
openKey,
|
|
4950
5117
|
draft,
|
|
@@ -4961,10 +5128,10 @@ var HotspotLayer = memo5(function HotspotLayer2({
|
|
|
4961
5128
|
onGo,
|
|
4962
5129
|
live
|
|
4963
5130
|
}) {
|
|
4964
|
-
const layer =
|
|
5131
|
+
const layer = useRef7(null);
|
|
4965
5132
|
useMarkerScale(layer);
|
|
4966
|
-
const { screenToFlowPosition } =
|
|
4967
|
-
const [moving, setMoving] =
|
|
5133
|
+
const { screenToFlowPosition } = useReactFlow4();
|
|
5134
|
+
const [moving, setMoving] = useState9(null);
|
|
4968
5135
|
const remote = useRemoteMoves(live, "hotspot");
|
|
4969
5136
|
const remoteAt = (spot) => {
|
|
4970
5137
|
for (const hotspot of spot.hotspots)
|
|
@@ -4995,7 +5162,7 @@ var HotspotLayer = memo5(function HotspotLayer2({
|
|
|
4995
5162
|
);
|
|
4996
5163
|
sendMove(live, "hotspot", spot.hotspots[0].id, null);
|
|
4997
5164
|
} : void 0;
|
|
4998
|
-
return /* @__PURE__ */
|
|
5165
|
+
return /* @__PURE__ */ jsx9(CanvasPortal, { children: /* @__PURE__ */ jsxs6(
|
|
4999
5166
|
"div",
|
|
5000
5167
|
{
|
|
5001
5168
|
ref: layer,
|
|
@@ -5006,14 +5173,14 @@ var HotspotLayer = memo5(function HotspotLayer2({
|
|
|
5006
5173
|
const open = spot.key === openKey;
|
|
5007
5174
|
const remotely = remoteAt(spot);
|
|
5008
5175
|
const dragged = moving?.key === spot.key ? moving : remotely ? { position: remotely } : void 0;
|
|
5009
|
-
return /* @__PURE__ */
|
|
5176
|
+
return /* @__PURE__ */ jsxs6(
|
|
5010
5177
|
SpotAt,
|
|
5011
5178
|
{
|
|
5012
5179
|
nodeId: dragged ? void 0 : spot.nodeId,
|
|
5013
5180
|
position: dragged ? dragged.position : spot.position,
|
|
5014
5181
|
zIndex: dragged ? 5 : open ? 3 : 1,
|
|
5015
5182
|
children: [
|
|
5016
|
-
/* @__PURE__ */
|
|
5183
|
+
/* @__PURE__ */ jsx9(
|
|
5017
5184
|
Marker,
|
|
5018
5185
|
{
|
|
5019
5186
|
spot,
|
|
@@ -5023,7 +5190,7 @@ var HotspotLayer = memo5(function HotspotLayer2({
|
|
|
5023
5190
|
onDrag: dragHandler(spot)
|
|
5024
5191
|
}
|
|
5025
5192
|
),
|
|
5026
|
-
open && !dragged && /* @__PURE__ */
|
|
5193
|
+
open && !dragged && /* @__PURE__ */ jsx9(
|
|
5027
5194
|
SpotPanel,
|
|
5028
5195
|
{
|
|
5029
5196
|
spot,
|
|
@@ -5039,22 +5206,22 @@ var HotspotLayer = memo5(function HotspotLayer2({
|
|
|
5039
5206
|
spot.key
|
|
5040
5207
|
);
|
|
5041
5208
|
}),
|
|
5042
|
-
draft && /* @__PURE__ */
|
|
5209
|
+
draft && /* @__PURE__ */ jsxs6(
|
|
5043
5210
|
SpotAt,
|
|
5044
5211
|
{
|
|
5045
5212
|
nodeId: draft.nodeId,
|
|
5046
5213
|
position: draft.nodeId ? void 0 : draft.position,
|
|
5047
5214
|
zIndex: 4,
|
|
5048
5215
|
children: [
|
|
5049
|
-
/* @__PURE__ */
|
|
5216
|
+
/* @__PURE__ */ jsx9(
|
|
5050
5217
|
"span",
|
|
5051
5218
|
{
|
|
5052
5219
|
className: "studio-hotspot-marker flex h-7 w-7 items-center justify-center rounded-full text-white",
|
|
5053
5220
|
style: { background: SEVERITIES.warning.color },
|
|
5054
|
-
children: /* @__PURE__ */
|
|
5221
|
+
children: /* @__PURE__ */ jsx9(SeverityIcon, { severity: "warning" })
|
|
5055
5222
|
}
|
|
5056
5223
|
),
|
|
5057
|
-
/* @__PURE__ */
|
|
5224
|
+
/* @__PURE__ */ jsx9("div", { className: panelClass2, children: /* @__PURE__ */ jsx9(
|
|
5058
5225
|
HotspotForm,
|
|
5059
5226
|
{
|
|
5060
5227
|
submitLabel: "Add hotspot",
|
|
@@ -5076,18 +5243,18 @@ function HotspotList({
|
|
|
5076
5243
|
}) {
|
|
5077
5244
|
const sorted = [...hotspots].sort(bySeverity);
|
|
5078
5245
|
if (!sorted.length)
|
|
5079
|
-
return /* @__PURE__ */
|
|
5080
|
-
return /* @__PURE__ */
|
|
5246
|
+
return /* @__PURE__ */ jsx9("p", { className: "px-4 py-6 text-center text-xs leading-relaxed text-[rgb(var(--ec-page-text-muted))]", children: "No hotspots yet. Press A, or right-click a node, to flag what people should know: a risk, a problem, or the key part." });
|
|
5247
|
+
return /* @__PURE__ */ jsx9("div", { className: "space-y-1.5 p-3", children: sorted.map((hotspot) => {
|
|
5081
5248
|
const on = hotspot.nodeId && nameOf(hotspot.nodeId);
|
|
5082
|
-
return /* @__PURE__ */
|
|
5249
|
+
return /* @__PURE__ */ jsxs6(
|
|
5083
5250
|
"button",
|
|
5084
5251
|
{
|
|
5085
5252
|
type: "button",
|
|
5086
5253
|
onClick: () => onOpen(hotspot),
|
|
5087
5254
|
className: "w-full rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))] px-2.5 py-2 text-left hover:border-[rgb(var(--ec-accent))]!",
|
|
5088
5255
|
children: [
|
|
5089
|
-
/* @__PURE__ */
|
|
5090
|
-
on && /* @__PURE__ */
|
|
5256
|
+
/* @__PURE__ */ jsx9(HotspotItem, { hotspot }),
|
|
5257
|
+
on && /* @__PURE__ */ jsxs6("p", { className: "mt-1.5 pl-[13px] text-[11px] text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
5091
5258
|
"On ",
|
|
5092
5259
|
on
|
|
5093
5260
|
] })
|
|
@@ -5098,76 +5265,9 @@ function HotspotList({
|
|
|
5098
5265
|
}) });
|
|
5099
5266
|
}
|
|
5100
5267
|
|
|
5101
|
-
// src/studio/components/icons.ts
|
|
5102
|
-
import {
|
|
5103
|
-
ArrowRightLeft,
|
|
5104
|
-
Bot as Bot2,
|
|
5105
|
-
Boxes,
|
|
5106
|
-
Archive,
|
|
5107
|
-
Database,
|
|
5108
|
-
DatabaseZap,
|
|
5109
|
-
Globe,
|
|
5110
|
-
Group,
|
|
5111
|
-
Mail,
|
|
5112
|
-
MonitorSmartphone,
|
|
5113
|
-
ScanSearch,
|
|
5114
|
-
Search,
|
|
5115
|
-
ServerIcon,
|
|
5116
|
-
StickyNote as StickyNote4,
|
|
5117
|
-
TableProperties,
|
|
5118
|
-
Type,
|
|
5119
|
-
User,
|
|
5120
|
-
Users as Users2,
|
|
5121
|
-
Zap
|
|
5122
|
-
} from "lucide-react";
|
|
5123
|
-
var NODE_ICONS = {
|
|
5124
|
-
[GROUP_TYPES.domain]: { icon: Boxes, className: "text-yellow-500" },
|
|
5125
|
-
[GROUP_TYPES.system]: { icon: Group, className: "text-violet-600" },
|
|
5126
|
-
// Catalog domains and systems added as cards
|
|
5127
|
-
"context-domain": { icon: Boxes, className: "text-yellow-500" },
|
|
5128
|
-
system: { icon: Group, className: "text-violet-600" },
|
|
5129
|
-
service: { icon: ServerIcon, className: "text-pink-600" },
|
|
5130
|
-
event: { icon: Zap, className: "text-orange-600" },
|
|
5131
|
-
command: { icon: Mail, className: "text-blue-600" },
|
|
5132
|
-
query: { icon: Search, className: "text-green-600" },
|
|
5133
|
-
channel: { icon: ArrowRightLeft, className: "text-gray-600" },
|
|
5134
|
-
data: { icon: Database, className: "text-blue-600" },
|
|
5135
|
-
// The other kinds of data store, in the components list
|
|
5136
|
-
"data:cache": { icon: DatabaseZap, className: "text-blue-600" },
|
|
5137
|
-
"data:searchIndex": { icon: ScanSearch, className: "text-blue-600" },
|
|
5138
|
-
"data:objectStore": { icon: Archive, className: "text-blue-600" },
|
|
5139
|
-
view: { icon: MonitorSmartphone, className: "text-sky-600" },
|
|
5140
|
-
externalSystem: { icon: Globe, className: "text-purple-600" },
|
|
5141
|
-
agent: { icon: Bot2, className: "text-violet-600" },
|
|
5142
|
-
actor: { icon: User, className: "text-yellow-500" },
|
|
5143
|
-
team: { icon: Users2, className: "text-emerald-600" },
|
|
5144
|
-
// A table of its properties, as the node shows it
|
|
5145
|
-
entity: { icon: TableProperties, className: "text-blue-600" },
|
|
5146
|
-
note: { icon: StickyNote4, className: "text-yellow-500" },
|
|
5147
|
-
text: { icon: Type, className: "text-[rgb(var(--ec-icon-color))]" }
|
|
5148
|
-
};
|
|
5149
|
-
var CATALOG_GROUPS = [
|
|
5150
|
-
{
|
|
5151
|
-
collection: "domains",
|
|
5152
|
-
label: "Domains",
|
|
5153
|
-
...NODE_ICONS[GROUP_TYPES.domain]
|
|
5154
|
-
},
|
|
5155
|
-
{
|
|
5156
|
-
collection: "systems",
|
|
5157
|
-
label: "Systems",
|
|
5158
|
-
...NODE_ICONS[GROUP_TYPES.system]
|
|
5159
|
-
},
|
|
5160
|
-
{ collection: "services", label: "Services", ...NODE_ICONS.service },
|
|
5161
|
-
{ collection: "events", label: "Events", ...NODE_ICONS.event },
|
|
5162
|
-
{ collection: "commands", label: "Commands", ...NODE_ICONS.command },
|
|
5163
|
-
{ collection: "queries", label: "Queries", ...NODE_ICONS.query },
|
|
5164
|
-
{ collection: "channels", label: "Channels", ...NODE_ICONS.channel },
|
|
5165
|
-
{ collection: "containers", label: "Data Stores", ...NODE_ICONS.data }
|
|
5166
|
-
];
|
|
5167
|
-
|
|
5168
5268
|
// src/studio/components/CanvasControls.tsx
|
|
5169
|
-
import { memo as
|
|
5170
|
-
import { useReactFlow as
|
|
5269
|
+
import { memo as memo7 } from "react";
|
|
5270
|
+
import { useReactFlow as useReactFlow5 } from "@xyflow/react";
|
|
5171
5271
|
import {
|
|
5172
5272
|
Hand,
|
|
5173
5273
|
Lock,
|
|
@@ -5176,24 +5276,24 @@ import {
|
|
|
5176
5276
|
MessageCircle as MessageCircle2,
|
|
5177
5277
|
MessageSquareText,
|
|
5178
5278
|
MousePointer2,
|
|
5179
|
-
Type
|
|
5279
|
+
Type,
|
|
5180
5280
|
Redo,
|
|
5181
5281
|
SendToBack as SendToBack2,
|
|
5182
|
-
StickyNote as
|
|
5282
|
+
StickyNote as StickyNote4,
|
|
5183
5283
|
TriangleAlert as TriangleAlert3,
|
|
5184
5284
|
Undo,
|
|
5185
5285
|
ZoomIn,
|
|
5186
5286
|
ZoomOut
|
|
5187
5287
|
} from "lucide-react";
|
|
5188
|
-
import { Fragment as
|
|
5288
|
+
import { Fragment as Fragment7, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
5189
5289
|
var FIT_VIEW_OPTIONS = DIAGRAM_FIT_VIEW_OPTIONS;
|
|
5190
5290
|
function WithKey({
|
|
5191
5291
|
shortcut,
|
|
5192
5292
|
children
|
|
5193
5293
|
}) {
|
|
5194
|
-
return /* @__PURE__ */
|
|
5195
|
-
/* @__PURE__ */
|
|
5196
|
-
/* @__PURE__ */
|
|
5294
|
+
return /* @__PURE__ */ jsxs7("span", { className: "relative flex h-8 w-8 items-center justify-center", children: [
|
|
5295
|
+
/* @__PURE__ */ jsx10("span", { className: "-translate-x-[3px] -translate-y-[2px]", children }),
|
|
5296
|
+
/* @__PURE__ */ jsx10(
|
|
5197
5297
|
"span",
|
|
5198
5298
|
{
|
|
5199
5299
|
"aria-hidden": true,
|
|
@@ -5214,13 +5314,13 @@ function LevelSwitch({
|
|
|
5214
5314
|
onChange,
|
|
5215
5315
|
unavailable
|
|
5216
5316
|
}) {
|
|
5217
|
-
return /* @__PURE__ */
|
|
5317
|
+
return /* @__PURE__ */ jsx10(
|
|
5218
5318
|
"div",
|
|
5219
5319
|
{
|
|
5220
5320
|
role: "group",
|
|
5221
5321
|
"aria-label": "Level of detail",
|
|
5222
5322
|
className: "flex items-center gap-0.5",
|
|
5223
|
-
children: LEVELS2.map(({ level: value, description }) => /* @__PURE__ */
|
|
5323
|
+
children: LEVELS2.map(({ level: value, description }) => /* @__PURE__ */ jsx10(
|
|
5224
5324
|
ToolbarButton,
|
|
5225
5325
|
{
|
|
5226
5326
|
label: `Level ${value}: ${description} (${value})`,
|
|
@@ -5228,7 +5328,7 @@ function LevelSwitch({
|
|
|
5228
5328
|
active: value === level,
|
|
5229
5329
|
disabled: !!unavailable?.[value],
|
|
5230
5330
|
onClick: () => onChange(value),
|
|
5231
|
-
children: /* @__PURE__ */
|
|
5331
|
+
children: /* @__PURE__ */ jsx10(WithKey, { shortcut: String(value), children: /* @__PURE__ */ jsxs7("span", { className: "text-xs font-semibold", children: [
|
|
5232
5332
|
"L",
|
|
5233
5333
|
value
|
|
5234
5334
|
] }) })
|
|
@@ -5238,7 +5338,7 @@ function LevelSwitch({
|
|
|
5238
5338
|
}
|
|
5239
5339
|
);
|
|
5240
5340
|
}
|
|
5241
|
-
var CanvasControls_default =
|
|
5341
|
+
var CanvasControls_default = memo7(function CanvasControls({
|
|
5242
5342
|
level,
|
|
5243
5343
|
onLevelChange,
|
|
5244
5344
|
unavailableLevels,
|
|
@@ -5262,38 +5362,38 @@ var CanvasControls_default = memo6(function CanvasControls({
|
|
|
5262
5362
|
}) {
|
|
5263
5363
|
return (
|
|
5264
5364
|
// At the top, as drawing tools have their tools
|
|
5265
|
-
/* @__PURE__ */
|
|
5266
|
-
/* @__PURE__ */
|
|
5267
|
-
/* @__PURE__ */
|
|
5365
|
+
/* @__PURE__ */ jsxs7("div", { className: "absolute left-1/2 top-3 z-10 -translate-x-1/2", children: [
|
|
5366
|
+
/* @__PURE__ */ jsxs7(Toolbar, { children: [
|
|
5367
|
+
/* @__PURE__ */ jsx10(
|
|
5268
5368
|
ToolbarButton,
|
|
5269
5369
|
{
|
|
5270
5370
|
label: locked ? `Locked${lockedBy ? ` by ${lockedBy}` : ""}: unlock it to change it (for everyone on it)` : "Lock the canvas (it can be looked at, not changed, by everyone on it)",
|
|
5271
5371
|
active: locked,
|
|
5272
5372
|
onClick: onToggleLock,
|
|
5273
|
-
children: locked ? /* @__PURE__ */
|
|
5373
|
+
children: locked ? /* @__PURE__ */ jsx10(Lock, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx10(LockOpen, { className: "h-4 w-4" })
|
|
5274
5374
|
}
|
|
5275
5375
|
),
|
|
5276
|
-
/* @__PURE__ */
|
|
5277
|
-
/* @__PURE__ */
|
|
5376
|
+
/* @__PURE__ */ jsx10(ToolbarDivider, {}),
|
|
5377
|
+
/* @__PURE__ */ jsx10(
|
|
5278
5378
|
ToolbarButton,
|
|
5279
5379
|
{
|
|
5280
5380
|
label: "Select (V)",
|
|
5281
5381
|
active: selectMode,
|
|
5282
5382
|
onClick: onSelectMode,
|
|
5283
|
-
children: /* @__PURE__ */
|
|
5383
|
+
children: /* @__PURE__ */ jsx10(WithKey, { shortcut: "V", children: /* @__PURE__ */ jsx10(MousePointer2, { className: "h-4 w-4" }) })
|
|
5284
5384
|
}
|
|
5285
5385
|
),
|
|
5286
|
-
/* @__PURE__ */
|
|
5386
|
+
/* @__PURE__ */ jsx10(
|
|
5287
5387
|
ToolbarButton,
|
|
5288
5388
|
{
|
|
5289
5389
|
label: "Hand (H): drag to move around",
|
|
5290
5390
|
active: handMode,
|
|
5291
5391
|
onClick: onHandMode,
|
|
5292
|
-
children: /* @__PURE__ */
|
|
5392
|
+
children: /* @__PURE__ */ jsx10(WithKey, { shortcut: "H", children: /* @__PURE__ */ jsx10(Hand, { className: "h-4 w-4" }) })
|
|
5293
5393
|
}
|
|
5294
5394
|
),
|
|
5295
|
-
/* @__PURE__ */
|
|
5296
|
-
/* @__PURE__ */
|
|
5395
|
+
/* @__PURE__ */ jsx10(ToolbarDivider, {}),
|
|
5396
|
+
/* @__PURE__ */ jsx10(
|
|
5297
5397
|
LevelSwitch,
|
|
5298
5398
|
{
|
|
5299
5399
|
level,
|
|
@@ -5301,8 +5401,8 @@ var CanvasControls_default = memo6(function CanvasControls({
|
|
|
5301
5401
|
unavailable: unavailableLevels
|
|
5302
5402
|
}
|
|
5303
5403
|
),
|
|
5304
|
-
/* @__PURE__ */
|
|
5305
|
-
/* @__PURE__ */
|
|
5404
|
+
/* @__PURE__ */ jsx10(ToolbarDivider, {}),
|
|
5405
|
+
/* @__PURE__ */ jsx10(
|
|
5306
5406
|
ToolbarButton,
|
|
5307
5407
|
{
|
|
5308
5408
|
label: editable ? "Sticky note (N): click where it goes" : `Sticky note (N): on L${level}, where it's clicked`,
|
|
@@ -5310,10 +5410,10 @@ var CanvasControls_default = memo6(function CanvasControls({
|
|
|
5310
5410
|
disabled: locked,
|
|
5311
5411
|
hint: locked ? "The canvas is locked" : void 0,
|
|
5312
5412
|
onClick: onToggleNoteMode,
|
|
5313
|
-
children: /* @__PURE__ */
|
|
5413
|
+
children: /* @__PURE__ */ jsx10(WithKey, { shortcut: "N", children: /* @__PURE__ */ jsx10(StickyNote4, { className: "h-4 w-4 text-yellow-500" }) })
|
|
5314
5414
|
}
|
|
5315
5415
|
),
|
|
5316
|
-
/* @__PURE__ */
|
|
5416
|
+
/* @__PURE__ */ jsx10(
|
|
5317
5417
|
ToolbarButton,
|
|
5318
5418
|
{
|
|
5319
5419
|
label: editable ? "Text (T): click anywhere and type" : `Text (T): on L${level}, where it's clicked`,
|
|
@@ -5321,19 +5421,19 @@ var CanvasControls_default = memo6(function CanvasControls({
|
|
|
5321
5421
|
disabled: locked,
|
|
5322
5422
|
hint: locked ? "The canvas is locked" : void 0,
|
|
5323
5423
|
onClick: onToggleTextMode,
|
|
5324
|
-
children: /* @__PURE__ */
|
|
5424
|
+
children: /* @__PURE__ */ jsx10(WithKey, { shortcut: "T", children: /* @__PURE__ */ jsx10(Type, { className: "h-4 w-4" }) })
|
|
5325
5425
|
}
|
|
5326
5426
|
),
|
|
5327
|
-
/* @__PURE__ */
|
|
5427
|
+
/* @__PURE__ */ jsx10(
|
|
5328
5428
|
ToolbarButton,
|
|
5329
5429
|
{
|
|
5330
5430
|
label: "Comment (C): click where it goes, or on a node",
|
|
5331
5431
|
active: commentMode,
|
|
5332
5432
|
onClick: onToggleCommentMode,
|
|
5333
|
-
children: /* @__PURE__ */
|
|
5433
|
+
children: /* @__PURE__ */ jsx10(WithKey, { shortcut: "C", children: /* @__PURE__ */ jsx10(MessageCircle2, { className: "h-4 w-4" }) })
|
|
5334
5434
|
}
|
|
5335
5435
|
),
|
|
5336
|
-
/* @__PURE__ */
|
|
5436
|
+
/* @__PURE__ */ jsx10(
|
|
5337
5437
|
ToolbarButton,
|
|
5338
5438
|
{
|
|
5339
5439
|
label: "Hotspot (A): click a node, or anywhere, to flag it",
|
|
@@ -5341,24 +5441,24 @@ var CanvasControls_default = memo6(function CanvasControls({
|
|
|
5341
5441
|
disabled: locked,
|
|
5342
5442
|
hint: locked ? "The canvas is locked" : void 0,
|
|
5343
5443
|
onClick: onToggleHotspotMode,
|
|
5344
|
-
children: /* @__PURE__ */
|
|
5444
|
+
children: /* @__PURE__ */ jsx10(WithKey, { shortcut: "A", children: /* @__PURE__ */ jsx10(TriangleAlert3, { className: "h-4 w-4 text-amber-600" }) })
|
|
5345
5445
|
}
|
|
5346
5446
|
),
|
|
5347
5447
|
extras
|
|
5348
5448
|
] }),
|
|
5349
|
-
(noteMode || textMode || commentMode || hotspotMode) && /* @__PURE__ */
|
|
5449
|
+
(noteMode || textMode || commentMode || hotspotMode) && /* @__PURE__ */ jsxs7("p", { className: "pointer-events-none mt-2 text-center text-xs text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
5350
5450
|
TOOL_HINTS[noteMode ? "note" : commentMode ? "comment" : hotspotMode ? "hotspot" : "text"],
|
|
5351
5451
|
" ",
|
|
5352
5452
|
"\xB7",
|
|
5353
5453
|
" ",
|
|
5354
|
-
/* @__PURE__ */
|
|
5454
|
+
/* @__PURE__ */ jsx10("kbd", { className: "rounded border border-[rgb(var(--ec-page-border))] px-1 font-sans text-[11px]", children: "Esc" }),
|
|
5355
5455
|
" ",
|
|
5356
5456
|
"to cancel"
|
|
5357
5457
|
] })
|
|
5358
5458
|
] })
|
|
5359
5459
|
);
|
|
5360
5460
|
});
|
|
5361
|
-
var ViewControls =
|
|
5461
|
+
var ViewControls = memo7(function ViewControls2({
|
|
5362
5462
|
canUndo,
|
|
5363
5463
|
canRedo,
|
|
5364
5464
|
onUndo,
|
|
@@ -5370,91 +5470,91 @@ var ViewControls = memo6(function ViewControls2({
|
|
|
5370
5470
|
comments,
|
|
5371
5471
|
hotspots
|
|
5372
5472
|
}) {
|
|
5373
|
-
const { zoomIn, zoomOut, fitView } =
|
|
5374
|
-
return /* @__PURE__ */
|
|
5375
|
-
/* @__PURE__ */
|
|
5376
|
-
/* @__PURE__ */
|
|
5473
|
+
const { zoomIn, zoomOut, fitView } = useReactFlow5();
|
|
5474
|
+
return /* @__PURE__ */ jsxs7(Fragment7, { children: [
|
|
5475
|
+
/* @__PURE__ */ jsxs7(Toolbar, { children: [
|
|
5476
|
+
/* @__PURE__ */ jsx10(
|
|
5377
5477
|
ToolbarButton,
|
|
5378
5478
|
{
|
|
5379
5479
|
label: "Zoom out",
|
|
5380
5480
|
onClick: () => void zoomOut({ duration: 200 }),
|
|
5381
|
-
children: /* @__PURE__ */
|
|
5481
|
+
children: /* @__PURE__ */ jsx10(ZoomOut, { className: "h-4 w-4" })
|
|
5382
5482
|
}
|
|
5383
5483
|
),
|
|
5384
|
-
/* @__PURE__ */
|
|
5385
|
-
/* @__PURE__ */
|
|
5484
|
+
/* @__PURE__ */ jsx10(ZoomLevel, {}),
|
|
5485
|
+
/* @__PURE__ */ jsx10(
|
|
5386
5486
|
ToolbarButton,
|
|
5387
5487
|
{
|
|
5388
5488
|
label: "Zoom in",
|
|
5389
5489
|
onClick: () => void zoomIn({ duration: 200 }),
|
|
5390
|
-
children: /* @__PURE__ */
|
|
5490
|
+
children: /* @__PURE__ */ jsx10(ZoomIn, { className: "h-4 w-4" })
|
|
5391
5491
|
}
|
|
5392
5492
|
)
|
|
5393
5493
|
] }),
|
|
5394
|
-
/* @__PURE__ */
|
|
5395
|
-
/* @__PURE__ */
|
|
5494
|
+
/* @__PURE__ */ jsxs7(Toolbar, { children: [
|
|
5495
|
+
/* @__PURE__ */ jsx10(
|
|
5396
5496
|
ToolbarButton,
|
|
5397
5497
|
{
|
|
5398
5498
|
label: "Undo (\u2318Z)",
|
|
5399
5499
|
hint: canUndo ? void 0 : "Nothing to undo",
|
|
5400
5500
|
disabled: !canUndo,
|
|
5401
5501
|
onClick: onUndo,
|
|
5402
|
-
children: /* @__PURE__ */
|
|
5502
|
+
children: /* @__PURE__ */ jsx10(Undo, { className: "h-4 w-4" })
|
|
5403
5503
|
}
|
|
5404
5504
|
),
|
|
5405
|
-
/* @__PURE__ */
|
|
5505
|
+
/* @__PURE__ */ jsx10(
|
|
5406
5506
|
ToolbarButton,
|
|
5407
5507
|
{
|
|
5408
5508
|
label: "Redo (\u21E7\u2318Z)",
|
|
5409
5509
|
hint: canRedo ? void 0 : "Nothing to redo",
|
|
5410
5510
|
disabled: !canRedo,
|
|
5411
5511
|
onClick: onRedo,
|
|
5412
|
-
children: /* @__PURE__ */
|
|
5512
|
+
children: /* @__PURE__ */ jsx10(Redo, { className: "h-4 w-4" })
|
|
5413
5513
|
}
|
|
5414
5514
|
)
|
|
5415
5515
|
] }),
|
|
5416
|
-
/* @__PURE__ */
|
|
5417
|
-
/* @__PURE__ */
|
|
5516
|
+
/* @__PURE__ */ jsxs7(Toolbar, { children: [
|
|
5517
|
+
/* @__PURE__ */ jsx10(
|
|
5418
5518
|
ToolbarButton,
|
|
5419
5519
|
{
|
|
5420
5520
|
label: "Fit view (\u21E71)",
|
|
5421
5521
|
onClick: () => void fitView({ ...fitOptions, duration: 500 }),
|
|
5422
|
-
children: /* @__PURE__ */
|
|
5522
|
+
children: /* @__PURE__ */ jsx10(Maximize, { className: "h-4 w-4" })
|
|
5423
5523
|
}
|
|
5424
5524
|
),
|
|
5425
|
-
/* @__PURE__ */
|
|
5525
|
+
/* @__PURE__ */ jsx10(
|
|
5426
5526
|
ToolbarButton,
|
|
5427
5527
|
{
|
|
5428
5528
|
label: reorderLabel,
|
|
5429
5529
|
hint: locked ? "The canvas is locked" : void 0,
|
|
5430
5530
|
disabled: locked,
|
|
5431
5531
|
onClick: onReorder,
|
|
5432
|
-
children: /* @__PURE__ */
|
|
5532
|
+
children: /* @__PURE__ */ jsx10(SendToBack2, { className: "h-4 w-4" })
|
|
5433
5533
|
}
|
|
5434
5534
|
)
|
|
5435
5535
|
] }),
|
|
5436
|
-
comments && /* @__PURE__ */
|
|
5437
|
-
/* @__PURE__ */
|
|
5536
|
+
comments && /* @__PURE__ */ jsxs7(Toolbar, { children: [
|
|
5537
|
+
/* @__PURE__ */ jsx10(
|
|
5438
5538
|
ToolbarButton,
|
|
5439
5539
|
{
|
|
5440
5540
|
label: comments.open ? `Comments (${comments.open} open)` : "Comments",
|
|
5441
5541
|
active: comments.active,
|
|
5442
5542
|
onClick: comments.onToggle,
|
|
5443
|
-
children: /* @__PURE__ */
|
|
5444
|
-
/* @__PURE__ */
|
|
5445
|
-
comments.open > 0 && /* @__PURE__ */
|
|
5543
|
+
children: /* @__PURE__ */ jsxs7("span", { className: "relative", children: [
|
|
5544
|
+
/* @__PURE__ */ jsx10(MessageSquareText, { className: "h-4 w-4" }),
|
|
5545
|
+
comments.open > 0 && /* @__PURE__ */ jsx10("span", { className: "absolute -right-2 -top-2 min-w-4 rounded-full bg-[rgb(var(--ec-accent))] px-1 text-center text-[9px] font-semibold leading-4 text-white", children: comments.open })
|
|
5446
5546
|
] })
|
|
5447
5547
|
}
|
|
5448
5548
|
),
|
|
5449
|
-
hotspots && /* @__PURE__ */
|
|
5549
|
+
hotspots && /* @__PURE__ */ jsx10(
|
|
5450
5550
|
ToolbarButton,
|
|
5451
5551
|
{
|
|
5452
5552
|
label: hotspots.count ? `Hotspots (${hotspots.count})` : "Hotspots",
|
|
5453
5553
|
active: hotspots.active,
|
|
5454
5554
|
onClick: hotspots.onToggle,
|
|
5455
|
-
children: /* @__PURE__ */
|
|
5456
|
-
/* @__PURE__ */
|
|
5457
|
-
hotspots.count > 0 && /* @__PURE__ */
|
|
5555
|
+
children: /* @__PURE__ */ jsxs7("span", { className: "relative", children: [
|
|
5556
|
+
/* @__PURE__ */ jsx10(TriangleAlert3, { className: "h-4 w-4" }),
|
|
5557
|
+
hotspots.count > 0 && /* @__PURE__ */ jsx10(
|
|
5458
5558
|
"span",
|
|
5459
5559
|
{
|
|
5460
5560
|
className: "absolute -right-2 -top-2 min-w-4 rounded-full px-1 text-center text-[9px] font-semibold leading-4 text-white",
|
|
@@ -5472,12 +5572,12 @@ var ViewControls = memo6(function ViewControls2({
|
|
|
5472
5572
|
});
|
|
5473
5573
|
|
|
5474
5574
|
// src/studio/components/ContainerChooser.tsx
|
|
5475
|
-
import { useEffect as
|
|
5476
|
-
import { X as
|
|
5477
|
-
import { jsx as
|
|
5575
|
+
import { useEffect as useEffect8, useState as useState10 } from "react";
|
|
5576
|
+
import { X as X4 } from "lucide-react";
|
|
5577
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
5478
5578
|
var plural = (count, noun) => `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
5479
|
-
var CardPreview = () => /* @__PURE__ */
|
|
5480
|
-
/* @__PURE__ */
|
|
5579
|
+
var CardPreview = () => /* @__PURE__ */ jsxs8("svg", { viewBox: "0 0 64 36", className: "h-9 w-16", "aria-hidden": true, children: [
|
|
5580
|
+
/* @__PURE__ */ jsx11(
|
|
5481
5581
|
"rect",
|
|
5482
5582
|
{
|
|
5483
5583
|
x: "18",
|
|
@@ -5492,7 +5592,7 @@ var CardPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36", cla
|
|
|
5492
5592
|
strokeWidth: "1.5"
|
|
5493
5593
|
}
|
|
5494
5594
|
),
|
|
5495
|
-
/* @__PURE__ */
|
|
5595
|
+
/* @__PURE__ */ jsx11(
|
|
5496
5596
|
"rect",
|
|
5497
5597
|
{
|
|
5498
5598
|
x: "23",
|
|
@@ -5504,7 +5604,7 @@ var CardPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36", cla
|
|
|
5504
5604
|
fillOpacity: "0.6"
|
|
5505
5605
|
}
|
|
5506
5606
|
),
|
|
5507
|
-
/* @__PURE__ */
|
|
5607
|
+
/* @__PURE__ */ jsx11(
|
|
5508
5608
|
"rect",
|
|
5509
5609
|
{
|
|
5510
5610
|
x: "23",
|
|
@@ -5516,7 +5616,7 @@ var CardPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36", cla
|
|
|
5516
5616
|
fillOpacity: "0.35"
|
|
5517
5617
|
}
|
|
5518
5618
|
),
|
|
5519
|
-
/* @__PURE__ */
|
|
5619
|
+
/* @__PURE__ */ jsx11(
|
|
5520
5620
|
"path",
|
|
5521
5621
|
{
|
|
5522
5622
|
d: "M46 18h12",
|
|
@@ -5526,7 +5626,7 @@ var CardPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36", cla
|
|
|
5526
5626
|
strokeDasharray: "2 2"
|
|
5527
5627
|
}
|
|
5528
5628
|
),
|
|
5529
|
-
/* @__PURE__ */
|
|
5629
|
+
/* @__PURE__ */ jsx11(
|
|
5530
5630
|
"rect",
|
|
5531
5631
|
{
|
|
5532
5632
|
x: "57",
|
|
@@ -5539,8 +5639,8 @@ var CardPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36", cla
|
|
|
5539
5639
|
}
|
|
5540
5640
|
)
|
|
5541
5641
|
] });
|
|
5542
|
-
var ContainerPreview = () => /* @__PURE__ */
|
|
5543
|
-
/* @__PURE__ */
|
|
5642
|
+
var ContainerPreview = () => /* @__PURE__ */ jsxs8("svg", { viewBox: "0 0 64 36", className: "h-9 w-16", "aria-hidden": true, children: [
|
|
5643
|
+
/* @__PURE__ */ jsx11(
|
|
5544
5644
|
"rect",
|
|
5545
5645
|
{
|
|
5546
5646
|
x: "4",
|
|
@@ -5555,7 +5655,7 @@ var ContainerPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36"
|
|
|
5555
5655
|
strokeWidth: "1.5"
|
|
5556
5656
|
}
|
|
5557
5657
|
),
|
|
5558
|
-
/* @__PURE__ */
|
|
5658
|
+
/* @__PURE__ */ jsx11(
|
|
5559
5659
|
"path",
|
|
5560
5660
|
{
|
|
5561
5661
|
d: "M4 10h56",
|
|
@@ -5564,7 +5664,7 @@ var ContainerPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36"
|
|
|
5564
5664
|
strokeWidth: "1"
|
|
5565
5665
|
}
|
|
5566
5666
|
),
|
|
5567
|
-
/* @__PURE__ */
|
|
5667
|
+
/* @__PURE__ */ jsx11(
|
|
5568
5668
|
"rect",
|
|
5569
5669
|
{
|
|
5570
5670
|
x: "8",
|
|
@@ -5576,7 +5676,7 @@ var ContainerPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36"
|
|
|
5576
5676
|
fillOpacity: "0.6"
|
|
5577
5677
|
}
|
|
5578
5678
|
),
|
|
5579
|
-
/* @__PURE__ */
|
|
5679
|
+
/* @__PURE__ */ jsx11(
|
|
5580
5680
|
"rect",
|
|
5581
5681
|
{
|
|
5582
5682
|
x: "10",
|
|
@@ -5588,7 +5688,7 @@ var ContainerPreview = () => /* @__PURE__ */ jsxs7("svg", { viewBox: "0 0 64 36"
|
|
|
5588
5688
|
fillOpacity: "0.5"
|
|
5589
5689
|
}
|
|
5590
5690
|
),
|
|
5591
|
-
/* @__PURE__ */
|
|
5691
|
+
/* @__PURE__ */ jsx11(
|
|
5592
5692
|
"rect",
|
|
5593
5693
|
{
|
|
5594
5694
|
x: "36",
|
|
@@ -5623,12 +5723,12 @@ function ContainerChooser({
|
|
|
5623
5723
|
onChoose,
|
|
5624
5724
|
onCancel
|
|
5625
5725
|
}) {
|
|
5626
|
-
const [withContents, setWithContents] =
|
|
5726
|
+
const [withContents, setWithContents] = useState10(true);
|
|
5627
5727
|
const contentsLabel = contents ? [
|
|
5628
5728
|
contents.systems > 0 && plural(contents.systems, "system"),
|
|
5629
5729
|
contents.services > 0 && plural(contents.services, "service")
|
|
5630
5730
|
].filter(Boolean).join(" and ") : "";
|
|
5631
|
-
|
|
5731
|
+
useEffect8(() => {
|
|
5632
5732
|
const onKeyDown = (event) => event.key === "Escape" && onCancel();
|
|
5633
5733
|
window.addEventListener("keydown", onKeyDown);
|
|
5634
5734
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
@@ -5641,7 +5741,7 @@ function ContainerChooser({
|
|
|
5641
5741
|
Math.max(position.y - 20, 12),
|
|
5642
5742
|
window.innerHeight - (contentsLabel ? 260 : 200)
|
|
5643
5743
|
);
|
|
5644
|
-
return /* @__PURE__ */
|
|
5744
|
+
return /* @__PURE__ */ jsx11("div", { className: "fixed inset-0 z-50", onPointerDown: onCancel, children: /* @__PURE__ */ jsxs8(
|
|
5645
5745
|
"div",
|
|
5646
5746
|
{
|
|
5647
5747
|
role: "dialog",
|
|
@@ -5650,26 +5750,26 @@ function ContainerChooser({
|
|
|
5650
5750
|
className: "absolute w-80 rounded-lg border p-1.5 shadow-xl bg-[rgb(var(--ec-card-bg))] border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text))]",
|
|
5651
5751
|
style: { left, top },
|
|
5652
5752
|
children: [
|
|
5653
|
-
/* @__PURE__ */
|
|
5654
|
-
/* @__PURE__ */
|
|
5655
|
-
/* @__PURE__ */
|
|
5753
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-start justify-between gap-2 px-2 pb-1.5 pt-1", children: [
|
|
5754
|
+
/* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
|
|
5755
|
+
/* @__PURE__ */ jsxs8("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
5656
5756
|
"Add this ",
|
|
5657
5757
|
kind,
|
|
5658
5758
|
" as"
|
|
5659
5759
|
] }),
|
|
5660
|
-
name && /* @__PURE__ */
|
|
5760
|
+
name && /* @__PURE__ */ jsx11("p", { className: "truncate text-xs font-semibold", children: name })
|
|
5661
5761
|
] }),
|
|
5662
|
-
/* @__PURE__ */
|
|
5762
|
+
/* @__PURE__ */ jsx11(
|
|
5663
5763
|
"button",
|
|
5664
5764
|
{
|
|
5665
5765
|
onClick: onCancel,
|
|
5666
5766
|
"aria-label": "Cancel",
|
|
5667
5767
|
className: "rounded p-0.5 text-[rgb(var(--ec-icon-color))] hover:bg-[rgb(var(--ec-page-border)/0.5)]",
|
|
5668
|
-
children: /* @__PURE__ */
|
|
5768
|
+
children: /* @__PURE__ */ jsx11(X4, { size: 14 })
|
|
5669
5769
|
}
|
|
5670
5770
|
)
|
|
5671
5771
|
] }),
|
|
5672
|
-
/* @__PURE__ */
|
|
5772
|
+
/* @__PURE__ */ jsx11("div", { className: "grid grid-cols-2 gap-1.5 px-0.5 pb-0.5", children: OPTIONS.map(({ as, label, hint, Preview }) => /* @__PURE__ */ jsxs8(
|
|
5673
5773
|
"button",
|
|
5674
5774
|
{
|
|
5675
5775
|
autoFocus: as === "container",
|
|
@@ -5678,15 +5778,15 @@ function ContainerChooser({
|
|
|
5678
5778
|
),
|
|
5679
5779
|
className: "flex flex-col items-center gap-1 rounded-md border px-2 pb-1.5 pt-2 text-xs outline-none transition-colors border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text-muted))] hover:border-[rgb(var(--ec-accent))] hover:bg-[color-mix(in_srgb,rgb(var(--ec-accent))_8%,transparent)] hover:text-[rgb(var(--ec-accent))] focus-visible:border-[rgb(var(--ec-accent))] focus-visible:text-[rgb(var(--ec-accent))]",
|
|
5680
5780
|
children: [
|
|
5681
|
-
/* @__PURE__ */
|
|
5682
|
-
/* @__PURE__ */
|
|
5683
|
-
/* @__PURE__ */
|
|
5781
|
+
/* @__PURE__ */ jsx11(Preview, {}),
|
|
5782
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold", children: label }),
|
|
5783
|
+
/* @__PURE__ */ jsx11("span", { className: "text-center text-[10px] leading-tight text-[rgb(var(--ec-page-text-muted))]", children: hint })
|
|
5684
5784
|
]
|
|
5685
5785
|
},
|
|
5686
5786
|
as
|
|
5687
5787
|
)) }),
|
|
5688
|
-
contentsLabel && /* @__PURE__ */
|
|
5689
|
-
/* @__PURE__ */
|
|
5788
|
+
contentsLabel && /* @__PURE__ */ jsxs8("label", { className: "mt-1 flex items-center gap-2 rounded-md px-2 py-1.5 text-[11px] text-[rgb(var(--ec-page-text-muted))]", children: [
|
|
5789
|
+
/* @__PURE__ */ jsx11(
|
|
5690
5790
|
"input",
|
|
5691
5791
|
{
|
|
5692
5792
|
type: "checkbox",
|
|
@@ -5704,29 +5804,29 @@ function ContainerChooser({
|
|
|
5704
5804
|
}
|
|
5705
5805
|
|
|
5706
5806
|
// src/studio/components/EditButton.tsx
|
|
5707
|
-
import { memo as
|
|
5708
|
-
import { NodeToolbar, Position as
|
|
5807
|
+
import { memo as memo8 } from "react";
|
|
5808
|
+
import { NodeToolbar, Position as Position4, useStore } from "@xyflow/react";
|
|
5709
5809
|
import { Info as Info2, Pencil as Pencil3 } from "lucide-react";
|
|
5710
|
-
import { Fragment as
|
|
5810
|
+
import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5711
5811
|
var MIN_SCALE = 0.4;
|
|
5712
5812
|
var MAX_SCALE = 1.6;
|
|
5713
5813
|
var OFFSET = 8;
|
|
5714
|
-
var EditButton_default =
|
|
5814
|
+
var EditButton_default = memo8(function EditButton({
|
|
5715
5815
|
nodeId,
|
|
5716
5816
|
locked,
|
|
5717
5817
|
onClick
|
|
5718
5818
|
}) {
|
|
5719
5819
|
const zoom = useStore((state) => state.transform[2]);
|
|
5720
5820
|
const scale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, zoom));
|
|
5721
|
-
return /* @__PURE__ */
|
|
5821
|
+
return /* @__PURE__ */ jsx12(
|
|
5722
5822
|
NodeToolbar,
|
|
5723
5823
|
{
|
|
5724
5824
|
nodeId,
|
|
5725
5825
|
isVisible: true,
|
|
5726
|
-
position:
|
|
5826
|
+
position: Position4.Top,
|
|
5727
5827
|
align: "end",
|
|
5728
5828
|
offset: OFFSET * scale,
|
|
5729
|
-
children: /* @__PURE__ */
|
|
5829
|
+
children: /* @__PURE__ */ jsx12(
|
|
5730
5830
|
"button",
|
|
5731
5831
|
{
|
|
5732
5832
|
type: "button",
|
|
@@ -5736,11 +5836,11 @@ var EditButton_default = memo7(function EditButton({
|
|
|
5736
5836
|
transformOrigin: "bottom right"
|
|
5737
5837
|
},
|
|
5738
5838
|
onClick,
|
|
5739
|
-
children: locked ? /* @__PURE__ */
|
|
5740
|
-
/* @__PURE__ */
|
|
5839
|
+
children: locked ? /* @__PURE__ */ jsxs9(Fragment8, { children: [
|
|
5840
|
+
/* @__PURE__ */ jsx12(Info2, { "aria-hidden": true }),
|
|
5741
5841
|
" Details"
|
|
5742
|
-
] }) : /* @__PURE__ */
|
|
5743
|
-
/* @__PURE__ */
|
|
5842
|
+
] }) : /* @__PURE__ */ jsxs9(Fragment8, { children: [
|
|
5843
|
+
/* @__PURE__ */ jsx12(Pencil3, { "aria-hidden": true }),
|
|
5744
5844
|
" Edit"
|
|
5745
5845
|
] })
|
|
5746
5846
|
}
|
|
@@ -5751,14 +5851,14 @@ var EditButton_default = memo7(function EditButton({
|
|
|
5751
5851
|
|
|
5752
5852
|
// src/studio/components/Palette.tsx
|
|
5753
5853
|
import {
|
|
5754
|
-
memo as
|
|
5755
|
-
useCallback as
|
|
5756
|
-
useEffect as
|
|
5757
|
-
useRef as
|
|
5758
|
-
useState as
|
|
5854
|
+
memo as memo9,
|
|
5855
|
+
useCallback as useCallback5,
|
|
5856
|
+
useEffect as useEffect9,
|
|
5857
|
+
useRef as useRef8,
|
|
5858
|
+
useState as useState11
|
|
5759
5859
|
} from "react";
|
|
5760
5860
|
import { ChevronDown, GripVertical as GripVertical2 } from "lucide-react";
|
|
5761
|
-
import { Fragment as
|
|
5861
|
+
import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5762
5862
|
var COMPONENT_DRAG_TYPE = "application/eventcatalog-studio";
|
|
5763
5863
|
var listedDefinitions = NODE_CATEGORIES.map((category) => ({
|
|
5764
5864
|
...category,
|
|
@@ -5802,7 +5902,7 @@ function PaletteItem({
|
|
|
5802
5902
|
title,
|
|
5803
5903
|
trailing
|
|
5804
5904
|
}) {
|
|
5805
|
-
return /* @__PURE__ */
|
|
5905
|
+
return /* @__PURE__ */ jsxs10(
|
|
5806
5906
|
"button",
|
|
5807
5907
|
{
|
|
5808
5908
|
type: "button",
|
|
@@ -5814,13 +5914,13 @@ function PaletteItem({
|
|
|
5814
5914
|
title,
|
|
5815
5915
|
className: `group flex w-full items-center gap-2.5 rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg))] py-1 pl-1 pr-2 text-left text-[rgb(var(--ec-page-text))] shadow-[0_1px_2px_rgb(0_0_0/0.05)] transition-[transform,box-shadow,border-color] duration-150 ${usable ? "cursor-grab hover:-translate-y-px hover:border-[color-mix(in_srgb,rgb(var(--ec-accent))_45%,transparent)]! hover:shadow-[0_4px_12px_rgb(0_0_0/0.08)] active:translate-y-0 active:cursor-grabbing" : "cursor-not-allowed opacity-40 grayscale"}`,
|
|
5816
5916
|
children: [
|
|
5817
|
-
/* @__PURE__ */
|
|
5818
|
-
/* @__PURE__ */
|
|
5819
|
-
/* @__PURE__ */
|
|
5820
|
-
description && /* @__PURE__ */
|
|
5917
|
+
/* @__PURE__ */ jsx13("span", { className: "flex h-8 w-8 flex-none items-center justify-center rounded-md bg-[rgb(var(--ec-content-hover))]", children: /* @__PURE__ */ jsx13(Icon, { size: 16, className: iconClassName }) }),
|
|
5918
|
+
/* @__PURE__ */ jsxs10("span", { className: "min-w-0 flex-1", children: [
|
|
5919
|
+
/* @__PURE__ */ jsx13("span", { className: "block truncate text-[13px] font-medium leading-tight", children: label }),
|
|
5920
|
+
description && /* @__PURE__ */ jsx13("span", { className: "block truncate text-[11px] leading-snug text-[rgb(var(--ec-page-text-muted))]", children: description })
|
|
5821
5921
|
] }),
|
|
5822
5922
|
trailing ?? (usable && onDragStart && // It's picked up and dragged on (a click adds it in the middle): a small handle says so
|
|
5823
|
-
/* @__PURE__ */
|
|
5923
|
+
/* @__PURE__ */ jsx13(
|
|
5824
5924
|
GripVertical2,
|
|
5825
5925
|
{
|
|
5826
5926
|
"aria-hidden": true,
|
|
@@ -5837,19 +5937,19 @@ function PaletteSection({
|
|
|
5837
5937
|
divided = false,
|
|
5838
5938
|
children
|
|
5839
5939
|
}) {
|
|
5840
|
-
return /* @__PURE__ */
|
|
5940
|
+
return /* @__PURE__ */ jsxs10(
|
|
5841
5941
|
"section",
|
|
5842
5942
|
{
|
|
5843
5943
|
className: divided ? "border-t border-[rgb(var(--ec-page-border))] pt-3" : "",
|
|
5844
5944
|
children: [
|
|
5845
|
-
/* @__PURE__ */
|
|
5846
|
-
/* @__PURE__ */
|
|
5945
|
+
/* @__PURE__ */ jsx13("h3", { className: "mb-1.5 text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))]", children: title }),
|
|
5946
|
+
/* @__PURE__ */ jsx13("div", { className: "space-y-1.5", children })
|
|
5847
5947
|
]
|
|
5848
5948
|
}
|
|
5849
5949
|
);
|
|
5850
5950
|
}
|
|
5851
5951
|
var COMPONENTS_TAB = "components";
|
|
5852
|
-
var Palette =
|
|
5952
|
+
var Palette = memo9(function Palette2({
|
|
5853
5953
|
level,
|
|
5854
5954
|
onAddComponent,
|
|
5855
5955
|
footer,
|
|
@@ -5859,7 +5959,7 @@ var Palette = memo8(function Palette2({
|
|
|
5859
5959
|
startCollapsed
|
|
5860
5960
|
}) {
|
|
5861
5961
|
const { startDrag, ghost } = useDragGhost();
|
|
5862
|
-
const [collapsed, setCollapsed] =
|
|
5962
|
+
const [collapsed, setCollapsed] = useState11(
|
|
5863
5963
|
() => startCollapsed ?? readCollapsed()
|
|
5864
5964
|
);
|
|
5865
5965
|
const remember = (next) => {
|
|
@@ -5869,13 +5969,13 @@ var Palette = memo8(function Palette2({
|
|
|
5869
5969
|
} catch {
|
|
5870
5970
|
}
|
|
5871
5971
|
};
|
|
5872
|
-
const toggle =
|
|
5972
|
+
const toggle = useCallback5(() => {
|
|
5873
5973
|
setCollapsed((current) => {
|
|
5874
5974
|
remember(!current);
|
|
5875
5975
|
return !current;
|
|
5876
5976
|
});
|
|
5877
5977
|
}, []);
|
|
5878
|
-
const [ownTab, setOwnTab] =
|
|
5978
|
+
const [ownTab, setOwnTab] = useState11(COMPONENTS_TAB);
|
|
5879
5979
|
const shown = tab ?? (tabs?.some((candidate) => candidate.id === ownTab) ? ownTab : COMPONENTS_TAB);
|
|
5880
5980
|
const choose = (next) => {
|
|
5881
5981
|
setOwnTab(next);
|
|
@@ -5885,8 +5985,8 @@ var Palette = memo8(function Palette2({
|
|
|
5885
5985
|
remember(false);
|
|
5886
5986
|
}
|
|
5887
5987
|
};
|
|
5888
|
-
const chosen =
|
|
5889
|
-
|
|
5988
|
+
const chosen = useRef8(tab);
|
|
5989
|
+
useEffect9(() => {
|
|
5890
5990
|
if (tab === chosen.current) return;
|
|
5891
5991
|
chosen.current = tab;
|
|
5892
5992
|
if (tab === void 0 || !collapsed) return;
|
|
@@ -5902,7 +6002,7 @@ var Palette = memo8(function Palette2({
|
|
|
5902
6002
|
const { label, summary, firstLevel } = definition;
|
|
5903
6003
|
const key = componentKey(definition);
|
|
5904
6004
|
const { icon, className } = NODE_ICONS[key] ?? NODE_ICONS[definition.type];
|
|
5905
|
-
return /* @__PURE__ */
|
|
6005
|
+
return /* @__PURE__ */ jsx13(
|
|
5906
6006
|
PaletteItem,
|
|
5907
6007
|
{
|
|
5908
6008
|
icon,
|
|
@@ -5921,18 +6021,18 @@ var Palette = memo8(function Palette2({
|
|
|
5921
6021
|
key
|
|
5922
6022
|
);
|
|
5923
6023
|
};
|
|
5924
|
-
const components2 = /* @__PURE__ */
|
|
6024
|
+
const components2 = /* @__PURE__ */ jsxs10(Fragment9, { children: [
|
|
5925
6025
|
listedDefinitions.map((category) => {
|
|
5926
6026
|
const definitions = category.definitions.filter(
|
|
5927
6027
|
(definition) => isShownOnLevel(definition.type, level)
|
|
5928
6028
|
);
|
|
5929
6029
|
if (!definitions.length) return null;
|
|
5930
|
-
return /* @__PURE__ */
|
|
6030
|
+
return /* @__PURE__ */ jsx13(PaletteSection, { title: category.label, children: definitions.map((definition) => tile(definition)) }, category.id);
|
|
5931
6031
|
}),
|
|
5932
|
-
unavailable.length > 0 && /* @__PURE__ */
|
|
6032
|
+
unavailable.length > 0 && /* @__PURE__ */ jsx13(PaletteSection, { title: `Not on Level ${level}`, divided: true, children: unavailable.map((definition) => tile(definition, false)) })
|
|
5933
6033
|
] });
|
|
5934
6034
|
const extra = tabs?.find((candidate) => candidate.id === shown);
|
|
5935
|
-
const tabButton = (id, label, badge) => /* @__PURE__ */
|
|
6035
|
+
const tabButton = (id, label, badge) => /* @__PURE__ */ jsxs10(
|
|
5936
6036
|
"button",
|
|
5937
6037
|
{
|
|
5938
6038
|
type: "button",
|
|
@@ -5942,18 +6042,18 @@ var Palette = memo8(function Palette2({
|
|
|
5942
6042
|
className: `flex flex-1 items-center justify-center gap-1 whitespace-nowrap rounded-md px-1.5 py-1 text-xs font-medium ${shown === id && !collapsed ? "bg-[rgb(var(--ec-card-bg))] text-[rgb(var(--ec-page-text))] shadow-sm" : "text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]"}`,
|
|
5943
6043
|
children: [
|
|
5944
6044
|
label,
|
|
5945
|
-
!!badge && /* @__PURE__ */
|
|
6045
|
+
!!badge && /* @__PURE__ */ jsx13("span", { className: "rounded-full bg-[rgb(var(--ec-accent))] px-1.5 text-[10px] leading-4 text-white", children: badge })
|
|
5946
6046
|
]
|
|
5947
6047
|
},
|
|
5948
6048
|
id
|
|
5949
6049
|
);
|
|
5950
|
-
return /* @__PURE__ */
|
|
6050
|
+
return /* @__PURE__ */ jsxs10(
|
|
5951
6051
|
"div",
|
|
5952
6052
|
{
|
|
5953
6053
|
className: `absolute left-3 top-[62px] z-10 flex w-[264px] flex-col ${collapsed ? "" : "bottom-[68px]"} rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg))] text-[rgb(var(--ec-page-text))] shadow-[0_8px_24px_rgb(0_0_0/0.08),0_1px_3px_rgb(0_0_0/0.05)]`,
|
|
5954
6054
|
children: [
|
|
5955
|
-
tabs?.length ? /* @__PURE__ */
|
|
5956
|
-
/* @__PURE__ */
|
|
6055
|
+
tabs?.length ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-none items-center gap-1 p-2", children: [
|
|
6056
|
+
/* @__PURE__ */ jsxs10(
|
|
5957
6057
|
"div",
|
|
5958
6058
|
{
|
|
5959
6059
|
role: "tablist",
|
|
@@ -5964,7 +6064,7 @@ var Palette = memo8(function Palette2({
|
|
|
5964
6064
|
]
|
|
5965
6065
|
}
|
|
5966
6066
|
),
|
|
5967
|
-
/* @__PURE__ */
|
|
6067
|
+
/* @__PURE__ */ jsx13(
|
|
5968
6068
|
"button",
|
|
5969
6069
|
{
|
|
5970
6070
|
type: "button",
|
|
@@ -5972,7 +6072,7 @@ var Palette = memo8(function Palette2({
|
|
|
5972
6072
|
"aria-expanded": !collapsed,
|
|
5973
6073
|
"aria-label": collapsed ? "Show the palette" : "Fold the palette away",
|
|
5974
6074
|
className: "flex-none rounded-md p-1 text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-page-border)/0.5)]",
|
|
5975
|
-
children: /* @__PURE__ */
|
|
6075
|
+
children: /* @__PURE__ */ jsx13(
|
|
5976
6076
|
ChevronDown,
|
|
5977
6077
|
{
|
|
5978
6078
|
"aria-hidden": true,
|
|
@@ -5981,7 +6081,7 @@ var Palette = memo8(function Palette2({
|
|
|
5981
6081
|
)
|
|
5982
6082
|
}
|
|
5983
6083
|
)
|
|
5984
|
-
] }) : /* @__PURE__ */
|
|
6084
|
+
] }) : /* @__PURE__ */ jsxs10(
|
|
5985
6085
|
"button",
|
|
5986
6086
|
{
|
|
5987
6087
|
type: "button",
|
|
@@ -5989,8 +6089,8 @@ var Palette = memo8(function Palette2({
|
|
|
5989
6089
|
"aria-expanded": !collapsed,
|
|
5990
6090
|
className: "flex flex-none items-center justify-between rounded-xl px-3.5 py-2.5 text-left text-[13px] font-semibold hover:bg-[rgb(var(--ec-content-hover))]!",
|
|
5991
6091
|
children: [
|
|
5992
|
-
/* @__PURE__ */
|
|
5993
|
-
/* @__PURE__ */
|
|
6092
|
+
/* @__PURE__ */ jsx13("span", { children: "Resources" }),
|
|
6093
|
+
/* @__PURE__ */ jsx13(
|
|
5994
6094
|
ChevronDown,
|
|
5995
6095
|
{
|
|
5996
6096
|
"aria-hidden": true,
|
|
@@ -6000,8 +6100,8 @@ var Palette = memo8(function Palette2({
|
|
|
6000
6100
|
]
|
|
6001
6101
|
}
|
|
6002
6102
|
),
|
|
6003
|
-
!collapsed && /* @__PURE__ */
|
|
6004
|
-
!collapsed && footer && /* @__PURE__ */
|
|
6103
|
+
!collapsed && /* @__PURE__ */ jsx13("div", { className: "min-h-0 flex-1 space-y-3 overflow-y-auto px-3 pb-3", children: extra ? extra.render(startDrag) : components2 }),
|
|
6104
|
+
!collapsed && footer && /* @__PURE__ */ jsx13("div", { className: "flex-none border-t border-[rgb(var(--ec-page-border))] px-3 py-2.5", children: footer }),
|
|
6005
6105
|
ghost
|
|
6006
6106
|
]
|
|
6007
6107
|
}
|
|
@@ -6009,7 +6109,7 @@ var Palette = memo8(function Palette2({
|
|
|
6009
6109
|
});
|
|
6010
6110
|
|
|
6011
6111
|
// src/studio/components/Shortcuts.tsx
|
|
6012
|
-
import { jsx as
|
|
6112
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
6013
6113
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform);
|
|
6014
6114
|
var MOD = isMac ? "\u2318" : "Ctrl";
|
|
6015
6115
|
var SHORTCUTS = [
|
|
@@ -6060,18 +6160,18 @@ var SHORTCUTS = [
|
|
|
6060
6160
|
}
|
|
6061
6161
|
];
|
|
6062
6162
|
function ShortcutsList({ omit = [] }) {
|
|
6063
|
-
return /* @__PURE__ */
|
|
6163
|
+
return /* @__PURE__ */ jsx14("div", { className: "grid min-h-0 gap-x-8 gap-y-5 overflow-y-auto px-5 py-4 md:grid-cols-2!", children: SHORTCUTS.map(({ group, items }) => ({
|
|
6064
6164
|
group,
|
|
6065
6165
|
items: items.filter(([label]) => !omit.includes(label))
|
|
6066
|
-
})).map(({ group, items }) => /* @__PURE__ */
|
|
6067
|
-
/* @__PURE__ */
|
|
6068
|
-
/* @__PURE__ */
|
|
6166
|
+
})).map(({ group, items }) => /* @__PURE__ */ jsxs11("section", { children: [
|
|
6167
|
+
/* @__PURE__ */ jsx14("h3", { className: "mb-2 text-[11px] font-semibold uppercase tracking-wide text-[rgb(var(--ec-page-text-muted))]", children: group }),
|
|
6168
|
+
/* @__PURE__ */ jsx14("ul", { className: "divide-y divide-[rgb(var(--ec-page-border))]", children: items.map(([label, keys]) => /* @__PURE__ */ jsxs11(
|
|
6069
6169
|
"li",
|
|
6070
6170
|
{
|
|
6071
6171
|
className: "flex items-center justify-between gap-3 py-1.5 text-sm",
|
|
6072
6172
|
children: [
|
|
6073
|
-
/* @__PURE__ */
|
|
6074
|
-
/* @__PURE__ */
|
|
6173
|
+
/* @__PURE__ */ jsx14("span", { children: label }),
|
|
6174
|
+
/* @__PURE__ */ jsx14("span", { className: "flex gap-1", children: keys.map((key) => /* @__PURE__ */ jsx14(
|
|
6075
6175
|
"kbd",
|
|
6076
6176
|
{
|
|
6077
6177
|
className: "min-w-6 rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 text-center font-sans text-xs text-[rgb(var(--ec-page-text-muted))]",
|
|
@@ -6087,9 +6187,9 @@ function ShortcutsList({ omit = [] }) {
|
|
|
6087
6187
|
}
|
|
6088
6188
|
|
|
6089
6189
|
// src/studio/components/EmptyCanvas.tsx
|
|
6090
|
-
import { useEffect as
|
|
6190
|
+
import { useEffect as useEffect10, useState as useState12 } from "react";
|
|
6091
6191
|
import { CircleHelp, FolderOpen, Plug } from "lucide-react";
|
|
6092
|
-
import { jsx as
|
|
6192
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6093
6193
|
var hintText = "font-[Excalifont,Inter,sans-serif] text-[14px] leading-snug text-[color-mix(in_srgb,rgb(var(--ec-page-text))_22%,transparent)]";
|
|
6094
6194
|
var arrow = {
|
|
6095
6195
|
fill: "none",
|
|
@@ -6099,24 +6199,24 @@ var arrow = {
|
|
|
6099
6199
|
strokeLinejoin: "round"
|
|
6100
6200
|
};
|
|
6101
6201
|
function Hints({ palette, live }) {
|
|
6102
|
-
return /* @__PURE__ */
|
|
6103
|
-
palette && /* @__PURE__ */
|
|
6104
|
-
/* @__PURE__ */
|
|
6105
|
-
/* @__PURE__ */
|
|
6106
|
-
/* @__PURE__ */
|
|
6202
|
+
return /* @__PURE__ */ jsxs12("div", { "aria-hidden": true, className: `hidden md:block! ${hintText}`, children: [
|
|
6203
|
+
palette && /* @__PURE__ */ jsxs12("div", { className: "absolute bottom-[120px] left-[290px] flex items-start gap-1", children: [
|
|
6204
|
+
/* @__PURE__ */ jsxs12("svg", { width: "56", height: "32", viewBox: "0 0 70 40", ...arrow, children: [
|
|
6205
|
+
/* @__PURE__ */ jsx15("path", { d: "M66 8 C 45 4, 22 10, 6 26" }),
|
|
6206
|
+
/* @__PURE__ */ jsx15("path", { d: "M6 26 L15.7 23.4 M6 26 L8.6 16.3" })
|
|
6107
6207
|
] }),
|
|
6108
|
-
/* @__PURE__ */
|
|
6208
|
+
/* @__PURE__ */ jsx15("p", { className: "-mt-0.5 max-w-[160px]", children: "Drag resources onto the canvas, then connect them" })
|
|
6109
6209
|
] }),
|
|
6110
|
-
/* @__PURE__ */
|
|
6111
|
-
/* @__PURE__ */
|
|
6112
|
-
/* @__PURE__ */
|
|
6113
|
-
/* @__PURE__ */
|
|
6210
|
+
/* @__PURE__ */ jsxs12("div", { className: "absolute left-[calc(50%+6px)] top-[66px] flex -translate-x-1/2 flex-col items-center", children: [
|
|
6211
|
+
/* @__PURE__ */ jsxs12("svg", { width: "32", height: "45", viewBox: "0 0 40 56", ...arrow, children: [
|
|
6212
|
+
/* @__PURE__ */ jsx15("path", { d: "M14 54 C 6 38, 10 18, 20 4" }),
|
|
6213
|
+
/* @__PURE__ */ jsx15("path", { d: "M20 4 L11.8 7.7 M20 4 L19.1 13" })
|
|
6114
6214
|
] }),
|
|
6115
|
-
/* @__PURE__ */
|
|
6215
|
+
/* @__PURE__ */ jsx15("p", { className: "mt-1 whitespace-nowrap", children: "Switch between levels of detail" })
|
|
6116
6216
|
] }),
|
|
6117
|
-
live && /* @__PURE__ */
|
|
6118
|
-
/* @__PURE__ */
|
|
6119
|
-
/* @__PURE__ */
|
|
6217
|
+
live && /* @__PURE__ */ jsxs12("div", { className: "absolute right-[52px] top-[66px] flex items-end gap-1", children: [
|
|
6218
|
+
/* @__PURE__ */ jsx15("p", { className: "mb-[-5px] max-w-[200px] text-right", children: "Start live collaboration with your team or agents" }),
|
|
6219
|
+
/* @__PURE__ */ jsxs12(
|
|
6120
6220
|
"svg",
|
|
6121
6221
|
{
|
|
6122
6222
|
width: "40",
|
|
@@ -6125,8 +6225,8 @@ function Hints({ palette, live }) {
|
|
|
6125
6225
|
className: "flex-none",
|
|
6126
6226
|
...arrow,
|
|
6127
6227
|
children: [
|
|
6128
|
-
/* @__PURE__ */
|
|
6129
|
-
/* @__PURE__ */
|
|
6228
|
+
/* @__PURE__ */ jsx15("path", { d: "M6 56 C 30 52, 42 30, 40 4" }),
|
|
6229
|
+
/* @__PURE__ */ jsx15("path", { d: "M40 4 L36.1 12.1 M40 4 L45.1 11.4" })
|
|
6130
6230
|
]
|
|
6131
6231
|
}
|
|
6132
6232
|
)
|
|
@@ -6143,9 +6243,9 @@ function EmptyCanvas({
|
|
|
6143
6243
|
palette,
|
|
6144
6244
|
live
|
|
6145
6245
|
}) {
|
|
6146
|
-
const [dragging, setDragging] =
|
|
6147
|
-
const [dropped, setDropped] =
|
|
6148
|
-
|
|
6246
|
+
const [dragging, setDragging] = useState12(false);
|
|
6247
|
+
const [dropped, setDropped] = useState12(false);
|
|
6248
|
+
useEffect10(() => {
|
|
6149
6249
|
const start = () => setDragging(true);
|
|
6150
6250
|
const end = () => setDragging(false);
|
|
6151
6251
|
const drop = () => {
|
|
@@ -6162,353 +6262,60 @@ function EmptyCanvas({
|
|
|
6162
6262
|
};
|
|
6163
6263
|
}, []);
|
|
6164
6264
|
if (dragging || dropped) return null;
|
|
6165
|
-
const item = (icon, label, onClick, hint) => /* @__PURE__ */
|
|
6265
|
+
const item = (icon, label, onClick, hint) => /* @__PURE__ */ jsxs12(
|
|
6166
6266
|
"button",
|
|
6167
6267
|
{
|
|
6168
6268
|
type: "button",
|
|
6169
6269
|
onClick,
|
|
6170
6270
|
className: "group flex h-11 w-full items-center gap-3.5 rounded-lg px-3 text-left text-[15px] text-[rgb(var(--ec-page-text-muted))] transition-colors hover:bg-[rgb(var(--ec-content-hover))]! hover:text-[rgb(var(--ec-page-text))]! [&_svg]:h-[18px] [&_svg]:w-[18px] [&_svg]:stroke-[1.75]",
|
|
6171
6271
|
children: [
|
|
6172
|
-
/* @__PURE__ */
|
|
6173
|
-
/* @__PURE__ */
|
|
6174
|
-
hint && /* @__PURE__ */
|
|
6272
|
+
/* @__PURE__ */ jsx15("span", { className: "flex flex-none", children: icon }),
|
|
6273
|
+
/* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 truncate", children: label }),
|
|
6274
|
+
hint && /* @__PURE__ */ jsx15("span", { className: "flex-none text-[13px] opacity-80", children: hint })
|
|
6175
6275
|
]
|
|
6176
6276
|
}
|
|
6177
6277
|
);
|
|
6178
6278
|
return (
|
|
6179
6279
|
// On the canvas itself: what's dragged in from the left still lands on it
|
|
6180
|
-
/* @__PURE__ */
|
|
6181
|
-
/* @__PURE__ */
|
|
6182
|
-
welcome && /* @__PURE__ */
|
|
6183
|
-
/* @__PURE__ */
|
|
6184
|
-
/* @__PURE__ */
|
|
6280
|
+
/* @__PURE__ */ jsxs12("div", { className: "pointer-events-none absolute inset-0 z-[5] flex items-center justify-center px-4 pb-16 pt-40", children: [
|
|
6281
|
+
/* @__PURE__ */ jsx15(Hints, { palette, live }),
|
|
6282
|
+
welcome && /* @__PURE__ */ jsxs12("div", { className: "pointer-events-auto flex w-full max-w-[440px] flex-col items-center", children: [
|
|
6283
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3 text-[rgb(var(--ec-page-text))]", children: [
|
|
6284
|
+
/* @__PURE__ */ jsx15(
|
|
6185
6285
|
"span",
|
|
6186
6286
|
{
|
|
6187
6287
|
className: "h-11 w-11 [&_svg]:h-full [&_svg]:w-full",
|
|
6188
6288
|
dangerouslySetInnerHTML: { __html: eventcatalog_logo_default }
|
|
6189
6289
|
}
|
|
6190
6290
|
),
|
|
6191
|
-
/* @__PURE__ */
|
|
6291
|
+
/* @__PURE__ */ jsxs12("span", { className: "text-[34px] font-bold tracking-tight", children: [
|
|
6192
6292
|
"EventCatalog",
|
|
6193
6293
|
" ",
|
|
6194
|
-
/* @__PURE__ */
|
|
6294
|
+
/* @__PURE__ */ jsx15("span", { className: "font-light text-[rgb(var(--ec-page-text-muted))]", children: "Studio" })
|
|
6195
6295
|
] })
|
|
6196
6296
|
] }),
|
|
6197
|
-
/* @__PURE__ */
|
|
6198
|
-
/* @__PURE__ */
|
|
6199
|
-
onOpen && item(/* @__PURE__ */
|
|
6200
|
-
onConnect && item(/* @__PURE__ */
|
|
6201
|
-
item(/* @__PURE__ */
|
|
6297
|
+
/* @__PURE__ */ jsx15("p", { className: "mt-5 text-center font-[Excalifont,Inter,sans-serif] text-[22px] leading-snug text-[color-mix(in_srgb,rgb(var(--ec-page-text))_38%,transparent)]", children: "Sketch, design and share architecture with your team and AI agents." }),
|
|
6298
|
+
/* @__PURE__ */ jsxs12("div", { className: "mt-10 w-full", children: [
|
|
6299
|
+
onOpen && item(/* @__PURE__ */ jsx15(FolderOpen, { "aria-hidden": true }), "Open", onOpen, `${MOD2}+O`),
|
|
6300
|
+
onConnect && item(/* @__PURE__ */ jsx15(Plug, { "aria-hidden": true }), "Connect to MCP Server", onConnect),
|
|
6301
|
+
item(/* @__PURE__ */ jsx15(CircleHelp, { "aria-hidden": true }), "Help", onHelp, "?")
|
|
6202
6302
|
] })
|
|
6203
6303
|
] })
|
|
6204
6304
|
] })
|
|
6205
6305
|
);
|
|
6206
6306
|
}
|
|
6207
6307
|
|
|
6208
|
-
// src/studio/components/NodeCard.tsx
|
|
6209
|
-
import {
|
|
6210
|
-
useCallback as useCallback5,
|
|
6211
|
-
useEffect as useEffect9,
|
|
6212
|
-
useRef as useRef7,
|
|
6213
|
-
useState as useState11
|
|
6214
|
-
} from "react";
|
|
6215
|
-
import { Check as Check2, X as X4 } from "lucide-react";
|
|
6216
|
-
import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6217
|
-
var MODAL_WIDTH = 300;
|
|
6218
|
-
var GAP2 = 12;
|
|
6219
|
-
var EDGE2 = 8;
|
|
6220
|
-
var ARROW_DOWN = 32;
|
|
6221
|
-
function useNodeAnchor(nodeId, containerRef, modalRef, bottomInset = EDGE2) {
|
|
6222
|
-
const [anchor, setAnchor] = useState11(null);
|
|
6223
|
-
useEffect9(() => {
|
|
6224
|
-
let frame = 0;
|
|
6225
|
-
const update = () => {
|
|
6226
|
-
const container = containerRef.current;
|
|
6227
|
-
const element = container?.querySelector(
|
|
6228
|
-
`.react-flow__node[data-id="${CSS.escape(nodeId)}"]`
|
|
6229
|
-
);
|
|
6230
|
-
if (container && element) {
|
|
6231
|
-
const bounds = container.getBoundingClientRect();
|
|
6232
|
-
const rect = element.getBoundingClientRect();
|
|
6233
|
-
const height = modalRef.current?.offsetHeight ?? 200;
|
|
6234
|
-
const width = modalRef.current?.offsetWidth || MODAL_WIDTH;
|
|
6235
|
-
const side = rect.right + GAP2 + width <= bounds.right - EDGE2 ? "right" : "left";
|
|
6236
|
-
const left = side === "right" ? rect.right - bounds.left + GAP2 : rect.left - bounds.left - GAP2 - width;
|
|
6237
|
-
const clamp = (value, max) => Math.min(Math.max(value, EDGE2), Math.max(max, EDGE2));
|
|
6238
|
-
const top = clamp(
|
|
6239
|
-
Math.min(rect.top, rect.top + rect.height / 2 - ARROW_DOWN) - bounds.top,
|
|
6240
|
-
bounds.height - height - bottomInset
|
|
6241
|
-
);
|
|
6242
|
-
const placed = clamp(left, bounds.width - width - EDGE2);
|
|
6243
|
-
const middle = rect.top + rect.height / 2 - bounds.top - top;
|
|
6244
|
-
const pointsAt = placed === left && middle >= 14 && middle <= height - 14 ? Math.round(middle) : void 0;
|
|
6245
|
-
const next = { side, left: placed, top, pointsAt };
|
|
6246
|
-
setAnchor(
|
|
6247
|
-
(previous) => previous?.left === next.left && previous?.top === next.top && previous?.side === next.side && previous?.pointsAt === next.pointsAt ? previous : next
|
|
6248
|
-
);
|
|
6249
|
-
}
|
|
6250
|
-
frame = requestAnimationFrame(update);
|
|
6251
|
-
};
|
|
6252
|
-
update();
|
|
6253
|
-
return () => cancelAnimationFrame(frame);
|
|
6254
|
-
}, [nodeId, containerRef, modalRef, bottomInset]);
|
|
6255
|
-
return anchor;
|
|
6256
|
-
}
|
|
6257
|
-
function useSavedFlash() {
|
|
6258
|
-
const [saved, setSaved] = useState11(false);
|
|
6259
|
-
const timer = useRef7(void 0);
|
|
6260
|
-
const showSaved = useCallback5(() => {
|
|
6261
|
-
setSaved(true);
|
|
6262
|
-
clearTimeout(timer.current);
|
|
6263
|
-
timer.current = setTimeout(() => setSaved(false), 1600);
|
|
6264
|
-
}, []);
|
|
6265
|
-
useEffect9(() => () => clearTimeout(timer.current), []);
|
|
6266
|
-
return { saved, showSaved };
|
|
6267
|
-
}
|
|
6268
|
-
function EditStatus({ saved }) {
|
|
6269
|
-
return /* @__PURE__ */ jsx15(
|
|
6270
|
-
"p",
|
|
6271
|
-
{
|
|
6272
|
-
className: `ec-edit-status ${saved ? "is-saved" : ""}`,
|
|
6273
|
-
"aria-live": "polite",
|
|
6274
|
-
children: saved ? /* @__PURE__ */ jsxs12(Fragment8, { children: [
|
|
6275
|
-
/* @__PURE__ */ jsx15(Check2, { "aria-hidden": true }),
|
|
6276
|
-
" Saved"
|
|
6277
|
-
] }) : "Changes save as you type"
|
|
6278
|
-
}
|
|
6279
|
-
);
|
|
6280
|
-
}
|
|
6281
|
-
function NodeCard({
|
|
6282
|
-
nodeId,
|
|
6283
|
-
containerRef,
|
|
6284
|
-
label,
|
|
6285
|
-
kicker,
|
|
6286
|
-
header,
|
|
6287
|
-
children,
|
|
6288
|
-
width = 340,
|
|
6289
|
-
bottomInset = 76,
|
|
6290
|
-
onClose
|
|
6291
|
-
}) {
|
|
6292
|
-
const cardRef = useRef7(null);
|
|
6293
|
-
const anchor = useNodeAnchor(nodeId, containerRef, cardRef, bottomInset);
|
|
6294
|
-
const onCloseRef = useRef7(onClose);
|
|
6295
|
-
onCloseRef.current = onClose;
|
|
6296
|
-
useEffect9(() => {
|
|
6297
|
-
const close = () => {
|
|
6298
|
-
const active = document.activeElement;
|
|
6299
|
-
if (active instanceof HTMLElement && cardRef.current?.contains(active))
|
|
6300
|
-
active.blur();
|
|
6301
|
-
onCloseRef.current();
|
|
6302
|
-
};
|
|
6303
|
-
const onPointerDown = (event) => {
|
|
6304
|
-
if (!cardRef.current?.contains(event.target)) close();
|
|
6305
|
-
};
|
|
6306
|
-
const onKeyDown = (event) => event.key === "Escape" && close();
|
|
6307
|
-
document.addEventListener("pointerdown", onPointerDown, true);
|
|
6308
|
-
document.addEventListener("keydown", onKeyDown);
|
|
6309
|
-
return () => {
|
|
6310
|
-
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
6311
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
6312
|
-
};
|
|
6313
|
-
}, []);
|
|
6314
|
-
const shown = !!anchor;
|
|
6315
|
-
const focusedFirst = useRef7(false);
|
|
6316
|
-
useEffect9(() => {
|
|
6317
|
-
if (!shown || focusedFirst.current) return;
|
|
6318
|
-
focusedFirst.current = true;
|
|
6319
|
-
const field = cardRef.current?.querySelector(
|
|
6320
|
-
"input:not([readonly]):not([disabled]), textarea:not([readonly]):not([disabled])"
|
|
6321
|
-
);
|
|
6322
|
-
if (!field) return;
|
|
6323
|
-
field.focus({ preventScroll: true });
|
|
6324
|
-
try {
|
|
6325
|
-
field.setSelectionRange(field.value.length, field.value.length);
|
|
6326
|
-
} catch {
|
|
6327
|
-
}
|
|
6328
|
-
}, [shown]);
|
|
6329
|
-
return /* @__PURE__ */ jsxs12(Fragment8, { children: [
|
|
6330
|
-
anchor?.pointsAt !== void 0 && /* @__PURE__ */ jsx15(
|
|
6331
|
-
"span",
|
|
6332
|
-
{
|
|
6333
|
-
"aria-hidden": true,
|
|
6334
|
-
className: `ec-doc-card-arrow is-${anchor.side}`,
|
|
6335
|
-
style: {
|
|
6336
|
-
top: anchor.top + anchor.pointsAt - 7,
|
|
6337
|
-
left: anchor.side === "right" ? anchor.left - 6 : anchor.left + width - 8
|
|
6338
|
-
}
|
|
6339
|
-
}
|
|
6340
|
-
),
|
|
6341
|
-
/* @__PURE__ */ jsxs12(
|
|
6342
|
-
"div",
|
|
6343
|
-
{
|
|
6344
|
-
ref: cardRef,
|
|
6345
|
-
className: "ec-doc-card",
|
|
6346
|
-
role: "dialog",
|
|
6347
|
-
"aria-label": label,
|
|
6348
|
-
style: {
|
|
6349
|
-
width,
|
|
6350
|
-
top: anchor?.top ?? 8,
|
|
6351
|
-
left: anchor?.left ?? 8,
|
|
6352
|
-
visibility: anchor ? "visible" : "hidden"
|
|
6353
|
-
},
|
|
6354
|
-
children: [
|
|
6355
|
-
/* @__PURE__ */ jsxs12("header", { className: "ec-doc-card-header", children: [
|
|
6356
|
-
/* @__PURE__ */ jsxs12("div", { className: "ec-doc-card-kicker", children: [
|
|
6357
|
-
kicker,
|
|
6358
|
-
/* @__PURE__ */ jsx15(
|
|
6359
|
-
"button",
|
|
6360
|
-
{
|
|
6361
|
-
type: "button",
|
|
6362
|
-
className: "ec-icon-button ec-doc-card-close",
|
|
6363
|
-
"aria-label": "Close",
|
|
6364
|
-
onClick: onClose,
|
|
6365
|
-
children: /* @__PURE__ */ jsx15(X4, { "aria-hidden": true })
|
|
6366
|
-
}
|
|
6367
|
-
)
|
|
6368
|
-
] }),
|
|
6369
|
-
header
|
|
6370
|
-
] }),
|
|
6371
|
-
children
|
|
6372
|
-
]
|
|
6373
|
-
}
|
|
6374
|
-
)
|
|
6375
|
-
] });
|
|
6376
|
-
}
|
|
6377
|
-
var SAVE_DELAY = 250;
|
|
6378
|
-
function EditableText({
|
|
6379
|
-
value,
|
|
6380
|
-
onSave,
|
|
6381
|
-
multiline = false,
|
|
6382
|
-
placeholder,
|
|
6383
|
-
className = "",
|
|
6384
|
-
label,
|
|
6385
|
-
required = false,
|
|
6386
|
-
onSaved
|
|
6387
|
-
}) {
|
|
6388
|
-
const [draft, setDraft] = useState11(value);
|
|
6389
|
-
const focused = useRef7(false);
|
|
6390
|
-
const before = useRef7(value);
|
|
6391
|
-
const pending = useRef7(null);
|
|
6392
|
-
const timer = useRef7(void 0);
|
|
6393
|
-
const latest = useRef7({ value, onSave, onSaved, required });
|
|
6394
|
-
latest.current = { value, onSave, onSaved, required };
|
|
6395
|
-
useEffect9(() => {
|
|
6396
|
-
if (!focused.current) setDraft(value);
|
|
6397
|
-
}, [value]);
|
|
6398
|
-
const flush = () => {
|
|
6399
|
-
clearTimeout(timer.current);
|
|
6400
|
-
const next = pending.current;
|
|
6401
|
-
pending.current = null;
|
|
6402
|
-
if (next === null) return;
|
|
6403
|
-
const {
|
|
6404
|
-
value: saved,
|
|
6405
|
-
onSave: save,
|
|
6406
|
-
onSaved: said,
|
|
6407
|
-
required: needed
|
|
6408
|
-
} = latest.current;
|
|
6409
|
-
if (needed && !next.trim() || next === saved) return;
|
|
6410
|
-
save(next);
|
|
6411
|
-
said?.();
|
|
6412
|
-
};
|
|
6413
|
-
useEffect9(() => flush, []);
|
|
6414
|
-
const change = (next) => {
|
|
6415
|
-
setDraft(next);
|
|
6416
|
-
pending.current = next;
|
|
6417
|
-
clearTimeout(timer.current);
|
|
6418
|
-
timer.current = setTimeout(flush, SAVE_DELAY);
|
|
6419
|
-
};
|
|
6420
|
-
const reverted = useRef7(false);
|
|
6421
|
-
const leave = () => {
|
|
6422
|
-
focused.current = false;
|
|
6423
|
-
if (reverted.current) {
|
|
6424
|
-
reverted.current = false;
|
|
6425
|
-
return;
|
|
6426
|
-
}
|
|
6427
|
-
const trimmed = draft.trim();
|
|
6428
|
-
if (required && !trimmed) {
|
|
6429
|
-
setDraft(before.current);
|
|
6430
|
-
pending.current = before.current;
|
|
6431
|
-
} else {
|
|
6432
|
-
if (trimmed !== draft) setDraft(trimmed);
|
|
6433
|
-
pending.current = trimmed;
|
|
6434
|
-
}
|
|
6435
|
-
flush();
|
|
6436
|
-
};
|
|
6437
|
-
const keys = (event) => {
|
|
6438
|
-
if (event.key === "Escape") {
|
|
6439
|
-
event.stopPropagation();
|
|
6440
|
-
setDraft(before.current);
|
|
6441
|
-
pending.current = before.current;
|
|
6442
|
-
flush();
|
|
6443
|
-
reverted.current = true;
|
|
6444
|
-
event.target.blur();
|
|
6445
|
-
} else if (event.key === "Enter" && (!multiline || event.metaKey || event.ctrlKey)) {
|
|
6446
|
-
event.preventDefault();
|
|
6447
|
-
event.target.blur();
|
|
6448
|
-
}
|
|
6449
|
-
};
|
|
6450
|
-
const focus = () => {
|
|
6451
|
-
focused.current = true;
|
|
6452
|
-
before.current = value;
|
|
6453
|
-
};
|
|
6454
|
-
const fit = (area) => {
|
|
6455
|
-
if (!area) return;
|
|
6456
|
-
area.style.height = "auto";
|
|
6457
|
-
area.style.height = `${area.scrollHeight + 2}px`;
|
|
6458
|
-
};
|
|
6459
|
-
return multiline ? /* @__PURE__ */ jsx15(
|
|
6460
|
-
"textarea",
|
|
6461
|
-
{
|
|
6462
|
-
ref: fit,
|
|
6463
|
-
"aria-label": label,
|
|
6464
|
-
value: draft,
|
|
6465
|
-
rows: 2,
|
|
6466
|
-
placeholder,
|
|
6467
|
-
onChange: (event) => {
|
|
6468
|
-
change(event.target.value);
|
|
6469
|
-
fit(event.target);
|
|
6470
|
-
},
|
|
6471
|
-
onFocus: focus,
|
|
6472
|
-
onBlur: leave,
|
|
6473
|
-
onKeyDown: keys,
|
|
6474
|
-
className: `ec-editable ${className}`
|
|
6475
|
-
}
|
|
6476
|
-
) : /* @__PURE__ */ jsx15(
|
|
6477
|
-
"input",
|
|
6478
|
-
{
|
|
6479
|
-
"aria-label": label,
|
|
6480
|
-
value: draft,
|
|
6481
|
-
placeholder,
|
|
6482
|
-
onChange: (event) => change(event.target.value),
|
|
6483
|
-
onFocus: focus,
|
|
6484
|
-
onBlur: leave,
|
|
6485
|
-
onKeyDown: keys,
|
|
6486
|
-
className: `ec-editable ${className}`
|
|
6487
|
-
}
|
|
6488
|
-
);
|
|
6489
|
-
}
|
|
6490
|
-
function Field({
|
|
6491
|
-
label,
|
|
6492
|
-
children,
|
|
6493
|
-
className = ""
|
|
6494
|
-
}) {
|
|
6495
|
-
return /* @__PURE__ */ jsxs12("label", { className: `ec-field ${className}`, children: [
|
|
6496
|
-
/* @__PURE__ */ jsx15("span", { className: "ec-field-label", children: label }),
|
|
6497
|
-
children
|
|
6498
|
-
] });
|
|
6499
|
-
}
|
|
6500
|
-
|
|
6501
6308
|
// src/studio/components/RemeasureHandles.tsx
|
|
6502
|
-
import { memo as
|
|
6309
|
+
import { memo as memo10, useEffect as useEffect11 } from "react";
|
|
6503
6310
|
import {
|
|
6504
6311
|
useStore as useStore2,
|
|
6505
6312
|
useUpdateNodeInternals as useUpdateNodeInternals2
|
|
6506
6313
|
} from "@xyflow/react";
|
|
6507
6314
|
var selectDomNode = (state) => state.domNode;
|
|
6508
|
-
var RemeasureHandles =
|
|
6315
|
+
var RemeasureHandles = memo10(function RemeasureHandles2() {
|
|
6509
6316
|
const domNode = useStore2(selectDomNode);
|
|
6510
6317
|
const updateNodeInternals = useUpdateNodeInternals2();
|
|
6511
|
-
|
|
6318
|
+
useEffect11(() => {
|
|
6512
6319
|
if (!domNode) return;
|
|
6513
6320
|
const pending = /* @__PURE__ */ new Set();
|
|
6514
6321
|
let frame = 0;
|
|
@@ -6547,6 +6354,10 @@ export {
|
|
|
6547
6354
|
CLIPBOARD_TYPE,
|
|
6548
6355
|
COMPONENT_DRAG_TYPE,
|
|
6549
6356
|
COMPONENT_TYPES,
|
|
6357
|
+
CONNECT_MIN_DISTANCE,
|
|
6358
|
+
CONNECT_PLACEHOLDER,
|
|
6359
|
+
CONNECT_PLACEHOLDER_EDGE,
|
|
6360
|
+
CONNECT_PLACEHOLDER_SIZE,
|
|
6550
6361
|
COUNTER_SCALE,
|
|
6551
6362
|
CanvasControls_default as CanvasControls,
|
|
6552
6363
|
CanvasPortal,
|
|
@@ -6555,6 +6366,8 @@ export {
|
|
|
6555
6366
|
ClaudeLogo,
|
|
6556
6367
|
CommentLayer,
|
|
6557
6368
|
CommentList,
|
|
6369
|
+
ConnectChooser,
|
|
6370
|
+
ConnectPlaceholderNode,
|
|
6558
6371
|
ContainerChooser,
|
|
6559
6372
|
ContextMenu,
|
|
6560
6373
|
CursorLogo,
|
|
@@ -6615,10 +6428,12 @@ export {
|
|
|
6615
6428
|
canPickWhereToSave,
|
|
6616
6429
|
canvasImage,
|
|
6617
6430
|
canvasToModel,
|
|
6431
|
+
centreBeyond,
|
|
6618
6432
|
changesNodesOrEdges,
|
|
6619
6433
|
cleanFileName,
|
|
6620
6434
|
componentKey,
|
|
6621
6435
|
connectNodes,
|
|
6436
|
+
connectedType,
|
|
6622
6437
|
containerFor,
|
|
6623
6438
|
copyNodes,
|
|
6624
6439
|
createEdge,
|
|
@@ -6632,6 +6447,7 @@ export {
|
|
|
6632
6447
|
deleteThreads,
|
|
6633
6448
|
downloadFile,
|
|
6634
6449
|
fileNameFor,
|
|
6450
|
+
filterConnectOptions,
|
|
6635
6451
|
findDropTarget,
|
|
6636
6452
|
findDropTargets,
|
|
6637
6453
|
findGroupAtPoint,
|
|
@@ -6643,6 +6459,7 @@ export {
|
|
|
6643
6459
|
getAnchorPosition,
|
|
6644
6460
|
getCanvasMaps,
|
|
6645
6461
|
getCanvasStatus,
|
|
6462
|
+
getConnectOptions,
|
|
6646
6463
|
getDiagramLevel,
|
|
6647
6464
|
getDiagramLevelUnavailable,
|
|
6648
6465
|
getEdgeLabel,
|
|
@@ -6659,8 +6476,11 @@ export {
|
|
|
6659
6476
|
getNoteLevel,
|
|
6660
6477
|
getResource,
|
|
6661
6478
|
getStructureKey,
|
|
6479
|
+
isAwayFrom,
|
|
6480
|
+
isCardType,
|
|
6662
6481
|
isCatalogCollection,
|
|
6663
6482
|
isDecided,
|
|
6483
|
+
isEmptyCanvasAt,
|
|
6664
6484
|
isGroupType,
|
|
6665
6485
|
isOnLevel,
|
|
6666
6486
|
isShownOnLevel,
|
|
@@ -6670,12 +6490,15 @@ export {
|
|
|
6670
6490
|
keepUnchanged,
|
|
6671
6491
|
layoutGraph,
|
|
6672
6492
|
levelPlaces,
|
|
6493
|
+
linkConnection,
|
|
6673
6494
|
modelToCanvas,
|
|
6674
6495
|
moveNode,
|
|
6675
6496
|
moveThread,
|
|
6676
6497
|
moveThreads,
|
|
6498
|
+
newCardData,
|
|
6677
6499
|
nodeDefinitions,
|
|
6678
6500
|
nodeTypes,
|
|
6501
|
+
notPlaceholder,
|
|
6679
6502
|
pasteNodes,
|
|
6680
6503
|
patchShared,
|
|
6681
6504
|
pickDiagramFile,
|
|
@@ -6719,6 +6542,7 @@ export {
|
|
|
6719
6542
|
updateHotspot,
|
|
6720
6543
|
updateNodeData,
|
|
6721
6544
|
updateResource,
|
|
6545
|
+
useConnectNew,
|
|
6722
6546
|
useCounterScale,
|
|
6723
6547
|
useDragGhost,
|
|
6724
6548
|
useNodeAnchor,
|