@witchcraft/layout 1.0.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 +474 -0
- package/dist/module.d.mts +14 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +26 -0
- package/dist/runtime/components/LayoutDecos.d.vue.ts +0 -0
- package/dist/runtime/components/LayoutDecos.vue +54 -0
- package/dist/runtime/components/LayoutDecos.vue.d.ts +0 -0
- package/dist/runtime/components/LayoutEdges.d.vue.ts +0 -0
- package/dist/runtime/components/LayoutEdges.vue +145 -0
- package/dist/runtime/components/LayoutEdges.vue.d.ts +0 -0
- package/dist/runtime/components/LayoutFrame.d.vue.ts +0 -0
- package/dist/runtime/components/LayoutFrame.vue +41 -0
- package/dist/runtime/components/LayoutFrame.vue.d.ts +0 -0
- package/dist/runtime/components/LayoutShapeSquare.d.vue.ts +0 -0
- package/dist/runtime/components/LayoutShapeSquare.vue +36 -0
- package/dist/runtime/components/LayoutShapeSquare.vue.d.ts +0 -0
- package/dist/runtime/components/LayoutWindow.d.vue.ts +0 -0
- package/dist/runtime/components/LayoutWindow.vue +183 -0
- package/dist/runtime/components/LayoutWindow.vue.d.ts +0 -0
- package/dist/runtime/composables/useFrames.d.ts +0 -0
- package/dist/runtime/composables/useFrames.js +184 -0
- package/dist/runtime/demo/App.d.vue.ts +0 -0
- package/dist/runtime/demo/App.vue +123 -0
- package/dist/runtime/demo/App.vue.d.ts +0 -0
- package/dist/runtime/demo/DemoControls.d.vue.ts +0 -0
- package/dist/runtime/demo/DemoControls.vue +14 -0
- package/dist/runtime/demo/DemoControls.vue.d.ts +0 -0
- package/dist/runtime/demo/README.md +1 -0
- package/dist/runtime/demo/main.d.ts +0 -0
- package/dist/runtime/demo/main.js +4 -0
- package/dist/runtime/demo/sharedLayoutInstance.d.ts +0 -0
- package/dist/runtime/demo/sharedLayoutInstance.js +5 -0
- package/dist/runtime/demo/tailwind.css +1 -0
- package/dist/runtime/drag/CloseAction.d.ts +0 -0
- package/dist/runtime/drag/CloseAction.js +121 -0
- package/dist/runtime/drag/DragActionHandler.d.ts +0 -0
- package/dist/runtime/drag/DragActionHandler.js +83 -0
- package/dist/runtime/drag/DragDirectionStore.d.ts +0 -0
- package/dist/runtime/drag/DragDirectionStore.js +45 -0
- package/dist/runtime/drag/SplitAction.d.ts +0 -0
- package/dist/runtime/drag/SplitAction.js +110 -0
- package/dist/runtime/drag/types.d.ts +0 -0
- package/dist/runtime/drag/types.js +0 -0
- package/dist/runtime/helpers/addPointsToIntersection.d.ts +0 -0
- package/dist/runtime/helpers/addPointsToIntersection.js +7 -0
- package/dist/runtime/helpers/assertEdgeSorted.d.ts +0 -0
- package/dist/runtime/helpers/assertEdgeSorted.js +7 -0
- package/dist/runtime/helpers/assertItemIn.d.ts +0 -0
- package/dist/runtime/helpers/assertItemIn.js +8 -0
- package/dist/runtime/helpers/assertItemNotIn.d.ts +0 -0
- package/dist/runtime/helpers/assertItemNotIn.js +7 -0
- package/dist/runtime/helpers/assertLayoutHasActiveWindow.d.ts +0 -0
- package/dist/runtime/helpers/assertLayoutHasActiveWindow.js +7 -0
- package/dist/runtime/helpers/assertValidWinAndFrame.d.ts +0 -0
- package/dist/runtime/helpers/assertValidWinAndFrame.js +5 -0
- package/dist/runtime/helpers/assertValidWinAndFrameIds.d.ts +0 -0
- package/dist/runtime/helpers/assertValidWinAndFrameIds.js +6 -0
- package/dist/runtime/helpers/assertWindowHasActiveFrame.d.ts +0 -0
- package/dist/runtime/helpers/assertWindowHasActiveFrame.js +7 -0
- package/dist/runtime/helpers/clampNumber.d.ts +0 -0
- package/dist/runtime/helpers/clampNumber.js +3 -0
- package/dist/runtime/helpers/cloneFrame.d.ts +0 -0
- package/dist/runtime/helpers/cloneFrame.js +3 -0
- package/dist/runtime/helpers/cloneFrames.d.ts +0 -0
- package/dist/runtime/helpers/cloneFrames.js +16 -0
- package/dist/runtime/helpers/containsEdge.d.ts +0 -0
- package/dist/runtime/helpers/containsEdge.js +13 -0
- package/dist/runtime/helpers/convertLayoutWindowToWorkspace.d.ts +0 -0
- package/dist/runtime/helpers/convertLayoutWindowToWorkspace.js +10 -0
- package/dist/runtime/helpers/copySize.d.ts +0 -0
- package/dist/runtime/helpers/copySize.js +5 -0
- package/dist/runtime/helpers/createEdge.d.ts +0 -0
- package/dist/runtime/helpers/createEdge.js +13 -0
- package/dist/runtime/helpers/dirToOrientation.d.ts +0 -0
- package/dist/runtime/helpers/dirToOrientation.js +10 -0
- package/dist/runtime/helpers/dirToSide.d.ts +0 -0
- package/dist/runtime/helpers/dirToSide.js +5 -0
- package/dist/runtime/helpers/doEdgesOverlap.d.ts +0 -0
- package/dist/runtime/helpers/doEdgesOverlap.js +22 -0
- package/dist/runtime/helpers/doesEdgeContinueEdge.d.ts +0 -0
- package/dist/runtime/helpers/doesEdgeContinueEdge.js +17 -0
- package/dist/runtime/helpers/edgeToPoints.d.ts +0 -0
- package/dist/runtime/helpers/edgeToPoints.js +3 -0
- package/dist/runtime/helpers/findDraggableEdge.d.ts +0 -0
- package/dist/runtime/helpers/findDraggableEdge.js +13 -0
- package/dist/runtime/helpers/findFrameDraggableEdges.d.ts +0 -0
- package/dist/runtime/helpers/findFrameDraggableEdges.js +18 -0
- package/dist/runtime/helpers/frameToEdges.d.ts +0 -0
- package/dist/runtime/helpers/frameToEdges.js +21 -0
- package/dist/runtime/helpers/frameToPoints.d.ts +0 -0
- package/dist/runtime/helpers/frameToPoints.js +7 -0
- package/dist/runtime/helpers/getEdgeOrientation.d.ts +0 -0
- package/dist/runtime/helpers/getEdgeOrientation.js +4 -0
- package/dist/runtime/helpers/getEdgeSharedDirection.d.ts +0 -0
- package/dist/runtime/helpers/getEdgeSharedDirection.js +7 -0
- package/dist/runtime/helpers/getEdgeSide.d.ts +0 -0
- package/dist/runtime/helpers/getEdgeSide.js +16 -0
- package/dist/runtime/helpers/getFrameById.d.ts +0 -0
- package/dist/runtime/helpers/getFrameById.js +5 -0
- package/dist/runtime/helpers/getFrameConstant.d.ts +0 -0
- package/dist/runtime/helpers/getFrameConstant.js +15 -0
- package/dist/runtime/helpers/getIntersections.d.ts +0 -0
- package/dist/runtime/helpers/getIntersections.js +63 -0
- package/dist/runtime/helpers/getIntersectionsCss.d.ts +0 -0
- package/dist/runtime/helpers/getIntersectionsCss.js +56 -0
- package/dist/runtime/helpers/getMoveEdgeInfo.d.ts +0 -0
- package/dist/runtime/helpers/getMoveEdgeInfo.js +42 -0
- package/dist/runtime/helpers/getResizeLimit.d.ts +0 -0
- package/dist/runtime/helpers/getResizeLimit.js +39 -0
- package/dist/runtime/helpers/getShapeSquareCss.d.ts +0 -0
- package/dist/runtime/helpers/getShapeSquareCss.js +17 -0
- package/dist/runtime/helpers/getSideTouching.d.ts +0 -0
- package/dist/runtime/helpers/getSideTouching.js +7 -0
- package/dist/runtime/helpers/getVisualEdgeCss.d.ts +0 -0
- package/dist/runtime/helpers/getVisualEdgeCss.js +40 -0
- package/dist/runtime/helpers/getVisualEdges.d.ts +0 -0
- package/dist/runtime/helpers/getVisualEdges.js +89 -0
- package/dist/runtime/helpers/getVisualEdgesCss.d.ts +0 -0
- package/dist/runtime/helpers/getVisualEdgesCss.js +4 -0
- package/dist/runtime/helpers/getWinAndFrameById.d.ts +0 -0
- package/dist/runtime/helpers/getWinAndFrameById.js +14 -0
- package/dist/runtime/helpers/getWinByFrameUuid.d.ts +0 -0
- package/dist/runtime/helpers/getWinByFrameUuid.js +13 -0
- package/dist/runtime/helpers/getWinById.d.ts +0 -0
- package/dist/runtime/helpers/getWinById.js +5 -0
- package/dist/runtime/helpers/getWindowConstant.d.ts +0 -0
- package/dist/runtime/helpers/getWindowConstant.js +14 -0
- package/dist/runtime/helpers/inRange.d.ts +0 -0
- package/dist/runtime/helpers/inRange.js +3 -0
- package/dist/runtime/helpers/index.d.ts +0 -0
- package/dist/runtime/helpers/index.js +62 -0
- package/dist/runtime/helpers/isEdgeEqual.d.ts +0 -0
- package/dist/runtime/helpers/isEdgeEqual.js +11 -0
- package/dist/runtime/helpers/isEdgeParallel.d.ts +0 -0
- package/dist/runtime/helpers/isEdgeParallel.js +7 -0
- package/dist/runtime/helpers/isPointEqual.d.ts +0 -0
- package/dist/runtime/helpers/isPointEqual.js +3 -0
- package/dist/runtime/helpers/isSizeAboveMin.d.ts +0 -0
- package/dist/runtime/helpers/isSizeAboveMin.js +3 -0
- package/dist/runtime/helpers/isSizeEqual.d.ts +0 -0
- package/dist/runtime/helpers/isSizeEqual.js +3 -0
- package/dist/runtime/helpers/isWindowEdge.d.ts +0 -0
- package/dist/runtime/helpers/isWindowEdge.js +7 -0
- package/dist/runtime/helpers/isWindowEdgePoint.d.ts +0 -0
- package/dist/runtime/helpers/isWindowEdgePoint.js +5 -0
- package/dist/runtime/helpers/moveEdge.d.ts +0 -0
- package/dist/runtime/helpers/moveEdge.js +8 -0
- package/dist/runtime/helpers/numberToScaledPercent.d.ts +0 -0
- package/dist/runtime/helpers/numberToScaledPercent.js +5 -0
- package/dist/runtime/helpers/numberToScaledSize.d.ts +0 -0
- package/dist/runtime/helpers/numberToScaledSize.js +19 -0
- package/dist/runtime/helpers/oppositeSide.d.ts +0 -0
- package/dist/runtime/helpers/oppositeSide.js +30 -0
- package/dist/runtime/helpers/resizeByEdge.d.ts +0 -0
- package/dist/runtime/helpers/resizeByEdge.js +29 -0
- package/dist/runtime/helpers/sideToDirection.d.ts +0 -0
- package/dist/runtime/helpers/sideToDirection.js +11 -0
- package/dist/runtime/helpers/sideToOrientation.d.ts +0 -0
- package/dist/runtime/helpers/sideToOrientation.js +10 -0
- package/dist/runtime/helpers/splitEdge.d.ts +0 -0
- package/dist/runtime/helpers/splitEdge.js +20 -0
- package/dist/runtime/helpers/toCoord.d.ts +0 -0
- package/dist/runtime/helpers/toCoord.js +10 -0
- package/dist/runtime/helpers/toId.d.ts +0 -0
- package/dist/runtime/helpers/toId.js +4 -0
- package/dist/runtime/helpers/toWindowCoord.d.ts +0 -0
- package/dist/runtime/helpers/toWindowCoord.js +14 -0
- package/dist/runtime/helpers/unionEdges.d.ts +0 -0
- package/dist/runtime/helpers/unionEdges.js +8 -0
- package/dist/runtime/helpers/updateWindowSizeWithEvent.d.ts +0 -0
- package/dist/runtime/helpers/updateWindowSizeWithEvent.js +8 -0
- package/dist/runtime/index.d.ts +0 -0
- package/dist/runtime/index.js +5 -0
- package/dist/runtime/layout/closeFrame.d.ts +0 -0
- package/dist/runtime/layout/closeFrame.js +13 -0
- package/dist/runtime/layout/closeFrames.d.ts +0 -0
- package/dist/runtime/layout/closeFrames.js +8 -0
- package/dist/runtime/layout/createSplitDecoEdge.d.ts +0 -0
- package/dist/runtime/layout/createSplitDecoEdge.js +24 -0
- package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +0 -0
- package/dist/runtime/layout/createSplitDecoFromDrag.js +14 -0
- package/dist/runtime/layout/debugFrame.d.ts +0 -0
- package/dist/runtime/layout/debugFrame.js +4 -0
- package/dist/runtime/layout/findFramesTouchingEdge.d.ts +0 -0
- package/dist/runtime/layout/findFramesTouchingEdge.js +33 -0
- package/dist/runtime/layout/findSafeSplitEdge.d.ts +0 -0
- package/dist/runtime/layout/findSafeSplitEdge.js +20 -0
- package/dist/runtime/layout/findVisualEdge.d.ts +0 -0
- package/dist/runtime/layout/findVisualEdge.js +9 -0
- package/dist/runtime/layout/frameCreate.d.ts +0 -0
- package/dist/runtime/layout/frameCreate.js +13 -0
- package/dist/runtime/layout/frameSplit.d.ts +0 -0
- package/dist/runtime/layout/frameSplit.js +9 -0
- package/dist/runtime/layout/getCloseFrameInfo.d.ts +0 -0
- package/dist/runtime/layout/getCloseFrameInfo.js +103 -0
- package/dist/runtime/layout/getFrameSplitInfo.d.ts +0 -0
- package/dist/runtime/layout/getFrameSplitInfo.js +40 -0
- package/dist/runtime/layout/getFrameTo.d.ts +0 -0
- package/dist/runtime/layout/getFrameTo.js +47 -0
- package/dist/runtime/layout/index.d.ts +0 -0
- package/dist/runtime/layout/index.js +22 -0
- package/dist/runtime/layout/isPointInFrame.d.ts +0 -0
- package/dist/runtime/layout/isPointInFrame.js +4 -0
- package/dist/runtime/layout/layoutAddWindow.d.ts +0 -0
- package/dist/runtime/layout/layoutAddWindow.js +4 -0
- package/dist/runtime/layout/layoutCreate.d.ts +0 -0
- package/dist/runtime/layout/layoutCreate.js +7 -0
- package/dist/runtime/layout/layoutRemoveWindow.d.ts +0 -0
- package/dist/runtime/layout/layoutRemoveWindow.js +5 -0
- package/dist/runtime/layout/resizeFrame.d.ts +0 -0
- package/dist/runtime/layout/resizeFrame.js +69 -0
- package/dist/runtime/layout/windowAddFrame.d.ts +0 -0
- package/dist/runtime/layout/windowAddFrame.js +4 -0
- package/dist/runtime/layout/windowCreate.d.ts +0 -0
- package/dist/runtime/layout/windowCreate.js +13 -0
- package/dist/runtime/layout/windowRemoveFrame.d.ts +0 -0
- package/dist/runtime/layout/windowRemoveFrame.js +5 -0
- package/dist/runtime/layout/windowSetActiveFrame.d.ts +0 -0
- package/dist/runtime/layout/windowSetActiveFrame.js +5 -0
- package/dist/runtime/settings.d.ts +0 -0
- package/dist/runtime/settings.js +54 -0
- package/dist/runtime/types/index.d.ts +0 -0
- package/dist/runtime/types/index.js +120 -0
- package/dist/runtime/utils/KnownError.d.ts +0 -0
- package/dist/runtime/utils/KnownError.js +9 -0
- package/dist/types.d.mts +5 -0
- package/package.json +153 -0
- package/src/module.ts +43 -0
- package/src/runtime/components/LayoutDecos.vue +62 -0
- package/src/runtime/components/LayoutEdges.vue +172 -0
- package/src/runtime/components/LayoutFrame.vue +47 -0
- package/src/runtime/components/LayoutShapeSquare.vue +38 -0
- package/src/runtime/components/LayoutWindow.vue +223 -0
- package/src/runtime/composables/useFrames.ts +251 -0
- package/src/runtime/demo/App.vue +140 -0
- package/src/runtime/demo/DemoControls.vue +17 -0
- package/src/runtime/demo/README.md +1 -0
- package/src/runtime/demo/main.ts +9 -0
- package/src/runtime/demo/sharedLayoutInstance.ts +7 -0
- package/src/runtime/demo/tailwind.css +4 -0
- package/src/runtime/drag/CloseAction.ts +158 -0
- package/src/runtime/drag/DragActionHandler.ts +146 -0
- package/src/runtime/drag/DragDirectionStore.ts +63 -0
- package/src/runtime/drag/SplitAction.ts +147 -0
- package/src/runtime/drag/types.ts +107 -0
- package/src/runtime/helpers/addPointsToIntersection.ts +9 -0
- package/src/runtime/helpers/assertEdgeSorted.ts +11 -0
- package/src/runtime/helpers/assertItemIn.ts +13 -0
- package/src/runtime/helpers/assertItemNotIn.ts +10 -0
- package/src/runtime/helpers/assertLayoutHasActiveWindow.ts +9 -0
- package/src/runtime/helpers/assertValidWinAndFrame.ts +16 -0
- package/src/runtime/helpers/assertValidWinAndFrameIds.ts +9 -0
- package/src/runtime/helpers/assertWindowHasActiveFrame.ts +9 -0
- package/src/runtime/helpers/clampNumber.ts +9 -0
- package/src/runtime/helpers/cloneFrame.ts +5 -0
- package/src/runtime/helpers/cloneFrames.ts +20 -0
- package/src/runtime/helpers/containsEdge.ts +16 -0
- package/src/runtime/helpers/convertLayoutWindowToWorkspace.ts +18 -0
- package/src/runtime/helpers/copySize.ts +7 -0
- package/src/runtime/helpers/createEdge.ts +19 -0
- package/src/runtime/helpers/dirToOrientation.ts +12 -0
- package/src/runtime/helpers/dirToSide.ts +7 -0
- package/src/runtime/helpers/doEdgesOverlap.ts +25 -0
- package/src/runtime/helpers/doesEdgeContinueEdge.ts +20 -0
- package/src/runtime/helpers/edgeToPoints.ts +5 -0
- package/src/runtime/helpers/findDraggableEdge.ts +24 -0
- package/src/runtime/helpers/findFrameDraggableEdges.ts +32 -0
- package/src/runtime/helpers/frameToEdges.ts +32 -0
- package/src/runtime/helpers/frameToPoints.ts +14 -0
- package/src/runtime/helpers/getEdgeOrientation.ts +6 -0
- package/src/runtime/helpers/getEdgeSharedDirection.ts +10 -0
- package/src/runtime/helpers/getEdgeSide.ts +27 -0
- package/src/runtime/helpers/getFrameById.ts +15 -0
- package/src/runtime/helpers/getFrameConstant.ts +22 -0
- package/src/runtime/helpers/getIntersections.ts +87 -0
- package/src/runtime/helpers/getIntersectionsCss.ts +65 -0
- package/src/runtime/helpers/getMoveEdgeInfo.ts +69 -0
- package/src/runtime/helpers/getResizeLimit.ts +60 -0
- package/src/runtime/helpers/getShapeSquareCss.ts +28 -0
- package/src/runtime/helpers/getSideTouching.ts +9 -0
- package/src/runtime/helpers/getVisualEdgeCss.ts +53 -0
- package/src/runtime/helpers/getVisualEdges.ts +155 -0
- package/src/runtime/helpers/getVisualEdgesCss.ts +13 -0
- package/src/runtime/helpers/getWinAndFrameById.ts +28 -0
- package/src/runtime/helpers/getWinByFrameUuid.ts +19 -0
- package/src/runtime/helpers/getWinById.ts +12 -0
- package/src/runtime/helpers/getWindowConstant.ts +21 -0
- package/src/runtime/helpers/inRange.ts +5 -0
- package/src/runtime/helpers/index.ts +64 -0
- package/src/runtime/helpers/isEdgeEqual.ts +14 -0
- package/src/runtime/helpers/isEdgeParallel.ts +10 -0
- package/src/runtime/helpers/isPointEqual.ts +5 -0
- package/src/runtime/helpers/isSizeAboveMin.ts +8 -0
- package/src/runtime/helpers/isSizeEqual.ts +5 -0
- package/src/runtime/helpers/isWindowEdge.ts +11 -0
- package/src/runtime/helpers/isWindowEdgePoint.ts +8 -0
- package/src/runtime/helpers/moveEdge.ts +21 -0
- package/src/runtime/helpers/numberToScaledPercent.ts +19 -0
- package/src/runtime/helpers/numberToScaledSize.ts +28 -0
- package/src/runtime/helpers/oppositeSide.ts +45 -0
- package/src/runtime/helpers/resizeByEdge.ts +45 -0
- package/src/runtime/helpers/sideToDirection.ts +15 -0
- package/src/runtime/helpers/sideToOrientation.ts +12 -0
- package/src/runtime/helpers/splitEdge.ts +23 -0
- package/src/runtime/helpers/toCoord.ts +13 -0
- package/src/runtime/helpers/toId.ts +9 -0
- package/src/runtime/helpers/toWindowCoord.ts +23 -0
- package/src/runtime/helpers/unionEdges.ts +11 -0
- package/src/runtime/helpers/updateWindowSizeWithEvent.ts +10 -0
- package/src/runtime/index.ts +5 -0
- package/src/runtime/layout/closeFrame.ts +33 -0
- package/src/runtime/layout/closeFrames.ts +14 -0
- package/src/runtime/layout/createSplitDecoEdge.ts +34 -0
- package/src/runtime/layout/createSplitDecoFromDrag.ts +24 -0
- package/src/runtime/layout/debugFrame.ts +6 -0
- package/src/runtime/layout/findFramesTouchingEdge.ts +92 -0
- package/src/runtime/layout/findSafeSplitEdge.ts +39 -0
- package/src/runtime/layout/findVisualEdge.ts +11 -0
- package/src/runtime/layout/frameCreate.ts +23 -0
- package/src/runtime/layout/frameSplit.ts +31 -0
- package/src/runtime/layout/getCloseFrameInfo.ts +193 -0
- package/src/runtime/layout/getFrameSplitInfo.ts +65 -0
- package/src/runtime/layout/getFrameTo.ts +65 -0
- package/src/runtime/layout/index.ts +24 -0
- package/src/runtime/layout/isPointInFrame.ts +7 -0
- package/src/runtime/layout/layoutAddWindow.ts +6 -0
- package/src/runtime/layout/layoutCreate.ts +12 -0
- package/src/runtime/layout/layoutRemoveWindow.ts +7 -0
- package/src/runtime/layout/resizeFrame.ts +106 -0
- package/src/runtime/layout/windowAddFrame.ts +10 -0
- package/src/runtime/layout/windowCreate.ts +18 -0
- package/src/runtime/layout/windowRemoveFrame.ts +7 -0
- package/src/runtime/layout/windowSetActiveFrame.ts +7 -0
- package/src/runtime/settings.ts +63 -0
- package/src/runtime/types/index.ts +293 -0
- package/src/runtime/utils/KnownError.ts +24 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn"
|
|
2
|
+
import { readable } from "@alanscodelog/utils/readable"
|
|
3
|
+
import { unreachable } from "@alanscodelog/utils/unreachable"
|
|
4
|
+
|
|
5
|
+
import { findFramesTouchingEdge } from "./findFramesTouchingEdge.js"
|
|
6
|
+
import { findVisualEdge } from "./findVisualEdge.js"
|
|
7
|
+
|
|
8
|
+
import { cloneFrame } from "../helpers/cloneFrame.js"
|
|
9
|
+
import { dirToSide } from "../helpers/dirToSide.js"
|
|
10
|
+
import { findFrameDraggableEdges } from "../helpers/findFrameDraggableEdges.js"
|
|
11
|
+
import { getEdgeOrientation } from "../helpers/getEdgeOrientation.js"
|
|
12
|
+
import { oppositeSide } from "../helpers/oppositeSide.js"
|
|
13
|
+
import { getMarginSize } from "../settings.js"
|
|
14
|
+
import { type Direction, type Edge, type EdgeSide, LAYOUT_ERROR, type LayoutFrame, type Size } from "../types/index.js"
|
|
15
|
+
import { KnownError } from "../utils/KnownError.js"
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Returns the information necessary to close a frame or frames (if force: true).
|
|
19
|
+
*
|
|
20
|
+
* Can close by direction or by frame edge.
|
|
21
|
+
*
|
|
22
|
+
* - Closing A in the left direction or by it's right edge would close A and expand B.
|
|
23
|
+
*
|
|
24
|
+
* - Closing A in the right direction or by it's left edge is not possible, since it's left edge is a window edge.
|
|
25
|
+
*
|
|
26
|
+
* ```
|
|
27
|
+
* ┌──┬──┐
|
|
28
|
+
* │A │B │
|
|
29
|
+
* └──┴──┘
|
|
30
|
+
* ```
|
|
31
|
+
* A list of possible directions/edges can be given to attempt closing by those directions/edges in that order.
|
|
32
|
+
*
|
|
33
|
+
* Frame closing does not always succeed:
|
|
34
|
+
*
|
|
35
|
+
* ## `force: false` (default)
|
|
36
|
+
*
|
|
37
|
+
* If two frames share a visual edge exactly, they can always be closed to either side.
|
|
38
|
+
* ```
|
|
39
|
+
* 🭮 🭬
|
|
40
|
+
* ┌──┬──┐
|
|
41
|
+
* │A │B │
|
|
42
|
+
* └──┴──┘
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* ## `force: true`
|
|
46
|
+
*
|
|
47
|
+
* If the visual edge contains multiple frames, `force: true` must be specified to be able to close them. Force is not guaranteed to succeed either though.
|
|
48
|
+
*
|
|
49
|
+
* There's two main scenarios to consider when we have multiple frames:
|
|
50
|
+
*
|
|
51
|
+
* - The frames all share an edge on the closing side. We can force close both without problems.
|
|
52
|
+
*
|
|
53
|
+
* So, for example, here A & B can be force closed to the left since they share their left edge (vertically).
|
|
54
|
+
* ```
|
|
55
|
+
* ─🭬
|
|
56
|
+
* ┌──┬──┐
|
|
57
|
+
* │A │C │
|
|
58
|
+
* ├──┤ │
|
|
59
|
+
* │B │ │
|
|
60
|
+
* └──┴──┘
|
|
61
|
+
* ```
|
|
62
|
+
* - If they do not share an edge to that side, we will attempt to close the frame IF it's the smallest frame and only modify the size of the others.
|
|
63
|
+
*
|
|
64
|
+
* For this to succeed, the difference between the smallest frame and the next smallest frame must be greater than the minimum size.
|
|
65
|
+
*
|
|
66
|
+
* For example, here, we have frames A, B, and C to the left of the visual edge. A and B are the smallest. A can be closed and the rest modified, but only if the difference between A and B is greater than the minimum size.
|
|
67
|
+
* ```
|
|
68
|
+
* 🭮──
|
|
69
|
+
*┌──────┬──┬──┐
|
|
70
|
+
*│E │A │F │
|
|
71
|
+
*├───┬──┴──┤ │
|
|
72
|
+
*│F │B │ │
|
|
73
|
+
*├───┴─────┤ │
|
|
74
|
+
*│C │ │
|
|
75
|
+
*└─────────┴──┘
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
export function getCloseFrameInfo<T extends "edge" | "dir">(
|
|
80
|
+
frames: LayoutFrame[],
|
|
81
|
+
visualEdges: Edge[],
|
|
82
|
+
frame: LayoutFrame,
|
|
83
|
+
/**
|
|
84
|
+
* The direction or edge (if closeBy = "edge") to search for possible closes.
|
|
85
|
+
*
|
|
86
|
+
* For example, a frame that touches the right window edge can only be closed "to the right" in the horizontal direction or by it's left edge. Another way to think about it is the left edge is "collapsed" towards the "right".
|
|
87
|
+
*/
|
|
88
|
+
closeDirOrSide: (T extends "dir" ? Direction : EdgeSide),
|
|
89
|
+
closeBy: T = "dir" as any as T,
|
|
90
|
+
force: boolean = false,
|
|
91
|
+
minSize: Size = getMarginSize()
|
|
92
|
+
): { modifiedFrames: LayoutFrame[], deletedFrames: LayoutFrame[] }
|
|
93
|
+
| KnownError<
|
|
94
|
+
| typeof LAYOUT_ERROR.CANT_CLOSE_NEARBY_FRAMES_TOO_SMALL
|
|
95
|
+
| typeof LAYOUT_ERROR.CANT_CLOSE_NO_DRAG_EDGE
|
|
96
|
+
| typeof LAYOUT_ERROR.CANT_CLOSE_SINGLE_FRAME
|
|
97
|
+
| typeof LAYOUT_ERROR.CANT_CLOSE_WITHOUT_FORCE
|
|
98
|
+
> {
|
|
99
|
+
if (frames.length === 1) {
|
|
100
|
+
return new KnownError(LAYOUT_ERROR.CANT_CLOSE_SINGLE_FRAME,
|
|
101
|
+
`Can't close frame ${frame.id}, it is the last frame in the window.`,
|
|
102
|
+
{ frame })
|
|
103
|
+
}
|
|
104
|
+
const side = closeBy === "dir"
|
|
105
|
+
? oppositeSide(dirToSide(closeDirOrSide as Direction))
|
|
106
|
+
: closeDirOrSide as EdgeSide
|
|
107
|
+
const sideOpposite = oppositeSide(side)
|
|
108
|
+
|
|
109
|
+
const draggableEdges = findFrameDraggableEdges(frame, visualEdges, !force, [side])
|
|
110
|
+
if (!draggableEdges) return new KnownError(LAYOUT_ERROR.CANT_CLOSE_NO_DRAG_EDGE, `Could not find draggable edge for frame ${frame.id}`, { frame })
|
|
111
|
+
const { edge: frameEdge } = draggableEdges[0]
|
|
112
|
+
|
|
113
|
+
const visualEdge = findVisualEdge(visualEdges, frameEdge)
|
|
114
|
+
if (visualEdge === undefined) unreachable()
|
|
115
|
+
const direction = oppositeSide(getEdgeOrientation(visualEdge))
|
|
116
|
+
const entriesInVisualEdges = findFramesTouchingEdge(visualEdge, frames)
|
|
117
|
+
|
|
118
|
+
if (entriesInVisualEdges.length === 0) unreachable()
|
|
119
|
+
const sizeKey = direction === "horizontal" ? "width" : "height"
|
|
120
|
+
const coordKey = direction === "horizontal" ? "x" : "y"
|
|
121
|
+
const thisFrameSize = frame[sizeKey]
|
|
122
|
+
const frameSizes: number[] = []
|
|
123
|
+
const oppositeSideEntries: typeof entriesInVisualEdges = []
|
|
124
|
+
const sameSideEntries: typeof entriesInVisualEdges = []
|
|
125
|
+
|
|
126
|
+
for (const _ of entriesInVisualEdges) {
|
|
127
|
+
if (_.side === side) {
|
|
128
|
+
sameSideEntries.push(_)
|
|
129
|
+
const size = _.frame[sizeKey]
|
|
130
|
+
pushIfNotIn(frameSizes, [size])
|
|
131
|
+
} else {
|
|
132
|
+
oppositeSideEntries.push(_)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
frameSizes.sort((a, b) => a - b)
|
|
137
|
+
|
|
138
|
+
const smallest: number = frameSizes[0]
|
|
139
|
+
const secondSmallest: number | undefined = frameSizes[1]
|
|
140
|
+
|
|
141
|
+
if (smallest < thisFrameSize) {
|
|
142
|
+
const nearbyErrorFrames = sameSideEntries.filter(_ => _.frame[sizeKey] < thisFrameSize).map(_ => _.frame)
|
|
143
|
+
return new KnownError(
|
|
144
|
+
LAYOUT_ERROR.CANT_CLOSE_NEARBY_FRAMES_TOO_SMALL,
|
|
145
|
+
// it's too complicated to calculate, happens in last example, if we get frame B, frame A is smaller
|
|
146
|
+
// attempting to resize it is very complicated
|
|
147
|
+
`Cannot close ${frame.id}, nearby affected frame/s ${readable(nearbyErrorFrames.map(_ => _.id))} are smaller than this one, we cannot calculate how to close it.`,
|
|
148
|
+
{ frame, nearbyFrames: nearbyErrorFrames, minSize }
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
if (thisFrameSize !== smallest) { unreachable() }
|
|
152
|
+
if (secondSmallest) {
|
|
153
|
+
if (secondSmallest - smallest < minSize[sizeKey]) {
|
|
154
|
+
const nearbyErrorFrames = sameSideEntries.filter(_ => frame[sizeKey] < minSize[sizeKey]).map(_ => _.frame)
|
|
155
|
+
return new KnownError(
|
|
156
|
+
LAYOUT_ERROR.CANT_CLOSE_NEARBY_FRAMES_TOO_SMALL,
|
|
157
|
+
`Closing this frame ${frame.id} would leave the following frame/s ${readable(nearbyErrorFrames.map(_ => _.id))} below the minimum size specified.`,
|
|
158
|
+
{ frame, nearbyFrames: nearbyErrorFrames, minSize }
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const modifiedFrames = []
|
|
163
|
+
const deletedFrames = []
|
|
164
|
+
const moveAmount = thisFrameSize
|
|
165
|
+
|
|
166
|
+
for (const entry of sameSideEntries) {
|
|
167
|
+
if (entry.frame[sizeKey] > thisFrameSize) {
|
|
168
|
+
const clone = cloneFrame(entry.frame)
|
|
169
|
+
if (side === "top" || side === "left") {
|
|
170
|
+
clone[coordKey] += moveAmount
|
|
171
|
+
}
|
|
172
|
+
clone[sizeKey] -= moveAmount
|
|
173
|
+
modifiedFrames.push(clone)
|
|
174
|
+
} else if (entry.frame[sizeKey] === thisFrameSize) deletedFrames.push(entry.frame)
|
|
175
|
+
else unreachable()
|
|
176
|
+
}
|
|
177
|
+
if (deletedFrames.length > 1 && !force) {
|
|
178
|
+
return new KnownError(
|
|
179
|
+
LAYOUT_ERROR.CANT_CLOSE_WITHOUT_FORCE,
|
|
180
|
+
`Cannot close in this direction, there are multiple frames in the same direction (${readable(deletedFrames.map(_ => _.id))}). Use force: true to close them.`,
|
|
181
|
+
{ frame, minSize, framesRequiredToBeDeleted: deletedFrames }
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
for (const entry of oppositeSideEntries) {
|
|
185
|
+
const clone = cloneFrame(entry.frame)
|
|
186
|
+
if (sideOpposite === "top" || sideOpposite === "left") {
|
|
187
|
+
clone[coordKey] -= moveAmount
|
|
188
|
+
}
|
|
189
|
+
clone[sizeKey] += moveAmount
|
|
190
|
+
modifiedFrames.push(clone)
|
|
191
|
+
}
|
|
192
|
+
return { modifiedFrames, deletedFrames }
|
|
193
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { findSafeSplitEdgeAndPosition } from "./findSafeSplitEdge.js"
|
|
2
|
+
import { frameCreate } from "./frameCreate.js"
|
|
3
|
+
|
|
4
|
+
import { cloneFrame } from "../helpers/cloneFrame.js"
|
|
5
|
+
import { getMarginSize, getSnapPoint } from "../settings.js"
|
|
6
|
+
import {
|
|
7
|
+
type Direction,
|
|
8
|
+
LAYOUT_ERROR,
|
|
9
|
+
type LayoutFrame,
|
|
10
|
+
type Point,
|
|
11
|
+
type Size
|
|
12
|
+
} from "../types/index.js"
|
|
13
|
+
import { KnownError } from "../utils/KnownError.js"
|
|
14
|
+
|
|
15
|
+
export function getFrameSplitInfo(
|
|
16
|
+
frame: LayoutFrame,
|
|
17
|
+
dir: Direction,
|
|
18
|
+
dragPointOrPosition: Point | number | "midpoint" = "midpoint",
|
|
19
|
+
minSize: Size = getMarginSize(),
|
|
20
|
+
snapAmount: Point = getSnapPoint()
|
|
21
|
+
) {
|
|
22
|
+
frame = cloneFrame(frame)
|
|
23
|
+
let newFrame = { ...frame }
|
|
24
|
+
const isHorz = dir === "left" || dir === "right"
|
|
25
|
+
|
|
26
|
+
const sizeKey: "width" | "height" = isHorz ? "width" : "height"
|
|
27
|
+
const posKey: "x" | "y" = isHorz ? "x" : "y"
|
|
28
|
+
|
|
29
|
+
const position = dragPointOrPosition === "midpoint"
|
|
30
|
+
? (isHorz ? frame.x + (frame.width / 2) : frame.y + (frame.height / 2))
|
|
31
|
+
: typeof dragPointOrPosition === "number"
|
|
32
|
+
? dragPointOrPosition
|
|
33
|
+
: dragPointOrPosition[isHorz ? "x" : "y"]
|
|
34
|
+
|
|
35
|
+
const safePosition = findSafeSplitEdgeAndPosition(
|
|
36
|
+
frame,
|
|
37
|
+
dir,
|
|
38
|
+
position,
|
|
39
|
+
snapAmount,
|
|
40
|
+
minSize
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
const newSize = dir === "right" || dir === "down"
|
|
44
|
+
? (frame[sizeKey] + frame[posKey]) - safePosition.position
|
|
45
|
+
: safePosition.position - frame[posKey]
|
|
46
|
+
|
|
47
|
+
if (newSize < minSize[sizeKey]) {
|
|
48
|
+
return new KnownError(
|
|
49
|
+
LAYOUT_ERROR.CANT_SPLIT_FRAME_TOO_SMALL,
|
|
50
|
+
`Can't split frame ${frame.id} in direction ${dir}, frame is too small to be split.`,
|
|
51
|
+
{ frame, newSize, minSize: minSize[sizeKey] }
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
newFrame[sizeKey] = newSize
|
|
56
|
+
frame[sizeKey] -= newSize
|
|
57
|
+
if (dir === "right" || dir === "down") {
|
|
58
|
+
newFrame[posKey] = safePosition.position
|
|
59
|
+
} else {
|
|
60
|
+
frame[posKey] = safePosition.position
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
newFrame = frameCreate({ ...newFrame, id: undefined })
|
|
64
|
+
return { splitFrame: frame, newFrame }
|
|
65
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { getMaxInt } from "../settings.js"
|
|
2
|
+
import type { EdgeSide, LayoutFrame } from "../types/index.js"
|
|
3
|
+
|
|
4
|
+
export function getFrameTo(
|
|
5
|
+
side: EdgeSide,
|
|
6
|
+
frame: LayoutFrame,
|
|
7
|
+
frames: LayoutFrame[]
|
|
8
|
+
): LayoutFrame | undefined {
|
|
9
|
+
const max = getMaxInt()
|
|
10
|
+
if ((side === "top" && frame.y === 0)
|
|
11
|
+
|| (side === "left" && frame.y === 0)
|
|
12
|
+
|| (side === "right" && frame.x + frame.width === max)
|
|
13
|
+
|| (side === "bottom" && frame.x + frame.height === max)) return undefined
|
|
14
|
+
|
|
15
|
+
let candidate: LayoutFrame | undefined
|
|
16
|
+
let candidateDistance = Infinity
|
|
17
|
+
const midPointX = frame.x + Math.round(frame.width / 2)
|
|
18
|
+
const midPointY = frame.y + Math.round(frame.height / 2)
|
|
19
|
+
const dir = side === "top" || side === "bottom" ? "horizontal" : "vertical"
|
|
20
|
+
const midPoint = dir === "horizontal" ? midPointX : midPointY
|
|
21
|
+
for (const other of frames) {
|
|
22
|
+
if (frame.id === other.id) continue
|
|
23
|
+
const isOutOfRange = dir === "horizontal"
|
|
24
|
+
? other.x + other.width <= frame.x || other.x >= frame.x + frame.width
|
|
25
|
+
: other.y + other.height <= frame.y || other.y >= frame.y + frame.height
|
|
26
|
+
if (isOutOfRange) continue
|
|
27
|
+
|
|
28
|
+
const otherMidPoint = dir === "horizontal"
|
|
29
|
+
? other.x + Math.round(other.width / 2)
|
|
30
|
+
: other.y + Math.round(other.height / 2)
|
|
31
|
+
const otherDist = Math.abs(midPoint - otherMidPoint)
|
|
32
|
+
switch (side) {
|
|
33
|
+
case "left":
|
|
34
|
+
if (other.x + other.width !== frame.x) continue
|
|
35
|
+
break
|
|
36
|
+
case "right":
|
|
37
|
+
if (other.x !== frame.x + frame.width) continue
|
|
38
|
+
break
|
|
39
|
+
case "top":
|
|
40
|
+
if (other.y + other.height !== frame.y) continue
|
|
41
|
+
break
|
|
42
|
+
case "bottom":
|
|
43
|
+
if (other.y !== frame.y + frame.height) continue
|
|
44
|
+
break
|
|
45
|
+
}
|
|
46
|
+
if (otherDist < candidateDistance) {
|
|
47
|
+
candidate = other
|
|
48
|
+
candidateDistance = otherDist
|
|
49
|
+
} else if (otherDist === candidateDistance && candidate) {
|
|
50
|
+
// future customizable preference?
|
|
51
|
+
if (dir === "vertical") {
|
|
52
|
+
// prefer top
|
|
53
|
+
if (other.y > candidate.y) {
|
|
54
|
+
candidate = other
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
// prefer left
|
|
58
|
+
if (other.x > candidate.x) {
|
|
59
|
+
candidate = other
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return candidate
|
|
65
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* Autogenerated Index */
|
|
2
|
+
|
|
3
|
+
export { closeFrame } from "./closeFrame.js"
|
|
4
|
+
export { closeFrames } from "./closeFrames.js"
|
|
5
|
+
export { createSplitDecoEdge } from "./createSplitDecoEdge.js"
|
|
6
|
+
export { createSplitDecoFromDrag } from "./createSplitDecoFromDrag.js"
|
|
7
|
+
export { debugFrame } from "./debugFrame.js"
|
|
8
|
+
export { findFramesTouchingEdge } from "./findFramesTouchingEdge.js"
|
|
9
|
+
export { findSafeSplitEdgeAndPosition } from "./findSafeSplitEdge.js"
|
|
10
|
+
export { findVisualEdge } from "./findVisualEdge.js"
|
|
11
|
+
export { frameCreate } from "./frameCreate.js"
|
|
12
|
+
export { frameSplit } from "./frameSplit.js"
|
|
13
|
+
export { getCloseFrameInfo } from "./getCloseFrameInfo.js"
|
|
14
|
+
export { getFrameSplitInfo } from "./getFrameSplitInfo.js"
|
|
15
|
+
export { getFrameTo } from "./getFrameTo.js"
|
|
16
|
+
export { isPointInFrame } from "./isPointInFrame.js"
|
|
17
|
+
export { layoutAddWindow } from "./layoutAddWindow.js"
|
|
18
|
+
export { layoutCreate } from "./layoutCreate.js"
|
|
19
|
+
export { layoutRemoveWindow } from "./layoutRemoveWindow.js"
|
|
20
|
+
export { resizeFrame } from "./resizeFrame.js"
|
|
21
|
+
export { windowAddFrame } from "./windowAddFrame.js"
|
|
22
|
+
export { windowCreate } from "./windowCreate.js"
|
|
23
|
+
export { windowRemoveFrame } from "./windowRemoveFrame.js"
|
|
24
|
+
export { windowSetActiveFrame } from "./windowSetActiveFrame.js"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { inRange } from "../helpers/inRange.js"
|
|
2
|
+
import type { LayoutFrame, Point } from "../types/index.js"
|
|
3
|
+
|
|
4
|
+
export function isPointInFrame(frame: LayoutFrame, point: Point): boolean {
|
|
5
|
+
return inRange(point.x, frame.x, frame.x + frame.width)
|
|
6
|
+
&& inRange(point.y, frame.y, frame.y + frame.height)
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { z } from "zod"
|
|
2
|
+
|
|
3
|
+
import type { Layout, zLayoutCreate } from "../types/index.js"
|
|
4
|
+
|
|
5
|
+
// todo ability to init with windows and checks
|
|
6
|
+
export function layoutCreate(opts: z.infer<typeof zLayoutCreate> = {}): Layout {
|
|
7
|
+
return {
|
|
8
|
+
windows: {},
|
|
9
|
+
activeWindow: undefined,
|
|
10
|
+
...opts
|
|
11
|
+
} satisfies Layout
|
|
12
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { findFramesTouchingEdge } from "./findFramesTouchingEdge.js"
|
|
2
|
+
|
|
3
|
+
import { clampNumber } from "../helpers/clampNumber.js"
|
|
4
|
+
import { frameToEdges } from "../helpers/frameToEdges.js"
|
|
5
|
+
import { getEdgeOrientation } from "../helpers/getEdgeOrientation.js"
|
|
6
|
+
import { getResizeLimit } from "../helpers/getResizeLimit.js"
|
|
7
|
+
import { getVisualEdges } from "../helpers/getVisualEdges.js"
|
|
8
|
+
import { isWindowEdge } from "../helpers/isWindowEdge.js"
|
|
9
|
+
import { resizeByEdge } from "../helpers/resizeByEdge.js"
|
|
10
|
+
import { getMarginSize } from "../settings.js"
|
|
11
|
+
import type { Edge, ExtendedDirection, LayoutFrame, LayoutWindow, Size } from "../types/index.js"
|
|
12
|
+
|
|
13
|
+
export function resizeFrame(
|
|
14
|
+
win: LayoutWindow,
|
|
15
|
+
frame: LayoutFrame,
|
|
16
|
+
dir: ExtendedDirection,
|
|
17
|
+
/** Scaled */
|
|
18
|
+
distance: Size,
|
|
19
|
+
/** Scaled */
|
|
20
|
+
minSize: Size = getMarginSize()
|
|
21
|
+
): boolean {
|
|
22
|
+
const originalDistance = distance
|
|
23
|
+
const frameEdges = frameToEdges(frame)
|
|
24
|
+
const resizeEdges = dir === "up"
|
|
25
|
+
? [frameEdges.top]
|
|
26
|
+
: dir === "down"
|
|
27
|
+
? [frameEdges.bottom]
|
|
28
|
+
: dir === "vertical"
|
|
29
|
+
? [frameEdges.top, frameEdges.bottom]
|
|
30
|
+
: dir === "left"
|
|
31
|
+
? [frameEdges.left]
|
|
32
|
+
: dir === "right"
|
|
33
|
+
? [frameEdges.right]
|
|
34
|
+
: [frameEdges.left, frameEdges.right]
|
|
35
|
+
|
|
36
|
+
let divideDistance = false
|
|
37
|
+
if (resizeEdges.length === 2) {
|
|
38
|
+
divideDistance = true
|
|
39
|
+
}
|
|
40
|
+
let ok = false
|
|
41
|
+
const edgeDirection = getEdgeOrientation(resizeEdges[0])
|
|
42
|
+
const margin = minSize[edgeDirection === "vertical" ? "width" : "height"]
|
|
43
|
+
|
|
44
|
+
let dist = distance[edgeDirection === "vertical" ? "width" : "height"]
|
|
45
|
+
if (divideDistance) { dist /= 2 }
|
|
46
|
+
|
|
47
|
+
for (const resizeEdge of resizeEdges) {
|
|
48
|
+
// simple resize dir
|
|
49
|
+
const _dir = dir === "horizontal"
|
|
50
|
+
? (resizeEdge === frameEdges.left ? "left" : "right")
|
|
51
|
+
: dir === "vertical"
|
|
52
|
+
? (resizeEdge === frameEdges.top ? "up" : "down")
|
|
53
|
+
: dir
|
|
54
|
+
|
|
55
|
+
let frameEdge = resizeEdge
|
|
56
|
+
|
|
57
|
+
const visualEdges = getVisualEdges(Object.values(win.frames), { separateByDir: true })
|
|
58
|
+
const edges = visualEdges[edgeDirection]
|
|
59
|
+
|
|
60
|
+
const isWinEdge = isWindowEdge(frameEdge, edgeDirection)
|
|
61
|
+
|
|
62
|
+
if (isWinEdge) {
|
|
63
|
+
if (edgeDirection === "horizontal") {
|
|
64
|
+
frameEdge = frameEdge === frameEdges.top ? frameEdges.bottom : frameEdges.top
|
|
65
|
+
} else {
|
|
66
|
+
frameEdge = frameEdge === frameEdges.right ? frameEdges.left : frameEdges.right
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let foundEdge: Edge | undefined
|
|
71
|
+
for (const edge of edges) {
|
|
72
|
+
if (edgeDirection === "horizontal") {
|
|
73
|
+
const isInRange = frameEdge.startX >= edge.startX && frameEdge.endX <= edge.endX
|
|
74
|
+
if (isInRange && frameEdge.startY === edge.startY) {
|
|
75
|
+
foundEdge = edge
|
|
76
|
+
break
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
const isInRange = frameEdge.startY >= edge.startY && frameEdge.endY <= edge.endY
|
|
80
|
+
if (isInRange && frameEdge.startX === edge.startX) {
|
|
81
|
+
foundEdge = edge
|
|
82
|
+
break
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!foundEdge) {
|
|
88
|
+
distance = originalDistance
|
|
89
|
+
continue
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const touchingFrames = findFramesTouchingEdge(foundEdge, Object.values(win.frames))?.map(_ => _.frame)
|
|
93
|
+
const posX = foundEdge.startX + (_dir === "left" ? -dist : dist)
|
|
94
|
+
const posY = foundEdge.startY + (_dir === "up" ? -dist : dist)
|
|
95
|
+
|
|
96
|
+
const wantedPos = edgeDirection === "horizontal" ? posY : posX
|
|
97
|
+
const limitInDir = getResizeLimit(foundEdge, touchingFrames, _dir, dist, margin)
|
|
98
|
+
const reverseClamp = (_dir === "right" || _dir === "down")
|
|
99
|
+
const pos = reverseClamp
|
|
100
|
+
? clampNumber(wantedPos, -Infinity, limitInDir)
|
|
101
|
+
: clampNumber(wantedPos, limitInDir, Infinity)
|
|
102
|
+
resizeByEdge(touchingFrames, foundEdge, _dir, pos, dist)
|
|
103
|
+
ok = true
|
|
104
|
+
}
|
|
105
|
+
return ok
|
|
106
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LayoutFrame, LayoutWindow } from "../types/index.js"
|
|
2
|
+
|
|
3
|
+
export function windowAddFrame(win: LayoutWindow, frame: LayoutFrame): LayoutFrame {
|
|
4
|
+
// todo check can add because of space
|
|
5
|
+
// avoid duplicates in case of user error
|
|
6
|
+
// we can't have duplicates because a frame can't be in two positions at once
|
|
7
|
+
// if we implement frame linking it will have to be some other way
|
|
8
|
+
win.frames[frame.id] = frame
|
|
9
|
+
return frame
|
|
10
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from "uuid"
|
|
2
|
+
import type { z } from "zod"
|
|
3
|
+
|
|
4
|
+
import type { LayoutWindow, zWindowCreate } from "../types/index.js"
|
|
5
|
+
|
|
6
|
+
/** Create a new window. Note that it will always have a new id if it's undefined. */
|
|
7
|
+
export function windowCreate(opts: z.infer<typeof zWindowCreate> = {}): LayoutWindow {
|
|
8
|
+
return {
|
|
9
|
+
frames: {},
|
|
10
|
+
activeFrame: undefined,
|
|
11
|
+
pxWidth: 0,
|
|
12
|
+
pxHeight: 0,
|
|
13
|
+
pxX: 0,
|
|
14
|
+
pxY: 0,
|
|
15
|
+
...opts,
|
|
16
|
+
id: opts.id ?? uuidv4()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Point, Size } from "./types/index.js"
|
|
2
|
+
|
|
3
|
+
const g = {
|
|
4
|
+
SCALE: 3,
|
|
5
|
+
maxInt: 100 * (10 ** 3),
|
|
6
|
+
SNAP_PERCENTAGE_X: 0.5,
|
|
7
|
+
SNAP_PERCENTAGE_Y: 0.5,
|
|
8
|
+
snapPoint: { x: Math.round(0.5 * (10 ** 3)), y: Math.round(0.5 * (10 ** 3)) },
|
|
9
|
+
MARGIN_PERCENTAGE_WIDTH: 10 ** 3,
|
|
10
|
+
MARGIN_PERCENTAGE_HEIGHT: 10 ** 3,
|
|
11
|
+
marginSize: { width: 10 ** 3, height: 10 ** 3 }
|
|
12
|
+
}
|
|
13
|
+
export const globalOptions = g
|
|
14
|
+
// todo think of better way :/
|
|
15
|
+
|
|
16
|
+
export function setScale(scale: number): void {
|
|
17
|
+
const max = 100 * (10 ** scale)
|
|
18
|
+
if (!Number.isSafeInteger(max)) {
|
|
19
|
+
throw new TypeError("Scale too high. Precision will be lost!")
|
|
20
|
+
}
|
|
21
|
+
g.SCALE = scale
|
|
22
|
+
g.maxInt = max
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getMaxInt(): number {
|
|
26
|
+
return g.maxInt
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function setSnapPercentage(snapPercentage: number | Point): void {
|
|
30
|
+
if (typeof snapPercentage === "number") {
|
|
31
|
+
g.SNAP_PERCENTAGE_X = snapPercentage
|
|
32
|
+
g.SNAP_PERCENTAGE_Y = snapPercentage
|
|
33
|
+
} else {
|
|
34
|
+
g.SNAP_PERCENTAGE_X = snapPercentage.x
|
|
35
|
+
g.SNAP_PERCENTAGE_Y = snapPercentage.y
|
|
36
|
+
}
|
|
37
|
+
g.snapPoint = {
|
|
38
|
+
x: Math.round(g.SNAP_PERCENTAGE_X * (10 ** g.SCALE)),
|
|
39
|
+
y: Math.round(g.SNAP_PERCENTAGE_Y * (10 ** g.SCALE))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getSnapPoint(): Readonly<Point> {
|
|
44
|
+
return g.snapPoint
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function setMarginPercentage(margin: number | Size): void {
|
|
48
|
+
if (typeof margin === "number") {
|
|
49
|
+
g.MARGIN_PERCENTAGE_WIDTH = margin
|
|
50
|
+
g.MARGIN_PERCENTAGE_HEIGHT = margin
|
|
51
|
+
} else {
|
|
52
|
+
g.MARGIN_PERCENTAGE_WIDTH = margin.width
|
|
53
|
+
g.MARGIN_PERCENTAGE_HEIGHT = margin.height
|
|
54
|
+
}
|
|
55
|
+
g.marginSize = {
|
|
56
|
+
width: Math.round(g.MARGIN_PERCENTAGE_WIDTH * (10 ** g.SCALE)),
|
|
57
|
+
height: Math.round(g.MARGIN_PERCENTAGE_HEIGHT * (10 ** g.SCALE))
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function getMarginSize(): Readonly<Size> {
|
|
62
|
+
return g.marginSize
|
|
63
|
+
}
|