@petrarca/sonnet-graph 0.8.0 → 0.9.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 +344 -8
- package/dist/index.js +1578 -395
- package/dist/index.js.map +1 -1
- package/package.json +19 -18
package/dist/index.js
CHANGED
|
@@ -1681,7 +1681,8 @@ import {
|
|
|
1681
1681
|
useEffect as useEffect4,
|
|
1682
1682
|
useRef as useRef4,
|
|
1683
1683
|
useState as useState6,
|
|
1684
|
-
useCallback as useCallback5
|
|
1684
|
+
useCallback as useCallback5,
|
|
1685
|
+
useMemo as useMemo4
|
|
1685
1686
|
} from "react";
|
|
1686
1687
|
import { devLog as devLog8 } from "@petrarca/sonnet-core";
|
|
1687
1688
|
import {
|
|
@@ -1690,38 +1691,87 @@ import {
|
|
|
1690
1691
|
} from "reagraph";
|
|
1691
1692
|
|
|
1692
1693
|
// src/components/rea/theme.ts
|
|
1693
|
-
import { lightTheme } from "reagraph";
|
|
1694
|
+
import { darkTheme, lightTheme } from "reagraph";
|
|
1694
1695
|
var highlightColor = SELECTION_COLOR;
|
|
1695
|
-
var
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1696
|
+
var HIGHLIGHT_TEXT = { light: "#1d4ed8", dark: "#93c5fd" };
|
|
1697
|
+
function reaTheme(dark, colors) {
|
|
1698
|
+
const base = dark ? darkTheme : lightTheme;
|
|
1699
|
+
const highlightColorText = dark ? HIGHLIGHT_TEXT.dark : HIGHLIGHT_TEXT.light;
|
|
1700
|
+
return {
|
|
1701
|
+
...base,
|
|
1702
|
+
canvas: { ...base.canvas, background: colors.background },
|
|
1703
|
+
node: {
|
|
1704
|
+
...base.node,
|
|
1705
|
+
activeFill: highlightColor,
|
|
1706
|
+
label: {
|
|
1707
|
+
...base.node.label,
|
|
1708
|
+
color: colors.text,
|
|
1709
|
+
stroke: colors.background,
|
|
1710
|
+
activeColor: highlightColorText
|
|
1711
|
+
}
|
|
1712
|
+
},
|
|
1713
|
+
ring: {
|
|
1714
|
+
...base.ring,
|
|
1715
|
+
activeFill: highlightColor
|
|
1716
|
+
},
|
|
1717
|
+
edge: {
|
|
1718
|
+
...base.edge,
|
|
1719
|
+
activeFill: highlightColor,
|
|
1720
|
+
label: {
|
|
1721
|
+
...base.edge.label,
|
|
1722
|
+
color: colors.text,
|
|
1723
|
+
stroke: colors.background,
|
|
1724
|
+
activeColor: highlightColorText
|
|
1725
|
+
}
|
|
1726
|
+
},
|
|
1727
|
+
arrow: {
|
|
1728
|
+
...base.arrow,
|
|
1729
|
+
activeFill: highlightColor
|
|
1716
1730
|
}
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
// src/graph/canvasColors.ts
|
|
1735
|
+
var FALLBACK = {
|
|
1736
|
+
background: "#ffffff",
|
|
1737
|
+
text: "#020817",
|
|
1738
|
+
labelBackground: "#f1f5f9",
|
|
1739
|
+
raised: "#39445a"
|
|
1722
1740
|
};
|
|
1741
|
+
function hslToHex(triple) {
|
|
1742
|
+
const match = triple.trim().match(/^(-?[\d.]+)(?:deg)?\s+([\d.]+)%\s+([\d.]+)%$/);
|
|
1743
|
+
if (!match) return void 0;
|
|
1744
|
+
const [h, s, l] = [
|
|
1745
|
+
Number(match[1]),
|
|
1746
|
+
Number(match[2]) / 100,
|
|
1747
|
+
Number(match[3]) / 100
|
|
1748
|
+
];
|
|
1749
|
+
const a = s * Math.min(l, 1 - l);
|
|
1750
|
+
const channel = (n) => {
|
|
1751
|
+
const k = (n + h / 30) % 12;
|
|
1752
|
+
const value = l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
|
|
1753
|
+
return Math.round(value * 255).toString(16).padStart(2, "0");
|
|
1754
|
+
};
|
|
1755
|
+
return `#${channel(0)}${channel(8)}${channel(4)}`;
|
|
1756
|
+
}
|
|
1757
|
+
function withAlpha(hex, alpha) {
|
|
1758
|
+
const [r, g, b] = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16));
|
|
1759
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
1760
|
+
}
|
|
1761
|
+
function canvasColors(theme) {
|
|
1762
|
+
const style = getComputedStyle(document.documentElement);
|
|
1763
|
+
const token = (name, fallback) => hslToHex(style.getPropertyValue(name)) ?? fallback;
|
|
1764
|
+
const text = token("--foreground", FALLBACK.text);
|
|
1765
|
+
return {
|
|
1766
|
+
background: token("--background", FALLBACK.background),
|
|
1767
|
+
text,
|
|
1768
|
+
labelBackground: token("--muted", FALLBACK.labelBackground),
|
|
1769
|
+
menu: theme === "dark" ? withAlpha(token("--border-strong", FALLBACK.raised), 0.95) : withAlpha(text, 0.75)
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1723
1772
|
|
|
1724
1773
|
// src/components/rea/ReaGraph.tsx
|
|
1774
|
+
import { useTheme } from "@petrarca/sonnet-core/hooks";
|
|
1725
1775
|
import { cn } from "@petrarca/sonnet-core";
|
|
1726
1776
|
|
|
1727
1777
|
// src/components/rea/LayoutAndCameraControls.tsx
|
|
@@ -1876,7 +1926,7 @@ import { Card as Card2 } from "@petrarca/sonnet-ui";
|
|
|
1876
1926
|
import { Card, Separator } from "@petrarca/sonnet-ui";
|
|
1877
1927
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1878
1928
|
function NodeHoverInfo({ node }) {
|
|
1879
|
-
return /* @__PURE__ */ jsx6(Card, { className: "absolute top-2 left-1/2 -translate-x-1/2 bg-
|
|
1929
|
+
return /* @__PURE__ */ jsx6(Card, { className: "absolute top-2 left-1/2 -translate-x-1/2 bg-card shadow-md p-2", children: /* @__PURE__ */ jsxs5("div", { className: "flex flex-row items-center gap-2", children: [
|
|
1880
1930
|
/* @__PURE__ */ jsx6(
|
|
1881
1931
|
Separator,
|
|
1882
1932
|
{
|
|
@@ -2312,6 +2362,11 @@ function ReaGraph({
|
|
|
2312
2362
|
if (edges.length > 0) devLog8("[ReGraph] sample edge", edges[0]);
|
|
2313
2363
|
}, [nodes, edges]);
|
|
2314
2364
|
const canvas = useRef4(null);
|
|
2365
|
+
const { theme: pageTheme } = useTheme();
|
|
2366
|
+
const theme = useMemo4(
|
|
2367
|
+
() => reaTheme(pageTheme === "dark", canvasColors(pageTheme)),
|
|
2368
|
+
[pageTheme]
|
|
2369
|
+
);
|
|
2315
2370
|
const [hoveredNode, setHoveredNode] = useState6(
|
|
2316
2371
|
void 0
|
|
2317
2372
|
);
|
|
@@ -2581,7 +2636,7 @@ function ReaGraph({
|
|
|
2581
2636
|
"div",
|
|
2582
2637
|
{
|
|
2583
2638
|
className: cn(
|
|
2584
|
-
"bg-
|
|
2639
|
+
"bg-background",
|
|
2585
2640
|
fullscreen ? "fixed inset-0 z-50 w-screen h-screen p-0 m-0" : "relative w-full h-full"
|
|
2586
2641
|
),
|
|
2587
2642
|
children: [
|
|
@@ -2658,6 +2713,7 @@ import {
|
|
|
2658
2713
|
useCallback as useCallback6
|
|
2659
2714
|
} from "react";
|
|
2660
2715
|
import { devLog as devLog10, errorLog as errorLog3 } from "@petrarca/sonnet-core";
|
|
2716
|
+
import { useTheme as useTheme2 } from "@petrarca/sonnet-core/hooks";
|
|
2661
2717
|
import cytoscape from "cytoscape";
|
|
2662
2718
|
import fcose from "cytoscape-fcose";
|
|
2663
2719
|
import cola from "cytoscape-cola";
|
|
@@ -2765,7 +2821,7 @@ function CytoscapeControls({
|
|
|
2765
2821
|
onResetView,
|
|
2766
2822
|
extraToolbarContent
|
|
2767
2823
|
}) {
|
|
2768
|
-
return /* @__PURE__ */ jsxs9("div", { className: "absolute right-2 top-2 flex flex-col border bg-
|
|
2824
|
+
return /* @__PURE__ */ jsxs9("div", { className: "absolute right-2 top-2 flex flex-col border bg-background rounded-md shadow-sm z-10", children: [
|
|
2769
2825
|
/* @__PURE__ */ jsx10(RendererDropdown, {}),
|
|
2770
2826
|
/* @__PURE__ */ jsx10(
|
|
2771
2827
|
ViewControls2,
|
|
@@ -3067,7 +3123,8 @@ var createNodeContextMenu = ({
|
|
|
3067
3123
|
cy,
|
|
3068
3124
|
useGraphExploration,
|
|
3069
3125
|
onCopyNode,
|
|
3070
|
-
onExpandRequest
|
|
3126
|
+
onExpandRequest,
|
|
3127
|
+
fillColor
|
|
3071
3128
|
}) => {
|
|
3072
3129
|
devLog9("[CxtMenu] Initializing node context menu");
|
|
3073
3130
|
return cy.cxtmenu({
|
|
@@ -3136,7 +3193,7 @@ var createNodeContextMenu = ({
|
|
|
3136
3193
|
}
|
|
3137
3194
|
],
|
|
3138
3195
|
menuRadius: 60,
|
|
3139
|
-
fillColor
|
|
3196
|
+
fillColor,
|
|
3140
3197
|
activeFillColor: "rgba(59, 130, 246, 0.75)",
|
|
3141
3198
|
// blue-500
|
|
3142
3199
|
activePadding: 10,
|
|
@@ -3155,7 +3212,8 @@ var createNodeContextMenu = ({
|
|
|
3155
3212
|
};
|
|
3156
3213
|
var createEdgeContextMenu = ({
|
|
3157
3214
|
cy,
|
|
3158
|
-
useGraphExploration
|
|
3215
|
+
useGraphExploration,
|
|
3216
|
+
fillColor
|
|
3159
3217
|
}) => {
|
|
3160
3218
|
return cy.cxtmenu({
|
|
3161
3219
|
selector: "edge",
|
|
@@ -3204,7 +3262,7 @@ var createEdgeContextMenu = ({
|
|
|
3204
3262
|
],
|
|
3205
3263
|
menuRadius: 90,
|
|
3206
3264
|
// Increased for more items
|
|
3207
|
-
fillColor
|
|
3265
|
+
fillColor,
|
|
3208
3266
|
activeFillColor: "rgba(239, 68, 68, 0.75)",
|
|
3209
3267
|
// red-500
|
|
3210
3268
|
activePadding: 10,
|
|
@@ -3221,6 +3279,139 @@ var createEdgeContextMenu = ({
|
|
|
3221
3279
|
|
|
3222
3280
|
// src/components/cyto/CytoscapeGraph.tsx
|
|
3223
3281
|
import { toast as toast4 } from "sonner";
|
|
3282
|
+
|
|
3283
|
+
// src/components/cyto/stylesheet.ts
|
|
3284
|
+
function graphStylesheet(colors) {
|
|
3285
|
+
return [
|
|
3286
|
+
// Base node style with data mappers for dynamic properties
|
|
3287
|
+
{
|
|
3288
|
+
selector: "node",
|
|
3289
|
+
style: {
|
|
3290
|
+
"background-color": "data(color)",
|
|
3291
|
+
// Read color from element data
|
|
3292
|
+
"background-opacity": 0.9,
|
|
3293
|
+
width: "data(size)",
|
|
3294
|
+
// Read size from element data
|
|
3295
|
+
height: "data(size)",
|
|
3296
|
+
shape: "ellipse",
|
|
3297
|
+
label: "data(label)",
|
|
3298
|
+
// Label text on a chip, in the theme's colours
|
|
3299
|
+
color: colors.text,
|
|
3300
|
+
"font-size": "11px",
|
|
3301
|
+
// Increased from 10px
|
|
3302
|
+
"font-weight": "500",
|
|
3303
|
+
// medium: legible on the chip without shouting
|
|
3304
|
+
"text-valign": "bottom",
|
|
3305
|
+
"text-halign": "center",
|
|
3306
|
+
"text-wrap": "wrap",
|
|
3307
|
+
"text-max-width": "120px",
|
|
3308
|
+
// Increased from 100px for longer labels
|
|
3309
|
+
"text-margin-y": 5,
|
|
3310
|
+
"text-background-color": colors.labelBackground,
|
|
3311
|
+
"text-background-opacity": 1,
|
|
3312
|
+
"text-background-padding": "3px",
|
|
3313
|
+
"text-background-shape": "roundrectangle",
|
|
3314
|
+
"border-width": 1,
|
|
3315
|
+
"border-color": colors.background,
|
|
3316
|
+
"border-opacity": 0.8
|
|
3317
|
+
}
|
|
3318
|
+
},
|
|
3319
|
+
// Override background color only when fill data is present
|
|
3320
|
+
{
|
|
3321
|
+
selector: "node[fill]",
|
|
3322
|
+
style: {
|
|
3323
|
+
"background-color": "data(fill)"
|
|
3324
|
+
}
|
|
3325
|
+
},
|
|
3326
|
+
{
|
|
3327
|
+
selector: "edge",
|
|
3328
|
+
style: {
|
|
3329
|
+
width: "data(size)",
|
|
3330
|
+
// Read width from element data
|
|
3331
|
+
"line-color": "data(color)",
|
|
3332
|
+
// Read color from element data
|
|
3333
|
+
"target-arrow-color": "data(color)",
|
|
3334
|
+
"target-arrow-shape": "triangle",
|
|
3335
|
+
"curve-style": "bezier",
|
|
3336
|
+
"control-point-step-size": 40,
|
|
3337
|
+
"control-point-weight": 0.5,
|
|
3338
|
+
opacity: 0.8,
|
|
3339
|
+
"arrow-scale": 0.8,
|
|
3340
|
+
"mid-target-arrow-shape": "none",
|
|
3341
|
+
"source-endpoint": "outside-to-node-or-label",
|
|
3342
|
+
"target-endpoint": "outside-to-node-or-label"
|
|
3343
|
+
}
|
|
3344
|
+
},
|
|
3345
|
+
// Dashed edges (when dashed property is true)
|
|
3346
|
+
{
|
|
3347
|
+
selector: "edge[dashed]",
|
|
3348
|
+
style: {
|
|
3349
|
+
"line-style": "dashed"
|
|
3350
|
+
}
|
|
3351
|
+
},
|
|
3352
|
+
// Show edge labels by default with good styling
|
|
3353
|
+
{
|
|
3354
|
+
selector: "edge[label]",
|
|
3355
|
+
style: {
|
|
3356
|
+
label: "data(label)",
|
|
3357
|
+
"font-size": "10px",
|
|
3358
|
+
// Increased from 8px for better readability
|
|
3359
|
+
"font-weight": "500",
|
|
3360
|
+
// Semi-bold for better visibility
|
|
3361
|
+
"text-background-color": colors.background,
|
|
3362
|
+
"text-background-opacity": 0.9,
|
|
3363
|
+
// Increased from 0.8 for better contrast
|
|
3364
|
+
"text-background-padding": "3px",
|
|
3365
|
+
// Increased from 2px
|
|
3366
|
+
"text-background-shape": "roundrectangle",
|
|
3367
|
+
"text-rotation": "autorotate",
|
|
3368
|
+
"text-margin-y": -8,
|
|
3369
|
+
// Adjusted for larger font
|
|
3370
|
+
color: colors.text
|
|
3371
|
+
}
|
|
3372
|
+
},
|
|
3373
|
+
{
|
|
3374
|
+
selector: "edge:selected",
|
|
3375
|
+
style: {
|
|
3376
|
+
"line-color": SELECTION_COLOR,
|
|
3377
|
+
"target-arrow-color": SELECTION_COLOR,
|
|
3378
|
+
// Modest bump over the base width (~3); selection is conveyed mainly
|
|
3379
|
+
// by colour + overlay, not a slab. (Was 8, which looked oversized.)
|
|
3380
|
+
width: 4,
|
|
3381
|
+
"z-index": 999,
|
|
3382
|
+
"font-size": "11px",
|
|
3383
|
+
"font-weight": "bold",
|
|
3384
|
+
"text-background-opacity": 1,
|
|
3385
|
+
"text-background-color": colors.background,
|
|
3386
|
+
"text-background-padding": "3px",
|
|
3387
|
+
"arrow-scale": 0.9,
|
|
3388
|
+
opacity: 1,
|
|
3389
|
+
"overlay-color": SELECTION_COLOR,
|
|
3390
|
+
"overlay-opacity": 0.08
|
|
3391
|
+
}
|
|
3392
|
+
},
|
|
3393
|
+
{
|
|
3394
|
+
selector: "node:selected",
|
|
3395
|
+
style: {
|
|
3396
|
+
"border-width": 10,
|
|
3397
|
+
// thicker circle outline
|
|
3398
|
+
"border-color": SELECTION_COLOR,
|
|
3399
|
+
"border-opacity": 1,
|
|
3400
|
+
"background-opacity": 1,
|
|
3401
|
+
"text-background-opacity": 1,
|
|
3402
|
+
"text-background-color": colors.background,
|
|
3403
|
+
"text-background-padding": "4px",
|
|
3404
|
+
"overlay-color": SELECTION_COLOR,
|
|
3405
|
+
"overlay-opacity": 0.18,
|
|
3406
|
+
width: 48,
|
|
3407
|
+
// slight size bump from 40
|
|
3408
|
+
height: 48
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
];
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3414
|
+
// src/components/cyto/CytoscapeGraph.tsx
|
|
3224
3415
|
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3225
3416
|
function CytoscapeExpandOverlay({
|
|
3226
3417
|
expandRequest,
|
|
@@ -3551,8 +3742,8 @@ function computeGraphViewState({
|
|
|
3551
3742
|
showEmptyMessage: !hasNodes && !hasExplorationState,
|
|
3552
3743
|
showFilteredMessage: !hasNodes && hasExplorationState,
|
|
3553
3744
|
showControls: hasNodes || hasExplorationState,
|
|
3554
|
-
outerClass: fullscreen ? "fixed inset-0 z-50 w-screen h-screen bg-
|
|
3555
|
-
innerClass: fullscreen ? "flex-1 relative overflow-hidden bg-
|
|
3745
|
+
outerClass: fullscreen ? "fixed inset-0 z-50 w-screen h-screen bg-background flex flex-col" : "w-full h-full flex flex-col relative",
|
|
3746
|
+
innerClass: fullscreen ? "flex-1 relative overflow-hidden bg-background" : "flex-1 relative border border-border rounded-md overflow-hidden bg-background"
|
|
3556
3747
|
};
|
|
3557
3748
|
}
|
|
3558
3749
|
function useFullscreen(fitToScreen, cyRef) {
|
|
@@ -3595,10 +3786,7 @@ function setupCytoscapeEventHandlers({
|
|
|
3595
3786
|
selectedEdgeRef,
|
|
3596
3787
|
setSelectedNodeIdsStore,
|
|
3597
3788
|
setSelectedEdgeStore,
|
|
3598
|
-
clearSelectionStore
|
|
3599
|
-
useGraphExploration,
|
|
3600
|
-
onCopyNode,
|
|
3601
|
-
onExpandRequest
|
|
3789
|
+
clearSelectionStore
|
|
3602
3790
|
}) {
|
|
3603
3791
|
const updateSelectedNodeIds = (nodeIds) => {
|
|
3604
3792
|
setSelectedNodeIdsStore(nodeIds);
|
|
@@ -3684,13 +3872,6 @@ function setupCytoscapeEventHandlers({
|
|
|
3684
3872
|
cy.on("tap", (evt) => {
|
|
3685
3873
|
if (evt.target === cy) clearAll();
|
|
3686
3874
|
});
|
|
3687
|
-
createNodeContextMenu({
|
|
3688
|
-
cy,
|
|
3689
|
-
useGraphExploration,
|
|
3690
|
-
onCopyNode,
|
|
3691
|
-
onExpandRequest
|
|
3692
|
-
});
|
|
3693
|
-
createEdgeContextMenu({ cy, useGraphExploration });
|
|
3694
3875
|
}
|
|
3695
3876
|
function CytoscapeGraph({
|
|
3696
3877
|
layout: initialLayout = "auto",
|
|
@@ -3716,6 +3897,7 @@ function CytoscapeGraph({
|
|
|
3716
3897
|
const baseNormalized = live.baseNormalized;
|
|
3717
3898
|
const useGraphFilter2 = useWorkspaceGraphFilter();
|
|
3718
3899
|
const useGraphExploration = useWorkspaceGraphExploration();
|
|
3900
|
+
const { theme } = useTheme2();
|
|
3719
3901
|
const useSelection3 = useWorkspaceSelection();
|
|
3720
3902
|
const useGraphFocus2 = useWorkspaceGraphFocus();
|
|
3721
3903
|
const lastDataChangeTime = useGraphFilter2((s) => s.lastDataChangeTime);
|
|
@@ -3791,135 +3973,7 @@ function CytoscapeGraph({
|
|
|
3791
3973
|
// Shift/Cmd to add a second node (e.g. for the two-node edge action).
|
|
3792
3974
|
// This matches the conventional canvas-selection expectation.
|
|
3793
3975
|
selectionType: "single",
|
|
3794
|
-
style:
|
|
3795
|
-
// Base node style with data mappers for dynamic properties
|
|
3796
|
-
{
|
|
3797
|
-
selector: "node",
|
|
3798
|
-
style: {
|
|
3799
|
-
"background-color": "data(color)",
|
|
3800
|
-
// Read color from element data
|
|
3801
|
-
"background-opacity": 0.9,
|
|
3802
|
-
width: "data(size)",
|
|
3803
|
-
// Read size from element data
|
|
3804
|
-
height: "data(size)",
|
|
3805
|
-
shape: "ellipse",
|
|
3806
|
-
label: "data(label)",
|
|
3807
|
-
// Dark gray text for readability on subtle gray background
|
|
3808
|
-
color: "#374151",
|
|
3809
|
-
"font-size": "11px",
|
|
3810
|
-
// Increased from 10px
|
|
3811
|
-
"font-weight": "bold",
|
|
3812
|
-
"text-valign": "bottom",
|
|
3813
|
-
"text-halign": "center",
|
|
3814
|
-
"text-wrap": "wrap",
|
|
3815
|
-
"text-max-width": "120px",
|
|
3816
|
-
// Increased from 100px for longer labels
|
|
3817
|
-
"text-margin-y": 5,
|
|
3818
|
-
// Subtle light gray label background
|
|
3819
|
-
"text-background-color": "#e5e7eb",
|
|
3820
|
-
// gray-200
|
|
3821
|
-
"text-background-opacity": 1,
|
|
3822
|
-
"text-background-padding": "3px",
|
|
3823
|
-
"text-background-shape": "roundrectangle",
|
|
3824
|
-
"border-width": 1,
|
|
3825
|
-
"border-color": "#ffffff",
|
|
3826
|
-
"border-opacity": 0.8
|
|
3827
|
-
}
|
|
3828
|
-
},
|
|
3829
|
-
// Override background color only when fill data is present
|
|
3830
|
-
{
|
|
3831
|
-
selector: "node[fill]",
|
|
3832
|
-
style: {
|
|
3833
|
-
"background-color": "data(fill)"
|
|
3834
|
-
}
|
|
3835
|
-
},
|
|
3836
|
-
{
|
|
3837
|
-
selector: "edge",
|
|
3838
|
-
style: {
|
|
3839
|
-
width: "data(size)",
|
|
3840
|
-
// Read width from element data
|
|
3841
|
-
"line-color": "data(color)",
|
|
3842
|
-
// Read color from element data
|
|
3843
|
-
"target-arrow-color": "data(color)",
|
|
3844
|
-
"target-arrow-shape": "triangle",
|
|
3845
|
-
"curve-style": "bezier",
|
|
3846
|
-
"control-point-step-size": 40,
|
|
3847
|
-
"control-point-weight": 0.5,
|
|
3848
|
-
opacity: 0.8,
|
|
3849
|
-
"arrow-scale": 0.8,
|
|
3850
|
-
"mid-target-arrow-shape": "none",
|
|
3851
|
-
"source-endpoint": "outside-to-node-or-label",
|
|
3852
|
-
"target-endpoint": "outside-to-node-or-label"
|
|
3853
|
-
}
|
|
3854
|
-
},
|
|
3855
|
-
// Dashed edges (when dashed property is true)
|
|
3856
|
-
{
|
|
3857
|
-
selector: "edge[dashed]",
|
|
3858
|
-
style: {
|
|
3859
|
-
"line-style": "dashed"
|
|
3860
|
-
}
|
|
3861
|
-
},
|
|
3862
|
-
// Show edge labels by default with good styling
|
|
3863
|
-
{
|
|
3864
|
-
selector: "edge[label]",
|
|
3865
|
-
style: {
|
|
3866
|
-
label: "data(label)",
|
|
3867
|
-
"font-size": "10px",
|
|
3868
|
-
// Increased from 8px for better readability
|
|
3869
|
-
"font-weight": "500",
|
|
3870
|
-
// Semi-bold for better visibility
|
|
3871
|
-
"text-background-color": "#ffffff",
|
|
3872
|
-
"text-background-opacity": 0.9,
|
|
3873
|
-
// Increased from 0.8 for better contrast
|
|
3874
|
-
"text-background-padding": "3px",
|
|
3875
|
-
// Increased from 2px
|
|
3876
|
-
"text-background-shape": "roundrectangle",
|
|
3877
|
-
"text-rotation": "autorotate",
|
|
3878
|
-
"text-margin-y": -8,
|
|
3879
|
-
// Adjusted for larger font
|
|
3880
|
-
color: "#1a1a1a"
|
|
3881
|
-
// Darker for better contrast
|
|
3882
|
-
}
|
|
3883
|
-
},
|
|
3884
|
-
{
|
|
3885
|
-
selector: "edge:selected",
|
|
3886
|
-
style: {
|
|
3887
|
-
"line-color": SELECTION_COLOR,
|
|
3888
|
-
"target-arrow-color": SELECTION_COLOR,
|
|
3889
|
-
// Modest bump over the base width (~3); selection is conveyed mainly
|
|
3890
|
-
// by colour + overlay, not a slab. (Was 8, which looked oversized.)
|
|
3891
|
-
width: 4,
|
|
3892
|
-
"z-index": 999,
|
|
3893
|
-
"font-size": "11px",
|
|
3894
|
-
"font-weight": "bold",
|
|
3895
|
-
"text-background-opacity": 1,
|
|
3896
|
-
"text-background-color": "#ffffff",
|
|
3897
|
-
"text-background-padding": "3px",
|
|
3898
|
-
"arrow-scale": 0.9,
|
|
3899
|
-
opacity: 1,
|
|
3900
|
-
"overlay-color": SELECTION_COLOR,
|
|
3901
|
-
"overlay-opacity": 0.08
|
|
3902
|
-
}
|
|
3903
|
-
},
|
|
3904
|
-
{
|
|
3905
|
-
selector: "node:selected",
|
|
3906
|
-
style: {
|
|
3907
|
-
"border-width": 10,
|
|
3908
|
-
// thicker circle outline
|
|
3909
|
-
"border-color": SELECTION_COLOR,
|
|
3910
|
-
"border-opacity": 1,
|
|
3911
|
-
"background-opacity": 1,
|
|
3912
|
-
"text-background-opacity": 1,
|
|
3913
|
-
"text-background-color": "#ffffff",
|
|
3914
|
-
"text-background-padding": "4px",
|
|
3915
|
-
"overlay-color": SELECTION_COLOR,
|
|
3916
|
-
"overlay-opacity": 0.18,
|
|
3917
|
-
width: 48,
|
|
3918
|
-
// slight size bump from 40
|
|
3919
|
-
height: 48
|
|
3920
|
-
}
|
|
3921
|
-
}
|
|
3922
|
-
],
|
|
3976
|
+
style: graphStylesheet(canvasColors(theme)),
|
|
3923
3977
|
layout: { name: "grid", fit: true, avoidOverlap: true, condense: true },
|
|
3924
3978
|
// initial quick layout
|
|
3925
3979
|
wheelSensitivity: 0.2
|
|
@@ -3933,10 +3987,7 @@ function CytoscapeGraph({
|
|
|
3933
3987
|
selectedEdgeRef,
|
|
3934
3988
|
setSelectedNodeIdsStore,
|
|
3935
3989
|
setSelectedEdgeStore,
|
|
3936
|
-
clearSelectionStore
|
|
3937
|
-
useGraphExploration,
|
|
3938
|
-
onCopyNode,
|
|
3939
|
-
onExpandRequest: setExpandRequest
|
|
3990
|
+
clearSelectionStore
|
|
3940
3991
|
});
|
|
3941
3992
|
}
|
|
3942
3993
|
return () => {
|
|
@@ -3944,6 +3995,27 @@ function CytoscapeGraph({
|
|
|
3944
3995
|
cyRef.current = null;
|
|
3945
3996
|
};
|
|
3946
3997
|
}, []);
|
|
3998
|
+
useEffect5(() => {
|
|
3999
|
+
const cy = cyRef.current;
|
|
4000
|
+
if (!cy) return;
|
|
4001
|
+
const colors = canvasColors(theme);
|
|
4002
|
+
cy.style(graphStylesheet(colors));
|
|
4003
|
+
const menus = [
|
|
4004
|
+
createNodeContextMenu({
|
|
4005
|
+
cy,
|
|
4006
|
+
useGraphExploration,
|
|
4007
|
+
onCopyNode,
|
|
4008
|
+
onExpandRequest: setExpandRequest,
|
|
4009
|
+
fillColor: colors.menu
|
|
4010
|
+
}),
|
|
4011
|
+
createEdgeContextMenu({
|
|
4012
|
+
cy,
|
|
4013
|
+
useGraphExploration,
|
|
4014
|
+
fillColor: colors.menu
|
|
4015
|
+
})
|
|
4016
|
+
];
|
|
4017
|
+
return () => menus.forEach((menu) => menu.destroy());
|
|
4018
|
+
}, [theme, useGraphExploration, onCopyNode]);
|
|
3947
4019
|
const elementIdsRef = useRef5("");
|
|
3948
4020
|
const lastLayoutRef = useRef5("");
|
|
3949
4021
|
const lastFitPaddingRef = useRef5(fitPadding);
|
|
@@ -4090,8 +4162,8 @@ function CytoscapeGraph({
|
|
|
4090
4162
|
onClose: () => setExpandRequest(null)
|
|
4091
4163
|
}
|
|
4092
4164
|
),
|
|
4093
|
-
showEmptyMessage && /* @__PURE__ */ jsx11("div", { className: "absolute inset-0 flex items-center justify-center text-xs text-
|
|
4094
|
-
showFilteredMessage && /* @__PURE__ */ jsx11("div", { className: "absolute inset-0 flex items-center justify-center text-xs text-
|
|
4165
|
+
showEmptyMessage && /* @__PURE__ */ jsx11("div", { className: "absolute inset-0 flex items-center justify-center text-xs text-muted-foreground pointer-events-none select-none", children: "No graph data to visualize (run a query or check the filters)" }),
|
|
4166
|
+
showFilteredMessage && /* @__PURE__ */ jsx11("div", { className: "absolute inset-0 flex items-center justify-center text-xs text-muted-foreground pointer-events-none select-none", children: 'All elements are hidden or filtered (click "Reset Focus" to restore)' }),
|
|
4095
4167
|
showControls && /* @__PURE__ */ jsx11(
|
|
4096
4168
|
CytoscapeControls_default,
|
|
4097
4169
|
{
|
|
@@ -4263,7 +4335,7 @@ var EdgeInfoCard_default = EdgeInfoCard;
|
|
|
4263
4335
|
// src/components/ActionPanel/Overview.tsx
|
|
4264
4336
|
import { Badge } from "@petrarca/sonnet-ui";
|
|
4265
4337
|
import { formatNumber, devLog as devLog11 } from "@petrarca/sonnet-core";
|
|
4266
|
-
import { useMemo as
|
|
4338
|
+
import { useMemo as useMemo5 } from "react";
|
|
4267
4339
|
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4268
4340
|
function computeEdgeToNodeLabels(nodesById, edgesById) {
|
|
4269
4341
|
const mapping = {};
|
|
@@ -4542,7 +4614,7 @@ function GraphOverview({
|
|
|
4542
4614
|
}
|
|
4543
4615
|
function Overview({ nodeBuckets, edgeSectionTitle } = {}) {
|
|
4544
4616
|
const { stats, colorPalette, labelCounts, edgeLabelCounts, baseNormalized } = useLiveGraphData();
|
|
4545
|
-
const edgeToNodeLabels =
|
|
4617
|
+
const edgeToNodeLabels = useMemo5(() => {
|
|
4546
4618
|
if (!baseNormalized?.nodesById || !baseNormalized?.edgesById) return {};
|
|
4547
4619
|
return computeEdgeToNodeLabels(
|
|
4548
4620
|
baseNormalized.nodesById,
|
|
@@ -4577,7 +4649,7 @@ function Overview({ nodeBuckets, edgeSectionTitle } = {}) {
|
|
|
4577
4649
|
var Overview_default = Overview;
|
|
4578
4650
|
|
|
4579
4651
|
// src/components/ActionPanel/ActionPanel.tsx
|
|
4580
|
-
import { useMemo as
|
|
4652
|
+
import { useMemo as useMemo6 } from "react";
|
|
4581
4653
|
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4582
4654
|
function ActionPanel({ actions }) {
|
|
4583
4655
|
const useSelection3 = useWorkspaceSelection();
|
|
@@ -4586,7 +4658,7 @@ function ActionPanel({ actions }) {
|
|
|
4586
4658
|
);
|
|
4587
4659
|
const selectedEdge = useSelection3((s) => s.selectedEdge);
|
|
4588
4660
|
const live = useLiveGraphData();
|
|
4589
|
-
const selectedNodes =
|
|
4661
|
+
const selectedNodes = useMemo6(
|
|
4590
4662
|
() => selectedNodeIds.map((id) => live.normalized.nodesById[id]).filter(Boolean),
|
|
4591
4663
|
[selectedNodeIds, live.normalized]
|
|
4592
4664
|
);
|
|
@@ -4613,11 +4685,30 @@ function ActionPanel({ actions }) {
|
|
|
4613
4685
|
}
|
|
4614
4686
|
var ActionPanel_default = ActionPanel;
|
|
4615
4687
|
|
|
4688
|
+
// src/components/CenteredMessage.tsx
|
|
4689
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
4690
|
+
var TONE = {
|
|
4691
|
+
muted: "text-muted-foreground",
|
|
4692
|
+
destructive: "text-destructive"
|
|
4693
|
+
};
|
|
4694
|
+
function CenteredMessage({
|
|
4695
|
+
children,
|
|
4696
|
+
tone = "muted"
|
|
4697
|
+
}) {
|
|
4698
|
+
return /* @__PURE__ */ jsx17(
|
|
4699
|
+
"div",
|
|
4700
|
+
{
|
|
4701
|
+
className: `flex-1 flex items-center justify-center text-sm ${TONE[tone]}`,
|
|
4702
|
+
children
|
|
4703
|
+
}
|
|
4704
|
+
);
|
|
4705
|
+
}
|
|
4706
|
+
|
|
4616
4707
|
// src/components/GraphA11yList/GraphA11yList.tsx
|
|
4617
|
-
import { useCallback as useCallback7, useMemo as
|
|
4708
|
+
import { useCallback as useCallback7, useMemo as useMemo7, useRef as useRef6 } from "react";
|
|
4618
4709
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
4619
4710
|
import { cn as cn2 } from "@petrarca/sonnet-core";
|
|
4620
|
-
import { jsx as
|
|
4711
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
4621
4712
|
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";
|
|
4622
4713
|
function GraphA11yList({
|
|
4623
4714
|
visible = false,
|
|
@@ -4637,7 +4728,7 @@ function GraphA11yList({
|
|
|
4637
4728
|
const setSelectedEdge = useSelection3(
|
|
4638
4729
|
(s) => s.setSelectedEdge
|
|
4639
4730
|
);
|
|
4640
|
-
const rows =
|
|
4731
|
+
const rows = useMemo7(() => {
|
|
4641
4732
|
const nodeRows = live.nodes.map((n) => ({
|
|
4642
4733
|
kind: "node",
|
|
4643
4734
|
id: String(n.id_),
|
|
@@ -4686,19 +4777,19 @@ function GraphA11yList({
|
|
|
4686
4777
|
[activateNode, setSelectedNodeIds, setSelectedEdge]
|
|
4687
4778
|
);
|
|
4688
4779
|
const isSelected = (row) => row.kind === "node" ? selectedNodeIds.includes(row.id) : selectedEdge?.id_ === row.edge.id_;
|
|
4689
|
-
return /* @__PURE__ */
|
|
4780
|
+
return /* @__PURE__ */ jsx18(
|
|
4690
4781
|
"div",
|
|
4691
4782
|
{
|
|
4692
4783
|
role: "listbox",
|
|
4693
4784
|
"aria-label": "Graph elements",
|
|
4694
4785
|
"aria-multiselectable": true,
|
|
4695
4786
|
className: cn2(visible ? "rounded-md border" : SR_ONLY, className),
|
|
4696
|
-
children: /* @__PURE__ */
|
|
4787
|
+
children: /* @__PURE__ */ jsx18(
|
|
4697
4788
|
"div",
|
|
4698
4789
|
{
|
|
4699
4790
|
ref: parentRef,
|
|
4700
4791
|
style: { maxHeight: visible ? maxHeight : void 0, overflow: "auto" },
|
|
4701
|
-
children: /* @__PURE__ */
|
|
4792
|
+
children: /* @__PURE__ */ jsx18(
|
|
4702
4793
|
"div",
|
|
4703
4794
|
{
|
|
4704
4795
|
style: {
|
|
@@ -4710,7 +4801,7 @@ function GraphA11yList({
|
|
|
4710
4801
|
const row = rows[vi.index];
|
|
4711
4802
|
if (!row) return null;
|
|
4712
4803
|
const selected = isSelected(row);
|
|
4713
|
-
return /* @__PURE__ */
|
|
4804
|
+
return /* @__PURE__ */ jsx18(
|
|
4714
4805
|
"button",
|
|
4715
4806
|
{
|
|
4716
4807
|
type: "button",
|
|
@@ -4728,7 +4819,7 @@ function GraphA11yList({
|
|
|
4728
4819
|
height: `${vi.size}px`,
|
|
4729
4820
|
transform: `translateY(${vi.start}px)`
|
|
4730
4821
|
},
|
|
4731
|
-
children: /* @__PURE__ */
|
|
4822
|
+
children: /* @__PURE__ */ jsx18("span", { className: "truncate", children: row.label })
|
|
4732
4823
|
},
|
|
4733
4824
|
vi.key
|
|
4734
4825
|
);
|
|
@@ -4870,7 +4961,7 @@ import { useCallback as useCallback8, useEffect as useEffect6, useRef as useRef7
|
|
|
4870
4961
|
import { ResizeHandle } from "@petrarca/sonnet-ui";
|
|
4871
4962
|
|
|
4872
4963
|
// src/graph-model/ModelActionPanel.tsx
|
|
4873
|
-
import { useMemo as
|
|
4964
|
+
import { useMemo as useMemo9, useState as useState13 } from "react";
|
|
4874
4965
|
import { Button as Button8, IconButton as IconButton2 } from "@petrarca/sonnet-ui";
|
|
4875
4966
|
import { GitBranchPlus, CirclePlus, Waypoints } from "lucide-react";
|
|
4876
4967
|
|
|
@@ -5185,7 +5276,7 @@ function deleteEdgeType(model, label) {
|
|
|
5185
5276
|
}
|
|
5186
5277
|
|
|
5187
5278
|
// src/graph-model/PropertyFormSheet.tsx
|
|
5188
|
-
import { useMemo as
|
|
5279
|
+
import { useMemo as useMemo8 } from "react";
|
|
5189
5280
|
import {
|
|
5190
5281
|
Sheet,
|
|
5191
5282
|
SheetContent,
|
|
@@ -5195,7 +5286,7 @@ import {
|
|
|
5195
5286
|
SheetDescription
|
|
5196
5287
|
} from "@petrarca/sonnet-ui";
|
|
5197
5288
|
import { JsonSchemaFormRenderer } from "@petrarca/sonnet-forms";
|
|
5198
|
-
import { jsx as
|
|
5289
|
+
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
5199
5290
|
var TYPE_OPTIONS = [
|
|
5200
5291
|
"string",
|
|
5201
5292
|
"integer",
|
|
@@ -5278,14 +5369,14 @@ function PropertyFormSheet({
|
|
|
5278
5369
|
widgetOptions,
|
|
5279
5370
|
onSave
|
|
5280
5371
|
}) {
|
|
5281
|
-
const widgets =
|
|
5372
|
+
const widgets = useMemo8(
|
|
5282
5373
|
() => [...DEFAULT_WIDGETS, ...widgetOptions ?? []],
|
|
5283
5374
|
[widgetOptions]
|
|
5284
5375
|
);
|
|
5285
|
-
const schema =
|
|
5286
|
-
const data =
|
|
5376
|
+
const schema = useMemo8(() => buildSchema(widgets), [widgets]);
|
|
5377
|
+
const data = useMemo8(() => toFormData(property), [property]);
|
|
5287
5378
|
const isEdit = !!property;
|
|
5288
|
-
return /* @__PURE__ */
|
|
5379
|
+
return /* @__PURE__ */ jsx19(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs16(SheetContent, { children: [
|
|
5289
5380
|
/* @__PURE__ */ jsxs16(SheetHeader, { children: [
|
|
5290
5381
|
/* @__PURE__ */ jsxs16(SheetTitle, { children: [
|
|
5291
5382
|
isEdit ? "Edit property" : "Add property",
|
|
@@ -5294,9 +5385,9 @@ function PropertyFormSheet({
|
|
|
5294
5385
|
" ",
|
|
5295
5386
|
ownerLabel
|
|
5296
5387
|
] }),
|
|
5297
|
-
/* @__PURE__ */
|
|
5388
|
+
/* @__PURE__ */ jsx19(SheetDescription, { children: "Define the property and how it is rendered." })
|
|
5298
5389
|
] }),
|
|
5299
|
-
/* @__PURE__ */
|
|
5390
|
+
/* @__PURE__ */ jsx19(SheetBody, { children: /* @__PURE__ */ jsx19(
|
|
5300
5391
|
JsonSchemaFormRenderer,
|
|
5301
5392
|
{
|
|
5302
5393
|
schema,
|
|
@@ -5327,7 +5418,7 @@ import {
|
|
|
5327
5418
|
} from "@petrarca/sonnet-ui";
|
|
5328
5419
|
import { FormSelect } from "@petrarca/sonnet-forms";
|
|
5329
5420
|
import { ArrowRight } from "lucide-react";
|
|
5330
|
-
import { jsx as
|
|
5421
|
+
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
5331
5422
|
var CARDINALITIES = ["ONE_TO_MANY", "ONE_TO_ONE"];
|
|
5332
5423
|
function RelationTypeField({
|
|
5333
5424
|
relType,
|
|
@@ -5340,7 +5431,7 @@ function RelationTypeField({
|
|
|
5340
5431
|
);
|
|
5341
5432
|
const options = labels.map((l) => ({ value: l, label: l }));
|
|
5342
5433
|
const canCreate = edgeTypeMode === "edit";
|
|
5343
|
-
return /* @__PURE__ */
|
|
5434
|
+
return /* @__PURE__ */ jsx20(
|
|
5344
5435
|
FormSelect,
|
|
5345
5436
|
{
|
|
5346
5437
|
label: "Relation type",
|
|
@@ -5363,12 +5454,12 @@ function DirectionField({
|
|
|
5363
5454
|
onSwap
|
|
5364
5455
|
}) {
|
|
5365
5456
|
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
5366
|
-
/* @__PURE__ */
|
|
5457
|
+
/* @__PURE__ */ jsx20("label", { className: "mb-1 block text-xs font-medium", children: "Direction" }),
|
|
5367
5458
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
5368
|
-
/* @__PURE__ */
|
|
5369
|
-
/* @__PURE__ */
|
|
5370
|
-
/* @__PURE__ */
|
|
5371
|
-
canSwap && /* @__PURE__ */
|
|
5459
|
+
/* @__PURE__ */ jsx20("span", { className: "font-medium", children: source }),
|
|
5460
|
+
/* @__PURE__ */ jsx20(ArrowRight, { className: "h-4 w-4 text-muted-foreground" }),
|
|
5461
|
+
/* @__PURE__ */ jsx20("span", { className: "font-medium", children: target }),
|
|
5462
|
+
canSwap && /* @__PURE__ */ jsx20(
|
|
5372
5463
|
Button6,
|
|
5373
5464
|
{
|
|
5374
5465
|
variant: "ghost",
|
|
@@ -5386,8 +5477,8 @@ function CardinalityField({
|
|
|
5386
5477
|
onChange
|
|
5387
5478
|
}) {
|
|
5388
5479
|
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
5389
|
-
/* @__PURE__ */
|
|
5390
|
-
/* @__PURE__ */
|
|
5480
|
+
/* @__PURE__ */ jsx20("label", { className: "mb-1 block text-xs font-medium", children: "Cardinality" }),
|
|
5481
|
+
/* @__PURE__ */ jsx20("div", { className: "flex gap-2", children: CARDINALITIES.map((c) => /* @__PURE__ */ jsx20(
|
|
5391
5482
|
Button6,
|
|
5392
5483
|
{
|
|
5393
5484
|
variant: c === cardinality ? "default" : "outline",
|
|
@@ -5427,13 +5518,13 @@ function RelationFormSheet({
|
|
|
5427
5518
|
});
|
|
5428
5519
|
onOpenChange(false);
|
|
5429
5520
|
};
|
|
5430
|
-
return /* @__PURE__ */
|
|
5521
|
+
return /* @__PURE__ */ jsx20(Sheet2, { open, onOpenChange, children: /* @__PURE__ */ jsxs17(SheetContent2, { children: [
|
|
5431
5522
|
/* @__PURE__ */ jsxs17(SheetHeader2, { children: [
|
|
5432
|
-
/* @__PURE__ */
|
|
5433
|
-
/* @__PURE__ */
|
|
5523
|
+
/* @__PURE__ */ jsx20(SheetTitle2, { children: isEdit ? "Edit relation" : "Create relation" }),
|
|
5524
|
+
/* @__PURE__ */ jsx20(SheetDescription2, { children: "A relation is stored on the source node type." })
|
|
5434
5525
|
] }),
|
|
5435
5526
|
/* @__PURE__ */ jsxs17(SheetBody2, { className: "flex flex-col gap-4", children: [
|
|
5436
|
-
/* @__PURE__ */
|
|
5527
|
+
/* @__PURE__ */ jsx20(
|
|
5437
5528
|
RelationTypeField,
|
|
5438
5529
|
{
|
|
5439
5530
|
relType,
|
|
@@ -5442,7 +5533,7 @@ function RelationFormSheet({
|
|
|
5442
5533
|
edgeTypeMode
|
|
5443
5534
|
}
|
|
5444
5535
|
),
|
|
5445
|
-
/* @__PURE__ */
|
|
5536
|
+
/* @__PURE__ */ jsx20(
|
|
5446
5537
|
DirectionField,
|
|
5447
5538
|
{
|
|
5448
5539
|
source,
|
|
@@ -5451,7 +5542,7 @@ function RelationFormSheet({
|
|
|
5451
5542
|
onSwap: () => setSwapped((s) => !s)
|
|
5452
5543
|
}
|
|
5453
5544
|
),
|
|
5454
|
-
/* @__PURE__ */
|
|
5545
|
+
/* @__PURE__ */ jsx20(
|
|
5455
5546
|
CardinalityField,
|
|
5456
5547
|
{
|
|
5457
5548
|
cardinality,
|
|
@@ -5459,8 +5550,8 @@ function RelationFormSheet({
|
|
|
5459
5550
|
}
|
|
5460
5551
|
),
|
|
5461
5552
|
/* @__PURE__ */ jsxs17("div", { className: "flex justify-end gap-2 pt-2", children: [
|
|
5462
|
-
/* @__PURE__ */
|
|
5463
|
-
/* @__PURE__ */
|
|
5553
|
+
/* @__PURE__ */ jsx20(Button6, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
5554
|
+
/* @__PURE__ */ jsx20(Button6, { disabled: !canSave, onClick: handleSave, children: isEdit ? "Save" : "Create relation" })
|
|
5464
5555
|
] })
|
|
5465
5556
|
] })
|
|
5466
5557
|
] }) });
|
|
@@ -5478,7 +5569,7 @@ import {
|
|
|
5478
5569
|
Button as Button7,
|
|
5479
5570
|
Input as Input2
|
|
5480
5571
|
} from "@petrarca/sonnet-ui";
|
|
5481
|
-
import { jsx as
|
|
5572
|
+
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
5482
5573
|
function NodeTypeNameSheet({
|
|
5483
5574
|
open,
|
|
5484
5575
|
onOpenChange,
|
|
@@ -5493,15 +5584,15 @@ function NodeTypeNameSheet({
|
|
|
5493
5584
|
const duplicate = trimmed !== initial && existing.includes(trimmed);
|
|
5494
5585
|
const canSave = trimmed.length > 0 && !duplicate;
|
|
5495
5586
|
const typeNoun = noun === "edge" ? "edge type" : "node type";
|
|
5496
|
-
return /* @__PURE__ */
|
|
5587
|
+
return /* @__PURE__ */ jsx21(Sheet3, { open, onOpenChange, children: /* @__PURE__ */ jsxs18(SheetContent3, { children: [
|
|
5497
5588
|
/* @__PURE__ */ jsxs18(SheetHeader3, { children: [
|
|
5498
|
-
/* @__PURE__ */
|
|
5499
|
-
/* @__PURE__ */
|
|
5589
|
+
/* @__PURE__ */ jsx21(SheetTitle3, { children: isEdit ? `Rename ${typeNoun}` : `Add ${typeNoun}` }),
|
|
5590
|
+
/* @__PURE__ */ jsx21(SheetDescription3, { children: "The label identifies this type and its instances." })
|
|
5500
5591
|
] }),
|
|
5501
5592
|
/* @__PURE__ */ jsxs18(SheetBody3, { className: "flex flex-col gap-4", children: [
|
|
5502
5593
|
/* @__PURE__ */ jsxs18("div", { children: [
|
|
5503
|
-
/* @__PURE__ */
|
|
5504
|
-
/* @__PURE__ */
|
|
5594
|
+
/* @__PURE__ */ jsx21("label", { className: "mb-1 block text-xs font-medium", children: "Label" }),
|
|
5595
|
+
/* @__PURE__ */ jsx21(
|
|
5505
5596
|
Input2,
|
|
5506
5597
|
{
|
|
5507
5598
|
value: name,
|
|
@@ -5510,11 +5601,11 @@ function NodeTypeNameSheet({
|
|
|
5510
5601
|
autoFocus: true
|
|
5511
5602
|
}
|
|
5512
5603
|
),
|
|
5513
|
-
duplicate && /* @__PURE__ */
|
|
5604
|
+
duplicate && /* @__PURE__ */ jsx21("p", { className: "mt-1 text-xs text-destructive", children: "A type with this label already exists." })
|
|
5514
5605
|
] }),
|
|
5515
5606
|
/* @__PURE__ */ jsxs18("div", { className: "flex justify-end gap-2", children: [
|
|
5516
|
-
/* @__PURE__ */
|
|
5517
|
-
/* @__PURE__ */
|
|
5607
|
+
/* @__PURE__ */ jsx21(Button7, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
5608
|
+
/* @__PURE__ */ jsx21(
|
|
5518
5609
|
Button7,
|
|
5519
5610
|
{
|
|
5520
5611
|
disabled: !canSave,
|
|
@@ -5531,7 +5622,7 @@ function NodeTypeNameSheet({
|
|
|
5531
5622
|
}
|
|
5532
5623
|
|
|
5533
5624
|
// src/graph-model/TypeDetailPanel.tsx
|
|
5534
|
-
import { Fragment as Fragment4, jsx as
|
|
5625
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
5535
5626
|
function relationViewOf(view) {
|
|
5536
5627
|
return {
|
|
5537
5628
|
relType: view.relType,
|
|
@@ -5545,8 +5636,8 @@ function SectionTitle({
|
|
|
5545
5636
|
action
|
|
5546
5637
|
}) {
|
|
5547
5638
|
return /* @__PURE__ */ jsxs19("div", { className: "mt-4 mb-2 flex items-center gap-2", children: [
|
|
5548
|
-
/* @__PURE__ */
|
|
5549
|
-
action && /* @__PURE__ */
|
|
5639
|
+
/* @__PURE__ */ jsx22("span", { className: "heading-meta", children }),
|
|
5640
|
+
action && /* @__PURE__ */ jsx22("span", { className: "ml-auto", children: action })
|
|
5550
5641
|
] });
|
|
5551
5642
|
}
|
|
5552
5643
|
function PropertyRows({
|
|
@@ -5557,37 +5648,37 @@ function PropertyRows({
|
|
|
5557
5648
|
onDelete
|
|
5558
5649
|
}) {
|
|
5559
5650
|
if (properties.length === 0) {
|
|
5560
|
-
return /* @__PURE__ */
|
|
5651
|
+
return /* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: emptyText });
|
|
5561
5652
|
}
|
|
5562
|
-
return /* @__PURE__ */
|
|
5653
|
+
return /* @__PURE__ */ jsx22("div", { className: "rounded-lg border divide-y", children: properties.map((p) => /* @__PURE__ */ jsxs19(
|
|
5563
5654
|
"div",
|
|
5564
5655
|
{
|
|
5565
5656
|
className: "group/row flex items-center gap-2 px-3 py-2",
|
|
5566
5657
|
children: [
|
|
5567
|
-
/* @__PURE__ */
|
|
5658
|
+
/* @__PURE__ */ jsx22("span", { className: "text-sm font-medium min-w-24", children: p.name }),
|
|
5568
5659
|
/* @__PURE__ */ jsxs19("span", { className: "flex-1 font-mono text-xs text-muted-foreground", children: [
|
|
5569
5660
|
p.type,
|
|
5570
5661
|
p.widget ? ` \xB7 ${p.widget}` : ""
|
|
5571
5662
|
] }),
|
|
5572
|
-
p.required && /* @__PURE__ */
|
|
5663
|
+
p.required && /* @__PURE__ */ jsx22(Badge2, { badgeColor: "orange", children: "required" }),
|
|
5573
5664
|
editable && /* @__PURE__ */ jsxs19("span", { className: "flex gap-1", children: [
|
|
5574
|
-
/* @__PURE__ */
|
|
5665
|
+
/* @__PURE__ */ jsx22(
|
|
5575
5666
|
IconButton,
|
|
5576
5667
|
{
|
|
5577
5668
|
label: "Edit property",
|
|
5578
5669
|
revealOnHover: true,
|
|
5579
5670
|
onClick: () => onEdit(p),
|
|
5580
|
-
children: /* @__PURE__ */
|
|
5671
|
+
children: /* @__PURE__ */ jsx22(Pencil, {})
|
|
5581
5672
|
}
|
|
5582
5673
|
),
|
|
5583
|
-
/* @__PURE__ */
|
|
5674
|
+
/* @__PURE__ */ jsx22(
|
|
5584
5675
|
IconButton,
|
|
5585
5676
|
{
|
|
5586
5677
|
label: "Delete property",
|
|
5587
5678
|
tone: "destructive",
|
|
5588
5679
|
revealOnHover: true,
|
|
5589
5680
|
onClick: () => onDelete(p),
|
|
5590
|
-
children: /* @__PURE__ */
|
|
5681
|
+
children: /* @__PURE__ */ jsx22(Trash2, {})
|
|
5591
5682
|
}
|
|
5592
5683
|
)
|
|
5593
5684
|
] })
|
|
@@ -5670,7 +5761,7 @@ function TypeDetailPanel({
|
|
|
5670
5761
|
if (!onChange) return;
|
|
5671
5762
|
onChange(updateRelation(model, source, prev.relType, prev.target, input));
|
|
5672
5763
|
};
|
|
5673
|
-
const propertiesSection = propsHidden ? null : /* @__PURE__ */
|
|
5764
|
+
const propertiesSection = propsHidden ? null : /* @__PURE__ */ jsx22(
|
|
5674
5765
|
PropertiesSection,
|
|
5675
5766
|
{
|
|
5676
5767
|
view,
|
|
@@ -5681,7 +5772,7 @@ function TypeDetailPanel({
|
|
|
5681
5772
|
}
|
|
5682
5773
|
);
|
|
5683
5774
|
return /* @__PURE__ */ jsxs19("div", { children: [
|
|
5684
|
-
view.kind === "node" ? /* @__PURE__ */
|
|
5775
|
+
view.kind === "node" ? /* @__PURE__ */ jsx22(
|
|
5685
5776
|
NodeDetail,
|
|
5686
5777
|
{
|
|
5687
5778
|
view,
|
|
@@ -5693,7 +5784,7 @@ function TypeDetailPanel({
|
|
|
5693
5784
|
onDeleteRelation: removeRelation,
|
|
5694
5785
|
children: propertiesSection
|
|
5695
5786
|
}
|
|
5696
|
-
) : view.kind === "edge" ? /* @__PURE__ */
|
|
5787
|
+
) : view.kind === "edge" ? /* @__PURE__ */ jsx22(
|
|
5697
5788
|
EdgeDetail,
|
|
5698
5789
|
{
|
|
5699
5790
|
view,
|
|
@@ -5702,7 +5793,7 @@ function TypeDetailPanel({
|
|
|
5702
5793
|
onDelete: () => onChange?.(deleteEdgeType(model, view.label)),
|
|
5703
5794
|
children: propertiesSection
|
|
5704
5795
|
}
|
|
5705
|
-
) : /* @__PURE__ */
|
|
5796
|
+
) : /* @__PURE__ */ jsx22(
|
|
5706
5797
|
RelationDetail,
|
|
5707
5798
|
{
|
|
5708
5799
|
view,
|
|
@@ -5712,7 +5803,7 @@ function TypeDetailPanel({
|
|
|
5712
5803
|
children: propertiesSection
|
|
5713
5804
|
}
|
|
5714
5805
|
),
|
|
5715
|
-
editable && /* @__PURE__ */
|
|
5806
|
+
editable && /* @__PURE__ */ jsx22(
|
|
5716
5807
|
DetailSheets,
|
|
5717
5808
|
{
|
|
5718
5809
|
model,
|
|
@@ -5757,7 +5848,7 @@ function DetailSheets({
|
|
|
5757
5848
|
}) {
|
|
5758
5849
|
const edgeTypeOptions = model.filter(isEdgeType).map(typeLabel);
|
|
5759
5850
|
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5760
|
-
/* @__PURE__ */
|
|
5851
|
+
/* @__PURE__ */ jsx22(
|
|
5761
5852
|
PropertyFormSheet,
|
|
5762
5853
|
{
|
|
5763
5854
|
open: sheet.open,
|
|
@@ -5768,7 +5859,7 @@ function DetailSheets({
|
|
|
5768
5859
|
onSave: onSaveProperty
|
|
5769
5860
|
}
|
|
5770
5861
|
),
|
|
5771
|
-
relSheet && (view.kind === "node" || view.kind === "relation") && /* @__PURE__ */
|
|
5862
|
+
relSheet && (view.kind === "node" || view.kind === "relation") && /* @__PURE__ */ jsx22(
|
|
5772
5863
|
RelationFormSheet,
|
|
5773
5864
|
{
|
|
5774
5865
|
open: !!relSheet,
|
|
@@ -5785,7 +5876,7 @@ function DetailSheets({
|
|
|
5785
5876
|
},
|
|
5786
5877
|
`${relSheet.relType}:${relSheet.target}`
|
|
5787
5878
|
),
|
|
5788
|
-
(view.kind === "node" || view.kind === "edge") && renameOpen && /* @__PURE__ */
|
|
5879
|
+
(view.kind === "node" || view.kind === "edge") && renameOpen && /* @__PURE__ */ jsx22(
|
|
5789
5880
|
NodeTypeNameSheet,
|
|
5790
5881
|
{
|
|
5791
5882
|
open: renameOpen,
|
|
@@ -5807,14 +5898,14 @@ function PropertiesSection({
|
|
|
5807
5898
|
onDelete
|
|
5808
5899
|
}) {
|
|
5809
5900
|
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5810
|
-
/* @__PURE__ */
|
|
5901
|
+
/* @__PURE__ */ jsx22(
|
|
5811
5902
|
SectionTitle,
|
|
5812
5903
|
{
|
|
5813
|
-
action: editable ? /* @__PURE__ */
|
|
5904
|
+
action: editable ? /* @__PURE__ */ jsx22(IconButton, { label: "Add property", onClick: onAdd, children: /* @__PURE__ */ jsx22(Plus, {}) }) : void 0,
|
|
5814
5905
|
children: "Properties"
|
|
5815
5906
|
}
|
|
5816
5907
|
),
|
|
5817
|
-
/* @__PURE__ */
|
|
5908
|
+
/* @__PURE__ */ jsx22(
|
|
5818
5909
|
PropertyRows,
|
|
5819
5910
|
{
|
|
5820
5911
|
properties: view.properties,
|
|
@@ -5838,9 +5929,9 @@ function NodeDetail({
|
|
|
5838
5929
|
}) {
|
|
5839
5930
|
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5840
5931
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
5841
|
-
/* @__PURE__ */
|
|
5842
|
-
/* @__PURE__ */
|
|
5843
|
-
nodeTypeEditable && /* @__PURE__ */
|
|
5932
|
+
/* @__PURE__ */ jsx22("span", { className: "text-base font-semibold", children: view.label }),
|
|
5933
|
+
/* @__PURE__ */ jsx22(Badge2, { children: "NODE TYPE" }),
|
|
5934
|
+
nodeTypeEditable && /* @__PURE__ */ jsx22(
|
|
5844
5935
|
RenameDeleteActions,
|
|
5845
5936
|
{
|
|
5846
5937
|
noun: "node type",
|
|
@@ -5849,15 +5940,15 @@ function NodeDetail({
|
|
|
5849
5940
|
}
|
|
5850
5941
|
)
|
|
5851
5942
|
] }),
|
|
5852
|
-
view.description && /* @__PURE__ */
|
|
5943
|
+
view.description && /* @__PURE__ */ jsx22("p", { className: "mt-1 text-sm text-muted-foreground", children: view.description }),
|
|
5853
5944
|
children,
|
|
5854
|
-
/* @__PURE__ */
|
|
5855
|
-
view.relations.length === 0 ? /* @__PURE__ */
|
|
5945
|
+
/* @__PURE__ */ jsx22(SectionTitle, { children: "Relations" }),
|
|
5946
|
+
view.relations.length === 0 ? /* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: "No relations." }) : /* @__PURE__ */ jsx22("div", { className: "rounded-lg border divide-y", children: view.relations.map((r) => /* @__PURE__ */ jsxs19(
|
|
5856
5947
|
"div",
|
|
5857
5948
|
{
|
|
5858
5949
|
className: "group/row flex items-center gap-2 px-3 py-2",
|
|
5859
5950
|
children: [
|
|
5860
|
-
/* @__PURE__ */
|
|
5951
|
+
/* @__PURE__ */ jsx22("span", { className: "text-sm font-medium min-w-24", children: r.relType }),
|
|
5861
5952
|
/* @__PURE__ */ jsxs19("span", { className: "flex-1 font-mono text-xs text-muted-foreground", children: [
|
|
5862
5953
|
"\u2192",
|
|
5863
5954
|
" ",
|
|
@@ -5868,23 +5959,23 @@ function NodeDetail({
|
|
|
5868
5959
|
cardinalityLabel(r.cardinality)
|
|
5869
5960
|
] }),
|
|
5870
5961
|
relationsEditable && /* @__PURE__ */ jsxs19("span", { className: "flex gap-1", children: [
|
|
5871
|
-
/* @__PURE__ */
|
|
5962
|
+
/* @__PURE__ */ jsx22(
|
|
5872
5963
|
IconButton,
|
|
5873
5964
|
{
|
|
5874
5965
|
label: "Edit relation",
|
|
5875
5966
|
revealOnHover: true,
|
|
5876
5967
|
onClick: () => onEditRelation(r),
|
|
5877
|
-
children: /* @__PURE__ */
|
|
5968
|
+
children: /* @__PURE__ */ jsx22(Pencil, {})
|
|
5878
5969
|
}
|
|
5879
5970
|
),
|
|
5880
|
-
/* @__PURE__ */
|
|
5971
|
+
/* @__PURE__ */ jsx22(
|
|
5881
5972
|
IconButton,
|
|
5882
5973
|
{
|
|
5883
5974
|
label: "Delete relation",
|
|
5884
5975
|
tone: "destructive",
|
|
5885
5976
|
revealOnHover: true,
|
|
5886
5977
|
onClick: () => onDeleteRelation(r),
|
|
5887
|
-
children: /* @__PURE__ */
|
|
5978
|
+
children: /* @__PURE__ */ jsx22(Trash2, {})
|
|
5888
5979
|
}
|
|
5889
5980
|
)
|
|
5890
5981
|
] })
|
|
@@ -5897,7 +5988,7 @@ function NodeDetail({
|
|
|
5897
5988
|
function EdgeTypeNote({
|
|
5898
5989
|
children
|
|
5899
5990
|
}) {
|
|
5900
|
-
return /* @__PURE__ */
|
|
5991
|
+
return /* @__PURE__ */ jsx22("p", { className: "mt-3 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground", children });
|
|
5901
5992
|
}
|
|
5902
5993
|
function RenameDeleteActions({
|
|
5903
5994
|
noun,
|
|
@@ -5906,14 +5997,14 @@ function RenameDeleteActions({
|
|
|
5906
5997
|
onDelete
|
|
5907
5998
|
}) {
|
|
5908
5999
|
return /* @__PURE__ */ jsxs19("span", { className: "ml-auto flex gap-1", children: [
|
|
5909
|
-
/* @__PURE__ */
|
|
5910
|
-
/* @__PURE__ */
|
|
6000
|
+
/* @__PURE__ */ jsx22(IconButton, { label: `${editVerb} ${noun}`, onClick: onRename, children: /* @__PURE__ */ jsx22(Pencil, {}) }),
|
|
6001
|
+
/* @__PURE__ */ jsx22(
|
|
5911
6002
|
IconButton,
|
|
5912
6003
|
{
|
|
5913
6004
|
label: `Delete ${noun}`,
|
|
5914
6005
|
tone: "destructive",
|
|
5915
6006
|
onClick: onDelete,
|
|
5916
|
-
children: /* @__PURE__ */
|
|
6007
|
+
children: /* @__PURE__ */ jsx22(Trash2, {})
|
|
5917
6008
|
}
|
|
5918
6009
|
)
|
|
5919
6010
|
] });
|
|
@@ -5927,9 +6018,9 @@ function EdgeDetail({
|
|
|
5927
6018
|
}) {
|
|
5928
6019
|
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5929
6020
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
5930
|
-
/* @__PURE__ */
|
|
5931
|
-
/* @__PURE__ */
|
|
5932
|
-
editable && /* @__PURE__ */
|
|
6021
|
+
/* @__PURE__ */ jsx22("span", { className: "text-base font-semibold", children: view.label }),
|
|
6022
|
+
/* @__PURE__ */ jsx22(Badge2, { children: "EDGE TYPE" }),
|
|
6023
|
+
editable && /* @__PURE__ */ jsx22(
|
|
5933
6024
|
RenameDeleteActions,
|
|
5934
6025
|
{
|
|
5935
6026
|
noun: "edge type",
|
|
@@ -5938,11 +6029,11 @@ function EdgeDetail({
|
|
|
5938
6029
|
}
|
|
5939
6030
|
)
|
|
5940
6031
|
] }),
|
|
5941
|
-
view.description && /* @__PURE__ */
|
|
6032
|
+
view.description && /* @__PURE__ */ jsx22("p", { className: "mt-1 text-sm text-muted-foreground", children: view.description }),
|
|
5942
6033
|
/* @__PURE__ */ jsxs19(EdgeTypeNote, { children: [
|
|
5943
6034
|
"These properties belong to the",
|
|
5944
6035
|
" ",
|
|
5945
|
-
/* @__PURE__ */
|
|
6036
|
+
/* @__PURE__ */ jsx22("span", { className: "font-medium", children: view.label }),
|
|
5946
6037
|
" edge type and are shared by every relation of this type."
|
|
5947
6038
|
] }),
|
|
5948
6039
|
children
|
|
@@ -5957,9 +6048,9 @@ function RelationDetail({
|
|
|
5957
6048
|
}) {
|
|
5958
6049
|
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
5959
6050
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
5960
|
-
/* @__PURE__ */
|
|
5961
|
-
/* @__PURE__ */
|
|
5962
|
-
editable && /* @__PURE__ */
|
|
6051
|
+
/* @__PURE__ */ jsx22("span", { className: "text-base font-semibold", children: view.relType }),
|
|
6052
|
+
/* @__PURE__ */ jsx22(Badge2, { children: "RELATION" }),
|
|
6053
|
+
editable && /* @__PURE__ */ jsx22(
|
|
5963
6054
|
RenameDeleteActions,
|
|
5964
6055
|
{
|
|
5965
6056
|
noun: "relation",
|
|
@@ -5970,16 +6061,16 @@ function RelationDetail({
|
|
|
5970
6061
|
)
|
|
5971
6062
|
] }),
|
|
5972
6063
|
/* @__PURE__ */ jsxs19("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
5973
|
-
/* @__PURE__ */
|
|
6064
|
+
/* @__PURE__ */ jsx22("span", { className: "font-medium text-foreground", children: view.source }),
|
|
5974
6065
|
" \u2192 ",
|
|
5975
|
-
/* @__PURE__ */
|
|
6066
|
+
/* @__PURE__ */ jsx22("span", { className: "font-medium text-foreground", children: view.target }),
|
|
5976
6067
|
" \xB7 ",
|
|
5977
6068
|
cardinalityLabel(view.cardinality)
|
|
5978
6069
|
] }),
|
|
5979
6070
|
/* @__PURE__ */ jsxs19(EdgeTypeNote, { children: [
|
|
5980
6071
|
"Properties are defined on the",
|
|
5981
6072
|
" ",
|
|
5982
|
-
/* @__PURE__ */
|
|
6073
|
+
/* @__PURE__ */ jsx22("span", { className: "font-medium", children: view.relType }),
|
|
5983
6074
|
" edge type, shared by every relation of this type -- not on this single relation."
|
|
5984
6075
|
] }),
|
|
5985
6076
|
children
|
|
@@ -6044,7 +6135,7 @@ function validateCapabilities(input) {
|
|
|
6044
6135
|
}
|
|
6045
6136
|
|
|
6046
6137
|
// src/graph-model/ModelActionPanel.tsx
|
|
6047
|
-
import { Fragment as Fragment5, jsx as
|
|
6138
|
+
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
6048
6139
|
function nodeTypeLabels(model) {
|
|
6049
6140
|
return model.filter(isNodeType).map(typeLabel);
|
|
6050
6141
|
}
|
|
@@ -6061,16 +6152,16 @@ function CreateRelationPrompt({
|
|
|
6061
6152
|
const [open, setOpen] = useState13(false);
|
|
6062
6153
|
return /* @__PURE__ */ jsxs20("div", { children: [
|
|
6063
6154
|
/* @__PURE__ */ jsxs20("div", { className: "text-sm", children: [
|
|
6064
|
-
/* @__PURE__ */
|
|
6155
|
+
/* @__PURE__ */ jsx23("span", { className: "font-medium", children: nodeA }),
|
|
6065
6156
|
" and ",
|
|
6066
|
-
/* @__PURE__ */
|
|
6157
|
+
/* @__PURE__ */ jsx23("span", { className: "font-medium", children: nodeB }),
|
|
6067
6158
|
" selected."
|
|
6068
6159
|
] }),
|
|
6069
6160
|
/* @__PURE__ */ jsxs20(Button8, { size: "sm", className: "mt-3 gap-1.5", onClick: () => setOpen(true), children: [
|
|
6070
|
-
/* @__PURE__ */
|
|
6161
|
+
/* @__PURE__ */ jsx23(GitBranchPlus, { className: "h-4 w-4" }),
|
|
6071
6162
|
"Create relation"
|
|
6072
6163
|
] }),
|
|
6073
|
-
/* @__PURE__ */
|
|
6164
|
+
/* @__PURE__ */ jsx23(
|
|
6074
6165
|
RelationFormSheet,
|
|
6075
6166
|
{
|
|
6076
6167
|
open,
|
|
@@ -6099,7 +6190,7 @@ function ModelActionPanel({
|
|
|
6099
6190
|
const selectedEdge = useSelection3((s) => s.selectedEdge);
|
|
6100
6191
|
const live = useLiveGraphData();
|
|
6101
6192
|
const labelsById = (ids) => ids.map((id) => live.normalized.nodesById[id]?.label_).filter((l) => !!l);
|
|
6102
|
-
const selection =
|
|
6193
|
+
const selection = useMemo9(() => {
|
|
6103
6194
|
if (selectedEdge) {
|
|
6104
6195
|
const r = resolveRelationEdge(selectedEdge);
|
|
6105
6196
|
if (r) {
|
|
@@ -6126,7 +6217,7 @@ function ModelActionPanel({
|
|
|
6126
6217
|
const schema = findType(model, l);
|
|
6127
6218
|
return schema ? isNodeType(schema) : false;
|
|
6128
6219
|
}) : [];
|
|
6129
|
-
return /* @__PURE__ */
|
|
6220
|
+
return /* @__PURE__ */ jsx23("div", { className: "h-full overflow-auto p-4", children: /* @__PURE__ */ jsx23(
|
|
6130
6221
|
PanelBody,
|
|
6131
6222
|
{
|
|
6132
6223
|
model,
|
|
@@ -6149,7 +6240,7 @@ function PanelBody({
|
|
|
6149
6240
|
twoLabels
|
|
6150
6241
|
}) {
|
|
6151
6242
|
if (selection) {
|
|
6152
|
-
return /* @__PURE__ */
|
|
6243
|
+
return /* @__PURE__ */ jsx23(
|
|
6153
6244
|
TypeDetailPanel,
|
|
6154
6245
|
{
|
|
6155
6246
|
model,
|
|
@@ -6163,7 +6254,7 @@ function PanelBody({
|
|
|
6163
6254
|
}
|
|
6164
6255
|
const canEdit = !readOnly && !!onChange;
|
|
6165
6256
|
if (twoLabels.length === 2 && canEdit && caps.relations === "edit") {
|
|
6166
|
-
return /* @__PURE__ */
|
|
6257
|
+
return /* @__PURE__ */ jsx23(
|
|
6167
6258
|
CreateRelationPrompt,
|
|
6168
6259
|
{
|
|
6169
6260
|
nodeA: twoLabels[0],
|
|
@@ -6175,7 +6266,7 @@ function PanelBody({
|
|
|
6175
6266
|
);
|
|
6176
6267
|
}
|
|
6177
6268
|
return /* @__PURE__ */ jsxs20(Fragment5, { children: [
|
|
6178
|
-
canEdit && /* @__PURE__ */
|
|
6269
|
+
canEdit && /* @__PURE__ */ jsx23(
|
|
6179
6270
|
AddTypeToolbar,
|
|
6180
6271
|
{
|
|
6181
6272
|
model,
|
|
@@ -6184,7 +6275,7 @@ function PanelBody({
|
|
|
6184
6275
|
canAddEdge: caps.edgeTypes === "edit"
|
|
6185
6276
|
}
|
|
6186
6277
|
),
|
|
6187
|
-
/* @__PURE__ */
|
|
6278
|
+
/* @__PURE__ */ jsx23(
|
|
6188
6279
|
Overview_default,
|
|
6189
6280
|
{
|
|
6190
6281
|
nodeBuckets: [
|
|
@@ -6205,7 +6296,7 @@ function AddTypeIconButton({
|
|
|
6205
6296
|
}) {
|
|
6206
6297
|
const [open, setOpen] = useState13(false);
|
|
6207
6298
|
return /* @__PURE__ */ jsxs20(Fragment5, { children: [
|
|
6208
|
-
/* @__PURE__ */
|
|
6299
|
+
/* @__PURE__ */ jsx23(
|
|
6209
6300
|
IconButton2,
|
|
6210
6301
|
{
|
|
6211
6302
|
label: tooltip,
|
|
@@ -6214,7 +6305,7 @@ function AddTypeIconButton({
|
|
|
6214
6305
|
children: icon
|
|
6215
6306
|
}
|
|
6216
6307
|
),
|
|
6217
|
-
/* @__PURE__ */
|
|
6308
|
+
/* @__PURE__ */ jsx23(
|
|
6218
6309
|
NodeTypeNameSheet,
|
|
6219
6310
|
{
|
|
6220
6311
|
open,
|
|
@@ -6235,21 +6326,21 @@ function AddTypeToolbar({
|
|
|
6235
6326
|
if (!canAddNode && !canAddEdge) return null;
|
|
6236
6327
|
const existing = model.map(typeLabel);
|
|
6237
6328
|
return /* @__PURE__ */ jsxs20("div", { className: "mb-3 flex gap-1.5", children: [
|
|
6238
|
-
canAddNode && /* @__PURE__ */
|
|
6329
|
+
canAddNode && /* @__PURE__ */ jsx23(
|
|
6239
6330
|
AddTypeIconButton,
|
|
6240
6331
|
{
|
|
6241
6332
|
tooltip: "Add node type",
|
|
6242
|
-
icon: /* @__PURE__ */
|
|
6333
|
+
icon: /* @__PURE__ */ jsx23(CirclePlus, {}),
|
|
6243
6334
|
noun: "node",
|
|
6244
6335
|
existing,
|
|
6245
6336
|
onSave: (name) => onChange(addNodeType(model, name))
|
|
6246
6337
|
}
|
|
6247
6338
|
),
|
|
6248
|
-
canAddEdge && /* @__PURE__ */
|
|
6339
|
+
canAddEdge && /* @__PURE__ */ jsx23(
|
|
6249
6340
|
AddTypeIconButton,
|
|
6250
6341
|
{
|
|
6251
6342
|
tooltip: "Add edge type",
|
|
6252
|
-
icon: /* @__PURE__ */
|
|
6343
|
+
icon: /* @__PURE__ */ jsx23(Waypoints, {}),
|
|
6253
6344
|
noun: "edge",
|
|
6254
6345
|
existing,
|
|
6255
6346
|
onSave: (name) => onChange(addEdgeType(model, name))
|
|
@@ -6259,7 +6350,7 @@ function AddTypeToolbar({
|
|
|
6259
6350
|
}
|
|
6260
6351
|
|
|
6261
6352
|
// src/graph-model/GraphModelEditor.tsx
|
|
6262
|
-
import { Fragment as Fragment6, jsx as
|
|
6353
|
+
import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
6263
6354
|
function createEditorStores() {
|
|
6264
6355
|
const graphFilter = createGraphFilterStore();
|
|
6265
6356
|
const graphData = createGraphDataStore();
|
|
@@ -6334,10 +6425,10 @@ function GraphModelEditor({
|
|
|
6334
6425
|
window.addEventListener("pointermove", move);
|
|
6335
6426
|
window.addEventListener("pointerup", up);
|
|
6336
6427
|
}, []);
|
|
6337
|
-
return /* @__PURE__ */
|
|
6338
|
-
/* @__PURE__ */
|
|
6428
|
+
return /* @__PURE__ */ jsx24(GraphStoresContext.Provider, { value: stores, children: /* @__PURE__ */ jsx24(GraphRendererProvider, { defaultRenderer, children: /* @__PURE__ */ jsxs21("div", { ref: rowRef, className: "flex w-full h-full overflow-hidden", children: [
|
|
6429
|
+
/* @__PURE__ */ jsx24("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx24(GraphVisualizer_default, {}) }),
|
|
6339
6430
|
!hideActionPanel && /* @__PURE__ */ jsxs21(Fragment6, { children: [
|
|
6340
|
-
/* @__PURE__ */
|
|
6431
|
+
/* @__PURE__ */ jsx24(
|
|
6341
6432
|
ResizeHandle,
|
|
6342
6433
|
{
|
|
6343
6434
|
orientation: "vertical",
|
|
@@ -6348,12 +6439,12 @@ function GraphModelEditor({
|
|
|
6348
6439
|
onDoubleClick: () => setPanelWidth(380)
|
|
6349
6440
|
}
|
|
6350
6441
|
),
|
|
6351
|
-
/* @__PURE__ */
|
|
6442
|
+
/* @__PURE__ */ jsx24(
|
|
6352
6443
|
"div",
|
|
6353
6444
|
{
|
|
6354
6445
|
style: { width: panelWidth },
|
|
6355
6446
|
className: "shrink-0 border-l overflow-hidden bg-card",
|
|
6356
|
-
children: /* @__PURE__ */
|
|
6447
|
+
children: /* @__PURE__ */ jsx24(
|
|
6357
6448
|
ModelActionPanel,
|
|
6358
6449
|
{
|
|
6359
6450
|
model: value,
|
|
@@ -6517,7 +6608,7 @@ function enrichSchemaWithRelations(baseSchema, relations) {
|
|
|
6517
6608
|
}
|
|
6518
6609
|
|
|
6519
6610
|
// src/graph-edit/GraphEditToolbar.tsx
|
|
6520
|
-
import { useCallback as useCallback12, useMemo as
|
|
6611
|
+
import { useCallback as useCallback12, useMemo as useMemo12, useState as useState18 } from "react";
|
|
6521
6612
|
import { IconButton as IconButton4 } from "@petrarca/sonnet-ui";
|
|
6522
6613
|
import { Plus as Plus3, Edit, Link, Trash2 as Trash23 } from "lucide-react";
|
|
6523
6614
|
|
|
@@ -6525,7 +6616,7 @@ import { Plus as Plus3, Edit, Link, Trash2 as Trash23 } from "lucide-react";
|
|
|
6525
6616
|
import {
|
|
6526
6617
|
useCallback as useCallback9,
|
|
6527
6618
|
useEffect as useEffect7,
|
|
6528
|
-
useMemo as
|
|
6619
|
+
useMemo as useMemo10,
|
|
6529
6620
|
useRef as useRef8,
|
|
6530
6621
|
useState as useState15
|
|
6531
6622
|
} from "react";
|
|
@@ -6544,7 +6635,7 @@ import {
|
|
|
6544
6635
|
JsonSchemaFormRenderer as JsonSchemaFormRenderer2
|
|
6545
6636
|
} from "@petrarca/sonnet-forms";
|
|
6546
6637
|
import { errorLog as errorLog4 } from "@petrarca/sonnet-core";
|
|
6547
|
-
import { Fragment as Fragment7, jsx as
|
|
6638
|
+
import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
6548
6639
|
var EMPTY_RESOLVED = {
|
|
6549
6640
|
schema: null,
|
|
6550
6641
|
uiSchema: {},
|
|
@@ -6656,11 +6747,11 @@ function LabelField({
|
|
|
6656
6747
|
}) {
|
|
6657
6748
|
if (isEdit) {
|
|
6658
6749
|
return /* @__PURE__ */ jsxs22("div", { children: [
|
|
6659
|
-
/* @__PURE__ */
|
|
6660
|
-
/* @__PURE__ */
|
|
6750
|
+
/* @__PURE__ */ jsx25("span", { className: "heading-meta block", children: "Label" }),
|
|
6751
|
+
/* @__PURE__ */ jsx25("span", { className: "text-sm text-muted-foreground", children: selectedLabel })
|
|
6661
6752
|
] });
|
|
6662
6753
|
}
|
|
6663
|
-
return /* @__PURE__ */
|
|
6754
|
+
return /* @__PURE__ */ jsx25(
|
|
6664
6755
|
FormSelect2,
|
|
6665
6756
|
{
|
|
6666
6757
|
label: "Label",
|
|
@@ -6695,7 +6786,7 @@ function NodeForm({
|
|
|
6695
6786
|
onSave,
|
|
6696
6787
|
onCancel
|
|
6697
6788
|
}) {
|
|
6698
|
-
return /* @__PURE__ */
|
|
6789
|
+
return /* @__PURE__ */ jsx25(
|
|
6699
6790
|
JsonSchemaFormRenderer2,
|
|
6700
6791
|
{
|
|
6701
6792
|
schema,
|
|
@@ -6731,11 +6822,11 @@ function NodeFormSheetBody({
|
|
|
6731
6822
|
}) {
|
|
6732
6823
|
return /* @__PURE__ */ jsxs22(Fragment7, { children: [
|
|
6733
6824
|
/* @__PURE__ */ jsxs22(SheetHeader4, { children: [
|
|
6734
|
-
/* @__PURE__ */
|
|
6735
|
-
/* @__PURE__ */
|
|
6825
|
+
/* @__PURE__ */ jsx25(SheetTitle4, { children: isEdit ? "Edit node" : "Add node" }),
|
|
6826
|
+
/* @__PURE__ */ jsx25(SheetDescription4, { children: isEdit ? "Edit this node's properties and relations." : "Create a node and (optionally) its relations." })
|
|
6736
6827
|
] }),
|
|
6737
6828
|
/* @__PURE__ */ jsxs22(SheetBody4, { className: "flex flex-col gap-4", children: [
|
|
6738
|
-
/* @__PURE__ */
|
|
6829
|
+
/* @__PURE__ */ jsx25(
|
|
6739
6830
|
LabelField,
|
|
6740
6831
|
{
|
|
6741
6832
|
isEdit,
|
|
@@ -6744,7 +6835,7 @@ function NodeFormSheetBody({
|
|
|
6744
6835
|
onSelect: onSelectLabel
|
|
6745
6836
|
}
|
|
6746
6837
|
),
|
|
6747
|
-
schema && /* @__PURE__ */
|
|
6838
|
+
schema && /* @__PURE__ */ jsx25(
|
|
6748
6839
|
NodeForm,
|
|
6749
6840
|
{
|
|
6750
6841
|
formKey,
|
|
@@ -6757,7 +6848,7 @@ function NodeFormSheetBody({
|
|
|
6757
6848
|
onCancel
|
|
6758
6849
|
}
|
|
6759
6850
|
),
|
|
6760
|
-
!isEdit && /* @__PURE__ */
|
|
6851
|
+
!isEdit && /* @__PURE__ */ jsx25(
|
|
6761
6852
|
FormCheckbox,
|
|
6762
6853
|
{
|
|
6763
6854
|
label: "Create another node",
|
|
@@ -6765,7 +6856,7 @@ function NodeFormSheetBody({
|
|
|
6765
6856
|
onChange: (c) => onKeepOpenChange(c === true)
|
|
6766
6857
|
}
|
|
6767
6858
|
),
|
|
6768
|
-
error && /* @__PURE__ */
|
|
6859
|
+
error && /* @__PURE__ */ jsx25(Alert2, { variant: "destructive", children: error })
|
|
6769
6860
|
] })
|
|
6770
6861
|
] });
|
|
6771
6862
|
}
|
|
@@ -6800,7 +6891,7 @@ function NodeFormSheet({
|
|
|
6800
6891
|
node
|
|
6801
6892
|
);
|
|
6802
6893
|
const existingData = useExistingFormData(port, node, relationTypes);
|
|
6803
|
-
const formData =
|
|
6894
|
+
const formData = useMemo10(() => existingData ?? {}, [existingData]);
|
|
6804
6895
|
const stableOnSaved = useStableRef(onSaved);
|
|
6805
6896
|
const stableOnOpenChange = useStableRef(onOpenChange);
|
|
6806
6897
|
const handleSave = useCallback9(
|
|
@@ -6836,7 +6927,7 @@ function NodeFormSheet({
|
|
|
6836
6927
|
stableOnOpenChange
|
|
6837
6928
|
]
|
|
6838
6929
|
);
|
|
6839
|
-
return /* @__PURE__ */
|
|
6930
|
+
return /* @__PURE__ */ jsx25(Sheet4, { open, onOpenChange, children: /* @__PURE__ */ jsx25(SheetContent4, { children: /* @__PURE__ */ jsx25(
|
|
6840
6931
|
NodeFormSheetBody,
|
|
6841
6932
|
{
|
|
6842
6933
|
isEdit,
|
|
@@ -6893,7 +6984,7 @@ async function saveNode({
|
|
|
6893
6984
|
}
|
|
6894
6985
|
|
|
6895
6986
|
// src/graph-edit/EdgeFormSheet.tsx
|
|
6896
|
-
import { useCallback as useCallback10, useEffect as useEffect8, useMemo as
|
|
6987
|
+
import { useCallback as useCallback10, useEffect as useEffect8, useMemo as useMemo11, useState as useState16 } from "react";
|
|
6897
6988
|
import {
|
|
6898
6989
|
Sheet as Sheet5,
|
|
6899
6990
|
SheetContent as SheetContent5,
|
|
@@ -6916,7 +7007,7 @@ import {
|
|
|
6916
7007
|
JsonSchemaFormRenderer as JsonSchemaFormRenderer3
|
|
6917
7008
|
} from "@petrarca/sonnet-forms";
|
|
6918
7009
|
import { errorLog as errorLog5 } from "@petrarca/sonnet-core";
|
|
6919
|
-
import { jsx as
|
|
7010
|
+
import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
6920
7011
|
function usePairState(port, schemaProvider, open, nodeAId, nodeALabel, nodeBId, nodeBLabel, reloadKey) {
|
|
6921
7012
|
const [active, setActive] = useState16([]);
|
|
6922
7013
|
const [available, setAvailable] = useState16([]);
|
|
@@ -6986,7 +7077,7 @@ var EMPTY_EDGE_SCHEMA = {
|
|
|
6986
7077
|
};
|
|
6987
7078
|
function useEdgeSchema(schemaProvider, draft) {
|
|
6988
7079
|
const [schema, setSchema] = useState16(null);
|
|
6989
|
-
const label =
|
|
7080
|
+
const label = useMemo11(() => draftLabel(draft), [draft]);
|
|
6990
7081
|
useEffect8(() => {
|
|
6991
7082
|
let cancelled = false;
|
|
6992
7083
|
if (!label) {
|
|
@@ -7008,7 +7099,7 @@ function useEdgeSchema(schemaProvider, draft) {
|
|
|
7008
7099
|
}
|
|
7009
7100
|
function useEditableEdgeTypes(schemaProvider, active) {
|
|
7010
7101
|
const [editable, setEditable] = useState16({});
|
|
7011
|
-
const labelsKey =
|
|
7102
|
+
const labelsKey = useMemo11(
|
|
7012
7103
|
() => Array.from(new Set(active.map((e) => e.label_))).sort().join("\0"),
|
|
7013
7104
|
[active]
|
|
7014
7105
|
);
|
|
@@ -7041,7 +7132,7 @@ function useEditableEdgeTypes(schemaProvider, active) {
|
|
|
7041
7132
|
function SectionTitle2({
|
|
7042
7133
|
children
|
|
7043
7134
|
}) {
|
|
7044
|
-
return /* @__PURE__ */
|
|
7135
|
+
return /* @__PURE__ */ jsx26("div", { className: "mb-2", children: /* @__PURE__ */ jsx26("span", { className: "heading-meta", children }) });
|
|
7045
7136
|
}
|
|
7046
7137
|
function EdgeRow({
|
|
7047
7138
|
label,
|
|
@@ -7050,18 +7141,18 @@ function EdgeRow({
|
|
|
7050
7141
|
onAdd
|
|
7051
7142
|
}) {
|
|
7052
7143
|
return /* @__PURE__ */ jsxs23("div", { className: "group/row flex items-center gap-2 px-3 py-2", children: [
|
|
7053
|
-
/* @__PURE__ */
|
|
7144
|
+
/* @__PURE__ */ jsx26("span", { className: "flex-1 text-sm font-medium", children: label }),
|
|
7054
7145
|
/* @__PURE__ */ jsxs23("span", { className: "flex gap-1", children: [
|
|
7055
|
-
onAdd && /* @__PURE__ */
|
|
7056
|
-
onEdit && /* @__PURE__ */
|
|
7057
|
-
onDelete && /* @__PURE__ */
|
|
7146
|
+
onAdd && /* @__PURE__ */ jsx26(IconButton3, { label: "Create edge", revealOnHover: true, onClick: onAdd, children: /* @__PURE__ */ jsx26(Plus2, {}) }),
|
|
7147
|
+
onEdit && /* @__PURE__ */ jsx26(IconButton3, { label: "Edit edge", revealOnHover: true, onClick: onEdit, children: /* @__PURE__ */ jsx26(Pencil2, {}) }),
|
|
7148
|
+
onDelete && /* @__PURE__ */ jsx26(
|
|
7058
7149
|
IconButton3,
|
|
7059
7150
|
{
|
|
7060
7151
|
label: "Delete edge",
|
|
7061
7152
|
tone: "destructive",
|
|
7062
7153
|
revealOnHover: true,
|
|
7063
7154
|
onClick: onDelete,
|
|
7064
|
-
children: /* @__PURE__ */
|
|
7155
|
+
children: /* @__PURE__ */ jsx26(Trash22, {})
|
|
7065
7156
|
}
|
|
7066
7157
|
)
|
|
7067
7158
|
] })
|
|
@@ -7098,8 +7189,8 @@ function PairLists({
|
|
|
7098
7189
|
"."
|
|
7099
7190
|
] }),
|
|
7100
7191
|
active.length > 0 && /* @__PURE__ */ jsxs23("div", { children: [
|
|
7101
|
-
/* @__PURE__ */
|
|
7102
|
-
/* @__PURE__ */
|
|
7192
|
+
/* @__PURE__ */ jsx26(SectionTitle2, { children: "Active edges" }),
|
|
7193
|
+
/* @__PURE__ */ jsx26("div", { className: "rounded-lg border divide-y", children: active.map((edge) => /* @__PURE__ */ jsx26(
|
|
7103
7194
|
EdgeRow,
|
|
7104
7195
|
{
|
|
7105
7196
|
label: edge.label_,
|
|
@@ -7110,8 +7201,8 @@ function PairLists({
|
|
|
7110
7201
|
)) })
|
|
7111
7202
|
] }),
|
|
7112
7203
|
available.length > 0 && /* @__PURE__ */ jsxs23("div", { children: [
|
|
7113
|
-
/* @__PURE__ */
|
|
7114
|
-
/* @__PURE__ */
|
|
7204
|
+
/* @__PURE__ */ jsx26(SectionTitle2, { children: "Available edges" }),
|
|
7205
|
+
/* @__PURE__ */ jsx26("div", { className: "rounded-lg border divide-y", children: available.map((entry) => /* @__PURE__ */ jsx26(
|
|
7115
7206
|
EdgeRow,
|
|
7116
7207
|
{
|
|
7117
7208
|
label: rowLabel(entry),
|
|
@@ -7137,7 +7228,7 @@ function DraftForm({
|
|
|
7137
7228
|
" ",
|
|
7138
7229
|
label
|
|
7139
7230
|
] }),
|
|
7140
|
-
/* @__PURE__ */
|
|
7231
|
+
/* @__PURE__ */ jsx26(
|
|
7141
7232
|
JsonSchemaFormRenderer3,
|
|
7142
7233
|
{
|
|
7143
7234
|
schema,
|
|
@@ -7242,16 +7333,16 @@ function EdgeFormSheet({
|
|
|
7242
7333
|
return /* @__PURE__ */ jsxs23(Sheet5, { open, onOpenChange, children: [
|
|
7243
7334
|
/* @__PURE__ */ jsxs23(SheetContent5, { children: [
|
|
7244
7335
|
/* @__PURE__ */ jsxs23(SheetHeader5, { children: [
|
|
7245
|
-
/* @__PURE__ */
|
|
7246
|
-
/* @__PURE__ */
|
|
7336
|
+
/* @__PURE__ */ jsx26(SheetTitle5, { children: "Edges" }),
|
|
7337
|
+
/* @__PURE__ */ jsx26(SheetDescription5, { children: "Manage the edges between the two selected nodes." })
|
|
7247
7338
|
] }),
|
|
7248
7339
|
/* @__PURE__ */ jsxs23(SheetBody5, { className: "flex flex-col gap-4", children: [
|
|
7249
7340
|
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
7250
|
-
/* @__PURE__ */
|
|
7251
|
-
/* @__PURE__ */
|
|
7252
|
-
/* @__PURE__ */
|
|
7341
|
+
/* @__PURE__ */ jsx26("span", { className: "font-medium", children: extractDisplayLabel(nodeA) }),
|
|
7342
|
+
/* @__PURE__ */ jsx26(ArrowRight2, { className: "h-4 w-4 text-muted-foreground" }),
|
|
7343
|
+
/* @__PURE__ */ jsx26("span", { className: "font-medium", children: extractDisplayLabel(nodeB) })
|
|
7253
7344
|
] }),
|
|
7254
|
-
!draft && /* @__PURE__ */
|
|
7345
|
+
!draft && /* @__PURE__ */ jsx26(
|
|
7255
7346
|
PairLists,
|
|
7256
7347
|
{
|
|
7257
7348
|
nodeALabel: nodeA.label_,
|
|
@@ -7265,7 +7356,7 @@ function EdgeFormSheet({
|
|
|
7265
7356
|
onCreate: (entry) => setDraft({ mode: "create", entry })
|
|
7266
7357
|
}
|
|
7267
7358
|
),
|
|
7268
|
-
draft && schema && /* @__PURE__ */
|
|
7359
|
+
draft && schema && /* @__PURE__ */ jsx26(
|
|
7269
7360
|
DraftForm,
|
|
7270
7361
|
{
|
|
7271
7362
|
draft,
|
|
@@ -7275,10 +7366,10 @@ function EdgeFormSheet({
|
|
|
7275
7366
|
onCancel: () => setDraft(null)
|
|
7276
7367
|
}
|
|
7277
7368
|
),
|
|
7278
|
-
error && /* @__PURE__ */
|
|
7369
|
+
error && /* @__PURE__ */ jsx26(Alert3, { variant: "destructive", children: error })
|
|
7279
7370
|
] })
|
|
7280
7371
|
] }),
|
|
7281
|
-
/* @__PURE__ */
|
|
7372
|
+
/* @__PURE__ */ jsx26(
|
|
7282
7373
|
DeleteEdgeConfirm,
|
|
7283
7374
|
{
|
|
7284
7375
|
edge: pendingDelete,
|
|
@@ -7293,18 +7384,18 @@ function DeleteEdgeConfirm({
|
|
|
7293
7384
|
onCancel,
|
|
7294
7385
|
onConfirm
|
|
7295
7386
|
}) {
|
|
7296
|
-
return /* @__PURE__ */
|
|
7387
|
+
return /* @__PURE__ */ jsx26(Dialog, { open: !!edge, onOpenChange: (o) => !o && onCancel(), children: /* @__PURE__ */ jsxs23(DialogContent, { children: [
|
|
7297
7388
|
/* @__PURE__ */ jsxs23(DialogHeader, { children: [
|
|
7298
|
-
/* @__PURE__ */
|
|
7389
|
+
/* @__PURE__ */ jsx26(DialogTitle, { children: "Delete edge" }),
|
|
7299
7390
|
/* @__PURE__ */ jsxs23(DialogDescription, { children: [
|
|
7300
7391
|
"Delete the edge ",
|
|
7301
|
-
/* @__PURE__ */
|
|
7392
|
+
/* @__PURE__ */ jsx26("strong", { children: edge?.label_ }),
|
|
7302
7393
|
"? This removes the relationship between the two nodes."
|
|
7303
7394
|
] })
|
|
7304
7395
|
] }),
|
|
7305
7396
|
/* @__PURE__ */ jsxs23(DialogFooter, { children: [
|
|
7306
|
-
/* @__PURE__ */
|
|
7307
|
-
/* @__PURE__ */
|
|
7397
|
+
/* @__PURE__ */ jsx26(Button9, { variant: "outline", onClick: onCancel, children: "Cancel" }),
|
|
7398
|
+
/* @__PURE__ */ jsx26(Button9, { variant: "destructive", onClick: onConfirm, children: "Delete" })
|
|
7308
7399
|
] })
|
|
7309
7400
|
] }) });
|
|
7310
7401
|
}
|
|
@@ -7322,7 +7413,7 @@ import {
|
|
|
7322
7413
|
Alert as Alert4
|
|
7323
7414
|
} from "@petrarca/sonnet-ui";
|
|
7324
7415
|
import { errorLog as errorLog6 } from "@petrarca/sonnet-core";
|
|
7325
|
-
import { jsx as
|
|
7416
|
+
import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
7326
7417
|
var EMPTY_DEPENDENT = {
|
|
7327
7418
|
inbound: [],
|
|
7328
7419
|
outbound: [],
|
|
@@ -7381,11 +7472,11 @@ function EdgeList({
|
|
|
7381
7472
|
}) {
|
|
7382
7473
|
if (edges.length === 0) return null;
|
|
7383
7474
|
return /* @__PURE__ */ jsxs24("div", { className: "mb-2", children: [
|
|
7384
|
-
/* @__PURE__ */
|
|
7385
|
-
/* @__PURE__ */
|
|
7475
|
+
/* @__PURE__ */ jsx27("span", { className: "heading-meta block", children: title }),
|
|
7476
|
+
/* @__PURE__ */ jsx27("ul", { className: "list-disc pl-6 text-sm", children: edges.map((edge) => {
|
|
7386
7477
|
const neighbour = direction === "inbound" ? names[edge.start_id_] : names[edge.end_id_];
|
|
7387
7478
|
const text = direction === "inbound" ? `${neighbour ?? "?"} \u2192 ${edge.label_}` : `${edge.label_} \u2192 ${neighbour ?? "?"}`;
|
|
7388
|
-
return /* @__PURE__ */
|
|
7479
|
+
return /* @__PURE__ */ jsx27("li", { children: neighbour ? text : edge.label_ }, edge.id_);
|
|
7389
7480
|
}) })
|
|
7390
7481
|
] });
|
|
7391
7482
|
}
|
|
@@ -7412,17 +7503,17 @@ function DeleteNodeDialog({
|
|
|
7412
7503
|
}
|
|
7413
7504
|
})();
|
|
7414
7505
|
}, [port, node.id_, onDeleted, onOpenChange]);
|
|
7415
|
-
return /* @__PURE__ */
|
|
7506
|
+
return /* @__PURE__ */ jsx27(Dialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs24(DialogContent2, { children: [
|
|
7416
7507
|
/* @__PURE__ */ jsxs24(DialogHeader2, { children: [
|
|
7417
|
-
/* @__PURE__ */
|
|
7508
|
+
/* @__PURE__ */ jsx27(DialogTitle2, { children: "Delete node" }),
|
|
7418
7509
|
/* @__PURE__ */ jsxs24(DialogDescription2, { children: [
|
|
7419
7510
|
"Delete the node ",
|
|
7420
|
-
/* @__PURE__ */
|
|
7511
|
+
/* @__PURE__ */ jsx27("strong", { children: extractDisplayLabel(node) }),
|
|
7421
7512
|
"?"
|
|
7422
7513
|
] })
|
|
7423
7514
|
] }),
|
|
7424
|
-
!hasEdges && /* @__PURE__ */
|
|
7425
|
-
/* @__PURE__ */
|
|
7515
|
+
!hasEdges && /* @__PURE__ */ jsx27("p", { className: "text-sm text-muted-foreground", children: "No connected edges." }),
|
|
7516
|
+
/* @__PURE__ */ jsx27(
|
|
7426
7517
|
EdgeList,
|
|
7427
7518
|
{
|
|
7428
7519
|
title: "Inbound edges",
|
|
@@ -7431,7 +7522,7 @@ function DeleteNodeDialog({
|
|
|
7431
7522
|
direction: "inbound"
|
|
7432
7523
|
}
|
|
7433
7524
|
),
|
|
7434
|
-
/* @__PURE__ */
|
|
7525
|
+
/* @__PURE__ */ jsx27(
|
|
7435
7526
|
EdgeList,
|
|
7436
7527
|
{
|
|
7437
7528
|
title: "Outbound edges",
|
|
@@ -7440,16 +7531,16 @@ function DeleteNodeDialog({
|
|
|
7440
7531
|
direction: "outbound"
|
|
7441
7532
|
}
|
|
7442
7533
|
),
|
|
7443
|
-
error && /* @__PURE__ */
|
|
7534
|
+
error && /* @__PURE__ */ jsx27(Alert4, { variant: "destructive", children: error }),
|
|
7444
7535
|
/* @__PURE__ */ jsxs24(DialogFooter2, { children: [
|
|
7445
|
-
/* @__PURE__ */
|
|
7446
|
-
/* @__PURE__ */
|
|
7536
|
+
/* @__PURE__ */ jsx27(Button10, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
7537
|
+
/* @__PURE__ */ jsx27(Button10, { variant: "destructive", onClick: handleDelete, children: "Delete" })
|
|
7447
7538
|
] })
|
|
7448
7539
|
] }) });
|
|
7449
7540
|
}
|
|
7450
7541
|
|
|
7451
7542
|
// src/graph-edit/GraphEditToolbar.tsx
|
|
7452
|
-
import { Fragment as Fragment8, jsx as
|
|
7543
|
+
import { Fragment as Fragment8, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
7453
7544
|
function toPerms(caps) {
|
|
7454
7545
|
const canCreateNode = caps.createNode === "edit";
|
|
7455
7546
|
const canUpdateNode = caps.updateNode === "edit";
|
|
@@ -7469,37 +7560,37 @@ function ToolbarButtons({
|
|
|
7469
7560
|
onOpen
|
|
7470
7561
|
}) {
|
|
7471
7562
|
return /* @__PURE__ */ jsxs25("div", { className: "flex gap-0.5", children: [
|
|
7472
|
-
perms.canCreateNode && /* @__PURE__ */
|
|
7563
|
+
perms.canCreateNode && /* @__PURE__ */ jsx28(
|
|
7473
7564
|
IconButton4,
|
|
7474
7565
|
{
|
|
7475
7566
|
label: "Add node",
|
|
7476
7567
|
variant: "outline",
|
|
7477
7568
|
disabled: count > 0,
|
|
7478
7569
|
onClick: () => onOpen("node-create"),
|
|
7479
|
-
children: /* @__PURE__ */
|
|
7570
|
+
children: /* @__PURE__ */ jsx28(Plus3, {})
|
|
7480
7571
|
}
|
|
7481
7572
|
),
|
|
7482
|
-
perms.canUpdateNode && /* @__PURE__ */
|
|
7573
|
+
perms.canUpdateNode && /* @__PURE__ */ jsx28(
|
|
7483
7574
|
IconButton4,
|
|
7484
7575
|
{
|
|
7485
7576
|
label: "Edit node",
|
|
7486
7577
|
variant: "outline",
|
|
7487
7578
|
disabled: count !== 1,
|
|
7488
7579
|
onClick: () => onOpen("node-edit"),
|
|
7489
|
-
children: /* @__PURE__ */
|
|
7580
|
+
children: /* @__PURE__ */ jsx28(Edit, {})
|
|
7490
7581
|
}
|
|
7491
7582
|
),
|
|
7492
|
-
perms.canEditEdges && /* @__PURE__ */
|
|
7583
|
+
perms.canEditEdges && /* @__PURE__ */ jsx28(
|
|
7493
7584
|
IconButton4,
|
|
7494
7585
|
{
|
|
7495
7586
|
label: "Edges",
|
|
7496
7587
|
variant: "outline",
|
|
7497
7588
|
disabled: count !== 2,
|
|
7498
7589
|
onClick: () => onOpen("edge"),
|
|
7499
|
-
children: /* @__PURE__ */
|
|
7590
|
+
children: /* @__PURE__ */ jsx28(Link, {})
|
|
7500
7591
|
}
|
|
7501
7592
|
),
|
|
7502
|
-
perms.canDeleteNode && /* @__PURE__ */
|
|
7593
|
+
perms.canDeleteNode && /* @__PURE__ */ jsx28(
|
|
7503
7594
|
IconButton4,
|
|
7504
7595
|
{
|
|
7505
7596
|
label: "Delete node",
|
|
@@ -7507,7 +7598,7 @@ function ToolbarButtons({
|
|
|
7507
7598
|
tone: "destructive",
|
|
7508
7599
|
disabled: count !== 1,
|
|
7509
7600
|
onClick: () => onOpen("delete"),
|
|
7510
|
-
children: /* @__PURE__ */
|
|
7601
|
+
children: /* @__PURE__ */ jsx28(Trash23, {})
|
|
7511
7602
|
}
|
|
7512
7603
|
)
|
|
7513
7604
|
] });
|
|
@@ -7530,7 +7621,7 @@ function ToolbarDialogs({
|
|
|
7530
7621
|
[onClose]
|
|
7531
7622
|
);
|
|
7532
7623
|
return /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7533
|
-
(perms.canCreateNode || perms.canUpdateNode) && /* @__PURE__ */
|
|
7624
|
+
(perms.canCreateNode || perms.canUpdateNode) && /* @__PURE__ */ jsx28(
|
|
7534
7625
|
NodeFormSheet,
|
|
7535
7626
|
{
|
|
7536
7627
|
open: dialog === "node-create" || dialog === "node-edit",
|
|
@@ -7542,7 +7633,7 @@ function ToolbarDialogs({
|
|
|
7542
7633
|
onSaved: onMutated
|
|
7543
7634
|
}
|
|
7544
7635
|
),
|
|
7545
|
-
perms.canEditEdges && firstNode && secondNode && /* @__PURE__ */
|
|
7636
|
+
perms.canEditEdges && firstNode && secondNode && /* @__PURE__ */ jsx28(
|
|
7546
7637
|
EdgeFormSheet,
|
|
7547
7638
|
{
|
|
7548
7639
|
open: dialog === "edge",
|
|
@@ -7555,7 +7646,7 @@ function ToolbarDialogs({
|
|
|
7555
7646
|
onChanged: onMutated
|
|
7556
7647
|
}
|
|
7557
7648
|
),
|
|
7558
|
-
perms.canDeleteNode && firstNode && /* @__PURE__ */
|
|
7649
|
+
perms.canDeleteNode && firstNode && /* @__PURE__ */ jsx28(
|
|
7559
7650
|
DeleteNodeDialog,
|
|
7560
7651
|
{
|
|
7561
7652
|
open: dialog === "delete",
|
|
@@ -7581,18 +7672,18 @@ function GraphEditToolbar({
|
|
|
7581
7672
|
);
|
|
7582
7673
|
const live = useLiveGraphData();
|
|
7583
7674
|
const [dialog, setDialog] = useState18(null);
|
|
7584
|
-
const perms =
|
|
7675
|
+
const perms = useMemo12(
|
|
7585
7676
|
() => toPerms(resolveGraphCapabilities(capabilities, readOnly)),
|
|
7586
7677
|
[capabilities, readOnly]
|
|
7587
7678
|
);
|
|
7588
|
-
const selectedNodes =
|
|
7679
|
+
const selectedNodes = useMemo12(
|
|
7589
7680
|
() => selectedNodeIds.map((id) => live.normalized.nodesById[id]).filter(Boolean),
|
|
7590
7681
|
[selectedNodeIds, live.normalized]
|
|
7591
7682
|
);
|
|
7592
7683
|
const stableOnMutated = useStableRef(onMutated);
|
|
7593
7684
|
if (!perms.anyEditable) return null;
|
|
7594
7685
|
return /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7595
|
-
/* @__PURE__ */
|
|
7686
|
+
/* @__PURE__ */ jsx28(
|
|
7596
7687
|
ToolbarButtons,
|
|
7597
7688
|
{
|
|
7598
7689
|
perms,
|
|
@@ -7600,7 +7691,7 @@ function GraphEditToolbar({
|
|
|
7600
7691
|
onOpen: setDialog
|
|
7601
7692
|
}
|
|
7602
7693
|
),
|
|
7603
|
-
/* @__PURE__ */
|
|
7694
|
+
/* @__PURE__ */ jsx28(
|
|
7604
7695
|
ToolbarDialogs,
|
|
7605
7696
|
{
|
|
7606
7697
|
perms,
|
|
@@ -8086,7 +8177,7 @@ function useFinderState() {
|
|
|
8086
8177
|
}
|
|
8087
8178
|
|
|
8088
8179
|
// src/finder/GraphFinder.tsx
|
|
8089
|
-
import { Fragment as Fragment9, jsx as
|
|
8180
|
+
import { Fragment as Fragment9, jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
8090
8181
|
function GraphFinder() {
|
|
8091
8182
|
const {
|
|
8092
8183
|
searchMode,
|
|
@@ -8108,7 +8199,7 @@ function GraphFinder() {
|
|
|
8108
8199
|
};
|
|
8109
8200
|
const both = searchMode === "both";
|
|
8110
8201
|
return /* @__PURE__ */ jsxs26("div", { className: "h-full flex flex-col p-4", children: [
|
|
8111
|
-
/* @__PURE__ */
|
|
8202
|
+
/* @__PURE__ */ jsx29("div", { className: "mb-3 flex-shrink-0", children: /* @__PURE__ */ jsx29(
|
|
8112
8203
|
FormSelect3,
|
|
8113
8204
|
{
|
|
8114
8205
|
label: "Search Mode",
|
|
@@ -8123,7 +8214,7 @@ function GraphFinder() {
|
|
|
8123
8214
|
}
|
|
8124
8215
|
) }),
|
|
8125
8216
|
/* @__PURE__ */ jsxs26("div", { className: "mb-4 flex-shrink-0 space-y-3", children: [
|
|
8126
|
-
(searchMode === "expression" || both) && /* @__PURE__ */
|
|
8217
|
+
(searchMode === "expression" || both) && /* @__PURE__ */ jsx29(
|
|
8127
8218
|
ExpressionInput,
|
|
8128
8219
|
{
|
|
8129
8220
|
value: expressionQuery,
|
|
@@ -8132,7 +8223,7 @@ function GraphFinder() {
|
|
|
8132
8223
|
both
|
|
8133
8224
|
}
|
|
8134
8225
|
),
|
|
8135
|
-
(searchMode === "fulltext" || both) && /* @__PURE__ */
|
|
8226
|
+
(searchMode === "fulltext" || both) && /* @__PURE__ */ jsx29(
|
|
8136
8227
|
FullTextInput,
|
|
8137
8228
|
{
|
|
8138
8229
|
value: fulltextQuery,
|
|
@@ -8146,10 +8237,10 @@ function GraphFinder() {
|
|
|
8146
8237
|
)
|
|
8147
8238
|
] }),
|
|
8148
8239
|
error && /* @__PURE__ */ jsxs26(Alert5, { variant: "destructive", className: "mb-4 flex-shrink-0", children: [
|
|
8149
|
-
/* @__PURE__ */
|
|
8150
|
-
/* @__PURE__ */
|
|
8240
|
+
/* @__PURE__ */ jsx29(AlertTitle, { children: "Query Error" }),
|
|
8241
|
+
/* @__PURE__ */ jsx29(AlertDescription, { children: error })
|
|
8151
8242
|
] }),
|
|
8152
|
-
hasSearched && !error && /* @__PURE__ */
|
|
8243
|
+
hasSearched && !error && /* @__PURE__ */ jsx29(ResultsPanel, { results, searchInfo })
|
|
8153
8244
|
] });
|
|
8154
8245
|
}
|
|
8155
8246
|
function ExpressionInput({
|
|
@@ -8159,8 +8250,8 @@ function ExpressionInput({
|
|
|
8159
8250
|
both
|
|
8160
8251
|
}) {
|
|
8161
8252
|
return /* @__PURE__ */ jsxs26("div", { children: [
|
|
8162
|
-
both && /* @__PURE__ */
|
|
8163
|
-
/* @__PURE__ */
|
|
8253
|
+
both && /* @__PURE__ */ jsx29("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Expression filter (applied first):" }),
|
|
8254
|
+
/* @__PURE__ */ jsx29(
|
|
8164
8255
|
FormTextarea,
|
|
8165
8256
|
{
|
|
8166
8257
|
placeholder: 'e.g., Person | filter name == "John"',
|
|
@@ -8171,7 +8262,7 @@ function ExpressionInput({
|
|
|
8171
8262
|
minRows: both ? 2 : 3
|
|
8172
8263
|
}
|
|
8173
8264
|
),
|
|
8174
|
-
!both && /* @__PURE__ */
|
|
8265
|
+
!both && /* @__PURE__ */ jsx29("div", { className: "text-xs text-muted-foreground mt-1", children: "Use pipes (|) to filter and transform. Available: nodes, edges, graph, and each label." })
|
|
8175
8266
|
] });
|
|
8176
8267
|
}
|
|
8177
8268
|
function FullTextInput({
|
|
@@ -8184,8 +8275,8 @@ function FullTextInput({
|
|
|
8184
8275
|
statsLabel
|
|
8185
8276
|
}) {
|
|
8186
8277
|
return /* @__PURE__ */ jsxs26("div", { children: [
|
|
8187
|
-
both && /* @__PURE__ */
|
|
8188
|
-
/* @__PURE__ */
|
|
8278
|
+
both && /* @__PURE__ */ jsx29("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Full-text search (on filtered results):" }),
|
|
8279
|
+
/* @__PURE__ */ jsx29(
|
|
8189
8280
|
FormTextarea,
|
|
8190
8281
|
{
|
|
8191
8282
|
placeholder: "e.g., software engineer machine learning",
|
|
@@ -8194,7 +8285,7 @@ function FullTextInput({
|
|
|
8194
8285
|
onKeyDown,
|
|
8195
8286
|
autosize: true,
|
|
8196
8287
|
minRows: both ? 2 : 3,
|
|
8197
|
-
rightSection: /* @__PURE__ */
|
|
8288
|
+
rightSection: /* @__PURE__ */ jsx29(SimpleTooltip5, { label: "Search", children: /* @__PURE__ */ jsx29(Button11, { variant: "ghost", size: "icon", onClick: onSearch, children: /* @__PURE__ */ jsx29(Search, { size: 16 }) }) }),
|
|
8198
8289
|
rightSectionWidth: 48
|
|
8199
8290
|
}
|
|
8200
8291
|
),
|
|
@@ -8217,9 +8308,9 @@ function ResultsPanel({
|
|
|
8217
8308
|
" ",
|
|
8218
8309
|
results.length === 1 ? "item" : "items"
|
|
8219
8310
|
] }),
|
|
8220
|
-
searchInfo && /* @__PURE__ */
|
|
8311
|
+
searchInfo && /* @__PURE__ */ jsx29("div", { className: "text-xs text-muted-foreground mt-1", children: searchInfo })
|
|
8221
8312
|
] }),
|
|
8222
|
-
results.length === 0 ? /* @__PURE__ */
|
|
8313
|
+
results.length === 0 ? /* @__PURE__ */ jsx29("div", { className: "text-sm text-muted-foreground italic", children: "No results found" }) : /* @__PURE__ */ jsx29("div", { className: "space-y-2 overflow-y-auto flex-1", children: results.map((item, index) => /* @__PURE__ */ jsx29(ResultItem, { item }, resultKey(item, index))) })
|
|
8223
8314
|
] });
|
|
8224
8315
|
}
|
|
8225
8316
|
function resultKey(item, index) {
|
|
@@ -8232,7 +8323,7 @@ function ResultItem({ item }) {
|
|
|
8232
8323
|
const useGraphFocus2 = useWorkspaceGraphFocus();
|
|
8233
8324
|
const requestFocus = useGraphFocus2((s) => s.requestFocus);
|
|
8234
8325
|
if (typeof item !== "object" || item === null) {
|
|
8235
|
-
return /* @__PURE__ */
|
|
8326
|
+
return /* @__PURE__ */ jsx29("div", { className: "p-3 bg-muted/40 rounded border border-border", children: /* @__PURE__ */ jsx29("div", { className: "text-sm font-medium", children: String(item) }) });
|
|
8236
8327
|
}
|
|
8237
8328
|
const isNodeItem = isNodeRow(item);
|
|
8238
8329
|
const isEdgeItem = isEdgeRow(item);
|
|
@@ -8241,7 +8332,7 @@ function ResultItem({ item }) {
|
|
|
8241
8332
|
if (!isGraphElement) return;
|
|
8242
8333
|
requestFocus(String(item.id_), isNodeItem ? "node" : "edge", shouldSelect);
|
|
8243
8334
|
};
|
|
8244
|
-
return /* @__PURE__ */
|
|
8335
|
+
return /* @__PURE__ */ jsx29(
|
|
8245
8336
|
"div",
|
|
8246
8337
|
{
|
|
8247
8338
|
className: `p-3 bg-background rounded border border-border transition-colors ${isGraphElement ? "hover:border-primary hover:bg-accent cursor-pointer" : ""}`,
|
|
@@ -8251,18 +8342,18 @@ function ResultItem({ item }) {
|
|
|
8251
8342
|
children: /* @__PURE__ */ jsxs26("div", { className: "flex items-start justify-between", children: [
|
|
8252
8343
|
/* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2", children: [
|
|
8253
8344
|
isNodeItem && /* @__PURE__ */ jsxs26(Fragment9, { children: [
|
|
8254
|
-
/* @__PURE__ */
|
|
8255
|
-
/* @__PURE__ */
|
|
8345
|
+
/* @__PURE__ */ jsx29("span", { className: "text-xs font-semibold px-2 py-0.5 bg-accent text-accent-foreground rounded", children: item.label_ }),
|
|
8346
|
+
/* @__PURE__ */ jsx29("span", { className: "text-sm font-medium", children: item.displayName })
|
|
8256
8347
|
] }),
|
|
8257
8348
|
isEdgeItem && /* @__PURE__ */ jsxs26(Fragment9, { children: [
|
|
8258
|
-
/* @__PURE__ */
|
|
8349
|
+
/* @__PURE__ */ jsx29("span", { className: "text-xs font-semibold px-2 py-0.5 bg-accent text-accent-foreground rounded", children: item.label_ }),
|
|
8259
8350
|
/* @__PURE__ */ jsxs26("span", { className: "text-xs text-muted-foreground", children: [
|
|
8260
8351
|
String(item.start_id_),
|
|
8261
8352
|
" -> ",
|
|
8262
8353
|
String(item.end_id_)
|
|
8263
8354
|
] })
|
|
8264
8355
|
] }),
|
|
8265
|
-
!isGraphElement && /* @__PURE__ */
|
|
8356
|
+
!isGraphElement && /* @__PURE__ */ jsx29("span", { className: "text-sm font-medium", children: "Object" })
|
|
8266
8357
|
] }),
|
|
8267
8358
|
isGraphElement && /* @__PURE__ */ jsxs26("span", { className: "text-xs text-muted-foreground", children: [
|
|
8268
8359
|
"ID: ",
|
|
@@ -8272,19 +8363,1091 @@ function ResultItem({ item }) {
|
|
|
8272
8363
|
}
|
|
8273
8364
|
);
|
|
8274
8365
|
}
|
|
8366
|
+
|
|
8367
|
+
// src/tabular/TabularVisualizer.tsx
|
|
8368
|
+
import { useCallback as useCallback13, useMemo as useMemo16, useState as useState22 } from "react";
|
|
8369
|
+
|
|
8370
|
+
// src/tabular/cellContext.ts
|
|
8371
|
+
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
8372
|
+
var TabularCellContext = createContext3({});
|
|
8373
|
+
function useTabularCellContext() {
|
|
8374
|
+
return useContext3(TabularCellContext);
|
|
8375
|
+
}
|
|
8376
|
+
|
|
8377
|
+
// src/tabular/columns.ts
|
|
8378
|
+
function isRecordRow(row) {
|
|
8379
|
+
return typeof row === "object" && row !== null && !Array.isArray(row);
|
|
8380
|
+
}
|
|
8381
|
+
function resolveColumnNames(colNames, columnCount) {
|
|
8382
|
+
const headers = namesFromColNames(colNames);
|
|
8383
|
+
while (headers.length < columnCount) {
|
|
8384
|
+
headers.push(`column_${headers.length + 1}`);
|
|
8385
|
+
}
|
|
8386
|
+
return headers;
|
|
8387
|
+
}
|
|
8388
|
+
function namesFromColNames(colNames) {
|
|
8389
|
+
if (!colNames) return [];
|
|
8390
|
+
const entries = Object.entries(colNames);
|
|
8391
|
+
const allNumeric = entries.every(([key]) => !isNaN(parseInt(key, 10)));
|
|
8392
|
+
if (allNumeric) {
|
|
8393
|
+
entries.sort((a, b) => parseInt(a[0], 10) - parseInt(b[0], 10));
|
|
8394
|
+
return entries.map(([, value]) => value);
|
|
8395
|
+
}
|
|
8396
|
+
return entries.map(([key]) => key);
|
|
8397
|
+
}
|
|
8398
|
+
function deriveHeaders(rows, colNames) {
|
|
8399
|
+
if (rows.length === 0) return { headers: [], mode: "value" };
|
|
8400
|
+
const recordKeys = /* @__PURE__ */ new Set();
|
|
8401
|
+
let maxArrayLength = 0;
|
|
8402
|
+
for (const row of rows) {
|
|
8403
|
+
if (isRecordRow(row)) {
|
|
8404
|
+
Object.keys(row).forEach((key) => recordKeys.add(key));
|
|
8405
|
+
} else if (Array.isArray(row)) {
|
|
8406
|
+
maxArrayLength = Math.max(maxArrayLength, row.length);
|
|
8407
|
+
}
|
|
8408
|
+
}
|
|
8409
|
+
if (recordKeys.size > 0) {
|
|
8410
|
+
return { headers: Array.from(recordKeys).sort(), mode: "record" };
|
|
8411
|
+
}
|
|
8412
|
+
if (maxArrayLength > 0) {
|
|
8413
|
+
return {
|
|
8414
|
+
headers: resolveColumnNames(colNames, maxArrayLength),
|
|
8415
|
+
mode: "array"
|
|
8416
|
+
};
|
|
8417
|
+
}
|
|
8418
|
+
return { headers: ["value"], mode: "value" };
|
|
8419
|
+
}
|
|
8420
|
+
function getCellValue(row, header, index, mode) {
|
|
8421
|
+
if (mode === "record" && isRecordRow(row)) return row[header];
|
|
8422
|
+
if (mode === "array" && Array.isArray(row)) return row[index];
|
|
8423
|
+
return row;
|
|
8424
|
+
}
|
|
8425
|
+
function rowCells(row) {
|
|
8426
|
+
if (Array.isArray(row)) return row;
|
|
8427
|
+
if (isRecordRow(row)) return Object.values(row);
|
|
8428
|
+
return [row];
|
|
8429
|
+
}
|
|
8430
|
+
|
|
8431
|
+
// src/tabular/ExportMenu.tsx
|
|
8432
|
+
import { useMemo as useMemo13 } from "react";
|
|
8433
|
+
import { ClipboardCopy, Download } from "lucide-react";
|
|
8434
|
+
import { toast as toast5 } from "sonner";
|
|
8435
|
+
import {
|
|
8436
|
+
Button as Button12,
|
|
8437
|
+
DropdownMenu as DropdownMenu5,
|
|
8438
|
+
DropdownMenuContent as DropdownMenuContent5,
|
|
8439
|
+
DropdownMenuItem as DropdownMenuItem5,
|
|
8440
|
+
DropdownMenuSeparator as DropdownMenuSeparator4,
|
|
8441
|
+
DropdownMenuTrigger as DropdownMenuTrigger5
|
|
8442
|
+
} from "@petrarca/sonnet-ui";
|
|
8443
|
+
|
|
8444
|
+
// src/tabular/exportTabular.ts
|
|
8445
|
+
function escapeDsvCell(value, delimiter) {
|
|
8446
|
+
if (value === null || value === void 0) return "";
|
|
8447
|
+
const str = typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
8448
|
+
const needsQuoting = str.includes(delimiter) || str.includes('"') || str.includes("\n") || str.includes("\r");
|
|
8449
|
+
return needsQuoting ? `"${str.replace(/"/g, '""')}"` : str;
|
|
8450
|
+
}
|
|
8451
|
+
function toDsv(rows, headers, mode, delimiter) {
|
|
8452
|
+
const lines = [
|
|
8453
|
+
headers.map((h) => escapeDsvCell(h, delimiter)).join(delimiter)
|
|
8454
|
+
];
|
|
8455
|
+
for (const row of rows) {
|
|
8456
|
+
const cells = headers.map(
|
|
8457
|
+
(header, index) => escapeDsvCell(getCellValue(row, header, index, mode), delimiter)
|
|
8458
|
+
);
|
|
8459
|
+
lines.push(cells.join(delimiter));
|
|
8460
|
+
}
|
|
8461
|
+
return lines.join("\n");
|
|
8462
|
+
}
|
|
8463
|
+
function toCsv(rows, headers, mode) {
|
|
8464
|
+
return toDsv(rows, headers, mode, ",");
|
|
8465
|
+
}
|
|
8466
|
+
function toTsv(rows, headers, mode) {
|
|
8467
|
+
return toDsv(rows, headers, mode, " ");
|
|
8468
|
+
}
|
|
8469
|
+
function toJson(rows, headers, mode) {
|
|
8470
|
+
const objects = rows.map((row) => {
|
|
8471
|
+
const obj = {};
|
|
8472
|
+
headers.forEach((header, index) => {
|
|
8473
|
+
obj[header] = getCellValue(row, header, index, mode);
|
|
8474
|
+
});
|
|
8475
|
+
return obj;
|
|
8476
|
+
});
|
|
8477
|
+
return JSON.stringify(objects, null, 2);
|
|
8478
|
+
}
|
|
8479
|
+
function isFlatExportSuitable(rows, headers, mode) {
|
|
8480
|
+
if (rows.length === 0 || headers.length === 0) return false;
|
|
8481
|
+
const sample = rows.slice(0, 3);
|
|
8482
|
+
return sample.some(
|
|
8483
|
+
(row) => headers.some((header, index) => {
|
|
8484
|
+
const value = getCellValue(row, header, index, mode);
|
|
8485
|
+
return value === null || value === void 0 || typeof value !== "object";
|
|
8486
|
+
})
|
|
8487
|
+
);
|
|
8488
|
+
}
|
|
8489
|
+
function downloadFile(content, filename, mimeType) {
|
|
8490
|
+
const blob = new Blob([content], { type: `${mimeType};charset=utf-8` });
|
|
8491
|
+
const url = URL.createObjectURL(blob);
|
|
8492
|
+
const anchor = document.createElement("a");
|
|
8493
|
+
anchor.href = url;
|
|
8494
|
+
anchor.download = filename;
|
|
8495
|
+
anchor.style.display = "none";
|
|
8496
|
+
document.body.appendChild(anchor);
|
|
8497
|
+
anchor.click();
|
|
8498
|
+
setTimeout(() => {
|
|
8499
|
+
document.body.removeChild(anchor);
|
|
8500
|
+
URL.revokeObjectURL(url);
|
|
8501
|
+
}, 100);
|
|
8502
|
+
}
|
|
8503
|
+
|
|
8504
|
+
// src/tabular/ExportMenu.tsx
|
|
8505
|
+
import { Fragment as Fragment10, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
8506
|
+
var CLIPBOARD_ROW_LIMIT = 1e3;
|
|
8507
|
+
function copyToClipboard(content, what) {
|
|
8508
|
+
navigator.clipboard.writeText(content).then(() => toast5.success(`Copied as ${what} to clipboard`)).catch(() => toast5.error("Failed to copy to clipboard"));
|
|
8509
|
+
}
|
|
8510
|
+
function ExportMenu({
|
|
8511
|
+
rows,
|
|
8512
|
+
headerInfo,
|
|
8513
|
+
fileName
|
|
8514
|
+
}) {
|
|
8515
|
+
const { headers, mode } = headerInfo;
|
|
8516
|
+
const flat = useMemo13(
|
|
8517
|
+
() => isFlatExportSuitable(rows, headers, mode),
|
|
8518
|
+
[rows, headers, mode]
|
|
8519
|
+
);
|
|
8520
|
+
const clipboard = rows.length <= CLIPBOARD_ROW_LIMIT;
|
|
8521
|
+
return /* @__PURE__ */ jsxs27(DropdownMenu5, { children: [
|
|
8522
|
+
/* @__PURE__ */ jsx30(DropdownMenuTrigger5, { asChild: true, children: /* @__PURE__ */ jsxs27(Button12, { variant: "outline", size: "sm", className: "gap-1.5 text-xs", children: [
|
|
8523
|
+
/* @__PURE__ */ jsx30(Download, { className: "h-3.5 w-3.5" }),
|
|
8524
|
+
"Export"
|
|
8525
|
+
] }) }),
|
|
8526
|
+
/* @__PURE__ */ jsxs27(DropdownMenuContent5, { align: "end", children: [
|
|
8527
|
+
flat && /* @__PURE__ */ jsxs27(Fragment10, { children: [
|
|
8528
|
+
/* @__PURE__ */ jsxs27(
|
|
8529
|
+
DropdownMenuItem5,
|
|
8530
|
+
{
|
|
8531
|
+
onClick: () => downloadFile(
|
|
8532
|
+
toCsv(rows, headers, mode),
|
|
8533
|
+
`${fileName}.csv`,
|
|
8534
|
+
"text/csv"
|
|
8535
|
+
),
|
|
8536
|
+
children: [
|
|
8537
|
+
/* @__PURE__ */ jsx30(Download, {}),
|
|
8538
|
+
"Download CSV"
|
|
8539
|
+
]
|
|
8540
|
+
}
|
|
8541
|
+
),
|
|
8542
|
+
/* @__PURE__ */ jsxs27(
|
|
8543
|
+
DropdownMenuItem5,
|
|
8544
|
+
{
|
|
8545
|
+
onClick: () => downloadFile(
|
|
8546
|
+
toTsv(rows, headers, mode),
|
|
8547
|
+
`${fileName}.tsv`,
|
|
8548
|
+
"text/tab-separated-values"
|
|
8549
|
+
),
|
|
8550
|
+
children: [
|
|
8551
|
+
/* @__PURE__ */ jsx30(Download, {}),
|
|
8552
|
+
"Download TSV"
|
|
8553
|
+
]
|
|
8554
|
+
}
|
|
8555
|
+
)
|
|
8556
|
+
] }),
|
|
8557
|
+
/* @__PURE__ */ jsxs27(
|
|
8558
|
+
DropdownMenuItem5,
|
|
8559
|
+
{
|
|
8560
|
+
onClick: () => downloadFile(
|
|
8561
|
+
toJson(rows, headers, mode),
|
|
8562
|
+
`${fileName}.json`,
|
|
8563
|
+
"application/json"
|
|
8564
|
+
),
|
|
8565
|
+
children: [
|
|
8566
|
+
/* @__PURE__ */ jsx30(Download, {}),
|
|
8567
|
+
"Download JSON"
|
|
8568
|
+
]
|
|
8569
|
+
}
|
|
8570
|
+
),
|
|
8571
|
+
clipboard && /* @__PURE__ */ jsxs27(Fragment10, { children: [
|
|
8572
|
+
/* @__PURE__ */ jsx30(DropdownMenuSeparator4, {}),
|
|
8573
|
+
flat && /* @__PURE__ */ jsxs27(
|
|
8574
|
+
DropdownMenuItem5,
|
|
8575
|
+
{
|
|
8576
|
+
onClick: () => copyToClipboard(toTsv(rows, headers, mode), "TSV"),
|
|
8577
|
+
children: [
|
|
8578
|
+
/* @__PURE__ */ jsx30(ClipboardCopy, {}),
|
|
8579
|
+
"Copy as TSV"
|
|
8580
|
+
]
|
|
8581
|
+
}
|
|
8582
|
+
),
|
|
8583
|
+
/* @__PURE__ */ jsxs27(
|
|
8584
|
+
DropdownMenuItem5,
|
|
8585
|
+
{
|
|
8586
|
+
onClick: () => copyToClipboard(toJson(rows, headers, mode), "JSON"),
|
|
8587
|
+
children: [
|
|
8588
|
+
/* @__PURE__ */ jsx30(ClipboardCopy, {}),
|
|
8589
|
+
"Copy as JSON"
|
|
8590
|
+
]
|
|
8591
|
+
}
|
|
8592
|
+
)
|
|
8593
|
+
] })
|
|
8594
|
+
] })
|
|
8595
|
+
] });
|
|
8596
|
+
}
|
|
8597
|
+
|
|
8598
|
+
// src/tabular/GraphInspector.tsx
|
|
8599
|
+
import { useMemo as useMemo14 } from "react";
|
|
8600
|
+
import { Copy as Copy2 } from "lucide-react";
|
|
8601
|
+
import { toast as toast6 } from "sonner";
|
|
8602
|
+
import {
|
|
8603
|
+
Button as Button13,
|
|
8604
|
+
JsonTree,
|
|
8605
|
+
PropertyList as PropertyList3,
|
|
8606
|
+
ScrollArea,
|
|
8607
|
+
Sheet as Sheet6,
|
|
8608
|
+
SheetBody as SheetBody6,
|
|
8609
|
+
SheetContent as SheetContent6,
|
|
8610
|
+
SheetDescription as SheetDescription6,
|
|
8611
|
+
SheetHeader as SheetHeader6,
|
|
8612
|
+
SheetTitle as SheetTitle6,
|
|
8613
|
+
Tabs,
|
|
8614
|
+
TabsContent,
|
|
8615
|
+
TabsList,
|
|
8616
|
+
TabsTrigger
|
|
8617
|
+
} from "@petrarca/sonnet-ui";
|
|
8618
|
+
|
|
8619
|
+
// src/tabular/graphCell.ts
|
|
8620
|
+
var CAPTION_PRIORITY = [
|
|
8621
|
+
"name",
|
|
8622
|
+
"title",
|
|
8623
|
+
"label",
|
|
8624
|
+
"displayName",
|
|
8625
|
+
"symbol",
|
|
8626
|
+
"id",
|
|
8627
|
+
"code"
|
|
8628
|
+
];
|
|
8629
|
+
function asGraphCell(value) {
|
|
8630
|
+
if (!value || typeof value !== "object") return null;
|
|
8631
|
+
const obj = value;
|
|
8632
|
+
if (obj.node && typeof obj.node === "object") {
|
|
8633
|
+
return { kind: "node", data: obj.node };
|
|
8634
|
+
}
|
|
8635
|
+
if (obj.edge && typeof obj.edge === "object") {
|
|
8636
|
+
return { kind: "edge", data: obj.edge };
|
|
8637
|
+
}
|
|
8638
|
+
return null;
|
|
8639
|
+
}
|
|
8640
|
+
function captionFor(cell, labelDisplayMap) {
|
|
8641
|
+
const { data } = cell;
|
|
8642
|
+
const config = labelDisplayMap?.[data.label_];
|
|
8643
|
+
if (config) {
|
|
8644
|
+
const resolved = extractDisplayLabel(data, config);
|
|
8645
|
+
if (resolved && resolved !== data.label_) return resolved;
|
|
8646
|
+
}
|
|
8647
|
+
const props = data.properties_ ?? {};
|
|
8648
|
+
const key = CAPTION_PRIORITY.find((k) => props[k] != null && props[k] !== "");
|
|
8649
|
+
if (key) return String(props[key]);
|
|
8650
|
+
return data.id_ != null ? `${data.label_} #${data.id_}` : data.label_;
|
|
8651
|
+
}
|
|
8652
|
+
function propertyCount(cell) {
|
|
8653
|
+
return Object.keys(cell.data.properties_ ?? {}).length;
|
|
8654
|
+
}
|
|
8655
|
+
function colorForLabel(label, palette) {
|
|
8656
|
+
if (!palette) return "hsl(var(--muted-foreground))";
|
|
8657
|
+
return palette[label] ?? palette.neutral ?? "hsl(var(--muted-foreground))";
|
|
8658
|
+
}
|
|
8659
|
+
|
|
8660
|
+
// src/tabular/GraphInspector.tsx
|
|
8661
|
+
import { Fragment as Fragment11, jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
8662
|
+
function copy(text, what) {
|
|
8663
|
+
navigator.clipboard.writeText(text).then(() => toast6.success(`Copied ${what}`)).catch(() => toast6.error("Failed to copy"));
|
|
8664
|
+
}
|
|
8665
|
+
function InspectorTitle({
|
|
8666
|
+
cell,
|
|
8667
|
+
color
|
|
8668
|
+
}) {
|
|
8669
|
+
return /* @__PURE__ */ jsxs28(SheetTitle6, { className: "flex items-center gap-2 text-base", children: [
|
|
8670
|
+
cell.kind === "node" ? /* @__PURE__ */ jsx31(
|
|
8671
|
+
"span",
|
|
8672
|
+
{
|
|
8673
|
+
"aria-hidden": "true",
|
|
8674
|
+
className: "h-3 w-3 shrink-0 rounded-full",
|
|
8675
|
+
style: { backgroundColor: color }
|
|
8676
|
+
}
|
|
8677
|
+
) : /* @__PURE__ */ jsx31("span", { "aria-hidden": "true", className: "text-sm", style: { color }, children: "\u2192" }),
|
|
8678
|
+
/* @__PURE__ */ jsx31("span", { className: "font-semibold", children: cell.data.label_ }),
|
|
8679
|
+
cell.data.id_ != null && /* @__PURE__ */ jsxs28("span", { className: "text-xs font-normal text-muted-foreground", children: [
|
|
8680
|
+
"#",
|
|
8681
|
+
cell.data.id_
|
|
8682
|
+
] })
|
|
8683
|
+
] });
|
|
8684
|
+
}
|
|
8685
|
+
function InspectorBody({ cell }) {
|
|
8686
|
+
return /* @__PURE__ */ jsx31(SheetBody6, { className: "flex-1 min-h-0 p-0", children: /* @__PURE__ */ jsxs28(Tabs, { defaultValue: "properties", className: "flex h-full flex-col", children: [
|
|
8687
|
+
/* @__PURE__ */ jsxs28(TabsList, { className: "mx-6", children: [
|
|
8688
|
+
/* @__PURE__ */ jsx31(TabsTrigger, { value: "properties", children: "Properties" }),
|
|
8689
|
+
/* @__PURE__ */ jsx31(TabsTrigger, { value: "json", children: "JSON" })
|
|
8690
|
+
] }),
|
|
8691
|
+
/* @__PURE__ */ jsx31(TabsContent, { value: "properties", className: "flex-1 min-h-0", children: /* @__PURE__ */ jsx31(ScrollArea, { className: "h-full px-6 py-3", children: /* @__PURE__ */ jsx31(PropertyList3, { properties: cell.data.properties_ ?? {} }) }) }),
|
|
8692
|
+
/* @__PURE__ */ jsx31(TabsContent, { value: "json", className: "flex-1 min-h-0", children: /* @__PURE__ */ jsx31(ScrollArea, { className: "h-full px-6 py-3", children: /* @__PURE__ */ jsx31("div", { className: "text-sm font-mono", children: /* @__PURE__ */ jsx31(JsonTree, { data: cell.data }) }) }) })
|
|
8693
|
+
] }) });
|
|
8694
|
+
}
|
|
8695
|
+
function GraphInspector({
|
|
8696
|
+
cell,
|
|
8697
|
+
open,
|
|
8698
|
+
onOpenChange,
|
|
8699
|
+
palette,
|
|
8700
|
+
labelDisplayMap
|
|
8701
|
+
}) {
|
|
8702
|
+
const caption = useMemo14(
|
|
8703
|
+
() => cell ? captionFor(cell, labelDisplayMap) : "",
|
|
8704
|
+
[cell, labelDisplayMap]
|
|
8705
|
+
);
|
|
8706
|
+
return /* @__PURE__ */ jsx31(Sheet6, { open, onOpenChange, children: /* @__PURE__ */ jsx31(
|
|
8707
|
+
SheetContent6,
|
|
8708
|
+
{
|
|
8709
|
+
side: "right",
|
|
8710
|
+
className: "w-[420px] sm:max-w-[420px] flex flex-col gap-0",
|
|
8711
|
+
children: cell && /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
8712
|
+
/* @__PURE__ */ jsxs28(SheetHeader6, { children: [
|
|
8713
|
+
/* @__PURE__ */ jsx31(
|
|
8714
|
+
InspectorTitle,
|
|
8715
|
+
{
|
|
8716
|
+
cell,
|
|
8717
|
+
color: colorForLabel(cell.data.label_, palette)
|
|
8718
|
+
}
|
|
8719
|
+
),
|
|
8720
|
+
/* @__PURE__ */ jsx31(SheetDescription6, { className: "truncate", children: caption })
|
|
8721
|
+
] }),
|
|
8722
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2 px-6 pb-2", children: [
|
|
8723
|
+
/* @__PURE__ */ jsxs28(
|
|
8724
|
+
Button13,
|
|
8725
|
+
{
|
|
8726
|
+
variant: "outline",
|
|
8727
|
+
size: "sm",
|
|
8728
|
+
className: "h-7 gap-1.5 text-xs",
|
|
8729
|
+
onClick: () => copy(JSON.stringify(cell.data, null, 2), "as JSON"),
|
|
8730
|
+
children: [
|
|
8731
|
+
/* @__PURE__ */ jsx31(Copy2, { className: "h-3 w-3" }),
|
|
8732
|
+
"Copy JSON"
|
|
8733
|
+
]
|
|
8734
|
+
}
|
|
8735
|
+
),
|
|
8736
|
+
cell.data.id_ != null && /* @__PURE__ */ jsxs28(
|
|
8737
|
+
Button13,
|
|
8738
|
+
{
|
|
8739
|
+
variant: "outline",
|
|
8740
|
+
size: "sm",
|
|
8741
|
+
className: "h-7 gap-1.5 text-xs",
|
|
8742
|
+
onClick: () => copy(String(cell.data.id_), "id"),
|
|
8743
|
+
children: [
|
|
8744
|
+
/* @__PURE__ */ jsx31(Copy2, { className: "h-3 w-3" }),
|
|
8745
|
+
"Copy id"
|
|
8746
|
+
]
|
|
8747
|
+
}
|
|
8748
|
+
)
|
|
8749
|
+
] }),
|
|
8750
|
+
cell.kind === "edge" && /* @__PURE__ */ jsxs28("div", { className: "px-6 pb-2 text-xs text-muted-foreground", children: [
|
|
8751
|
+
cell.data.start_id_,
|
|
8752
|
+
" ",
|
|
8753
|
+
/* @__PURE__ */ jsx31("span", { className: "text-foreground", children: "\u2192" }),
|
|
8754
|
+
" ",
|
|
8755
|
+
cell.data.end_id_
|
|
8756
|
+
] }),
|
|
8757
|
+
/* @__PURE__ */ jsx31(InspectorBody, { cell })
|
|
8758
|
+
] })
|
|
8759
|
+
}
|
|
8760
|
+
) });
|
|
8761
|
+
}
|
|
8762
|
+
|
|
8763
|
+
// src/tabular/PaginationFooter.tsx
|
|
8764
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
8765
|
+
import { Button as Button14 } from "@petrarca/sonnet-ui";
|
|
8766
|
+
|
|
8767
|
+
// src/tabular/pagination.ts
|
|
8768
|
+
function pageLabels(page, rowsOnPage) {
|
|
8769
|
+
const end = page.offset + rowsOnPage;
|
|
8770
|
+
const range = rowsOnPage > 0 ? `${(page.offset + 1).toLocaleString()}\u2013${end.toLocaleString()}` : "0";
|
|
8771
|
+
const total = page.total != null ? page.total.toLocaleString() : `${end.toLocaleString()}+`;
|
|
8772
|
+
return { range, total };
|
|
8773
|
+
}
|
|
8774
|
+
|
|
8775
|
+
// src/tabular/PaginationFooter.tsx
|
|
8776
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
8777
|
+
function PageSizeSelect({
|
|
8778
|
+
size,
|
|
8779
|
+
options,
|
|
8780
|
+
onChange
|
|
8781
|
+
}) {
|
|
8782
|
+
return /* @__PURE__ */ jsxs29("label", { className: "flex items-center gap-1.5", children: [
|
|
8783
|
+
/* @__PURE__ */ jsx32("span", { children: "Rows" }),
|
|
8784
|
+
/* @__PURE__ */ jsx32(
|
|
8785
|
+
"select",
|
|
8786
|
+
{
|
|
8787
|
+
className: "rounded border border-border bg-background px-1.5 py-0.5 text-foreground",
|
|
8788
|
+
value: size,
|
|
8789
|
+
onChange: (e) => onChange(Number(e.target.value)),
|
|
8790
|
+
children: options.map((opt) => /* @__PURE__ */ jsx32("option", { value: opt, children: opt }, opt))
|
|
8791
|
+
}
|
|
8792
|
+
)
|
|
8793
|
+
] });
|
|
8794
|
+
}
|
|
8795
|
+
function PageNav({
|
|
8796
|
+
pageIndex,
|
|
8797
|
+
hasMore,
|
|
8798
|
+
onPageChange
|
|
8799
|
+
}) {
|
|
8800
|
+
return /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-1", children: [
|
|
8801
|
+
/* @__PURE__ */ jsx32(
|
|
8802
|
+
Button14,
|
|
8803
|
+
{
|
|
8804
|
+
variant: "outline",
|
|
8805
|
+
size: "sm",
|
|
8806
|
+
className: "h-7 gap-1 px-2",
|
|
8807
|
+
disabled: pageIndex <= 0,
|
|
8808
|
+
onClick: () => onPageChange(pageIndex - 1),
|
|
8809
|
+
"aria-label": "Previous page",
|
|
8810
|
+
children: /* @__PURE__ */ jsx32(ChevronLeft, { className: "h-3.5 w-3.5" })
|
|
8811
|
+
}
|
|
8812
|
+
),
|
|
8813
|
+
/* @__PURE__ */ jsxs29("span", { className: "px-1", children: [
|
|
8814
|
+
"Page ",
|
|
8815
|
+
pageIndex + 1
|
|
8816
|
+
] }),
|
|
8817
|
+
/* @__PURE__ */ jsx32(
|
|
8818
|
+
Button14,
|
|
8819
|
+
{
|
|
8820
|
+
variant: "outline",
|
|
8821
|
+
size: "sm",
|
|
8822
|
+
className: "h-7 gap-1 px-2",
|
|
8823
|
+
disabled: !hasMore,
|
|
8824
|
+
onClick: () => onPageChange(pageIndex + 1),
|
|
8825
|
+
"aria-label": "Next page",
|
|
8826
|
+
children: /* @__PURE__ */ jsx32(ChevronRight, { className: "h-3.5 w-3.5" })
|
|
8827
|
+
}
|
|
8828
|
+
)
|
|
8829
|
+
] });
|
|
8830
|
+
}
|
|
8831
|
+
function PaginationFooter({
|
|
8832
|
+
page,
|
|
8833
|
+
rowsOnPage,
|
|
8834
|
+
controls
|
|
8835
|
+
}) {
|
|
8836
|
+
if (!page) return null;
|
|
8837
|
+
const { range, total } = pageLabels(page, rowsOnPage);
|
|
8838
|
+
const {
|
|
8839
|
+
pageIndex,
|
|
8840
|
+
pageSize,
|
|
8841
|
+
pageSizeOptions,
|
|
8842
|
+
onPageChange,
|
|
8843
|
+
onPageSizeChange
|
|
8844
|
+
} = controls;
|
|
8845
|
+
return /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between gap-4 border-t border-border px-3 py-2 text-xs text-muted-foreground shrink-0", children: [
|
|
8846
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-2", children: [
|
|
8847
|
+
/* @__PURE__ */ jsxs29("span", { children: [
|
|
8848
|
+
"Showing ",
|
|
8849
|
+
/* @__PURE__ */ jsx32("span", { className: "text-foreground", children: range }),
|
|
8850
|
+
" of",
|
|
8851
|
+
" ",
|
|
8852
|
+
/* @__PURE__ */ jsx32("span", { className: "text-foreground", children: total })
|
|
8853
|
+
] }),
|
|
8854
|
+
page.truncated && /* @__PURE__ */ jsx32("span", { className: "text-amber-600 dark:text-amber-400", children: "(capped)" })
|
|
8855
|
+
] }),
|
|
8856
|
+
onPageChange && /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-3", children: [
|
|
8857
|
+
pageSizeOptions && onPageSizeChange && /* @__PURE__ */ jsx32(
|
|
8858
|
+
PageSizeSelect,
|
|
8859
|
+
{
|
|
8860
|
+
size: pageSize ?? page.limit,
|
|
8861
|
+
options: pageSizeOptions,
|
|
8862
|
+
onChange: onPageSizeChange
|
|
8863
|
+
}
|
|
8864
|
+
),
|
|
8865
|
+
/* @__PURE__ */ jsx32(
|
|
8866
|
+
PageNav,
|
|
8867
|
+
{
|
|
8868
|
+
pageIndex,
|
|
8869
|
+
hasMore: page.has_more,
|
|
8870
|
+
onPageChange
|
|
8871
|
+
}
|
|
8872
|
+
)
|
|
8873
|
+
] })
|
|
8874
|
+
] });
|
|
8875
|
+
}
|
|
8876
|
+
|
|
8877
|
+
// src/tabular/JsonCell.tsx
|
|
8878
|
+
import React18 from "react";
|
|
8879
|
+
import { escapeHtml, formatJsonValue } from "@petrarca/sonnet-core";
|
|
8880
|
+
|
|
8881
|
+
// src/tabular/GraphChip.tsx
|
|
8882
|
+
import React17, { useMemo as useMemo15 } from "react";
|
|
8883
|
+
import { ArrowRight as ArrowRight3 } from "lucide-react";
|
|
8884
|
+
import { SimpleTooltip as SimpleTooltip6 } from "@petrarca/sonnet-ui";
|
|
8885
|
+
import { jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
8886
|
+
function GraphChipImpl({ cell }) {
|
|
8887
|
+
const { palette, labelDisplayMap, onInspect } = useTabularCellContext();
|
|
8888
|
+
const caption = useMemo15(
|
|
8889
|
+
() => captionFor(cell, labelDisplayMap),
|
|
8890
|
+
[cell, labelDisplayMap]
|
|
8891
|
+
);
|
|
8892
|
+
const extraProps = useMemo15(() => propertyCount(cell), [cell]);
|
|
8893
|
+
const color = colorForLabel(cell.data.label_, palette);
|
|
8894
|
+
const isNode = cell.kind === "node";
|
|
8895
|
+
const idSuffix = cell.data.id_ != null ? ` #${cell.data.id_}` : "";
|
|
8896
|
+
const propsLabel = `${extraProps} ${extraProps === 1 ? "property" : "properties"}`;
|
|
8897
|
+
return /* @__PURE__ */ jsx33(SimpleTooltip6, { label: `${cell.data.label_}${idSuffix} \xB7 ${caption}`, children: /* @__PURE__ */ jsxs30(
|
|
8898
|
+
"button",
|
|
8899
|
+
{
|
|
8900
|
+
type: "button",
|
|
8901
|
+
onClick: () => onInspect?.(cell),
|
|
8902
|
+
"aria-label": `${isNode ? "Node" : "Relationship"} ${cell.data.label_}, ${caption}, ${propsLabel}. Activate to inspect.`,
|
|
8903
|
+
className: "inline-flex max-w-full items-center gap-1.5 rounded-full border border-border bg-card px-2 py-0.5 text-xs hover:bg-state-hover focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8904
|
+
children: [
|
|
8905
|
+
isNode ? /* @__PURE__ */ jsx33(
|
|
8906
|
+
"span",
|
|
8907
|
+
{
|
|
8908
|
+
"aria-hidden": "true",
|
|
8909
|
+
className: "h-2.5 w-2.5 shrink-0 rounded-full",
|
|
8910
|
+
style: { backgroundColor: color }
|
|
8911
|
+
}
|
|
8912
|
+
) : /* @__PURE__ */ jsx33(
|
|
8913
|
+
ArrowRight3,
|
|
8914
|
+
{
|
|
8915
|
+
"aria-hidden": "true",
|
|
8916
|
+
className: "h-3 w-3 shrink-0",
|
|
8917
|
+
style: { color }
|
|
8918
|
+
}
|
|
8919
|
+
),
|
|
8920
|
+
/* @__PURE__ */ jsx33("span", { className: "shrink-0 font-semibold text-foreground", children: cell.data.label_ }),
|
|
8921
|
+
/* @__PURE__ */ jsx33("span", { className: "truncate text-muted-foreground", children: caption }),
|
|
8922
|
+
extraProps > 0 && /* @__PURE__ */ jsxs30("span", { className: "shrink-0 text-tertiary-foreground", children: [
|
|
8923
|
+
"+",
|
|
8924
|
+
extraProps
|
|
8925
|
+
] })
|
|
8926
|
+
]
|
|
8927
|
+
}
|
|
8928
|
+
) });
|
|
8929
|
+
}
|
|
8930
|
+
var GraphChip = React17.memo(GraphChipImpl);
|
|
8931
|
+
|
|
8932
|
+
// src/tabular/JsonCell.tsx
|
|
8933
|
+
import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
8934
|
+
function ScalarValue({
|
|
8935
|
+
value
|
|
8936
|
+
}) {
|
|
8937
|
+
if (value === null || value === void 0) {
|
|
8938
|
+
return /* @__PURE__ */ jsx34("span", { style: { color: "var(--json-null)" }, children: "null" });
|
|
8939
|
+
}
|
|
8940
|
+
if (typeof value === "string") {
|
|
8941
|
+
return /* @__PURE__ */ jsxs31("span", { style: { color: "var(--json-string)" }, children: [
|
|
8942
|
+
'"',
|
|
8943
|
+
escapeHtml(value),
|
|
8944
|
+
'"'
|
|
8945
|
+
] });
|
|
8946
|
+
}
|
|
8947
|
+
if (typeof value === "number") {
|
|
8948
|
+
return /* @__PURE__ */ jsx34("span", { style: { color: "var(--json-number)" }, children: value });
|
|
8949
|
+
}
|
|
8950
|
+
return /* @__PURE__ */ jsx34("span", { style: { color: "var(--json-boolean)" }, children: value ? "true" : "false" });
|
|
8951
|
+
}
|
|
8952
|
+
function JsonRenderer({
|
|
8953
|
+
value,
|
|
8954
|
+
className = "max-w-sm"
|
|
8955
|
+
}) {
|
|
8956
|
+
if (value === null || typeof value !== "object") {
|
|
8957
|
+
return /* @__PURE__ */ jsx34(
|
|
8958
|
+
ScalarValue,
|
|
8959
|
+
{
|
|
8960
|
+
value
|
|
8961
|
+
}
|
|
8962
|
+
);
|
|
8963
|
+
}
|
|
8964
|
+
return /* @__PURE__ */ jsx34(
|
|
8965
|
+
"div",
|
|
8966
|
+
{
|
|
8967
|
+
className: `text-sm font-mono whitespace-pre-wrap break-words ${className}`,
|
|
8968
|
+
dangerouslySetInnerHTML: { __html: formatJsonValue(value) }
|
|
8969
|
+
}
|
|
8970
|
+
);
|
|
8971
|
+
}
|
|
8972
|
+
function JsonCellImpl({ value }) {
|
|
8973
|
+
const graphCell = asGraphCell(value);
|
|
8974
|
+
if (graphCell) return /* @__PURE__ */ jsx34(GraphChip, { cell: graphCell });
|
|
8975
|
+
return /* @__PURE__ */ jsx34(JsonRenderer, { value });
|
|
8976
|
+
}
|
|
8977
|
+
var JsonCell = React18.memo(JsonCellImpl);
|
|
8978
|
+
|
|
8979
|
+
// src/tabular/tableColumns.tsx
|
|
8980
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
8981
|
+
var COLUMN_SIZING = {
|
|
8982
|
+
record: { size: 220, minSize: 140, maxSize: 280 },
|
|
8983
|
+
array: { size: 200, minSize: 140, maxSize: 260 },
|
|
8984
|
+
value: { size: 200, minSize: 140, maxSize: 260 }
|
|
8985
|
+
};
|
|
8986
|
+
function buildColumns(headerInfo, rowOffset, sortingEnabled) {
|
|
8987
|
+
const { headers, mode } = headerInfo;
|
|
8988
|
+
const sizing = COLUMN_SIZING[mode];
|
|
8989
|
+
const dataColumns = headers.map((header, index) => ({
|
|
8990
|
+
id: header,
|
|
8991
|
+
header,
|
|
8992
|
+
accessorFn: (row) => getCellValue(row, header, index, mode),
|
|
8993
|
+
cell: ({ getValue }) => /* @__PURE__ */ jsx35(JsonCell, { value: getValue() }),
|
|
8994
|
+
enableSorting: sortingEnabled,
|
|
8995
|
+
...sizing
|
|
8996
|
+
}));
|
|
8997
|
+
return [
|
|
8998
|
+
{
|
|
8999
|
+
id: "__index",
|
|
9000
|
+
header: "#",
|
|
9001
|
+
enableSorting: false,
|
|
9002
|
+
size: 48,
|
|
9003
|
+
minSize: 40,
|
|
9004
|
+
maxSize: 64,
|
|
9005
|
+
cell: ({ row }) => /* @__PURE__ */ jsx35("span", { className: "text-muted-foreground", children: rowOffset + row.index + 1 })
|
|
9006
|
+
},
|
|
9007
|
+
...dataColumns
|
|
9008
|
+
];
|
|
9009
|
+
}
|
|
9010
|
+
|
|
9011
|
+
// src/tabular/VirtualTable.tsx
|
|
9012
|
+
import { useRef as useRef10, useState as useState21 } from "react";
|
|
9013
|
+
import {
|
|
9014
|
+
flexRender,
|
|
9015
|
+
getCoreRowModel,
|
|
9016
|
+
getSortedRowModel,
|
|
9017
|
+
useReactTable
|
|
9018
|
+
} from "@tanstack/react-table";
|
|
9019
|
+
import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
|
|
9020
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
9021
|
+
var ROW_HEIGHT = 41;
|
|
9022
|
+
var HEADER_PADDING = { index: "px-2 py-2", data: "px-4 py-2" };
|
|
9023
|
+
var CELL_PADDING = { index: "px-2 py-3", data: "px-4 py-3" };
|
|
9024
|
+
function padding(table, columnId) {
|
|
9025
|
+
return columnId === "__index" ? table.index : table.data;
|
|
9026
|
+
}
|
|
9027
|
+
function SortIndicator({
|
|
9028
|
+
sorted
|
|
9029
|
+
}) {
|
|
9030
|
+
if (sorted === "asc") return /* @__PURE__ */ jsx36("span", { className: "text-muted-foreground", children: "\u25B2" });
|
|
9031
|
+
if (sorted === "desc")
|
|
9032
|
+
return /* @__PURE__ */ jsx36("span", { className: "text-muted-foreground", children: "\u25BC" });
|
|
9033
|
+
return null;
|
|
9034
|
+
}
|
|
9035
|
+
function HeaderCell({
|
|
9036
|
+
header
|
|
9037
|
+
}) {
|
|
9038
|
+
const width = { width: `${header.getSize()}px` };
|
|
9039
|
+
if (header.isPlaceholder)
|
|
9040
|
+
return /* @__PURE__ */ jsx36("th", { className: "border-r border-border", style: width });
|
|
9041
|
+
const sortable = header.column.getCanSort();
|
|
9042
|
+
const sorted = header.column.getIsSorted();
|
|
9043
|
+
const ariaSort = sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none";
|
|
9044
|
+
return /* @__PURE__ */ jsx36(
|
|
9045
|
+
"th",
|
|
9046
|
+
{
|
|
9047
|
+
scope: "col",
|
|
9048
|
+
"aria-sort": sortable ? ariaSort : void 0,
|
|
9049
|
+
className: `text-left text-xs font-semibold tracking-wide border-r border-border ${padding(HEADER_PADDING, header.id)} ${sortable ? "cursor-pointer select-none" : ""}`,
|
|
9050
|
+
onClick: sortable ? header.column.getToggleSortingHandler() : void 0,
|
|
9051
|
+
style: width,
|
|
9052
|
+
children: /* @__PURE__ */ jsxs32("span", { className: "inline-flex items-center gap-1", children: [
|
|
9053
|
+
flexRender(header.column.columnDef.header, header.getContext()),
|
|
9054
|
+
/* @__PURE__ */ jsx36(SortIndicator, { sorted })
|
|
9055
|
+
] })
|
|
9056
|
+
}
|
|
9057
|
+
);
|
|
9058
|
+
}
|
|
9059
|
+
function SpacerRow({
|
|
9060
|
+
height,
|
|
9061
|
+
colSpan
|
|
9062
|
+
}) {
|
|
9063
|
+
if (height <= 0) return null;
|
|
9064
|
+
return /* @__PURE__ */ jsx36("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx36("td", { style: { height: `${height}px` }, colSpan }) });
|
|
9065
|
+
}
|
|
9066
|
+
function VirtualTable({
|
|
9067
|
+
rows,
|
|
9068
|
+
columns
|
|
9069
|
+
}) {
|
|
9070
|
+
const [sorting, setSorting] = useState21([]);
|
|
9071
|
+
const [columnSizing, setColumnSizing] = useState21({});
|
|
9072
|
+
const table = useReactTable({
|
|
9073
|
+
data: rows,
|
|
9074
|
+
columns,
|
|
9075
|
+
state: { sorting, columnSizing },
|
|
9076
|
+
onSortingChange: setSorting,
|
|
9077
|
+
onColumnSizingChange: setColumnSizing,
|
|
9078
|
+
enableSortingRemoval: true,
|
|
9079
|
+
// 'onEnd' commits the width once, instead of re-rendering cells per pixel.
|
|
9080
|
+
columnResizeMode: "onEnd",
|
|
9081
|
+
getCoreRowModel: getCoreRowModel(),
|
|
9082
|
+
getSortedRowModel: getSortedRowModel()
|
|
9083
|
+
});
|
|
9084
|
+
const tableRows = table.getRowModel().rows;
|
|
9085
|
+
const scrollRef = useRef10(null);
|
|
9086
|
+
const virtualizer = useVirtualizer2({
|
|
9087
|
+
count: tableRows.length,
|
|
9088
|
+
getScrollElement: () => scrollRef.current,
|
|
9089
|
+
estimateSize: () => ROW_HEIGHT,
|
|
9090
|
+
overscan: 12
|
|
9091
|
+
});
|
|
9092
|
+
const virtualRows = virtualizer.getVirtualItems();
|
|
9093
|
+
const paddingTop = virtualRows.length > 0 ? virtualRows[0].start : 0;
|
|
9094
|
+
const paddingBottom = virtualRows.length > 0 ? virtualizer.getTotalSize() - virtualRows[virtualRows.length - 1].end : 0;
|
|
9095
|
+
return /* @__PURE__ */ jsx36("div", { ref: scrollRef, className: "flex-1 overflow-auto px-3 min-h-0", children: /* @__PURE__ */ jsxs32("table", { className: "min-w-full table-fixed border border-border border-collapse text-sm font-mono text-foreground shadow-sm", children: [
|
|
9096
|
+
/* @__PURE__ */ jsx36("thead", { className: "sticky top-0 z-10 bg-muted text-muted-foreground", children: table.getHeaderGroups().map((group) => /* @__PURE__ */ jsx36("tr", { className: "border-b border-border", children: group.headers.map((header) => /* @__PURE__ */ jsx36(HeaderCell, { header }, header.id)) }, group.id)) }),
|
|
9097
|
+
/* @__PURE__ */ jsxs32("tbody", { children: [
|
|
9098
|
+
/* @__PURE__ */ jsx36(SpacerRow, { height: paddingTop, colSpan: columns.length }),
|
|
9099
|
+
virtualRows.map((virtualRow) => {
|
|
9100
|
+
const row = tableRows[virtualRow.index];
|
|
9101
|
+
return /* @__PURE__ */ jsx36(
|
|
9102
|
+
"tr",
|
|
9103
|
+
{
|
|
9104
|
+
"data-index": virtualRow.index,
|
|
9105
|
+
ref: virtualizer.measureElement,
|
|
9106
|
+
className: "border-b border-border",
|
|
9107
|
+
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx36(
|
|
9108
|
+
"td",
|
|
9109
|
+
{
|
|
9110
|
+
className: `align-top border-r border-border bg-background ${padding(CELL_PADDING, cell.column.id)}`,
|
|
9111
|
+
style: { width: `${cell.column.getSize()}px` },
|
|
9112
|
+
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
9113
|
+
},
|
|
9114
|
+
cell.id
|
|
9115
|
+
))
|
|
9116
|
+
},
|
|
9117
|
+
row.id
|
|
9118
|
+
);
|
|
9119
|
+
}),
|
|
9120
|
+
/* @__PURE__ */ jsx36(SpacerRow, { height: paddingBottom, colSpan: columns.length })
|
|
9121
|
+
] })
|
|
9122
|
+
] }) });
|
|
9123
|
+
}
|
|
9124
|
+
|
|
9125
|
+
// src/tabular/TabularVisualizer.tsx
|
|
9126
|
+
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
9127
|
+
function paletteFromRows(rows) {
|
|
9128
|
+
const nodes = [];
|
|
9129
|
+
for (const row of rows) {
|
|
9130
|
+
for (const cell of rowCells(row)) {
|
|
9131
|
+
const gc = asGraphCell(cell);
|
|
9132
|
+
if (gc?.kind === "node") nodes.push({ label_: gc.data.label_ });
|
|
9133
|
+
}
|
|
9134
|
+
}
|
|
9135
|
+
return buildColorPaletteFromNodes(nodes);
|
|
9136
|
+
}
|
|
9137
|
+
function useInspector() {
|
|
9138
|
+
const [cell, setCell] = useState22(null);
|
|
9139
|
+
const [open, setOpen] = useState22(false);
|
|
9140
|
+
const onInspect = useCallback13((next) => {
|
|
9141
|
+
setCell(next);
|
|
9142
|
+
setOpen(true);
|
|
9143
|
+
}, []);
|
|
9144
|
+
return { cell, open, setOpen, onInspect };
|
|
9145
|
+
}
|
|
9146
|
+
function TabularVisualizer({
|
|
9147
|
+
result,
|
|
9148
|
+
labelDisplayMap,
|
|
9149
|
+
exportFileName = "query-result",
|
|
9150
|
+
pageIndex = 0,
|
|
9151
|
+
...controls
|
|
9152
|
+
}) {
|
|
9153
|
+
const rows = useMemo16(() => result?.rows ?? [], [result]);
|
|
9154
|
+
const page = result?.page ?? null;
|
|
9155
|
+
const headerInfo = useMemo16(
|
|
9156
|
+
() => deriveHeaders(rows, result?.colNames),
|
|
9157
|
+
[rows, result?.colNames]
|
|
9158
|
+
);
|
|
9159
|
+
const palette = useMemo16(() => paletteFromRows(rows), [rows]);
|
|
9160
|
+
const inspector = useInspector();
|
|
9161
|
+
const { onInspect } = inspector;
|
|
9162
|
+
const cellContext = useMemo16(
|
|
9163
|
+
() => ({ palette, labelDisplayMap, onInspect }),
|
|
9164
|
+
[palette, labelDisplayMap, onInspect]
|
|
9165
|
+
);
|
|
9166
|
+
const rowOffset = page?.offset ?? 0;
|
|
9167
|
+
const columns = useMemo16(
|
|
9168
|
+
() => buildColumns(headerInfo, rowOffset, !page),
|
|
9169
|
+
[headerInfo, rowOffset, page]
|
|
9170
|
+
);
|
|
9171
|
+
if (!result)
|
|
9172
|
+
return /* @__PURE__ */ jsx37(CenteredMessage, { children: "No tabular data available." });
|
|
9173
|
+
if (rows.length === 0)
|
|
9174
|
+
return /* @__PURE__ */ jsx37(CenteredMessage, { children: "Result set is empty." });
|
|
9175
|
+
return /* @__PURE__ */ jsx37(TabularCellContext.Provider, { value: cellContext, children: /* @__PURE__ */ jsxs33("div", { className: "w-full h-full flex flex-col bg-background", children: [
|
|
9176
|
+
/* @__PURE__ */ jsx37("div", { className: "flex justify-end px-3 pt-3 pb-2 shrink-0", children: /* @__PURE__ */ jsx37(
|
|
9177
|
+
ExportMenu,
|
|
9178
|
+
{
|
|
9179
|
+
rows,
|
|
9180
|
+
headerInfo,
|
|
9181
|
+
fileName: exportFileName
|
|
9182
|
+
}
|
|
9183
|
+
) }),
|
|
9184
|
+
/* @__PURE__ */ jsx37(VirtualTable, { rows, columns }),
|
|
9185
|
+
/* @__PURE__ */ jsx37(
|
|
9186
|
+
PaginationFooter,
|
|
9187
|
+
{
|
|
9188
|
+
page,
|
|
9189
|
+
rowsOnPage: rows.length,
|
|
9190
|
+
controls: { pageIndex, ...controls }
|
|
9191
|
+
}
|
|
9192
|
+
),
|
|
9193
|
+
/* @__PURE__ */ jsx37(
|
|
9194
|
+
GraphInspector,
|
|
9195
|
+
{
|
|
9196
|
+
cell: inspector.cell,
|
|
9197
|
+
open: inspector.open,
|
|
9198
|
+
onOpenChange: inspector.setOpen,
|
|
9199
|
+
palette,
|
|
9200
|
+
labelDisplayMap
|
|
9201
|
+
}
|
|
9202
|
+
)
|
|
9203
|
+
] }) });
|
|
9204
|
+
}
|
|
9205
|
+
|
|
9206
|
+
// src/tabular/ResultViewTabs.tsx
|
|
9207
|
+
import { Tabs as Tabs2, TabsList as TabsList2, TabsTrigger as TabsTrigger2 } from "@petrarca/sonnet-ui";
|
|
9208
|
+
import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
9209
|
+
function ResultViewTabs({
|
|
9210
|
+
value,
|
|
9211
|
+
onChange
|
|
9212
|
+
}) {
|
|
9213
|
+
return /* @__PURE__ */ jsx38(Tabs2, { value, onValueChange: (v) => onChange(v), children: /* @__PURE__ */ jsxs34(TabsList2, { children: [
|
|
9214
|
+
/* @__PURE__ */ jsx38(TabsTrigger2, { value: "graph", children: "Graph View" }),
|
|
9215
|
+
/* @__PURE__ */ jsx38(TabsTrigger2, { value: "table", children: "Table View" })
|
|
9216
|
+
] }) });
|
|
9217
|
+
}
|
|
9218
|
+
|
|
9219
|
+
// src/tabular/resultView.ts
|
|
9220
|
+
import { useState as useState23 } from "react";
|
|
9221
|
+
function classifyResult(isGraph, rowCount) {
|
|
9222
|
+
if (isGraph) return "graph";
|
|
9223
|
+
return rowCount > 0 ? "tabular" : "empty";
|
|
9224
|
+
}
|
|
9225
|
+
function isViewValid(view, kind) {
|
|
9226
|
+
return view === "table" || kind !== "tabular";
|
|
9227
|
+
}
|
|
9228
|
+
function naturalView(kind) {
|
|
9229
|
+
return kind === "graph" ? "graph" : "table";
|
|
9230
|
+
}
|
|
9231
|
+
function useResultView(kind, resultKey2, { initialView } = {}) {
|
|
9232
|
+
const [state, setState] = useState23(() => ({
|
|
9233
|
+
key: resultKey2,
|
|
9234
|
+
view: initialView ?? naturalView(kind)
|
|
9235
|
+
}));
|
|
9236
|
+
let view = state.view;
|
|
9237
|
+
if (state.key !== resultKey2) {
|
|
9238
|
+
const firstResult = state.key == null && resultKey2 != null;
|
|
9239
|
+
view = firstResult ? naturalView(kind) : state.view;
|
|
9240
|
+
if (!isViewValid(view, kind)) view = naturalView(kind);
|
|
9241
|
+
setState({ key: resultKey2, view });
|
|
9242
|
+
}
|
|
9243
|
+
const setView = (next) => setState((s) => ({ ...s, view: next }));
|
|
9244
|
+
return [view, setView];
|
|
9245
|
+
}
|
|
9246
|
+
|
|
9247
|
+
// src/workspace/panes.ts
|
|
9248
|
+
function choosePane(view, kind) {
|
|
9249
|
+
if (view === "graph") {
|
|
9250
|
+
return isViewValid("graph", kind) ? "graph" : "graph-unavailable";
|
|
9251
|
+
}
|
|
9252
|
+
return kind === "empty" ? "table-empty" : "table";
|
|
9253
|
+
}
|
|
9254
|
+
|
|
9255
|
+
// src/workspace/ResultWorkspace.tsx
|
|
9256
|
+
import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
9257
|
+
function ResultWorkspace({
|
|
9258
|
+
kind,
|
|
9259
|
+
resultKey: resultKey2,
|
|
9260
|
+
graphPane,
|
|
9261
|
+
tablePane,
|
|
9262
|
+
view: controlledView,
|
|
9263
|
+
onViewChange,
|
|
9264
|
+
initialView
|
|
9265
|
+
}) {
|
|
9266
|
+
const [ownView, setOwnView] = useResultView(kind, resultKey2, { initialView });
|
|
9267
|
+
const view = controlledView ?? ownView;
|
|
9268
|
+
const setView = (next) => {
|
|
9269
|
+
if (next === view) return;
|
|
9270
|
+
setOwnView(next);
|
|
9271
|
+
onViewChange?.(next);
|
|
9272
|
+
};
|
|
9273
|
+
const pane = choosePane(view, kind);
|
|
9274
|
+
return (
|
|
9275
|
+
// contain-inline-size: the workspace fills the width it is given and never
|
|
9276
|
+
// asks its parent for more. Without it a wide table (long names, virtualized
|
|
9277
|
+
// so it changes as you scroll) widens any shrink-to-fit ancestor -- e.g. a
|
|
9278
|
+
// scroll area's display:table wrapper -- and pushes the whole page sideways.
|
|
9279
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex flex-col w-full h-full min-h-0 min-w-0 [contain:inline-size]", children: [
|
|
9280
|
+
/* @__PURE__ */ jsx39("div", { className: "shrink-0", children: /* @__PURE__ */ jsx39(ResultViewTabs, { value: view, onChange: setView }) }),
|
|
9281
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex-1 overflow-hidden flex min-h-0", children: [
|
|
9282
|
+
pane === "graph" && graphPane,
|
|
9283
|
+
pane === "graph-unavailable" && /* @__PURE__ */ jsx39(CenteredMessage, { children: "This result cannot be displayed in the graph view." }),
|
|
9284
|
+
pane === "table" && tablePane,
|
|
9285
|
+
pane === "table-empty" && /* @__PURE__ */ jsx39(CenteredMessage, { children: "No results to display." })
|
|
9286
|
+
] })
|
|
9287
|
+
] })
|
|
9288
|
+
);
|
|
9289
|
+
}
|
|
9290
|
+
|
|
9291
|
+
// src/workspace/GraphPane.tsx
|
|
9292
|
+
import { ResizeHandle as ResizeHandle2 } from "@petrarca/sonnet-ui";
|
|
9293
|
+
|
|
9294
|
+
// src/workspace/usePanelResize.ts
|
|
9295
|
+
import { useCallback as useCallback14, useEffect as useEffect12, useRef as useRef11, useState as useState24 } from "react";
|
|
9296
|
+
function usePanelResize({
|
|
9297
|
+
defaultWidth,
|
|
9298
|
+
minWidth,
|
|
9299
|
+
maxWidth
|
|
9300
|
+
}) {
|
|
9301
|
+
const [width, setWidth] = useState24(defaultWidth);
|
|
9302
|
+
const dragging = useRef11(false);
|
|
9303
|
+
const startX = useRef11(0);
|
|
9304
|
+
const startWidth = useRef11(0);
|
|
9305
|
+
const finish = useCallback14(() => {
|
|
9306
|
+
if (!dragging.current) return;
|
|
9307
|
+
dragging.current = false;
|
|
9308
|
+
document.body.classList.remove("select-none");
|
|
9309
|
+
}, []);
|
|
9310
|
+
useEffect12(() => {
|
|
9311
|
+
const clamp = (v) => Math.min(Math.max(v, minWidth), maxWidth);
|
|
9312
|
+
const onMove = (e) => {
|
|
9313
|
+
if (!dragging.current) return;
|
|
9314
|
+
setWidth(clamp(startWidth.current - (e.clientX - startX.current)));
|
|
9315
|
+
};
|
|
9316
|
+
const onKey = (e) => {
|
|
9317
|
+
if (e.key !== "Escape" || !dragging.current) return;
|
|
9318
|
+
setWidth(startWidth.current);
|
|
9319
|
+
finish();
|
|
9320
|
+
};
|
|
9321
|
+
window.addEventListener("pointermove", onMove);
|
|
9322
|
+
window.addEventListener("pointerup", finish);
|
|
9323
|
+
window.addEventListener("pointercancel", finish);
|
|
9324
|
+
window.addEventListener("keydown", onKey);
|
|
9325
|
+
return () => {
|
|
9326
|
+
window.removeEventListener("pointermove", onMove);
|
|
9327
|
+
window.removeEventListener("pointerup", finish);
|
|
9328
|
+
window.removeEventListener("pointercancel", finish);
|
|
9329
|
+
window.removeEventListener("keydown", onKey);
|
|
9330
|
+
};
|
|
9331
|
+
}, [finish, minWidth, maxWidth]);
|
|
9332
|
+
const onPointerDown = useCallback14(
|
|
9333
|
+
(e) => {
|
|
9334
|
+
dragging.current = true;
|
|
9335
|
+
startX.current = e.clientX;
|
|
9336
|
+
startWidth.current = width;
|
|
9337
|
+
document.body.classList.add("select-none");
|
|
9338
|
+
},
|
|
9339
|
+
[width]
|
|
9340
|
+
);
|
|
9341
|
+
const onDoubleClick = useCallback14(
|
|
9342
|
+
() => setWidth(defaultWidth),
|
|
9343
|
+
[defaultWidth]
|
|
9344
|
+
);
|
|
9345
|
+
return { width, onPointerDown, onDoubleClick };
|
|
9346
|
+
}
|
|
9347
|
+
|
|
9348
|
+
// src/workspace/GraphPane.tsx
|
|
9349
|
+
import { Fragment as Fragment12, jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
9350
|
+
var PANEL_DEFAULT_WIDTH = 320;
|
|
9351
|
+
var PANEL_MIN_WIDTH = 260;
|
|
9352
|
+
var PANEL_MAX_WIDTH = 640;
|
|
9353
|
+
function ActionPanelSlot({
|
|
9354
|
+
actions
|
|
9355
|
+
}) {
|
|
9356
|
+
const visible = useActionPanelStore((s) => s.state) === "visible";
|
|
9357
|
+
const { width, onPointerDown, onDoubleClick } = usePanelResize({
|
|
9358
|
+
defaultWidth: PANEL_DEFAULT_WIDTH,
|
|
9359
|
+
minWidth: PANEL_MIN_WIDTH,
|
|
9360
|
+
maxWidth: PANEL_MAX_WIDTH
|
|
9361
|
+
});
|
|
9362
|
+
if (!visible) return null;
|
|
9363
|
+
return /* @__PURE__ */ jsxs36(Fragment12, { children: [
|
|
9364
|
+
/* @__PURE__ */ jsx40(
|
|
9365
|
+
ResizeHandle2,
|
|
9366
|
+
{
|
|
9367
|
+
orientation: "vertical",
|
|
9368
|
+
"aria-valuenow": width,
|
|
9369
|
+
"aria-valuemin": PANEL_MIN_WIDTH,
|
|
9370
|
+
"aria-valuemax": PANEL_MAX_WIDTH,
|
|
9371
|
+
tabIndex: 0,
|
|
9372
|
+
onPointerDown,
|
|
9373
|
+
onDoubleClick
|
|
9374
|
+
}
|
|
9375
|
+
),
|
|
9376
|
+
/* @__PURE__ */ jsx40("div", { className: "flex-shrink-0 min-h-0 overflow-hidden", style: { width }, children: /* @__PURE__ */ jsx40(ActionPanel_default, { actions }) })
|
|
9377
|
+
] });
|
|
9378
|
+
}
|
|
9379
|
+
function GraphPane({
|
|
9380
|
+
ready = true,
|
|
9381
|
+
loadingLabel = "Preparing graph\u2026",
|
|
9382
|
+
banner,
|
|
9383
|
+
actions,
|
|
9384
|
+
defaultRenderer = "cytoscape",
|
|
9385
|
+
onRendererChange,
|
|
9386
|
+
...visualizerProps
|
|
9387
|
+
}) {
|
|
9388
|
+
return /* @__PURE__ */ jsxs36(
|
|
9389
|
+
GraphRendererProvider,
|
|
9390
|
+
{
|
|
9391
|
+
defaultRenderer,
|
|
9392
|
+
onRendererChange,
|
|
9393
|
+
children: [
|
|
9394
|
+
ready && /* @__PURE__ */ jsx40(GraphA11yList, {}),
|
|
9395
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex-1 flex overflow-hidden min-h-0", children: [
|
|
9396
|
+
!ready && /* @__PURE__ */ jsx40(CenteredMessage, { children: loadingLabel }),
|
|
9397
|
+
ready && /* @__PURE__ */ jsxs36("div", { className: "relative flex-1 min-w-0 overflow-hidden", children: [
|
|
9398
|
+
banner,
|
|
9399
|
+
/* @__PURE__ */ jsx40(GraphVisualizer_default, { ...visualizerProps })
|
|
9400
|
+
] }),
|
|
9401
|
+
ready && /* @__PURE__ */ jsx40(ActionPanelSlot, { actions })
|
|
9402
|
+
] })
|
|
9403
|
+
]
|
|
9404
|
+
}
|
|
9405
|
+
);
|
|
9406
|
+
}
|
|
9407
|
+
|
|
9408
|
+
// src/workspace/LargeResultBanner.tsx
|
|
9409
|
+
import { Info } from "lucide-react";
|
|
9410
|
+
import { formatNumber as formatNumber2 } from "@petrarca/sonnet-core";
|
|
9411
|
+
import { jsx as jsx41, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
9412
|
+
function LargeResultBanner({
|
|
9413
|
+
page
|
|
9414
|
+
}) {
|
|
9415
|
+
if (!page || !page.has_more) return null;
|
|
9416
|
+
const returned = page.returned ?? page.limit;
|
|
9417
|
+
const total = page.total != null ? formatNumber2(page.total) : `${formatNumber2(returned)}+`;
|
|
9418
|
+
return /* @__PURE__ */ jsx41("div", { className: "pointer-events-none absolute left-1/2 top-3 z-10 -translate-x-1/2", children: /* @__PURE__ */ jsxs37("div", { className: "pointer-events-auto flex items-center gap-2 rounded-md border border-border bg-card/95 px-3 py-1.5 text-xs text-muted-foreground shadow-sm backdrop-blur", children: [
|
|
9419
|
+
/* @__PURE__ */ jsx41(Info, { className: "h-3.5 w-3.5 shrink-0 text-primary" }),
|
|
9420
|
+
/* @__PURE__ */ jsxs37("span", { children: [
|
|
9421
|
+
"Showing first",
|
|
9422
|
+
" ",
|
|
9423
|
+
/* @__PURE__ */ jsx41("span", { className: "text-foreground", children: formatNumber2(returned) }),
|
|
9424
|
+
" of",
|
|
9425
|
+
" ",
|
|
9426
|
+
/* @__PURE__ */ jsx41("span", { className: "text-foreground", children: total }),
|
|
9427
|
+
" results \u2014 refine your query or add filters to focus."
|
|
9428
|
+
] })
|
|
9429
|
+
] }) });
|
|
9430
|
+
}
|
|
8275
9431
|
export {
|
|
8276
9432
|
ActionPanel_default as ActionPanel,
|
|
9433
|
+
CenteredMessage,
|
|
8277
9434
|
DeleteNodeDialog,
|
|
8278
9435
|
EMPTY_NORMALIZED,
|
|
8279
9436
|
EdgeFormSheet,
|
|
8280
9437
|
EdgeInfoCard_default as EdgeInfoCard,
|
|
8281
9438
|
GraphA11yList,
|
|
9439
|
+
GraphChip,
|
|
8282
9440
|
GraphEditToolbar,
|
|
8283
9441
|
GraphFinder,
|
|
9442
|
+
GraphInspector,
|
|
8284
9443
|
GraphModelEditor,
|
|
9444
|
+
GraphPane,
|
|
8285
9445
|
GraphRendererProvider,
|
|
8286
9446
|
GraphStoresContext,
|
|
8287
9447
|
GraphVisualizer_default as GraphVisualizer,
|
|
9448
|
+
JsonCell,
|
|
9449
|
+
JsonRenderer,
|
|
9450
|
+
LargeResultBanner,
|
|
8288
9451
|
ModelActionPanel,
|
|
8289
9452
|
NodeFormSheet,
|
|
8290
9453
|
NodeInfoCard_default as NodeInfoCard,
|
|
@@ -8295,14 +9458,22 @@ export {
|
|
|
8295
9458
|
QueryEditor,
|
|
8296
9459
|
QueryHistory,
|
|
8297
9460
|
RelationFormSheet,
|
|
9461
|
+
ResultViewTabs,
|
|
9462
|
+
ResultWorkspace,
|
|
9463
|
+
TabularVisualizer,
|
|
8298
9464
|
TypeDetailPanel,
|
|
8299
9465
|
addEdgeType,
|
|
8300
9466
|
addNodeType,
|
|
8301
9467
|
addRelation,
|
|
9468
|
+
asGraphCell,
|
|
8302
9469
|
buildColorPalette,
|
|
8303
9470
|
buildColorPaletteFromNodes,
|
|
8304
9471
|
capabilitiesSchema,
|
|
9472
|
+
captionFor,
|
|
8305
9473
|
cardinalityLabel,
|
|
9474
|
+
choosePane,
|
|
9475
|
+
classifyResult,
|
|
9476
|
+
colorForLabel,
|
|
8306
9477
|
createActionPanelStore,
|
|
8307
9478
|
createGraphDataStore,
|
|
8308
9479
|
createGraphExplorationStore,
|
|
@@ -8316,6 +9487,8 @@ export {
|
|
|
8316
9487
|
deleteNodeType,
|
|
8317
9488
|
deleteRelation,
|
|
8318
9489
|
deleteRelationProperty,
|
|
9490
|
+
deriveHeaders,
|
|
9491
|
+
downloadFile,
|
|
8319
9492
|
edgeTypeView,
|
|
8320
9493
|
editableRelations,
|
|
8321
9494
|
enrichEdge,
|
|
@@ -8329,20 +9502,25 @@ export {
|
|
|
8329
9502
|
findEdgeType,
|
|
8330
9503
|
findType,
|
|
8331
9504
|
flattenGraphData,
|
|
9505
|
+
getCellValue,
|
|
8332
9506
|
graphCapabilitiesSchema,
|
|
8333
9507
|
groupEdgesByRelation,
|
|
8334
9508
|
hasProperties,
|
|
8335
9509
|
hasRelationFields,
|
|
8336
9510
|
initializeFormData,
|
|
8337
9511
|
isEdgeType,
|
|
9512
|
+
isFlatExportSuitable,
|
|
8338
9513
|
isNodeType,
|
|
8339
9514
|
isRawGraphNode,
|
|
8340
9515
|
isRelationField,
|
|
9516
|
+
isViewValid,
|
|
8341
9517
|
isVisualEdge,
|
|
8342
9518
|
isVisualNode,
|
|
8343
9519
|
modelToGraph,
|
|
9520
|
+
naturalView,
|
|
8344
9521
|
nodeTypeView,
|
|
8345
9522
|
normalizeGraph,
|
|
9523
|
+
propertyCount,
|
|
8346
9524
|
reconcileFilter,
|
|
8347
9525
|
relationFieldName,
|
|
8348
9526
|
relationTitle,
|
|
@@ -8351,15 +9529,19 @@ export {
|
|
|
8351
9529
|
renameEdgeType,
|
|
8352
9530
|
renameNodeType,
|
|
8353
9531
|
resolveCapabilities,
|
|
9532
|
+
resolveColumnNames,
|
|
8354
9533
|
resolveGraphCapabilities,
|
|
8355
9534
|
resolveRelationEdge,
|
|
8356
9535
|
setEdgeTypeProperty,
|
|
8357
9536
|
setNodeProperty,
|
|
8358
9537
|
setRelationProperty,
|
|
9538
|
+
toCsv,
|
|
8359
9539
|
toCytoscapeEdge,
|
|
8360
9540
|
toCytoscapeNode,
|
|
9541
|
+
toJson,
|
|
8361
9542
|
toReagraphEdge,
|
|
8362
9543
|
toReagraphNode,
|
|
9544
|
+
toTsv,
|
|
8363
9545
|
typeLabel,
|
|
8364
9546
|
updateRelation,
|
|
8365
9547
|
useActionPanelStore,
|
|
@@ -8369,6 +9551,7 @@ export {
|
|
|
8369
9551
|
useGraphSearch,
|
|
8370
9552
|
useLiveGraphData,
|
|
8371
9553
|
useReagraphData,
|
|
9554
|
+
useResultView,
|
|
8372
9555
|
useStableRef,
|
|
8373
9556
|
useWorkspaceGraphData,
|
|
8374
9557
|
useWorkspaceGraphExploration,
|