system-canvas-standalone 0.1.2 → 0.2.1
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/system-canvas.js +828 -186
- package/dist/system-canvas.js.map +1 -1
- package/dist/system-canvas.min.js +10 -10
- package/dist/system-canvas.min.js.map +1 -1
- package/package.json +22 -6
package/dist/system-canvas.js
CHANGED
|
@@ -12759,12 +12759,12 @@ var SystemCanvas = (() => {
|
|
|
12759
12759
|
render: () => render,
|
|
12760
12760
|
themes: () => themes
|
|
12761
12761
|
});
|
|
12762
|
-
var
|
|
12762
|
+
var import_react22 = __toESM(require_react(), 1);
|
|
12763
12763
|
var import_client = __toESM(require_client(), 1);
|
|
12764
12764
|
|
|
12765
12765
|
// ../react/dist/components/SystemCanvas.js
|
|
12766
|
-
var
|
|
12767
|
-
var
|
|
12766
|
+
var import_jsx_runtime28 = __toESM(require_jsx_runtime(), 1);
|
|
12767
|
+
var import_react21 = __toESM(require_react(), 1);
|
|
12768
12768
|
|
|
12769
12769
|
// ../core/dist/themes/dark.js
|
|
12770
12770
|
var darkTheme = {
|
|
@@ -12827,6 +12827,25 @@ var SystemCanvas = (() => {
|
|
|
12827
12827
|
fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', monospace",
|
|
12828
12828
|
fontSize: 12
|
|
12829
12829
|
},
|
|
12830
|
+
contextMenu: {
|
|
12831
|
+
background: "rgba(15, 23, 42, 0.96)",
|
|
12832
|
+
// slate-900 near-opaque
|
|
12833
|
+
borderColor: "rgba(71, 85, 105, 0.6)",
|
|
12834
|
+
// slate-600
|
|
12835
|
+
borderRadius: 8,
|
|
12836
|
+
itemColor: "#e2e8f0",
|
|
12837
|
+
// slate-200
|
|
12838
|
+
itemHoverBackground: "rgba(71, 85, 105, 0.35)",
|
|
12839
|
+
destructiveItemColor: "#fb7185",
|
|
12840
|
+
// rose-400
|
|
12841
|
+
fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', monospace",
|
|
12842
|
+
fontSize: 12,
|
|
12843
|
+
paddingY: 4,
|
|
12844
|
+
paddingX: 4,
|
|
12845
|
+
itemPaddingY: 5,
|
|
12846
|
+
itemPaddingX: 10,
|
|
12847
|
+
shadow: "0 8px 24px rgba(0,0,0,0.35)"
|
|
12848
|
+
},
|
|
12830
12849
|
lanes: {
|
|
12831
12850
|
bandFillEven: "rgba(30, 41, 59, 0.18)",
|
|
12832
12851
|
// slate-800 soft
|
|
@@ -12912,6 +12931,21 @@ var SystemCanvas = (() => {
|
|
|
12912
12931
|
fontFamily: "'JetBrains Mono', monospace",
|
|
12913
12932
|
fontSize: 11
|
|
12914
12933
|
},
|
|
12934
|
+
contextMenu: {
|
|
12935
|
+
background: "rgba(0, 0, 0, 0.96)",
|
|
12936
|
+
borderColor: "rgba(55, 65, 81, 0.7)",
|
|
12937
|
+
borderRadius: 6,
|
|
12938
|
+
itemColor: "#d1d5db",
|
|
12939
|
+
itemHoverBackground: "rgba(0, 255, 136, 0.12)",
|
|
12940
|
+
destructiveItemColor: "#f87171",
|
|
12941
|
+
fontFamily: "'JetBrains Mono', monospace",
|
|
12942
|
+
fontSize: 11,
|
|
12943
|
+
paddingY: 3,
|
|
12944
|
+
paddingX: 3,
|
|
12945
|
+
itemPaddingY: 5,
|
|
12946
|
+
itemPaddingX: 10,
|
|
12947
|
+
shadow: "0 8px 24px rgba(0,255,136,0.08)"
|
|
12948
|
+
},
|
|
12915
12949
|
lanes: {
|
|
12916
12950
|
bandFillEven: "rgba(17, 17, 17, 0.7)",
|
|
12917
12951
|
bandFillOdd: "rgba(0, 0, 0, 0)",
|
|
@@ -12998,6 +13032,21 @@ var SystemCanvas = (() => {
|
|
|
12998
13032
|
fontFamily: "'Inter', 'Helvetica Neue', sans-serif",
|
|
12999
13033
|
fontSize: 12
|
|
13000
13034
|
},
|
|
13035
|
+
contextMenu: {
|
|
13036
|
+
background: "rgba(255, 255, 255, 0.98)",
|
|
13037
|
+
borderColor: "rgba(203, 213, 225, 0.9)",
|
|
13038
|
+
borderRadius: 8,
|
|
13039
|
+
itemColor: "#1e293b",
|
|
13040
|
+
itemHoverBackground: "rgba(148, 163, 184, 0.18)",
|
|
13041
|
+
destructiveItemColor: "#dc2626",
|
|
13042
|
+
fontFamily: "'Inter', 'Helvetica Neue', sans-serif",
|
|
13043
|
+
fontSize: 12,
|
|
13044
|
+
paddingY: 4,
|
|
13045
|
+
paddingX: 4,
|
|
13046
|
+
itemPaddingY: 5,
|
|
13047
|
+
itemPaddingX: 10,
|
|
13048
|
+
shadow: "0 8px 24px rgba(15,23,42,0.12)"
|
|
13049
|
+
},
|
|
13001
13050
|
lanes: {
|
|
13002
13051
|
bandFillEven: "rgba(148, 163, 184, 0.10)",
|
|
13003
13052
|
// slate-400 soft
|
|
@@ -13077,6 +13126,21 @@ var SystemCanvas = (() => {
|
|
|
13077
13126
|
fontFamily: "'JetBrains Mono', monospace",
|
|
13078
13127
|
fontSize: 11
|
|
13079
13128
|
},
|
|
13129
|
+
contextMenu: {
|
|
13130
|
+
background: "rgba(10, 22, 40, 0.97)",
|
|
13131
|
+
borderColor: "rgba(74, 144, 217, 0.45)",
|
|
13132
|
+
borderRadius: 6,
|
|
13133
|
+
itemColor: "#d4e5f7",
|
|
13134
|
+
itemHoverBackground: "rgba(74, 144, 217, 0.18)",
|
|
13135
|
+
destructiveItemColor: "#fb7185",
|
|
13136
|
+
fontFamily: "'JetBrains Mono', monospace",
|
|
13137
|
+
fontSize: 11,
|
|
13138
|
+
paddingY: 3,
|
|
13139
|
+
paddingX: 3,
|
|
13140
|
+
itemPaddingY: 5,
|
|
13141
|
+
itemPaddingX: 10,
|
|
13142
|
+
shadow: "0 8px 24px rgba(10,22,40,0.5)"
|
|
13143
|
+
},
|
|
13080
13144
|
lanes: {
|
|
13081
13145
|
bandFillEven: "rgba(19, 34, 68, 0.45)",
|
|
13082
13146
|
bandFillOdd: "rgba(19, 34, 68, 0.15)",
|
|
@@ -13154,6 +13218,21 @@ var SystemCanvas = (() => {
|
|
|
13154
13218
|
fontFamily: "'IBM Plex Mono', monospace",
|
|
13155
13219
|
fontSize: 12
|
|
13156
13220
|
},
|
|
13221
|
+
contextMenu: {
|
|
13222
|
+
background: "rgba(26, 23, 20, 0.97)",
|
|
13223
|
+
borderColor: "rgba(107, 94, 74, 0.6)",
|
|
13224
|
+
borderRadius: 8,
|
|
13225
|
+
itemColor: "#e8ddd0",
|
|
13226
|
+
itemHoverBackground: "rgba(107, 94, 74, 0.3)",
|
|
13227
|
+
destructiveItemColor: "#fb7185",
|
|
13228
|
+
fontFamily: "'IBM Plex Mono', monospace",
|
|
13229
|
+
fontSize: 12,
|
|
13230
|
+
paddingY: 4,
|
|
13231
|
+
paddingX: 4,
|
|
13232
|
+
itemPaddingY: 5,
|
|
13233
|
+
itemPaddingX: 10,
|
|
13234
|
+
shadow: "0 8px 24px rgba(0,0,0,0.4)"
|
|
13235
|
+
},
|
|
13157
13236
|
lanes: {
|
|
13158
13237
|
bandFillEven: "rgba(42, 37, 32, 0.55)",
|
|
13159
13238
|
bandFillOdd: "rgba(42, 37, 32, 0.2)",
|
|
@@ -13232,6 +13311,21 @@ var SystemCanvas = (() => {
|
|
|
13232
13311
|
fontFamily: "'Inter', 'Helvetica Neue', sans-serif",
|
|
13233
13312
|
fontSize: 12
|
|
13234
13313
|
},
|
|
13314
|
+
contextMenu: {
|
|
13315
|
+
background: "rgba(15, 17, 21, 0.96)",
|
|
13316
|
+
borderColor: "rgba(63, 69, 83, 0.8)",
|
|
13317
|
+
borderRadius: 8,
|
|
13318
|
+
itemColor: "#e8ebf2",
|
|
13319
|
+
itemHoverBackground: "rgba(90, 100, 120, 0.3)",
|
|
13320
|
+
destructiveItemColor: "#fb7185",
|
|
13321
|
+
fontFamily: "'Inter', 'Helvetica Neue', sans-serif",
|
|
13322
|
+
fontSize: 12,
|
|
13323
|
+
paddingY: 4,
|
|
13324
|
+
paddingX: 4,
|
|
13325
|
+
itemPaddingY: 5,
|
|
13326
|
+
itemPaddingX: 10,
|
|
13327
|
+
shadow: "0 8px 24px rgba(0,0,0,0.4)"
|
|
13328
|
+
},
|
|
13235
13329
|
// Slightly stronger lane fills than the other themes — roadmap columns
|
|
13236
13330
|
// should read as the primary structure of the canvas.
|
|
13237
13331
|
lanes: {
|
|
@@ -13458,10 +13552,16 @@ var SystemCanvas = (() => {
|
|
|
13458
13552
|
group: { ...base.group, ...partial.group },
|
|
13459
13553
|
breadcrumbs: { ...base.breadcrumbs, ...partial.breadcrumbs },
|
|
13460
13554
|
lanes: { ...base.lanes, ...partial.lanes },
|
|
13555
|
+
// contextMenu is optional on CanvasTheme but darkTheme always defines it,
|
|
13556
|
+
// so the resolved theme is guaranteed to have a populated block as long
|
|
13557
|
+
// as `base` is a complete theme (which is the contract).
|
|
13558
|
+
contextMenu: partial.contextMenu ? { ...base.contextMenu, ...partial.contextMenu } : base.contextMenu,
|
|
13461
13559
|
presetColors: { ...base.presetColors, ...partial.presetColors },
|
|
13462
13560
|
categories: { ...base.categories, ...partial.categories },
|
|
13463
13561
|
icons: partial.icons ? { ...base.icons ?? {}, ...partial.icons } : base.icons,
|
|
13464
|
-
nodeActions: partial.nodeActions ?? base.nodeActions
|
|
13562
|
+
nodeActions: partial.nodeActions ?? base.nodeActions,
|
|
13563
|
+
showToolbarDelete: partial.showToolbarDelete ?? base.showToolbarDelete,
|
|
13564
|
+
toolbarAlign: partial.toolbarAlign ?? base.toolbarAlign
|
|
13465
13565
|
};
|
|
13466
13566
|
}
|
|
13467
13567
|
function resolveColor(color2, theme) {
|
|
@@ -13809,6 +13909,29 @@ var SystemCanvas = (() => {
|
|
|
13809
13909
|
return getNodeActions(theme);
|
|
13810
13910
|
}
|
|
13811
13911
|
|
|
13912
|
+
// ../core/dist/contextMenu.js
|
|
13913
|
+
function matchesContextMenuItem(item, node, ctx) {
|
|
13914
|
+
const m = item.match;
|
|
13915
|
+
if (!m)
|
|
13916
|
+
return true;
|
|
13917
|
+
if (m.categories) {
|
|
13918
|
+
if (!node.category)
|
|
13919
|
+
return false;
|
|
13920
|
+
if (!m.categories.includes(node.category))
|
|
13921
|
+
return false;
|
|
13922
|
+
}
|
|
13923
|
+
if (m.types) {
|
|
13924
|
+
if (!m.types.includes(node.type))
|
|
13925
|
+
return false;
|
|
13926
|
+
}
|
|
13927
|
+
if (m.when && !m.when(node, ctx))
|
|
13928
|
+
return false;
|
|
13929
|
+
return true;
|
|
13930
|
+
}
|
|
13931
|
+
function filterContextMenuItems(items, node, ctx) {
|
|
13932
|
+
return items.filter((item) => matchesContextMenuItem(item, node, ctx));
|
|
13933
|
+
}
|
|
13934
|
+
|
|
13812
13935
|
// ../core/dist/rollup.js
|
|
13813
13936
|
function rollupNodes(canvas, predicate) {
|
|
13814
13937
|
const nodes = canvas?.nodes ?? [];
|
|
@@ -13839,6 +13962,23 @@ var SystemCanvas = (() => {
|
|
|
13839
13962
|
var TAB_BADGE_EM = 1.4;
|
|
13840
13963
|
var TAB_BADGE_LIFT = 10;
|
|
13841
13964
|
var TAB_BADGE_OVERHANG = 8;
|
|
13965
|
+
function cornerSlotClearance(spec, fontSize) {
|
|
13966
|
+
if (!spec)
|
|
13967
|
+
return 0;
|
|
13968
|
+
if (spec.kind !== "dot" && spec.kind !== "icon")
|
|
13969
|
+
return 0;
|
|
13970
|
+
const corner = CORNER_EM * fontSize;
|
|
13971
|
+
let renderedWidth = corner;
|
|
13972
|
+
if (spec.kind === "icon") {
|
|
13973
|
+
const explicitSize = spec.size;
|
|
13974
|
+
if (typeof explicitSize === "number" && explicitSize > corner) {
|
|
13975
|
+
renderedWidth = explicitSize;
|
|
13976
|
+
}
|
|
13977
|
+
}
|
|
13978
|
+
const gap = Math.max(8, Math.round(fontSize * 0.75));
|
|
13979
|
+
const overhang = Math.max(0, (renderedWidth - corner) / 2);
|
|
13980
|
+
return overhang + corner + gap;
|
|
13981
|
+
}
|
|
13842
13982
|
function computeCategorySlotRegions(node, theme, slots) {
|
|
13843
13983
|
const { x, y, width, height } = node;
|
|
13844
13984
|
const fs = theme.node.fontSize;
|
|
@@ -13906,12 +14046,16 @@ var SystemCanvas = (() => {
|
|
|
13906
14046
|
width: tab,
|
|
13907
14047
|
height: tab
|
|
13908
14048
|
},
|
|
13909
|
-
topLeft: {
|
|
13910
|
-
|
|
13911
|
-
y: y + CORNER_INSET
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
14049
|
+
topLeft: (() => {
|
|
14050
|
+
const usesInlineRow = slots?.topLeft !== void 0 && (slots.topLeft.kind === "dot" || slots.topLeft.kind === "icon") && slots.header === void 0;
|
|
14051
|
+
const slotY = usesInlineRow ? y + (height - corner) / 2 : y + CORNER_INSET;
|
|
14052
|
+
return {
|
|
14053
|
+
x: x + CORNER_INSET,
|
|
14054
|
+
y: slotY,
|
|
14055
|
+
width: corner,
|
|
14056
|
+
height: corner
|
|
14057
|
+
};
|
|
14058
|
+
})(),
|
|
13915
14059
|
topRight: {
|
|
13916
14060
|
x: x + width - CORNER_INSET - corner,
|
|
13917
14061
|
y: y + CORNER_INSET,
|
|
@@ -13930,18 +14074,49 @@ var SystemCanvas = (() => {
|
|
|
13930
14074
|
width: corner,
|
|
13931
14075
|
height: corner
|
|
13932
14076
|
},
|
|
13933
|
-
header: {
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
14077
|
+
header: (() => {
|
|
14078
|
+
let hx = x + HEADER_INSET_X;
|
|
14079
|
+
let hw = Math.max(0, width - HEADER_INSET_X * 2);
|
|
14080
|
+
const leftClear = cornerSlotClearance(slots?.topLeft, fs);
|
|
14081
|
+
if (leftClear > 0) {
|
|
14082
|
+
const leftEdge = x + CORNER_INSET + leftClear;
|
|
14083
|
+
const shift = Math.max(0, leftEdge - hx);
|
|
14084
|
+
hx += shift;
|
|
14085
|
+
hw = Math.max(0, hw - shift);
|
|
14086
|
+
}
|
|
14087
|
+
const rightClear = cornerSlotClearance(slots?.topRight, fs);
|
|
14088
|
+
if (rightClear > 0) {
|
|
14089
|
+
const rightEdge = x + width - CORNER_INSET - rightClear;
|
|
14090
|
+
const currentRight = hx + hw;
|
|
14091
|
+
const shrink = Math.max(0, currentRight - rightEdge);
|
|
14092
|
+
hw = Math.max(0, hw - shrink);
|
|
14093
|
+
}
|
|
14094
|
+
return { x: hx, y: y + HEADER_INSET_Y, width: hw, height: header };
|
|
14095
|
+
})(),
|
|
14096
|
+
footer: (() => {
|
|
14097
|
+
let fx = x + HEADER_INSET_X;
|
|
14098
|
+
let fw = Math.max(0, width - HEADER_INSET_X * 2);
|
|
14099
|
+
const leftClear = cornerSlotClearance(slots?.bottomLeft, fs);
|
|
14100
|
+
if (leftClear > 0) {
|
|
14101
|
+
const leftEdge = x + CORNER_INSET + leftClear;
|
|
14102
|
+
const shift = Math.max(0, leftEdge - fx);
|
|
14103
|
+
fx += shift;
|
|
14104
|
+
fw = Math.max(0, fw - shift);
|
|
14105
|
+
}
|
|
14106
|
+
const rightClear = cornerSlotClearance(slots?.bottomRight, fs);
|
|
14107
|
+
if (rightClear > 0) {
|
|
14108
|
+
const rightEdge = x + width - CORNER_INSET - rightClear;
|
|
14109
|
+
const currentRight = fx + fw;
|
|
14110
|
+
const shrink = Math.max(0, currentRight - rightEdge);
|
|
14111
|
+
fw = Math.max(0, fw - shrink);
|
|
14112
|
+
}
|
|
14113
|
+
return {
|
|
14114
|
+
x: fx,
|
|
14115
|
+
y: y + height - FOOTER_INSET_Y - footer,
|
|
14116
|
+
width: fw,
|
|
14117
|
+
height: footer
|
|
14118
|
+
};
|
|
14119
|
+
})(),
|
|
13945
14120
|
body: {
|
|
13946
14121
|
x: bodyX,
|
|
13947
14122
|
y: bodyY,
|
|
@@ -14064,13 +14239,26 @@ var SystemCanvas = (() => {
|
|
|
14064
14239
|
left = regions.leftEdge.width + 4;
|
|
14065
14240
|
if (slots.rightEdge)
|
|
14066
14241
|
right = regions.rightEdge.width + 4;
|
|
14067
|
-
if (slots.topLeft && slots.topLeft.kind === "dot") {
|
|
14068
|
-
|
|
14242
|
+
if (slots.topLeft && (slots.topLeft.kind === "dot" || slots.topLeft.kind === "icon")) {
|
|
14243
|
+
const region = regions.topLeft;
|
|
14244
|
+
let renderedWidth = region.width;
|
|
14245
|
+
if (slots.topLeft.kind === "icon") {
|
|
14246
|
+
const explicitSize = slots.topLeft.size;
|
|
14247
|
+
if (typeof explicitSize === "number" && explicitSize > region.width) {
|
|
14248
|
+
renderedWidth = explicitSize;
|
|
14249
|
+
}
|
|
14250
|
+
}
|
|
14251
|
+
const iconLeftFromNode = region.x - node.x + (region.width - renderedWidth) / 2;
|
|
14252
|
+
const gap = Math.max(8, Math.round(theme.node.fontSize * 0.75));
|
|
14253
|
+
left = Math.max(left, iconLeftFromNode + renderedWidth + gap);
|
|
14069
14254
|
}
|
|
14070
|
-
const
|
|
14255
|
+
const hasTopRowSignal = slots.header !== void 0 || slots.topRight !== void 0 || slots.bodyTop !== void 0 || slots.footer !== void 0;
|
|
14256
|
+
const hasInlineLeftMarker = slots.topLeft !== void 0 && (slots.topLeft.kind === "dot" || slots.topLeft.kind === "icon");
|
|
14257
|
+
const isDashboard = hasTopRowSignal || hasInlineLeftMarker;
|
|
14071
14258
|
if (isDashboard) {
|
|
14072
|
-
if (!slots.header)
|
|
14259
|
+
if (hasTopRowSignal && !slots.header) {
|
|
14073
14260
|
top = Math.max(top, HEADER_INSET_Y);
|
|
14261
|
+
}
|
|
14074
14262
|
left = Math.max(left, HEADER_INSET_X);
|
|
14075
14263
|
right = Math.max(right, HEADER_INSET_X);
|
|
14076
14264
|
}
|
|
@@ -14168,6 +14356,29 @@ var SystemCanvas = (() => {
|
|
|
14168
14356
|
}
|
|
14169
14357
|
return out;
|
|
14170
14358
|
}
|
|
14359
|
+
function truncateToWidth(text, maxWidth, fontSize) {
|
|
14360
|
+
if (!text)
|
|
14361
|
+
return text;
|
|
14362
|
+
if (maxWidth <= 0)
|
|
14363
|
+
return text;
|
|
14364
|
+
if (measureTextWidth(text, fontSize) <= maxWidth)
|
|
14365
|
+
return text;
|
|
14366
|
+
const ellipsis = "\u2026";
|
|
14367
|
+
let lo = 0;
|
|
14368
|
+
let hi = text.length;
|
|
14369
|
+
let best = 0;
|
|
14370
|
+
while (lo <= hi) {
|
|
14371
|
+
const mid = lo + hi >> 1;
|
|
14372
|
+
const candidate = text.slice(0, mid) + ellipsis;
|
|
14373
|
+
if (measureTextWidth(candidate, fontSize) <= maxWidth) {
|
|
14374
|
+
best = mid;
|
|
14375
|
+
lo = mid + 1;
|
|
14376
|
+
} else {
|
|
14377
|
+
hi = mid - 1;
|
|
14378
|
+
}
|
|
14379
|
+
}
|
|
14380
|
+
return text.slice(0, best) + ellipsis;
|
|
14381
|
+
}
|
|
14171
14382
|
function ellipsize(line, maxWidth, fontSize) {
|
|
14172
14383
|
const ellipsis = "\u2026";
|
|
14173
14384
|
if (measureTextWidth(line + ellipsis, fontSize) <= maxWidth) {
|
|
@@ -14180,7 +14391,7 @@ var SystemCanvas = (() => {
|
|
|
14180
14391
|
if (measureTextWidth(candidate, fontSize) <= maxWidth)
|
|
14181
14392
|
return candidate;
|
|
14182
14393
|
}
|
|
14183
|
-
return line
|
|
14394
|
+
return truncateToWidth(line, maxWidth, fontSize);
|
|
14184
14395
|
}
|
|
14185
14396
|
|
|
14186
14397
|
// ../core/dist/canvas.js
|
|
@@ -14484,7 +14695,12 @@ var SystemCanvas = (() => {
|
|
|
14484
14695
|
onContextMenu({
|
|
14485
14696
|
type,
|
|
14486
14697
|
target,
|
|
14487
|
-
position: canvasPos
|
|
14698
|
+
position: canvasPos,
|
|
14699
|
+
// Raw viewport coords from the original MouseEvent. Consumers
|
|
14700
|
+
// rendering a `position: fixed` floating menu need these — the
|
|
14701
|
+
// canvas-space `position` would be wrong because it walks
|
|
14702
|
+
// with the user's pan/zoom.
|
|
14703
|
+
screenPosition: { x: event.clientX, y: event.clientY }
|
|
14488
14704
|
});
|
|
14489
14705
|
};
|
|
14490
14706
|
}, [onContextMenu, viewport]);
|
|
@@ -14520,11 +14736,43 @@ var SystemCanvas = (() => {
|
|
|
14520
14736
|
var import_react3 = __toESM(require_react(), 1);
|
|
14521
14737
|
var DRAG_THRESHOLD = 3;
|
|
14522
14738
|
function useNodeDrag(options) {
|
|
14523
|
-
const { viewport, nodesRef, onCommit } = options;
|
|
14739
|
+
const { viewport, nodesRef, onCommit, svgRef, canDropNodeOn, onNodeDrop } = options;
|
|
14524
14740
|
const [dragOverrides, setDragOverrides] = (0, import_react3.useState)(() => /* @__PURE__ */ new Map());
|
|
14525
14741
|
const [isDragging, setIsDragging] = (0, import_react3.useState)(false);
|
|
14742
|
+
const [dropTargetId, setDropTargetId] = (0, import_react3.useState)(null);
|
|
14526
14743
|
const stateRef = (0, import_react3.useRef)(null);
|
|
14527
14744
|
const movedRef = (0, import_react3.useRef)(false);
|
|
14745
|
+
const canDropNodeOnRef = (0, import_react3.useRef)(canDropNodeOn);
|
|
14746
|
+
canDropNodeOnRef.current = canDropNodeOn;
|
|
14747
|
+
const onNodeDropRef = (0, import_react3.useRef)(onNodeDrop);
|
|
14748
|
+
onNodeDropRef.current = onNodeDrop;
|
|
14749
|
+
const svgRefRef = (0, import_react3.useRef)(svgRef);
|
|
14750
|
+
svgRefRef.current = svgRef;
|
|
14751
|
+
const dropTargetIdRef = (0, import_react3.useRef)(null);
|
|
14752
|
+
const computeDropTarget = (0, import_react3.useCallback)((clientX, clientY) => {
|
|
14753
|
+
const cb = canDropNodeOnRef.current;
|
|
14754
|
+
const st = stateRef.current;
|
|
14755
|
+
const nodes = nodesRef.current;
|
|
14756
|
+
const svg = svgRefRef.current?.current;
|
|
14757
|
+
if (!cb || !st || !nodes || !svg)
|
|
14758
|
+
return null;
|
|
14759
|
+
const rect = svg.getBoundingClientRect();
|
|
14760
|
+
const vp = viewport.current ?? { x: 0, y: 0, zoom: 1 };
|
|
14761
|
+
const { x, y } = screenToCanvas(clientX - rect.left, clientY - rect.top, vp);
|
|
14762
|
+
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
14763
|
+
const n = nodes[i];
|
|
14764
|
+
if (st.moving.has(n.id))
|
|
14765
|
+
continue;
|
|
14766
|
+
if (x < n.x || x > n.x + n.width)
|
|
14767
|
+
continue;
|
|
14768
|
+
if (y < n.y || y > n.y + n.height)
|
|
14769
|
+
continue;
|
|
14770
|
+
if (cb([st.source], n))
|
|
14771
|
+
return n.id;
|
|
14772
|
+
return null;
|
|
14773
|
+
}
|
|
14774
|
+
return null;
|
|
14775
|
+
}, [nodesRef, viewport]);
|
|
14528
14776
|
const onPointerMove = (0, import_react3.useCallback)((event) => {
|
|
14529
14777
|
const st = stateRef.current;
|
|
14530
14778
|
if (!st || event.pointerId !== st.pointerId)
|
|
@@ -14546,7 +14794,12 @@ var SystemCanvas = (() => {
|
|
|
14546
14794
|
next.set(id2, { x: start2.startX + dx, y: start2.startY + dy });
|
|
14547
14795
|
}
|
|
14548
14796
|
setDragOverrides(next);
|
|
14549
|
-
|
|
14797
|
+
const nextTarget = computeDropTarget(event.clientX, event.clientY);
|
|
14798
|
+
if (nextTarget !== dropTargetIdRef.current) {
|
|
14799
|
+
dropTargetIdRef.current = nextTarget;
|
|
14800
|
+
setDropTargetId(nextTarget);
|
|
14801
|
+
}
|
|
14802
|
+
}, [viewport, computeDropTarget]);
|
|
14550
14803
|
const finishDrag = (0, import_react3.useCallback)((commit) => {
|
|
14551
14804
|
const st = stateRef.current;
|
|
14552
14805
|
if (!st)
|
|
@@ -14559,17 +14812,38 @@ var SystemCanvas = (() => {
|
|
|
14559
14812
|
st.captureTarget.releasePointerCapture?.(st.pointerId);
|
|
14560
14813
|
} catch {
|
|
14561
14814
|
}
|
|
14815
|
+
const dropTarget = dropTargetIdRef.current;
|
|
14816
|
+
if (commit && movedRef.current && dropTarget) {
|
|
14817
|
+
const nodes = nodesRef.current;
|
|
14818
|
+
const target = nodes?.find((n) => n.id === dropTarget) ?? null;
|
|
14819
|
+
if (target && onNodeDropRef.current) {
|
|
14820
|
+
onNodeDropRef.current([st.source], target);
|
|
14821
|
+
stateRef.current = null;
|
|
14822
|
+
movedRef.current = false;
|
|
14823
|
+
dropTargetIdRef.current = null;
|
|
14824
|
+
setIsDragging(false);
|
|
14825
|
+
setDragOverrides(/* @__PURE__ */ new Map());
|
|
14826
|
+
setDropTargetId(null);
|
|
14827
|
+
return;
|
|
14828
|
+
}
|
|
14829
|
+
}
|
|
14562
14830
|
if (commit && movedRef.current) {
|
|
14563
14831
|
const overrides = Array.from(dragOverridesRef.current.entries());
|
|
14564
|
-
|
|
14565
|
-
|
|
14832
|
+
if (overrides.length > 0) {
|
|
14833
|
+
const updates = overrides.map(([id2, pos]) => ({
|
|
14834
|
+
id: id2,
|
|
14835
|
+
patch: { x: Math.round(pos.x), y: Math.round(pos.y) }
|
|
14836
|
+
}));
|
|
14837
|
+
onCommit(updates);
|
|
14566
14838
|
}
|
|
14567
14839
|
}
|
|
14568
14840
|
stateRef.current = null;
|
|
14569
14841
|
movedRef.current = false;
|
|
14842
|
+
dropTargetIdRef.current = null;
|
|
14570
14843
|
setIsDragging(false);
|
|
14571
14844
|
setDragOverrides(/* @__PURE__ */ new Map());
|
|
14572
|
-
|
|
14845
|
+
setDropTargetId(null);
|
|
14846
|
+
}, [onPointerMove, onCommit, nodesRef]);
|
|
14573
14847
|
const dragOverridesRef = (0, import_react3.useRef)(dragOverrides);
|
|
14574
14848
|
dragOverridesRef.current = dragOverrides;
|
|
14575
14849
|
const onPointerUpRef = (0, import_react3.useRef)(null);
|
|
@@ -14609,9 +14883,11 @@ var SystemCanvas = (() => {
|
|
|
14609
14883
|
startClientY: event.clientY,
|
|
14610
14884
|
captureTarget: event.currentTarget,
|
|
14611
14885
|
pointerId: event.pointerId,
|
|
14612
|
-
moving
|
|
14886
|
+
moving,
|
|
14887
|
+
source: node
|
|
14613
14888
|
};
|
|
14614
14889
|
movedRef.current = false;
|
|
14890
|
+
dropTargetIdRef.current = null;
|
|
14615
14891
|
try {
|
|
14616
14892
|
;
|
|
14617
14893
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
@@ -14621,7 +14897,7 @@ var SystemCanvas = (() => {
|
|
|
14621
14897
|
window.addEventListener("pointerup", onPointerUp);
|
|
14622
14898
|
window.addEventListener("pointercancel", onPointerCancel);
|
|
14623
14899
|
}, [nodesRef, onPointerMove, onPointerUp, onPointerCancel]);
|
|
14624
|
-
return { dragOverrides, onPointerDown, isDragging };
|
|
14900
|
+
return { dragOverrides, dropTargetId, onPointerDown, isDragging };
|
|
14625
14901
|
}
|
|
14626
14902
|
|
|
14627
14903
|
// ../react/dist/hooks/useNodeResize.js
|
|
@@ -14896,11 +15172,15 @@ var SystemCanvas = (() => {
|
|
|
14896
15172
|
return { x, y, zoom };
|
|
14897
15173
|
}
|
|
14898
15174
|
function useZoomNavigation(options) {
|
|
14899
|
-
const { enabled, config, nodes, currentCanvas, parentFrame, canvases, onResolveCanvas, onSeedCanvas, theme, getViewportSize, onEnter, onExit } = options;
|
|
15175
|
+
const { enabled, config, nodes, currentCanvas, parentFrame, canvases, onResolveCanvas, onSeedCanvas, theme, getViewportSize, getCursorScreenPos, onEnter, onExit } = options;
|
|
14900
15176
|
const committingRef = (0, import_react6.useRef)(false);
|
|
14901
15177
|
(0, import_react6.useEffect)(() => {
|
|
14902
15178
|
committingRef.current = false;
|
|
14903
15179
|
}, [currentCanvas]);
|
|
15180
|
+
const exitArmedRef = (0, import_react6.useRef)(false);
|
|
15181
|
+
(0, import_react6.useEffect)(() => {
|
|
15182
|
+
exitArmedRef.current = false;
|
|
15183
|
+
}, [currentCanvas, parentFrame]);
|
|
14904
15184
|
const prefetchRef = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
|
|
14905
15185
|
const prefetch = (0, import_react6.useCallback)((ref) => {
|
|
14906
15186
|
if (!onResolveCanvas)
|
|
@@ -14928,36 +15208,87 @@ var SystemCanvas = (() => {
|
|
|
14928
15208
|
const size = getViewportSize();
|
|
14929
15209
|
if (!size)
|
|
14930
15210
|
return;
|
|
14931
|
-
|
|
14932
|
-
|
|
14933
|
-
|
|
14934
|
-
|
|
14935
|
-
|
|
14936
|
-
const
|
|
14937
|
-
|
|
14938
|
-
|
|
14939
|
-
|
|
15211
|
+
const cursor = getCursorScreenPos();
|
|
15212
|
+
const viewportCenterX = size.width / 2;
|
|
15213
|
+
const viewportCenterY = size.height / 2;
|
|
15214
|
+
let cursorNode = null;
|
|
15215
|
+
if (cursor) {
|
|
15216
|
+
for (const n of nodes) {
|
|
15217
|
+
if (!n.ref)
|
|
15218
|
+
continue;
|
|
15219
|
+
const screen = canvasRectToScreenRect({ x: n.x, y: n.y, width: n.width, height: n.height }, vp);
|
|
15220
|
+
if (cursor.x < screen.x || cursor.x > screen.x + screen.width || cursor.y < screen.y || cursor.y > screen.y + screen.height) {
|
|
15221
|
+
continue;
|
|
15222
|
+
}
|
|
15223
|
+
const area = screen.width * screen.height;
|
|
15224
|
+
if (!cursorNode || area < cursorNode.area) {
|
|
15225
|
+
cursorNode = { node: n, screen, area };
|
|
15226
|
+
}
|
|
15227
|
+
}
|
|
15228
|
+
}
|
|
15229
|
+
let bestCandidate = null;
|
|
15230
|
+
if (cursorNode) {
|
|
15231
|
+
const screen = cursorNode.screen;
|
|
14940
15232
|
const fillFraction = Math.max(screen.width / size.width, screen.height / size.height);
|
|
14941
|
-
if (fillFraction >= config.prefetchThreshold &&
|
|
14942
|
-
prefetch(
|
|
15233
|
+
if (fillFraction >= config.prefetchThreshold && cursorNode.node.ref) {
|
|
15234
|
+
prefetch(cursorNode.node.ref);
|
|
14943
15235
|
}
|
|
14944
15236
|
if (fillFraction >= config.enterThreshold) {
|
|
14945
|
-
|
|
14946
|
-
|
|
15237
|
+
bestCandidate = { node: cursorNode.node, screen, distSq: 0 };
|
|
15238
|
+
}
|
|
15239
|
+
for (const n of nodes) {
|
|
15240
|
+
if (!n.ref)
|
|
15241
|
+
continue;
|
|
15242
|
+
if (n === cursorNode.node)
|
|
15243
|
+
continue;
|
|
15244
|
+
const s = canvasRectToScreenRect({ x: n.x, y: n.y, width: n.width, height: n.height }, vp);
|
|
15245
|
+
const ff = Math.max(s.width / size.width, s.height / size.height);
|
|
15246
|
+
if (ff >= config.prefetchThreshold)
|
|
14947
15247
|
prefetch(n.ref);
|
|
15248
|
+
}
|
|
15249
|
+
} else {
|
|
15250
|
+
for (const n of nodes) {
|
|
15251
|
+
if (!n.ref)
|
|
15252
|
+
continue;
|
|
15253
|
+
const screen = canvasRectToScreenRect({ x: n.x, y: n.y, width: n.width, height: n.height }, vp);
|
|
15254
|
+
const centerX = screen.x + screen.width / 2;
|
|
15255
|
+
const centerY = screen.y + screen.height / 2;
|
|
15256
|
+
const centerOnScreen = centerX >= 0 && centerX <= size.width && centerY >= 0 && centerY <= size.height;
|
|
15257
|
+
if (!centerOnScreen)
|
|
14948
15258
|
continue;
|
|
15259
|
+
const fillFraction = Math.max(screen.width / size.width, screen.height / size.height);
|
|
15260
|
+
if (fillFraction >= config.prefetchThreshold && fillFraction < config.enterThreshold) {
|
|
15261
|
+
prefetch(n.ref);
|
|
14949
15262
|
}
|
|
15263
|
+
if (fillFraction >= config.enterThreshold) {
|
|
15264
|
+
const dx = centerX - viewportCenterX;
|
|
15265
|
+
const dy = centerY - viewportCenterY;
|
|
15266
|
+
const distSq = dx * dx + dy * dy;
|
|
15267
|
+
if (!bestCandidate || distSq < bestCandidate.distSq) {
|
|
15268
|
+
bestCandidate = { node: n, screen, distSq };
|
|
15269
|
+
}
|
|
15270
|
+
}
|
|
15271
|
+
}
|
|
15272
|
+
}
|
|
15273
|
+
if (bestCandidate) {
|
|
15274
|
+
const n = bestCandidate.node;
|
|
15275
|
+
const screen = bestCandidate.screen;
|
|
15276
|
+
const ref = n.ref;
|
|
15277
|
+
const childData = canvases?.[ref] ?? prefetchRef.current.get(ref)?.data;
|
|
15278
|
+
if (!childData) {
|
|
15279
|
+
prefetch(ref);
|
|
15280
|
+
} else {
|
|
14950
15281
|
const resolved = resolveCanvas(childData, theme);
|
|
14951
|
-
if (resolved.nodes.length
|
|
14952
|
-
|
|
14953
|
-
|
|
14954
|
-
|
|
14955
|
-
|
|
14956
|
-
|
|
14957
|
-
|
|
14958
|
-
|
|
14959
|
-
|
|
14960
|
-
|
|
15282
|
+
if (resolved.nodes.length > 0) {
|
|
15283
|
+
const bounds = computeBoundingBox(resolved.nodes);
|
|
15284
|
+
const targetRect = expandRect(screen, config.landingScale);
|
|
15285
|
+
const landingPad = Math.min(targetRect.width, targetRect.height) * config.landingPadding;
|
|
15286
|
+
let targetTransform = fitBoundsIntoRect(bounds, targetRect, landingPad);
|
|
15287
|
+
targetTransform = clampTransformToViewport(targetTransform, bounds, size, 16);
|
|
15288
|
+
committingRef.current = true;
|
|
15289
|
+
onEnter(n, targetTransform);
|
|
15290
|
+
return;
|
|
15291
|
+
}
|
|
14961
15292
|
}
|
|
14962
15293
|
}
|
|
14963
15294
|
if (parentFrame && nodes.length > 0) {
|
|
@@ -14971,6 +15302,12 @@ var SystemCanvas = (() => {
|
|
|
14971
15302
|
height: bounds.height
|
|
14972
15303
|
}, vp);
|
|
14973
15304
|
const fillFraction = Math.max(screen.width / size.width, screen.height / size.height);
|
|
15305
|
+
if (!exitArmedRef.current) {
|
|
15306
|
+
if (fillFraction > config.exitThreshold) {
|
|
15307
|
+
exitArmedRef.current = true;
|
|
15308
|
+
}
|
|
15309
|
+
return;
|
|
15310
|
+
}
|
|
14974
15311
|
if (fillFraction <= config.exitThreshold) {
|
|
14975
15312
|
const targetTransform = fitBoundsIntoRect({
|
|
14976
15313
|
minX: parentFrame.parentNodeRect.x,
|
|
@@ -14997,6 +15334,7 @@ var SystemCanvas = (() => {
|
|
|
14997
15334
|
theme,
|
|
14998
15335
|
config,
|
|
14999
15336
|
getViewportSize,
|
|
15337
|
+
getCursorScreenPos,
|
|
15000
15338
|
prefetch,
|
|
15001
15339
|
onEnter,
|
|
15002
15340
|
onExit
|
|
@@ -17872,17 +18210,67 @@ var SystemCanvas = (() => {
|
|
|
17872
18210
|
|
|
17873
18211
|
// ../react/dist/components/NodeIcon.js
|
|
17874
18212
|
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
|
17875
|
-
function NodeIcon({ icon, x, y, size = 14, color: color2, opacity = 0.7, customIcons }) {
|
|
18213
|
+
function NodeIcon({ icon, x, y, size = 14, color: color2, opacity = 0.7, customIcons, mode = "stroke", viewBox = 16 }) {
|
|
17876
18214
|
const pathData = customIcons?.[icon] ?? iconPaths[icon];
|
|
17877
18215
|
if (!pathData)
|
|
17878
18216
|
return null;
|
|
17879
|
-
|
|
18217
|
+
const defaultStrokeWidth = viewBox * 0.075;
|
|
18218
|
+
return (0, import_jsx_runtime.jsx)("g", { transform: `translate(${x}, ${y})`, pointerEvents: "none", opacity, children: pathData.map((entry, i) => {
|
|
18219
|
+
const spec = typeof entry === "string" ? { d: entry } : entry;
|
|
18220
|
+
const pathMode = spec.mode ?? mode;
|
|
18221
|
+
const rawStrokeWidth = spec.strokeWidth ?? defaultStrokeWidth;
|
|
18222
|
+
const renderedStrokeWidth = rawStrokeWidth * size / viewBox;
|
|
18223
|
+
return (0, import_jsx_runtime.jsx)("path", {
|
|
18224
|
+
d: scalePathData(spec.d, size, viewBox),
|
|
18225
|
+
fill: pathMode === "fill" ? color2 : "none",
|
|
18226
|
+
stroke: pathMode === "stroke" ? color2 : "none",
|
|
18227
|
+
strokeWidth: pathMode === "stroke" ? renderedStrokeWidth : 0,
|
|
18228
|
+
strokeLinecap: pathMode === "stroke" ? "round" : void 0,
|
|
18229
|
+
strokeLinejoin: pathMode === "stroke" ? "round" : void 0,
|
|
18230
|
+
// Brand silhouettes are typically authored as a single path
|
|
18231
|
+
// whose holes are expressed with subpath winding. `evenodd`
|
|
18232
|
+
// is the safe choice; nonzero would fill some holes solid.
|
|
18233
|
+
fillRule: pathMode === "fill" ? "evenodd" : void 0
|
|
18234
|
+
}, i);
|
|
18235
|
+
}) });
|
|
17880
18236
|
}
|
|
17881
|
-
function scalePathData(d, size) {
|
|
17882
|
-
const scale = size /
|
|
17883
|
-
|
|
17884
|
-
|
|
17885
|
-
|
|
18237
|
+
function scalePathData(d, size, source) {
|
|
18238
|
+
const scale = size / source;
|
|
18239
|
+
const out = [];
|
|
18240
|
+
const numberAtStart = /^-?(?:\d+\.?\d*|\.\d+)/;
|
|
18241
|
+
let isArc = false;
|
|
18242
|
+
let arcIndex = 0;
|
|
18243
|
+
let i = 0;
|
|
18244
|
+
while (i < d.length) {
|
|
18245
|
+
const ch = d[i];
|
|
18246
|
+
if (ch === " " || ch === "," || ch === " " || ch === "\n" || ch === "\r") {
|
|
18247
|
+
i++;
|
|
18248
|
+
continue;
|
|
18249
|
+
}
|
|
18250
|
+
if (/[a-zA-Z]/.test(ch)) {
|
|
18251
|
+
out.push(ch);
|
|
18252
|
+
isArc = ch === "a" || ch === "A";
|
|
18253
|
+
arcIndex = 0;
|
|
18254
|
+
i++;
|
|
18255
|
+
continue;
|
|
18256
|
+
}
|
|
18257
|
+
if (isArc && (arcIndex === 3 || arcIndex === 4)) {
|
|
18258
|
+
out.push(ch === "0" ? "0" : "1");
|
|
18259
|
+
arcIndex = (arcIndex + 1) % 7;
|
|
18260
|
+
i++;
|
|
18261
|
+
continue;
|
|
18262
|
+
}
|
|
18263
|
+
const m = numberAtStart.exec(d.substring(i));
|
|
18264
|
+
if (!m) {
|
|
18265
|
+
i++;
|
|
18266
|
+
continue;
|
|
18267
|
+
}
|
|
18268
|
+
out.push(String(parseFloat(m[0]) * scale));
|
|
18269
|
+
if (isArc)
|
|
18270
|
+
arcIndex = (arcIndex + 1) % 7;
|
|
18271
|
+
i += m[0].length;
|
|
18272
|
+
}
|
|
18273
|
+
return out.join(" ");
|
|
17886
18274
|
}
|
|
17887
18275
|
var iconPaths = {
|
|
17888
18276
|
// Database: cylinder shape
|
|
@@ -17975,11 +18363,12 @@ var SystemCanvas = (() => {
|
|
|
17975
18363
|
// ../react/dist/components/RefIndicator.js
|
|
17976
18364
|
var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
|
|
17977
18365
|
var import_react8 = __toESM(require_react(), 1);
|
|
17978
|
-
function RefIndicator({ node, theme, nodeX, nodeY, nodeWidth, nodeHeight, strokeColor, strokeWidth, corner = "bottom-right", size
|
|
18366
|
+
function RefIndicator({ node, theme, nodeX, nodeY, nodeWidth, nodeHeight, strokeColor, strokeWidth, corner = "bottom-right", size: sizeProp, onNavigate }) {
|
|
17979
18367
|
const [hover, setHover] = (0, import_react8.useState)(false);
|
|
17980
18368
|
const iconKind = theme.node.refIndicator.icon;
|
|
17981
18369
|
if (iconKind === "none")
|
|
17982
18370
|
return null;
|
|
18371
|
+
const size = sizeProp ?? theme.node.refIndicator.size ?? 18;
|
|
17983
18372
|
const stopAll = (e) => e.stopPropagation();
|
|
17984
18373
|
const right = nodeX + nodeWidth;
|
|
17985
18374
|
const bottom = nodeY + nodeHeight;
|
|
@@ -18025,19 +18414,22 @@ var SystemCanvas = (() => {
|
|
|
18025
18414
|
return (0, import_jsx_runtime2.jsxs)("g", { className: "system-canvas-ref-indicator", style: { cursor: "pointer" }, onClick: (e) => {
|
|
18026
18415
|
e.stopPropagation();
|
|
18027
18416
|
onNavigate(node, e);
|
|
18028
|
-
}, onDoubleClick: stopAll, onPointerDown: stopAll, onMouseDown: stopAll, onPointerEnter: () => setHover(true), onPointerLeave: () => setHover(false), children: [hover && (0, import_jsx_runtime2.jsx)("path", { d: hoverPath, fill: hoverFill, pointerEvents: "none" }), (0, import_jsx_runtime2.jsx)("path", { d: carvePath, fill: "none", stroke: strokeColor, strokeWidth: sw, strokeLinecap: "butt", strokeLinejoin: "round", pointerEvents: "none" }), (0, import_jsx_runtime2.jsx)("rect", { x: squareX, y: squareY, width: size, height: size, fill: "transparent" }), (0, import_jsx_runtime2.jsx)(Glyph, { kind: iconKind, cx, cy, color: hover ? hoverGlyph : restGlyph })] });
|
|
18417
|
+
}, onDoubleClick: stopAll, onPointerDown: stopAll, onMouseDown: stopAll, onPointerEnter: () => setHover(true), onPointerLeave: () => setHover(false), children: [hover && (0, import_jsx_runtime2.jsx)("path", { d: hoverPath, fill: hoverFill, pointerEvents: "none" }), (0, import_jsx_runtime2.jsx)("path", { d: carvePath, fill: "none", stroke: strokeColor, strokeWidth: sw, strokeLinecap: "butt", strokeLinejoin: "round", pointerEvents: "none" }), (0, import_jsx_runtime2.jsx)("rect", { x: squareX, y: squareY, width: size, height: size, fill: "transparent" }), (0, import_jsx_runtime2.jsx)(Glyph, { kind: iconKind, cx, cy, color: hover ? hoverGlyph : restGlyph, size })] });
|
|
18029
18418
|
}
|
|
18030
|
-
function Glyph({ kind, cx, cy, color: color2 }) {
|
|
18031
|
-
const s =
|
|
18419
|
+
function Glyph({ kind, cx, cy, color: color2, size }) {
|
|
18420
|
+
const s = size / 6;
|
|
18421
|
+
const sw = Math.max(1, size / 9);
|
|
18032
18422
|
switch (kind) {
|
|
18033
18423
|
case "chevron":
|
|
18034
|
-
return (0, import_jsx_runtime2.jsx)("path", { d: `M ${cx - s / 2} ${cy - s} L ${cx + s / 2} ${cy} L ${cx - s / 2} ${cy + s}`, fill: "none", stroke: color2, strokeWidth:
|
|
18424
|
+
return (0, import_jsx_runtime2.jsx)("path", { d: `M ${cx - s / 2} ${cy - s} L ${cx + s / 2} ${cy} L ${cx - s / 2} ${cy + s}`, fill: "none", stroke: color2, strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round", pointerEvents: "none" });
|
|
18035
18425
|
case "arrow": {
|
|
18036
18426
|
const h = s * 0.9;
|
|
18037
|
-
return (0, import_jsx_runtime2.jsx)("path", { d: `M ${cx - s} ${cy} L ${cx + s} ${cy} M ${cx + s - h} ${cy - h} L ${cx + s} ${cy} L ${cx + s - h} ${cy + h}`, fill: "none", stroke: color2, strokeWidth:
|
|
18427
|
+
return (0, import_jsx_runtime2.jsx)("path", { d: `M ${cx - s} ${cy} L ${cx + s} ${cy} M ${cx + s - h} ${cy - h} L ${cx + s} ${cy} L ${cx + s - h} ${cy + h}`, fill: "none", stroke: color2, strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round", pointerEvents: "none" });
|
|
18428
|
+
}
|
|
18429
|
+
case "expand": {
|
|
18430
|
+
const sw2 = Math.max(1, size / 12);
|
|
18431
|
+
return (0, import_jsx_runtime2.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime2.jsx)("path", { d: `M ${cx - s} ${cy - s} L ${cx + s} ${cy - s} L ${cx + s} ${cy + s} L ${cx - s} ${cy + s} Z`, fill: "none", stroke: color2, strokeWidth: sw2, strokeLinejoin: "round" }), (0, import_jsx_runtime2.jsx)("line", { x1: cx, y1: cy - s + 1, x2: cx, y2: cy + s - 1, stroke: color2, strokeWidth: sw2, strokeLinecap: "round" }), (0, import_jsx_runtime2.jsx)("line", { x1: cx - s + 1, y1: cy, x2: cx + s - 1, y2: cy, stroke: color2, strokeWidth: sw2, strokeLinecap: "round" })] });
|
|
18038
18432
|
}
|
|
18039
|
-
case "expand":
|
|
18040
|
-
return (0, import_jsx_runtime2.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime2.jsx)("path", { d: `M ${cx - s} ${cy - s} L ${cx + s} ${cy - s} L ${cx + s} ${cy + s} L ${cx - s} ${cy + s} Z`, fill: "none", stroke: color2, strokeWidth: 1.5, strokeLinejoin: "round" }), (0, import_jsx_runtime2.jsx)("line", { x1: cx, y1: cy - s + 1, x2: cx, y2: cy + s - 1, stroke: color2, strokeWidth: 1.5, strokeLinecap: "round" }), (0, import_jsx_runtime2.jsx)("line", { x1: cx - s + 1, y1: cy, x2: cx + s - 1, y2: cy, stroke: color2, strokeWidth: 1.5, strokeLinecap: "round" })] });
|
|
18041
18433
|
}
|
|
18042
18434
|
}
|
|
18043
18435
|
|
|
@@ -18164,7 +18556,7 @@ var SystemCanvas = (() => {
|
|
|
18164
18556
|
// ../react/dist/primitives/NodeText.js
|
|
18165
18557
|
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
18166
18558
|
var import_react9 = __toESM(require_react(), 1);
|
|
18167
|
-
function NodeText({ region, value, theme, color: color2, fill, align = "start", fontWeight = 500, uppercase = false, useLabelFont = false, fontFamily, fontSize: fontSizeProp, wrap = false, maxLines, lineHeight: lineHeightProp }) {
|
|
18559
|
+
function NodeText({ region, value, theme, color: color2, fill, align = "start", fontWeight = 500, uppercase = false, useLabelFont = false, fontFamily, fontSize: fontSizeProp, wrap = false, maxLines, lineHeight: lineHeightProp, verticalAlign = "top" }) {
|
|
18168
18560
|
const reactId = (0, import_react9.useId)();
|
|
18169
18561
|
const safeId = reactId.replace(/:/g, "");
|
|
18170
18562
|
if (!value)
|
|
@@ -18178,13 +18570,16 @@ var SystemCanvas = (() => {
|
|
|
18178
18570
|
const fillAttr = gradId ? `url(#${gradId})` : color2 ?? theme.node.sublabelColor;
|
|
18179
18571
|
const displayValue = uppercase ? value.toUpperCase() : value;
|
|
18180
18572
|
if (!wrap) {
|
|
18573
|
+
const rendered = truncateToWidth(displayValue, region.width, fontSize);
|
|
18181
18574
|
const y = region.y + region.height / 2 + fontSize * 0.36;
|
|
18182
|
-
return (0, import_jsx_runtime7.jsxs)("g", { pointerEvents: "none", children: [fill && (0, import_jsx_runtime7.jsx)(GradientDef, { id: gradId, fill }), (0, import_jsx_runtime7.jsx)("text", { x, y, fill: fillAttr, fontSize, fontWeight, fontFamily: font, textAnchor: anchor, letterSpacing: uppercase ? 0.8 : 0.2, pointerEvents: "none", children:
|
|
18575
|
+
return (0, import_jsx_runtime7.jsxs)("g", { pointerEvents: "none", children: [fill && (0, import_jsx_runtime7.jsx)(GradientDef, { id: gradId, fill }), (0, import_jsx_runtime7.jsx)("text", { x, y, fill: fillAttr, fontSize, fontWeight, fontFamily: font, textAnchor: anchor, letterSpacing: uppercase ? 0.8 : 0.2, pointerEvents: "none", children: rendered })] });
|
|
18183
18576
|
}
|
|
18184
18577
|
const lines = wrapTextWithBreaks(displayValue, region.width, fontSize, maxLines);
|
|
18185
18578
|
if (lines.length === 0)
|
|
18186
18579
|
return null;
|
|
18187
|
-
const
|
|
18580
|
+
const blockHeight = fontSize + (lines.length - 1) * lineHeight;
|
|
18581
|
+
const topY = region.y + fontSize;
|
|
18582
|
+
const baseY = verticalAlign === "center" ? region.y + (region.height - blockHeight) / 2 + fontSize : verticalAlign === "bottom" ? region.y + region.height - blockHeight + fontSize : topY;
|
|
18188
18583
|
const clipId = `sc-text-clip-${safeId}`;
|
|
18189
18584
|
return (0, import_jsx_runtime7.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime7.jsxs)("defs", { children: [fill && (0, import_jsx_runtime7.jsx)(GradientDef, { id: gradId, fill }), (0, import_jsx_runtime7.jsx)("clipPath", { id: clipId, children: (0, import_jsx_runtime7.jsx)("rect", { x: region.x, y: region.y, width: region.width, height: region.height }) })] }), (0, import_jsx_runtime7.jsx)("g", { clipPath: `url(#${clipId})`, pointerEvents: "none", children: (0, import_jsx_runtime7.jsx)("text", { x, y: baseY, fill: fillAttr, fontSize, fontWeight, fontFamily: font, textAnchor: anchor, letterSpacing: uppercase ? 0.8 : 0.2, pointerEvents: "none", children: lines.map((line, i) => (0, import_jsx_runtime7.jsx)("tspan", { x, dy: i === 0 ? 0 : lineHeight, children: line || " " }, i)) }) })] });
|
|
18190
18585
|
}
|
|
@@ -18336,6 +18731,20 @@ var SystemCanvas = (() => {
|
|
|
18336
18731
|
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18337
18732
|
return (0, import_jsx_runtime9.jsx)(NodeDot, { region, color: color2 });
|
|
18338
18733
|
}
|
|
18734
|
+
case "icon": {
|
|
18735
|
+
const name = resolveAccessor(spec.name, ctx);
|
|
18736
|
+
if (!name)
|
|
18737
|
+
return null;
|
|
18738
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18739
|
+
const opacity = resolveAccessorOr(spec.opacity, 1, ctx);
|
|
18740
|
+
const mode = resolveAccessorOr(spec.mode, "stroke", ctx);
|
|
18741
|
+
const viewBox = resolveAccessorOr(spec.viewBox, 16, ctx);
|
|
18742
|
+
const auto = Math.max(8, Math.min(region.width, region.height) - 2);
|
|
18743
|
+
const size = resolveAccessorOr(spec.size, auto, ctx);
|
|
18744
|
+
const x = region.x + (region.width - size) / 2;
|
|
18745
|
+
const y = region.y + (region.height - size) / 2;
|
|
18746
|
+
return (0, import_jsx_runtime9.jsx)(NodeIcon, { icon: name, x, y, size, color: color2, opacity, customIcons: theme.icons, mode, viewBox });
|
|
18747
|
+
}
|
|
18339
18748
|
case "custom": {
|
|
18340
18749
|
return spec.render(ctx);
|
|
18341
18750
|
}
|
|
@@ -18363,20 +18772,21 @@ var SystemCanvas = (() => {
|
|
|
18363
18772
|
const contentY = y + reservedTop;
|
|
18364
18773
|
const contentWidth = Math.max(0, width - reservedLeft - reservedRight);
|
|
18365
18774
|
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
18366
|
-
const
|
|
18367
|
-
const
|
|
18368
|
-
const
|
|
18369
|
-
const sublabel = lines[1];
|
|
18775
|
+
const LABEL_PAD_X = 10;
|
|
18776
|
+
const LABEL_PAD_Y = 6;
|
|
18777
|
+
const text = node.text ?? node.id;
|
|
18370
18778
|
const hasBodySlot = slots?.body !== void 0;
|
|
18371
18779
|
const hasHeader = reservedTop > 0;
|
|
18372
|
-
const
|
|
18780
|
+
const hasInlineLeftMarker = slots?.topLeft !== void 0 && (slots.topLeft.kind === "dot" || slots.topLeft.kind === "icon") && !hasHeader;
|
|
18781
|
+
const isLeftAligned = hasHeader || hasInlineLeftMarker;
|
|
18373
18782
|
const labelFontSize = theme.node.fontSize + (hasHeader ? 1 : 0);
|
|
18374
|
-
const
|
|
18375
|
-
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
|
|
18379
|
-
|
|
18783
|
+
const labelAlign = isLeftAligned ? "start" : "center";
|
|
18784
|
+
return (0, import_jsx_runtime10.jsxs)("g", { className: "system-canvas-node system-canvas-node--text", style: { cursor: onPointerDown ? "move" : node.isNavigable ? "pointer" : "default" }, onClick: (e) => onClick(node, e), onDoubleClick: (e) => onDoubleClick(node, e), onContextMenu: (e) => onContextMenu(node, e), onPointerDown: onPointerDown ? (e) => onPointerDown(node, e) : void 0, children: [(0, import_jsx_runtime10.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: theme.background }), (0, import_jsx_runtime10.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: node.resolvedFill, stroke: node.resolvedStroke, strokeWidth: theme.node.strokeWidth }), !isEditing && !hasBodySlot && (0, import_jsx_runtime10.jsx)(NodeText, { region: {
|
|
18785
|
+
x: contentX + LABEL_PAD_X,
|
|
18786
|
+
y: contentY + LABEL_PAD_Y,
|
|
18787
|
+
width: Math.max(0, contentWidth - LABEL_PAD_X * 2),
|
|
18788
|
+
height: Math.max(0, contentHeight - LABEL_PAD_Y * 2)
|
|
18789
|
+
}, value: text, theme, color: theme.node.labelColor, align: labelAlign, fontWeight: 600, fontSize: labelFontSize, useLabelFont: true, wrap: true, verticalAlign: hasHeader ? "top" : "center" }), node.resolvedIcon && (0, import_jsx_runtime10.jsx)(NodeIcon, { icon: node.resolvedIcon, x: x + 8 + reservedLeft, y: contentY + contentHeight / 2 - 7, size: 14, color: node.resolvedStroke, opacity: 0.7, customIcons: theme.icons }), slots && (0, import_jsx_runtime10.jsx)(CategorySlotsLayer, { node, theme, canvases, slots }), node.isNavigable && (0, import_jsx_runtime10.jsx)(RefIndicator, { node, theme, nodeX: x, nodeY: y, nodeWidth: width, nodeHeight: height, strokeColor: node.resolvedStroke, strokeWidth: theme.node.strokeWidth, corner: toKebabCorner(refCorner), onNavigate })] });
|
|
18380
18790
|
}
|
|
18381
18791
|
|
|
18382
18792
|
// ../react/dist/components/FileNode.js
|
|
@@ -18390,6 +18800,7 @@ var SystemCanvas = (() => {
|
|
|
18390
18800
|
const fold = 10;
|
|
18391
18801
|
const textPadding = 10 + reservedLeft;
|
|
18392
18802
|
const maxTextWidth = width - textPadding - reservedRight - fold;
|
|
18803
|
+
const LABEL_PAD_Y = 6;
|
|
18393
18804
|
const contentY = y + reservedTop;
|
|
18394
18805
|
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
18395
18806
|
const shapePath = [
|
|
@@ -18408,7 +18819,12 @@ var SystemCanvas = (() => {
|
|
|
18408
18819
|
const strokeColor = node.resolvedStroke;
|
|
18409
18820
|
const thinStroke = 0.75;
|
|
18410
18821
|
const clipId = `file-clip-${node.id}`;
|
|
18411
|
-
return (0, import_jsx_runtime11.jsxs)("g", { className: "system-canvas-node system-canvas-node--file", style: { cursor: onPointerDown ? "move" : node.isNavigable ? "pointer" : "default" }, onClick: (e) => onClick(node, e), onDoubleClick: (e) => onDoubleClick(node, e), onContextMenu: (e) => onContextMenu(node, e), onPointerDown: onPointerDown ? (e) => onPointerDown(node, e) : void 0, children: [(0, import_jsx_runtime11.jsx)("defs", { children: (0, import_jsx_runtime11.jsx)("clipPath", { id: clipId, children: (0, import_jsx_runtime11.jsx)("rect", { x: x + textPadding, y: contentY, width: maxTextWidth, height: contentHeight }) }) }), (0, import_jsx_runtime11.jsx)("path", { d: shapePath, fill: theme.background }), (0, import_jsx_runtime11.jsx)("path", { d: shapePath, fill: node.resolvedFill, stroke: strokeColor, strokeWidth: thinStroke }), (0, import_jsx_runtime11.jsx)("path", { d: foldPath, fill: "none", stroke: strokeColor, strokeWidth: thinStroke, opacity: 0.5 }), !isEditing && !slots?.body && (0, import_jsx_runtime11.jsxs)("g", { clipPath: `url(#${clipId})`, children: [dirPath && (0, import_jsx_runtime11.jsxs)("text", { x: x + textPadding, y: contentY + 14, fill: theme.node.sublabelColor, fontSize: theme.node.sublabelFontSize - 1, fontFamily: theme.node.fontFamily, pointerEvents: "none", opacity: 0.6, children: [dirPath, "/"] }), (0, import_jsx_runtime11.jsx)(
|
|
18822
|
+
return (0, import_jsx_runtime11.jsxs)("g", { className: "system-canvas-node system-canvas-node--file", style: { cursor: onPointerDown ? "move" : node.isNavigable ? "pointer" : "default" }, onClick: (e) => onClick(node, e), onDoubleClick: (e) => onDoubleClick(node, e), onContextMenu: (e) => onContextMenu(node, e), onPointerDown: onPointerDown ? (e) => onPointerDown(node, e) : void 0, children: [(0, import_jsx_runtime11.jsx)("defs", { children: (0, import_jsx_runtime11.jsx)("clipPath", { id: clipId, children: (0, import_jsx_runtime11.jsx)("rect", { x: x + textPadding, y: contentY, width: maxTextWidth, height: contentHeight }) }) }), (0, import_jsx_runtime11.jsx)("path", { d: shapePath, fill: theme.background }), (0, import_jsx_runtime11.jsx)("path", { d: shapePath, fill: node.resolvedFill, stroke: strokeColor, strokeWidth: thinStroke }), (0, import_jsx_runtime11.jsx)("path", { d: foldPath, fill: "none", stroke: strokeColor, strokeWidth: thinStroke, opacity: 0.5 }), !isEditing && !slots?.body && (0, import_jsx_runtime11.jsxs)("g", { clipPath: `url(#${clipId})`, children: [dirPath && (0, import_jsx_runtime11.jsxs)("text", { x: x + textPadding, y: contentY + 14, fill: theme.node.sublabelColor, fontSize: theme.node.sublabelFontSize - 1, fontFamily: theme.node.fontFamily, pointerEvents: "none", opacity: 0.6, children: [dirPath, "/"] }), (0, import_jsx_runtime11.jsx)(NodeText, { region: {
|
|
18823
|
+
x: x + textPadding,
|
|
18824
|
+
y: dirPath ? contentY + 18 : contentY + (subpath ? 8 : LABEL_PAD_Y),
|
|
18825
|
+
width: maxTextWidth,
|
|
18826
|
+
height: dirPath ? Math.max(0, contentHeight - 18 - (subpath ? 16 : 0)) : Math.max(0, contentHeight - (subpath ? 16 : 0) - LABEL_PAD_Y * 2)
|
|
18827
|
+
}, value: fileName, theme, color: theme.node.labelColor, align: "start", fontWeight: 500, fontSize: theme.node.fontSize - 1, wrap: true, verticalAlign: dirPath ? "top" : "center" }), subpath && (0, import_jsx_runtime11.jsx)("text", { x: x + textPadding, y: contentY + (dirPath ? 40 : contentHeight / 2 + theme.node.fontSize + 2), fill: theme.node.sublabelColor, fontSize: theme.node.sublabelFontSize, fontFamily: theme.node.fontFamily, pointerEvents: "none", children: subpath })] }), slots && (0, import_jsx_runtime11.jsx)(CategorySlotsLayer, { node, theme, canvases, slots }), node.isNavigable && (0, import_jsx_runtime11.jsx)(RefIndicator, { node, theme, nodeX: x, nodeY: y, nodeWidth: width, nodeHeight: height, strokeColor, strokeWidth: thinStroke, corner: toKebabCorner(refCorner), onNavigate })] });
|
|
18412
18828
|
}
|
|
18413
18829
|
|
|
18414
18830
|
// ../react/dist/components/LinkNode.js
|
|
@@ -18419,14 +18835,21 @@ var SystemCanvas = (() => {
|
|
|
18419
18835
|
const contentY = y + reservedTop;
|
|
18420
18836
|
const contentWidth = Math.max(0, width - reservedLeft - reservedRight);
|
|
18421
18837
|
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
18422
|
-
const
|
|
18838
|
+
const glyphReserve = 20;
|
|
18839
|
+
const LABEL_PAD_X = 10;
|
|
18840
|
+
const LABEL_PAD_Y = 6;
|
|
18423
18841
|
let displayUrl = node.url ?? "";
|
|
18424
18842
|
try {
|
|
18425
18843
|
const url = new URL(displayUrl);
|
|
18426
18844
|
displayUrl = url.hostname;
|
|
18427
18845
|
} catch {
|
|
18428
18846
|
}
|
|
18429
|
-
return (0, import_jsx_runtime12.jsxs)("g", { className: "system-canvas-node system-canvas-node--link", style: { cursor: onPointerDown ? "move" : "pointer" }, onClick: (e) => onClick(node, e), onDoubleClick: (e) => onDoubleClick(node, e), onContextMenu: (e) => onContextMenu(node, e), onPointerDown: onPointerDown ? (e) => onPointerDown(node, e) : void 0, children: [(0, import_jsx_runtime12.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: theme.background }), (0, import_jsx_runtime12.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: node.resolvedFill, stroke: node.resolvedStroke, strokeWidth: theme.node.strokeWidth }), !isEditing && !slots?.body && (0, import_jsx_runtime12.jsx)("text", { x: contentX + 12, y: contentY + contentHeight / 2 + 4, fill: node.resolvedStroke, fontSize: 12, fontFamily: theme.node.fontFamily, pointerEvents: "none", opacity: 0.6, children: "\u29C9" }), !isEditing && !slots?.body && (0, import_jsx_runtime12.jsx)(
|
|
18847
|
+
return (0, import_jsx_runtime12.jsxs)("g", { className: "system-canvas-node system-canvas-node--link", style: { cursor: onPointerDown ? "move" : "pointer" }, onClick: (e) => onClick(node, e), onDoubleClick: (e) => onDoubleClick(node, e), onContextMenu: (e) => onContextMenu(node, e), onPointerDown: onPointerDown ? (e) => onPointerDown(node, e) : void 0, children: [(0, import_jsx_runtime12.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: theme.background }), (0, import_jsx_runtime12.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: node.resolvedFill, stroke: node.resolvedStroke, strokeWidth: theme.node.strokeWidth }), !isEditing && !slots?.body && (0, import_jsx_runtime12.jsx)("text", { x: contentX + 12, y: contentY + contentHeight / 2 + 4, fill: node.resolvedStroke, fontSize: 12, fontFamily: theme.node.fontFamily, pointerEvents: "none", opacity: 0.6, children: "\u29C9" }), !isEditing && !slots?.body && (0, import_jsx_runtime12.jsx)(NodeText, { region: {
|
|
18848
|
+
x: contentX + glyphReserve,
|
|
18849
|
+
y: contentY + LABEL_PAD_Y,
|
|
18850
|
+
width: Math.max(0, contentWidth - glyphReserve - LABEL_PAD_X),
|
|
18851
|
+
height: Math.max(0, contentHeight - LABEL_PAD_Y * 2)
|
|
18852
|
+
}, value: displayUrl, theme, color: theme.node.labelColor, align: "center", fontWeight: 600, fontSize: theme.node.fontSize, wrap: true, verticalAlign: "center" }), slots && (0, import_jsx_runtime12.jsx)(CategorySlotsLayer, { node, theme, canvases, slots }), node.isNavigable && (0, import_jsx_runtime12.jsx)(RefIndicator, { node, theme, nodeX: x, nodeY: y, nodeWidth: width, nodeHeight: height, strokeColor: node.resolvedStroke, strokeWidth: theme.node.strokeWidth, corner: toKebabCorner(refCorner), onNavigate })] });
|
|
18430
18853
|
}
|
|
18431
18854
|
|
|
18432
18855
|
// ../react/dist/components/GroupNode.js
|
|
@@ -18552,7 +18975,8 @@ var SystemCanvas = (() => {
|
|
|
18552
18975
|
const isEditing = editingId === edge.id;
|
|
18553
18976
|
const baseColor = edge.color ? resolveColor(edge.color, theme).stroke : theme.edge.stroke;
|
|
18554
18977
|
const edgeColor = isSelected ? theme.node.labelColor : baseColor;
|
|
18555
|
-
const
|
|
18978
|
+
const baseStrokeWidth = edge.strokeWidth ?? theme.edge.strokeWidth;
|
|
18979
|
+
const strokeWidth = isSelected ? baseStrokeWidth * 1.75 : baseStrokeWidth;
|
|
18556
18980
|
const toEnd = edge.toEnd ?? "arrow";
|
|
18557
18981
|
const fromEnd = edge.fromEnd ?? "none";
|
|
18558
18982
|
const arrowId = "system-canvas-arrowhead";
|
|
@@ -18615,6 +19039,10 @@ var SystemCanvas = (() => {
|
|
|
18615
19039
|
const fontFamily = theme.node.fontFamily;
|
|
18616
19040
|
const fontSize = theme.node.fontSize;
|
|
18617
19041
|
const padding = 8;
|
|
19042
|
+
const slots = getCategorySlots(node, theme);
|
|
19043
|
+
const reservations = computeReflowReservations(node, theme, slots);
|
|
19044
|
+
const hasHeader = reservations.top > 0;
|
|
19045
|
+
const textAlign = node.type === "text" && !hasHeader ? "center" : "left";
|
|
18618
19046
|
const commonFieldStyle = {
|
|
18619
19047
|
width: "100%",
|
|
18620
19048
|
height: "100%",
|
|
@@ -18628,7 +19056,7 @@ var SystemCanvas = (() => {
|
|
|
18628
19056
|
borderRadius: node.resolvedCornerRadius,
|
|
18629
19057
|
outline: "none",
|
|
18630
19058
|
resize: "none",
|
|
18631
|
-
textAlign
|
|
19059
|
+
textAlign
|
|
18632
19060
|
};
|
|
18633
19061
|
return (0, import_jsx_runtime17.jsx)("foreignObject", { x: node.x, y: node.y, width: node.width, height: node.height, onPointerDown: stopPointer, onMouseDown: stopPointer, onClick: stopPointer, onDoubleClick: stopPointer, children: node.type === "text" ? (0, import_jsx_runtime17.jsx)("textarea", { ref: textareaRef, value, onChange: (e) => setValue(e.target.value), onBlur: commit, onKeyDown: (e) => {
|
|
18634
19062
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
@@ -18998,7 +19426,7 @@ var SystemCanvas = (() => {
|
|
|
18998
19426
|
// ../react/dist/components/Viewport.js
|
|
18999
19427
|
var HOVER_PADDING = 10;
|
|
19000
19428
|
var EDGE_PROXIMITY = 16;
|
|
19001
|
-
var Viewport = (0, import_react15.forwardRef)(function Viewport2({ nodes, edges, nodeMap, theme, edgeStyle, columns, rows, canvases, minZoom, maxZoom, defaultViewport, onViewportChange, onNodeClick, onNodeDoubleClick, onNodeNavigate, onEdgeClick, onEdgeDoubleClick, onCanvasClick, onCanvasContextMenu, onNodeContextMenu, onEdgeContextMenu, onNodePointerDown, selectedId, editingId, selectedEdgeId, editingEdgeId, dragOverrides, resizeOverrides, onResizeHandlePointerDown, onEditorCommit, onEditorCancel, onEdgeEditorCommit, onEdgeEditorCancel, pendingEdge, onConnectionHandlePointerDown, edgeCreateEnabled, autoFit = "canvas-change", canvasRef, handoffTransform, onHandoffApplied, handoffFadeMs = 0 }, ref) {
|
|
19429
|
+
var Viewport = (0, import_react15.forwardRef)(function Viewport2({ nodes, edges, nodeMap, theme, edgeStyle, columns, rows, canvases, minZoom, maxZoom, defaultViewport, onViewportChange, onNodeClick, onNodeDoubleClick, onNodeNavigate, onEdgeClick, onEdgeDoubleClick, onCanvasClick, onCanvasContextMenu, onNodeContextMenu, onEdgeContextMenu, onNodePointerDown, selectedId, editingId, selectedEdgeId, editingEdgeId, dragOverrides, dropTargetId, resizeOverrides, onResizeHandlePointerDown, onEditorCommit, onEditorCancel, onEdgeEditorCommit, onEdgeEditorCancel, pendingEdge, onConnectionHandlePointerDown, edgeCreateEnabled, autoFit = "canvas-change", canvasRef, handoffTransform, onHandoffApplied, handoffFadeMs = 0 }, ref) {
|
|
19002
19430
|
const { svgRef, groupRef, viewport, fitToContent, zoomToNode, setTransform } = useViewport({
|
|
19003
19431
|
minZoom,
|
|
19004
19432
|
maxZoom,
|
|
@@ -19041,6 +19469,7 @@ var SystemCanvas = (() => {
|
|
|
19041
19469
|
}, []);
|
|
19042
19470
|
const [hoveredNodeId, setHoveredNodeId] = (0, import_react15.useState)(null);
|
|
19043
19471
|
const [hoveredSide, setHoveredSide] = (0, import_react15.useState)(null);
|
|
19472
|
+
const cursorPosRef = (0, import_react15.useRef)(null);
|
|
19044
19473
|
(0, import_react15.useImperativeHandle)(ref, () => ({
|
|
19045
19474
|
zoomToNode: (node, onComplete, options) => {
|
|
19046
19475
|
navigatingRef.current = true;
|
|
@@ -19049,7 +19478,8 @@ var SystemCanvas = (() => {
|
|
|
19049
19478
|
fitToContent,
|
|
19050
19479
|
setTransform,
|
|
19051
19480
|
getSvgElement: () => svgRef.current,
|
|
19052
|
-
getViewport: () => viewport.current ?? { x: 0, y: 0, zoom: 1 }
|
|
19481
|
+
getViewport: () => viewport.current ?? { x: 0, y: 0, zoom: 1 },
|
|
19482
|
+
getCursorScreenPos: () => cursorPosRef.current
|
|
19053
19483
|
}));
|
|
19054
19484
|
const renderNodes = (0, import_react15.useMemo)(() => {
|
|
19055
19485
|
const hasDrag = dragOverrides && dragOverrides.size > 0;
|
|
@@ -19132,14 +19562,17 @@ var SystemCanvas = (() => {
|
|
|
19132
19562
|
]);
|
|
19133
19563
|
const editingNode = editingId ? renderNodes.find((n) => n.id === editingId) ?? null : null;
|
|
19134
19564
|
const handleSvgPointerMove = (0, import_react15.useCallback)((event) => {
|
|
19135
|
-
if (!edgeCreateEnabled)
|
|
19136
|
-
return;
|
|
19137
19565
|
const svg = svgRef.current;
|
|
19138
19566
|
if (!svg)
|
|
19139
19567
|
return;
|
|
19140
19568
|
const rect = svg.getBoundingClientRect();
|
|
19569
|
+
const cursorScreenX = event.clientX - rect.left;
|
|
19570
|
+
const cursorScreenY = event.clientY - rect.top;
|
|
19571
|
+
cursorPosRef.current = { x: cursorScreenX, y: cursorScreenY };
|
|
19572
|
+
if (!edgeCreateEnabled)
|
|
19573
|
+
return;
|
|
19141
19574
|
const vp = viewport.current ?? { x: 0, y: 0, zoom: 1 };
|
|
19142
|
-
const { x, y } = screenToCanvas(
|
|
19575
|
+
const { x, y } = screenToCanvas(cursorScreenX, cursorScreenY, vp);
|
|
19143
19576
|
const pad = HOVER_PADDING;
|
|
19144
19577
|
let hit = null;
|
|
19145
19578
|
for (let i = renderNodes.length - 1; i >= 0; i--) {
|
|
@@ -19183,11 +19616,13 @@ var SystemCanvas = (() => {
|
|
|
19183
19616
|
const handleSvgPointerLeave = (0, import_react15.useCallback)(() => {
|
|
19184
19617
|
setHoveredNodeId(null);
|
|
19185
19618
|
setHoveredSide(null);
|
|
19619
|
+
cursorPosRef.current = null;
|
|
19186
19620
|
}, []);
|
|
19187
19621
|
const handlesNodeId = pendingEdge?.sourceId ?? hoveredNodeId;
|
|
19188
19622
|
const handlesNode = edgeCreateEnabled && handlesNodeId ? renderNodeMap.get(handlesNodeId) ?? null : null;
|
|
19189
19623
|
const pendingSourceNode = pendingEdge ? renderNodeMap.get(pendingEdge.sourceId) ?? null : null;
|
|
19190
19624
|
const pendingTargetNode = pendingEdge?.hoveredTargetId && pendingEdge.hoveredTargetId !== pendingEdge.sourceId ? renderNodeMap.get(pendingEdge.hoveredTargetId) ?? null : null;
|
|
19625
|
+
const dropTargetNode = dropTargetId ? renderNodeMap.get(dropTargetId) ?? null : null;
|
|
19191
19626
|
const editingEdge = editingEdgeId ? edges.find((e) => e.id === editingEdgeId) ?? null : null;
|
|
19192
19627
|
const editingEdgeMidpoint = (() => {
|
|
19193
19628
|
if (!editingEdge)
|
|
@@ -19207,7 +19642,7 @@ var SystemCanvas = (() => {
|
|
|
19207
19642
|
WebkitUserSelect: "none",
|
|
19208
19643
|
MozUserSelect: "none",
|
|
19209
19644
|
msUserSelect: "none"
|
|
19210
|
-
}, onClick: onCanvasClick, onContextMenu: onCanvasContextMenu, onPointerMove: handleSvgPointerMove, onPointerLeave: handleSvgPointerLeave, children: [(0, import_jsx_runtime22.jsx)("defs", { children: (0, import_jsx_runtime22.jsx)("pattern", { id: "system-canvas-grid", width: theme.grid.size, height: theme.grid.size, patternUnits: "userSpaceOnUse", children: (0, import_jsx_runtime22.jsx)("path", { d: `M ${theme.grid.size} 0 L 0 0 0 ${theme.grid.size}`, fill: "none", stroke: theme.grid.color, strokeWidth: theme.grid.strokeWidth }) }) }), (0, import_jsx_runtime22.jsx)("rect", { x: "-50000", y: "-50000", width: "100000", height: "100000", fill: "url(#system-canvas-grid)" }), (0, import_jsx_runtime22.jsxs)("g", { ref: groupRef, children: [(0, import_jsx_runtime22.jsx)(LanesBackground, { columns, rows, theme }), (0, import_jsx_runtime22.jsx)(NodeRenderer, { nodes: renderNodes, theme, onClick: onNodeClick, onDoubleClick: onNodeDoubleClick, onContextMenu: onNodeContextMenu, onNavigate: onNodeNavigate, onPointerDown: onNodePointerDown, selectedId, editingId, canvases, only: "groups" }), (0, import_jsx_runtime22.jsx)(EdgeRenderer, { edges, nodeMap: renderNodeMap, theme, defaultEdgeStyle: edgeStyle, onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, selectedId: selectedEdgeId, editingId: editingEdgeId }), (0, import_jsx_runtime22.jsx)(NodeRenderer, { nodes: renderNodes, theme, onClick: onNodeClick, onDoubleClick: onNodeDoubleClick, onContextMenu: onNodeContextMenu, onNavigate: onNodeNavigate, onPointerDown: onNodePointerDown, selectedId, editingId, onResizeHandlePointerDown, canvases, only: "non-groups" }), pendingTargetNode && (0, import_jsx_runtime22.jsx)("rect", { className: "system-canvas-drop-target", x: pendingTargetNode.x - 4, y: pendingTargetNode.y - 4, width: pendingTargetNode.width + 8, height: pendingTargetNode.height + 8, rx: pendingTargetNode.resolvedCornerRadius + 4, fill: "none", stroke: theme.node.labelColor, strokeWidth: 2, opacity: 0.85, pointerEvents: "none" }), pendingEdge && pendingSourceNode && (0, import_jsx_runtime22.jsx)(PendingEdgeRenderer, { sourceNode: pendingSourceNode, sourceSide: pendingEdge.sourceSide, cursor: pendingEdge.cursor, targetNode: pendingTargetNode, theme, defaultEdgeStyle: edgeStyle }), handlesNode && onConnectionHandlePointerDown && (0, import_jsx_runtime22.jsx)(ConnectionHandles, { node: handlesNode, theme, onHandlePointerDown: onConnectionHandlePointerDown, immediate: !!pendingEdge, activeSide: hoveredSide }), editingNode && onEditorCommit && onEditorCancel && (0, import_jsx_runtime22.jsx)(NodeEditor, { node: editingNode, theme, onCommit: onEditorCommit, onCancel: onEditorCancel }), editingEdge && editingEdgeMidpoint && onEdgeEditorCommit && onEdgeEditorCancel && (0, import_jsx_runtime22.jsx)(EdgeLabelEditor, { initialLabel: editingEdge.label ?? "", midpoint: editingEdgeMidpoint, theme, onCommit: onEdgeEditorCommit, onCancel: onEdgeEditorCancel })] })] });
|
|
19645
|
+
}, onClick: onCanvasClick, onContextMenu: onCanvasContextMenu, onPointerMove: handleSvgPointerMove, onPointerLeave: handleSvgPointerLeave, children: [(0, import_jsx_runtime22.jsx)("defs", { children: (0, import_jsx_runtime22.jsx)("pattern", { id: "system-canvas-grid", width: theme.grid.size, height: theme.grid.size, patternUnits: "userSpaceOnUse", children: (0, import_jsx_runtime22.jsx)("path", { d: `M ${theme.grid.size} 0 L 0 0 0 ${theme.grid.size}`, fill: "none", stroke: theme.grid.color, strokeWidth: theme.grid.strokeWidth }) }) }), (0, import_jsx_runtime22.jsx)("rect", { x: "-50000", y: "-50000", width: "100000", height: "100000", fill: "url(#system-canvas-grid)" }), (0, import_jsx_runtime22.jsxs)("g", { ref: groupRef, children: [(0, import_jsx_runtime22.jsx)(LanesBackground, { columns, rows, theme }), (0, import_jsx_runtime22.jsx)(NodeRenderer, { nodes: renderNodes, theme, onClick: onNodeClick, onDoubleClick: onNodeDoubleClick, onContextMenu: onNodeContextMenu, onNavigate: onNodeNavigate, onPointerDown: onNodePointerDown, selectedId, editingId, canvases, only: "groups" }), (0, import_jsx_runtime22.jsx)(EdgeRenderer, { edges, nodeMap: renderNodeMap, theme, defaultEdgeStyle: edgeStyle, onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, selectedId: selectedEdgeId, editingId: editingEdgeId }), (0, import_jsx_runtime22.jsx)(NodeRenderer, { nodes: renderNodes, theme, onClick: onNodeClick, onDoubleClick: onNodeDoubleClick, onContextMenu: onNodeContextMenu, onNavigate: onNodeNavigate, onPointerDown: onNodePointerDown, selectedId, editingId, onResizeHandlePointerDown, canvases, only: "non-groups" }), pendingTargetNode && (0, import_jsx_runtime22.jsx)("rect", { className: "system-canvas-drop-target", x: pendingTargetNode.x - 4, y: pendingTargetNode.y - 4, width: pendingTargetNode.width + 8, height: pendingTargetNode.height + 8, rx: pendingTargetNode.resolvedCornerRadius + 4, fill: "none", stroke: theme.node.labelColor, strokeWidth: 2, opacity: 0.85, pointerEvents: "none" }), dropTargetNode && (0, import_jsx_runtime22.jsx)("rect", { className: "system-canvas-drop-target system-canvas-node-drop-target", x: dropTargetNode.x - 4, y: dropTargetNode.y - 4, width: dropTargetNode.width + 8, height: dropTargetNode.height + 8, rx: dropTargetNode.resolvedCornerRadius + 4, fill: "none", stroke: theme.node.labelColor, strokeWidth: 2, strokeDasharray: "6 4", opacity: 0.9, pointerEvents: "none" }), pendingEdge && pendingSourceNode && (0, import_jsx_runtime22.jsx)(PendingEdgeRenderer, { sourceNode: pendingSourceNode, sourceSide: pendingEdge.sourceSide, cursor: pendingEdge.cursor, targetNode: pendingTargetNode, theme, defaultEdgeStyle: edgeStyle }), handlesNode && onConnectionHandlePointerDown && (0, import_jsx_runtime22.jsx)(ConnectionHandles, { node: handlesNode, theme, onHandlePointerDown: onConnectionHandlePointerDown, immediate: !!pendingEdge, activeSide: hoveredSide }), editingNode && onEditorCommit && onEditorCancel && (0, import_jsx_runtime22.jsx)(NodeEditor, { node: editingNode, theme, onCommit: onEditorCommit, onCancel: onEditorCancel }), editingEdge && editingEdgeMidpoint && onEdgeEditorCommit && onEdgeEditorCancel && (0, import_jsx_runtime22.jsx)(EdgeLabelEditor, { initialLabel: editingEdge.label ?? "", midpoint: editingEdgeMidpoint, theme, onCommit: onEdgeEditorCommit, onCancel: onEdgeEditorCancel })] })] });
|
|
19211
19646
|
});
|
|
19212
19647
|
|
|
19213
19648
|
// ../react/dist/components/Breadcrumbs.js
|
|
@@ -19436,7 +19871,7 @@ var SystemCanvas = (() => {
|
|
|
19436
19871
|
const cx = visibleLeft + visibleW / 2;
|
|
19437
19872
|
if (endScreen <= colsOffsetLeft || startScreen >= width)
|
|
19438
19873
|
return null;
|
|
19439
|
-
return (0, import_jsx_runtime25.jsxs)("g", { children: [(0, import_jsx_runtime25.jsx)("line", { x1: startScreen, y1: pinned ? headerSize : y + headerSize, x2: startScreen, y2: pinned ? 0 : y, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth }), (0, import_jsx_runtime25.jsx)("text", { x: cx, y: (pinned ? 0 : y) + headerSize / 2, textAnchor: "middle", dominantBaseline: "middle", fill: lanesTheme.headerTextColor, fontFamily: lanesTheme.headerFontFamily, fontSize: lanesTheme.headerFontSize, style: { userSelect: "none" }, children:
|
|
19874
|
+
return (0, import_jsx_runtime25.jsxs)("g", { children: [(0, import_jsx_runtime25.jsx)("line", { x1: startScreen, y1: pinned ? headerSize : y + headerSize, x2: startScreen, y2: pinned ? 0 : y, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth }), (0, import_jsx_runtime25.jsx)("text", { x: cx, y: (pinned ? 0 : y) + headerSize / 2, textAnchor: "middle", dominantBaseline: "middle", fill: lanesTheme.headerTextColor, fontFamily: lanesTheme.headerFontFamily, fontSize: lanesTheme.headerFontSize, style: { userSelect: "none" }, children: truncateToWidth2(col.label, visibleW - pad * 2, lanesTheme.headerFontSize) })] }, `colh-${col.id}`);
|
|
19440
19875
|
}), pinned && (0, import_jsx_runtime25.jsx)("line", { x1: colsOffsetLeft, y1: headerSize, x2: width, y2: headerSize, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth })] }), hasRows && (0, import_jsx_runtime25.jsxs)("g", { children: [pinned && (0, import_jsx_runtime25.jsx)("rect", { x: 0, y: rowsOffsetTop, width: headerSize, height: height - rowsOffsetTop, fill: lanesTheme.headerBackground }), rows.map((row) => {
|
|
19441
19876
|
const startScreen = canvasToScreen(0, row.start, viewport).y;
|
|
19442
19877
|
const endScreen = canvasToScreen(0, row.start + row.size, viewport).y;
|
|
@@ -19448,10 +19883,10 @@ var SystemCanvas = (() => {
|
|
|
19448
19883
|
const cy = visibleTop + visibleH / 2;
|
|
19449
19884
|
if (endScreen <= rowsOffsetTop || startScreen >= height)
|
|
19450
19885
|
return null;
|
|
19451
|
-
return (0, import_jsx_runtime25.jsxs)("g", { children: [(0, import_jsx_runtime25.jsx)("line", { x1: pinned ? 0 : x, y1: startScreen, x2: pinned ? headerSize : x + headerSize, y2: startScreen, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth }), (0, import_jsx_runtime25.jsx)("text", { x: (pinned ? 0 : x) + headerSize / 2, y: cy, textAnchor: "middle", dominantBaseline: "middle", fill: lanesTheme.headerTextColor, fontFamily: lanesTheme.headerFontFamily, fontSize: lanesTheme.headerFontSize, transform: `rotate(-90 ${(pinned ? 0 : x) + headerSize / 2} ${cy})`, style: { userSelect: "none" }, children:
|
|
19886
|
+
return (0, import_jsx_runtime25.jsxs)("g", { children: [(0, import_jsx_runtime25.jsx)("line", { x1: pinned ? 0 : x, y1: startScreen, x2: pinned ? headerSize : x + headerSize, y2: startScreen, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth }), (0, import_jsx_runtime25.jsx)("text", { x: (pinned ? 0 : x) + headerSize / 2, y: cy, textAnchor: "middle", dominantBaseline: "middle", fill: lanesTheme.headerTextColor, fontFamily: lanesTheme.headerFontFamily, fontSize: lanesTheme.headerFontSize, transform: `rotate(-90 ${(pinned ? 0 : x) + headerSize / 2} ${cy})`, style: { userSelect: "none" }, children: truncateToWidth2(row.label, visibleH - pad * 2, lanesTheme.headerFontSize) })] }, `rowh-${row.id}`);
|
|
19452
19887
|
}), pinned && (0, import_jsx_runtime25.jsx)("line", { x1: headerSize, y1: rowsOffsetTop, x2: headerSize, y2: height, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth })] }), hasColumns && hasRows && pinned && (0, import_jsx_runtime25.jsx)("rect", { x: 0, y: 0, width: headerSize, height: headerSize, fill: lanesTheme.headerBackground })] });
|
|
19453
19888
|
}
|
|
19454
|
-
function
|
|
19889
|
+
function truncateToWidth2(label, availablePx, fontSize) {
|
|
19455
19890
|
if (availablePx <= 0)
|
|
19456
19891
|
return "";
|
|
19457
19892
|
const charPx = fontSize * 0.6;
|
|
@@ -19493,8 +19928,10 @@ var SystemCanvas = (() => {
|
|
|
19493
19928
|
raf = requestAnimationFrame(tick);
|
|
19494
19929
|
return () => cancelAnimationFrame(raf);
|
|
19495
19930
|
}, [getViewport]);
|
|
19496
|
-
const
|
|
19497
|
-
const
|
|
19931
|
+
const align = theme.toolbarAlign ?? "center";
|
|
19932
|
+
const anchorCanvasX = align === "left" ? node.x : align === "right" ? node.x + node.width : node.x + node.width / 2;
|
|
19933
|
+
const topAnchor = canvasToScreen(anchorCanvasX, node.y, viewport);
|
|
19934
|
+
const bottomAnchor = canvasToScreen(anchorCanvasX, node.y + node.height, viewport);
|
|
19498
19935
|
const toolbarRef = (0, import_react19.useRef)(null);
|
|
19499
19936
|
const [size, setSize] = (0, import_react19.useState)({ width: 0, height: 0 });
|
|
19500
19937
|
(0, import_react19.useEffect)(() => {
|
|
@@ -19503,17 +19940,17 @@ var SystemCanvas = (() => {
|
|
|
19503
19940
|
return;
|
|
19504
19941
|
const update = () => {
|
|
19505
19942
|
const r = el.getBoundingClientRect();
|
|
19506
|
-
setSize({ width: r.width, height: r.height });
|
|
19943
|
+
setSize((prev) => prev.width === r.width && prev.height === r.height ? prev : { width: r.width, height: r.height });
|
|
19507
19944
|
};
|
|
19508
19945
|
update();
|
|
19509
19946
|
const ro = new ResizeObserver(update);
|
|
19510
19947
|
ro.observe(el);
|
|
19511
19948
|
return () => ro.disconnect();
|
|
19512
|
-
});
|
|
19513
|
-
let left =
|
|
19514
|
-
let top =
|
|
19949
|
+
}, []);
|
|
19950
|
+
let left = align === "left" ? topAnchor.x : align === "right" ? topAnchor.x - size.width : topAnchor.x - size.width / 2;
|
|
19951
|
+
let top = topAnchor.y - size.height - NODE_GAP;
|
|
19515
19952
|
if (top < FLIP_MARGIN) {
|
|
19516
|
-
top =
|
|
19953
|
+
top = bottomAnchor.y + NODE_GAP;
|
|
19517
19954
|
}
|
|
19518
19955
|
left = Math.max(FLIP_MARGIN, Math.min(left, containerWidth - size.width - FLIP_MARGIN));
|
|
19519
19956
|
const patch = (update) => onPatch(update);
|
|
@@ -19552,7 +19989,7 @@ var SystemCanvas = (() => {
|
|
|
19552
19989
|
}
|
|
19553
19990
|
function DefaultToolbarContent({ node, theme, onPatch, onDelete }) {
|
|
19554
19991
|
const groups = (0, import_react19.useMemo)(() => getNodeActionsForNode(node, theme), [node, theme]);
|
|
19555
|
-
const showDelete =
|
|
19992
|
+
const showDelete = theme.showToolbarDelete === true;
|
|
19556
19993
|
return (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [groups.map((group, i) => (0, import_jsx_runtime26.jsxs)(import_react19.default.Fragment, { children: [i > 0 && (0, import_jsx_runtime26.jsx)(Divider2, { theme }), (0, import_jsx_runtime26.jsx)(ActionGroupView, { group, node, theme, onPatch })] }, group.id)), showDelete && (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [(0, import_jsx_runtime26.jsx)(Divider2, { theme }), (0, import_jsx_runtime26.jsx)(DeleteButton, { theme, onDelete })] })] });
|
|
19557
19994
|
}
|
|
19558
19995
|
function Divider2({ theme }) {
|
|
@@ -19707,16 +20144,134 @@ var SystemCanvas = (() => {
|
|
|
19707
20144
|
}, children: (0, import_jsx_runtime26.jsx)("svg", { width: DELETE_SIZE, height: DELETE_SIZE, viewBox: "0 0 16 16", children: (0, import_jsx_runtime26.jsx)("path", { d: "M 3 5 L 13 5 M 6 5 L 6 3 L 10 3 L 10 5 M 5 5 L 5.5 14 L 10.5 14 L 11 5 M 7 7 L 7 12 M 9 7 L 9 12", fill: "none", stroke: "currentColor", strokeWidth: 1.2, strokeLinecap: "round", strokeLinejoin: "round" }) }) });
|
|
19708
20145
|
}
|
|
19709
20146
|
|
|
20147
|
+
// ../react/dist/components/NodeContextMenuOverlay.js
|
|
20148
|
+
var import_jsx_runtime27 = __toESM(require_jsx_runtime(), 1);
|
|
20149
|
+
var import_react20 = __toESM(require_react(), 1);
|
|
20150
|
+
var ESTIMATED_MENU_WIDTH = 200;
|
|
20151
|
+
var MIN_MENU_WIDTH = 160;
|
|
20152
|
+
var VIEWPORT_MARGIN = 8;
|
|
20153
|
+
function NodeContextMenuOverlay({ state, config, theme, onClose }) {
|
|
20154
|
+
const rootRef = (0, import_react20.useRef)(null);
|
|
20155
|
+
const [hoveredId, setHoveredId] = (0, import_react20.useState)(null);
|
|
20156
|
+
(0, import_react20.useEffect)(() => {
|
|
20157
|
+
if (state)
|
|
20158
|
+
setHoveredId(null);
|
|
20159
|
+
}, [state]);
|
|
20160
|
+
(0, import_react20.useEffect)(() => {
|
|
20161
|
+
if (!state)
|
|
20162
|
+
return;
|
|
20163
|
+
function onDown(e) {
|
|
20164
|
+
const root2 = rootRef.current;
|
|
20165
|
+
if (!root2)
|
|
20166
|
+
return;
|
|
20167
|
+
if (root2.contains(e.target))
|
|
20168
|
+
return;
|
|
20169
|
+
onClose();
|
|
20170
|
+
}
|
|
20171
|
+
function onKey(e) {
|
|
20172
|
+
if (e.key === "Escape") {
|
|
20173
|
+
e.stopPropagation();
|
|
20174
|
+
onClose();
|
|
20175
|
+
}
|
|
20176
|
+
}
|
|
20177
|
+
function onScroll() {
|
|
20178
|
+
onClose();
|
|
20179
|
+
}
|
|
20180
|
+
window.addEventListener("mousedown", onDown);
|
|
20181
|
+
window.addEventListener("keydown", onKey);
|
|
20182
|
+
window.addEventListener("scroll", onScroll, true);
|
|
20183
|
+
window.addEventListener("blur", onClose);
|
|
20184
|
+
return () => {
|
|
20185
|
+
window.removeEventListener("mousedown", onDown);
|
|
20186
|
+
window.removeEventListener("keydown", onKey);
|
|
20187
|
+
window.removeEventListener("scroll", onScroll, true);
|
|
20188
|
+
window.removeEventListener("blur", onClose);
|
|
20189
|
+
};
|
|
20190
|
+
}, [state, onClose]);
|
|
20191
|
+
if (!state)
|
|
20192
|
+
return null;
|
|
20193
|
+
const cm = theme.contextMenu;
|
|
20194
|
+
if (!cm)
|
|
20195
|
+
return null;
|
|
20196
|
+
const vw = typeof window !== "undefined" ? window.innerWidth : 0;
|
|
20197
|
+
const vh = typeof window !== "undefined" ? window.innerHeight : 0;
|
|
20198
|
+
const itemHeight = cm.itemPaddingY * 2 + cm.fontSize + 4;
|
|
20199
|
+
const estimatedHeight = state.items.length * itemHeight + cm.paddingY * 2;
|
|
20200
|
+
const left = vw ? Math.min(state.screenPosition.x, vw - ESTIMATED_MENU_WIDTH - VIEWPORT_MARGIN) : state.screenPosition.x;
|
|
20201
|
+
const top = vh ? Math.min(state.screenPosition.y, vh - estimatedHeight - VIEWPORT_MARGIN) : state.screenPosition.y;
|
|
20202
|
+
const matchCtx = { canvasRef: state.canvasRef };
|
|
20203
|
+
const anyIcon = state.items.some((item) => !!item.icon);
|
|
20204
|
+
return (0, import_jsx_runtime27.jsx)("div", {
|
|
20205
|
+
ref: rootRef,
|
|
20206
|
+
role: "menu",
|
|
20207
|
+
// Stop right-clicks inside the menu from bubbling into the document
|
|
20208
|
+
// listener and re-opening the canvas-level menu.
|
|
20209
|
+
onContextMenu: (e) => {
|
|
20210
|
+
e.preventDefault();
|
|
20211
|
+
e.stopPropagation();
|
|
20212
|
+
},
|
|
20213
|
+
style: {
|
|
20214
|
+
position: "fixed",
|
|
20215
|
+
left,
|
|
20216
|
+
top,
|
|
20217
|
+
zIndex: 1e3,
|
|
20218
|
+
minWidth: MIN_MENU_WIDTH,
|
|
20219
|
+
padding: `${cm.paddingY}px ${cm.paddingX}px`,
|
|
20220
|
+
background: cm.background,
|
|
20221
|
+
color: cm.itemColor,
|
|
20222
|
+
border: `1px solid ${cm.borderColor}`,
|
|
20223
|
+
borderRadius: cm.borderRadius,
|
|
20224
|
+
boxShadow: cm.shadow,
|
|
20225
|
+
fontFamily: cm.fontFamily,
|
|
20226
|
+
fontSize: cm.fontSize,
|
|
20227
|
+
backdropFilter: "blur(10px)",
|
|
20228
|
+
userSelect: "none",
|
|
20229
|
+
// `pointer-events: auto` so the menu still receives clicks even
|
|
20230
|
+
// when a parent canvas overlay disables them.
|
|
20231
|
+
pointerEvents: "auto"
|
|
20232
|
+
},
|
|
20233
|
+
children: state.items.map((item) => {
|
|
20234
|
+
const isDisabled = item.disabled?.(state.node, matchCtx) ?? false;
|
|
20235
|
+
const isHovered = !isDisabled && hoveredId === item.id;
|
|
20236
|
+
const color2 = item.destructive ? cm.destructiveItemColor : cm.itemColor;
|
|
20237
|
+
return (0, import_jsx_runtime27.jsxs)("div", { role: "menuitem", "aria-disabled": isDisabled, onMouseEnter: () => !isDisabled && setHoveredId(item.id), onMouseLeave: () => setHoveredId((id2) => id2 === item.id ? null : id2), onClick: () => {
|
|
20238
|
+
if (isDisabled)
|
|
20239
|
+
return;
|
|
20240
|
+
config.onSelect(item.id, state.node, {
|
|
20241
|
+
canvasRef: state.canvasRef,
|
|
20242
|
+
screenPosition: state.screenPosition
|
|
20243
|
+
});
|
|
20244
|
+
onClose();
|
|
20245
|
+
}, style: {
|
|
20246
|
+
display: "flex",
|
|
20247
|
+
alignItems: "center",
|
|
20248
|
+
gap: 10,
|
|
20249
|
+
padding: `${cm.itemPaddingY}px ${cm.itemPaddingX}px`,
|
|
20250
|
+
borderRadius: Math.max(0, cm.borderRadius - 4),
|
|
20251
|
+
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
20252
|
+
opacity: isDisabled ? 0.45 : 1,
|
|
20253
|
+
background: isHovered ? cm.itemHoverBackground : "transparent",
|
|
20254
|
+
color: color2
|
|
20255
|
+
}, children: [item.icon ? (0, import_jsx_runtime27.jsx)("svg", { width: 14, height: 14, viewBox: "0 0 16 16", style: { flexShrink: 0, overflow: "visible" }, children: (0, import_jsx_runtime27.jsx)(NodeIcon, { icon: item.icon, x: 0, y: 0, size: 14, color: color2, opacity: 1, customIcons: theme.icons }) }) : anyIcon ? (
|
|
20256
|
+
// Only reserve a spacer when other items in the same menu
|
|
20257
|
+
// do have icons — keeps labels vertically aligned in a
|
|
20258
|
+
// mixed menu without padding lone-item menus.
|
|
20259
|
+
(0, import_jsx_runtime27.jsx)("span", { style: { width: 14, flexShrink: 0 }, "aria-hidden": true })
|
|
20260
|
+
) : null, (0, import_jsx_runtime27.jsx)("span", { children: item.label })] }, item.id);
|
|
20261
|
+
})
|
|
20262
|
+
});
|
|
20263
|
+
}
|
|
20264
|
+
|
|
19710
20265
|
// ../react/dist/components/SystemCanvas.js
|
|
19711
20266
|
var CASCADE_WINDOW_MS = 1500;
|
|
19712
20267
|
var CASCADE_OFFSET = 20;
|
|
19713
|
-
var SystemCanvas = (0,
|
|
19714
|
-
const zoomNavConfig = (0,
|
|
20268
|
+
var SystemCanvas = (0, import_react21.forwardRef)(function SystemCanvas2({ canvas, onResolveCanvas, canvases, rootLabel = "Home", onNavigate, onBreadcrumbClick, onBreadcrumbsChange, onNodeClick, onNodeDoubleClick, onEdgeClick, onEdgeDoubleClick, onContextMenu, onSelectionChange, nodeContextMenu, editable = false, onNodeAdd, onNodeUpdate, onNodesUpdate, onNodeDelete, onEdgeUpdate, onEdgeDelete, onEdgeAdd, canDropNodeOn, onNodeDrop, renderAddNodeButton, showNodeToolbar = true, renderNodeToolbar, theme: themeProp, themes: customThemes, edgeStyle = "bezier", defaultViewport, minZoom: minZoomProp, maxZoom, onViewportChange, autoFit = "canvas-change", laneHeaders = "pinned", snapToLanes = false, zoomNavigation = false, className, style }, forwardedRef) {
|
|
20269
|
+
const zoomNavConfig = (0, import_react21.useMemo)(() => {
|
|
19715
20270
|
const defaults = {
|
|
19716
20271
|
enterThreshold: 0.66,
|
|
19717
20272
|
exitThreshold: 0.33,
|
|
19718
20273
|
prefetchThreshold: 0.4,
|
|
19719
|
-
landingScale: 1.
|
|
20274
|
+
landingScale: 1.3,
|
|
19720
20275
|
landingPadding: 0.08,
|
|
19721
20276
|
fadeDuration: 216
|
|
19722
20277
|
};
|
|
@@ -19736,16 +20291,16 @@ var SystemCanvas = (() => {
|
|
|
19736
20291
|
}, [zoomNavigation]);
|
|
19737
20292
|
const effectiveMaxZoom = maxZoom ?? (zoomNavConfig.enabled ? 16 : 4);
|
|
19738
20293
|
const effectiveMinZoom = minZoomProp ?? (zoomNavConfig.enabled ? 0.01 : 0.1);
|
|
19739
|
-
(0,
|
|
20294
|
+
(0, import_react21.useEffect)(() => {
|
|
19740
20295
|
const env = globalThis.process?.env?.NODE_ENV;
|
|
19741
20296
|
if (editable && !canvases && env !== "production") {
|
|
19742
20297
|
console.warn("[system-canvas] `editable` is enabled but `canvases` prop is missing. Edits to sub-canvases will not be reflected without a synchronous ref \u2192 CanvasData map.");
|
|
19743
20298
|
}
|
|
19744
20299
|
}, [editable, canvases]);
|
|
19745
|
-
const [parentFrames, setParentFrames] = (0,
|
|
19746
|
-
const [pendingHandoff, setPendingHandoff] = (0,
|
|
19747
|
-
const suppressNextHandoffClearRef = (0,
|
|
19748
|
-
const handleBreadcrumbClick = (0,
|
|
20300
|
+
const [parentFrames, setParentFrames] = (0, import_react21.useState)([]);
|
|
20301
|
+
const [pendingHandoff, setPendingHandoff] = (0, import_react21.useState)(null);
|
|
20302
|
+
const suppressNextHandoffClearRef = (0, import_react21.useRef)(false);
|
|
20303
|
+
const handleBreadcrumbClick = (0, import_react21.useCallback)((index) => {
|
|
19749
20304
|
setParentFrames((prev) => prev.slice(0, index));
|
|
19750
20305
|
if (suppressNextHandoffClearRef.current) {
|
|
19751
20306
|
suppressNextHandoffClearRef.current = false;
|
|
@@ -19762,7 +20317,10 @@ var SystemCanvas = (() => {
|
|
|
19762
20317
|
onNavigate,
|
|
19763
20318
|
onBreadcrumbClick: handleBreadcrumbClick
|
|
19764
20319
|
});
|
|
19765
|
-
|
|
20320
|
+
(0, import_react21.useEffect)(() => {
|
|
20321
|
+
onBreadcrumbsChange?.(breadcrumbs);
|
|
20322
|
+
}, [breadcrumbs, onBreadcrumbsChange]);
|
|
20323
|
+
const theme = (0, import_react21.useMemo)(() => {
|
|
19766
20324
|
const registry = { ...themes, ...customThemes };
|
|
19767
20325
|
const resolveByName = (name) => name && registry[name] ? registry[name] : null;
|
|
19768
20326
|
if (themeProp) {
|
|
@@ -19773,22 +20331,22 @@ var SystemCanvas = (() => {
|
|
|
19773
20331
|
}
|
|
19774
20332
|
return resolveByName(currentCanvas.theme?.base) ?? resolveByName(canvas.theme?.base) ?? darkTheme;
|
|
19775
20333
|
}, [themeProp, customThemes, currentCanvas.theme?.base, canvas.theme?.base]);
|
|
19776
|
-
const { nodes, edges, nodeMap } = (0,
|
|
20334
|
+
const { nodes, edges, nodeMap } = (0, import_react21.useMemo)(() => {
|
|
19777
20335
|
const resolved = resolveCanvas(currentCanvas, theme);
|
|
19778
20336
|
const map = buildNodeMap(resolved.nodes);
|
|
19779
20337
|
return { nodes: resolved.nodes, edges: resolved.edges, nodeMap: map };
|
|
19780
20338
|
}, [currentCanvas, theme]);
|
|
19781
|
-
const nodesRef = (0,
|
|
20339
|
+
const nodesRef = (0, import_react21.useRef)(nodes);
|
|
19782
20340
|
nodesRef.current = nodes;
|
|
19783
|
-
const viewportStateRef = (0,
|
|
19784
|
-
const viewportHandleRef = (0,
|
|
19785
|
-
const navigateToRefRef = (0,
|
|
20341
|
+
const viewportStateRef = (0, import_react21.useRef)(defaultViewport ?? { x: 0, y: 0, zoom: 1 });
|
|
20342
|
+
const viewportHandleRef = (0, import_react21.useRef)(null);
|
|
20343
|
+
const navigateToRefRef = (0, import_react21.useRef)(navigateToRef);
|
|
19786
20344
|
navigateToRefRef.current = navigateToRef;
|
|
19787
|
-
const navigateToBreadcrumbRef = (0,
|
|
20345
|
+
const navigateToBreadcrumbRef = (0, import_react21.useRef)(navigateToBreadcrumb);
|
|
19788
20346
|
navigateToBreadcrumbRef.current = navigateToBreadcrumb;
|
|
19789
|
-
const breadcrumbsRef = (0,
|
|
20347
|
+
const breadcrumbsRef = (0, import_react21.useRef)(breadcrumbs);
|
|
19790
20348
|
breadcrumbsRef.current = breadcrumbs;
|
|
19791
|
-
(0,
|
|
20349
|
+
(0, import_react21.useImperativeHandle)(forwardedRef, () => ({
|
|
19792
20350
|
zoomIntoNode: (nodeId, options) => {
|
|
19793
20351
|
return new Promise((resolve) => {
|
|
19794
20352
|
const node = nodesRef.current.find((n) => n.id === nodeId);
|
|
@@ -19820,19 +20378,51 @@ var SystemCanvas = (() => {
|
|
|
19820
20378
|
navigateToBreadcrumbRef.current(0);
|
|
19821
20379
|
}
|
|
19822
20380
|
}), [forwardedRef]);
|
|
19823
|
-
const [selectedId, setSelectedId] = (0,
|
|
19824
|
-
const [editingId, setEditingId] = (0,
|
|
19825
|
-
const [selectedEdgeId, setSelectedEdgeId] = (0,
|
|
19826
|
-
const [editingEdgeId, setEditingEdgeId] = (0,
|
|
19827
|
-
(0,
|
|
20381
|
+
const [selectedId, setSelectedId] = (0, import_react21.useState)(null);
|
|
20382
|
+
const [editingId, setEditingId] = (0, import_react21.useState)(null);
|
|
20383
|
+
const [selectedEdgeId, setSelectedEdgeId] = (0, import_react21.useState)(null);
|
|
20384
|
+
const [editingEdgeId, setEditingEdgeId] = (0, import_react21.useState)(null);
|
|
20385
|
+
(0, import_react21.useEffect)(() => {
|
|
19828
20386
|
setSelectedId(null);
|
|
19829
20387
|
setEditingId(null);
|
|
19830
20388
|
setSelectedEdgeId(null);
|
|
19831
20389
|
setEditingEdgeId(null);
|
|
19832
20390
|
}, [currentCanvasRef]);
|
|
19833
|
-
const
|
|
19834
|
-
|
|
19835
|
-
|
|
20391
|
+
const onSelectionChangeRef = (0, import_react21.useRef)(onSelectionChange);
|
|
20392
|
+
(0, import_react21.useEffect)(() => {
|
|
20393
|
+
onSelectionChangeRef.current = onSelectionChange;
|
|
20394
|
+
}, [onSelectionChange]);
|
|
20395
|
+
const lastEmittedSelectionRef = (0, import_react21.useRef)({ kind: null, id: null, canvasRef: void 0 });
|
|
20396
|
+
(0, import_react21.useEffect)(() => {
|
|
20397
|
+
const cb = onSelectionChangeRef.current;
|
|
20398
|
+
let next = null;
|
|
20399
|
+
if (selectedId) {
|
|
20400
|
+
const node = nodeMap.get(selectedId);
|
|
20401
|
+
if (node)
|
|
20402
|
+
next = { kind: "node", node, canvasRef: currentCanvasRef };
|
|
20403
|
+
}
|
|
20404
|
+
if (!next && selectedEdgeId) {
|
|
20405
|
+
const edge = edges.find((e) => e.id === selectedEdgeId);
|
|
20406
|
+
if (edge)
|
|
20407
|
+
next = { kind: "edge", edge, canvasRef: currentCanvasRef };
|
|
20408
|
+
}
|
|
20409
|
+
const last = lastEmittedSelectionRef.current;
|
|
20410
|
+
const nextKind = next?.kind ?? null;
|
|
20411
|
+
const nextId = next ? next.kind === "node" ? next.node.id : next.edge.id : null;
|
|
20412
|
+
const nextRef = next?.canvasRef;
|
|
20413
|
+
if (last.kind === nextKind && last.id === nextId && last.canvasRef === nextRef) {
|
|
20414
|
+
return;
|
|
20415
|
+
}
|
|
20416
|
+
lastEmittedSelectionRef.current = {
|
|
20417
|
+
kind: nextKind,
|
|
20418
|
+
id: nextId,
|
|
20419
|
+
canvasRef: nextRef
|
|
20420
|
+
};
|
|
20421
|
+
cb?.(next);
|
|
20422
|
+
}, [selectedId, selectedEdgeId, currentCanvasRef, nodeMap, edges]);
|
|
20423
|
+
const containerRef = (0, import_react21.useRef)(null);
|
|
20424
|
+
const [containerSize, setContainerSize] = (0, import_react21.useState)({ width: 0, height: 0 });
|
|
20425
|
+
(0, import_react21.useEffect)(() => {
|
|
19836
20426
|
const el = containerRef.current;
|
|
19837
20427
|
if (!el)
|
|
19838
20428
|
return;
|
|
@@ -19847,42 +20437,67 @@ var SystemCanvas = (() => {
|
|
|
19847
20437
|
}, []);
|
|
19848
20438
|
const hasLanes = currentCanvas.columns && currentCanvas.columns.length > 0 || currentCanvas.rows && currentCanvas.rows.length > 0;
|
|
19849
20439
|
const showLaneHeaders = hasLanes && laneHeaders !== "none";
|
|
19850
|
-
const getViewportState = (0,
|
|
19851
|
-
const
|
|
20440
|
+
const getViewportState = (0, import_react21.useCallback)(() => viewportStateRef.current ?? { x: 0, y: 0, zoom: 1 }, []);
|
|
20441
|
+
const applyLaneSnap = (0, import_react21.useCallback)((id2, patch) => {
|
|
20442
|
+
if (!snapToLanes)
|
|
20443
|
+
return patch;
|
|
20444
|
+
const cols = currentCanvas.columns;
|
|
20445
|
+
const rows = currentCanvas.rows;
|
|
20446
|
+
const node = nodesRef.current.find((n) => n.id === id2);
|
|
19852
20447
|
let final = patch;
|
|
19853
|
-
|
|
19854
|
-
|
|
19855
|
-
|
|
19856
|
-
const
|
|
19857
|
-
|
|
19858
|
-
|
|
19859
|
-
|
|
19860
|
-
|
|
19861
|
-
|
|
19862
|
-
|
|
19863
|
-
|
|
19864
|
-
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19868
|
-
|
|
19869
|
-
|
|
19870
|
-
|
|
19871
|
-
|
|
19872
|
-
|
|
20448
|
+
const nx = patch.x;
|
|
20449
|
+
const ny = patch.y;
|
|
20450
|
+
if (cols && cols.length > 0 && nx != null) {
|
|
20451
|
+
const snapped = snapToLane(nx, cols, {
|
|
20452
|
+
edge: "center",
|
|
20453
|
+
size: node?.width ?? 0
|
|
20454
|
+
});
|
|
20455
|
+
final = { ...final, x: Math.round(snapped) };
|
|
20456
|
+
}
|
|
20457
|
+
if (rows && rows.length > 0 && ny != null) {
|
|
20458
|
+
const snapped = snapToLane(ny, rows, {
|
|
20459
|
+
edge: "center",
|
|
20460
|
+
size: node?.height ?? 0
|
|
20461
|
+
});
|
|
20462
|
+
final = { ...final, y: Math.round(snapped) };
|
|
20463
|
+
}
|
|
20464
|
+
return final;
|
|
20465
|
+
}, [snapToLanes, currentCanvas.columns, currentCanvas.rows]);
|
|
20466
|
+
const commitResize = (0, import_react21.useCallback)((id2, patch) => {
|
|
20467
|
+
onNodeUpdate?.(id2, applyLaneSnap(id2, patch), currentCanvasRef);
|
|
20468
|
+
}, [onNodeUpdate, currentCanvasRef, applyLaneSnap]);
|
|
20469
|
+
const commitDragBatch = (0, import_react21.useCallback)((updates) => {
|
|
20470
|
+
const final = updates.map((u) => ({
|
|
20471
|
+
id: u.id,
|
|
20472
|
+
patch: applyLaneSnap(u.id, u.patch)
|
|
20473
|
+
}));
|
|
20474
|
+
if (onNodesUpdate) {
|
|
20475
|
+
onNodesUpdate(final, currentCanvasRef);
|
|
20476
|
+
return;
|
|
19873
20477
|
}
|
|
19874
|
-
onNodeUpdate
|
|
19875
|
-
|
|
19876
|
-
|
|
20478
|
+
if (!onNodeUpdate)
|
|
20479
|
+
return;
|
|
20480
|
+
for (const { id: id2, patch } of final) {
|
|
20481
|
+
onNodeUpdate(id2, patch, currentCanvasRef);
|
|
20482
|
+
}
|
|
20483
|
+
}, [onNodeUpdate, onNodesUpdate, currentCanvasRef, applyLaneSnap]);
|
|
20484
|
+
const svgProxyRef = (0, import_react21.useRef)(null);
|
|
20485
|
+
const handleNodeDrop = (0, import_react21.useCallback)((sources, target) => {
|
|
20486
|
+
onNodeDrop?.(sources, target, { canvasRef: currentCanvasRef });
|
|
20487
|
+
}, [onNodeDrop, currentCanvasRef]);
|
|
20488
|
+
const { dragOverrides, dropTargetId, onPointerDown: onNodePointerDown } = useNodeDrag({
|
|
19877
20489
|
viewport: viewportStateRef,
|
|
19878
20490
|
nodesRef,
|
|
19879
|
-
onCommit:
|
|
20491
|
+
onCommit: commitDragBatch,
|
|
20492
|
+
svgRef: svgProxyRef,
|
|
20493
|
+
canDropNodeOn,
|
|
20494
|
+
onNodeDrop: handleNodeDrop
|
|
19880
20495
|
});
|
|
19881
20496
|
const { resizeOverrides, onHandlePointerDown: onResizeHandlePointerDown } = useNodeResize({
|
|
19882
20497
|
viewport: viewportStateRef,
|
|
19883
|
-
onCommit:
|
|
20498
|
+
onCommit: commitResize
|
|
19884
20499
|
});
|
|
19885
|
-
const selectedResolvedNode = (0,
|
|
20500
|
+
const selectedResolvedNode = (0, import_react21.useMemo)(() => {
|
|
19886
20501
|
if (!selectedId)
|
|
19887
20502
|
return null;
|
|
19888
20503
|
const base = nodeMap.get(selectedId);
|
|
@@ -19898,9 +20513,8 @@ var SystemCanvas = (() => {
|
|
|
19898
20513
|
}
|
|
19899
20514
|
return base;
|
|
19900
20515
|
}, [selectedId, nodeMap, dragOverrides, resizeOverrides]);
|
|
19901
|
-
const svgProxyRef = (0, import_react20.useRef)(null);
|
|
19902
20516
|
svgProxyRef.current = viewportHandleRef.current?.getSvgElement() ?? null;
|
|
19903
|
-
const handleEdgeCreated = (0,
|
|
20517
|
+
const handleEdgeCreated = (0, import_react21.useCallback)((edge) => {
|
|
19904
20518
|
onEdgeAdd?.(edge, currentCanvasRef);
|
|
19905
20519
|
}, [onEdgeAdd, currentCanvasRef]);
|
|
19906
20520
|
const { pending: pendingEdge, onHandlePointerDown: onConnectionHandlePointerDown } = useEdgeCreate({
|
|
@@ -19909,7 +20523,7 @@ var SystemCanvas = (() => {
|
|
|
19909
20523
|
nodesRef,
|
|
19910
20524
|
onCreate: handleEdgeCreated
|
|
19911
20525
|
});
|
|
19912
|
-
const handleNavigableNodeClick = (0,
|
|
20526
|
+
const handleNavigableNodeClick = (0, import_react21.useCallback)((node) => {
|
|
19913
20527
|
const frame2 = {
|
|
19914
20528
|
parentCanvasRef: currentCanvasRef,
|
|
19915
20529
|
parentNodeRect: {
|
|
@@ -19936,7 +20550,7 @@ var SystemCanvas = (() => {
|
|
|
19936
20550
|
navigateToRef(node);
|
|
19937
20551
|
}
|
|
19938
20552
|
}, [navigateToRef, currentCanvasRef, zoomNavConfig.enabled]);
|
|
19939
|
-
const handleZoomEnter = (0,
|
|
20553
|
+
const handleZoomEnter = (0, import_react21.useCallback)((node, targetTransform) => {
|
|
19940
20554
|
const frame2 = {
|
|
19941
20555
|
parentCanvasRef: currentCanvasRef,
|
|
19942
20556
|
parentNodeRect: {
|
|
@@ -19950,7 +20564,7 @@ var SystemCanvas = (() => {
|
|
|
19950
20564
|
setPendingHandoff(targetTransform);
|
|
19951
20565
|
navigateToRef(node);
|
|
19952
20566
|
}, [currentCanvasRef, navigateToRef]);
|
|
19953
|
-
const handleZoomExit = (0,
|
|
20567
|
+
const handleZoomExit = (0, import_react21.useCallback)((targetTransform) => {
|
|
19954
20568
|
setPendingHandoff(targetTransform);
|
|
19955
20569
|
suppressNextHandoffClearRef.current = true;
|
|
19956
20570
|
navigateToBreadcrumb(breadcrumbs.length - 2);
|
|
@@ -19973,30 +20587,58 @@ var SystemCanvas = (() => {
|
|
|
19973
20587
|
const rect = svg.getBoundingClientRect();
|
|
19974
20588
|
return { width: rect.width, height: rect.height };
|
|
19975
20589
|
},
|
|
20590
|
+
getCursorScreenPos: () => viewportHandleRef.current?.getCursorScreenPos() ?? null,
|
|
19976
20591
|
onEnter: handleZoomEnter,
|
|
19977
20592
|
onExit: handleZoomExit
|
|
19978
20593
|
});
|
|
19979
|
-
const handleViewportChange = (0,
|
|
20594
|
+
const handleViewportChange = (0, import_react21.useCallback)((vp) => {
|
|
19980
20595
|
viewportStateRef.current = vp;
|
|
19981
20596
|
handleZoomNavViewportChange(vp);
|
|
19982
20597
|
onViewportChange?.(vp);
|
|
19983
20598
|
}, [handleZoomNavViewportChange, onViewportChange]);
|
|
19984
|
-
const handleHandoffApplied = (0,
|
|
20599
|
+
const handleHandoffApplied = (0, import_react21.useCallback)(() => {
|
|
19985
20600
|
setPendingHandoff(null);
|
|
19986
20601
|
clearZoomNavCommitting();
|
|
19987
20602
|
}, [clearZoomNavCommitting]);
|
|
19988
|
-
const handleBeginEdit = (0,
|
|
20603
|
+
const handleBeginEdit = (0, import_react21.useCallback)((node) => {
|
|
19989
20604
|
setEditingId(node.id);
|
|
19990
20605
|
}, []);
|
|
19991
|
-
const handleBeginEditEdge = (0,
|
|
20606
|
+
const handleBeginEditEdge = (0, import_react21.useCallback)((edge) => {
|
|
19992
20607
|
setEditingEdgeId(edge.id);
|
|
19993
20608
|
}, []);
|
|
20609
|
+
const [contextMenuState, setContextMenuState] = (0, import_react21.useState)(null);
|
|
20610
|
+
(0, import_react21.useEffect)(() => {
|
|
20611
|
+
setContextMenuState(null);
|
|
20612
|
+
}, [currentCanvasRef]);
|
|
20613
|
+
const handleContextMenu = (0, import_react21.useCallback)((event) => {
|
|
20614
|
+
onContextMenu?.(event);
|
|
20615
|
+
if (!nodeContextMenu)
|
|
20616
|
+
return;
|
|
20617
|
+
if (event.type !== "node")
|
|
20618
|
+
return;
|
|
20619
|
+
const node = event.target;
|
|
20620
|
+
if (!node)
|
|
20621
|
+
return;
|
|
20622
|
+
const matched = filterContextMenuItems(nodeContextMenu.items, node, {
|
|
20623
|
+
canvasRef: currentCanvasRef ?? null
|
|
20624
|
+
});
|
|
20625
|
+
if (matched.length === 0) {
|
|
20626
|
+
setContextMenuState(null);
|
|
20627
|
+
return;
|
|
20628
|
+
}
|
|
20629
|
+
setContextMenuState({
|
|
20630
|
+
items: matched,
|
|
20631
|
+
node,
|
|
20632
|
+
screenPosition: event.screenPosition,
|
|
20633
|
+
canvasRef: currentCanvasRef ?? null
|
|
20634
|
+
});
|
|
20635
|
+
}, [onContextMenu, nodeContextMenu, currentCanvasRef]);
|
|
19994
20636
|
const { handleNodeClick, handleNodeDoubleClick, handleNodeNavigate, handleEdgeClick, handleEdgeDoubleClick, handleCanvasClick, handleCanvasContextMenu, handleNodeContextMenu, handleEdgeContextMenu } = useCanvasInteraction({
|
|
19995
20637
|
onNodeClick,
|
|
19996
20638
|
onNodeDoubleClick,
|
|
19997
20639
|
onEdgeClick,
|
|
19998
20640
|
onEdgeDoubleClick,
|
|
19999
|
-
onContextMenu,
|
|
20641
|
+
onContextMenu: handleContextMenu,
|
|
20000
20642
|
onNavigableNodeClick: handleNavigableNodeClick,
|
|
20001
20643
|
viewport: viewportStateRef,
|
|
20002
20644
|
editable,
|
|
@@ -20005,27 +20647,27 @@ var SystemCanvas = (() => {
|
|
|
20005
20647
|
onSelectEdge: setSelectedEdgeId,
|
|
20006
20648
|
onBeginEditEdge: handleBeginEditEdge
|
|
20007
20649
|
});
|
|
20008
|
-
const handleEditorCommit = (0,
|
|
20650
|
+
const handleEditorCommit = (0, import_react21.useCallback)((patch) => {
|
|
20009
20651
|
if (editingId) {
|
|
20010
20652
|
onNodeUpdate?.(editingId, patch, currentCanvasRef);
|
|
20011
20653
|
}
|
|
20012
20654
|
setEditingId(null);
|
|
20013
20655
|
}, [editingId, onNodeUpdate, currentCanvasRef]);
|
|
20014
|
-
const handleEditorCancel = (0,
|
|
20656
|
+
const handleEditorCancel = (0, import_react21.useCallback)(() => {
|
|
20015
20657
|
setEditingId(null);
|
|
20016
20658
|
}, []);
|
|
20017
|
-
const handleEdgeEditorCommit = (0,
|
|
20659
|
+
const handleEdgeEditorCommit = (0, import_react21.useCallback)((patch) => {
|
|
20018
20660
|
if (editingEdgeId) {
|
|
20019
20661
|
onEdgeUpdate?.(editingEdgeId, patch, currentCanvasRef);
|
|
20020
20662
|
}
|
|
20021
20663
|
setEditingEdgeId(null);
|
|
20022
20664
|
}, [editingEdgeId, onEdgeUpdate, currentCanvasRef]);
|
|
20023
|
-
const handleEdgeEditorCancel = (0,
|
|
20665
|
+
const handleEdgeEditorCancel = (0, import_react21.useCallback)(() => {
|
|
20024
20666
|
setEditingEdgeId(null);
|
|
20025
20667
|
}, []);
|
|
20026
|
-
const lastAddRef = (0,
|
|
20027
|
-
const menuOptions = (0,
|
|
20028
|
-
const addNode2 = (0,
|
|
20668
|
+
const lastAddRef = (0, import_react21.useRef)(null);
|
|
20669
|
+
const menuOptions = (0, import_react21.useMemo)(() => getNodeMenuOptions(currentCanvas, theme), [currentCanvas, theme]);
|
|
20670
|
+
const addNode2 = (0, import_react21.useCallback)((option, position) => {
|
|
20029
20671
|
let x, y;
|
|
20030
20672
|
if (position) {
|
|
20031
20673
|
x = position.x;
|
|
@@ -20057,7 +20699,7 @@ var SystemCanvas = (() => {
|
|
|
20057
20699
|
const node = createNodeFromOption(option, Math.round(x), Math.round(y), void 0, theme);
|
|
20058
20700
|
onNodeAdd?.(node, currentCanvasRef);
|
|
20059
20701
|
}, [onNodeAdd, currentCanvasRef, theme]);
|
|
20060
|
-
const handleKeyDown = (0,
|
|
20702
|
+
const handleKeyDown = (0, import_react21.useCallback)((e) => {
|
|
20061
20703
|
if (!editable)
|
|
20062
20704
|
return;
|
|
20063
20705
|
if (e.key === "Escape") {
|
|
@@ -20091,14 +20733,14 @@ var SystemCanvas = (() => {
|
|
|
20091
20733
|
currentCanvasRef
|
|
20092
20734
|
]);
|
|
20093
20735
|
const renderProps = { options: menuOptions, addNode: addNode2, theme };
|
|
20094
|
-
return (0,
|
|
20736
|
+
return (0, import_jsx_runtime28.jsxs)("div", { ref: containerRef, className: `system-canvas ${className ?? ""}`, tabIndex: editable ? 0 : -1, onKeyDown: handleKeyDown, style: {
|
|
20095
20737
|
position: "relative",
|
|
20096
20738
|
width: "100%",
|
|
20097
20739
|
height: "100%",
|
|
20098
20740
|
overflow: "hidden",
|
|
20099
20741
|
outline: "none",
|
|
20100
20742
|
...style
|
|
20101
|
-
}, children: [(0,
|
|
20743
|
+
}, children: [(0, import_jsx_runtime28.jsx)(Breadcrumbs, { breadcrumbs, theme: theme.breadcrumbs, onNavigate: navigateToBreadcrumb }), isLoading && (0, import_jsx_runtime28.jsx)("div", { className: "system-canvas-loading", style: {
|
|
20102
20744
|
position: "absolute",
|
|
20103
20745
|
top: 12,
|
|
20104
20746
|
right: 12,
|
|
@@ -20110,12 +20752,12 @@ var SystemCanvas = (() => {
|
|
|
20110
20752
|
fontFamily: theme.node.fontFamily,
|
|
20111
20753
|
fontSize: 12,
|
|
20112
20754
|
backdropFilter: "blur(8px)"
|
|
20113
|
-
}, children: "Loading..." }), (0,
|
|
20755
|
+
}, children: "Loading..." }), (0, import_jsx_runtime28.jsx)(Viewport, { ref: viewportHandleRef, nodes, edges, nodeMap, theme, edgeStyle, columns: currentCanvas.columns, rows: currentCanvas.rows, canvases, minZoom: effectiveMinZoom, maxZoom: effectiveMaxZoom, defaultViewport, autoFit, canvasRef: currentCanvasRef, handoffTransform: pendingHandoff, onHandoffApplied: handleHandoffApplied, handoffFadeMs: zoomNavConfig.fadeDuration, onViewportChange: handleViewportChange, onNodeClick: handleNodeClick, onNodeDoubleClick: handleNodeDoubleClick, onNodeNavigate: handleNodeNavigate, onEdgeClick: handleEdgeClick, onEdgeDoubleClick: handleEdgeDoubleClick, onCanvasClick: editable ? handleCanvasClick : void 0, onCanvasContextMenu: handleCanvasContextMenu, onNodeContextMenu: handleNodeContextMenu, onEdgeContextMenu: handleEdgeContextMenu, onNodePointerDown: editable ? onNodePointerDown : void 0, selectedId: editable ? selectedId : null, editingId: editable ? editingId : null, selectedEdgeId: editable ? selectedEdgeId : null, editingEdgeId: editable ? editingEdgeId : null, dragOverrides, dropTargetId, resizeOverrides, onResizeHandlePointerDown: editable ? onResizeHandlePointerDown : void 0, onEditorCommit: handleEditorCommit, onEditorCancel: handleEditorCancel, onEdgeEditorCommit: handleEdgeEditorCommit, onEdgeEditorCancel: handleEdgeEditorCancel, pendingEdge: editable ? pendingEdge : null, onConnectionHandlePointerDown: editable ? onConnectionHandlePointerDown : void 0, edgeCreateEnabled: editable }), showLaneHeaders && (0, import_jsx_runtime28.jsx)(LaneHeaders, { columns: currentCanvas.columns, rows: currentCanvas.rows, theme, getViewport: getViewportState, width: containerSize.width, height: containerSize.height, pinned: laneHeaders === "pinned" }), editable && showNodeToolbar && selectedResolvedNode && !editingId && (0, import_jsx_runtime28.jsx)(NodeToolbar, { node: selectedResolvedNode, theme, onPatch: (update) => {
|
|
20114
20756
|
onNodeUpdate?.(selectedResolvedNode.id, update, currentCanvasRef);
|
|
20115
20757
|
}, onDelete: () => {
|
|
20116
20758
|
onNodeDelete?.(selectedResolvedNode.id, currentCanvasRef);
|
|
20117
20759
|
setSelectedId(null);
|
|
20118
|
-
}, getViewport: getViewportState, containerWidth: containerSize.width, containerHeight: containerSize.height, render: renderNodeToolbar }), editable && (renderAddNodeButton ? renderAddNodeButton(renderProps) : (0,
|
|
20760
|
+
}, getViewport: getViewportState, containerWidth: containerSize.width, containerHeight: containerSize.height, render: renderNodeToolbar }), editable && (renderAddNodeButton ? renderAddNodeButton(renderProps) : (0, import_jsx_runtime28.jsx)(AddNodeButton, { ...renderProps })), nodeContextMenu && (0, import_jsx_runtime28.jsx)(NodeContextMenuOverlay, { state: contextMenuState, config: nodeContextMenu, theme, onClose: () => setContextMenuState(null) })] });
|
|
20119
20761
|
});
|
|
20120
20762
|
|
|
20121
20763
|
// src/index.tsx
|
|
@@ -20226,7 +20868,7 @@ var SystemCanvas = (() => {
|
|
|
20226
20868
|
onEdgeUpdate: handleEdgeUpdate,
|
|
20227
20869
|
onEdgeDelete: handleEdgeDelete
|
|
20228
20870
|
};
|
|
20229
|
-
root2.render(
|
|
20871
|
+
root2.render(import_react22.default.createElement(SystemCanvas, props));
|
|
20230
20872
|
};
|
|
20231
20873
|
doRender();
|
|
20232
20874
|
return {
|