@ai-matrx/canvas 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +17 -2
- package/dist/index.cjs +76 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -4
- package/dist/index.d.ts +13 -4
- package/dist/index.js +76 -7
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +427 -202
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +77 -44
- package/dist/react.d.ts +77 -44
- package/dist/react.js +381 -156
- package/dist/react.js.map +1 -1
- package/dist/styles.css +71 -38
- package/dist/{toggleKind-DhDmWExm.d.cts → toggleKind-CAI7pndj.d.cts} +21 -2
- package/dist/{toggleKind-DhDmWExm.d.ts → toggleKind-CAI7pndj.d.ts} +21 -2
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -34,6 +34,8 @@ var react_exports = {};
|
|
|
34
34
|
__export(react_exports, {
|
|
35
35
|
BrowserBar: () => BrowserBar,
|
|
36
36
|
BrowserTabs: () => BrowserTabs,
|
|
37
|
+
CANVAS_ACTIVE_TAB_MIN_WIDTH: () => CANVAS_ACTIVE_TAB_MIN_WIDTH,
|
|
38
|
+
CANVAS_TAB_MIN_WIDTH: () => CANVAS_TAB_MIN_WIDTH,
|
|
37
39
|
CanvasColumn: () => CanvasColumn,
|
|
38
40
|
CanvasFrame: () => CanvasFrame,
|
|
39
41
|
CanvasHeaderButton: () => CanvasHeaderButton,
|
|
@@ -46,8 +48,10 @@ __export(react_exports, {
|
|
|
46
48
|
CanvasTab: () => CanvasTab,
|
|
47
49
|
CanvasToggle: () => CanvasToggle,
|
|
48
50
|
CanvasWindowScope: () => CanvasWindowScope,
|
|
51
|
+
beginCanvasResize: () => beginCanvasResize,
|
|
49
52
|
canvasSessionKey: () => canvasSessionKey,
|
|
50
53
|
defineCanvasKind: () => defineCanvasKind,
|
|
54
|
+
fitCanvasTabs: () => fitCanvasTabs,
|
|
51
55
|
getCanvasKind: () => getCanvasKind,
|
|
52
56
|
itemTitle: () => itemTitle,
|
|
53
57
|
listCanvasKinds: () => listCanvasKinds,
|
|
@@ -62,6 +66,7 @@ __export(react_exports, {
|
|
|
62
66
|
useCanvasKinds: () => useCanvasKinds,
|
|
63
67
|
useCanvasLauncherEntries: () => useCanvasLauncherEntries,
|
|
64
68
|
useCanvasLauncherEntry: () => useCanvasLauncherEntry,
|
|
69
|
+
useCanvasMenuItems: () => useCanvasMenuItems,
|
|
65
70
|
useCanvasNativeBodies: () => useCanvasNativeBodies,
|
|
66
71
|
useCanvasPresentation: () => useCanvasPresentation,
|
|
67
72
|
useCanvasState: () => useCanvasState,
|
|
@@ -72,7 +77,46 @@ __export(react_exports, {
|
|
|
72
77
|
module.exports = __toCommonJS(react_exports);
|
|
73
78
|
|
|
74
79
|
// src/react/provider.tsx
|
|
75
|
-
var
|
|
80
|
+
var import_react3 = require("react");
|
|
81
|
+
|
|
82
|
+
// src/react/menuItems.ts
|
|
83
|
+
var import_react = require("react");
|
|
84
|
+
var useIsoLayoutEffect = typeof window === "undefined" ? import_react.useEffect : import_react.useLayoutEffect;
|
|
85
|
+
function createCanvasItemMenus() {
|
|
86
|
+
const sources = /* @__PURE__ */ new Map();
|
|
87
|
+
return {
|
|
88
|
+
register(itemId, read) {
|
|
89
|
+
let set = sources.get(itemId);
|
|
90
|
+
if (!set) sources.set(itemId, set = /* @__PURE__ */ new Set());
|
|
91
|
+
set.add(read);
|
|
92
|
+
return () => {
|
|
93
|
+
const current = sources.get(itemId);
|
|
94
|
+
current?.delete(read);
|
|
95
|
+
if (current && current.size === 0) sources.delete(itemId);
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
read(itemId) {
|
|
99
|
+
const out = [];
|
|
100
|
+
for (const read of sources.get(itemId) ?? []) {
|
|
101
|
+
try {
|
|
102
|
+
out.push(...read());
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error("[@ai-matrx/canvas] a body's menu entries threw", error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function useCanvasMenuItems(itemId, items) {
|
|
112
|
+
const { itemMenus } = useCanvasInternals();
|
|
113
|
+
const latest = (0, import_react.useRef)(items);
|
|
114
|
+
latest.current = items;
|
|
115
|
+
useIsoLayoutEffect(() => {
|
|
116
|
+
if (!itemId) return void 0;
|
|
117
|
+
return itemMenus.register(itemId, () => latest.current);
|
|
118
|
+
}, [itemMenus, itemId]);
|
|
119
|
+
}
|
|
76
120
|
|
|
77
121
|
// src/core/types.ts
|
|
78
122
|
var CANVAS_MAIN_WINDOW = "main";
|
|
@@ -241,6 +285,8 @@ var canvasActions = {
|
|
|
241
285
|
navigate: (itemId, to) => ({ type: `${P}navigate`, payload: { itemId, to, now: Date.now() } }),
|
|
242
286
|
/** Returns a tab to what it showed before its last navigate. */
|
|
243
287
|
back: (itemId) => ({ type: `${P}back`, payload: { itemId, now: Date.now() } }),
|
|
288
|
+
/** Re-does the last Back (the step Back left), with that step's live body. */
|
|
289
|
+
forward: (itemId) => ({ type: `${P}forward`, payload: { itemId, now: Date.now() } }),
|
|
244
290
|
closeItem: (itemId) => ({ type: `${P}closeItem`, payload: { itemId } }),
|
|
245
291
|
closeOthers: (itemId) => ({ type: `${P}closeOthers`, payload: { itemId } }),
|
|
246
292
|
activate: (itemId) => ({ type: `${P}activate`, payload: { itemId } }),
|
|
@@ -441,6 +487,7 @@ function newItem(kind, key, title, data, now, steps) {
|
|
|
441
487
|
const id = canvasItemId(kind, key);
|
|
442
488
|
const history = steps?.history ?? [];
|
|
443
489
|
const kept = steps?.kept ?? [];
|
|
490
|
+
const forward = steps?.forward ?? [];
|
|
444
491
|
return {
|
|
445
492
|
id,
|
|
446
493
|
kind,
|
|
@@ -452,7 +499,8 @@ function newItem(kind, key, title, data, now, steps) {
|
|
|
452
499
|
// A reused instance is the SAME live body coming back (Back, or returning to a kept step).
|
|
453
500
|
instance: steps?.instance ?? `${now.toString(36)}:${id}`,
|
|
454
501
|
...history.length > 0 ? { history: history.slice(-CANVAS_HISTORY_LIMIT) } : {},
|
|
455
|
-
...kept.length > 0 ? { kept: kept.slice(-CANVAS_KEEP_ALIVE_DEPTH) } : {}
|
|
502
|
+
...kept.length > 0 ? { kept: kept.slice(-CANVAS_KEEP_ALIVE_DEPTH) } : {},
|
|
503
|
+
...forward.length > 0 ? { forward: forward.slice(-CANVAS_HISTORY_LIMIT) } : {}
|
|
456
504
|
};
|
|
457
505
|
}
|
|
458
506
|
function historyEntry(item) {
|
|
@@ -498,12 +546,14 @@ function sanitizeHistory(raw) {
|
|
|
498
546
|
function sanitizeItem(item) {
|
|
499
547
|
const history = sanitizeHistory(item.history);
|
|
500
548
|
const kept = sanitizeHistory(item.kept).slice(-CANVAS_KEEP_ALIVE_DEPTH);
|
|
501
|
-
const
|
|
549
|
+
const forward = sanitizeHistory(item.forward);
|
|
550
|
+
const { history: _history, kept: _kept, forward: _forward, instance, ...rest } = item;
|
|
502
551
|
return {
|
|
503
552
|
...rest,
|
|
504
553
|
...typeof instance === "string" && instance ? { instance } : {},
|
|
505
554
|
...history.length > 0 ? { history } : {},
|
|
506
|
-
...kept.length > 0 ? { kept } : {}
|
|
555
|
+
...kept.length > 0 ? { kept } : {},
|
|
556
|
+
...forward.length > 0 ? { forward } : {}
|
|
507
557
|
};
|
|
508
558
|
}
|
|
509
559
|
function clampWidth(width) {
|
|
@@ -694,6 +744,9 @@ function canvasReducer(state = createInitialCanvasState(), action) {
|
|
|
694
744
|
const keptIndex = keptAll.findIndex((entry) => canvasItemId(entry.kind, entry.key) === targetId);
|
|
695
745
|
const revived = keptIndex >= 0 ? keptAll[keptIndex] : void 0;
|
|
696
746
|
const kept = keptAll.filter((_, i) => i !== keptIndex);
|
|
747
|
+
const forwardAll = current.forward ?? [];
|
|
748
|
+
const nextForward = forwardAll[forwardAll.length - 1];
|
|
749
|
+
const forward = nextForward && canvasItemId(nextForward.kind, nextForward.key) === targetId ? forwardAll.slice(0, -1) : [];
|
|
697
750
|
return replaceInPlace(
|
|
698
751
|
state,
|
|
699
752
|
current,
|
|
@@ -703,7 +756,7 @@ function canvasReducer(state = createInitialCanvasState(), action) {
|
|
|
703
756
|
to.title !== void 0 ? to.title : revived?.title ?? null,
|
|
704
757
|
to.data !== void 0 ? to.data : revived?.data ?? null,
|
|
705
758
|
now,
|
|
706
|
-
{ history, kept, instance: revived?.instance }
|
|
759
|
+
{ history, kept, forward, instance: revived?.instance }
|
|
707
760
|
)
|
|
708
761
|
);
|
|
709
762
|
}
|
|
@@ -719,10 +772,36 @@ function canvasReducer(state = createInitialCanvasState(), action) {
|
|
|
719
772
|
return focusExisting(canvasReducer(state, canvasActions.closeItem(itemId)), targetId);
|
|
720
773
|
}
|
|
721
774
|
const kept = [...(current.kept ?? []).filter((k) => canvasItemId(k.kind, k.key) !== itemId), historyEntry(current)];
|
|
775
|
+
const forward = [...current.forward ?? [], historyEntry(current)];
|
|
722
776
|
return replaceInPlace(
|
|
723
777
|
state,
|
|
724
778
|
current,
|
|
725
|
-
newItem(entry.kind, entry.key, entry.title, entry.data, now, { history: history.slice(0, -1), kept, instance: entry.instance })
|
|
779
|
+
newItem(entry.kind, entry.key, entry.title, entry.data, now, { history: history.slice(0, -1), kept, forward, instance: entry.instance })
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
case `${P}forward`: {
|
|
783
|
+
const { itemId, now } = action.payload;
|
|
784
|
+
const current = state.items[itemId];
|
|
785
|
+
const forwardAll = current?.forward ?? [];
|
|
786
|
+
const entry = forwardAll[forwardAll.length - 1];
|
|
787
|
+
if (!current || !entry || !paneOf(state, itemId)) return state;
|
|
788
|
+
const targetId = canvasItemId(entry.kind, entry.key);
|
|
789
|
+
if (targetId === itemId) return state;
|
|
790
|
+
if (state.items[targetId]) {
|
|
791
|
+
return focusExisting(canvasReducer(state, canvasActions.closeItem(itemId)), targetId);
|
|
792
|
+
}
|
|
793
|
+
const keptAll = current.kept ?? [];
|
|
794
|
+
const revived = keptAll.find((k) => canvasItemId(k.kind, k.key) === targetId);
|
|
795
|
+
const kept = keptAll.filter((k) => canvasItemId(k.kind, k.key) !== targetId);
|
|
796
|
+
return replaceInPlace(
|
|
797
|
+
state,
|
|
798
|
+
current,
|
|
799
|
+
newItem(entry.kind, entry.key, entry.title, entry.data, now, {
|
|
800
|
+
history: [...current.history ?? [], historyEntry(current)],
|
|
801
|
+
kept,
|
|
802
|
+
forward: forwardAll.slice(0, -1),
|
|
803
|
+
instance: revived?.instance ?? entry.instance
|
|
804
|
+
})
|
|
726
805
|
);
|
|
727
806
|
}
|
|
728
807
|
case `${P}closeItem`: {
|
|
@@ -974,6 +1053,7 @@ function toPersistableSnapshot(state, isRestorable) {
|
|
|
974
1053
|
}
|
|
975
1054
|
|
|
976
1055
|
// src/core/rules.ts
|
|
1056
|
+
var CANVAS_PANE_MIN_WIDTH = 280;
|
|
977
1057
|
var CANVAS_WEB_LAYOUT_RULES = {
|
|
978
1058
|
defaultWidth: CANVAS_DEFAULT_WIDTH,
|
|
979
1059
|
minWidth: CANVAS_MIN_WIDTH,
|
|
@@ -981,7 +1061,9 @@ var CANVAS_WEB_LAYOUT_RULES = {
|
|
|
981
1061
|
// Split down 70/30 like the desktop: what opens below (notifications, a feed) is the smaller pane.
|
|
982
1062
|
stackSplit: 0.7,
|
|
983
1063
|
sideSplit: 0.5,
|
|
984
|
-
|
|
1064
|
+
// A pane narrower than this cannot show a header (Back, a readable tab, "+", the menu, close) and a
|
|
1065
|
+
// body side by side with another: a split right that would go under it stacks instead.
|
|
1066
|
+
paneMinWidth: CANVAS_PANE_MIN_WIDTH
|
|
985
1067
|
};
|
|
986
1068
|
var clampFraction = (value, fallback) => Number.isFinite(value) ? Math.min(0.88, Math.max(0.12, value)) : fallback;
|
|
987
1069
|
function resolveCanvasLayoutRules(rules) {
|
|
@@ -1020,6 +1102,9 @@ var CANVAS_SHORTCUTS = [
|
|
|
1020
1102
|
{ id: "canvas.toggleFullscreen", accelerator: "CmdOrCtrl+Shift+Enter", when: "canvas-focus", label: "Expand canvas", web: true },
|
|
1021
1103
|
{ id: "canvas.splitRight", accelerator: "CmdOrCtrl+Alt+\\", when: "canvas-focus", label: "Split right", web: true },
|
|
1022
1104
|
{ id: "canvas.splitDown", accelerator: "CmdOrCtrl+Alt+Shift+\\", when: "canvas-focus", label: "Split down", web: true },
|
|
1105
|
+
// Browsers own ⌘[ / ⌘] for their own history: data for a desktop host (and the header's Back / Forward).
|
|
1106
|
+
{ id: "canvas.back", accelerator: "CmdOrCtrl+[", when: "canvas-focus", label: "Back", web: false },
|
|
1107
|
+
{ id: "canvas.forward", accelerator: "CmdOrCtrl+]", when: "canvas-focus", label: "Forward", web: false },
|
|
1023
1108
|
{ id: "canvas.closeTab", accelerator: "CmdOrCtrl+W", when: "canvas-focus", label: "Close tab", web: false },
|
|
1024
1109
|
{ id: "canvas.nextTab", accelerator: "Ctrl+Tab", when: "canvas-focus", label: "Next tab", web: false },
|
|
1025
1110
|
{ id: "canvas.previousTab", accelerator: "Ctrl+Shift+Tab", when: "canvas-focus", label: "Previous tab", web: false }
|
|
@@ -1069,11 +1154,17 @@ function runCanvasCommand(controller, id, windowId = controller.windowId) {
|
|
|
1069
1154
|
if (!frame2?.isOpen || !pane) return false;
|
|
1070
1155
|
controller.splitPane(pane.id, id === "canvas.splitRight" ? "horizontal" : "vertical", pane.itemIds.length > 1 ? pane.activeItemId ?? void 0 : void 0);
|
|
1071
1156
|
return true;
|
|
1157
|
+
case "canvas.back":
|
|
1158
|
+
if (!frame2?.isOpen || !pane?.activeItemId) return false;
|
|
1159
|
+
return controller.back(pane.activeItemId) !== null;
|
|
1160
|
+
case "canvas.forward":
|
|
1161
|
+
if (!frame2?.isOpen || !pane?.activeItemId) return false;
|
|
1162
|
+
return controller.forward(pane.activeItemId) !== null;
|
|
1072
1163
|
default:
|
|
1073
1164
|
return false;
|
|
1074
1165
|
}
|
|
1075
1166
|
}
|
|
1076
|
-
var CODE_FOR = { "\\": "Backslash", Tab: "Tab", Escape: "Escape", Enter: "Enter" };
|
|
1167
|
+
var CODE_FOR = { "\\": "Backslash", "[": "BracketLeft", "]": "BracketRight", Tab: "Tab", Escape: "Escape", Enter: "Enter" };
|
|
1077
1168
|
function matchesCanvasAccelerator(input, accelerator, isMac3) {
|
|
1078
1169
|
const parts = accelerator.split("+");
|
|
1079
1170
|
const key = parts.pop() ?? "";
|
|
@@ -1190,6 +1281,13 @@ function view(shared, windowId) {
|
|
|
1190
1281
|
dispatch(canvasActions.back(itemId));
|
|
1191
1282
|
return canvasItemId(entry.kind, entry.key);
|
|
1192
1283
|
},
|
|
1284
|
+
forward(itemId) {
|
|
1285
|
+
const forward = store.getState().items[itemId]?.forward ?? [];
|
|
1286
|
+
const entry = forward[forward.length - 1];
|
|
1287
|
+
if (!entry) return null;
|
|
1288
|
+
dispatch(canvasActions.forward(itemId));
|
|
1289
|
+
return canvasItemId(entry.kind, entry.key);
|
|
1290
|
+
},
|
|
1193
1291
|
newTab(paneId) {
|
|
1194
1292
|
const state = store.getState();
|
|
1195
1293
|
const frame2 = canvasWindowFrame(state, windowId);
|
|
@@ -1456,6 +1554,16 @@ function selectCanvasWindowItemCount(s, windowId) {
|
|
|
1456
1554
|
var NO_WINDOWS = Object.freeze({});
|
|
1457
1555
|
var NO_HISTORY = Object.freeze([]);
|
|
1458
1556
|
var selectCanvasCanGoBack = (s, itemId) => (s.items[itemId]?.history?.length ?? 0) > 0;
|
|
1557
|
+
var selectCanvasCanGoForward = (s, itemId) => (s.items[itemId]?.forward?.length ?? 0) > 0;
|
|
1558
|
+
function selectCanvasPresentedPaneId(s, windowId) {
|
|
1559
|
+
const f = frame(s, windowId);
|
|
1560
|
+
if (!f) return null;
|
|
1561
|
+
const ids = listPaneIds(f.layout);
|
|
1562
|
+
const holds = (id) => (s.panes[id]?.itemIds.length ?? 0) > 0;
|
|
1563
|
+
const focused = ids.find((id) => id === f.focusedPaneId);
|
|
1564
|
+
if (focused && holds(focused)) return focused;
|
|
1565
|
+
return ids.find(holds) ?? focused ?? ids[0] ?? null;
|
|
1566
|
+
}
|
|
1459
1567
|
|
|
1460
1568
|
// src/core/presentation.ts
|
|
1461
1569
|
var CANVAS_PHONE_MAX_WIDTH = 767;
|
|
@@ -1499,7 +1607,9 @@ function toggleKind(controller, input) {
|
|
|
1499
1607
|
const before = selectCanvasKindVisibility(controller.getState(), input.kind, key);
|
|
1500
1608
|
if (before === "visible") {
|
|
1501
1609
|
if ((input.whenVisible ?? "close") === "close") {
|
|
1610
|
+
const windowId = canvasWindowOfItem(controller.getState(), itemId);
|
|
1502
1611
|
controller.close(itemId);
|
|
1612
|
+
if (windowId && selectCanvasWindowItemCount(controller.getState(), windowId) === 0) controller.hide(windowId);
|
|
1503
1613
|
} else {
|
|
1504
1614
|
controller.hide(canvasWindowOfItem(controller.getState(), itemId) ?? void 0);
|
|
1505
1615
|
}
|
|
@@ -1521,7 +1631,7 @@ function toggleKind(controller, input) {
|
|
|
1521
1631
|
}
|
|
1522
1632
|
|
|
1523
1633
|
// src/react/layer.tsx
|
|
1524
|
-
var
|
|
1634
|
+
var import_react2 = require("react");
|
|
1525
1635
|
var import_react_dom = require("react-dom");
|
|
1526
1636
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1527
1637
|
function createCanvasLayer(getPorts) {
|
|
@@ -1588,9 +1698,9 @@ function createCanvasLayer(getPorts) {
|
|
|
1588
1698
|
};
|
|
1589
1699
|
}
|
|
1590
1700
|
function CanvasDomOverlay({ layer }) {
|
|
1591
|
-
const elements = (0,
|
|
1592
|
-
const [mounted, setMounted] = (0,
|
|
1593
|
-
(0,
|
|
1701
|
+
const elements = (0, import_react2.useSyncExternalStore)(layer.dom.subscribe, layer.dom.list, layer.dom.list);
|
|
1702
|
+
const [mounted, setMounted] = (0, import_react2.useState)(false);
|
|
1703
|
+
(0, import_react2.useEffect)(() => setMounted(true), []);
|
|
1594
1704
|
if (!mounted || elements.length === 0 || typeof document === "undefined") return null;
|
|
1595
1705
|
return (0, import_react_dom.createPortal)(
|
|
1596
1706
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mxc-overlay", "aria-hidden": "true", children: elements.map(([id, element]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FloatingView, { element }, id)) }),
|
|
@@ -1606,11 +1716,11 @@ function FloatingView({ element }) {
|
|
|
1606
1716
|
return null;
|
|
1607
1717
|
}
|
|
1608
1718
|
function Tooltip({ element }) {
|
|
1609
|
-
const ref = (0,
|
|
1719
|
+
const ref = (0, import_react2.useRef)(null);
|
|
1610
1720
|
const { anchor, side, text } = element;
|
|
1611
1721
|
const top = side === "bottom" ? anchor.y + anchor.height + 6 : anchor.y - 6;
|
|
1612
1722
|
const centre = anchor.x + anchor.width / 2;
|
|
1613
|
-
(0,
|
|
1723
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
1614
1724
|
const el = ref.current;
|
|
1615
1725
|
if (!el) return;
|
|
1616
1726
|
const width = el.offsetWidth;
|
|
@@ -1714,7 +1824,7 @@ function escapeBelongsElsewhere(event) {
|
|
|
1714
1824
|
const active = typeof document === "undefined" ? null : document.activeElement;
|
|
1715
1825
|
return !!active?.closest?.('[role="menu"], [role="dialog"], [role="alertdialog"], [role="listbox"]');
|
|
1716
1826
|
}
|
|
1717
|
-
var CanvasContext = (0,
|
|
1827
|
+
var CanvasContext = (0, import_react3.createContext)(null);
|
|
1718
1828
|
function sessionHooksFor(kindId) {
|
|
1719
1829
|
const kind = getCanvasKind(kindId);
|
|
1720
1830
|
if (!kind || kind.restore !== "session") return void 0;
|
|
@@ -1741,13 +1851,13 @@ function CanvasProvider({
|
|
|
1741
1851
|
overlay,
|
|
1742
1852
|
onNativeBodyFrame
|
|
1743
1853
|
}) {
|
|
1744
|
-
const hostPorts = (0,
|
|
1854
|
+
const hostPorts = (0, import_react3.useMemo)(
|
|
1745
1855
|
() => ({ itemActions, popOut, dockBack, showMenu, overlay, onNativeBodyFrame }),
|
|
1746
1856
|
[itemActions, popOut, dockBack, showMenu, overlay, onNativeBodyFrame]
|
|
1747
1857
|
);
|
|
1748
|
-
const portsRef = (0,
|
|
1858
|
+
const portsRef = (0, import_react3.useRef)(hostPorts);
|
|
1749
1859
|
portsRef.current = hostPorts;
|
|
1750
|
-
const [{ controller, layer, launcherEntries }] = (0,
|
|
1860
|
+
const [{ controller, layer, launcherEntries, itemMenus }] = (0, import_react3.useState)(() => ({
|
|
1751
1861
|
controller: createCanvasController({
|
|
1752
1862
|
store: store ?? createCanvasStore(),
|
|
1753
1863
|
persistence: persistence === void 0 ? createLocalStorageCanvasPersistence() : persistence,
|
|
@@ -1761,11 +1871,12 @@ function CanvasProvider({
|
|
|
1761
1871
|
preferredTarget: (kind) => getCanvasKind(kind)?.preferredTarget
|
|
1762
1872
|
}),
|
|
1763
1873
|
layer: createCanvasLayer(() => portsRef.current),
|
|
1764
|
-
launcherEntries: createLauncherEntryStore()
|
|
1874
|
+
launcherEntries: createLauncherEntryStore(),
|
|
1875
|
+
itemMenus: createCanvasItemMenus()
|
|
1765
1876
|
}));
|
|
1766
1877
|
const windowId = controller.windowId;
|
|
1767
|
-
(0,
|
|
1768
|
-
(0,
|
|
1878
|
+
(0, import_react3.useEffect)(() => controller.start(), [controller]);
|
|
1879
|
+
(0, import_react3.useEffect)(() => {
|
|
1769
1880
|
if (!hotkeys) return;
|
|
1770
1881
|
const isMac3 = isMacPlatform();
|
|
1771
1882
|
const applies = (when, event) => {
|
|
@@ -1786,9 +1897,9 @@ function CanvasProvider({
|
|
|
1786
1897
|
window.addEventListener("keydown", onKey);
|
|
1787
1898
|
return () => window.removeEventListener("keydown", onKey);
|
|
1788
1899
|
}, [controller, hotkeys, windowId]);
|
|
1789
|
-
const value = (0,
|
|
1790
|
-
() => ({ controller, windowId, ports: hostPorts, layer, regionWidth, tabStrip, launcherEntries }),
|
|
1791
|
-
[controller, windowId, hostPorts, layer, regionWidth, tabStrip, launcherEntries]
|
|
1900
|
+
const value = (0, import_react3.useMemo)(
|
|
1901
|
+
() => ({ controller, windowId, ports: hostPorts, layer, regionWidth, tabStrip, launcherEntries, itemMenus }),
|
|
1902
|
+
[controller, windowId, hostPorts, layer, regionWidth, tabStrip, launcherEntries, itemMenus]
|
|
1792
1903
|
);
|
|
1793
1904
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(CanvasContext.Provider, { value, children: [
|
|
1794
1905
|
children,
|
|
@@ -1797,14 +1908,14 @@ function CanvasProvider({
|
|
|
1797
1908
|
}
|
|
1798
1909
|
function CanvasWindowScope({ windowId, children }) {
|
|
1799
1910
|
const parent = useCanvasContext();
|
|
1800
|
-
const value = (0,
|
|
1911
|
+
const value = (0, import_react3.useMemo)(() => {
|
|
1801
1912
|
const id = canvasWindowId(windowId);
|
|
1802
1913
|
return { ...parent, windowId: id, controller: parent.controller.forWindow(id) };
|
|
1803
1914
|
}, [parent, windowId]);
|
|
1804
1915
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CanvasContext.Provider, { value, children });
|
|
1805
1916
|
}
|
|
1806
1917
|
function useCanvasContext() {
|
|
1807
|
-
const value = (0,
|
|
1918
|
+
const value = (0, import_react3.useContext)(CanvasContext);
|
|
1808
1919
|
if (!value) throw new Error("[@ai-matrx/canvas] useCanvas* must be used inside <CanvasProvider>.");
|
|
1809
1920
|
return value;
|
|
1810
1921
|
}
|
|
@@ -1812,16 +1923,16 @@ function useCanvasInternals() {
|
|
|
1812
1923
|
return useCanvasContext();
|
|
1813
1924
|
}
|
|
1814
1925
|
function useOptionalCanvasInternals() {
|
|
1815
|
-
return (0,
|
|
1926
|
+
return (0, import_react3.useContext)(CanvasContext);
|
|
1816
1927
|
}
|
|
1817
1928
|
function useCanvas() {
|
|
1818
1929
|
return useCanvasContext().controller;
|
|
1819
1930
|
}
|
|
1820
1931
|
function useOptionalCanvas() {
|
|
1821
|
-
return (0,
|
|
1932
|
+
return (0, import_react3.useContext)(CanvasContext)?.controller ?? null;
|
|
1822
1933
|
}
|
|
1823
1934
|
function useCanvasWindowId() {
|
|
1824
|
-
return (0,
|
|
1935
|
+
return (0, import_react3.useContext)(CanvasContext)?.windowId ?? CANVAS_MAIN_WINDOW;
|
|
1825
1936
|
}
|
|
1826
1937
|
function useCanvasHostPorts() {
|
|
1827
1938
|
return useCanvasContext().ports;
|
|
@@ -1830,16 +1941,16 @@ function useCanvasNativeBodies() {
|
|
|
1830
1941
|
return useCanvasContext().layer.native;
|
|
1831
1942
|
}
|
|
1832
1943
|
function useRegisterCanvasPresence() {
|
|
1833
|
-
const context = (0,
|
|
1944
|
+
const context = (0, import_react3.useContext)(CanvasContext);
|
|
1834
1945
|
const controller = context?.controller;
|
|
1835
1946
|
const windowId = context?.windowId;
|
|
1836
|
-
(0,
|
|
1947
|
+
(0, import_react3.useEffect)(() => controller?.registerPresentation(windowId), [controller, windowId]);
|
|
1837
1948
|
}
|
|
1838
1949
|
var noPresence = () => () => void 0;
|
|
1839
1950
|
function useCanvasIsPresented() {
|
|
1840
|
-
const context = (0,
|
|
1951
|
+
const context = (0, import_react3.useContext)(CanvasContext);
|
|
1841
1952
|
const controller = context?.controller;
|
|
1842
|
-
return (0,
|
|
1953
|
+
return (0, import_react3.useSyncExternalStore)(
|
|
1843
1954
|
controller ? controller.subscribePresentation : noPresence,
|
|
1844
1955
|
() => controller?.isPresented() ?? false,
|
|
1845
1956
|
() => false
|
|
@@ -1847,7 +1958,7 @@ function useCanvasIsPresented() {
|
|
|
1847
1958
|
}
|
|
1848
1959
|
function useCanvasState(selector) {
|
|
1849
1960
|
const { store } = useCanvasContext().controller;
|
|
1850
|
-
return (0,
|
|
1961
|
+
return (0, import_react3.useSyncExternalStore)(
|
|
1851
1962
|
store.subscribe,
|
|
1852
1963
|
() => selector(store.getState()),
|
|
1853
1964
|
() => selector(store.getState())
|
|
@@ -1855,9 +1966,9 @@ function useCanvasState(selector) {
|
|
|
1855
1966
|
}
|
|
1856
1967
|
var NO_SUBSCRIPTION = () => () => void 0;
|
|
1857
1968
|
function useOptionalCanvasState(selector, fallback) {
|
|
1858
|
-
const store = (0,
|
|
1969
|
+
const store = (0, import_react3.useContext)(CanvasContext)?.controller.store;
|
|
1859
1970
|
const read = () => store ? selector(store.getState()) : fallback;
|
|
1860
|
-
return (0,
|
|
1971
|
+
return (0, import_react3.useSyncExternalStore)(store ? store.subscribe : NO_SUBSCRIPTION, read, read);
|
|
1861
1972
|
}
|
|
1862
1973
|
function useCanvasKindToggle(input) {
|
|
1863
1974
|
const controller = useCanvasContext().controller;
|
|
@@ -1871,28 +1982,28 @@ function useCanvasKindToggle(input) {
|
|
|
1871
1982
|
};
|
|
1872
1983
|
}
|
|
1873
1984
|
function useCanvasKinds() {
|
|
1874
|
-
(0,
|
|
1985
|
+
(0, import_react3.useSyncExternalStore)(subscribeCanvasKinds, getCanvasKindsVersion, getCanvasKindsVersion);
|
|
1875
1986
|
return listCanvasKinds();
|
|
1876
1987
|
}
|
|
1877
1988
|
function useCanvasKind(id) {
|
|
1878
|
-
(0,
|
|
1989
|
+
(0, import_react3.useSyncExternalStore)(subscribeCanvasKinds, getCanvasKindsVersion, getCanvasKindsVersion);
|
|
1879
1990
|
return getCanvasKind(id);
|
|
1880
1991
|
}
|
|
1881
1992
|
var NO_ENTRIES = Object.freeze([]);
|
|
1882
1993
|
var noEntries = () => NO_ENTRIES;
|
|
1883
1994
|
function useCanvasLauncherEntry(entry) {
|
|
1884
|
-
const store = (0,
|
|
1995
|
+
const store = (0, import_react3.useContext)(CanvasContext)?.launcherEntries;
|
|
1885
1996
|
const fingerprint = JSON.stringify([entry.kind, entry.key, entry.title ?? null, entry.data ?? null]);
|
|
1886
1997
|
const icon = entry.icon;
|
|
1887
|
-
(0,
|
|
1998
|
+
(0, import_react3.useEffect)(() => {
|
|
1888
1999
|
if (!store) return void 0;
|
|
1889
2000
|
const [kind, key, title, data] = JSON.parse(fingerprint);
|
|
1890
2001
|
return store.add({ kind, key, title, data, ...icon ? { icon } : {} });
|
|
1891
2002
|
}, [store, fingerprint, icon]);
|
|
1892
2003
|
}
|
|
1893
2004
|
function useCanvasLauncherEntries() {
|
|
1894
|
-
const store = (0,
|
|
1895
|
-
const all = (0,
|
|
2005
|
+
const store = (0, import_react3.useContext)(CanvasContext)?.launcherEntries;
|
|
2006
|
+
const all = (0, import_react3.useSyncExternalStore)(store ? store.subscribe : NO_SUBSCRIPTION, store ? store.list : noEntries, store ? store.list : noEntries);
|
|
1896
2007
|
const seen = /* @__PURE__ */ new Set();
|
|
1897
2008
|
const out = [];
|
|
1898
2009
|
for (let i = all.length - 1; i >= 0; i -= 1) {
|
|
@@ -1905,14 +2016,14 @@ function useCanvasLauncherEntries() {
|
|
|
1905
2016
|
}
|
|
1906
2017
|
|
|
1907
2018
|
// src/react/CanvasColumn.tsx
|
|
1908
|
-
var
|
|
2019
|
+
var import_react10 = require("react");
|
|
1909
2020
|
var import_tap_target = require("@ai-matrx/tap-target");
|
|
1910
2021
|
|
|
1911
2022
|
// src/react/bodies.tsx
|
|
1912
|
-
var
|
|
2023
|
+
var import_react8 = require("react");
|
|
1913
2024
|
|
|
1914
2025
|
// src/react/chrome.tsx
|
|
1915
|
-
var
|
|
2026
|
+
var import_react4 = require("react");
|
|
1916
2027
|
|
|
1917
2028
|
// src/react/icons.tsx
|
|
1918
2029
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -2010,16 +2121,15 @@ var LayoutGridIcon = (p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Glyph,
|
|
|
2010
2121
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { width: "7", height: "7", x: "14", y: "14", rx: "1" }),
|
|
2011
2122
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { width: "7", height: "7", x: "3", y: "14", rx: "1" })
|
|
2012
2123
|
] });
|
|
2013
|
-
var
|
|
2014
|
-
var ChevronRightIcon = (p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Glyph, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m9 18 6-6-6-6" }) });
|
|
2124
|
+
var ChevronDownIcon = (p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Glyph, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m6 9 6 6 6-6" }) });
|
|
2015
2125
|
|
|
2016
2126
|
// src/react/chrome.tsx
|
|
2017
2127
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2018
|
-
var
|
|
2128
|
+
var useIsoLayoutEffect2 = typeof window === "undefined" ? import_react4.useEffect : import_react4.useLayoutEffect;
|
|
2019
2129
|
function useTruncated(title) {
|
|
2020
|
-
const ref = (0,
|
|
2021
|
-
const [truncated, setTruncated] = (0,
|
|
2022
|
-
|
|
2130
|
+
const ref = (0, import_react4.useRef)(null);
|
|
2131
|
+
const [truncated, setTruncated] = (0, import_react4.useState)(false);
|
|
2132
|
+
useIsoLayoutEffect2(() => {
|
|
2023
2133
|
const el = ref.current;
|
|
2024
2134
|
if (!el) return void 0;
|
|
2025
2135
|
const check = () => setTruncated(el.scrollWidth - el.clientWidth > 1);
|
|
@@ -2033,15 +2143,15 @@ function useTruncated(title) {
|
|
|
2033
2143
|
var cx = (...names) => names.filter(Boolean).join(" ");
|
|
2034
2144
|
function useTooltip(text) {
|
|
2035
2145
|
const internals = useOptionalCanvasInternals();
|
|
2036
|
-
const timer = (0,
|
|
2037
|
-
const hide = (0,
|
|
2146
|
+
const timer = (0, import_react4.useRef)(null);
|
|
2147
|
+
const hide = (0, import_react4.useRef)(null);
|
|
2038
2148
|
const close = () => {
|
|
2039
2149
|
if (timer.current) clearTimeout(timer.current);
|
|
2040
2150
|
timer.current = null;
|
|
2041
2151
|
hide.current?.();
|
|
2042
2152
|
hide.current = null;
|
|
2043
2153
|
};
|
|
2044
|
-
(0,
|
|
2154
|
+
(0, import_react4.useEffect)(() => close, []);
|
|
2045
2155
|
if (!text) return { close, handlers: {} };
|
|
2046
2156
|
if (!internals) return { close, handlers: { title: text } };
|
|
2047
2157
|
const open = (element, delay) => {
|
|
@@ -2067,7 +2177,7 @@ function useTooltip(text) {
|
|
|
2067
2177
|
}
|
|
2068
2178
|
};
|
|
2069
2179
|
}
|
|
2070
|
-
var CanvasHeaderButton = (0,
|
|
2180
|
+
var CanvasHeaderButton = (0, import_react4.forwardRef)(function CanvasHeaderButton2({ label, shortcut, available = true, size = "sm", pressed, className, children, onClick, onPointerEnter, onPointerLeave, onPointerDown, onFocus, onBlur, ...rest }, ref) {
|
|
2071
2181
|
const tooltip = useTooltip(shortcut ? `${label} (${shortcut})` : label);
|
|
2072
2182
|
const own = tooltip.handlers;
|
|
2073
2183
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -2112,12 +2222,12 @@ var CanvasHeaderButton = (0, import_react3.forwardRef)(function CanvasHeaderButt
|
|
|
2112
2222
|
}
|
|
2113
2223
|
);
|
|
2114
2224
|
});
|
|
2115
|
-
var CanvasMenuTrigger = (0,
|
|
2225
|
+
var CanvasMenuTrigger = (0, import_react4.forwardRef)(
|
|
2116
2226
|
function CanvasMenuTrigger2({ label = "More", ...props }, ref) {
|
|
2117
2227
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CanvasHeaderButton, { ref, label, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, {}) });
|
|
2118
2228
|
}
|
|
2119
2229
|
);
|
|
2120
|
-
var CanvasPanel = (0,
|
|
2230
|
+
var CanvasPanel = (0, import_react4.forwardRef)(function CanvasPanel2({
|
|
2121
2231
|
panelId,
|
|
2122
2232
|
title,
|
|
2123
2233
|
leading,
|
|
@@ -2167,7 +2277,7 @@ var CanvasPanel = (0, import_react3.forwardRef)(function CanvasPanel2({
|
|
|
2167
2277
|
function CanvasPanelEmpty({ children, className }) {
|
|
2168
2278
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { "data-slot": "canvas-panel-empty", className: cx("mxc-empty-line", className), children });
|
|
2169
2279
|
}
|
|
2170
|
-
var CanvasTab = (0,
|
|
2280
|
+
var CanvasTab = (0, import_react4.forwardRef)(function CanvasTab2({ title, icon, note, active, onSelect, onClose, className, onKeyDown, onClick, ...rest }, ref) {
|
|
2171
2281
|
const shown = title || "New tab";
|
|
2172
2282
|
const name = useTruncated(shown);
|
|
2173
2283
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -2236,9 +2346,9 @@ function BrowserTabs({ tabs, activeId, onSelect, onClose, onNew, newLabel = "New
|
|
|
2236
2346
|
] });
|
|
2237
2347
|
}
|
|
2238
2348
|
function BrowserBar({ url, canGoBack, canGoForward, onBack, onForward, onReload, onNavigate, trailing, className }) {
|
|
2239
|
-
const [draft, setDraft] = (0,
|
|
2240
|
-
const [editing, setEditing] = (0,
|
|
2241
|
-
(0,
|
|
2349
|
+
const [draft, setDraft] = (0, import_react4.useState)(url);
|
|
2350
|
+
const [editing, setEditing] = (0, import_react4.useState)(false);
|
|
2351
|
+
(0, import_react4.useEffect)(() => {
|
|
2242
2352
|
if (!editing) setDraft(url);
|
|
2243
2353
|
}, [url, editing]);
|
|
2244
2354
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { "data-slot": "browser-bar", className: cx("mxc-browser-bar", className), children: [
|
|
@@ -2280,15 +2390,15 @@ function BrowserBar({ url, canGoBack, canGoForward, onBack, onForward, onReload,
|
|
|
2280
2390
|
}
|
|
2281
2391
|
|
|
2282
2392
|
// src/react/dnd.ts
|
|
2283
|
-
var
|
|
2393
|
+
var import_react5 = require("react");
|
|
2284
2394
|
var CANVAS_DRAG_MIME = "application/x-matrx-canvas-item";
|
|
2285
2395
|
function useTabDrag(itemId, title) {
|
|
2286
2396
|
const { layer } = useCanvasInternals();
|
|
2287
|
-
const active = (0,
|
|
2397
|
+
const active = (0, import_react5.useRef)([]);
|
|
2288
2398
|
const end = () => {
|
|
2289
2399
|
for (const dispose of active.current.splice(0)) dispose();
|
|
2290
2400
|
};
|
|
2291
|
-
(0,
|
|
2401
|
+
(0, import_react5.useEffect)(() => end, []);
|
|
2292
2402
|
return {
|
|
2293
2403
|
draggable: true,
|
|
2294
2404
|
onDragStart: (event) => {
|
|
@@ -2303,8 +2413,8 @@ function useTabDrag(itemId, title) {
|
|
|
2303
2413
|
function usePaneDrop(paneId, getOutline) {
|
|
2304
2414
|
const canvas = useCanvas();
|
|
2305
2415
|
const { layer } = useCanvasInternals();
|
|
2306
|
-
const drop = (0,
|
|
2307
|
-
(0,
|
|
2416
|
+
const drop = (0, import_react5.useRef)(null);
|
|
2417
|
+
(0, import_react5.useEffect)(() => () => drop.current?.(), []);
|
|
2308
2418
|
const hide = () => {
|
|
2309
2419
|
drop.current?.();
|
|
2310
2420
|
drop.current = null;
|
|
@@ -2435,16 +2545,19 @@ function useItemKind(kindId) {
|
|
|
2435
2545
|
const registered = useCanvasKind(kindId);
|
|
2436
2546
|
return kindId === CANVAS_LAUNCHER_KIND ? CANVAS_LAUNCHER_KIND_DEFINITION : registered;
|
|
2437
2547
|
}
|
|
2548
|
+
function resolveItemKind(kindId, lookup) {
|
|
2549
|
+
return kindId === CANVAS_LAUNCHER_KIND ? CANVAS_LAUNCHER_KIND_DEFINITION : lookup(kindId);
|
|
2550
|
+
}
|
|
2438
2551
|
|
|
2439
2552
|
// src/react/presentation.tsx
|
|
2440
|
-
var
|
|
2441
|
-
var CanvasPresentationContext = (0,
|
|
2553
|
+
var import_react6 = require("react");
|
|
2554
|
+
var CanvasPresentationContext = (0, import_react6.createContext)(null);
|
|
2442
2555
|
function useCanvasPresentation() {
|
|
2443
|
-
return (0,
|
|
2556
|
+
return (0, import_react6.useContext)(CanvasPresentationContext);
|
|
2444
2557
|
}
|
|
2445
2558
|
|
|
2446
2559
|
// src/react/slots.ts
|
|
2447
|
-
var
|
|
2560
|
+
var import_react7 = require("react");
|
|
2448
2561
|
var ZERO = Object.freeze({ width: 0, height: 0 });
|
|
2449
2562
|
function createCanvasSlots() {
|
|
2450
2563
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -2511,16 +2624,16 @@ function createCanvasSlots() {
|
|
|
2511
2624
|
}
|
|
2512
2625
|
};
|
|
2513
2626
|
}
|
|
2514
|
-
var CanvasSlotsContext = (0,
|
|
2627
|
+
var CanvasSlotsContext = (0, import_react7.createContext)(null);
|
|
2515
2628
|
function useCanvasSlots() {
|
|
2516
|
-
return (0,
|
|
2629
|
+
return (0, import_react7.useContext)(CanvasSlotsContext);
|
|
2517
2630
|
}
|
|
2518
|
-
var CanvasSinglePaneContext = (0,
|
|
2631
|
+
var CanvasSinglePaneContext = (0, import_react7.createContext)(false);
|
|
2519
2632
|
function useCanvasSinglePane() {
|
|
2520
|
-
return (0,
|
|
2633
|
+
return (0, import_react7.useContext)(CanvasSinglePaneContext);
|
|
2521
2634
|
}
|
|
2522
2635
|
function useSlotSize(slots, paneId) {
|
|
2523
|
-
return (0,
|
|
2636
|
+
return (0, import_react7.useSyncExternalStore)(
|
|
2524
2637
|
slots.subscribe,
|
|
2525
2638
|
() => slots.size(paneId),
|
|
2526
2639
|
() => ZERO
|
|
@@ -2529,12 +2642,12 @@ function useSlotSize(slots, paneId) {
|
|
|
2529
2642
|
|
|
2530
2643
|
// src/react/bodies.tsx
|
|
2531
2644
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2532
|
-
var
|
|
2645
|
+
var useIsoLayoutEffect3 = typeof window === "undefined" ? import_react8.useEffect : import_react8.useLayoutEffect;
|
|
2533
2646
|
var LAZY = /* @__PURE__ */ Symbol.for("ai-matrx.canvas.lazy");
|
|
2534
2647
|
function kindComponent(kind) {
|
|
2535
2648
|
if (kind.component) return kind.component;
|
|
2536
2649
|
const holder = kind;
|
|
2537
|
-
if (!holder[LAZY] && kind.load) holder[LAZY] = (0,
|
|
2650
|
+
if (!holder[LAZY] && kind.load) holder[LAZY] = (0, import_react8.lazy)(kind.load);
|
|
2538
2651
|
return holder[LAZY] ?? null;
|
|
2539
2652
|
}
|
|
2540
2653
|
function resetKindComponent(kind) {
|
|
@@ -2542,7 +2655,7 @@ function resetKindComponent(kind) {
|
|
|
2542
2655
|
}
|
|
2543
2656
|
function usePanePresentation(slots, paneId, isFullscreen, paneCount) {
|
|
2544
2657
|
const size = useSlotSize(slots, paneId);
|
|
2545
|
-
return (0,
|
|
2658
|
+
return (0, import_react8.useMemo)(
|
|
2546
2659
|
() => canvasPresentation({ width: size.width, height: size.height, isFullscreen, paneCount }),
|
|
2547
2660
|
[size.width, size.height, isFullscreen, paneCount]
|
|
2548
2661
|
);
|
|
@@ -2580,17 +2693,24 @@ function layerSignature(state, windowId, onlyPane) {
|
|
|
2580
2693
|
}
|
|
2581
2694
|
}
|
|
2582
2695
|
rows.sort((a, b) => a.born - b.born || a.hostId.localeCompare(b.hostId));
|
|
2583
|
-
const head = [
|
|
2696
|
+
const head = [
|
|
2697
|
+
frame2.isOpen ? "1" : "0",
|
|
2698
|
+
frame2.isFullscreen ? "1" : "0",
|
|
2699
|
+
frame2.focusedPaneId,
|
|
2700
|
+
String(paneIds.length),
|
|
2701
|
+
selectCanvasPresentedPaneId(state, windowId) ?? ""
|
|
2702
|
+
].join(SEP2);
|
|
2584
2703
|
return [head, ...rows.map((r) => r.row)].join(ROW);
|
|
2585
2704
|
}
|
|
2586
2705
|
function parseSignature(signature) {
|
|
2587
2706
|
if (!signature) return null;
|
|
2588
2707
|
const [head = "", ...rows] = signature.split(ROW);
|
|
2589
|
-
const [open, full, focusedPaneId = "", count = "1"] = head.split(SEP2);
|
|
2708
|
+
const [open, full, focusedPaneId = "", count = "1", presentedPaneId = ""] = head.split(SEP2);
|
|
2590
2709
|
return {
|
|
2591
2710
|
isOpen: open === "1",
|
|
2592
2711
|
isFullscreen: full === "1",
|
|
2593
2712
|
focusedPaneId,
|
|
2713
|
+
presentedPaneId,
|
|
2594
2714
|
paneCount: Number(count) || 1,
|
|
2595
2715
|
placed: rows.map((row) => {
|
|
2596
2716
|
const [hostId = "", itemId = "", paneId = "", active, kept] = row.split(SEP2);
|
|
@@ -2642,12 +2762,12 @@ function CanvasBodyLayer() {
|
|
|
2642
2762
|
const slots = useCanvasSlots();
|
|
2643
2763
|
const signature = useCanvasState((s) => layerSignature(s, windowId));
|
|
2644
2764
|
const single = useCanvasSinglePane();
|
|
2645
|
-
const root = (0,
|
|
2646
|
-
const [placement] = (0,
|
|
2765
|
+
const root = (0, import_react8.useRef)(null);
|
|
2766
|
+
const [placement] = (0, import_react8.useState)(
|
|
2647
2767
|
() => slots ? createPlacement(() => root.current, slots, () => layer.native.remeasure()) : null
|
|
2648
2768
|
);
|
|
2649
|
-
|
|
2650
|
-
|
|
2769
|
+
useIsoLayoutEffect3(() => placement?.place());
|
|
2770
|
+
useIsoLayoutEffect3(() => slots && placement ? slots.subscribe(placement.place) : void 0, [slots, placement]);
|
|
2651
2771
|
const shape = parseSignature(signature);
|
|
2652
2772
|
if (!slots || !placement || !shape) return null;
|
|
2653
2773
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: root, className: "mxc-bodies", "data-mxc-bodies": windowId, children: shape.placed.map(({ hostId, itemId, paneId, active, kept }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -2657,7 +2777,7 @@ function CanvasBodyLayer() {
|
|
|
2657
2777
|
itemId,
|
|
2658
2778
|
kept,
|
|
2659
2779
|
paneId,
|
|
2660
|
-
visible: shape.isOpen && active && (!single || paneId === shape.
|
|
2780
|
+
visible: shape.isOpen && active && (!single || paneId === shape.presentedPaneId),
|
|
2661
2781
|
focused: active && shape.focusedPaneId === paneId,
|
|
2662
2782
|
isFullscreen: shape.isFullscreen,
|
|
2663
2783
|
paneCount: shape.paneCount,
|
|
@@ -2700,7 +2820,7 @@ function stepAsItem(step, openedAt) {
|
|
|
2700
2820
|
...step.instance ? { instance: step.instance } : {}
|
|
2701
2821
|
};
|
|
2702
2822
|
}
|
|
2703
|
-
var BodyHost = (0,
|
|
2823
|
+
var BodyHost = (0, import_react8.memo)(function BodyHost2({
|
|
2704
2824
|
hostId,
|
|
2705
2825
|
itemId,
|
|
2706
2826
|
kept,
|
|
@@ -2720,16 +2840,16 @@ var BodyHost = (0, import_react7.memo)(function BodyHost2({
|
|
|
2720
2840
|
return ownerItem ? keptCanvasSteps(ownerItem).find((e) => e.instance === hostId) : void 0;
|
|
2721
2841
|
});
|
|
2722
2842
|
const owner = useCanvasState((s) => kept ? s.items[itemId]?.openedAt : void 0);
|
|
2723
|
-
const keptItem = (0,
|
|
2843
|
+
const keptItem = (0, import_react8.useMemo)(() => step ? stepAsItem(step, owner ?? 0) : void 0, [step, owner]);
|
|
2724
2844
|
const item = kept ? keptItem : live;
|
|
2725
2845
|
const kind = useItemKind(item?.kind ?? "");
|
|
2726
|
-
const element = (0,
|
|
2727
|
-
const [everShown, setEverShown] = (0,
|
|
2846
|
+
const element = (0, import_react8.useRef)(null);
|
|
2847
|
+
const [everShown, setEverShown] = (0, import_react8.useState)(visible);
|
|
2728
2848
|
if (visible && !everShown) setEverShown(true);
|
|
2729
2849
|
const mounted = kind?.unmountWhenHidden ? visible : everShown;
|
|
2730
2850
|
const presentation = usePanePresentation(slots, paneId, isFullscreen, paneCount);
|
|
2731
2851
|
const drop = usePaneDrop(paneId, () => slots.section(paneId));
|
|
2732
|
-
|
|
2852
|
+
useIsoLayoutEffect3(() => {
|
|
2733
2853
|
const el = element.current;
|
|
2734
2854
|
if (!placement || !el) return void 0;
|
|
2735
2855
|
return placement.register(hostId, { element: el, paneId });
|
|
@@ -2795,7 +2915,7 @@ function ItemContent({
|
|
|
2795
2915
|
}
|
|
2796
2916
|
return rendered;
|
|
2797
2917
|
}
|
|
2798
|
-
var Rendered = (0,
|
|
2918
|
+
var Rendered = (0, import_react8.memo)(function Rendered2({
|
|
2799
2919
|
kind,
|
|
2800
2920
|
item,
|
|
2801
2921
|
paneId,
|
|
@@ -2806,7 +2926,7 @@ var Rendered = (0, import_react7.memo)(function Rendered2({
|
|
|
2806
2926
|
presentation
|
|
2807
2927
|
}) {
|
|
2808
2928
|
const props = { item, data: item.data, paneId, isFocused, isVisible, canvas, windowId, presentation };
|
|
2809
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ItemBoundary, { item, onClose: () => canvas.close(item.id), onRetry: () => resetKindComponent(kind), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ItemBoundary, { item, onClose: () => canvas.close(item.id), onRetry: () => resetKindComponent(kind), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react8.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mxc-loading", "aria-busy": "true" }), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(KindRender, { kind, props }) }) });
|
|
2810
2930
|
});
|
|
2811
2931
|
function KindRender({ kind, props }) {
|
|
2812
2932
|
const Render = kindComponent(kind);
|
|
@@ -2815,8 +2935,8 @@ function KindRender({ kind, props }) {
|
|
|
2815
2935
|
}
|
|
2816
2936
|
function NativeBody({ itemId, windowId, visible, children }) {
|
|
2817
2937
|
const { layer } = useCanvasInternals();
|
|
2818
|
-
const ref = (0,
|
|
2819
|
-
const measure = (0,
|
|
2938
|
+
const ref = (0, import_react8.useRef)(null);
|
|
2939
|
+
const measure = (0, import_react8.useRef)(() => void 0);
|
|
2820
2940
|
measure.current = () => {
|
|
2821
2941
|
const el = ref.current;
|
|
2822
2942
|
const box = visible && el?.isConnected ? el.getBoundingClientRect() : null;
|
|
@@ -2827,8 +2947,8 @@ function NativeBody({ itemId, windowId, visible, children }) {
|
|
|
2827
2947
|
const rect = { ...toCanvasRect(box), devicePixelRatio: window.devicePixelRatio || 1 };
|
|
2828
2948
|
layer.native.report(itemId, rect, { visible: !layer.isBlocked(), windowId });
|
|
2829
2949
|
};
|
|
2830
|
-
|
|
2831
|
-
|
|
2950
|
+
useIsoLayoutEffect3(() => measure.current());
|
|
2951
|
+
useIsoLayoutEffect3(() => {
|
|
2832
2952
|
const el = ref.current;
|
|
2833
2953
|
const run = () => measure.current();
|
|
2834
2954
|
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(run);
|
|
@@ -2854,7 +2974,7 @@ function ItemProblem({ message, onClose, onRetry }) {
|
|
|
2854
2974
|
] })
|
|
2855
2975
|
] });
|
|
2856
2976
|
}
|
|
2857
|
-
var ItemBoundary = class extends
|
|
2977
|
+
var ItemBoundary = class extends import_react8.Component {
|
|
2858
2978
|
state = { error: null };
|
|
2859
2979
|
static getDerivedStateFromError(error) {
|
|
2860
2980
|
return { error };
|
|
@@ -2880,11 +3000,28 @@ var ItemBoundary = class extends import_react7.Component {
|
|
|
2880
3000
|
}
|
|
2881
3001
|
};
|
|
2882
3002
|
|
|
3003
|
+
// src/react/resizeGesture.ts
|
|
3004
|
+
function beginCanvasResize(mode) {
|
|
3005
|
+
if (typeof document === "undefined") return () => void 0;
|
|
3006
|
+
const root = document.documentElement;
|
|
3007
|
+
root.dataset.mxcResizing = mode;
|
|
3008
|
+
document.getSelection?.()?.removeAllRanges();
|
|
3009
|
+
const refuse = (event) => event.preventDefault();
|
|
3010
|
+
document.addEventListener("selectstart", refuse, true);
|
|
3011
|
+
let ended = false;
|
|
3012
|
+
return () => {
|
|
3013
|
+
if (ended) return;
|
|
3014
|
+
ended = true;
|
|
3015
|
+
delete root.dataset.mxcResizing;
|
|
3016
|
+
document.removeEventListener("selectstart", refuse, true);
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
|
|
2883
3020
|
// src/react/CanvasPane.tsx
|
|
2884
|
-
var
|
|
3021
|
+
var import_react9 = require("react");
|
|
2885
3022
|
var Menu = __toESM(require("@radix-ui/react-dropdown-menu"), 1);
|
|
2886
3023
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2887
|
-
var
|
|
3024
|
+
var useIsoLayoutEffect4 = typeof window === "undefined" ? import_react9.useEffect : import_react9.useLayoutEffect;
|
|
2888
3025
|
function itemTitle(item, kind) {
|
|
2889
3026
|
if (item.title) return item.title;
|
|
2890
3027
|
if (item.kind === CANVAS_LAUNCHER_KIND) return "New tab";
|
|
@@ -2921,7 +3058,7 @@ function CanvasPaneView({ paneId }) {
|
|
|
2921
3058
|
const canvas = useCanvas();
|
|
2922
3059
|
const { windowId, tabStrip } = useCanvasInternals();
|
|
2923
3060
|
const columnSlots = useCanvasSlots();
|
|
2924
|
-
const [ownSlots] = (0,
|
|
3061
|
+
const [ownSlots] = (0, import_react9.useState)(createCanvasSlots);
|
|
2925
3062
|
const slots = columnSlots ?? ownSlots;
|
|
2926
3063
|
const pane = useCanvasState((s) => s.panes[paneId]);
|
|
2927
3064
|
const active = useCanvasState((s) => {
|
|
@@ -2934,14 +3071,15 @@ function CanvasPaneView({ paneId }) {
|
|
|
2934
3071
|
const paneCount = useCanvasState((s) => selectCanvasPaneCount(s, windowId));
|
|
2935
3072
|
const role = useCanvasState((s) => windowId === CANVAS_MAIN_WINDOW ? "main" : s.windows[windowId]?.role ?? "window");
|
|
2936
3073
|
const canGoBack = useCanvasState((s) => active ? selectCanvasCanGoBack(s, active.id) : false);
|
|
3074
|
+
const canGoForward = useCanvasState((s) => active ? selectCanvasCanGoForward(s, active.id) : false);
|
|
2937
3075
|
const kind = useItemKind(active?.kind ?? "");
|
|
2938
3076
|
const singlePane = useCanvasSinglePane();
|
|
2939
3077
|
const windowTabs = useCanvasState((s) => singlePane ? windowTabsSignature(s, windowId) : "");
|
|
2940
|
-
const sectionRef = (0,
|
|
2941
|
-
const bodyRef = (0,
|
|
3078
|
+
const sectionRef = (0, import_react9.useRef)(null);
|
|
3079
|
+
const bodyRef = (0, import_react9.useRef)(null);
|
|
2942
3080
|
const presentation = usePanePresentation(slots, paneId, isFullscreen, paneCount);
|
|
2943
3081
|
const drop = usePaneDrop(paneId, () => sectionRef.current);
|
|
2944
|
-
|
|
3082
|
+
useIsoLayoutEffect4(() => {
|
|
2945
3083
|
const body = bodyRef.current;
|
|
2946
3084
|
const section = sectionRef.current;
|
|
2947
3085
|
if (body) slots.set(paneId, body);
|
|
@@ -2969,7 +3107,17 @@ function CanvasPaneView({ paneId }) {
|
|
|
2969
3107
|
focused,
|
|
2970
3108
|
"data-mxc-pane": paneId,
|
|
2971
3109
|
header: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2972
|
-
canGoBack && active ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-back", label: "Back", onClick: () => void canvas.back(active.id), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArrowLeftIcon, {}) }) : null,
|
|
3110
|
+
canGoBack && active ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-back", label: "Back", shortcut: canvasShortcutHint("canvas.back", isMac()), onClick: () => void canvas.back(active.id), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArrowLeftIcon, {}) }) : null,
|
|
3111
|
+
canGoForward && active ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3112
|
+
CanvasHeaderButton,
|
|
3113
|
+
{
|
|
3114
|
+
className: "mxc-forward",
|
|
3115
|
+
label: "Forward",
|
|
3116
|
+
shortcut: canvasShortcutHint("canvas.forward", isMac()),
|
|
3117
|
+
onClick: () => void canvas.forward(active.id),
|
|
3118
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArrowRightIcon, {})
|
|
3119
|
+
}
|
|
3120
|
+
) : null,
|
|
2973
3121
|
single && active ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SingleTitle, { item: active, kind }) : tabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TabStrip, { tabs, activeItemId: pane.activeItemId }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mxc-panel-title", children: "New tab" }),
|
|
2974
3122
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-new-tab", label: "New tab", onClick: () => void canvas.newTab(paneId), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlusIcon, {}) })
|
|
2975
3123
|
] }),
|
|
@@ -2978,7 +3126,19 @@ function CanvasPaneView({ paneId }) {
|
|
|
2978
3126
|
// Its own gapless row: a kind's tap buttons space themselves (the tap-target placement rule).
|
|
2979
3127
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mxc-kind-actions", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Action, { ...kindProps }) })
|
|
2980
3128
|
) : null,
|
|
2981
|
-
renderMenu: () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3129
|
+
renderMenu: () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3130
|
+
PaneMenu,
|
|
3131
|
+
{
|
|
3132
|
+
paneId,
|
|
3133
|
+
windowId,
|
|
3134
|
+
activeItem: active,
|
|
3135
|
+
kind,
|
|
3136
|
+
kindProps,
|
|
3137
|
+
tabCount: pane.itemIds.length,
|
|
3138
|
+
role,
|
|
3139
|
+
canSplit: !singlePane
|
|
3140
|
+
}
|
|
3141
|
+
),
|
|
2982
3142
|
expanded: isFullscreen,
|
|
2983
3143
|
onToggleExpand: () => canvas.setFullscreen(!isFullscreen),
|
|
2984
3144
|
expandShortcut: canvasShortcutHint("canvas.toggleFullscreen", isMac()),
|
|
@@ -2996,7 +3156,7 @@ function CanvasPaneView({ paneId }) {
|
|
|
2996
3156
|
}
|
|
2997
3157
|
);
|
|
2998
3158
|
}
|
|
2999
|
-
var ToolbarBoundary = class extends
|
|
3159
|
+
var ToolbarBoundary = class extends import_react9.Component {
|
|
3000
3160
|
state = { failed: false };
|
|
3001
3161
|
static getDerivedStateFromError() {
|
|
3002
3162
|
return { failed: true };
|
|
@@ -3012,77 +3172,135 @@ function SingleTitle({ item, kind }) {
|
|
|
3012
3172
|
const canvas = useCanvas();
|
|
3013
3173
|
const title = itemTitle(item, kind);
|
|
3014
3174
|
const drag = useTabDrag(item.id, title);
|
|
3175
|
+
const name = useTruncated(title);
|
|
3015
3176
|
const Icon = kind?.icon ?? AlertIcon;
|
|
3016
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "mxc-panel-title mxc-single-title", "data-draggable": "", title, ...drag, children: [
|
|
3177
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "mxc-panel-title mxc-single-title", "data-draggable": "", "data-truncated": name.truncated ? "" : void 0, title, ...drag, children: [
|
|
3017
3178
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { className: "mxc-title-icon" }),
|
|
3018
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mxc-tab-title", children: title }),
|
|
3179
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { ref: name.ref, className: "mxc-tab-title", children: title }),
|
|
3019
3180
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "mxc-tab-close", "data-slot": "browser-tab-close", "aria-label": `Close ${title}`, onClick: () => canvas.close(item.id), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) })
|
|
3020
3181
|
] });
|
|
3021
3182
|
}
|
|
3183
|
+
var CANVAS_TAB_MIN_WIDTH = 78;
|
|
3184
|
+
var CANVAS_ACTIVE_TAB_MIN_WIDTH = 100;
|
|
3185
|
+
var TAB_LIST_BUTTON_ROOM = 30;
|
|
3186
|
+
var TAB_GAP = 2;
|
|
3187
|
+
function fitCanvasTabs(count, activeIndex, width) {
|
|
3188
|
+
if (count <= 0) return { start: 0, end: 0, overflow: false, compact: false };
|
|
3189
|
+
const need = (n) => CANVAS_ACTIVE_TAB_MIN_WIDTH + (n - 1) * (CANVAS_TAB_MIN_WIDTH + TAB_GAP);
|
|
3190
|
+
if (width <= 0 || need(count) <= width) return { start: 0, end: count, overflow: false, compact: false };
|
|
3191
|
+
if (count === 1) return { start: 0, end: 1, overflow: false, compact: true };
|
|
3192
|
+
let fit = 1;
|
|
3193
|
+
while (fit + 1 < count && need(fit + 1) + TAB_LIST_BUTTON_ROOM <= width) fit += 1;
|
|
3194
|
+
const active = Math.min(Math.max(activeIndex, 0), count - 1);
|
|
3195
|
+
const start = active < fit ? 0 : active - fit + 1;
|
|
3196
|
+
return { start, end: start + fit, overflow: true, compact: need(fit) + TAB_LIST_BUTTON_ROOM > width };
|
|
3197
|
+
}
|
|
3022
3198
|
function TabStrip({ tabs, activeItemId }) {
|
|
3023
|
-
const
|
|
3024
|
-
const
|
|
3025
|
-
const
|
|
3026
|
-
|
|
3027
|
-
const el = strip.current;
|
|
3028
|
-
if (!el) return;
|
|
3029
|
-
const start = el.scrollLeft > 1;
|
|
3030
|
-
const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
3031
|
-
setOverflow((prev) => prev.start === start && prev.end === end ? prev : { start, end });
|
|
3032
|
-
};
|
|
3033
|
-
const tabKey = tabs.map((tab) => tab.itemId).join("|");
|
|
3034
|
-
useIsoLayoutEffect3(() => {
|
|
3199
|
+
const canvas = useCanvas();
|
|
3200
|
+
const strip = (0, import_react9.useRef)(null);
|
|
3201
|
+
const [width, setWidth] = (0, import_react9.useState)(0);
|
|
3202
|
+
useIsoLayoutEffect4(() => {
|
|
3035
3203
|
const el = strip.current;
|
|
3036
3204
|
if (!el) return void 0;
|
|
3037
|
-
const
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
const left = tab.offsetLeft;
|
|
3041
|
-
const right = left + tab.offsetWidth;
|
|
3042
|
-
if (left < el.scrollLeft) el.scrollLeft = left;
|
|
3043
|
-
else if (right > el.scrollLeft + el.clientWidth) el.scrollLeft = right - el.clientWidth;
|
|
3044
|
-
}
|
|
3045
|
-
measure.current();
|
|
3046
|
-
};
|
|
3047
|
-
reveal();
|
|
3048
|
-
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(reveal);
|
|
3205
|
+
const read = () => setWidth(Math.floor(el.getBoundingClientRect().width));
|
|
3206
|
+
read();
|
|
3207
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(read);
|
|
3049
3208
|
observer?.observe(el);
|
|
3050
|
-
for (const tab of el.querySelectorAll('[role="tab"]')) observer?.observe(tab);
|
|
3051
3209
|
return () => observer?.disconnect();
|
|
3052
|
-
}, [
|
|
3053
|
-
const
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
if (typeof el.scrollBy === "function") el.scrollBy({ left: by, behavior: "smooth" });
|
|
3058
|
-
else el.scrollLeft += by;
|
|
3059
|
-
};
|
|
3060
|
-
const overflowing = overflow.start || overflow.end;
|
|
3210
|
+
}, []);
|
|
3211
|
+
const activeIndex = Math.max(0, tabs.findIndex((tab) => tab.itemId === activeItemId));
|
|
3212
|
+
const fit = fitCanvasTabs(tabs.length, activeIndex, width);
|
|
3213
|
+
const shown = tabs.slice(fit.start, fit.end);
|
|
3214
|
+
const hidden = tabs.length - shown.length;
|
|
3061
3215
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3062
3216
|
"div",
|
|
3063
3217
|
{
|
|
3218
|
+
ref: strip,
|
|
3064
3219
|
className: "mxc-tabstrip",
|
|
3065
|
-
"data-overflow":
|
|
3066
|
-
"data-
|
|
3067
|
-
"
|
|
3220
|
+
"data-overflow": fit.overflow ? "" : void 0,
|
|
3221
|
+
"data-compact": fit.compact ? "" : void 0,
|
|
3222
|
+
style: { ["--mxc-tab-min"]: `${CANVAS_TAB_MIN_WIDTH}px`, ["--mxc-tab-active-min"]: `${CANVAS_ACTIVE_TAB_MIN_WIDTH}px` },
|
|
3068
3223
|
children: [
|
|
3069
|
-
overflowing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-tabs-scroll", label: "Scroll tabs left", available: overflow.start, onClick: () => page(-1), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronLeftIcon, {}) }) : null,
|
|
3070
3224
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3071
3225
|
"div",
|
|
3072
3226
|
{
|
|
3073
|
-
ref: strip,
|
|
3074
3227
|
className: "mxc-tabs",
|
|
3075
3228
|
role: "tablist",
|
|
3076
3229
|
"aria-label": "Canvas tabs",
|
|
3077
|
-
onScroll: () => measure.current(),
|
|
3078
3230
|
onWheel: (event) => {
|
|
3079
|
-
|
|
3080
|
-
|
|
3231
|
+
if (!fit.overflow || Math.abs(event.deltaY) < Math.abs(event.deltaX) || tabs.length < 2) return;
|
|
3232
|
+
const next = tabs[(activeIndex + (event.deltaY > 0 ? 1 : -1) + tabs.length) % tabs.length];
|
|
3233
|
+
if (next) canvas.activate(next.itemId);
|
|
3081
3234
|
},
|
|
3082
|
-
children:
|
|
3235
|
+
children: shown.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ItemTab, { itemId: tab.itemId, paneId: tab.paneId, index: tab.index, active: tab.itemId === activeItemId }, tab.itemId))
|
|
3083
3236
|
}
|
|
3084
3237
|
),
|
|
3085
|
-
|
|
3238
|
+
fit.overflow ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TabListMenu, { tabs, activeItemId, hidden }) : null
|
|
3239
|
+
]
|
|
3240
|
+
}
|
|
3241
|
+
);
|
|
3242
|
+
}
|
|
3243
|
+
function TabListMenu({ tabs, activeItemId, hidden }) {
|
|
3244
|
+
const canvas = useCanvas();
|
|
3245
|
+
const { ports, layer } = useCanvasInternals();
|
|
3246
|
+
const blocking = (0, import_react9.useRef)(null);
|
|
3247
|
+
(0, import_react9.useEffect)(() => () => blocking.current?.(), []);
|
|
3248
|
+
const label = `All tabs (${tabs.length})`;
|
|
3249
|
+
const trigger = (props) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(CanvasHeaderButton, { className: "mxc-tab-list", label, "data-hidden-count": hidden, ...props, children: [
|
|
3250
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronDownIcon, {}),
|
|
3251
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mxc-tab-list-count", "aria-hidden": "true", children: hidden })
|
|
3252
|
+
] });
|
|
3253
|
+
const showMenu = ports.showMenu;
|
|
3254
|
+
if (showMenu) {
|
|
3255
|
+
return trigger({
|
|
3256
|
+
onClick: (event) => {
|
|
3257
|
+
const state = canvas.getState();
|
|
3258
|
+
const entries = tabs.map((tab) => {
|
|
3259
|
+
const item = state.items[tab.itemId];
|
|
3260
|
+
const title = item ? itemTitle(item, resolveItemKind(item.kind, getCanvasKind)) : tab.itemId;
|
|
3261
|
+
return { type: "item", id: tab.itemId, label: tab.itemId === activeItemId ? `${title} (current)` : title };
|
|
3262
|
+
});
|
|
3263
|
+
void showMenu(entries, toCanvasRect(event.currentTarget.getBoundingClientRect())).then(
|
|
3264
|
+
(chosen) => {
|
|
3265
|
+
if (chosen) canvas.activate(chosen);
|
|
3266
|
+
},
|
|
3267
|
+
(error) => console.error("[@ai-matrx/canvas] the host menu failed", error)
|
|
3268
|
+
);
|
|
3269
|
+
}
|
|
3270
|
+
});
|
|
3271
|
+
}
|
|
3272
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3273
|
+
Menu.Root,
|
|
3274
|
+
{
|
|
3275
|
+
onOpenChange: (open) => {
|
|
3276
|
+
blocking.current?.();
|
|
3277
|
+
blocking.current = open ? layer.beginBlocking() : null;
|
|
3278
|
+
},
|
|
3279
|
+
children: [
|
|
3280
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Trigger, { asChild: true, children: trigger({}) }),
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Content, { align: "end", sideOffset: 4, className: "mxc-menu mxc-tab-list-menu", "aria-label": "All tabs", children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TabListEntry, { itemId: tab.itemId, active: tab.itemId === activeItemId }, tab.itemId)) }) })
|
|
3282
|
+
]
|
|
3283
|
+
}
|
|
3284
|
+
);
|
|
3285
|
+
}
|
|
3286
|
+
function TabListEntry({ itemId, active }) {
|
|
3287
|
+
const canvas = useCanvas();
|
|
3288
|
+
const item = useCanvasState((s) => s.items[itemId]);
|
|
3289
|
+
const kind = useItemKind(item?.kind ?? "");
|
|
3290
|
+
if (!item) return null;
|
|
3291
|
+
const Icon = kind?.icon ?? AlertIcon;
|
|
3292
|
+
const title = itemTitle(item, kind);
|
|
3293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3294
|
+
Menu.Item,
|
|
3295
|
+
{
|
|
3296
|
+
className: "mxc-menu-item mxc-tab-list-item",
|
|
3297
|
+
"data-active": active ? "" : void 0,
|
|
3298
|
+
"aria-current": active ? "true" : void 0,
|
|
3299
|
+
title,
|
|
3300
|
+
onSelect: () => canvas.activate(itemId),
|
|
3301
|
+
children: [
|
|
3302
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, {}),
|
|
3303
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mxc-tab-list-title", children: title })
|
|
3086
3304
|
]
|
|
3087
3305
|
}
|
|
3088
3306
|
);
|
|
@@ -3126,42 +3344,48 @@ function PaneMenu({
|
|
|
3126
3344
|
kind,
|
|
3127
3345
|
kindProps,
|
|
3128
3346
|
tabCount,
|
|
3129
|
-
role
|
|
3347
|
+
role,
|
|
3348
|
+
canSplit
|
|
3130
3349
|
}) {
|
|
3131
3350
|
const canvas = useCanvas();
|
|
3132
|
-
const { ports, layer } = useCanvasInternals();
|
|
3351
|
+
const { ports, layer, itemMenus } = useCanvasInternals();
|
|
3133
3352
|
const moveId = tabCount > 1 ? activeItem?.id : void 0;
|
|
3134
|
-
const blocking = (0,
|
|
3135
|
-
(0,
|
|
3136
|
-
const
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
[
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3353
|
+
const blocking = (0, import_react9.useRef)(null);
|
|
3354
|
+
(0, import_react9.useEffect)(() => () => blocking.current?.(), []);
|
|
3355
|
+
const buildSections = () => {
|
|
3356
|
+
const kindItems = kind?.menuItems && kindProps ? safeMenu(() => kind.menuItems?.(kindProps)) : [];
|
|
3357
|
+
const hostItems = activeItem && ports.itemActions ? safeMenu(() => ports.itemActions?.(activeItem, kind)) : [];
|
|
3358
|
+
const bodyItems = activeItem ? itemMenus.read(activeItem.id) : [];
|
|
3359
|
+
return [
|
|
3360
|
+
[...kindItems, ...bodyItems, ...hostItems].map((entry) => ({ ...entry, id: `item:${entry.id}` })),
|
|
3361
|
+
[
|
|
3362
|
+
...canSplit ? [
|
|
3363
|
+
{ id: "split-right", label: "Split right", icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SplitRightIcon, {}), onSelect: () => canvas.splitPane(paneId, "horizontal", moveId) },
|
|
3364
|
+
{ id: "split-down", label: "Split down", icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SplitDownIcon, {}), onSelect: () => canvas.splitPane(paneId, "vertical", moveId) }
|
|
3365
|
+
] : [],
|
|
3366
|
+
...activeItem && role === "pop-out" ? [{ id: "dock-back", label: "Dock back", icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DockIcon, {}), onSelect: () => void canvas.dockBack(activeItem.id) }] : activeItem && ports.popOut ? [{ id: "pop-out", label: "Pop out", icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PopOutIcon, {}), onSelect: () => void canvas.popOut(activeItem.id) }] : []
|
|
3367
|
+
],
|
|
3368
|
+
activeItem ? [
|
|
3369
|
+
{ id: "close-tab", label: "Close tab", onSelect: () => canvas.close(activeItem.id) },
|
|
3370
|
+
...tabCount > 1 ? [{ id: "close-others", label: "Close other tabs", onSelect: () => canvas.closeOthers(activeItem.id) }] : []
|
|
3371
|
+
] : []
|
|
3372
|
+
].filter((section) => section.length > 0);
|
|
3373
|
+
};
|
|
3150
3374
|
const showMenu = ports.showMenu;
|
|
3151
3375
|
if (showMenu) {
|
|
3152
|
-
const entries = [];
|
|
3153
|
-
const handlers = /* @__PURE__ */ new Map();
|
|
3154
|
-
sections.forEach((section, i) => {
|
|
3155
|
-
if (i > 0) entries.push({ type: "separator" });
|
|
3156
|
-
for (const action of section) {
|
|
3157
|
-
entries.push({ type: "item", id: action.id, label: action.label, ...action.destructive ? { destructive: true } : {} });
|
|
3158
|
-
handlers.set(action.id, action.onSelect);
|
|
3159
|
-
}
|
|
3160
|
-
});
|
|
3161
3376
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3162
3377
|
CanvasMenuTrigger,
|
|
3163
3378
|
{
|
|
3164
3379
|
onClick: (event) => {
|
|
3380
|
+
const entries = [];
|
|
3381
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
3382
|
+
buildSections().forEach((section, i) => {
|
|
3383
|
+
if (i > 0) entries.push({ type: "separator" });
|
|
3384
|
+
for (const action of section) {
|
|
3385
|
+
entries.push({ type: "item", id: action.id, label: action.label, ...action.destructive ? { destructive: true } : {} });
|
|
3386
|
+
handlers.set(action.id, action.onSelect);
|
|
3387
|
+
}
|
|
3388
|
+
});
|
|
3165
3389
|
const anchor = toCanvasRect(event.currentTarget.getBoundingClientRect());
|
|
3166
3390
|
void showMenu(entries, anchor).then(
|
|
3167
3391
|
(chosen) => {
|
|
@@ -3182,11 +3406,14 @@ function PaneMenu({
|
|
|
3182
3406
|
},
|
|
3183
3407
|
children: [
|
|
3184
3408
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasMenuTrigger, {}) }),
|
|
3185
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Content, { align: "end", sideOffset: 4, className: "mxc-menu", children:
|
|
3409
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Content, { align: "end", sideOffset: 4, className: "mxc-menu", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MenuSections, { build: buildSections }) }) })
|
|
3186
3410
|
]
|
|
3187
3411
|
}
|
|
3188
3412
|
);
|
|
3189
3413
|
}
|
|
3414
|
+
function MenuSections({ build }) {
|
|
3415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: build().map((section, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MenuSection, { first: i === 0, actions: section }, i)) });
|
|
3416
|
+
}
|
|
3190
3417
|
function MenuSection({ first, actions }) {
|
|
3191
3418
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3192
3419
|
first ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Menu.Separator, { className: "mxc-menu-separator" }),
|
|
@@ -3207,13 +3434,13 @@ function safeMenu(build) {
|
|
|
3207
3434
|
|
|
3208
3435
|
// src/react/CanvasColumn.tsx
|
|
3209
3436
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3210
|
-
var
|
|
3437
|
+
var useIsoLayoutEffect5 = typeof window === "undefined" ? import_react10.useEffect : import_react10.useLayoutEffect;
|
|
3211
3438
|
function subscribeViewport(listener) {
|
|
3212
3439
|
window.addEventListener("resize", listener);
|
|
3213
3440
|
return () => window.removeEventListener("resize", listener);
|
|
3214
3441
|
}
|
|
3215
3442
|
function useViewportWidth() {
|
|
3216
|
-
return (0,
|
|
3443
|
+
return (0, import_react10.useSyncExternalStore)(subscribeViewport, () => window.innerWidth, () => 0);
|
|
3217
3444
|
}
|
|
3218
3445
|
function useRegionWidth() {
|
|
3219
3446
|
const viewport = useViewportWidth();
|
|
@@ -3236,15 +3463,15 @@ function CanvasColumn({ className, style, onLiveWidth, placement = "docked" }) {
|
|
|
3236
3463
|
const isFullscreen = useCanvasState((s) => selectCanvasIsFullscreen(s, windowId));
|
|
3237
3464
|
const width = useCanvasState((s) => selectCanvasWidth(s, windowId));
|
|
3238
3465
|
const layout = useCanvasState((s) => selectCanvasLayout(s, windowId));
|
|
3239
|
-
const
|
|
3466
|
+
const presentedPaneId = useCanvasState((s) => selectCanvasPresentedPaneId(s, windowId));
|
|
3240
3467
|
const region = useRegionWidth();
|
|
3241
3468
|
const viewport = useViewportWidth();
|
|
3242
3469
|
const singlePane = placement === "docked" && viewport > 0 && viewport <= CANVAS_PHONE_MAX_WIDTH;
|
|
3243
|
-
const [dragWidth, setDragWidth] = (0,
|
|
3244
|
-
const [slots] = (0,
|
|
3245
|
-
const ref = (0,
|
|
3470
|
+
const [dragWidth, setDragWidth] = (0, import_react10.useState)(null);
|
|
3471
|
+
const [slots] = (0, import_react10.useState)(createCanvasSlots);
|
|
3472
|
+
const ref = (0, import_react10.useRef)(null);
|
|
3246
3473
|
useRegisterCanvasPresence();
|
|
3247
|
-
(0,
|
|
3474
|
+
(0, import_react10.useEffect)(() => {
|
|
3248
3475
|
const el = ref.current;
|
|
3249
3476
|
if (!el) return void 0;
|
|
3250
3477
|
let frame2 = 0;
|
|
@@ -3305,7 +3532,7 @@ function CanvasColumn({ className, style, onLiveWidth, placement = "docked" }) {
|
|
|
3305
3532
|
}
|
|
3306
3533
|
) : null,
|
|
3307
3534
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasSlotsContext.Provider, { value: slots, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(CanvasSinglePaneContext.Provider, { value: singlePane, children: [
|
|
3308
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mxc-layout", "data-single-pane": singlePane ? "" : void 0, children: singlePane ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasPaneView, { paneId:
|
|
3535
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mxc-layout", "data-single-pane": singlePane ? "" : void 0, children: singlePane ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasPaneView, { paneId: presentedPaneId ?? listPaneIds(layout)[0] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LayoutNodeView, { node: layout }) }),
|
|
3309
3536
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasBodyLayer, {})
|
|
3310
3537
|
] }) })
|
|
3311
3538
|
] })
|
|
@@ -3314,13 +3541,14 @@ function CanvasColumn({ className, style, onLiveWidth, placement = "docked" }) {
|
|
|
3314
3541
|
}
|
|
3315
3542
|
function WidthHandle({ width, region, onDrag }) {
|
|
3316
3543
|
const canvas = useCanvas();
|
|
3317
|
-
const start = (0,
|
|
3544
|
+
const start = (0, import_react10.useRef)(null);
|
|
3545
|
+
(0, import_react10.useEffect)(() => () => start.current?.end(), []);
|
|
3318
3546
|
const clamp = (next) => clampDraggedCanvasWidth(next, region, canvas.rules);
|
|
3319
3547
|
const onPointerDown = (event) => {
|
|
3320
3548
|
event.preventDefault();
|
|
3321
3549
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
3322
|
-
start.current
|
|
3323
|
-
|
|
3550
|
+
start.current?.end();
|
|
3551
|
+
start.current = { x: event.clientX, width, end: beginCanvasResize("") };
|
|
3324
3552
|
};
|
|
3325
3553
|
const onPointerMove = (event) => {
|
|
3326
3554
|
if (!start.current) return;
|
|
@@ -3329,8 +3557,8 @@ function WidthHandle({ width, region, onDrag }) {
|
|
|
3329
3557
|
const finish = (event) => {
|
|
3330
3558
|
if (!start.current) return;
|
|
3331
3559
|
const next = clamp(start.current.width + (start.current.x - event.clientX));
|
|
3560
|
+
start.current.end();
|
|
3332
3561
|
start.current = null;
|
|
3333
|
-
delete document.documentElement.dataset.mxcResizing;
|
|
3334
3562
|
onDrag(null);
|
|
3335
3563
|
canvas.setWidth(next);
|
|
3336
3564
|
};
|
|
@@ -3347,6 +3575,7 @@ function WidthHandle({ width, region, onDrag }) {
|
|
|
3347
3575
|
onPointerMove,
|
|
3348
3576
|
onPointerUp: finish,
|
|
3349
3577
|
onPointerCancel: finish,
|
|
3578
|
+
onLostPointerCapture: finish,
|
|
3350
3579
|
onDoubleClick: () => canvas.setWidth(clamp(Math.round(region / 2))),
|
|
3351
3580
|
onKeyDown: (event) => {
|
|
3352
3581
|
if (event.key === "ArrowLeft") canvas.setWidth(clamp(width + 32));
|
|
@@ -3355,17 +3584,13 @@ function WidthHandle({ width, region, onDrag }) {
|
|
|
3355
3584
|
}
|
|
3356
3585
|
);
|
|
3357
3586
|
}
|
|
3358
|
-
function presentedPane(layout, focused) {
|
|
3359
|
-
const ids = listPaneIds(layout);
|
|
3360
|
-
return ids.find((id) => id === focused) ?? ids[0];
|
|
3361
|
-
}
|
|
3362
3587
|
function LayoutNodeView({ node }) {
|
|
3363
3588
|
if (node.type === "pane") return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasPaneView, { paneId: node.paneId });
|
|
3364
3589
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SplitView, { node });
|
|
3365
3590
|
}
|
|
3366
3591
|
function useMeasuredWidth(ref, enabled) {
|
|
3367
|
-
const [width, setWidth] = (0,
|
|
3368
|
-
|
|
3592
|
+
const [width, setWidth] = (0, import_react10.useState)(0);
|
|
3593
|
+
useIsoLayoutEffect5(() => {
|
|
3369
3594
|
const el = ref.current;
|
|
3370
3595
|
if (!enabled || !el) return;
|
|
3371
3596
|
setWidth(el.getBoundingClientRect().width);
|
|
@@ -3378,8 +3603,8 @@ function useMeasuredWidth(ref, enabled) {
|
|
|
3378
3603
|
}
|
|
3379
3604
|
function SplitView({ node }) {
|
|
3380
3605
|
const canvas = useCanvas();
|
|
3381
|
-
const ref = (0,
|
|
3382
|
-
const [liveSizes, setLiveSizes] = (0,
|
|
3606
|
+
const ref = (0, import_react10.useRef)(null);
|
|
3607
|
+
const [liveSizes, setLiveSizes] = (0, import_react10.useState)(null);
|
|
3383
3608
|
const sizes = liveSizes ?? node.sizes;
|
|
3384
3609
|
const measuredWidth = useMeasuredWidth(ref, node.orientation === "horizontal" && canvas.rules.paneMinWidth > 0);
|
|
3385
3610
|
const stacked = node.orientation === "horizontal" && shouldStackSplit(measuredWidth, node.children.length, canvas.rules);
|
|
@@ -3396,7 +3621,7 @@ function SplitView({ node }) {
|
|
|
3396
3621
|
const base = [...node.sizes];
|
|
3397
3622
|
const pair = (base[index] ?? 0) + (base[index + 1] ?? 0);
|
|
3398
3623
|
const target = event.currentTarget;
|
|
3399
|
-
|
|
3624
|
+
const end = beginCanvasResize(horizontal ? "col" : "row");
|
|
3400
3625
|
const compute = (pos) => {
|
|
3401
3626
|
const delta = (pos - origin) / total;
|
|
3402
3627
|
const min = CANVAS_MIN_SPLIT_FRACTION;
|
|
@@ -3411,7 +3636,7 @@ function SplitView({ node }) {
|
|
|
3411
3636
|
target.removeEventListener("pointermove", move);
|
|
3412
3637
|
target.removeEventListener("pointerup", up);
|
|
3413
3638
|
target.removeEventListener("pointercancel", up);
|
|
3414
|
-
|
|
3639
|
+
end();
|
|
3415
3640
|
setLiveSizes(null);
|
|
3416
3641
|
canvas.resizeSplit(node.id, compute(horizontal ? e.clientX : e.clientY));
|
|
3417
3642
|
};
|