react-native-smart-grid 0.1.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/LICENSE +20 -0
- package/README.md +554 -0
- package/lib/module/components/DragLayer.js +71 -0
- package/lib/module/components/DragLayer.js.map +1 -0
- package/lib/module/components/DraggableTile.js +79 -0
- package/lib/module/components/DraggableTile.js.map +1 -0
- package/lib/module/components/GhostTile.js +37 -0
- package/lib/module/components/GhostTile.js.map +1 -0
- package/lib/module/components/GridTile.js +25 -0
- package/lib/module/components/GridTile.js.map +1 -0
- package/lib/module/components/ResizeHandle.js +72 -0
- package/lib/module/components/ResizeHandle.js.map +1 -0
- package/lib/module/components/SmartGrid.js +363 -0
- package/lib/module/components/SmartGrid.js.map +1 -0
- package/lib/module/context/GridDragContext.js +130 -0
- package/lib/module/context/GridDragContext.js.map +1 -0
- package/lib/module/engine/GridEngine.js +148 -0
- package/lib/module/engine/GridEngine.js.map +1 -0
- package/lib/module/engine/autoArrange.js +54 -0
- package/lib/module/engine/autoArrange.js.map +1 -0
- package/lib/module/engine/collisions.js +67 -0
- package/lib/module/engine/collisions.js.map +1 -0
- package/lib/module/hooks/useTileGesture.js +62 -0
- package/lib/module/hooks/useTileGesture.js.map +1 -0
- package/lib/module/index.js +9 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/layout/LayoutCalculator.js +29 -0
- package/lib/module/layout/LayoutCalculator.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/pixelToGrid.js +22 -0
- package/lib/module/utils/pixelToGrid.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/components/DragLayer.d.ts +11 -0
- package/lib/typescript/src/components/DragLayer.d.ts.map +1 -0
- package/lib/typescript/src/components/DraggableTile.d.ts +14 -0
- package/lib/typescript/src/components/DraggableTile.d.ts.map +1 -0
- package/lib/typescript/src/components/GhostTile.d.ts +9 -0
- package/lib/typescript/src/components/GhostTile.d.ts.map +1 -0
- package/lib/typescript/src/components/GridTile.d.ts +9 -0
- package/lib/typescript/src/components/GridTile.d.ts.map +1 -0
- package/lib/typescript/src/components/ResizeHandle.d.ts +9 -0
- package/lib/typescript/src/components/ResizeHandle.d.ts.map +1 -0
- package/lib/typescript/src/components/SmartGrid.d.ts +214 -0
- package/lib/typescript/src/components/SmartGrid.d.ts.map +1 -0
- package/lib/typescript/src/context/GridDragContext.d.ts +44 -0
- package/lib/typescript/src/context/GridDragContext.d.ts.map +1 -0
- package/lib/typescript/src/engine/GridEngine.d.ts +35 -0
- package/lib/typescript/src/engine/GridEngine.d.ts.map +1 -0
- package/lib/typescript/src/engine/autoArrange.d.ts +4 -0
- package/lib/typescript/src/engine/autoArrange.d.ts.map +1 -0
- package/lib/typescript/src/engine/collisions.d.ts +3 -0
- package/lib/typescript/src/engine/collisions.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useTileGesture.d.ts +13 -0
- package/lib/typescript/src/hooks/useTileGesture.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/layout/LayoutCalculator.d.ts +15 -0
- package/lib/typescript/src/layout/LayoutCalculator.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +105 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/pixelToGrid.d.ts +9 -0
- package/lib/typescript/src/utils/pixelToGrid.d.ts.map +1 -0
- package/package.json +161 -0
- package/src/components/DragLayer.tsx +71 -0
- package/src/components/DraggableTile.tsx +88 -0
- package/src/components/GhostTile.tsx +42 -0
- package/src/components/GridTile.tsx +27 -0
- package/src/components/ResizeHandle.tsx +74 -0
- package/src/components/SmartGrid.tsx +506 -0
- package/src/context/GridDragContext.tsx +191 -0
- package/src/engine/GridEngine.ts +148 -0
- package/src/engine/autoArrange.ts +59 -0
- package/src/engine/collisions.ts +87 -0
- package/src/hooks/useTileGesture.ts +88 -0
- package/src/index.tsx +29 -0
- package/src/layout/LayoutCalculator.ts +50 -0
- package/src/types.ts +113 -0
- package/src/utils/pixelToGrid.ts +31 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, useRef, useState } from 'react';
|
|
4
|
+
import { useSharedValue } from 'react-native-reanimated';
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
const GridDragContext = /*#__PURE__*/createContext(null);
|
|
7
|
+
export function useGridDrag() {
|
|
8
|
+
const ctx = useContext(GridDragContext);
|
|
9
|
+
if (!ctx) throw new Error('useGridDrag must be used within SmartGrid');
|
|
10
|
+
return ctx;
|
|
11
|
+
}
|
|
12
|
+
export function GridDragProvider({
|
|
13
|
+
children,
|
|
14
|
+
isEditing,
|
|
15
|
+
draggable,
|
|
16
|
+
selectable,
|
|
17
|
+
multiSelect,
|
|
18
|
+
selectedTileIds,
|
|
19
|
+
onDrop,
|
|
20
|
+
onResize,
|
|
21
|
+
onSelect,
|
|
22
|
+
onTilePress,
|
|
23
|
+
onHaptic
|
|
24
|
+
}) {
|
|
25
|
+
const dragAbsX = useSharedValue(0);
|
|
26
|
+
const dragAbsY = useSharedValue(0);
|
|
27
|
+
const isDragging = useSharedValue(false);
|
|
28
|
+
const [activeTile, setActiveTile] = useState(null);
|
|
29
|
+
const [ghostPosition, setGhostPosition] = useState(null);
|
|
30
|
+
const [initialRect, setInitialRect] = useState(null);
|
|
31
|
+
const ghostRef = useRef(null);
|
|
32
|
+
const activeTileRef = useRef(null);
|
|
33
|
+
const containerPageX = useRef(0);
|
|
34
|
+
const containerPageY = useRef(0);
|
|
35
|
+
const scrollYRef = useRef(0);
|
|
36
|
+
function startDrag(tile, rect) {
|
|
37
|
+
activeTileRef.current = tile;
|
|
38
|
+
ghostRef.current = tile.position;
|
|
39
|
+
isDragging.value = true;
|
|
40
|
+
setActiveTile(tile);
|
|
41
|
+
setInitialRect(rect);
|
|
42
|
+
setGhostPosition(tile.position);
|
|
43
|
+
onHaptic?.('pick-up');
|
|
44
|
+
}
|
|
45
|
+
function selectTile(tile) {
|
|
46
|
+
const already = selectedTileIds.includes(tile.id);
|
|
47
|
+
if (already) {
|
|
48
|
+
onSelect(selectedTileIds.filter(id => id !== tile.id));
|
|
49
|
+
} else if (multiSelect) {
|
|
50
|
+
onSelect([...selectedTileIds, tile.id]);
|
|
51
|
+
} else {
|
|
52
|
+
onSelect([tile.id]);
|
|
53
|
+
}
|
|
54
|
+
onHaptic?.('pick-up');
|
|
55
|
+
}
|
|
56
|
+
function updateGhost(pos) {
|
|
57
|
+
if (pos.x === ghostRef.current?.x && pos.y === ghostRef.current?.y) return;
|
|
58
|
+
ghostRef.current = pos;
|
|
59
|
+
setGhostPosition(pos);
|
|
60
|
+
onHaptic?.('snap');
|
|
61
|
+
}
|
|
62
|
+
function endDrag(finalPosition) {
|
|
63
|
+
const tile = activeTileRef.current;
|
|
64
|
+
isDragging.value = false;
|
|
65
|
+
activeTileRef.current = null;
|
|
66
|
+
ghostRef.current = null;
|
|
67
|
+
setActiveTile(null);
|
|
68
|
+
setGhostPosition(null);
|
|
69
|
+
setInitialRect(null);
|
|
70
|
+
onHaptic?.('drop');
|
|
71
|
+
if (!tile || !finalPosition) return;
|
|
72
|
+
const stationary = finalPosition.x === tile.position.x && finalPosition.y === tile.position.y;
|
|
73
|
+
if (stationary && selectable && tile.selectable !== false) {
|
|
74
|
+
const already = selectedTileIds.includes(tile.id);
|
|
75
|
+
if (already) {
|
|
76
|
+
onSelect(selectedTileIds.filter(id => id !== tile.id));
|
|
77
|
+
} else if (multiSelect) {
|
|
78
|
+
onSelect([...selectedTileIds, tile.id]);
|
|
79
|
+
} else {
|
|
80
|
+
onSelect([tile.id]);
|
|
81
|
+
}
|
|
82
|
+
} else if (!stationary) {
|
|
83
|
+
onSelect([]);
|
|
84
|
+
onDrop(tile, finalPosition);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function commitResize(tile, newSize) {
|
|
88
|
+
onHaptic?.('resize');
|
|
89
|
+
onResize(tile, newSize);
|
|
90
|
+
}
|
|
91
|
+
function handleTilePress(tile) {
|
|
92
|
+
if (selectable && selectedTileIds.length > 0 && tile.selectable !== false) {
|
|
93
|
+
const already = selectedTileIds.includes(tile.id);
|
|
94
|
+
if (already) {
|
|
95
|
+
onSelect(selectedTileIds.filter(id => id !== tile.id));
|
|
96
|
+
} else if (multiSelect) {
|
|
97
|
+
onSelect([...selectedTileIds, tile.id]);
|
|
98
|
+
} else {
|
|
99
|
+
onSelect([tile.id]);
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
onTilePress?.(tile);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return /*#__PURE__*/_jsx(GridDragContext.Provider, {
|
|
106
|
+
value: {
|
|
107
|
+
dragAbsX,
|
|
108
|
+
dragAbsY,
|
|
109
|
+
isDragging,
|
|
110
|
+
activeTile,
|
|
111
|
+
ghostPosition,
|
|
112
|
+
initialRect,
|
|
113
|
+
selectedTileIds,
|
|
114
|
+
containerPageX,
|
|
115
|
+
containerPageY,
|
|
116
|
+
scrollYRef,
|
|
117
|
+
startDrag,
|
|
118
|
+
updateGhost,
|
|
119
|
+
endDrag,
|
|
120
|
+
selectTile,
|
|
121
|
+
onTilePress: handleTilePress,
|
|
122
|
+
isEditing,
|
|
123
|
+
draggable,
|
|
124
|
+
selectable,
|
|
125
|
+
commitResize
|
|
126
|
+
},
|
|
127
|
+
children: children
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=GridDragContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","createContext","useContext","useRef","useState","useSharedValue","jsx","_jsx","GridDragContext","useGridDrag","ctx","Error","GridDragProvider","children","isEditing","draggable","selectable","multiSelect","selectedTileIds","onDrop","onResize","onSelect","onTilePress","onHaptic","dragAbsX","dragAbsY","isDragging","activeTile","setActiveTile","ghostPosition","setGhostPosition","initialRect","setInitialRect","ghostRef","activeTileRef","containerPageX","containerPageY","scrollYRef","startDrag","tile","rect","current","position","value","selectTile","already","includes","id","filter","updateGhost","pos","x","y","endDrag","finalPosition","stationary","commitResize","newSize","handleTilePress","length","Provider"],"sourceRoot":"..\\..\\..\\src","sources":["context/GridDragContext.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Sentinel value marking a cell as occupied by a tile with the given id.
|
|
4
|
+
// The matrix stores tile ids so we can look up who owns a cell in O(1).
|
|
5
|
+
// null = empty, string = tile id
|
|
6
|
+
|
|
7
|
+
export class GridEngine {
|
|
8
|
+
constructor(columns, initialRows = 20) {
|
|
9
|
+
this.columns = columns;
|
|
10
|
+
this.matrix = GridEngine.createMatrix(columns, initialRows);
|
|
11
|
+
}
|
|
12
|
+
static createMatrix(columns, rows) {
|
|
13
|
+
return Array.from({
|
|
14
|
+
length: rows
|
|
15
|
+
}, () => Array(columns).fill(null));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// ── Accessors ────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
get rowCount() {
|
|
21
|
+
return this.matrix.length;
|
|
22
|
+
}
|
|
23
|
+
get columnCount() {
|
|
24
|
+
return this.columns;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ── Core operations ──────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
isOccupied(pos, size, ignoreId) {
|
|
30
|
+
for (let row = pos.y; row < pos.y + size.h; row++) {
|
|
31
|
+
for (let col = pos.x; col < pos.x + size.w; col++) {
|
|
32
|
+
if (col < 0 || col >= this.columns) return true; // out of bounds
|
|
33
|
+
this.growIfNeeded(row);
|
|
34
|
+
const cell = this.matrix[row][col];
|
|
35
|
+
if (cell !== null && cell !== ignoreId) return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
isInBounds(pos, size) {
|
|
41
|
+
return pos.x >= 0 && pos.x + size.w <= this.columns && pos.y >= 0;
|
|
42
|
+
}
|
|
43
|
+
placeAt(id, pos, size) {
|
|
44
|
+
for (let row = pos.y; row < pos.y + size.h; row++) {
|
|
45
|
+
this.growIfNeeded(row);
|
|
46
|
+
for (let col = pos.x; col < pos.x + size.w; col++) {
|
|
47
|
+
this.matrix[row][col] = id;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
removeFrom(pos, size) {
|
|
52
|
+
for (let row = pos.y; row < pos.y + size.h; row++) {
|
|
53
|
+
if (row >= this.matrix.length) break;
|
|
54
|
+
for (let col = pos.x; col < pos.x + size.w; col++) {
|
|
55
|
+
if (col < this.columns) this.matrix[row][col] = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
removeById(id) {
|
|
60
|
+
for (let row = 0; row < this.matrix.length; row++) {
|
|
61
|
+
for (let col = 0; col < this.columns; col++) {
|
|
62
|
+
if (this.matrix[row][col] === id) {
|
|
63
|
+
this.matrix[row][col] = null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── Placement search ─────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Scan top-left to bottom-right for the first position where `size` fits.
|
|
73
|
+
* Returns null if the grid (up to maxRows) is full.
|
|
74
|
+
*/
|
|
75
|
+
findFirstFit(size, maxRows = this.matrix.length + size.h) {
|
|
76
|
+
for (let row = 0; row < maxRows; row++) {
|
|
77
|
+
this.growIfNeeded(row + size.h - 1);
|
|
78
|
+
for (let col = 0; col <= this.columns - size.w; col++) {
|
|
79
|
+
const pos = {
|
|
80
|
+
x: col,
|
|
81
|
+
y: row
|
|
82
|
+
};
|
|
83
|
+
if (!this.isOccupied(pos, size)) return pos;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Returns ids of all tiles that overlap the given region, excluding ignoreId.
|
|
91
|
+
*/
|
|
92
|
+
getCollisions(pos, size, ignoreId) {
|
|
93
|
+
const hits = new Set();
|
|
94
|
+
for (let row = pos.y; row < pos.y + size.h; row++) {
|
|
95
|
+
if (row >= this.matrix.length) break;
|
|
96
|
+
for (let col = pos.x; col < pos.x + size.w; col++) {
|
|
97
|
+
if (col >= this.columns) break;
|
|
98
|
+
const cell = this.matrix[row][col];
|
|
99
|
+
if (cell !== null && cell !== ignoreId) hits.add(cell);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return hits;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── Serialization ────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Rebuild the entire matrix from a layout snapshot.
|
|
109
|
+
* Call this when restoring a saved layout.
|
|
110
|
+
*/
|
|
111
|
+
loadLayout(items) {
|
|
112
|
+
const maxRow = items.reduce((m, item) => Math.max(m, item.position.y + item.size.h), 0);
|
|
113
|
+
this.matrix = GridEngine.createMatrix(this.columns, Math.max(maxRow + 5, 20));
|
|
114
|
+
for (const item of items) {
|
|
115
|
+
this.placeAt(item.id, item.position, item.size);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Dump the positions of all occupied cells grouped by tile id.
|
|
121
|
+
* Useful for debugging — not the same as a layout snapshot.
|
|
122
|
+
*/
|
|
123
|
+
debugDump() {
|
|
124
|
+
const out = {};
|
|
125
|
+
for (let row = 0; row < this.matrix.length; row++) {
|
|
126
|
+
for (let col = 0; col < this.columns; col++) {
|
|
127
|
+
const id = this.matrix[row][col];
|
|
128
|
+
if (id) {
|
|
129
|
+
if (!out[id]) out[id] = [];
|
|
130
|
+
out[id].push({
|
|
131
|
+
x: col,
|
|
132
|
+
y: row
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── Internal helpers ─────────────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
growIfNeeded(rowIndex) {
|
|
143
|
+
while (this.matrix.length <= rowIndex) {
|
|
144
|
+
this.matrix.push(Array(this.columns).fill(null));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=GridEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["GridEngine","constructor","columns","initialRows","matrix","createMatrix","rows","Array","from","length","fill","rowCount","columnCount","isOccupied","pos","size","ignoreId","row","y","h","col","x","w","growIfNeeded","cell","isInBounds","placeAt","id","removeFrom","removeById","findFirstFit","maxRows","getCollisions","hits","Set","add","loadLayout","items","maxRow","reduce","m","item","Math","max","position","debugDump","out","push","rowIndex"],"sourceRoot":"..\\..\\..\\src","sources":["engine/GridEngine.ts"],"mappings":";;AAEA;AACA;AAC2B;;AAE3B,OAAO,MAAMA,UAAU,CAAC;EAItBC,WAAWA,CAACC,OAAe,EAAEC,WAAW,GAAG,EAAE,EAAE;IAC7C,IAAI,CAACD,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACE,MAAM,GAAGJ,UAAU,CAACK,YAAY,CAACH,OAAO,EAAEC,WAAW,CAAC;EAC7D;EAEA,OAAeE,YAAYA,CAACH,OAAe,EAAEI,IAAY,EAAY;IACnE,OAAOC,KAAK,CAACC,IAAI,CAAC;MAAEC,MAAM,EAAEH;IAAK,CAAC,EAAE,MAAMC,KAAK,CAACL,OAAO,CAAC,CAACQ,IAAI,CAAC,IAAI,CAAC,CAAC;EACtE;;EAEA;;EAEA,IAAIC,QAAQA,CAAA,EAAW;IACrB,OAAO,IAAI,CAACP,MAAM,CAACK,MAAM;EAC3B;EAEA,IAAIG,WAAWA,CAAA,EAAW;IACxB,OAAO,IAAI,CAACV,OAAO;EACrB;;EAEA;;EAEAW,UAAUA,CAACC,GAAiB,EAAEC,IAAc,EAAEC,QAAiB,EAAW;IACxE,KAAK,IAAIC,GAAG,GAAGH,GAAG,CAACI,CAAC,EAAED,GAAG,GAAGH,GAAG,CAACI,CAAC,GAAGH,IAAI,CAACI,CAAC,EAAEF,GAAG,EAAE,EAAE;MACjD,KAAK,IAAIG,GAAG,GAAGN,GAAG,CAACO,CAAC,EAAED,GAAG,GAAGN,GAAG,CAACO,CAAC,GAAGN,IAAI,CAACO,CAAC,EAAEF,GAAG,EAAE,EAAE;QACjD,IAAIA,GAAG,GAAG,CAAC,IAAIA,GAAG,IAAI,IAAI,CAAClB,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC;QACjD,IAAI,CAACqB,YAAY,CAACN,GAAG,CAAC;QACtB,MAAMO,IAAI,GAAG,IAAI,CAACpB,MAAM,CAACa,GAAG,CAAC,CAAEG,GAAG,CAAE;QACpC,IAAII,IAAI,KAAK,IAAI,IAAIA,IAAI,KAAKR,QAAQ,EAAE,OAAO,IAAI;MACrD;IACF;IACA,OAAO,KAAK;EACd;EAEAS,UAAUA,CAACX,GAAiB,EAAEC,IAAc,EAAW;IACrD,OAAOD,GAAG,CAACO,CAAC,IAAI,CAAC,IAAIP,GAAG,CAACO,CAAC,GAAGN,IAAI,CAACO,CAAC,IAAI,IAAI,CAACpB,OAAO,IAAIY,GAAG,CAACI,CAAC,IAAI,CAAC;EACnE;EAEAQ,OAAOA,CAACC,EAAU,EAAEb,GAAiB,EAAEC,IAAc,EAAQ;IAC3D,KAAK,IAAIE,GAAG,GAAGH,GAAG,CAACI,CAAC,EAAED,GAAG,GAAGH,GAAG,CAACI,CAAC,GAAGH,IAAI,CAACI,CAAC,EAAEF,GAAG,EAAE,EAAE;MACjD,IAAI,CAACM,YAAY,CAACN,GAAG,CAAC;MACtB,KAAK,IAAIG,GAAG,GAAGN,GAAG,CAACO,CAAC,EAAED,GAAG,GAAGN,GAAG,CAACO,CAAC,GAAGN,IAAI,CAACO,CAAC,EAAEF,GAAG,EAAE,EAAE;QACjD,IAAI,CAAChB,MAAM,CAACa,GAAG,CAAC,CAAEG,GAAG,CAAC,GAAGO,EAAE;MAC7B;IACF;EACF;EAEAC,UAAUA,CAACd,GAAiB,EAAEC,IAAc,EAAQ;IAClD,KAAK,IAAIE,GAAG,GAAGH,GAAG,CAACI,CAAC,EAAED,GAAG,GAAGH,GAAG,CAACI,CAAC,GAAGH,IAAI,CAACI,CAAC,EAAEF,GAAG,EAAE,EAAE;MACjD,IAAIA,GAAG,IAAI,IAAI,CAACb,MAAM,CAACK,MAAM,EAAE;MAC/B,KAAK,IAAIW,GAAG,GAAGN,GAAG,CAACO,CAAC,EAAED,GAAG,GAAGN,GAAG,CAACO,CAAC,GAAGN,IAAI,CAACO,CAAC,EAAEF,GAAG,EAAE,EAAE;QACjD,IAAIA,GAAG,GAAG,IAAI,CAAClB,OAAO,EAAE,IAAI,CAACE,MAAM,CAACa,GAAG,CAAC,CAAEG,GAAG,CAAC,GAAG,IAAI;MACvD;IACF;EACF;EAEAS,UAAUA,CAACF,EAAU,EAAQ;IAC3B,KAAK,IAAIV,GAAG,GAAG,CAAC,EAAEA,GAAG,GAAG,IAAI,CAACb,MAAM,CAACK,MAAM,EAAEQ,GAAG,EAAE,EAAE;MACjD,KAAK,IAAIG,GAAG,GAAG,CAAC,EAAEA,GAAG,GAAG,IAAI,CAAClB,OAAO,EAAEkB,GAAG,EAAE,EAAE;QAC3C,IAAI,IAAI,CAAChB,MAAM,CAACa,GAAG,CAAC,CAAEG,GAAG,CAAC,KAAKO,EAAE,EAAE;UACjC,IAAI,CAACvB,MAAM,CAACa,GAAG,CAAC,CAAEG,GAAG,CAAC,GAAG,IAAI;QAC/B;MACF;IACF;EACF;;EAEA;;EAEA;AACF;AACA;AACA;EACEU,YAAYA,CAACf,IAAc,EAAEgB,OAAO,GAAG,IAAI,CAAC3B,MAAM,CAACK,MAAM,GAAGM,IAAI,CAACI,CAAC,EAAuB;IACvF,KAAK,IAAIF,GAAG,GAAG,CAAC,EAAEA,GAAG,GAAGc,OAAO,EAAEd,GAAG,EAAE,EAAE;MACtC,IAAI,CAACM,YAAY,CAACN,GAAG,GAAGF,IAAI,CAACI,CAAC,GAAG,CAAC,CAAC;MACnC,KAAK,IAAIC,GAAG,GAAG,CAAC,EAAEA,GAAG,IAAI,IAAI,CAAClB,OAAO,GAAGa,IAAI,CAACO,CAAC,EAAEF,GAAG,EAAE,EAAE;QACrD,MAAMN,GAAiB,GAAG;UAAEO,CAAC,EAAED,GAAG;UAAEF,CAAC,EAAED;QAAI,CAAC;QAC5C,IAAI,CAAC,IAAI,CAACJ,UAAU,CAACC,GAAG,EAAEC,IAAI,CAAC,EAAE,OAAOD,GAAG;MAC7C;IACF;IACA,OAAO,IAAI;EACb;;EAEA;AACF;AACA;EACEkB,aAAaA,CAAClB,GAAiB,EAAEC,IAAc,EAAEC,QAAiB,EAAe;IAC/E,MAAMiB,IAAI,GAAG,IAAIC,GAAG,CAAS,CAAC;IAC9B,KAAK,IAAIjB,GAAG,GAAGH,GAAG,CAACI,CAAC,EAAED,GAAG,GAAGH,GAAG,CAACI,CAAC,GAAGH,IAAI,CAACI,CAAC,EAAEF,GAAG,EAAE,EAAE;MACjD,IAAIA,GAAG,IAAI,IAAI,CAACb,MAAM,CAACK,MAAM,EAAE;MAC/B,KAAK,IAAIW,GAAG,GAAGN,GAAG,CAACO,CAAC,EAAED,GAAG,GAAGN,GAAG,CAACO,CAAC,GAAGN,IAAI,CAACO,CAAC,EAAEF,GAAG,EAAE,EAAE;QACjD,IAAIA,GAAG,IAAI,IAAI,CAAClB,OAAO,EAAE;QACzB,MAAMsB,IAAI,GAAG,IAAI,CAACpB,MAAM,CAACa,GAAG,CAAC,CAAEG,GAAG,CAAE;QACpC,IAAII,IAAI,KAAK,IAAI,IAAIA,IAAI,KAAKR,QAAQ,EAAEiB,IAAI,CAACE,GAAG,CAACX,IAAI,CAAC;MACxD;IACF;IACA,OAAOS,IAAI;EACb;;EAEA;;EAEA;AACF;AACA;AACA;EACEG,UAAUA,CAACC,KAAmB,EAAQ;IACpC,MAAMC,MAAM,GAAGD,KAAK,CAACE,MAAM,CAAC,CAACC,CAAC,EAAEC,IAAI,KAAKC,IAAI,CAACC,GAAG,CAACH,CAAC,EAAEC,IAAI,CAACG,QAAQ,CAAC1B,CAAC,GAAGuB,IAAI,CAAC1B,IAAI,CAACI,CAAC,CAAC,EAAE,CAAC,CAAC;IACvF,IAAI,CAACf,MAAM,GAAGJ,UAAU,CAACK,YAAY,CAAC,IAAI,CAACH,OAAO,EAAEwC,IAAI,CAACC,GAAG,CAACL,MAAM,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7E,KAAK,MAAMG,IAAI,IAAIJ,KAAK,EAAE;MACxB,IAAI,CAACX,OAAO,CAACe,IAAI,CAACd,EAAE,EAAEc,IAAI,CAACG,QAAQ,EAAEH,IAAI,CAAC1B,IAAI,CAAC;IACjD;EACF;;EAEA;AACF;AACA;AACA;EACE8B,SAASA,CAAA,EAAmC;IAC1C,MAAMC,GAAmC,GAAG,CAAC,CAAC;IAC9C,KAAK,IAAI7B,GAAG,GAAG,CAAC,EAAEA,GAAG,GAAG,IAAI,CAACb,MAAM,CAACK,MAAM,EAAEQ,GAAG,EAAE,EAAE;MACjD,KAAK,IAAIG,GAAG,GAAG,CAAC,EAAEA,GAAG,GAAG,IAAI,CAAClB,OAAO,EAAEkB,GAAG,EAAE,EAAE;QAC3C,MAAMO,EAAE,GAAG,IAAI,CAACvB,MAAM,CAACa,GAAG,CAAC,CAAEG,GAAG,CAAC;QACjC,IAAIO,EAAE,EAAE;UACN,IAAI,CAACmB,GAAG,CAACnB,EAAE,CAAC,EAAEmB,GAAG,CAACnB,EAAE,CAAC,GAAG,EAAE;UAC1BmB,GAAG,CAACnB,EAAE,CAAC,CAAEoB,IAAI,CAAC;YAAE1B,CAAC,EAAED,GAAG;YAAEF,CAAC,EAAED;UAAI,CAAC,CAAC;QACnC;MACF;IACF;IACA,OAAO6B,GAAG;EACZ;;EAEA;;EAEQvB,YAAYA,CAACyB,QAAgB,EAAQ;IAC3C,OAAO,IAAI,CAAC5C,MAAM,CAACK,MAAM,IAAIuC,QAAQ,EAAE;MACrC,IAAI,CAAC5C,MAAM,CAAC2C,IAAI,CAACxC,KAAK,CAAC,IAAI,CAACL,OAAO,CAAC,CAACQ,IAAI,CAAC,IAAI,CAAC,CAAC;IAClD;EACF;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { GridEngine } from "./GridEngine.js";
|
|
4
|
+
export function autoArrange(tiles, columns) {
|
|
5
|
+
const engine = new GridEngine(columns);
|
|
6
|
+
const sorted = [...tiles].sort((a, b) => b.size.w * b.size.h - a.size.w * a.size.h);
|
|
7
|
+
const newPositions = new Map();
|
|
8
|
+
for (const tile of sorted) {
|
|
9
|
+
const pos = engine.findFirstFit(tile.size) ?? tile.position;
|
|
10
|
+
engine.placeAt(tile.id, pos, tile.size);
|
|
11
|
+
newPositions.set(tile.id, pos);
|
|
12
|
+
}
|
|
13
|
+
return tiles.map(t => ({
|
|
14
|
+
...t,
|
|
15
|
+
position: newPositions.get(t.id) ?? t.position
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
export function applyGravity(tiles, columns, gravity) {
|
|
19
|
+
if (gravity === 'none') return tiles;
|
|
20
|
+
const engine = new GridEngine(columns);
|
|
21
|
+
const sorted = [...tiles].sort(gravity === 'up' ? (a, b) => a.position.y - b.position.y || a.position.x - b.position.x : (a, b) => a.position.x - b.position.x || a.position.y - b.position.y);
|
|
22
|
+
const newPositions = new Map();
|
|
23
|
+
for (const tile of sorted) {
|
|
24
|
+
const pos = slideToward(tile.position, tile.size, engine, gravity);
|
|
25
|
+
engine.placeAt(tile.id, pos, tile.size);
|
|
26
|
+
newPositions.set(tile.id, pos);
|
|
27
|
+
}
|
|
28
|
+
return tiles.map(t => ({
|
|
29
|
+
...t,
|
|
30
|
+
position: newPositions.get(t.id) ?? t.position
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
function slideToward(start, size, engine, gravity) {
|
|
34
|
+
let {
|
|
35
|
+
x,
|
|
36
|
+
y
|
|
37
|
+
} = start;
|
|
38
|
+
if (gravity === 'up') {
|
|
39
|
+
while (y > 0 && !engine.isOccupied({
|
|
40
|
+
x,
|
|
41
|
+
y: y - 1
|
|
42
|
+
}, size)) y--;
|
|
43
|
+
} else {
|
|
44
|
+
while (x > 0 && !engine.isOccupied({
|
|
45
|
+
x: x - 1,
|
|
46
|
+
y
|
|
47
|
+
}, size)) x--;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
x,
|
|
51
|
+
y
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=autoArrange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["GridEngine","autoArrange","tiles","columns","engine","sorted","sort","a","b","size","w","h","newPositions","Map","tile","pos","findFirstFit","position","placeAt","id","set","map","t","get","applyGravity","gravity","y","x","slideToward","start","isOccupied"],"sourceRoot":"..\\..\\..\\src","sources":["engine/autoArrange.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { GridEngine } from "./GridEngine.js";
|
|
4
|
+
export function resolveCollisions(tiles, draggedId, targetPosition, behavior, columns) {
|
|
5
|
+
if (behavior === 'swap') return resolveSwap(tiles, draggedId, targetPosition);
|
|
6
|
+
return resolvePush(tiles, draggedId, targetPosition, columns);
|
|
7
|
+
}
|
|
8
|
+
function resolveSwap(tiles, draggedId, targetPosition) {
|
|
9
|
+
const dragged = tiles.find(t => t.id === draggedId);
|
|
10
|
+
if (!dragged) return tiles;
|
|
11
|
+
const cx = targetPosition.x + dragged.size.w / 2;
|
|
12
|
+
const cy = targetPosition.y + dragged.size.h / 2;
|
|
13
|
+
const swapTarget = tiles.find(t => t.id !== draggedId && cx > t.position.x && cx < t.position.x + t.size.w && cy > t.position.y && cy < t.position.y + t.size.h);
|
|
14
|
+
const fromPos = dragged.position;
|
|
15
|
+
return tiles.map(t => {
|
|
16
|
+
if (t.id === draggedId) return {
|
|
17
|
+
...t,
|
|
18
|
+
position: targetPosition
|
|
19
|
+
};
|
|
20
|
+
if (swapTarget && t.id === swapTarget.id) return {
|
|
21
|
+
...t,
|
|
22
|
+
position: fromPos
|
|
23
|
+
};
|
|
24
|
+
return t;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function resolvePush(tiles, draggedId, targetPosition, columns) {
|
|
28
|
+
const dragged = tiles.find(t => t.id === draggedId);
|
|
29
|
+
if (!dragged) return tiles;
|
|
30
|
+
const engine = new GridEngine(columns);
|
|
31
|
+
const others = tiles.filter(t => t.id !== draggedId);
|
|
32
|
+
for (const t of others) {
|
|
33
|
+
engine.placeAt(t.id, t.position, t.size);
|
|
34
|
+
}
|
|
35
|
+
const collisions = engine.getCollisions(targetPosition, dragged.size);
|
|
36
|
+
if (collisions.size === 0) {
|
|
37
|
+
return tiles.map(t => t.id === draggedId ? {
|
|
38
|
+
...t,
|
|
39
|
+
position: targetPosition
|
|
40
|
+
} : t);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Claim the target space, then re-home displaced tiles in top-left order.
|
|
44
|
+
for (const id of collisions) {
|
|
45
|
+
engine.removeById(id);
|
|
46
|
+
}
|
|
47
|
+
engine.placeAt(draggedId, targetPosition, dragged.size);
|
|
48
|
+
const displaced = others.filter(t => collisions.has(t.id)).sort((a, b) => a.position.y - b.position.y || a.position.x - b.position.x);
|
|
49
|
+
const newPositions = new Map();
|
|
50
|
+
for (const t of displaced) {
|
|
51
|
+
const pos = engine.findFirstFit(t.size) ?? t.position;
|
|
52
|
+
engine.placeAt(t.id, pos, t.size);
|
|
53
|
+
newPositions.set(t.id, pos);
|
|
54
|
+
}
|
|
55
|
+
return tiles.map(t => {
|
|
56
|
+
if (t.id === draggedId) return {
|
|
57
|
+
...t,
|
|
58
|
+
position: targetPosition
|
|
59
|
+
};
|
|
60
|
+
const pos = newPositions.get(t.id);
|
|
61
|
+
return pos ? {
|
|
62
|
+
...t,
|
|
63
|
+
position: pos
|
|
64
|
+
} : t;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=collisions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["GridEngine","resolveCollisions","tiles","draggedId","targetPosition","behavior","columns","resolveSwap","resolvePush","dragged","find","t","id","cx","x","size","w","cy","y","h","swapTarget","position","fromPos","map","engine","others","filter","placeAt","collisions","getCollisions","removeById","displaced","has","sort","a","b","newPositions","Map","pos","findFirstFit","set","get"],"sourceRoot":"..\\..\\..\\src","sources":["engine/collisions.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Gesture } from 'react-native-gesture-handler';
|
|
4
|
+
import { runOnJS } from 'react-native-reanimated';
|
|
5
|
+
import { useGridDrag } from "../context/GridDragContext.js";
|
|
6
|
+
import { pixelToGrid } from "../utils/pixelToGrid.js";
|
|
7
|
+
export function useTileGesture({
|
|
8
|
+
tile,
|
|
9
|
+
rect,
|
|
10
|
+
config,
|
|
11
|
+
containerWidth
|
|
12
|
+
}) {
|
|
13
|
+
const drag = useGridDrag();
|
|
14
|
+
const canDrag = drag.draggable && tile.draggable !== false;
|
|
15
|
+
const canSelect = drag.selectable && tile.selectable !== false;
|
|
16
|
+
function onDragStart() {
|
|
17
|
+
drag.startDrag(tile, rect);
|
|
18
|
+
}
|
|
19
|
+
function onDragMove(absX, absY) {
|
|
20
|
+
const pos = pixelToGrid(absX, absY, drag.containerPageX.current, drag.containerPageY.current, drag.scrollYRef.current, config, tile.size, containerWidth);
|
|
21
|
+
drag.updateGhost(pos);
|
|
22
|
+
}
|
|
23
|
+
function onDragEnd() {
|
|
24
|
+
drag.endDrag(drag.ghostPosition ?? tile.position);
|
|
25
|
+
}
|
|
26
|
+
function onLongPressSelect() {
|
|
27
|
+
drag.selectTile(tile);
|
|
28
|
+
}
|
|
29
|
+
function onPress() {
|
|
30
|
+
drag.onTilePress(tile);
|
|
31
|
+
}
|
|
32
|
+
const tap = Gesture.Tap().maxDuration(200) // must complete before the 300ms long-press activates drag
|
|
33
|
+
.onEnd(() => {
|
|
34
|
+
runOnJS(onPress)();
|
|
35
|
+
});
|
|
36
|
+
const pan = Gesture.Pan().enabled(canDrag || canSelect).activateAfterLongPress(300).onStart(() => {
|
|
37
|
+
if (canDrag) {
|
|
38
|
+
runOnJS(onDragStart)();
|
|
39
|
+
} else {
|
|
40
|
+
// draggable=false: select immediately on long-press activation, not on release
|
|
41
|
+
runOnJS(onLongPressSelect)();
|
|
42
|
+
}
|
|
43
|
+
}).onUpdate(e => {
|
|
44
|
+
if (!canDrag) return;
|
|
45
|
+
drag.dragAbsX.value = e.absoluteX;
|
|
46
|
+
drag.dragAbsY.value = e.absoluteY;
|
|
47
|
+
runOnJS(onDragMove)(e.absoluteX, e.absoluteY);
|
|
48
|
+
}).onEnd(() => {
|
|
49
|
+
if (canDrag) {
|
|
50
|
+
runOnJS(onDragEnd)();
|
|
51
|
+
}
|
|
52
|
+
}).onFinalize(() => {
|
|
53
|
+
if (canDrag && drag.isDragging.value) {
|
|
54
|
+
runOnJS(onDragEnd)();
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
const gesture = Gesture.Simultaneous(pan, tap);
|
|
58
|
+
return {
|
|
59
|
+
gesture
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=useTileGesture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Gesture","runOnJS","useGridDrag","pixelToGrid","useTileGesture","tile","rect","config","containerWidth","drag","canDrag","draggable","canSelect","selectable","onDragStart","startDrag","onDragMove","absX","absY","pos","containerPageX","current","containerPageY","scrollYRef","size","updateGhost","onDragEnd","endDrag","ghostPosition","position","onLongPressSelect","selectTile","onPress","onTilePress","tap","Tap","maxDuration","onEnd","pan","Pan","enabled","activateAfterLongPress","onStart","onUpdate","e","dragAbsX","value","absoluteX","dragAbsY","absoluteY","onFinalize","isDragging","gesture","Simultaneous"],"sourceRoot":"..\\..\\..\\src","sources":["hooks/useTileGesture.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export { GridEngine } from "./engine/GridEngine.js";
|
|
4
|
+
export { resolveCollisions } from "./engine/collisions.js";
|
|
5
|
+
export { autoArrange, applyGravity } from "./engine/autoArrange.js";
|
|
6
|
+
export { columnWidth, tileToPixelRect, gridTotalHeight, isInViewport } from "./layout/LayoutCalculator.js";
|
|
7
|
+
export { pixelToGrid } from "./utils/pixelToGrid.js";
|
|
8
|
+
export { SmartGrid } from "./components/SmartGrid.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["GridEngine","resolveCollisions","autoArrange","applyGravity","columnWidth","tileToPixelRect","gridTotalHeight","isInViewport","pixelToGrid","SmartGrid"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAaA,SAASA,UAAU,QAAQ,wBAAqB;AAChD,SAASC,iBAAiB,QAAQ,wBAAqB;AACvD,SAASC,WAAW,EAAEC,YAAY,QAAQ,yBAAsB;AAGhE,SACEC,WAAW,EACXC,eAAe,EACfC,eAAe,EACfC,YAAY,QACP,8BAA2B;AAElC,SAASC,WAAW,QAAQ,wBAAqB;AAGjD,SAASC,SAAS,QAAQ,2BAAwB","ignoreList":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export function columnWidth(config, containerWidth) {
|
|
4
|
+
const available = containerWidth - config.padding * 2 - config.gap * (config.columns - 1);
|
|
5
|
+
return available / config.columns;
|
|
6
|
+
}
|
|
7
|
+
export function tileToPixelRect(position, size, config, containerWidth) {
|
|
8
|
+
const colW = columnWidth(config, containerWidth);
|
|
9
|
+
const {
|
|
10
|
+
gap,
|
|
11
|
+
padding,
|
|
12
|
+
rowHeight
|
|
13
|
+
} = config;
|
|
14
|
+
return {
|
|
15
|
+
x: padding + position.x * (colW + gap),
|
|
16
|
+
y: padding + position.y * (rowHeight + gap),
|
|
17
|
+
width: size.w * colW + (size.w - 1) * gap,
|
|
18
|
+
height: size.h * rowHeight + (size.h - 1) * gap
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function gridTotalHeight(tiles, config) {
|
|
22
|
+
if (tiles.length === 0) return config.padding * 2;
|
|
23
|
+
const maxRow = tiles.reduce((m, t) => Math.max(m, t.position.y + t.size.h), 0);
|
|
24
|
+
return config.padding * 2 + maxRow * config.rowHeight + Math.max(0, maxRow - 1) * config.gap;
|
|
25
|
+
}
|
|
26
|
+
export function isInViewport(rect, scrollY, viewportHeight, overscan = 200) {
|
|
27
|
+
return rect.y + rect.height >= scrollY - overscan && rect.y <= scrollY + viewportHeight + overscan;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=LayoutCalculator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["columnWidth","config","containerWidth","available","padding","gap","columns","tileToPixelRect","position","size","colW","rowHeight","x","y","width","w","height","h","gridTotalHeight","tiles","length","maxRow","reduce","m","t","Math","max","isInViewport","rect","scrollY","viewportHeight","overscan"],"sourceRoot":"..\\..\\..\\src","sources":["layout/LayoutCalculator.ts"],"mappings":";;AASA,OAAO,SAASA,WAAWA,CAACC,MAAkB,EAAEC,cAAsB,EAAU;EAC9E,MAAMC,SAAS,GAAGD,cAAc,GAAGD,MAAM,CAACG,OAAO,GAAG,CAAC,GAAGH,MAAM,CAACI,GAAG,IAAIJ,MAAM,CAACK,OAAO,GAAG,CAAC,CAAC;EACzF,OAAOH,SAAS,GAAGF,MAAM,CAACK,OAAO;AACnC;AAEA,OAAO,SAASC,eAAeA,CAC7BC,QAAsB,EACtBC,IAAc,EACdR,MAAkB,EAClBC,cAAsB,EACX;EACX,MAAMQ,IAAI,GAAGV,WAAW,CAACC,MAAM,EAAEC,cAAc,CAAC;EAChD,MAAM;IAAEG,GAAG;IAAED,OAAO;IAAEO;EAAU,CAAC,GAAGV,MAAM;EAC1C,OAAO;IACLW,CAAC,EAAER,OAAO,GAAGI,QAAQ,CAACI,CAAC,IAAIF,IAAI,GAAGL,GAAG,CAAC;IACtCQ,CAAC,EAAET,OAAO,GAAGI,QAAQ,CAACK,CAAC,IAAIF,SAAS,GAAGN,GAAG,CAAC;IAC3CS,KAAK,EAAEL,IAAI,CAACM,CAAC,GAAGL,IAAI,GAAG,CAACD,IAAI,CAACM,CAAC,GAAG,CAAC,IAAIV,GAAG;IACzCW,MAAM,EAAEP,IAAI,CAACQ,CAAC,GAAGN,SAAS,GAAG,CAACF,IAAI,CAACQ,CAAC,GAAG,CAAC,IAAIZ;EAC9C,CAAC;AACH;AAEA,OAAO,SAASa,eAAeA,CAC7BC,KAAwD,EACxDlB,MAAkB,EACV;EACR,IAAIkB,KAAK,CAACC,MAAM,KAAK,CAAC,EAAE,OAAOnB,MAAM,CAACG,OAAO,GAAG,CAAC;EACjD,MAAMiB,MAAM,GAAGF,KAAK,CAACG,MAAM,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKC,IAAI,CAACC,GAAG,CAACH,CAAC,EAAEC,CAAC,CAAChB,QAAQ,CAACK,CAAC,GAAGW,CAAC,CAACf,IAAI,CAACQ,CAAC,CAAC,EAAE,CAAC,CAAC;EAC9E,OAAOhB,MAAM,CAACG,OAAO,GAAG,CAAC,GAAGiB,MAAM,GAAGpB,MAAM,CAACU,SAAS,GAAGc,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEL,MAAM,GAAG,CAAC,CAAC,GAAGpB,MAAM,CAACI,GAAG;AAC9F;AAEA,OAAO,SAASsB,YAAYA,CAC1BC,IAAe,EACfC,OAAe,EACfC,cAAsB,EACtBC,QAAQ,GAAG,GAAG,EACL;EACT,OACEH,IAAI,CAACf,CAAC,GAAGe,IAAI,CAACZ,MAAM,IAAIa,OAAO,GAAGE,QAAQ,IAC1CH,IAAI,CAACf,CAAC,IAAIgB,OAAO,GAAGC,cAAc,GAAGC,QAAQ;AAEjD","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"..\\..\\src","sources":["types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { columnWidth } from "../layout/LayoutCalculator.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Convert an absolute screen position (from gesture handler) to a grid cell,
|
|
7
|
+
* accounting for the container's page offset and the current scroll position.
|
|
8
|
+
*
|
|
9
|
+
* The returned position is clamped so the tile stays within grid bounds.
|
|
10
|
+
*/
|
|
11
|
+
export function pixelToGrid(absX, absY, containerPageX, containerPageY, scrollY, config, size, containerWidth) {
|
|
12
|
+
const colW = columnWidth(config, containerWidth);
|
|
13
|
+
const relX = absX - containerPageX - config.padding;
|
|
14
|
+
const relY = absY - containerPageY + scrollY - config.padding;
|
|
15
|
+
const x = Math.floor(relX / (colW + config.gap));
|
|
16
|
+
const y = Math.floor(relY / (config.rowHeight + config.gap));
|
|
17
|
+
return {
|
|
18
|
+
x: Math.max(0, Math.min(x, config.columns - size.w)),
|
|
19
|
+
y: Math.max(0, y)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=pixelToGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["columnWidth","pixelToGrid","absX","absY","containerPageX","containerPageY","scrollY","config","size","containerWidth","colW","relX","padding","relY","x","Math","floor","gap","y","rowHeight","max","min","columns","w"],"sourceRoot":"..\\..\\..\\src","sources":["utils/pixelToGrid.ts"],"mappings":";;AACA,SAASA,WAAW,QAAQ,+BAA4B;;AAExD;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CACzBC,IAAY,EACZC,IAAY,EACZC,cAAsB,EACtBC,cAAsB,EACtBC,OAAe,EACfC,MAAkB,EAClBC,IAAc,EACdC,cAAsB,EACR;EACd,MAAMC,IAAI,GAAGV,WAAW,CAACO,MAAM,EAAEE,cAAc,CAAC;EAChD,MAAME,IAAI,GAAGT,IAAI,GAAGE,cAAc,GAAGG,MAAM,CAACK,OAAO;EACnD,MAAMC,IAAI,GAAGV,IAAI,GAAGE,cAAc,GAAGC,OAAO,GAAGC,MAAM,CAACK,OAAO;EAE7D,MAAME,CAAC,GAAGC,IAAI,CAACC,KAAK,CAACL,IAAI,IAAID,IAAI,GAAGH,MAAM,CAACU,GAAG,CAAC,CAAC;EAChD,MAAMC,CAAC,GAAGH,IAAI,CAACC,KAAK,CAACH,IAAI,IAAIN,MAAM,CAACY,SAAS,GAAGZ,MAAM,CAACU,GAAG,CAAC,CAAC;EAE5D,OAAO;IACLH,CAAC,EAAEC,IAAI,CAACK,GAAG,CAAC,CAAC,EAAEL,IAAI,CAACM,GAAG,CAACP,CAAC,EAAEP,MAAM,CAACe,OAAO,GAAGd,IAAI,CAACe,CAAC,CAAC,CAAC;IACpDL,CAAC,EAAEH,IAAI,CAACK,GAAG,CAAC,CAAC,EAAEF,CAAC;EAClB,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Tile } from '../types.js';
|
|
2
|
+
import type { PixelRect } from '../layout/LayoutCalculator.js';
|
|
3
|
+
type Props<TData> = {
|
|
4
|
+
tile: Tile<TData>;
|
|
5
|
+
initialRect: PixelRect;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
declare function DragLayerInner<TData>({ tile: _tile, initialRect, children }: Props<TData>): import("react").JSX.Element;
|
|
9
|
+
export declare const DragLayer: typeof DragLayerInner;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=DragLayer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DragLayer.d.ts","sourceRoot":"","sources":["../../../../src/components/DragLayer.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAU,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA4B,CAAC;AAI5D,KAAK,KAAK,CAAC,KAAK,IAAI;IAClB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,WAAW,EAAE,SAAS,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,iBAAS,cAAc,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,+BAmClF;AAED,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { PlacedTile, GridConfig } from '../types.js';
|
|
3
|
+
import type { PixelRect } from '../layout/LayoutCalculator.js';
|
|
4
|
+
type Props<TData> = {
|
|
5
|
+
tile: PlacedTile<TData>;
|
|
6
|
+
rect: PixelRect;
|
|
7
|
+
config: GridConfig;
|
|
8
|
+
containerWidth: number;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
};
|
|
11
|
+
declare function DraggableTileInner<TData>({ tile, rect, config, containerWidth, children, }: Props<TData>): React.JSX.Element;
|
|
12
|
+
export declare const DraggableTile: typeof DraggableTileInner;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=DraggableTile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DraggableTile.d.ts","sourceRoot":"","sources":["../../../../src/components/DraggableTile.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0B,MAAM,OAAO,CAAC;AAW/C,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAU,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA4B,CAAC;AAI5D,KAAK,KAAK,CAAC,KAAK,IAAI;IAClB,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,iBAAS,kBAAkB,CAAC,KAAK,EAAE,EACjC,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,QAAQ,GACT,EAAE,KAAK,CAAC,KAAK,CAAC,qBAyCd;AAED,eAAO,MAAM,aAAa,EAA+B,OAAO,kBAAkB,CAAC"}
|