@witchcraft/layout 0.1.3 → 0.2.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 (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
@@ -1,57 +1,88 @@
1
1
  <template>
2
2
  <!-- overflow hidden is because the borders inside will make it overflow -->
3
- <div :class="twMerge(
4
- `window
5
- relative
6
- overflow-hidden
7
- `,
3
+ <div
4
+ :class="twMerge(
5
+ `
6
+ layout-wrapper
7
+ flex
8
+ flex-col
9
+ `,
8
10
  isDragging && `dragging cursor-pointer`,
9
11
  requestType && `request-${requestType}`,
10
12
  $attrs.class
11
13
  )"
12
- ref="windowEl"
13
14
  v-bind="{ ...$attrs, class: void 0 }"
14
15
  >
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="frameProps"
21
- @focus="windowSetActiveFrame(win, frame.id)"
16
+ <!-- we need the size withot borders for correct px calculations -->
17
+ <div class="
18
+ layout-window
19
+ relative
20
+ overflow-hidden
21
+ flex-1
22
+ " ref="windowEl">
23
+ <template v-if="windowEl && win">
24
+ <LayoutFrameComponent
25
+ :frame="frame"
26
+ :is-active-frame="frame.id === win.activeFrame"
27
+ v-for="frame of frames"
28
+ :key="frame.id"
29
+ v-bind="frameProps"
30
+ @focus="windowSetActiveFrame(win, frame.id)"
31
+ >
32
+ <slot :name="`frame-${frame.id}`" v-bind="{ frame }"/>
33
+ </LayoutFrameComponent>
34
+ <LayoutEdgesComponent
35
+ :win="win"
36
+ :active-frame="win.activeFrame ? frames[win.activeFrame] : void 0"
37
+ :edges="visualEdges"
38
+ :intersections="intersections"
39
+ :dragging-edge="draggingEdges.length === 1 ? draggingEdges[0] : void 0"
40
+ :dragging-intersection="draggingIntersection"
41
+ v-bind="edgesProps"
42
+ @drag-start="dragStart"
43
+ />
44
+ <LayoutDecosComponent
45
+ :shapes="shapes"
46
+ />
47
+ <slot name="extra-decos"/>
48
+ </template>
49
+ </div>
50
+ <Teleport
51
+ v-if="isDragging === 'frame' && frameDragFrameId && dragPoint"
52
+ :to="ghostTeleportTo"
53
+ defer
54
+ >
55
+ <div
56
+ class="fixed z-[9999] pointer-events-none"
57
+ :style="{
58
+ left: dragPoint.x / settings.maxInt * win.pxWidth + win.pxX + 'px',
59
+ top: dragPoint.y / settings.maxInt * win.pxHeight + win.pxY + 'px',
60
+ width: frames[frameDragFrameId] ? frames[frameDragFrameId].width / settings.maxInt * win.pxWidth + 'px' : void 0,
61
+ height: frames[frameDragFrameId] ? frames[frameDragFrameId].height / settings.maxInt * win.pxHeight + 'px' : void 0
62
+ }"
22
63
  >
23
- <slot :name="`frame-${frame.id}`" v-bind="{ frame }"/>
24
- </LayoutFrameComponent>
25
- <LayoutEdgesComponent
26
- :win="win"
27
- :active-frame="win.activeFrame ? frames[win.activeFrame] : void 0"
28
- :edges="visualEdges"
29
- :intersections="intersections"
30
- :dragging-edge="draggingEdges.length === 1 ? draggingEdges[0] : void 0"
31
- :dragging-intersection="draggingIntersection"
32
- v-bind="edgesProps"
33
- @drag-start="dragStart"
34
- />
35
- <LayoutDecosComponent
36
- :frames="frames"
37
- :split-decos="splitDecos"
38
- :close-decos="closeDecos"
39
- />
40
- <slot name="extra-decos"/>
41
- </template>
42
- <Teleport v-if="instructionsTeleportTo && filteredUsageInstructions.length > 0" defer :to="instructionsTeleportTo">
64
+ <slot
65
+ :id="frameDragFrameId"
66
+ :name="`frame-drag-ghost`"
67
+ >
68
+ <div class="frame-drag-ghost border border-neutral-500 bg-white/50 w-10 h-10"/>
69
+ </slot>
70
+ </div>
71
+ </Teleport>
72
+ <Teleport v-if="textHintsTeleportTo && textHints.length > 0" :to="textHintsTeleportTo" defer>
43
73
  <span aria-live="polite">
44
74
  <span
45
- class="
46
- after:content-['┃']
75
+ :class="twMerge(`
76
+ text-hint
77
+ after:content-['\u2503']
47
78
  last:after:content-none
48
79
  after:mx-1
49
- after:text-gray-500
50
- "
51
- v-for="instruction of filteredUsageInstructions"
52
- :key="instruction"
80
+ after:text-neutral-500
81
+ `, instruction.classes)"
82
+ v-for="instruction of textHints"
83
+ :key="instruction.text"
53
84
  >
54
- {{ instruction }}
85
+ {{ instruction.text }}
55
86
  </span>
56
87
  </span>
57
88
  </Teleport>
@@ -61,62 +92,34 @@
61
92
  <script setup>
62
93
  import { useGlobalResizeObserver } from "@witchcraft/ui/composables/useGlobalResizeObserver";
63
94
  import { twMerge } from "@witchcraft/ui/utils/twMerge";
64
- import { computed, ref, useAttrs, watch } from "vue";
65
- import {} from "vue";
95
+ import { computed, provide, reactive, ref, useAttrs, watch } from "vue";
66
96
  import LayoutDecosComponent from "./LayoutDecos.vue";
67
97
  import LayoutEdgesComponent from "./LayoutEdges.vue";
68
98
  import LayoutFrameComponent from "./LayoutFrame.vue";
69
99
  import { useFrames } from "../composables/useFrames.js";
70
- import { CloseAction } from "../drag/CloseAction";
100
+ import { createDefaultHandlers } from "../drag/createDefaultHandlers.js";
71
101
  import { DragActionHandler } from "../drag/DragActionHandler";
72
- import { SplitAction } from "../drag/SplitAction.js";
73
- import {} from "../drag/types.js";
102
+ import { dragContextInjectionKey } from "../drag/types.js";
74
103
  import { updateWindowWithEvent } from "../helpers/updateWindowSizeWithEvent.js";
75
104
  import { windowSetActiveFrame } from "../layout/windowSetActiveFrame.js";
76
- import {} from "../types/index.js";
105
+ import { settings } from "../settings.js";
77
106
  const $attrs = useAttrs();
78
107
  const win = defineModel("win", { type: Object, ...{ required: true } });
79
108
  const props = defineProps({
80
- additionalDragActions: { type: Array, required: false, default: () => [] },
81
- splitKeyHandler: { type: Function, required: false, default: void 0 },
82
- closeKeyHandler: { type: Function, required: false, default: void 0 },
83
- usageInstructions: { type: Object, required: false, default: () => ({}) },
84
- instructionsTeleportTo: { type: null, required: true },
109
+ actionHandlers: { type: Array, required: false, default: void 0 },
110
+ textHints: { type: Array, required: false, default: () => [] },
111
+ textHintsTeleportTo: { type: null, required: true, default: void 0 },
112
+ ghostTeleportTo: { type: String, required: false, default: "#root" },
85
113
  allowWindowSizeUpdate: { type: Boolean, required: false, default: true },
86
114
  frameProps: { type: Object, required: false },
87
115
  edgesProps: { type: Object, required: false }
88
116
  });
89
117
  const emit = defineEmits(["isShowingDrag", "dragState"]);
90
- const filteredUsageInstructions = computed(() => Object.values(props.usageInstructions).filter((_) => _ !== void 0).map((_) => _));
91
- const splitKeyHandler = props.splitKeyHandler ?? ((e, state2) => e.altKey || state2.isDraggingFromWindowEdge);
92
- const closeKeyHandler = props.closeKeyHandler ?? ((e) => {
93
- if (e.ctrlKey && e.shiftKey) {
94
- return "force";
95
- }
96
- if (e.shiftKey) return true;
97
- return false;
98
- });
99
118
  const windowEl = ref(null);
100
- const showDragging = ref(true);
101
- const closeDecos = ref([]);
102
- const splitDecos = ref([]);
103
119
  const requestType = ref();
104
120
  const dragActionHandler = new DragActionHandler(
105
- (type, _e, state2) => type === "move" ? !state2.isDraggingFromWindowEdge : void 0,
106
121
  [
107
- new SplitAction(
108
- splitKeyHandler,
109
- ((decos) => splitDecos.value = decos),
110
- {
111
- onStart: () => showDragging.value = false,
112
- onCancel: () => showDragging.value = true
113
- }
114
- ),
115
- new CloseAction(
116
- closeKeyHandler,
117
- ((decos) => closeDecos.value = decos)
118
- ),
119
- ...props.additionalDragActions
122
+ ...props.actionHandlers ?? createDefaultHandlers()
120
123
  ],
121
124
  {
122
125
  onEvent: (e, cancel) => {
@@ -134,20 +137,27 @@ const dragActionHandler = new DragActionHandler(
134
137
  }
135
138
  }
136
139
  );
140
+ dragActionHandler.shapes = reactive([]);
141
+ dragActionHandler.textHints = reactive({ actions: [], errors: [] });
142
+ const shapes = dragActionHandler.shapes;
143
+ const dragContext = useFrames(
144
+ win,
145
+ dragActionHandler
146
+ );
137
147
  const {
138
148
  dragStart,
149
+ dragPoint,
139
150
  visualEdges,
140
151
  isDragging,
141
152
  draggingEdges,
142
153
  draggingIntersection,
143
154
  frames,
144
155
  intersections,
145
- state
146
- } = useFrames(
147
- win,
148
- showDragging,
149
- dragActionHandler
150
- );
156
+ state,
157
+ frameDragFrameId,
158
+ showDragging
159
+ } = dragContext;
160
+ provide(dragContextInjectionKey, dragContext);
151
161
  function getWindowOffset() {
152
162
  const windowElRect = windowEl.value.getBoundingClientRect();
153
163
  return {
@@ -178,6 +188,7 @@ watch(showDragging, () => emit("isShowingDrag", showDragging.value));
178
188
  defineExpose({
179
189
  state,
180
190
  win,
181
- updateWindowSize
191
+ updateWindowSize,
192
+ dragActionHandler
182
193
  });
183
194
  </script>
@@ -1,11 +1,15 @@
1
+ import { DragActionHandler } from "../drag/DragActionHandler";
1
2
  import { type DragState, type IDragAction } from "../drag/types.js";
2
- import { type LayoutEdgesProps, type LayoutFrameProps, type LayoutWindow } from "../types/index.js";
3
+ import type { LayoutEdgesProps, LayoutFrameProps, LayoutWindow } from "../types/index.js";
3
4
  type __VLS_Props = {
4
- additionalDragActions?: IDragAction[];
5
- splitKeyHandler?: (e: PointerEvent | KeyboardEvent, state: DragState) => boolean;
6
- closeKeyHandler?: (e: PointerEvent | KeyboardEvent, state: DragState) => boolean;
7
- usageInstructions?: Record<string, string | undefined>;
8
- instructionsTeleportTo: string | undefined;
5
+ /** Custom drag action handlers. Falls back to default split/close/frame handlers if not provided. */
6
+ actionHandlers?: IDragAction[];
7
+ textHints?: {
8
+ text: string;
9
+ classes?: string;
10
+ }[];
11
+ textHintsTeleportTo: string | undefined;
12
+ ghostTeleportTo?: string;
9
13
  /**
10
14
  * You might need to temporarily disable updating the window size while transitioning, depending on your layout.
11
15
  *
@@ -23,9 +27,13 @@ type __VLS_PublicProps = __VLS_Props & {
23
27
  };
24
28
  declare var __VLS_9: any, __VLS_10: {
25
29
  frame: any;
26
- }, __VLS_22: {};
30
+ }, __VLS_22: {}, __VLS_29: any, __VLS_30: {
31
+ id: any;
32
+ };
27
33
  type __VLS_Slots = {} & {
28
34
  [K in NonNullable<typeof __VLS_9>]?: (props: typeof __VLS_10) => any;
35
+ } & {
36
+ [K in NonNullable<typeof __VLS_29>]?: (props: typeof __VLS_30) => any;
29
37
  } & {
30
38
  'extra-decos'?: (props: typeof __VLS_22) => any;
31
39
  };
@@ -39,7 +47,9 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_PublicProps,
39
47
  x: number;
40
48
  y: number;
41
49
  } | undefined;
42
- isDragging: boolean;
50
+ isDragging: false | "edge" | "frame";
51
+ showDragging: boolean;
52
+ draggingFrameId: string | undefined;
43
53
  draggingEdges: {
44
54
  startX: number;
45
55
  startY: number;
@@ -85,6 +95,7 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_PublicProps,
85
95
  }>;
86
96
  win: import("vue").ModelRef<import("../types/index.js").BaseLayoutWindow, string, import("../types/index.js").BaseLayoutWindow, import("../types/index.js").BaseLayoutWindow>;
87
97
  updateWindowSize: typeof updateWindowSize;
98
+ dragActionHandler: DragActionHandler<IDragAction[], import("@alanscodelog/utils").RecordFromArray<IDragAction[], "name">>;
88
99
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
89
100
  "update:win": (value: import("../types/index.js").BaseLayoutWindow) => any;
90
101
  } & {
@@ -95,10 +106,13 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_PublicProps,
95
106
  onDragState?: ((value: DragState) => any) | undefined;
96
107
  "onUpdate:win"?: ((value: import("../types/index.js").BaseLayoutWindow) => any) | undefined;
97
108
  }>, {
98
- additionalDragActions: IDragAction[];
99
- splitKeyHandler: (e: PointerEvent | KeyboardEvent, state: DragState) => boolean;
100
- closeKeyHandler: (e: PointerEvent | KeyboardEvent, state: DragState) => boolean;
101
- usageInstructions: Record<string, string | undefined>;
109
+ actionHandlers: IDragAction[];
110
+ textHints: {
111
+ text: string;
112
+ classes?: string;
113
+ }[];
114
+ textHintsTeleportTo: string | undefined;
115
+ ghostTeleportTo: string;
102
116
  allowWindowSizeUpdate: boolean;
103
117
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
104
118
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
@@ -1,30 +1,28 @@
1
1
  import type { Ref } from "vue";
2
- import type { DragChangeHandler, DragState } from "../drag/types.js";
3
- import type { Edge, IntersectionEntry, LayoutFrame, LayoutWindow } from "../types/index.js";
4
- export declare function useFrames(win: Ref<LayoutWindow>,
5
- /** Whether to show merged the moved frames while dragging. */
6
- showDragging: Ref<boolean>, handler: {
2
+ import type { DragChangeHandler, DragChangeResult, DragState, EdgeDragStartData, FrameDragStartData } from "../drag/types.js";
3
+ import type { IntersectionEntry, LayoutFrame, LayoutWindow } from "../types/index.js";
4
+ export declare function useFrames(win: Ref<LayoutWindow>, handler: {
7
5
  eventHandler: (e: KeyboardEvent, state: DragState, forceRecalculateEdges: () => void) => void;
8
6
  /**
9
- * Called when the drag coordinates change (during any event). Should return true to allow the edges to be moved, or false to prevent it.
7
+ * Called when the drag coordinates change (during any event). Should return true to allow the edges to be updated/moved, or false to prevent it.
8
+ *
9
+ * Can return anything for the end event as it's ignored.
10
10
  *
11
11
  * Can be used to save some context/info to later apply safely during onDragApply.
12
12
  */
13
- onDragChange: DragChangeHandler;
13
+ onDragChange: (...args: Parameters<DragChangeHandler>) => DragChangeResult;
14
14
  /**
15
15
  * Called when drag will be applied. If dragEnd was called with apply false, it will not be called.
16
16
  * Return false to not apply the regular drag end changes (i.e. return false to reset to the position before dragging).
17
17
  */
18
18
  onDragApply: ((state: DragState, forceRecalculateEdges: () => void) => boolean);
19
19
  }): {
20
- dragStart: (e: PointerEvent, { edge, intersection }: {
21
- edge?: Edge;
22
- intersection?: IntersectionEntry;
23
- }) => void;
20
+ dragStart: <T extends "edge" | "frame">(e: PointerEvent, type: T, data: T extends "edge" ? EdgeDragStartData : FrameDragStartData) => void;
24
21
  dragEnd: (e?: PointerEvent, { apply }?: {
25
22
  apply?: boolean;
26
23
  }) => void;
27
24
  cancel: () => void;
25
+ dragMove: (e: PointerEvent) => void;
28
26
  dragDirections: Ref<{
29
27
  horizontal: "up" | "down" | "left" | "right" | undefined;
30
28
  vertical: "up" | "down" | "left" | "right" | undefined;
@@ -39,7 +37,7 @@ showDragging: Ref<boolean>, handler: {
39
37
  x: number;
40
38
  y: number;
41
39
  } | undefined>;
42
- isDragging: Ref<boolean, boolean>;
40
+ isDragging: Ref<false | "edge" | "frame", false | "edge" | "frame">;
43
41
  draggingEdges: Ref<{
44
42
  startX: number;
45
43
  startY: number;
@@ -133,7 +131,9 @@ showDragging: Ref<boolean>, handler: {
133
131
  x: number;
134
132
  y: number;
135
133
  } | undefined;
136
- isDragging: boolean;
134
+ isDragging: false | "edge" | "frame";
135
+ showDragging: boolean;
136
+ draggingFrameId: string | undefined;
137
137
  draggingEdges: {
138
138
  startX: number;
139
139
  startY: number;
@@ -177,4 +177,6 @@ showDragging: Ref<boolean>, handler: {
177
177
  isDraggingFromWindowEdge: boolean;
178
178
  win: import("../types/index.js").BaseLayoutWindow;
179
179
  }>;
180
+ showDragging: Ref<boolean, boolean>;
181
+ frameDragFrameId: Ref<string | undefined, string | undefined>;
180
182
  };
@@ -1,6 +1,6 @@
1
1
  import { debounce } from "@alanscodelog/utils/debounce";
2
2
  import { keys } from "@alanscodelog/utils/keys";
3
- import { computed, onBeforeUnmount, onMounted, ref, watchEffect } from "vue";
3
+ import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
4
4
  import { DragDirectionStore } from "../drag/DragDirectionStore.js";
5
5
  import { cloneFrame } from "../helpers/cloneFrame.js";
6
6
  import { getIntersections } from "../helpers/getIntersections.js";
@@ -9,8 +9,8 @@ import { isWindowEdge } from "../helpers/isWindowEdge.js";
9
9
  import { moveEdge } from "../helpers/moveEdge.js";
10
10
  import { toWindowCoord } from "../helpers/toWindowCoord.js";
11
11
  import { findFramesTouchingEdge } from "../layout/findFramesTouchingEdge.js";
12
- import { isPointInFrame } from "../layout/isPointInFrame.js";
13
- export function useFrames(win, showDragging, handler) {
12
+ import { isPointInRect } from "../layout/isPointInRect.js";
13
+ export function useFrames(win, handler) {
14
14
  const draggingEdges = ref([]);
15
15
  const touchingFrames = ref([]);
16
16
  const allTouchingFrames = computed(() => {
@@ -24,17 +24,19 @@ export function useFrames(win, showDragging, handler) {
24
24
  });
25
25
  const touchingFramesArrays = computed(() => touchingFrames.value.map((entry) => Object.values(entry)));
26
26
  const isDragging = ref(false);
27
+ const showDragging = ref(false);
27
28
  const dragPoint = ref();
28
29
  const dragDirections = ref({});
29
30
  const draggingIntersection = ref(void 0);
30
31
  const isDraggingFromWindowEdge = ref(false);
32
+ const frameDragFrameId = ref();
31
33
  const frames = computed(
32
34
  () => isDragging.value && showDragging.value ? { ...win.value.frames, ...allTouchingFrames.value } : win.value.frames
33
35
  );
34
36
  const dragHoveredFrame = computed(() => {
35
37
  if (isDragging.value) {
36
38
  for (const id of keys(frames.value)) {
37
- if (isPointInFrame(frames.value[id], dragPoint.value)) {
39
+ if (isPointInRect(frames.value[id], dragPoint.value)) {
38
40
  return frames.value[id];
39
41
  }
40
42
  }
@@ -46,10 +48,11 @@ export function useFrames(win, showDragging, handler) {
46
48
  const debounceGetDraggableEdges = debounce((f) => {
47
49
  visualEdges.value = getVisualEdges(f, { includeWindowEdges: true });
48
50
  }, 50, {});
49
- watchEffect(() => {
51
+ watch([isDragging, frames], () => {
50
52
  if (isDragging.value) return;
51
53
  debounceGetDraggableEdges(Object.values(frames.value));
52
- });
54
+ }, { deep: true });
55
+ debounceGetDraggableEdges(Object.values(frames.value));
53
56
  function forceRecalculateEdges() {
54
57
  visualEdges.value = getVisualEdges(Object.values(frames.value), { includeWindowEdges: true });
55
58
  }
@@ -60,6 +63,8 @@ export function useFrames(win, showDragging, handler) {
60
63
  dragDirections: dragDirections.value,
61
64
  dragPoint: dragPoint.value,
62
65
  isDragging: isDragging.value,
66
+ showDragging: showDragging.value,
67
+ draggingFrameId: frameDragFrameId.value,
63
68
  draggingEdges: draggingEdges.value,
64
69
  draggingIntersection: draggingIntersection.value,
65
70
  visualEdges: visualEdges.value,
@@ -78,10 +83,12 @@ export function useFrames(win, showDragging, handler) {
78
83
  isDragging.value = false;
79
84
  dragPoint.value = void 0;
80
85
  touchingFrames.value = [];
86
+ frameDragFrameId.value = void 0;
81
87
  dragDirStore.reset();
88
+ showDragging.value = false;
82
89
  forceRecalculateEdges();
83
90
  }
84
- function dragStart(e, { edge, intersection }) {
91
+ function dragStart(e, type, data) {
85
92
  controller = new AbortController();
86
93
  controller.signal.addEventListener("abort", () => resetState());
87
94
  e.preventDefault();
@@ -89,31 +96,38 @@ export function useFrames(win, showDragging, handler) {
89
96
  window.addEventListener("pointerup", dragEnd, { signal: controller.signal });
90
97
  const point = toWindowCoord(win.value, e);
91
98
  dragPoint.value = point;
92
- isDragging.value = true;
93
- draggingIntersection.value = intersection;
94
- draggingEdges.value = edge ? [edge] : [
95
- ...draggingIntersection.value?.sharedEdges.horizontal ?? [],
96
- ...draggingIntersection.value?.sharedEdges.vertical ?? []
97
- ];
98
99
  dragDirStore.update(point);
99
- isDraggingFromWindowEdge.value = draggingEdges.value.some((_) => isWindowEdge(_));
100
- const framesArray = Object.values(win.value.frames);
101
- touchingFrames.value = [];
102
- const clones = /* @__PURE__ */ new Map();
103
- for (let i = 0; i < draggingEdges.value.length; i++) {
104
- const draggingEdge = draggingEdges.value[i];
105
- touchingFrames.value[i] = {};
106
- for (const { frame } of findFramesTouchingEdge(draggingEdge, framesArray)) {
107
- if (!clones.has(frame.id)) {
108
- const clone = cloneFrame(frame);
109
- touchingFrames.value[i][frame.id] = clone;
110
- clones.set(frame.id, clone);
111
- } else {
112
- touchingFrames.value[i][frame.id] = clones.get(frame.id);
100
+ isDragging.value = type;
101
+ showDragging.value = true;
102
+ if (type === "frame") {
103
+ frameDragFrameId.value = data.frameId;
104
+ } else {
105
+ const { edge, intersection } = data;
106
+ draggingIntersection.value = intersection;
107
+ draggingEdges.value = edge ? [edge] : [
108
+ ...draggingIntersection.value?.sharedEdges.horizontal ?? [],
109
+ ...draggingIntersection.value?.sharedEdges.vertical ?? []
110
+ ];
111
+ isDraggingFromWindowEdge.value = draggingEdges.value.some((_) => isWindowEdge(_));
112
+ const framesArray = Object.values(win.value.frames);
113
+ touchingFrames.value = [];
114
+ const clones = /* @__PURE__ */ new Map();
115
+ for (let i = 0; i < draggingEdges.value.length; i++) {
116
+ const draggingEdge = draggingEdges.value[i];
117
+ touchingFrames.value[i] = {};
118
+ for (const { frame } of findFramesTouchingEdge(draggingEdge, framesArray)) {
119
+ if (!clones.has(frame.id)) {
120
+ const clone = cloneFrame(frame);
121
+ touchingFrames.value[i][frame.id] = clone;
122
+ clones.set(frame.id, clone);
123
+ } else {
124
+ touchingFrames.value[i][frame.id] = clones.get(frame.id);
125
+ }
113
126
  }
114
127
  }
115
128
  }
116
- handler.onDragChange("start", e, state.value, forceRecalculateEdges, cancel);
129
+ const res = handler.onDragChange("start", e, state.value, forceRecalculateEdges, cancel);
130
+ showDragging.value = res.showDragging ?? true;
117
131
  }
118
132
  function dragMove(e) {
119
133
  e.preventDefault();
@@ -121,17 +135,20 @@ export function useFrames(win, showDragging, handler) {
121
135
  const didChange = dragDirStore.update(point);
122
136
  dragPoint.value = point;
123
137
  if (!didChange) return;
124
- const allowed = handler.onDragChange("move", e, state.value, forceRecalculateEdges, cancel);
125
- if (!allowed) return;
126
- requestAnimationFrame(() => {
127
- for (let i = 0; i < draggingEdges.value.length; i++) {
128
- const draggingEdge = draggingEdges.value[i];
129
- if (draggingEdge) {
130
- moveEdge(touchingFramesArrays.value[i], draggingEdge, point);
138
+ const res = handler.onDragChange("move", e, state.value, forceRecalculateEdges, cancel);
139
+ showDragging.value = res.showDragging ?? true;
140
+ if (!res.updateEdges) return;
141
+ if (isDragging.value === "edge") {
142
+ requestAnimationFrame(() => {
143
+ for (let i = 0; i < draggingEdges.value.length; i++) {
144
+ const draggingEdge = draggingEdges.value[i];
145
+ if (draggingEdge) {
146
+ moveEdge(touchingFramesArrays.value[i], draggingEdge, point);
147
+ }
131
148
  }
132
- }
133
- forceRecalculateEdges();
134
- });
149
+ forceRecalculateEdges();
150
+ });
151
+ }
135
152
  }
136
153
  function dragEnd(e, { apply = true } = {}) {
137
154
  if (e) {
@@ -166,6 +183,7 @@ export function useFrames(win, showDragging, handler) {
166
183
  dragStart,
167
184
  dragEnd,
168
185
  cancel,
186
+ dragMove,
169
187
  dragDirections,
170
188
  dragPoint,
171
189
  isDragging,
@@ -179,6 +197,8 @@ export function useFrames(win, showDragging, handler) {
179
197
  intersections,
180
198
  isDraggingFromWindowEdge,
181
199
  forceRecalculateEdges,
182
- state
200
+ state,
201
+ showDragging,
202
+ frameDragFrameId
183
203
  };
184
204
  }