system-canvas-standalone 0.1.0 → 0.1.2
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 +1195 -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.55;
|
|
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,357 @@ 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 lines = wrapTextWithBreaks(displayValue, region.width, fontSize, maxLines);
|
|
18185
|
+
if (lines.length === 0)
|
|
18186
|
+
return null;
|
|
18187
|
+
const baseY = region.y + fontSize;
|
|
18188
|
+
const clipId = `sc-text-clip-${safeId}`;
|
|
18189
|
+
return (0, import_jsx_runtime7.jsxs)("g", { pointerEvents: "none", children: [(0, import_jsx_runtime7.jsxs)("defs", { children: [fill && (0, import_jsx_runtime7.jsx)(GradientDef, { id: gradId, fill }), (0, import_jsx_runtime7.jsx)("clipPath", { id: clipId, children: (0, import_jsx_runtime7.jsx)("rect", { x: region.x, y: region.y, width: region.width, height: region.height }) })] }), (0, import_jsx_runtime7.jsx)("g", { clipPath: `url(#${clipId})`, pointerEvents: "none", children: (0, import_jsx_runtime7.jsx)("text", { x, y: baseY, fill: fillAttr, fontSize, fontWeight, fontFamily: font, textAnchor: anchor, letterSpacing: uppercase ? 0.8 : 0.2, pointerEvents: "none", children: lines.map((line, i) => (0, import_jsx_runtime7.jsx)("tspan", { x, dy: i === 0 ? 0 : lineHeight, children: line || " " }, i)) }) })] });
|
|
18190
|
+
}
|
|
18191
|
+
function GradientDef({ id: id2, fill }) {
|
|
18192
|
+
const angle = fill.angle ?? 0;
|
|
18193
|
+
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 })] });
|
|
18194
|
+
}
|
|
18195
|
+
|
|
18196
|
+
// ../react/dist/primitives/NodeStatusPill.js
|
|
18197
|
+
var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
|
|
18198
|
+
function NodeStatusPill({ region, value, theme, color: color2, textColor, fill }) {
|
|
18199
|
+
const label = value.toUpperCase();
|
|
18200
|
+
if (!label)
|
|
18201
|
+
return null;
|
|
18202
|
+
const h = Math.min(region.height, 18);
|
|
18203
|
+
const fontSize = Math.max(9, h * 0.62);
|
|
18204
|
+
const padX = 8;
|
|
18205
|
+
const w = Math.max(h * 1.6, label.length * fontSize * 0.62 + padX * 2);
|
|
18206
|
+
const x = region.x + region.width - w;
|
|
18207
|
+
const y = region.y + (region.height - h) / 2;
|
|
18208
|
+
const rx = h / 2;
|
|
18209
|
+
const cx = x + w / 2;
|
|
18210
|
+
const cy = y + h / 2;
|
|
18211
|
+
const tint = fill ?? toTint(color2);
|
|
18212
|
+
const fg = textColor ?? color2;
|
|
18213
|
+
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 })] });
|
|
18214
|
+
}
|
|
18215
|
+
function toTint(color2) {
|
|
18216
|
+
if (color2.startsWith("#") && (color2.length === 7 || color2.length === 4)) {
|
|
18217
|
+
let r;
|
|
18218
|
+
let g;
|
|
18219
|
+
let b;
|
|
18220
|
+
if (color2.length === 7) {
|
|
18221
|
+
r = parseInt(color2.slice(1, 3), 16);
|
|
18222
|
+
g = parseInt(color2.slice(3, 5), 16);
|
|
18223
|
+
b = parseInt(color2.slice(5, 7), 16);
|
|
18224
|
+
} else {
|
|
18225
|
+
r = parseInt(color2[1] + color2[1], 16);
|
|
18226
|
+
g = parseInt(color2[2] + color2[2], 16);
|
|
18227
|
+
b = parseInt(color2[3] + color2[3], 16);
|
|
18228
|
+
}
|
|
18229
|
+
if (!Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b)) {
|
|
18230
|
+
return `rgba(${r}, ${g}, ${b}, 0.15)`;
|
|
18231
|
+
}
|
|
18232
|
+
}
|
|
18233
|
+
return "rgba(255, 255, 255, 0.08)";
|
|
18234
|
+
}
|
|
18235
|
+
|
|
18236
|
+
// ../react/dist/components/CategorySlotsLayer.js
|
|
18237
|
+
function CategorySlotsLayer({ node, theme, canvases, slots: slotsProp }) {
|
|
18238
|
+
const slots = slotsProp ?? getCategorySlots(node, theme);
|
|
18239
|
+
const regions = (0, import_react10.useMemo)(() => computeCategorySlotRegions(node, theme, slots), [node, theme, slots]);
|
|
18240
|
+
const reactId = (0, import_react10.useId)();
|
|
18241
|
+
const clipId = `sc-edge-clip-${reactId.replace(/:/g, "")}`;
|
|
18242
|
+
if (!slots)
|
|
18243
|
+
return null;
|
|
18244
|
+
const getSubCanvas = (ref) => canvases?.[ref];
|
|
18245
|
+
const entries = slotEntries(slots);
|
|
18246
|
+
if (entries.length === 0)
|
|
18247
|
+
return null;
|
|
18248
|
+
const edgeEntries = entries.filter(([p]) => isEdgePosition(p));
|
|
18249
|
+
const otherEntries = entries.filter(([p]) => !isEdgePosition(p));
|
|
18250
|
+
const renderEntry = ([position, spec]) => {
|
|
18251
|
+
const region = regions[position];
|
|
18252
|
+
const ctx = {
|
|
18253
|
+
node,
|
|
18254
|
+
theme,
|
|
18255
|
+
region,
|
|
18256
|
+
getSubCanvas,
|
|
18257
|
+
canvases,
|
|
18258
|
+
rollup: (predicate) => node.ref ? rollupNodes(getSubCanvas(node.ref), predicate) : { total: 0, matched: 0, fraction: 0 }
|
|
18259
|
+
};
|
|
18260
|
+
return (0, import_jsx_runtime9.jsx)(SlotView, { position, spec, ctx }, position);
|
|
18261
|
+
};
|
|
18262
|
+
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)] });
|
|
18263
|
+
}
|
|
18264
|
+
function isEdgePosition(p) {
|
|
18265
|
+
return p === "topEdge" || p === "bottomEdge" || p === "leftEdge" || p === "rightEdge";
|
|
18266
|
+
}
|
|
18267
|
+
function SlotView({ position, spec, ctx }) {
|
|
18268
|
+
try {
|
|
18269
|
+
return renderSlot(position, spec, ctx);
|
|
18270
|
+
} catch (err) {
|
|
18271
|
+
const env = globalThis.process?.env?.NODE_ENV;
|
|
18272
|
+
if (env !== "production") {
|
|
18273
|
+
console.warn("[system-canvas] slot render failed", position, err);
|
|
18274
|
+
}
|
|
18275
|
+
return null;
|
|
18276
|
+
}
|
|
18277
|
+
}
|
|
18278
|
+
function renderSlot(position, spec, ctx) {
|
|
18279
|
+
const { theme, node, region } = ctx;
|
|
18280
|
+
const nodeColor = node.resolvedStroke;
|
|
18281
|
+
switch (spec.kind) {
|
|
18282
|
+
case "color": {
|
|
18283
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18284
|
+
const length = resolveAccessorOr(spec.length, 0.55, ctx);
|
|
18285
|
+
return (0, import_jsx_runtime9.jsx)(NodeColorFill, { region, color: color2, position, extent: spec.extent, length });
|
|
18286
|
+
}
|
|
18287
|
+
case "progress": {
|
|
18288
|
+
const value = resolveAccessor(spec.value, ctx);
|
|
18289
|
+
if (spec.hideWhenZero && (!Number.isFinite(value) || value <= 0)) {
|
|
18290
|
+
return null;
|
|
18291
|
+
}
|
|
18292
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18293
|
+
const bgColor = resolveAccessorOr(spec.bgColor, "rgba(255,255,255,0.08)", ctx);
|
|
18294
|
+
return (0, import_jsx_runtime9.jsx)(NodeProgressBar, { region, value, color: color2, bgColor });
|
|
18295
|
+
}
|
|
18296
|
+
case "count": {
|
|
18297
|
+
const raw = resolveAccessor(spec.value, ctx);
|
|
18298
|
+
const hideWhenEmpty = spec.hideWhenEmpty !== false;
|
|
18299
|
+
if (hideWhenEmpty) {
|
|
18300
|
+
if (raw === 0 || raw === "" || raw == null)
|
|
18301
|
+
return null;
|
|
18302
|
+
}
|
|
18303
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18304
|
+
const textColor = resolveAccessorOr(spec.textColor, theme.background, ctx);
|
|
18305
|
+
return (0, import_jsx_runtime9.jsx)(NodeCountBadge, { region, value: raw, theme, color: color2, textColor, position });
|
|
18306
|
+
}
|
|
18307
|
+
case "pill": {
|
|
18308
|
+
const value = resolveAccessor(spec.value, ctx);
|
|
18309
|
+
if (!value)
|
|
18310
|
+
return null;
|
|
18311
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18312
|
+
const textColor = spec.textColor ? resolveAccessor(spec.textColor, ctx) : void 0;
|
|
18313
|
+
const fill = spec.fill ? resolveAccessor(spec.fill, ctx) : void 0;
|
|
18314
|
+
return (0, import_jsx_runtime9.jsx)(NodeStatusPill, { region, value, theme, color: color2, textColor, fill });
|
|
18315
|
+
}
|
|
18316
|
+
case "text": {
|
|
18317
|
+
const value = resolveAccessor(spec.value, ctx);
|
|
18318
|
+
const color2 = resolveAccessorOr(spec.color, position === "body" ? theme.node.labelColor : theme.node.sublabelColor, ctx);
|
|
18319
|
+
const defaultAlign = position === "header" || position === "footer" || position === "body" ? "start" : "center";
|
|
18320
|
+
const align = spec.align ?? defaultAlign;
|
|
18321
|
+
const isHeader = position === "header";
|
|
18322
|
+
const isBody = position === "body";
|
|
18323
|
+
const defaultWeight = isHeader ? 700 : isBody ? 600 : 500;
|
|
18324
|
+
const defaultUppercase = isHeader;
|
|
18325
|
+
const defaultUseLabelFont = isHeader || isBody;
|
|
18326
|
+
const defaultFontSize = isBody ? Math.round(theme.node.fontSize * 1.35) : void 0;
|
|
18327
|
+
const fontSize = spec.fontSize !== void 0 ? resolveAccessor(spec.fontSize, ctx) : defaultFontSize;
|
|
18328
|
+
const fontWeight = spec.fontWeight !== void 0 ? resolveAccessor(spec.fontWeight, ctx) : defaultWeight;
|
|
18329
|
+
const fontFamily = spec.fontFamily !== void 0 ? resolveAccessor(spec.fontFamily, ctx) : void 0;
|
|
18330
|
+
const wrap = spec.wrap ?? isBody;
|
|
18331
|
+
const lineHeight = spec.lineHeight !== void 0 ? resolveAccessor(spec.lineHeight, ctx) : void 0;
|
|
18332
|
+
const fill = spec.fill !== void 0 ? resolveAccessor(spec.fill, ctx) : void 0;
|
|
18333
|
+
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 });
|
|
18334
|
+
}
|
|
18335
|
+
case "dot": {
|
|
18336
|
+
const color2 = resolveAccessorOr(spec.color, nodeColor, ctx);
|
|
18337
|
+
return (0, import_jsx_runtime9.jsx)(NodeDot, { region, color: color2 });
|
|
18338
|
+
}
|
|
18339
|
+
case "custom": {
|
|
18340
|
+
return spec.render(ctx);
|
|
18341
|
+
}
|
|
18342
|
+
}
|
|
18343
|
+
}
|
|
18344
|
+
|
|
18345
|
+
// ../react/dist/components/refCorner.js
|
|
18346
|
+
function toKebabCorner(c) {
|
|
18347
|
+
switch (c) {
|
|
18348
|
+
case "topLeft":
|
|
18349
|
+
return "top-left";
|
|
18350
|
+
case "topRight":
|
|
18351
|
+
return "top-right";
|
|
18352
|
+
case "bottomLeft":
|
|
18353
|
+
return "bottom-left";
|
|
18354
|
+
case "bottomRight":
|
|
18355
|
+
return "bottom-right";
|
|
18356
|
+
}
|
|
18357
|
+
}
|
|
18358
|
+
|
|
17630
18359
|
// ../react/dist/components/TextNode.js
|
|
17631
|
-
function TextNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18360
|
+
function TextNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "bottomRight" }) {
|
|
17632
18361
|
const { x, y, width, height } = node;
|
|
17633
|
-
const
|
|
18362
|
+
const contentX = x + reservedLeft;
|
|
18363
|
+
const contentY = y + reservedTop;
|
|
18364
|
+
const contentWidth = Math.max(0, width - reservedLeft - reservedRight);
|
|
18365
|
+
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
17634
18366
|
const text = node.text ?? "";
|
|
17635
18367
|
const lines = text.split("\n").filter(Boolean);
|
|
17636
18368
|
const mainLabel = lines[0] ?? node.id;
|
|
17637
18369
|
const sublabel = lines[1];
|
|
17638
|
-
const
|
|
18370
|
+
const hasBodySlot = slots?.body !== void 0;
|
|
18371
|
+
const hasHeader = reservedTop > 0;
|
|
18372
|
+
const labelFont = theme.node.labelFont ?? theme.node.fontFamily;
|
|
18373
|
+
const labelFontSize = theme.node.fontSize + (hasHeader ? 1 : 0);
|
|
18374
|
+
const lineHeight = labelFontSize + 4;
|
|
17639
18375
|
const totalTextHeight = sublabel ? lineHeight + theme.node.sublabelFontSize + 4 : lineHeight;
|
|
17640
|
-
const
|
|
17641
|
-
|
|
18376
|
+
const labelAnchor = hasHeader ? "start" : "middle";
|
|
18377
|
+
const labelX = hasHeader ? contentX : contentX + contentWidth / 2;
|
|
18378
|
+
const textStartY = hasHeader ? contentY + labelFontSize + 2 : contentY + (contentHeight - totalTextHeight) / 2 + labelFontSize;
|
|
18379
|
+
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
18380
|
}
|
|
17643
18381
|
|
|
17644
18382
|
// ../react/dist/components/FileNode.js
|
|
17645
|
-
var
|
|
17646
|
-
function FileNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18383
|
+
var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
|
|
18384
|
+
function FileNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "bottomRight" }) {
|
|
17647
18385
|
const { x, y, width, height } = node;
|
|
17648
18386
|
const filePath = node.file ?? "";
|
|
17649
18387
|
const fileName = filePath.split("/").pop() ?? filePath;
|
|
17650
18388
|
const dirPath = filePath.includes("/") ? filePath.slice(0, filePath.lastIndexOf("/")) : "";
|
|
17651
18389
|
const subpath = node.subpath ?? "";
|
|
17652
18390
|
const fold = 10;
|
|
17653
|
-
const textPadding = 10;
|
|
17654
|
-
const maxTextWidth = width - textPadding
|
|
18391
|
+
const textPadding = 10 + reservedLeft;
|
|
18392
|
+
const maxTextWidth = width - textPadding - reservedRight - fold;
|
|
18393
|
+
const contentY = y + reservedTop;
|
|
18394
|
+
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
17655
18395
|
const shapePath = [
|
|
17656
18396
|
`M ${x + 2} ${y}`,
|
|
17657
18397
|
`L ${x + width - fold} ${y}`,
|
|
@@ -17668,35 +18408,41 @@ var SystemCanvas = (() => {
|
|
|
17668
18408
|
const strokeColor = node.resolvedStroke;
|
|
17669
18409
|
const thinStroke = 0.75;
|
|
17670
18410
|
const clipId = `file-clip-${node.id}`;
|
|
17671
|
-
return (0,
|
|
18411
|
+
return (0, import_jsx_runtime11.jsxs)("g", { className: "system-canvas-node system-canvas-node--file", style: { cursor: onPointerDown ? "move" : node.isNavigable ? "pointer" : "default" }, onClick: (e) => onClick(node, e), onDoubleClick: (e) => onDoubleClick(node, e), onContextMenu: (e) => onContextMenu(node, e), onPointerDown: onPointerDown ? (e) => onPointerDown(node, e) : void 0, children: [(0, import_jsx_runtime11.jsx)("defs", { children: (0, import_jsx_runtime11.jsx)("clipPath", { id: clipId, children: (0, import_jsx_runtime11.jsx)("rect", { x: x + textPadding, y: contentY, width: maxTextWidth, height: contentHeight }) }) }), (0, import_jsx_runtime11.jsx)("path", { d: shapePath, fill: theme.background }), (0, import_jsx_runtime11.jsx)("path", { d: shapePath, fill: node.resolvedFill, stroke: strokeColor, strokeWidth: thinStroke }), (0, import_jsx_runtime11.jsx)("path", { d: foldPath, fill: "none", stroke: strokeColor, strokeWidth: thinStroke, opacity: 0.5 }), !isEditing && !slots?.body && (0, import_jsx_runtime11.jsxs)("g", { clipPath: `url(#${clipId})`, children: [dirPath && (0, import_jsx_runtime11.jsxs)("text", { x: x + textPadding, y: contentY + 14, fill: theme.node.sublabelColor, fontSize: theme.node.sublabelFontSize - 1, fontFamily: theme.node.fontFamily, pointerEvents: "none", opacity: 0.6, children: [dirPath, "/"] }), (0, import_jsx_runtime11.jsx)("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
18412
|
}
|
|
17673
18413
|
|
|
17674
18414
|
// ../react/dist/components/LinkNode.js
|
|
17675
|
-
var
|
|
17676
|
-
function LinkNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18415
|
+
var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
|
|
18416
|
+
function LinkNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "bottomRight" }) {
|
|
17677
18417
|
const { x, y, width, height } = node;
|
|
17678
|
-
const
|
|
18418
|
+
const contentX = x + reservedLeft;
|
|
18419
|
+
const contentY = y + reservedTop;
|
|
18420
|
+
const contentWidth = Math.max(0, width - reservedLeft - reservedRight);
|
|
18421
|
+
const contentHeight = Math.max(0, height - reservedTop - reservedBottom);
|
|
18422
|
+
const cx = contentX + contentWidth / 2;
|
|
17679
18423
|
let displayUrl = node.url ?? "";
|
|
17680
18424
|
try {
|
|
17681
18425
|
const url = new URL(displayUrl);
|
|
17682
18426
|
displayUrl = url.hostname;
|
|
17683
18427
|
} catch {
|
|
17684
18428
|
}
|
|
17685
|
-
return (0,
|
|
18429
|
+
return (0, import_jsx_runtime12.jsxs)("g", { className: "system-canvas-node system-canvas-node--link", style: { cursor: onPointerDown ? "move" : "pointer" }, onClick: (e) => onClick(node, e), onDoubleClick: (e) => onDoubleClick(node, e), onContextMenu: (e) => onContextMenu(node, e), onPointerDown: onPointerDown ? (e) => onPointerDown(node, e) : void 0, children: [(0, import_jsx_runtime12.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: theme.background }), (0, import_jsx_runtime12.jsx)("rect", { x, y, width, height, rx: node.resolvedCornerRadius, fill: node.resolvedFill, stroke: node.resolvedStroke, strokeWidth: theme.node.strokeWidth }), !isEditing && !slots?.body && (0, import_jsx_runtime12.jsx)("text", { x: contentX + 12, y: contentY + contentHeight / 2 + 4, fill: node.resolvedStroke, fontSize: 12, fontFamily: theme.node.fontFamily, pointerEvents: "none", opacity: 0.6, children: "\u29C9" }), !isEditing && !slots?.body && (0, import_jsx_runtime12.jsx)("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
18430
|
}
|
|
17687
18431
|
|
|
17688
18432
|
// ../react/dist/components/GroupNode.js
|
|
17689
|
-
var
|
|
17690
|
-
function GroupNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing }) {
|
|
18433
|
+
var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
18434
|
+
function GroupNode({ node, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, isSelected, isEditing, slots, canvases, reservedTop = 0, reservedBottom = 0, reservedLeft = 0, reservedRight = 0, refCorner = "topRight" }) {
|
|
17691
18435
|
const { x, y, width, height } = node;
|
|
17692
18436
|
const stroke = node.color ? node.resolvedStroke : theme.group.stroke;
|
|
17693
18437
|
const fill = node.color ? node.resolvedFill : theme.group.fill;
|
|
17694
|
-
|
|
18438
|
+
const labelX = x + 12 + reservedLeft;
|
|
18439
|
+
const labelY = y + reservedTop + theme.group.labelFontSize + 8;
|
|
18440
|
+
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
18441
|
}
|
|
17696
18442
|
|
|
17697
18443
|
// ../react/dist/components/ResizeHandles.js
|
|
17698
|
-
var
|
|
17699
|
-
var
|
|
18444
|
+
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
18445
|
+
var import_react11 = __toESM(require_react(), 1);
|
|
17700
18446
|
var HANDLE_SIZE = 7;
|
|
17701
18447
|
var CORNERS = [
|
|
17702
18448
|
{ corner: "nw", cursor: "nwse-resize", anchor: "nw" },
|
|
@@ -17707,7 +18453,7 @@ var SystemCanvas = (() => {
|
|
|
17707
18453
|
var cornerInset = (cornerRadius) => Math.min(cornerRadius * 0.25, 3);
|
|
17708
18454
|
function ResizeHandles({ node, theme, onHandlePointerDown }) {
|
|
17709
18455
|
const { x, y, width, height } = node;
|
|
17710
|
-
const [hoveredCorner, setHoveredCorner] = (0,
|
|
18456
|
+
const [hoveredCorner, setHoveredCorner] = (0, import_react11.useState)(null);
|
|
17711
18457
|
const handleColor = node.resolvedStroke ?? theme.node.labelColor;
|
|
17712
18458
|
const i = cornerInset(node.resolvedCornerRadius);
|
|
17713
18459
|
const anchorPos = (anchor) => {
|
|
@@ -17722,36 +18468,54 @@ var SystemCanvas = (() => {
|
|
|
17722
18468
|
return { cx: x + width - i, cy: y + height - i };
|
|
17723
18469
|
}
|
|
17724
18470
|
};
|
|
17725
|
-
return (0,
|
|
18471
|
+
return (0, import_jsx_runtime14.jsx)("g", { className: "system-canvas-resize-handles", pointerEvents: "all", children: CORNERS.map(({ corner, cursor, anchor }) => {
|
|
17726
18472
|
const { cx, cy } = anchorPos(anchor);
|
|
17727
18473
|
const isHovered = hoveredCorner === corner;
|
|
17728
18474
|
const s = isHovered ? HANDLE_SIZE + 2 : HANDLE_SIZE;
|
|
17729
18475
|
const half = s / 2;
|
|
17730
|
-
return (0,
|
|
18476
|
+
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
18477
|
}) });
|
|
17732
18478
|
}
|
|
17733
18479
|
|
|
17734
18480
|
// ../react/dist/components/NodeRenderer.js
|
|
17735
|
-
function NodeRenderer({ nodes, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, selectedId, editingId, onResizeHandlePointerDown, only }) {
|
|
18481
|
+
function NodeRenderer({ nodes, theme, onClick, onDoubleClick, onContextMenu, onNavigate, onPointerDown, selectedId, editingId, onResizeHandlePointerDown, canvases, only }) {
|
|
17736
18482
|
const groups = nodes.filter((n) => n.type === "group");
|
|
17737
18483
|
const others = nodes.filter((n) => n.type !== "group");
|
|
17738
|
-
const common = (node) =>
|
|
17739
|
-
node,
|
|
17740
|
-
theme,
|
|
17741
|
-
|
|
17742
|
-
|
|
17743
|
-
|
|
17744
|
-
|
|
17745
|
-
|
|
17746
|
-
|
|
17747
|
-
|
|
17748
|
-
|
|
18484
|
+
const common = (node) => {
|
|
18485
|
+
const slots = getCategorySlots(node, theme);
|
|
18486
|
+
const reservations = computeReflowReservations(node, theme, slots);
|
|
18487
|
+
const defaultCorner = node.type === "group" ? "topRight" : "bottomRight";
|
|
18488
|
+
const refCorner = pickRefIndicatorCorner(defaultCorner, slots);
|
|
18489
|
+
return {
|
|
18490
|
+
node,
|
|
18491
|
+
theme,
|
|
18492
|
+
onClick,
|
|
18493
|
+
onDoubleClick,
|
|
18494
|
+
onContextMenu,
|
|
18495
|
+
onNavigate,
|
|
18496
|
+
onPointerDown,
|
|
18497
|
+
isSelected: selectedId === node.id,
|
|
18498
|
+
isEditing: editingId === node.id,
|
|
18499
|
+
slots,
|
|
18500
|
+
canvases,
|
|
18501
|
+
reservedTop: reservations.top,
|
|
18502
|
+
reservedBottom: reservations.bottom,
|
|
18503
|
+
reservedLeft: reservations.left,
|
|
18504
|
+
reservedRight: reservations.right,
|
|
18505
|
+
refCorner
|
|
18506
|
+
};
|
|
18507
|
+
};
|
|
17749
18508
|
const selectedNode = selectedId && editingId !== selectedId ? nodes.find((n) => n.id === selectedId) : void 0;
|
|
17750
18509
|
const renderResizeHandles = only !== "groups" && selectedNode && onResizeHandlePointerDown;
|
|
17751
|
-
return (0,
|
|
18510
|
+
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
18511
|
const Component = getNodeComponent(node.type);
|
|
17753
|
-
return (0,
|
|
17754
|
-
}), renderResizeHandles && (0,
|
|
18512
|
+
return (0, import_jsx_runtime15.jsx)(Component, { ...common(node) }, node.id);
|
|
18513
|
+
}), renderResizeHandles && (0, import_jsx_runtime15.jsx)(ResizeHandles, { node: selectedNode, theme, onHandlePointerDown: onResizeHandlePointerDown }), renderResizeHandles && (() => {
|
|
18514
|
+
const slots = getCategorySlots(selectedNode, theme);
|
|
18515
|
+
if (!slots?.topRightOuter)
|
|
18516
|
+
return null;
|
|
18517
|
+
return (0, import_jsx_runtime15.jsx)(CategorySlotsLayer, { node: selectedNode, theme, canvases, slots: { topRightOuter: slots.topRightOuter } });
|
|
18518
|
+
})()] });
|
|
17755
18519
|
}
|
|
17756
18520
|
function getNodeComponent(type) {
|
|
17757
18521
|
switch (type) {
|
|
@@ -17765,9 +18529,9 @@ var SystemCanvas = (() => {
|
|
|
17765
18529
|
}
|
|
17766
18530
|
|
|
17767
18531
|
// ../react/dist/components/EdgeRenderer.js
|
|
17768
|
-
var
|
|
18532
|
+
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
17769
18533
|
function EdgeRenderer({ edges, nodeMap, theme, defaultEdgeStyle, onClick, onDoubleClick, onContextMenu, selectedId, editingId }) {
|
|
17770
|
-
return (0,
|
|
18534
|
+
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
18535
|
const aSel = selectedId === a.edge.id ? 2 : 0;
|
|
17772
18536
|
const bSel = selectedId === b.edge.id ? 2 : 0;
|
|
17773
18537
|
const aCol = a.edge.color ? 1 : 0;
|
|
@@ -17792,20 +18556,36 @@ var SystemCanvas = (() => {
|
|
|
17792
18556
|
const toEnd = edge.toEnd ?? "arrow";
|
|
17793
18557
|
const fromEnd = edge.fromEnd ?? "none";
|
|
17794
18558
|
const arrowId = "system-canvas-arrowhead";
|
|
17795
|
-
return (0,
|
|
18559
|
+
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
18560
|
})] });
|
|
17797
18561
|
}
|
|
17798
18562
|
|
|
17799
18563
|
// ../react/dist/components/NodeEditor.js
|
|
17800
|
-
var
|
|
17801
|
-
var
|
|
18564
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
18565
|
+
var import_react12 = __toESM(require_react(), 1);
|
|
17802
18566
|
function NodeEditor({ node, theme, onCommit, onCancel }) {
|
|
18567
|
+
const editableFields = useCategoryFields(node, theme);
|
|
18568
|
+
if (editableFields) {
|
|
18569
|
+
return (0, import_jsx_runtime17.jsx)(FormEditor, { node, theme, fields: editableFields, onCommit, onCancel });
|
|
18570
|
+
}
|
|
18571
|
+
return (0, import_jsx_runtime17.jsx)(SingleFieldEditor, { node, theme, onCommit, onCancel });
|
|
18572
|
+
}
|
|
18573
|
+
function useCategoryFields(node, theme) {
|
|
18574
|
+
if (!node.category)
|
|
18575
|
+
return null;
|
|
18576
|
+
const def = theme.categories[node.category];
|
|
18577
|
+
const fields = def?.editableFields;
|
|
18578
|
+
if (!fields || fields.length === 0)
|
|
18579
|
+
return null;
|
|
18580
|
+
return fields;
|
|
18581
|
+
}
|
|
18582
|
+
function SingleFieldEditor({ node, theme, onCommit, onCancel }) {
|
|
17803
18583
|
const initial = getInitialValue(node);
|
|
17804
|
-
const [value, setValue] = (0,
|
|
17805
|
-
const textareaRef = (0,
|
|
17806
|
-
const inputRef = (0,
|
|
17807
|
-
const committedRef = (0,
|
|
17808
|
-
(0,
|
|
18584
|
+
const [value, setValue] = (0, import_react12.useState)(initial);
|
|
18585
|
+
const textareaRef = (0, import_react12.useRef)(null);
|
|
18586
|
+
const inputRef = (0, import_react12.useRef)(null);
|
|
18587
|
+
const committedRef = (0, import_react12.useRef)(false);
|
|
18588
|
+
(0, import_react12.useEffect)(() => {
|
|
17809
18589
|
const el = textareaRef.current ?? inputRef.current;
|
|
17810
18590
|
if (el) {
|
|
17811
18591
|
el.focus();
|
|
@@ -17821,7 +18601,7 @@ var SystemCanvas = (() => {
|
|
|
17821
18601
|
onCancel();
|
|
17822
18602
|
return;
|
|
17823
18603
|
}
|
|
17824
|
-
onCommit(
|
|
18604
|
+
onCommit(buildSingleFieldPatch(node, value));
|
|
17825
18605
|
};
|
|
17826
18606
|
const cancel = () => {
|
|
17827
18607
|
if (committedRef.current)
|
|
@@ -17850,7 +18630,7 @@ var SystemCanvas = (() => {
|
|
|
17850
18630
|
resize: "none",
|
|
17851
18631
|
textAlign: node.type === "text" ? "center" : "left"
|
|
17852
18632
|
};
|
|
17853
|
-
return (0,
|
|
18633
|
+
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
18634
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
17855
18635
|
e.preventDefault();
|
|
17856
18636
|
commit();
|
|
@@ -17858,7 +18638,7 @@ var SystemCanvas = (() => {
|
|
|
17858
18638
|
e.preventDefault();
|
|
17859
18639
|
cancel();
|
|
17860
18640
|
}
|
|
17861
|
-
}, style: commonFieldStyle }) : (0,
|
|
18641
|
+
}, style: commonFieldStyle }) : (0, import_jsx_runtime17.jsx)("input", { ref: inputRef, value, onChange: (e) => setValue(e.target.value), onBlur: commit, onKeyDown: (e) => {
|
|
17862
18642
|
if (e.key === "Enter") {
|
|
17863
18643
|
e.preventDefault();
|
|
17864
18644
|
commit();
|
|
@@ -17882,7 +18662,7 @@ var SystemCanvas = (() => {
|
|
|
17882
18662
|
return "";
|
|
17883
18663
|
}
|
|
17884
18664
|
}
|
|
17885
|
-
function
|
|
18665
|
+
function buildSingleFieldPatch(node, value) {
|
|
17886
18666
|
switch (node.type) {
|
|
17887
18667
|
case "text":
|
|
17888
18668
|
return { text: value };
|
|
@@ -17896,16 +18676,176 @@ var SystemCanvas = (() => {
|
|
|
17896
18676
|
return {};
|
|
17897
18677
|
}
|
|
17898
18678
|
}
|
|
18679
|
+
function FormEditor({ node, theme, fields, onCommit, onCancel }) {
|
|
18680
|
+
const initial = (0, import_react12.useMemo)(() => readInitialValues(node, fields), [node, fields]);
|
|
18681
|
+
const [values, setValues] = (0, import_react12.useState)(initial);
|
|
18682
|
+
const committedRef = (0, import_react12.useRef)(false);
|
|
18683
|
+
const panelRef = (0, import_react12.useRef)(null);
|
|
18684
|
+
const width = Math.max(node.width, 240);
|
|
18685
|
+
const height = Math.max(node.height, 36 + fields.length * 44);
|
|
18686
|
+
const commit = () => {
|
|
18687
|
+
if (committedRef.current)
|
|
18688
|
+
return;
|
|
18689
|
+
committedRef.current = true;
|
|
18690
|
+
const patch = buildFormPatch(node, fields, initial, values);
|
|
18691
|
+
if (!patch) {
|
|
18692
|
+
onCancel();
|
|
18693
|
+
return;
|
|
18694
|
+
}
|
|
18695
|
+
onCommit(patch);
|
|
18696
|
+
};
|
|
18697
|
+
const cancel = () => {
|
|
18698
|
+
if (committedRef.current)
|
|
18699
|
+
return;
|
|
18700
|
+
committedRef.current = true;
|
|
18701
|
+
onCancel();
|
|
18702
|
+
};
|
|
18703
|
+
const onBlurPanel = (e) => {
|
|
18704
|
+
const next = e.relatedTarget;
|
|
18705
|
+
if (next && panelRef.current?.contains(next))
|
|
18706
|
+
return;
|
|
18707
|
+
commit();
|
|
18708
|
+
};
|
|
18709
|
+
const stopPointer = (e) => {
|
|
18710
|
+
e.stopPropagation();
|
|
18711
|
+
};
|
|
18712
|
+
(0, import_react12.useEffect)(() => {
|
|
18713
|
+
const el = panelRef.current;
|
|
18714
|
+
if (!el)
|
|
18715
|
+
return;
|
|
18716
|
+
const first = el.querySelector("input, textarea, select, button");
|
|
18717
|
+
first?.focus();
|
|
18718
|
+
if (first instanceof HTMLInputElement && first.type === "text") {
|
|
18719
|
+
const end = first.value.length;
|
|
18720
|
+
first.setSelectionRange(end, end);
|
|
18721
|
+
}
|
|
18722
|
+
}, []);
|
|
18723
|
+
const fieldLabelColor = theme.node.sublabelColor;
|
|
18724
|
+
const inputStyle = {
|
|
18725
|
+
width: "100%",
|
|
18726
|
+
boxSizing: "border-box",
|
|
18727
|
+
padding: "6px 8px",
|
|
18728
|
+
fontFamily: theme.node.fontFamily,
|
|
18729
|
+
fontSize: theme.node.fontSize - 1,
|
|
18730
|
+
background: theme.background,
|
|
18731
|
+
color: theme.node.labelColor,
|
|
18732
|
+
border: `1px solid ${theme.breadcrumbs.separatorColor}`,
|
|
18733
|
+
borderRadius: 6,
|
|
18734
|
+
outline: "none"
|
|
18735
|
+
};
|
|
18736
|
+
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) => {
|
|
18737
|
+
if (e.key === "Escape") {
|
|
18738
|
+
e.preventDefault();
|
|
18739
|
+
cancel();
|
|
18740
|
+
} else if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
18741
|
+
e.preventDefault();
|
|
18742
|
+
commit();
|
|
18743
|
+
} else if (e.key === "Enter" && !(e.target instanceof HTMLTextAreaElement)) {
|
|
18744
|
+
e.preventDefault();
|
|
18745
|
+
const panel = panelRef.current;
|
|
18746
|
+
if (!panel)
|
|
18747
|
+
return;
|
|
18748
|
+
const focusables = Array.from(panel.querySelectorAll("input, textarea, select"));
|
|
18749
|
+
const idx = focusables.indexOf(e.target);
|
|
18750
|
+
if (idx === -1 || idx === focusables.length - 1)
|
|
18751
|
+
commit();
|
|
18752
|
+
else
|
|
18753
|
+
focusables[idx + 1].focus();
|
|
18754
|
+
}
|
|
18755
|
+
}, style: {
|
|
18756
|
+
width: "100%",
|
|
18757
|
+
boxSizing: "border-box",
|
|
18758
|
+
display: "flex",
|
|
18759
|
+
flexDirection: "column",
|
|
18760
|
+
gap: 8,
|
|
18761
|
+
padding: 10,
|
|
18762
|
+
background: theme.breadcrumbs.background,
|
|
18763
|
+
color: theme.node.labelColor,
|
|
18764
|
+
border: `1.5px solid ${theme.node.labelColor}`,
|
|
18765
|
+
borderRadius: node.resolvedCornerRadius,
|
|
18766
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.25)",
|
|
18767
|
+
backdropFilter: "blur(8px)",
|
|
18768
|
+
fontFamily: theme.node.fontFamily
|
|
18769
|
+
}, children: fields.map((field) => {
|
|
18770
|
+
const v = values[field.path];
|
|
18771
|
+
const setV = (next) => setValues((prev) => ({ ...prev, [field.path]: next }));
|
|
18772
|
+
const label = field.label ?? field.path;
|
|
18773
|
+
return (0, import_jsx_runtime17.jsxs)("label", { style: {
|
|
18774
|
+
display: "flex",
|
|
18775
|
+
flexDirection: "column",
|
|
18776
|
+
gap: 3,
|
|
18777
|
+
fontSize: 10,
|
|
18778
|
+
color: fieldLabelColor,
|
|
18779
|
+
textTransform: "uppercase",
|
|
18780
|
+
letterSpacing: 0.5
|
|
18781
|
+
}, children: [(0, import_jsx_runtime17.jsx)("span", { children: label }), renderControl(field, v, setV, inputStyle, theme)] }, field.path);
|
|
18782
|
+
}) }) });
|
|
18783
|
+
}
|
|
18784
|
+
function renderControl(field, value, setValue, inputStyle, theme) {
|
|
18785
|
+
switch (field.kind) {
|
|
18786
|
+
case "textarea":
|
|
18787
|
+
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 } });
|
|
18788
|
+
case "number":
|
|
18789
|
+
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) => {
|
|
18790
|
+
const v = e.target.value;
|
|
18791
|
+
setValue(v === "" ? void 0 : Number(v));
|
|
18792
|
+
}, placeholder: field.placeholder, style: inputStyle });
|
|
18793
|
+
case "select":
|
|
18794
|
+
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))] });
|
|
18795
|
+
case "boolean":
|
|
18796
|
+
return (0, import_jsx_runtime17.jsx)("input", { type: "checkbox", checked: !!value, onChange: (e) => setValue(e.target.checked), style: {
|
|
18797
|
+
alignSelf: "flex-start",
|
|
18798
|
+
width: 16,
|
|
18799
|
+
height: 16,
|
|
18800
|
+
accentColor: theme.node.labelColor
|
|
18801
|
+
} });
|
|
18802
|
+
case "text":
|
|
18803
|
+
default:
|
|
18804
|
+
return (0, import_jsx_runtime17.jsx)("input", { type: "text", value: value ?? "", onChange: (e) => setValue(e.target.value), placeholder: field.placeholder, style: inputStyle });
|
|
18805
|
+
}
|
|
18806
|
+
}
|
|
18807
|
+
function readInitialValues(node, fields) {
|
|
18808
|
+
const out = {};
|
|
18809
|
+
for (const f of fields) {
|
|
18810
|
+
out[f.path] = getAtPath(node, f.path);
|
|
18811
|
+
}
|
|
18812
|
+
return out;
|
|
18813
|
+
}
|
|
18814
|
+
function buildFormPatch(node, fields, initial, current) {
|
|
18815
|
+
let changed = false;
|
|
18816
|
+
for (const f of fields) {
|
|
18817
|
+
if (current[f.path] !== initial[f.path]) {
|
|
18818
|
+
changed = true;
|
|
18819
|
+
break;
|
|
18820
|
+
}
|
|
18821
|
+
}
|
|
18822
|
+
if (!changed)
|
|
18823
|
+
return null;
|
|
18824
|
+
let working = { ...node };
|
|
18825
|
+
for (const f of fields) {
|
|
18826
|
+
working = setAtPath(working, f.path, current[f.path]);
|
|
18827
|
+
}
|
|
18828
|
+
const patch = {};
|
|
18829
|
+
const topKeys = /* @__PURE__ */ new Set();
|
|
18830
|
+
for (const f of fields) {
|
|
18831
|
+
topKeys.add(f.path.split(".")[0]);
|
|
18832
|
+
}
|
|
18833
|
+
for (const k of topKeys) {
|
|
18834
|
+
;
|
|
18835
|
+
patch[k] = working[k];
|
|
18836
|
+
}
|
|
18837
|
+
return patch;
|
|
18838
|
+
}
|
|
17899
18839
|
|
|
17900
18840
|
// ../react/dist/components/EdgeLabelEditor.js
|
|
17901
|
-
var
|
|
17902
|
-
var
|
|
18841
|
+
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
18842
|
+
var import_react13 = __toESM(require_react(), 1);
|
|
17903
18843
|
var EDITOR_WIDTH = 110;
|
|
17904
18844
|
function EdgeLabelEditor({ initialLabel, midpoint, theme, onCommit, onCancel }) {
|
|
17905
|
-
const [value, setValue] = (0,
|
|
17906
|
-
const inputRef = (0,
|
|
17907
|
-
const committedRef = (0,
|
|
17908
|
-
(0,
|
|
18845
|
+
const [value, setValue] = (0, import_react13.useState)(initialLabel);
|
|
18846
|
+
const inputRef = (0, import_react13.useRef)(null);
|
|
18847
|
+
const committedRef = (0, import_react13.useRef)(false);
|
|
18848
|
+
(0, import_react13.useEffect)(() => {
|
|
17909
18849
|
const el = inputRef.current;
|
|
17910
18850
|
if (el) {
|
|
17911
18851
|
el.focus();
|
|
@@ -17934,7 +18874,7 @@ var SystemCanvas = (() => {
|
|
|
17934
18874
|
};
|
|
17935
18875
|
const fontSize = theme.edge.labelFontSize;
|
|
17936
18876
|
const height = fontSize + 14;
|
|
17937
|
-
return (0,
|
|
18877
|
+
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
18878
|
if (e.key === "Enter") {
|
|
17939
18879
|
e.preventDefault();
|
|
17940
18880
|
commit();
|
|
@@ -17959,8 +18899,8 @@ var SystemCanvas = (() => {
|
|
|
17959
18899
|
}
|
|
17960
18900
|
|
|
17961
18901
|
// ../react/dist/components/ConnectionHandles.js
|
|
17962
|
-
var
|
|
17963
|
-
var
|
|
18902
|
+
var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
|
|
18903
|
+
var import_react14 = __toESM(require_react(), 1);
|
|
17964
18904
|
var SIDES = ["top", "right", "bottom", "left"];
|
|
17965
18905
|
var HANDLE_RADIUS = 4;
|
|
17966
18906
|
var HANDLE_HIT_RADIUS = 10;
|
|
@@ -17969,9 +18909,9 @@ var SystemCanvas = (() => {
|
|
|
17969
18909
|
var HOVER_SCALE = 1.42;
|
|
17970
18910
|
var HOVER_TRANSITION_MS = 120;
|
|
17971
18911
|
function ConnectionHandles({ node, theme, onHandlePointerDown, immediate, activeSide }) {
|
|
17972
|
-
const [visible, setVisible] = (0,
|
|
17973
|
-
const [hoveredSide, setHoveredSide] = (0,
|
|
17974
|
-
(0,
|
|
18912
|
+
const [visible, setVisible] = (0, import_react14.useState)(!!immediate);
|
|
18913
|
+
const [hoveredSide, setHoveredSide] = (0, import_react14.useState)(null);
|
|
18914
|
+
(0, import_react14.useEffect)(() => {
|
|
17975
18915
|
if (immediate) {
|
|
17976
18916
|
setVisible(true);
|
|
17977
18917
|
return;
|
|
@@ -17982,16 +18922,16 @@ var SystemCanvas = (() => {
|
|
|
17982
18922
|
}, [node.id, immediate]);
|
|
17983
18923
|
const handleColor = node.resolvedStroke ?? theme.node.labelColor;
|
|
17984
18924
|
const sidesToRender = immediate ? SIDES : activeSide ? [activeSide] : [];
|
|
17985
|
-
return (0,
|
|
18925
|
+
return (0, import_jsx_runtime19.jsx)("g", { className: "system-canvas-connection-handles", pointerEvents: "auto", style: {
|
|
17986
18926
|
opacity: visible ? 1 : 0,
|
|
17987
18927
|
transition: `opacity ${FADE_DURATION_MS}ms ease-out`
|
|
17988
18928
|
}, children: sidesToRender.map((side) => {
|
|
17989
18929
|
const { x, y } = computeAnchorPoint(node, side);
|
|
17990
18930
|
const isHovered = hoveredSide === side;
|
|
17991
|
-
return (0,
|
|
18931
|
+
return (0, import_jsx_runtime19.jsxs)("g", { style: { cursor: "crosshair" }, onPointerEnter: () => setHoveredSide(side), onPointerLeave: () => setHoveredSide((s) => s === side ? null : s), onPointerDown: (e) => {
|
|
17992
18932
|
e.stopPropagation();
|
|
17993
18933
|
onHandlePointerDown(node, side, e);
|
|
17994
|
-
}, children: [(0,
|
|
18934
|
+
}, 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
18935
|
// Scale around the handle's own center. CSS transforms on
|
|
17996
18936
|
// SVG elements use the element's user-space origin by
|
|
17997
18937
|
// default, so we set transform-origin explicitly.
|
|
@@ -18003,7 +18943,7 @@ var SystemCanvas = (() => {
|
|
|
18003
18943
|
}
|
|
18004
18944
|
|
|
18005
18945
|
// ../react/dist/components/PendingEdgeRenderer.js
|
|
18006
|
-
var
|
|
18946
|
+
var import_jsx_runtime20 = __toESM(require_jsx_runtime(), 1);
|
|
18007
18947
|
function PendingEdgeRenderer({ sourceNode, sourceSide, cursor, targetNode, theme, defaultEdgeStyle }) {
|
|
18008
18948
|
const endNode = targetNode ?? {
|
|
18009
18949
|
id: "__pending__",
|
|
@@ -18025,11 +18965,11 @@ var SystemCanvas = (() => {
|
|
|
18025
18965
|
toNode: endNode.id
|
|
18026
18966
|
};
|
|
18027
18967
|
const pathD = computeEdgePath(pendingEdge, sourceNode, endNode, defaultEdgeStyle);
|
|
18028
|
-
return (0,
|
|
18968
|
+
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
18969
|
}
|
|
18030
18970
|
|
|
18031
18971
|
// ../react/dist/components/LanesBackground.js
|
|
18032
|
-
var
|
|
18972
|
+
var import_jsx_runtime21 = __toESM(require_jsx_runtime(), 1);
|
|
18033
18973
|
var LANE_EXTENT = 1e5;
|
|
18034
18974
|
function LanesBackground({ columns, rows, theme }) {
|
|
18035
18975
|
const hasColumns = columns && columns.length > 0;
|
|
@@ -18044,31 +18984,31 @@ var SystemCanvas = (() => {
|
|
|
18044
18984
|
}
|
|
18045
18985
|
return index % 2 === 0 ? lanesTheme.bandFillEven : lanesTheme.bandFillOdd;
|
|
18046
18986
|
};
|
|
18047
|
-
return (0,
|
|
18987
|
+
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
18988
|
if (i === 0)
|
|
18049
18989
|
return null;
|
|
18050
|
-
return (0,
|
|
18990
|
+
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
18991
|
}), hasColumns && columns.map((col, i) => {
|
|
18052
18992
|
if (i === 0)
|
|
18053
18993
|
return null;
|
|
18054
|
-
return (0,
|
|
18994
|
+
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
18995
|
})] });
|
|
18056
18996
|
}
|
|
18057
18997
|
|
|
18058
18998
|
// ../react/dist/components/Viewport.js
|
|
18059
18999
|
var HOVER_PADDING = 10;
|
|
18060
19000
|
var EDGE_PROXIMITY = 16;
|
|
18061
|
-
var Viewport = (0,
|
|
19001
|
+
var Viewport = (0, import_react15.forwardRef)(function Viewport2({ nodes, edges, nodeMap, theme, edgeStyle, columns, rows, canvases, minZoom, maxZoom, defaultViewport, onViewportChange, onNodeClick, onNodeDoubleClick, onNodeNavigate, onEdgeClick, onEdgeDoubleClick, onCanvasClick, onCanvasContextMenu, onNodeContextMenu, onEdgeContextMenu, onNodePointerDown, selectedId, editingId, selectedEdgeId, editingEdgeId, dragOverrides, resizeOverrides, onResizeHandlePointerDown, onEditorCommit, onEditorCancel, onEdgeEditorCommit, onEdgeEditorCancel, pendingEdge, onConnectionHandlePointerDown, edgeCreateEnabled, autoFit = "canvas-change", canvasRef, handoffTransform, onHandoffApplied, handoffFadeMs = 0 }, ref) {
|
|
18062
19002
|
const { svgRef, groupRef, viewport, fitToContent, zoomToNode, setTransform } = useViewport({
|
|
18063
19003
|
minZoom,
|
|
18064
19004
|
maxZoom,
|
|
18065
19005
|
defaultViewport,
|
|
18066
19006
|
onViewportChange
|
|
18067
19007
|
});
|
|
18068
|
-
const navigatingRef = (0,
|
|
18069
|
-
const fadeRafRef = (0,
|
|
18070
|
-
const fadeTimeoutRef = (0,
|
|
18071
|
-
const triggerFade = (0,
|
|
19008
|
+
const navigatingRef = (0, import_react15.useRef)(false);
|
|
19009
|
+
const fadeRafRef = (0, import_react15.useRef)(null);
|
|
19010
|
+
const fadeTimeoutRef = (0, import_react15.useRef)(null);
|
|
19011
|
+
const triggerFade = (0, import_react15.useCallback)((durationMs) => {
|
|
18072
19012
|
if (durationMs <= 0)
|
|
18073
19013
|
return;
|
|
18074
19014
|
const g = groupRef.current;
|
|
@@ -18091,7 +19031,7 @@ var SystemCanvas = (() => {
|
|
|
18091
19031
|
}, durationMs + 16);
|
|
18092
19032
|
});
|
|
18093
19033
|
}, []);
|
|
18094
|
-
(0,
|
|
19034
|
+
(0, import_react15.useEffect)(() => {
|
|
18095
19035
|
return () => {
|
|
18096
19036
|
if (fadeRafRef.current !== null)
|
|
18097
19037
|
cancelAnimationFrame(fadeRafRef.current);
|
|
@@ -18099,9 +19039,9 @@ var SystemCanvas = (() => {
|
|
|
18099
19039
|
clearTimeout(fadeTimeoutRef.current);
|
|
18100
19040
|
};
|
|
18101
19041
|
}, []);
|
|
18102
|
-
const [hoveredNodeId, setHoveredNodeId] = (0,
|
|
18103
|
-
const [hoveredSide, setHoveredSide] = (0,
|
|
18104
|
-
(0,
|
|
19042
|
+
const [hoveredNodeId, setHoveredNodeId] = (0, import_react15.useState)(null);
|
|
19043
|
+
const [hoveredSide, setHoveredSide] = (0, import_react15.useState)(null);
|
|
19044
|
+
(0, import_react15.useImperativeHandle)(ref, () => ({
|
|
18105
19045
|
zoomToNode: (node, onComplete, options) => {
|
|
18106
19046
|
navigatingRef.current = true;
|
|
18107
19047
|
zoomToNode(node, onComplete, options);
|
|
@@ -18111,7 +19051,7 @@ var SystemCanvas = (() => {
|
|
|
18111
19051
|
getSvgElement: () => svgRef.current,
|
|
18112
19052
|
getViewport: () => viewport.current ?? { x: 0, y: 0, zoom: 1 }
|
|
18113
19053
|
}));
|
|
18114
|
-
const renderNodes = (0,
|
|
19054
|
+
const renderNodes = (0, import_react15.useMemo)(() => {
|
|
18115
19055
|
const hasDrag = dragOverrides && dragOverrides.size > 0;
|
|
18116
19056
|
const hasResize = resizeOverrides && resizeOverrides.size > 0;
|
|
18117
19057
|
if (!hasDrag && !hasResize)
|
|
@@ -18124,7 +19064,7 @@ var SystemCanvas = (() => {
|
|
|
18124
19064
|
return d ? { ...n, x: d.x, y: d.y } : n;
|
|
18125
19065
|
});
|
|
18126
19066
|
}, [nodes, dragOverrides, resizeOverrides]);
|
|
18127
|
-
const renderNodeMap = (0,
|
|
19067
|
+
const renderNodeMap = (0, import_react15.useMemo)(() => {
|
|
18128
19068
|
const hasDrag = dragOverrides && dragOverrides.size > 0;
|
|
18129
19069
|
const hasResize = resizeOverrides && resizeOverrides.size > 0;
|
|
18130
19070
|
if (!hasDrag && !hasResize)
|
|
@@ -18135,11 +19075,11 @@ var SystemCanvas = (() => {
|
|
|
18135
19075
|
}
|
|
18136
19076
|
return m;
|
|
18137
19077
|
}, [renderNodes, nodeMap, dragOverrides, resizeOverrides]);
|
|
18138
|
-
const latestNodesRef = (0,
|
|
18139
|
-
(0,
|
|
19078
|
+
const latestNodesRef = (0, import_react15.useRef)(nodes);
|
|
19079
|
+
(0, import_react15.useEffect)(() => {
|
|
18140
19080
|
latestNodesRef.current = nodes;
|
|
18141
19081
|
}, [nodes]);
|
|
18142
|
-
const fitNow = (0,
|
|
19082
|
+
const fitNow = (0, import_react15.useCallback)(() => {
|
|
18143
19083
|
const current = latestNodesRef.current;
|
|
18144
19084
|
if (current.length === 0)
|
|
18145
19085
|
return;
|
|
@@ -18149,7 +19089,7 @@ var SystemCanvas = (() => {
|
|
|
18149
19089
|
fitToContent(current, animate);
|
|
18150
19090
|
});
|
|
18151
19091
|
}, [fitToContent]);
|
|
18152
|
-
(0,
|
|
19092
|
+
(0, import_react15.useEffect)(() => {
|
|
18153
19093
|
if (defaultViewport)
|
|
18154
19094
|
return;
|
|
18155
19095
|
if (autoFit !== "always")
|
|
@@ -18158,8 +19098,8 @@ var SystemCanvas = (() => {
|
|
|
18158
19098
|
return;
|
|
18159
19099
|
fitNow();
|
|
18160
19100
|
}, [nodes, autoFit, defaultViewport, fitNow]);
|
|
18161
|
-
const fittedForRef = (0,
|
|
18162
|
-
(0,
|
|
19101
|
+
const fittedForRef = (0, import_react15.useRef)(null);
|
|
19102
|
+
(0, import_react15.useEffect)(() => {
|
|
18163
19103
|
if (defaultViewport)
|
|
18164
19104
|
return;
|
|
18165
19105
|
if (autoFit !== "canvas-change" && autoFit !== "initial")
|
|
@@ -18191,7 +19131,7 @@ var SystemCanvas = (() => {
|
|
|
18191
19131
|
triggerFade
|
|
18192
19132
|
]);
|
|
18193
19133
|
const editingNode = editingId ? renderNodes.find((n) => n.id === editingId) ?? null : null;
|
|
18194
|
-
const handleSvgPointerMove = (0,
|
|
19134
|
+
const handleSvgPointerMove = (0, import_react15.useCallback)((event) => {
|
|
18195
19135
|
if (!edgeCreateEnabled)
|
|
18196
19136
|
return;
|
|
18197
19137
|
const svg = svgRef.current;
|
|
@@ -18240,7 +19180,7 @@ var SystemCanvas = (() => {
|
|
|
18240
19180
|
setHoveredSide((prev) => prev === null ? prev : null);
|
|
18241
19181
|
}
|
|
18242
19182
|
}, [edgeCreateEnabled, renderNodes, svgRef, viewport]);
|
|
18243
|
-
const handleSvgPointerLeave = (0,
|
|
19183
|
+
const handleSvgPointerLeave = (0, import_react15.useCallback)(() => {
|
|
18244
19184
|
setHoveredNodeId(null);
|
|
18245
19185
|
setHoveredSide(null);
|
|
18246
19186
|
}, []);
|
|
@@ -18258,7 +19198,7 @@ var SystemCanvas = (() => {
|
|
|
18258
19198
|
return null;
|
|
18259
19199
|
return computeEdgeMidpoint(editingEdge, from, to);
|
|
18260
19200
|
})();
|
|
18261
|
-
return (0,
|
|
19201
|
+
return (0, import_jsx_runtime22.jsxs)("svg", { ref: svgRef, className: "system-canvas-viewport", style: {
|
|
18262
19202
|
width: "100%",
|
|
18263
19203
|
height: "100%",
|
|
18264
19204
|
display: "block",
|
|
@@ -18267,16 +19207,16 @@ var SystemCanvas = (() => {
|
|
|
18267
19207
|
WebkitUserSelect: "none",
|
|
18268
19208
|
MozUserSelect: "none",
|
|
18269
19209
|
msUserSelect: "none"
|
|
18270
|
-
}, onClick: onCanvasClick, onContextMenu: onCanvasContextMenu, onPointerMove: handleSvgPointerMove, onPointerLeave: handleSvgPointerLeave, children: [(0,
|
|
19210
|
+
}, onClick: onCanvasClick, onContextMenu: onCanvasContextMenu, onPointerMove: handleSvgPointerMove, onPointerLeave: handleSvgPointerLeave, children: [(0, import_jsx_runtime22.jsx)("defs", { children: (0, import_jsx_runtime22.jsx)("pattern", { id: "system-canvas-grid", width: theme.grid.size, height: theme.grid.size, patternUnits: "userSpaceOnUse", children: (0, import_jsx_runtime22.jsx)("path", { d: `M ${theme.grid.size} 0 L 0 0 0 ${theme.grid.size}`, fill: "none", stroke: theme.grid.color, strokeWidth: theme.grid.strokeWidth }) }) }), (0, import_jsx_runtime22.jsx)("rect", { x: "-50000", y: "-50000", width: "100000", height: "100000", fill: "url(#system-canvas-grid)" }), (0, import_jsx_runtime22.jsxs)("g", { ref: groupRef, children: [(0, import_jsx_runtime22.jsx)(LanesBackground, { columns, rows, theme }), (0, import_jsx_runtime22.jsx)(NodeRenderer, { nodes: renderNodes, theme, onClick: onNodeClick, onDoubleClick: onNodeDoubleClick, onContextMenu: onNodeContextMenu, onNavigate: onNodeNavigate, onPointerDown: onNodePointerDown, selectedId, editingId, canvases, only: "groups" }), (0, import_jsx_runtime22.jsx)(EdgeRenderer, { edges, nodeMap: renderNodeMap, theme, defaultEdgeStyle: edgeStyle, onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, selectedId: selectedEdgeId, editingId: editingEdgeId }), (0, import_jsx_runtime22.jsx)(NodeRenderer, { nodes: renderNodes, theme, onClick: onNodeClick, onDoubleClick: onNodeDoubleClick, onContextMenu: onNodeContextMenu, onNavigate: onNodeNavigate, onPointerDown: onNodePointerDown, selectedId, editingId, onResizeHandlePointerDown, canvases, only: "non-groups" }), pendingTargetNode && (0, import_jsx_runtime22.jsx)("rect", { className: "system-canvas-drop-target", x: pendingTargetNode.x - 4, y: pendingTargetNode.y - 4, width: pendingTargetNode.width + 8, height: pendingTargetNode.height + 8, rx: pendingTargetNode.resolvedCornerRadius + 4, fill: "none", stroke: theme.node.labelColor, strokeWidth: 2, opacity: 0.85, pointerEvents: "none" }), pendingEdge && pendingSourceNode && (0, import_jsx_runtime22.jsx)(PendingEdgeRenderer, { sourceNode: pendingSourceNode, sourceSide: pendingEdge.sourceSide, cursor: pendingEdge.cursor, targetNode: pendingTargetNode, theme, defaultEdgeStyle: edgeStyle }), handlesNode && onConnectionHandlePointerDown && (0, import_jsx_runtime22.jsx)(ConnectionHandles, { node: handlesNode, theme, onHandlePointerDown: onConnectionHandlePointerDown, immediate: !!pendingEdge, activeSide: hoveredSide }), editingNode && onEditorCommit && onEditorCancel && (0, import_jsx_runtime22.jsx)(NodeEditor, { node: editingNode, theme, onCommit: onEditorCommit, onCancel: onEditorCancel }), editingEdge && editingEdgeMidpoint && onEdgeEditorCommit && onEdgeEditorCancel && (0, import_jsx_runtime22.jsx)(EdgeLabelEditor, { initialLabel: editingEdge.label ?? "", midpoint: editingEdgeMidpoint, theme, onCommit: onEdgeEditorCommit, onCancel: onEdgeEditorCancel })] })] });
|
|
18271
19211
|
});
|
|
18272
19212
|
|
|
18273
19213
|
// ../react/dist/components/Breadcrumbs.js
|
|
18274
|
-
var
|
|
18275
|
-
var
|
|
19214
|
+
var import_jsx_runtime23 = __toESM(require_jsx_runtime(), 1);
|
|
19215
|
+
var import_react16 = __toESM(require_react(), 1);
|
|
18276
19216
|
function Breadcrumbs({ breadcrumbs, theme, onNavigate }) {
|
|
18277
19217
|
if (breadcrumbs.length <= 1)
|
|
18278
19218
|
return null;
|
|
18279
|
-
return (0,
|
|
19219
|
+
return (0, import_jsx_runtime23.jsx)("div", { className: "system-canvas-breadcrumbs", style: {
|
|
18280
19220
|
position: "absolute",
|
|
18281
19221
|
top: 12,
|
|
18282
19222
|
left: 12,
|
|
@@ -18293,10 +19233,10 @@ var SystemCanvas = (() => {
|
|
|
18293
19233
|
backdropFilter: "blur(8px)"
|
|
18294
19234
|
}, children: breadcrumbs.map((crumb, index) => {
|
|
18295
19235
|
const isLast = index === breadcrumbs.length - 1;
|
|
18296
|
-
return (0,
|
|
19236
|
+
return (0, import_jsx_runtime23.jsxs)(import_react16.default.Fragment, { children: [index > 0 && (0, import_jsx_runtime23.jsx)("span", { style: {
|
|
18297
19237
|
color: theme.separatorColor,
|
|
18298
19238
|
margin: "0 2px"
|
|
18299
|
-
}, children: "/" }), (0,
|
|
19239
|
+
}, children: "/" }), (0, import_jsx_runtime23.jsx)("span", { onClick: isLast ? void 0 : () => onNavigate(index), style: {
|
|
18300
19240
|
color: isLast ? theme.activeColor : theme.textColor,
|
|
18301
19241
|
cursor: isLast ? "default" : "pointer",
|
|
18302
19242
|
fontWeight: isLast ? 600 : 400,
|
|
@@ -18316,12 +19256,12 @@ var SystemCanvas = (() => {
|
|
|
18316
19256
|
}
|
|
18317
19257
|
|
|
18318
19258
|
// ../react/dist/components/AddNodeButton.js
|
|
18319
|
-
var
|
|
18320
|
-
var
|
|
19259
|
+
var import_jsx_runtime24 = __toESM(require_jsx_runtime(), 1);
|
|
19260
|
+
var import_react17 = __toESM(require_react(), 1);
|
|
18321
19261
|
function AddNodeButton({ options, addNode: addNode2, theme }) {
|
|
18322
|
-
const [open, setOpen] = (0,
|
|
18323
|
-
const rootRef = (0,
|
|
18324
|
-
(0,
|
|
19262
|
+
const [open, setOpen] = (0, import_react17.useState)(false);
|
|
19263
|
+
const rootRef = (0, import_react17.useRef)(null);
|
|
19264
|
+
(0, import_react17.useEffect)(() => {
|
|
18325
19265
|
if (!open)
|
|
18326
19266
|
return;
|
|
18327
19267
|
function onDocClick(e) {
|
|
@@ -18344,7 +19284,7 @@ var SystemCanvas = (() => {
|
|
|
18344
19284
|
}, [open]);
|
|
18345
19285
|
const categoryOptions = options.filter((o) => o.kind === "category");
|
|
18346
19286
|
const typeOptions = options.filter((o) => o.kind === "type");
|
|
18347
|
-
return (0,
|
|
19287
|
+
return (0, import_jsx_runtime24.jsxs)("div", { ref: rootRef, className: "system-canvas-add-node", style: {
|
|
18348
19288
|
position: "absolute",
|
|
18349
19289
|
bottom: 16,
|
|
18350
19290
|
right: 16,
|
|
@@ -18352,7 +19292,7 @@ var SystemCanvas = (() => {
|
|
|
18352
19292
|
fontFamily: theme.breadcrumbs.fontFamily,
|
|
18353
19293
|
fontSize: theme.breadcrumbs.fontSize,
|
|
18354
19294
|
userSelect: "none"
|
|
18355
|
-
}, children: [open && (0,
|
|
19295
|
+
}, children: [open && (0, import_jsx_runtime24.jsxs)("div", { style: {
|
|
18356
19296
|
position: "absolute",
|
|
18357
19297
|
bottom: 52,
|
|
18358
19298
|
right: 0,
|
|
@@ -18365,13 +19305,13 @@ var SystemCanvas = (() => {
|
|
|
18365
19305
|
borderRadius: 10,
|
|
18366
19306
|
boxShadow: "0 8px 24px rgba(0,0,0,0.35)",
|
|
18367
19307
|
backdropFilter: "blur(10px)"
|
|
18368
|
-
}, children: [categoryOptions.length > 0 && (0,
|
|
19308
|
+
}, 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
19309
|
addNode2(opt);
|
|
18370
19310
|
setOpen(false);
|
|
18371
|
-
} }, `cat-${opt.value}`)), (0,
|
|
19311
|
+
} }, `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
19312
|
addNode2(opt);
|
|
18373
19313
|
setOpen(false);
|
|
18374
|
-
} }, `type-${opt.value}`))] }), (0,
|
|
19314
|
+
} }, `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
19315
|
width: 44,
|
|
18376
19316
|
height: 44,
|
|
18377
19317
|
borderRadius: 22,
|
|
@@ -18392,7 +19332,7 @@ var SystemCanvas = (() => {
|
|
|
18392
19332
|
}, children: "+" })] });
|
|
18393
19333
|
}
|
|
18394
19334
|
function SectionLabel({ theme, children: children2 }) {
|
|
18395
|
-
return (0,
|
|
19335
|
+
return (0, import_jsx_runtime24.jsx)("div", { style: {
|
|
18396
19336
|
padding: "4px 8px",
|
|
18397
19337
|
fontSize: theme.breadcrumbs.fontSize - 2,
|
|
18398
19338
|
color: theme.breadcrumbs.textColor,
|
|
@@ -18402,7 +19342,7 @@ var SystemCanvas = (() => {
|
|
|
18402
19342
|
}, children: children2 });
|
|
18403
19343
|
}
|
|
18404
19344
|
function Divider({ theme }) {
|
|
18405
|
-
return (0,
|
|
19345
|
+
return (0, import_jsx_runtime24.jsx)("div", { style: {
|
|
18406
19346
|
height: 1,
|
|
18407
19347
|
margin: "4px 0",
|
|
18408
19348
|
background: theme.breadcrumbs.separatorColor,
|
|
@@ -18410,9 +19350,9 @@ var SystemCanvas = (() => {
|
|
|
18410
19350
|
} });
|
|
18411
19351
|
}
|
|
18412
19352
|
function MenuRow({ theme, option, onClick }) {
|
|
18413
|
-
const [hover, setHover] = (0,
|
|
19353
|
+
const [hover, setHover] = (0, import_react17.useState)(false);
|
|
18414
19354
|
const swatchSize = 18;
|
|
18415
|
-
return (0,
|
|
19355
|
+
return (0, import_jsx_runtime24.jsxs)("div", { role: "button", onClick, onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: {
|
|
18416
19356
|
display: "flex",
|
|
18417
19357
|
alignItems: "center",
|
|
18418
19358
|
gap: 8,
|
|
@@ -18421,7 +19361,7 @@ var SystemCanvas = (() => {
|
|
|
18421
19361
|
cursor: "pointer",
|
|
18422
19362
|
background: hover ? "rgba(255,255,255,0.06)" : "transparent",
|
|
18423
19363
|
color: theme.breadcrumbs.activeColor
|
|
18424
|
-
}, children: [option.kind === "category" ? (0,
|
|
19364
|
+
}, children: [option.kind === "category" ? (0, import_jsx_runtime24.jsx)("span", { style: {
|
|
18425
19365
|
width: swatchSize,
|
|
18426
19366
|
height: swatchSize,
|
|
18427
19367
|
borderRadius: 4,
|
|
@@ -18431,13 +19371,13 @@ var SystemCanvas = (() => {
|
|
|
18431
19371
|
alignItems: "center",
|
|
18432
19372
|
justifyContent: "center",
|
|
18433
19373
|
flexShrink: 0
|
|
18434
|
-
}, children: option.icon && (0,
|
|
19374
|
+
}, 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
19375
|
width: swatchSize,
|
|
18436
19376
|
height: swatchSize,
|
|
18437
19377
|
borderRadius: 4,
|
|
18438
19378
|
border: `1px dashed ${theme.breadcrumbs.separatorColor}`,
|
|
18439
19379
|
flexShrink: 0
|
|
18440
|
-
} }), (0,
|
|
19380
|
+
} }), (0, import_jsx_runtime24.jsx)("span", { style: { textTransform: "capitalize" }, children: option.label }), (0, import_jsx_runtime24.jsx)("span", { style: {
|
|
18441
19381
|
marginLeft: "auto",
|
|
18442
19382
|
fontSize: theme.breadcrumbs.fontSize - 2,
|
|
18443
19383
|
opacity: 0.5
|
|
@@ -18445,13 +19385,13 @@ var SystemCanvas = (() => {
|
|
|
18445
19385
|
}
|
|
18446
19386
|
|
|
18447
19387
|
// ../react/dist/components/LaneHeaders.js
|
|
18448
|
-
var
|
|
18449
|
-
var
|
|
19388
|
+
var import_jsx_runtime25 = __toESM(require_jsx_runtime(), 1);
|
|
19389
|
+
var import_react18 = __toESM(require_react(), 1);
|
|
18450
19390
|
function LaneHeaders({ columns, rows, theme, getViewport, width, height, pinned = true }) {
|
|
18451
19391
|
const hasColumns = columns && columns.length > 0;
|
|
18452
19392
|
const hasRows = rows && rows.length > 0;
|
|
18453
|
-
const [viewport, setViewport] = (0,
|
|
18454
|
-
(0,
|
|
19393
|
+
const [viewport, setViewport] = (0, import_react18.useState)(() => getViewport());
|
|
19394
|
+
(0, import_react18.useEffect)(() => {
|
|
18455
19395
|
if (!hasColumns && !hasRows)
|
|
18456
19396
|
return;
|
|
18457
19397
|
let raf = 0;
|
|
@@ -18478,14 +19418,14 @@ var SystemCanvas = (() => {
|
|
|
18478
19418
|
const pad = lanesTheme.headerPadding;
|
|
18479
19419
|
const colsOffsetLeft = hasRows && pinned ? headerSize : 0;
|
|
18480
19420
|
const rowsOffsetTop = hasColumns && pinned ? headerSize : 0;
|
|
18481
|
-
return (0,
|
|
19421
|
+
return (0, import_jsx_runtime25.jsxs)("svg", { className: "system-canvas-lane-headers", style: {
|
|
18482
19422
|
position: "absolute",
|
|
18483
19423
|
top: 0,
|
|
18484
19424
|
left: 0,
|
|
18485
19425
|
width,
|
|
18486
19426
|
height,
|
|
18487
19427
|
pointerEvents: "none"
|
|
18488
|
-
}, children: [hasColumns && (0,
|
|
19428
|
+
}, 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
19429
|
const startScreen = canvasToScreen(col.start, 0, viewport).x;
|
|
18490
19430
|
const endScreen = canvasToScreen(col.start + col.size, 0, viewport).x;
|
|
18491
19431
|
const w = endScreen - startScreen;
|
|
@@ -18496,8 +19436,8 @@ var SystemCanvas = (() => {
|
|
|
18496
19436
|
const cx = visibleLeft + visibleW / 2;
|
|
18497
19437
|
if (endScreen <= colsOffsetLeft || startScreen >= width)
|
|
18498
19438
|
return null;
|
|
18499
|
-
return (0,
|
|
18500
|
-
}), pinned && (0,
|
|
19439
|
+
return (0, import_jsx_runtime25.jsxs)("g", { children: [(0, import_jsx_runtime25.jsx)("line", { x1: startScreen, y1: pinned ? headerSize : y + headerSize, x2: startScreen, y2: pinned ? 0 : y, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth }), (0, import_jsx_runtime25.jsx)("text", { x: cx, y: (pinned ? 0 : y) + headerSize / 2, textAnchor: "middle", dominantBaseline: "middle", fill: lanesTheme.headerTextColor, fontFamily: lanesTheme.headerFontFamily, fontSize: lanesTheme.headerFontSize, style: { userSelect: "none" }, children: truncateToWidth(col.label, visibleW - pad * 2, lanesTheme.headerFontSize) })] }, `colh-${col.id}`);
|
|
19440
|
+
}), 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
19441
|
const startScreen = canvasToScreen(0, row.start, viewport).y;
|
|
18502
19442
|
const endScreen = canvasToScreen(0, row.start + row.size, viewport).y;
|
|
18503
19443
|
const h = endScreen - startScreen;
|
|
@@ -18508,8 +19448,8 @@ var SystemCanvas = (() => {
|
|
|
18508
19448
|
const cy = visibleTop + visibleH / 2;
|
|
18509
19449
|
if (endScreen <= rowsOffsetTop || startScreen >= height)
|
|
18510
19450
|
return null;
|
|
18511
|
-
return (0,
|
|
18512
|
-
}), pinned && (0,
|
|
19451
|
+
return (0, import_jsx_runtime25.jsxs)("g", { children: [(0, import_jsx_runtime25.jsx)("line", { x1: pinned ? 0 : x, y1: startScreen, x2: pinned ? headerSize : x + headerSize, y2: startScreen, stroke: lanesTheme.dividerColor, strokeWidth: lanesTheme.dividerWidth }), (0, import_jsx_runtime25.jsx)("text", { x: (pinned ? 0 : x) + headerSize / 2, y: cy, textAnchor: "middle", dominantBaseline: "middle", fill: lanesTheme.headerTextColor, fontFamily: lanesTheme.headerFontFamily, fontSize: lanesTheme.headerFontSize, transform: `rotate(-90 ${(pinned ? 0 : x) + headerSize / 2} ${cy})`, style: { userSelect: "none" }, children: truncateToWidth(row.label, visibleH - pad * 2, lanesTheme.headerFontSize) })] }, `rowh-${row.id}`);
|
|
19452
|
+
}), 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
19453
|
}
|
|
18514
19454
|
function truncateToWidth(label, availablePx, fontSize) {
|
|
18515
19455
|
if (availablePx <= 0)
|
|
@@ -18524,8 +19464,8 @@ var SystemCanvas = (() => {
|
|
|
18524
19464
|
}
|
|
18525
19465
|
|
|
18526
19466
|
// ../react/dist/components/NodeToolbar.js
|
|
18527
|
-
var
|
|
18528
|
-
var
|
|
19467
|
+
var import_jsx_runtime26 = __toESM(require_jsx_runtime(), 1);
|
|
19468
|
+
var import_react19 = __toESM(require_react(), 1);
|
|
18529
19469
|
var NODE_GAP = 10;
|
|
18530
19470
|
var FLIP_MARGIN = 8;
|
|
18531
19471
|
var PADDING = 6;
|
|
@@ -18534,8 +19474,8 @@ var SystemCanvas = (() => {
|
|
|
18534
19474
|
var BUTTON_SIZE = 28;
|
|
18535
19475
|
var DELETE_SIZE = 14;
|
|
18536
19476
|
function NodeToolbar({ node, theme, onPatch, onDelete, getViewport, containerWidth, containerHeight, render: render2 }) {
|
|
18537
|
-
const [viewport, setViewport] = (0,
|
|
18538
|
-
(0,
|
|
19477
|
+
const [viewport, setViewport] = (0, import_react19.useState)(() => getViewport());
|
|
19478
|
+
(0, import_react19.useEffect)(() => {
|
|
18539
19479
|
let raf = 0;
|
|
18540
19480
|
let lastX = -Infinity;
|
|
18541
19481
|
let lastY = -Infinity;
|
|
@@ -18555,9 +19495,9 @@ var SystemCanvas = (() => {
|
|
|
18555
19495
|
}, [getViewport]);
|
|
18556
19496
|
const topCenter = canvasToScreen(node.x + node.width / 2, node.y, viewport);
|
|
18557
19497
|
const bottomCenter = canvasToScreen(node.x + node.width / 2, node.y + node.height, viewport);
|
|
18558
|
-
const toolbarRef = (0,
|
|
18559
|
-
const [size, setSize] = (0,
|
|
18560
|
-
(0,
|
|
19498
|
+
const toolbarRef = (0, import_react19.useRef)(null);
|
|
19499
|
+
const [size, setSize] = (0, import_react19.useState)({ width: 0, height: 0 });
|
|
19500
|
+
(0, import_react19.useEffect)(() => {
|
|
18561
19501
|
const el = toolbarRef.current;
|
|
18562
19502
|
if (!el)
|
|
18563
19503
|
return;
|
|
@@ -18578,7 +19518,7 @@ var SystemCanvas = (() => {
|
|
|
18578
19518
|
left = Math.max(FLIP_MARGIN, Math.min(left, containerWidth - size.width - FLIP_MARGIN));
|
|
18579
19519
|
const patch = (update) => onPatch(update);
|
|
18580
19520
|
const deleteNode = () => onDelete();
|
|
18581
|
-
return (0,
|
|
19521
|
+
return (0, import_jsx_runtime26.jsx)("div", {
|
|
18582
19522
|
ref: toolbarRef,
|
|
18583
19523
|
className: "system-canvas-node-toolbar",
|
|
18584
19524
|
// Stop pointer events from bubbling to the canvas (which would
|
|
@@ -18607,15 +19547,16 @@ var SystemCanvas = (() => {
|
|
|
18607
19547
|
userSelect: "none",
|
|
18608
19548
|
whiteSpace: "nowrap"
|
|
18609
19549
|
},
|
|
18610
|
-
children: render2 ? render2({ node, theme, patch, deleteNode }) : (0,
|
|
19550
|
+
children: render2 ? render2({ node, theme, patch, deleteNode }) : (0, import_jsx_runtime26.jsx)(DefaultToolbarContent, { node, theme, onPatch: patch, onDelete: deleteNode })
|
|
18611
19551
|
});
|
|
18612
19552
|
}
|
|
18613
19553
|
function DefaultToolbarContent({ node, theme, onPatch, onDelete }) {
|
|
18614
|
-
const groups = (0,
|
|
18615
|
-
|
|
19554
|
+
const groups = (0, import_react19.useMemo)(() => getNodeActionsForNode(node, theme), [node, theme]);
|
|
19555
|
+
const showDelete = !theme.hideToolbarDelete;
|
|
19556
|
+
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
19557
|
}
|
|
18617
19558
|
function Divider2({ theme }) {
|
|
18618
|
-
return (0,
|
|
19559
|
+
return (0, import_jsx_runtime26.jsx)("div", { style: {
|
|
18619
19560
|
width: 1,
|
|
18620
19561
|
alignSelf: "stretch",
|
|
18621
19562
|
background: theme.breadcrumbs.separatorColor,
|
|
@@ -18628,23 +19569,23 @@ var SystemCanvas = (() => {
|
|
|
18628
19569
|
return null;
|
|
18629
19570
|
const kind = group.kind ?? "buttons";
|
|
18630
19571
|
if (kind === "menu") {
|
|
18631
|
-
return (0,
|
|
19572
|
+
return (0, import_jsx_runtime26.jsx)(MenuGroup, { group, actions, node, theme, onPatch });
|
|
18632
19573
|
}
|
|
18633
|
-
return (0,
|
|
19574
|
+
return (0, import_jsx_runtime26.jsx)("div", { title: group.label, style: { display: "flex", alignItems: "center", gap: BUTTON_GAP }, children: actions.map((action) => {
|
|
18634
19575
|
const handleClick = () => {
|
|
18635
19576
|
const patch = resolveActionPatch(action, node);
|
|
18636
19577
|
onPatch(patch);
|
|
18637
19578
|
};
|
|
18638
19579
|
const active = action.isActive?.(node) ?? false;
|
|
18639
19580
|
if (kind === "swatches") {
|
|
18640
|
-
return (0,
|
|
19581
|
+
return (0, import_jsx_runtime26.jsx)(SwatchButton, { action, active, theme, onClick: handleClick }, action.id);
|
|
18641
19582
|
}
|
|
18642
|
-
return (0,
|
|
19583
|
+
return (0, import_jsx_runtime26.jsx)(IconButton, { action, active, theme, onClick: handleClick }, action.id);
|
|
18643
19584
|
}) });
|
|
18644
19585
|
}
|
|
18645
19586
|
function SwatchButton({ action, active, theme, onClick }) {
|
|
18646
19587
|
const color2 = action.swatch ?? theme.node.labelColor;
|
|
18647
|
-
return (0,
|
|
19588
|
+
return (0, import_jsx_runtime26.jsx)("button", { type: "button", title: action.label, onClick, style: {
|
|
18648
19589
|
width: SWATCH_SIZE,
|
|
18649
19590
|
height: SWATCH_SIZE,
|
|
18650
19591
|
borderRadius: "50%",
|
|
@@ -18658,7 +19599,7 @@ var SystemCanvas = (() => {
|
|
|
18658
19599
|
}, onMouseDown: (e) => e.preventDefault() });
|
|
18659
19600
|
}
|
|
18660
19601
|
function IconButton({ action, active, theme, onClick }) {
|
|
18661
|
-
return (0,
|
|
19602
|
+
return (0, import_jsx_runtime26.jsx)("button", { type: "button", title: action.label, onClick, style: {
|
|
18662
19603
|
width: BUTTON_SIZE,
|
|
18663
19604
|
height: BUTTON_SIZE,
|
|
18664
19605
|
display: "inline-flex",
|
|
@@ -18671,17 +19612,17 @@ var SystemCanvas = (() => {
|
|
|
18671
19612
|
cursor: "pointer",
|
|
18672
19613
|
padding: 0,
|
|
18673
19614
|
outline: "none"
|
|
18674
|
-
}, onMouseDown: (e) => e.preventDefault(), children: action.icon ? (0,
|
|
19615
|
+
}, 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
19616
|
width: 10,
|
|
18676
19617
|
height: 10,
|
|
18677
19618
|
borderRadius: "50%",
|
|
18678
19619
|
background: action.swatch
|
|
18679
|
-
} }) : (0,
|
|
19620
|
+
} }) : (0, import_jsx_runtime26.jsx)("span", { style: { fontSize: 10 }, children: action.label.slice(0, 2) }) });
|
|
18680
19621
|
}
|
|
18681
19622
|
function MenuGroup({ group, actions, node, theme, onPatch }) {
|
|
18682
|
-
const [open, setOpen] = (0,
|
|
18683
|
-
const wrapRef = (0,
|
|
18684
|
-
(0,
|
|
19623
|
+
const [open, setOpen] = (0, import_react19.useState)(false);
|
|
19624
|
+
const wrapRef = (0, import_react19.useRef)(null);
|
|
19625
|
+
(0, import_react19.useEffect)(() => {
|
|
18685
19626
|
if (!open)
|
|
18686
19627
|
return;
|
|
18687
19628
|
const onDown = (e) => {
|
|
@@ -18694,7 +19635,7 @@ var SystemCanvas = (() => {
|
|
|
18694
19635
|
const active = actions.find((a) => a.isActive?.(node));
|
|
18695
19636
|
const triggerLabel = active?.label ?? group.label ?? "Menu";
|
|
18696
19637
|
const triggerIcon = active?.icon ?? void 0;
|
|
18697
|
-
return (0,
|
|
19638
|
+
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
19639
|
height: BUTTON_SIZE,
|
|
18699
19640
|
display: "inline-flex",
|
|
18700
19641
|
alignItems: "center",
|
|
@@ -18708,7 +19649,7 @@ var SystemCanvas = (() => {
|
|
|
18708
19649
|
fontFamily: "inherit",
|
|
18709
19650
|
fontSize: "inherit",
|
|
18710
19651
|
outline: "none"
|
|
18711
|
-
}, onMouseDown: (e) => e.preventDefault(), children: [triggerIcon && (0,
|
|
19652
|
+
}, 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
19653
|
position: "absolute",
|
|
18713
19654
|
top: "100%",
|
|
18714
19655
|
left: 0,
|
|
@@ -18723,7 +19664,7 @@ var SystemCanvas = (() => {
|
|
|
18723
19664
|
zIndex: 1
|
|
18724
19665
|
}, children: actions.map((action) => {
|
|
18725
19666
|
const isActive = action.isActive?.(node) ?? false;
|
|
18726
|
-
return (0,
|
|
19667
|
+
return (0, import_jsx_runtime26.jsxs)("button", { type: "button", onClick: () => {
|
|
18727
19668
|
onPatch(resolveActionPatch(action, node));
|
|
18728
19669
|
setOpen(false);
|
|
18729
19670
|
}, style: {
|
|
@@ -18740,17 +19681,17 @@ var SystemCanvas = (() => {
|
|
|
18740
19681
|
fontFamily: "inherit",
|
|
18741
19682
|
fontSize: "inherit",
|
|
18742
19683
|
textAlign: "left"
|
|
18743
|
-
}, onMouseDown: (e) => e.preventDefault(), children: [action.icon && (0,
|
|
19684
|
+
}, 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
19685
|
width: 10,
|
|
18745
19686
|
height: 10,
|
|
18746
19687
|
borderRadius: "50%",
|
|
18747
19688
|
background: action.swatch,
|
|
18748
19689
|
flexShrink: 0
|
|
18749
|
-
} }), (0,
|
|
19690
|
+
} }), (0, import_jsx_runtime26.jsx)("span", { children: action.label })] }, action.id);
|
|
18750
19691
|
}) })] });
|
|
18751
19692
|
}
|
|
18752
19693
|
function DeleteButton({ theme, onDelete }) {
|
|
18753
|
-
return (0,
|
|
19694
|
+
return (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Delete", onClick: onDelete, onMouseDown: (e) => e.preventDefault(), style: {
|
|
18754
19695
|
width: BUTTON_SIZE,
|
|
18755
19696
|
height: BUTTON_SIZE,
|
|
18756
19697
|
display: "inline-flex",
|
|
@@ -18763,21 +19704,21 @@ var SystemCanvas = (() => {
|
|
|
18763
19704
|
cursor: "pointer",
|
|
18764
19705
|
padding: 0,
|
|
18765
19706
|
outline: "none"
|
|
18766
|
-
}, children: (0,
|
|
19707
|
+
}, 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
19708
|
}
|
|
18768
19709
|
|
|
18769
19710
|
// ../react/dist/components/SystemCanvas.js
|
|
18770
19711
|
var CASCADE_WINDOW_MS = 1500;
|
|
18771
19712
|
var CASCADE_OFFSET = 20;
|
|
18772
|
-
var SystemCanvas = (0,
|
|
18773
|
-
const zoomNavConfig = (0,
|
|
19713
|
+
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) {
|
|
19714
|
+
const zoomNavConfig = (0, import_react20.useMemo)(() => {
|
|
18774
19715
|
const defaults = {
|
|
18775
19716
|
enterThreshold: 0.66,
|
|
18776
19717
|
exitThreshold: 0.33,
|
|
18777
19718
|
prefetchThreshold: 0.4,
|
|
18778
19719
|
landingScale: 1.2,
|
|
18779
19720
|
landingPadding: 0.08,
|
|
18780
|
-
fadeDuration:
|
|
19721
|
+
fadeDuration: 216
|
|
18781
19722
|
};
|
|
18782
19723
|
if (!zoomNavigation)
|
|
18783
19724
|
return { enabled: false, ...defaults };
|
|
@@ -18795,16 +19736,16 @@ var SystemCanvas = (() => {
|
|
|
18795
19736
|
}, [zoomNavigation]);
|
|
18796
19737
|
const effectiveMaxZoom = maxZoom ?? (zoomNavConfig.enabled ? 16 : 4);
|
|
18797
19738
|
const effectiveMinZoom = minZoomProp ?? (zoomNavConfig.enabled ? 0.01 : 0.1);
|
|
18798
|
-
(0,
|
|
19739
|
+
(0, import_react20.useEffect)(() => {
|
|
18799
19740
|
const env = globalThis.process?.env?.NODE_ENV;
|
|
18800
19741
|
if (editable && !canvases && env !== "production") {
|
|
18801
19742
|
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
19743
|
}
|
|
18803
19744
|
}, [editable, canvases]);
|
|
18804
|
-
const [parentFrames, setParentFrames] = (0,
|
|
18805
|
-
const [pendingHandoff, setPendingHandoff] = (0,
|
|
18806
|
-
const suppressNextHandoffClearRef = (0,
|
|
18807
|
-
const handleBreadcrumbClick = (0,
|
|
19745
|
+
const [parentFrames, setParentFrames] = (0, import_react20.useState)([]);
|
|
19746
|
+
const [pendingHandoff, setPendingHandoff] = (0, import_react20.useState)(null);
|
|
19747
|
+
const suppressNextHandoffClearRef = (0, import_react20.useRef)(false);
|
|
19748
|
+
const handleBreadcrumbClick = (0, import_react20.useCallback)((index) => {
|
|
18808
19749
|
setParentFrames((prev) => prev.slice(0, index));
|
|
18809
19750
|
if (suppressNextHandoffClearRef.current) {
|
|
18810
19751
|
suppressNextHandoffClearRef.current = false;
|
|
@@ -18821,7 +19762,7 @@ var SystemCanvas = (() => {
|
|
|
18821
19762
|
onNavigate,
|
|
18822
19763
|
onBreadcrumbClick: handleBreadcrumbClick
|
|
18823
19764
|
});
|
|
18824
|
-
const theme = (0,
|
|
19765
|
+
const theme = (0, import_react20.useMemo)(() => {
|
|
18825
19766
|
const registry = { ...themes, ...customThemes };
|
|
18826
19767
|
const resolveByName = (name) => name && registry[name] ? registry[name] : null;
|
|
18827
19768
|
if (themeProp) {
|
|
@@ -18832,22 +19773,22 @@ var SystemCanvas = (() => {
|
|
|
18832
19773
|
}
|
|
18833
19774
|
return resolveByName(currentCanvas.theme?.base) ?? resolveByName(canvas.theme?.base) ?? darkTheme;
|
|
18834
19775
|
}, [themeProp, customThemes, currentCanvas.theme?.base, canvas.theme?.base]);
|
|
18835
|
-
const { nodes, edges, nodeMap } = (0,
|
|
19776
|
+
const { nodes, edges, nodeMap } = (0, import_react20.useMemo)(() => {
|
|
18836
19777
|
const resolved = resolveCanvas(currentCanvas, theme);
|
|
18837
19778
|
const map = buildNodeMap(resolved.nodes);
|
|
18838
19779
|
return { nodes: resolved.nodes, edges: resolved.edges, nodeMap: map };
|
|
18839
19780
|
}, [currentCanvas, theme]);
|
|
18840
|
-
const nodesRef = (0,
|
|
19781
|
+
const nodesRef = (0, import_react20.useRef)(nodes);
|
|
18841
19782
|
nodesRef.current = nodes;
|
|
18842
|
-
const viewportStateRef = (0,
|
|
18843
|
-
const viewportHandleRef = (0,
|
|
18844
|
-
const navigateToRefRef = (0,
|
|
19783
|
+
const viewportStateRef = (0, import_react20.useRef)(defaultViewport ?? { x: 0, y: 0, zoom: 1 });
|
|
19784
|
+
const viewportHandleRef = (0, import_react20.useRef)(null);
|
|
19785
|
+
const navigateToRefRef = (0, import_react20.useRef)(navigateToRef);
|
|
18845
19786
|
navigateToRefRef.current = navigateToRef;
|
|
18846
|
-
const navigateToBreadcrumbRef = (0,
|
|
19787
|
+
const navigateToBreadcrumbRef = (0, import_react20.useRef)(navigateToBreadcrumb);
|
|
18847
19788
|
navigateToBreadcrumbRef.current = navigateToBreadcrumb;
|
|
18848
|
-
const breadcrumbsRef = (0,
|
|
19789
|
+
const breadcrumbsRef = (0, import_react20.useRef)(breadcrumbs);
|
|
18849
19790
|
breadcrumbsRef.current = breadcrumbs;
|
|
18850
|
-
(0,
|
|
19791
|
+
(0, import_react20.useImperativeHandle)(forwardedRef, () => ({
|
|
18851
19792
|
zoomIntoNode: (nodeId, options) => {
|
|
18852
19793
|
return new Promise((resolve) => {
|
|
18853
19794
|
const node = nodesRef.current.find((n) => n.id === nodeId);
|
|
@@ -18879,19 +19820,19 @@ var SystemCanvas = (() => {
|
|
|
18879
19820
|
navigateToBreadcrumbRef.current(0);
|
|
18880
19821
|
}
|
|
18881
19822
|
}), [forwardedRef]);
|
|
18882
|
-
const [selectedId, setSelectedId] = (0,
|
|
18883
|
-
const [editingId, setEditingId] = (0,
|
|
18884
|
-
const [selectedEdgeId, setSelectedEdgeId] = (0,
|
|
18885
|
-
const [editingEdgeId, setEditingEdgeId] = (0,
|
|
18886
|
-
(0,
|
|
19823
|
+
const [selectedId, setSelectedId] = (0, import_react20.useState)(null);
|
|
19824
|
+
const [editingId, setEditingId] = (0, import_react20.useState)(null);
|
|
19825
|
+
const [selectedEdgeId, setSelectedEdgeId] = (0, import_react20.useState)(null);
|
|
19826
|
+
const [editingEdgeId, setEditingEdgeId] = (0, import_react20.useState)(null);
|
|
19827
|
+
(0, import_react20.useEffect)(() => {
|
|
18887
19828
|
setSelectedId(null);
|
|
18888
19829
|
setEditingId(null);
|
|
18889
19830
|
setSelectedEdgeId(null);
|
|
18890
19831
|
setEditingEdgeId(null);
|
|
18891
19832
|
}, [currentCanvasRef]);
|
|
18892
|
-
const containerRef = (0,
|
|
18893
|
-
const [containerSize, setContainerSize] = (0,
|
|
18894
|
-
(0,
|
|
19833
|
+
const containerRef = (0, import_react20.useRef)(null);
|
|
19834
|
+
const [containerSize, setContainerSize] = (0, import_react20.useState)({ width: 0, height: 0 });
|
|
19835
|
+
(0, import_react20.useEffect)(() => {
|
|
18895
19836
|
const el = containerRef.current;
|
|
18896
19837
|
if (!el)
|
|
18897
19838
|
return;
|
|
@@ -18906,19 +19847,28 @@ var SystemCanvas = (() => {
|
|
|
18906
19847
|
}, []);
|
|
18907
19848
|
const hasLanes = currentCanvas.columns && currentCanvas.columns.length > 0 || currentCanvas.rows && currentCanvas.rows.length > 0;
|
|
18908
19849
|
const showLaneHeaders = hasLanes && laneHeaders !== "none";
|
|
18909
|
-
const getViewportState = (0,
|
|
18910
|
-
const commitDrag = (0,
|
|
19850
|
+
const getViewportState = (0, import_react20.useCallback)(() => viewportStateRef.current ?? { x: 0, y: 0, zoom: 1 }, []);
|
|
19851
|
+
const commitDrag = (0, import_react20.useCallback)((id2, patch) => {
|
|
18911
19852
|
let final = patch;
|
|
18912
19853
|
if (snapToLanes) {
|
|
18913
19854
|
const cols = currentCanvas.columns;
|
|
18914
19855
|
const rows = currentCanvas.rows;
|
|
19856
|
+
const node = nodesRef.current.find((n) => n.id === id2);
|
|
18915
19857
|
const nx = patch.x;
|
|
18916
19858
|
const ny = patch.y;
|
|
18917
19859
|
if (cols && cols.length > 0 && nx != null) {
|
|
18918
|
-
|
|
19860
|
+
const snapped = snapToLane(nx, cols, {
|
|
19861
|
+
edge: "center",
|
|
19862
|
+
size: node?.width ?? 0
|
|
19863
|
+
});
|
|
19864
|
+
final = { ...final, x: Math.round(snapped) };
|
|
18919
19865
|
}
|
|
18920
19866
|
if (rows && rows.length > 0 && ny != null) {
|
|
18921
|
-
|
|
19867
|
+
const snapped = snapToLane(ny, rows, {
|
|
19868
|
+
edge: "center",
|
|
19869
|
+
size: node?.height ?? 0
|
|
19870
|
+
});
|
|
19871
|
+
final = { ...final, y: Math.round(snapped) };
|
|
18922
19872
|
}
|
|
18923
19873
|
}
|
|
18924
19874
|
onNodeUpdate?.(id2, final, currentCanvasRef);
|
|
@@ -18932,7 +19882,7 @@ var SystemCanvas = (() => {
|
|
|
18932
19882
|
viewport: viewportStateRef,
|
|
18933
19883
|
onCommit: commitDrag
|
|
18934
19884
|
});
|
|
18935
|
-
const selectedResolvedNode = (0,
|
|
19885
|
+
const selectedResolvedNode = (0, import_react20.useMemo)(() => {
|
|
18936
19886
|
if (!selectedId)
|
|
18937
19887
|
return null;
|
|
18938
19888
|
const base = nodeMap.get(selectedId);
|
|
@@ -18948,9 +19898,9 @@ var SystemCanvas = (() => {
|
|
|
18948
19898
|
}
|
|
18949
19899
|
return base;
|
|
18950
19900
|
}, [selectedId, nodeMap, dragOverrides, resizeOverrides]);
|
|
18951
|
-
const svgProxyRef = (0,
|
|
19901
|
+
const svgProxyRef = (0, import_react20.useRef)(null);
|
|
18952
19902
|
svgProxyRef.current = viewportHandleRef.current?.getSvgElement() ?? null;
|
|
18953
|
-
const handleEdgeCreated = (0,
|
|
19903
|
+
const handleEdgeCreated = (0, import_react20.useCallback)((edge) => {
|
|
18954
19904
|
onEdgeAdd?.(edge, currentCanvasRef);
|
|
18955
19905
|
}, [onEdgeAdd, currentCanvasRef]);
|
|
18956
19906
|
const { pending: pendingEdge, onHandlePointerDown: onConnectionHandlePointerDown } = useEdgeCreate({
|
|
@@ -18959,7 +19909,7 @@ var SystemCanvas = (() => {
|
|
|
18959
19909
|
nodesRef,
|
|
18960
19910
|
onCreate: handleEdgeCreated
|
|
18961
19911
|
});
|
|
18962
|
-
const handleNavigableNodeClick = (0,
|
|
19912
|
+
const handleNavigableNodeClick = (0, import_react20.useCallback)((node) => {
|
|
18963
19913
|
const frame2 = {
|
|
18964
19914
|
parentCanvasRef: currentCanvasRef,
|
|
18965
19915
|
parentNodeRect: {
|
|
@@ -18970,16 +19920,23 @@ var SystemCanvas = (() => {
|
|
|
18970
19920
|
}
|
|
18971
19921
|
};
|
|
18972
19922
|
setParentFrames((prev) => [...prev, frame2]);
|
|
19923
|
+
if (!zoomNavConfig.enabled) {
|
|
19924
|
+
navigateToRef(node);
|
|
19925
|
+
return;
|
|
19926
|
+
}
|
|
18973
19927
|
const handle = viewportHandleRef.current;
|
|
18974
19928
|
if (handle) {
|
|
18975
19929
|
handle.zoomToNode(node, () => {
|
|
19930
|
+
const finalVp = viewportStateRef.current;
|
|
19931
|
+
if (finalVp)
|
|
19932
|
+
setPendingHandoff({ ...finalVp });
|
|
18976
19933
|
navigateToRef(node);
|
|
18977
19934
|
});
|
|
18978
19935
|
} else {
|
|
18979
19936
|
navigateToRef(node);
|
|
18980
19937
|
}
|
|
18981
|
-
}, [navigateToRef, currentCanvasRef]);
|
|
18982
|
-
const handleZoomEnter = (0,
|
|
19938
|
+
}, [navigateToRef, currentCanvasRef, zoomNavConfig.enabled]);
|
|
19939
|
+
const handleZoomEnter = (0, import_react20.useCallback)((node, targetTransform) => {
|
|
18983
19940
|
const frame2 = {
|
|
18984
19941
|
parentCanvasRef: currentCanvasRef,
|
|
18985
19942
|
parentNodeRect: {
|
|
@@ -18993,7 +19950,7 @@ var SystemCanvas = (() => {
|
|
|
18993
19950
|
setPendingHandoff(targetTransform);
|
|
18994
19951
|
navigateToRef(node);
|
|
18995
19952
|
}, [currentCanvasRef, navigateToRef]);
|
|
18996
|
-
const handleZoomExit = (0,
|
|
19953
|
+
const handleZoomExit = (0, import_react20.useCallback)((targetTransform) => {
|
|
18997
19954
|
setPendingHandoff(targetTransform);
|
|
18998
19955
|
suppressNextHandoffClearRef.current = true;
|
|
18999
19956
|
navigateToBreadcrumb(breadcrumbs.length - 2);
|
|
@@ -19019,19 +19976,19 @@ var SystemCanvas = (() => {
|
|
|
19019
19976
|
onEnter: handleZoomEnter,
|
|
19020
19977
|
onExit: handleZoomExit
|
|
19021
19978
|
});
|
|
19022
|
-
const handleViewportChange = (0,
|
|
19979
|
+
const handleViewportChange = (0, import_react20.useCallback)((vp) => {
|
|
19023
19980
|
viewportStateRef.current = vp;
|
|
19024
19981
|
handleZoomNavViewportChange(vp);
|
|
19025
19982
|
onViewportChange?.(vp);
|
|
19026
19983
|
}, [handleZoomNavViewportChange, onViewportChange]);
|
|
19027
|
-
const handleHandoffApplied = (0,
|
|
19984
|
+
const handleHandoffApplied = (0, import_react20.useCallback)(() => {
|
|
19028
19985
|
setPendingHandoff(null);
|
|
19029
19986
|
clearZoomNavCommitting();
|
|
19030
19987
|
}, [clearZoomNavCommitting]);
|
|
19031
|
-
const handleBeginEdit = (0,
|
|
19988
|
+
const handleBeginEdit = (0, import_react20.useCallback)((node) => {
|
|
19032
19989
|
setEditingId(node.id);
|
|
19033
19990
|
}, []);
|
|
19034
|
-
const handleBeginEditEdge = (0,
|
|
19991
|
+
const handleBeginEditEdge = (0, import_react20.useCallback)((edge) => {
|
|
19035
19992
|
setEditingEdgeId(edge.id);
|
|
19036
19993
|
}, []);
|
|
19037
19994
|
const { handleNodeClick, handleNodeDoubleClick, handleNodeNavigate, handleEdgeClick, handleEdgeDoubleClick, handleCanvasClick, handleCanvasContextMenu, handleNodeContextMenu, handleEdgeContextMenu } = useCanvasInteraction({
|
|
@@ -19048,27 +20005,27 @@ var SystemCanvas = (() => {
|
|
|
19048
20005
|
onSelectEdge: setSelectedEdgeId,
|
|
19049
20006
|
onBeginEditEdge: handleBeginEditEdge
|
|
19050
20007
|
});
|
|
19051
|
-
const handleEditorCommit = (0,
|
|
20008
|
+
const handleEditorCommit = (0, import_react20.useCallback)((patch) => {
|
|
19052
20009
|
if (editingId) {
|
|
19053
20010
|
onNodeUpdate?.(editingId, patch, currentCanvasRef);
|
|
19054
20011
|
}
|
|
19055
20012
|
setEditingId(null);
|
|
19056
20013
|
}, [editingId, onNodeUpdate, currentCanvasRef]);
|
|
19057
|
-
const handleEditorCancel = (0,
|
|
20014
|
+
const handleEditorCancel = (0, import_react20.useCallback)(() => {
|
|
19058
20015
|
setEditingId(null);
|
|
19059
20016
|
}, []);
|
|
19060
|
-
const handleEdgeEditorCommit = (0,
|
|
20017
|
+
const handleEdgeEditorCommit = (0, import_react20.useCallback)((patch) => {
|
|
19061
20018
|
if (editingEdgeId) {
|
|
19062
20019
|
onEdgeUpdate?.(editingEdgeId, patch, currentCanvasRef);
|
|
19063
20020
|
}
|
|
19064
20021
|
setEditingEdgeId(null);
|
|
19065
20022
|
}, [editingEdgeId, onEdgeUpdate, currentCanvasRef]);
|
|
19066
|
-
const handleEdgeEditorCancel = (0,
|
|
20023
|
+
const handleEdgeEditorCancel = (0, import_react20.useCallback)(() => {
|
|
19067
20024
|
setEditingEdgeId(null);
|
|
19068
20025
|
}, []);
|
|
19069
|
-
const lastAddRef = (0,
|
|
19070
|
-
const menuOptions = (0,
|
|
19071
|
-
const addNode2 = (0,
|
|
20026
|
+
const lastAddRef = (0, import_react20.useRef)(null);
|
|
20027
|
+
const menuOptions = (0, import_react20.useMemo)(() => getNodeMenuOptions(currentCanvas, theme), [currentCanvas, theme]);
|
|
20028
|
+
const addNode2 = (0, import_react20.useCallback)((option, position) => {
|
|
19072
20029
|
let x, y;
|
|
19073
20030
|
if (position) {
|
|
19074
20031
|
x = position.x;
|
|
@@ -19097,10 +20054,10 @@ var SystemCanvas = (() => {
|
|
|
19097
20054
|
y += nextOffset;
|
|
19098
20055
|
lastAddRef.current = { t: now2, offset: nextOffset };
|
|
19099
20056
|
}
|
|
19100
|
-
const node = createNodeFromOption(option, Math.round(x), Math.round(y));
|
|
20057
|
+
const node = createNodeFromOption(option, Math.round(x), Math.round(y), void 0, theme);
|
|
19101
20058
|
onNodeAdd?.(node, currentCanvasRef);
|
|
19102
|
-
}, [onNodeAdd, currentCanvasRef]);
|
|
19103
|
-
const handleKeyDown = (0,
|
|
20059
|
+
}, [onNodeAdd, currentCanvasRef, theme]);
|
|
20060
|
+
const handleKeyDown = (0, import_react20.useCallback)((e) => {
|
|
19104
20061
|
if (!editable)
|
|
19105
20062
|
return;
|
|
19106
20063
|
if (e.key === "Escape") {
|
|
@@ -19134,14 +20091,14 @@ var SystemCanvas = (() => {
|
|
|
19134
20091
|
currentCanvasRef
|
|
19135
20092
|
]);
|
|
19136
20093
|
const renderProps = { options: menuOptions, addNode: addNode2, theme };
|
|
19137
|
-
return (0,
|
|
20094
|
+
return (0, import_jsx_runtime27.jsxs)("div", { ref: containerRef, className: `system-canvas ${className ?? ""}`, tabIndex: editable ? 0 : -1, onKeyDown: handleKeyDown, style: {
|
|
19138
20095
|
position: "relative",
|
|
19139
20096
|
width: "100%",
|
|
19140
20097
|
height: "100%",
|
|
19141
20098
|
overflow: "hidden",
|
|
19142
20099
|
outline: "none",
|
|
19143
20100
|
...style
|
|
19144
|
-
}, children: [(0,
|
|
20101
|
+
}, 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
20102
|
position: "absolute",
|
|
19146
20103
|
top: 12,
|
|
19147
20104
|
right: 12,
|
|
@@ -19153,12 +20110,12 @@ var SystemCanvas = (() => {
|
|
|
19153
20110
|
fontFamily: theme.node.fontFamily,
|
|
19154
20111
|
fontSize: 12,
|
|
19155
20112
|
backdropFilter: "blur(8px)"
|
|
19156
|
-
}, children: "Loading..." }), (0,
|
|
20113
|
+
}, 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
20114
|
onNodeUpdate?.(selectedResolvedNode.id, update, currentCanvasRef);
|
|
19158
20115
|
}, onDelete: () => {
|
|
19159
20116
|
onNodeDelete?.(selectedResolvedNode.id, currentCanvasRef);
|
|
19160
20117
|
setSelectedId(null);
|
|
19161
|
-
}, getViewport: getViewportState, containerWidth: containerSize.width, containerHeight: containerSize.height, render: renderNodeToolbar }), editable && (renderAddNodeButton ? renderAddNodeButton(renderProps) : (0,
|
|
20118
|
+
}, getViewport: getViewportState, containerWidth: containerSize.width, containerHeight: containerSize.height, render: renderNodeToolbar }), editable && (renderAddNodeButton ? renderAddNodeButton(renderProps) : (0, import_jsx_runtime27.jsx)(AddNodeButton, { ...renderProps }))] });
|
|
19162
20119
|
});
|
|
19163
20120
|
|
|
19164
20121
|
// src/index.tsx
|
|
@@ -19269,7 +20226,7 @@ var SystemCanvas = (() => {
|
|
|
19269
20226
|
onEdgeUpdate: handleEdgeUpdate,
|
|
19270
20227
|
onEdgeDelete: handleEdgeDelete
|
|
19271
20228
|
};
|
|
19272
|
-
root2.render(
|
|
20229
|
+
root2.render(import_react21.default.createElement(SystemCanvas, props));
|
|
19273
20230
|
};
|
|
19274
20231
|
doRender();
|
|
19275
20232
|
return {
|