@griddle/vue 0.1.5 → 0.1.7
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/GriddleGrid.vue.d.ts.map +1 -1
- package/dist/index.js +547 -530
- package/dist/index.js.map +1 -1
- package/dist/interaction.d.ts +19 -0
- package/dist/interaction.d.ts.map +1 -0
- package/dist/interaction.js +26 -0
- package/dist/interaction.js.map +1 -0
- package/package.json +3 -3
- package/src/GriddleGrid.vue +28 -8
- package/src/interaction.ts +53 -0
package/src/GriddleGrid.vue
CHANGED
|
@@ -112,6 +112,11 @@ import {
|
|
|
112
112
|
import type { TileLayout } from '@griddle/core';
|
|
113
113
|
import type { GriddleApi } from './useGriddle.js';
|
|
114
114
|
import { animateReposition, liftTransition } from './animation.js';
|
|
115
|
+
import {
|
|
116
|
+
measureInteractionScale,
|
|
117
|
+
toLocalInteractionDelta,
|
|
118
|
+
type InteractionScale,
|
|
119
|
+
} from './interaction.js';
|
|
115
120
|
|
|
116
121
|
const props = defineProps<{
|
|
117
122
|
api: GriddleApi;
|
|
@@ -208,6 +213,7 @@ interface DragVisual {
|
|
|
208
213
|
const drag = ref<DragVisual | null>(null);
|
|
209
214
|
let dragStartPointerX = 0;
|
|
210
215
|
let dragStartPointerY = 0;
|
|
216
|
+
let interactionScale: InteractionScale = { x: 1, y: 1 };
|
|
211
217
|
|
|
212
218
|
interface GroupDragVisual {
|
|
213
219
|
tileIds: string[];
|
|
@@ -277,6 +283,7 @@ function beginPendingDrag(pending: PendingDragState): boolean {
|
|
|
277
283
|
|
|
278
284
|
dragStartPointerX = pending.startPointerX;
|
|
279
285
|
dragStartPointerY = pending.startPointerY;
|
|
286
|
+
interactionScale = measureInteractionScale(scrollEl.value);
|
|
280
287
|
|
|
281
288
|
if (pending.mode === 'pin') {
|
|
282
289
|
const layout = computeTileLayout({
|
|
@@ -411,6 +418,7 @@ function onBackgroundPointerDown(e: PointerEvent) {
|
|
|
411
418
|
function onResizeHandleDown(e: PointerEvent, tile: Tile, c: Corner) {
|
|
412
419
|
if (tile.resizable === false) return;
|
|
413
420
|
(e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);
|
|
421
|
+
interactionScale = measureInteractionScale(scrollEl.value);
|
|
414
422
|
resize.value = {
|
|
415
423
|
tileId: tile.id,
|
|
416
424
|
corner: c,
|
|
@@ -461,15 +469,21 @@ function onPointerMove(e: PointerEvent) {
|
|
|
461
469
|
const d = drag.value;
|
|
462
470
|
const r = resize.value;
|
|
463
471
|
if (pd) {
|
|
464
|
-
const dx
|
|
465
|
-
|
|
472
|
+
const { dx, dy } = toLocalInteractionDelta(
|
|
473
|
+
e.clientX - pd.startPointerX,
|
|
474
|
+
e.clientY - pd.startPointerY,
|
|
475
|
+
interactionScale,
|
|
476
|
+
);
|
|
466
477
|
const newPinPx = { x: pd.startPinPx.x + dx, y: pd.startPinPx.y + dy };
|
|
467
478
|
const newPin = pixelsToPin(newPinPx, config.value);
|
|
468
479
|
props.api.grid.setTilePinned(pd.tileId, newPin);
|
|
469
480
|
}
|
|
470
481
|
if (gd) {
|
|
471
|
-
const dx
|
|
472
|
-
|
|
482
|
+
const { dx, dy } = toLocalInteractionDelta(
|
|
483
|
+
e.clientX - dragStartPointerX,
|
|
484
|
+
e.clientY - dragStartPointerY,
|
|
485
|
+
interactionScale,
|
|
486
|
+
);
|
|
473
487
|
const dcol = Math.round(dx / colSize.value);
|
|
474
488
|
const drow = Math.round(dy / rowSize.value);
|
|
475
489
|
const result = groupDragController.update({ dcol, drow });
|
|
@@ -483,8 +497,11 @@ function onPointerMove(e: PointerEvent) {
|
|
|
483
497
|
if (result.changed) syncTiles();
|
|
484
498
|
}
|
|
485
499
|
if (d) {
|
|
486
|
-
const dx
|
|
487
|
-
|
|
500
|
+
const { dx, dy } = toLocalInteractionDelta(
|
|
501
|
+
e.clientX - dragStartPointerX,
|
|
502
|
+
e.clientY - dragStartPointerY,
|
|
503
|
+
interactionScale,
|
|
504
|
+
);
|
|
488
505
|
const candidateCol = d.pickupCol + Math.round(dx / colSize.value);
|
|
489
506
|
const candidateRow = d.pickupRow + Math.round(dy / rowSize.value);
|
|
490
507
|
const result = dragController.update({ col: candidateCol, row: candidateRow });
|
|
@@ -501,8 +518,11 @@ function onPointerMove(e: PointerEvent) {
|
|
|
501
518
|
if (result.changed) syncTiles();
|
|
502
519
|
}
|
|
503
520
|
if (r) {
|
|
504
|
-
const dx
|
|
505
|
-
|
|
521
|
+
const { dx, dy } = toLocalInteractionDelta(
|
|
522
|
+
e.clientX - r.startPointerX,
|
|
523
|
+
e.clientY - r.startPointerY,
|
|
524
|
+
interactionScale,
|
|
525
|
+
);
|
|
506
526
|
let dw = 0, dh = 0, dcol = 0, drow = 0;
|
|
507
527
|
const stepsX = Math.round(dx / colSize.value);
|
|
508
528
|
const stepsY = Math.round(dy / rowSize.value);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface InteractionScale {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
type MeasurableElement = Pick<
|
|
7
|
+
HTMLElement,
|
|
8
|
+
'getBoundingClientRect' | 'offsetWidth' | 'offsetHeight'
|
|
9
|
+
>;
|
|
10
|
+
|
|
11
|
+
function validScale(value: number): number | null {
|
|
12
|
+
return Number.isFinite(value) && value > 0 ? value : null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Measure how CSS transforms map an element's local coordinate space into
|
|
17
|
+
* viewport pixels. PointerEvent.clientX/clientY are viewport coordinates,
|
|
18
|
+
* while Griddle's cells and inline transforms use the element's local CSS
|
|
19
|
+
* pixels, so drag math must cross this boundary explicitly.
|
|
20
|
+
*/
|
|
21
|
+
export function measureInteractionScale(
|
|
22
|
+
element: MeasurableElement | null,
|
|
23
|
+
): InteractionScale {
|
|
24
|
+
if (!element) return { x: 1, y: 1 };
|
|
25
|
+
|
|
26
|
+
const rect = element.getBoundingClientRect();
|
|
27
|
+
const measuredX = validScale(
|
|
28
|
+
element.offsetWidth > 0 ? rect.width / element.offsetWidth : NaN,
|
|
29
|
+
);
|
|
30
|
+
const measuredY = validScale(
|
|
31
|
+
element.offsetHeight > 0 ? rect.height / element.offsetHeight : NaN,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// A content-sized grid can temporarily report a zero height while mounting.
|
|
35
|
+
// Prefer the other measured axis before falling back to an unscaled value;
|
|
36
|
+
// this also handles the common uniform transform: scale(...) host.
|
|
37
|
+
return {
|
|
38
|
+
x: measuredX ?? measuredY ?? 1,
|
|
39
|
+
y: measuredY ?? measuredX ?? 1,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Convert a viewport-space pointer delta into the grid's local CSS pixels. */
|
|
44
|
+
export function toLocalInteractionDelta(
|
|
45
|
+
dx: number,
|
|
46
|
+
dy: number,
|
|
47
|
+
scale: InteractionScale,
|
|
48
|
+
): { dx: number; dy: number } {
|
|
49
|
+
return {
|
|
50
|
+
dx: dx / scale.x,
|
|
51
|
+
dy: dy / scale.y,
|
|
52
|
+
};
|
|
53
|
+
}
|