@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,223 @@
1
+ <template>
2
+ <!-- overflow hidden is because the borders inside will make it overflow -->
3
+ <div :class="twMerge(
4
+ `window
5
+ relative
6
+ overflow-hidden
7
+ `,
8
+ isDragging && `dragging cursor-pointer`,
9
+ requestType && `request-${requestType}`,
10
+ $attrs.attrs.class
11
+ )"
12
+ ref="windowEl"
13
+ v-bind="{...$attrs.attrs, class: undefined}"
14
+ >
15
+ <template v-if="windowEl && win">
16
+ <LayoutFrameComponent :frame="frame"
17
+ :is-active-frame="frame.id === win.activeFrame"
18
+ v-for="frame of frames"
19
+ :key="frame.id"
20
+ v-bind="$attrs.frameAttrs"
21
+ @focus="windowSetActiveFrame(win, frame.id)"
22
+ >
23
+ <slot :name="`frame-${frame.id}`" v-bind="{frame}"/>
24
+ </LayoutFrameComponent>
25
+ <LayoutEdgesComponent
26
+ :win="win"
27
+ :active-frame="win.activeFrame ? frames[win.activeFrame] : undefined"
28
+ :edges="visualEdges"
29
+ :intersections="intersections"
30
+ :dragging-edge="draggingEdges.length === 1 ? draggingEdges[0] : undefined"
31
+ :dragging-intersection="draggingIntersection"
32
+ v-bind="$attrs.edgesAttrs"
33
+ @drag-start="dragStart"
34
+ />
35
+ <LayoutDecosComponent
36
+ :frames="frames"
37
+ :split-decos="splitDecos"
38
+ :close-decos="closeDecos"
39
+ v-bind="$attrs.decosAttrs"
40
+ />
41
+ <slot name="extra-decos"/>
42
+ </template>
43
+ <Teleport v-if="instructionsTeleportTo && filteredUsageInstructions.length > 0" defer :to="instructionsTeleportTo">
44
+ <span aria-live="polite">
45
+ <span
46
+ class="
47
+ after:content-['┃']
48
+ after:text-accent-500
49
+ last:after:content-none
50
+ after:mx-1
51
+ after:text-gray-500
52
+ "
53
+ v-for="instruction of filteredUsageInstructions"
54
+ :key="instruction"
55
+ >
56
+ {{ instruction }}
57
+ </span>
58
+ </span>
59
+ </Teleport>
60
+ </div>
61
+ </template>
62
+ <script lang="ts" setup>
63
+ import { useDivideAttrs } from "@witchcraft/ui/composables/useDivideAttrs"
64
+ import { useGlobalResizeObserver } from "@witchcraft/ui/composables/useGlobalResizeObserver"
65
+ import { twMerge } from "@witchcraft/ui/utils/twMerge"
66
+ import { computed, ref,watch } from "vue"
67
+
68
+ import LayoutDecosComponent from "./LayoutDecos.vue"
69
+ import LayoutEdgesComponent from "./LayoutEdges.vue"
70
+ import LayoutFrameComponent from "./LayoutFrame.vue"
71
+
72
+ import { useFrames } from "../composables/useFrames.js"
73
+ import { CloseAction } from "../drag/CloseAction"
74
+ import { DragActionHandler } from "../drag/DragActionHandler"
75
+ import { SplitAction } from "../drag/SplitAction.js"
76
+ import { type DragState, type IDragAction } from "../drag/types.js"
77
+ import { updateWindowWithEvent } from "../helpers/updateWindowSizeWithEvent.js"
78
+ import { windowSetActiveFrame } from "../layout/windowSetActiveFrame.js"
79
+ import { type CloseDeco, type LayoutWindow, type SplitDeco } from "../types/index.js"
80
+
81
+ const $attrs = useDivideAttrs(["frame", "edges", "decos"] as const)
82
+
83
+ const win = defineModel<LayoutWindow>("win", { required: true })
84
+
85
+ const props = withDefaults(defineProps<{
86
+ additionalDragActions?: IDragAction[]
87
+ splitKeyHandler?: (e: PointerEvent | KeyboardEvent, state: DragState) => boolean
88
+ closeKeyHandler?: (e: PointerEvent | KeyboardEvent, state: DragState) => boolean
89
+ usageInstructions?: Record<string, string | undefined>
90
+ instructionsTeleportTo: string | undefined
91
+ /**
92
+ * You might need to temporarily disable updating the window size while transitioning, depending on your layout.
93
+ *
94
+ * For example, if the component is in a flex container, during transition, there will be two components, and it will suddenly jump in size to being 1/2 the height. We can avoid this by using the known height (from win), but to do so, we can't let this component update the size while transitioning.
95
+ *
96
+ * When this is turned back on again, it will trigger an update. You can also trigger updates manually with the exposed updateWindowSize function.
97
+ */
98
+ allowWindowSizeUpdate?: boolean
99
+ }>(), {
100
+ additionalDragActions: () => ([]),
101
+ splitKeyHandler: undefined,
102
+ closeKeyHandler: undefined,
103
+ usageInstructions: () => ({ }),
104
+ instructionTeleportTo: undefined,
105
+ allowWindowSizeUpdate: true
106
+ })
107
+ const emit = defineEmits<{
108
+ (e: "isShowingDrag", value: boolean): void
109
+ (e: "dragState", value: DragState): void
110
+ }>()
111
+
112
+ const filteredUsageInstructions = computed(() => Object.values(props.usageInstructions).filter(_ => _ !== undefined).map(_ => _))
113
+
114
+ const splitKeyHandler = props.splitKeyHandler ?? ((e: PointerEvent | KeyboardEvent, state: DragState) =>
115
+ e.altKey || state.isDraggingFromWindowEdge)
116
+ const closeKeyHandler = props.closeKeyHandler ?? ((e: PointerEvent | KeyboardEvent) => {
117
+ if (e.ctrlKey && e.shiftKey) {
118
+ return "force"
119
+ }
120
+ if (e.shiftKey) return true
121
+ return false
122
+ })
123
+
124
+
125
+ const windowEl = ref<HTMLElement | null>(null)
126
+
127
+ const showDragging = ref(true)
128
+
129
+ const closeDecos = ref<CloseDeco[]>([])
130
+ const splitDecos = ref<SplitDeco[]>([])
131
+ const requestType = ref<"split" | "close" | undefined | string>()
132
+
133
+ const dragActionHandler = new DragActionHandler(
134
+ (
135
+ type: "start" | "move" | "end",
136
+ _e: PointerEvent | KeyboardEvent | undefined,
137
+ state: DragState
138
+ ) => type === "move" ? !state.isDraggingFromWindowEdge : undefined,
139
+ [
140
+ new SplitAction(
141
+ splitKeyHandler,
142
+ ((decos: SplitDeco[]) => splitDecos.value = decos),
143
+ {
144
+ onStart: () => showDragging.value = false,
145
+ onCancel: () => showDragging.value = true,
146
+ }),
147
+ new CloseAction(
148
+ closeKeyHandler,
149
+ ((decos: CloseDeco[]) => closeDecos.value = decos),
150
+ ),
151
+ ...props.additionalDragActions
152
+ ],
153
+ {
154
+ onEvent: (e, cancel) => {
155
+ showDragging.value = true
156
+ if (e instanceof KeyboardEvent && e.key === "Escape") {
157
+ cancel()
158
+ }
159
+ },
160
+ onRequestChange: type => {
161
+ requestType.value = type
162
+ },
163
+ onEnd: () => {
164
+ requestType.value = undefined
165
+ showDragging.value = true
166
+ }
167
+ }
168
+ )
169
+
170
+ const {
171
+ dragStart,
172
+ visualEdges,
173
+ isDragging,
174
+ draggingEdges,
175
+ draggingIntersection,
176
+ frames,
177
+ intersections,
178
+ state,
179
+ } = useFrames(
180
+ win,
181
+ showDragging,
182
+ dragActionHandler,
183
+ )
184
+
185
+
186
+ function getWindowOffset() {
187
+ const windowElRect = windowEl.value!.getBoundingClientRect()
188
+ return {
189
+ pxX: Math.floor(windowElRect.x),
190
+ pxY: Math.floor(windowElRect.y),
191
+ }
192
+ }
193
+ function getWindowSize() {
194
+ const windowElRect = windowEl.value!.getBoundingClientRect()
195
+ return {
196
+ pxWidth: Math.floor(windowElRect.width),
197
+ pxHeight: Math.floor(windowElRect.height),
198
+ }
199
+ }
200
+ function updateWindowSize() {
201
+ if (!props.allowWindowSizeUpdate) return
202
+ const newSize = { ...getWindowSize(), ...getWindowOffset() }
203
+ updateWindowWithEvent(win.value, newSize)
204
+ }
205
+ useGlobalResizeObserver(windowEl, updateWindowSize)
206
+ watch(() => props.allowWindowSizeUpdate, (newval, oldval) => {
207
+ if (oldval === false && newval === true) {
208
+ updateWindowSize()
209
+ }
210
+ })
211
+
212
+
213
+ watch(state, () => emit("dragState", state.value))
214
+ watch(showDragging, () => emit("isShowingDrag", showDragging.value))
215
+
216
+ defineExpose({
217
+ state,
218
+ win,
219
+ updateWindowSize,
220
+ })
221
+
222
+ </script>
223
+
@@ -0,0 +1,251 @@
1
+ import { debounce } from "@alanscodelog/utils/debounce"
2
+ import { keys } from "@alanscodelog/utils/keys"
3
+ import type { Ref } from "vue"
4
+ import { computed, onBeforeUnmount, onMounted, ref, watchEffect } from "vue"
5
+
6
+ import { DragDirectionStore } from "../drag/DragDirectionStore.js"
7
+ import type { DragChangeHandler, DragState } from "../drag/types.js"
8
+ import { cloneFrame } from "../helpers/cloneFrame.js"
9
+ import { getIntersections } from "../helpers/getIntersections.js"
10
+ import { getVisualEdges } from "../helpers/getVisualEdges.js"
11
+ import { isWindowEdge } from "../helpers/isWindowEdge.js"
12
+ import { moveEdge } from "../helpers/moveEdge.js"
13
+ import { toWindowCoord } from "../helpers/toWindowCoord.js"
14
+ import { findFramesTouchingEdge } from "../layout/findFramesTouchingEdge.js"
15
+ import { isPointInFrame } from "../layout/isPointInFrame.js"
16
+ import type { Direction, Edge, IntersectionEntry, LayoutFrame, LayoutWindow, Orientation, Point } from "../types/index.js"
17
+
18
+ export function useFrames(
19
+ win: Ref<LayoutWindow>,
20
+ /** Whether to show merged the moved frames while dragging. */
21
+ showDragging: Ref<boolean>,
22
+ handler: {
23
+ eventHandler: (e: KeyboardEvent, state: DragState, forceRecalculateEdges: () => void) => void
24
+ /**
25
+ * Called when the drag coordinates change (during any event). Should return true to allow the edges to be moved, or false to prevent it.
26
+ *
27
+ * Can be used to save some context/info to later apply safely during onDragApply.
28
+ */
29
+ onDragChange: DragChangeHandler
30
+ /**
31
+ * Called when drag will be applied. If dragEnd was called with apply false, it will not be called.
32
+ * Return false to not apply the regular drag end changes (i.e. return false to reset to the position before dragging).
33
+ */
34
+ onDragApply: ((state: DragState, forceRecalculateEdges: () => void) => boolean)
35
+ }
36
+ ) {
37
+ const draggingEdges = ref<Edge[]>([])
38
+
39
+ // each entry corresponds to the frames touching the corresponding dragging edge
40
+ const touchingFrames = ref<Record<string, LayoutFrame>[]>([])
41
+ const allTouchingFrames = computed(() => {
42
+ const result: Record<string, LayoutFrame> = {}
43
+ for (const entry of touchingFrames.value) {
44
+ for (const frame of Object.values(entry)) {
45
+ result[frame.id] = frame
46
+ }
47
+ }
48
+ return result
49
+ })
50
+
51
+ const touchingFramesArrays = computed(() => touchingFrames.value.map(entry => Object.values(entry)))
52
+
53
+ const isDragging = ref(false)
54
+ const dragPoint = ref<Point | undefined>()
55
+
56
+ const dragDirections = ref<Record<Orientation, Direction | undefined>>({} as any)
57
+
58
+ const draggingIntersection = ref<IntersectionEntry | undefined>(undefined)
59
+ const isDraggingFromWindowEdge = ref<boolean>(false)
60
+
61
+ const frames = computed(() =>
62
+ isDragging.value && showDragging.value
63
+ ? { ...win.value.frames, ...allTouchingFrames.value }
64
+ : win.value.frames
65
+ )
66
+
67
+ const dragHoveredFrame = computed(() => {
68
+ if (isDragging.value) {
69
+ for (const id of keys(frames.value)) {
70
+ if (isPointInFrame(frames.value[id], dragPoint.value!)) {
71
+ return frames.value[id]
72
+ }
73
+ }
74
+ }
75
+ return undefined
76
+ })
77
+
78
+ const visualEdges = ref<Edge[]>([])
79
+ const intersections = computed(() => getIntersections(visualEdges.value))
80
+ // avoid expensive calculation of edges when lots of frames are added/removed
81
+ // all at once (e.g. by clicking on some command many times in a row)
82
+ const debounceGetDraggableEdges = debounce((f: LayoutFrame[]) => {
83
+ visualEdges.value = getVisualEdges(f, { includeWindowEdges: true })
84
+ }, 50, {}) as any
85
+
86
+ watchEffect(() => {
87
+ // let request animation force recalc
88
+ if (isDragging.value) return
89
+ // otherwise use more performant debounced version
90
+ debounceGetDraggableEdges(Object.values(frames.value))
91
+ })
92
+ function forceRecalculateEdges(): void {
93
+ visualEdges.value = getVisualEdges(Object.values(frames.value), { includeWindowEdges: true })
94
+ }
95
+
96
+ const dragDirStore = new DragDirectionStore({
97
+ onUpdate: dir => dragDirections.value = dir
98
+ })
99
+
100
+ const state = computed(() => ({
101
+ dragDirections: dragDirections.value,
102
+ dragPoint: dragPoint.value,
103
+ isDragging: isDragging.value,
104
+ draggingEdges: draggingEdges.value,
105
+ draggingIntersection: draggingIntersection.value,
106
+ visualEdges: visualEdges.value,
107
+ touchingFrames: touchingFrames.value,
108
+ touchingFramesArrays: touchingFramesArrays.value,
109
+ frames: frames.value,
110
+ dragHoveredFrame: dragHoveredFrame.value,
111
+ intersections: intersections.value,
112
+ isDraggingFromWindowEdge: isDraggingFromWindowEdge.value,
113
+ win: win.value
114
+ } satisfies DragState))
115
+
116
+ let controller: AbortController
117
+
118
+ function resetState(): void {
119
+ draggingEdges.value = []
120
+ draggingIntersection.value = undefined
121
+ isDragging.value = false
122
+ dragPoint.value = undefined
123
+ touchingFrames.value = []
124
+ dragDirStore.reset()
125
+ forceRecalculateEdges()
126
+ }
127
+
128
+ function dragStart(e: PointerEvent, { edge, intersection }: { edge?: Edge, intersection?: IntersectionEntry }): void {
129
+ controller = new AbortController()
130
+ controller.signal.addEventListener("abort", () => resetState())
131
+
132
+ e.preventDefault()
133
+ window.addEventListener("pointermove", dragMove, { signal: controller.signal })
134
+ window.addEventListener("pointerup", dragEnd, { signal: controller.signal })
135
+
136
+ const point = toWindowCoord(win.value, e)
137
+ dragPoint.value = point
138
+
139
+ isDragging.value = true
140
+
141
+ draggingIntersection.value = intersection
142
+
143
+ draggingEdges.value = edge
144
+ ? [edge]
145
+ : [
146
+ ...(draggingIntersection.value?.sharedEdges.horizontal ?? []),
147
+ ...(draggingIntersection.value?.sharedEdges.vertical ?? [])
148
+ ]
149
+
150
+ dragDirStore.update(point)
151
+ isDraggingFromWindowEdge.value = draggingEdges.value.some(_ => isWindowEdge(_))
152
+
153
+ const framesArray = Object.values(win.value.frames)
154
+
155
+ touchingFrames.value = []
156
+ // all frames in touchingFrames must be clones
157
+ // BUT they must be the same clone even if they are referenced by multiple dragging edges
158
+ const clones = new Map<string, LayoutFrame>()
159
+ for (let i = 0; i < draggingEdges.value.length; i++) {
160
+ const draggingEdge = draggingEdges.value[i]
161
+ touchingFrames.value[i] = {}
162
+ for (const { frame } of findFramesTouchingEdge(draggingEdge, framesArray)) {
163
+ if (!clones.has(frame.id)) {
164
+ const clone = cloneFrame(frame)
165
+ touchingFrames.value[i][frame.id] = clone
166
+ clones.set(frame.id, clone)
167
+ } else {
168
+ touchingFrames.value[i][frame.id] = clones.get(frame.id)!
169
+ }
170
+ }
171
+ }
172
+
173
+ handler.onDragChange("start", e, state.value, forceRecalculateEdges, cancel)
174
+ }
175
+
176
+ function dragMove(e: PointerEvent): void {
177
+ e.preventDefault()
178
+ const point = toWindowCoord(win.value, e)
179
+ const didChange = dragDirStore.update(point)
180
+ dragPoint.value = point
181
+ if (!didChange) return
182
+ const allowed = handler.onDragChange("move", e, state.value, forceRecalculateEdges, cancel)
183
+
184
+ if (!allowed) return
185
+ requestAnimationFrame(() => {
186
+ for (let i = 0; i < draggingEdges.value.length; i++) {
187
+ const draggingEdge = draggingEdges.value[i]
188
+ if (draggingEdge) {
189
+ moveEdge(touchingFramesArrays.value[i], draggingEdge, point)
190
+ }
191
+ }
192
+ forceRecalculateEdges()
193
+ })
194
+ }
195
+
196
+ function dragEnd(e?: PointerEvent, { apply = true }: { apply?: boolean } = {}): void {
197
+ if (e) {
198
+ const point = toWindowCoord(win.value, e)
199
+ dragPoint.value = point
200
+ }
201
+
202
+ const doApply = apply && handler.onDragApply(state.value, forceRecalculateEdges)
203
+ if (doApply) {
204
+ for (const frame of touchingFramesArrays.value.flat()) {
205
+ win!.value.frames[frame.id] = frame
206
+ }
207
+ }
208
+
209
+ handler.onDragChange("end", e, state.value, forceRecalculateEdges, cancel)
210
+
211
+ // this can get called from elsewhere
212
+ // also takes care of cleanup
213
+ controller?.abort()
214
+ }
215
+ function cancel(): void {
216
+ dragEnd(undefined, { apply: false })
217
+ }
218
+ const keydownController = new AbortController()
219
+ const wrappedKeydownHandler = (e: KeyboardEvent): void => {
220
+ handler.eventHandler(e, state.value, forceRecalculateEdges)
221
+ }
222
+ onMounted(() => {
223
+ window.addEventListener("keydown", wrappedKeydownHandler, { signal: keydownController.signal })
224
+ window.addEventListener("keyup", wrappedKeydownHandler, { signal: keydownController.signal })
225
+ })
226
+
227
+ onBeforeUnmount(() => {
228
+ controller?.abort()
229
+ keydownController?.abort()
230
+ })
231
+
232
+ return {
233
+ dragStart,
234
+ dragEnd,
235
+ cancel,
236
+ dragDirections,
237
+ dragPoint,
238
+ isDragging,
239
+ draggingEdges,
240
+ draggingIntersection,
241
+ visualEdges,
242
+ touchingFrames,
243
+ touchingFramesArrays,
244
+ frames,
245
+ dragHoveredFrame,
246
+ intersections,
247
+ isDraggingFromWindowEdge,
248
+ forceRecalculateEdges,
249
+ state
250
+ }
251
+ }
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <WRoot class="gap-2 p-2">
3
+ <DemoControls
4
+ :frames="frames!"
5
+ />
6
+ <LayoutWindow v-if="win"
7
+ class="
8
+ flex-1 w-full
9
+ border-1
10
+ border-neutral-300
11
+ dark:border-neutral-700
12
+ rounded-md
13
+ flex-1
14
+ self-stretch
15
+ [&_.frame]:flex
16
+ [&_.frame]:flex-col
17
+ [&_.frame]:outline-hidden
18
+ [&_.active-frame-edge]:rounded-md
19
+ [&_.active-frame-edge]:border-none
20
+ [&_.drag-edge:hover+.edge]:bg-accent-500/20
21
+ [&_.grabbed-edge]:bg-accent-500
22
+ [&.request-split_.grabbed-edge]:hidden
23
+ [&.request-split_.drag-edge]:hidden
24
+ [&_.deco-split-new-frame]:rounded-md
25
+ [&_.deco-close-frame]:rounded-md
26
+ [&_.deco-close-frame]:bg-orange-500/50
27
+ "
28
+ :usage-instructions="usageInstructions"
29
+ instructions-teleport-to="#status-bar"
30
+ v-model:win="win"
31
+ @is-showing-drag="isShowingDrag = $event"
32
+ @drag-state="dragState = $event"
33
+ >
34
+ <template #[`frame-${f.id}`] v-for="f in frames" :key="f.id">
35
+ <div
36
+ :data-is-active="win.activeFrame === f.id"
37
+ :class="twMerge(`
38
+ border-2
39
+ border-neutral-500
40
+ h-full
41
+ rounded-md
42
+ overflow-auto
43
+ `,
44
+ win.activeFrame === f.id && `border-blue-500`
45
+ )"
46
+ @click="win.activeFrame=f.id"
47
+ >
48
+ <!--
49
+ Avoid placing the padding on the first div in the frame.
50
+ Set it on the first child instead, so that the frame can shrink as small as possible.
51
+ Too big a border can also be a problem, but usually it's small enough that it's beneath the min frame width/height allowed.
52
+ -->
53
+ <div class="p-2"> {{ debugFrame(f) }} </div>
54
+ </div>
55
+ </template>
56
+ </LayoutWindow>
57
+ </Wroot>
58
+ </template>
59
+ <script lang="ts" setup>
60
+ import { keys } from "@alanscodelog/utils/keys"
61
+ // playground not resolving???
62
+ // todo this breaks the non-playground build
63
+ import WRoot from "@witchcraft/ui/components/LibRoot"
64
+ import { twMerge } from "@witchcraft/ui/utils/twMerge"
65
+ import { computed, onBeforeMount, ref } from "vue"
66
+
67
+ import DemoControls from "./DemoControls.vue"
68
+ import { app } from "./sharedLayoutInstance.js"
69
+
70
+ import LayoutWindow from "../components/LayoutWindow.vue"
71
+ import type { DragState } from "../drag/types.js"
72
+ import { debugFrame } from "../layout/debugFrame.js"
73
+ import {
74
+ frameCreate,
75
+ layoutAddWindow,
76
+ windowAddFrame,
77
+ windowCreate,
78
+ } from "../layout/index.js"
79
+ import { getMaxInt } from "../settings.js"
80
+ import { type Layout, type Pos, type Size } from "../types/index.js"
81
+
82
+
83
+ const winId = ref<string | undefined>(undefined)
84
+ const win = computed(() => winId.value !== undefined ? app.layout.windows[winId.value] : undefined)
85
+
86
+ const frames = computed(() => {
87
+ if (!win.value) return
88
+ return Object.values(win.value.frames)
89
+ })
90
+ onBeforeMount(() => {
91
+ layoutInitialize(app.layout)
92
+ winId.value = keys(app.layout.windows)[0]
93
+ })
94
+
95
+ const isDragging = ref(false)
96
+ function layoutInitialize(layout: Layout, { defaultPos, defaultSize }: {
97
+ defaultPos: Pos
98
+ defaultSize: Size
99
+ } = {
100
+ defaultPos: { x: 0, y: 0 },
101
+ defaultSize: { width: 0, height: 0 },
102
+ }) {
103
+ const w = layoutAddWindow(
104
+ layout,
105
+ windowCreate({
106
+ ...defaultPos,
107
+ ...defaultSize,
108
+ frames: {},
109
+ })
110
+ )
111
+
112
+ layout.activeWindow = w.id
113
+ const max = getMaxInt()
114
+ const frame = windowAddFrame(w, frameCreate({
115
+ x: 0,
116
+ y: 0,
117
+ width: max,
118
+ height: max,
119
+ }))
120
+ w.activeFrame = frame.id
121
+ }
122
+
123
+ // whether layout window is showing the edge beneath the mouse
124
+ // as determined by the DragActionHandler in LayoutWindow
125
+ const isShowingDrag = ref(false)
126
+ // drag state as returned by useFrames in LayoutWindow
127
+ const dragState = ref<DragState | undefined>(undefined)
128
+
129
+ const usageInstructions = computed(() => ({
130
+ // names are arbitrary and don't mean anything, they just make things easier
131
+ // if a key is undefined, it's ignored
132
+ none: !dragState.value?.isDragging ? "Drag from an edge to create a new frame." : undefined,
133
+ split: dragState.value?.isDragging ? "Hold Alt to Split" : undefined,
134
+ close: dragState.value?.isDragging ? "Shift+Drag to Close" : undefined,
135
+ forceClose: dragState.value?.isDragging ? "Ctrl+Shift+Drag to Force Close" : undefined
136
+ }))
137
+
138
+ </script>
139
+
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div class="border-2 border-neutral-500 p-2 rounded-md flex">
3
+ <div class="">Instruction/status bar:</div>
4
+ <div id="status-bar" class="px-2 flex-1 overflow-x-auto scrollbar-hidden"/>
5
+ <WDarkModeSwitcher :show-label="false"/>
6
+ </div>
7
+ </template>
8
+ <script lang="ts" setup>
9
+ import WDarkModeSwitcher from "@witchcraft/ui/components/LibDarkModeSwitcher"
10
+
11
+ import type { LayoutFrame } from "../types/index.js"
12
+
13
+ defineProps<{
14
+ frames: LayoutFrame[]
15
+ }>()
16
+
17
+ </script>
@@ -0,0 +1 @@
1
+ This is structured like this so we can check the demo is both buildable from nuxt and vite.
@@ -0,0 +1,9 @@
1
+ /** @private */
2
+ import "./tailwind.css"
3
+
4
+ import { createApp } from "vue"
5
+
6
+ import App from "./App.vue"
7
+
8
+ createApp(App)
9
+ .mount("#app")
@@ -0,0 +1,7 @@
1
+ import { reactive } from "vue"
2
+
3
+ import { layoutCreate } from "../layout/layoutCreate.js"
4
+
5
+ export const app = reactive({
6
+ layout: layoutCreate()
7
+ })
@@ -0,0 +1,4 @@
1
+ @import "tailwindcss" source("../");
2
+
3
+ @import "../../../playground/.nuxt/witchcraft-ui.css";
4
+ @import "../../../playground/.nuxt/witchcraft-layout.css";