@witchcraft/layout 0.1.3 → 0.2.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.
Files changed (189) hide show
  1. package/README.md +27 -24
  2. package/dist/module.json +1 -1
  3. package/dist/runtime/components/FrameDragHandle.d.vue.ts +15 -0
  4. package/dist/runtime/components/FrameDragHandle.vue +28 -0
  5. package/dist/runtime/components/FrameDragHandle.vue.d.ts +15 -0
  6. package/dist/runtime/components/LayoutDecos.d.vue.ts +2 -4
  7. package/dist/runtime/components/LayoutDecos.vue +10 -29
  8. package/dist/runtime/components/LayoutDecos.vue.d.ts +2 -4
  9. package/dist/runtime/components/LayoutEdges.d.vue.ts +3 -3
  10. package/dist/runtime/components/LayoutEdges.vue +8 -8
  11. package/dist/runtime/components/LayoutEdges.vue.d.ts +3 -3
  12. package/dist/runtime/components/LayoutFrame.d.vue.ts +1 -1
  13. package/dist/runtime/components/LayoutFrame.vue +0 -1
  14. package/dist/runtime/components/LayoutFrame.vue.d.ts +1 -1
  15. package/dist/runtime/components/LayoutShapeSquare.d.vue.ts +3 -1
  16. package/dist/runtime/components/LayoutShapeSquare.vue.d.ts +3 -1
  17. package/dist/runtime/components/LayoutWindow.d.vue.ts +26 -12
  18. package/dist/runtime/components/LayoutWindow.vue +95 -84
  19. package/dist/runtime/components/LayoutWindow.vue.d.ts +26 -12
  20. package/dist/runtime/composables/useFrames.d.ts +15 -13
  21. package/dist/runtime/composables/useFrames.js +59 -39
  22. package/dist/runtime/demo/App.vue +116 -30
  23. package/dist/runtime/demo/DemoControls.d.vue.ts +4 -1
  24. package/dist/runtime/demo/DemoControls.vue +98 -4
  25. package/dist/runtime/demo/DemoControls.vue.d.ts +4 -1
  26. package/dist/runtime/drag/CloseAction.d.ts +26 -5
  27. package/dist/runtime/drag/CloseAction.js +87 -40
  28. package/dist/runtime/drag/DragActionHandler.d.ts +20 -8
  29. package/dist/runtime/drag/DragActionHandler.js +47 -12
  30. package/dist/runtime/drag/FrameDragAction.d.ts +45 -0
  31. package/dist/runtime/drag/FrameDragAction.js +143 -0
  32. package/dist/runtime/drag/SplitAction.d.ts +32 -11
  33. package/dist/runtime/drag/SplitAction.js +82 -24
  34. package/dist/runtime/drag/createDefaultHandlers.d.ts +9 -0
  35. package/dist/runtime/drag/createDefaultHandlers.js +10 -0
  36. package/dist/runtime/drag/defaultDragActions.d.ts +9 -0
  37. package/dist/runtime/drag/defaultDragActions.js +10 -0
  38. package/dist/runtime/drag/types.d.ts +82 -13
  39. package/dist/runtime/drag/types.js +1 -0
  40. package/dist/runtime/helpers/createZoneSideClipPath.d.ts +12 -0
  41. package/dist/runtime/helpers/createZoneSideClipPath.js +17 -0
  42. package/dist/runtime/helpers/doEdgesOverlap.d.ts +3 -1
  43. package/dist/runtime/helpers/doEdgesOverlap.js +5 -5
  44. package/dist/runtime/helpers/getDockBoundaries.d.ts +19 -0
  45. package/dist/runtime/helpers/getDockBoundaries.js +14 -0
  46. package/dist/runtime/helpers/getEdgeLength.d.ts +2 -0
  47. package/dist/runtime/helpers/getEdgeLength.js +5 -0
  48. package/dist/runtime/helpers/getIntersections.js +2 -2
  49. package/dist/runtime/helpers/getIntersectionsCss.js +2 -2
  50. package/dist/runtime/helpers/getMoveEdgeInfo.js +2 -2
  51. package/dist/runtime/helpers/getResizeLimit.js +2 -2
  52. package/dist/runtime/helpers/getShapeSquareCss.js +2 -2
  53. package/dist/runtime/helpers/getVisualEdgeCss.js +2 -2
  54. package/dist/runtime/helpers/getVisualEdges.d.ts +1 -1
  55. package/dist/runtime/helpers/getVisualEdges.js +4 -3
  56. package/dist/runtime/helpers/index.d.ts +4 -0
  57. package/dist/runtime/helpers/index.js +4 -0
  58. package/dist/runtime/helpers/isEdgeEqual.js +2 -4
  59. package/dist/runtime/helpers/isWindowEdge.js +2 -2
  60. package/dist/runtime/helpers/isWindowEdgePoint.js +2 -2
  61. package/dist/runtime/helpers/moveEdge.js +2 -2
  62. package/dist/runtime/helpers/numberToScaledPercent.d.ts +1 -1
  63. package/dist/runtime/helpers/numberToScaledPercent.js +2 -2
  64. package/dist/runtime/helpers/numberToScaledSize.js +2 -2
  65. package/dist/runtime/helpers/rotateFrames.d.ts +7 -0
  66. package/dist/runtime/helpers/rotateFrames.js +36 -0
  67. package/dist/runtime/helpers/scaledPointToPx.d.ts +13 -0
  68. package/dist/runtime/helpers/scaledPointToPx.js +7 -0
  69. package/dist/runtime/helpers/toWindowCoord.js +2 -2
  70. package/dist/runtime/layout/applyFrameChanges.d.ts +10 -0
  71. package/dist/runtime/layout/applyFrameChanges.js +29 -0
  72. package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +6 -1
  73. package/dist/runtime/layout/createSplitDecoFromDrag.js +4 -4
  74. package/dist/runtime/layout/createSplitDecoShapes.d.ts +7 -0
  75. package/dist/runtime/layout/{createSplitDecoEdge.js → createSplitDecoShapes.js} +6 -3
  76. package/dist/runtime/layout/debugFrame.js +2 -1
  77. package/dist/runtime/layout/findSafeSplitEdge.js +2 -2
  78. package/dist/runtime/layout/frameCreate.js +2 -2
  79. package/dist/runtime/layout/getCloseFrameInfo.d.ts +7 -6
  80. package/dist/runtime/layout/getCloseFrameInfo.js +10 -3
  81. package/dist/runtime/layout/getDragZones.d.ts +8 -0
  82. package/dist/runtime/layout/getDragZones.js +32 -0
  83. package/dist/runtime/layout/getFillEmptySpaceInfo.d.ts +65 -0
  84. package/dist/runtime/layout/getFillEmptySpaceInfo.js +69 -0
  85. package/dist/runtime/layout/getFrameCollapseInfo.d.ts +13 -0
  86. package/dist/runtime/layout/getFrameCollapseInfo.js +93 -0
  87. package/dist/runtime/layout/getFrameDockInfo.d.ts +9 -0
  88. package/dist/runtime/layout/getFrameDockInfo.js +82 -0
  89. package/dist/runtime/layout/getFrameDragZones.d.ts +16 -0
  90. package/dist/runtime/layout/getFrameDragZones.js +74 -0
  91. package/dist/runtime/layout/getFrameRearrangeInfo.d.ts +139 -0
  92. package/dist/runtime/layout/getFrameRearrangeInfo.js +87 -0
  93. package/dist/runtime/layout/getFrameSplitInfo.d.ts +7 -5
  94. package/dist/runtime/layout/getFrameSplitInfo.js +10 -3
  95. package/dist/runtime/layout/getFrameSwapInfo.d.ts +9 -0
  96. package/dist/runtime/layout/getFrameSwapInfo.js +27 -0
  97. package/dist/runtime/layout/getFrameTo.js +2 -2
  98. package/dist/runtime/layout/getFrameUncollapseInfo.d.ts +12 -0
  99. package/dist/runtime/layout/getFrameUncollapseInfo.js +88 -0
  100. package/dist/runtime/layout/getFrameUndockInfo.d.ts +13 -0
  101. package/dist/runtime/layout/getFrameUndockInfo.js +51 -0
  102. package/dist/runtime/layout/getFramesRedistributeInfo.d.ts +29 -0
  103. package/dist/runtime/layout/getFramesRedistributeInfo.js +53 -0
  104. package/dist/runtime/layout/getWindowDragZones.d.ts +6 -0
  105. package/dist/runtime/layout/getWindowDragZones.js +49 -0
  106. package/dist/runtime/layout/index.d.ts +14 -5
  107. package/dist/runtime/layout/index.js +14 -5
  108. package/dist/runtime/layout/isPointInRect.d.ts +7 -0
  109. package/dist/runtime/layout/{isPointInFrame.js → isPointInRect.js} +1 -1
  110. package/dist/runtime/layout/resizeFrame.js +2 -2
  111. package/dist/runtime/settings.d.ts +41 -16
  112. package/dist/runtime/settings.js +95 -53
  113. package/dist/runtime/types/index.d.ts +324 -54
  114. package/dist/runtime/types/index.js +54 -20
  115. package/package.json +28 -29
  116. package/src/runtime/components/FrameDragHandle.vue +30 -0
  117. package/src/runtime/components/LayoutDecos.vue +12 -36
  118. package/src/runtime/components/LayoutEdges.vue +27 -23
  119. package/src/runtime/components/LayoutFrame.vue +6 -5
  120. package/src/runtime/components/LayoutShapeSquare.vue +9 -3
  121. package/src/runtime/components/LayoutWindow.vue +110 -101
  122. package/src/runtime/composables/useFrames.ts +80 -50
  123. package/src/runtime/demo/App.vue +126 -36
  124. package/src/runtime/demo/DemoControls.vue +115 -6
  125. package/src/runtime/drag/CloseAction.ts +106 -44
  126. package/src/runtime/drag/DragActionHandler.ts +71 -20
  127. package/src/runtime/drag/FrameDragAction.ts +202 -0
  128. package/src/runtime/drag/SplitAction.ts +106 -34
  129. package/src/runtime/drag/createDefaultHandlers.ts +19 -0
  130. package/src/runtime/drag/defaultDragActions.ts +19 -0
  131. package/src/runtime/drag/types.ts +90 -20
  132. package/src/runtime/helpers/createZoneSideClipPath.ts +41 -0
  133. package/src/runtime/helpers/doEdgesOverlap.ts +11 -5
  134. package/src/runtime/helpers/getDockBoundaries.ts +36 -0
  135. package/src/runtime/helpers/getEdgeLength.ts +10 -0
  136. package/src/runtime/helpers/getIntersections.ts +2 -2
  137. package/src/runtime/helpers/getIntersectionsCss.ts +2 -2
  138. package/src/runtime/helpers/getMoveEdgeInfo.ts +2 -2
  139. package/src/runtime/helpers/getResizeLimit.ts +2 -2
  140. package/src/runtime/helpers/getShapeSquareCss.ts +2 -2
  141. package/src/runtime/helpers/getVisualEdgeCss.ts +2 -2
  142. package/src/runtime/helpers/getVisualEdges.ts +5 -4
  143. package/src/runtime/helpers/index.ts +4 -0
  144. package/src/runtime/helpers/isEdgeEqual.ts +2 -4
  145. package/src/runtime/helpers/isWindowEdge.ts +2 -2
  146. package/src/runtime/helpers/isWindowEdgePoint.ts +2 -2
  147. package/src/runtime/helpers/moveEdge.ts +2 -2
  148. package/src/runtime/helpers/numberToScaledPercent.ts +3 -3
  149. package/src/runtime/helpers/numberToScaledSize.ts +2 -2
  150. package/src/runtime/helpers/rotateFrames.ts +45 -0
  151. package/src/runtime/helpers/scaledPointToPx.ts +13 -0
  152. package/src/runtime/helpers/toWindowCoord.ts +2 -2
  153. package/src/runtime/layout/applyFrameChanges.ts +39 -0
  154. package/src/runtime/layout/createSplitDecoFromDrag.ts +12 -6
  155. package/src/runtime/layout/{createSplitDecoEdge.ts → createSplitDecoShapes.ts} +17 -7
  156. package/src/runtime/layout/debugFrame.ts +1 -1
  157. package/src/runtime/layout/findSafeSplitEdge.ts +3 -3
  158. package/src/runtime/layout/frameCreate.ts +2 -2
  159. package/src/runtime/layout/getCloseFrameInfo.ts +21 -8
  160. package/src/runtime/layout/getDragZones.ts +48 -0
  161. package/src/runtime/layout/getFillEmptySpaceInfo.ts +177 -0
  162. package/src/runtime/layout/getFrameCollapseInfo.ts +164 -0
  163. package/src/runtime/layout/getFrameDockInfo.ts +126 -0
  164. package/src/runtime/layout/getFrameDragZones.ts +100 -0
  165. package/src/runtime/layout/getFrameRearrangeInfo.ts +261 -0
  166. package/src/runtime/layout/getFrameSplitInfo.ts +21 -8
  167. package/src/runtime/layout/getFrameSwapInfo.ts +45 -0
  168. package/src/runtime/layout/getFrameTo.ts +2 -2
  169. package/src/runtime/layout/getFrameUncollapseInfo.ts +160 -0
  170. package/src/runtime/layout/getFrameUndockInfo.ts +97 -0
  171. package/src/runtime/layout/getFramesRedistributeInfo.ts +98 -0
  172. package/src/runtime/layout/getWindowDragZones.ts +59 -0
  173. package/src/runtime/layout/index.ts +14 -5
  174. package/src/runtime/layout/isPointInRect.ts +7 -0
  175. package/src/runtime/layout/resizeFrame.ts +2 -2
  176. package/src/runtime/settings.ts +69 -49
  177. package/src/runtime/types/index.ts +143 -28
  178. package/dist/runtime/layout/closeFrame.d.ts +0 -5
  179. package/dist/runtime/layout/closeFrame.js +0 -13
  180. package/dist/runtime/layout/closeFrames.d.ts +0 -2
  181. package/dist/runtime/layout/closeFrames.js +0 -8
  182. package/dist/runtime/layout/createSplitDecoEdge.d.ts +0 -2
  183. package/dist/runtime/layout/frameSplit.d.ts +0 -16
  184. package/dist/runtime/layout/frameSplit.js +0 -9
  185. package/dist/runtime/layout/isPointInFrame.d.ts +0 -2
  186. package/src/runtime/layout/closeFrame.ts +0 -33
  187. package/src/runtime/layout/closeFrames.ts +0 -14
  188. package/src/runtime/layout/frameSplit.ts +0 -31
  189. package/src/runtime/layout/isPointInFrame.ts +0 -7
@@ -4,9 +4,7 @@ import { z } from "zod"
4
4
 
5
5
  export * from "../drag/types.js"
6
6
 
7
- import type { HTMLAttributes } from "vue"
8
-
9
- import { getMaxInt } from "../settings.js"
7
+ import { settings } from "../settings.js"
10
8
 
11
9
  export const zUuid = z.uuid()
12
10
  export type AnyUuid = z.infer<typeof zUuid>
@@ -22,7 +20,7 @@ export type FrameId = z.infer<typeof zFrameId>
22
20
  export const zScaledIntPercentage = z.number()
23
21
  .int()
24
22
  .min(0)
25
- .max(getMaxInt())
23
+ .max(settings.maxInt)
26
24
  .nonnegative()
27
25
 
28
26
  const zPx = z.number()
@@ -111,9 +109,13 @@ export type IntersectionEntry = {
111
109
  sharedEdges: { horizontal: Edge[], vertical: Edge[] }
112
110
  isWindowEdge: boolean
113
111
  }
114
- export const zLayoutFrame = z.looseObject({
115
- id: z.uuid()
116
- }).extend(zBaseSquare.shape)
112
+
113
+
114
+ export const zLayoutFrame = zBaseSquare.extend({
115
+ id: z.uuid(),
116
+ docked: zSide.optional(),
117
+ collapsed: z.union([z.literal(false), z.number()]).optional()
118
+ }).loose()
117
119
 
118
120
  export const zLayoutFrameLoose = zLayoutFrame.loose()
119
121
 
@@ -126,7 +128,11 @@ export type ExtendedLayout = Register extends { ExtendedLayout: infer T } ? T :
126
128
  export type ExtendedWorkspace = Register extends { ExtendedWorkspace: infer T } ? T : unknown
127
129
  /* eslint-enable @typescript-eslint/naming-convention */
128
130
 
129
- export type BaseLayoutFrame = Size & Pos & { id: FrameId }
131
+ export type BaseLayoutFrame = Size & Pos & {
132
+ id: FrameId
133
+ docked?: EdgeSide | false
134
+ collapsed?: false | number
135
+ }
130
136
  export type LayoutFrame = ExtendedLayoutFrame & BaseLayoutFrame
131
137
  export type LayoutFrames = Record<string, LayoutFrame>
132
138
 
@@ -153,7 +159,24 @@ export type BaseLayoutWindow = {
153
159
  export type LayoutWindow = ExtendedLayoutWindow & BaseLayoutWindow
154
160
  export type LayoutWindows = Record<string, LayoutWindow>
155
161
 
156
- const baseWorkspace = zLayoutWindow.pick({ activeFrame: true, frames: true })
162
+ const baseWorkspace = baseLayoutWindow.pick({ activeFrame: true, frames: true }).superRefine((data, ctx) => {
163
+ for (const [frameId, frame] of Object.entries(data.frames ?? {})) {
164
+ if ((frame as any).docked === undefined) continue
165
+ const edge = (frame as any).docked
166
+ if (edge === "left" && (frame as any).x !== 0) {
167
+ ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on left edge must have x=0`, path: ["frames", frameId, "x"] })
168
+ }
169
+ if (edge === "right" && (frame as any).x + (frame as any).width !== settings.maxInt) {
170
+ ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on right edge must have x+width=maxInt`, path: ["frames", frameId, "x"] })
171
+ }
172
+ if (edge === "top" && (frame as any).y !== 0) {
173
+ ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on top edge must have y=0`, path: ["frames", frameId, "y"] })
174
+ }
175
+ if (edge === "bottom" && (frame as any).y + (frame as any).height !== settings.maxInt) {
176
+ ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on bottom edge must have y+height=maxInt`, path: ["frames", frameId, "y"] })
177
+ }
178
+ }
179
+ })
157
180
  export const zWorkspace = baseWorkspace.strict()
158
181
  export const zWorkspaceLoose = zWorkspace.loose()
159
182
 
@@ -180,43 +203,49 @@ export type Layout = ExtendedLayout & {
180
203
  activeWindow?: string
181
204
  windows: LayoutWindows
182
205
  }
206
+ const zLayoutShape = z.discriminatedUnion("type", [
207
+ z.object({ type: z.literal("square"), data: zBaseSquare, attrs: z.record(z.string(), z.string()).optional() }),
208
+ z.object({ type: z.literal("edge"), data: zEdge, attrs: z.record(z.string(), z.string()).optional() })
209
+ ])
183
210
 
184
- export const zSplitDecoShapes = z.object({
185
- edge: zEdge,
186
- newFrame: zBaseSquare
187
- }).strict()
211
+ export type LayoutShape = z.infer<typeof zLayoutShape>
188
212
 
189
- export type SplitDecoShapes = z.infer<typeof zSplitDecoShapes>
190
- export const zSplitDeco = z.object({
213
+ const zBaseDeco = z.object({
214
+ shapes: z.array(zLayoutShape).default([])
215
+ })
216
+
217
+ export type BaseDeco = z.infer<typeof zBaseDeco>
218
+
219
+ export const zSplitDeco = zBaseDeco.extend({
191
220
  id: z.uuid(),
192
221
  type: z.literal("split"),
193
222
  position: zScaledIntPercentage,
194
- direction: zDirection,
195
- shapes: zSplitDecoShapes
196
- }).strict()
223
+ direction: zDirection
224
+ })
197
225
  export const zRawSplitDeco = zSplitDeco.omit({ shapes: true })
198
226
  export type RawSplitDeco = z.infer<typeof zRawSplitDeco>
199
227
  export type SplitDeco = z.infer<typeof zSplitDeco>
200
228
 
201
- const zCloseDeco = z.object({
229
+ const zCloseDeco = zBaseDeco.extend({
202
230
  id: z.uuid(),
203
231
  type: z.literal("close"),
204
232
  force: z.boolean().optional()
205
- }).strict()
233
+ })
206
234
  export type CloseDeco = z.infer<typeof zCloseDeco>
207
235
 
208
- const zDropDeco = z.object({
236
+
237
+ const zFrameDragDeco = zBaseDeco.extend({
209
238
  id: z.uuid(),
210
239
  type: z.literal("drop"),
211
240
  position: zSide.or(z.enum(["center"]))
212
- }).strict()
241
+ })
213
242
 
214
- export type DropDeco = z.infer<typeof zDropDeco>
243
+ export type FrameDragDeco = z.infer<typeof zFrameDragDeco>
215
244
 
216
245
  export const zDeco = z.union([
217
246
  zSplitDeco,
218
247
  zCloseDeco,
219
- zDropDeco
248
+ zFrameDragDeco
220
249
  ])
221
250
 
222
251
  export type Deco = z.infer<typeof zDeco>
@@ -231,7 +260,20 @@ export const LAYOUT_ERROR = enumFromArray([
231
260
  "CANT_CLOSE_NEARBY_FRAMES_TOO_SMALL",
232
261
  "CANT_CLOSE_SINGLE_FRAME",
233
262
  "CANT_SPLIT_FRAME_TOO_SMALL",
234
- "CANT_CLOSE_WITHOUT_FORCE"
263
+ "CANT_CLOSE_WITHOUT_FORCE",
264
+ "CANT_SWAP_WITH_SELF",
265
+ "CANT_REARRANGE_TO_SAME_RELATIVE_POSITION",
266
+ "CANT_REARRANGE_WITH_DOCKED_EDGES",
267
+ "CANT_REARRANGE_DOCKED_WITH_NON_DOCKED",
268
+ "CANT_SPLIT_DOCKED_FRAME",
269
+ "NO_SPACE_TO_REDISTRIBUTE",
270
+ "REDISTRIBUTE_OUT_OF_BOUNDS",
271
+ "FRAME_ALREADY_DOCKED_ON_SIDE",
272
+ "CANT_LEAVE_NO_UNDOCKED_FRAMES",
273
+ "CANT_UNDOCK_COLLAPSED_FRAME",
274
+ "CANT_COLLAPSE_NOT_DOCKED",
275
+ "CANT_UNCOLLAPSE_NOT_COLLAPSED",
276
+ "NO_FILL_CANDIDATES"
235
277
  ])
236
278
 
237
279
  export type LayoutError = EnumLike<typeof LAYOUT_ERROR>
@@ -270,11 +312,80 @@ export type LayoutErrorsInfo = {
270
312
  frame: LayoutFrame
271
313
  framesRequiredToBeDeleted: LayoutFrame[]
272
314
  }
315
+ [LAYOUT_ERROR.CANT_SWAP_WITH_SELF]: {
316
+ frame: LayoutFrame
317
+ }
318
+ [LAYOUT_ERROR.CANT_REARRANGE_TO_SAME_RELATIVE_POSITION]: {
319
+ draggingFrameId: string
320
+ hoveredFrameId: string
321
+ zoneSide: DragZone["side"]
322
+ }
323
+ [LAYOUT_ERROR.CANT_REARRANGE_WITH_DOCKED_EDGES]: {
324
+ draggingFrameId: string
325
+ hoveredFrameId: string
326
+ zoneSide: DragZone["side"]
327
+ }
328
+ [LAYOUT_ERROR.CANT_REARRANGE_DOCKED_WITH_NON_DOCKED]: {
329
+ draggingFrameId: string
330
+ hoveredFrameId: string
331
+ zoneSide: DragZone["side"]
332
+ }
333
+ [LAYOUT_ERROR.CANT_SPLIT_DOCKED_FRAME]: {
334
+ frame: LayoutFrame
335
+ }
336
+ [LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE]: {
337
+ minFrameSize: number
338
+ frameSizeNeeded: number
339
+ }
340
+ [LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS]: {
341
+ min: number
342
+ max: number
343
+ wanted: number
344
+ }
345
+ [LAYOUT_ERROR.FRAME_ALREADY_DOCKED_ON_SIDE]: {
346
+ side: EdgeSide
347
+ id: string
348
+ }
349
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
350
+ [LAYOUT_ERROR.CANT_LEAVE_NO_UNDOCKED_FRAMES]: {}
351
+ [LAYOUT_ERROR.CANT_UNDOCK_COLLAPSED_FRAME]: {
352
+ frame: string
353
+ }
354
+ [LAYOUT_ERROR.CANT_COLLAPSE_NOT_DOCKED]: {
355
+ frame: LayoutFrame
356
+ }
357
+ [LAYOUT_ERROR.CANT_UNCOLLAPSE_NOT_COLLAPSED]: {
358
+ frame: LayoutFrame
359
+ }
360
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
361
+ [LAYOUT_ERROR.NO_FILL_CANDIDATES]: {}
273
362
  }
274
363
 
275
364
  // todo rename to toOpposite
276
365
  export type HasOpposite = Direction | EdgeSide | ExtendedDirection | ExtendedEdgeSide | keyof Point | keyof Size
277
366
 
367
+
368
+ export type BaseDragZone = {
369
+ x: number
370
+ y: number
371
+ width: number
372
+ height: number
373
+ pxWidth: number
374
+ pxHeight: number
375
+ }
376
+
377
+ export type FrameDragZone = BaseDragZone & {
378
+ type: "frame"
379
+ side: EdgeSide | "center"
380
+ }
381
+
382
+ export type WindowEdgeZone = BaseDragZone & {
383
+ type: "window"
384
+ side: EdgeSide
385
+ }
386
+
387
+ export type DragZone = FrameDragZone | WindowEdgeZone
388
+
278
389
  export const zWindowCreate = zLayoutWindowLoose
279
390
  .partial({ id: true, pxWidth: true, pxHeight: true, pxX: true, pxY: true })
280
391
  .extend({ frames: zLayoutWindow.shape.frames.optional() })
@@ -297,9 +408,6 @@ export type LayoutShapeSquareProps
297
408
  = & {
298
409
  css: BaseSquareCss
299
410
  }
300
- & /** @vue-ignore */ Omit<HTMLAttributes, "class" | "onFocus">
301
- & /** @vue-ignore */ { class?: string }
302
-
303
411
 
304
412
  export type LayoutEdgesProps
305
413
  = & {
@@ -315,6 +423,13 @@ export type LayoutEdgesProps
315
423
  & Partial<LayoutShapeSquareProps>
316
424
 
317
425
 
426
+ export type LayoutChange<TInfo = never> = {
427
+ modified: LayoutFrame[]
428
+ created: LayoutFrame[]
429
+ deleted: LayoutFrame[]
430
+ info?: TInfo
431
+ }
432
+
318
433
  export type LayoutFrameProps
319
434
  = & {
320
435
  frame: LayoutFrame
@@ -1,5 +0,0 @@
1
- import type { Direction, Edge, EdgeSide, LAYOUT_ERROR, LayoutFrame, LayoutWindow, Size } from "../types/index.js";
2
- import type { KnownError } from "../utils/KnownError.js";
3
- export declare function closeFrame<T extends "edge" | "dir">(win: LayoutWindow, visualEdges: Edge[], frame: LayoutFrame,
4
- /** See {@link getCloseFrameInfo} */
5
- closeDirOrSide: (T extends "dir" ? Direction : EdgeSide), closeBy?: T, force?: boolean, minSize?: Size): LayoutFrame[] | KnownError<typeof LAYOUT_ERROR.CANT_CLOSE_NEARBY_FRAMES_TOO_SMALL | typeof LAYOUT_ERROR.CANT_CLOSE_NO_DRAG_EDGE | typeof LAYOUT_ERROR.CANT_CLOSE_SINGLE_FRAME | typeof LAYOUT_ERROR.CANT_CLOSE_WITHOUT_FORCE>;
@@ -1,13 +0,0 @@
1
- import { closeFrames } from "./closeFrames.js";
2
- import { getCloseFrameInfo } from "./getCloseFrameInfo.js";
3
- import { getMarginSize } from "../settings.js";
4
- export function closeFrame(win, visualEdges, frame, closeDirOrSide, closeBy = "dir", force = false, minSize = getMarginSize()) {
5
- const canClose = getCloseFrameInfo(Object.values(win.frames), visualEdges, frame, closeDirOrSide, closeBy, force, minSize);
6
- if (canClose instanceof Error) {
7
- return canClose;
8
- }
9
- const { deletedFrames, modifiedFrames } = canClose;
10
- closeFrames(win, deletedFrames, modifiedFrames);
11
- win.activeFrame = modifiedFrames[0].id;
12
- return deletedFrames;
13
- }
@@ -1,2 +0,0 @@
1
- import type { LayoutFrame, LayoutWindow } from "../types/index.js";
2
- export declare function closeFrames(win: LayoutWindow, deletedFrames: LayoutFrame[], modifiedFrames: LayoutFrame[]): void;
@@ -1,8 +0,0 @@
1
- export function closeFrames(win, deletedFrames, modifiedFrames) {
2
- for (const f of deletedFrames) {
3
- delete win.frames[f.id];
4
- }
5
- for (const mod of modifiedFrames) {
6
- win.frames[mod.id] = mod;
7
- }
8
- }
@@ -1,2 +0,0 @@
1
- import type { LayoutFrame, Point, RawSplitDeco, Size, SplitDecoShapes } from "../types/index.js";
2
- export declare function createSplitDecoEdge(frames: Record<string, LayoutFrame>, deco: RawSplitDeco, snapAmount?: Point, minSize?: Size): SplitDecoShapes;
@@ -1,16 +0,0 @@
1
- import type { LayoutFrame, LayoutWindow } from "../types/index.js";
2
- /**
3
- * Apply a frame split. See {@link getFrameSplitInfo}
4
- * ```ts
5
- * // undefined if we can't split
6
- * const splitInfo = getFrameSplitInfo()
7
- * if (splitInfo) {
8
- * frameSplit(win, splitInfo)
9
- *
10
- * }
11
- * ```
12
- */
13
- export declare function frameSplit(win: LayoutWindow, { splitFrame, newFrame }: {
14
- splitFrame: LayoutFrame;
15
- newFrame: LayoutFrame;
16
- }): LayoutFrame | undefined;
@@ -1,9 +0,0 @@
1
- import { keys } from "@alanscodelog/utils/keys";
2
- export function frameSplit(win, { splitFrame, newFrame }) {
3
- const winFrame = win.frames[splitFrame.id];
4
- for (const key of keys(splitFrame)) {
5
- winFrame[key] = splitFrame[key];
6
- }
7
- win.frames[newFrame.id] = newFrame;
8
- return newFrame;
9
- }
@@ -1,2 +0,0 @@
1
- import type { LayoutFrame, Point } from "../types/index.js";
2
- export declare function isPointInFrame(frame: LayoutFrame, point: Point): boolean;
@@ -1,33 +0,0 @@
1
- import { closeFrames } from "./closeFrames.js"
2
- import { getCloseFrameInfo } from "./getCloseFrameInfo.js"
3
-
4
- import { getMarginSize } from "../settings.js"
5
- import type { Direction, Edge, EdgeSide, LAYOUT_ERROR, LayoutFrame, LayoutWindow, Size } from "../types/index.js"
6
- import type { KnownError } from "../utils/KnownError.js"
7
-
8
- export function closeFrame<T extends "edge" | "dir">(
9
- win: LayoutWindow,
10
- visualEdges: Edge[],
11
- frame: LayoutFrame,
12
- /** See {@link getCloseFrameInfo} */
13
- // future, support multiple dirs? return aggregate error?
14
- closeDirOrSide: (T extends "dir" ? Direction : EdgeSide),
15
- closeBy: T = "dir" as any as T,
16
- force: boolean = false,
17
- minSize: Size = getMarginSize()
18
- ): LayoutFrame[]
19
- | KnownError<
20
- | typeof LAYOUT_ERROR.CANT_CLOSE_NEARBY_FRAMES_TOO_SMALL
21
- | typeof LAYOUT_ERROR.CANT_CLOSE_NO_DRAG_EDGE
22
- | typeof LAYOUT_ERROR.CANT_CLOSE_SINGLE_FRAME
23
- | typeof LAYOUT_ERROR.CANT_CLOSE_WITHOUT_FORCE
24
- > {
25
- const canClose = getCloseFrameInfo(Object.values(win.frames), visualEdges, frame, closeDirOrSide, closeBy, force, minSize)
26
- if ((canClose instanceof Error)) {
27
- return canClose
28
- }
29
- const { deletedFrames, modifiedFrames } = canClose
30
- closeFrames(win, deletedFrames, modifiedFrames)
31
- win.activeFrame = modifiedFrames[0].id
32
- return deletedFrames
33
- }
@@ -1,14 +0,0 @@
1
- import type { LayoutFrame, LayoutWindow } from "../types/index.js"
2
-
3
- export function closeFrames(
4
- win: LayoutWindow,
5
- deletedFrames: LayoutFrame[],
6
- modifiedFrames: LayoutFrame[]
7
- ): void {
8
- for (const f of deletedFrames) {
9
- delete win.frames[f.id]
10
- }
11
- for (const mod of modifiedFrames) {
12
- win.frames[mod.id] = mod
13
- }
14
- }
@@ -1,31 +0,0 @@
1
- import { keys } from "@alanscodelog/utils/keys"
2
-
3
- import type { LayoutFrame, LayoutWindow } from "../types/index.js"
4
-
5
- /**
6
- * Apply a frame split. See {@link getFrameSplitInfo}
7
- * ```ts
8
- * // undefined if we can't split
9
- * const splitInfo = getFrameSplitInfo()
10
- * if (splitInfo) {
11
- * frameSplit(win, splitInfo)
12
- *
13
- * }
14
- * ```
15
- */
16
-
17
- export function frameSplit(
18
- win: LayoutWindow,
19
- { splitFrame, newFrame }: {
20
- splitFrame: LayoutFrame
21
- newFrame: LayoutFrame
22
- }
23
- ): LayoutFrame | undefined {
24
- const winFrame = win.frames[splitFrame.id]
25
- for (const key of keys(splitFrame)) {
26
- // @ts-expect-error wut
27
- winFrame[key] = splitFrame[key]
28
- }
29
- win.frames[newFrame.id] = newFrame
30
- return newFrame
31
- }
@@ -1,7 +0,0 @@
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
- }