@petrarca/sonnet-graph 0.7.0 → 0.8.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/index.d.ts +304 -3
- package/dist/index.js +1483 -609
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -182,15 +182,225 @@ var EMPTY_NORMALIZED = {
|
|
|
182
182
|
edgeIds: []
|
|
183
183
|
};
|
|
184
184
|
|
|
185
|
-
// src/
|
|
185
|
+
// src/graph/extractFromRows.ts
|
|
186
|
+
function isNodeCell(value) {
|
|
187
|
+
return typeof value === "object" && value !== null && "node" in value;
|
|
188
|
+
}
|
|
189
|
+
function isEdgeCell(value) {
|
|
190
|
+
return typeof value === "object" && value !== null && "edge" in value;
|
|
191
|
+
}
|
|
192
|
+
function extractGraphFromRows(rows) {
|
|
193
|
+
const nodesById = /* @__PURE__ */ new Map();
|
|
194
|
+
const edgesById = /* @__PURE__ */ new Map();
|
|
195
|
+
for (const row of rows) {
|
|
196
|
+
for (const cell of row) {
|
|
197
|
+
if (isNodeCell(cell) && cell.node.id_ !== void 0) {
|
|
198
|
+
nodesById.set(cell.node.id_, cell.node);
|
|
199
|
+
} else if (isEdgeCell(cell) && cell.edge.id_ !== void 0) {
|
|
200
|
+
edgesById.set(cell.edge.id_, cell.edge);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
nodes: [...nodesById.values()],
|
|
206
|
+
edges: [...edgesById.values()],
|
|
207
|
+
isGraph: nodesById.size > 0 || edgesById.size > 0
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// src/query/QueryEditor.tsx
|
|
212
|
+
import { useRef, useCallback, useEffect, useState } from "react";
|
|
213
|
+
import {
|
|
214
|
+
Alert,
|
|
215
|
+
Button,
|
|
216
|
+
InputGroup,
|
|
217
|
+
InputGroupAddon,
|
|
218
|
+
InputGroupButton,
|
|
219
|
+
InputGroupTextarea,
|
|
220
|
+
SimpleTooltip
|
|
221
|
+
} from "@petrarca/sonnet-ui";
|
|
222
|
+
import { copyTextToClipboard } from "@petrarca/sonnet-core";
|
|
223
|
+
import { Play, Copy } from "lucide-react";
|
|
224
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
225
|
+
var LINE_HEIGHT = 24;
|
|
226
|
+
function CopyErrorButton({
|
|
227
|
+
error,
|
|
228
|
+
query
|
|
229
|
+
}) {
|
|
230
|
+
return /* @__PURE__ */ jsx(SimpleTooltip, { label: "Copy error and query", children: /* @__PURE__ */ jsx(
|
|
231
|
+
Button,
|
|
232
|
+
{
|
|
233
|
+
variant: "ghost",
|
|
234
|
+
size: "icon",
|
|
235
|
+
onClick: () => copyTextToClipboard(`Error: ${error}
|
|
236
|
+
|
|
237
|
+
Query:
|
|
238
|
+
${query}`),
|
|
239
|
+
className: "ml-2",
|
|
240
|
+
children: /* @__PURE__ */ jsx(Copy, { size: 16 })
|
|
241
|
+
}
|
|
242
|
+
) });
|
|
243
|
+
}
|
|
244
|
+
function QueryEditor({
|
|
245
|
+
value,
|
|
246
|
+
onExecute,
|
|
247
|
+
onChange,
|
|
248
|
+
isLoading = false,
|
|
249
|
+
error = null,
|
|
250
|
+
placeholder = "Example: MATCH (p)-[e]->(t) RETURN p,e,t LIMIT 10",
|
|
251
|
+
minRows = 1,
|
|
252
|
+
maxRows = 12,
|
|
253
|
+
className,
|
|
254
|
+
renderActions
|
|
255
|
+
}) {
|
|
256
|
+
const textareaRef = useRef(null);
|
|
257
|
+
const [localValue, setLocalValue] = useState(value);
|
|
258
|
+
const handleResize = useCallback(() => {
|
|
259
|
+
const textarea = textareaRef.current;
|
|
260
|
+
if (!textarea) return;
|
|
261
|
+
textarea.style.height = "auto";
|
|
262
|
+
const minH = minRows * LINE_HEIGHT;
|
|
263
|
+
const maxH = maxRows * LINE_HEIGHT;
|
|
264
|
+
const newHeight = Math.min(Math.max(textarea.scrollHeight, minH), maxH);
|
|
265
|
+
textarea.style.height = `${newHeight}px`;
|
|
266
|
+
textarea.style.overflowY = textarea.scrollHeight > maxH ? "auto" : "hidden";
|
|
267
|
+
}, [minRows, maxRows]);
|
|
268
|
+
useEffect(() => {
|
|
269
|
+
setLocalValue(value);
|
|
270
|
+
if (textareaRef.current && textareaRef.current.value !== value) {
|
|
271
|
+
textareaRef.current.value = value;
|
|
272
|
+
}
|
|
273
|
+
setTimeout(handleResize, 0);
|
|
274
|
+
}, [value, handleResize]);
|
|
275
|
+
const handleExecute = useCallback(() => {
|
|
276
|
+
const current = textareaRef.current?.value || "";
|
|
277
|
+
if (!current.trim()) return;
|
|
278
|
+
onExecute(current);
|
|
279
|
+
}, [onExecute]);
|
|
280
|
+
const handleKeyDown = useCallback(
|
|
281
|
+
(e) => {
|
|
282
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
|
283
|
+
e.preventDefault();
|
|
284
|
+
handleExecute();
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
[handleExecute]
|
|
288
|
+
);
|
|
289
|
+
const textareaRefCallback = (element) => {
|
|
290
|
+
textareaRef.current = element;
|
|
291
|
+
if (element) setTimeout(handleResize, 0);
|
|
292
|
+
};
|
|
293
|
+
const handleChange = useCallback(
|
|
294
|
+
(e) => {
|
|
295
|
+
setLocalValue(e.target.value);
|
|
296
|
+
onChange?.(e.target.value);
|
|
297
|
+
setTimeout(handleResize, 0);
|
|
298
|
+
},
|
|
299
|
+
[onChange, handleResize]
|
|
300
|
+
);
|
|
301
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
302
|
+
/* @__PURE__ */ jsxs(InputGroup, { className: "!ring-0 !ring-offset-0 focus:!ring-0 has-[[data-slot=input-group-control]:focus-visible]:!ring-0", children: [
|
|
303
|
+
/* @__PURE__ */ jsx(
|
|
304
|
+
InputGroupTextarea,
|
|
305
|
+
{
|
|
306
|
+
ref: textareaRefCallback,
|
|
307
|
+
value: localValue,
|
|
308
|
+
onChange: handleChange,
|
|
309
|
+
onKeyDown: handleKeyDown,
|
|
310
|
+
placeholder,
|
|
311
|
+
className: "resize-none font-mono",
|
|
312
|
+
style: { minHeight: `${minRows * LINE_HEIGHT}px` },
|
|
313
|
+
rows: minRows
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
/* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", className: "gap-0", children: renderActions ? renderActions({ onExecute: handleExecute, isLoading }) : /* @__PURE__ */ jsx(
|
|
317
|
+
InputGroupButton,
|
|
318
|
+
{
|
|
319
|
+
onClick: handleExecute,
|
|
320
|
+
disabled: isLoading,
|
|
321
|
+
title: "Execute query (Ctrl+Enter)",
|
|
322
|
+
children: /* @__PURE__ */ jsx(Play, { size: 16 })
|
|
323
|
+
}
|
|
324
|
+
) })
|
|
325
|
+
] }),
|
|
326
|
+
error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", className: "p-2 py-1 mt-1", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-row justify-between items-start", children: [
|
|
327
|
+
/* @__PURE__ */ jsx("pre", { className: "text-sm m-0 flex-1 whitespace-pre-wrap break-words md:text-sm", children: error }),
|
|
328
|
+
/* @__PURE__ */ jsx(CopyErrorButton, { error, query: localValue })
|
|
329
|
+
] }) })
|
|
330
|
+
] });
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/query/history.ts
|
|
186
334
|
import { create } from "zustand";
|
|
335
|
+
import { persist } from "zustand/middleware";
|
|
336
|
+
var DEFAULT_LIMIT = 50;
|
|
337
|
+
function createQueryHistoryStore(persistKey, limit = DEFAULT_LIMIT) {
|
|
338
|
+
return create()(
|
|
339
|
+
persist(
|
|
340
|
+
(set, get) => ({
|
|
341
|
+
queries: [],
|
|
342
|
+
add: (query) => {
|
|
343
|
+
const trimmed = query.trim();
|
|
344
|
+
if (!trimmed) return;
|
|
345
|
+
set({
|
|
346
|
+
queries: [
|
|
347
|
+
trimmed,
|
|
348
|
+
...get().queries.filter((q) => q !== trimmed)
|
|
349
|
+
].slice(0, limit)
|
|
350
|
+
});
|
|
351
|
+
},
|
|
352
|
+
clear: () => set({ queries: [] })
|
|
353
|
+
}),
|
|
354
|
+
{ name: persistKey, version: 1 }
|
|
355
|
+
)
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// src/query/QueryHistory.tsx
|
|
360
|
+
import { History as HistoryIcon } from "lucide-react";
|
|
361
|
+
import {
|
|
362
|
+
Button as Button2,
|
|
363
|
+
DropdownMenu,
|
|
364
|
+
DropdownMenuContent,
|
|
365
|
+
DropdownMenuItem,
|
|
366
|
+
DropdownMenuSeparator,
|
|
367
|
+
DropdownMenuTrigger
|
|
368
|
+
} from "@petrarca/sonnet-ui";
|
|
369
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
370
|
+
function QueryHistory({
|
|
371
|
+
store,
|
|
372
|
+
onSelect
|
|
373
|
+
}) {
|
|
374
|
+
const queries = store((s) => s.queries);
|
|
375
|
+
const clear = store((s) => s.clear);
|
|
376
|
+
return /* @__PURE__ */ jsxs2(DropdownMenu, { children: [
|
|
377
|
+
/* @__PURE__ */ jsx2(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
378
|
+
Button2,
|
|
379
|
+
{
|
|
380
|
+
variant: "ghost",
|
|
381
|
+
size: "icon",
|
|
382
|
+
title: "Query history",
|
|
383
|
+
disabled: queries.length === 0,
|
|
384
|
+
children: /* @__PURE__ */ jsx2(HistoryIcon, { size: 16 })
|
|
385
|
+
}
|
|
386
|
+
) }),
|
|
387
|
+
/* @__PURE__ */ jsxs2(DropdownMenuContent, { align: "end", className: "max-w-[560px]", children: [
|
|
388
|
+
queries.map((q) => /* @__PURE__ */ jsx2(DropdownMenuItem, { onClick: () => onSelect(q), children: /* @__PURE__ */ jsx2("span", { className: "truncate font-mono text-xs", children: q }) }, q)),
|
|
389
|
+
queries.length > 0 && /* @__PURE__ */ jsx2(DropdownMenuSeparator, {}),
|
|
390
|
+
/* @__PURE__ */ jsx2(DropdownMenuItem, { onClick: clear, disabled: queries.length === 0, children: "Clear history" })
|
|
391
|
+
] })
|
|
392
|
+
] });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/stores/Selection.ts
|
|
396
|
+
import { create as create2 } from "zustand";
|
|
187
397
|
import { devLog } from "@petrarca/sonnet-core";
|
|
188
398
|
var MAX_NODE_SELECTION = 2;
|
|
189
399
|
function evictToMax(selected, id, max = MAX_NODE_SELECTION) {
|
|
190
400
|
return [...selected.filter((existing) => existing !== id), id].slice(-max);
|
|
191
401
|
}
|
|
192
402
|
function createSelectionStore() {
|
|
193
|
-
return
|
|
403
|
+
return create2()((set, get) => ({
|
|
194
404
|
selectedNodeIds: [],
|
|
195
405
|
setSelectedNodeIds: (ids) => {
|
|
196
406
|
const prev = get().selectedNodeIds;
|
|
@@ -217,10 +427,10 @@ function createSelectionStore() {
|
|
|
217
427
|
var useSelection = createSelectionStore();
|
|
218
428
|
|
|
219
429
|
// src/stores/GraphData.ts
|
|
220
|
-
import { create as
|
|
430
|
+
import { create as create3 } from "zustand";
|
|
221
431
|
import { devLog as devLog2 } from "@petrarca/sonnet-core";
|
|
222
432
|
function createGraphDataStore() {
|
|
223
|
-
return
|
|
433
|
+
return create3()((set, get) => ({
|
|
224
434
|
nodes: [],
|
|
225
435
|
edges: [],
|
|
226
436
|
stats: void 0,
|
|
@@ -328,7 +538,7 @@ function createGraphDataStore() {
|
|
|
328
538
|
var useGraphData = createGraphDataStore();
|
|
329
539
|
|
|
330
540
|
// src/stores/GraphFilter.ts
|
|
331
|
-
import { create as
|
|
541
|
+
import { create as create4 } from "zustand";
|
|
332
542
|
function calculateNodeLabelUpdate(affectedLabels, currentNodeFilters, allNodesDisabled) {
|
|
333
543
|
if (affectedLabels.length === 0) return null;
|
|
334
544
|
if (allNodesDisabled) {
|
|
@@ -366,7 +576,7 @@ function handleToggleFilter(label, current, exists, getNodeLabelUpdate, set) {
|
|
|
366
576
|
set({ edgeLabelFilters: next, ...nodeUpdate });
|
|
367
577
|
}
|
|
368
578
|
function createGraphFilterStore() {
|
|
369
|
-
return
|
|
579
|
+
return create4()((set, get) => ({
|
|
370
580
|
nodeLabelFilters: [],
|
|
371
581
|
allLabelsDisabled: false,
|
|
372
582
|
edgeLabelFilters: [],
|
|
@@ -442,7 +652,7 @@ function createGraphFilterStore() {
|
|
|
442
652
|
var useGraphFilter = createGraphFilterStore();
|
|
443
653
|
|
|
444
654
|
// src/stores/GraphExploration.ts
|
|
445
|
-
import { create as
|
|
655
|
+
import { create as create5 } from "zustand";
|
|
446
656
|
import { devLog as devLog3, errorLog } from "@petrarca/sonnet-core";
|
|
447
657
|
import { toast } from "sonner";
|
|
448
658
|
function collectReachable(startId, direction, allEdges, includeStart) {
|
|
@@ -569,7 +779,7 @@ function mergeExpandedLabelsIntoFilters(stores, enrichedNodes, nodeId2) {
|
|
|
569
779
|
}
|
|
570
780
|
function createGraphExplorationStore(deps) {
|
|
571
781
|
const stores = deps;
|
|
572
|
-
return
|
|
782
|
+
return create5()((set, get) => ({
|
|
573
783
|
focusedNodeIds: /* @__PURE__ */ new Set(),
|
|
574
784
|
isFocusMode: false,
|
|
575
785
|
hiddenElementIds: /* @__PURE__ */ new Set(),
|
|
@@ -978,7 +1188,7 @@ function createGraphExplorationStore(deps) {
|
|
|
978
1188
|
}
|
|
979
1189
|
|
|
980
1190
|
// src/stores/GraphFocus.ts
|
|
981
|
-
import { create as
|
|
1191
|
+
import { create as create6 } from "zustand";
|
|
982
1192
|
import { devLog as devLog4 } from "@petrarca/sonnet-core";
|
|
983
1193
|
function buildStore() {
|
|
984
1194
|
return (set, get) => ({
|
|
@@ -1012,13 +1222,13 @@ function buildStore() {
|
|
|
1012
1222
|
});
|
|
1013
1223
|
}
|
|
1014
1224
|
function createGraphFocusStore() {
|
|
1015
|
-
return
|
|
1225
|
+
return create6()(buildStore());
|
|
1016
1226
|
}
|
|
1017
1227
|
var useGraphFocus = createGraphFocusStore();
|
|
1018
1228
|
var GraphFocus_default = useGraphFocus;
|
|
1019
1229
|
|
|
1020
1230
|
// src/stores/ActionPanelStore.ts
|
|
1021
|
-
import { create as
|
|
1231
|
+
import { create as create7 } from "zustand";
|
|
1022
1232
|
import { devLog as devLog5 } from "@petrarca/sonnet-core";
|
|
1023
1233
|
function buildStore2() {
|
|
1024
1234
|
return (set, get) => ({
|
|
@@ -1039,7 +1249,7 @@ function buildStore2() {
|
|
|
1039
1249
|
});
|
|
1040
1250
|
}
|
|
1041
1251
|
function createActionPanelStore() {
|
|
1042
|
-
return
|
|
1252
|
+
return create7()(buildStore2());
|
|
1043
1253
|
}
|
|
1044
1254
|
var useActionPanelStore = createActionPanelStore();
|
|
1045
1255
|
|
|
@@ -1072,18 +1282,18 @@ function useWorkspaceGraphFocus() {
|
|
|
1072
1282
|
}
|
|
1073
1283
|
|
|
1074
1284
|
// src/hooks/useStableRef.ts
|
|
1075
|
-
import { useCallback, useRef } from "react";
|
|
1285
|
+
import { useCallback as useCallback2, useRef as useRef2 } from "react";
|
|
1076
1286
|
function useStableRef(fn) {
|
|
1077
|
-
const ref =
|
|
1287
|
+
const ref = useRef2(fn);
|
|
1078
1288
|
ref.current = fn;
|
|
1079
|
-
return
|
|
1289
|
+
return useCallback2(
|
|
1080
1290
|
((...args) => ref.current?.(...args)),
|
|
1081
1291
|
[]
|
|
1082
1292
|
);
|
|
1083
1293
|
}
|
|
1084
1294
|
|
|
1085
1295
|
// src/hooks/useLiveGraphData.ts
|
|
1086
|
-
import { useMemo, useEffect } from "react";
|
|
1296
|
+
import { useMemo, useEffect as useEffect2 } from "react";
|
|
1087
1297
|
import { devLog as devLog6 } from "@petrarca/sonnet-core";
|
|
1088
1298
|
function useLiveGraphData() {
|
|
1089
1299
|
const useGraphFilter2 = useWorkspaceGraphFilter();
|
|
@@ -1111,7 +1321,7 @@ function useLiveGraphData() {
|
|
|
1111
1321
|
focusedCount: focusedNodeIds.size,
|
|
1112
1322
|
hiddenCount: hiddenElementIds.size
|
|
1113
1323
|
});
|
|
1114
|
-
|
|
1324
|
+
useEffect2(() => {
|
|
1115
1325
|
useGraphFocus2.getState().clearOverrides();
|
|
1116
1326
|
}, [lastDataChangeTime, useGraphFocus2]);
|
|
1117
1327
|
const allLabelCounts = useMemo(() => {
|
|
@@ -1309,7 +1519,7 @@ function useLiveGraphData() {
|
|
|
1309
1519
|
edges: availableEdges.length
|
|
1310
1520
|
};
|
|
1311
1521
|
}, [stats, availableNodes.length, availableEdges.length]);
|
|
1312
|
-
|
|
1522
|
+
useEffect2(() => {
|
|
1313
1523
|
const { clearOverrides } = useGraphFocus2.getState();
|
|
1314
1524
|
clearOverrides();
|
|
1315
1525
|
}, [
|
|
@@ -1448,30 +1658,30 @@ function useGraphRenderer() {
|
|
|
1448
1658
|
}
|
|
1449
1659
|
|
|
1450
1660
|
// src/hooks/graphRendererProvider.tsx
|
|
1451
|
-
import { useState, useCallback as
|
|
1452
|
-
import { jsx } from "react/jsx-runtime";
|
|
1661
|
+
import { useState as useState2, useCallback as useCallback3 } from "react";
|
|
1662
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1453
1663
|
function GraphRendererProvider({
|
|
1454
1664
|
children,
|
|
1455
1665
|
defaultRenderer = "cytoscape",
|
|
1456
1666
|
onRendererChange
|
|
1457
1667
|
}) {
|
|
1458
|
-
const [renderer, setRendererState] =
|
|
1459
|
-
const setRenderer =
|
|
1668
|
+
const [renderer, setRendererState] = useState2(defaultRenderer);
|
|
1669
|
+
const setRenderer = useCallback3(
|
|
1460
1670
|
(newRenderer) => {
|
|
1461
1671
|
setRendererState(newRenderer);
|
|
1462
1672
|
onRendererChange?.(newRenderer);
|
|
1463
1673
|
},
|
|
1464
1674
|
[onRendererChange]
|
|
1465
1675
|
);
|
|
1466
|
-
return /* @__PURE__ */
|
|
1676
|
+
return /* @__PURE__ */ jsx3(GraphRendererContext.Provider, { value: { renderer, setRenderer }, children });
|
|
1467
1677
|
}
|
|
1468
1678
|
|
|
1469
1679
|
// src/components/rea/ReaGraph.tsx
|
|
1470
1680
|
import {
|
|
1471
|
-
useEffect as
|
|
1472
|
-
useRef as
|
|
1473
|
-
useState as
|
|
1474
|
-
useCallback as
|
|
1681
|
+
useEffect as useEffect4,
|
|
1682
|
+
useRef as useRef4,
|
|
1683
|
+
useState as useState6,
|
|
1684
|
+
useCallback as useCallback5
|
|
1475
1685
|
} from "react";
|
|
1476
1686
|
import { devLog as devLog8 } from "@petrarca/sonnet-core";
|
|
1477
1687
|
import {
|
|
@@ -1516,43 +1726,43 @@ import { cn } from "@petrarca/sonnet-core";
|
|
|
1516
1726
|
|
|
1517
1727
|
// src/components/rea/LayoutAndCameraControls.tsx
|
|
1518
1728
|
import {
|
|
1519
|
-
Button as
|
|
1520
|
-
DropdownMenu as
|
|
1521
|
-
DropdownMenuContent as
|
|
1522
|
-
DropdownMenuItem as
|
|
1729
|
+
Button as Button4,
|
|
1730
|
+
DropdownMenu as DropdownMenu3,
|
|
1731
|
+
DropdownMenuContent as DropdownMenuContent3,
|
|
1732
|
+
DropdownMenuItem as DropdownMenuItem3,
|
|
1523
1733
|
DropdownMenuLabel,
|
|
1524
|
-
DropdownMenuSeparator,
|
|
1525
|
-
DropdownMenuTrigger as
|
|
1526
|
-
SimpleTooltip as
|
|
1734
|
+
DropdownMenuSeparator as DropdownMenuSeparator2,
|
|
1735
|
+
DropdownMenuTrigger as DropdownMenuTrigger3,
|
|
1736
|
+
SimpleTooltip as SimpleTooltip3
|
|
1527
1737
|
} from "@petrarca/sonnet-ui";
|
|
1528
1738
|
import { LayoutPanelTop, Maximize, Shrink, ArrowUp, Eye } from "lucide-react";
|
|
1529
|
-
import { useState as
|
|
1739
|
+
import { useState as useState3 } from "react";
|
|
1530
1740
|
|
|
1531
1741
|
// src/components/shared/RendererDropdown.tsx
|
|
1532
1742
|
import {
|
|
1533
|
-
Button,
|
|
1534
|
-
DropdownMenu,
|
|
1535
|
-
DropdownMenuContent,
|
|
1536
|
-
DropdownMenuItem,
|
|
1537
|
-
DropdownMenuTrigger,
|
|
1538
|
-
SimpleTooltip
|
|
1743
|
+
Button as Button3,
|
|
1744
|
+
DropdownMenu as DropdownMenu2,
|
|
1745
|
+
DropdownMenuContent as DropdownMenuContent2,
|
|
1746
|
+
DropdownMenuItem as DropdownMenuItem2,
|
|
1747
|
+
DropdownMenuTrigger as DropdownMenuTrigger2,
|
|
1748
|
+
SimpleTooltip as SimpleTooltip2
|
|
1539
1749
|
} from "@petrarca/sonnet-ui";
|
|
1540
|
-
import { jsx as
|
|
1750
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1541
1751
|
function RendererDropdown() {
|
|
1542
1752
|
const { renderer, setRenderer } = useGraphRenderer();
|
|
1543
|
-
return /* @__PURE__ */
|
|
1544
|
-
/* @__PURE__ */
|
|
1545
|
-
/* @__PURE__ */
|
|
1546
|
-
/* @__PURE__ */
|
|
1547
|
-
|
|
1753
|
+
return /* @__PURE__ */ jsxs3(DropdownMenu2, { children: [
|
|
1754
|
+
/* @__PURE__ */ jsx4(SimpleTooltip2, { label: "Renderer", side: "left", children: /* @__PURE__ */ jsx4(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx4(Button3, { variant: "ghost", size: "icon", children: renderer === "reagraph" ? "RG" : "CY" }) }) }),
|
|
1755
|
+
/* @__PURE__ */ jsxs3(DropdownMenuContent2, { side: "left", align: "start", children: [
|
|
1756
|
+
/* @__PURE__ */ jsx4(
|
|
1757
|
+
DropdownMenuItem2,
|
|
1548
1758
|
{
|
|
1549
1759
|
onClick: () => setRenderer("reagraph"),
|
|
1550
1760
|
className: renderer === "reagraph" ? "text-blue-600" : "",
|
|
1551
1761
|
children: "Reagraph"
|
|
1552
1762
|
}
|
|
1553
1763
|
),
|
|
1554
|
-
/* @__PURE__ */
|
|
1555
|
-
|
|
1764
|
+
/* @__PURE__ */ jsx4(
|
|
1765
|
+
DropdownMenuItem2,
|
|
1556
1766
|
{
|
|
1557
1767
|
onClick: () => setRenderer("cytoscape"),
|
|
1558
1768
|
className: renderer === "cytoscape" ? "text-blue-600" : "",
|
|
@@ -1564,46 +1774,46 @@ function RendererDropdown() {
|
|
|
1564
1774
|
}
|
|
1565
1775
|
|
|
1566
1776
|
// src/components/rea/LayoutAndCameraControls.tsx
|
|
1567
|
-
import { Fragment, jsx as
|
|
1777
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1568
1778
|
function PathSelectionDropdown({
|
|
1569
1779
|
setPathSelectionType
|
|
1570
1780
|
}) {
|
|
1571
|
-
return /* @__PURE__ */
|
|
1572
|
-
/* @__PURE__ */
|
|
1573
|
-
/* @__PURE__ */
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
/* @__PURE__ */
|
|
1577
|
-
/* @__PURE__ */
|
|
1781
|
+
return /* @__PURE__ */ jsxs4(DropdownMenu3, { children: [
|
|
1782
|
+
/* @__PURE__ */ jsx5(SimpleTooltip3, { label: "Path Selection Type", side: "left", children: /* @__PURE__ */ jsx5(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx5(Button4, { variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx5(ArrowUp, {}) }) }) }),
|
|
1783
|
+
/* @__PURE__ */ jsxs4(DropdownMenuContent3, { side: "left", align: "start", children: [
|
|
1784
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => setPathSelectionType("direct"), children: "None" }),
|
|
1785
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => setPathSelectionType("all"), children: "All Paths" }),
|
|
1786
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => setPathSelectionType("in"), children: "Inbound" }),
|
|
1787
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => setPathSelectionType("out"), children: "Outbound" })
|
|
1578
1788
|
] })
|
|
1579
1789
|
] });
|
|
1580
1790
|
}
|
|
1581
1791
|
function LayoutDropdown({ updateLayout }) {
|
|
1582
|
-
const [showTooltip, setShowTooltip] =
|
|
1792
|
+
const [showTooltip, setShowTooltip] = useState3(true);
|
|
1583
1793
|
const handleSelect = (layout) => {
|
|
1584
1794
|
updateLayout(layout);
|
|
1585
1795
|
setShowTooltip(false);
|
|
1586
1796
|
setTimeout(() => setShowTooltip(true), 500);
|
|
1587
1797
|
};
|
|
1588
|
-
const trigger = /* @__PURE__ */
|
|
1589
|
-
return /* @__PURE__ */
|
|
1590
|
-
showTooltip ? /* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1592
|
-
/* @__PURE__ */
|
|
1593
|
-
/* @__PURE__ */
|
|
1594
|
-
/* @__PURE__ */
|
|
1595
|
-
/* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
1598
|
-
/* @__PURE__ */
|
|
1599
|
-
/* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
/* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__PURE__ */
|
|
1604
|
-
/* @__PURE__ */
|
|
1605
|
-
/* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1798
|
+
const trigger = /* @__PURE__ */ jsx5(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx5(Button4, { variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx5(LayoutPanelTop, {}) }) });
|
|
1799
|
+
return /* @__PURE__ */ jsxs4(DropdownMenu3, { children: [
|
|
1800
|
+
showTooltip ? /* @__PURE__ */ jsx5(SimpleTooltip3, { label: "Layout", side: "left", children: trigger }) : trigger,
|
|
1801
|
+
/* @__PURE__ */ jsxs4(DropdownMenuContent3, { side: "left", align: "start", children: [
|
|
1802
|
+
/* @__PURE__ */ jsx5(DropdownMenuLabel, { children: "Force-directed Layouts" }),
|
|
1803
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("forceDirected2d"), children: "Force Directed" }),
|
|
1804
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("forceatlas2"), children: "Force Atlas 2" }),
|
|
1805
|
+
/* @__PURE__ */ jsx5(DropdownMenuSeparator2, {}),
|
|
1806
|
+
/* @__PURE__ */ jsx5(DropdownMenuLabel, { children: "Tree Layouts" }),
|
|
1807
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("treeTd2d"), children: "Tree Top-Down" }),
|
|
1808
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("treeLr2d"), children: "Tree Left-Right" }),
|
|
1809
|
+
/* @__PURE__ */ jsx5(DropdownMenuSeparator2, {}),
|
|
1810
|
+
/* @__PURE__ */ jsx5(DropdownMenuLabel, { children: "Circular & Radial Layouts" }),
|
|
1811
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("circular2d"), children: "Circular" }),
|
|
1812
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("radialOut2d"), children: "Radial Out" }),
|
|
1813
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("concentric2d"), children: "Concentric" }),
|
|
1814
|
+
/* @__PURE__ */ jsx5(DropdownMenuSeparator2, {}),
|
|
1815
|
+
/* @__PURE__ */ jsx5(DropdownMenuLabel, { children: "Utility Layouts" }),
|
|
1816
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem3, { onClick: () => handleSelect("nooverlap"), children: "No Overlap" })
|
|
1607
1817
|
] })
|
|
1608
1818
|
] });
|
|
1609
1819
|
}
|
|
@@ -1615,15 +1825,15 @@ function ViewControls({
|
|
|
1615
1825
|
isFocusMode,
|
|
1616
1826
|
onResetView
|
|
1617
1827
|
}) {
|
|
1618
|
-
return /* @__PURE__ */
|
|
1619
|
-
/* @__PURE__ */
|
|
1620
|
-
/* @__PURE__ */
|
|
1621
|
-
(hasHiddenElements || isFocusMode) && onResetView && /* @__PURE__ */
|
|
1622
|
-
|
|
1828
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1829
|
+
/* @__PURE__ */ jsx5(SimpleTooltip3, { label: "Fullscreen", side: "left", children: /* @__PURE__ */ jsx5(Button4, { variant: "ghost", size: "icon", onClick: toggleFullscreen, children: !fullscreen ? /* @__PURE__ */ jsx5(Maximize, {}) : /* @__PURE__ */ jsx5(Shrink, {}) }) }),
|
|
1830
|
+
/* @__PURE__ */ jsx5(SimpleTooltip3, { label: "Fit to screen", side: "left", children: /* @__PURE__ */ jsx5(Button4, { variant: "ghost", size: "icon", onClick: fitToScreen, children: /* @__PURE__ */ jsx5(Shrink, {}) }) }),
|
|
1831
|
+
(hasHiddenElements || isFocusMode) && onResetView && /* @__PURE__ */ jsx5(
|
|
1832
|
+
SimpleTooltip3,
|
|
1623
1833
|
{
|
|
1624
1834
|
label: isFocusMode ? "Reset Focus" : "Show All Hidden",
|
|
1625
1835
|
side: "left",
|
|
1626
|
-
children: /* @__PURE__ */
|
|
1836
|
+
children: /* @__PURE__ */ jsx5(Button4, { variant: "ghost", size: "icon", onClick: onResetView, children: /* @__PURE__ */ jsx5(Eye, {}) })
|
|
1627
1837
|
}
|
|
1628
1838
|
)
|
|
1629
1839
|
] });
|
|
@@ -1639,9 +1849,9 @@ function LayoutAndCameraControls({
|
|
|
1639
1849
|
onResetView,
|
|
1640
1850
|
extraToolbarContent
|
|
1641
1851
|
}) {
|
|
1642
|
-
return /* @__PURE__ */
|
|
1643
|
-
/* @__PURE__ */
|
|
1644
|
-
/* @__PURE__ */
|
|
1852
|
+
return /* @__PURE__ */ jsxs4("div", { className: "absolute right-2 top-2 flex flex-col border", children: [
|
|
1853
|
+
/* @__PURE__ */ jsx5(RendererDropdown, {}),
|
|
1854
|
+
/* @__PURE__ */ jsx5(
|
|
1645
1855
|
ViewControls,
|
|
1646
1856
|
{
|
|
1647
1857
|
fullscreen,
|
|
@@ -1652,9 +1862,9 @@ function LayoutAndCameraControls({
|
|
|
1652
1862
|
onResetView
|
|
1653
1863
|
}
|
|
1654
1864
|
),
|
|
1655
|
-
/* @__PURE__ */
|
|
1865
|
+
/* @__PURE__ */ jsx5(PathSelectionDropdown, { setPathSelectionType }),
|
|
1656
1866
|
extraToolbarContent,
|
|
1657
|
-
/* @__PURE__ */
|
|
1867
|
+
/* @__PURE__ */ jsx5(LayoutDropdown, { updateLayout })
|
|
1658
1868
|
] });
|
|
1659
1869
|
}
|
|
1660
1870
|
var LayoutAndCameraControls_default = LayoutAndCameraControls;
|
|
@@ -1664,10 +1874,10 @@ import { Card as Card2 } from "@petrarca/sonnet-ui";
|
|
|
1664
1874
|
|
|
1665
1875
|
// src/components/rea/NodeHoverInfo.tsx
|
|
1666
1876
|
import { Card, Separator } from "@petrarca/sonnet-ui";
|
|
1667
|
-
import { jsx as
|
|
1877
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1668
1878
|
function NodeHoverInfo({ node }) {
|
|
1669
|
-
return /* @__PURE__ */
|
|
1670
|
-
/* @__PURE__ */
|
|
1879
|
+
return /* @__PURE__ */ jsx6(Card, { className: "absolute top-2 left-1/2 -translate-x-1/2 bg-white shadow-md p-2", children: /* @__PURE__ */ jsxs5("div", { className: "flex flex-row items-center gap-2", children: [
|
|
1880
|
+
/* @__PURE__ */ jsx6(
|
|
1671
1881
|
Separator,
|
|
1672
1882
|
{
|
|
1673
1883
|
orientation: "vertical",
|
|
@@ -1676,43 +1886,43 @@ function NodeHoverInfo({ node }) {
|
|
|
1676
1886
|
style: { backgroundColor: node.fill }
|
|
1677
1887
|
}
|
|
1678
1888
|
),
|
|
1679
|
-
/* @__PURE__ */
|
|
1680
|
-
/* @__PURE__ */
|
|
1681
|
-
/* @__PURE__ */
|
|
1889
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
1890
|
+
/* @__PURE__ */ jsxs5("p", { children: [
|
|
1891
|
+
/* @__PURE__ */ jsxs5("strong", { children: [
|
|
1682
1892
|
node.data.label_,
|
|
1683
1893
|
": "
|
|
1684
1894
|
] }),
|
|
1685
1895
|
node.label
|
|
1686
1896
|
] }),
|
|
1687
|
-
/* @__PURE__ */
|
|
1897
|
+
/* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: node.data.id_ })
|
|
1688
1898
|
] })
|
|
1689
1899
|
] }) });
|
|
1690
1900
|
}
|
|
1691
1901
|
var NodeHoverInfo_default = NodeHoverInfo;
|
|
1692
1902
|
|
|
1693
1903
|
// src/components/rea/ReaContextMenu.tsx
|
|
1694
|
-
import
|
|
1904
|
+
import React4, { useState as useState5 } from "react";
|
|
1695
1905
|
import { devLog as devLog7 } from "@petrarca/sonnet-core";
|
|
1696
1906
|
|
|
1697
1907
|
// src/components/rea/ExpandOptionsPanel.tsx
|
|
1698
|
-
import { useCallback as
|
|
1908
|
+
import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
|
|
1699
1909
|
import { Checkbox, Input, Label } from "@petrarca/sonnet-ui";
|
|
1700
|
-
import { jsx as
|
|
1910
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1701
1911
|
function ExpandOptionsPanel({
|
|
1702
1912
|
nodeLabel,
|
|
1703
1913
|
onExpand,
|
|
1704
1914
|
onBack,
|
|
1705
1915
|
getEdgeTypes
|
|
1706
1916
|
}) {
|
|
1707
|
-
const [direction, setDirection] =
|
|
1708
|
-
const [limit, setLimit] =
|
|
1709
|
-
const [edgeTypes, setEdgeTypes] =
|
|
1710
|
-
const [selectedTypes, setSelectedTypes] =
|
|
1711
|
-
const [loading, setLoading] =
|
|
1712
|
-
const [offset, setOffset] =
|
|
1713
|
-
const expandBtnRef =
|
|
1714
|
-
const dragRef =
|
|
1715
|
-
const onPointerDown =
|
|
1917
|
+
const [direction, setDirection] = useState4("both");
|
|
1918
|
+
const [limit, setLimit] = useState4(100);
|
|
1919
|
+
const [edgeTypes, setEdgeTypes] = useState4([]);
|
|
1920
|
+
const [selectedTypes, setSelectedTypes] = useState4([]);
|
|
1921
|
+
const [loading, setLoading] = useState4(!!getEdgeTypes);
|
|
1922
|
+
const [offset, setOffset] = useState4({ x: 0, y: 0 });
|
|
1923
|
+
const expandBtnRef = useRef3(null);
|
|
1924
|
+
const dragRef = useRef3(null);
|
|
1925
|
+
const onPointerDown = useCallback4(
|
|
1716
1926
|
(e) => {
|
|
1717
1927
|
if (e.target.closest("button")) return;
|
|
1718
1928
|
e.preventDefault();
|
|
@@ -1726,16 +1936,16 @@ function ExpandOptionsPanel({
|
|
|
1726
1936
|
},
|
|
1727
1937
|
[offset]
|
|
1728
1938
|
);
|
|
1729
|
-
const onPointerMove =
|
|
1939
|
+
const onPointerMove = useCallback4((e) => {
|
|
1730
1940
|
if (!dragRef.current) return;
|
|
1731
1941
|
const dx = e.clientX - dragRef.current.startX;
|
|
1732
1942
|
const dy = e.clientY - dragRef.current.startY;
|
|
1733
1943
|
setOffset({ x: dragRef.current.origX + dx, y: dragRef.current.origY + dy });
|
|
1734
1944
|
}, []);
|
|
1735
|
-
const onPointerUp =
|
|
1945
|
+
const onPointerUp = useCallback4(() => {
|
|
1736
1946
|
dragRef.current = null;
|
|
1737
1947
|
}, []);
|
|
1738
|
-
|
|
1948
|
+
useEffect3(() => {
|
|
1739
1949
|
if (!getEdgeTypes) return;
|
|
1740
1950
|
setLoading(true);
|
|
1741
1951
|
getEdgeTypes().then((types) => {
|
|
@@ -1760,18 +1970,18 @@ function ExpandOptionsPanel({
|
|
|
1760
1970
|
};
|
|
1761
1971
|
const allSelected = selectedTypes.length === edgeTypes.length;
|
|
1762
1972
|
const noneSelected = edgeTypes.length > 0 && selectedTypes.length === 0;
|
|
1763
|
-
|
|
1973
|
+
useEffect3(() => {
|
|
1764
1974
|
if (!loading && !noneSelected) {
|
|
1765
1975
|
expandBtnRef.current?.focus();
|
|
1766
1976
|
}
|
|
1767
1977
|
}, [loading, noneSelected]);
|
|
1768
|
-
return /* @__PURE__ */
|
|
1978
|
+
return /* @__PURE__ */ jsxs6(
|
|
1769
1979
|
"div",
|
|
1770
1980
|
{
|
|
1771
1981
|
className: "bg-background border border-border rounded-md shadow-md p-2.5 min-w-48 space-y-2",
|
|
1772
1982
|
style: { transform: `translate(${offset.x}px, ${offset.y}px)` },
|
|
1773
1983
|
children: [
|
|
1774
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsxs6(
|
|
1775
1985
|
"div",
|
|
1776
1986
|
{
|
|
1777
1987
|
className: "flex items-center justify-between gap-2 cursor-grab active:cursor-grabbing select-none",
|
|
@@ -1779,7 +1989,7 @@ function ExpandOptionsPanel({
|
|
|
1779
1989
|
onPointerMove,
|
|
1780
1990
|
onPointerUp,
|
|
1781
1991
|
children: [
|
|
1782
|
-
/* @__PURE__ */
|
|
1992
|
+
/* @__PURE__ */ jsx7(
|
|
1783
1993
|
"button",
|
|
1784
1994
|
{
|
|
1785
1995
|
className: "text-[11px] text-muted-foreground hover:text-foreground cursor-pointer",
|
|
@@ -1787,13 +1997,13 @@ function ExpandOptionsPanel({
|
|
|
1787
1997
|
children: "Back"
|
|
1788
1998
|
}
|
|
1789
1999
|
),
|
|
1790
|
-
/* @__PURE__ */
|
|
2000
|
+
/* @__PURE__ */ jsx7("span", { className: "text-[11px] font-medium text-foreground truncate max-w-32", children: nodeLabel })
|
|
1791
2001
|
]
|
|
1792
2002
|
}
|
|
1793
2003
|
),
|
|
1794
|
-
/* @__PURE__ */
|
|
1795
|
-
/* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
2004
|
+
/* @__PURE__ */ jsxs6("div", { className: "space-y-1", children: [
|
|
2005
|
+
/* @__PURE__ */ jsx7(Label, { className: "text-[11px] text-muted-foreground", children: "Direction" }),
|
|
2006
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-0.5", children: ["both", "out", "in"].map((dir) => /* @__PURE__ */ jsx7(
|
|
1797
2007
|
"button",
|
|
1798
2008
|
{
|
|
1799
2009
|
className: `flex-1 px-2 py-1 text-[11px] capitalize rounded border cursor-pointer ${direction === dir ? "bg-primary/10 text-primary border-primary/40 font-medium" : "bg-background text-muted-foreground border-border hover:bg-muted"}`,
|
|
@@ -1803,10 +2013,10 @@ function ExpandOptionsPanel({
|
|
|
1803
2013
|
dir
|
|
1804
2014
|
)) })
|
|
1805
2015
|
] }),
|
|
1806
|
-
!loading && edgeTypes.length > 1 && /* @__PURE__ */
|
|
1807
|
-
/* @__PURE__ */
|
|
1808
|
-
/* @__PURE__ */
|
|
1809
|
-
/* @__PURE__ */
|
|
2016
|
+
!loading && edgeTypes.length > 1 && /* @__PURE__ */ jsxs6("div", { className: "space-y-1", children: [
|
|
2017
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between", children: [
|
|
2018
|
+
/* @__PURE__ */ jsx7(Label, { className: "text-[11px] text-muted-foreground", children: "Rel Types" }),
|
|
2019
|
+
/* @__PURE__ */ jsx7(
|
|
1810
2020
|
"button",
|
|
1811
2021
|
{
|
|
1812
2022
|
className: "text-[10px] text-muted-foreground hover:text-foreground cursor-pointer",
|
|
@@ -1815,12 +2025,12 @@ function ExpandOptionsPanel({
|
|
|
1815
2025
|
}
|
|
1816
2026
|
)
|
|
1817
2027
|
] }),
|
|
1818
|
-
/* @__PURE__ */
|
|
2028
|
+
/* @__PURE__ */ jsx7("div", { className: "space-y-0.5 max-h-32 overflow-y-auto", children: edgeTypes.map((type) => /* @__PURE__ */ jsxs6(
|
|
1819
2029
|
"label",
|
|
1820
2030
|
{
|
|
1821
2031
|
className: "flex items-center gap-1.5 text-[11px] cursor-pointer",
|
|
1822
2032
|
children: [
|
|
1823
|
-
/* @__PURE__ */
|
|
2033
|
+
/* @__PURE__ */ jsx7(
|
|
1824
2034
|
Checkbox,
|
|
1825
2035
|
{
|
|
1826
2036
|
checked: selectedTypes.includes(type),
|
|
@@ -1828,15 +2038,15 @@ function ExpandOptionsPanel({
|
|
|
1828
2038
|
className: "h-3 w-3"
|
|
1829
2039
|
}
|
|
1830
2040
|
),
|
|
1831
|
-
/* @__PURE__ */
|
|
2041
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate", children: type })
|
|
1832
2042
|
]
|
|
1833
2043
|
},
|
|
1834
2044
|
type
|
|
1835
2045
|
)) })
|
|
1836
2046
|
] }),
|
|
1837
|
-
/* @__PURE__ */
|
|
1838
|
-
/* @__PURE__ */
|
|
1839
|
-
/* @__PURE__ */
|
|
2047
|
+
/* @__PURE__ */ jsxs6("div", { className: "space-y-1", children: [
|
|
2048
|
+
/* @__PURE__ */ jsx7(Label, { className: "text-[11px] text-muted-foreground", children: "Limit" }),
|
|
2049
|
+
/* @__PURE__ */ jsx7(
|
|
1840
2050
|
Input,
|
|
1841
2051
|
{
|
|
1842
2052
|
type: "number",
|
|
@@ -1851,7 +2061,7 @@ function ExpandOptionsPanel({
|
|
|
1851
2061
|
}
|
|
1852
2062
|
)
|
|
1853
2063
|
] }),
|
|
1854
|
-
/* @__PURE__ */
|
|
2064
|
+
/* @__PURE__ */ jsx7(
|
|
1855
2065
|
"button",
|
|
1856
2066
|
{
|
|
1857
2067
|
ref: expandBtnRef,
|
|
@@ -1869,7 +2079,7 @@ function ExpandOptionsPanel({
|
|
|
1869
2079
|
var ExpandOptionsPanel_default = ExpandOptionsPanel;
|
|
1870
2080
|
|
|
1871
2081
|
// src/components/rea/ReaContextMenu.tsx
|
|
1872
|
-
import { jsx as
|
|
2082
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1873
2083
|
function ReaContextMenu({
|
|
1874
2084
|
data,
|
|
1875
2085
|
onClose,
|
|
@@ -1878,8 +2088,8 @@ function ReaContextMenu({
|
|
|
1878
2088
|
onCopyNode,
|
|
1879
2089
|
getNodeEdgeTypes
|
|
1880
2090
|
}) {
|
|
1881
|
-
const [showExpandPanel, setShowExpandPanel] =
|
|
1882
|
-
|
|
2091
|
+
const [showExpandPanel, setShowExpandPanel] = useState5(false);
|
|
2092
|
+
React4.useEffect(() => {
|
|
1883
2093
|
const handleKey = (e) => {
|
|
1884
2094
|
if (e.key === "Escape") onClose();
|
|
1885
2095
|
};
|
|
@@ -1989,7 +2199,7 @@ function ReaContextMenu({
|
|
|
1989
2199
|
const menuItems = elementType === "node" ? nodeMenuItems : edgeMenuItems;
|
|
1990
2200
|
if (showExpandPanel && elementType === "node") {
|
|
1991
2201
|
const nodeLabel = data.label || data.id;
|
|
1992
|
-
return /* @__PURE__ */
|
|
2202
|
+
return /* @__PURE__ */ jsx8(
|
|
1993
2203
|
ExpandOptionsPanel_default,
|
|
1994
2204
|
{
|
|
1995
2205
|
nodeLabel: String(nodeLabel),
|
|
@@ -1999,9 +2209,9 @@ function ReaContextMenu({
|
|
|
1999
2209
|
}
|
|
2000
2210
|
);
|
|
2001
2211
|
}
|
|
2002
|
-
return /* @__PURE__ */
|
|
2003
|
-
menuItems.map((item, index) => /* @__PURE__ */
|
|
2004
|
-
/* @__PURE__ */
|
|
2212
|
+
return /* @__PURE__ */ jsxs7("div", { className: "bg-background border border-border rounded-md shadow-lg py-1 min-w-48", children: [
|
|
2213
|
+
menuItems.map((item, index) => /* @__PURE__ */ jsxs7(React4.Fragment, { children: [
|
|
2214
|
+
/* @__PURE__ */ jsx8(
|
|
2005
2215
|
"button",
|
|
2006
2216
|
{
|
|
2007
2217
|
className: "w-full text-left px-3 py-2 text-sm hover:bg-muted/50 cursor-pointer",
|
|
@@ -2009,10 +2219,10 @@ function ReaContextMenu({
|
|
|
2009
2219
|
children: item.label
|
|
2010
2220
|
}
|
|
2011
2221
|
),
|
|
2012
|
-
index === 1 && /* @__PURE__ */
|
|
2222
|
+
index === 1 && /* @__PURE__ */ jsx8("div", { className: "border-t border-border my-1" })
|
|
2013
2223
|
] }, item.label)),
|
|
2014
|
-
/* @__PURE__ */
|
|
2015
|
-
/* @__PURE__ */
|
|
2224
|
+
/* @__PURE__ */ jsx8("div", { className: "border-t border-border my-1" }),
|
|
2225
|
+
/* @__PURE__ */ jsx8(
|
|
2016
2226
|
"button",
|
|
2017
2227
|
{
|
|
2018
2228
|
className: "w-full text-left px-3 py-1.5 text-xs text-muted-foreground hover:bg-muted/50 cursor-pointer",
|
|
@@ -2026,7 +2236,7 @@ var ReaContextMenu_default = ReaContextMenu;
|
|
|
2026
2236
|
|
|
2027
2237
|
// src/components/rea/ReaGraph.tsx
|
|
2028
2238
|
import { toast as toast2 } from "sonner";
|
|
2029
|
-
import { jsx as
|
|
2239
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2030
2240
|
function findElementInGraphData(elementId, elementType, nodes, edges) {
|
|
2031
2241
|
if (elementType === "node") {
|
|
2032
2242
|
const node = nodes.find((n) => n.id === elementId);
|
|
@@ -2093,21 +2303,21 @@ function ReaGraph({
|
|
|
2093
2303
|
extraToolbarContent,
|
|
2094
2304
|
getNodeEdgeTypes
|
|
2095
2305
|
}) {
|
|
2096
|
-
const isMountedRef =
|
|
2306
|
+
const isMountedRef = useRef4(false);
|
|
2097
2307
|
const { nodes, edges } = useReagraphData();
|
|
2098
2308
|
const { normalized } = useLiveGraphData();
|
|
2099
|
-
|
|
2309
|
+
useEffect4(() => {
|
|
2100
2310
|
devLog8("[ReGraph] counts", { nodes: nodes.length, edges: edges.length });
|
|
2101
2311
|
if (nodes.length > 0) devLog8("[ReGraph] sample node", nodes[0]);
|
|
2102
2312
|
if (edges.length > 0) devLog8("[ReGraph] sample edge", edges[0]);
|
|
2103
2313
|
}, [nodes, edges]);
|
|
2104
|
-
const canvas =
|
|
2105
|
-
const [hoveredNode, setHoveredNode] =
|
|
2314
|
+
const canvas = useRef4(null);
|
|
2315
|
+
const [hoveredNode, setHoveredNode] = useState6(
|
|
2106
2316
|
void 0
|
|
2107
2317
|
);
|
|
2108
|
-
const [layout, setLayout] =
|
|
2109
|
-
const [fullscreen, setFullscreen] =
|
|
2110
|
-
const [pathSelectionType, setPathSelectionType] =
|
|
2318
|
+
const [layout, setLayout] = useState6("forceDirected2d");
|
|
2319
|
+
const [fullscreen, setFullscreen] = useState6(false);
|
|
2320
|
+
const [pathSelectionType, setPathSelectionType] = useState6("direct");
|
|
2111
2321
|
const useGraphSelection = useWorkspaceSelection();
|
|
2112
2322
|
const useGraphFilter2 = useWorkspaceGraphFilter();
|
|
2113
2323
|
const useGraphExploration = useWorkspaceGraphExploration();
|
|
@@ -2134,7 +2344,7 @@ function ReaGraph({
|
|
|
2134
2344
|
pathSelectionType,
|
|
2135
2345
|
type: "multi"
|
|
2136
2346
|
});
|
|
2137
|
-
|
|
2347
|
+
useEffect4(() => {
|
|
2138
2348
|
const unsubscribe = useGraphFocus2.subscribe((state) => {
|
|
2139
2349
|
const focusAction = state.focusAction;
|
|
2140
2350
|
if (!focusAction || !canvas.current) return;
|
|
@@ -2158,12 +2368,12 @@ function ReaGraph({
|
|
|
2158
2368
|
});
|
|
2159
2369
|
return unsubscribe;
|
|
2160
2370
|
}, [nodes, edges, setSelectedNodeIds, setSelectedEdge, useGraphFocus2]);
|
|
2161
|
-
|
|
2371
|
+
useEffect4(() => {
|
|
2162
2372
|
if (!canvas.current) return;
|
|
2163
2373
|
clearSelections();
|
|
2164
2374
|
clearSelectionStore();
|
|
2165
2375
|
}, [lastDataChangeTime, clearSelections, clearSelectionStore]);
|
|
2166
|
-
const fitToScreen =
|
|
2376
|
+
const fitToScreen = useCallback5(
|
|
2167
2377
|
(reason) => {
|
|
2168
2378
|
if (!isMountedRef.current) return;
|
|
2169
2379
|
if (nodes.length === 0) return;
|
|
@@ -2189,7 +2399,7 @@ function ReaGraph({
|
|
|
2189
2399
|
},
|
|
2190
2400
|
[nodes.length]
|
|
2191
2401
|
);
|
|
2192
|
-
|
|
2402
|
+
useEffect4(() => {
|
|
2193
2403
|
isMountedRef.current = true;
|
|
2194
2404
|
fitToScreen("mount");
|
|
2195
2405
|
const state = useGraphSelection.getState();
|
|
@@ -2209,9 +2419,9 @@ function ReaGraph({
|
|
|
2209
2419
|
isMountedRef.current = false;
|
|
2210
2420
|
};
|
|
2211
2421
|
}, [fitToScreen, setSelections, setSelectedEdge, useGraphSelection]);
|
|
2212
|
-
const selectionsRef =
|
|
2422
|
+
const selectionsRef = useRef4(selections);
|
|
2213
2423
|
selectionsRef.current = selections;
|
|
2214
|
-
|
|
2424
|
+
useEffect4(() => {
|
|
2215
2425
|
const inSync = (nodeIds) => {
|
|
2216
2426
|
const cur = selectionsRef.current;
|
|
2217
2427
|
return cur.length === nodeIds.length && nodeIds.every((id) => cur.includes(id));
|
|
@@ -2223,7 +2433,7 @@ function ReaGraph({
|
|
|
2223
2433
|
});
|
|
2224
2434
|
return unsubscribe;
|
|
2225
2435
|
}, [useGraphSelection, setSelections]);
|
|
2226
|
-
|
|
2436
|
+
useEffect4(() => {
|
|
2227
2437
|
if (isMountedRef.current) fitToScreen("counts-changed");
|
|
2228
2438
|
}, [nodes.length, edges.length, fitToScreen]);
|
|
2229
2439
|
function updateLayout(next) {
|
|
@@ -2271,12 +2481,12 @@ function ReaGraph({
|
|
|
2271
2481
|
setSelectedEdge(null);
|
|
2272
2482
|
if (onCanvasClick) onCanvasClick(e);
|
|
2273
2483
|
}
|
|
2274
|
-
|
|
2484
|
+
useEffect4(() => {
|
|
2275
2485
|
if (!isMountedRef.current) return;
|
|
2276
2486
|
const selectedNodes = selections.map((id) => nodes.find((n) => n.id === id)).filter(Boolean);
|
|
2277
2487
|
setSelectedNodeIds(selectedNodes.map((n) => n.id));
|
|
2278
2488
|
}, [selections, nodes]);
|
|
2279
|
-
|
|
2489
|
+
useEffect4(() => {
|
|
2280
2490
|
if (!isMountedRef.current) return;
|
|
2281
2491
|
const currentSelectedIds = useGraphSelection.getState().selectedNodeIds;
|
|
2282
2492
|
if (!currentSelectedIds.length) return;
|
|
@@ -2295,7 +2505,7 @@ function ReaGraph({
|
|
|
2295
2505
|
setSelectedEdge,
|
|
2296
2506
|
useGraphSelection
|
|
2297
2507
|
]);
|
|
2298
|
-
|
|
2508
|
+
useEffect4(() => {
|
|
2299
2509
|
if (!isMountedRef.current) return;
|
|
2300
2510
|
const currentSelectedIds = useGraphSelection.getState().selectedNodeIds;
|
|
2301
2511
|
if (!currentSelectedIds.length) return;
|
|
@@ -2307,7 +2517,7 @@ function ReaGraph({
|
|
|
2307
2517
|
if (stillPresentIds.length < 2) setSelectedEdge(null);
|
|
2308
2518
|
}
|
|
2309
2519
|
}, [nodes, setSelectedNodeIds, setSelectedEdge, useGraphSelection]);
|
|
2310
|
-
|
|
2520
|
+
useEffect4(() => {
|
|
2311
2521
|
if (!fullscreen) return;
|
|
2312
2522
|
const prevOverflow = document.body.style.overflow;
|
|
2313
2523
|
document.body.style.overflow = "hidden";
|
|
@@ -2321,7 +2531,7 @@ function ReaGraph({
|
|
|
2321
2531
|
window.removeEventListener("keydown", handleKey);
|
|
2322
2532
|
};
|
|
2323
2533
|
}, [fullscreen, fitToScreen]);
|
|
2324
|
-
|
|
2534
|
+
useEffect4(() => {
|
|
2325
2535
|
if (!fullscreen) return;
|
|
2326
2536
|
const id = setTimeout(() => {
|
|
2327
2537
|
if (canvas.current) {
|
|
@@ -2330,7 +2540,7 @@ function ReaGraph({
|
|
|
2330
2540
|
}, 50);
|
|
2331
2541
|
return () => clearTimeout(id);
|
|
2332
2542
|
}, [fullscreen, fitToScreen]);
|
|
2333
|
-
|
|
2543
|
+
useEffect4(() => {
|
|
2334
2544
|
if (!isMountedRef.current) return;
|
|
2335
2545
|
const handleResize = () => {
|
|
2336
2546
|
if (isMountedRef.current && canvas.current) {
|
|
@@ -2342,8 +2552,8 @@ function ReaGraph({
|
|
|
2342
2552
|
window.removeEventListener("resize", handleResize);
|
|
2343
2553
|
};
|
|
2344
2554
|
}, [fitToScreen]);
|
|
2345
|
-
const firstDataRef =
|
|
2346
|
-
|
|
2555
|
+
const firstDataRef = useRef4(true);
|
|
2556
|
+
useEffect4(() => {
|
|
2347
2557
|
if (!isMountedRef.current) return;
|
|
2348
2558
|
if (nodes.length > 0) {
|
|
2349
2559
|
if (firstDataRef.current) {
|
|
@@ -2356,18 +2566,18 @@ function ReaGraph({
|
|
|
2356
2566
|
}, [nodes.length, fitToScreen]);
|
|
2357
2567
|
if (nodes.length === 0) {
|
|
2358
2568
|
devLog8("[ReGraph] empty state render");
|
|
2359
|
-
return /* @__PURE__ */
|
|
2360
|
-
/* @__PURE__ */
|
|
2361
|
-
/* @__PURE__ */
|
|
2569
|
+
return /* @__PURE__ */ jsxs8(Card2, { className: "relative w-full h-full items-center justify-center text-slate-500 gap-2 shadow-xs p-4", children: [
|
|
2570
|
+
/* @__PURE__ */ jsx9("div", { children: "No data to display." }),
|
|
2571
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
2362
2572
|
"Please",
|
|
2363
2573
|
" ",
|
|
2364
|
-
/* @__PURE__ */
|
|
2574
|
+
/* @__PURE__ */ jsx9("span", { className: "font-semibold", children: "run a query, check filters, or add a node" }),
|
|
2365
2575
|
" ",
|
|
2366
2576
|
"to the workbench to populate the graph."
|
|
2367
2577
|
] })
|
|
2368
2578
|
] });
|
|
2369
2579
|
}
|
|
2370
|
-
return /* @__PURE__ */
|
|
2580
|
+
return /* @__PURE__ */ jsxs8(
|
|
2371
2581
|
"div",
|
|
2372
2582
|
{
|
|
2373
2583
|
className: cn(
|
|
@@ -2375,7 +2585,7 @@ function ReaGraph({
|
|
|
2375
2585
|
fullscreen ? "fixed inset-0 z-50 w-screen h-screen p-0 m-0" : "relative w-full h-full"
|
|
2376
2586
|
),
|
|
2377
2587
|
children: [
|
|
2378
|
-
/* @__PURE__ */
|
|
2588
|
+
/* @__PURE__ */ jsx9(Card2, { className: "h-full shadow-xs p-4", children: /* @__PURE__ */ jsx9(
|
|
2379
2589
|
GraphCanvas,
|
|
2380
2590
|
{
|
|
2381
2591
|
ref: canvas,
|
|
@@ -2400,7 +2610,7 @@ function ReaGraph({
|
|
|
2400
2610
|
elementId: data.id,
|
|
2401
2611
|
elementType
|
|
2402
2612
|
});
|
|
2403
|
-
return /* @__PURE__ */
|
|
2613
|
+
return /* @__PURE__ */ jsx9(
|
|
2404
2614
|
ReaContextMenu_default,
|
|
2405
2615
|
{
|
|
2406
2616
|
data,
|
|
@@ -2414,8 +2624,8 @@ function ReaGraph({
|
|
|
2414
2624
|
}
|
|
2415
2625
|
}
|
|
2416
2626
|
) }),
|
|
2417
|
-
hoveredNode && /* @__PURE__ */
|
|
2418
|
-
/* @__PURE__ */
|
|
2627
|
+
hoveredNode && /* @__PURE__ */ jsx9(NodeHoverInfo_default, { node: hoveredNode }),
|
|
2628
|
+
/* @__PURE__ */ jsx9(
|
|
2419
2629
|
LayoutAndCameraControls_default,
|
|
2420
2630
|
{
|
|
2421
2631
|
fitToScreen,
|
|
@@ -2442,10 +2652,10 @@ var ReaGraph_default = ReaGraph;
|
|
|
2442
2652
|
|
|
2443
2653
|
// src/components/cyto/CytoscapeGraph.tsx
|
|
2444
2654
|
import {
|
|
2445
|
-
useEffect as
|
|
2446
|
-
useRef as
|
|
2447
|
-
useState as
|
|
2448
|
-
useCallback as
|
|
2655
|
+
useEffect as useEffect5,
|
|
2656
|
+
useRef as useRef5,
|
|
2657
|
+
useState as useState7,
|
|
2658
|
+
useCallback as useCallback6
|
|
2449
2659
|
} from "react";
|
|
2450
2660
|
import { devLog as devLog10, errorLog as errorLog3 } from "@petrarca/sonnet-core";
|
|
2451
2661
|
import cytoscape from "cytoscape";
|
|
@@ -2459,17 +2669,17 @@ import cxtmenu from "cytoscape-cxtmenu";
|
|
|
2459
2669
|
|
|
2460
2670
|
// src/components/cyto/CytoscapeControls.tsx
|
|
2461
2671
|
import {
|
|
2462
|
-
Button as
|
|
2463
|
-
DropdownMenu as
|
|
2464
|
-
DropdownMenuContent as
|
|
2465
|
-
DropdownMenuItem as
|
|
2672
|
+
Button as Button5,
|
|
2673
|
+
DropdownMenu as DropdownMenu4,
|
|
2674
|
+
DropdownMenuContent as DropdownMenuContent4,
|
|
2675
|
+
DropdownMenuItem as DropdownMenuItem4,
|
|
2466
2676
|
DropdownMenuLabel as DropdownMenuLabel2,
|
|
2467
|
-
DropdownMenuSeparator as
|
|
2468
|
-
DropdownMenuTrigger as
|
|
2469
|
-
SimpleTooltip as
|
|
2677
|
+
DropdownMenuSeparator as DropdownMenuSeparator3,
|
|
2678
|
+
DropdownMenuTrigger as DropdownMenuTrigger4,
|
|
2679
|
+
SimpleTooltip as SimpleTooltip4
|
|
2470
2680
|
} from "@petrarca/sonnet-ui";
|
|
2471
2681
|
import { LayoutPanelTop as LayoutPanelTop2, Monitor, Frame, Eye as Eye2, Minus } from "lucide-react";
|
|
2472
|
-
import { Fragment as Fragment2, jsx as
|
|
2682
|
+
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2473
2683
|
function ViewControls2({
|
|
2474
2684
|
zoomIn,
|
|
2475
2685
|
zoomOut,
|
|
@@ -2480,17 +2690,17 @@ function ViewControls2({
|
|
|
2480
2690
|
isFocusMode,
|
|
2481
2691
|
onResetView
|
|
2482
2692
|
}) {
|
|
2483
|
-
return /* @__PURE__ */
|
|
2484
|
-
/* @__PURE__ */
|
|
2485
|
-
/* @__PURE__ */
|
|
2486
|
-
/* @__PURE__ */
|
|
2487
|
-
/* @__PURE__ */
|
|
2488
|
-
(hasHiddenElements || isFocusMode) && onResetView && /* @__PURE__ */
|
|
2489
|
-
|
|
2693
|
+
return /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
2694
|
+
/* @__PURE__ */ jsx10(SimpleTooltip4, { label: "Zoom In", side: "left", children: /* @__PURE__ */ jsx10(Button5, { variant: "ghost", size: "icon", onClick: zoomIn, children: /* @__PURE__ */ jsx10("span", { style: { fontWeight: 600 }, children: "+" }) }) }),
|
|
2695
|
+
/* @__PURE__ */ jsx10(SimpleTooltip4, { label: "Zoom Out", side: "left", children: /* @__PURE__ */ jsx10(Button5, { variant: "ghost", size: "icon", onClick: zoomOut, children: /* @__PURE__ */ jsx10(Minus, {}) }) }),
|
|
2696
|
+
/* @__PURE__ */ jsx10(SimpleTooltip4, { label: "Fullscreen", side: "left", children: /* @__PURE__ */ jsx10(Button5, { variant: "ghost", size: "icon", onClick: toggleFullscreen, children: !fullscreen ? /* @__PURE__ */ jsx10(Monitor, {}) : /* @__PURE__ */ jsx10(Frame, {}) }) }),
|
|
2697
|
+
/* @__PURE__ */ jsx10(SimpleTooltip4, { label: "Fit to screen", side: "left", children: /* @__PURE__ */ jsx10(Button5, { variant: "ghost", size: "icon", onClick: fitToScreen, children: /* @__PURE__ */ jsx10(Frame, {}) }) }),
|
|
2698
|
+
(hasHiddenElements || isFocusMode) && onResetView && /* @__PURE__ */ jsx10(
|
|
2699
|
+
SimpleTooltip4,
|
|
2490
2700
|
{
|
|
2491
2701
|
label: isFocusMode ? "Reset Focus" : "Show All Hidden",
|
|
2492
2702
|
side: "left",
|
|
2493
|
-
children: /* @__PURE__ */
|
|
2703
|
+
children: /* @__PURE__ */ jsx10(Button5, { variant: "ghost", size: "icon", onClick: onResetView, children: /* @__PURE__ */ jsx10(Eye2, {}) })
|
|
2494
2704
|
}
|
|
2495
2705
|
)
|
|
2496
2706
|
] });
|
|
@@ -2525,13 +2735,13 @@ var LAYOUT_GROUPS = [
|
|
|
2525
2735
|
}
|
|
2526
2736
|
];
|
|
2527
2737
|
function LayoutDropdown2({ currentLayout, updateLayout }) {
|
|
2528
|
-
return /* @__PURE__ */
|
|
2529
|
-
/* @__PURE__ */
|
|
2530
|
-
/* @__PURE__ */
|
|
2531
|
-
groupIdx > 0 && /* @__PURE__ */
|
|
2532
|
-
/* @__PURE__ */
|
|
2533
|
-
group.items.map((item) => /* @__PURE__ */
|
|
2534
|
-
|
|
2738
|
+
return /* @__PURE__ */ jsxs9(DropdownMenu4, { children: [
|
|
2739
|
+
/* @__PURE__ */ jsx10(SimpleTooltip4, { label: "Layout", side: "left", children: /* @__PURE__ */ jsx10(DropdownMenuTrigger4, { asChild: true, children: /* @__PURE__ */ jsx10(Button5, { variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx10(LayoutPanelTop2, {}) }) }) }),
|
|
2740
|
+
/* @__PURE__ */ jsx10(DropdownMenuContent4, { side: "left", align: "start", children: LAYOUT_GROUPS.map((group, groupIdx) => /* @__PURE__ */ jsxs9("div", { children: [
|
|
2741
|
+
groupIdx > 0 && /* @__PURE__ */ jsx10(DropdownMenuSeparator3, {}),
|
|
2742
|
+
/* @__PURE__ */ jsx10(DropdownMenuLabel2, { children: group.label }),
|
|
2743
|
+
group.items.map((item) => /* @__PURE__ */ jsx10(
|
|
2744
|
+
DropdownMenuItem4,
|
|
2535
2745
|
{
|
|
2536
2746
|
onClick: () => updateLayout(item.layout),
|
|
2537
2747
|
className: currentLayout === item.layout ? "text-blue-600" : "",
|
|
@@ -2555,9 +2765,9 @@ function CytoscapeControls({
|
|
|
2555
2765
|
onResetView,
|
|
2556
2766
|
extraToolbarContent
|
|
2557
2767
|
}) {
|
|
2558
|
-
return /* @__PURE__ */
|
|
2559
|
-
/* @__PURE__ */
|
|
2560
|
-
/* @__PURE__ */
|
|
2768
|
+
return /* @__PURE__ */ jsxs9("div", { className: "absolute right-2 top-2 flex flex-col border bg-white rounded-md shadow-sm z-10", children: [
|
|
2769
|
+
/* @__PURE__ */ jsx10(RendererDropdown, {}),
|
|
2770
|
+
/* @__PURE__ */ jsx10(
|
|
2561
2771
|
ViewControls2,
|
|
2562
2772
|
{
|
|
2563
2773
|
zoomIn,
|
|
@@ -2571,7 +2781,7 @@ function CytoscapeControls({
|
|
|
2571
2781
|
}
|
|
2572
2782
|
),
|
|
2573
2783
|
extraToolbarContent,
|
|
2574
|
-
/* @__PURE__ */
|
|
2784
|
+
/* @__PURE__ */ jsx10(
|
|
2575
2785
|
LayoutDropdown2,
|
|
2576
2786
|
{
|
|
2577
2787
|
currentLayout,
|
|
@@ -3011,7 +3221,7 @@ var createEdgeContextMenu = ({
|
|
|
3011
3221
|
|
|
3012
3222
|
// src/components/cyto/CytoscapeGraph.tsx
|
|
3013
3223
|
import { toast as toast4 } from "sonner";
|
|
3014
|
-
import { jsx as
|
|
3224
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3015
3225
|
function CytoscapeExpandOverlay({
|
|
3016
3226
|
expandRequest,
|
|
3017
3227
|
containerRef,
|
|
@@ -3019,7 +3229,7 @@ function CytoscapeExpandOverlay({
|
|
|
3019
3229
|
getNodeEdgeTypes,
|
|
3020
3230
|
onClose
|
|
3021
3231
|
}) {
|
|
3022
|
-
return /* @__PURE__ */
|
|
3232
|
+
return /* @__PURE__ */ jsx11(
|
|
3023
3233
|
"div",
|
|
3024
3234
|
{
|
|
3025
3235
|
className: "absolute z-50",
|
|
@@ -3034,7 +3244,7 @@ function CytoscapeExpandOverlay({
|
|
|
3034
3244
|
),
|
|
3035
3245
|
transform: "translate(-50%, 12px)"
|
|
3036
3246
|
},
|
|
3037
|
-
children: /* @__PURE__ */
|
|
3247
|
+
children: /* @__PURE__ */ jsx11(
|
|
3038
3248
|
ExpandOptionsPanel_default,
|
|
3039
3249
|
{
|
|
3040
3250
|
nodeLabel: expandRequest.nodeLabel,
|
|
@@ -3346,8 +3556,8 @@ function computeGraphViewState({
|
|
|
3346
3556
|
};
|
|
3347
3557
|
}
|
|
3348
3558
|
function useFullscreen(fitToScreen, cyRef) {
|
|
3349
|
-
const [fullscreen, setFullscreen] =
|
|
3350
|
-
|
|
3559
|
+
const [fullscreen, setFullscreen] = useState7(false);
|
|
3560
|
+
useEffect5(() => {
|
|
3351
3561
|
if (fullscreen) {
|
|
3352
3562
|
const prevOverflow = document.body.style.overflow;
|
|
3353
3563
|
document.body.style.overflow = "hidden";
|
|
@@ -3362,7 +3572,7 @@ function useFullscreen(fitToScreen, cyRef) {
|
|
|
3362
3572
|
};
|
|
3363
3573
|
}
|
|
3364
3574
|
}, [fullscreen, fitToScreen]);
|
|
3365
|
-
|
|
3575
|
+
useEffect5(() => {
|
|
3366
3576
|
if (!fullscreen) return;
|
|
3367
3577
|
const id = setTimeout(() => {
|
|
3368
3578
|
if (cyRef.current) {
|
|
@@ -3375,7 +3585,7 @@ function useFullscreen(fitToScreen, cyRef) {
|
|
|
3375
3585
|
return {
|
|
3376
3586
|
fullscreen,
|
|
3377
3587
|
setFullscreen,
|
|
3378
|
-
toggleFullscreen:
|
|
3588
|
+
toggleFullscreen: useCallback6(() => setFullscreen((f) => !f), [])
|
|
3379
3589
|
};
|
|
3380
3590
|
}
|
|
3381
3591
|
function setupCytoscapeEventHandlers({
|
|
@@ -3489,16 +3699,16 @@ function CytoscapeGraph({
|
|
|
3489
3699
|
extraToolbarContent,
|
|
3490
3700
|
getNodeEdgeTypes
|
|
3491
3701
|
}) {
|
|
3492
|
-
const containerRef =
|
|
3493
|
-
const cyRef =
|
|
3494
|
-
const isInitializedRef =
|
|
3495
|
-
const [currentLayout, setCurrentLayout] =
|
|
3496
|
-
const [expandRequest, setExpandRequest] =
|
|
3702
|
+
const containerRef = useRef5(null);
|
|
3703
|
+
const cyRef = useRef5(null);
|
|
3704
|
+
const isInitializedRef = useRef5(false);
|
|
3705
|
+
const [currentLayout, setCurrentLayout] = useState7(initialLayout);
|
|
3706
|
+
const [expandRequest, setExpandRequest] = useState7(
|
|
3497
3707
|
null
|
|
3498
3708
|
);
|
|
3499
|
-
const nodesRef =
|
|
3500
|
-
const edgesRef =
|
|
3501
|
-
const pendingFocusActionRef =
|
|
3709
|
+
const nodesRef = useRef5([]);
|
|
3710
|
+
const edgesRef = useRef5([]);
|
|
3711
|
+
const pendingFocusActionRef = useRef5(null);
|
|
3502
3712
|
const cytoData = useCytoscapeData();
|
|
3503
3713
|
const live = useLiveGraphData();
|
|
3504
3714
|
const nodes = live.nodes;
|
|
@@ -3519,13 +3729,13 @@ function CytoscapeGraph({
|
|
|
3519
3729
|
setSelectedEdge: setSelectedEdgeStore,
|
|
3520
3730
|
clear: clearSelectionStore
|
|
3521
3731
|
} = useSelection3.getState();
|
|
3522
|
-
const selectedNodeIdsRef =
|
|
3732
|
+
const selectedNodeIdsRef = useRef5(
|
|
3523
3733
|
useSelection3.getState().selectedNodeIds
|
|
3524
3734
|
);
|
|
3525
|
-
const selectedEdgeRef =
|
|
3735
|
+
const selectedEdgeRef = useRef5(
|
|
3526
3736
|
useSelection3.getState().selectedEdge
|
|
3527
3737
|
);
|
|
3528
|
-
|
|
3738
|
+
useEffect5(() => {
|
|
3529
3739
|
const applyStoreSelection = (nodeIds, edge) => {
|
|
3530
3740
|
selectedNodeIdsRef.current = nodeIds;
|
|
3531
3741
|
selectedEdgeRef.current = edge;
|
|
@@ -3565,13 +3775,13 @@ function CytoscapeGraph({
|
|
|
3565
3775
|
});
|
|
3566
3776
|
return unsubscribe;
|
|
3567
3777
|
}, [useSelection3]);
|
|
3568
|
-
|
|
3778
|
+
useEffect5(() => {
|
|
3569
3779
|
nodesRef.current = nodes;
|
|
3570
3780
|
}, [nodes]);
|
|
3571
|
-
|
|
3781
|
+
useEffect5(() => {
|
|
3572
3782
|
edgesRef.current = edges;
|
|
3573
3783
|
}, [edges]);
|
|
3574
|
-
|
|
3784
|
+
useEffect5(() => {
|
|
3575
3785
|
if (!containerRef.current || cyRef.current) return;
|
|
3576
3786
|
isInitializedRef.current = true;
|
|
3577
3787
|
cyRef.current = cytoscape({
|
|
@@ -3734,10 +3944,10 @@ function CytoscapeGraph({
|
|
|
3734
3944
|
cyRef.current = null;
|
|
3735
3945
|
};
|
|
3736
3946
|
}, []);
|
|
3737
|
-
const elementIdsRef =
|
|
3738
|
-
const lastLayoutRef =
|
|
3739
|
-
const lastFitPaddingRef =
|
|
3740
|
-
|
|
3947
|
+
const elementIdsRef = useRef5("");
|
|
3948
|
+
const lastLayoutRef = useRef5("");
|
|
3949
|
+
const lastFitPaddingRef = useRef5(fitPadding);
|
|
3950
|
+
useEffect5(() => {
|
|
3741
3951
|
const cy = cyRef.current;
|
|
3742
3952
|
if (!cy || !isInitializedRef.current) return;
|
|
3743
3953
|
const currentIds = nodes.map((n) => n.id_).sort().join(",") + "|" + edges.map((e) => e.id_).sort().join(",");
|
|
@@ -3811,12 +4021,12 @@ function CytoscapeGraph({
|
|
|
3811
4021
|
});
|
|
3812
4022
|
}
|
|
3813
4023
|
}, [nodes, edges, currentLayout, fitPadding]);
|
|
3814
|
-
|
|
4024
|
+
useEffect5(() => {
|
|
3815
4025
|
if (!cyRef.current) return;
|
|
3816
4026
|
cyRef.current.elements().unselect();
|
|
3817
4027
|
clearSelectionStore();
|
|
3818
4028
|
}, [lastDataChangeTime, clearSelectionStore]);
|
|
3819
|
-
|
|
4029
|
+
useEffect5(() => {
|
|
3820
4030
|
const unsubscribe = useGraphFocus2.subscribe((state) => {
|
|
3821
4031
|
handleFocusStateChange({
|
|
3822
4032
|
focusStore: useGraphFocus2,
|
|
@@ -3841,15 +4051,15 @@ function CytoscapeGraph({
|
|
|
3841
4051
|
const updateLayout = (newLayout) => {
|
|
3842
4052
|
setCurrentLayout(newLayout);
|
|
3843
4053
|
};
|
|
3844
|
-
const fitToScreen =
|
|
4054
|
+
const fitToScreen = useCallback6(() => {
|
|
3845
4055
|
if (cyRef.current) {
|
|
3846
4056
|
cyRef.current.fit(void 0, fitPadding);
|
|
3847
4057
|
}
|
|
3848
4058
|
}, [fitPadding]);
|
|
3849
|
-
|
|
4059
|
+
useEffect5(() => {
|
|
3850
4060
|
fitToScreen();
|
|
3851
4061
|
}, [nodes.length, fitToScreen]);
|
|
3852
|
-
|
|
4062
|
+
useEffect5(() => {
|
|
3853
4063
|
if (!isInitializedRef.current) return;
|
|
3854
4064
|
const handleResize = () => cyRef.current?.resize();
|
|
3855
4065
|
window.addEventListener("resize", handleResize);
|
|
@@ -3868,9 +4078,9 @@ function CytoscapeGraph({
|
|
|
3868
4078
|
isFocusMode,
|
|
3869
4079
|
fullscreen
|
|
3870
4080
|
});
|
|
3871
|
-
return /* @__PURE__ */
|
|
3872
|
-
/* @__PURE__ */
|
|
3873
|
-
expandRequest && /* @__PURE__ */
|
|
4081
|
+
return /* @__PURE__ */ jsx11("div", { className: outerClass, children: /* @__PURE__ */ jsxs10("div", { className: innerClass, children: [
|
|
4082
|
+
/* @__PURE__ */ jsx11("div", { ref: containerRef, className: "absolute inset-0" }),
|
|
4083
|
+
expandRequest && /* @__PURE__ */ jsx11(
|
|
3874
4084
|
CytoscapeExpandOverlay,
|
|
3875
4085
|
{
|
|
3876
4086
|
expandRequest,
|
|
@@ -3880,9 +4090,9 @@ function CytoscapeGraph({
|
|
|
3880
4090
|
onClose: () => setExpandRequest(null)
|
|
3881
4091
|
}
|
|
3882
4092
|
),
|
|
3883
|
-
showEmptyMessage && /* @__PURE__ */
|
|
3884
|
-
showFilteredMessage && /* @__PURE__ */
|
|
3885
|
-
showControls && /* @__PURE__ */
|
|
4093
|
+
showEmptyMessage && /* @__PURE__ */ jsx11("div", { className: "absolute inset-0 flex items-center justify-center text-xs text-gray-500 pointer-events-none select-none", children: "No graph data to visualize (run a query or check the filters)" }),
|
|
4094
|
+
showFilteredMessage && /* @__PURE__ */ jsx11("div", { className: "absolute inset-0 flex items-center justify-center text-xs text-gray-500 pointer-events-none select-none", children: 'All elements are hidden or filtered (click "Reset Focus" to restore)' }),
|
|
4095
|
+
showControls && /* @__PURE__ */ jsx11(
|
|
3886
4096
|
CytoscapeControls_default,
|
|
3887
4097
|
{
|
|
3888
4098
|
updateLayout,
|
|
@@ -3930,15 +4140,15 @@ function CytoscapeGraph({
|
|
|
3930
4140
|
var CytoscapeGraph_default = CytoscapeGraph;
|
|
3931
4141
|
|
|
3932
4142
|
// src/components/GraphVisualizer.tsx
|
|
3933
|
-
import { jsx as
|
|
4143
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3934
4144
|
function GraphVisualizer({
|
|
3935
4145
|
onCopyNode,
|
|
3936
4146
|
extraToolbarContent,
|
|
3937
4147
|
getNodeEdgeTypes
|
|
3938
4148
|
}) {
|
|
3939
4149
|
const { renderer } = useGraphRenderer();
|
|
3940
|
-
return /* @__PURE__ */
|
|
3941
|
-
renderer === "reagraph" && /* @__PURE__ */
|
|
4150
|
+
return /* @__PURE__ */ jsx12("div", { className: "relative w-full h-full flex flex-col overflow-hidden", children: /* @__PURE__ */ jsxs11("div", { className: "flex-1 h-full", children: [
|
|
4151
|
+
renderer === "reagraph" && /* @__PURE__ */ jsx12(
|
|
3942
4152
|
ReaGraph_default,
|
|
3943
4153
|
{
|
|
3944
4154
|
onCopyNode,
|
|
@@ -3947,7 +4157,7 @@ function GraphVisualizer({
|
|
|
3947
4157
|
},
|
|
3948
4158
|
"reagraph"
|
|
3949
4159
|
),
|
|
3950
|
-
renderer === "cytoscape" && /* @__PURE__ */
|
|
4160
|
+
renderer === "cytoscape" && /* @__PURE__ */ jsx12(
|
|
3951
4161
|
CytoscapeGraph_default,
|
|
3952
4162
|
{
|
|
3953
4163
|
onCopyNode,
|
|
@@ -3964,7 +4174,7 @@ var GraphVisualizer_default = GraphVisualizer;
|
|
|
3964
4174
|
import { Card as Card5 } from "@petrarca/sonnet-ui";
|
|
3965
4175
|
|
|
3966
4176
|
// src/components/ActionPanel/NodeInfoCard.tsx
|
|
3967
|
-
import { useState as
|
|
4177
|
+
import { useState as useState8 } from "react";
|
|
3968
4178
|
import {
|
|
3969
4179
|
Card as Card3,
|
|
3970
4180
|
Collapsible,
|
|
@@ -3972,11 +4182,11 @@ import {
|
|
|
3972
4182
|
CollapsibleTrigger,
|
|
3973
4183
|
PropertyList
|
|
3974
4184
|
} from "@petrarca/sonnet-ui";
|
|
3975
|
-
import { copyTextToClipboard } from "@petrarca/sonnet-core";
|
|
3976
|
-
import { jsx as
|
|
4185
|
+
import { copyTextToClipboard as copyTextToClipboard2 } from "@petrarca/sonnet-core";
|
|
4186
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3977
4187
|
function NodeInfoCard({ node }) {
|
|
3978
|
-
const [showProperties, setShowProperties] =
|
|
3979
|
-
return /* @__PURE__ */
|
|
4188
|
+
const [showProperties, setShowProperties] = useState8(false);
|
|
4189
|
+
return /* @__PURE__ */ jsxs12(
|
|
3980
4190
|
Card3,
|
|
3981
4191
|
{
|
|
3982
4192
|
className: "w-full rounded-lg overflow-hidden bg-muted/30 border shadow-none p-3",
|
|
@@ -3984,20 +4194,20 @@ function NodeInfoCard({ node }) {
|
|
|
3984
4194
|
borderLeft: `4px solid ${node.visual.color}`
|
|
3985
4195
|
},
|
|
3986
4196
|
children: [
|
|
3987
|
-
/* @__PURE__ */
|
|
3988
|
-
/* @__PURE__ */
|
|
3989
|
-
/* @__PURE__ */
|
|
4197
|
+
/* @__PURE__ */ jsx13("p", { className: "text-sm leading-tight font-medium mb-0", children: node.label_ }),
|
|
4198
|
+
/* @__PURE__ */ jsx13("p", { className: "text-sm leading-tight mb-1", children: node.visual.displayName }),
|
|
4199
|
+
/* @__PURE__ */ jsx13(
|
|
3990
4200
|
"p",
|
|
3991
4201
|
{
|
|
3992
4202
|
className: "text-xs text-muted-foreground cursor-pointer select-all mb-2",
|
|
3993
|
-
onClick: () =>
|
|
4203
|
+
onClick: () => copyTextToClipboard2(String(node.id_)),
|
|
3994
4204
|
title: "Click to copy id",
|
|
3995
4205
|
children: node.id_
|
|
3996
4206
|
}
|
|
3997
4207
|
),
|
|
3998
|
-
/* @__PURE__ */
|
|
3999
|
-
/* @__PURE__ */
|
|
4000
|
-
/* @__PURE__ */
|
|
4208
|
+
/* @__PURE__ */ jsxs12(Collapsible, { open: showProperties, onOpenChange: setShowProperties, children: [
|
|
4209
|
+
/* @__PURE__ */ jsx13(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsx13("button", { className: "text-xs cursor-pointer", children: showProperties ? "Hide" : "Show more" }) }),
|
|
4210
|
+
/* @__PURE__ */ jsx13(CollapsibleContent, { children: /* @__PURE__ */ jsx13("div", { className: "mt-2", children: /* @__PURE__ */ jsx13(PropertyList, { properties: node.properties_ || {}, showHeader: true }) }) })
|
|
4001
4211
|
] })
|
|
4002
4212
|
]
|
|
4003
4213
|
}
|
|
@@ -4006,7 +4216,7 @@ function NodeInfoCard({ node }) {
|
|
|
4006
4216
|
var NodeInfoCard_default = NodeInfoCard;
|
|
4007
4217
|
|
|
4008
4218
|
// src/components/ActionPanel/EdgeInfoCard.tsx
|
|
4009
|
-
import { useState as
|
|
4219
|
+
import { useState as useState9 } from "react";
|
|
4010
4220
|
import {
|
|
4011
4221
|
Card as Card4,
|
|
4012
4222
|
Collapsible as Collapsible2,
|
|
@@ -4015,11 +4225,11 @@ import {
|
|
|
4015
4225
|
PropertyList as PropertyList2
|
|
4016
4226
|
} from "@petrarca/sonnet-ui";
|
|
4017
4227
|
import { ArrowDown } from "lucide-react";
|
|
4018
|
-
import { copyTextToClipboard as
|
|
4019
|
-
import { jsx as
|
|
4228
|
+
import { copyTextToClipboard as copyTextToClipboard3 } from "@petrarca/sonnet-core";
|
|
4229
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4020
4230
|
function EdgeInfoCard({ edge }) {
|
|
4021
|
-
const [showProperties, setShowProperties] =
|
|
4022
|
-
return /* @__PURE__ */
|
|
4231
|
+
const [showProperties, setShowProperties] = useState9(false);
|
|
4232
|
+
return /* @__PURE__ */ jsxs13(
|
|
4023
4233
|
Card4,
|
|
4024
4234
|
{
|
|
4025
4235
|
className: "w-full rounded-lg overflow-hidden bg-muted/30 border shadow-none p-3",
|
|
@@ -4027,22 +4237,22 @@ function EdgeInfoCard({ edge }) {
|
|
|
4027
4237
|
borderLeft: `4px solid ${edge.visual.color}`
|
|
4028
4238
|
},
|
|
4029
4239
|
children: [
|
|
4030
|
-
/* @__PURE__ */
|
|
4031
|
-
/* @__PURE__ */
|
|
4032
|
-
/* @__PURE__ */
|
|
4240
|
+
/* @__PURE__ */ jsxs13("p", { className: "text-sm leading-tight mb-1", children: [
|
|
4241
|
+
/* @__PURE__ */ jsx14(ArrowDown, { className: "inline-block mr-1 opacity-70 align-middle h-3.5 w-3.5" }),
|
|
4242
|
+
/* @__PURE__ */ jsx14("strong", { className: "font-medium align-middle", children: edge.label_ })
|
|
4033
4243
|
] }),
|
|
4034
|
-
edge.id_ && /* @__PURE__ */
|
|
4244
|
+
edge.id_ && /* @__PURE__ */ jsx14(
|
|
4035
4245
|
"p",
|
|
4036
4246
|
{
|
|
4037
4247
|
className: "text-xs text-muted-foreground select-all cursor-pointer mt-1 mb-2",
|
|
4038
4248
|
title: "Click to copy edge id",
|
|
4039
|
-
onClick: () =>
|
|
4249
|
+
onClick: () => copyTextToClipboard3(String(edge.id_)),
|
|
4040
4250
|
children: edge.id_
|
|
4041
4251
|
}
|
|
4042
4252
|
),
|
|
4043
|
-
edge.properties_ && Object.keys(edge.properties_).length > 0 && /* @__PURE__ */
|
|
4044
|
-
/* @__PURE__ */
|
|
4045
|
-
/* @__PURE__ */
|
|
4253
|
+
edge.properties_ && Object.keys(edge.properties_).length > 0 && /* @__PURE__ */ jsxs13(Collapsible2, { open: showProperties, onOpenChange: setShowProperties, children: [
|
|
4254
|
+
/* @__PURE__ */ jsx14(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsx14("button", { className: "text-xs cursor-pointer", children: showProperties ? "Hide" : "Show more" }) }),
|
|
4255
|
+
/* @__PURE__ */ jsx14(CollapsibleContent2, { children: /* @__PURE__ */ jsx14("div", { className: "mt-2", children: /* @__PURE__ */ jsx14(PropertyList2, { properties: edge.properties_ || {}, showHeader: true }) }) })
|
|
4046
4256
|
] })
|
|
4047
4257
|
]
|
|
4048
4258
|
}
|
|
@@ -4054,7 +4264,7 @@ var EdgeInfoCard_default = EdgeInfoCard;
|
|
|
4054
4264
|
import { Badge } from "@petrarca/sonnet-ui";
|
|
4055
4265
|
import { formatNumber, devLog as devLog11 } from "@petrarca/sonnet-core";
|
|
4056
4266
|
import { useMemo as useMemo4 } from "react";
|
|
4057
|
-
import { Fragment as Fragment3, jsx as
|
|
4267
|
+
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4058
4268
|
function computeEdgeToNodeLabels(nodesById, edgesById) {
|
|
4059
4269
|
const mapping = {};
|
|
4060
4270
|
for (const edge of Object.values(edgesById)) {
|
|
@@ -4087,7 +4297,7 @@ function AllToggleBadge({
|
|
|
4087
4297
|
badgeKey
|
|
4088
4298
|
}) {
|
|
4089
4299
|
const bgColor = allDisabled ? colorPalette["faded"] : colorPalette["neutral"];
|
|
4090
|
-
return /* @__PURE__ */
|
|
4300
|
+
return /* @__PURE__ */ jsxs14(
|
|
4091
4301
|
Badge,
|
|
4092
4302
|
{
|
|
4093
4303
|
className: "cursor-pointer text-xs px-2.5 py-0.5",
|
|
@@ -4115,7 +4325,7 @@ function NodeLabelBadges({
|
|
|
4115
4325
|
}) {
|
|
4116
4326
|
return labels.map((label) => {
|
|
4117
4327
|
const bgColor = shown.has(label) ? colorPalette[label] : colorPalette["faded"];
|
|
4118
|
-
return /* @__PURE__ */
|
|
4328
|
+
return /* @__PURE__ */ jsxs14(
|
|
4119
4329
|
Badge,
|
|
4120
4330
|
{
|
|
4121
4331
|
className: "cursor-pointer text-xs px-2.5 py-0.5",
|
|
@@ -4153,7 +4363,7 @@ function EdgeLabelBadges({
|
|
|
4153
4363
|
colorPalette,
|
|
4154
4364
|
"neutral"
|
|
4155
4365
|
);
|
|
4156
|
-
return /* @__PURE__ */
|
|
4366
|
+
return /* @__PURE__ */ jsxs14(
|
|
4157
4367
|
Badge,
|
|
4158
4368
|
{
|
|
4159
4369
|
className: "cursor-pointer text-xs px-2.5 py-0.5",
|
|
@@ -4256,9 +4466,9 @@ function GraphOverview({
|
|
|
4256
4466
|
nodeLabelFilters
|
|
4257
4467
|
);
|
|
4258
4468
|
const handleEdgeToggle = toggleAllEdgeLabelsDisabled;
|
|
4259
|
-
return /* @__PURE__ */
|
|
4260
|
-
/* @__PURE__ */
|
|
4261
|
-
allLabels.length > 0 && /* @__PURE__ */
|
|
4469
|
+
return /* @__PURE__ */ jsxs14(Fragment3, { children: [
|
|
4470
|
+
/* @__PURE__ */ jsx15("p", { className: "mt-2 heading-component", children: "Overview" }),
|
|
4471
|
+
allLabels.length > 0 && /* @__PURE__ */ jsx15("div", { children: buckets.map((bucket) => {
|
|
4262
4472
|
if (bucket.labels.length === 0) return null;
|
|
4263
4473
|
const bucketAllDisabled = isBucketAllOff(
|
|
4264
4474
|
bucket.labels,
|
|
@@ -4270,10 +4480,10 @@ function GraphOverview({
|
|
|
4270
4480
|
shownNodeLabels,
|
|
4271
4481
|
setNodeFilterState
|
|
4272
4482
|
);
|
|
4273
|
-
return /* @__PURE__ */
|
|
4274
|
-
/* @__PURE__ */
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
/* @__PURE__ */
|
|
4483
|
+
return /* @__PURE__ */ jsxs14("div", { className: "mb-2", children: [
|
|
4484
|
+
/* @__PURE__ */ jsx15("p", { className: "heading-meta mb-2", children: bucket.title }),
|
|
4485
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-start gap-2", children: [
|
|
4486
|
+
/* @__PURE__ */ jsx15(
|
|
4277
4487
|
AllToggleBadge,
|
|
4278
4488
|
{
|
|
4279
4489
|
allDisabled: bucketAllDisabled,
|
|
@@ -4283,7 +4493,7 @@ function GraphOverview({
|
|
|
4283
4493
|
badgeKey: `all-${bucket.title}`
|
|
4284
4494
|
}
|
|
4285
4495
|
),
|
|
4286
|
-
/* @__PURE__ */
|
|
4496
|
+
/* @__PURE__ */ jsx15(
|
|
4287
4497
|
NodeLabelBadges,
|
|
4288
4498
|
{
|
|
4289
4499
|
labels: bucket.labels,
|
|
@@ -4301,10 +4511,10 @@ function GraphOverview({
|
|
|
4301
4511
|
] })
|
|
4302
4512
|
] }, bucket.title);
|
|
4303
4513
|
}) }),
|
|
4304
|
-
allEdgeLabels.length > 0 && /* @__PURE__ */
|
|
4305
|
-
/* @__PURE__ */
|
|
4306
|
-
/* @__PURE__ */
|
|
4307
|
-
/* @__PURE__ */
|
|
4514
|
+
allEdgeLabels.length > 0 && /* @__PURE__ */ jsxs14("div", { children: [
|
|
4515
|
+
/* @__PURE__ */ jsx15("p", { className: "heading-meta mb-2", children: edgeSectionTitle }),
|
|
4516
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-start gap-2", children: [
|
|
4517
|
+
/* @__PURE__ */ jsx15(
|
|
4308
4518
|
AllToggleBadge,
|
|
4309
4519
|
{
|
|
4310
4520
|
allDisabled: allEdgeLabelsDisabled,
|
|
@@ -4314,7 +4524,7 @@ function GraphOverview({
|
|
|
4314
4524
|
badgeKey: "edge-all"
|
|
4315
4525
|
}
|
|
4316
4526
|
),
|
|
4317
|
-
/* @__PURE__ */
|
|
4527
|
+
/* @__PURE__ */ jsx15(
|
|
4318
4528
|
EdgeLabelBadges,
|
|
4319
4529
|
{
|
|
4320
4530
|
labels: allEdgeLabels,
|
|
@@ -4340,16 +4550,16 @@ function Overview({ nodeBuckets, edgeSectionTitle } = {}) {
|
|
|
4340
4550
|
);
|
|
4341
4551
|
}, [baseNormalized]);
|
|
4342
4552
|
if (stats && stats.values != null && stats.values > 0) {
|
|
4343
|
-
return /* @__PURE__ */
|
|
4344
|
-
/* @__PURE__ */
|
|
4345
|
-
/* @__PURE__ */
|
|
4553
|
+
return /* @__PURE__ */ jsxs14(Fragment3, { children: [
|
|
4554
|
+
/* @__PURE__ */ jsx15("p", { className: "mt-2 heading-component", children: "Overview" }),
|
|
4555
|
+
/* @__PURE__ */ jsxs14("p", { className: "text-sm text-muted-foreground", children: [
|
|
4346
4556
|
formatNumber(stats.values),
|
|
4347
4557
|
" Values"
|
|
4348
4558
|
] })
|
|
4349
4559
|
] });
|
|
4350
4560
|
}
|
|
4351
4561
|
if (stats && stats.nodes > 0 && colorPalette) {
|
|
4352
|
-
return /* @__PURE__ */
|
|
4562
|
+
return /* @__PURE__ */ jsx15(
|
|
4353
4563
|
GraphOverview,
|
|
4354
4564
|
{
|
|
4355
4565
|
stats,
|
|
@@ -4368,7 +4578,7 @@ var Overview_default = Overview;
|
|
|
4368
4578
|
|
|
4369
4579
|
// src/components/ActionPanel/ActionPanel.tsx
|
|
4370
4580
|
import { useMemo as useMemo5 } from "react";
|
|
4371
|
-
import { jsx as
|
|
4581
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4372
4582
|
function ActionPanel({ actions }) {
|
|
4373
4583
|
const useSelection3 = useWorkspaceSelection();
|
|
4374
4584
|
const selectedNodeIds = useSelection3(
|
|
@@ -4384,18 +4594,18 @@ function ActionPanel({ actions }) {
|
|
|
4384
4594
|
const secondNode = selectedNodes?.[1];
|
|
4385
4595
|
const hasEdge = !!selectedEdge;
|
|
4386
4596
|
const showOverview = !firstNode && !hasEdge;
|
|
4387
|
-
return /* @__PURE__ */
|
|
4597
|
+
return /* @__PURE__ */ jsxs15(
|
|
4388
4598
|
Card5,
|
|
4389
4599
|
{
|
|
4390
4600
|
className: "h-full min-w-64 flex flex-col bg-card shadow-none p-4",
|
|
4391
4601
|
style: { maxHeight: "100%", overflow: "hidden" },
|
|
4392
4602
|
children: [
|
|
4393
|
-
actions && /* @__PURE__ */
|
|
4394
|
-
/* @__PURE__ */
|
|
4395
|
-
firstNode && /* @__PURE__ */
|
|
4396
|
-
hasEdge && selectedEdge && /* @__PURE__ */
|
|
4397
|
-
secondNode && /* @__PURE__ */
|
|
4398
|
-
showOverview && /* @__PURE__ */
|
|
4603
|
+
actions && /* @__PURE__ */ jsx16("div", { className: "flex-shrink-0 mb-2", children: actions }),
|
|
4604
|
+
/* @__PURE__ */ jsx16("div", { className: "flex-1 overflow-auto pr-1", children: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-3", children: [
|
|
4605
|
+
firstNode && /* @__PURE__ */ jsx16(NodeInfoCard_default, { node: firstNode }),
|
|
4606
|
+
hasEdge && selectedEdge && /* @__PURE__ */ jsx16(EdgeInfoCard_default, { edge: selectedEdge }),
|
|
4607
|
+
secondNode && /* @__PURE__ */ jsx16(NodeInfoCard_default, { node: secondNode }),
|
|
4608
|
+
showOverview && /* @__PURE__ */ jsx16(Overview_default, {})
|
|
4399
4609
|
] }) })
|
|
4400
4610
|
]
|
|
4401
4611
|
}
|
|
@@ -4404,10 +4614,10 @@ function ActionPanel({ actions }) {
|
|
|
4404
4614
|
var ActionPanel_default = ActionPanel;
|
|
4405
4615
|
|
|
4406
4616
|
// src/components/GraphA11yList/GraphA11yList.tsx
|
|
4407
|
-
import { useCallback as
|
|
4617
|
+
import { useCallback as useCallback7, useMemo as useMemo6, useRef as useRef6 } from "react";
|
|
4408
4618
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
4409
4619
|
import { cn as cn2 } from "@petrarca/sonnet-core";
|
|
4410
|
-
import { jsx as
|
|
4620
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
4411
4621
|
var SR_ONLY = "absolute h-px w-px overflow-hidden whitespace-nowrap border-0 p-0 [clip:rect(0,0,0,0)] [clip-path:inset(50%)] -m-px";
|
|
4412
4622
|
function GraphA11yList({
|
|
4413
4623
|
visible = false,
|
|
@@ -4442,14 +4652,14 @@ function GraphA11yList({
|
|
|
4442
4652
|
}));
|
|
4443
4653
|
return [...nodeRows, ...edgeRows];
|
|
4444
4654
|
}, [live.nodes, live.edges]);
|
|
4445
|
-
const parentRef =
|
|
4655
|
+
const parentRef = useRef6(null);
|
|
4446
4656
|
const virtualizer = useVirtualizer({
|
|
4447
4657
|
count: rows.length,
|
|
4448
4658
|
getScrollElement: () => parentRef.current,
|
|
4449
4659
|
estimateSize: () => rowHeight,
|
|
4450
4660
|
overscan: 8
|
|
4451
4661
|
});
|
|
4452
|
-
const activateNode =
|
|
4662
|
+
const activateNode = useCallback7(
|
|
4453
4663
|
(id, additive) => {
|
|
4454
4664
|
setSelectedEdge(null);
|
|
4455
4665
|
if (!additive) {
|
|
@@ -4464,7 +4674,7 @@ function GraphA11yList({
|
|
|
4464
4674
|
},
|
|
4465
4675
|
[selectedNodeIds, setSelectedNodeIds, setSelectedEdge]
|
|
4466
4676
|
);
|
|
4467
|
-
const selectRow =
|
|
4677
|
+
const selectRow = useCallback7(
|
|
4468
4678
|
(row, e) => {
|
|
4469
4679
|
if (row.kind === "node") {
|
|
4470
4680
|
activateNode(row.id, e.metaKey || e.ctrlKey || e.shiftKey);
|
|
@@ -4476,19 +4686,19 @@ function GraphA11yList({
|
|
|
4476
4686
|
[activateNode, setSelectedNodeIds, setSelectedEdge]
|
|
4477
4687
|
);
|
|
4478
4688
|
const isSelected = (row) => row.kind === "node" ? selectedNodeIds.includes(row.id) : selectedEdge?.id_ === row.edge.id_;
|
|
4479
|
-
return /* @__PURE__ */
|
|
4689
|
+
return /* @__PURE__ */ jsx17(
|
|
4480
4690
|
"div",
|
|
4481
4691
|
{
|
|
4482
4692
|
role: "listbox",
|
|
4483
4693
|
"aria-label": "Graph elements",
|
|
4484
4694
|
"aria-multiselectable": true,
|
|
4485
4695
|
className: cn2(visible ? "rounded-md border" : SR_ONLY, className),
|
|
4486
|
-
children: /* @__PURE__ */
|
|
4696
|
+
children: /* @__PURE__ */ jsx17(
|
|
4487
4697
|
"div",
|
|
4488
4698
|
{
|
|
4489
4699
|
ref: parentRef,
|
|
4490
4700
|
style: { maxHeight: visible ? maxHeight : void 0, overflow: "auto" },
|
|
4491
|
-
children: /* @__PURE__ */
|
|
4701
|
+
children: /* @__PURE__ */ jsx17(
|
|
4492
4702
|
"div",
|
|
4493
4703
|
{
|
|
4494
4704
|
style: {
|
|
@@ -4500,7 +4710,7 @@ function GraphA11yList({
|
|
|
4500
4710
|
const row = rows[vi.index];
|
|
4501
4711
|
if (!row) return null;
|
|
4502
4712
|
const selected = isSelected(row);
|
|
4503
|
-
return /* @__PURE__ */
|
|
4713
|
+
return /* @__PURE__ */ jsx17(
|
|
4504
4714
|
"button",
|
|
4505
4715
|
{
|
|
4506
4716
|
type: "button",
|
|
@@ -4518,7 +4728,7 @@ function GraphA11yList({
|
|
|
4518
4728
|
height: `${vi.size}px`,
|
|
4519
4729
|
transform: `translateY(${vi.start}px)`
|
|
4520
4730
|
},
|
|
4521
|
-
children: /* @__PURE__ */
|
|
4731
|
+
children: /* @__PURE__ */ jsx17("span", { className: "truncate", children: row.label })
|
|
4522
4732
|
},
|
|
4523
4733
|
vi.key
|
|
4524
4734
|
);
|
|
@@ -4656,16 +4866,16 @@ function reconcileFilter(current, model, baselineReset, showEdgeTypes) {
|
|
|
4656
4866
|
}
|
|
4657
4867
|
|
|
4658
4868
|
// src/graph-model/GraphModelEditor.tsx
|
|
4659
|
-
import { useCallback as
|
|
4869
|
+
import { useCallback as useCallback8, useEffect as useEffect6, useRef as useRef7, useState as useState14 } from "react";
|
|
4660
4870
|
import { ResizeHandle } from "@petrarca/sonnet-ui";
|
|
4661
4871
|
|
|
4662
4872
|
// src/graph-model/ModelActionPanel.tsx
|
|
4663
|
-
import { useMemo as useMemo8, useState as
|
|
4664
|
-
import { Button as
|
|
4873
|
+
import { useMemo as useMemo8, useState as useState13 } from "react";
|
|
4874
|
+
import { Button as Button8, IconButton as IconButton2 } from "@petrarca/sonnet-ui";
|
|
4665
4875
|
import { GitBranchPlus, CirclePlus, Waypoints } from "lucide-react";
|
|
4666
4876
|
|
|
4667
4877
|
// src/graph-model/TypeDetailPanel.tsx
|
|
4668
|
-
import { useState as
|
|
4878
|
+
import { useState as useState12 } from "react";
|
|
4669
4879
|
import { Badge as Badge2, IconButton } from "@petrarca/sonnet-ui";
|
|
4670
4880
|
import { Plus, Pencil, Trash2 } from "lucide-react";
|
|
4671
4881
|
|
|
@@ -4985,7 +5195,7 @@ import {
|
|
|
4985
5195
|
SheetDescription
|
|
4986
5196
|
} from "@petrarca/sonnet-ui";
|
|
4987
5197
|
import { JsonSchemaFormRenderer } from "@petrarca/sonnet-forms";
|
|
4988
|
-
import { jsx as
|
|
5198
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4989
5199
|
var TYPE_OPTIONS = [
|
|
4990
5200
|
"string",
|
|
4991
5201
|
"integer",
|
|
@@ -5075,18 +5285,18 @@ function PropertyFormSheet({
|
|
|
5075
5285
|
const schema = useMemo7(() => buildSchema(widgets), [widgets]);
|
|
5076
5286
|
const data = useMemo7(() => toFormData(property), [property]);
|
|
5077
5287
|
const isEdit = !!property;
|
|
5078
|
-
return /* @__PURE__ */
|
|
5079
|
-
/* @__PURE__ */
|
|
5080
|
-
/* @__PURE__ */
|
|
5288
|
+
return /* @__PURE__ */ jsx18(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs16(SheetContent, { children: [
|
|
5289
|
+
/* @__PURE__ */ jsxs16(SheetHeader, { children: [
|
|
5290
|
+
/* @__PURE__ */ jsxs16(SheetTitle, { children: [
|
|
5081
5291
|
isEdit ? "Edit property" : "Add property",
|
|
5082
5292
|
" ",
|
|
5083
5293
|
"\u2014",
|
|
5084
5294
|
" ",
|
|
5085
5295
|
ownerLabel
|
|
5086
5296
|
] }),
|
|
5087
|
-
/* @__PURE__ */
|
|
5297
|
+
/* @__PURE__ */ jsx18(SheetDescription, { children: "Define the property and how it is rendered." })
|
|
5088
5298
|
] }),
|
|
5089
|
-
/* @__PURE__ */
|
|
5299
|
+
/* @__PURE__ */ jsx18(SheetBody, { children: /* @__PURE__ */ jsx18(
|
|
5090
5300
|
JsonSchemaFormRenderer,
|
|
5091
5301
|
{
|
|
5092
5302
|
schema,
|
|
@@ -5105,7 +5315,7 @@ function PropertyFormSheet({
|
|
|
5105
5315
|
}
|
|
5106
5316
|
|
|
5107
5317
|
// src/graph-model/RelationFormSheet.tsx
|
|
5108
|
-
import { useState as
|
|
5318
|
+
import { useState as useState10 } from "react";
|
|
5109
5319
|
import {
|
|
5110
5320
|
Sheet as Sheet2,
|
|
5111
5321
|
SheetContent as SheetContent2,
|
|
@@ -5113,11 +5323,11 @@ import {
|
|
|
5113
5323
|
SheetBody as SheetBody2,
|
|
5114
5324
|
SheetTitle as SheetTitle2,
|
|
5115
5325
|
SheetDescription as SheetDescription2,
|
|
5116
|
-
Button as
|
|
5326
|
+
Button as Button6
|
|
5117
5327
|
} from "@petrarca/sonnet-ui";
|
|
5118
5328
|
import { FormSelect } from "@petrarca/sonnet-forms";
|
|
5119
5329
|
import { ArrowRight } from "lucide-react";
|
|
5120
|
-
import { jsx as
|
|
5330
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
5121
5331
|
var CARDINALITIES = ["ONE_TO_MANY", "ONE_TO_ONE"];
|
|
5122
5332
|
function RelationTypeField({
|
|
5123
5333
|
relType,
|
|
@@ -5130,7 +5340,7 @@ function RelationTypeField({
|
|
|
5130
5340
|
);
|
|
5131
5341
|
const options = labels.map((l) => ({ value: l, label: l }));
|
|
5132
5342
|
const canCreate = edgeTypeMode === "edit";
|
|
5133
|
-
return /* @__PURE__ */
|
|
5343
|
+
return /* @__PURE__ */ jsx19(
|
|
5134
5344
|
FormSelect,
|
|
5135
5345
|
{
|
|
5136
5346
|
label: "Relation type",
|
|
@@ -5152,14 +5362,14 @@ function DirectionField({
|
|
|
5152
5362
|
canSwap,
|
|
5153
5363
|
onSwap
|
|
5154
5364
|
}) {
|
|
5155
|
-
return /* @__PURE__ */
|
|
5156
|
-
/* @__PURE__ */
|
|
5157
|
-
/* @__PURE__ */
|
|
5158
|
-
/* @__PURE__ */
|
|
5159
|
-
/* @__PURE__ */
|
|
5160
|
-
/* @__PURE__ */
|
|
5161
|
-
canSwap && /* @__PURE__ */
|
|
5162
|
-
|
|
5365
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
5366
|
+
/* @__PURE__ */ jsx19("label", { className: "mb-1 block text-xs font-medium", children: "Direction" }),
|
|
5367
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
5368
|
+
/* @__PURE__ */ jsx19("span", { className: "font-medium", children: source }),
|
|
5369
|
+
/* @__PURE__ */ jsx19(ArrowRight, { className: "h-4 w-4 text-muted-foreground" }),
|
|
5370
|
+
/* @__PURE__ */ jsx19("span", { className: "font-medium", children: target }),
|
|
5371
|
+
canSwap && /* @__PURE__ */ jsx19(
|
|
5372
|
+
Button6,
|
|
5163
5373
|
{
|
|
5164
5374
|
variant: "ghost",
|
|
5165
5375
|
size: "sm",
|
|
@@ -5175,10 +5385,10 @@ function CardinalityField({
|
|
|
5175
5385
|
cardinality,
|
|
5176
5386
|
onChange
|
|
5177
5387
|
}) {
|
|
5178
|
-
return /* @__PURE__ */
|
|
5179
|
-
/* @__PURE__ */
|
|
5180
|
-
/* @__PURE__ */
|
|
5181
|
-
|
|
5388
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
5389
|
+
/* @__PURE__ */ jsx19("label", { className: "mb-1 block text-xs font-medium", children: "Cardinality" }),
|
|
5390
|
+
/* @__PURE__ */ jsx19("div", { className: "flex gap-2", children: CARDINALITIES.map((c) => /* @__PURE__ */ jsx19(
|
|
5391
|
+
Button6,
|
|
5182
5392
|
{
|
|
5183
5393
|
variant: c === cardinality ? "default" : "outline",
|
|
5184
5394
|
size: "sm",
|
|
@@ -5199,9 +5409,9 @@ function RelationFormSheet({
|
|
|
5199
5409
|
edgeTypeMode = "edit",
|
|
5200
5410
|
onSave
|
|
5201
5411
|
}) {
|
|
5202
|
-
const [relType, setRelType] =
|
|
5203
|
-
const [swapped, setSwapped] =
|
|
5204
|
-
const [cardinality, setCardinality] =
|
|
5412
|
+
const [relType, setRelType] = useState10(initial?.relType ?? "");
|
|
5413
|
+
const [swapped, setSwapped] = useState10(false);
|
|
5414
|
+
const [cardinality, setCardinality] = useState10(
|
|
5205
5415
|
initial?.cardinality ?? "ONE_TO_MANY"
|
|
5206
5416
|
);
|
|
5207
5417
|
const source = swapped ? nodeB : nodeA;
|
|
@@ -5217,13 +5427,13 @@ function RelationFormSheet({
|
|
|
5217
5427
|
});
|
|
5218
5428
|
onOpenChange(false);
|
|
5219
5429
|
};
|
|
5220
|
-
return /* @__PURE__ */
|
|
5221
|
-
/* @__PURE__ */
|
|
5222
|
-
/* @__PURE__ */
|
|
5223
|
-
/* @__PURE__ */
|
|
5430
|
+
return /* @__PURE__ */ jsx19(Sheet2, { open, onOpenChange, children: /* @__PURE__ */ jsxs17(SheetContent2, { children: [
|
|
5431
|
+
/* @__PURE__ */ jsxs17(SheetHeader2, { children: [
|
|
5432
|
+
/* @__PURE__ */ jsx19(SheetTitle2, { children: isEdit ? "Edit relation" : "Create relation" }),
|
|
5433
|
+
/* @__PURE__ */ jsx19(SheetDescription2, { children: "A relation is stored on the source node type." })
|
|
5224
5434
|
] }),
|
|
5225
|
-
/* @__PURE__ */
|
|
5226
|
-
/* @__PURE__ */
|
|
5435
|
+
/* @__PURE__ */ jsxs17(SheetBody2, { className: "flex flex-col gap-4", children: [
|
|
5436
|
+
/* @__PURE__ */ jsx19(
|
|
5227
5437
|
RelationTypeField,
|
|
5228
5438
|
{
|
|
5229
5439
|
relType,
|
|
@@ -5232,7 +5442,7 @@ function RelationFormSheet({
|
|
|
5232
5442
|
edgeTypeMode
|
|
5233
5443
|
}
|
|
5234
5444
|
),
|
|
5235
|
-
/* @__PURE__ */
|
|
5445
|
+
/* @__PURE__ */ jsx19(
|
|
5236
5446
|
DirectionField,
|
|
5237
5447
|
{
|
|
5238
5448
|
source,
|
|
@@ -5241,23 +5451,23 @@ function RelationFormSheet({
|
|
|
5241
5451
|
onSwap: () => setSwapped((s) => !s)
|
|
5242
5452
|
}
|
|
5243
5453
|
),
|
|
5244
|
-
/* @__PURE__ */
|
|
5454
|
+
/* @__PURE__ */ jsx19(
|
|
5245
5455
|
CardinalityField,
|
|
5246
5456
|
{
|
|
5247
5457
|
cardinality,
|
|
5248
5458
|
onChange: setCardinality
|
|
5249
5459
|
}
|
|
5250
5460
|
),
|
|
5251
|
-
/* @__PURE__ */
|
|
5252
|
-
/* @__PURE__ */
|
|
5253
|
-
/* @__PURE__ */
|
|
5461
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex justify-end gap-2 pt-2", children: [
|
|
5462
|
+
/* @__PURE__ */ jsx19(Button6, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
5463
|
+
/* @__PURE__ */ jsx19(Button6, { disabled: !canSave, onClick: handleSave, children: isEdit ? "Save" : "Create relation" })
|
|
5254
5464
|
] })
|
|
5255
5465
|
] })
|
|
5256
5466
|
] }) });
|
|
5257
5467
|
}
|
|
5258
5468
|
|
|
5259
5469
|
// src/graph-model/NodeTypeNameSheet.tsx
|
|
5260
|
-
import { useState as
|
|
5470
|
+
import { useState as useState11 } from "react";
|
|
5261
5471
|
import {
|
|
5262
5472
|
Sheet as Sheet3,
|
|
5263
5473
|
SheetContent as SheetContent3,
|
|
@@ -5265,10 +5475,10 @@ import {
|
|
|
5265
5475
|
SheetBody as SheetBody3,
|
|
5266
5476
|
SheetTitle as SheetTitle3,
|
|
5267
5477
|
SheetDescription as SheetDescription3,
|
|
5268
|
-
Button as
|
|
5478
|
+
Button as Button7,
|
|
5269
5479
|
Input as Input2
|
|
5270
5480
|
} from "@petrarca/sonnet-ui";
|
|
5271
|
-
import { jsx as
|
|
5481
|
+
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
5272
5482
|
function NodeTypeNameSheet({
|
|
5273
5483
|
open,
|
|
5274
5484
|
onOpenChange,
|
|
@@ -5277,21 +5487,21 @@ function NodeTypeNameSheet({
|
|
|
5277
5487
|
noun = "node",
|
|
5278
5488
|
onSave
|
|
5279
5489
|
}) {
|
|
5280
|
-
const [name, setName] =
|
|
5490
|
+
const [name, setName] = useState11(initial ?? "");
|
|
5281
5491
|
const isEdit = initial !== void 0;
|
|
5282
5492
|
const trimmed = name.trim();
|
|
5283
5493
|
const duplicate = trimmed !== initial && existing.includes(trimmed);
|
|
5284
5494
|
const canSave = trimmed.length > 0 && !duplicate;
|
|
5285
5495
|
const typeNoun = noun === "edge" ? "edge type" : "node type";
|
|
5286
|
-
return /* @__PURE__ */
|
|
5287
|
-
/* @__PURE__ */
|
|
5288
|
-
/* @__PURE__ */
|
|
5289
|
-
/* @__PURE__ */
|
|
5496
|
+
return /* @__PURE__ */ jsx20(Sheet3, { open, onOpenChange, children: /* @__PURE__ */ jsxs18(SheetContent3, { children: [
|
|
5497
|
+
/* @__PURE__ */ jsxs18(SheetHeader3, { children: [
|
|
5498
|
+
/* @__PURE__ */ jsx20(SheetTitle3, { children: isEdit ? `Rename ${typeNoun}` : `Add ${typeNoun}` }),
|
|
5499
|
+
/* @__PURE__ */ jsx20(SheetDescription3, { children: "The label identifies this type and its instances." })
|
|
5290
5500
|
] }),
|
|
5291
|
-
/* @__PURE__ */
|
|
5292
|
-
/* @__PURE__ */
|
|
5293
|
-
/* @__PURE__ */
|
|
5294
|
-
/* @__PURE__ */
|
|
5501
|
+
/* @__PURE__ */ jsxs18(SheetBody3, { className: "flex flex-col gap-4", children: [
|
|
5502
|
+
/* @__PURE__ */ jsxs18("div", { children: [
|
|
5503
|
+
/* @__PURE__ */ jsx20("label", { className: "mb-1 block text-xs font-medium", children: "Label" }),
|
|
5504
|
+
/* @__PURE__ */ jsx20(
|
|
5295
5505
|
Input2,
|
|
5296
5506
|
{
|
|
5297
5507
|
value: name,
|
|
@@ -5300,12 +5510,12 @@ function NodeTypeNameSheet({
|
|
|
5300
5510
|
autoFocus: true
|
|
5301
5511
|
}
|
|
5302
5512
|
),
|
|
5303
|
-
duplicate && /* @__PURE__ */
|
|
5513
|
+
duplicate && /* @__PURE__ */ jsx20("p", { className: "mt-1 text-xs text-destructive", children: "A type with this label already exists." })
|
|
5304
5514
|
] }),
|
|
5305
|
-
/* @__PURE__ */
|
|
5306
|
-
/* @__PURE__ */
|
|
5307
|
-
/* @__PURE__ */
|
|
5308
|
-
|
|
5515
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex justify-end gap-2", children: [
|
|
5516
|
+
/* @__PURE__ */ jsx20(Button7, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
5517
|
+
/* @__PURE__ */ jsx20(
|
|
5518
|
+
Button7,
|
|
5309
5519
|
{
|
|
5310
5520
|
disabled: !canSave,
|
|
5311
5521
|
onClick: () => {
|
|
@@ -5321,7 +5531,7 @@ function NodeTypeNameSheet({
|
|
|
5321
5531
|
}
|
|
5322
5532
|
|
|
5323
5533
|
// src/graph-model/TypeDetailPanel.tsx
|
|
5324
|
-
import { Fragment as Fragment4, jsx as
|
|
5534
|
+
import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
5325
5535
|
function relationViewOf(view) {
|
|
5326
5536
|
return {
|
|
5327
5537
|
relType: view.relType,
|
|
@@ -5334,9 +5544,9 @@ function SectionTitle({
|
|
|
5334
5544
|
children,
|
|
5335
5545
|
action
|
|
5336
5546
|
}) {
|
|
5337
|
-
return /* @__PURE__ */
|
|
5338
|
-
/* @__PURE__ */
|
|
5339
|
-
action && /* @__PURE__ */
|
|
5547
|
+
return /* @__PURE__ */ jsxs19("div", { className: "mt-4 mb-2 flex items-center gap-2", children: [
|
|
5548
|
+
/* @__PURE__ */ jsx21("span", { className: "heading-meta", children }),
|
|
5549
|
+
action && /* @__PURE__ */ jsx21("span", { className: "ml-auto", children: action })
|
|
5340
5550
|
] });
|
|
5341
5551
|
}
|
|
5342
5552
|
function PropertyRows({
|
|
@@ -5347,37 +5557,37 @@ function PropertyRows({
|
|
|
5347
5557
|
onDelete
|
|
5348
5558
|
}) {
|
|
5349
5559
|
if (properties.length === 0) {
|
|
5350
|
-
return /* @__PURE__ */
|
|
5560
|
+
return /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: emptyText });
|
|
5351
5561
|
}
|
|
5352
|
-
return /* @__PURE__ */
|
|
5562
|
+
return /* @__PURE__ */ jsx21("div", { className: "rounded-lg border divide-y", children: properties.map((p) => /* @__PURE__ */ jsxs19(
|
|
5353
5563
|
"div",
|
|
5354
5564
|
{
|
|
5355
5565
|
className: "group/row flex items-center gap-2 px-3 py-2",
|
|
5356
5566
|
children: [
|
|
5357
|
-
/* @__PURE__ */
|
|
5358
|
-
/* @__PURE__ */
|
|
5567
|
+
/* @__PURE__ */ jsx21("span", { className: "text-sm font-medium min-w-24", children: p.name }),
|
|
5568
|
+
/* @__PURE__ */ jsxs19("span", { className: "flex-1 font-mono text-xs text-muted-foreground", children: [
|
|
5359
5569
|
p.type,
|
|
5360
5570
|
p.widget ? ` \xB7 ${p.widget}` : ""
|
|
5361
5571
|
] }),
|
|
5362
|
-
p.required && /* @__PURE__ */
|
|
5363
|
-
editable && /* @__PURE__ */
|
|
5364
|
-
/* @__PURE__ */
|
|
5572
|
+
p.required && /* @__PURE__ */ jsx21(Badge2, { badgeColor: "orange", children: "required" }),
|
|
5573
|
+
editable && /* @__PURE__ */ jsxs19("span", { className: "flex gap-1", children: [
|
|
5574
|
+
/* @__PURE__ */ jsx21(
|
|
5365
5575
|
IconButton,
|
|
5366
5576
|
{
|
|
5367
5577
|
label: "Edit property",
|
|
5368
5578
|
revealOnHover: true,
|
|
5369
5579
|
onClick: () => onEdit(p),
|
|
5370
|
-
children: /* @__PURE__ */
|
|
5580
|
+
children: /* @__PURE__ */ jsx21(Pencil, {})
|
|
5371
5581
|
}
|
|
5372
5582
|
),
|
|
5373
|
-
/* @__PURE__ */
|
|
5583
|
+
/* @__PURE__ */ jsx21(
|
|
5374
5584
|
IconButton,
|
|
5375
5585
|
{
|
|
5376
5586
|
label: "Delete property",
|
|
5377
5587
|
tone: "destructive",
|
|
5378
5588
|
revealOnHover: true,
|
|
5379
5589
|
onClick: () => onDelete(p),
|
|
5380
|
-
children: /* @__PURE__ */
|
|
5590
|
+
children: /* @__PURE__ */ jsx21(Trash2, {})
|
|
5381
5591
|
}
|
|
5382
5592
|
)
|
|
5383
5593
|
] })
|
|
@@ -5431,9 +5641,9 @@ function TypeDetailPanel({
|
|
|
5431
5641
|
capabilities,
|
|
5432
5642
|
widgetOptions
|
|
5433
5643
|
}) {
|
|
5434
|
-
const [sheet, setSheet] =
|
|
5435
|
-
const [relSheet, setRelSheet] =
|
|
5436
|
-
const [renameOpen, setRenameOpen] =
|
|
5644
|
+
const [sheet, setSheet] = useState12({ open: false });
|
|
5645
|
+
const [relSheet, setRelSheet] = useState12(null);
|
|
5646
|
+
const [renameOpen, setRenameOpen] = useState12(false);
|
|
5437
5647
|
const view = resolveView(model, selection);
|
|
5438
5648
|
if (!view) return null;
|
|
5439
5649
|
const editable = !readOnly && !!onChange;
|
|
@@ -5460,7 +5670,7 @@ function TypeDetailPanel({
|
|
|
5460
5670
|
if (!onChange) return;
|
|
5461
5671
|
onChange(updateRelation(model, source, prev.relType, prev.target, input));
|
|
5462
5672
|
};
|
|
5463
|
-
const propertiesSection = propsHidden ? null : /* @__PURE__ */
|
|
5673
|
+
const propertiesSection = propsHidden ? null : /* @__PURE__ */ jsx21(
|
|
5464
5674
|
PropertiesSection,
|
|
5465
5675
|
{
|
|
5466
5676
|
view,
|
|
@@ -5470,8 +5680,8 @@ function TypeDetailPanel({
|
|
|
5470
5680
|
onDelete: removeProperty
|
|
5471
5681
|
}
|
|
5472
5682
|
);
|
|
5473
|
-
return /* @__PURE__ */
|
|
5474
|
-
view.kind === "node" ? /* @__PURE__ */
|
|
5683
|
+
return /* @__PURE__ */ jsxs19("div", { children: [
|
|
5684
|
+
view.kind === "node" ? /* @__PURE__ */ jsx21(
|
|
5475
5685
|
NodeDetail,
|
|
5476
5686
|
{
|
|
5477
5687
|
view,
|
|
@@ -5483,7 +5693,7 @@ function TypeDetailPanel({
|
|
|
5483
5693
|
onDeleteRelation: removeRelation,
|
|
5484
5694
|
children: propertiesSection
|
|
5485
5695
|
}
|
|
5486
|
-
) : view.kind === "edge" ? /* @__PURE__ */
|
|
5696
|
+
) : view.kind === "edge" ? /* @__PURE__ */ jsx21(
|
|
5487
5697
|
EdgeDetail,
|
|
5488
5698
|
{
|
|
5489
5699
|
view,
|
|
@@ -5492,7 +5702,7 @@ function TypeDetailPanel({
|
|
|
5492
5702
|
onDelete: () => onChange?.(deleteEdgeType(model, view.label)),
|
|
5493
5703
|
children: propertiesSection
|
|
5494
5704
|
}
|
|
5495
|
-
) : /* @__PURE__ */
|
|
5705
|
+
) : /* @__PURE__ */ jsx21(
|
|
5496
5706
|
RelationDetail,
|
|
5497
5707
|
{
|
|
5498
5708
|
view,
|
|
@@ -5502,7 +5712,7 @@ function TypeDetailPanel({
|
|
|
5502
5712
|
children: propertiesSection
|
|
5503
5713
|
}
|
|
5504
5714
|
),
|
|
5505
|
-
editable && /* @__PURE__ */
|
|
5715
|
+
editable && /* @__PURE__ */ jsx21(
|
|
5506
5716
|
DetailSheets,
|
|
5507
5717
|
{
|
|
5508
5718
|
model,
|
|
@@ -5546,8 +5756,8 @@ function DetailSheets({
|
|
|
5546
5756
|
onRename
|
|
5547
5757
|
}) {
|
|
5548
5758
|
const edgeTypeOptions = model.filter(isEdgeType).map(typeLabel);
|
|
5549
|
-
return /* @__PURE__ */
|
|
5550
|
-
/* @__PURE__ */
|
|
5759
|
+
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5760
|
+
/* @__PURE__ */ jsx21(
|
|
5551
5761
|
PropertyFormSheet,
|
|
5552
5762
|
{
|
|
5553
5763
|
open: sheet.open,
|
|
@@ -5558,7 +5768,7 @@ function DetailSheets({
|
|
|
5558
5768
|
onSave: onSaveProperty
|
|
5559
5769
|
}
|
|
5560
5770
|
),
|
|
5561
|
-
relSheet && (view.kind === "node" || view.kind === "relation") && /* @__PURE__ */
|
|
5771
|
+
relSheet && (view.kind === "node" || view.kind === "relation") && /* @__PURE__ */ jsx21(
|
|
5562
5772
|
RelationFormSheet,
|
|
5563
5773
|
{
|
|
5564
5774
|
open: !!relSheet,
|
|
@@ -5575,7 +5785,7 @@ function DetailSheets({
|
|
|
5575
5785
|
},
|
|
5576
5786
|
`${relSheet.relType}:${relSheet.target}`
|
|
5577
5787
|
),
|
|
5578
|
-
(view.kind === "node" || view.kind === "edge") && renameOpen && /* @__PURE__ */
|
|
5788
|
+
(view.kind === "node" || view.kind === "edge") && renameOpen && /* @__PURE__ */ jsx21(
|
|
5579
5789
|
NodeTypeNameSheet,
|
|
5580
5790
|
{
|
|
5581
5791
|
open: renameOpen,
|
|
@@ -5596,15 +5806,15 @@ function PropertiesSection({
|
|
|
5596
5806
|
onEdit,
|
|
5597
5807
|
onDelete
|
|
5598
5808
|
}) {
|
|
5599
|
-
return /* @__PURE__ */
|
|
5600
|
-
/* @__PURE__ */
|
|
5809
|
+
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5810
|
+
/* @__PURE__ */ jsx21(
|
|
5601
5811
|
SectionTitle,
|
|
5602
5812
|
{
|
|
5603
|
-
action: editable ? /* @__PURE__ */
|
|
5813
|
+
action: editable ? /* @__PURE__ */ jsx21(IconButton, { label: "Add property", onClick: onAdd, children: /* @__PURE__ */ jsx21(Plus, {}) }) : void 0,
|
|
5604
5814
|
children: "Properties"
|
|
5605
5815
|
}
|
|
5606
5816
|
),
|
|
5607
|
-
/* @__PURE__ */
|
|
5817
|
+
/* @__PURE__ */ jsx21(
|
|
5608
5818
|
PropertyRows,
|
|
5609
5819
|
{
|
|
5610
5820
|
properties: view.properties,
|
|
@@ -5626,11 +5836,11 @@ function NodeDetail({
|
|
|
5626
5836
|
onDeleteRelation,
|
|
5627
5837
|
children
|
|
5628
5838
|
}) {
|
|
5629
|
-
return /* @__PURE__ */
|
|
5630
|
-
/* @__PURE__ */
|
|
5631
|
-
/* @__PURE__ */
|
|
5632
|
-
/* @__PURE__ */
|
|
5633
|
-
nodeTypeEditable && /* @__PURE__ */
|
|
5839
|
+
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5840
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
5841
|
+
/* @__PURE__ */ jsx21("span", { className: "text-base font-semibold", children: view.label }),
|
|
5842
|
+
/* @__PURE__ */ jsx21(Badge2, { children: "NODE TYPE" }),
|
|
5843
|
+
nodeTypeEditable && /* @__PURE__ */ jsx21(
|
|
5634
5844
|
RenameDeleteActions,
|
|
5635
5845
|
{
|
|
5636
5846
|
noun: "node type",
|
|
@@ -5639,16 +5849,16 @@ function NodeDetail({
|
|
|
5639
5849
|
}
|
|
5640
5850
|
)
|
|
5641
5851
|
] }),
|
|
5642
|
-
view.description && /* @__PURE__ */
|
|
5852
|
+
view.description && /* @__PURE__ */ jsx21("p", { className: "mt-1 text-sm text-muted-foreground", children: view.description }),
|
|
5643
5853
|
children,
|
|
5644
|
-
/* @__PURE__ */
|
|
5645
|
-
view.relations.length === 0 ? /* @__PURE__ */
|
|
5854
|
+
/* @__PURE__ */ jsx21(SectionTitle, { children: "Relations" }),
|
|
5855
|
+
view.relations.length === 0 ? /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: "No relations." }) : /* @__PURE__ */ jsx21("div", { className: "rounded-lg border divide-y", children: view.relations.map((r) => /* @__PURE__ */ jsxs19(
|
|
5646
5856
|
"div",
|
|
5647
5857
|
{
|
|
5648
5858
|
className: "group/row flex items-center gap-2 px-3 py-2",
|
|
5649
5859
|
children: [
|
|
5650
|
-
/* @__PURE__ */
|
|
5651
|
-
/* @__PURE__ */
|
|
5860
|
+
/* @__PURE__ */ jsx21("span", { className: "text-sm font-medium min-w-24", children: r.relType }),
|
|
5861
|
+
/* @__PURE__ */ jsxs19("span", { className: "flex-1 font-mono text-xs text-muted-foreground", children: [
|
|
5652
5862
|
"\u2192",
|
|
5653
5863
|
" ",
|
|
5654
5864
|
r.target,
|
|
@@ -5657,24 +5867,24 @@ function NodeDetail({
|
|
|
5657
5867
|
" ",
|
|
5658
5868
|
cardinalityLabel(r.cardinality)
|
|
5659
5869
|
] }),
|
|
5660
|
-
relationsEditable && /* @__PURE__ */
|
|
5661
|
-
/* @__PURE__ */
|
|
5870
|
+
relationsEditable && /* @__PURE__ */ jsxs19("span", { className: "flex gap-1", children: [
|
|
5871
|
+
/* @__PURE__ */ jsx21(
|
|
5662
5872
|
IconButton,
|
|
5663
5873
|
{
|
|
5664
5874
|
label: "Edit relation",
|
|
5665
5875
|
revealOnHover: true,
|
|
5666
5876
|
onClick: () => onEditRelation(r),
|
|
5667
|
-
children: /* @__PURE__ */
|
|
5877
|
+
children: /* @__PURE__ */ jsx21(Pencil, {})
|
|
5668
5878
|
}
|
|
5669
5879
|
),
|
|
5670
|
-
/* @__PURE__ */
|
|
5880
|
+
/* @__PURE__ */ jsx21(
|
|
5671
5881
|
IconButton,
|
|
5672
5882
|
{
|
|
5673
5883
|
label: "Delete relation",
|
|
5674
5884
|
tone: "destructive",
|
|
5675
5885
|
revealOnHover: true,
|
|
5676
5886
|
onClick: () => onDeleteRelation(r),
|
|
5677
|
-
children: /* @__PURE__ */
|
|
5887
|
+
children: /* @__PURE__ */ jsx21(Trash2, {})
|
|
5678
5888
|
}
|
|
5679
5889
|
)
|
|
5680
5890
|
] })
|
|
@@ -5687,7 +5897,7 @@ function NodeDetail({
|
|
|
5687
5897
|
function EdgeTypeNote({
|
|
5688
5898
|
children
|
|
5689
5899
|
}) {
|
|
5690
|
-
return /* @__PURE__ */
|
|
5900
|
+
return /* @__PURE__ */ jsx21("p", { className: "mt-3 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground", children });
|
|
5691
5901
|
}
|
|
5692
5902
|
function RenameDeleteActions({
|
|
5693
5903
|
noun,
|
|
@@ -5695,15 +5905,15 @@ function RenameDeleteActions({
|
|
|
5695
5905
|
onRename,
|
|
5696
5906
|
onDelete
|
|
5697
5907
|
}) {
|
|
5698
|
-
return /* @__PURE__ */
|
|
5699
|
-
/* @__PURE__ */
|
|
5700
|
-
/* @__PURE__ */
|
|
5908
|
+
return /* @__PURE__ */ jsxs19("span", { className: "ml-auto flex gap-1", children: [
|
|
5909
|
+
/* @__PURE__ */ jsx21(IconButton, { label: `${editVerb} ${noun}`, onClick: onRename, children: /* @__PURE__ */ jsx21(Pencil, {}) }),
|
|
5910
|
+
/* @__PURE__ */ jsx21(
|
|
5701
5911
|
IconButton,
|
|
5702
5912
|
{
|
|
5703
5913
|
label: `Delete ${noun}`,
|
|
5704
5914
|
tone: "destructive",
|
|
5705
5915
|
onClick: onDelete,
|
|
5706
|
-
children: /* @__PURE__ */
|
|
5916
|
+
children: /* @__PURE__ */ jsx21(Trash2, {})
|
|
5707
5917
|
}
|
|
5708
5918
|
)
|
|
5709
5919
|
] });
|
|
@@ -5715,11 +5925,11 @@ function EdgeDetail({
|
|
|
5715
5925
|
onDelete,
|
|
5716
5926
|
children
|
|
5717
5927
|
}) {
|
|
5718
|
-
return /* @__PURE__ */
|
|
5719
|
-
/* @__PURE__ */
|
|
5720
|
-
/* @__PURE__ */
|
|
5721
|
-
/* @__PURE__ */
|
|
5722
|
-
editable && /* @__PURE__ */
|
|
5928
|
+
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5929
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
5930
|
+
/* @__PURE__ */ jsx21("span", { className: "text-base font-semibold", children: view.label }),
|
|
5931
|
+
/* @__PURE__ */ jsx21(Badge2, { children: "EDGE TYPE" }),
|
|
5932
|
+
editable && /* @__PURE__ */ jsx21(
|
|
5723
5933
|
RenameDeleteActions,
|
|
5724
5934
|
{
|
|
5725
5935
|
noun: "edge type",
|
|
@@ -5728,11 +5938,11 @@ function EdgeDetail({
|
|
|
5728
5938
|
}
|
|
5729
5939
|
)
|
|
5730
5940
|
] }),
|
|
5731
|
-
view.description && /* @__PURE__ */
|
|
5732
|
-
/* @__PURE__ */
|
|
5941
|
+
view.description && /* @__PURE__ */ jsx21("p", { className: "mt-1 text-sm text-muted-foreground", children: view.description }),
|
|
5942
|
+
/* @__PURE__ */ jsxs19(EdgeTypeNote, { children: [
|
|
5733
5943
|
"These properties belong to the",
|
|
5734
5944
|
" ",
|
|
5735
|
-
/* @__PURE__ */
|
|
5945
|
+
/* @__PURE__ */ jsx21("span", { className: "font-medium", children: view.label }),
|
|
5736
5946
|
" edge type and are shared by every relation of this type."
|
|
5737
5947
|
] }),
|
|
5738
5948
|
children
|
|
@@ -5745,11 +5955,11 @@ function RelationDetail({
|
|
|
5745
5955
|
onDelete,
|
|
5746
5956
|
children
|
|
5747
5957
|
}) {
|
|
5748
|
-
return /* @__PURE__ */
|
|
5749
|
-
/* @__PURE__ */
|
|
5750
|
-
/* @__PURE__ */
|
|
5751
|
-
/* @__PURE__ */
|
|
5752
|
-
editable && /* @__PURE__ */
|
|
5958
|
+
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5959
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
5960
|
+
/* @__PURE__ */ jsx21("span", { className: "text-base font-semibold", children: view.relType }),
|
|
5961
|
+
/* @__PURE__ */ jsx21(Badge2, { children: "RELATION" }),
|
|
5962
|
+
editable && /* @__PURE__ */ jsx21(
|
|
5753
5963
|
RenameDeleteActions,
|
|
5754
5964
|
{
|
|
5755
5965
|
noun: "relation",
|
|
@@ -5759,17 +5969,17 @@ function RelationDetail({
|
|
|
5759
5969
|
}
|
|
5760
5970
|
)
|
|
5761
5971
|
] }),
|
|
5762
|
-
/* @__PURE__ */
|
|
5763
|
-
/* @__PURE__ */
|
|
5972
|
+
/* @__PURE__ */ jsxs19("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
5973
|
+
/* @__PURE__ */ jsx21("span", { className: "font-medium text-foreground", children: view.source }),
|
|
5764
5974
|
" \u2192 ",
|
|
5765
|
-
/* @__PURE__ */
|
|
5975
|
+
/* @__PURE__ */ jsx21("span", { className: "font-medium text-foreground", children: view.target }),
|
|
5766
5976
|
" \xB7 ",
|
|
5767
5977
|
cardinalityLabel(view.cardinality)
|
|
5768
5978
|
] }),
|
|
5769
|
-
/* @__PURE__ */
|
|
5979
|
+
/* @__PURE__ */ jsxs19(EdgeTypeNote, { children: [
|
|
5770
5980
|
"Properties are defined on the",
|
|
5771
5981
|
" ",
|
|
5772
|
-
/* @__PURE__ */
|
|
5982
|
+
/* @__PURE__ */ jsx21("span", { className: "font-medium", children: view.relType }),
|
|
5773
5983
|
" edge type, shared by every relation of this type -- not on this single relation."
|
|
5774
5984
|
] }),
|
|
5775
5985
|
children
|
|
@@ -5834,7 +6044,7 @@ function validateCapabilities(input) {
|
|
|
5834
6044
|
}
|
|
5835
6045
|
|
|
5836
6046
|
// src/graph-model/ModelActionPanel.tsx
|
|
5837
|
-
import { Fragment as Fragment5, jsx as
|
|
6047
|
+
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
5838
6048
|
function nodeTypeLabels(model) {
|
|
5839
6049
|
return model.filter(isNodeType).map(typeLabel);
|
|
5840
6050
|
}
|
|
@@ -5848,19 +6058,19 @@ function CreateRelationPrompt({
|
|
|
5848
6058
|
edgeTypeMode,
|
|
5849
6059
|
onChange
|
|
5850
6060
|
}) {
|
|
5851
|
-
const [open, setOpen] =
|
|
5852
|
-
return /* @__PURE__ */
|
|
5853
|
-
/* @__PURE__ */
|
|
5854
|
-
/* @__PURE__ */
|
|
6061
|
+
const [open, setOpen] = useState13(false);
|
|
6062
|
+
return /* @__PURE__ */ jsxs20("div", { children: [
|
|
6063
|
+
/* @__PURE__ */ jsxs20("div", { className: "text-sm", children: [
|
|
6064
|
+
/* @__PURE__ */ jsx22("span", { className: "font-medium", children: nodeA }),
|
|
5855
6065
|
" and ",
|
|
5856
|
-
/* @__PURE__ */
|
|
6066
|
+
/* @__PURE__ */ jsx22("span", { className: "font-medium", children: nodeB }),
|
|
5857
6067
|
" selected."
|
|
5858
6068
|
] }),
|
|
5859
|
-
/* @__PURE__ */
|
|
5860
|
-
/* @__PURE__ */
|
|
6069
|
+
/* @__PURE__ */ jsxs20(Button8, { size: "sm", className: "mt-3 gap-1.5", onClick: () => setOpen(true), children: [
|
|
6070
|
+
/* @__PURE__ */ jsx22(GitBranchPlus, { className: "h-4 w-4" }),
|
|
5861
6071
|
"Create relation"
|
|
5862
6072
|
] }),
|
|
5863
|
-
/* @__PURE__ */
|
|
6073
|
+
/* @__PURE__ */ jsx22(
|
|
5864
6074
|
RelationFormSheet,
|
|
5865
6075
|
{
|
|
5866
6076
|
open,
|
|
@@ -5916,7 +6126,7 @@ function ModelActionPanel({
|
|
|
5916
6126
|
const schema = findType(model, l);
|
|
5917
6127
|
return schema ? isNodeType(schema) : false;
|
|
5918
6128
|
}) : [];
|
|
5919
|
-
return /* @__PURE__ */
|
|
6129
|
+
return /* @__PURE__ */ jsx22("div", { className: "h-full overflow-auto p-4", children: /* @__PURE__ */ jsx22(
|
|
5920
6130
|
PanelBody,
|
|
5921
6131
|
{
|
|
5922
6132
|
model,
|
|
@@ -5939,7 +6149,7 @@ function PanelBody({
|
|
|
5939
6149
|
twoLabels
|
|
5940
6150
|
}) {
|
|
5941
6151
|
if (selection) {
|
|
5942
|
-
return /* @__PURE__ */
|
|
6152
|
+
return /* @__PURE__ */ jsx22(
|
|
5943
6153
|
TypeDetailPanel,
|
|
5944
6154
|
{
|
|
5945
6155
|
model,
|
|
@@ -5953,7 +6163,7 @@ function PanelBody({
|
|
|
5953
6163
|
}
|
|
5954
6164
|
const canEdit = !readOnly && !!onChange;
|
|
5955
6165
|
if (twoLabels.length === 2 && canEdit && caps.relations === "edit") {
|
|
5956
|
-
return /* @__PURE__ */
|
|
6166
|
+
return /* @__PURE__ */ jsx22(
|
|
5957
6167
|
CreateRelationPrompt,
|
|
5958
6168
|
{
|
|
5959
6169
|
nodeA: twoLabels[0],
|
|
@@ -5964,8 +6174,8 @@ function PanelBody({
|
|
|
5964
6174
|
}
|
|
5965
6175
|
);
|
|
5966
6176
|
}
|
|
5967
|
-
return /* @__PURE__ */
|
|
5968
|
-
canEdit && /* @__PURE__ */
|
|
6177
|
+
return /* @__PURE__ */ jsxs20(Fragment5, { children: [
|
|
6178
|
+
canEdit && /* @__PURE__ */ jsx22(
|
|
5969
6179
|
AddTypeToolbar,
|
|
5970
6180
|
{
|
|
5971
6181
|
model,
|
|
@@ -5974,7 +6184,7 @@ function PanelBody({
|
|
|
5974
6184
|
canAddEdge: caps.edgeTypes === "edit"
|
|
5975
6185
|
}
|
|
5976
6186
|
),
|
|
5977
|
-
/* @__PURE__ */
|
|
6187
|
+
/* @__PURE__ */ jsx22(
|
|
5978
6188
|
Overview_default,
|
|
5979
6189
|
{
|
|
5980
6190
|
nodeBuckets: [
|
|
@@ -5993,9 +6203,9 @@ function AddTypeIconButton({
|
|
|
5993
6203
|
existing,
|
|
5994
6204
|
onSave
|
|
5995
6205
|
}) {
|
|
5996
|
-
const [open, setOpen] =
|
|
5997
|
-
return /* @__PURE__ */
|
|
5998
|
-
/* @__PURE__ */
|
|
6206
|
+
const [open, setOpen] = useState13(false);
|
|
6207
|
+
return /* @__PURE__ */ jsxs20(Fragment5, { children: [
|
|
6208
|
+
/* @__PURE__ */ jsx22(
|
|
5999
6209
|
IconButton2,
|
|
6000
6210
|
{
|
|
6001
6211
|
label: tooltip,
|
|
@@ -6004,7 +6214,7 @@ function AddTypeIconButton({
|
|
|
6004
6214
|
children: icon
|
|
6005
6215
|
}
|
|
6006
6216
|
),
|
|
6007
|
-
/* @__PURE__ */
|
|
6217
|
+
/* @__PURE__ */ jsx22(
|
|
6008
6218
|
NodeTypeNameSheet,
|
|
6009
6219
|
{
|
|
6010
6220
|
open,
|
|
@@ -6024,22 +6234,22 @@ function AddTypeToolbar({
|
|
|
6024
6234
|
}) {
|
|
6025
6235
|
if (!canAddNode && !canAddEdge) return null;
|
|
6026
6236
|
const existing = model.map(typeLabel);
|
|
6027
|
-
return /* @__PURE__ */
|
|
6028
|
-
canAddNode && /* @__PURE__ */
|
|
6237
|
+
return /* @__PURE__ */ jsxs20("div", { className: "mb-3 flex gap-1.5", children: [
|
|
6238
|
+
canAddNode && /* @__PURE__ */ jsx22(
|
|
6029
6239
|
AddTypeIconButton,
|
|
6030
6240
|
{
|
|
6031
6241
|
tooltip: "Add node type",
|
|
6032
|
-
icon: /* @__PURE__ */
|
|
6242
|
+
icon: /* @__PURE__ */ jsx22(CirclePlus, {}),
|
|
6033
6243
|
noun: "node",
|
|
6034
6244
|
existing,
|
|
6035
6245
|
onSave: (name) => onChange(addNodeType(model, name))
|
|
6036
6246
|
}
|
|
6037
6247
|
),
|
|
6038
|
-
canAddEdge && /* @__PURE__ */
|
|
6248
|
+
canAddEdge && /* @__PURE__ */ jsx22(
|
|
6039
6249
|
AddTypeIconButton,
|
|
6040
6250
|
{
|
|
6041
6251
|
tooltip: "Add edge type",
|
|
6042
|
-
icon: /* @__PURE__ */
|
|
6252
|
+
icon: /* @__PURE__ */ jsx22(Waypoints, {}),
|
|
6043
6253
|
noun: "edge",
|
|
6044
6254
|
existing,
|
|
6045
6255
|
onSave: (name) => onChange(addEdgeType(model, name))
|
|
@@ -6049,7 +6259,7 @@ function AddTypeToolbar({
|
|
|
6049
6259
|
}
|
|
6050
6260
|
|
|
6051
6261
|
// src/graph-model/GraphModelEditor.tsx
|
|
6052
|
-
import { Fragment as Fragment6, jsx as
|
|
6262
|
+
import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
6053
6263
|
function createEditorStores() {
|
|
6054
6264
|
const graphFilter = createGraphFilterStore();
|
|
6055
6265
|
const graphData = createGraphDataStore();
|
|
@@ -6086,14 +6296,14 @@ function GraphModelEditor({
|
|
|
6086
6296
|
defaultRenderer = "cytoscape",
|
|
6087
6297
|
hideActionPanel = false
|
|
6088
6298
|
}) {
|
|
6089
|
-
const storesRef =
|
|
6299
|
+
const storesRef = useRef7(null);
|
|
6090
6300
|
if (!storesRef.current) storesRef.current = createEditorStores();
|
|
6091
6301
|
const stores = storesRef.current;
|
|
6092
6302
|
const caps = resolveCapabilities(capabilities, readOnly);
|
|
6093
6303
|
const showEdgeTypes = caps.showEdgeTypes;
|
|
6094
|
-
const firstLoadRef =
|
|
6095
|
-
const prevShowEdgeTypesRef =
|
|
6096
|
-
|
|
6304
|
+
const firstLoadRef = useRef7(true);
|
|
6305
|
+
const prevShowEdgeTypesRef = useRef7(showEdgeTypes);
|
|
6306
|
+
useEffect6(() => {
|
|
6097
6307
|
loadModel(stores, value);
|
|
6098
6308
|
const filter = stores.graphFilter.getState();
|
|
6099
6309
|
const baselineReset = firstLoadRef.current || prevShowEdgeTypesRef.current !== showEdgeTypes;
|
|
@@ -6107,9 +6317,9 @@ function GraphModelEditor({
|
|
|
6107
6317
|
firstLoadRef.current = false;
|
|
6108
6318
|
prevShowEdgeTypesRef.current = showEdgeTypes;
|
|
6109
6319
|
}, [stores, value, showEdgeTypes]);
|
|
6110
|
-
const rowRef =
|
|
6111
|
-
const [panelWidth, setPanelWidth] =
|
|
6112
|
-
const startResize =
|
|
6320
|
+
const rowRef = useRef7(null);
|
|
6321
|
+
const [panelWidth, setPanelWidth] = useState14(380);
|
|
6322
|
+
const startResize = useCallback8((e) => {
|
|
6113
6323
|
e.preventDefault();
|
|
6114
6324
|
const target = e.currentTarget;
|
|
6115
6325
|
target.setPointerCapture(e.pointerId);
|
|
@@ -6124,10 +6334,10 @@ function GraphModelEditor({
|
|
|
6124
6334
|
window.addEventListener("pointermove", move);
|
|
6125
6335
|
window.addEventListener("pointerup", up);
|
|
6126
6336
|
}, []);
|
|
6127
|
-
return /* @__PURE__ */
|
|
6128
|
-
/* @__PURE__ */
|
|
6129
|
-
!hideActionPanel && /* @__PURE__ */
|
|
6130
|
-
/* @__PURE__ */
|
|
6337
|
+
return /* @__PURE__ */ jsx23(GraphStoresContext.Provider, { value: stores, children: /* @__PURE__ */ jsx23(GraphRendererProvider, { defaultRenderer, children: /* @__PURE__ */ jsxs21("div", { ref: rowRef, className: "flex w-full h-full overflow-hidden", children: [
|
|
6338
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx23(GraphVisualizer_default, {}) }),
|
|
6339
|
+
!hideActionPanel && /* @__PURE__ */ jsxs21(Fragment6, { children: [
|
|
6340
|
+
/* @__PURE__ */ jsx23(
|
|
6131
6341
|
ResizeHandle,
|
|
6132
6342
|
{
|
|
6133
6343
|
orientation: "vertical",
|
|
@@ -6138,12 +6348,12 @@ function GraphModelEditor({
|
|
|
6138
6348
|
onDoubleClick: () => setPanelWidth(380)
|
|
6139
6349
|
}
|
|
6140
6350
|
),
|
|
6141
|
-
/* @__PURE__ */
|
|
6351
|
+
/* @__PURE__ */ jsx23(
|
|
6142
6352
|
"div",
|
|
6143
6353
|
{
|
|
6144
6354
|
style: { width: panelWidth },
|
|
6145
6355
|
className: "shrink-0 border-l overflow-hidden bg-card",
|
|
6146
|
-
children: /* @__PURE__ */
|
|
6356
|
+
children: /* @__PURE__ */ jsx23(
|
|
6147
6357
|
ModelActionPanel,
|
|
6148
6358
|
{
|
|
6149
6359
|
model: value,
|
|
@@ -6307,17 +6517,17 @@ function enrichSchemaWithRelations(baseSchema, relations) {
|
|
|
6307
6517
|
}
|
|
6308
6518
|
|
|
6309
6519
|
// src/graph-edit/GraphEditToolbar.tsx
|
|
6310
|
-
import { useCallback as
|
|
6520
|
+
import { useCallback as useCallback12, useMemo as useMemo11, useState as useState18 } from "react";
|
|
6311
6521
|
import { IconButton as IconButton4 } from "@petrarca/sonnet-ui";
|
|
6312
6522
|
import { Plus as Plus3, Edit, Link, Trash2 as Trash23 } from "lucide-react";
|
|
6313
6523
|
|
|
6314
6524
|
// src/graph-edit/NodeFormSheet.tsx
|
|
6315
6525
|
import {
|
|
6316
|
-
useCallback as
|
|
6317
|
-
useEffect as
|
|
6526
|
+
useCallback as useCallback9,
|
|
6527
|
+
useEffect as useEffect7,
|
|
6318
6528
|
useMemo as useMemo9,
|
|
6319
|
-
useRef as
|
|
6320
|
-
useState as
|
|
6529
|
+
useRef as useRef8,
|
|
6530
|
+
useState as useState15
|
|
6321
6531
|
} from "react";
|
|
6322
6532
|
import {
|
|
6323
6533
|
Sheet as Sheet4,
|
|
@@ -6326,7 +6536,7 @@ import {
|
|
|
6326
6536
|
SheetBody as SheetBody4,
|
|
6327
6537
|
SheetTitle as SheetTitle4,
|
|
6328
6538
|
SheetDescription as SheetDescription4,
|
|
6329
|
-
Alert
|
|
6539
|
+
Alert as Alert2
|
|
6330
6540
|
} from "@petrarca/sonnet-ui";
|
|
6331
6541
|
import {
|
|
6332
6542
|
FormSelect as FormSelect2,
|
|
@@ -6334,7 +6544,7 @@ import {
|
|
|
6334
6544
|
JsonSchemaFormRenderer as JsonSchemaFormRenderer2
|
|
6335
6545
|
} from "@petrarca/sonnet-forms";
|
|
6336
6546
|
import { errorLog as errorLog4 } from "@petrarca/sonnet-core";
|
|
6337
|
-
import { Fragment as Fragment7, jsx as
|
|
6547
|
+
import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
6338
6548
|
var EMPTY_RESOLVED = {
|
|
6339
6549
|
schema: null,
|
|
6340
6550
|
uiSchema: {},
|
|
@@ -6358,10 +6568,10 @@ function resolveBaseSchema(provided, node) {
|
|
|
6358
6568
|
return { type: "object", properties: {} };
|
|
6359
6569
|
}
|
|
6360
6570
|
function useNodeSchema(schemaProvider, label, node) {
|
|
6361
|
-
const [resolved, setResolved] =
|
|
6362
|
-
const nodeRef =
|
|
6571
|
+
const [resolved, setResolved] = useState15(EMPTY_RESOLVED);
|
|
6572
|
+
const nodeRef = useRef8(node);
|
|
6363
6573
|
nodeRef.current = node;
|
|
6364
|
-
|
|
6574
|
+
useEffect7(() => {
|
|
6365
6575
|
let cancelled = false;
|
|
6366
6576
|
if (!label) {
|
|
6367
6577
|
setResolved(EMPTY_RESOLVED);
|
|
@@ -6399,11 +6609,11 @@ function useNodeSchema(schemaProvider, label, node) {
|
|
|
6399
6609
|
return resolved;
|
|
6400
6610
|
}
|
|
6401
6611
|
function useExistingFormData(port, node, relationTypes) {
|
|
6402
|
-
const [data, setData] =
|
|
6612
|
+
const [data, setData] = useState15(null);
|
|
6403
6613
|
const nodeId2 = node?.id_;
|
|
6404
|
-
const propertiesRef =
|
|
6614
|
+
const propertiesRef = useRef8(node?.properties_);
|
|
6405
6615
|
propertiesRef.current = node?.properties_;
|
|
6406
|
-
|
|
6616
|
+
useEffect7(() => {
|
|
6407
6617
|
let cancelled = false;
|
|
6408
6618
|
if (nodeId2 == null) {
|
|
6409
6619
|
setData(null);
|
|
@@ -6445,12 +6655,12 @@ function LabelField({
|
|
|
6445
6655
|
onSelect
|
|
6446
6656
|
}) {
|
|
6447
6657
|
if (isEdit) {
|
|
6448
|
-
return /* @__PURE__ */
|
|
6449
|
-
/* @__PURE__ */
|
|
6450
|
-
/* @__PURE__ */
|
|
6658
|
+
return /* @__PURE__ */ jsxs22("div", { children: [
|
|
6659
|
+
/* @__PURE__ */ jsx24("span", { className: "heading-meta block", children: "Label" }),
|
|
6660
|
+
/* @__PURE__ */ jsx24("span", { className: "text-sm text-muted-foreground", children: selectedLabel })
|
|
6451
6661
|
] });
|
|
6452
6662
|
}
|
|
6453
|
-
return /* @__PURE__ */
|
|
6663
|
+
return /* @__PURE__ */ jsx24(
|
|
6454
6664
|
FormSelect2,
|
|
6455
6665
|
{
|
|
6456
6666
|
label: "Label",
|
|
@@ -6462,8 +6672,8 @@ function LabelField({
|
|
|
6462
6672
|
);
|
|
6463
6673
|
}
|
|
6464
6674
|
function useCreateModeLabels(schemaProvider, open, isEdit) {
|
|
6465
|
-
const [labels, setLabels] =
|
|
6466
|
-
|
|
6675
|
+
const [labels, setLabels] = useState15([]);
|
|
6676
|
+
useEffect7(() => {
|
|
6467
6677
|
let cancelled = false;
|
|
6468
6678
|
if (!open || isEdit) return;
|
|
6469
6679
|
void schemaProvider.listNodeLabels().then((ls) => {
|
|
@@ -6485,7 +6695,7 @@ function NodeForm({
|
|
|
6485
6695
|
onSave,
|
|
6486
6696
|
onCancel
|
|
6487
6697
|
}) {
|
|
6488
|
-
return /* @__PURE__ */
|
|
6698
|
+
return /* @__PURE__ */ jsx24(
|
|
6489
6699
|
JsonSchemaFormRenderer2,
|
|
6490
6700
|
{
|
|
6491
6701
|
schema,
|
|
@@ -6519,13 +6729,13 @@ function NodeFormSheetBody({
|
|
|
6519
6729
|
onSave,
|
|
6520
6730
|
onCancel
|
|
6521
6731
|
}) {
|
|
6522
|
-
return /* @__PURE__ */
|
|
6523
|
-
/* @__PURE__ */
|
|
6524
|
-
/* @__PURE__ */
|
|
6525
|
-
/* @__PURE__ */
|
|
6732
|
+
return /* @__PURE__ */ jsxs22(Fragment7, { children: [
|
|
6733
|
+
/* @__PURE__ */ jsxs22(SheetHeader4, { children: [
|
|
6734
|
+
/* @__PURE__ */ jsx24(SheetTitle4, { children: isEdit ? "Edit node" : "Add node" }),
|
|
6735
|
+
/* @__PURE__ */ jsx24(SheetDescription4, { children: isEdit ? "Edit this node's properties and relations." : "Create a node and (optionally) its relations." })
|
|
6526
6736
|
] }),
|
|
6527
|
-
/* @__PURE__ */
|
|
6528
|
-
/* @__PURE__ */
|
|
6737
|
+
/* @__PURE__ */ jsxs22(SheetBody4, { className: "flex flex-col gap-4", children: [
|
|
6738
|
+
/* @__PURE__ */ jsx24(
|
|
6529
6739
|
LabelField,
|
|
6530
6740
|
{
|
|
6531
6741
|
isEdit,
|
|
@@ -6534,7 +6744,7 @@ function NodeFormSheetBody({
|
|
|
6534
6744
|
onSelect: onSelectLabel
|
|
6535
6745
|
}
|
|
6536
6746
|
),
|
|
6537
|
-
schema && /* @__PURE__ */
|
|
6747
|
+
schema && /* @__PURE__ */ jsx24(
|
|
6538
6748
|
NodeForm,
|
|
6539
6749
|
{
|
|
6540
6750
|
formKey,
|
|
@@ -6547,7 +6757,7 @@ function NodeFormSheetBody({
|
|
|
6547
6757
|
onCancel
|
|
6548
6758
|
}
|
|
6549
6759
|
),
|
|
6550
|
-
!isEdit && /* @__PURE__ */
|
|
6760
|
+
!isEdit && /* @__PURE__ */ jsx24(
|
|
6551
6761
|
FormCheckbox,
|
|
6552
6762
|
{
|
|
6553
6763
|
label: "Create another node",
|
|
@@ -6555,7 +6765,7 @@ function NodeFormSheetBody({
|
|
|
6555
6765
|
onChange: (c) => onKeepOpenChange(c === true)
|
|
6556
6766
|
}
|
|
6557
6767
|
),
|
|
6558
|
-
error && /* @__PURE__ */
|
|
6768
|
+
error && /* @__PURE__ */ jsx24(Alert2, { variant: "destructive", children: error })
|
|
6559
6769
|
] })
|
|
6560
6770
|
] });
|
|
6561
6771
|
}
|
|
@@ -6569,14 +6779,14 @@ function NodeFormSheet({
|
|
|
6569
6779
|
onSaved
|
|
6570
6780
|
}) {
|
|
6571
6781
|
const isEdit = !!node?.id_;
|
|
6572
|
-
const [selectedLabel, setSelectedLabel] =
|
|
6782
|
+
const [selectedLabel, setSelectedLabel] = useState15(
|
|
6573
6783
|
node?.label_ ?? null
|
|
6574
6784
|
);
|
|
6575
|
-
const [error, setError] =
|
|
6576
|
-
const [keepOpen, setKeepOpen] =
|
|
6577
|
-
const [formNonce, setFormNonce] =
|
|
6785
|
+
const [error, setError] = useState15("");
|
|
6786
|
+
const [keepOpen, setKeepOpen] = useState15(false);
|
|
6787
|
+
const [formNonce, setFormNonce] = useState15(0);
|
|
6578
6788
|
const labels = useCreateModeLabels(schemaProvider, open, isEdit);
|
|
6579
|
-
|
|
6789
|
+
useEffect7(() => {
|
|
6580
6790
|
if (open) {
|
|
6581
6791
|
setSelectedLabel(node?.label_ ?? null);
|
|
6582
6792
|
setError("");
|
|
@@ -6593,7 +6803,7 @@ function NodeFormSheet({
|
|
|
6593
6803
|
const formData = useMemo9(() => existingData ?? {}, [existingData]);
|
|
6594
6804
|
const stableOnSaved = useStableRef(onSaved);
|
|
6595
6805
|
const stableOnOpenChange = useStableRef(onOpenChange);
|
|
6596
|
-
const handleSave =
|
|
6806
|
+
const handleSave = useCallback9(
|
|
6597
6807
|
(data) => {
|
|
6598
6808
|
if (!selectedLabel) return;
|
|
6599
6809
|
void (async () => {
|
|
@@ -6626,7 +6836,7 @@ function NodeFormSheet({
|
|
|
6626
6836
|
stableOnOpenChange
|
|
6627
6837
|
]
|
|
6628
6838
|
);
|
|
6629
|
-
return /* @__PURE__ */
|
|
6839
|
+
return /* @__PURE__ */ jsx24(Sheet4, { open, onOpenChange, children: /* @__PURE__ */ jsx24(SheetContent4, { children: /* @__PURE__ */ jsx24(
|
|
6630
6840
|
NodeFormSheetBody,
|
|
6631
6841
|
{
|
|
6632
6842
|
isEdit,
|
|
@@ -6683,7 +6893,7 @@ async function saveNode({
|
|
|
6683
6893
|
}
|
|
6684
6894
|
|
|
6685
6895
|
// src/graph-edit/EdgeFormSheet.tsx
|
|
6686
|
-
import { useCallback as
|
|
6896
|
+
import { useCallback as useCallback10, useEffect as useEffect8, useMemo as useMemo10, useState as useState16 } from "react";
|
|
6687
6897
|
import {
|
|
6688
6898
|
Sheet as Sheet5,
|
|
6689
6899
|
SheetContent as SheetContent5,
|
|
@@ -6697,20 +6907,20 @@ import {
|
|
|
6697
6907
|
DialogTitle,
|
|
6698
6908
|
DialogDescription,
|
|
6699
6909
|
DialogFooter,
|
|
6700
|
-
Button as
|
|
6910
|
+
Button as Button9,
|
|
6701
6911
|
IconButton as IconButton3,
|
|
6702
|
-
Alert as
|
|
6912
|
+
Alert as Alert3
|
|
6703
6913
|
} from "@petrarca/sonnet-ui";
|
|
6704
6914
|
import { Pencil as Pencil2, Plus as Plus2, Trash2 as Trash22, ArrowRight as ArrowRight2 } from "lucide-react";
|
|
6705
6915
|
import {
|
|
6706
6916
|
JsonSchemaFormRenderer as JsonSchemaFormRenderer3
|
|
6707
6917
|
} from "@petrarca/sonnet-forms";
|
|
6708
6918
|
import { errorLog as errorLog5 } from "@petrarca/sonnet-core";
|
|
6709
|
-
import { jsx as
|
|
6919
|
+
import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
6710
6920
|
function usePairState(port, schemaProvider, open, nodeAId, nodeALabel, nodeBId, nodeBLabel, reloadKey) {
|
|
6711
|
-
const [active, setActive] =
|
|
6712
|
-
const [available, setAvailable] =
|
|
6713
|
-
|
|
6921
|
+
const [active, setActive] = useState16([]);
|
|
6922
|
+
const [available, setAvailable] = useState16([]);
|
|
6923
|
+
useEffect8(() => {
|
|
6714
6924
|
let cancelled = false;
|
|
6715
6925
|
if (!open || nodeAId == null || nodeBId == null) {
|
|
6716
6926
|
setActive([]);
|
|
@@ -6775,9 +6985,9 @@ var EMPTY_EDGE_SCHEMA = {
|
|
|
6775
6985
|
properties: {}
|
|
6776
6986
|
};
|
|
6777
6987
|
function useEdgeSchema(schemaProvider, draft) {
|
|
6778
|
-
const [schema, setSchema] =
|
|
6988
|
+
const [schema, setSchema] = useState16(null);
|
|
6779
6989
|
const label = useMemo10(() => draftLabel(draft), [draft]);
|
|
6780
|
-
|
|
6990
|
+
useEffect8(() => {
|
|
6781
6991
|
let cancelled = false;
|
|
6782
6992
|
if (!label) {
|
|
6783
6993
|
setSchema(null);
|
|
@@ -6797,12 +7007,12 @@ function useEdgeSchema(schemaProvider, draft) {
|
|
|
6797
7007
|
return schema;
|
|
6798
7008
|
}
|
|
6799
7009
|
function useEditableEdgeTypes(schemaProvider, active) {
|
|
6800
|
-
const [editable, setEditable] =
|
|
7010
|
+
const [editable, setEditable] = useState16({});
|
|
6801
7011
|
const labelsKey = useMemo10(
|
|
6802
7012
|
() => Array.from(new Set(active.map((e) => e.label_))).sort().join("\0"),
|
|
6803
7013
|
[active]
|
|
6804
7014
|
);
|
|
6805
|
-
|
|
7015
|
+
useEffect8(() => {
|
|
6806
7016
|
let cancelled = false;
|
|
6807
7017
|
const labels = labelsKey ? labelsKey.split("\0") : [];
|
|
6808
7018
|
if (labels.length === 0) {
|
|
@@ -6831,7 +7041,7 @@ function useEditableEdgeTypes(schemaProvider, active) {
|
|
|
6831
7041
|
function SectionTitle2({
|
|
6832
7042
|
children
|
|
6833
7043
|
}) {
|
|
6834
|
-
return /* @__PURE__ */
|
|
7044
|
+
return /* @__PURE__ */ jsx25("div", { className: "mb-2", children: /* @__PURE__ */ jsx25("span", { className: "heading-meta", children }) });
|
|
6835
7045
|
}
|
|
6836
7046
|
function EdgeRow({
|
|
6837
7047
|
label,
|
|
@@ -6839,19 +7049,19 @@ function EdgeRow({
|
|
|
6839
7049
|
onDelete,
|
|
6840
7050
|
onAdd
|
|
6841
7051
|
}) {
|
|
6842
|
-
return /* @__PURE__ */
|
|
6843
|
-
/* @__PURE__ */
|
|
6844
|
-
/* @__PURE__ */
|
|
6845
|
-
onAdd && /* @__PURE__ */
|
|
6846
|
-
onEdit && /* @__PURE__ */
|
|
6847
|
-
onDelete && /* @__PURE__ */
|
|
7052
|
+
return /* @__PURE__ */ jsxs23("div", { className: "group/row flex items-center gap-2 px-3 py-2", children: [
|
|
7053
|
+
/* @__PURE__ */ jsx25("span", { className: "flex-1 text-sm font-medium", children: label }),
|
|
7054
|
+
/* @__PURE__ */ jsxs23("span", { className: "flex gap-1", children: [
|
|
7055
|
+
onAdd && /* @__PURE__ */ jsx25(IconButton3, { label: "Create edge", revealOnHover: true, onClick: onAdd, children: /* @__PURE__ */ jsx25(Plus2, {}) }),
|
|
7056
|
+
onEdit && /* @__PURE__ */ jsx25(IconButton3, { label: "Edit edge", revealOnHover: true, onClick: onEdit, children: /* @__PURE__ */ jsx25(Pencil2, {}) }),
|
|
7057
|
+
onDelete && /* @__PURE__ */ jsx25(
|
|
6848
7058
|
IconButton3,
|
|
6849
7059
|
{
|
|
6850
7060
|
label: "Delete edge",
|
|
6851
7061
|
tone: "destructive",
|
|
6852
7062
|
revealOnHover: true,
|
|
6853
7063
|
onClick: onDelete,
|
|
6854
|
-
children: /* @__PURE__ */
|
|
7064
|
+
children: /* @__PURE__ */ jsx25(Trash22, {})
|
|
6855
7065
|
}
|
|
6856
7066
|
)
|
|
6857
7067
|
] })
|
|
@@ -6879,17 +7089,17 @@ function PairLists({
|
|
|
6879
7089
|
const to = entry.sourceId === nodeAId ? nodeBLabel : nodeALabel;
|
|
6880
7090
|
return `${entry.label} (${from} -> ${to})`;
|
|
6881
7091
|
};
|
|
6882
|
-
return /* @__PURE__ */
|
|
6883
|
-
empty && /* @__PURE__ */
|
|
7092
|
+
return /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-4", children: [
|
|
7093
|
+
empty && /* @__PURE__ */ jsxs23("p", { className: "text-xs text-muted-foreground", children: [
|
|
6884
7094
|
"No edges are defined between ",
|
|
6885
7095
|
nodeALabel,
|
|
6886
7096
|
" and ",
|
|
6887
7097
|
nodeBLabel,
|
|
6888
7098
|
"."
|
|
6889
7099
|
] }),
|
|
6890
|
-
active.length > 0 && /* @__PURE__ */
|
|
6891
|
-
/* @__PURE__ */
|
|
6892
|
-
/* @__PURE__ */
|
|
7100
|
+
active.length > 0 && /* @__PURE__ */ jsxs23("div", { children: [
|
|
7101
|
+
/* @__PURE__ */ jsx25(SectionTitle2, { children: "Active edges" }),
|
|
7102
|
+
/* @__PURE__ */ jsx25("div", { className: "rounded-lg border divide-y", children: active.map((edge) => /* @__PURE__ */ jsx25(
|
|
6893
7103
|
EdgeRow,
|
|
6894
7104
|
{
|
|
6895
7105
|
label: edge.label_,
|
|
@@ -6899,9 +7109,9 @@ function PairLists({
|
|
|
6899
7109
|
edge.id_
|
|
6900
7110
|
)) })
|
|
6901
7111
|
] }),
|
|
6902
|
-
available.length > 0 && /* @__PURE__ */
|
|
6903
|
-
/* @__PURE__ */
|
|
6904
|
-
/* @__PURE__ */
|
|
7112
|
+
available.length > 0 && /* @__PURE__ */ jsxs23("div", { children: [
|
|
7113
|
+
/* @__PURE__ */ jsx25(SectionTitle2, { children: "Available edges" }),
|
|
7114
|
+
/* @__PURE__ */ jsx25("div", { className: "rounded-lg border divide-y", children: available.map((entry) => /* @__PURE__ */ jsx25(
|
|
6905
7115
|
EdgeRow,
|
|
6906
7116
|
{
|
|
6907
7117
|
label: rowLabel(entry),
|
|
@@ -6921,13 +7131,13 @@ function DraftForm({
|
|
|
6921
7131
|
}) {
|
|
6922
7132
|
const label = draft.mode === "create" ? draft.entry.label : draft.edge.label_;
|
|
6923
7133
|
const data = draft.mode === "edit" ? draft.edge.properties_ ?? {} : {};
|
|
6924
|
-
return /* @__PURE__ */
|
|
6925
|
-
/* @__PURE__ */
|
|
7134
|
+
return /* @__PURE__ */ jsxs23("div", { children: [
|
|
7135
|
+
/* @__PURE__ */ jsxs23(SectionTitle2, { children: [
|
|
6926
7136
|
draft.mode === "create" ? "Add" : "Edit",
|
|
6927
7137
|
" ",
|
|
6928
7138
|
label
|
|
6929
7139
|
] }),
|
|
6930
|
-
/* @__PURE__ */
|
|
7140
|
+
/* @__PURE__ */ jsx25(
|
|
6931
7141
|
JsonSchemaFormRenderer3,
|
|
6932
7142
|
{
|
|
6933
7143
|
schema,
|
|
@@ -6955,10 +7165,10 @@ function EdgeFormSheet({
|
|
|
6955
7165
|
widgets,
|
|
6956
7166
|
onChanged
|
|
6957
7167
|
}) {
|
|
6958
|
-
const [reloadKey, setReloadKey] =
|
|
6959
|
-
const [draft, setDraft] =
|
|
6960
|
-
const [error, setError] =
|
|
6961
|
-
const [pendingDelete, setPendingDelete] =
|
|
7168
|
+
const [reloadKey, setReloadKey] = useState16(0);
|
|
7169
|
+
const [draft, setDraft] = useState16(null);
|
|
7170
|
+
const [error, setError] = useState16("");
|
|
7171
|
+
const [pendingDelete, setPendingDelete] = useState16(null);
|
|
6962
7172
|
const { active, available } = usePairState(
|
|
6963
7173
|
port,
|
|
6964
7174
|
schemaProvider,
|
|
@@ -6973,18 +7183,18 @@ function EdgeFormSheet({
|
|
|
6973
7183
|
const editableTypes = useEditableEdgeTypes(schemaProvider, active);
|
|
6974
7184
|
const nodeAId = nodeA.id_;
|
|
6975
7185
|
const nodeBId = nodeB.id_;
|
|
6976
|
-
|
|
7186
|
+
useEffect8(() => {
|
|
6977
7187
|
if (open) {
|
|
6978
7188
|
setDraft(null);
|
|
6979
7189
|
setError("");
|
|
6980
7190
|
setPendingDelete(null);
|
|
6981
7191
|
}
|
|
6982
7192
|
}, [open, nodeAId, nodeBId]);
|
|
6983
|
-
const reload =
|
|
7193
|
+
const reload = useCallback10(() => {
|
|
6984
7194
|
setReloadKey((k) => k + 1);
|
|
6985
7195
|
onChanged?.();
|
|
6986
7196
|
}, [onChanged]);
|
|
6987
|
-
const handleSave =
|
|
7197
|
+
const handleSave = useCallback10(
|
|
6988
7198
|
(formData) => {
|
|
6989
7199
|
if (!draft) return;
|
|
6990
7200
|
const { properties } = extractRelationFields(formData);
|
|
@@ -7016,7 +7226,7 @@ function EdgeFormSheet({
|
|
|
7016
7226
|
},
|
|
7017
7227
|
[draft, port, reload]
|
|
7018
7228
|
);
|
|
7019
|
-
const confirmDelete =
|
|
7229
|
+
const confirmDelete = useCallback10(async () => {
|
|
7020
7230
|
const edge = pendingDelete;
|
|
7021
7231
|
if (!edge || edge.id_ == null) return;
|
|
7022
7232
|
try {
|
|
@@ -7029,19 +7239,19 @@ function EdgeFormSheet({
|
|
|
7029
7239
|
setError(e instanceof Error ? e.message : "Failed to delete edge");
|
|
7030
7240
|
}
|
|
7031
7241
|
}, [pendingDelete, port, reload]);
|
|
7032
|
-
return /* @__PURE__ */
|
|
7033
|
-
/* @__PURE__ */
|
|
7034
|
-
/* @__PURE__ */
|
|
7035
|
-
/* @__PURE__ */
|
|
7036
|
-
/* @__PURE__ */
|
|
7242
|
+
return /* @__PURE__ */ jsxs23(Sheet5, { open, onOpenChange, children: [
|
|
7243
|
+
/* @__PURE__ */ jsxs23(SheetContent5, { children: [
|
|
7244
|
+
/* @__PURE__ */ jsxs23(SheetHeader5, { children: [
|
|
7245
|
+
/* @__PURE__ */ jsx25(SheetTitle5, { children: "Edges" }),
|
|
7246
|
+
/* @__PURE__ */ jsx25(SheetDescription5, { children: "Manage the edges between the two selected nodes." })
|
|
7037
7247
|
] }),
|
|
7038
|
-
/* @__PURE__ */
|
|
7039
|
-
/* @__PURE__ */
|
|
7040
|
-
/* @__PURE__ */
|
|
7041
|
-
/* @__PURE__ */
|
|
7042
|
-
/* @__PURE__ */
|
|
7248
|
+
/* @__PURE__ */ jsxs23(SheetBody5, { className: "flex flex-col gap-4", children: [
|
|
7249
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
7250
|
+
/* @__PURE__ */ jsx25("span", { className: "font-medium", children: extractDisplayLabel(nodeA) }),
|
|
7251
|
+
/* @__PURE__ */ jsx25(ArrowRight2, { className: "h-4 w-4 text-muted-foreground" }),
|
|
7252
|
+
/* @__PURE__ */ jsx25("span", { className: "font-medium", children: extractDisplayLabel(nodeB) })
|
|
7043
7253
|
] }),
|
|
7044
|
-
!draft && /* @__PURE__ */
|
|
7254
|
+
!draft && /* @__PURE__ */ jsx25(
|
|
7045
7255
|
PairLists,
|
|
7046
7256
|
{
|
|
7047
7257
|
nodeALabel: nodeA.label_,
|
|
@@ -7055,7 +7265,7 @@ function EdgeFormSheet({
|
|
|
7055
7265
|
onCreate: (entry) => setDraft({ mode: "create", entry })
|
|
7056
7266
|
}
|
|
7057
7267
|
),
|
|
7058
|
-
draft && schema && /* @__PURE__ */
|
|
7268
|
+
draft && schema && /* @__PURE__ */ jsx25(
|
|
7059
7269
|
DraftForm,
|
|
7060
7270
|
{
|
|
7061
7271
|
draft,
|
|
@@ -7065,10 +7275,10 @@ function EdgeFormSheet({
|
|
|
7065
7275
|
onCancel: () => setDraft(null)
|
|
7066
7276
|
}
|
|
7067
7277
|
),
|
|
7068
|
-
error && /* @__PURE__ */
|
|
7278
|
+
error && /* @__PURE__ */ jsx25(Alert3, { variant: "destructive", children: error })
|
|
7069
7279
|
] })
|
|
7070
7280
|
] }),
|
|
7071
|
-
/* @__PURE__ */
|
|
7281
|
+
/* @__PURE__ */ jsx25(
|
|
7072
7282
|
DeleteEdgeConfirm,
|
|
7073
7283
|
{
|
|
7074
7284
|
edge: pendingDelete,
|
|
@@ -7083,24 +7293,24 @@ function DeleteEdgeConfirm({
|
|
|
7083
7293
|
onCancel,
|
|
7084
7294
|
onConfirm
|
|
7085
7295
|
}) {
|
|
7086
|
-
return /* @__PURE__ */
|
|
7087
|
-
/* @__PURE__ */
|
|
7088
|
-
/* @__PURE__ */
|
|
7089
|
-
/* @__PURE__ */
|
|
7296
|
+
return /* @__PURE__ */ jsx25(Dialog, { open: !!edge, onOpenChange: (o) => !o && onCancel(), children: /* @__PURE__ */ jsxs23(DialogContent, { children: [
|
|
7297
|
+
/* @__PURE__ */ jsxs23(DialogHeader, { children: [
|
|
7298
|
+
/* @__PURE__ */ jsx25(DialogTitle, { children: "Delete edge" }),
|
|
7299
|
+
/* @__PURE__ */ jsxs23(DialogDescription, { children: [
|
|
7090
7300
|
"Delete the edge ",
|
|
7091
|
-
/* @__PURE__ */
|
|
7301
|
+
/* @__PURE__ */ jsx25("strong", { children: edge?.label_ }),
|
|
7092
7302
|
"? This removes the relationship between the two nodes."
|
|
7093
7303
|
] })
|
|
7094
7304
|
] }),
|
|
7095
|
-
/* @__PURE__ */
|
|
7096
|
-
/* @__PURE__ */
|
|
7097
|
-
/* @__PURE__ */
|
|
7305
|
+
/* @__PURE__ */ jsxs23(DialogFooter, { children: [
|
|
7306
|
+
/* @__PURE__ */ jsx25(Button9, { variant: "outline", onClick: onCancel, children: "Cancel" }),
|
|
7307
|
+
/* @__PURE__ */ jsx25(Button9, { variant: "destructive", onClick: onConfirm, children: "Delete" })
|
|
7098
7308
|
] })
|
|
7099
7309
|
] }) });
|
|
7100
7310
|
}
|
|
7101
7311
|
|
|
7102
7312
|
// src/graph-edit/DeleteNodeDialog.tsx
|
|
7103
|
-
import { useCallback as
|
|
7313
|
+
import { useCallback as useCallback11, useEffect as useEffect9, useState as useState17 } from "react";
|
|
7104
7314
|
import {
|
|
7105
7315
|
Dialog as Dialog2,
|
|
7106
7316
|
DialogContent as DialogContent2,
|
|
@@ -7108,19 +7318,19 @@ import {
|
|
|
7108
7318
|
DialogTitle as DialogTitle2,
|
|
7109
7319
|
DialogDescription as DialogDescription2,
|
|
7110
7320
|
DialogFooter as DialogFooter2,
|
|
7111
|
-
Button as
|
|
7112
|
-
Alert as
|
|
7321
|
+
Button as Button10,
|
|
7322
|
+
Alert as Alert4
|
|
7113
7323
|
} from "@petrarca/sonnet-ui";
|
|
7114
7324
|
import { errorLog as errorLog6 } from "@petrarca/sonnet-core";
|
|
7115
|
-
import { jsx as
|
|
7325
|
+
import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
7116
7326
|
var EMPTY_DEPENDENT = {
|
|
7117
7327
|
inbound: [],
|
|
7118
7328
|
outbound: [],
|
|
7119
7329
|
names: {}
|
|
7120
7330
|
};
|
|
7121
7331
|
function useDependentEdges(port, open, node) {
|
|
7122
|
-
const [dependent, setDependent] =
|
|
7123
|
-
|
|
7332
|
+
const [dependent, setDependent] = useState17(EMPTY_DEPENDENT);
|
|
7333
|
+
useEffect9(() => {
|
|
7124
7334
|
if (!open) return;
|
|
7125
7335
|
if (node.id_ == null) {
|
|
7126
7336
|
setDependent(EMPTY_DEPENDENT);
|
|
@@ -7170,12 +7380,12 @@ function EdgeList({
|
|
|
7170
7380
|
direction
|
|
7171
7381
|
}) {
|
|
7172
7382
|
if (edges.length === 0) return null;
|
|
7173
|
-
return /* @__PURE__ */
|
|
7174
|
-
/* @__PURE__ */
|
|
7175
|
-
/* @__PURE__ */
|
|
7383
|
+
return /* @__PURE__ */ jsxs24("div", { className: "mb-2", children: [
|
|
7384
|
+
/* @__PURE__ */ jsx26("span", { className: "heading-meta block", children: title }),
|
|
7385
|
+
/* @__PURE__ */ jsx26("ul", { className: "list-disc pl-6 text-sm", children: edges.map((edge) => {
|
|
7176
7386
|
const neighbour = direction === "inbound" ? names[edge.start_id_] : names[edge.end_id_];
|
|
7177
7387
|
const text = direction === "inbound" ? `${neighbour ?? "?"} \u2192 ${edge.label_}` : `${edge.label_} \u2192 ${neighbour ?? "?"}`;
|
|
7178
|
-
return /* @__PURE__ */
|
|
7388
|
+
return /* @__PURE__ */ jsx26("li", { children: neighbour ? text : edge.label_ }, edge.id_);
|
|
7179
7389
|
}) })
|
|
7180
7390
|
] });
|
|
7181
7391
|
}
|
|
@@ -7187,9 +7397,9 @@ function DeleteNodeDialog({
|
|
|
7187
7397
|
onDeleted
|
|
7188
7398
|
}) {
|
|
7189
7399
|
const { inbound, outbound, names } = useDependentEdges(port, open, node);
|
|
7190
|
-
const [error, setError] =
|
|
7400
|
+
const [error, setError] = useState17("");
|
|
7191
7401
|
const hasEdges = inbound.length > 0 || outbound.length > 0;
|
|
7192
|
-
const handleDelete =
|
|
7402
|
+
const handleDelete = useCallback11(() => {
|
|
7193
7403
|
if (node.id_ == null) return;
|
|
7194
7404
|
void (async () => {
|
|
7195
7405
|
try {
|
|
@@ -7202,17 +7412,17 @@ function DeleteNodeDialog({
|
|
|
7202
7412
|
}
|
|
7203
7413
|
})();
|
|
7204
7414
|
}, [port, node.id_, onDeleted, onOpenChange]);
|
|
7205
|
-
return /* @__PURE__ */
|
|
7206
|
-
/* @__PURE__ */
|
|
7207
|
-
/* @__PURE__ */
|
|
7208
|
-
/* @__PURE__ */
|
|
7415
|
+
return /* @__PURE__ */ jsx26(Dialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs24(DialogContent2, { children: [
|
|
7416
|
+
/* @__PURE__ */ jsxs24(DialogHeader2, { children: [
|
|
7417
|
+
/* @__PURE__ */ jsx26(DialogTitle2, { children: "Delete node" }),
|
|
7418
|
+
/* @__PURE__ */ jsxs24(DialogDescription2, { children: [
|
|
7209
7419
|
"Delete the node ",
|
|
7210
|
-
/* @__PURE__ */
|
|
7420
|
+
/* @__PURE__ */ jsx26("strong", { children: extractDisplayLabel(node) }),
|
|
7211
7421
|
"?"
|
|
7212
7422
|
] })
|
|
7213
7423
|
] }),
|
|
7214
|
-
!hasEdges && /* @__PURE__ */
|
|
7215
|
-
/* @__PURE__ */
|
|
7424
|
+
!hasEdges && /* @__PURE__ */ jsx26("p", { className: "text-sm text-muted-foreground", children: "No connected edges." }),
|
|
7425
|
+
/* @__PURE__ */ jsx26(
|
|
7216
7426
|
EdgeList,
|
|
7217
7427
|
{
|
|
7218
7428
|
title: "Inbound edges",
|
|
@@ -7221,7 +7431,7 @@ function DeleteNodeDialog({
|
|
|
7221
7431
|
direction: "inbound"
|
|
7222
7432
|
}
|
|
7223
7433
|
),
|
|
7224
|
-
/* @__PURE__ */
|
|
7434
|
+
/* @__PURE__ */ jsx26(
|
|
7225
7435
|
EdgeList,
|
|
7226
7436
|
{
|
|
7227
7437
|
title: "Outbound edges",
|
|
@@ -7230,16 +7440,16 @@ function DeleteNodeDialog({
|
|
|
7230
7440
|
direction: "outbound"
|
|
7231
7441
|
}
|
|
7232
7442
|
),
|
|
7233
|
-
error && /* @__PURE__ */
|
|
7234
|
-
/* @__PURE__ */
|
|
7235
|
-
/* @__PURE__ */
|
|
7236
|
-
/* @__PURE__ */
|
|
7443
|
+
error && /* @__PURE__ */ jsx26(Alert4, { variant: "destructive", children: error }),
|
|
7444
|
+
/* @__PURE__ */ jsxs24(DialogFooter2, { children: [
|
|
7445
|
+
/* @__PURE__ */ jsx26(Button10, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
7446
|
+
/* @__PURE__ */ jsx26(Button10, { variant: "destructive", onClick: handleDelete, children: "Delete" })
|
|
7237
7447
|
] })
|
|
7238
7448
|
] }) });
|
|
7239
7449
|
}
|
|
7240
7450
|
|
|
7241
7451
|
// src/graph-edit/GraphEditToolbar.tsx
|
|
7242
|
-
import { Fragment as Fragment8, jsx as
|
|
7452
|
+
import { Fragment as Fragment8, jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
7243
7453
|
function toPerms(caps) {
|
|
7244
7454
|
const canCreateNode = caps.createNode === "edit";
|
|
7245
7455
|
const canUpdateNode = caps.updateNode === "edit";
|
|
@@ -7258,38 +7468,38 @@ function ToolbarButtons({
|
|
|
7258
7468
|
count,
|
|
7259
7469
|
onOpen
|
|
7260
7470
|
}) {
|
|
7261
|
-
return /* @__PURE__ */
|
|
7262
|
-
perms.canCreateNode && /* @__PURE__ */
|
|
7471
|
+
return /* @__PURE__ */ jsxs25("div", { className: "flex gap-0.5", children: [
|
|
7472
|
+
perms.canCreateNode && /* @__PURE__ */ jsx27(
|
|
7263
7473
|
IconButton4,
|
|
7264
7474
|
{
|
|
7265
7475
|
label: "Add node",
|
|
7266
7476
|
variant: "outline",
|
|
7267
7477
|
disabled: count > 0,
|
|
7268
7478
|
onClick: () => onOpen("node-create"),
|
|
7269
|
-
children: /* @__PURE__ */
|
|
7479
|
+
children: /* @__PURE__ */ jsx27(Plus3, {})
|
|
7270
7480
|
}
|
|
7271
7481
|
),
|
|
7272
|
-
perms.canUpdateNode && /* @__PURE__ */
|
|
7482
|
+
perms.canUpdateNode && /* @__PURE__ */ jsx27(
|
|
7273
7483
|
IconButton4,
|
|
7274
7484
|
{
|
|
7275
7485
|
label: "Edit node",
|
|
7276
7486
|
variant: "outline",
|
|
7277
7487
|
disabled: count !== 1,
|
|
7278
7488
|
onClick: () => onOpen("node-edit"),
|
|
7279
|
-
children: /* @__PURE__ */
|
|
7489
|
+
children: /* @__PURE__ */ jsx27(Edit, {})
|
|
7280
7490
|
}
|
|
7281
7491
|
),
|
|
7282
|
-
perms.canEditEdges && /* @__PURE__ */
|
|
7492
|
+
perms.canEditEdges && /* @__PURE__ */ jsx27(
|
|
7283
7493
|
IconButton4,
|
|
7284
7494
|
{
|
|
7285
7495
|
label: "Edges",
|
|
7286
7496
|
variant: "outline",
|
|
7287
7497
|
disabled: count !== 2,
|
|
7288
7498
|
onClick: () => onOpen("edge"),
|
|
7289
|
-
children: /* @__PURE__ */
|
|
7499
|
+
children: /* @__PURE__ */ jsx27(Link, {})
|
|
7290
7500
|
}
|
|
7291
7501
|
),
|
|
7292
|
-
perms.canDeleteNode && /* @__PURE__ */
|
|
7502
|
+
perms.canDeleteNode && /* @__PURE__ */ jsx27(
|
|
7293
7503
|
IconButton4,
|
|
7294
7504
|
{
|
|
7295
7505
|
label: "Delete node",
|
|
@@ -7297,7 +7507,7 @@ function ToolbarButtons({
|
|
|
7297
7507
|
tone: "destructive",
|
|
7298
7508
|
disabled: count !== 1,
|
|
7299
7509
|
onClick: () => onOpen("delete"),
|
|
7300
|
-
children: /* @__PURE__ */
|
|
7510
|
+
children: /* @__PURE__ */ jsx27(Trash23, {})
|
|
7301
7511
|
}
|
|
7302
7512
|
)
|
|
7303
7513
|
] });
|
|
@@ -7313,14 +7523,14 @@ function ToolbarDialogs({
|
|
|
7313
7523
|
onClose,
|
|
7314
7524
|
onMutated
|
|
7315
7525
|
}) {
|
|
7316
|
-
const onChange =
|
|
7526
|
+
const onChange = useCallback12(
|
|
7317
7527
|
(o) => {
|
|
7318
7528
|
if (!o) onClose();
|
|
7319
7529
|
},
|
|
7320
7530
|
[onClose]
|
|
7321
7531
|
);
|
|
7322
|
-
return /* @__PURE__ */
|
|
7323
|
-
(perms.canCreateNode || perms.canUpdateNode) && /* @__PURE__ */
|
|
7532
|
+
return /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7533
|
+
(perms.canCreateNode || perms.canUpdateNode) && /* @__PURE__ */ jsx27(
|
|
7324
7534
|
NodeFormSheet,
|
|
7325
7535
|
{
|
|
7326
7536
|
open: dialog === "node-create" || dialog === "node-edit",
|
|
@@ -7332,7 +7542,7 @@ function ToolbarDialogs({
|
|
|
7332
7542
|
onSaved: onMutated
|
|
7333
7543
|
}
|
|
7334
7544
|
),
|
|
7335
|
-
perms.canEditEdges && firstNode && secondNode && /* @__PURE__ */
|
|
7545
|
+
perms.canEditEdges && firstNode && secondNode && /* @__PURE__ */ jsx27(
|
|
7336
7546
|
EdgeFormSheet,
|
|
7337
7547
|
{
|
|
7338
7548
|
open: dialog === "edge",
|
|
@@ -7345,7 +7555,7 @@ function ToolbarDialogs({
|
|
|
7345
7555
|
onChanged: onMutated
|
|
7346
7556
|
}
|
|
7347
7557
|
),
|
|
7348
|
-
perms.canDeleteNode && firstNode && /* @__PURE__ */
|
|
7558
|
+
perms.canDeleteNode && firstNode && /* @__PURE__ */ jsx27(
|
|
7349
7559
|
DeleteNodeDialog,
|
|
7350
7560
|
{
|
|
7351
7561
|
open: dialog === "delete",
|
|
@@ -7370,7 +7580,7 @@ function GraphEditToolbar({
|
|
|
7370
7580
|
(s) => s.selectedNodeIds
|
|
7371
7581
|
);
|
|
7372
7582
|
const live = useLiveGraphData();
|
|
7373
|
-
const [dialog, setDialog] =
|
|
7583
|
+
const [dialog, setDialog] = useState18(null);
|
|
7374
7584
|
const perms = useMemo11(
|
|
7375
7585
|
() => toPerms(resolveGraphCapabilities(capabilities, readOnly)),
|
|
7376
7586
|
[capabilities, readOnly]
|
|
@@ -7381,8 +7591,8 @@ function GraphEditToolbar({
|
|
|
7381
7591
|
);
|
|
7382
7592
|
const stableOnMutated = useStableRef(onMutated);
|
|
7383
7593
|
if (!perms.anyEditable) return null;
|
|
7384
|
-
return /* @__PURE__ */
|
|
7385
|
-
/* @__PURE__ */
|
|
7594
|
+
return /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7595
|
+
/* @__PURE__ */ jsx27(
|
|
7386
7596
|
ToolbarButtons,
|
|
7387
7597
|
{
|
|
7388
7598
|
perms,
|
|
@@ -7390,7 +7600,7 @@ function GraphEditToolbar({
|
|
|
7390
7600
|
onOpen: setDialog
|
|
7391
7601
|
}
|
|
7392
7602
|
),
|
|
7393
|
-
/* @__PURE__ */
|
|
7603
|
+
/* @__PURE__ */ jsx27(
|
|
7394
7604
|
ToolbarDialogs,
|
|
7395
7605
|
{
|
|
7396
7606
|
perms,
|
|
@@ -7406,6 +7616,662 @@ function GraphEditToolbar({
|
|
|
7406
7616
|
)
|
|
7407
7617
|
] });
|
|
7408
7618
|
}
|
|
7619
|
+
|
|
7620
|
+
// src/finder/GraphFinder.tsx
|
|
7621
|
+
import { FormSelect as FormSelect3, FormTextarea } from "@petrarca/sonnet-forms";
|
|
7622
|
+
import {
|
|
7623
|
+
Alert as Alert5,
|
|
7624
|
+
AlertDescription,
|
|
7625
|
+
AlertTitle,
|
|
7626
|
+
Button as Button11,
|
|
7627
|
+
SimpleTooltip as SimpleTooltip5
|
|
7628
|
+
} from "@petrarca/sonnet-ui";
|
|
7629
|
+
import { Search } from "lucide-react";
|
|
7630
|
+
|
|
7631
|
+
// src/finder/useFinderState.ts
|
|
7632
|
+
import { useState as useState20, useEffect as useEffect11 } from "react";
|
|
7633
|
+
import mistql from "mistql";
|
|
7634
|
+
|
|
7635
|
+
// src/finder/flattenGraphData.ts
|
|
7636
|
+
function flattenGraphData(normalized) {
|
|
7637
|
+
const flattenedNodes = normalized.nodeIds.map((id) => {
|
|
7638
|
+
const node = normalized.nodesById[id];
|
|
7639
|
+
return {
|
|
7640
|
+
...node.properties_,
|
|
7641
|
+
id_: node.id_,
|
|
7642
|
+
label_: node.label_,
|
|
7643
|
+
displayName: node.visual.displayName,
|
|
7644
|
+
color: node.visual.color
|
|
7645
|
+
};
|
|
7646
|
+
});
|
|
7647
|
+
const flattenedEdges = normalized.edgeIds.map((id) => {
|
|
7648
|
+
const edge = normalized.edgesById[id];
|
|
7649
|
+
return {
|
|
7650
|
+
...edge.properties_ || {},
|
|
7651
|
+
id_: edge.id_,
|
|
7652
|
+
label_: edge.label_,
|
|
7653
|
+
start_id_: edge.start_id_,
|
|
7654
|
+
end_id_: edge.end_id_
|
|
7655
|
+
};
|
|
7656
|
+
});
|
|
7657
|
+
const nodesByLabel = groupByLabel(flattenedNodes);
|
|
7658
|
+
const edgesByLabel = groupByLabel(flattenedEdges);
|
|
7659
|
+
return {
|
|
7660
|
+
nodes: flattenedNodes,
|
|
7661
|
+
edges: flattenedEdges,
|
|
7662
|
+
graph: [...flattenedNodes, ...flattenedEdges],
|
|
7663
|
+
_labels: Object.keys(nodesByLabel),
|
|
7664
|
+
_edgeLabels: Object.keys(edgesByLabel),
|
|
7665
|
+
...nodesByLabel,
|
|
7666
|
+
...edgesByLabel
|
|
7667
|
+
};
|
|
7668
|
+
}
|
|
7669
|
+
function groupByLabel(items) {
|
|
7670
|
+
const byLabel = {};
|
|
7671
|
+
for (const item of items) {
|
|
7672
|
+
(byLabel[item.label_] ??= []).push(item);
|
|
7673
|
+
}
|
|
7674
|
+
return byLabel;
|
|
7675
|
+
}
|
|
7676
|
+
|
|
7677
|
+
// src/finder/useGraphSearch.ts
|
|
7678
|
+
import { useRef as useRef9, useState as useState19, useEffect as useEffect10 } from "react";
|
|
7679
|
+
import { errorLog as errorLog7 } from "@petrarca/sonnet-core";
|
|
7680
|
+
|
|
7681
|
+
// src/finder/OramaSearchService.ts
|
|
7682
|
+
import { create as create8, insert, search } from "@orama/orama";
|
|
7683
|
+
|
|
7684
|
+
// src/finder/oramaSchemaBuilder.ts
|
|
7685
|
+
function buildOramaSchema() {
|
|
7686
|
+
return {
|
|
7687
|
+
id_: "string",
|
|
7688
|
+
type: "string",
|
|
7689
|
+
label_: "string",
|
|
7690
|
+
displayName: "string",
|
|
7691
|
+
searchableText: "string",
|
|
7692
|
+
properties_json: "string",
|
|
7693
|
+
isVisible: "boolean",
|
|
7694
|
+
start_id_: "string",
|
|
7695
|
+
end_id_: "string"
|
|
7696
|
+
};
|
|
7697
|
+
}
|
|
7698
|
+
function getDefaultFieldBoosting() {
|
|
7699
|
+
return {
|
|
7700
|
+
displayName: 2,
|
|
7701
|
+
searchableText: 1.5,
|
|
7702
|
+
properties_json: 1
|
|
7703
|
+
};
|
|
7704
|
+
}
|
|
7705
|
+
|
|
7706
|
+
// src/finder/oramaTransformers.ts
|
|
7707
|
+
function transformNodeToOramaDoc(node, normalized) {
|
|
7708
|
+
return {
|
|
7709
|
+
id_: String(node.id_),
|
|
7710
|
+
type: "node",
|
|
7711
|
+
label_: node.label_,
|
|
7712
|
+
displayName: node.visual.displayName || node.label_,
|
|
7713
|
+
searchableText: buildSearchableText(node),
|
|
7714
|
+
properties_json: JSON.stringify(node.properties_ || {}),
|
|
7715
|
+
isVisible: normalized ? !normalized.hiddenNodeIds.has(String(node.id_)) : true
|
|
7716
|
+
};
|
|
7717
|
+
}
|
|
7718
|
+
function transformEdgeToOramaDoc(edge, normalized) {
|
|
7719
|
+
return {
|
|
7720
|
+
id_: String(edge.id_),
|
|
7721
|
+
type: "edge",
|
|
7722
|
+
label_: edge.label_,
|
|
7723
|
+
displayName: edge.label_,
|
|
7724
|
+
searchableText: buildSearchableTextEdge(edge),
|
|
7725
|
+
properties_json: JSON.stringify(edge.properties_ || {}),
|
|
7726
|
+
isVisible: normalized ? !normalized.hiddenEdgeIds.has(String(edge.id_)) : true,
|
|
7727
|
+
start_id_: String(edge.start_id_),
|
|
7728
|
+
end_id_: String(edge.end_id_)
|
|
7729
|
+
};
|
|
7730
|
+
}
|
|
7731
|
+
function buildSearchableText(node) {
|
|
7732
|
+
const parts = [node.label_, node.visual.displayName || ""];
|
|
7733
|
+
appendPropertyValues(parts, node.properties_);
|
|
7734
|
+
return parts.filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
7735
|
+
}
|
|
7736
|
+
function buildSearchableTextEdge(edge) {
|
|
7737
|
+
const parts = [edge.label_];
|
|
7738
|
+
appendPropertyValues(parts, edge.properties_);
|
|
7739
|
+
return parts.filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
7740
|
+
}
|
|
7741
|
+
function appendPropertyValues(parts, properties) {
|
|
7742
|
+
if (!properties) return;
|
|
7743
|
+
for (const value of Object.values(properties)) {
|
|
7744
|
+
if (value == null) continue;
|
|
7745
|
+
if (Array.isArray(value)) {
|
|
7746
|
+
parts.push(...value.map(String));
|
|
7747
|
+
} else if (typeof value === "object") {
|
|
7748
|
+
parts.push(JSON.stringify(value));
|
|
7749
|
+
} else {
|
|
7750
|
+
parts.push(String(value));
|
|
7751
|
+
}
|
|
7752
|
+
}
|
|
7753
|
+
}
|
|
7754
|
+
|
|
7755
|
+
// src/finder/OramaSearchService.ts
|
|
7756
|
+
function buildWhereClause(options) {
|
|
7757
|
+
const where = {};
|
|
7758
|
+
const includeNodes = options.includeNodes ?? true;
|
|
7759
|
+
const includeEdges = options.includeEdges ?? true;
|
|
7760
|
+
if (includeNodes !== includeEdges) {
|
|
7761
|
+
where.type = includeNodes ? "node" : "edge";
|
|
7762
|
+
}
|
|
7763
|
+
const labels = options.labels;
|
|
7764
|
+
if (labels?.length) {
|
|
7765
|
+
where.label_ = labels.length === 1 ? labels[0] : { in: labels };
|
|
7766
|
+
}
|
|
7767
|
+
if (options.visibleOnly) {
|
|
7768
|
+
where.isVisible = true;
|
|
7769
|
+
}
|
|
7770
|
+
return where;
|
|
7771
|
+
}
|
|
7772
|
+
var OramaSearchService = class {
|
|
7773
|
+
db = null;
|
|
7774
|
+
config;
|
|
7775
|
+
isDirty = false;
|
|
7776
|
+
isInitialized = false;
|
|
7777
|
+
lastIndexBuild = null;
|
|
7778
|
+
stats = { totalIndexed: 0, nodesIndexed: 0, edgesIndexed: 0 };
|
|
7779
|
+
constructor(config = {}) {
|
|
7780
|
+
this.config = {
|
|
7781
|
+
debug: config.debug ?? false,
|
|
7782
|
+
maxNodes: config.maxNodes ?? 1e5,
|
|
7783
|
+
lazyInit: config.lazyInit ?? true
|
|
7784
|
+
};
|
|
7785
|
+
}
|
|
7786
|
+
// ---- lifecycle ----------------------------------------------------------
|
|
7787
|
+
/** Create the empty index with the finder schema (idempotent). */
|
|
7788
|
+
async initialize() {
|
|
7789
|
+
if (this.isInitialized) return;
|
|
7790
|
+
this.db = await create8({
|
|
7791
|
+
schema: buildOramaSchema(),
|
|
7792
|
+
components: {
|
|
7793
|
+
tokenizer: {
|
|
7794
|
+
stemming: true,
|
|
7795
|
+
stopWords: ["the", "a", "an", "and", "or", "but"]
|
|
7796
|
+
}
|
|
7797
|
+
}
|
|
7798
|
+
});
|
|
7799
|
+
this.isInitialized = true;
|
|
7800
|
+
this.isDirty = false;
|
|
7801
|
+
}
|
|
7802
|
+
/** Drop all documents (recreates the index; Orama has no bulk delete). */
|
|
7803
|
+
async clear() {
|
|
7804
|
+
if (!this.db) return;
|
|
7805
|
+
this.isInitialized = false;
|
|
7806
|
+
await this.initialize();
|
|
7807
|
+
this.stats = { totalIndexed: 0, nodesIndexed: 0, edgesIndexed: 0 };
|
|
7808
|
+
this.lastIndexBuild = null;
|
|
7809
|
+
this.isDirty = false;
|
|
7810
|
+
}
|
|
7811
|
+
/** Mark the index stale so the next search rebuilds it. */
|
|
7812
|
+
markDirty() {
|
|
7813
|
+
this.isDirty = true;
|
|
7814
|
+
}
|
|
7815
|
+
/** Whether the index needs a (re)build before searching. */
|
|
7816
|
+
needsRebuild() {
|
|
7817
|
+
return this.isDirty || !this.isInitialized;
|
|
7818
|
+
}
|
|
7819
|
+
// ---- indexing -----------------------------------------------------------
|
|
7820
|
+
/** Rebuild the whole index from the given nodes and edges. */
|
|
7821
|
+
async rebuildIndex(nodes, edges, normalized) {
|
|
7822
|
+
if (!this.isInitialized) await this.initialize();
|
|
7823
|
+
await this.clear();
|
|
7824
|
+
if (!this.db) throw new Error("Finder index not initialized");
|
|
7825
|
+
let indexedNodes = nodes;
|
|
7826
|
+
if (nodes.length > this.config.maxNodes) {
|
|
7827
|
+
if (this.config.debug) {
|
|
7828
|
+
console.warn(
|
|
7829
|
+
`[GraphFinder] node count (${nodes.length}) exceeds maxNodes (${this.config.maxNodes}); truncating`
|
|
7830
|
+
);
|
|
7831
|
+
}
|
|
7832
|
+
indexedNodes = nodes.slice(0, this.config.maxNodes);
|
|
7833
|
+
}
|
|
7834
|
+
for (const node of indexedNodes) {
|
|
7835
|
+
await insert(this.db, transformNodeToOramaDoc(node, normalized));
|
|
7836
|
+
}
|
|
7837
|
+
for (const edge of edges) {
|
|
7838
|
+
await insert(this.db, transformEdgeToOramaDoc(edge, normalized));
|
|
7839
|
+
}
|
|
7840
|
+
this.stats = {
|
|
7841
|
+
totalIndexed: indexedNodes.length + edges.length,
|
|
7842
|
+
nodesIndexed: indexedNodes.length,
|
|
7843
|
+
edgesIndexed: edges.length
|
|
7844
|
+
};
|
|
7845
|
+
this.lastIndexBuild = Date.now();
|
|
7846
|
+
this.isDirty = false;
|
|
7847
|
+
}
|
|
7848
|
+
// ---- search -------------------------------------------------------------
|
|
7849
|
+
/** Run a full-text query against the index. */
|
|
7850
|
+
async search(options) {
|
|
7851
|
+
if (!this.db || !this.isInitialized || this.isDirty) return [];
|
|
7852
|
+
const { term, limit = 50, boost } = options;
|
|
7853
|
+
const where = buildWhereClause(options);
|
|
7854
|
+
const results = await search(this.db, {
|
|
7855
|
+
term,
|
|
7856
|
+
where: Object.keys(where).length > 0 ? where : void 0,
|
|
7857
|
+
limit,
|
|
7858
|
+
boost: boost || getDefaultFieldBoosting(),
|
|
7859
|
+
tolerance: 1
|
|
7860
|
+
// allow a 1-character typo
|
|
7861
|
+
});
|
|
7862
|
+
return results.hits.map((hit) => ({
|
|
7863
|
+
document: hit.document,
|
|
7864
|
+
score: hit.score
|
|
7865
|
+
}));
|
|
7866
|
+
}
|
|
7867
|
+
// ---- status -------------------------------------------------------------
|
|
7868
|
+
/** Current index statistics. */
|
|
7869
|
+
getStats() {
|
|
7870
|
+
return {
|
|
7871
|
+
...this.stats,
|
|
7872
|
+
lastIndexBuild: this.lastIndexBuild,
|
|
7873
|
+
isReady: this.isInitialized && !this.isDirty
|
|
7874
|
+
};
|
|
7875
|
+
}
|
|
7876
|
+
/** Whether the index is ready to serve searches. */
|
|
7877
|
+
isReady() {
|
|
7878
|
+
return this.isInitialized && !this.isDirty;
|
|
7879
|
+
}
|
|
7880
|
+
};
|
|
7881
|
+
|
|
7882
|
+
// src/finder/useGraphSearch.ts
|
|
7883
|
+
function useGraphSearch() {
|
|
7884
|
+
const { baseNormalized } = useLiveGraphData();
|
|
7885
|
+
const serviceRef = useRef9(null);
|
|
7886
|
+
const [isReady, setIsReady] = useState19(false);
|
|
7887
|
+
const [isIndexing, setIsIndexing] = useState19(false);
|
|
7888
|
+
const [error, setError] = useState19(null);
|
|
7889
|
+
const [stats, setStats] = useState19(null);
|
|
7890
|
+
const lastDataKeyRef = useRef9("");
|
|
7891
|
+
useEffect10(() => {
|
|
7892
|
+
const nodeCount = Object.keys(baseNormalized.nodesById).length;
|
|
7893
|
+
const edgeCount = Object.keys(baseNormalized.edgesById).length;
|
|
7894
|
+
const currentKey = `${nodeCount}-${edgeCount}`;
|
|
7895
|
+
if (!serviceRef.current) serviceRef.current = new OramaSearchService();
|
|
7896
|
+
const service = serviceRef.current;
|
|
7897
|
+
const changed = currentKey !== lastDataKeyRef.current;
|
|
7898
|
+
if (changed && lastDataKeyRef.current !== "") {
|
|
7899
|
+
lastDataKeyRef.current = currentKey;
|
|
7900
|
+
service.markDirty();
|
|
7901
|
+
setIsReady(false);
|
|
7902
|
+
setStats(service.getStats());
|
|
7903
|
+
} else if (lastDataKeyRef.current === "") {
|
|
7904
|
+
lastDataKeyRef.current = currentKey;
|
|
7905
|
+
}
|
|
7906
|
+
}, [baseNormalized]);
|
|
7907
|
+
const ensureIndexReady = async () => {
|
|
7908
|
+
const nodes = Object.values(baseNormalized.nodesById);
|
|
7909
|
+
const edges = Object.values(baseNormalized.edgesById);
|
|
7910
|
+
const service = serviceRef.current;
|
|
7911
|
+
if (!service) return false;
|
|
7912
|
+
if (service.isReady() && !service.needsRebuild()) return true;
|
|
7913
|
+
setIsIndexing(true);
|
|
7914
|
+
setError(null);
|
|
7915
|
+
try {
|
|
7916
|
+
if (!service.isReady()) await service.initialize();
|
|
7917
|
+
await service.rebuildIndex(nodes, edges);
|
|
7918
|
+
setIsReady(true);
|
|
7919
|
+
setStats(service.getStats());
|
|
7920
|
+
return true;
|
|
7921
|
+
} catch (err) {
|
|
7922
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
7923
|
+
setIsReady(false);
|
|
7924
|
+
return false;
|
|
7925
|
+
} finally {
|
|
7926
|
+
setIsIndexing(false);
|
|
7927
|
+
}
|
|
7928
|
+
};
|
|
7929
|
+
const search2 = async (query, searchOptions) => {
|
|
7930
|
+
const term = query.trim();
|
|
7931
|
+
if (!term) return [];
|
|
7932
|
+
try {
|
|
7933
|
+
const ready = await ensureIndexReady();
|
|
7934
|
+
if (!ready || !serviceRef.current) return [];
|
|
7935
|
+
return await serviceRef.current.search({ term, ...searchOptions });
|
|
7936
|
+
} catch (err) {
|
|
7937
|
+
errorLog7("[GraphFinder] search error:", err);
|
|
7938
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
7939
|
+
return [];
|
|
7940
|
+
}
|
|
7941
|
+
};
|
|
7942
|
+
return { search: search2, isReady, isIndexing, stats, error };
|
|
7943
|
+
}
|
|
7944
|
+
|
|
7945
|
+
// src/finder/useFinderState.ts
|
|
7946
|
+
function isNodeRow(item) {
|
|
7947
|
+
return "displayName" in item && !("start_id_" in item);
|
|
7948
|
+
}
|
|
7949
|
+
function isEdgeRow(item) {
|
|
7950
|
+
return "start_id_" in item && "end_id_" in item;
|
|
7951
|
+
}
|
|
7952
|
+
function deduplicateResults(items) {
|
|
7953
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7954
|
+
const deduped = [];
|
|
7955
|
+
for (const raw of items) {
|
|
7956
|
+
if (raw && typeof raw === "object" && "id_" in raw) {
|
|
7957
|
+
const item = raw;
|
|
7958
|
+
const key = `${isEdgeRow(item) ? "edge" : "node"}:${String(item.id_)}`;
|
|
7959
|
+
if (!seen.has(key)) {
|
|
7960
|
+
seen.add(key);
|
|
7961
|
+
deduped.push(item);
|
|
7962
|
+
}
|
|
7963
|
+
} else {
|
|
7964
|
+
deduped.push(raw);
|
|
7965
|
+
}
|
|
7966
|
+
}
|
|
7967
|
+
return deduped;
|
|
7968
|
+
}
|
|
7969
|
+
function oramaHitToRow(r) {
|
|
7970
|
+
const doc = r.document;
|
|
7971
|
+
const properties = doc.properties_json ? JSON.parse(doc.properties_json) : {};
|
|
7972
|
+
return {
|
|
7973
|
+
id_: doc.id_,
|
|
7974
|
+
label_: doc.label_,
|
|
7975
|
+
displayName: doc.displayName,
|
|
7976
|
+
...doc.type === "edge" ? { start_id_: doc.start_id_, end_id_: doc.end_id_ } : {},
|
|
7977
|
+
...properties
|
|
7978
|
+
};
|
|
7979
|
+
}
|
|
7980
|
+
function useFinderState() {
|
|
7981
|
+
const useGraphFilter2 = useWorkspaceGraphFilter();
|
|
7982
|
+
const [searchMode, setSearchMode] = useState20("fulltext");
|
|
7983
|
+
const [expressionQuery, setExpressionQuery] = useState20("");
|
|
7984
|
+
const [fulltextQuery, setFulltextQuery] = useState20("");
|
|
7985
|
+
const [results, setResults] = useState20([]);
|
|
7986
|
+
const [error, setError] = useState20(null);
|
|
7987
|
+
const [hasSearched, setHasSearched] = useState20(false);
|
|
7988
|
+
const [searchInfo, setSearchInfo] = useState20("");
|
|
7989
|
+
const { baseNormalized, normalized } = useLiveGraphData();
|
|
7990
|
+
const lastDataChangeTime = useGraphFilter2((s) => s.lastDataChangeTime);
|
|
7991
|
+
const { search: fullTextSearch, isIndexing, stats } = useGraphSearch();
|
|
7992
|
+
useEffect11(() => {
|
|
7993
|
+
setExpressionQuery("");
|
|
7994
|
+
setFulltextQuery("");
|
|
7995
|
+
setResults([]);
|
|
7996
|
+
setError(null);
|
|
7997
|
+
setHasSearched(false);
|
|
7998
|
+
setSearchInfo("");
|
|
7999
|
+
}, [lastDataChangeTime]);
|
|
8000
|
+
const buildQueryData = () => {
|
|
8001
|
+
const all = flattenGraphData(baseNormalized);
|
|
8002
|
+
const visible = flattenGraphData(normalized);
|
|
8003
|
+
return {
|
|
8004
|
+
...all,
|
|
8005
|
+
vnodes: visible.nodes,
|
|
8006
|
+
vedges: visible.edges,
|
|
8007
|
+
vgraph: visible.graph
|
|
8008
|
+
};
|
|
8009
|
+
};
|
|
8010
|
+
const runExpression = () => {
|
|
8011
|
+
const result = mistql.query(expressionQuery, buildQueryData());
|
|
8012
|
+
const arr = Array.isArray(result) ? result : [result];
|
|
8013
|
+
setResults(deduplicateResults(arr));
|
|
8014
|
+
setHasSearched(true);
|
|
8015
|
+
};
|
|
8016
|
+
const runFullText = async () => {
|
|
8017
|
+
const hits = await fullTextSearch(fulltextQuery);
|
|
8018
|
+
setResults(deduplicateResults(hits.map(oramaHitToRow)));
|
|
8019
|
+
setHasSearched(true);
|
|
8020
|
+
};
|
|
8021
|
+
const runBoth = async () => {
|
|
8022
|
+
const exprResult = expressionQuery.trim() ? mistql.query(expressionQuery, buildQueryData()) : buildQueryData().graph;
|
|
8023
|
+
const exprArray = Array.isArray(exprResult) ? exprResult : [exprResult];
|
|
8024
|
+
if (!fulltextQuery.trim()) {
|
|
8025
|
+
setResults(deduplicateResults(exprArray));
|
|
8026
|
+
setSearchInfo(`${exprArray.length} items after expression filter`);
|
|
8027
|
+
setHasSearched(true);
|
|
8028
|
+
return;
|
|
8029
|
+
}
|
|
8030
|
+
const exprIds = new Set(
|
|
8031
|
+
exprArray.filter((i) => i && typeof i === "object" && "id_" in i).map((i) => String(i.id_))
|
|
8032
|
+
);
|
|
8033
|
+
const hits = await fullTextSearch(fulltextQuery);
|
|
8034
|
+
const filtered = hits.filter((h) => exprIds.has(h.document.id_));
|
|
8035
|
+
const deduped = deduplicateResults(filtered.map(oramaHitToRow));
|
|
8036
|
+
setResults(deduped);
|
|
8037
|
+
setSearchInfo(
|
|
8038
|
+
`${exprArray.length} items after expression -> ${deduped.length} matches in full-text search`
|
|
8039
|
+
);
|
|
8040
|
+
setHasSearched(true);
|
|
8041
|
+
};
|
|
8042
|
+
const activeQuery = () => {
|
|
8043
|
+
if (searchMode === "expression") return expressionQuery;
|
|
8044
|
+
if (searchMode === "fulltext") return fulltextQuery;
|
|
8045
|
+
return expressionQuery || fulltextQuery;
|
|
8046
|
+
};
|
|
8047
|
+
const runActiveMode = async () => {
|
|
8048
|
+
if (searchMode === "expression") return runExpression();
|
|
8049
|
+
if (searchMode === "fulltext") return runFullText();
|
|
8050
|
+
return runBoth();
|
|
8051
|
+
};
|
|
8052
|
+
const handleSearch = async () => {
|
|
8053
|
+
if (!activeQuery().trim()) {
|
|
8054
|
+
setError(null);
|
|
8055
|
+
setResults([]);
|
|
8056
|
+
setHasSearched(false);
|
|
8057
|
+
setSearchInfo("");
|
|
8058
|
+
return;
|
|
8059
|
+
}
|
|
8060
|
+
try {
|
|
8061
|
+
setError(null);
|
|
8062
|
+
setSearchInfo("");
|
|
8063
|
+
await runActiveMode();
|
|
8064
|
+
} catch (err) {
|
|
8065
|
+
setError(err instanceof Error ? err.message : "Search execution failed");
|
|
8066
|
+
setResults([]);
|
|
8067
|
+
setHasSearched(true);
|
|
8068
|
+
setSearchInfo("");
|
|
8069
|
+
}
|
|
8070
|
+
};
|
|
8071
|
+
return {
|
|
8072
|
+
searchMode,
|
|
8073
|
+
setSearchMode,
|
|
8074
|
+
expressionQuery,
|
|
8075
|
+
setExpressionQuery,
|
|
8076
|
+
fulltextQuery,
|
|
8077
|
+
setFulltextQuery,
|
|
8078
|
+
results,
|
|
8079
|
+
error,
|
|
8080
|
+
hasSearched,
|
|
8081
|
+
searchInfo,
|
|
8082
|
+
isIndexing,
|
|
8083
|
+
statsLabel: stats && stats.isReady ? ` - ${stats.totalIndexed} indexed` : "",
|
|
8084
|
+
handleSearch
|
|
8085
|
+
};
|
|
8086
|
+
}
|
|
8087
|
+
|
|
8088
|
+
// src/finder/GraphFinder.tsx
|
|
8089
|
+
import { Fragment as Fragment9, jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
8090
|
+
function GraphFinder() {
|
|
8091
|
+
const {
|
|
8092
|
+
searchMode,
|
|
8093
|
+
setSearchMode,
|
|
8094
|
+
expressionQuery,
|
|
8095
|
+
setExpressionQuery,
|
|
8096
|
+
fulltextQuery,
|
|
8097
|
+
setFulltextQuery,
|
|
8098
|
+
results,
|
|
8099
|
+
error,
|
|
8100
|
+
hasSearched,
|
|
8101
|
+
searchInfo,
|
|
8102
|
+
isIndexing,
|
|
8103
|
+
statsLabel,
|
|
8104
|
+
handleSearch
|
|
8105
|
+
} = useFinderState();
|
|
8106
|
+
const handleKeyDown = (e) => {
|
|
8107
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") handleSearch();
|
|
8108
|
+
};
|
|
8109
|
+
const both = searchMode === "both";
|
|
8110
|
+
return /* @__PURE__ */ jsxs26("div", { className: "h-full flex flex-col p-4", children: [
|
|
8111
|
+
/* @__PURE__ */ jsx28("div", { className: "mb-3 flex-shrink-0", children: /* @__PURE__ */ jsx28(
|
|
8112
|
+
FormSelect3,
|
|
8113
|
+
{
|
|
8114
|
+
label: "Search Mode",
|
|
8115
|
+
value: searchMode,
|
|
8116
|
+
onChange: (value) => setSearchMode(value || "fulltext"),
|
|
8117
|
+
options: [
|
|
8118
|
+
{ value: "fulltext", label: "Full-Text" },
|
|
8119
|
+
{ value: "expression", label: "Expression" },
|
|
8120
|
+
{ value: "both", label: "Both" }
|
|
8121
|
+
],
|
|
8122
|
+
clearable: false
|
|
8123
|
+
}
|
|
8124
|
+
) }),
|
|
8125
|
+
/* @__PURE__ */ jsxs26("div", { className: "mb-4 flex-shrink-0 space-y-3", children: [
|
|
8126
|
+
(searchMode === "expression" || both) && /* @__PURE__ */ jsx28(
|
|
8127
|
+
ExpressionInput,
|
|
8128
|
+
{
|
|
8129
|
+
value: expressionQuery,
|
|
8130
|
+
onChange: setExpressionQuery,
|
|
8131
|
+
onKeyDown: handleKeyDown,
|
|
8132
|
+
both
|
|
8133
|
+
}
|
|
8134
|
+
),
|
|
8135
|
+
(searchMode === "fulltext" || both) && /* @__PURE__ */ jsx28(
|
|
8136
|
+
FullTextInput,
|
|
8137
|
+
{
|
|
8138
|
+
value: fulltextQuery,
|
|
8139
|
+
onChange: setFulltextQuery,
|
|
8140
|
+
onKeyDown: handleKeyDown,
|
|
8141
|
+
onSearch: handleSearch,
|
|
8142
|
+
both,
|
|
8143
|
+
isIndexing,
|
|
8144
|
+
statsLabel
|
|
8145
|
+
}
|
|
8146
|
+
)
|
|
8147
|
+
] }),
|
|
8148
|
+
error && /* @__PURE__ */ jsxs26(Alert5, { variant: "destructive", className: "mb-4 flex-shrink-0", children: [
|
|
8149
|
+
/* @__PURE__ */ jsx28(AlertTitle, { children: "Query Error" }),
|
|
8150
|
+
/* @__PURE__ */ jsx28(AlertDescription, { children: error })
|
|
8151
|
+
] }),
|
|
8152
|
+
hasSearched && !error && /* @__PURE__ */ jsx28(ResultsPanel, { results, searchInfo })
|
|
8153
|
+
] });
|
|
8154
|
+
}
|
|
8155
|
+
function ExpressionInput({
|
|
8156
|
+
value,
|
|
8157
|
+
onChange,
|
|
8158
|
+
onKeyDown,
|
|
8159
|
+
both
|
|
8160
|
+
}) {
|
|
8161
|
+
return /* @__PURE__ */ jsxs26("div", { children: [
|
|
8162
|
+
both && /* @__PURE__ */ jsx28("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Expression filter (applied first):" }),
|
|
8163
|
+
/* @__PURE__ */ jsx28(
|
|
8164
|
+
FormTextarea,
|
|
8165
|
+
{
|
|
8166
|
+
placeholder: 'e.g., Person | filter name == "John"',
|
|
8167
|
+
value,
|
|
8168
|
+
onChange: (e) => onChange(e.target.value),
|
|
8169
|
+
onKeyDown,
|
|
8170
|
+
autosize: true,
|
|
8171
|
+
minRows: both ? 2 : 3
|
|
8172
|
+
}
|
|
8173
|
+
),
|
|
8174
|
+
!both && /* @__PURE__ */ jsx28("div", { className: "text-xs text-muted-foreground mt-1", children: "Use pipes (|) to filter and transform. Available: nodes, edges, graph, and each label." })
|
|
8175
|
+
] });
|
|
8176
|
+
}
|
|
8177
|
+
function FullTextInput({
|
|
8178
|
+
value,
|
|
8179
|
+
onChange,
|
|
8180
|
+
onKeyDown,
|
|
8181
|
+
onSearch,
|
|
8182
|
+
both,
|
|
8183
|
+
isIndexing,
|
|
8184
|
+
statsLabel
|
|
8185
|
+
}) {
|
|
8186
|
+
return /* @__PURE__ */ jsxs26("div", { children: [
|
|
8187
|
+
both && /* @__PURE__ */ jsx28("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Full-text search (on filtered results):" }),
|
|
8188
|
+
/* @__PURE__ */ jsx28(
|
|
8189
|
+
FormTextarea,
|
|
8190
|
+
{
|
|
8191
|
+
placeholder: "e.g., software engineer machine learning",
|
|
8192
|
+
value,
|
|
8193
|
+
onChange: (e) => onChange(e.target.value),
|
|
8194
|
+
onKeyDown,
|
|
8195
|
+
autosize: true,
|
|
8196
|
+
minRows: both ? 2 : 3,
|
|
8197
|
+
rightSection: /* @__PURE__ */ jsx28(SimpleTooltip5, { label: "Search", children: /* @__PURE__ */ jsx28(Button11, { variant: "ghost", size: "icon", onClick: onSearch, children: /* @__PURE__ */ jsx28(Search, { size: 16 }) }) }),
|
|
8198
|
+
rightSectionWidth: 48
|
|
8199
|
+
}
|
|
8200
|
+
),
|
|
8201
|
+
!both && /* @__PURE__ */ jsxs26("div", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
8202
|
+
"Natural language search with typo tolerance",
|
|
8203
|
+
isIndexing && " - building index...",
|
|
8204
|
+
statsLabel
|
|
8205
|
+
] })
|
|
8206
|
+
] });
|
|
8207
|
+
}
|
|
8208
|
+
function ResultsPanel({
|
|
8209
|
+
results,
|
|
8210
|
+
searchInfo
|
|
8211
|
+
}) {
|
|
8212
|
+
return /* @__PURE__ */ jsxs26("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
8213
|
+
/* @__PURE__ */ jsxs26("div", { className: "mb-2 flex-shrink-0", children: [
|
|
8214
|
+
/* @__PURE__ */ jsxs26("div", { className: "text-sm font-semibold", children: [
|
|
8215
|
+
"Results: ",
|
|
8216
|
+
results.length,
|
|
8217
|
+
" ",
|
|
8218
|
+
results.length === 1 ? "item" : "items"
|
|
8219
|
+
] }),
|
|
8220
|
+
searchInfo && /* @__PURE__ */ jsx28("div", { className: "text-xs text-muted-foreground mt-1", children: searchInfo })
|
|
8221
|
+
] }),
|
|
8222
|
+
results.length === 0 ? /* @__PURE__ */ jsx28("div", { className: "text-sm text-muted-foreground italic", children: "No results found" }) : /* @__PURE__ */ jsx28("div", { className: "space-y-2 overflow-y-auto flex-1", children: results.map((item, index) => /* @__PURE__ */ jsx28(ResultItem, { item }, resultKey(item, index))) })
|
|
8223
|
+
] });
|
|
8224
|
+
}
|
|
8225
|
+
function resultKey(item, index) {
|
|
8226
|
+
if (item && typeof item === "object" && "id_" in item) {
|
|
8227
|
+
return `${isEdgeRow(item) ? "edge" : "node"}:${String(item.id_)}`;
|
|
8228
|
+
}
|
|
8229
|
+
return String(index);
|
|
8230
|
+
}
|
|
8231
|
+
function ResultItem({ item }) {
|
|
8232
|
+
const useGraphFocus2 = useWorkspaceGraphFocus();
|
|
8233
|
+
const requestFocus = useGraphFocus2((s) => s.requestFocus);
|
|
8234
|
+
if (typeof item !== "object" || item === null) {
|
|
8235
|
+
return /* @__PURE__ */ jsx28("div", { className: "p-3 bg-muted/40 rounded border border-border", children: /* @__PURE__ */ jsx28("div", { className: "text-sm font-medium", children: String(item) }) });
|
|
8236
|
+
}
|
|
8237
|
+
const isNodeItem = isNodeRow(item);
|
|
8238
|
+
const isEdgeItem = isEdgeRow(item);
|
|
8239
|
+
const isGraphElement = isNodeItem || isEdgeItem;
|
|
8240
|
+
const focus = (shouldSelect) => {
|
|
8241
|
+
if (!isGraphElement) return;
|
|
8242
|
+
requestFocus(String(item.id_), isNodeItem ? "node" : "edge", shouldSelect);
|
|
8243
|
+
};
|
|
8244
|
+
return /* @__PURE__ */ jsx28(
|
|
8245
|
+
"div",
|
|
8246
|
+
{
|
|
8247
|
+
className: `p-3 bg-background rounded border border-border transition-colors ${isGraphElement ? "hover:border-primary hover:bg-accent cursor-pointer" : ""}`,
|
|
8248
|
+
onClick: () => focus(false),
|
|
8249
|
+
onDoubleClick: () => focus(true),
|
|
8250
|
+
title: isGraphElement ? "Click to focus, double-click to focus and select" : void 0,
|
|
8251
|
+
children: /* @__PURE__ */ jsxs26("div", { className: "flex items-start justify-between", children: [
|
|
8252
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2", children: [
|
|
8253
|
+
isNodeItem && /* @__PURE__ */ jsxs26(Fragment9, { children: [
|
|
8254
|
+
/* @__PURE__ */ jsx28("span", { className: "text-xs font-semibold px-2 py-0.5 bg-accent text-accent-foreground rounded", children: item.label_ }),
|
|
8255
|
+
/* @__PURE__ */ jsx28("span", { className: "text-sm font-medium", children: item.displayName })
|
|
8256
|
+
] }),
|
|
8257
|
+
isEdgeItem && /* @__PURE__ */ jsxs26(Fragment9, { children: [
|
|
8258
|
+
/* @__PURE__ */ jsx28("span", { className: "text-xs font-semibold px-2 py-0.5 bg-accent text-accent-foreground rounded", children: item.label_ }),
|
|
8259
|
+
/* @__PURE__ */ jsxs26("span", { className: "text-xs text-muted-foreground", children: [
|
|
8260
|
+
String(item.start_id_),
|
|
8261
|
+
" -> ",
|
|
8262
|
+
String(item.end_id_)
|
|
8263
|
+
] })
|
|
8264
|
+
] }),
|
|
8265
|
+
!isGraphElement && /* @__PURE__ */ jsx28("span", { className: "text-sm font-medium", children: "Object" })
|
|
8266
|
+
] }),
|
|
8267
|
+
isGraphElement && /* @__PURE__ */ jsxs26("span", { className: "text-xs text-muted-foreground", children: [
|
|
8268
|
+
"ID: ",
|
|
8269
|
+
String(item.id_)
|
|
8270
|
+
] })
|
|
8271
|
+
] })
|
|
8272
|
+
}
|
|
8273
|
+
);
|
|
8274
|
+
}
|
|
7409
8275
|
export {
|
|
7410
8276
|
ActionPanel_default as ActionPanel,
|
|
7411
8277
|
DeleteNodeDialog,
|
|
@@ -7414,6 +8280,7 @@ export {
|
|
|
7414
8280
|
EdgeInfoCard_default as EdgeInfoCard,
|
|
7415
8281
|
GraphA11yList,
|
|
7416
8282
|
GraphEditToolbar,
|
|
8283
|
+
GraphFinder,
|
|
7417
8284
|
GraphModelEditor,
|
|
7418
8285
|
GraphRendererProvider,
|
|
7419
8286
|
GraphStoresContext,
|
|
@@ -7422,8 +8289,11 @@ export {
|
|
|
7422
8289
|
NodeFormSheet,
|
|
7423
8290
|
NodeInfoCard_default as NodeInfoCard,
|
|
7424
8291
|
NodeTypeNameSheet,
|
|
8292
|
+
OramaSearchService,
|
|
7425
8293
|
Overview_default as Overview,
|
|
7426
8294
|
PropertyFormSheet,
|
|
8295
|
+
QueryEditor,
|
|
8296
|
+
QueryHistory,
|
|
7427
8297
|
RelationFormSheet,
|
|
7428
8298
|
TypeDetailPanel,
|
|
7429
8299
|
addEdgeType,
|
|
@@ -7438,6 +8308,7 @@ export {
|
|
|
7438
8308
|
createGraphExplorationStore,
|
|
7439
8309
|
createGraphFilterStore,
|
|
7440
8310
|
createGraphFocusStore,
|
|
8311
|
+
createQueryHistoryStore,
|
|
7441
8312
|
createSelectionStore,
|
|
7442
8313
|
deleteEdgeType,
|
|
7443
8314
|
deleteEdgeTypeProperty,
|
|
@@ -7453,9 +8324,11 @@ export {
|
|
|
7453
8324
|
enrichNodes,
|
|
7454
8325
|
enrichSchemaWithRelations,
|
|
7455
8326
|
extractDisplayLabel,
|
|
8327
|
+
extractGraphFromRows,
|
|
7456
8328
|
extractRelationFields,
|
|
7457
8329
|
findEdgeType,
|
|
7458
8330
|
findType,
|
|
8331
|
+
flattenGraphData,
|
|
7459
8332
|
graphCapabilitiesSchema,
|
|
7460
8333
|
groupEdgesByRelation,
|
|
7461
8334
|
hasProperties,
|
|
@@ -7493,6 +8366,7 @@ export {
|
|
|
7493
8366
|
useCytoscapeData,
|
|
7494
8367
|
GraphFocus_default as useGraphFocus,
|
|
7495
8368
|
useGraphRenderer,
|
|
8369
|
+
useGraphSearch,
|
|
7496
8370
|
useLiveGraphData,
|
|
7497
8371
|
useReagraphData,
|
|
7498
8372
|
useStableRef,
|