regular-layout 0.2.1 → 0.3.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.
- package/dist/index.js +6 -6
- package/dist/index.js.map +4 -4
- package/dist/layout/calculate_edge.d.ts +2 -2
- package/dist/layout/calculate_path.d.ts +12 -0
- package/dist/layout/generate_grid.d.ts +3 -3
- package/dist/layout/generate_overlay.d.ts +1 -1
- package/dist/layout/insert_child.d.ts +2 -2
- package/dist/layout/redistribute_panel_sizes.d.ts +2 -2
- package/dist/layout/types.d.ts +11 -11
- package/dist/regular-layout-frame.d.ts +10 -3
- package/dist/regular-layout.d.ts +58 -14
- package/package.json +4 -2
- package/src/layout/calculate_edge.ts +19 -8
- package/src/layout/calculate_intersect.ts +11 -5
- package/src/layout/calculate_path.ts +53 -0
- package/src/layout/flatten.ts +3 -3
- package/src/layout/generate_grid.ts +8 -8
- package/src/layout/generate_overlay.ts +1 -1
- package/src/layout/insert_child.ts +21 -21
- package/src/layout/redistribute_panel_sizes.ts +20 -16
- package/src/layout/remove_child.ts +11 -11
- package/src/layout/types.ts +13 -13
- package/src/regular-layout-frame.ts +53 -68
- package/src/regular-layout-tab.ts +5 -5
- package/src/regular-layout.ts +146 -105
package/src/regular-layout.ts
CHANGED
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
TabLayout,
|
|
26
26
|
OverlayMode,
|
|
27
27
|
Orientation,
|
|
28
|
+
LayoutPathTraversal,
|
|
28
29
|
} from "./layout/types.ts";
|
|
29
30
|
import { calculate_intersection } from "./layout/calculate_intersect.ts";
|
|
30
31
|
import { remove_child } from "./layout/remove_child.ts";
|
|
@@ -33,12 +34,23 @@ import { redistribute_panel_sizes } from "./layout/redistribute_panel_sizes.ts";
|
|
|
33
34
|
import { updateOverlaySheet } from "./layout/generate_overlay.ts";
|
|
34
35
|
import { calculate_edge } from "./layout/calculate_edge.ts";
|
|
35
36
|
import { flatten } from "./layout/flatten.ts";
|
|
37
|
+
import { calculate_path } from "./layout/calculate_path.ts";
|
|
36
38
|
import {
|
|
37
39
|
DEFAULT_PHYSICS,
|
|
38
40
|
type PhysicsUpdate,
|
|
39
41
|
type Physics,
|
|
40
42
|
} from "./layout/constants.ts";
|
|
41
43
|
|
|
44
|
+
/**
|
|
45
|
+
* An interface which models the fields of `PointerEvent` that
|
|
46
|
+
* `<regular-layour>` actually uses, making it easier to sub out with an
|
|
47
|
+
* JavaScript object lieral when you don't have a `PointerEvent` handy.
|
|
48
|
+
*/
|
|
49
|
+
export interface PointerEventCoordinates {
|
|
50
|
+
clientX: number;
|
|
51
|
+
clientY: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
42
54
|
/**
|
|
43
55
|
* A Web Component that provides a resizable panel layout system.
|
|
44
56
|
* Panels are arranged using CSS Grid and can be resized by dragging dividers.
|
|
@@ -71,6 +83,22 @@ import {
|
|
|
71
83
|
* layout.restore(state);
|
|
72
84
|
* ```
|
|
73
85
|
*
|
|
86
|
+
* @remarks
|
|
87
|
+
*
|
|
88
|
+
* Why does this implementation use a `<slot>` at all? We must use
|
|
89
|
+
* `<slot>` and the Shadow DOM to scope the grid CSS rules to each
|
|
90
|
+
* instance of `<regular-layout>` (without e.g. giving them unique
|
|
91
|
+
* `"id"` and injecting into `document,head`), and we can only select
|
|
92
|
+
* `::slotted` light DOM children from `adoptedStyleSheets` on the
|
|
93
|
+
* `ShadowRoot`.
|
|
94
|
+
*
|
|
95
|
+
* Why does this implementation use a single `<slot>` and the child
|
|
96
|
+
* `"name"` attribute, as opposed to a named `<slot name="my_slot">`
|
|
97
|
+
* and the built-in `"slot"` child attribute? Children with a `"slot"`
|
|
98
|
+
* attribute don't fallback to the un-named `<slot>`, so using the
|
|
99
|
+
* latter implementation would require synchronizing the light DOM
|
|
100
|
+
* and shadow DOM slots/slotted children continuously.
|
|
101
|
+
*
|
|
74
102
|
*/
|
|
75
103
|
export class RegularLayout extends HTMLElement {
|
|
76
104
|
private _shadowRoot: ShadowRoot;
|
|
@@ -86,17 +114,6 @@ export class RegularLayout extends HTMLElement {
|
|
|
86
114
|
super();
|
|
87
115
|
this._physics = DEFAULT_PHYSICS;
|
|
88
116
|
this._panel = structuredClone(EMPTY_PANEL);
|
|
89
|
-
|
|
90
|
-
// Why does this implementation use a `<slot>` at all? We must use
|
|
91
|
-
// `<slot>` and the Shadow DOM to scope the grid CSS rules to each
|
|
92
|
-
// instance of `<regular-layout>` (without e.g. giving them unique
|
|
93
|
-
// `"id"` and injecting into `document,head`), and we can only select
|
|
94
|
-
// `::slotted` light DOM children from `adoptedStyleSheets` on the
|
|
95
|
-
// `ShadowRoot`.
|
|
96
|
-
|
|
97
|
-
// In addition, this model uses a single un-named `<slot>` to host all
|
|
98
|
-
// light-DOM children, and the child's `"name"` attribute to identify
|
|
99
|
-
// its position in the `Layout`. Alternatively, using named
|
|
100
117
|
this._shadowRoot = this.attachShadow({ mode: "open" });
|
|
101
118
|
this._shadowRoot.innerHTML = `<slot></slot>`;
|
|
102
119
|
this._stylesheet = new CSSStyleSheet();
|
|
@@ -109,12 +126,14 @@ export class RegularLayout extends HTMLElement {
|
|
|
109
126
|
}
|
|
110
127
|
|
|
111
128
|
connectedCallback() {
|
|
129
|
+
this.addEventListener("dblclick", this.onDblClick);
|
|
112
130
|
this.addEventListener("pointerdown", this.onPointerDown);
|
|
113
131
|
this.addEventListener("pointerup", this.onPointerUp);
|
|
114
132
|
this.addEventListener("pointermove", this.onPointerMove);
|
|
115
133
|
}
|
|
116
134
|
|
|
117
135
|
disconnectedCallback() {
|
|
136
|
+
this.removeEventListener("dblclick", this.onDblClick);
|
|
118
137
|
this.removeEventListener("pointerdown", this.onPointerDown);
|
|
119
138
|
this.removeEventListener("pointerup", this.onPointerUp);
|
|
120
139
|
this.removeEventListener("pointermove", this.onPointerMove);
|
|
@@ -123,36 +142,33 @@ export class RegularLayout extends HTMLElement {
|
|
|
123
142
|
/**
|
|
124
143
|
* Determines which panel is at a given screen coordinate.
|
|
125
144
|
*
|
|
126
|
-
* @param
|
|
127
|
-
*
|
|
145
|
+
* @param coordinates - `PointerEvent`, `MouseEvent`, or just X and Y
|
|
146
|
+
* coordinates in screen pixels.
|
|
128
147
|
* @returns Panel information if a panel is at that position, null otherwise.
|
|
129
148
|
*/
|
|
130
149
|
calculateIntersect = (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const panel = calculate_intersection(
|
|
137
|
-
col,
|
|
138
|
-
row,
|
|
139
|
-
this._panel,
|
|
140
|
-
check_dividers ? { rect, size: this._physics.GRID_DIVIDER_SIZE } : null,
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
if (panel?.type === "layout-path") {
|
|
144
|
-
return { ...panel, layout: this.save() };
|
|
145
|
-
}
|
|
150
|
+
coordinates: PointerEventCoordinates,
|
|
151
|
+
): LayoutPath | null => {
|
|
152
|
+
const [col, row, _] = this.relativeCoordinates(coordinates, false);
|
|
153
|
+
return calculate_intersection(col, row, this._panel);
|
|
154
|
+
};
|
|
146
155
|
|
|
147
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Calculates the index path for a panel with the given name.
|
|
158
|
+
*
|
|
159
|
+
* @param name - The name of the panel to find.
|
|
160
|
+
* @returns The panel's index path if found, `null` otherwise.
|
|
161
|
+
*/
|
|
162
|
+
calculatePath = (name: string): number[] | null => {
|
|
163
|
+
return calculate_path(name, this._panel);
|
|
148
164
|
};
|
|
149
165
|
|
|
150
166
|
/**
|
|
151
167
|
* Sets the visual overlay state during drag-and-drop operations.
|
|
152
168
|
* Displays a preview of where a panel would be placed at the given coordinates.
|
|
153
169
|
*
|
|
154
|
-
* @param
|
|
155
|
-
*
|
|
170
|
+
* @param event - `PointerEvent`, `MouseEvent`, or just X and Y
|
|
171
|
+
* coordinates in screen pixels.
|
|
156
172
|
* @param dragTarget - A `LayoutPath` (presumably from `calculateIntersect`)
|
|
157
173
|
* which points to the drag element in the current layout.
|
|
158
174
|
* @param className - The CSS class name to use for the overlay panel
|
|
@@ -162,18 +178,20 @@ export class RegularLayout extends HTMLElement {
|
|
|
162
178
|
* "absolute".
|
|
163
179
|
*/
|
|
164
180
|
setOverlayState = (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
{ slot }: LayoutPath<unknown>,
|
|
181
|
+
event: PointerEventCoordinates,
|
|
182
|
+
{ slot }: LayoutPath,
|
|
168
183
|
className: string = this._physics.OVERLAY_CLASSNAME,
|
|
169
184
|
mode: OverlayMode = this._physics.OVERLAY_DEFAULT,
|
|
170
185
|
) => {
|
|
171
186
|
const panel = remove_child(this._panel, slot);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
187
|
+
const query = `:scope > [${this._physics.CHILD_ATTRIBUTE_NAME}="${slot}"]`;
|
|
188
|
+
const drag_element = this.querySelector(query);
|
|
189
|
+
if (drag_element) {
|
|
190
|
+
drag_element.classList.add(className);
|
|
191
|
+
}
|
|
175
192
|
|
|
176
|
-
|
|
193
|
+
// TODO: Don't recalculate box (but this currently protects against resize).
|
|
194
|
+
const [col, row, box, style] = this.relativeCoordinates(event, true);
|
|
177
195
|
let drop_target = calculate_intersection(col, row, panel);
|
|
178
196
|
if (drop_target) {
|
|
179
197
|
drop_target = calculate_edge(
|
|
@@ -193,7 +211,6 @@ export class RegularLayout extends HTMLElement {
|
|
|
193
211
|
this._stylesheet.replaceSync(css);
|
|
194
212
|
} else if (mode === "absolute") {
|
|
195
213
|
const grid_css = create_css_grid_layout(panel, undefined, this._physics);
|
|
196
|
-
|
|
197
214
|
const overlay_css = updateOverlaySheet(
|
|
198
215
|
slot,
|
|
199
216
|
box,
|
|
@@ -206,15 +223,15 @@ export class RegularLayout extends HTMLElement {
|
|
|
206
223
|
}
|
|
207
224
|
|
|
208
225
|
const event_name = `${this._physics.CUSTOM_EVENT_NAME_PREFIX}-before-update`;
|
|
209
|
-
const
|
|
210
|
-
this.dispatchEvent(
|
|
226
|
+
const custom_event = new CustomEvent<Layout>(event_name, { detail: panel });
|
|
227
|
+
this.dispatchEvent(custom_event);
|
|
211
228
|
};
|
|
212
229
|
|
|
213
230
|
/**
|
|
214
231
|
* Clears the overlay state and commits the panel placement.
|
|
215
232
|
*
|
|
216
|
-
* @param
|
|
217
|
-
*
|
|
233
|
+
* @param event - `PointerEvent`, `MouseEvent`, or just X and Y
|
|
234
|
+
* coordinates in screen pixels.
|
|
218
235
|
* @param dragTarget - A `LayoutPath` (presumably from `calculateIntersect`)
|
|
219
236
|
* which points to the drag element in the current layout.
|
|
220
237
|
* @param className - The CSS class name to use for the overlay panel
|
|
@@ -223,46 +240,53 @@ export class RegularLayout extends HTMLElement {
|
|
|
223
240
|
* passed to `setOverlayState`. Defaults to "absolute".
|
|
224
241
|
*/
|
|
225
242
|
clearOverlayState = (
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
drag_target: LayoutPath<Layout>,
|
|
243
|
+
event: PointerEventCoordinates | null,
|
|
244
|
+
{ slot, layout }: LayoutPath,
|
|
229
245
|
className: string = this._physics.OVERLAY_CLASSNAME,
|
|
230
246
|
) => {
|
|
231
247
|
let panel = this._panel;
|
|
232
|
-
panel = remove_child(panel,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
248
|
+
panel = remove_child(panel, slot);
|
|
249
|
+
const query = `:scope > [${this._physics.CHILD_ATTRIBUTE_NAME}="${slot}"]`;
|
|
250
|
+
const drag_element = this.querySelector(query);
|
|
251
|
+
if (drag_element) {
|
|
252
|
+
drag_element.classList.remove(className);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (event === null) {
|
|
256
|
+
this.restore(layout);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const [col, row, box] = this.relativeCoordinates(event, false);
|
|
242
261
|
let drop_target = calculate_intersection(col, row, panel);
|
|
243
262
|
if (drop_target) {
|
|
244
263
|
drop_target = calculate_edge(
|
|
245
264
|
col,
|
|
246
265
|
row,
|
|
247
266
|
panel,
|
|
248
|
-
|
|
267
|
+
slot,
|
|
249
268
|
drop_target,
|
|
250
269
|
box,
|
|
251
270
|
this._physics,
|
|
252
271
|
);
|
|
253
272
|
}
|
|
254
273
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
274
|
+
if (drop_target) {
|
|
275
|
+
const orientation = drop_target?.is_edge
|
|
276
|
+
? drop_target.orientation
|
|
277
|
+
: undefined;
|
|
278
|
+
|
|
279
|
+
const new_layout = insert_child(
|
|
280
|
+
panel,
|
|
281
|
+
slot,
|
|
282
|
+
drop_target.path,
|
|
283
|
+
orientation,
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
this.restore(new_layout);
|
|
287
|
+
} else {
|
|
288
|
+
this.restore(layout);
|
|
289
|
+
}
|
|
266
290
|
};
|
|
267
291
|
|
|
268
292
|
/**
|
|
@@ -278,7 +302,7 @@ export class RegularLayout extends HTMLElement {
|
|
|
278
302
|
*/
|
|
279
303
|
insertPanel = (
|
|
280
304
|
name: string,
|
|
281
|
-
path:
|
|
305
|
+
path: LayoutPathTraversal = [],
|
|
282
306
|
split?: boolean | Orientation,
|
|
283
307
|
) => {
|
|
284
308
|
let orientation: Orientation | undefined;
|
|
@@ -308,10 +332,11 @@ export class RegularLayout extends HTMLElement {
|
|
|
308
332
|
* @returns The TabLayout containing the panel if found, null otherwise.
|
|
309
333
|
*/
|
|
310
334
|
getPanel = (name: string, layout: Layout = this._panel): TabLayout | null => {
|
|
311
|
-
if (layout.type === "
|
|
312
|
-
if (layout.
|
|
335
|
+
if (layout.type === "tab-layout") {
|
|
336
|
+
if (layout.tabs.includes(name)) {
|
|
313
337
|
return layout;
|
|
314
338
|
}
|
|
339
|
+
|
|
315
340
|
return null;
|
|
316
341
|
}
|
|
317
342
|
|
|
@@ -347,7 +372,6 @@ export class RegularLayout extends HTMLElement {
|
|
|
347
372
|
restore = (layout: Layout, _is_flattened: boolean = false) => {
|
|
348
373
|
this._panel = !_is_flattened ? flatten(layout) : layout;
|
|
349
374
|
const css = create_css_grid_layout(this._panel, undefined, this._physics);
|
|
350
|
-
|
|
351
375
|
this._stylesheet.replaceSync(css);
|
|
352
376
|
const event_name = `${this._physics.CUSTOM_EVENT_NAME_PREFIX}-update`;
|
|
353
377
|
const event = new CustomEvent<Layout>(event_name, { detail: this._panel });
|
|
@@ -397,16 +421,15 @@ export class RegularLayout extends HTMLElement {
|
|
|
397
421
|
* Transforms absolute pixel positions into normalized coordinates (0-1 range)
|
|
398
422
|
* relative to the layout's bounding box.
|
|
399
423
|
*
|
|
400
|
-
* @param
|
|
401
|
-
*
|
|
424
|
+
* @param coordinates - `PointerEvent`, `MouseEvent`, or just X and Y
|
|
425
|
+
* coordinates in screen pixels.
|
|
402
426
|
* @returns A tuple containing:
|
|
403
427
|
* - col: Normalized X coordinate (0 = left edge, 1 = right edge)
|
|
404
428
|
* - row: Normalized Y coordinate (0 = top edge, 1 = bottom edge)
|
|
405
429
|
* - box: The layout element's bounding rectangle
|
|
406
430
|
*/
|
|
407
431
|
relativeCoordinates = (
|
|
408
|
-
|
|
409
|
-
clientY: number,
|
|
432
|
+
event: PointerEventCoordinates,
|
|
410
433
|
recalculate_bounds: boolean = true,
|
|
411
434
|
): [number, number, DOMRect, CSSStyleDeclaration] => {
|
|
412
435
|
if (recalculate_bounds || !this._dimensions) {
|
|
@@ -419,12 +442,13 @@ export class RegularLayout extends HTMLElement {
|
|
|
419
442
|
const box = this._dimensions.box;
|
|
420
443
|
const style = this._dimensions.style;
|
|
421
444
|
const col =
|
|
422
|
-
(clientX - box.left - parseFloat(style.paddingLeft)) /
|
|
445
|
+
(event.clientX - box.left - parseFloat(style.paddingLeft)) /
|
|
423
446
|
(box.width -
|
|
424
447
|
parseFloat(style.paddingLeft) -
|
|
425
448
|
parseFloat(style.paddingRight));
|
|
449
|
+
|
|
426
450
|
const row =
|
|
427
|
-
(clientY - box.top - parseFloat(style.paddingTop)) /
|
|
451
|
+
(event.clientY - box.top - parseFloat(style.paddingTop)) /
|
|
428
452
|
(box.height -
|
|
429
453
|
parseFloat(style.paddingTop) -
|
|
430
454
|
parseFloat(style.paddingBottom));
|
|
@@ -432,17 +456,49 @@ export class RegularLayout extends HTMLElement {
|
|
|
432
456
|
return [col, row, box, style];
|
|
433
457
|
};
|
|
434
458
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
459
|
+
/**
|
|
460
|
+
* Calculates the Euclidean distance in pixels between the current pointer
|
|
461
|
+
* coordinates and a drag target's position within the layout.
|
|
462
|
+
*
|
|
463
|
+
* @param coordinates - The current pointer event coordinates.
|
|
464
|
+
* @param drag_target - The layout path representing the drag target
|
|
465
|
+
* position.
|
|
466
|
+
* @returns The distance in pixels between the coordinates and the drag
|
|
467
|
+
* target.
|
|
468
|
+
*/
|
|
469
|
+
diffCoordinates = (
|
|
470
|
+
event: PointerEventCoordinates,
|
|
471
|
+
drag_target: LayoutPath,
|
|
472
|
+
): number => {
|
|
473
|
+
const [column, row, box] = this.relativeCoordinates(event, false);
|
|
474
|
+
const dx = (column - drag_target.column) * box.width;
|
|
475
|
+
const dy = (row - drag_target.row) * box.height;
|
|
476
|
+
return Math.sqrt(dx ** 2 + dy ** 2);
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
private onDblClick = (event: MouseEvent) => {
|
|
480
|
+
const [col, row, rect] = this.relativeCoordinates(event, false);
|
|
481
|
+
const divider = calculate_intersection(col, row, this._panel, {
|
|
482
|
+
rect,
|
|
483
|
+
size: this._physics.GRID_DIVIDER_SIZE,
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
if (divider?.type === "horizontal" || divider?.type === "vertical") {
|
|
487
|
+
const panel = redistribute_panel_sizes(
|
|
488
|
+
this._panel,
|
|
489
|
+
divider.path,
|
|
490
|
+
undefined,
|
|
440
491
|
);
|
|
441
492
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
493
|
+
this.restore(panel, true);
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
private onPointerDown = (event: PointerEvent) => {
|
|
498
|
+
if (!this._physics.GRID_DIVIDER_CHECK_TARGET || event.target === this) {
|
|
499
|
+
const [col, row, rect] = this.relativeCoordinates(event);
|
|
500
|
+
const size = this._physics.GRID_DIVIDER_SIZE;
|
|
501
|
+
const hit = calculate_intersection(col, row, this._panel, { rect, size });
|
|
446
502
|
if (hit && hit.type !== "layout-path") {
|
|
447
503
|
this._drag_target = [hit, col, row];
|
|
448
504
|
this.setPointerCapture(event.pointerId);
|
|
@@ -453,12 +509,7 @@ export class RegularLayout extends HTMLElement {
|
|
|
453
509
|
|
|
454
510
|
private onPointerMove = (event: PointerEvent) => {
|
|
455
511
|
if (this._drag_target) {
|
|
456
|
-
const [col, row] = this.relativeCoordinates(
|
|
457
|
-
event.clientX,
|
|
458
|
-
event.clientY,
|
|
459
|
-
false,
|
|
460
|
-
);
|
|
461
|
-
|
|
512
|
+
const [col, row] = this.relativeCoordinates(event, false);
|
|
462
513
|
const [{ path, type }, old_col, old_row] = this._drag_target;
|
|
463
514
|
const offset = type === "horizontal" ? old_col - col : old_row - row;
|
|
464
515
|
const panel = redistribute_panel_sizes(this._panel, path, offset);
|
|
@@ -476,12 +527,7 @@ export class RegularLayout extends HTMLElement {
|
|
|
476
527
|
return;
|
|
477
528
|
}
|
|
478
529
|
|
|
479
|
-
const [col, row, rect] = this.relativeCoordinates(
|
|
480
|
-
event.clientX,
|
|
481
|
-
event.clientY,
|
|
482
|
-
false,
|
|
483
|
-
);
|
|
484
|
-
|
|
530
|
+
const [col, row, rect] = this.relativeCoordinates(event, false);
|
|
485
531
|
const divider = calculate_intersection(col, row, this._panel, {
|
|
486
532
|
rect,
|
|
487
533
|
size: this._physics.GRID_DIVIDER_SIZE,
|
|
@@ -502,12 +548,7 @@ export class RegularLayout extends HTMLElement {
|
|
|
502
548
|
private onPointerUp = (event: PointerEvent) => {
|
|
503
549
|
if (this._drag_target) {
|
|
504
550
|
this.releasePointerCapture(event.pointerId);
|
|
505
|
-
const [col, row] = this.relativeCoordinates(
|
|
506
|
-
event.clientX,
|
|
507
|
-
event.clientY,
|
|
508
|
-
false,
|
|
509
|
-
);
|
|
510
|
-
|
|
551
|
+
const [col, row] = this.relativeCoordinates(event, false);
|
|
511
552
|
const [{ path, type }, old_col, old_row] = this._drag_target;
|
|
512
553
|
const offset = type === "horizontal" ? old_col - col : old_row - row;
|
|
513
554
|
const panel = redistribute_panel_sizes(this._panel, path, offset);
|