@witchcraft/layout 0.3.0 → 0.4.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/README.md +79 -74
- package/dist/module.json +1 -1
- package/dist/module.mjs +6 -1
- package/dist/runtime/components/FrameDragHandle.vue +1 -1
- package/dist/runtime/components/LayoutDecosEdges.d.vue.ts +15 -0
- package/dist/runtime/components/LayoutDecosEdges.vue +34 -0
- package/dist/runtime/components/LayoutDecosEdges.vue.d.ts +15 -0
- package/dist/runtime/components/LayoutDecosRects.d.vue.ts +15 -0
- package/dist/runtime/components/LayoutDecosRects.vue +37 -0
- package/dist/runtime/components/LayoutDecosRects.vue.d.ts +15 -0
- package/dist/runtime/components/LayoutDragEdgeGrabbed.d.vue.ts +2 -0
- package/dist/runtime/components/LayoutDragEdgeGrabbed.vue +43 -0
- package/dist/runtime/components/LayoutDragEdgeGrabbed.vue.d.ts +2 -0
- package/dist/runtime/components/LayoutDragEdgeHandle.d.vue.ts +9 -0
- package/dist/runtime/components/LayoutDragEdgeHandle.vue +44 -0
- package/dist/runtime/components/LayoutDragEdgeHandle.vue.d.ts +9 -0
- package/dist/runtime/components/{LayoutDecos.d.vue.ts → LayoutDragEdgeVisible.d.vue.ts} +3 -2
- package/dist/runtime/components/LayoutDragEdgeVisible.vue +38 -0
- package/dist/runtime/components/{LayoutDecos.vue.d.ts → LayoutDragEdgeVisible.vue.d.ts} +3 -2
- package/dist/runtime/components/LayoutDragEdges.d.vue.ts +21 -0
- package/dist/runtime/components/LayoutDragEdges.vue +67 -0
- package/dist/runtime/components/LayoutDragEdges.vue.d.ts +21 -0
- package/dist/runtime/components/LayoutEdgesActiveFrame.d.vue.ts +2 -0
- package/dist/runtime/components/LayoutEdgesActiveFrame.vue +35 -0
- package/dist/runtime/components/LayoutEdgesActiveFrame.vue.d.ts +2 -0
- package/dist/runtime/components/LayoutFrame.d.vue.ts +7 -6
- package/dist/runtime/components/LayoutFrame.vue +18 -14
- package/dist/runtime/components/LayoutFrame.vue.d.ts +7 -6
- package/dist/runtime/components/LayoutIntersectionHandle.d.vue.ts +10 -0
- package/dist/runtime/components/LayoutIntersectionHandle.vue +36 -0
- package/dist/runtime/components/LayoutIntersectionHandle.vue.d.ts +10 -0
- package/dist/runtime/components/LayoutIntersectionVisible.d.vue.ts +6 -0
- package/dist/runtime/components/LayoutIntersectionVisible.vue +34 -0
- package/dist/runtime/components/LayoutIntersectionVisible.vue.d.ts +6 -0
- package/dist/runtime/components/LayoutIntersections.d.vue.ts +21 -0
- package/dist/runtime/components/LayoutIntersections.vue +52 -0
- package/dist/runtime/components/LayoutIntersections.vue.d.ts +21 -0
- package/dist/runtime/components/{LayoutShapeSquare.d.vue.ts → LayoutShapeRect.d.vue.ts} +2 -2
- package/dist/runtime/components/{LayoutShapeSquare.vue.d.ts → LayoutShapeRect.vue.d.ts} +2 -2
- package/dist/runtime/components/LayoutWindow.d.vue.ts +252 -14
- package/dist/runtime/components/LayoutWindow.vue +27 -48
- package/dist/runtime/components/LayoutWindow.vue.d.ts +252 -14
- package/dist/runtime/composables/useFrames.d.ts +859 -2
- package/dist/runtime/composables/useFrames.js +2 -0
- package/dist/runtime/demo/App.vue +122 -74
- package/dist/runtime/demo/DemoControls.vue +7 -5
- package/dist/runtime/demo/index.html +12 -0
- package/dist/runtime/demo/tailwind.css +1 -1
- package/dist/runtime/drag/CloseAction.d.ts +1 -2
- package/dist/runtime/drag/CloseAction.js +1 -1
- package/dist/runtime/drag/DragActionHandler.d.ts +5 -3
- package/dist/runtime/drag/DragActionHandler.js +40 -6
- package/dist/runtime/drag/FrameDragAction.js +6 -7
- package/dist/runtime/drag/SplitAction.d.ts +1 -2
- package/dist/runtime/drag/SplitAction.js +1 -1
- package/dist/runtime/drag/createDefaultHandlers.d.ts +1 -1
- package/dist/runtime/drag/defaultDragActions.d.ts +1 -1
- package/dist/runtime/helpers/consoleDebugWindow.d.ts +43 -0
- package/dist/runtime/helpers/consoleDebugWindow.js +222 -0
- package/dist/runtime/helpers/convertLayoutWindowToWorkspace.js +2 -2
- package/dist/runtime/helpers/framesRedistributeFix.d.ts +87 -0
- package/dist/runtime/helpers/framesRedistributeFix.js +54 -0
- package/dist/runtime/helpers/getMoveEdgeInfo.d.ts +6 -2
- package/dist/runtime/helpers/getMoveEdgeInfo.js +11 -2
- package/dist/runtime/helpers/getPinnedEdgesForCollapsedFrames.d.ts +5 -0
- package/dist/runtime/helpers/getPinnedEdgesForCollapsedFrames.js +18 -0
- package/dist/runtime/helpers/getShapeRectCss.d.ts +7 -0
- package/dist/runtime/helpers/{getShapeSquareCss.js → getShapeRectCss.js} +1 -1
- package/dist/runtime/helpers/index.d.ts +3 -3
- package/dist/runtime/helpers/index.js +3 -3
- package/dist/runtime/helpers/moveEdge.js +3 -1
- package/dist/runtime/helpers/pxSizeToScaledSize.d.ts +2 -0
- package/dist/runtime/helpers/{numberToScaledSize.js → pxSizeToScaledSize.js} +1 -1
- package/dist/runtime/helpers/updateWindowSizeWithEvent.d.ts +3 -0
- package/dist/runtime/helpers/validateLayoutShape.d.ts +5 -0
- package/dist/runtime/helpers/validateLayoutShape.js +28 -0
- package/dist/runtime/layout/applyFrameChanges.js +6 -0
- package/dist/runtime/layout/createSplitDecoShapes.js +1 -1
- package/dist/runtime/layout/getFrameCollapseInfo.d.ts +5 -2
- package/dist/runtime/layout/getFrameCollapseInfo.js +16 -46
- package/dist/runtime/layout/getFrameDockInfo.d.ts +1 -1
- package/dist/runtime/layout/getFrameDockInfo.js +5 -1
- package/dist/runtime/layout/getFrameUncollapseInfo.d.ts +5 -2
- package/dist/runtime/layout/getFrameUncollapseInfo.js +16 -50
- package/dist/runtime/layout/getFramesRedistributeInfo.d.ts +20 -4
- package/dist/runtime/layout/getFramesRedistributeInfo.js +31 -2
- package/dist/runtime/layout/getRelaxFramesInfo.d.ts +7 -0
- package/dist/runtime/layout/getRelaxFramesInfo.js +91 -0
- package/dist/runtime/layout/getUpdateWindowSizeInfo.d.ts +13 -0
- package/dist/runtime/layout/getUpdateWindowSizeInfo.js +65 -0
- package/dist/runtime/layout/index.d.ts +1 -0
- package/dist/runtime/layout/index.js +1 -0
- package/dist/runtime/layout/resizeFrame.js +1 -3
- package/dist/runtime/settings.d.ts +26 -19
- package/dist/runtime/settings.js +57 -22
- package/dist/runtime/types/index.d.ts +1243 -30
- package/dist/runtime/types/index.js +22 -8
- package/dist/runtime/types/vue.d.ts +41 -0
- package/dist/runtime/{drag/types.js → types/vue.js} +1 -0
- package/dist/runtime/utils/cssToKey.d.ts +5 -0
- package/dist/runtime/utils/cssToKey.js +3 -0
- package/package.json +11 -12
- package/src/module.ts +6 -1
- package/src/runtime/components/FrameDragHandle.vue +1 -1
- package/src/runtime/components/LayoutDecosEdges.vue +38 -0
- package/src/runtime/components/LayoutDecosRects.vue +42 -0
- package/src/runtime/components/LayoutDragEdgeGrabbed.vue +50 -0
- package/src/runtime/components/LayoutDragEdgeHandle.vue +52 -0
- package/src/runtime/components/LayoutDragEdgeVisible.vue +45 -0
- package/src/runtime/components/LayoutDragEdges.vue +78 -0
- package/src/runtime/components/LayoutEdgesActiveFrame.vue +43 -0
- package/src/runtime/components/LayoutFrame.vue +22 -15
- package/src/runtime/components/LayoutIntersectionHandle.vue +45 -0
- package/src/runtime/components/LayoutIntersectionVisible.vue +41 -0
- package/src/runtime/components/LayoutIntersections.vue +64 -0
- package/src/runtime/components/{LayoutShapeSquare.vue → LayoutShapeRect.vue} +2 -2
- package/src/runtime/components/LayoutWindow.vue +29 -49
- package/src/runtime/composables/useFrames.ts +7 -2
- package/src/runtime/demo/App.vue +128 -78
- package/src/runtime/demo/DemoControls.vue +7 -5
- package/src/runtime/demo/index.html +12 -0
- package/src/runtime/demo/tailwind.css +3 -0
- package/src/runtime/drag/CloseAction.ts +2 -3
- package/src/runtime/drag/DragActionHandler.ts +48 -10
- package/src/runtime/drag/FrameDragAction.ts +4 -5
- package/src/runtime/drag/SplitAction.ts +4 -3
- package/src/runtime/drag/createDefaultHandlers.ts +2 -1
- package/src/runtime/drag/defaultDragActions.ts +2 -1
- package/src/runtime/helpers/consoleDebugWindow.ts +331 -0
- package/src/runtime/helpers/convertLayoutWindowToWorkspace.ts +2 -2
- package/src/runtime/helpers/framesRedistributeFix.ts +162 -0
- package/src/runtime/helpers/getMoveEdgeInfo.ts +22 -5
- package/src/runtime/helpers/getPinnedEdgesForCollapsedFrames.ts +29 -0
- package/src/runtime/helpers/{getShapeSquareCss.ts → getShapeRectCss.ts} +3 -3
- package/src/runtime/helpers/index.ts +4 -3
- package/src/runtime/helpers/moveEdge.ts +3 -1
- package/src/runtime/helpers/{numberToScaledSize.ts → pxSizeToScaledSize.ts} +2 -2
- package/src/runtime/helpers/updateWindowSizeWithEvent.ts +3 -0
- package/src/runtime/helpers/validateLayoutShape.ts +46 -0
- package/src/runtime/layout/applyFrameChanges.ts +5 -0
- package/src/runtime/layout/createSplitDecoShapes.ts +1 -1
- package/src/runtime/layout/getFrameCollapseInfo.ts +26 -85
- package/src/runtime/layout/getFrameDockInfo.ts +8 -1
- package/src/runtime/layout/getFrameUncollapseInfo.ts +29 -96
- package/src/runtime/layout/getFramesRedistributeInfo.ts +60 -5
- package/src/runtime/layout/getRelaxFramesInfo.ts +139 -0
- package/src/runtime/layout/getUpdateWindowSizeInfo.ts +105 -0
- package/src/runtime/layout/index.ts +1 -0
- package/src/runtime/layout/resizeFrame.ts +4 -3
- package/src/runtime/settings.ts +78 -25
- package/src/runtime/types/index.ts +205 -33
- package/src/runtime/types/vue.ts +41 -0
- package/src/runtime/utils/cssToKey.ts +8 -0
- package/dist/runtime/components/LayoutDecos.vue +0 -26
- package/dist/runtime/components/LayoutEdges.d.vue.ts +0 -17
- package/dist/runtime/components/LayoutEdges.vue +0 -144
- package/dist/runtime/components/LayoutEdges.vue.d.ts +0 -17
- package/dist/runtime/drag/types.d.ts +0 -161
- package/dist/runtime/helpers/clampNumber.d.ts +0 -1
- package/dist/runtime/helpers/clampNumber.js +0 -3
- package/dist/runtime/helpers/getShapeSquareCss.d.ts +0 -7
- package/dist/runtime/helpers/numberToScaledSize.d.ts +0 -2
- package/src/runtime/components/LayoutDecos.vue +0 -28
- package/src/runtime/components/LayoutEdges.vue +0 -170
- package/src/runtime/drag/types.ts +0 -177
- package/src/runtime/helpers/clampNumber.ts +0 -9
- /package/dist/runtime/components/{LayoutShapeSquare.vue → LayoutShapeRect.vue} +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { castType } from "@alanscodelog/utils/castType";
|
|
2
|
+
import { settings } from "../settings.js";
|
|
3
|
+
export function consoleDebugWindow(win, targetWidth = 100, labelFunc = createDebugLabeler()) {
|
|
4
|
+
const consoleCharAspect = 0.5;
|
|
5
|
+
const windowAspect = win.pxWidth / win.pxHeight;
|
|
6
|
+
const effectiveRatio = 1 / windowAspect * consoleCharAspect;
|
|
7
|
+
console.log(boxesToText(Object.values(win.frames), targetWidth, {
|
|
8
|
+
heightScale: effectiveRatio,
|
|
9
|
+
labelFunc
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
export function boxesToText(boxes, targetWidth = 100, {
|
|
13
|
+
border = {},
|
|
14
|
+
heightScale = 1,
|
|
15
|
+
labelFunc = () => ""
|
|
16
|
+
} = {}) {
|
|
17
|
+
border = {
|
|
18
|
+
horizontal: "\u2500",
|
|
19
|
+
vertical: "\u2502",
|
|
20
|
+
topLeft: "\u250C",
|
|
21
|
+
topRight: "\u2510",
|
|
22
|
+
bottomLeft: "\u2514",
|
|
23
|
+
bottomRight: "\u2518",
|
|
24
|
+
cross: "\u253C",
|
|
25
|
+
fill: " ",
|
|
26
|
+
labelBg: " ",
|
|
27
|
+
...border
|
|
28
|
+
};
|
|
29
|
+
castType(border);
|
|
30
|
+
const normBoxes = boxes.map((box) => ({
|
|
31
|
+
...box,
|
|
32
|
+
original: box,
|
|
33
|
+
id: box.id,
|
|
34
|
+
x: box.x / 100,
|
|
35
|
+
y: box.y / 100,
|
|
36
|
+
width: box.width / 100,
|
|
37
|
+
height: box.height / 100
|
|
38
|
+
}));
|
|
39
|
+
let minX = Infinity, minY = Infinity;
|
|
40
|
+
let maxX = -Infinity, maxY = -Infinity;
|
|
41
|
+
normBoxes.forEach((box) => {
|
|
42
|
+
minX = Math.min(minX, box.x);
|
|
43
|
+
minY = Math.min(minY, box.y);
|
|
44
|
+
maxX = Math.max(maxX, box.x + box.width);
|
|
45
|
+
maxY = Math.max(maxY, box.y + box.height);
|
|
46
|
+
});
|
|
47
|
+
const availableWidth = targetWidth;
|
|
48
|
+
const availableHeight = Math.floor(availableWidth * heightScale);
|
|
49
|
+
const totalWidth = maxX - minX || 1;
|
|
50
|
+
const totalHeight = maxY - minY || 1;
|
|
51
|
+
const scaleX_final = availableWidth / totalWidth;
|
|
52
|
+
const scaleY_final = availableHeight / totalHeight;
|
|
53
|
+
const scaledBoxes = normBoxes.map((box) => {
|
|
54
|
+
const idPart = box.id !== void 0 && box.id !== null && box.id !== "" ? String(box.id) : "??";
|
|
55
|
+
const funcLabel = labelFunc(box.original);
|
|
56
|
+
const label = funcLabel && funcLabel.trim() ? `${idPart} ${funcLabel}` : idPart;
|
|
57
|
+
return {
|
|
58
|
+
id: box.id,
|
|
59
|
+
x: (box.x - minX) * scaleX_final,
|
|
60
|
+
y: (box.y - minY) * scaleY_final,
|
|
61
|
+
width: box.width * scaleX_final,
|
|
62
|
+
height: box.height * scaleY_final,
|
|
63
|
+
label,
|
|
64
|
+
original: box
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
const cols = Math.min(availableWidth, Math.floor(totalWidth * scaleX_final));
|
|
68
|
+
const rows = Math.min(availableHeight, Math.floor(totalHeight * scaleY_final));
|
|
69
|
+
if (cols < 1 || rows < 1) {
|
|
70
|
+
return new Error("Grid too small to display");
|
|
71
|
+
}
|
|
72
|
+
const grid = Array(rows).fill(null).map(
|
|
73
|
+
() => Array(cols).fill(null).map(() => ({
|
|
74
|
+
char: border.fill,
|
|
75
|
+
priority: 0,
|
|
76
|
+
type: "fill",
|
|
77
|
+
boxIndex: -1
|
|
78
|
+
}))
|
|
79
|
+
);
|
|
80
|
+
function setCell(x, y, char, priority, type, boxIndex) {
|
|
81
|
+
if (x < 0 || y < 0 || x >= cols || y >= rows) return;
|
|
82
|
+
const current = grid[y][x];
|
|
83
|
+
if (boxIndex > current.boxIndex || boxIndex === current.boxIndex && priority > current.priority) {
|
|
84
|
+
grid[y][x] = { char, priority, type, boxIndex };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function getCell(x, y) {
|
|
88
|
+
if (x < 0 || y < 0 || x >= cols || y >= rows) return void 0;
|
|
89
|
+
return grid[y][x];
|
|
90
|
+
}
|
|
91
|
+
for (let boxIndex = scaledBoxes.length - 1; boxIndex >= 0; boxIndex--) {
|
|
92
|
+
const box = scaledBoxes[boxIndex];
|
|
93
|
+
const x1 = Math.round(box.x);
|
|
94
|
+
const y1 = Math.round(box.y);
|
|
95
|
+
const x2 = Math.round(box.x + box.width);
|
|
96
|
+
const y2 = Math.round(box.y + box.height);
|
|
97
|
+
const clampedX1 = Math.max(0, Math.min(cols - 1, x1));
|
|
98
|
+
const clampedY1 = Math.max(0, Math.min(rows - 1, y1));
|
|
99
|
+
const clampedX2 = Math.max(0, Math.min(cols - 1, x2));
|
|
100
|
+
const clampedY2 = Math.max(0, Math.min(rows - 1, y2));
|
|
101
|
+
if (clampedX1 >= clampedX2 || clampedY1 >= clampedY2) continue;
|
|
102
|
+
const edgePriority = 10;
|
|
103
|
+
if (clampedY1 >= 0 && clampedY1 < rows) {
|
|
104
|
+
for (let x = clampedX1 + 1; x < clampedX2; x++) {
|
|
105
|
+
const cell = getCell(x, clampedY1);
|
|
106
|
+
if (cell && cell.type === "vertical" && cell.boxIndex !== boxIndex) {
|
|
107
|
+
setCell(x, clampedY1, border.cross, edgePriority, "cross", boxIndex);
|
|
108
|
+
} else {
|
|
109
|
+
setCell(x, clampedY1, border.horizontal, edgePriority, "horizontal", boxIndex);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (clampedY2 >= 0 && clampedY2 < rows && clampedY2 !== clampedY1) {
|
|
114
|
+
for (let x = clampedX1 + 1; x < clampedX2; x++) {
|
|
115
|
+
const cell = getCell(x, clampedY2);
|
|
116
|
+
if (cell && cell.type === "vertical" && cell.boxIndex !== boxIndex) {
|
|
117
|
+
setCell(x, clampedY2, border.cross, edgePriority, "cross", boxIndex);
|
|
118
|
+
} else {
|
|
119
|
+
setCell(x, clampedY2, border.horizontal, edgePriority, "horizontal", boxIndex);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (clampedX1 >= 0 && clampedX1 < cols) {
|
|
124
|
+
for (let y = clampedY1 + 1; y < clampedY2; y++) {
|
|
125
|
+
const cell = getCell(clampedX1, y);
|
|
126
|
+
if (cell && (cell.type === "horizontal" || cell.type === "cross") && cell.boxIndex !== boxIndex) {
|
|
127
|
+
setCell(clampedX1, y, border.cross, edgePriority, "cross", boxIndex);
|
|
128
|
+
} else {
|
|
129
|
+
setCell(clampedX1, y, border.vertical, edgePriority, "vertical", boxIndex);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (clampedX2 >= 0 && clampedX2 < cols && clampedX2 !== clampedX1) {
|
|
134
|
+
for (let y = clampedY1 + 1; y < clampedY2; y++) {
|
|
135
|
+
const cell = getCell(clampedX2, y);
|
|
136
|
+
if (cell && (cell.type === "horizontal" || cell.type === "cross") && cell.boxIndex !== boxIndex) {
|
|
137
|
+
setCell(clampedX2, y, border.cross, edgePriority, "cross", boxIndex);
|
|
138
|
+
} else {
|
|
139
|
+
setCell(clampedX2, y, border.vertical, edgePriority, "vertical", boxIndex);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const cornerPriority = 20;
|
|
144
|
+
const corners = [
|
|
145
|
+
{ x: clampedX1, y: clampedY1, char: border.topLeft, type: "corner" },
|
|
146
|
+
{ x: clampedX2, y: clampedY1, char: border.topRight, type: "corner" },
|
|
147
|
+
{ x: clampedX1, y: clampedY2, char: border.bottomLeft, type: "corner" },
|
|
148
|
+
{ x: clampedX2, y: clampedY2, char: border.bottomRight, type: "corner" }
|
|
149
|
+
];
|
|
150
|
+
corners.forEach((corner) => {
|
|
151
|
+
if (corner.x < 0 || corner.y < 0 || corner.x >= cols || corner.y >= rows) return;
|
|
152
|
+
const cell = getCell(corner.x, corner.y);
|
|
153
|
+
if (cell && cell.boxIndex !== boxIndex && cell.type !== "fill") {
|
|
154
|
+
if (cell.type === "horizontal" || cell.type === "vertical" || cell.type === "cross") {
|
|
155
|
+
setCell(corner.x, corner.y, border.cross, cornerPriority, "cross", boxIndex);
|
|
156
|
+
} else {
|
|
157
|
+
setCell(corner.x, corner.y, corner.char, cornerPriority, corner.type, boxIndex);
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
setCell(corner.x, corner.y, corner.char, cornerPriority, corner.type, boxIndex);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
const labelPriority = 30;
|
|
164
|
+
if (box.label && box.label.trim().length > 0) {
|
|
165
|
+
const labelText = String(box.label);
|
|
166
|
+
const boxWidth = clampedX2 - clampedX1;
|
|
167
|
+
const boxHeight = clampedY2 - clampedY1;
|
|
168
|
+
const interiorWidth = boxWidth - 2;
|
|
169
|
+
const interiorHeight = boxHeight - 2;
|
|
170
|
+
if (interiorWidth >= 1 && interiorHeight >= 0) {
|
|
171
|
+
let displayText = labelText;
|
|
172
|
+
if (displayText.length > interiorWidth) {
|
|
173
|
+
displayText = displayText.substring(0, interiorWidth);
|
|
174
|
+
}
|
|
175
|
+
const interiorLeft = clampedX1 + 1;
|
|
176
|
+
const interiorRight = clampedX2 - 1;
|
|
177
|
+
const interiorTop = clampedY1 + 1;
|
|
178
|
+
const interiorBottom = clampedY2 - 1;
|
|
179
|
+
const interiorCenterX = Math.floor((interiorLeft + interiorRight) / 2);
|
|
180
|
+
const interiorCenterY = Math.floor((interiorTop + interiorBottom) / 2);
|
|
181
|
+
let startX = interiorCenterX - Math.floor(displayText.length / 2);
|
|
182
|
+
if (startX < interiorLeft) {
|
|
183
|
+
startX = interiorLeft;
|
|
184
|
+
}
|
|
185
|
+
if (startX + displayText.length > interiorRight) {
|
|
186
|
+
startX = interiorRight - displayText.length;
|
|
187
|
+
}
|
|
188
|
+
for (let i = 0; i < displayText.length; i++) {
|
|
189
|
+
const xPos = startX + i;
|
|
190
|
+
const yPos = interiorCenterY;
|
|
191
|
+
if (xPos >= interiorLeft && xPos < interiorRight && yPos >= interiorTop && yPos < interiorBottom) {
|
|
192
|
+
setCell(xPos, yPos, border.labelBg, labelPriority, "label", boxIndex);
|
|
193
|
+
setCell(xPos, yPos, displayText[i], labelPriority + 1, "label", boxIndex);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const displayGrid = grid.map((row) => row.map((cell) => cell.char).join("")).join("\n");
|
|
200
|
+
return displayGrid;
|
|
201
|
+
}
|
|
202
|
+
export function createDebugLabeler({
|
|
203
|
+
showPxSize = false,
|
|
204
|
+
showCollapsed = true,
|
|
205
|
+
showDocked = true,
|
|
206
|
+
showSize = true,
|
|
207
|
+
showPos = true,
|
|
208
|
+
getWin
|
|
209
|
+
} = {}) {
|
|
210
|
+
return function(f) {
|
|
211
|
+
if (showPxSize && !getWin) throw new Error("showPxSize is true but getWin is not provided");
|
|
212
|
+
const win = showPxSize ? getWin?.(f) : void 0;
|
|
213
|
+
const widthPx = showPxSize ? Math.round(f.width / settings.maxInt * win.pxWidth) : void 0;
|
|
214
|
+
const heightPx = showPxSize ? Math.round(f.height / settings.maxInt * win.pxHeight) : void 0;
|
|
215
|
+
const isCollapsed = showCollapsed && typeof f.collapsed === "number" ? "~" : "";
|
|
216
|
+
const isDocked = showDocked && f.docked ? "*" : "";
|
|
217
|
+
const size = showSize ? ` ${f.width}x${f.height}` : "";
|
|
218
|
+
const pos = showPos ? ` ${f.x},${f.y}` : "";
|
|
219
|
+
const pxSize = showPxSize ? ` ${widthPx}x${heightPx}px` : "";
|
|
220
|
+
return `${isCollapsed}${isDocked}${size}${pos}${pxSize}`;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { walk } from "@alanscodelog/utils/walk";
|
|
2
2
|
export function convertLayoutWindowToWorkspace(layout) {
|
|
3
|
-
const l =
|
|
3
|
+
const l = walk(layout, void 0, { save: true });
|
|
4
4
|
delete l.id;
|
|
5
5
|
delete l.pxHeight;
|
|
6
6
|
delete l.pxWidth;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { EdgeSide, LayoutFrame, LayoutWindow } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Prepares frames that need to be temporarily repositioned before redistribution
|
|
4
|
+
* and returns functions to apply/revert the fixes after redistribution. Used mostly internally for collapse/uncollapse of docked frames and similar operations.
|
|
5
|
+
*
|
|
6
|
+
* It exists because if you try to resize a layout like this to the right, you will get issues with frame edges not lining up as frame B would be resized less than A. If you had a frame at the empty space that you excluded, it's right edge would no longer align with B's.
|
|
7
|
+
*
|
|
8
|
+
* This helper takes frames like A, moves the edge so it's shared then moved them back. Just excluding them from the calcuation usually leads to subtler errors. Such as if there are frames after A and B to the right, excluding A would mean A's right edge would stop aligning with those other frames.
|
|
9
|
+
*
|
|
10
|
+
* ┌────────────┐
|
|
11
|
+
* │A │
|
|
12
|
+
* └──┬─────────┤
|
|
13
|
+
* │B │
|
|
14
|
+
* └─────────┘
|
|
15
|
+
*
|
|
16
|
+
* It has two modes, shrink and expand meant for collapse/uncollapse operations.
|
|
17
|
+
*
|
|
18
|
+
* ## Expand
|
|
19
|
+
*
|
|
20
|
+
* When multiple frames are docked* they may share an edge like this:
|
|
21
|
+
* For example, if we collapse A, we need to allow everything else to expand,
|
|
22
|
+
* but if we expand D it will overflow the bounds of the window and we'd get an error.
|
|
23
|
+
* To avoid this, we shrink these frames towards the opposite side first.
|
|
24
|
+
*
|
|
25
|
+
* collapsed size/amount
|
|
26
|
+
* ├──┘
|
|
27
|
+
* │ shrink amount
|
|
28
|
+
* │ ├───┘
|
|
29
|
+
* ├──────┬───────────┐
|
|
30
|
+
* │A*│ │B* │
|
|
31
|
+
* │ ├──────┬────┤
|
|
32
|
+
* │ │ │E │C* │
|
|
33
|
+
* │ │ │ │
|
|
34
|
+
* ├──┴───┴──────┤ │
|
|
35
|
+
* │D* │ │
|
|
36
|
+
* └──────┬──────┴────┘
|
|
37
|
+
* │we would shrink D to here
|
|
38
|
+
*
|
|
39
|
+
* D.x = A.x + A.width, and then subtract the difference from it's width
|
|
40
|
+
*
|
|
41
|
+
* ***IMPROTANT: It needs to stay aligned with the right side of A and the rest of the frames, or redistribute doesn't know how to redistribute it properly.
|
|
42
|
+
*
|
|
43
|
+
* When redistribute expands it again by shrinkAmount it will end up at A.x + collapseSize.
|
|
44
|
+
*
|
|
45
|
+
* This works fine when collapseSize is 0, but otherwise breaks so we keep a list of
|
|
46
|
+
* fixes to make after redistributing to place it's left edge back at the right place (it's right edge will have been moved by redistribute).
|
|
47
|
+
*
|
|
48
|
+
* ## Shrink
|
|
49
|
+
*
|
|
50
|
+
* Mirrors collapse, the only difference being we can skip the fixes if the frame was fully collapsed to 0.
|
|
51
|
+
*
|
|
52
|
+
* Why is this? Well take this example where A is docked and collapsed and B is docked, in the following two cases we would have no problems expanding as B ends where A begins, but if B shares the edge and A is not fully collapsed it is no longer aligned with the "end" of A.
|
|
53
|
+
*
|
|
54
|
+
* Ok:
|
|
55
|
+
* A - fully collapsed to 0
|
|
56
|
+
* ~ ┌──────────┐
|
|
57
|
+
* │ │B* │
|
|
58
|
+
* │ ├──────────┤
|
|
59
|
+
* │ │ │
|
|
60
|
+
* │ │ │
|
|
61
|
+
* │ └──────────┘
|
|
62
|
+
*
|
|
63
|
+
* Ok:
|
|
64
|
+
* A collapsed to non-zero size
|
|
65
|
+
* Note B still shares A's right edge
|
|
66
|
+
* ┌──┬─────────┐
|
|
67
|
+
* │A~│B* │
|
|
68
|
+
* │ ├─────────┤
|
|
69
|
+
* │ │ │
|
|
70
|
+
* │ │ │
|
|
71
|
+
* └──┴─────────┘
|
|
72
|
+
*
|
|
73
|
+
* Causes issues:
|
|
74
|
+
* A collapsed to non-zero size with B docked first
|
|
75
|
+
* B looses alignment with A causing issues when redistributing
|
|
76
|
+
* ┌────────────┐
|
|
77
|
+
* │B* │
|
|
78
|
+
* ├──┬─────────┤
|
|
79
|
+
* │A~│ │
|
|
80
|
+
* │ │ │
|
|
81
|
+
* └──┴─────────┘
|
|
82
|
+
*
|
|
83
|
+
*/
|
|
84
|
+
export declare function framesRedistributeFix(win: LayoutWindow, frame: LayoutFrame, dockedSide: EdgeSide, posKey: "x" | "y", sizeKey: "width" | "height", mode?: "shrink" | "expand"): {
|
|
85
|
+
applyFixes: () => void;
|
|
86
|
+
toFix: string[];
|
|
87
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { oppositeSide } from "./oppositeSide.js";
|
|
2
|
+
import { settings } from "../settings.js";
|
|
3
|
+
export function framesRedistributeFix(win, frame, dockedSide, posKey, sizeKey, mode = "shrink") {
|
|
4
|
+
const framesToFix = [];
|
|
5
|
+
const opposite = oppositeSide(dockedSide);
|
|
6
|
+
if (mode === "expand" && frame[sizeKey] === 0) {
|
|
7
|
+
return {
|
|
8
|
+
applyFixes: () => {
|
|
9
|
+
},
|
|
10
|
+
toFix: []
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
for (const other of Object.values(win.frames)) {
|
|
14
|
+
if (frame.id === other.id || !other.docked) continue;
|
|
15
|
+
if (mode === "expand" && (other.width === 0 || other.height === 0)) continue;
|
|
16
|
+
if (other.docked === opposite) continue;
|
|
17
|
+
if (dockedSide === "left" || dockedSide === "top") {
|
|
18
|
+
if (other[posKey] !== 0) continue;
|
|
19
|
+
other[posKey] = frame[posKey] + frame[sizeKey];
|
|
20
|
+
other[sizeKey] -= frame[sizeKey];
|
|
21
|
+
framesToFix.push({
|
|
22
|
+
id: other.id,
|
|
23
|
+
posKey,
|
|
24
|
+
sizeKey,
|
|
25
|
+
type: "start"
|
|
26
|
+
});
|
|
27
|
+
} else {
|
|
28
|
+
if (other[posKey] + other[sizeKey] !== settings.maxInt) continue;
|
|
29
|
+
other[sizeKey] -= frame[sizeKey];
|
|
30
|
+
framesToFix.push({
|
|
31
|
+
id: other.id,
|
|
32
|
+
posKey,
|
|
33
|
+
sizeKey,
|
|
34
|
+
type: "end"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
applyFixes: () => {
|
|
40
|
+
for (const fix of framesToFix) {
|
|
41
|
+
const other = win.frames[fix.id];
|
|
42
|
+
if (fix.type === "start") {
|
|
43
|
+
const sizeDiff = other[fix.posKey];
|
|
44
|
+
other[fix.posKey] = 0;
|
|
45
|
+
other[fix.sizeKey] += sizeDiff;
|
|
46
|
+
} else {
|
|
47
|
+
const sizeDiff = settings.maxInt - (other[fix.posKey] + other[fix.sizeKey]);
|
|
48
|
+
other[fix.sizeKey] += sizeDiff;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
toFix: framesToFix.map((f) => f.id)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { Direction, Edge, LayoutFrame, Point, Size } from "../types/index.js";
|
|
2
|
+
import { LAYOUT_ERROR } from "../types/index.js";
|
|
3
|
+
import { KnownError } from "../utils/KnownError.js";
|
|
2
4
|
export declare function getMoveEdgeInfo(touchingFrames: LayoutFrame[], edge: Edge,
|
|
3
5
|
/** Window scaled/snaped position. See {@link toWindowCoord} */
|
|
4
|
-
position: Point, margin?: Size, clamp?: boolean
|
|
6
|
+
position: Point, margin?: Size, clamp?: boolean,
|
|
7
|
+
/** Skip the collapsed frame check. Used internally during window resize adjustments. */
|
|
8
|
+
ignoreCollapsedCheck?: boolean): {
|
|
5
9
|
x: number;
|
|
6
10
|
y: number;
|
|
7
11
|
dir: Direction;
|
|
8
12
|
isPassedLimit: boolean;
|
|
9
13
|
pos: number;
|
|
10
14
|
distance: number;
|
|
11
|
-
}
|
|
15
|
+
} | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_COLLAPSED_FRAME>;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { clampNumber } from "
|
|
1
|
+
import { clampNumber } from "@alanscodelog/utils/clampNumber";
|
|
2
2
|
import { getEdgeOrientation } from "./getEdgeOrientation.js";
|
|
3
3
|
import { getResizeLimit } from "./getResizeLimit.js";
|
|
4
4
|
import { settings } from "../settings.js";
|
|
5
|
-
|
|
5
|
+
import { LAYOUT_ERROR } from "../types/index.js";
|
|
6
|
+
import { KnownError } from "../utils/KnownError.js";
|
|
7
|
+
export function getMoveEdgeInfo(touchingFrames, edge, position, margin = settings.minSizeScaled, clamp = true, ignoreCollapsedCheck = false) {
|
|
8
|
+
if (!ignoreCollapsedCheck) {
|
|
9
|
+
for (const frame of touchingFrames) {
|
|
10
|
+
if (frame.collapsed) {
|
|
11
|
+
return new KnownError(LAYOUT_ERROR.CANT_RESIZE_COLLAPSED_FRAME, `Cannot resize non-0 collapsed frame ${frame.id}.`, { frame });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
6
15
|
const { x: posX, y: posY } = position;
|
|
7
16
|
const edgeDirection = getEdgeOrientation(edge);
|
|
8
17
|
const dir = edgeDirection === "horizontal" ? posY < edge.startY ? "up" : "down" : posX < edge.startX ? "left" : "right";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function getPinnedEdgesForCollapsedFrames(win, frame, dockedSide, posKey, sizeKey) {
|
|
2
|
+
const pinnedEdgeCoordinates = [];
|
|
3
|
+
const isHorizontal = dockedSide === "left" || dockedSide === "right";
|
|
4
|
+
for (const other of Object.values(win.frames)) {
|
|
5
|
+
if (frame.id === other.id || !other.collapsed) continue;
|
|
6
|
+
const otherIsHorizontal = other.docked === "left" || other.docked === "right";
|
|
7
|
+
if (isHorizontal === otherIsHorizontal) {
|
|
8
|
+
if (other.docked === "left" || other.docked === "top") {
|
|
9
|
+
const edge = other[posKey] + other[sizeKey];
|
|
10
|
+
pinnedEdgeCoordinates.push(edge);
|
|
11
|
+
} else {
|
|
12
|
+
const edge = other[posKey];
|
|
13
|
+
pinnedEdgeCoordinates.push(edge);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return pinnedEdgeCoordinates;
|
|
18
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { clampNumber } from "@alanscodelog/utils/clampNumber";
|
|
1
2
|
export { addPointsToIntersection } from "./addPointsToIntersection.js";
|
|
2
3
|
export { assertEdgeSorted } from "./assertEdgeSorted.js";
|
|
3
4
|
export { assertItemIn } from "./assertItemIn.js";
|
|
@@ -6,7 +7,6 @@ export { assertLayoutHasActiveWindow } from "./assertLayoutHasActiveWindow.js";
|
|
|
6
7
|
export { assertValidWinAndFrame } from "./assertValidWinAndFrame.js";
|
|
7
8
|
export { assertValidWinAndFrameIds } from "./assertValidWinAndFrameIds.js";
|
|
8
9
|
export { assertWindowHasActiveFrame } from "./assertWindowHasActiveFrame.js";
|
|
9
|
-
export { clampNumber } from "./clampNumber.js";
|
|
10
10
|
export { cloneFrame } from "./cloneFrame.js";
|
|
11
11
|
export { cloneFrames } from "./cloneFrames.js";
|
|
12
12
|
export { containsEdge } from "./containsEdge.js";
|
|
@@ -33,7 +33,7 @@ export { getIntersections } from "./getIntersections.js";
|
|
|
33
33
|
export { getIntersectionsCss } from "./getIntersectionsCss.js";
|
|
34
34
|
export { getMoveEdgeInfo } from "./getMoveEdgeInfo.js";
|
|
35
35
|
export { getResizeLimit } from "./getResizeLimit.js";
|
|
36
|
-
export {
|
|
36
|
+
export { getShapeRectCss } from "./getShapeRectCss.js";
|
|
37
37
|
export { getSideTouching } from "./getSideTouching.js";
|
|
38
38
|
export { getVisualEdgeCss } from "./getVisualEdgeCss.js";
|
|
39
39
|
export { getVisualEdges } from "./getVisualEdges.js";
|
|
@@ -52,7 +52,7 @@ export { isWindowEdge } from "./isWindowEdge.js";
|
|
|
52
52
|
export { isWindowEdgePoint } from "./isWindowEdgePoint.js";
|
|
53
53
|
export { moveEdge } from "./moveEdge.js";
|
|
54
54
|
export { numberToScaledPercent } from "./numberToScaledPercent.js";
|
|
55
|
-
export {
|
|
55
|
+
export { pxSizeToScaledSize } from "./pxSizeToScaledSize.js";
|
|
56
56
|
export { oppositeSide } from "./oppositeSide.js";
|
|
57
57
|
export { resizeByEdge } from "./resizeByEdge.js";
|
|
58
58
|
export { scaledPointToPx } from "./scaledPointToPx.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { clampNumber } from "@alanscodelog/utils/clampNumber";
|
|
1
2
|
export { addPointsToIntersection } from "./addPointsToIntersection.js";
|
|
2
3
|
export { assertEdgeSorted } from "./assertEdgeSorted.js";
|
|
3
4
|
export { assertItemIn } from "./assertItemIn.js";
|
|
@@ -6,7 +7,6 @@ export { assertLayoutHasActiveWindow } from "./assertLayoutHasActiveWindow.js";
|
|
|
6
7
|
export { assertValidWinAndFrame } from "./assertValidWinAndFrame.js";
|
|
7
8
|
export { assertValidWinAndFrameIds } from "./assertValidWinAndFrameIds.js";
|
|
8
9
|
export { assertWindowHasActiveFrame } from "./assertWindowHasActiveFrame.js";
|
|
9
|
-
export { clampNumber } from "./clampNumber.js";
|
|
10
10
|
export { cloneFrame } from "./cloneFrame.js";
|
|
11
11
|
export { cloneFrames } from "./cloneFrames.js";
|
|
12
12
|
export { containsEdge } from "./containsEdge.js";
|
|
@@ -33,7 +33,7 @@ export { getIntersections } from "./getIntersections.js";
|
|
|
33
33
|
export { getIntersectionsCss } from "./getIntersectionsCss.js";
|
|
34
34
|
export { getMoveEdgeInfo } from "./getMoveEdgeInfo.js";
|
|
35
35
|
export { getResizeLimit } from "./getResizeLimit.js";
|
|
36
|
-
export {
|
|
36
|
+
export { getShapeRectCss } from "./getShapeRectCss.js";
|
|
37
37
|
export { getSideTouching } from "./getSideTouching.js";
|
|
38
38
|
export { getVisualEdgeCss } from "./getVisualEdgeCss.js";
|
|
39
39
|
export { getVisualEdges } from "./getVisualEdges.js";
|
|
@@ -52,7 +52,7 @@ export { isWindowEdge } from "./isWindowEdge.js";
|
|
|
52
52
|
export { isWindowEdgePoint } from "./isWindowEdgePoint.js";
|
|
53
53
|
export { moveEdge } from "./moveEdge.js";
|
|
54
54
|
export { numberToScaledPercent } from "./numberToScaledPercent.js";
|
|
55
|
-
export {
|
|
55
|
+
export { pxSizeToScaledSize } from "./pxSizeToScaledSize.js";
|
|
56
56
|
export { oppositeSide } from "./oppositeSide.js";
|
|
57
57
|
export { resizeByEdge } from "./resizeByEdge.js";
|
|
58
58
|
export { scaledPointToPx } from "./scaledPointToPx.js";
|
|
@@ -3,6 +3,8 @@ import { resizeByEdge } from "./resizeByEdge.js";
|
|
|
3
3
|
import { settings } from "../settings.js";
|
|
4
4
|
export function moveEdge(touchingFrames, edge, position, margin = settings.minSizeScaled) {
|
|
5
5
|
if (!edge || !touchingFrames) return;
|
|
6
|
-
const
|
|
6
|
+
const result = getMoveEdgeInfo(touchingFrames, edge, position, margin);
|
|
7
|
+
if (result instanceof Error) return;
|
|
8
|
+
const { pos, dir, distance } = result;
|
|
7
9
|
resizeByEdge(touchingFrames, edge, dir, pos, distance);
|
|
8
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { unreachable } from "@alanscodelog/utils/unreachable";
|
|
2
2
|
import { numberToScaledPercent } from "./numberToScaledPercent.js";
|
|
3
3
|
import { settings } from "../settings.js";
|
|
4
|
-
export function
|
|
4
|
+
export function pxSizeToScaledSize(win, size, scale = settings.maxInt) {
|
|
5
5
|
const scaledSize = {
|
|
6
6
|
width: numberToScaledPercent(
|
|
7
7
|
typeof size === "number" ? size : size.pxWidth,
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import type { LayoutWindow, PxPos, PxSize } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* See also the experimental {@link getUpdateWindowSizeInfo} for the function that will likely replace this.
|
|
4
|
+
*/
|
|
2
5
|
export declare function updateWindowWithEvent(win: LayoutWindow, event: PxPos & PxSize): void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LayoutFrame } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* For testing, validates the resulting layout is valid (frames do not overlap, have no gaps between them and form a rectangular area.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateLayoutShape(frames: Pick<LayoutFrame, "x" | "y" | "width" | "height">[]): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function validateLayoutShape(frames) {
|
|
2
|
+
const n = frames.length;
|
|
3
|
+
if (n === 0) return false;
|
|
4
|
+
let totalArea = 0;
|
|
5
|
+
let minX = Infinity, minY = Infinity;
|
|
6
|
+
let maxX = -Infinity, maxY = -Infinity;
|
|
7
|
+
for (const f of frames) {
|
|
8
|
+
totalArea += f.width * f.height;
|
|
9
|
+
minX = Math.min(minX, f.x);
|
|
10
|
+
minY = Math.min(minY, f.y);
|
|
11
|
+
maxX = Math.max(maxX, f.x + f.width);
|
|
12
|
+
maxY = Math.max(maxY, f.y + f.height);
|
|
13
|
+
}
|
|
14
|
+
const boundingArea = (maxX - minX) * (maxY - minY);
|
|
15
|
+
if (Math.abs(totalArea - boundingArea) > 1e-3) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
for (let i = 0; i < n; i++) {
|
|
19
|
+
for (let j = i + 1; j < n; j++) {
|
|
20
|
+
const a = frames[i];
|
|
21
|
+
const b = frames[j];
|
|
22
|
+
if (a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
@@ -22,6 +22,6 @@ export function createSplitDecoShapes(frames, deco, snapAmount = settings.snapPo
|
|
|
22
22
|
}
|
|
23
23
|
return [
|
|
24
24
|
{ type: "edge", data: edge, attrs: { class: classes.splitEdge ?? "deco-split-edge bg-red-500" } },
|
|
25
|
-
{ type: "
|
|
25
|
+
{ type: "rect", data: newFrame, attrs: { class: classes.splitNewFrame ?? "deco-split-new-frame bg-blue-500/50" } }
|
|
26
26
|
];
|
|
27
27
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LayoutChange, LayoutWindow } from "../types/index.js";
|
|
1
|
+
import type { LayoutChange, LayoutWindow, Size } from "../types/index.js";
|
|
2
2
|
import { LAYOUT_ERROR } from "../types/index.js";
|
|
3
3
|
import { KnownError } from "../utils/KnownError.js";
|
|
4
4
|
/**
|
|
@@ -10,4 +10,7 @@ import { KnownError } from "../utils/KnownError.js";
|
|
|
10
10
|
* the freed space to neighboring frames. The pre-collapse size is stored in
|
|
11
11
|
* `collapsed` so it can be restored later.
|
|
12
12
|
*/
|
|
13
|
-
export declare function getFrameCollapseInfo(win: LayoutWindow, frameId: string
|
|
13
|
+
export declare function getFrameCollapseInfo(win: LayoutWindow, frameId: string, { collapseSizeScaled }?: {
|
|
14
|
+
/** Override the target collapse size. If provided, the frame will collapse to this size instead of settings.collapseSizeScaled. */
|
|
15
|
+
collapseSizeScaled?: Size;
|
|
16
|
+
}): LayoutChange | KnownError<typeof LAYOUT_ERROR.CANT_COLLAPSE_NOT_DOCKED> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES>;
|