@tutti-os/workbench-surface 0.0.26 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +17 -5
- package/dist/index.js +322 -73
- package/dist/index.js.map +1 -1
- package/dist/styles/workbench.css +0 -474
- package/dist/styles/workbenchStyle.test.ts +0 -49
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -43,6 +43,9 @@ function createWorkbenchCommands(store) {
|
|
|
43
43
|
applyLayoutPreset(nodeIDs, preset) {
|
|
44
44
|
store.dispatch({ type: "applyLayoutPreset", nodeIDs, preset });
|
|
45
45
|
},
|
|
46
|
+
applyVisibleLayoutPreset(preset) {
|
|
47
|
+
store.dispatch({ type: "applyVisibleLayoutPreset", preset });
|
|
48
|
+
},
|
|
46
49
|
applyActiveSnapTarget(nodeID) {
|
|
47
50
|
store.dispatch({ type: "applyActiveSnapTarget", nodeID });
|
|
48
51
|
},
|
|
@@ -104,6 +107,7 @@ var defaultWorkbenchSurfaceSize = {
|
|
|
104
107
|
// src/core/geometry.ts
|
|
105
108
|
var WORKBENCH_MIN_VISIBLE_PX = 40;
|
|
106
109
|
var WORKBENCH_LAYOUT_PRESET_GAP_PX = 12;
|
|
110
|
+
var WORKBENCH_EDGE_SNAP_THRESHOLD_PX = 24;
|
|
107
111
|
function normalizeWorkbenchLayoutConstraints(constraints = {}) {
|
|
108
112
|
return {
|
|
109
113
|
minWidth: constraints.minWidth ?? defaultWorkbenchLayoutConstraints.minWidth,
|
|
@@ -241,18 +245,53 @@ function getWorkbenchSnapRect(snapTarget, surfaceSize, constraints = defaultWork
|
|
|
241
245
|
sizeConstraints
|
|
242
246
|
);
|
|
243
247
|
const full = getWorkbenchSafeLayoutRect(surfaceSize, normalized);
|
|
248
|
+
const halfWidth = Math.round(full.width / 2);
|
|
249
|
+
const halfHeight = Math.round(full.height / 2);
|
|
244
250
|
const clampSnapRect = (rect) => clampWorkbenchRect(rect, surfaceSize, normalized);
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
switch (snapTarget) {
|
|
252
|
+
case "left":
|
|
253
|
+
return clampSnapRect({ ...full, width: halfWidth });
|
|
254
|
+
case "right":
|
|
255
|
+
return clampSnapRect({
|
|
256
|
+
...full,
|
|
257
|
+
x: full.x + full.width - halfWidth,
|
|
258
|
+
width: halfWidth
|
|
259
|
+
});
|
|
260
|
+
case "top":
|
|
261
|
+
return clampSnapRect(full);
|
|
262
|
+
case "bottom":
|
|
263
|
+
return clampSnapRect({
|
|
264
|
+
...full,
|
|
265
|
+
y: full.y + full.height - halfHeight,
|
|
266
|
+
height: halfHeight
|
|
267
|
+
});
|
|
268
|
+
case "top-left":
|
|
269
|
+
return clampSnapRect({ ...full, width: halfWidth, height: halfHeight });
|
|
270
|
+
case "top-right":
|
|
271
|
+
return clampSnapRect({
|
|
272
|
+
...full,
|
|
273
|
+
x: full.x + full.width - halfWidth,
|
|
274
|
+
width: halfWidth,
|
|
275
|
+
height: halfHeight
|
|
276
|
+
});
|
|
277
|
+
case "bottom-left":
|
|
278
|
+
return clampSnapRect({
|
|
279
|
+
...full,
|
|
280
|
+
y: full.y + full.height - halfHeight,
|
|
281
|
+
width: halfWidth,
|
|
282
|
+
height: halfHeight
|
|
283
|
+
});
|
|
284
|
+
case "bottom-right":
|
|
285
|
+
return clampSnapRect({
|
|
286
|
+
...full,
|
|
287
|
+
x: full.x + full.width - halfWidth,
|
|
288
|
+
y: full.y + full.height - halfHeight,
|
|
289
|
+
width: halfWidth,
|
|
290
|
+
height: halfHeight
|
|
291
|
+
});
|
|
292
|
+
case null:
|
|
293
|
+
return null;
|
|
254
294
|
}
|
|
255
|
-
return null;
|
|
256
295
|
}
|
|
257
296
|
function getWorkbenchQuickLayoutRect(target, surfaceSize, constraints = defaultWorkbenchLayoutConstraints, sizeConstraints) {
|
|
258
297
|
const normalized = resolveWorkbenchRectConstraints(
|
|
@@ -260,6 +299,8 @@ function getWorkbenchQuickLayoutRect(target, surfaceSize, constraints = defaultW
|
|
|
260
299
|
sizeConstraints
|
|
261
300
|
);
|
|
262
301
|
const full = getWorkbenchSafeLayoutRect(surfaceSize, normalized);
|
|
302
|
+
const halfWidth = Math.round(full.width / 2);
|
|
303
|
+
const halfHeight = Math.round(full.height / 2);
|
|
263
304
|
const clampQuickLayoutRect = (rect) => clampWorkbenchRect(rect, surfaceSize, normalized);
|
|
264
305
|
switch (target) {
|
|
265
306
|
case "left":
|
|
@@ -281,13 +322,50 @@ function getWorkbenchQuickLayoutRect(target, surfaceSize, constraints = defaultW
|
|
|
281
322
|
height: Math.round(full.height / 2)
|
|
282
323
|
});
|
|
283
324
|
case "bottom": {
|
|
284
|
-
const height = Math.round(full.height / 2);
|
|
285
325
|
return clampQuickLayoutRect({
|
|
286
326
|
...full,
|
|
287
|
-
y: full.y + full.height -
|
|
327
|
+
y: full.y + full.height - halfHeight,
|
|
328
|
+
height: halfHeight
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
case "center": {
|
|
332
|
+
const width = Math.round(full.width * 0.72);
|
|
333
|
+
const height = Math.round(full.height * 0.72);
|
|
334
|
+
return clampQuickLayoutRect({
|
|
335
|
+
x: full.x + Math.round((full.width - width) / 2),
|
|
336
|
+
y: full.y + Math.round((full.height - height) / 2),
|
|
337
|
+
width,
|
|
288
338
|
height
|
|
289
339
|
});
|
|
290
340
|
}
|
|
341
|
+
case "top-left":
|
|
342
|
+
return clampQuickLayoutRect({
|
|
343
|
+
...full,
|
|
344
|
+
width: halfWidth,
|
|
345
|
+
height: halfHeight
|
|
346
|
+
});
|
|
347
|
+
case "top-right":
|
|
348
|
+
return clampQuickLayoutRect({
|
|
349
|
+
...full,
|
|
350
|
+
x: full.x + full.width - halfWidth,
|
|
351
|
+
width: halfWidth,
|
|
352
|
+
height: halfHeight
|
|
353
|
+
});
|
|
354
|
+
case "bottom-left":
|
|
355
|
+
return clampQuickLayoutRect({
|
|
356
|
+
...full,
|
|
357
|
+
y: full.y + full.height - halfHeight,
|
|
358
|
+
width: halfWidth,
|
|
359
|
+
height: halfHeight
|
|
360
|
+
});
|
|
361
|
+
case "bottom-right":
|
|
362
|
+
return clampQuickLayoutRect({
|
|
363
|
+
...full,
|
|
364
|
+
x: full.x + full.width - halfWidth,
|
|
365
|
+
y: full.y + full.height - halfHeight,
|
|
366
|
+
width: halfWidth,
|
|
367
|
+
height: halfHeight
|
|
368
|
+
});
|
|
291
369
|
}
|
|
292
370
|
}
|
|
293
371
|
function resolveWorkbenchRectConstraints(constraints = defaultWorkbenchLayoutConstraints, sizeConstraints) {
|
|
@@ -340,10 +418,34 @@ function getWorkbenchSafeLayoutRect(surfaceSize, constraints = defaultWorkbenchL
|
|
|
340
418
|
}
|
|
341
419
|
function inferWorkbenchSnapTarget(dragPoint, surfaceSize, threshold = 0, constraints = defaultWorkbenchLayoutConstraints) {
|
|
342
420
|
const frame = getWorkbenchLayoutFrame(surfaceSize, constraints);
|
|
343
|
-
const
|
|
344
|
-
|
|
421
|
+
const crossesLeft = threshold > 0 ? dragPoint.x <= frame.x + threshold : dragPoint.x < frame.x || frame.x === 0 && dragPoint.x <= 0;
|
|
422
|
+
const crossesRight = threshold > 0 ? dragPoint.x >= frame.x + frame.width - threshold : dragPoint.x > frame.x + frame.width || frame.x + frame.width === surfaceSize.width && dragPoint.x >= surfaceSize.width;
|
|
423
|
+
const crossesTop = threshold > 0 ? dragPoint.y <= frame.y + threshold : dragPoint.y < frame.y || frame.y === 0 && dragPoint.y <= 0;
|
|
424
|
+
const crossesBottom = threshold > 0 ? dragPoint.y >= frame.y + frame.height - threshold : dragPoint.y > frame.y + frame.height || frame.y + frame.height === surfaceSize.height && dragPoint.y >= surfaceSize.height;
|
|
425
|
+
if (crossesTop && crossesLeft) {
|
|
426
|
+
return "top-left";
|
|
427
|
+
}
|
|
428
|
+
if (crossesTop && crossesRight) {
|
|
429
|
+
return "top-right";
|
|
430
|
+
}
|
|
431
|
+
if (crossesBottom && crossesLeft) {
|
|
432
|
+
return "bottom-left";
|
|
433
|
+
}
|
|
434
|
+
if (crossesBottom && crossesRight) {
|
|
435
|
+
return "bottom-right";
|
|
436
|
+
}
|
|
437
|
+
if (crossesTop) {
|
|
345
438
|
return "top";
|
|
346
439
|
}
|
|
440
|
+
if (crossesBottom) {
|
|
441
|
+
return "bottom";
|
|
442
|
+
}
|
|
443
|
+
if (crossesLeft) {
|
|
444
|
+
return "left";
|
|
445
|
+
}
|
|
446
|
+
if (crossesRight) {
|
|
447
|
+
return "right";
|
|
448
|
+
}
|
|
347
449
|
return null;
|
|
348
450
|
}
|
|
349
451
|
function rectsEqual(left, right) {
|
|
@@ -618,49 +720,14 @@ function reduceWorkbenchState(state, action) {
|
|
|
618
720
|
minimizedAtUnixMs: null
|
|
619
721
|
};
|
|
620
722
|
});
|
|
621
|
-
case "applyLayoutPreset":
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
action.preset,
|
|
629
|
-
state.surfaceSize,
|
|
630
|
-
state.layoutConstraints
|
|
631
|
-
);
|
|
632
|
-
if (!frames) {
|
|
633
|
-
return state;
|
|
634
|
-
}
|
|
635
|
-
const frameByNodeID = new Map(
|
|
636
|
-
nodeIDs.map((nodeID, index) => [nodeID, frames[index]])
|
|
723
|
+
case "applyLayoutPreset":
|
|
724
|
+
return applyLayoutPresetToNodes(state, action.nodeIDs, action.preset);
|
|
725
|
+
case "applyVisibleLayoutPreset":
|
|
726
|
+
return applyLayoutPresetToNodes(
|
|
727
|
+
state,
|
|
728
|
+
state.nodes.filter((node) => !node.isMinimized).map((node) => node.id),
|
|
729
|
+
action.preset
|
|
637
730
|
);
|
|
638
|
-
const nodes = state.nodes.map((node) => {
|
|
639
|
-
const frame = frameByNodeID.get(node.id);
|
|
640
|
-
if (!frame) {
|
|
641
|
-
return node;
|
|
642
|
-
}
|
|
643
|
-
const nextFrame = clampWorkbenchRect(
|
|
644
|
-
frame,
|
|
645
|
-
state.surfaceSize,
|
|
646
|
-
state.layoutConstraints,
|
|
647
|
-
node.sizeConstraints
|
|
648
|
-
);
|
|
649
|
-
return {
|
|
650
|
-
...node,
|
|
651
|
-
frame: nextFrame,
|
|
652
|
-
displayMode: "floating",
|
|
653
|
-
restoreFrame: null,
|
|
654
|
-
isMinimized: false,
|
|
655
|
-
minimizedAtUnixMs: null
|
|
656
|
-
};
|
|
657
|
-
});
|
|
658
|
-
let nodeStack = state.nodeStack;
|
|
659
|
-
for (const nodeID of nodeIDs) {
|
|
660
|
-
nodeStack = focusWorkbenchStack(nodeStack, nodeID);
|
|
661
|
-
}
|
|
662
|
-
return { ...state, nodes, nodeStack };
|
|
663
|
-
}
|
|
664
731
|
case "applyActiveSnapTarget":
|
|
665
732
|
case "applySnapTarget":
|
|
666
733
|
return updateNode(state, action.nodeID, (node) => {
|
|
@@ -864,6 +931,49 @@ function updateNode(state, nodeID, update) {
|
|
|
864
931
|
nodeStack: focusWorkbenchStack(state.nodeStack, nodeID)
|
|
865
932
|
};
|
|
866
933
|
}
|
|
934
|
+
function applyLayoutPresetToNodes(state, inputNodeIDs, preset) {
|
|
935
|
+
const nodeIDs = uniqueKnownNodeIDs(state.nodes, inputNodeIDs);
|
|
936
|
+
if (nodeIDs.length === 0) {
|
|
937
|
+
return state;
|
|
938
|
+
}
|
|
939
|
+
const frames = getWorkbenchLayoutPresetFrames(
|
|
940
|
+
nodeIDs.length,
|
|
941
|
+
preset,
|
|
942
|
+
state.surfaceSize,
|
|
943
|
+
state.layoutConstraints
|
|
944
|
+
);
|
|
945
|
+
if (!frames) {
|
|
946
|
+
return state;
|
|
947
|
+
}
|
|
948
|
+
const frameByNodeID = new Map(
|
|
949
|
+
nodeIDs.map((nodeID, index) => [nodeID, frames[index]])
|
|
950
|
+
);
|
|
951
|
+
const nodes = state.nodes.map((node) => {
|
|
952
|
+
const frame = frameByNodeID.get(node.id);
|
|
953
|
+
if (!frame) {
|
|
954
|
+
return node;
|
|
955
|
+
}
|
|
956
|
+
const nextFrame = clampWorkbenchRect(
|
|
957
|
+
frame,
|
|
958
|
+
state.surfaceSize,
|
|
959
|
+
state.layoutConstraints,
|
|
960
|
+
node.sizeConstraints
|
|
961
|
+
);
|
|
962
|
+
return {
|
|
963
|
+
...node,
|
|
964
|
+
frame: nextFrame,
|
|
965
|
+
displayMode: "floating",
|
|
966
|
+
restoreFrame: null,
|
|
967
|
+
isMinimized: false,
|
|
968
|
+
minimizedAtUnixMs: null
|
|
969
|
+
};
|
|
970
|
+
});
|
|
971
|
+
let nodeStack = state.nodeStack;
|
|
972
|
+
for (const nodeID of nodeIDs) {
|
|
973
|
+
nodeStack = focusWorkbenchStack(nodeStack, nodeID);
|
|
974
|
+
}
|
|
975
|
+
return { ...state, nodes, nodeStack };
|
|
976
|
+
}
|
|
867
977
|
function uniqueKnownNodeIDs(nodes, nodeIDs) {
|
|
868
978
|
const knownNodeIDs = new Set(nodes.map((node) => node.id));
|
|
869
979
|
const orderedNodeIDs = [];
|
|
@@ -1015,6 +1125,11 @@ function summarizeWorkbenchAction(action) {
|
|
|
1015
1125
|
nodeIDs: action.nodeIDs,
|
|
1016
1126
|
preset: action.preset
|
|
1017
1127
|
};
|
|
1128
|
+
case "applyVisibleLayoutPreset":
|
|
1129
|
+
return {
|
|
1130
|
+
type: action.type,
|
|
1131
|
+
preset: action.preset
|
|
1132
|
+
};
|
|
1018
1133
|
case "applySnapTarget":
|
|
1019
1134
|
return {
|
|
1020
1135
|
type: action.type,
|
|
@@ -1629,6 +1744,16 @@ function selectFocusedWorkbenchNode(state) {
|
|
|
1629
1744
|
const focusedID = state.nodeStack.at(-1);
|
|
1630
1745
|
return state.nodes.find((node) => node.id === focusedID) ?? null;
|
|
1631
1746
|
}
|
|
1747
|
+
function selectFocusedVisibleWorkbenchNode(state) {
|
|
1748
|
+
const nodeByID = new Map(state.nodes.map((node) => [node.id, node]));
|
|
1749
|
+
for (let index = state.nodeStack.length - 1; index >= 0; index -= 1) {
|
|
1750
|
+
const node = nodeByID.get(state.nodeStack[index] ?? "");
|
|
1751
|
+
if (node && !node.isMinimized) {
|
|
1752
|
+
return node;
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
return state.nodes.find((node) => !node.isMinimized) ?? null;
|
|
1756
|
+
}
|
|
1632
1757
|
function selectFullscreenNodeToExitBeforeDockLaunch(state, targetNodeID) {
|
|
1633
1758
|
const nodeByID = new Map(state.nodes.map((node) => [node.id, node]));
|
|
1634
1759
|
const isVisibleFullscreenNode = (node) => {
|
|
@@ -1854,27 +1979,46 @@ import { useCallback as useCallback4 } from "react";
|
|
|
1854
1979
|
|
|
1855
1980
|
// src/react/hooks/useWorkbenchSnap.ts
|
|
1856
1981
|
import { useCallback as useCallback3 } from "react";
|
|
1982
|
+
|
|
1983
|
+
// src/react/hooks/workbenchSnapTarget.ts
|
|
1984
|
+
function resolveWorkbenchActiveSnapTarget(target, options = {}) {
|
|
1985
|
+
if (options.edgeSnapEnabled) {
|
|
1986
|
+
return target;
|
|
1987
|
+
}
|
|
1988
|
+
switch (target) {
|
|
1989
|
+
case "top":
|
|
1990
|
+
case "top-left":
|
|
1991
|
+
case "top-right":
|
|
1992
|
+
return "top";
|
|
1993
|
+
default:
|
|
1994
|
+
return null;
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
// src/react/hooks/useWorkbenchSnap.ts
|
|
1857
1999
|
function useWorkbenchSnap() {
|
|
1858
2000
|
const controller = useWorkbenchController();
|
|
1859
2001
|
return useCallback3(
|
|
1860
|
-
(
|
|
2002
|
+
(pointerClientPoint, options = {}) => {
|
|
1861
2003
|
const target = inferWorkbenchSnapTarget(
|
|
1862
|
-
|
|
2004
|
+
pointerClientPoint,
|
|
1863
2005
|
controller.getSnapshot().surfaceSize,
|
|
1864
|
-
|
|
2006
|
+
options.edgeSnapEnabled ? WORKBENCH_EDGE_SNAP_THRESHOLD_PX : 0,
|
|
1865
2007
|
controller.getSnapshot().layoutConstraints
|
|
1866
2008
|
);
|
|
1867
|
-
|
|
1868
|
-
|
|
2009
|
+
const activeTarget = resolveWorkbenchActiveSnapTarget(target, options);
|
|
2010
|
+
controller.commands.setActiveSnapTarget(activeTarget);
|
|
2011
|
+
return activeTarget;
|
|
1869
2012
|
},
|
|
1870
2013
|
[controller]
|
|
1871
2014
|
);
|
|
1872
2015
|
}
|
|
1873
2016
|
|
|
1874
2017
|
// src/react/hooks/useWorkbenchDrag.ts
|
|
1875
|
-
function useWorkbenchDrag(node) {
|
|
2018
|
+
function useWorkbenchDrag(node, options = {}) {
|
|
1876
2019
|
const controller = useWorkbenchController();
|
|
1877
2020
|
const updateSnap = useWorkbenchSnap();
|
|
2021
|
+
const edgeSnapEnabled = options.edgeSnapEnabled === true;
|
|
1878
2022
|
return useCallback4(
|
|
1879
2023
|
(event) => {
|
|
1880
2024
|
if (event.button !== 0) {
|
|
@@ -1892,7 +2036,10 @@ function useWorkbenchDrag(node) {
|
|
|
1892
2036
|
x: initialFrame.x + moveEvent.clientX - origin.x,
|
|
1893
2037
|
y: initialFrame.y + moveEvent.clientY - origin.y
|
|
1894
2038
|
};
|
|
1895
|
-
updateSnap(
|
|
2039
|
+
updateSnap(
|
|
2040
|
+
{ x: moveEvent.clientX, y: moveEvent.clientY },
|
|
2041
|
+
{ edgeSnapEnabled }
|
|
2042
|
+
);
|
|
1896
2043
|
controller.commands.dragNode(node.id, nextFrame);
|
|
1897
2044
|
};
|
|
1898
2045
|
const clearListeners = () => {
|
|
@@ -1903,7 +2050,10 @@ function useWorkbenchDrag(node) {
|
|
|
1903
2050
|
window.removeEventListener("pointercancel", cancelDrag);
|
|
1904
2051
|
};
|
|
1905
2052
|
const finishDrag = (upEvent) => {
|
|
1906
|
-
if (updateSnap(
|
|
2053
|
+
if (updateSnap(
|
|
2054
|
+
{ x: upEvent.clientX, y: upEvent.clientY },
|
|
2055
|
+
{ edgeSnapEnabled }
|
|
2056
|
+
) !== null) {
|
|
1907
2057
|
controller.commands.applyActiveSnapTarget(node.id);
|
|
1908
2058
|
}
|
|
1909
2059
|
clearListeners();
|
|
@@ -1915,7 +2065,7 @@ function useWorkbenchDrag(node) {
|
|
|
1915
2065
|
window.addEventListener("pointerup", finishDrag);
|
|
1916
2066
|
window.addEventListener("pointercancel", cancelDrag);
|
|
1917
2067
|
},
|
|
1918
|
-
[controller, node.frame, node.id, updateSnap]
|
|
2068
|
+
[controller, edgeSnapEnabled, node.frame, node.id, updateSnap]
|
|
1919
2069
|
);
|
|
1920
2070
|
}
|
|
1921
2071
|
|
|
@@ -2047,6 +2197,7 @@ function resolveWorkbenchNodeTypeId(data) {
|
|
|
2047
2197
|
}
|
|
2048
2198
|
function WorkbenchWindowFrame({
|
|
2049
2199
|
children,
|
|
2200
|
+
edgeSnapEnabled = false,
|
|
2050
2201
|
fullscreenHeaderMode,
|
|
2051
2202
|
genie,
|
|
2052
2203
|
hiddenMounted = false,
|
|
@@ -2071,7 +2222,7 @@ function WorkbenchWindowFrame({
|
|
|
2071
2222
|
const isResizing = useWorkbenchSelector(
|
|
2072
2223
|
(state) => state.activeResizeNodeId === node.id
|
|
2073
2224
|
);
|
|
2074
|
-
const onDragStart = useWorkbenchDrag(node);
|
|
2225
|
+
const onDragStart = useWorkbenchDrag(node, { edgeSnapEnabled });
|
|
2075
2226
|
const onHeaderDoubleClick = () => {
|
|
2076
2227
|
if (!interactive) {
|
|
2077
2228
|
return;
|
|
@@ -2272,6 +2423,7 @@ function stringArraysEqual(left, right) {
|
|
|
2272
2423
|
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2273
2424
|
function WorkbenchNodeLayer({
|
|
2274
2425
|
genie,
|
|
2426
|
+
edgeSnapEnabled = false,
|
|
2275
2427
|
interactive = true,
|
|
2276
2428
|
presentation,
|
|
2277
2429
|
renderNode,
|
|
@@ -2319,6 +2471,7 @@ function WorkbenchNodeLayer({
|
|
|
2319
2471
|
{
|
|
2320
2472
|
fullscreenHeaderMode: resolveFullscreenHeaderMode,
|
|
2321
2473
|
genie,
|
|
2474
|
+
edgeSnapEnabled,
|
|
2322
2475
|
interactive,
|
|
2323
2476
|
nodeID,
|
|
2324
2477
|
presentation,
|
|
@@ -2337,6 +2490,7 @@ function WorkbenchNodeLayer({
|
|
|
2337
2490
|
function WorkbenchNodeLayerItem({
|
|
2338
2491
|
fullscreenHeaderMode,
|
|
2339
2492
|
genie,
|
|
2493
|
+
edgeSnapEnabled,
|
|
2340
2494
|
interactive,
|
|
2341
2495
|
nodeID,
|
|
2342
2496
|
presentation,
|
|
@@ -2362,6 +2516,7 @@ function WorkbenchNodeLayerItem({
|
|
|
2362
2516
|
return /* @__PURE__ */ jsx6(
|
|
2363
2517
|
WorkbenchWindowFrame,
|
|
2364
2518
|
{
|
|
2519
|
+
edgeSnapEnabled,
|
|
2365
2520
|
hiddenMounted: node.isMinimized,
|
|
2366
2521
|
interactive,
|
|
2367
2522
|
presentation,
|
|
@@ -2398,26 +2553,111 @@ var MemoizedWorkbenchNodeLayerItem = memo(
|
|
|
2398
2553
|
|
|
2399
2554
|
// src/react/hooks/useWorkbenchShortcuts.ts
|
|
2400
2555
|
import { useEffect as useEffect2 } from "react";
|
|
2401
|
-
|
|
2556
|
+
|
|
2557
|
+
// src/react/hooks/workbenchShortcutIntent.ts
|
|
2558
|
+
function resolveWorkbenchShortcutIntent(event, options = {}) {
|
|
2559
|
+
if (event.defaultPrevented || isEditableShortcutTarget(event.target ?? null)) {
|
|
2560
|
+
return null;
|
|
2561
|
+
}
|
|
2562
|
+
if (event.key === "Escape" && !event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey) {
|
|
2563
|
+
return { type: "exitFullscreen" };
|
|
2564
|
+
}
|
|
2565
|
+
if (!matchesWindowManagementShortcutPreset(
|
|
2566
|
+
event,
|
|
2567
|
+
options.windowManagementShortcutPreset ?? null
|
|
2568
|
+
)) {
|
|
2569
|
+
return null;
|
|
2570
|
+
}
|
|
2571
|
+
switch (event.key) {
|
|
2572
|
+
case "ArrowLeft":
|
|
2573
|
+
return { type: "applyFocusedSnapTarget", snapTarget: "left" };
|
|
2574
|
+
case "ArrowRight":
|
|
2575
|
+
return { type: "applyFocusedSnapTarget", snapTarget: "right" };
|
|
2576
|
+
case "ArrowUp":
|
|
2577
|
+
return { type: "applyFocusedQuickLayout", target: "top" };
|
|
2578
|
+
case "ArrowDown":
|
|
2579
|
+
return { type: "applyFocusedQuickLayout", target: "bottom" };
|
|
2580
|
+
case "0":
|
|
2581
|
+
return {
|
|
2582
|
+
type: "applyVisibleLayoutPreset",
|
|
2583
|
+
preset: { kind: "balanced" }
|
|
2584
|
+
};
|
|
2585
|
+
default:
|
|
2586
|
+
return null;
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
function matchesWindowManagementShortcutPreset(event, preset) {
|
|
2590
|
+
if (preset === null) {
|
|
2591
|
+
return false;
|
|
2592
|
+
}
|
|
2593
|
+
if (!event.metaKey || event.ctrlKey || event.altKey) {
|
|
2594
|
+
return false;
|
|
2595
|
+
}
|
|
2596
|
+
switch (preset) {
|
|
2597
|
+
case "commandArrows":
|
|
2598
|
+
return !event.shiftKey;
|
|
2599
|
+
case "commandShiftArrows":
|
|
2600
|
+
return event.shiftKey === true;
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
function isEditableShortcutTarget(target) {
|
|
2604
|
+
const candidate = target;
|
|
2605
|
+
const tagName = candidate?.tagName?.toUpperCase();
|
|
2606
|
+
return candidate?.isContentEditable === true || tagName === "INPUT" || tagName === "TEXTAREA" || tagName === "SELECT";
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
// src/react/hooks/useWorkbenchShortcuts.ts
|
|
2610
|
+
function useWorkbenchShortcuts(options = {}) {
|
|
2402
2611
|
const controller = useWorkbenchController();
|
|
2612
|
+
const enabled = options.enabled ?? true;
|
|
2613
|
+
const windowManagementShortcutPreset = options.windowManagementShortcutPreset ?? null;
|
|
2403
2614
|
useEffect2(() => {
|
|
2404
2615
|
if (!enabled) {
|
|
2405
2616
|
return void 0;
|
|
2406
2617
|
}
|
|
2407
2618
|
const onKeyDown = (event) => {
|
|
2408
|
-
|
|
2619
|
+
const intent = resolveWorkbenchShortcutIntent(event, {
|
|
2620
|
+
windowManagementShortcutPreset
|
|
2621
|
+
});
|
|
2622
|
+
if (!intent) {
|
|
2409
2623
|
return;
|
|
2410
2624
|
}
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
controller.
|
|
2625
|
+
let handled = false;
|
|
2626
|
+
const focusedNode = selectFocusedVisibleWorkbenchNode(
|
|
2627
|
+
controller.getSnapshot()
|
|
2628
|
+
);
|
|
2629
|
+
if (intent.type === "exitFullscreen") {
|
|
2630
|
+
if (focusedNode?.displayMode === "fullscreen") {
|
|
2631
|
+
controller.commands.exitFullscreen(focusedNode.id);
|
|
2632
|
+
handled = true;
|
|
2633
|
+
}
|
|
2634
|
+
} else if (intent.type === "applyFocusedSnapTarget") {
|
|
2635
|
+
if (focusedNode) {
|
|
2636
|
+
controller.commands.applySnapTarget(
|
|
2637
|
+
focusedNode.id,
|
|
2638
|
+
intent.snapTarget
|
|
2639
|
+
);
|
|
2640
|
+
handled = true;
|
|
2641
|
+
}
|
|
2642
|
+
} else if (intent.type === "applyFocusedQuickLayout") {
|
|
2643
|
+
if (focusedNode) {
|
|
2644
|
+
controller.commands.applyQuickLayout(focusedNode.id, intent.target);
|
|
2645
|
+
handled = true;
|
|
2646
|
+
}
|
|
2647
|
+
} else {
|
|
2648
|
+
controller.commands.applyVisibleLayoutPreset(intent.preset);
|
|
2649
|
+
handled = true;
|
|
2650
|
+
}
|
|
2651
|
+
if (handled) {
|
|
2652
|
+
event.preventDefault();
|
|
2653
|
+
event.stopPropagation();
|
|
2414
2654
|
}
|
|
2415
2655
|
};
|
|
2416
2656
|
window.addEventListener("keydown", onKeyDown);
|
|
2417
2657
|
return () => {
|
|
2418
2658
|
window.removeEventListener("keydown", onKeyDown);
|
|
2419
2659
|
};
|
|
2420
|
-
}, [controller, enabled]);
|
|
2660
|
+
}, [controller, enabled, windowManagementShortcutPreset]);
|
|
2421
2661
|
}
|
|
2422
2662
|
|
|
2423
2663
|
// src/react/hooks/useWorkbenchSurfaceSize.ts
|
|
@@ -4346,6 +4586,7 @@ function WorkbenchSurface({
|
|
|
4346
4586
|
shortcutsEnabled,
|
|
4347
4587
|
shouldCaptureNodePreviewImage,
|
|
4348
4588
|
wallpaper,
|
|
4589
|
+
windowManagement,
|
|
4349
4590
|
windowChromeMode,
|
|
4350
4591
|
windowChromeI18n
|
|
4351
4592
|
}) {
|
|
@@ -4378,6 +4619,7 @@ function WorkbenchSurface({
|
|
|
4378
4619
|
shortcutsEnabled,
|
|
4379
4620
|
shouldCaptureNodePreviewImage,
|
|
4380
4621
|
wallpaper,
|
|
4622
|
+
windowManagement,
|
|
4381
4623
|
windowChromeMode,
|
|
4382
4624
|
windowChromeI18n
|
|
4383
4625
|
}
|
|
@@ -4410,6 +4652,7 @@ function WorkbenchSurfaceInner({
|
|
|
4410
4652
|
shortcutsEnabled,
|
|
4411
4653
|
shouldCaptureNodePreviewImage,
|
|
4412
4654
|
wallpaper,
|
|
4655
|
+
windowManagement,
|
|
4413
4656
|
windowChromeMode,
|
|
4414
4657
|
windowChromeI18n
|
|
4415
4658
|
}) {
|
|
@@ -4432,7 +4675,10 @@ function WorkbenchSurfaceInner({
|
|
|
4432
4675
|
resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
|
|
4433
4676
|
shouldCaptureNodePreviewImage
|
|
4434
4677
|
});
|
|
4435
|
-
useWorkbenchShortcuts(
|
|
4678
|
+
useWorkbenchShortcuts({
|
|
4679
|
+
enabled: (shortcutsEnabled ?? true) && interactive,
|
|
4680
|
+
windowManagementShortcutPreset: windowManagement?.shortcutPreset ?? null
|
|
4681
|
+
});
|
|
4436
4682
|
useEffect4(() => {
|
|
4437
4683
|
if (!layoutConstraints) {
|
|
4438
4684
|
return;
|
|
@@ -4472,6 +4718,7 @@ function WorkbenchSurfaceInner({
|
|
|
4472
4718
|
interactive,
|
|
4473
4719
|
presentation,
|
|
4474
4720
|
renderNode,
|
|
4721
|
+
edgeSnapEnabled: windowManagement?.edgeSnapEnabled === true,
|
|
4475
4722
|
renderWindowActions,
|
|
4476
4723
|
renderWindowHeader,
|
|
4477
4724
|
shouldKeepMinimizedNodeMounted,
|
|
@@ -12185,6 +12432,7 @@ function WorkbenchHost({
|
|
|
12185
12432
|
snapshotRepository,
|
|
12186
12433
|
shortcutsEnabled,
|
|
12187
12434
|
wallpaper,
|
|
12435
|
+
windowManagement,
|
|
12188
12436
|
workspaceId
|
|
12189
12437
|
}) {
|
|
12190
12438
|
const hostRuntimeConfig = useMemo7(
|
|
@@ -12309,6 +12557,7 @@ function WorkbenchHost({
|
|
|
12309
12557
|
shortcutsEnabled,
|
|
12310
12558
|
shouldCaptureNodePreviewImage: surfaceRenderers.shouldCaptureNodePreviewImage,
|
|
12311
12559
|
wallpaper,
|
|
12560
|
+
windowManagement,
|
|
12312
12561
|
windowChromeI18n,
|
|
12313
12562
|
windowChromeMode: surfaceRenderers.windowChromeMode
|
|
12314
12563
|
}
|