@vuu-ui/vuu-layout 0.5.15 → 0.5.17

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 (181) hide show
  1. package/LICENSE +201 -0
  2. package/cjs/index.js +20 -0
  3. package/cjs/index.js.map +7 -0
  4. package/esm/index.js +20 -0
  5. package/esm/index.js.map +7 -0
  6. package/index.css +2 -0
  7. package/index.css.map +7 -0
  8. package/package.json +16 -10
  9. package/types/Component.d.ts +7 -0
  10. package/types/DraggableLayout.d.ts +6 -0
  11. package/types/chest-of-drawers/Chest.d.ts +10 -0
  12. package/types/chest-of-drawers/Drawer.d.ts +18 -0
  13. package/{src/chest-of-drawers/index.ts → types/chest-of-drawers/index.d.ts} +0 -0
  14. package/types/common-types.d.ts +8 -0
  15. package/types/debug.d.ts +2 -0
  16. package/types/drag-drop/BoxModel.d.ts +143 -0
  17. package/types/drag-drop/DragState.d.ts +46 -0
  18. package/types/drag-drop/Draggable.d.ts +23 -0
  19. package/types/drag-drop/DropMenu.d.ts +10 -0
  20. package/types/drag-drop/DropTarget.d.ts +61 -0
  21. package/types/drag-drop/DropTargetRenderer.d.ts +18 -0
  22. package/types/drag-drop/dragDropTypes.d.ts +51 -0
  23. package/{src/drag-drop/index.ts → types/drag-drop/index.d.ts} +0 -1
  24. package/types/editable-label/EditableLabel.d.ts +9 -0
  25. package/{src/editable-label/index.ts → types/editable-label/index.d.ts} +0 -0
  26. package/types/flexbox/Flexbox.d.ts +5 -0
  27. package/types/flexbox/FlexboxLayout.d.ts +6 -0
  28. package/types/flexbox/FluidGrid.d.ts +7 -0
  29. package/types/flexbox/FluidGridLayout.d.ts +6 -0
  30. package/types/flexbox/Splitter.d.ts +13 -0
  31. package/types/flexbox/flexbox-utils.d.ts +12 -0
  32. package/types/flexbox/flexboxTypes.d.ts +51 -0
  33. package/{src/flexbox/index.ts → types/flexbox/index.d.ts} +0 -1
  34. package/types/flexbox/useResponsiveSizing.d.ts +10 -0
  35. package/types/flexbox/useSplitterResizing.d.ts +2 -0
  36. package/{src/index.ts → types/index.d.ts} +0 -1
  37. package/types/layout-action.d.ts +21 -0
  38. package/types/layout-header/ActionButton.d.ts +8 -0
  39. package/types/layout-header/Header.d.ts +13 -0
  40. package/{src/layout-header/index.ts → types/layout-header/index.d.ts} +0 -0
  41. package/types/layout-provider/LayoutProvider.d.ts +14 -0
  42. package/types/layout-provider/LayoutProviderContext.d.ts +8 -0
  43. package/{src/layout-provider/index.ts → types/layout-provider/index.d.ts} +0 -1
  44. package/types/layout-provider/useLayoutDragDrop.d.ts +4 -0
  45. package/types/layout-reducer/flexUtils.d.ts +22 -0
  46. package/{src/layout-reducer/index.ts → types/layout-reducer/index.d.ts} +0 -1
  47. package/types/layout-reducer/insert-layout-element.d.ts +8 -0
  48. package/types/layout-reducer/layout-reducer.d.ts +3 -0
  49. package/types/layout-reducer/layoutTypes.d.ts +130 -0
  50. package/types/layout-reducer/layoutUtils.d.ts +28 -0
  51. package/types/layout-reducer/remove-layout-element.d.ts +3 -0
  52. package/types/layout-reducer/replace-layout-element.d.ts +6 -0
  53. package/types/layout-reducer/resize-flex-children.d.ts +3 -0
  54. package/types/layout-reducer/wrap-layout-element.d.ts +9 -0
  55. package/types/layout-view/View.d.ts +5 -0
  56. package/types/layout-view/ViewContext.d.ts +18 -0
  57. package/{src/layout-view/index.ts → types/layout-view/index.d.ts} +0 -1
  58. package/types/layout-view/useView.d.ts +21 -0
  59. package/types/layout-view/useViewActionDispatcher.d.ts +8 -0
  60. package/types/layout-view/useViewResize.d.ts +7 -0
  61. package/types/layout-view/viewTypes.d.ts +18 -0
  62. package/types/palette/Palette.d.ts +18 -0
  63. package/types/palette/PaletteSalt.d.ts +14 -0
  64. package/{src/palette/index.ts → types/palette/index.d.ts} +0 -1
  65. package/types/placeholder/Placeholder.d.ts +12 -0
  66. package/{src/placeholder/index.ts → types/placeholder/index.d.ts} +0 -0
  67. package/types/registry/ComponentRegistry.d.ts +14 -0
  68. package/{src/registry/index.ts → types/registry/index.d.ts} +0 -0
  69. package/types/responsive/breakpoints.d.ts +4 -0
  70. package/{src/responsive/index.ts → types/responsive/index.d.ts} +0 -0
  71. package/types/responsive/measureMinimumNodeSize.d.ts +1 -0
  72. package/types/responsive/overflowUtils.d.ts +2 -0
  73. package/types/responsive/use-breakpoints.d.ts +7 -0
  74. package/types/responsive/useResizeObserver.d.ts +12 -0
  75. package/types/responsive/utils.d.ts +6 -0
  76. package/types/stack/Stack.d.ts +4 -0
  77. package/types/stack/StackLayout.d.ts +7 -0
  78. package/{src/stack/index.ts → types/stack/index.d.ts} +0 -1
  79. package/types/stack/stackTypes.d.ts +20 -0
  80. package/types/tabs/TabPanel.d.ts +7 -0
  81. package/{src/tabs/index.ts → types/tabs/index.d.ts} +0 -0
  82. package/types/tools/config-wrapper/ConfigWrapper.d.ts +2 -0
  83. package/{src/tools/config-wrapper/index.ts → types/tools/config-wrapper/index.d.ts} +0 -0
  84. package/types/tools/devtools-box/layout-configurator.d.ts +31 -0
  85. package/types/tools/devtools-tree/layout-tree-viewer.d.ts +5 -0
  86. package/{src/tools/index.ts → types/tools/index.d.ts} +0 -1
  87. package/types/use-persistent-state.d.ts +11 -0
  88. package/{src/utils/index.ts → types/utils/index.d.ts} +0 -0
  89. package/types/utils/pathUtils.d.ts +18 -0
  90. package/types/utils/propUtils.d.ts +5 -0
  91. package/types/utils/refUtils.d.ts +2 -0
  92. package/types/utils/styleUtils.d.ts +3 -0
  93. package/types/utils/typeOf.d.ts +4 -0
  94. package/src/Component.css +0 -0
  95. package/src/Component.tsx +0 -20
  96. package/src/DraggableLayout.css +0 -18
  97. package/src/DraggableLayout.tsx +0 -26
  98. package/src/__tests__/flexbox-utils.spec.js +0 -90
  99. package/src/chest-of-drawers/Chest.css +0 -36
  100. package/src/chest-of-drawers/Chest.tsx +0 -42
  101. package/src/chest-of-drawers/Drawer.css +0 -159
  102. package/src/chest-of-drawers/Drawer.tsx +0 -118
  103. package/src/common-types.ts +0 -9
  104. package/src/debug.ts +0 -16
  105. package/src/drag-drop/BoxModel.ts +0 -551
  106. package/src/drag-drop/DragState.ts +0 -219
  107. package/src/drag-drop/Draggable.ts +0 -282
  108. package/src/drag-drop/DropMenu.css +0 -71
  109. package/src/drag-drop/DropMenu.tsx +0 -61
  110. package/src/drag-drop/DropTarget.ts +0 -393
  111. package/src/drag-drop/DropTargetRenderer.css +0 -40
  112. package/src/drag-drop/DropTargetRenderer.tsx +0 -277
  113. package/src/drag-drop/dragDropTypes.ts +0 -47
  114. package/src/editable-label/EditableLabel.css +0 -28
  115. package/src/editable-label/EditableLabel.tsx +0 -99
  116. package/src/flexbox/Flexbox.css +0 -45
  117. package/src/flexbox/Flexbox.tsx +0 -70
  118. package/src/flexbox/FlexboxLayout.tsx +0 -28
  119. package/src/flexbox/FluidGrid.css +0 -134
  120. package/src/flexbox/FluidGrid.tsx +0 -82
  121. package/src/flexbox/FluidGridLayout.tsx +0 -9
  122. package/src/flexbox/Splitter.css +0 -140
  123. package/src/flexbox/Splitter.tsx +0 -127
  124. package/src/flexbox/flexbox-utils.ts +0 -128
  125. package/src/flexbox/flexboxTypes.ts +0 -68
  126. package/src/flexbox/useResponsiveSizing.ts +0 -82
  127. package/src/flexbox/useSplitterResizing.ts +0 -270
  128. package/src/layout-action.ts +0 -21
  129. package/src/layout-header/ActionButton.tsx +0 -23
  130. package/src/layout-header/Header.css +0 -8
  131. package/src/layout-header/Header.tsx +0 -216
  132. package/src/layout-provider/LayoutProvider.tsx +0 -161
  133. package/src/layout-provider/LayoutProviderContext.ts +0 -17
  134. package/src/layout-provider/useLayoutDragDrop.ts +0 -210
  135. package/src/layout-reducer/flexUtils.ts +0 -276
  136. package/src/layout-reducer/insert-layout-element.ts +0 -365
  137. package/src/layout-reducer/layout-reducer.ts +0 -237
  138. package/src/layout-reducer/layoutTypes.ts +0 -159
  139. package/src/layout-reducer/layoutUtils.ts +0 -288
  140. package/src/layout-reducer/remove-layout-element.ts +0 -226
  141. package/src/layout-reducer/replace-layout-element.ts +0 -113
  142. package/src/layout-reducer/resize-flex-children.ts +0 -55
  143. package/src/layout-reducer/wrap-layout-element.ts +0 -307
  144. package/src/layout-view/View.css +0 -61
  145. package/src/layout-view/View.tsx +0 -143
  146. package/src/layout-view/ViewContext.ts +0 -30
  147. package/src/layout-view/useView.tsx +0 -104
  148. package/src/layout-view/useViewActionDispatcher.ts +0 -123
  149. package/src/layout-view/useViewResize.ts +0 -53
  150. package/src/layout-view/viewTypes.ts +0 -35
  151. package/src/palette/Palette.css +0 -33
  152. package/src/palette/Palette.tsx +0 -140
  153. package/src/palette/PaletteSalt.css +0 -9
  154. package/src/palette/PaletteSalt.tsx +0 -79
  155. package/src/placeholder/Placeholder.css +0 -10
  156. package/src/placeholder/Placeholder.tsx +0 -38
  157. package/src/registry/ComponentRegistry.ts +0 -44
  158. package/src/responsive/breakpoints.ts +0 -62
  159. package/src/responsive/measureMinimumNodeSize.ts +0 -23
  160. package/src/responsive/overflowUtils.js +0 -14
  161. package/src/responsive/use-breakpoints.ts +0 -101
  162. package/src/responsive/useResizeObserver.ts +0 -154
  163. package/src/responsive/utils.ts +0 -37
  164. package/src/stack/Stack.css +0 -39
  165. package/src/stack/Stack.tsx +0 -173
  166. package/src/stack/StackLayout.tsx +0 -119
  167. package/src/stack/stackTypes.ts +0 -22
  168. package/src/tabs/TabPanel.css +0 -12
  169. package/src/tabs/TabPanel.tsx +0 -17
  170. package/src/tools/config-wrapper/ConfigWrapper.tsx +0 -55
  171. package/src/tools/devtools-box/layout-configurator.css +0 -112
  172. package/src/tools/devtools-box/layout-configurator.jsx +0 -369
  173. package/src/tools/devtools-tree/layout-tree-viewer.css +0 -15
  174. package/src/tools/devtools-tree/layout-tree-viewer.jsx +0 -36
  175. package/src/use-persistent-state.ts +0 -112
  176. package/src/utils/pathUtils.ts +0 -283
  177. package/src/utils/propUtils.ts +0 -26
  178. package/src/utils/refUtils.ts +0 -16
  179. package/src/utils/styleUtils.ts +0 -13
  180. package/src/utils/typeOf.ts +0 -25
  181. package/tsconfig-emit-types.json +0 -11
@@ -1,551 +0,0 @@
1
- import { ReactElement } from "react";
2
- import { rect } from "../common-types";
3
- import { LayoutModel } from "../layout-reducer";
4
- import { isContainer } from "../registry/ComponentRegistry";
5
- import { getProps, typeOf } from "../utils";
6
- import { DragDropRect, DropPos, RelativePosition } from "./dragDropTypes";
7
-
8
- export const positionValues = {
9
- north: 1,
10
- east: 2,
11
- south: 4,
12
- west: 8,
13
- header: 16,
14
- centre: 32,
15
- absolute: 64,
16
- };
17
-
18
- export const RelativeDropPosition = {
19
- AFTER: "after" as RelativePosition,
20
- BEFORE: "before" as RelativePosition,
21
- };
22
-
23
- export const Position = Object.freeze({
24
- North: _position("north"),
25
- East: _position("east"),
26
- South: _position("south"),
27
- West: _position("west"),
28
- Header: _position("header"),
29
- Centre: _position("centre"),
30
- Absolute: _position("absolute"),
31
- });
32
-
33
- function _position(str: keyof typeof positionValues) {
34
- return Object.freeze({
35
- offset:
36
- str === "north" || str === "west"
37
- ? 0
38
- : str === "south" || str === "east"
39
- ? 1
40
- : NaN,
41
- valueOf: function () {
42
- return positionValues[str];
43
- },
44
- toString: function () {
45
- return str;
46
- },
47
- North: str === "north",
48
- South: str === "south",
49
- East: str === "east",
50
- West: str === "west",
51
- Header: str === "header",
52
- Centre: str === "centre",
53
- NorthOrSouth: str === "north" || str === "south",
54
- EastOrWest: str === "east" || str === "west",
55
- NorthOrWest: str === "north" || str === "west",
56
- SouthOrEast: str === "east" || str === "south",
57
- Absolute: str === "absolute",
58
- });
59
- }
60
-
61
- const NORTH = Position.North,
62
- SOUTH = Position.South,
63
- EAST = Position.East,
64
- WEST = Position.West,
65
- HEADER = Position.Header,
66
- CENTRE = Position.Centre;
67
-
68
- export interface Measurements {
69
- [key: string]: DragDropRect;
70
- }
71
-
72
- export class BoxModel {
73
- //TODO we should accept initial let,top offsets here
74
- // if dropTargets are supplied, we will only allow drop operations directly on these targets
75
- // TODO we will need to make this more flexible e.g allowing drop anywhere within these target
76
- static measure(
77
- model: ReactElement,
78
- dropTargetPaths: string[] = []
79
- ): Measurements {
80
- const measurements: Measurements = {};
81
- measureRootComponent(model, measurements, dropTargetPaths);
82
- return measurements;
83
- }
84
-
85
- static allBoxesContainingPoint(
86
- layout: LayoutModel,
87
- measurements: Measurements,
88
- x: number,
89
- y: number,
90
- validDropTargets?: string[]
91
- ) {
92
- return allBoxesContainingPoint(
93
- layout,
94
- measurements,
95
- x,
96
- y,
97
- validDropTargets
98
- ).reverse();
99
- }
100
- }
101
-
102
- export function pointPositionWithinRect(
103
- x: number,
104
- y: number,
105
- rect: DragDropRect,
106
- borderZone = 30
107
- ) {
108
- const width = rect.right - rect.left;
109
- const height = rect.bottom - rect.top;
110
- const posX = x - rect.left;
111
- const posY = y - rect.top;
112
- let closeToTheEdge = 0;
113
-
114
- if (posX < borderZone) closeToTheEdge += 8;
115
- if (posX > width - borderZone) closeToTheEdge += 2;
116
- if (posY < borderZone) closeToTheEdge += 1;
117
- if (posY > height - borderZone) closeToTheEdge += 4;
118
-
119
- return { pctX: posX / width, pctY: posY / height, closeToTheEdge };
120
- }
121
-
122
- export function getPosition(
123
- x: number,
124
- y: number,
125
- rect: DragDropRect,
126
- targetOrientation?: "row" | "column"
127
- ): DropPos {
128
- const { BEFORE, AFTER } = RelativeDropPosition;
129
- const { pctX, pctY, closeToTheEdge } = pointPositionWithinRect(x, y, rect);
130
- let position;
131
- let tab;
132
-
133
- if (targetOrientation === "row") {
134
- position = pctX < 0.5 ? WEST : EAST;
135
- } else if (rect.header && containsPoint(rect.header, x, y)) {
136
- position = HEADER;
137
-
138
- if (rect.Stack) {
139
- const tabCount = rect.Stack.length;
140
- if (tabCount === 0) {
141
- tab = {
142
- index: -1,
143
- left: rect.left,
144
- positionRelativeToTab: AFTER,
145
- width: 0,
146
- };
147
- } else {
148
- //TODO account for gaps between tabs
149
- const targetTab = rect.Stack.find(
150
- ({ left, right }) => x >= left && x <= right
151
- );
152
- if (targetTab) {
153
- const tabWidth = targetTab.right - targetTab.left;
154
- tab = {
155
- index: rect.Stack.indexOf(targetTab),
156
- left: targetTab.left,
157
- positionRelativeToTab:
158
- (x - targetTab.left) / tabWidth < 0.5 ? BEFORE : AFTER,
159
- width: tabWidth,
160
- };
161
- } else {
162
- const lastTab = rect.Stack[tabCount - 1];
163
- tab = {
164
- left: lastTab.right,
165
- width: 0,
166
- index: tabCount,
167
- positionRelativeToTab: AFTER,
168
- };
169
- }
170
- }
171
- } else if (rect.header.titleWidth) {
172
- const tabWidth = rect.header.titleWidth;
173
- tab = {
174
- index: -1,
175
- left: rect.left,
176
- positionRelativeToTab:
177
- (x - rect.left) / tabWidth < 0.5 ? BEFORE : AFTER,
178
- width: tabWidth,
179
- };
180
- } else {
181
- tab = {
182
- left: rect.left,
183
- width: 0,
184
- positionRelativeToTab: BEFORE,
185
- index: -1,
186
- };
187
- }
188
- } else {
189
- position = getPositionWithinBox(x, y, rect, pctX, pctY);
190
- }
191
- return { position: position!, x, y, closeToTheEdge, tab };
192
- }
193
-
194
- function getPositionWithinBox(
195
- x: number,
196
- y: number,
197
- rect: DragDropRect,
198
- pctX: number,
199
- pctY: number
200
- ) {
201
- const centerBox = getCenteredBox(rect, 0.2);
202
- if (containsPoint(centerBox, x, y)) {
203
- return CENTRE;
204
- } else {
205
- const quadrant = `${pctY < 0.5 ? "north" : "south"}${
206
- pctX < 0.5 ? "west" : "east"
207
- }`;
208
-
209
- switch (quadrant) {
210
- case "northwest":
211
- return pctX > pctY ? NORTH : WEST;
212
- case "northeast":
213
- return 1 - pctX > pctY ? NORTH : EAST;
214
- case "southeast":
215
- return pctX > pctY ? EAST : SOUTH;
216
- case "southwest":
217
- return 1 - pctX > pctY ? WEST : SOUTH;
218
- default:
219
- }
220
- }
221
- }
222
-
223
- function getCenteredBox(
224
- { right, left, top, bottom }: DragDropRect,
225
- pctSize: number
226
- ) {
227
- const pctOffset = (1 - pctSize) / 2;
228
- const w = (right - left) * pctOffset;
229
- const h = (bottom - top) * pctOffset;
230
- return { left: left + w, top: top + h, right: right - w, bottom: bottom - h };
231
- }
232
-
233
- function measureRootComponent(
234
- rootComponent: ReactElement,
235
- measurements: Measurements,
236
- dropTargets: string[]
237
- ) {
238
- const {
239
- id,
240
- "data-path": dataPath,
241
- path = dataPath,
242
- } = getProps(rootComponent);
243
- const type = typeOf(rootComponent) as string;
244
-
245
- if (id && path) {
246
- const [rect, el] = measureComponentDomElement(rootComponent);
247
- measureComponent(rootComponent, rect, el, measurements);
248
- if (isContainer(type)) {
249
- collectChildMeasurements(rootComponent, measurements, dropTargets);
250
- }
251
- }
252
- }
253
-
254
- function measureComponent(
255
- component: LayoutModel,
256
- rect: DragDropRect,
257
- el: HTMLElement,
258
- measurements: Measurements
259
- ) {
260
- const {
261
- "data-path": dataPath,
262
- path = dataPath,
263
- header,
264
- } = getProps(component);
265
-
266
- measurements[path] = rect;
267
-
268
- const type = typeOf(component);
269
- if (header || type === "Stack") {
270
- const headerEl = el.querySelector(".vuuHeader");
271
- if (headerEl) {
272
- const { top, left, right, bottom } = headerEl.getBoundingClientRect();
273
- measurements[path].header = {
274
- top: Math.round(top),
275
- left: Math.round(left),
276
- right: Math.round(right),
277
- bottom: Math.round(bottom),
278
- };
279
- if (type === "Stack") {
280
- measurements[path].Stack = Array.from(
281
- headerEl.querySelectorAll(".saltTab")
282
- )
283
- .map((tab) => tab.getBoundingClientRect())
284
- .map(({ left, right }) => ({ left, right }));
285
- } else {
286
- const titleEl = headerEl.querySelector('[class^="vuuHeader-title"]');
287
- const { header } = measurements[path];
288
- if (titleEl && header) {
289
- header.titleWidth = titleEl.clientWidth;
290
- }
291
- }
292
- }
293
- }
294
-
295
- return measurements[path];
296
- }
297
-
298
- function collectChildMeasurements(
299
- component: LayoutModel,
300
- measurements: Measurements,
301
- dropTargets: string[],
302
- preX = 0,
303
- posX = 0,
304
- preY = 0,
305
- posY = 0
306
- ) {
307
- const {
308
- children,
309
- "data-path": dataPath,
310
- path = dataPath,
311
- style,
312
- active = 0,
313
- } = getProps(component);
314
-
315
- const type = typeOf(component);
316
- const isFlexbox = type === "Flexbox";
317
- const isStack = type === "Stack";
318
- const isTower = isFlexbox && style.flexDirection === "column";
319
- const isTerrace = isFlexbox && style.flexDirection === "row";
320
-
321
- const childrenToMeasure = isStack
322
- ? children.filter((_child: ReactElement, idx: number) => idx === active)
323
- : children.filter(omitDragging);
324
-
325
- type measuredTuple = [DragDropRect, HTMLElement, ReactElement];
326
- // Collect all the measurements in first pass ...
327
- const childMeasurements: measuredTuple[] = childrenToMeasure.map(
328
- (child: ReactElement) => {
329
- const [rect, el] = measureComponentDomElement(child);
330
-
331
- return [
332
- {
333
- ...rect,
334
- top: rect.top - preY,
335
- right: rect.right + posX,
336
- bottom: rect.bottom + posY,
337
- left: rect.left - preX,
338
- },
339
- el,
340
- child,
341
- ];
342
- }
343
- );
344
-
345
- // ...so that, in the second pass, we can identify gaps ...
346
- const expandedMeasurements = childMeasurements.map(
347
- ([rect, el, child], i, all) => {
348
- // generate a 'local' splitter adjustment for children adjacent to splitters
349
- let localPreX;
350
- let localPosX;
351
- let localPreY;
352
- let localPosY;
353
- let gapPre;
354
- let gapPos;
355
- const n = all.length - 1;
356
- if (isTerrace) {
357
- gapPre = i === 0 ? 0 : rect.left - all[i - 1][0].right;
358
- gapPos = i === n ? 0 : all[i + 1][0].left - rect.right;
359
- // we don't need to divide the leading gap, as half the gap will
360
- // already have been assigned to the preceeding child in the
361
- // previous loop iteration.
362
- localPreX = i === 0 ? 0 : gapPre === 0 ? 0 : gapPre;
363
- localPosX = i === n ? 0 : gapPos === 0 ? 0 : gapPos - gapPos / 2;
364
- rect.left -= localPreX;
365
- rect.right += localPosX;
366
- localPreY = preY;
367
- localPosY = posY;
368
- } else if (isTower) {
369
- gapPre = i === 0 ? 0 : rect.top - all[i - 1][0].bottom;
370
- gapPos = i === n ? 0 : all[i + 1][0].top - rect.bottom;
371
- // we don't need to divide the leading gap, as half the gap will
372
- // already have been assigned to the preceeding child in the
373
- // previous loop iteration.
374
- localPreY = i === 0 ? 0 : gapPre === 0 ? 0 : gapPre;
375
- localPosY = i === n ? 0 : gapPos === 0 ? 0 : gapPos - gapPos / 2;
376
- rect.top -= localPreY;
377
- rect.bottom += localPosY;
378
- localPreX = preX;
379
- localPosX = posX;
380
- }
381
-
382
- const componentMeasurements = measureComponent(
383
- child,
384
- rect,
385
- el,
386
- measurements
387
- );
388
-
389
- const childType = typeOf(child) as string;
390
- if (isContainer(childType)) {
391
- collectChildMeasurements(
392
- child,
393
- measurements,
394
- dropTargets,
395
- localPreX,
396
- localPosX,
397
- localPreY,
398
- localPosY
399
- );
400
- }
401
- return componentMeasurements;
402
- }
403
- );
404
- if (childMeasurements.length) {
405
- measurements[path].children = expandedMeasurements;
406
- }
407
- }
408
-
409
- function omitDragging(component: ReactElement) {
410
- const { id } = getProps(component);
411
- const el = document.getElementById(id);
412
- if (el) {
413
- return el.dataset.dragging !== "true";
414
- } else {
415
- console.warn(`BoxModel: no element found with id #${id}`);
416
- return false;
417
- }
418
- }
419
-
420
- function measureComponentDomElement(
421
- component: LayoutModel
422
- ): [DragDropRect, HTMLElement, LayoutModel] {
423
- const { id } = getProps(component) as { id: string };
424
- if (id === undefined) {
425
- throw Error("`BoxModel.measureComponentElement, component has no id");
426
- }
427
- const el = document.getElementById(id);
428
- if (!el) {
429
- throw Error(
430
- "BoxModel.measureComponentElement, no DOM element found for component"
431
- );
432
- }
433
- // Note: height and width are not required for dropTarget identification, but
434
- // are used in sizing calculations on drop
435
- const { top, left, right, bottom, height, width } =
436
- el.getBoundingClientRect();
437
- let scrolling = undefined;
438
- const type = typeOf(component) as string;
439
- if (isContainer(type)) {
440
- const scrollHeight = el.scrollHeight;
441
- if (scrollHeight > height) {
442
- scrolling = { id, scrollHeight, scrollTop: el.scrollTop };
443
- }
444
- }
445
- return [
446
- {
447
- top: Math.round(top),
448
- left: Math.round(left),
449
- right: Math.round(right),
450
- bottom: Math.round(bottom),
451
- height: Math.round(height),
452
- width: Math.round(width),
453
- scrolling,
454
- },
455
- el,
456
- component,
457
- ];
458
- }
459
-
460
- function allBoxesContainingPoint(
461
- component: LayoutModel,
462
- measurements: Measurements,
463
- x: number,
464
- y: number,
465
- dropTargets?: string[],
466
- boxes: LayoutModel[] = []
467
- ): LayoutModel[] {
468
- const {
469
- children,
470
- "data-path": dataPath,
471
- path = dataPath,
472
- } = getProps(component);
473
-
474
- const type = typeOf(component) as string;
475
- const rect = measurements[path];
476
- if (!containsPoint(rect, x, y)) return boxes;
477
-
478
- if (dropTargets && dropTargets.length) {
479
- if (dropTargets.includes(path)) {
480
- boxes.push(component);
481
- } else if (
482
- dropTargets.some((dropTargetPath) => dropTargetPath.startsWith(path))
483
- ) {
484
- // keep going
485
- } else {
486
- return boxes;
487
- }
488
- } else {
489
- boxes.push(component);
490
- }
491
-
492
- if (!isContainer(type)) {
493
- return boxes;
494
- }
495
-
496
- if (rect.header && containsPoint(rect.header, x, y)) {
497
- return boxes;
498
- }
499
-
500
- if (rect.scrolling) {
501
- scrollIntoViewIfNeccesary(rect, x, y);
502
- }
503
-
504
- for (let i = 0; i < children.length; i++) {
505
- if (type === "Stack" && component.props.active !== i) {
506
- continue;
507
- }
508
- const nestedBoxes = allBoxesContainingPoint(
509
- children[i],
510
- measurements,
511
- x,
512
- y,
513
- dropTargets
514
- );
515
- if (nestedBoxes.length) {
516
- return boxes.concat(nestedBoxes);
517
- }
518
- }
519
- return boxes;
520
- }
521
-
522
- function containsPoint(rect: rect, x: number, y: number) {
523
- if (rect) {
524
- return x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom;
525
- }
526
- }
527
-
528
- function scrollIntoViewIfNeccesary(
529
- { top, bottom, scrolling }: DragDropRect,
530
- x: number,
531
- y: number
532
- ) {
533
- if (scrolling) {
534
- const { id, scrollTop, scrollHeight } = scrolling;
535
- const height = bottom - top;
536
- if (scrollTop === 0 && bottom - y < 50) {
537
- const scrollMax = scrollHeight - height;
538
- const el = document.getElementById(id) as HTMLElement;
539
- el.scrollTo({ left: 0, top: scrollMax, behavior: "smooth" });
540
- scrolling.scrollTop = scrollMax;
541
- } else if (scrollTop > 0 && y - top < 50) {
542
- const el = document.getElementById(id) as HTMLElement;
543
- el.scrollTo({ left: 0, top: 0, behavior: "smooth" });
544
- scrolling.scrollTop = 0;
545
- } else {
546
- return false;
547
- }
548
- } else {
549
- return false;
550
- }
551
- }