system-canvas-standalone 0.1.0 → 0.1.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 +1197 -238
- package/dist/system-canvas.js.map +1 -1
- package/dist/system-canvas.min.js +10 -9
- package/dist/system-canvas.min.js.map +1 -1
- package/package.json +1 -1
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_react21 = __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_runtime27 = __toESM(require_jsx_runtime(), 1);
|
|
12767
|
+
var import_react20 = __toESM(require_react(), 1);
|
|
12768
12768
|
|
|
12769
12769
|
// ../core/dist/themes/dark.js
|
|
12770
12770
|
var darkTheme = {
|
|
@@ -13723,20 +13723,28 @@ var SystemCanvas = (() => {
|
|
|
13723
13723
|
return pos;
|
|
13724
13724
|
const edge = options.edge ?? "start";
|
|
13725
13725
|
const size = options.size ?? 0;
|
|
13726
|
-
if (edge === "start") {
|
|
13727
|
-
const
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13726
|
+
if (edge === "start" || edge === "center") {
|
|
13727
|
+
const center = pos + size / 2;
|
|
13728
|
+
const containing = findLaneAt(center, lanes);
|
|
13729
|
+
let target;
|
|
13730
|
+
if (containing) {
|
|
13731
|
+
target = containing;
|
|
13732
|
+
} else {
|
|
13733
|
+
let best2 = lanes[0];
|
|
13734
|
+
let bestDist2 = Math.abs(center - (best2.start + best2.size / 2));
|
|
13735
|
+
for (const lane of lanes) {
|
|
13736
|
+
const d = Math.abs(center - (lane.start + lane.size / 2));
|
|
13737
|
+
if (d < bestDist2) {
|
|
13738
|
+
best2 = lane;
|
|
13739
|
+
bestDist2 = d;
|
|
13740
|
+
}
|
|
13741
|
+
}
|
|
13742
|
+
target = best2;
|
|
13743
|
+
}
|
|
13744
|
+
if (edge === "center") {
|
|
13745
|
+
return target.start + (target.size - size) / 2;
|
|
13746
|
+
}
|
|
13747
|
+
return target.start;
|
|
13740
13748
|
}
|
|
13741
13749
|
const boundaries = [];
|
|
13742
13750
|
for (const lane of lanes)
|
|
@@ -13792,8 +13800,397 @@ var SystemCanvas = (() => {
|
|
|
13792
13800
|
function filterActionsForNode(group, node) {
|
|
13793
13801
|
return group.actions.filter((a) => !a.appliesTo || a.appliesTo(node));
|
|
13794
13802
|
}
|
|
13803
|
+
function getNodeActionsForNode(node, theme) {
|
|
13804
|
+
if (node.category) {
|
|
13805
|
+
const def = theme.categories?.[node.category];
|
|
13806
|
+
if (def?.toolbar && def.toolbar.length > 0)
|
|
13807
|
+
return def.toolbar;
|
|
13808
|
+
}
|
|
13809
|
+
return getNodeActions(theme);
|
|
13810
|
+
}
|
|
13811
|
+
|
|
13812
|
+
// ../core/dist/rollup.js
|
|
13813
|
+
function rollupNodes(canvas, predicate) {
|
|
13814
|
+
const nodes = canvas?.nodes ?? [];
|
|
13815
|
+
const total = nodes.length;
|
|
13816
|
+
if (total === 0)
|
|
13817
|
+
return { total: 0, matched: 0, fraction: 0 };
|
|
13818
|
+
let matched = 0;
|
|
13819
|
+
for (const n of nodes) {
|
|
13820
|
+
if (predicate(n))
|
|
13821
|
+
matched++;
|
|
13822
|
+
}
|
|
13823
|
+
return { total, matched, fraction: matched / total };
|
|
13824
|
+
}
|
|
13825
|
+
|
|
13826
|
+
// ../core/dist/slots.js
|
|
13827
|
+
var CORNER_INSET = 8;
|
|
13828
|
+
var CORNER_EM = 1.25;
|
|
13829
|
+
var HEADER_EM = 1;
|
|
13830
|
+
var FOOTER_EM = 1;
|
|
13831
|
+
var HEADER_INSET_X = 14;
|
|
13832
|
+
var HEADER_INSET_Y = 10;
|
|
13833
|
+
var FOOTER_INSET_Y = 10;
|
|
13834
|
+
var TOP_EDGE_PX = 5;
|
|
13835
|
+
var RIGHT_EDGE_PX = 4;
|
|
13836
|
+
var LEFT_EDGE_PX = 4;
|
|
13837
|
+
var BOTTOM_EDGE_MIN_PX = 6;
|
|
13838
|
+
var BOTTOM_EDGE_HEIGHT_RATIO = 0.08;
|
|
13839
|
+
var TAB_BADGE_EM = 1.4;
|
|
13840
|
+
var TAB_BADGE_LIFT = 10;
|
|
13841
|
+
var TAB_BADGE_OVERHANG = 8;
|
|
13842
|
+
function computeCategorySlotRegions(node, theme, slots) {
|
|
13843
|
+
const { x, y, width, height } = node;
|
|
13844
|
+
const fs = theme.node.fontSize;
|
|
13845
|
+
const corner = CORNER_EM * fs;
|
|
13846
|
+
const header = HEADER_EM * fs;
|
|
13847
|
+
const footer = FOOTER_EM * fs;
|
|
13848
|
+
const tab = TAB_BADGE_EM * fs;
|
|
13849
|
+
const bottomEdge = Math.max(BOTTOM_EDGE_MIN_PX, Math.round(height * BOTTOM_EDGE_HEIGHT_RATIO));
|
|
13850
|
+
const bodyReservations = computeBodyReservations(node, theme, slots);
|
|
13851
|
+
const bodyX = x + bodyReservations.left;
|
|
13852
|
+
const bodyY = y + bodyReservations.top;
|
|
13853
|
+
const bodyWidth = Math.max(0, width - bodyReservations.left - bodyReservations.right);
|
|
13854
|
+
const bodyHeight = Math.max(0, height - bodyReservations.top - bodyReservations.bottom);
|
|
13855
|
+
return {
|
|
13856
|
+
topEdge: {
|
|
13857
|
+
x,
|
|
13858
|
+
y,
|
|
13859
|
+
width,
|
|
13860
|
+
height: TOP_EDGE_PX
|
|
13861
|
+
},
|
|
13862
|
+
bottomEdge: {
|
|
13863
|
+
x,
|
|
13864
|
+
y: y + height - bottomEdge,
|
|
13865
|
+
width,
|
|
13866
|
+
height: bottomEdge
|
|
13867
|
+
},
|
|
13868
|
+
leftEdge: {
|
|
13869
|
+
x,
|
|
13870
|
+
y,
|
|
13871
|
+
width: LEFT_EDGE_PX,
|
|
13872
|
+
height
|
|
13873
|
+
},
|
|
13874
|
+
rightEdge: {
|
|
13875
|
+
x: x + width - RIGHT_EDGE_PX,
|
|
13876
|
+
y,
|
|
13877
|
+
width: RIGHT_EDGE_PX,
|
|
13878
|
+
height
|
|
13879
|
+
},
|
|
13880
|
+
bodyTop: (() => {
|
|
13881
|
+
const hasHeader = slots?.header !== void 0;
|
|
13882
|
+
const bandHeight = Math.max(4, Math.round(fs * 0.35));
|
|
13883
|
+
const bandY = hasHeader ? (
|
|
13884
|
+
// Just below the header strip. Header height is ~fs + 4
|
|
13885
|
+
// and sits at HEADER_INSET_Y; pad another small gap so the
|
|
13886
|
+
// bar reads as decoration rather than a divider line.
|
|
13887
|
+
y + HEADER_INSET_Y + fs + 6
|
|
13888
|
+
) : (
|
|
13889
|
+
// Legacy: under one line of body text.
|
|
13890
|
+
y + HEADER_INSET_Y + fs + Math.round(fs * 0.9)
|
|
13891
|
+
);
|
|
13892
|
+
return {
|
|
13893
|
+
x: x + HEADER_INSET_X,
|
|
13894
|
+
y: bandY,
|
|
13895
|
+
width: Math.max(0, width - HEADER_INSET_X * 2),
|
|
13896
|
+
height: bandHeight
|
|
13897
|
+
};
|
|
13898
|
+
})(),
|
|
13899
|
+
topRightOuter: {
|
|
13900
|
+
// Hangs off the top-right corner. The region extends past the
|
|
13901
|
+
// node's right edge so the badge reads as a notification tab
|
|
13902
|
+
// clinging to the outside of the corner rather than sitting on
|
|
13903
|
+
// top of the node.
|
|
13904
|
+
x: x + width - tab + TAB_BADGE_OVERHANG,
|
|
13905
|
+
y: y - TAB_BADGE_LIFT,
|
|
13906
|
+
width: tab,
|
|
13907
|
+
height: tab
|
|
13908
|
+
},
|
|
13909
|
+
topLeft: {
|
|
13910
|
+
x: x + CORNER_INSET,
|
|
13911
|
+
y: y + CORNER_INSET,
|
|
13912
|
+
width: corner,
|
|
13913
|
+
height: corner
|
|
13914
|
+
},
|
|
13915
|
+
topRight: {
|
|
13916
|
+
x: x + width - CORNER_INSET - corner,
|
|
13917
|
+
y: y + CORNER_INSET,
|
|
13918
|
+
width: corner,
|
|
13919
|
+
height: corner
|
|
13920
|
+
},
|
|
13921
|
+
bottomLeft: {
|
|
13922
|
+
x: x + CORNER_INSET,
|
|
13923
|
+
y: y + height - CORNER_INSET - corner,
|
|
13924
|
+
width: corner,
|
|
13925
|
+
height: corner
|
|
13926
|
+
},
|
|
13927
|
+
bottomRight: {
|
|
13928
|
+
x: x + width - CORNER_INSET - corner,
|
|
13929
|
+
y: y + height - CORNER_INSET - corner,
|
|
13930
|
+
width: corner,
|
|
13931
|
+
height: corner
|
|
13932
|
+
},
|
|
13933
|
+
header: {
|
|
13934
|
+
x: x + HEADER_INSET_X,
|
|
13935
|
+
y: y + HEADER_INSET_Y,
|
|
13936
|
+
width: Math.max(0, width - HEADER_INSET_X * 2),
|
|
13937
|
+
height: header
|
|
13938
|
+
},
|
|
13939
|
+
footer: {
|
|
13940
|
+
x: x + HEADER_INSET_X,
|
|
13941
|
+
y: y + height - FOOTER_INSET_Y - footer,
|
|
13942
|
+
width: Math.max(0, width - HEADER_INSET_X * 2),
|
|
13943
|
+
height: footer
|
|
13944
|
+
},
|
|
13945
|
+
body: {
|
|
13946
|
+
x: bodyX,
|
|
13947
|
+
y: bodyY,
|
|
13948
|
+
width: bodyWidth,
|
|
13949
|
+
height: bodyHeight
|
|
13950
|
+
}
|
|
13951
|
+
};
|
|
13952
|
+
}
|
|
13953
|
+
function computeBodyReservations(node, theme, slots) {
|
|
13954
|
+
if (!slots) {
|
|
13955
|
+
return {
|
|
13956
|
+
top: HEADER_INSET_Y,
|
|
13957
|
+
bottom: FOOTER_INSET_Y,
|
|
13958
|
+
left: HEADER_INSET_X,
|
|
13959
|
+
right: HEADER_INSET_X
|
|
13960
|
+
};
|
|
13961
|
+
}
|
|
13962
|
+
const r = computeReflowReservationsInternal(node, theme, slots);
|
|
13963
|
+
let top = Math.max(r.top, HEADER_INSET_Y);
|
|
13964
|
+
if (slots.bodyTop && slots.header) {
|
|
13965
|
+
const fs = theme.node.fontSize;
|
|
13966
|
+
const bandHeight = Math.max(4, Math.round(fs * 0.35));
|
|
13967
|
+
const bandBottomFromTop = HEADER_INSET_Y + fs + 6 + bandHeight + 6;
|
|
13968
|
+
top = Math.max(top, bandBottomFromTop);
|
|
13969
|
+
}
|
|
13970
|
+
return {
|
|
13971
|
+
top,
|
|
13972
|
+
bottom: Math.max(r.bottom, FOOTER_INSET_Y),
|
|
13973
|
+
left: Math.max(r.left, HEADER_INSET_X),
|
|
13974
|
+
right: Math.max(r.right, HEADER_INSET_X)
|
|
13975
|
+
};
|
|
13976
|
+
}
|
|
13977
|
+
function isFn(v) {
|
|
13978
|
+
return typeof v === "function";
|
|
13979
|
+
}
|
|
13980
|
+
function resolveAccessor(accessor, ctx) {
|
|
13981
|
+
return isFn(accessor) ? accessor(ctx) : accessor;
|
|
13982
|
+
}
|
|
13983
|
+
function resolveAccessorOr(accessor, fallback, ctx) {
|
|
13984
|
+
if (accessor === void 0)
|
|
13985
|
+
return fallback;
|
|
13986
|
+
return resolveAccessor(accessor, ctx);
|
|
13987
|
+
}
|
|
13988
|
+
function getCategorySlots(node, theme) {
|
|
13989
|
+
if (!node.category)
|
|
13990
|
+
return void 0;
|
|
13991
|
+
const def = theme.categories[node.category];
|
|
13992
|
+
return def?.slots;
|
|
13993
|
+
}
|
|
13994
|
+
function pickRefIndicatorCorner(defaultCorner, slots) {
|
|
13995
|
+
if (!slots)
|
|
13996
|
+
return defaultCorner;
|
|
13997
|
+
const occupied = (c) => {
|
|
13998
|
+
if (slots[c])
|
|
13999
|
+
return true;
|
|
14000
|
+
if ((c === "topLeft" || c === "topRight") && slots.header)
|
|
14001
|
+
return true;
|
|
14002
|
+
if ((c === "bottomLeft" || c === "bottomRight") && slots.footer)
|
|
14003
|
+
return true;
|
|
14004
|
+
if (c === "topRight" && slots.topRightOuter)
|
|
14005
|
+
return true;
|
|
14006
|
+
return false;
|
|
14007
|
+
};
|
|
14008
|
+
if (!occupied(defaultCorner))
|
|
14009
|
+
return defaultCorner;
|
|
14010
|
+
const order = {
|
|
14011
|
+
topLeft: ["bottomRight", "topRight", "bottomLeft"],
|
|
14012
|
+
topRight: ["bottomLeft", "bottomRight", "topLeft"],
|
|
14013
|
+
bottomLeft: ["topRight", "topLeft", "bottomRight"],
|
|
14014
|
+
bottomRight: ["topLeft", "bottomLeft", "topRight"]
|
|
14015
|
+
};
|
|
14016
|
+
for (const c of order[defaultCorner]) {
|
|
14017
|
+
if (!occupied(c))
|
|
14018
|
+
return c;
|
|
14019
|
+
}
|
|
14020
|
+
return defaultCorner;
|
|
14021
|
+
}
|
|
14022
|
+
function slotEntries(slots) {
|
|
14023
|
+
const positions = [
|
|
14024
|
+
"topEdge",
|
|
14025
|
+
"bottomEdge",
|
|
14026
|
+
"leftEdge",
|
|
14027
|
+
"rightEdge",
|
|
14028
|
+
"header",
|
|
14029
|
+
"footer",
|
|
14030
|
+
"body",
|
|
14031
|
+
"bodyTop",
|
|
14032
|
+
"topLeft",
|
|
14033
|
+
"topRight",
|
|
14034
|
+
"bottomLeft",
|
|
14035
|
+
"bottomRight",
|
|
14036
|
+
// Outer positions paint last so they visually sit above the node's
|
|
14037
|
+
// own stroke — a tab badge needs to clip into the node's corner.
|
|
14038
|
+
"topRightOuter"
|
|
14039
|
+
];
|
|
14040
|
+
const out = [];
|
|
14041
|
+
for (const p of positions) {
|
|
14042
|
+
const s = slots[p];
|
|
14043
|
+
if (s)
|
|
14044
|
+
out.push([p, s]);
|
|
14045
|
+
}
|
|
14046
|
+
return out;
|
|
14047
|
+
}
|
|
14048
|
+
function computeReflowReservations(node, theme, slots) {
|
|
14049
|
+
return computeReflowReservationsInternal(node, theme, slots);
|
|
14050
|
+
}
|
|
14051
|
+
function computeReflowReservationsInternal(node, theme, slots) {
|
|
14052
|
+
if (!slots)
|
|
14053
|
+
return { top: 0, bottom: 0, left: 0, right: 0 };
|
|
14054
|
+
const regions = computeCategorySlotRegions(node, theme);
|
|
14055
|
+
let top = 0;
|
|
14056
|
+
let bottom = 0;
|
|
14057
|
+
let left = 0;
|
|
14058
|
+
let right = 0;
|
|
14059
|
+
if (slots.header)
|
|
14060
|
+
top = regions.header.height + HEADER_INSET_Y + 6;
|
|
14061
|
+
if (slots.footer)
|
|
14062
|
+
bottom = regions.footer.height + FOOTER_INSET_Y + 4;
|
|
14063
|
+
if (slots.leftEdge)
|
|
14064
|
+
left = regions.leftEdge.width + 4;
|
|
14065
|
+
if (slots.rightEdge)
|
|
14066
|
+
right = regions.rightEdge.width + 4;
|
|
14067
|
+
if (slots.topLeft && slots.topLeft.kind === "dot") {
|
|
14068
|
+
left = Math.max(left, regions.topLeft.x + regions.topLeft.width - node.x + 6);
|
|
14069
|
+
}
|
|
14070
|
+
const isDashboard = slots.header !== void 0 || slots.topRight !== void 0 || slots.bodyTop !== void 0 || slots.footer !== void 0 || slots.topLeft !== void 0 && slots.topLeft.kind === "dot";
|
|
14071
|
+
if (isDashboard) {
|
|
14072
|
+
if (!slots.header)
|
|
14073
|
+
top = Math.max(top, HEADER_INSET_Y);
|
|
14074
|
+
left = Math.max(left, HEADER_INSET_X);
|
|
14075
|
+
right = Math.max(right, HEADER_INSET_X);
|
|
14076
|
+
}
|
|
14077
|
+
if (slots.topRight && slots.topRight.kind === "pill") {
|
|
14078
|
+
right = Math.max(right, Math.round(theme.node.fontSize * 3.6));
|
|
14079
|
+
}
|
|
14080
|
+
const vertSpace = node.height - top - bottom;
|
|
14081
|
+
if (vertSpace < theme.node.fontSize) {
|
|
14082
|
+
top = 0;
|
|
14083
|
+
bottom = 0;
|
|
14084
|
+
}
|
|
14085
|
+
const horSpace = node.width - left - right;
|
|
14086
|
+
if (horSpace < theme.node.fontSize) {
|
|
14087
|
+
left = 0;
|
|
14088
|
+
right = 0;
|
|
14089
|
+
}
|
|
14090
|
+
return { top, bottom, left, right };
|
|
14091
|
+
}
|
|
14092
|
+
|
|
14093
|
+
// ../core/dist/paths.js
|
|
14094
|
+
function getAtPath(obj, path) {
|
|
14095
|
+
if (obj == null)
|
|
14096
|
+
return void 0;
|
|
14097
|
+
const parts = path.split(".");
|
|
14098
|
+
let cur = obj;
|
|
14099
|
+
for (const p of parts) {
|
|
14100
|
+
if (cur == null || typeof cur !== "object")
|
|
14101
|
+
return void 0;
|
|
14102
|
+
cur = cur[p];
|
|
14103
|
+
}
|
|
14104
|
+
return cur;
|
|
14105
|
+
}
|
|
14106
|
+
function setAtPath(obj, path, value) {
|
|
14107
|
+
const parts = path.split(".");
|
|
14108
|
+
const root2 = obj ? { ...obj } : {};
|
|
14109
|
+
let cur = root2;
|
|
14110
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
14111
|
+
const key = parts[i];
|
|
14112
|
+
const next = cur[key];
|
|
14113
|
+
const cloned = next != null && typeof next === "object" && !Array.isArray(next) ? { ...next } : {};
|
|
14114
|
+
cur[key] = cloned;
|
|
14115
|
+
cur = cloned;
|
|
14116
|
+
}
|
|
14117
|
+
cur[parts[parts.length - 1]] = value;
|
|
14118
|
+
return root2;
|
|
14119
|
+
}
|
|
14120
|
+
|
|
14121
|
+
// ../core/dist/text.js
|
|
14122
|
+
var GLYPH_WIDTH_RATIO = 0.62;
|
|
14123
|
+
function measureTextWidth(text, fontSize) {
|
|
14124
|
+
if (!text)
|
|
14125
|
+
return 0;
|
|
14126
|
+
return text.length * fontSize * GLYPH_WIDTH_RATIO;
|
|
14127
|
+
}
|
|
14128
|
+
function wrapText(text, maxWidth, fontSize) {
|
|
14129
|
+
if (!text)
|
|
14130
|
+
return [""];
|
|
14131
|
+
if (maxWidth <= 0)
|
|
14132
|
+
return [text];
|
|
14133
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
14134
|
+
if (words.length === 0)
|
|
14135
|
+
return [""];
|
|
14136
|
+
const lines = [];
|
|
14137
|
+
let current = "";
|
|
14138
|
+
for (const word of words) {
|
|
14139
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
14140
|
+
if (measureTextWidth(candidate, fontSize) > maxWidth && current) {
|
|
14141
|
+
lines.push(current);
|
|
14142
|
+
current = word;
|
|
14143
|
+
} else {
|
|
14144
|
+
current = candidate;
|
|
14145
|
+
}
|
|
14146
|
+
}
|
|
14147
|
+
if (current)
|
|
14148
|
+
lines.push(current);
|
|
14149
|
+
return lines.length > 0 ? lines : [""];
|
|
14150
|
+
}
|
|
14151
|
+
function wrapTextWithBreaks(text, maxWidth, fontSize, maxLines) {
|
|
14152
|
+
if (!text)
|
|
14153
|
+
return [];
|
|
14154
|
+
const paragraphs = text.split("\n");
|
|
14155
|
+
const out = [];
|
|
14156
|
+
for (const para of paragraphs) {
|
|
14157
|
+
if (para === "") {
|
|
14158
|
+
out.push("");
|
|
14159
|
+
continue;
|
|
14160
|
+
}
|
|
14161
|
+
out.push(...wrapText(para, maxWidth, fontSize));
|
|
14162
|
+
}
|
|
14163
|
+
if (maxLines !== void 0 && maxLines > 0 && out.length > maxLines) {
|
|
14164
|
+
const truncated = out.slice(0, maxLines);
|
|
14165
|
+
const last = truncated[truncated.length - 1];
|
|
14166
|
+
truncated[truncated.length - 1] = ellipsize(last, maxWidth, fontSize);
|
|
14167
|
+
return truncated;
|
|
14168
|
+
}
|
|
14169
|
+
return out;
|
|
14170
|
+
}
|
|
14171
|
+
function ellipsize(line, maxWidth, fontSize) {
|
|
14172
|
+
const ellipsis = "\u2026";
|
|
14173
|
+
if (measureTextWidth(line + ellipsis, fontSize) <= maxWidth) {
|
|
14174
|
+
return line + ellipsis;
|
|
14175
|
+
}
|
|
14176
|
+
const words = line.split(" ");
|
|
14177
|
+
while (words.length > 1) {
|
|
14178
|
+
words.pop();
|
|
14179
|
+
const candidate = words.join(" ") + ellipsis;
|
|
14180
|
+
if (measureTextWidth(candidate, fontSize) <= maxWidth)
|
|
14181
|
+
return candidate;
|
|
14182
|
+
}
|
|
14183
|
+
return line + ellipsis;
|
|
14184
|
+
}
|
|
13795
14185
|
|
|
13796
14186
|
// ../core/dist/canvas.js
|
|
14187
|
+
function deepClone(value) {
|
|
14188
|
+
const g = globalThis;
|
|
14189
|
+
if (typeof g.structuredClone === "function") {
|
|
14190
|
+
return g.structuredClone(value);
|
|
14191
|
+
}
|
|
14192
|
+
return JSON.parse(JSON.stringify(value));
|
|
14193
|
+
}
|
|
13797
14194
|
function resolveCanvas(canvas, theme) {
|
|
13798
14195
|
const effectiveTheme = canvas.theme?.categories ? {
|
|
13799
14196
|
...theme,
|
|
@@ -13856,7 +14253,7 @@ var SystemCanvas = (() => {
|
|
|
13856
14253
|
}));
|
|
13857
14254
|
return [...categoryOptions, ...typeOptions];
|
|
13858
14255
|
}
|
|
13859
|
-
function createNodeFromOption(option, x, y, id2 = generateNodeId()) {
|
|
14256
|
+
function createNodeFromOption(option, x, y, id2 = generateNodeId(), theme) {
|
|
13860
14257
|
const base = {
|
|
13861
14258
|
id: id2,
|
|
13862
14259
|
type: option.nodeType,
|
|
@@ -13865,6 +14262,10 @@ var SystemCanvas = (() => {
|
|
|
13865
14262
|
};
|
|
13866
14263
|
if (option.kind === "category") {
|
|
13867
14264
|
base.category = option.value;
|
|
14265
|
+
const def = theme?.categories?.[option.value];
|
|
14266
|
+
if (def?.defaultCustomData) {
|
|
14267
|
+
base.customData = deepClone(def.defaultCustomData);
|
|
14268
|
+
}
|
|
13868
14269
|
}
|
|
13869
14270
|
switch (option.nodeType) {
|
|
13870
14271
|
case "text":
|
|
@@ -14607,8 +15008,8 @@ var SystemCanvas = (() => {
|
|
|
14607
15008
|
}
|
|
14608
15009
|
|
|
14609
15010
|
// ../react/dist/components/Viewport.js
|
|
14610
|
-
var
|
|
14611
|
-
var
|
|
15011
|
+
var import_jsx_runtime22 = __toESM(require_jsx_runtime(), 1);
|
|
15012
|
+
var import_react15 = __toESM(require_react(), 1);
|
|
14612
15013
|
|
|
14613
15014
|
// ../react/dist/hooks/useViewport.js
|
|
14614
15015
|
var import_react7 = __toESM(require_react(), 1);
|
|
@@ -17442,13 +17843,13 @@ var SystemCanvas = (() => {
|
|
|
17442
17843
|
if (options2?.targetZoom != null) {
|
|
17443
17844
|
targetZoom = options2.targetZoom;
|
|
17444
17845
|
} else {
|
|
17445
|
-
const padding =
|
|
17846
|
+
const padding = 8;
|
|
17446
17847
|
const scaleX = rect.width / (node.width + padding * 2);
|
|
17447
17848
|
const scaleY = rect.height / (node.height + padding * 2);
|
|
17448
|
-
targetZoom = Math.min(scaleX, scaleY,
|
|
17849
|
+
targetZoom = Math.min(scaleX, scaleY, 12);
|
|
17449
17850
|
}
|
|
17450
17851
|
const t = identity2.translate(rect.width / 2 - nodeCx * targetZoom, rect.height / 2 - nodeCy * targetZoom).scale(targetZoom);
|
|
17451
|
-
select_default2(svg).transition().duration(options2?.durationMs ??
|
|
17852
|
+
select_default2(svg).transition().duration(options2?.durationMs ?? 900).call(zoomBehaviorRef.current.transform, t).on("end", () => {
|
|
17452
17853
|
onComplete?.();
|
|
17453
17854
|
});
|
|
17454
17855
|
}, []);
|
|
@@ -17464,10 +17865,10 @@ var SystemCanvas = (() => {
|
|
|
17464
17865
|
}
|
|
17465
17866
|
|
|
17466
17867
|
// ../react/dist/components/NodeRenderer.js
|
|
17467
|
-
var
|
|
17868
|
+
var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
|
|
17468
17869
|
|
|
17469
17870
|
// ../react/dist/components/TextNode.js
|
|
17470
|
-
var
|
|
17871
|
+
var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
|
|
17471
17872
|
|
|
17472
17873
|
// ../react/dist/components/NodeIcon.js
|
|
17473
17874
|
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
|
@@ -17582,7 +17983,8 @@ var SystemCanvas = (() => {
|
|
|
17582
17983
|
const stopAll = (e) => e.stopPropagation();
|
|
17583
17984
|
const right = nodeX + nodeWidth;
|
|
17584
17985
|
const bottom = nodeY + nodeHeight;
|
|
17585
|
-
const
|
|
17986
|
+
const isTopCorner = corner === "top-left" || corner === "top-right";
|
|
17987
|
+
const nodeRadius = isTopCorner ? theme.group.cornerRadius : node.resolvedCornerRadius;
|
|
17586
17988
|
const innerR = Math.max(0, Math.min(nodeRadius * 0.64, size / 2));
|
|
17587
17989
|
let squareX;
|
|
17588
17990
|
let squareY;
|
|
@@ -17591,10 +17993,18 @@ var SystemCanvas = (() => {
|
|
|
17591
17993
|
squareX = right - size;
|
|
17592
17994
|
squareY = bottom - size;
|
|
17593
17995
|
carvePath = `M ${right} ${squareY} L ${squareX + innerR} ${squareY} A ${innerR} ${innerR} 0 0 0 ${squareX} ${squareY + innerR} L ${squareX} ${bottom}`;
|
|
17594
|
-
} else {
|
|
17996
|
+
} else if (corner === "top-right") {
|
|
17595
17997
|
squareX = right - size;
|
|
17596
17998
|
squareY = nodeY;
|
|
17597
17999
|
carvePath = `M ${squareX} ${nodeY} L ${squareX} ${squareY + size - innerR} A ${innerR} ${innerR} 0 0 0 ${squareX + innerR} ${squareY + size} L ${right} ${squareY + size}`;
|
|
18000
|
+
} else if (corner === "bottom-left") {
|
|
18001
|
+
squareX = nodeX;
|
|
18002
|
+
squareY = bottom - size;
|
|
18003
|
+
carvePath = `M ${squareX + size} ${bottom} L ${squareX + size} ${squareY + innerR} A ${innerR} ${innerR} 0 0 0 ${squareX + size - innerR} ${squareY} L ${nodeX} ${squareY}`;
|
|
18004
|
+
} else {
|
|
18005
|
+
squareX = nodeX;
|
|
18006
|
+
squareY = nodeY;
|
|
18007
|
+
carvePath = `M ${squareX + size} ${nodeY} L ${squareX + size} ${squareY + size - innerR} A ${innerR} ${innerR} 0 0 1 ${squareX + size - innerR} ${squareY + size} L ${nodeX} ${squareY + size}`;
|
|
17598
18008
|
}
|
|
17599
18009
|
const cx = squareX + size / 2;
|
|
17600
18010
|
const cy = squareY + size / 2;
|
|
@@ -17605,8 +18015,12 @@ var SystemCanvas = (() => {
|
|
|
17605
18015
|
let hoverPath;
|
|
17606
18016
|
if (corner === "bottom-right") {
|
|
17607
18017
|
hoverPath = `M ${right} ${squareY} L ${right} ${bottom} L ${squareX} ${bottom} L ${squareX} ${squareY + innerR} A ${innerR} ${innerR} 0 0 1 ${squareX + innerR} ${squareY} Z`;
|
|
17608
|
-
} else {
|
|
18018
|
+
} else if (corner === "top-right") {
|
|
17609
18019
|
hoverPath = `M ${squareX} ${nodeY} L ${right} ${nodeY} L ${right} ${squareY + size} L ${squareX + innerR} ${squareY + size} A ${innerR} ${innerR} 0 0 1 ${squareX} ${squareY + size - innerR} Z`;
|
|
18020
|
+
} else if (corner === "bottom-left") {
|
|
18021
|
+
hoverPath = `M ${nodeX} ${squareY} L ${squareX + size - innerR} ${squareY} A ${innerR} ${innerR} 0 0 1 ${squareX + size} ${squareY + innerR} L ${squareX + size} ${bottom} L ${nodeX} ${bottom} Z`;
|
|
18022
|
+
} else {
|
|
18023
|
+
hoverPath = `M ${nodeX} ${nodeY} L ${squareX + size} ${nodeY} L ${squareX + size} ${squareY + size - innerR} A ${innerR} ${innerR} 0 0 1 ${squareX + size - innerR} ${squareY + size} L ${nodeX} ${squareY + size} Z`;
|
|
17610
18024
|
}
|
|
17611
18025
|
return (0, import_jsx_runtime2.jsxs)("g", { className: "system-canvas-ref-indicator", style: { cursor: "pointer" }, onClick: (e) => {
|
|
17612
18026
|
e.stopPropagation();
|
|
@@ -17627,31 +18041,359 @@ var SystemCanvas = (() => {
|
|
|
17627
18041
|
}
|
|
17628
18042
|
}
|
|
17629
18043
|
|
|
18044
|
+
// ../react/dist/components/CategorySlotsLayer.js
|
|
18045
|
+
var import_jsx_runtime9 = __toESM(require_jsx_runtime(), 1);
|
|
18046
|
+
var import_react10 = __toESM(require_react(), 1);
|
|
18047
|
+
|
|
18048
|
+
// ../react/dist/primitives/NodeColorFill.js
|
|
18049
|
+
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
18050
|
+
function NodeColorFill({ region, color: color2, position, extent, length = 0.55, cornerRadius, opacity = 1 }) {
|
|
18051
|
+
const isEdge = position === "topEdge" || position === "bottomEdge" || position === "leftEdge" || position === "rightEdge";
|
|
18052
|
+
const effectiveExtent = extent ?? (isEdge ? "short" : "full");
|
|
18053
|
+
if (isEdge && effectiveExtent === "short") {
|
|
18054
|
+
return (0, import_jsx_runtime3.jsx)(ShortEdgeStrip, { region, color: color2, position, length: Math.max(0.1, Math.min(1, length)), opacity });
|
|
18055
|
+
}
|
|
18056
|
+
const rx = cornerRadius ?? // On full-width edge strips, round a bit so the ends tuck under the
|
|
18057
|
+
// node's own rounded corners cleanly.
|
|
18058
|
+
(isEdge ? Math.min(region.height, region.width) / 2 : 0);
|
|
18059
|
+
return (0, import_jsx_runtime3.jsx)("rect", { x: region.x, y: region.y, width: region.width, height: region.height, rx, fill: color2, opacity, pointerEvents: "none" });
|
|
18060
|
+
}
|
|
18061
|
+
function ShortEdgeStrip({ region, color: color2, position, length, opacity }) {
|
|
18062
|
+
let x = region.x;
|
|
18063
|
+
let y = region.y;
|
|
18064
|
+
let w = region.width;
|
|
18065
|
+
let h = region.height;
|
|
18066
|
+
if (position === "topEdge" || position === "bottomEdge") {
|
|
18067
|
+
w = region.width * length;
|
|
18068
|
+
} else {
|
|
18069
|
+
h = region.height * length;
|
|
18070
|
+
}
|
|
18071
|
+
const shortDim = Math.min(w, h);
|
|
18072
|
+
const rx = shortDim / 2;
|
|
18073
|
+
return (0, import_jsx_runtime3.jsx)("rect", { x, y, width: w, height: h, rx, fill: color2, opacity, pointerEvents: "none" });
|
|
18074
|
+
}
|
|
18075
|
+
|
|
18076
|
+
// ../react/dist/primitives/NodeProgressBar.js
|
|
18077
|
+
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
|
18078
|
+
function NodeProgressBar({ region, value, color: color2, bgColor, cornerRadius, trackAlpha = 0.12 }) {
|
|
18079
|
+
const v = Math.max(0, Math.min(1, value));
|
|
18080
|
+
const filled = Math.max(0, region.width * v);
|
|
18081
|
+
const rx = cornerRadius ?? Math.min(region.width, region.height) / 2;
|
|
18082
|
+
const track = bgColor ?? colorWithAlpha(color2, trackAlpha);
|
|
18083
|
+
return (0, import_jsx_runtime4.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime4.jsx)("rect", { x: region.x, y: region.y, width: region.width, height: region.height, rx, fill: track }), filled > 0 && (0, import_jsx_runtime4.jsx)("rect", { x: region.x, y: region.y, width: filled, height: region.height, rx, fill: color2 })] });
|
|
18084
|
+
}
|
|
18085
|
+
function colorWithAlpha(color2, alpha) {
|
|
18086
|
+
if (color2.startsWith("#")) {
|
|
18087
|
+
const h = color2.slice(1);
|
|
18088
|
+
let r;
|
|
18089
|
+
let g;
|
|
18090
|
+
let b;
|
|
18091
|
+
if (h.length === 3) {
|
|
18092
|
+
r = parseInt(h[0] + h[0], 16);
|
|
18093
|
+
g = parseInt(h[1] + h[1], 16);
|
|
18094
|
+
b = parseInt(h[2] + h[2], 16);
|
|
18095
|
+
} else if (h.length === 6) {
|
|
18096
|
+
r = parseInt(h.slice(0, 2), 16);
|
|
18097
|
+
g = parseInt(h.slice(2, 4), 16);
|
|
18098
|
+
b = parseInt(h.slice(4, 6), 16);
|
|
18099
|
+
} else {
|
|
18100
|
+
return `rgba(255, 255, 255, ${alpha})`;
|
|
18101
|
+
}
|
|
18102
|
+
if (!Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b)) {
|
|
18103
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
18104
|
+
}
|
|
18105
|
+
}
|
|
18106
|
+
const match = color2.match(/^rgba?\(([^)]+)\)$/);
|
|
18107
|
+
if (match) {
|
|
18108
|
+
const parts = match[1].split(",").map((p) => p.trim());
|
|
18109
|
+
if (parts.length >= 3) {
|
|
18110
|
+
return `rgba(${parts[0]}, ${parts[1]}, ${parts[2]}, ${alpha})`;
|
|
18111
|
+
}
|
|
18112
|
+
}
|
|
18113
|
+
return `rgba(255, 255, 255, ${alpha})`;
|
|
18114
|
+
}
|
|
18115
|
+
|
|
18116
|
+
// ../react/dist/primitives/NodeCountBadge.js
|
|
18117
|
+
var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
|
|
18118
|
+
function NodeCountBadge({ region, value, theme, color: color2, textColor, position }) {
|
|
18119
|
+
const label = typeof value === "number" ? String(value) : value;
|
|
18120
|
+
if (label.length === 0)
|
|
18121
|
+
return null;
|
|
18122
|
+
const fill = color2 ?? theme.node.refIndicator.color;
|
|
18123
|
+
const text = textColor ?? theme.background;
|
|
18124
|
+
if (position === "topRightOuter") {
|
|
18125
|
+
return (0, import_jsx_runtime5.jsx)(TabBadge, { region, label, fill, text, theme });
|
|
18126
|
+
}
|
|
18127
|
+
return (0, import_jsx_runtime5.jsx)(PillBadge, { region, label, fill, text, theme });
|
|
18128
|
+
}
|
|
18129
|
+
function TabBadge({ region, label, fill, text, theme }) {
|
|
18130
|
+
const h = region.height;
|
|
18131
|
+
const minW = h;
|
|
18132
|
+
const fontSize = Math.max(9, h * 0.58);
|
|
18133
|
+
const estW = label.length <= 1 ? minW : Math.max(minW, fontSize * 0.7 * label.length + 10);
|
|
18134
|
+
const w = Math.min(estW, h * 3);
|
|
18135
|
+
const x = region.x + region.width - w;
|
|
18136
|
+
const y = region.y;
|
|
18137
|
+
const rx = Math.min(6, h / 3);
|
|
18138
|
+
const cx = x + w / 2;
|
|
18139
|
+
const cy = y + h / 2;
|
|
18140
|
+
const ringWidth = 2;
|
|
18141
|
+
return (0, import_jsx_runtime5.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime5.jsx)("rect", { x: x - ringWidth, y: y - ringWidth, width: w + ringWidth * 2, height: h + ringWidth * 2, rx: rx + ringWidth, fill: theme.background }), (0, import_jsx_runtime5.jsx)("rect", { x, y, width: w, height: h, rx, fill }), (0, import_jsx_runtime5.jsx)("text", { x: cx, y: cy + fontSize * 0.35, fill: text, fontSize, fontWeight: 700, fontFamily: theme.node.fontFamily, textAnchor: "middle", children: label })] });
|
|
18142
|
+
}
|
|
18143
|
+
function PillBadge({ region, label, fill, text, theme }) {
|
|
18144
|
+
const fontSize = Math.max(9, Math.min(region.height * 0.7, 14));
|
|
18145
|
+
const estWidth = Math.max(region.height, region.height * 0.65 + label.length * fontSize * 0.55);
|
|
18146
|
+
const width = Math.min(estWidth, region.width * 1.6);
|
|
18147
|
+
const height = region.height;
|
|
18148
|
+
const cx = region.x + region.width / 2;
|
|
18149
|
+
const cy = region.y + region.height / 2;
|
|
18150
|
+
const x = cx - width / 2;
|
|
18151
|
+
const y = cy - height / 2;
|
|
18152
|
+
return (0, import_jsx_runtime5.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime5.jsx)("rect", { x, y, width, height, rx: height / 2, fill }), (0, import_jsx_runtime5.jsx)("text", { x: cx, y: cy + fontSize * 0.35, fill: text, fontSize, fontWeight: 600, fontFamily: theme.node.fontFamily, textAnchor: "middle", children: label })] });
|
|
18153
|
+
}
|
|
18154
|
+
|
|
18155
|
+
// ../react/dist/primitives/NodeDot.js
|
|
18156
|
+
var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
|
|
18157
|
+
function NodeDot({ region, color: color2 }) {
|
|
18158
|
+
const cx = region.x + region.width / 2;
|
|
18159
|
+
const cy = region.y + region.height / 2;
|
|
18160
|
+
const r = Math.max(2, Math.min(region.width, region.height) * 0.2);
|
|
18161
|
+
return (0, import_jsx_runtime6.jsx)("circle", { cx, cy, r, fill: color2, pointerEvents: "none" });
|
|
18162
|
+
}
|
|
18163
|
+
|
|
18164
|
+
// ../react/dist/primitives/NodeText.js
|
|
18165
|
+
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
18166
|
+
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 }) {
|
|
18168
|
+
const reactId = (0, import_react9.useId)();
|
|
18169
|
+
const safeId = reactId.replace(/:/g, "");
|
|
18170
|
+
if (!value)
|
|
18171
|
+
return null;
|
|
18172
|
+
const fontSize = fontSizeProp ?? Math.max(9, Math.min(theme.node.fontSize - 2, region.height * 0.85));
|
|
18173
|
+
const lineHeight = lineHeightProp ?? Math.round(fontSize * 1.25);
|
|
18174
|
+
const anchor = align === "start" ? "start" : align === "center" ? "middle" : "end";
|
|
18175
|
+
const x = align === "start" ? region.x : align === "center" ? region.x + region.width / 2 : region.x + region.width;
|
|
18176
|
+
const font = fontFamily ?? (useLabelFont ? theme.node.labelFont ?? theme.node.fontFamily : theme.node.fontFamily);
|
|
18177
|
+
const gradId = fill ? `sc-text-grad-${safeId}` : void 0;
|
|
18178
|
+
const fillAttr = gradId ? `url(#${gradId})` : color2 ?? theme.node.sublabelColor;
|
|
18179
|
+
const displayValue = uppercase ? value.toUpperCase() : value;
|
|
18180
|
+
if (!wrap) {
|
|
18181
|
+
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: displayValue })] });
|
|
18183
|
+
}
|
|
18184
|
+
const wrapInset = 4;
|
|
18185
|
+
const wrapWidth = Math.max(0, region.width - wrapInset * 2);
|
|
18186
|
+
const lines = wrapTextWithBreaks(displayValue, wrapWidth, fontSize, maxLines);
|
|
18187
|
+
if (lines.length === 0)
|
|
18188
|
+
return null;
|
|
18189
|
+
const baseY = region.y + fontSize;
|
|
18190
|
+
const clipId = `sc-text-clip-${safeId}`;
|
|
18191
|
+
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)) }) })] });
|
|
18192
|
+
}
|
|
18193
|
+
function GradientDef({ id: id2, fill }) {
|
|
18194
|
+
const angle = fill.angle ?? 0;
|
|
18195
|
+
return (0, import_jsx_runtime7.jsxs)("linearGradient", { id: id2, x1: "0", y1: "0", x2: "1", y2: "0", gradientUnits: "objectBoundingBox", gradientTransform: angle ? `rotate(${angle} 0.5 0.5)` : void 0, children: [(0, import_jsx_runtime7.jsx)("stop", { offset: "0%", stopColor: fill.from }), (0, import_jsx_runtime7.jsx)("stop", { offset: "100%", stopColor: fill.to })] });
|
|
18196
|
+
}
|
|
18197
|
+
|
|
18198
|
+
// ../react/dist/primitives/NodeStatusPill.js
|
|
18199
|
+
var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
|
|
18200
|
+
function NodeStatusPill({ region, value, theme, color: color2, textColor, fill }) {
|
|
18201
|
+
const label = value.toUpperCase();
|
|
18202
|
+
if (!label)
|
|
18203
|
+
return null;
|
|
18204
|
+
const h = Math.min(region.height, 18);
|
|
18205
|
+
const fontSize = Math.max(9, h * 0.62);
|
|
18206
|
+
const padX = 8;
|
|
18207
|
+
const w = Math.max(h * 1.6, label.length * fontSize * 0.62 + padX * 2);
|
|
18208
|
+
const x = region.x + region.width - w;
|
|
18209
|
+
const y = region.y + (region.height - h) / 2;
|
|
18210
|
+
const rx = h / 2;
|
|
18211
|
+
const cx = x + w / 2;
|
|
18212
|
+
const cy = y + h / 2;
|
|
18213
|
+
const tint = fill ?? toTint(color2);
|
|
18214
|
+
const fg = textColor ?? color2;
|
|
18215
|
+
return (0, import_jsx_runtime8.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime8.jsx)("rect", { x, y, width: w, height: h, rx, fill: tint }), (0, import_jsx_runtime8.jsx)("text", { x: cx, y: cy + fontSize * 0.35, fill: fg, fontSize, fontWeight: 700, fontFamily: theme.node.fontFamily, textAnchor: "middle", letterSpacing: 0.6, children: label })] });
|
|
18216
|
+
}
|
|
18217
|
+
function toTint(color2) {
|
|
18218
|
+
if (color2.startsWith("#") && (color2.length === 7 || color2.length === 4)) {
|
|
18219
|
+
let r;
|
|
18220
|
+
let g;
|
|
18221
|
+
let b;
|
|
18222
|
+
if (color2.length === 7) {
|
|
18223
|
+
r = parseInt(color2.slice(1, 3), 16);
|
|
18224
|
+
g = parseInt(color2.slice(3, 5), 16);
|
|
18225
|
+
b = parseInt(color2.slice(5, 7), 16);
|
|
18226
|
+
} else {
|
|
18227
|
+
r = parseInt(color2[1] + color2[1], 16);
|
|
18228
|
+
g = parseInt(color2[2] + color2[2], 16);
|
|
18229
|
+
b = parseInt(color2[3] + color2[3], 16);
|
|
18230
|
+
}
|
|
18231
|
+
if (!Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b)) {
|
|
18232
|
+
return `rgba(${r}, ${g}, ${b}, 0.15)`;
|
|
18233
|
+
}
|
|
18234
|
+
}
|
|
18235
|
+
return "rgba(255, 255, 255, 0.08)";
|
|
18236
|
+
}
|
|
18237
|
+
|
|
18238
|
+
// ../react/dist/components/CategorySlotsLayer.js
|
|
18239
|
+
function CategorySlotsLayer({ node, theme, canvases, slots: slotsProp }) {
|
|
18240
|
+
const slots = slotsProp ?? getCategorySlots(node, theme);
|
|
18241
|
+
const regions = (0, import_react10.useMemo)(() => computeCategorySlotRegions(node, theme, slots), [node, theme, slots]);
|
|
18242
|
+
const reactId = (0, import_react10.useId)();
|
|
18243
|
+
const clipId = `sc-edge-clip-${reactId.replace(/:/g, "")}`;
|
|
18244
|
+
if (!slots)
|
|
18245
|
+
return null;
|
|
18246
|
+
const getSubCanvas = (ref) => canvases?.[ref];
|
|
18247
|
+
const entries = slotEntries(slots);
|
|
18248
|
+
if (entries.length === 0)
|
|
18249
|
+
return null;
|
|
18250
|
+
const edgeEntries = entries.filter(([p]) => isEdgePosition(p));
|
|
18251
|
+
const otherEntries = entries.filter(([p]) => !isEdgePosition(p));
|
|
18252
|
+
const renderEntry = ([position, spec]) => {
|
|
18253
|
+
const region = regions[position];
|
|
18254
|
+
const ctx = {
|
|
18255
|
+
node,
|
|
18256
|
+
theme,
|
|
18257
|
+
region,
|
|
18258
|
+
getSubCanvas,
|
|
18259
|
+
canvases,
|
|
18260
|
+
rollup: (predicate) => node.ref ? rollupNodes(getSubCanvas(node.ref), predicate) : { total: 0, matched: 0, fraction: 0 }
|
|
18261
|
+
};
|
|
18262
|
+
return (0, import_jsx_runtime9.jsx)(SlotView, { position, spec, ctx }, position);
|
|
18263
|
+
};
|
|
18264
|
+
return (0, import_jsx_runtime9.jsxs)("g", { className: "system-canvas-slots", pointerEvents: "none", children: [edgeEntries.length > 0 && (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [(0, import_jsx_runtime9.jsx)("defs", { children: (0, import_jsx_runtime9.jsx)("clipPath", { id: clipId, children: (0, import_jsx_runtime9.jsx)("rect", { x: node.x, y: node.y, width: node.width, height: node.height, rx: node.resolvedCornerRadius }) }) }), (0, import_jsx_runtime9.jsx)("g", { clipPath: `url(#${clipId})`, children: edgeEntries.map(renderEntry) })] }), otherEntries.map(renderEntry)] });
|
|
18265
|
+
}
|
|
18266
|
+
function isEdgePosition(p) {
|
|
18267
|
+
return p === "topEdge" || p === "bottomEdge" || p === "leftEdge" || p === "rightEdge";
|
|
18268
|
+
}
|
|
18269
|
+
function SlotView({ position, spec, ctx }) {
|
|
18270
|
+
try {
|
|
18271
|
+
return renderSlot(position, spec, ctx);
|
|
18272
|
+
} catch (err) {
|
|
18273
|
+
const env = globalThis.process?.env?.NODE_ENV;
|
|
18274
|
+
if (env !== "production") {
|
|
18275
|
+
console.warn("[system-canvas] slot render failed", position, err);
|
|
18276
|
+
}
|
|
18277
|
+
return null;
|
|
18278
|
+
}
|
|
18279
|
+
}
|
|
18280
|
+
function renderSlot(position, spec, ctx) {
|
|
18281
|
+
const { theme, node, region } = ctx;
|
|
18282
|
+
const nodeColor = node.resolvedStroke;
|
|
18283
|
+
switch (spec.kind) {
|
|
18284
|
+
case "color": {
|
|
18285
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18286
|
+
const length = resolveAccessorOr(spec.length, 0.55, ctx);
|
|
18287
|
+
return (0, import_jsx_runtime9.jsx)(NodeColorFill, { region, color: color2, position, extent: spec.extent, length });
|
|
18288
|
+
}
|
|
18289
|
+
case "progress": {
|
|
18290
|
+
const value = resolveAccessor(spec.value, ctx);
|
|
18291
|
+
if (spec.hideWhenZero && (!Number.isFinite(value) || value <= 0)) {
|
|
18292
|
+
return null;
|
|
18293
|
+
}
|
|
18294
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18295
|
+
const bgColor = resolveAccessorOr(spec.bgColor, "rgba(255,255,255,0.08)", ctx);
|
|
18296
|
+
return (0, import_jsx_runtime9.jsx)(NodeProgressBar, { region, value, color: color2, bgColor });
|
|
18297
|
+
}
|
|
18298
|
+
case "count": {
|
|
18299
|
+
const raw = resolveAccessor(spec.value, ctx);
|
|
18300
|
+
const hideWhenEmpty = spec.hideWhenEmpty !== false;
|
|
18301
|
+
if (hideWhenEmpty) {
|
|
18302
|
+
if (raw === 0 || raw === "" || raw == null)
|
|
18303
|
+
return null;
|
|
18304
|
+
}
|
|
18305
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18306
|
+
const textColor = resolveAccessorOr(spec.textColor, theme.background, ctx);
|
|
18307
|
+
return (0, import_jsx_runtime9.jsx)(NodeCountBadge, { region, value: raw, theme, color: color2, textColor, position });
|
|
18308
|
+
}
|
|
18309
|
+
case "pill": {
|
|
18310
|
+
const value = resolveAccessor(spec.value, ctx);
|
|
18311
|
+
if (!value)
|
|
18312
|
+
return null;
|
|
18313
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18314
|
+
const textColor = spec.textColor ? resolveAccessor(spec.textColor, ctx) : void 0;
|
|
18315
|
+
const fill = spec.fill ? resolveAccessor(spec.fill, ctx) : void 0;
|
|
18316
|
+
return (0, import_jsx_runtime9.jsx)(NodeStatusPill, { region, value, theme, color: color2, textColor, fill });
|
|
18317
|
+
}
|
|
18318
|
+
case "text": {
|
|
18319
|
+
const value = resolveAccessor(spec.value, ctx);
|
|
18320
|
+
const color2 = resolveAccessorOr(spec.color, position === "body" ? theme.node.labelColor : theme.node.sublabelColor, ctx);
|
|
18321
|
+
const defaultAlign = position === "header" || position === "footer" || position === "body" ? "start" : "center";
|
|
18322
|
+
const align = spec.align ?? defaultAlign;
|
|
18323
|
+
const isHeader = position === "header";
|
|
18324
|
+
const isBody = position === "body";
|
|
18325
|
+
const defaultWeight = isHeader ? 700 : isBody ? 600 : 500;
|
|
18326
|
+
const defaultUppercase = isHeader;
|
|
18327
|
+
const defaultUseLabelFont = isHeader || isBody;
|
|
18328
|
+
const defaultFontSize = isBody ? Math.round(theme.node.fontSize * 1.35) : void 0;
|
|
18329
|
+
const fontSize = spec.fontSize !== void 0 ? resolveAccessor(spec.fontSize, ctx) : defaultFontSize;
|
|
18330
|
+
const fontWeight = spec.fontWeight !== void 0 ? resolveAccessor(spec.fontWeight, ctx) : defaultWeight;
|
|
18331
|
+
const fontFamily = spec.fontFamily !== void 0 ? resolveAccessor(spec.fontFamily, ctx) : void 0;
|
|
18332
|
+
const wrap = spec.wrap ?? isBody;
|
|
18333
|
+
const lineHeight = spec.lineHeight !== void 0 ? resolveAccessor(spec.lineHeight, ctx) : void 0;
|
|
18334
|
+
const fill = spec.fill !== void 0 ? resolveAccessor(spec.fill, ctx) : void 0;
|
|
18335
|
+
return (0, import_jsx_runtime9.jsx)(NodeText, { region, value, theme, color: color2, fill, align, fontWeight, uppercase: spec.uppercase ?? defaultUppercase, useLabelFont: spec.useLabelFont ?? defaultUseLabelFont, fontFamily, fontSize, wrap, maxLines: spec.maxLines, lineHeight });
|
|
18336
|
+
}
|
|
18337
|
+
case "dot": {
|
|
18338
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18339
|
+
return (0, import_jsx_runtime9.jsx)(NodeDot, { region, color: color2 });
|
|
18340
|
+
}
|
|
18341
|
+
case "custom": {
|
|
18342
|
+
return spec.render(ctx);
|
|
18343
|
+
}
|
|
18344
|
+
}
|
|
18345
|
+
}
|
|
18346
|
+
|
|
18347
|
+
// ../react/dist/components/refCorner.js
|
|
18348
|
+
function toKebabCorner(c) {
|
|
18349
|
+
switch (c) {
|
|
18350
|
+
case "topLeft":
|
|
18351
|
+
return "top-left";
|
|
18352
|
+
case "topRight":
|
|
18353
|
+
return "top-right";
|
|
18354
|
+
case "bottomLeft":
|
|
18355
|
+
return "bottom-left";
|
|
18356
|
+
case "bottomRight":
|
|
18357
|
+
return "bottom-right";
|
|
18358
|
+
}
|
|
18359
|
+
}
|
|
18360
|
+
|
|
17630
18361
|
// ../react/dist/components/TextNode.js
|
|
17631
|
-
function TextNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18362
|
+
function TextNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "bottomRight" }) {
|
|
17632
18363
|
const { x, y, width, height } = node;
|
|
17633
|
-
const
|
|
18364
|
+
const contentX = x + reservedLeft;
|
|
18365
|
+
const contentY = y + reservedTop;
|
|
18366
|
+
const contentWidth = Math.max(0, width - reservedLeft - reservedRight);
|
|
18367
|
+
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
17634
18368
|
const text = node.text ?? "";
|
|
17635
18369
|
const lines = text.split("\n").filter(Boolean);
|
|
17636
18370
|
const mainLabel = lines[0] ?? node.id;
|
|
17637
18371
|
const sublabel = lines[1];
|
|
17638
|
-
const
|
|
18372
|
+
const hasBodySlot = slots?.body !== void 0;
|
|
18373
|
+
const hasHeader = reservedTop > 0;
|
|
18374
|
+
const labelFont = theme.node.labelFont ?? theme.node.fontFamily;
|
|
18375
|
+
const labelFontSize = theme.node.fontSize + (hasHeader ? 1 : 0);
|
|
18376
|
+
const lineHeight = labelFontSize + 4;
|
|
17639
18377
|
const totalTextHeight = sublabel ? lineHeight + theme.node.sublabelFontSize + 4 : lineHeight;
|
|
17640
|
-
const
|
|
17641
|
-
|
|
18378
|
+
const labelAnchor = hasHeader ? "start" : "middle";
|
|
18379
|
+
const labelX = hasHeader ? contentX : contentX + contentWidth / 2;
|
|
18380
|
+
const textStartY = hasHeader ? contentY + labelFontSize + 2 : contentY + (contentHeight - totalTextHeight) / 2 + labelFontSize;
|
|
18381
|
+
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)("text", { x: labelX, y: textStartY, fill: theme.node.labelColor, fontSize: labelFontSize, fontWeight: 600, fontFamily: labelFont, textAnchor: labelAnchor, pointerEvents: "none", children: mainLabel }), !isEditing && !hasBodySlot && sublabel && (0, import_jsx_runtime10.jsx)("text", { x: labelX, y: textStartY + lineHeight, fill: theme.node.sublabelColor, fontSize: theme.node.sublabelFontSize, fontFamily: theme.node.fontFamily, textAnchor: labelAnchor, pointerEvents: "none", children: sublabel }), 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 })] });
|
|
17642
18382
|
}
|
|
17643
18383
|
|
|
17644
18384
|
// ../react/dist/components/FileNode.js
|
|
17645
|
-
var
|
|
17646
|
-
function FileNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18385
|
+
var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
|
|
18386
|
+
function FileNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "bottomRight" }) {
|
|
17647
18387
|
const { x, y, width, height } = node;
|
|
17648
18388
|
const filePath = node.file ?? "";
|
|
17649
18389
|
const fileName = filePath.split("/").pop() ?? filePath;
|
|
17650
18390
|
const dirPath = filePath.includes("/") ? filePath.slice(0, filePath.lastIndexOf("/")) : "";
|
|
17651
18391
|
const subpath = node.subpath ?? "";
|
|
17652
18392
|
const fold = 10;
|
|
17653
|
-
const textPadding = 10;
|
|
17654
|
-
const maxTextWidth = width - textPadding
|
|
18393
|
+
const textPadding = 10 + reservedLeft;
|
|
18394
|
+
const maxTextWidth = width - textPadding - reservedRight - fold;
|
|
18395
|
+
const contentY = y + reservedTop;
|
|
18396
|
+
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
17655
18397
|
const shapePath = [
|
|
17656
18398
|
`M ${x + 2} ${y}`,
|
|
17657
18399
|
`L ${x + width - fold} ${y}`,
|
|
@@ -17668,35 +18410,41 @@ var SystemCanvas = (() => {
|
|
|
17668
18410
|
const strokeColor = node.resolvedStroke;
|
|
17669
18411
|
const thinStroke = 0.75;
|
|
17670
18412
|
const clipId = `file-clip-${node.id}`;
|
|
17671
|
-
return (0,
|
|
18413
|
+
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)("text", { x: x + textPadding, y: contentY + (dirPath ? 28 : contentHeight / 2 + (subpath ? -2 : 4)), fill: theme.node.labelColor, fontSize: theme.node.fontSize - 1, fontWeight: 500, fontFamily: theme.node.fontFamily, pointerEvents: "none", children: fileName }), 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 })] });
|
|
17672
18414
|
}
|
|
17673
18415
|
|
|
17674
18416
|
// ../react/dist/components/LinkNode.js
|
|
17675
|
-
var
|
|
17676
|
-
function LinkNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18417
|
+
var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
|
|
18418
|
+
function LinkNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "bottomRight" }) {
|
|
17677
18419
|
const { x, y, width, height } = node;
|
|
17678
|
-
const
|
|
18420
|
+
const contentX = x + reservedLeft;
|
|
18421
|
+
const contentY = y + reservedTop;
|
|
18422
|
+
const contentWidth = Math.max(0, width - reservedLeft - reservedRight);
|
|
18423
|
+
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
18424
|
+
const cx = contentX + contentWidth / 2;
|
|
17679
18425
|
let displayUrl = node.url ?? "";
|
|
17680
18426
|
try {
|
|
17681
18427
|
const url = new URL(displayUrl);
|
|
17682
18428
|
displayUrl = url.hostname;
|
|
17683
18429
|
} catch {
|
|
17684
18430
|
}
|
|
17685
|
-
return (0,
|
|
18431
|
+
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)("text", { x: cx, y: contentY + contentHeight / 2 + 4, fill: theme.node.labelColor, fontSize: theme.node.fontSize, fontWeight: 600, fontFamily: theme.node.fontFamily, textAnchor: "middle", pointerEvents: "none", textDecoration: "underline", children: displayUrl }), 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 })] });
|
|
17686
18432
|
}
|
|
17687
18433
|
|
|
17688
18434
|
// ../react/dist/components/GroupNode.js
|
|
17689
|
-
var
|
|
17690
|
-
function GroupNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18435
|
+
var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
18436
|
+
function GroupNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "topRight" }) {
|
|
17691
18437
|
const { x, y, width, height } = node;
|
|
17692
18438
|
const stroke = node.color ? node.resolvedStroke : theme.group.stroke;
|
|
17693
18439
|
const fill = node.color ? node.resolvedFill : theme.group.fill;
|
|
17694
|
-
|
|
18440
|
+
const labelX = x + 12 + reservedLeft;
|
|
18441
|
+
const labelY = y + reservedTop + theme.group.labelFontSize + 8;
|
|
18442
|
+
return (0, import_jsx_runtime13.jsxs)("g", { className: "system-canvas-node system-canvas-node--group", 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_runtime13.jsx)("rect", { x, y, width, height, rx: theme.group.cornerRadius, fill, stroke, strokeWidth: theme.group.strokeWidth, strokeDasharray: theme.group.strokeDasharray }), !isEditing && !slots?.body && node.label && (0, import_jsx_runtime13.jsx)("text", { x: labelX, y: labelY, fill: node.color ? stroke : theme.group.labelColor, fontSize: theme.group.labelFontSize, fontWeight: 600, fontFamily: theme.node.fontFamily, pointerEvents: "none", children: node.label }), slots && (0, import_jsx_runtime13.jsx)(CategorySlotsLayer, { node, theme, canvases, slots }), node.isNavigable && (0, import_jsx_runtime13.jsx)(RefIndicator, { node, theme, nodeX: x, nodeY: y, nodeWidth: width, nodeHeight: height, strokeColor: stroke, strokeWidth: theme.group.strokeWidth, corner: toKebabCorner(refCorner), onNavigate })] });
|
|
17695
18443
|
}
|
|
17696
18444
|
|
|
17697
18445
|
// ../react/dist/components/ResizeHandles.js
|
|
17698
|
-
var
|
|
17699
|
-
var
|
|
18446
|
+
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
18447
|
+
var import_react11 = __toESM(require_react(), 1);
|
|
17700
18448
|
var HANDLE_SIZE = 7;
|
|
17701
18449
|
var CORNERS = [
|
|
17702
18450
|
{ corner: "nw", cursor: "nwse-resize", anchor: "nw" },
|
|
@@ -17707,7 +18455,7 @@ var SystemCanvas = (() => {
|
|
|
17707
18455
|
var cornerInset = (cornerRadius) => Math.min(cornerRadius * 0.25, 3);
|
|
17708
18456
|
function ResizeHandles({ node, theme, onHandlePointerDown }) {
|
|
17709
18457
|
const { x, y, width, height } = node;
|
|
17710
|
-
const [hoveredCorner, setHoveredCorner] = (0,
|
|
18458
|
+
const [hoveredCorner, setHoveredCorner] = (0, import_react11.useState)(null);
|
|
17711
18459
|
const handleColor = node.resolvedStroke ?? theme.node.labelColor;
|
|
17712
18460
|
const i = cornerInset(node.resolvedCornerRadius);
|
|
17713
18461
|
const anchorPos = (anchor) => {
|
|
@@ -17722,36 +18470,54 @@ var SystemCanvas = (() => {
|
|
|
17722
18470
|
return { cx: x + width - i, cy: y + height - i };
|
|
17723
18471
|
}
|
|
17724
18472
|
};
|
|
17725
|
-
return (0,
|
|
18473
|
+
return (0, import_jsx_runtime14.jsx)("g", { className: "system-canvas-resize-handles", pointerEvents: "all", children: CORNERS.map(({ corner, cursor, anchor }) => {
|
|
17726
18474
|
const { cx, cy } = anchorPos(anchor);
|
|
17727
18475
|
const isHovered = hoveredCorner === corner;
|
|
17728
18476
|
const s = isHovered ? HANDLE_SIZE + 2 : HANDLE_SIZE;
|
|
17729
18477
|
const half = s / 2;
|
|
17730
|
-
return (0,
|
|
18478
|
+
return (0, import_jsx_runtime14.jsx)("rect", { x: cx - half, y: cy - half, width: s, height: s, fill: handleColor, style: { cursor }, onPointerEnter: () => setHoveredCorner(corner), onPointerLeave: () => setHoveredCorner((c) => c === corner ? null : c), onPointerDown: (e) => onHandlePointerDown(node, corner, e), onClick: (e) => e.stopPropagation(), onDoubleClick: (e) => e.stopPropagation() }, corner);
|
|
17731
18479
|
}) });
|
|
17732
18480
|
}
|
|
17733
18481
|
|
|
17734
18482
|
// ../react/dist/components/NodeRenderer.js
|
|
17735
|
-
function NodeRenderer({ nodes, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, selectedId, editingId, onResizeHandlePointerDown, only }) {
|
|
18483
|
+
function NodeRenderer({ nodes, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, selectedId, editingId, onResizeHandlePointerDown, canvases, only }) {
|
|
17736
18484
|
const groups = nodes.filter((n) => n.type === "group");
|
|
17737
18485
|
const others = nodes.filter((n) => n.type !== "group");
|
|
17738
|
-
const common = (node) =>
|
|
17739
|
-
node,
|
|
17740
|
-
theme,
|
|
17741
|
-
|
|
17742
|
-
|
|
17743
|
-
|
|
17744
|
-
|
|
17745
|
-
|
|
17746
|
-
|
|
17747
|
-
|
|
17748
|
-
|
|
18486
|
+
const common = (node) => {
|
|
18487
|
+
const slots = getCategorySlots(node, theme);
|
|
18488
|
+
const reservations = computeReflowReservations(node, theme, slots);
|
|
18489
|
+
const defaultCorner = node.type === "group" ? "topRight" : "bottomRight";
|
|
18490
|
+
const refCorner = pickRefIndicatorCorner(defaultCorner, slots);
|
|
18491
|
+
return {
|
|
18492
|
+
node,
|
|
18493
|
+
theme,
|
|
18494
|
+
onClick,
|
|
18495
|
+
onDoubleClick,
|
|
18496
|
+
onContextMenu,
|
|
18497
|
+
onNavigate,
|
|
18498
|
+
onPointerDown,
|
|
18499
|
+
isSelected: selectedId === node.id,
|
|
18500
|
+
isEditing: editingId === node.id,
|
|
18501
|
+
slots,
|
|
18502
|
+
canvases,
|
|
18503
|
+
reservedTop: reservations.top,
|
|
18504
|
+
reservedBottom: reservations.bottom,
|
|
18505
|
+
reservedLeft: reservations.left,
|
|
18506
|
+
reservedRight: reservations.right,
|
|
18507
|
+
refCorner
|
|
18508
|
+
};
|
|
18509
|
+
};
|
|
17749
18510
|
const selectedNode = selectedId && editingId !== selectedId ? nodes.find((n) => n.id === selectedId) : void 0;
|
|
17750
18511
|
const renderResizeHandles = only !== "groups" && selectedNode && onResizeHandlePointerDown;
|
|
17751
|
-
return (0,
|
|
18512
|
+
return (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [only !== "non-groups" && groups.map((node) => (0, import_jsx_runtime15.jsx)(GroupNode, { ...common(node) }, node.id)), only !== "groups" && others.map((node) => {
|
|
17752
18513
|
const Component = getNodeComponent(node.type);
|
|
17753
|
-
return (0,
|
|
17754
|
-
}), renderResizeHandles && (0,
|
|
18514
|
+
return (0, import_jsx_runtime15.jsx)(Component, { ...common(node) }, node.id);
|
|
18515
|
+
}), renderResizeHandles && (0, import_jsx_runtime15.jsx)(ResizeHandles, { node: selectedNode, theme, onHandlePointerDown: onResizeHandlePointerDown }), renderResizeHandles && (() => {
|
|
18516
|
+
const slots = getCategorySlots(selectedNode, theme);
|
|
18517
|
+
if (!slots?.topRightOuter)
|
|
18518
|
+
return null;
|
|
18519
|
+
return (0, import_jsx_runtime15.jsx)(CategorySlotsLayer, { node: selectedNode, theme, canvases, slots: { topRightOuter: slots.topRightOuter } });
|
|
18520
|
+
})()] });
|
|
17755
18521
|
}
|
|
17756
18522
|
function getNodeComponent(type) {
|
|
17757
18523
|
switch (type) {
|
|
@@ -17765,9 +18531,9 @@ var SystemCanvas = (() => {
|
|
|
17765
18531
|
}
|
|
17766
18532
|
|
|
17767
18533
|
// ../react/dist/components/EdgeRenderer.js
|
|
17768
|
-
var
|
|
18534
|
+
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
17769
18535
|
function EdgeRenderer({ edges, nodeMap, theme, defaultEdgeStyle, onClick, onDoubleClick, onContextMenu, selectedId, editingId }) {
|
|
17770
|
-
return (0,
|
|
18536
|
+
return (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [(0, import_jsx_runtime16.jsx)("defs", { children: (0, import_jsx_runtime16.jsx)("marker", { id: "system-canvas-arrowhead", markerWidth: theme.edge.arrowSize, markerHeight: theme.edge.arrowSize * 0.7, refX: theme.edge.arrowSize - 1, refY: theme.edge.arrowSize * 0.35, orient: "auto", markerUnits: "userSpaceOnUse", children: (0, import_jsx_runtime16.jsx)("polygon", { points: `0 0, ${theme.edge.arrowSize} ${theme.edge.arrowSize * 0.35}, 0 ${theme.edge.arrowSize * 0.7}`, fill: "context-stroke" }) }) }), [...edges].map((edge, i) => ({ edge, i })).sort((a, b) => {
|
|
17771
18537
|
const aSel = selectedId === a.edge.id ? 2 : 0;
|
|
17772
18538
|
const bSel = selectedId === b.edge.id ? 2 : 0;
|
|
17773
18539
|
const aCol = a.edge.color ? 1 : 0;
|
|
@@ -17792,20 +18558,36 @@ var SystemCanvas = (() => {
|
|
|
17792
18558
|
const toEnd = edge.toEnd ?? "arrow";
|
|
17793
18559
|
const fromEnd = edge.fromEnd ?? "none";
|
|
17794
18560
|
const arrowId = "system-canvas-arrowhead";
|
|
17795
|
-
return (0,
|
|
18561
|
+
return (0, import_jsx_runtime16.jsxs)("g", { className: "system-canvas-edge", style: { cursor: "pointer" }, onClick: (e) => onClick(edge, e), onDoubleClick: (e) => onDoubleClick?.(edge, e), onContextMenu: (e) => onContextMenu(edge, e), children: [(0, import_jsx_runtime16.jsx)("path", { d: pathD, fill: "none", stroke: "transparent", strokeWidth: 12 }), (0, import_jsx_runtime16.jsx)("path", { d: pathD, fill: "none", stroke: edgeColor, strokeWidth, markerEnd: toEnd === "arrow" ? `url(#${arrowId})` : void 0, markerStart: fromEnd === "arrow" ? `url(#${arrowId})` : void 0 }), edge.label && !isEditing && (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [(0, import_jsx_runtime16.jsx)("rect", { x: midpoint.x - edge.label.length * 3 - 4, y: midpoint.y - theme.edge.labelFontSize - 2, width: edge.label.length * 6 + 8, height: theme.edge.labelFontSize + 6, rx: 3, fill: theme.background, opacity: 0.8 }), (0, import_jsx_runtime16.jsx)("text", { x: midpoint.x, y: midpoint.y, fill: isSelected ? theme.node.labelColor : theme.edge.labelColor, fontSize: theme.edge.labelFontSize, fontFamily: theme.node.fontFamily, textAnchor: "middle", pointerEvents: "none", children: edge.label })] })] }, edge.id);
|
|
17796
18562
|
})] });
|
|
17797
18563
|
}
|
|
17798
18564
|
|
|
17799
18565
|
// ../react/dist/components/NodeEditor.js
|
|
17800
|
-
var
|
|
17801
|
-
var
|
|
18566
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
18567
|
+
var import_react12 = __toESM(require_react(), 1);
|
|
17802
18568
|
function NodeEditor({ node, theme, onCommit, onCancel }) {
|
|
18569
|
+
const editableFields = useCategoryFields(node, theme);
|
|
18570
|
+
if (editableFields) {
|
|
18571
|
+
return (0, import_jsx_runtime17.jsx)(FormEditor, { node, theme, fields: editableFields, onCommit, onCancel });
|
|
18572
|
+
}
|
|
18573
|
+
return (0, import_jsx_runtime17.jsx)(SingleFieldEditor, { node, theme, onCommit, onCancel });
|
|
18574
|
+
}
|
|
18575
|
+
function useCategoryFields(node, theme) {
|
|
18576
|
+
if (!node.category)
|
|
18577
|
+
return null;
|
|
18578
|
+
const def = theme.categories[node.category];
|
|
18579
|
+
const fields = def?.editableFields;
|
|
18580
|
+
if (!fields || fields.length === 0)
|
|
18581
|
+
return null;
|
|
18582
|
+
return fields;
|
|
18583
|
+
}
|
|
18584
|
+
function SingleFieldEditor({ node, theme, onCommit, onCancel }) {
|
|
17803
18585
|
const initial = getInitialValue(node);
|
|
17804
|
-
const [value, setValue] = (0,
|
|
17805
|
-
const textareaRef = (0,
|
|
17806
|
-
const inputRef = (0,
|
|
17807
|
-
const committedRef = (0,
|
|
17808
|
-
(0,
|
|
18586
|
+
const [value, setValue] = (0, import_react12.useState)(initial);
|
|
18587
|
+
const textareaRef = (0, import_react12.useRef)(null);
|
|
18588
|
+
const inputRef = (0, import_react12.useRef)(null);
|
|
18589
|
+
const committedRef = (0, import_react12.useRef)(false);
|
|
18590
|
+
(0, import_react12.useEffect)(() => {
|
|
17809
18591
|
const el = textareaRef.current ?? inputRef.current;
|
|
17810
18592
|
if (el) {
|
|
17811
18593
|
el.focus();
|
|
@@ -17821,7 +18603,7 @@ var SystemCanvas = (() => {
|
|
|
17821
18603
|
onCancel();
|
|
17822
18604
|
return;
|
|
17823
18605
|
}
|
|
17824
|
-
onCommit(
|
|
18606
|
+
onCommit(buildSingleFieldPatch(node, value));
|
|
17825
18607
|
};
|
|
17826
18608
|
const cancel = () => {
|
|
17827
18609
|
if (committedRef.current)
|
|
@@ -17850,7 +18632,7 @@ var SystemCanvas = (() => {
|
|
|
17850
18632
|
resize: "none",
|
|
17851
18633
|
textAlign: node.type === "text" ? "center" : "left"
|
|
17852
18634
|
};
|
|
17853
|
-
return (0,
|
|
18635
|
+
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) => {
|
|
17854
18636
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
17855
18637
|
e.preventDefault();
|
|
17856
18638
|
commit();
|
|
@@ -17858,7 +18640,7 @@ var SystemCanvas = (() => {
|
|
|
17858
18640
|
e.preventDefault();
|
|
17859
18641
|
cancel();
|
|
17860
18642
|
}
|
|
17861
|
-
}, style: commonFieldStyle }) : (0,
|
|
18643
|
+
}, style: commonFieldStyle }) : (0, import_jsx_runtime17.jsx)("input", { ref: inputRef, value, onChange: (e) => setValue(e.target.value), onBlur: commit, onKeyDown: (e) => {
|
|
17862
18644
|
if (e.key === "Enter") {
|
|
17863
18645
|
e.preventDefault();
|
|
17864
18646
|
commit();
|
|
@@ -17882,7 +18664,7 @@ var SystemCanvas = (() => {
|
|
|
17882
18664
|
return "";
|
|
17883
18665
|
}
|
|
17884
18666
|
}
|
|
17885
|
-
function
|
|
18667
|
+
function buildSingleFieldPatch(node, value) {
|
|
17886
18668
|
switch (node.type) {
|
|
17887
18669
|
case "text":
|
|
17888
18670
|
return { text: value };
|
|
@@ -17896,16 +18678,176 @@ var SystemCanvas = (() => {
|
|
|
17896
18678
|
return {};
|
|
17897
18679
|
}
|
|
17898
18680
|
}
|
|
18681
|
+
function FormEditor({ node, theme, fields, onCommit, onCancel }) {
|
|
18682
|
+
const initial = (0, import_react12.useMemo)(() => readInitialValues(node, fields), [node, fields]);
|
|
18683
|
+
const [values, setValues] = (0, import_react12.useState)(initial);
|
|
18684
|
+
const committedRef = (0, import_react12.useRef)(false);
|
|
18685
|
+
const panelRef = (0, import_react12.useRef)(null);
|
|
18686
|
+
const width = Math.max(node.width, 240);
|
|
18687
|
+
const height = Math.max(node.height, 36 + fields.length * 44);
|
|
18688
|
+
const commit = () => {
|
|
18689
|
+
if (committedRef.current)
|
|
18690
|
+
return;
|
|
18691
|
+
committedRef.current = true;
|
|
18692
|
+
const patch = buildFormPatch(node, fields, initial, values);
|
|
18693
|
+
if (!patch) {
|
|
18694
|
+
onCancel();
|
|
18695
|
+
return;
|
|
18696
|
+
}
|
|
18697
|
+
onCommit(patch);
|
|
18698
|
+
};
|
|
18699
|
+
const cancel = () => {
|
|
18700
|
+
if (committedRef.current)
|
|
18701
|
+
return;
|
|
18702
|
+
committedRef.current = true;
|
|
18703
|
+
onCancel();
|
|
18704
|
+
};
|
|
18705
|
+
const onBlurPanel = (e) => {
|
|
18706
|
+
const next = e.relatedTarget;
|
|
18707
|
+
if (next && panelRef.current?.contains(next))
|
|
18708
|
+
return;
|
|
18709
|
+
commit();
|
|
18710
|
+
};
|
|
18711
|
+
const stopPointer = (e) => {
|
|
18712
|
+
e.stopPropagation();
|
|
18713
|
+
};
|
|
18714
|
+
(0, import_react12.useEffect)(() => {
|
|
18715
|
+
const el = panelRef.current;
|
|
18716
|
+
if (!el)
|
|
18717
|
+
return;
|
|
18718
|
+
const first = el.querySelector("input, textarea, select, button");
|
|
18719
|
+
first?.focus();
|
|
18720
|
+
if (first instanceof HTMLInputElement && first.type === "text") {
|
|
18721
|
+
const end = first.value.length;
|
|
18722
|
+
first.setSelectionRange(end, end);
|
|
18723
|
+
}
|
|
18724
|
+
}, []);
|
|
18725
|
+
const fieldLabelColor = theme.node.sublabelColor;
|
|
18726
|
+
const inputStyle = {
|
|
18727
|
+
width: "100%",
|
|
18728
|
+
boxSizing: "border-box",
|
|
18729
|
+
padding: "6px 8px",
|
|
18730
|
+
fontFamily: theme.node.fontFamily,
|
|
18731
|
+
fontSize: theme.node.fontSize - 1,
|
|
18732
|
+
background: theme.background,
|
|
18733
|
+
color: theme.node.labelColor,
|
|
18734
|
+
border: `1px solid ${theme.breadcrumbs.separatorColor}`,
|
|
18735
|
+
borderRadius: 6,
|
|
18736
|
+
outline: "none"
|
|
18737
|
+
};
|
|
18738
|
+
return (0, import_jsx_runtime17.jsx)("foreignObject", { x: node.x, y: node.y, width, height, onPointerDown: stopPointer, onMouseDown: stopPointer, onClick: stopPointer, onDoubleClick: stopPointer, children: (0, import_jsx_runtime17.jsx)("div", { ref: panelRef, onBlur: onBlurPanel, onKeyDown: (e) => {
|
|
18739
|
+
if (e.key === "Escape") {
|
|
18740
|
+
e.preventDefault();
|
|
18741
|
+
cancel();
|
|
18742
|
+
} else if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
18743
|
+
e.preventDefault();
|
|
18744
|
+
commit();
|
|
18745
|
+
} else if (e.key === "Enter" && !(e.target instanceof HTMLTextAreaElement)) {
|
|
18746
|
+
e.preventDefault();
|
|
18747
|
+
const panel = panelRef.current;
|
|
18748
|
+
if (!panel)
|
|
18749
|
+
return;
|
|
18750
|
+
const focusables = Array.from(panel.querySelectorAll("input, textarea, select"));
|
|
18751
|
+
const idx = focusables.indexOf(e.target);
|
|
18752
|
+
if (idx === -1 || idx === focusables.length - 1)
|
|
18753
|
+
commit();
|
|
18754
|
+
else
|
|
18755
|
+
focusables[idx + 1].focus();
|
|
18756
|
+
}
|
|
18757
|
+
}, style: {
|
|
18758
|
+
width: "100%",
|
|
18759
|
+
boxSizing: "border-box",
|
|
18760
|
+
display: "flex",
|
|
18761
|
+
flexDirection: "column",
|
|
18762
|
+
gap: 8,
|
|
18763
|
+
padding: 10,
|
|
18764
|
+
background: theme.breadcrumbs.background,
|
|
18765
|
+
color: theme.node.labelColor,
|
|
18766
|
+
border: `1.5px solid ${theme.node.labelColor}`,
|
|
18767
|
+
borderRadius: node.resolvedCornerRadius,
|
|
18768
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.25)",
|
|
18769
|
+
backdropFilter: "blur(8px)",
|
|
18770
|
+
fontFamily: theme.node.fontFamily
|
|
18771
|
+
}, children: fields.map((field) => {
|
|
18772
|
+
const v = values[field.path];
|
|
18773
|
+
const setV = (next) => setValues((prev) => ({ ...prev, [field.path]: next }));
|
|
18774
|
+
const label = field.label ?? field.path;
|
|
18775
|
+
return (0, import_jsx_runtime17.jsxs)("label", { style: {
|
|
18776
|
+
display: "flex",
|
|
18777
|
+
flexDirection: "column",
|
|
18778
|
+
gap: 3,
|
|
18779
|
+
fontSize: 10,
|
|
18780
|
+
color: fieldLabelColor,
|
|
18781
|
+
textTransform: "uppercase",
|
|
18782
|
+
letterSpacing: 0.5
|
|
18783
|
+
}, children: [(0, import_jsx_runtime17.jsx)("span", { children: label }), renderControl(field, v, setV, inputStyle, theme)] }, field.path);
|
|
18784
|
+
}) }) });
|
|
18785
|
+
}
|
|
18786
|
+
function renderControl(field, value, setValue, inputStyle, theme) {
|
|
18787
|
+
switch (field.kind) {
|
|
18788
|
+
case "textarea":
|
|
18789
|
+
return (0, import_jsx_runtime17.jsx)("textarea", { value: value ?? "", onChange: (e) => setValue(e.target.value), placeholder: field.placeholder, rows: 3, style: { ...inputStyle, resize: "vertical", minHeight: 60 } });
|
|
18790
|
+
case "number":
|
|
18791
|
+
return (0, import_jsx_runtime17.jsx)("input", { type: "number", value: value == null ? "" : String(value), min: field.min, max: field.max, step: field.step, onChange: (e) => {
|
|
18792
|
+
const v = e.target.value;
|
|
18793
|
+
setValue(v === "" ? void 0 : Number(v));
|
|
18794
|
+
}, placeholder: field.placeholder, style: inputStyle });
|
|
18795
|
+
case "select":
|
|
18796
|
+
return (0, import_jsx_runtime17.jsxs)("select", { value: value ?? "", onChange: (e) => setValue(e.target.value), style: inputStyle, children: [!field.options?.some((o) => o.value === value) && (0, import_jsx_runtime17.jsx)("option", { value: "", children: "\u2014" }), field.options?.map((o) => (0, import_jsx_runtime17.jsx)("option", { value: o.value, children: o.label ?? o.value }, o.value))] });
|
|
18797
|
+
case "boolean":
|
|
18798
|
+
return (0, import_jsx_runtime17.jsx)("input", { type: "checkbox", checked: !!value, onChange: (e) => setValue(e.target.checked), style: {
|
|
18799
|
+
alignSelf: "flex-start",
|
|
18800
|
+
width: 16,
|
|
18801
|
+
height: 16,
|
|
18802
|
+
accentColor: theme.node.labelColor
|
|
18803
|
+
} });
|
|
18804
|
+
case "text":
|
|
18805
|
+
default:
|
|
18806
|
+
return (0, import_jsx_runtime17.jsx)("input", { type: "text", value: value ?? "", onChange: (e) => setValue(e.target.value), placeholder: field.placeholder, style: inputStyle });
|
|
18807
|
+
}
|
|
18808
|
+
}
|
|
18809
|
+
function readInitialValues(node, fields) {
|
|
18810
|
+
const out = {};
|
|
18811
|
+
for (const f of fields) {
|
|
18812
|
+
out[f.path] = getAtPath(node, f.path);
|
|
18813
|
+
}
|
|
18814
|
+
return out;
|
|
18815
|
+
}
|
|
18816
|
+
function buildFormPatch(node, fields, initial, current) {
|
|
18817
|
+
let changed = false;
|
|
18818
|
+
for (const f of fields) {
|
|
18819
|
+
if (current[f.path] !== initial[f.path]) {
|
|
18820
|
+
changed = true;
|
|
18821
|
+
break;
|
|
18822
|
+
}
|
|
18823
|
+
}
|
|
18824
|
+
if (!changed)
|
|
18825
|
+
return null;
|
|
18826
|
+
let working = { ...node };
|
|
18827
|
+
for (const f of fields) {
|
|
18828
|
+
working = setAtPath(working, f.path, current[f.path]);
|
|
18829
|
+
}
|
|
18830
|
+
const patch = {};
|
|
18831
|
+
const topKeys = /* @__PURE__ */ new Set();
|
|
18832
|
+
for (const f of fields) {
|
|
18833
|
+
topKeys.add(f.path.split(".")[0]);
|
|
18834
|
+
}
|
|
18835
|
+
for (const k of topKeys) {
|
|
18836
|
+
;
|
|
18837
|
+
patch[k] = working[k];
|
|
18838
|
+
}
|
|
18839
|
+
return patch;
|
|
18840
|
+
}
|
|
17899
18841
|
|
|
17900
18842
|
// ../react/dist/components/EdgeLabelEditor.js
|
|
17901
|
-
var
|
|
17902
|
-
var
|
|
18843
|
+
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
18844
|
+
var import_react13 = __toESM(require_react(), 1);
|
|
17903
18845
|
var EDITOR_WIDTH = 110;
|
|
17904
18846
|
function EdgeLabelEditor({ initialLabel, midpoint, theme, onCommit, onCancel }) {
|
|
17905
|
-
const [value, setValue] = (0,
|
|
17906
|
-
const inputRef = (0,
|
|
17907
|
-
const committedRef = (0,
|
|
17908
|
-
(0,
|
|
18847
|
+
const [value, setValue] = (0, import_react13.useState)(initialLabel);
|
|
18848
|
+
const inputRef = (0, import_react13.useRef)(null);
|
|
18849
|
+
const committedRef = (0, import_react13.useRef)(false);
|
|
18850
|
+
(0, import_react13.useEffect)(() => {
|
|
17909
18851
|
const el = inputRef.current;
|
|
17910
18852
|
if (el) {
|
|
17911
18853
|
el.focus();
|
|
@@ -17934,7 +18876,7 @@ var SystemCanvas = (() => {
|
|
|
17934
18876
|
};
|
|
17935
18877
|
const fontSize = theme.edge.labelFontSize;
|
|
17936
18878
|
const height = fontSize + 14;
|
|
17937
|
-
return (0,
|
|
18879
|
+
return (0, import_jsx_runtime18.jsx)("foreignObject", { x: midpoint.x - EDITOR_WIDTH / 2, y: midpoint.y - height / 2, width: EDITOR_WIDTH, height, onPointerDown: stopPointer, onMouseDown: stopPointer, onClick: stopPointer, onDoubleClick: stopPointer, children: (0, import_jsx_runtime18.jsx)("input", { ref: inputRef, value, onChange: (e) => setValue(e.target.value), onBlur: commit, onKeyDown: (e) => {
|
|
17938
18880
|
if (e.key === "Enter") {
|
|
17939
18881
|
e.preventDefault();
|
|
17940
18882
|
commit();
|
|
@@ -17959,8 +18901,8 @@ var SystemCanvas = (() => {
|
|
|
17959
18901
|
}
|
|
17960
18902
|
|
|
17961
18903
|
// ../react/dist/components/ConnectionHandles.js
|
|
17962
|
-
var
|
|
17963
|
-
var
|
|
18904
|
+
var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
|
|
18905
|
+
var import_react14 = __toESM(require_react(), 1);
|
|
17964
18906
|
var SIDES = ["top", "right", "bottom", "left"];
|
|
17965
18907
|
var HANDLE_RADIUS = 4;
|
|
17966
18908
|
var HANDLE_HIT_RADIUS = 10;
|
|
@@ -17969,9 +18911,9 @@ var SystemCanvas = (() => {
|
|
|
17969
18911
|
var HOVER_SCALE = 1.42;
|
|
17970
18912
|
var HOVER_TRANSITION_MS = 120;
|
|
17971
18913
|
function ConnectionHandles({ node, theme, onHandlePointerDown, immediate, activeSide }) {
|
|
17972
|
-
const [visible, setVisible] = (0,
|
|
17973
|
-
const [hoveredSide, setHoveredSide] = (0,
|
|
17974
|
-
(0,
|
|
18914
|
+
const [visible, setVisible] = (0, import_react14.useState)(!!immediate);
|
|
18915
|
+
const [hoveredSide, setHoveredSide] = (0, import_react14.useState)(null);
|
|
18916
|
+
(0, import_react14.useEffect)(() => {
|
|
17975
18917
|
if (immediate) {
|
|
17976
18918
|
setVisible(true);
|
|
17977
18919
|
return;
|
|
@@ -17982,16 +18924,16 @@ var SystemCanvas = (() => {
|
|
|
17982
18924
|
}, [node.id, immediate]);
|
|
17983
18925
|
const handleColor = node.resolvedStroke ?? theme.node.labelColor;
|
|
17984
18926
|
const sidesToRender = immediate ? SIDES : activeSide ? [activeSide] : [];
|
|
17985
|
-
return (0,
|
|
18927
|
+
return (0, import_jsx_runtime19.jsx)("g", { className: "system-canvas-connection-handles", pointerEvents: "auto", style: {
|
|
17986
18928
|
opacity: visible ? 1 : 0,
|
|
17987
18929
|
transition: `opacity ${FADE_DURATION_MS}ms ease-out`
|
|
17988
18930
|
}, children: sidesToRender.map((side) => {
|
|
17989
18931
|
const { x, y } = computeAnchorPoint(node, side);
|
|
17990
18932
|
const isHovered = hoveredSide === side;
|
|
17991
|
-
return (0,
|
|
18933
|
+
return (0, import_jsx_runtime19.jsxs)("g", { style: { cursor: "crosshair" }, onPointerEnter: () => setHoveredSide(side), onPointerLeave: () => setHoveredSide((s) => s === side ? null : s), onPointerDown: (e) => {
|
|
17992
18934
|
e.stopPropagation();
|
|
17993
18935
|
onHandlePointerDown(node, side, e);
|
|
17994
|
-
}, children: [(0,
|
|
18936
|
+
}, children: [(0, import_jsx_runtime19.jsx)("circle", { cx: x, cy: y, r: HANDLE_HIT_RADIUS, fill: "transparent" }), (0, import_jsx_runtime19.jsx)("circle", { cx: x, cy: y, r: HANDLE_RADIUS, fill: handleColor, pointerEvents: "none", style: {
|
|
17995
18937
|
// Scale around the handle's own center. CSS transforms on
|
|
17996
18938
|
// SVG elements use the element's user-space origin by
|
|
17997
18939
|
// default, so we set transform-origin explicitly.
|
|
@@ -18003,7 +18945,7 @@ var SystemCanvas = (() => {
|
|
|
18003
18945
|
}
|
|
18004
18946
|
|
|
18005
18947
|
// ../react/dist/components/PendingEdgeRenderer.js
|
|
18006
|
-
var
|
|
18948
|
+
var import_jsx_runtime20 = __toESM(require_jsx_runtime(), 1);
|
|
18007
18949
|
function PendingEdgeRenderer({ sourceNode, sourceSide, cursor, targetNode, theme, defaultEdgeStyle }) {
|
|
18008
18950
|
const endNode = targetNode ?? {
|
|
18009
18951
|
id: "__pending__",
|
|
@@ -18025,11 +18967,11 @@ var SystemCanvas = (() => {
|
|
|
18025
18967
|
toNode: endNode.id
|
|
18026
18968
|
};
|
|
18027
18969
|
const pathD = computeEdgePath(pendingEdge, sourceNode, endNode, defaultEdgeStyle);
|
|
18028
|
-
return (0,
|
|
18970
|
+
return (0, import_jsx_runtime20.jsxs)("g", { className: "system-canvas-pending-edge", pointerEvents: "none", children: [(0, import_jsx_runtime20.jsx)("path", { d: pathD, fill: "none", stroke: theme.node.labelColor, strokeWidth: theme.edge.strokeWidth * 1.25, strokeDasharray: "5,4", opacity: 0.85 }), !targetNode && (0, import_jsx_runtime20.jsx)("circle", { cx: cursor.x, cy: cursor.y, r: 4, fill: theme.background, stroke: theme.node.labelColor, strokeWidth: 1.5 })] });
|
|
18029
18971
|
}
|
|
18030
18972
|
|
|
18031
18973
|
// ../react/dist/components/LanesBackground.js
|
|
18032
|
-
var
|
|
18974
|
+
var import_jsx_runtime21 = __toESM(require_jsx_runtime(), 1);
|
|
18033
18975
|
var LANE_EXTENT = 1e5;
|
|
18034
18976
|
function LanesBackground({ columns, rows, theme }) {
|
|
18035
18977
|
const hasColumns = columns && columns.length > 0;
|
|
@@ -18044,31 +18986,31 @@ var SystemCanvas = (() => {
|
|
|
18044
18986
|
}
|
|
18045
18987
|
return index % 2 === 0 ? lanesTheme.bandFillEven : lanesTheme.bandFillOdd;
|
|
18046
18988
|
};
|
|
18047
|
-
return (0,
|
|
18989
|
+
return (0, import_jsx_runtime21.jsxs)("g", { className: "system-canvas-lanes", pointerEvents: "none", children: [hasRows && rows.map((row, i) => (0, import_jsx_runtime21.jsx)("rect", { x: -LANE_EXTENT, y: row.start, width: LANE_EXTENT * 2, height: row.size, fill: fillForLane(row, i) }, `row-${row.id}`)), hasColumns && columns.map((col, i) => (0, import_jsx_runtime21.jsx)("rect", { x: col.start, y: -LANE_EXTENT, width: col.size, height: LANE_EXTENT * 2, fill: fillForLane(col, i) }, `col-${col.id}`)), hasRows && rows.map((row, i) => {
|
|
18048
18990
|
if (i === 0)
|
|
18049
18991
|
return null;
|
|
18050
|
-
return (0,
|
|
18992
|
+
return (0, import_jsx_runtime21.jsx)("line", { x1: -LANE_EXTENT, y1: row.start, x2: LANE_EXTENT, y2: row.start, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth, vectorEffect: "non-scaling-stroke" }, `rowdiv-${row.id}`);
|
|
18051
18993
|
}), hasColumns && columns.map((col, i) => {
|
|
18052
18994
|
if (i === 0)
|
|
18053
18995
|
return null;
|
|
18054
|
-
return (0,
|
|
18996
|
+
return (0, import_jsx_runtime21.jsx)("line", { x1: col.start, y1: -LANE_EXTENT, x2: col.start, y2: LANE_EXTENT, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth, vectorEffect: "non-scaling-stroke" }, `coldiv-${col.id}`);
|
|
18055
18997
|
})] });
|
|
18056
18998
|
}
|
|
18057
18999
|
|
|
18058
19000
|
// ../react/dist/components/Viewport.js
|
|
18059
19001
|
var HOVER_PADDING = 10;
|
|
18060
19002
|
var EDGE_PROXIMITY = 16;
|
|
18061
|
-
var Viewport = (0,
|
|
19003
|
+
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) {
|
|
18062
19004
|
const { svgRef, groupRef, viewport, fitToContent, zoomToNode, setTransform } = useViewport({
|
|
18063
19005
|
minZoom,
|
|
18064
19006
|
maxZoom,
|
|
18065
19007
|
defaultViewport,
|
|
18066
19008
|
onViewportChange
|
|
18067
19009
|
});
|
|
18068
|
-
const navigatingRef = (0,
|
|
18069
|
-
const fadeRafRef = (0,
|
|
18070
|
-
const fadeTimeoutRef = (0,
|
|
18071
|
-
const triggerFade = (0,
|
|
19010
|
+
const navigatingRef = (0, import_react15.useRef)(false);
|
|
19011
|
+
const fadeRafRef = (0, import_react15.useRef)(null);
|
|
19012
|
+
const fadeTimeoutRef = (0, import_react15.useRef)(null);
|
|
19013
|
+
const triggerFade = (0, import_react15.useCallback)((durationMs) => {
|
|
18072
19014
|
if (durationMs <= 0)
|
|
18073
19015
|
return;
|
|
18074
19016
|
const g = groupRef.current;
|
|
@@ -18091,7 +19033,7 @@ var SystemCanvas = (() => {
|
|
|
18091
19033
|
}, durationMs + 16);
|
|
18092
19034
|
});
|
|
18093
19035
|
}, []);
|
|
18094
|
-
(0,
|
|
19036
|
+
(0, import_react15.useEffect)(() => {
|
|
18095
19037
|
return () => {
|
|
18096
19038
|
if (fadeRafRef.current !== null)
|
|
18097
19039
|
cancelAnimationFrame(fadeRafRef.current);
|
|
@@ -18099,9 +19041,9 @@ var SystemCanvas = (() => {
|
|
|
18099
19041
|
clearTimeout(fadeTimeoutRef.current);
|
|
18100
19042
|
};
|
|
18101
19043
|
}, []);
|
|
18102
|
-
const [hoveredNodeId, setHoveredNodeId] = (0,
|
|
18103
|
-
const [hoveredSide, setHoveredSide] = (0,
|
|
18104
|
-
(0,
|
|
19044
|
+
const [hoveredNodeId, setHoveredNodeId] = (0, import_react15.useState)(null);
|
|
19045
|
+
const [hoveredSide, setHoveredSide] = (0, import_react15.useState)(null);
|
|
19046
|
+
(0, import_react15.useImperativeHandle)(ref, () => ({
|
|
18105
19047
|
zoomToNode: (node, onComplete, options) => {
|
|
18106
19048
|
navigatingRef.current = true;
|
|
18107
19049
|
zoomToNode(node, onComplete, options);
|
|
@@ -18111,7 +19053,7 @@ var SystemCanvas = (() => {
|
|
|
18111
19053
|
getSvgElement: () => svgRef.current,
|
|
18112
19054
|
getViewport: () => viewport.current ?? { x: 0, y: 0, zoom: 1 }
|
|
18113
19055
|
}));
|
|
18114
|
-
const renderNodes = (0,
|
|
19056
|
+
const renderNodes = (0, import_react15.useMemo)(() => {
|
|
18115
19057
|
const hasDrag = dragOverrides && dragOverrides.size > 0;
|
|
18116
19058
|
const hasResize = resizeOverrides && resizeOverrides.size > 0;
|
|
18117
19059
|
if (!hasDrag && !hasResize)
|
|
@@ -18124,7 +19066,7 @@ var SystemCanvas = (() => {
|
|
|
18124
19066
|
return d ? { ...n, x: d.x, y: d.y } : n;
|
|
18125
19067
|
});
|
|
18126
19068
|
}, [nodes, dragOverrides, resizeOverrides]);
|
|
18127
|
-
const renderNodeMap = (0,
|
|
19069
|
+
const renderNodeMap = (0, import_react15.useMemo)(() => {
|
|
18128
19070
|
const hasDrag = dragOverrides && dragOverrides.size > 0;
|
|
18129
19071
|
const hasResize = resizeOverrides && resizeOverrides.size > 0;
|
|
18130
19072
|
if (!hasDrag && !hasResize)
|
|
@@ -18135,11 +19077,11 @@ var SystemCanvas = (() => {
|
|
|
18135
19077
|
}
|
|
18136
19078
|
return m;
|
|
18137
19079
|
}, [renderNodes, nodeMap, dragOverrides, resizeOverrides]);
|
|
18138
|
-
const latestNodesRef = (0,
|
|
18139
|
-
(0,
|
|
19080
|
+
const latestNodesRef = (0, import_react15.useRef)(nodes);
|
|
19081
|
+
(0, import_react15.useEffect)(() => {
|
|
18140
19082
|
latestNodesRef.current = nodes;
|
|
18141
19083
|
}, [nodes]);
|
|
18142
|
-
const fitNow = (0,
|
|
19084
|
+
const fitNow = (0, import_react15.useCallback)(() => {
|
|
18143
19085
|
const current = latestNodesRef.current;
|
|
18144
19086
|
if (current.length === 0)
|
|
18145
19087
|
return;
|
|
@@ -18149,7 +19091,7 @@ var SystemCanvas = (() => {
|
|
|
18149
19091
|
fitToContent(current, animate);
|
|
18150
19092
|
});
|
|
18151
19093
|
}, [fitToContent]);
|
|
18152
|
-
(0,
|
|
19094
|
+
(0, import_react15.useEffect)(() => {
|
|
18153
19095
|
if (defaultViewport)
|
|
18154
19096
|
return;
|
|
18155
19097
|
if (autoFit !== "always")
|
|
@@ -18158,8 +19100,8 @@ var SystemCanvas = (() => {
|
|
|
18158
19100
|
return;
|
|
18159
19101
|
fitNow();
|
|
18160
19102
|
}, [nodes, autoFit, defaultViewport, fitNow]);
|
|
18161
|
-
const fittedForRef = (0,
|
|
18162
|
-
(0,
|
|
19103
|
+
const fittedForRef = (0, import_react15.useRef)(null);
|
|
19104
|
+
(0, import_react15.useEffect)(() => {
|
|
18163
19105
|
if (defaultViewport)
|
|
18164
19106
|
return;
|
|
18165
19107
|
if (autoFit !== "canvas-change" && autoFit !== "initial")
|
|
@@ -18191,7 +19133,7 @@ var SystemCanvas = (() => {
|
|
|
18191
19133
|
triggerFade
|
|
18192
19134
|
]);
|
|
18193
19135
|
const editingNode = editingId ? renderNodes.find((n) => n.id === editingId) ?? null : null;
|
|
18194
|
-
const handleSvgPointerMove = (0,
|
|
19136
|
+
const handleSvgPointerMove = (0, import_react15.useCallback)((event) => {
|
|
18195
19137
|
if (!edgeCreateEnabled)
|
|
18196
19138
|
return;
|
|
18197
19139
|
const svg = svgRef.current;
|
|
@@ -18240,7 +19182,7 @@ var SystemCanvas = (() => {
|
|
|
18240
19182
|
setHoveredSide((prev) => prev === null ? prev : null);
|
|
18241
19183
|
}
|
|
18242
19184
|
}, [edgeCreateEnabled, renderNodes, svgRef, viewport]);
|
|
18243
|
-
const handleSvgPointerLeave = (0,
|
|
19185
|
+
const handleSvgPointerLeave = (0, import_react15.useCallback)(() => {
|
|
18244
19186
|
setHoveredNodeId(null);
|
|
18245
19187
|
setHoveredSide(null);
|
|
18246
19188
|
}, []);
|
|
@@ -18258,7 +19200,7 @@ var SystemCanvas = (() => {
|
|
|
18258
19200
|
return null;
|
|
18259
19201
|
return computeEdgeMidpoint(editingEdge, from, to);
|
|
18260
19202
|
})();
|
|
18261
|
-
return (0,
|
|
19203
|
+
return (0, import_jsx_runtime22.jsxs)("svg", { ref: svgRef, className: "system-canvas-viewport", style: {
|
|
18262
19204
|
width: "100%",
|
|
18263
19205
|
height: "100%",
|
|
18264
19206
|
display: "block",
|
|
@@ -18267,16 +19209,16 @@ var SystemCanvas = (() => {
|
|
|
18267
19209
|
WebkitUserSelect: "none",
|
|
18268
19210
|
MozUserSelect: "none",
|
|
18269
19211
|
msUserSelect: "none"
|
|
18270
|
-
}, onClick: onCanvasClick, onContextMenu: onCanvasContextMenu, onPointerMove: handleSvgPointerMove, onPointerLeave: handleSvgPointerLeave, children: [(0,
|
|
19212
|
+
}, 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 })] })] });
|
|
18271
19213
|
});
|
|
18272
19214
|
|
|
18273
19215
|
// ../react/dist/components/Breadcrumbs.js
|
|
18274
|
-
var
|
|
18275
|
-
var
|
|
19216
|
+
var import_jsx_runtime23 = __toESM(require_jsx_runtime(), 1);
|
|
19217
|
+
var import_react16 = __toESM(require_react(), 1);
|
|
18276
19218
|
function Breadcrumbs({ breadcrumbs, theme, onNavigate }) {
|
|
18277
19219
|
if (breadcrumbs.length <= 1)
|
|
18278
19220
|
return null;
|
|
18279
|
-
return (0,
|
|
19221
|
+
return (0, import_jsx_runtime23.jsx)("div", { className: "system-canvas-breadcrumbs", style: {
|
|
18280
19222
|
position: "absolute",
|
|
18281
19223
|
top: 12,
|
|
18282
19224
|
left: 12,
|
|
@@ -18293,10 +19235,10 @@ var SystemCanvas = (() => {
|
|
|
18293
19235
|
backdropFilter: "blur(8px)"
|
|
18294
19236
|
}, children: breadcrumbs.map((crumb, index) => {
|
|
18295
19237
|
const isLast = index === breadcrumbs.length - 1;
|
|
18296
|
-
return (0,
|
|
19238
|
+
return (0, import_jsx_runtime23.jsxs)(import_react16.default.Fragment, { children: [index > 0 && (0, import_jsx_runtime23.jsx)("span", { style: {
|
|
18297
19239
|
color: theme.separatorColor,
|
|
18298
19240
|
margin: "0 2px"
|
|
18299
|
-
}, children: "/" }), (0,
|
|
19241
|
+
}, children: "/" }), (0, import_jsx_runtime23.jsx)("span", { onClick: isLast ? void 0 : () => onNavigate(index), style: {
|
|
18300
19242
|
color: isLast ? theme.activeColor : theme.textColor,
|
|
18301
19243
|
cursor: isLast ? "default" : "pointer",
|
|
18302
19244
|
fontWeight: isLast ? 600 : 400,
|
|
@@ -18316,12 +19258,12 @@ var SystemCanvas = (() => {
|
|
|
18316
19258
|
}
|
|
18317
19259
|
|
|
18318
19260
|
// ../react/dist/components/AddNodeButton.js
|
|
18319
|
-
var
|
|
18320
|
-
var
|
|
19261
|
+
var import_jsx_runtime24 = __toESM(require_jsx_runtime(), 1);
|
|
19262
|
+
var import_react17 = __toESM(require_react(), 1);
|
|
18321
19263
|
function AddNodeButton({ options, addNode: addNode2, theme }) {
|
|
18322
|
-
const [open, setOpen] = (0,
|
|
18323
|
-
const rootRef = (0,
|
|
18324
|
-
(0,
|
|
19264
|
+
const [open, setOpen] = (0, import_react17.useState)(false);
|
|
19265
|
+
const rootRef = (0, import_react17.useRef)(null);
|
|
19266
|
+
(0, import_react17.useEffect)(() => {
|
|
18325
19267
|
if (!open)
|
|
18326
19268
|
return;
|
|
18327
19269
|
function onDocClick(e) {
|
|
@@ -18344,7 +19286,7 @@ var SystemCanvas = (() => {
|
|
|
18344
19286
|
}, [open]);
|
|
18345
19287
|
const categoryOptions = options.filter((o) => o.kind === "category");
|
|
18346
19288
|
const typeOptions = options.filter((o) => o.kind === "type");
|
|
18347
|
-
return (0,
|
|
19289
|
+
return (0, import_jsx_runtime24.jsxs)("div", { ref: rootRef, className: "system-canvas-add-node", style: {
|
|
18348
19290
|
position: "absolute",
|
|
18349
19291
|
bottom: 16,
|
|
18350
19292
|
right: 16,
|
|
@@ -18352,7 +19294,7 @@ var SystemCanvas = (() => {
|
|
|
18352
19294
|
fontFamily: theme.breadcrumbs.fontFamily,
|
|
18353
19295
|
fontSize: theme.breadcrumbs.fontSize,
|
|
18354
19296
|
userSelect: "none"
|
|
18355
|
-
}, children: [open && (0,
|
|
19297
|
+
}, children: [open && (0, import_jsx_runtime24.jsxs)("div", { style: {
|
|
18356
19298
|
position: "absolute",
|
|
18357
19299
|
bottom: 52,
|
|
18358
19300
|
right: 0,
|
|
@@ -18365,13 +19307,13 @@ var SystemCanvas = (() => {
|
|
|
18365
19307
|
borderRadius: 10,
|
|
18366
19308
|
boxShadow: "0 8px 24px rgba(0,0,0,0.35)",
|
|
18367
19309
|
backdropFilter: "blur(10px)"
|
|
18368
|
-
}, children: [categoryOptions.length > 0 && (0,
|
|
19310
|
+
}, children: [categoryOptions.length > 0 && (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [(0, import_jsx_runtime24.jsx)(SectionLabel, { theme, children: "Categories" }), categoryOptions.map((opt) => (0, import_jsx_runtime24.jsx)(MenuRow, { theme, option: opt, onClick: () => {
|
|
18369
19311
|
addNode2(opt);
|
|
18370
19312
|
setOpen(false);
|
|
18371
|
-
} }, `cat-${opt.value}`)), (0,
|
|
19313
|
+
} }, `cat-${opt.value}`)), (0, import_jsx_runtime24.jsx)(Divider, { theme })] }), (0, import_jsx_runtime24.jsx)(SectionLabel, { theme, children: "Basic" }), typeOptions.map((opt) => (0, import_jsx_runtime24.jsx)(MenuRow, { theme, option: opt, onClick: () => {
|
|
18372
19314
|
addNode2(opt);
|
|
18373
19315
|
setOpen(false);
|
|
18374
|
-
} }, `type-${opt.value}`))] }), (0,
|
|
19316
|
+
} }, `type-${opt.value}`))] }), (0, import_jsx_runtime24.jsx)("button", { type: "button", "aria-label": open ? "Close add node menu" : "Add node", onClick: () => setOpen((v) => !v), style: {
|
|
18375
19317
|
width: 44,
|
|
18376
19318
|
height: 44,
|
|
18377
19319
|
borderRadius: 22,
|
|
@@ -18392,7 +19334,7 @@ var SystemCanvas = (() => {
|
|
|
18392
19334
|
}, children: "+" })] });
|
|
18393
19335
|
}
|
|
18394
19336
|
function SectionLabel({ theme, children: children2 }) {
|
|
18395
|
-
return (0,
|
|
19337
|
+
return (0, import_jsx_runtime24.jsx)("div", { style: {
|
|
18396
19338
|
padding: "4px 8px",
|
|
18397
19339
|
fontSize: theme.breadcrumbs.fontSize - 2,
|
|
18398
19340
|
color: theme.breadcrumbs.textColor,
|
|
@@ -18402,7 +19344,7 @@ var SystemCanvas = (() => {
|
|
|
18402
19344
|
}, children: children2 });
|
|
18403
19345
|
}
|
|
18404
19346
|
function Divider({ theme }) {
|
|
18405
|
-
return (0,
|
|
19347
|
+
return (0, import_jsx_runtime24.jsx)("div", { style: {
|
|
18406
19348
|
height: 1,
|
|
18407
19349
|
margin: "4px 0",
|
|
18408
19350
|
background: theme.breadcrumbs.separatorColor,
|
|
@@ -18410,9 +19352,9 @@ var SystemCanvas = (() => {
|
|
|
18410
19352
|
} });
|
|
18411
19353
|
}
|
|
18412
19354
|
function MenuRow({ theme, option, onClick }) {
|
|
18413
|
-
const [hover, setHover] = (0,
|
|
19355
|
+
const [hover, setHover] = (0, import_react17.useState)(false);
|
|
18414
19356
|
const swatchSize = 18;
|
|
18415
|
-
return (0,
|
|
19357
|
+
return (0, import_jsx_runtime24.jsxs)("div", { role: "button", onClick, onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: {
|
|
18416
19358
|
display: "flex",
|
|
18417
19359
|
alignItems: "center",
|
|
18418
19360
|
gap: 8,
|
|
@@ -18421,7 +19363,7 @@ var SystemCanvas = (() => {
|
|
|
18421
19363
|
cursor: "pointer",
|
|
18422
19364
|
background: hover ? "rgba(255,255,255,0.06)" : "transparent",
|
|
18423
19365
|
color: theme.breadcrumbs.activeColor
|
|
18424
|
-
}, children: [option.kind === "category" ? (0,
|
|
19366
|
+
}, children: [option.kind === "category" ? (0, import_jsx_runtime24.jsx)("span", { style: {
|
|
18425
19367
|
width: swatchSize,
|
|
18426
19368
|
height: swatchSize,
|
|
18427
19369
|
borderRadius: 4,
|
|
@@ -18431,13 +19373,13 @@ var SystemCanvas = (() => {
|
|
|
18431
19373
|
alignItems: "center",
|
|
18432
19374
|
justifyContent: "center",
|
|
18433
19375
|
flexShrink: 0
|
|
18434
|
-
}, children: option.icon && (0,
|
|
19376
|
+
}, children: option.icon && (0, import_jsx_runtime24.jsx)("svg", { width: 12, height: 12, viewBox: "0 0 14 14", style: { overflow: "visible" }, children: (0, import_jsx_runtime24.jsx)("g", { transform: "translate(-1, -1)", children: (0, import_jsx_runtime24.jsx)(NodeIcon, { icon: option.icon, x: 0, y: 0, size: 14, color: option.stroke ?? theme.breadcrumbs.activeColor, opacity: 0.9, customIcons: theme.icons }) }) }) }) : (0, import_jsx_runtime24.jsx)("span", { style: {
|
|
18435
19377
|
width: swatchSize,
|
|
18436
19378
|
height: swatchSize,
|
|
18437
19379
|
borderRadius: 4,
|
|
18438
19380
|
border: `1px dashed ${theme.breadcrumbs.separatorColor}`,
|
|
18439
19381
|
flexShrink: 0
|
|
18440
|
-
} }), (0,
|
|
19382
|
+
} }), (0, import_jsx_runtime24.jsx)("span", { style: { textTransform: "capitalize" }, children: option.label }), (0, import_jsx_runtime24.jsx)("span", { style: {
|
|
18441
19383
|
marginLeft: "auto",
|
|
18442
19384
|
fontSize: theme.breadcrumbs.fontSize - 2,
|
|
18443
19385
|
opacity: 0.5
|
|
@@ -18445,13 +19387,13 @@ var SystemCanvas = (() => {
|
|
|
18445
19387
|
}
|
|
18446
19388
|
|
|
18447
19389
|
// ../react/dist/components/LaneHeaders.js
|
|
18448
|
-
var
|
|
18449
|
-
var
|
|
19390
|
+
var import_jsx_runtime25 = __toESM(require_jsx_runtime(), 1);
|
|
19391
|
+
var import_react18 = __toESM(require_react(), 1);
|
|
18450
19392
|
function LaneHeaders({ columns, rows, theme, getViewport, width, height, pinned = true }) {
|
|
18451
19393
|
const hasColumns = columns && columns.length > 0;
|
|
18452
19394
|
const hasRows = rows && rows.length > 0;
|
|
18453
|
-
const [viewport, setViewport] = (0,
|
|
18454
|
-
(0,
|
|
19395
|
+
const [viewport, setViewport] = (0, import_react18.useState)(() => getViewport());
|
|
19396
|
+
(0, import_react18.useEffect)(() => {
|
|
18455
19397
|
if (!hasColumns && !hasRows)
|
|
18456
19398
|
return;
|
|
18457
19399
|
let raf = 0;
|
|
@@ -18478,14 +19420,14 @@ var SystemCanvas = (() => {
|
|
|
18478
19420
|
const pad = lanesTheme.headerPadding;
|
|
18479
19421
|
const colsOffsetLeft = hasRows && pinned ? headerSize : 0;
|
|
18480
19422
|
const rowsOffsetTop = hasColumns && pinned ? headerSize : 0;
|
|
18481
|
-
return (0,
|
|
19423
|
+
return (0, import_jsx_runtime25.jsxs)("svg", { className: "system-canvas-lane-headers", style: {
|
|
18482
19424
|
position: "absolute",
|
|
18483
19425
|
top: 0,
|
|
18484
19426
|
left: 0,
|
|
18485
19427
|
width,
|
|
18486
19428
|
height,
|
|
18487
19429
|
pointerEvents: "none"
|
|
18488
|
-
}, children: [hasColumns && (0,
|
|
19430
|
+
}, children: [hasColumns && (0, import_jsx_runtime25.jsxs)("g", { children: [pinned && (0, import_jsx_runtime25.jsx)("rect", { x: colsOffsetLeft, y: 0, width: width - colsOffsetLeft, height: headerSize, fill: lanesTheme.headerBackground }), columns.map((col) => {
|
|
18489
19431
|
const startScreen = canvasToScreen(col.start, 0, viewport).x;
|
|
18490
19432
|
const endScreen = canvasToScreen(col.start + col.size, 0, viewport).x;
|
|
18491
19433
|
const w = endScreen - startScreen;
|
|
@@ -18496,8 +19438,8 @@ var SystemCanvas = (() => {
|
|
|
18496
19438
|
const cx = visibleLeft + visibleW / 2;
|
|
18497
19439
|
if (endScreen <= colsOffsetLeft || startScreen >= width)
|
|
18498
19440
|
return null;
|
|
18499
|
-
return (0,
|
|
18500
|
-
}), pinned && (0,
|
|
19441
|
+
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: truncateToWidth(col.label, visibleW - pad * 2, lanesTheme.headerFontSize) })] }, `colh-${col.id}`);
|
|
19442
|
+
}), 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) => {
|
|
18501
19443
|
const startScreen = canvasToScreen(0, row.start, viewport).y;
|
|
18502
19444
|
const endScreen = canvasToScreen(0, row.start + row.size, viewport).y;
|
|
18503
19445
|
const h = endScreen - startScreen;
|
|
@@ -18508,8 +19450,8 @@ var SystemCanvas = (() => {
|
|
|
18508
19450
|
const cy = visibleTop + visibleH / 2;
|
|
18509
19451
|
if (endScreen <= rowsOffsetTop || startScreen >= height)
|
|
18510
19452
|
return null;
|
|
18511
|
-
return (0,
|
|
18512
|
-
}), pinned && (0,
|
|
19453
|
+
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: truncateToWidth(row.label, visibleH - pad * 2, lanesTheme.headerFontSize) })] }, `rowh-${row.id}`);
|
|
19454
|
+
}), 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 })] });
|
|
18513
19455
|
}
|
|
18514
19456
|
function truncateToWidth(label, availablePx, fontSize) {
|
|
18515
19457
|
if (availablePx <= 0)
|
|
@@ -18524,8 +19466,8 @@ var SystemCanvas = (() => {
|
|
|
18524
19466
|
}
|
|
18525
19467
|
|
|
18526
19468
|
// ../react/dist/components/NodeToolbar.js
|
|
18527
|
-
var
|
|
18528
|
-
var
|
|
19469
|
+
var import_jsx_runtime26 = __toESM(require_jsx_runtime(), 1);
|
|
19470
|
+
var import_react19 = __toESM(require_react(), 1);
|
|
18529
19471
|
var NODE_GAP = 10;
|
|
18530
19472
|
var FLIP_MARGIN = 8;
|
|
18531
19473
|
var PADDING = 6;
|
|
@@ -18534,8 +19476,8 @@ var SystemCanvas = (() => {
|
|
|
18534
19476
|
var BUTTON_SIZE = 28;
|
|
18535
19477
|
var DELETE_SIZE = 14;
|
|
18536
19478
|
function NodeToolbar({ node, theme, onPatch, onDelete, getViewport, containerWidth, containerHeight, render: render2 }) {
|
|
18537
|
-
const [viewport, setViewport] = (0,
|
|
18538
|
-
(0,
|
|
19479
|
+
const [viewport, setViewport] = (0, import_react19.useState)(() => getViewport());
|
|
19480
|
+
(0, import_react19.useEffect)(() => {
|
|
18539
19481
|
let raf = 0;
|
|
18540
19482
|
let lastX = -Infinity;
|
|
18541
19483
|
let lastY = -Infinity;
|
|
@@ -18555,9 +19497,9 @@ var SystemCanvas = (() => {
|
|
|
18555
19497
|
}, [getViewport]);
|
|
18556
19498
|
const topCenter = canvasToScreen(node.x + node.width / 2, node.y, viewport);
|
|
18557
19499
|
const bottomCenter = canvasToScreen(node.x + node.width / 2, node.y + node.height, viewport);
|
|
18558
|
-
const toolbarRef = (0,
|
|
18559
|
-
const [size, setSize] = (0,
|
|
18560
|
-
(0,
|
|
19500
|
+
const toolbarRef = (0, import_react19.useRef)(null);
|
|
19501
|
+
const [size, setSize] = (0, import_react19.useState)({ width: 0, height: 0 });
|
|
19502
|
+
(0, import_react19.useEffect)(() => {
|
|
18561
19503
|
const el = toolbarRef.current;
|
|
18562
19504
|
if (!el)
|
|
18563
19505
|
return;
|
|
@@ -18578,7 +19520,7 @@ var SystemCanvas = (() => {
|
|
|
18578
19520
|
left = Math.max(FLIP_MARGIN, Math.min(left, containerWidth - size.width - FLIP_MARGIN));
|
|
18579
19521
|
const patch = (update) => onPatch(update);
|
|
18580
19522
|
const deleteNode = () => onDelete();
|
|
18581
|
-
return (0,
|
|
19523
|
+
return (0, import_jsx_runtime26.jsx)("div", {
|
|
18582
19524
|
ref: toolbarRef,
|
|
18583
19525
|
className: "system-canvas-node-toolbar",
|
|
18584
19526
|
// Stop pointer events from bubbling to the canvas (which would
|
|
@@ -18607,15 +19549,16 @@ var SystemCanvas = (() => {
|
|
|
18607
19549
|
userSelect: "none",
|
|
18608
19550
|
whiteSpace: "nowrap"
|
|
18609
19551
|
},
|
|
18610
|
-
children: render2 ? render2({ node, theme, patch, deleteNode }) : (0,
|
|
19552
|
+
children: render2 ? render2({ node, theme, patch, deleteNode }) : (0, import_jsx_runtime26.jsx)(DefaultToolbarContent, { node, theme, onPatch: patch, onDelete: deleteNode })
|
|
18611
19553
|
});
|
|
18612
19554
|
}
|
|
18613
19555
|
function DefaultToolbarContent({ node, theme, onPatch, onDelete }) {
|
|
18614
|
-
const groups = (0,
|
|
18615
|
-
|
|
19556
|
+
const groups = (0, import_react19.useMemo)(() => getNodeActionsForNode(node, theme), [node, theme]);
|
|
19557
|
+
const showDelete = !theme.hideToolbarDelete;
|
|
19558
|
+
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 })] })] });
|
|
18616
19559
|
}
|
|
18617
19560
|
function Divider2({ theme }) {
|
|
18618
|
-
return (0,
|
|
19561
|
+
return (0, import_jsx_runtime26.jsx)("div", { style: {
|
|
18619
19562
|
width: 1,
|
|
18620
19563
|
alignSelf: "stretch",
|
|
18621
19564
|
background: theme.breadcrumbs.separatorColor,
|
|
@@ -18628,23 +19571,23 @@ var SystemCanvas = (() => {
|
|
|
18628
19571
|
return null;
|
|
18629
19572
|
const kind = group.kind ?? "buttons";
|
|
18630
19573
|
if (kind === "menu") {
|
|
18631
|
-
return (0,
|
|
19574
|
+
return (0, import_jsx_runtime26.jsx)(MenuGroup, { group, actions, node, theme, onPatch });
|
|
18632
19575
|
}
|
|
18633
|
-
return (0,
|
|
19576
|
+
return (0, import_jsx_runtime26.jsx)("div", { title: group.label, style: { display: "flex", alignItems: "center", gap: BUTTON_GAP }, children: actions.map((action) => {
|
|
18634
19577
|
const handleClick = () => {
|
|
18635
19578
|
const patch = resolveActionPatch(action, node);
|
|
18636
19579
|
onPatch(patch);
|
|
18637
19580
|
};
|
|
18638
19581
|
const active = action.isActive?.(node) ?? false;
|
|
18639
19582
|
if (kind === "swatches") {
|
|
18640
|
-
return (0,
|
|
19583
|
+
return (0, import_jsx_runtime26.jsx)(SwatchButton, { action, active, theme, onClick: handleClick }, action.id);
|
|
18641
19584
|
}
|
|
18642
|
-
return (0,
|
|
19585
|
+
return (0, import_jsx_runtime26.jsx)(IconButton, { action, active, theme, onClick: handleClick }, action.id);
|
|
18643
19586
|
}) });
|
|
18644
19587
|
}
|
|
18645
19588
|
function SwatchButton({ action, active, theme, onClick }) {
|
|
18646
19589
|
const color2 = action.swatch ?? theme.node.labelColor;
|
|
18647
|
-
return (0,
|
|
19590
|
+
return (0, import_jsx_runtime26.jsx)("button", { type: "button", title: action.label, onClick, style: {
|
|
18648
19591
|
width: SWATCH_SIZE,
|
|
18649
19592
|
height: SWATCH_SIZE,
|
|
18650
19593
|
borderRadius: "50%",
|
|
@@ -18658,7 +19601,7 @@ var SystemCanvas = (() => {
|
|
|
18658
19601
|
}, onMouseDown: (e) => e.preventDefault() });
|
|
18659
19602
|
}
|
|
18660
19603
|
function IconButton({ action, active, theme, onClick }) {
|
|
18661
|
-
return (0,
|
|
19604
|
+
return (0, import_jsx_runtime26.jsx)("button", { type: "button", title: action.label, onClick, style: {
|
|
18662
19605
|
width: BUTTON_SIZE,
|
|
18663
19606
|
height: BUTTON_SIZE,
|
|
18664
19607
|
display: "inline-flex",
|
|
@@ -18671,17 +19614,17 @@ var SystemCanvas = (() => {
|
|
|
18671
19614
|
cursor: "pointer",
|
|
18672
19615
|
padding: 0,
|
|
18673
19616
|
outline: "none"
|
|
18674
|
-
}, onMouseDown: (e) => e.preventDefault(), children: action.icon ? (0,
|
|
19617
|
+
}, onMouseDown: (e) => e.preventDefault(), children: action.icon ? (0, import_jsx_runtime26.jsx)("svg", { width: 16, height: 16, viewBox: "0 0 16 16", children: (0, import_jsx_runtime26.jsx)(NodeIcon, { icon: action.icon, x: 0, y: 0, size: 16, color: active ? theme.breadcrumbs.activeColor : theme.breadcrumbs.textColor, opacity: 1, customIcons: theme.icons }) }) : action.swatch ? (0, import_jsx_runtime26.jsx)("span", { style: {
|
|
18675
19618
|
width: 10,
|
|
18676
19619
|
height: 10,
|
|
18677
19620
|
borderRadius: "50%",
|
|
18678
19621
|
background: action.swatch
|
|
18679
|
-
} }) : (0,
|
|
19622
|
+
} }) : (0, import_jsx_runtime26.jsx)("span", { style: { fontSize: 10 }, children: action.label.slice(0, 2) }) });
|
|
18680
19623
|
}
|
|
18681
19624
|
function MenuGroup({ group, actions, node, theme, onPatch }) {
|
|
18682
|
-
const [open, setOpen] = (0,
|
|
18683
|
-
const wrapRef = (0,
|
|
18684
|
-
(0,
|
|
19625
|
+
const [open, setOpen] = (0, import_react19.useState)(false);
|
|
19626
|
+
const wrapRef = (0, import_react19.useRef)(null);
|
|
19627
|
+
(0, import_react19.useEffect)(() => {
|
|
18685
19628
|
if (!open)
|
|
18686
19629
|
return;
|
|
18687
19630
|
const onDown = (e) => {
|
|
@@ -18694,7 +19637,7 @@ var SystemCanvas = (() => {
|
|
|
18694
19637
|
const active = actions.find((a) => a.isActive?.(node));
|
|
18695
19638
|
const triggerLabel = active?.label ?? group.label ?? "Menu";
|
|
18696
19639
|
const triggerIcon = active?.icon ?? void 0;
|
|
18697
|
-
return (0,
|
|
19640
|
+
return (0, import_jsx_runtime26.jsxs)("div", { ref: wrapRef, style: { position: "relative" }, children: [(0, import_jsx_runtime26.jsxs)("button", { type: "button", title: group.label, onClick: () => setOpen((v) => !v), style: {
|
|
18698
19641
|
height: BUTTON_SIZE,
|
|
18699
19642
|
display: "inline-flex",
|
|
18700
19643
|
alignItems: "center",
|
|
@@ -18708,7 +19651,7 @@ var SystemCanvas = (() => {
|
|
|
18708
19651
|
fontFamily: "inherit",
|
|
18709
19652
|
fontSize: "inherit",
|
|
18710
19653
|
outline: "none"
|
|
18711
|
-
}, onMouseDown: (e) => e.preventDefault(), children: [triggerIcon && (0,
|
|
19654
|
+
}, onMouseDown: (e) => e.preventDefault(), children: [triggerIcon && (0, import_jsx_runtime26.jsx)("svg", { width: 14, height: 14, viewBox: "0 0 16 16", children: (0, import_jsx_runtime26.jsx)(NodeIcon, { icon: triggerIcon, x: 0, y: 0, size: 14, color: theme.breadcrumbs.textColor, opacity: 1, customIcons: theme.icons }) }), (0, import_jsx_runtime26.jsx)("span", { children: triggerLabel }), (0, import_jsx_runtime26.jsx)("span", { style: { opacity: 0.6, fontSize: 8 }, children: "\u25BE" })] }), open && (0, import_jsx_runtime26.jsx)("div", { style: {
|
|
18712
19655
|
position: "absolute",
|
|
18713
19656
|
top: "100%",
|
|
18714
19657
|
left: 0,
|
|
@@ -18723,7 +19666,7 @@ var SystemCanvas = (() => {
|
|
|
18723
19666
|
zIndex: 1
|
|
18724
19667
|
}, children: actions.map((action) => {
|
|
18725
19668
|
const isActive = action.isActive?.(node) ?? false;
|
|
18726
|
-
return (0,
|
|
19669
|
+
return (0, import_jsx_runtime26.jsxs)("button", { type: "button", onClick: () => {
|
|
18727
19670
|
onPatch(resolveActionPatch(action, node));
|
|
18728
19671
|
setOpen(false);
|
|
18729
19672
|
}, style: {
|
|
@@ -18740,17 +19683,17 @@ var SystemCanvas = (() => {
|
|
|
18740
19683
|
fontFamily: "inherit",
|
|
18741
19684
|
fontSize: "inherit",
|
|
18742
19685
|
textAlign: "left"
|
|
18743
|
-
}, onMouseDown: (e) => e.preventDefault(), children: [action.icon && (0,
|
|
19686
|
+
}, onMouseDown: (e) => e.preventDefault(), children: [action.icon && (0, import_jsx_runtime26.jsx)("svg", { width: 14, height: 14, viewBox: "0 0 16 16", children: (0, import_jsx_runtime26.jsx)(NodeIcon, { icon: action.icon, x: 0, y: 0, size: 14, color: isActive ? theme.breadcrumbs.activeColor : theme.breadcrumbs.textColor, opacity: 1, customIcons: theme.icons }) }), action.swatch && (0, import_jsx_runtime26.jsx)("span", { style: {
|
|
18744
19687
|
width: 10,
|
|
18745
19688
|
height: 10,
|
|
18746
19689
|
borderRadius: "50%",
|
|
18747
19690
|
background: action.swatch,
|
|
18748
19691
|
flexShrink: 0
|
|
18749
|
-
} }), (0,
|
|
19692
|
+
} }), (0, import_jsx_runtime26.jsx)("span", { children: action.label })] }, action.id);
|
|
18750
19693
|
}) })] });
|
|
18751
19694
|
}
|
|
18752
19695
|
function DeleteButton({ theme, onDelete }) {
|
|
18753
|
-
return (0,
|
|
19696
|
+
return (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Delete", onClick: onDelete, onMouseDown: (e) => e.preventDefault(), style: {
|
|
18754
19697
|
width: BUTTON_SIZE,
|
|
18755
19698
|
height: BUTTON_SIZE,
|
|
18756
19699
|
display: "inline-flex",
|
|
@@ -18763,21 +19706,21 @@ var SystemCanvas = (() => {
|
|
|
18763
19706
|
cursor: "pointer",
|
|
18764
19707
|
padding: 0,
|
|
18765
19708
|
outline: "none"
|
|
18766
|
-
}, children: (0,
|
|
19709
|
+
}, 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" }) }) });
|
|
18767
19710
|
}
|
|
18768
19711
|
|
|
18769
19712
|
// ../react/dist/components/SystemCanvas.js
|
|
18770
19713
|
var CASCADE_WINDOW_MS = 1500;
|
|
18771
19714
|
var CASCADE_OFFSET = 20;
|
|
18772
|
-
var SystemCanvas = (0,
|
|
18773
|
-
const zoomNavConfig = (0,
|
|
19715
|
+
var SystemCanvas = (0, import_react20.forwardRef)(function SystemCanvas2({ canvas, onResolveCanvas, canvases, rootLabel = "Home", onNavigate, onBreadcrumbClick, onNodeClick, onNodeDoubleClick, onEdgeClick, onEdgeDoubleClick, onContextMenu, editable = false, onNodeAdd, onNodeUpdate, onNodeDelete, onEdgeUpdate, onEdgeDelete, onEdgeAdd, 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) {
|
|
19716
|
+
const zoomNavConfig = (0, import_react20.useMemo)(() => {
|
|
18774
19717
|
const defaults = {
|
|
18775
19718
|
enterThreshold: 0.66,
|
|
18776
19719
|
exitThreshold: 0.33,
|
|
18777
19720
|
prefetchThreshold: 0.4,
|
|
18778
19721
|
landingScale: 1.2,
|
|
18779
19722
|
landingPadding: 0.08,
|
|
18780
|
-
fadeDuration:
|
|
19723
|
+
fadeDuration: 216
|
|
18781
19724
|
};
|
|
18782
19725
|
if (!zoomNavigation)
|
|
18783
19726
|
return { enabled: false, ...defaults };
|
|
@@ -18795,16 +19738,16 @@ var SystemCanvas = (() => {
|
|
|
18795
19738
|
}, [zoomNavigation]);
|
|
18796
19739
|
const effectiveMaxZoom = maxZoom ?? (zoomNavConfig.enabled ? 16 : 4);
|
|
18797
19740
|
const effectiveMinZoom = minZoomProp ?? (zoomNavConfig.enabled ? 0.01 : 0.1);
|
|
18798
|
-
(0,
|
|
19741
|
+
(0, import_react20.useEffect)(() => {
|
|
18799
19742
|
const env = globalThis.process?.env?.NODE_ENV;
|
|
18800
19743
|
if (editable && !canvases && env !== "production") {
|
|
18801
19744
|
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.");
|
|
18802
19745
|
}
|
|
18803
19746
|
}, [editable, canvases]);
|
|
18804
|
-
const [parentFrames, setParentFrames] = (0,
|
|
18805
|
-
const [pendingHandoff, setPendingHandoff] = (0,
|
|
18806
|
-
const suppressNextHandoffClearRef = (0,
|
|
18807
|
-
const handleBreadcrumbClick = (0,
|
|
19747
|
+
const [parentFrames, setParentFrames] = (0, import_react20.useState)([]);
|
|
19748
|
+
const [pendingHandoff, setPendingHandoff] = (0, import_react20.useState)(null);
|
|
19749
|
+
const suppressNextHandoffClearRef = (0, import_react20.useRef)(false);
|
|
19750
|
+
const handleBreadcrumbClick = (0, import_react20.useCallback)((index) => {
|
|
18808
19751
|
setParentFrames((prev) => prev.slice(0, index));
|
|
18809
19752
|
if (suppressNextHandoffClearRef.current) {
|
|
18810
19753
|
suppressNextHandoffClearRef.current = false;
|
|
@@ -18821,7 +19764,7 @@ var SystemCanvas = (() => {
|
|
|
18821
19764
|
onNavigate,
|
|
18822
19765
|
onBreadcrumbClick: handleBreadcrumbClick
|
|
18823
19766
|
});
|
|
18824
|
-
const theme = (0,
|
|
19767
|
+
const theme = (0, import_react20.useMemo)(() => {
|
|
18825
19768
|
const registry = { ...themes, ...customThemes };
|
|
18826
19769
|
const resolveByName = (name) => name && registry[name] ? registry[name] : null;
|
|
18827
19770
|
if (themeProp) {
|
|
@@ -18832,22 +19775,22 @@ var SystemCanvas = (() => {
|
|
|
18832
19775
|
}
|
|
18833
19776
|
return resolveByName(currentCanvas.theme?.base) ?? resolveByName(canvas.theme?.base) ?? darkTheme;
|
|
18834
19777
|
}, [themeProp, customThemes, currentCanvas.theme?.base, canvas.theme?.base]);
|
|
18835
|
-
const { nodes, edges, nodeMap } = (0,
|
|
19778
|
+
const { nodes, edges, nodeMap } = (0, import_react20.useMemo)(() => {
|
|
18836
19779
|
const resolved = resolveCanvas(currentCanvas, theme);
|
|
18837
19780
|
const map = buildNodeMap(resolved.nodes);
|
|
18838
19781
|
return { nodes: resolved.nodes, edges: resolved.edges, nodeMap: map };
|
|
18839
19782
|
}, [currentCanvas, theme]);
|
|
18840
|
-
const nodesRef = (0,
|
|
19783
|
+
const nodesRef = (0, import_react20.useRef)(nodes);
|
|
18841
19784
|
nodesRef.current = nodes;
|
|
18842
|
-
const viewportStateRef = (0,
|
|
18843
|
-
const viewportHandleRef = (0,
|
|
18844
|
-
const navigateToRefRef = (0,
|
|
19785
|
+
const viewportStateRef = (0, import_react20.useRef)(defaultViewport ?? { x: 0, y: 0, zoom: 1 });
|
|
19786
|
+
const viewportHandleRef = (0, import_react20.useRef)(null);
|
|
19787
|
+
const navigateToRefRef = (0, import_react20.useRef)(navigateToRef);
|
|
18845
19788
|
navigateToRefRef.current = navigateToRef;
|
|
18846
|
-
const navigateToBreadcrumbRef = (0,
|
|
19789
|
+
const navigateToBreadcrumbRef = (0, import_react20.useRef)(navigateToBreadcrumb);
|
|
18847
19790
|
navigateToBreadcrumbRef.current = navigateToBreadcrumb;
|
|
18848
|
-
const breadcrumbsRef = (0,
|
|
19791
|
+
const breadcrumbsRef = (0, import_react20.useRef)(breadcrumbs);
|
|
18849
19792
|
breadcrumbsRef.current = breadcrumbs;
|
|
18850
|
-
(0,
|
|
19793
|
+
(0, import_react20.useImperativeHandle)(forwardedRef, () => ({
|
|
18851
19794
|
zoomIntoNode: (nodeId, options) => {
|
|
18852
19795
|
return new Promise((resolve) => {
|
|
18853
19796
|
const node = nodesRef.current.find((n) => n.id === nodeId);
|
|
@@ -18879,19 +19822,19 @@ var SystemCanvas = (() => {
|
|
|
18879
19822
|
navigateToBreadcrumbRef.current(0);
|
|
18880
19823
|
}
|
|
18881
19824
|
}), [forwardedRef]);
|
|
18882
|
-
const [selectedId, setSelectedId] = (0,
|
|
18883
|
-
const [editingId, setEditingId] = (0,
|
|
18884
|
-
const [selectedEdgeId, setSelectedEdgeId] = (0,
|
|
18885
|
-
const [editingEdgeId, setEditingEdgeId] = (0,
|
|
18886
|
-
(0,
|
|
19825
|
+
const [selectedId, setSelectedId] = (0, import_react20.useState)(null);
|
|
19826
|
+
const [editingId, setEditingId] = (0, import_react20.useState)(null);
|
|
19827
|
+
const [selectedEdgeId, setSelectedEdgeId] = (0, import_react20.useState)(null);
|
|
19828
|
+
const [editingEdgeId, setEditingEdgeId] = (0, import_react20.useState)(null);
|
|
19829
|
+
(0, import_react20.useEffect)(() => {
|
|
18887
19830
|
setSelectedId(null);
|
|
18888
19831
|
setEditingId(null);
|
|
18889
19832
|
setSelectedEdgeId(null);
|
|
18890
19833
|
setEditingEdgeId(null);
|
|
18891
19834
|
}, [currentCanvasRef]);
|
|
18892
|
-
const containerRef = (0,
|
|
18893
|
-
const [containerSize, setContainerSize] = (0,
|
|
18894
|
-
(0,
|
|
19835
|
+
const containerRef = (0, import_react20.useRef)(null);
|
|
19836
|
+
const [containerSize, setContainerSize] = (0, import_react20.useState)({ width: 0, height: 0 });
|
|
19837
|
+
(0, import_react20.useEffect)(() => {
|
|
18895
19838
|
const el = containerRef.current;
|
|
18896
19839
|
if (!el)
|
|
18897
19840
|
return;
|
|
@@ -18906,19 +19849,28 @@ var SystemCanvas = (() => {
|
|
|
18906
19849
|
}, []);
|
|
18907
19850
|
const hasLanes = currentCanvas.columns && currentCanvas.columns.length > 0 || currentCanvas.rows && currentCanvas.rows.length > 0;
|
|
18908
19851
|
const showLaneHeaders = hasLanes && laneHeaders !== "none";
|
|
18909
|
-
const getViewportState = (0,
|
|
18910
|
-
const commitDrag = (0,
|
|
19852
|
+
const getViewportState = (0, import_react20.useCallback)(() => viewportStateRef.current ?? { x: 0, y: 0, zoom: 1 }, []);
|
|
19853
|
+
const commitDrag = (0, import_react20.useCallback)((id2, patch) => {
|
|
18911
19854
|
let final = patch;
|
|
18912
19855
|
if (snapToLanes) {
|
|
18913
19856
|
const cols = currentCanvas.columns;
|
|
18914
19857
|
const rows = currentCanvas.rows;
|
|
19858
|
+
const node = nodesRef.current.find((n) => n.id === id2);
|
|
18915
19859
|
const nx = patch.x;
|
|
18916
19860
|
const ny = patch.y;
|
|
18917
19861
|
if (cols && cols.length > 0 && nx != null) {
|
|
18918
|
-
|
|
19862
|
+
const snapped = snapToLane(nx, cols, {
|
|
19863
|
+
edge: "center",
|
|
19864
|
+
size: node?.width ?? 0
|
|
19865
|
+
});
|
|
19866
|
+
final = { ...final, x: Math.round(snapped) };
|
|
18919
19867
|
}
|
|
18920
19868
|
if (rows && rows.length > 0 && ny != null) {
|
|
18921
|
-
|
|
19869
|
+
const snapped = snapToLane(ny, rows, {
|
|
19870
|
+
edge: "center",
|
|
19871
|
+
size: node?.height ?? 0
|
|
19872
|
+
});
|
|
19873
|
+
final = { ...final, y: Math.round(snapped) };
|
|
18922
19874
|
}
|
|
18923
19875
|
}
|
|
18924
19876
|
onNodeUpdate?.(id2, final, currentCanvasRef);
|
|
@@ -18932,7 +19884,7 @@ var SystemCanvas = (() => {
|
|
|
18932
19884
|
viewport: viewportStateRef,
|
|
18933
19885
|
onCommit: commitDrag
|
|
18934
19886
|
});
|
|
18935
|
-
const selectedResolvedNode = (0,
|
|
19887
|
+
const selectedResolvedNode = (0, import_react20.useMemo)(() => {
|
|
18936
19888
|
if (!selectedId)
|
|
18937
19889
|
return null;
|
|
18938
19890
|
const base = nodeMap.get(selectedId);
|
|
@@ -18948,9 +19900,9 @@ var SystemCanvas = (() => {
|
|
|
18948
19900
|
}
|
|
18949
19901
|
return base;
|
|
18950
19902
|
}, [selectedId, nodeMap, dragOverrides, resizeOverrides]);
|
|
18951
|
-
const svgProxyRef = (0,
|
|
19903
|
+
const svgProxyRef = (0, import_react20.useRef)(null);
|
|
18952
19904
|
svgProxyRef.current = viewportHandleRef.current?.getSvgElement() ?? null;
|
|
18953
|
-
const handleEdgeCreated = (0,
|
|
19905
|
+
const handleEdgeCreated = (0, import_react20.useCallback)((edge) => {
|
|
18954
19906
|
onEdgeAdd?.(edge, currentCanvasRef);
|
|
18955
19907
|
}, [onEdgeAdd, currentCanvasRef]);
|
|
18956
19908
|
const { pending: pendingEdge, onHandlePointerDown: onConnectionHandlePointerDown } = useEdgeCreate({
|
|
@@ -18959,7 +19911,7 @@ var SystemCanvas = (() => {
|
|
|
18959
19911
|
nodesRef,
|
|
18960
19912
|
onCreate: handleEdgeCreated
|
|
18961
19913
|
});
|
|
18962
|
-
const handleNavigableNodeClick = (0,
|
|
19914
|
+
const handleNavigableNodeClick = (0, import_react20.useCallback)((node) => {
|
|
18963
19915
|
const frame2 = {
|
|
18964
19916
|
parentCanvasRef: currentCanvasRef,
|
|
18965
19917
|
parentNodeRect: {
|
|
@@ -18970,16 +19922,23 @@ var SystemCanvas = (() => {
|
|
|
18970
19922
|
}
|
|
18971
19923
|
};
|
|
18972
19924
|
setParentFrames((prev) => [...prev, frame2]);
|
|
19925
|
+
if (!zoomNavConfig.enabled) {
|
|
19926
|
+
navigateToRef(node);
|
|
19927
|
+
return;
|
|
19928
|
+
}
|
|
18973
19929
|
const handle = viewportHandleRef.current;
|
|
18974
19930
|
if (handle) {
|
|
18975
19931
|
handle.zoomToNode(node, () => {
|
|
19932
|
+
const finalVp = viewportStateRef.current;
|
|
19933
|
+
if (finalVp)
|
|
19934
|
+
setPendingHandoff({ ...finalVp });
|
|
18976
19935
|
navigateToRef(node);
|
|
18977
19936
|
});
|
|
18978
19937
|
} else {
|
|
18979
19938
|
navigateToRef(node);
|
|
18980
19939
|
}
|
|
18981
|
-
}, [navigateToRef, currentCanvasRef]);
|
|
18982
|
-
const handleZoomEnter = (0,
|
|
19940
|
+
}, [navigateToRef, currentCanvasRef, zoomNavConfig.enabled]);
|
|
19941
|
+
const handleZoomEnter = (0, import_react20.useCallback)((node, targetTransform) => {
|
|
18983
19942
|
const frame2 = {
|
|
18984
19943
|
parentCanvasRef: currentCanvasRef,
|
|
18985
19944
|
parentNodeRect: {
|
|
@@ -18993,7 +19952,7 @@ var SystemCanvas = (() => {
|
|
|
18993
19952
|
setPendingHandoff(targetTransform);
|
|
18994
19953
|
navigateToRef(node);
|
|
18995
19954
|
}, [currentCanvasRef, navigateToRef]);
|
|
18996
|
-
const handleZoomExit = (0,
|
|
19955
|
+
const handleZoomExit = (0, import_react20.useCallback)((targetTransform) => {
|
|
18997
19956
|
setPendingHandoff(targetTransform);
|
|
18998
19957
|
suppressNextHandoffClearRef.current = true;
|
|
18999
19958
|
navigateToBreadcrumb(breadcrumbs.length - 2);
|
|
@@ -19019,19 +19978,19 @@ var SystemCanvas = (() => {
|
|
|
19019
19978
|
onEnter: handleZoomEnter,
|
|
19020
19979
|
onExit: handleZoomExit
|
|
19021
19980
|
});
|
|
19022
|
-
const handleViewportChange = (0,
|
|
19981
|
+
const handleViewportChange = (0, import_react20.useCallback)((vp) => {
|
|
19023
19982
|
viewportStateRef.current = vp;
|
|
19024
19983
|
handleZoomNavViewportChange(vp);
|
|
19025
19984
|
onViewportChange?.(vp);
|
|
19026
19985
|
}, [handleZoomNavViewportChange, onViewportChange]);
|
|
19027
|
-
const handleHandoffApplied = (0,
|
|
19986
|
+
const handleHandoffApplied = (0, import_react20.useCallback)(() => {
|
|
19028
19987
|
setPendingHandoff(null);
|
|
19029
19988
|
clearZoomNavCommitting();
|
|
19030
19989
|
}, [clearZoomNavCommitting]);
|
|
19031
|
-
const handleBeginEdit = (0,
|
|
19990
|
+
const handleBeginEdit = (0, import_react20.useCallback)((node) => {
|
|
19032
19991
|
setEditingId(node.id);
|
|
19033
19992
|
}, []);
|
|
19034
|
-
const handleBeginEditEdge = (0,
|
|
19993
|
+
const handleBeginEditEdge = (0, import_react20.useCallback)((edge) => {
|
|
19035
19994
|
setEditingEdgeId(edge.id);
|
|
19036
19995
|
}, []);
|
|
19037
19996
|
const { handleNodeClick, handleNodeDoubleClick, handleNodeNavigate, handleEdgeClick, handleEdgeDoubleClick, handleCanvasClick, handleCanvasContextMenu, handleNodeContextMenu, handleEdgeContextMenu } = useCanvasInteraction({
|
|
@@ -19048,27 +20007,27 @@ var SystemCanvas = (() => {
|
|
|
19048
20007
|
onSelectEdge: setSelectedEdgeId,
|
|
19049
20008
|
onBeginEditEdge: handleBeginEditEdge
|
|
19050
20009
|
});
|
|
19051
|
-
const handleEditorCommit = (0,
|
|
20010
|
+
const handleEditorCommit = (0, import_react20.useCallback)((patch) => {
|
|
19052
20011
|
if (editingId) {
|
|
19053
20012
|
onNodeUpdate?.(editingId, patch, currentCanvasRef);
|
|
19054
20013
|
}
|
|
19055
20014
|
setEditingId(null);
|
|
19056
20015
|
}, [editingId, onNodeUpdate, currentCanvasRef]);
|
|
19057
|
-
const handleEditorCancel = (0,
|
|
20016
|
+
const handleEditorCancel = (0, import_react20.useCallback)(() => {
|
|
19058
20017
|
setEditingId(null);
|
|
19059
20018
|
}, []);
|
|
19060
|
-
const handleEdgeEditorCommit = (0,
|
|
20019
|
+
const handleEdgeEditorCommit = (0, import_react20.useCallback)((patch) => {
|
|
19061
20020
|
if (editingEdgeId) {
|
|
19062
20021
|
onEdgeUpdate?.(editingEdgeId, patch, currentCanvasRef);
|
|
19063
20022
|
}
|
|
19064
20023
|
setEditingEdgeId(null);
|
|
19065
20024
|
}, [editingEdgeId, onEdgeUpdate, currentCanvasRef]);
|
|
19066
|
-
const handleEdgeEditorCancel = (0,
|
|
20025
|
+
const handleEdgeEditorCancel = (0, import_react20.useCallback)(() => {
|
|
19067
20026
|
setEditingEdgeId(null);
|
|
19068
20027
|
}, []);
|
|
19069
|
-
const lastAddRef = (0,
|
|
19070
|
-
const menuOptions = (0,
|
|
19071
|
-
const addNode2 = (0,
|
|
20028
|
+
const lastAddRef = (0, import_react20.useRef)(null);
|
|
20029
|
+
const menuOptions = (0, import_react20.useMemo)(() => getNodeMenuOptions(currentCanvas, theme), [currentCanvas, theme]);
|
|
20030
|
+
const addNode2 = (0, import_react20.useCallback)((option, position) => {
|
|
19072
20031
|
let x, y;
|
|
19073
20032
|
if (position) {
|
|
19074
20033
|
x = position.x;
|
|
@@ -19097,10 +20056,10 @@ var SystemCanvas = (() => {
|
|
|
19097
20056
|
y += nextOffset;
|
|
19098
20057
|
lastAddRef.current = { t: now2, offset: nextOffset };
|
|
19099
20058
|
}
|
|
19100
|
-
const node = createNodeFromOption(option, Math.round(x), Math.round(y));
|
|
20059
|
+
const node = createNodeFromOption(option, Math.round(x), Math.round(y), void 0, theme);
|
|
19101
20060
|
onNodeAdd?.(node, currentCanvasRef);
|
|
19102
|
-
}, [onNodeAdd, currentCanvasRef]);
|
|
19103
|
-
const handleKeyDown = (0,
|
|
20061
|
+
}, [onNodeAdd, currentCanvasRef, theme]);
|
|
20062
|
+
const handleKeyDown = (0, import_react20.useCallback)((e) => {
|
|
19104
20063
|
if (!editable)
|
|
19105
20064
|
return;
|
|
19106
20065
|
if (e.key === "Escape") {
|
|
@@ -19134,14 +20093,14 @@ var SystemCanvas = (() => {
|
|
|
19134
20093
|
currentCanvasRef
|
|
19135
20094
|
]);
|
|
19136
20095
|
const renderProps = { options: menuOptions, addNode: addNode2, theme };
|
|
19137
|
-
return (0,
|
|
20096
|
+
return (0, import_jsx_runtime27.jsxs)("div", { ref: containerRef, className: `system-canvas ${className ?? ""}`, tabIndex: editable ? 0 : -1, onKeyDown: handleKeyDown, style: {
|
|
19138
20097
|
position: "relative",
|
|
19139
20098
|
width: "100%",
|
|
19140
20099
|
height: "100%",
|
|
19141
20100
|
overflow: "hidden",
|
|
19142
20101
|
outline: "none",
|
|
19143
20102
|
...style
|
|
19144
|
-
}, children: [(0,
|
|
20103
|
+
}, children: [(0, import_jsx_runtime27.jsx)(Breadcrumbs, { breadcrumbs, theme: theme.breadcrumbs, onNavigate: navigateToBreadcrumb }), isLoading && (0, import_jsx_runtime27.jsx)("div", { className: "system-canvas-loading", style: {
|
|
19145
20104
|
position: "absolute",
|
|
19146
20105
|
top: 12,
|
|
19147
20106
|
right: 12,
|
|
@@ -19153,12 +20112,12 @@ var SystemCanvas = (() => {
|
|
|
19153
20112
|
fontFamily: theme.node.fontFamily,
|
|
19154
20113
|
fontSize: 12,
|
|
19155
20114
|
backdropFilter: "blur(8px)"
|
|
19156
|
-
}, children: "Loading..." }), (0,
|
|
20115
|
+
}, children: "Loading..." }), (0, import_jsx_runtime27.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, 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_runtime27.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_runtime27.jsx)(NodeToolbar, { node: selectedResolvedNode, theme, onPatch: (update) => {
|
|
19157
20116
|
onNodeUpdate?.(selectedResolvedNode.id, update, currentCanvasRef);
|
|
19158
20117
|
}, onDelete: () => {
|
|
19159
20118
|
onNodeDelete?.(selectedResolvedNode.id, currentCanvasRef);
|
|
19160
20119
|
setSelectedId(null);
|
|
19161
|
-
}, getViewport: getViewportState, containerWidth: containerSize.width, containerHeight: containerSize.height, render: renderNodeToolbar }), editable && (renderAddNodeButton ? renderAddNodeButton(renderProps) : (0,
|
|
20120
|
+
}, getViewport: getViewportState, containerWidth: containerSize.width, containerHeight: containerSize.height, render: renderNodeToolbar }), editable && (renderAddNodeButton ? renderAddNodeButton(renderProps) : (0, import_jsx_runtime27.jsx)(AddNodeButton, { ...renderProps }))] });
|
|
19162
20121
|
});
|
|
19163
20122
|
|
|
19164
20123
|
// src/index.tsx
|
|
@@ -19269,7 +20228,7 @@ var SystemCanvas = (() => {
|
|
|
19269
20228
|
onEdgeUpdate: handleEdgeUpdate,
|
|
19270
20229
|
onEdgeDelete: handleEdgeDelete
|
|
19271
20230
|
};
|
|
19272
|
-
root2.render(
|
|
20231
|
+
root2.render(import_react21.default.createElement(SystemCanvas, props));
|
|
19273
20232
|
};
|
|
19274
20233
|
doRender();
|
|
19275
20234
|
return {
|