@witchcraft/layout 0.0.1

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.
Files changed (336) hide show
  1. package/README.md +474 -0
  2. package/dist/module.d.mts +14 -0
  3. package/dist/module.json +9 -0
  4. package/dist/module.mjs +26 -0
  5. package/dist/runtime/components/LayoutDecos.d.vue.ts +0 -0
  6. package/dist/runtime/components/LayoutDecos.vue +54 -0
  7. package/dist/runtime/components/LayoutDecos.vue.d.ts +0 -0
  8. package/dist/runtime/components/LayoutEdges.d.vue.ts +0 -0
  9. package/dist/runtime/components/LayoutEdges.vue +145 -0
  10. package/dist/runtime/components/LayoutEdges.vue.d.ts +0 -0
  11. package/dist/runtime/components/LayoutFrame.d.vue.ts +0 -0
  12. package/dist/runtime/components/LayoutFrame.vue +41 -0
  13. package/dist/runtime/components/LayoutFrame.vue.d.ts +0 -0
  14. package/dist/runtime/components/LayoutShapeSquare.d.vue.ts +0 -0
  15. package/dist/runtime/components/LayoutShapeSquare.vue +36 -0
  16. package/dist/runtime/components/LayoutShapeSquare.vue.d.ts +0 -0
  17. package/dist/runtime/components/LayoutWindow.d.vue.ts +0 -0
  18. package/dist/runtime/components/LayoutWindow.vue +183 -0
  19. package/dist/runtime/components/LayoutWindow.vue.d.ts +0 -0
  20. package/dist/runtime/composables/useFrames.d.ts +0 -0
  21. package/dist/runtime/composables/useFrames.js +184 -0
  22. package/dist/runtime/demo/App.d.vue.ts +0 -0
  23. package/dist/runtime/demo/App.vue +121 -0
  24. package/dist/runtime/demo/App.vue.d.ts +0 -0
  25. package/dist/runtime/demo/DemoControls.d.vue.ts +0 -0
  26. package/dist/runtime/demo/DemoControls.vue +14 -0
  27. package/dist/runtime/demo/DemoControls.vue.d.ts +0 -0
  28. package/dist/runtime/demo/README.md +1 -0
  29. package/dist/runtime/demo/main.d.ts +0 -0
  30. package/dist/runtime/demo/main.js +4 -0
  31. package/dist/runtime/demo/sharedLayoutInstance.d.ts +0 -0
  32. package/dist/runtime/demo/sharedLayoutInstance.js +5 -0
  33. package/dist/runtime/demo/tailwind.css +1 -0
  34. package/dist/runtime/drag/CloseAction.d.ts +0 -0
  35. package/dist/runtime/drag/CloseAction.js +121 -0
  36. package/dist/runtime/drag/DragActionHandler.d.ts +0 -0
  37. package/dist/runtime/drag/DragActionHandler.js +83 -0
  38. package/dist/runtime/drag/DragDirectionStore.d.ts +0 -0
  39. package/dist/runtime/drag/DragDirectionStore.js +45 -0
  40. package/dist/runtime/drag/SplitAction.d.ts +0 -0
  41. package/dist/runtime/drag/SplitAction.js +110 -0
  42. package/dist/runtime/drag/types.d.ts +0 -0
  43. package/dist/runtime/drag/types.js +0 -0
  44. package/dist/runtime/helpers/addPointsToIntersection.d.ts +0 -0
  45. package/dist/runtime/helpers/addPointsToIntersection.js +7 -0
  46. package/dist/runtime/helpers/assertEdgeSorted.d.ts +0 -0
  47. package/dist/runtime/helpers/assertEdgeSorted.js +7 -0
  48. package/dist/runtime/helpers/assertItemIn.d.ts +0 -0
  49. package/dist/runtime/helpers/assertItemIn.js +8 -0
  50. package/dist/runtime/helpers/assertItemNotIn.d.ts +0 -0
  51. package/dist/runtime/helpers/assertItemNotIn.js +7 -0
  52. package/dist/runtime/helpers/assertLayoutHasActiveWindow.d.ts +0 -0
  53. package/dist/runtime/helpers/assertLayoutHasActiveWindow.js +7 -0
  54. package/dist/runtime/helpers/assertValidWinAndFrame.d.ts +0 -0
  55. package/dist/runtime/helpers/assertValidWinAndFrame.js +5 -0
  56. package/dist/runtime/helpers/assertValidWinAndFrameIds.d.ts +0 -0
  57. package/dist/runtime/helpers/assertValidWinAndFrameIds.js +6 -0
  58. package/dist/runtime/helpers/assertWindowHasActiveFrame.d.ts +0 -0
  59. package/dist/runtime/helpers/assertWindowHasActiveFrame.js +7 -0
  60. package/dist/runtime/helpers/clampNumber.d.ts +0 -0
  61. package/dist/runtime/helpers/clampNumber.js +3 -0
  62. package/dist/runtime/helpers/cloneFrame.d.ts +0 -0
  63. package/dist/runtime/helpers/cloneFrame.js +3 -0
  64. package/dist/runtime/helpers/cloneFrames.d.ts +0 -0
  65. package/dist/runtime/helpers/cloneFrames.js +16 -0
  66. package/dist/runtime/helpers/containsEdge.d.ts +0 -0
  67. package/dist/runtime/helpers/containsEdge.js +13 -0
  68. package/dist/runtime/helpers/convertLayoutWindowToWorkspace.d.ts +0 -0
  69. package/dist/runtime/helpers/convertLayoutWindowToWorkspace.js +10 -0
  70. package/dist/runtime/helpers/copySize.d.ts +0 -0
  71. package/dist/runtime/helpers/copySize.js +5 -0
  72. package/dist/runtime/helpers/createEdge.d.ts +0 -0
  73. package/dist/runtime/helpers/createEdge.js +13 -0
  74. package/dist/runtime/helpers/dirToOrientation.d.ts +0 -0
  75. package/dist/runtime/helpers/dirToOrientation.js +10 -0
  76. package/dist/runtime/helpers/dirToSide.d.ts +0 -0
  77. package/dist/runtime/helpers/dirToSide.js +5 -0
  78. package/dist/runtime/helpers/doEdgesOverlap.d.ts +0 -0
  79. package/dist/runtime/helpers/doEdgesOverlap.js +22 -0
  80. package/dist/runtime/helpers/doesEdgeContinueEdge.d.ts +0 -0
  81. package/dist/runtime/helpers/doesEdgeContinueEdge.js +17 -0
  82. package/dist/runtime/helpers/edgeToPoints.d.ts +0 -0
  83. package/dist/runtime/helpers/edgeToPoints.js +3 -0
  84. package/dist/runtime/helpers/findDraggableEdge.d.ts +0 -0
  85. package/dist/runtime/helpers/findDraggableEdge.js +13 -0
  86. package/dist/runtime/helpers/findFrameDraggableEdges.d.ts +0 -0
  87. package/dist/runtime/helpers/findFrameDraggableEdges.js +18 -0
  88. package/dist/runtime/helpers/frameToEdges.d.ts +0 -0
  89. package/dist/runtime/helpers/frameToEdges.js +21 -0
  90. package/dist/runtime/helpers/frameToPoints.d.ts +0 -0
  91. package/dist/runtime/helpers/frameToPoints.js +7 -0
  92. package/dist/runtime/helpers/getEdgeOrientation.d.ts +0 -0
  93. package/dist/runtime/helpers/getEdgeOrientation.js +4 -0
  94. package/dist/runtime/helpers/getEdgeSharedDirection.d.ts +0 -0
  95. package/dist/runtime/helpers/getEdgeSharedDirection.js +7 -0
  96. package/dist/runtime/helpers/getEdgeSide.d.ts +0 -0
  97. package/dist/runtime/helpers/getEdgeSide.js +16 -0
  98. package/dist/runtime/helpers/getFrameById.d.ts +0 -0
  99. package/dist/runtime/helpers/getFrameById.js +5 -0
  100. package/dist/runtime/helpers/getFrameConstant.d.ts +0 -0
  101. package/dist/runtime/helpers/getFrameConstant.js +15 -0
  102. package/dist/runtime/helpers/getIntersections.d.ts +0 -0
  103. package/dist/runtime/helpers/getIntersections.js +63 -0
  104. package/dist/runtime/helpers/getIntersectionsCss.d.ts +0 -0
  105. package/dist/runtime/helpers/getIntersectionsCss.js +56 -0
  106. package/dist/runtime/helpers/getMoveEdgeInfo.d.ts +0 -0
  107. package/dist/runtime/helpers/getMoveEdgeInfo.js +42 -0
  108. package/dist/runtime/helpers/getResizeLimit.d.ts +0 -0
  109. package/dist/runtime/helpers/getResizeLimit.js +39 -0
  110. package/dist/runtime/helpers/getShapeSquareCss.d.ts +0 -0
  111. package/dist/runtime/helpers/getShapeSquareCss.js +17 -0
  112. package/dist/runtime/helpers/getSideTouching.d.ts +0 -0
  113. package/dist/runtime/helpers/getSideTouching.js +7 -0
  114. package/dist/runtime/helpers/getVisualEdgeCss.d.ts +0 -0
  115. package/dist/runtime/helpers/getVisualEdgeCss.js +40 -0
  116. package/dist/runtime/helpers/getVisualEdges.d.ts +0 -0
  117. package/dist/runtime/helpers/getVisualEdges.js +89 -0
  118. package/dist/runtime/helpers/getVisualEdgesCss.d.ts +0 -0
  119. package/dist/runtime/helpers/getVisualEdgesCss.js +4 -0
  120. package/dist/runtime/helpers/getWinAndFrameById.d.ts +0 -0
  121. package/dist/runtime/helpers/getWinAndFrameById.js +14 -0
  122. package/dist/runtime/helpers/getWinByFrameUuid.d.ts +0 -0
  123. package/dist/runtime/helpers/getWinByFrameUuid.js +13 -0
  124. package/dist/runtime/helpers/getWinById.d.ts +0 -0
  125. package/dist/runtime/helpers/getWinById.js +5 -0
  126. package/dist/runtime/helpers/getWindowConstant.d.ts +0 -0
  127. package/dist/runtime/helpers/getWindowConstant.js +14 -0
  128. package/dist/runtime/helpers/inRange.d.ts +0 -0
  129. package/dist/runtime/helpers/inRange.js +3 -0
  130. package/dist/runtime/helpers/index.d.ts +0 -0
  131. package/dist/runtime/helpers/index.js +62 -0
  132. package/dist/runtime/helpers/isEdgeEqual.d.ts +0 -0
  133. package/dist/runtime/helpers/isEdgeEqual.js +11 -0
  134. package/dist/runtime/helpers/isEdgeParallel.d.ts +0 -0
  135. package/dist/runtime/helpers/isEdgeParallel.js +7 -0
  136. package/dist/runtime/helpers/isPointEqual.d.ts +0 -0
  137. package/dist/runtime/helpers/isPointEqual.js +3 -0
  138. package/dist/runtime/helpers/isSizeAboveMin.d.ts +0 -0
  139. package/dist/runtime/helpers/isSizeAboveMin.js +3 -0
  140. package/dist/runtime/helpers/isSizeEqual.d.ts +0 -0
  141. package/dist/runtime/helpers/isSizeEqual.js +3 -0
  142. package/dist/runtime/helpers/isWindowEdge.d.ts +0 -0
  143. package/dist/runtime/helpers/isWindowEdge.js +7 -0
  144. package/dist/runtime/helpers/isWindowEdgePoint.d.ts +0 -0
  145. package/dist/runtime/helpers/isWindowEdgePoint.js +5 -0
  146. package/dist/runtime/helpers/moveEdge.d.ts +0 -0
  147. package/dist/runtime/helpers/moveEdge.js +8 -0
  148. package/dist/runtime/helpers/numberToScaledPercent.d.ts +0 -0
  149. package/dist/runtime/helpers/numberToScaledPercent.js +5 -0
  150. package/dist/runtime/helpers/numberToScaledSize.d.ts +0 -0
  151. package/dist/runtime/helpers/numberToScaledSize.js +19 -0
  152. package/dist/runtime/helpers/oppositeSide.d.ts +0 -0
  153. package/dist/runtime/helpers/oppositeSide.js +30 -0
  154. package/dist/runtime/helpers/resizeByEdge.d.ts +0 -0
  155. package/dist/runtime/helpers/resizeByEdge.js +29 -0
  156. package/dist/runtime/helpers/sideToDirection.d.ts +0 -0
  157. package/dist/runtime/helpers/sideToDirection.js +11 -0
  158. package/dist/runtime/helpers/sideToOrientation.d.ts +0 -0
  159. package/dist/runtime/helpers/sideToOrientation.js +10 -0
  160. package/dist/runtime/helpers/splitEdge.d.ts +0 -0
  161. package/dist/runtime/helpers/splitEdge.js +20 -0
  162. package/dist/runtime/helpers/toCoord.d.ts +0 -0
  163. package/dist/runtime/helpers/toCoord.js +10 -0
  164. package/dist/runtime/helpers/toId.d.ts +0 -0
  165. package/dist/runtime/helpers/toId.js +4 -0
  166. package/dist/runtime/helpers/toWindowCoord.d.ts +0 -0
  167. package/dist/runtime/helpers/toWindowCoord.js +14 -0
  168. package/dist/runtime/helpers/unionEdges.d.ts +0 -0
  169. package/dist/runtime/helpers/unionEdges.js +8 -0
  170. package/dist/runtime/helpers/updateWindowSizeWithEvent.d.ts +0 -0
  171. package/dist/runtime/helpers/updateWindowSizeWithEvent.js +8 -0
  172. package/dist/runtime/index.d.ts +0 -0
  173. package/dist/runtime/index.js +5 -0
  174. package/dist/runtime/layout/closeFrame.d.ts +0 -0
  175. package/dist/runtime/layout/closeFrame.js +13 -0
  176. package/dist/runtime/layout/closeFrames.d.ts +0 -0
  177. package/dist/runtime/layout/closeFrames.js +8 -0
  178. package/dist/runtime/layout/createSplitDecoEdge.d.ts +0 -0
  179. package/dist/runtime/layout/createSplitDecoEdge.js +24 -0
  180. package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +0 -0
  181. package/dist/runtime/layout/createSplitDecoFromDrag.js +14 -0
  182. package/dist/runtime/layout/debugFrame.d.ts +0 -0
  183. package/dist/runtime/layout/debugFrame.js +4 -0
  184. package/dist/runtime/layout/findFramesTouchingEdge.d.ts +0 -0
  185. package/dist/runtime/layout/findFramesTouchingEdge.js +33 -0
  186. package/dist/runtime/layout/findSafeSplitEdge.d.ts +0 -0
  187. package/dist/runtime/layout/findSafeSplitEdge.js +20 -0
  188. package/dist/runtime/layout/findVisualEdge.d.ts +0 -0
  189. package/dist/runtime/layout/findVisualEdge.js +9 -0
  190. package/dist/runtime/layout/frameCreate.d.ts +0 -0
  191. package/dist/runtime/layout/frameCreate.js +13 -0
  192. package/dist/runtime/layout/frameSplit.d.ts +0 -0
  193. package/dist/runtime/layout/frameSplit.js +9 -0
  194. package/dist/runtime/layout/getCloseFrameInfo.d.ts +0 -0
  195. package/dist/runtime/layout/getCloseFrameInfo.js +103 -0
  196. package/dist/runtime/layout/getFrameSplitInfo.d.ts +0 -0
  197. package/dist/runtime/layout/getFrameSplitInfo.js +40 -0
  198. package/dist/runtime/layout/getFrameTo.d.ts +0 -0
  199. package/dist/runtime/layout/getFrameTo.js +47 -0
  200. package/dist/runtime/layout/index.d.ts +0 -0
  201. package/dist/runtime/layout/index.js +22 -0
  202. package/dist/runtime/layout/isPointInFrame.d.ts +0 -0
  203. package/dist/runtime/layout/isPointInFrame.js +4 -0
  204. package/dist/runtime/layout/layoutAddWindow.d.ts +0 -0
  205. package/dist/runtime/layout/layoutAddWindow.js +4 -0
  206. package/dist/runtime/layout/layoutCreate.d.ts +0 -0
  207. package/dist/runtime/layout/layoutCreate.js +7 -0
  208. package/dist/runtime/layout/layoutRemoveWindow.d.ts +0 -0
  209. package/dist/runtime/layout/layoutRemoveWindow.js +5 -0
  210. package/dist/runtime/layout/resizeFrame.d.ts +0 -0
  211. package/dist/runtime/layout/resizeFrame.js +69 -0
  212. package/dist/runtime/layout/windowAddFrame.d.ts +0 -0
  213. package/dist/runtime/layout/windowAddFrame.js +4 -0
  214. package/dist/runtime/layout/windowCreate.d.ts +0 -0
  215. package/dist/runtime/layout/windowCreate.js +13 -0
  216. package/dist/runtime/layout/windowRemoveFrame.d.ts +0 -0
  217. package/dist/runtime/layout/windowRemoveFrame.js +5 -0
  218. package/dist/runtime/layout/windowSetActiveFrame.d.ts +0 -0
  219. package/dist/runtime/layout/windowSetActiveFrame.js +5 -0
  220. package/dist/runtime/settings.d.ts +0 -0
  221. package/dist/runtime/settings.js +54 -0
  222. package/dist/runtime/types/index.d.ts +0 -0
  223. package/dist/runtime/types/index.js +120 -0
  224. package/dist/runtime/utils/KnownError.d.ts +0 -0
  225. package/dist/runtime/utils/KnownError.js +9 -0
  226. package/dist/types.d.mts +5 -0
  227. package/package.json +153 -0
  228. package/src/module.ts +43 -0
  229. package/src/runtime/components/LayoutDecos.vue +62 -0
  230. package/src/runtime/components/LayoutEdges.vue +172 -0
  231. package/src/runtime/components/LayoutFrame.vue +47 -0
  232. package/src/runtime/components/LayoutShapeSquare.vue +38 -0
  233. package/src/runtime/components/LayoutWindow.vue +223 -0
  234. package/src/runtime/composables/useFrames.ts +251 -0
  235. package/src/runtime/demo/App.vue +139 -0
  236. package/src/runtime/demo/DemoControls.vue +17 -0
  237. package/src/runtime/demo/README.md +1 -0
  238. package/src/runtime/demo/main.ts +9 -0
  239. package/src/runtime/demo/sharedLayoutInstance.ts +7 -0
  240. package/src/runtime/demo/tailwind.css +4 -0
  241. package/src/runtime/drag/CloseAction.ts +158 -0
  242. package/src/runtime/drag/DragActionHandler.ts +146 -0
  243. package/src/runtime/drag/DragDirectionStore.ts +63 -0
  244. package/src/runtime/drag/SplitAction.ts +147 -0
  245. package/src/runtime/drag/types.ts +107 -0
  246. package/src/runtime/helpers/addPointsToIntersection.ts +9 -0
  247. package/src/runtime/helpers/assertEdgeSorted.ts +11 -0
  248. package/src/runtime/helpers/assertItemIn.ts +13 -0
  249. package/src/runtime/helpers/assertItemNotIn.ts +10 -0
  250. package/src/runtime/helpers/assertLayoutHasActiveWindow.ts +9 -0
  251. package/src/runtime/helpers/assertValidWinAndFrame.ts +16 -0
  252. package/src/runtime/helpers/assertValidWinAndFrameIds.ts +9 -0
  253. package/src/runtime/helpers/assertWindowHasActiveFrame.ts +9 -0
  254. package/src/runtime/helpers/clampNumber.ts +9 -0
  255. package/src/runtime/helpers/cloneFrame.ts +5 -0
  256. package/src/runtime/helpers/cloneFrames.ts +20 -0
  257. package/src/runtime/helpers/containsEdge.ts +16 -0
  258. package/src/runtime/helpers/convertLayoutWindowToWorkspace.ts +18 -0
  259. package/src/runtime/helpers/copySize.ts +7 -0
  260. package/src/runtime/helpers/createEdge.ts +19 -0
  261. package/src/runtime/helpers/dirToOrientation.ts +12 -0
  262. package/src/runtime/helpers/dirToSide.ts +7 -0
  263. package/src/runtime/helpers/doEdgesOverlap.ts +25 -0
  264. package/src/runtime/helpers/doesEdgeContinueEdge.ts +20 -0
  265. package/src/runtime/helpers/edgeToPoints.ts +5 -0
  266. package/src/runtime/helpers/findDraggableEdge.ts +24 -0
  267. package/src/runtime/helpers/findFrameDraggableEdges.ts +32 -0
  268. package/src/runtime/helpers/frameToEdges.ts +32 -0
  269. package/src/runtime/helpers/frameToPoints.ts +14 -0
  270. package/src/runtime/helpers/getEdgeOrientation.ts +6 -0
  271. package/src/runtime/helpers/getEdgeSharedDirection.ts +10 -0
  272. package/src/runtime/helpers/getEdgeSide.ts +27 -0
  273. package/src/runtime/helpers/getFrameById.ts +15 -0
  274. package/src/runtime/helpers/getFrameConstant.ts +22 -0
  275. package/src/runtime/helpers/getIntersections.ts +87 -0
  276. package/src/runtime/helpers/getIntersectionsCss.ts +65 -0
  277. package/src/runtime/helpers/getMoveEdgeInfo.ts +69 -0
  278. package/src/runtime/helpers/getResizeLimit.ts +60 -0
  279. package/src/runtime/helpers/getShapeSquareCss.ts +28 -0
  280. package/src/runtime/helpers/getSideTouching.ts +9 -0
  281. package/src/runtime/helpers/getVisualEdgeCss.ts +53 -0
  282. package/src/runtime/helpers/getVisualEdges.ts +155 -0
  283. package/src/runtime/helpers/getVisualEdgesCss.ts +13 -0
  284. package/src/runtime/helpers/getWinAndFrameById.ts +28 -0
  285. package/src/runtime/helpers/getWinByFrameUuid.ts +19 -0
  286. package/src/runtime/helpers/getWinById.ts +12 -0
  287. package/src/runtime/helpers/getWindowConstant.ts +21 -0
  288. package/src/runtime/helpers/inRange.ts +5 -0
  289. package/src/runtime/helpers/index.ts +64 -0
  290. package/src/runtime/helpers/isEdgeEqual.ts +14 -0
  291. package/src/runtime/helpers/isEdgeParallel.ts +10 -0
  292. package/src/runtime/helpers/isPointEqual.ts +5 -0
  293. package/src/runtime/helpers/isSizeAboveMin.ts +8 -0
  294. package/src/runtime/helpers/isSizeEqual.ts +5 -0
  295. package/src/runtime/helpers/isWindowEdge.ts +11 -0
  296. package/src/runtime/helpers/isWindowEdgePoint.ts +8 -0
  297. package/src/runtime/helpers/moveEdge.ts +21 -0
  298. package/src/runtime/helpers/numberToScaledPercent.ts +19 -0
  299. package/src/runtime/helpers/numberToScaledSize.ts +28 -0
  300. package/src/runtime/helpers/oppositeSide.ts +45 -0
  301. package/src/runtime/helpers/resizeByEdge.ts +45 -0
  302. package/src/runtime/helpers/sideToDirection.ts +15 -0
  303. package/src/runtime/helpers/sideToOrientation.ts +12 -0
  304. package/src/runtime/helpers/splitEdge.ts +23 -0
  305. package/src/runtime/helpers/toCoord.ts +13 -0
  306. package/src/runtime/helpers/toId.ts +9 -0
  307. package/src/runtime/helpers/toWindowCoord.ts +23 -0
  308. package/src/runtime/helpers/unionEdges.ts +11 -0
  309. package/src/runtime/helpers/updateWindowSizeWithEvent.ts +10 -0
  310. package/src/runtime/index.ts +5 -0
  311. package/src/runtime/layout/closeFrame.ts +33 -0
  312. package/src/runtime/layout/closeFrames.ts +14 -0
  313. package/src/runtime/layout/createSplitDecoEdge.ts +34 -0
  314. package/src/runtime/layout/createSplitDecoFromDrag.ts +24 -0
  315. package/src/runtime/layout/debugFrame.ts +6 -0
  316. package/src/runtime/layout/findFramesTouchingEdge.ts +92 -0
  317. package/src/runtime/layout/findSafeSplitEdge.ts +39 -0
  318. package/src/runtime/layout/findVisualEdge.ts +11 -0
  319. package/src/runtime/layout/frameCreate.ts +23 -0
  320. package/src/runtime/layout/frameSplit.ts +31 -0
  321. package/src/runtime/layout/getCloseFrameInfo.ts +193 -0
  322. package/src/runtime/layout/getFrameSplitInfo.ts +65 -0
  323. package/src/runtime/layout/getFrameTo.ts +65 -0
  324. package/src/runtime/layout/index.ts +24 -0
  325. package/src/runtime/layout/isPointInFrame.ts +7 -0
  326. package/src/runtime/layout/layoutAddWindow.ts +6 -0
  327. package/src/runtime/layout/layoutCreate.ts +12 -0
  328. package/src/runtime/layout/layoutRemoveWindow.ts +7 -0
  329. package/src/runtime/layout/resizeFrame.ts +106 -0
  330. package/src/runtime/layout/windowAddFrame.ts +10 -0
  331. package/src/runtime/layout/windowCreate.ts +18 -0
  332. package/src/runtime/layout/windowRemoveFrame.ts +7 -0
  333. package/src/runtime/layout/windowSetActiveFrame.ts +7 -0
  334. package/src/runtime/settings.ts +63 -0
  335. package/src/runtime/types/index.ts +293 -0
  336. 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,6 @@
1
+ import type { Layout, LayoutWindow } from "../types/index.js"
2
+
3
+ export function layoutAddWindow(layout: Layout, win: LayoutWindow): LayoutWindow {
4
+ layout.windows[win.id] = win
5
+ return win
6
+ }
@@ -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,7 @@
1
+ import { toId } from "../helpers/toId.js"
2
+ import type { Layout, LayoutWindow } from "../types/index.js"
3
+
4
+ export function layoutRemoveWindow(layout: Layout, win: LayoutWindow | string): void {
5
+ const id = toId(win)
6
+ delete layout.windows[id]
7
+ }
@@ -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,7 @@
1
+ import { toId } from "../helpers/toId.js"
2
+ import type { LayoutFrame, LayoutWindow } from "../types/index.js"
3
+
4
+ export function windowRemoveFrame(win: LayoutWindow, frame: LayoutFrame | string): void {
5
+ const id = toId(frame)
6
+ delete win.frames[id]
7
+ }
@@ -0,0 +1,7 @@
1
+ import { toId } from "../helpers/toId.js"
2
+ import type { LayoutFrame, LayoutWindow } from "../types/index.js"
3
+
4
+ export function windowSetActiveFrame(win: LayoutWindow, frame: LayoutFrame | string): void {
5
+ const id = toId(frame)
6
+ win.activeFrame = id
7
+ }
@@ -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
+ }