@griddle/core 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 +21 -0
- package/README.md +54 -0
- package/dist/compaction.d.ts +3 -0
- package/dist/compaction.d.ts.map +1 -0
- package/dist/compaction.js +85 -0
- package/dist/compaction.js.map +1 -0
- package/dist/drag.d.ts +52 -0
- package/dist/drag.d.ts.map +1 -0
- package/dist/drag.js +120 -0
- package/dist/drag.js.map +1 -0
- package/dist/events.d.ts +9 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +22 -0
- package/dist/events.js.map +1 -0
- package/dist/geometry.d.ts +33 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +164 -0
- package/dist/geometry.js.map +1 -0
- package/dist/grid.d.ts +100 -0
- package/dist/grid.d.ts.map +1 -0
- package/dist/grid.js +539 -0
- package/dist/grid.js.map +1 -0
- package/dist/group-drag.d.ts +41 -0
- package/dist/group-drag.d.ts.map +1 -0
- package/dist/group-drag.js +97 -0
- package/dist/group-drag.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/loop.d.ts +99 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +188 -0
- package/dist/loop.js.map +1 -0
- package/dist/movement.d.ts +17 -0
- package/dist/movement.d.ts.map +1 -0
- package/dist/movement.js +333 -0
- package/dist/movement.js.map +1 -0
- package/dist/packing.d.ts +16 -0
- package/dist/packing.d.ts.map +1 -0
- package/dist/packing.js +159 -0
- package/dist/packing.js.map +1 -0
- package/dist/pan.d.ts +58 -0
- package/dist/pan.d.ts.map +1 -0
- package/dist/pan.js +174 -0
- package/dist/pan.js.map +1 -0
- package/dist/positioning.d.ts +117 -0
- package/dist/positioning.d.ts.map +1 -0
- package/dist/positioning.js +251 -0
- package/dist/positioning.js.map +1 -0
- package/dist/repack.d.ts +4 -0
- package/dist/repack.d.ts.map +1 -0
- package/dist/repack.js +179 -0
- package/dist/repack.js.map +1 -0
- package/dist/types.d.ts +236 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/virtualize.d.ts +27 -0
- package/dist/virtualize.d.ts.map +1 -0
- package/dist/virtualize.js +53 -0
- package/dist/virtualize.js.map +1 -0
- package/package.json +55 -0
- package/src/compaction.ts +80 -0
- package/src/drag.ts +146 -0
- package/src/events.ts +25 -0
- package/src/geometry.ts +199 -0
- package/src/grid.ts +578 -0
- package/src/group-drag.ts +120 -0
- package/src/index.ts +78 -0
- package/src/loop.ts +246 -0
- package/src/movement.ts +363 -0
- package/src/packing.ts +169 -0
- package/src/pan.ts +217 -0
- package/src/positioning.ts +292 -0
- package/src/repack.ts +212 -0
- package/src/types.ts +262 -0
- package/src/virtualize.ts +77 -0
package/dist/movement.js
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
// Movement engine — implements Rules 1-6 of the drag/drop spec.
|
|
2
|
+
//
|
|
3
|
+
// The engine mutates the grid in place during attempts but takes a snapshot at
|
|
4
|
+
// each rule boundary so it can roll back on failure. If every rule rejects the
|
|
5
|
+
// move (and the BFS fallback can't repack), the original grid is restored and
|
|
6
|
+
// moveTile returns false.
|
|
7
|
+
//
|
|
8
|
+
// Rule overview:
|
|
9
|
+
// 1. Empty target — drop straight in.
|
|
10
|
+
// 2. Same-footprint swap — adjacent partner with identical w×h: swap them.
|
|
11
|
+
// 3-5. Single-step displace — push each overlapping victim by enough cells
|
|
12
|
+
// along a priority direction to clear the dragger's full footprint.
|
|
13
|
+
// Each victim is placed independently; if any victim has no legal slot
|
|
14
|
+
// the rule rejects and we fall through.
|
|
15
|
+
// 6. Cascade push — push the victim AND any blockers it runs into
|
|
16
|
+
// along a priority direction. On infinite axes this loops until the
|
|
17
|
+
// target rect is clear (tiles slide off into space). On fixed grids,
|
|
18
|
+
// the cascade may run out of room — the move falls through to the 0-1
|
|
19
|
+
// BFS repack solver as a last resort.
|
|
20
|
+
import { directionStep, faceClosestToOrigin, footprintEquals, priorityDirections, rectsAdjacent, rectsOverlap, tileRect, } from './geometry.js';
|
|
21
|
+
import { solvePushBFS } from './repack.js';
|
|
22
|
+
/**
|
|
23
|
+
* Attempt to move `tileId` to `target`. On success, the grid is mutated in
|
|
24
|
+
* place and `true` is returned. On failure, the grid is left unchanged and
|
|
25
|
+
* `false` is returned.
|
|
26
|
+
*/
|
|
27
|
+
export function moveTile(grid, tileId, target, opts = {}) {
|
|
28
|
+
const tile = grid.getTile(tileId);
|
|
29
|
+
if (!tile)
|
|
30
|
+
return false;
|
|
31
|
+
const originRect = opts.forceFromRect ?? tileRect(tile);
|
|
32
|
+
const targetRect = { col: target.col, row: target.row, w: tile.w, h: tile.h };
|
|
33
|
+
if (!grid.rectInBounds(targetRect))
|
|
34
|
+
return false;
|
|
35
|
+
const overlap = grid.tilesIn(targetRect, new Set([tileId]));
|
|
36
|
+
// Rule 1: empty space
|
|
37
|
+
if (overlap.length === 0) {
|
|
38
|
+
grid._setTilePos(tileId, target);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
// Rule 2: adjacent same-footprint swap
|
|
42
|
+
if (overlap.length === 1 &&
|
|
43
|
+
rectsAdjacent(originRect, tileRect(overlap[0])) &&
|
|
44
|
+
footprintEquals(overlap[0], tile)) {
|
|
45
|
+
const other = overlap[0];
|
|
46
|
+
const otherPos = { col: other.col, row: other.row };
|
|
47
|
+
const originPos = { col: originRect.col, row: originRect.row };
|
|
48
|
+
grid._setTilePos(tileId, otherPos);
|
|
49
|
+
grid._setTilePos(other.id, originPos);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
// Rule 3-5: try independent single-displacement of each overlapper.
|
|
53
|
+
//
|
|
54
|
+
// Each victim is placed in turn against the live grid. The ONLY tile we
|
|
55
|
+
// ignore when checking for collisions is the dragger itself — it still
|
|
56
|
+
// sits at originRect at this point and shouldn't block the displacement
|
|
57
|
+
// search. Any victim already moved into its new slot DOES block the next
|
|
58
|
+
// victim's candidate; otherwise two displaced tiles can land on the same
|
|
59
|
+
// cell (visible to the user as one tile "only moving 1 unit" because the
|
|
60
|
+
// overlap collapses two tiles into the same rendered position).
|
|
61
|
+
const snapshot = grid.snapshotTiles();
|
|
62
|
+
const dirs = priorityDirections(originRect, targetRect);
|
|
63
|
+
const draggerOnly = new Set([tileId]);
|
|
64
|
+
let allPlaced = true;
|
|
65
|
+
for (const victim of overlap) {
|
|
66
|
+
const moved = tryDisplaceVictim(grid, victim.id, dirs, targetRect, draggerOnly);
|
|
67
|
+
if (!moved) {
|
|
68
|
+
allPlaced = false;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (allPlaced) {
|
|
73
|
+
grid._setTilePos(tileId, target);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
grid.restoreTiles(snapshot);
|
|
77
|
+
// Rule 6: try cascading push along each priority direction.
|
|
78
|
+
// First: if the primary direction is on an infinite axis, use unbounded chain push.
|
|
79
|
+
// Otherwise: try minimum-clearance cascade push along each priority direction in turn.
|
|
80
|
+
const primaryDir = faceClosestToOrigin(originRect, targetRect);
|
|
81
|
+
if (isInfiniteDirection(grid, primaryDir)) {
|
|
82
|
+
if (pushChainInfinite(grid, tileId, target, primaryDir))
|
|
83
|
+
return true;
|
|
84
|
+
grid.restoreTiles(snapshot);
|
|
85
|
+
}
|
|
86
|
+
for (const dir of dirs) {
|
|
87
|
+
if (cascadePushOverlap(grid, tileId, targetRect, dir)) {
|
|
88
|
+
grid._setTilePos(tileId, target);
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
grid.restoreTiles(snapshot);
|
|
92
|
+
}
|
|
93
|
+
// Final fallback: 0-1 BFS on fixed grid.
|
|
94
|
+
const solved = solvePushBFS(grid, tileId, target, originRect);
|
|
95
|
+
if (!solved) {
|
|
96
|
+
grid.restoreTiles(snapshot);
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Displace `victimId` by the minimum cell count along one of `priorityDirs`
|
|
103
|
+
* such that it no longer overlaps `targetRect`, stays in bounds, and lands clear.
|
|
104
|
+
* Cardinal: clear on the moving axis. Diagonal: min(kxClear, kyClear) cells.
|
|
105
|
+
*/
|
|
106
|
+
function tryDisplaceVictim(grid, victimId, priorityDirs, targetRect, ignore) {
|
|
107
|
+
const victim = grid.getTile(victimId);
|
|
108
|
+
if (!victim)
|
|
109
|
+
return false;
|
|
110
|
+
const victimRect = tileRect(victim);
|
|
111
|
+
for (const dir of priorityDirs) {
|
|
112
|
+
const { dx, dy } = directionStep(dir);
|
|
113
|
+
let kxClear = Infinity;
|
|
114
|
+
if (dx > 0) {
|
|
115
|
+
kxClear = Math.max(1, targetRect.col + targetRect.w - victimRect.col);
|
|
116
|
+
}
|
|
117
|
+
else if (dx < 0) {
|
|
118
|
+
kxClear = Math.max(1, victimRect.col + victimRect.w - targetRect.col);
|
|
119
|
+
}
|
|
120
|
+
let kyClear = Infinity;
|
|
121
|
+
if (dy > 0) {
|
|
122
|
+
kyClear = Math.max(1, targetRect.row + targetRect.h - victimRect.row);
|
|
123
|
+
}
|
|
124
|
+
else if (dy < 0) {
|
|
125
|
+
kyClear = Math.max(1, victimRect.row + victimRect.h - targetRect.row);
|
|
126
|
+
}
|
|
127
|
+
let k;
|
|
128
|
+
if (dx === 0 && dy === 0)
|
|
129
|
+
continue;
|
|
130
|
+
else if (dx === 0)
|
|
131
|
+
k = kyClear;
|
|
132
|
+
else if (dy === 0)
|
|
133
|
+
k = kxClear;
|
|
134
|
+
else
|
|
135
|
+
k = Math.min(kxClear, kyClear);
|
|
136
|
+
if (!isFinite(k))
|
|
137
|
+
continue;
|
|
138
|
+
const candidate = {
|
|
139
|
+
col: victimRect.col + k * dx,
|
|
140
|
+
row: victimRect.row + k * dy,
|
|
141
|
+
w: victim.w,
|
|
142
|
+
h: victim.h,
|
|
143
|
+
};
|
|
144
|
+
if (!grid.rectInBounds(candidate))
|
|
145
|
+
continue;
|
|
146
|
+
const blockIds = new Set(ignore);
|
|
147
|
+
blockIds.add(victimId);
|
|
148
|
+
const hits = grid.tilesIn(candidate, blockIds);
|
|
149
|
+
if (hits.length === 0) {
|
|
150
|
+
grid._setTilePos(victimId, { col: candidate.col, row: candidate.row });
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
function isInfiniteDirection(grid, dir) {
|
|
157
|
+
const { dx, dy } = directionStep(dir);
|
|
158
|
+
if (dx !== 0 && !grid.config.infiniteX)
|
|
159
|
+
return false;
|
|
160
|
+
if (dy !== 0 && !grid.config.infiniteY)
|
|
161
|
+
return false;
|
|
162
|
+
if (dx !== 0 && grid.config.infiniteX)
|
|
163
|
+
return true;
|
|
164
|
+
if (dy !== 0 && grid.config.infiniteY)
|
|
165
|
+
return true;
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Push every tile that overlaps `targetRect` by enough cells along `dir` to clear it,
|
|
170
|
+
* cascading through any tiles those pushes collide with. Aborts if any chained push
|
|
171
|
+
* would go out of bounds. Mutates the grid; caller restores on failure.
|
|
172
|
+
*
|
|
173
|
+
* For cardinal `dir`: each victim moves k = enough-to-clear cells.
|
|
174
|
+
* For diagonal `dir`: same logic — k = min cell count to clear via either axis.
|
|
175
|
+
*/
|
|
176
|
+
function cascadePushOverlap(grid, draggerId, targetRect, dir) {
|
|
177
|
+
const { dx, dy } = directionStep(dir);
|
|
178
|
+
if (dx === 0 && dy === 0)
|
|
179
|
+
return false;
|
|
180
|
+
const initialOverlap = grid.tilesIn(targetRect, new Set([draggerId]));
|
|
181
|
+
if (initialOverlap.length === 0)
|
|
182
|
+
return true; // already clear
|
|
183
|
+
// Build the per-tile shift map. Each tile shifts by some multiple of (dx,dy).
|
|
184
|
+
// Start with the overlappers — each needs enough k to clear targetRect.
|
|
185
|
+
const shift = new Map(); // tileId -> k cells along (dx,dy)
|
|
186
|
+
const queue = [];
|
|
187
|
+
function neededKForClearing(victim, blockRect) {
|
|
188
|
+
let kx = Infinity;
|
|
189
|
+
if (dx > 0)
|
|
190
|
+
kx = Math.max(1, blockRect.col + blockRect.w - victim.col);
|
|
191
|
+
else if (dx < 0)
|
|
192
|
+
kx = Math.max(1, victim.col + victim.w - blockRect.col);
|
|
193
|
+
let ky = Infinity;
|
|
194
|
+
if (dy > 0)
|
|
195
|
+
ky = Math.max(1, blockRect.row + blockRect.h - victim.row);
|
|
196
|
+
else if (dy < 0)
|
|
197
|
+
ky = Math.max(1, victim.row + victim.h - blockRect.row);
|
|
198
|
+
if (dx === 0)
|
|
199
|
+
return ky;
|
|
200
|
+
if (dy === 0)
|
|
201
|
+
return kx;
|
|
202
|
+
return Math.min(kx, ky);
|
|
203
|
+
}
|
|
204
|
+
for (const v of initialOverlap) {
|
|
205
|
+
const k = neededKForClearing(v, targetRect);
|
|
206
|
+
if (!isFinite(k))
|
|
207
|
+
return false;
|
|
208
|
+
shift.set(v.id, k);
|
|
209
|
+
queue.push({ id: v.id, k });
|
|
210
|
+
}
|
|
211
|
+
// Helper: where will tile `id` end up given current shift map?
|
|
212
|
+
function shiftedRect(t) {
|
|
213
|
+
const k = shift.get(t.id) ?? 0;
|
|
214
|
+
return { col: t.col + k * dx, row: t.row + k * dy, w: t.w, h: t.h };
|
|
215
|
+
}
|
|
216
|
+
const safety = 1000;
|
|
217
|
+
let iters = 0;
|
|
218
|
+
while (queue.length > 0) {
|
|
219
|
+
if (iters++ > safety)
|
|
220
|
+
return false;
|
|
221
|
+
const { id } = queue.shift();
|
|
222
|
+
const tile = grid.getTile(id);
|
|
223
|
+
if (!tile)
|
|
224
|
+
continue;
|
|
225
|
+
const newRect = shiftedRect(tile);
|
|
226
|
+
if (!grid.rectInBounds(newRect))
|
|
227
|
+
return false;
|
|
228
|
+
// Find any non-dragger tiles that this push collides with.
|
|
229
|
+
for (const other of grid.tiles) {
|
|
230
|
+
if (other.id === id || other.id === draggerId)
|
|
231
|
+
continue;
|
|
232
|
+
const otherShifted = shiftedRect(other);
|
|
233
|
+
if (rectsOverlap(newRect, otherShifted)) {
|
|
234
|
+
// Need to push `other` further along dir to clear newRect.
|
|
235
|
+
const additional = neededKForClearing(other, newRect);
|
|
236
|
+
if (!isFinite(additional))
|
|
237
|
+
return false;
|
|
238
|
+
const prevK = shift.get(other.id) ?? 0;
|
|
239
|
+
// The other tile is currently shifted by prevK. After moving `tile` by k,
|
|
240
|
+
// other must be shifted relative to its CURRENT position by `additional` more.
|
|
241
|
+
// But neededKForClearing is computed against `other`'s ORIGINAL position…
|
|
242
|
+
// we need to use its currently-shifted position. Recompute:
|
|
243
|
+
const movedOther = {
|
|
244
|
+
...other,
|
|
245
|
+
col: other.col + prevK * dx,
|
|
246
|
+
row: other.row + prevK * dy,
|
|
247
|
+
};
|
|
248
|
+
const extra = neededKForClearing(movedOther, newRect);
|
|
249
|
+
if (!isFinite(extra))
|
|
250
|
+
return false;
|
|
251
|
+
const newK = prevK + extra;
|
|
252
|
+
if (newK <= prevK)
|
|
253
|
+
continue; // no progress, would loop
|
|
254
|
+
shift.set(other.id, newK);
|
|
255
|
+
queue.push({ id: other.id, k: newK });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Validate all final positions in bounds and pairwise non-overlapping (against
|
|
260
|
+
// each other and against the dragger's targetRect — which now must be free).
|
|
261
|
+
const finalById = new Map();
|
|
262
|
+
for (const t of grid.tiles) {
|
|
263
|
+
if (t.id === draggerId)
|
|
264
|
+
continue;
|
|
265
|
+
finalById.set(t.id, shiftedRect(t));
|
|
266
|
+
}
|
|
267
|
+
for (const [id, rect] of finalById) {
|
|
268
|
+
if (!grid.rectInBounds(rect))
|
|
269
|
+
return false;
|
|
270
|
+
if (rectsOverlap(rect, targetRect))
|
|
271
|
+
return false;
|
|
272
|
+
for (const [otherId, otherRect] of finalById) {
|
|
273
|
+
if (otherId === id)
|
|
274
|
+
continue;
|
|
275
|
+
if (rectsOverlap(rect, otherRect))
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Commit.
|
|
280
|
+
for (const [id, rect] of finalById) {
|
|
281
|
+
grid._setTilePos(id, { col: rect.col, row: rect.row });
|
|
282
|
+
}
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Infinite-axis push chain. While anything overlaps `target`, shove every
|
|
287
|
+
* overlapper one cell along `dir`; any tile a shoved tile then collides with
|
|
288
|
+
* gets queued and shoved on the same pass. The grid grows infinitely along
|
|
289
|
+
* `dir`, so this always terminates with a clear target — though it may slide
|
|
290
|
+
* tiles arbitrarily far. Caller restores the snapshot on failure (e.g. if the
|
|
291
|
+
* safety limit trips).
|
|
292
|
+
*/
|
|
293
|
+
function pushChainInfinite(grid, tileId, target, dir) {
|
|
294
|
+
const dragger = grid.getTile(tileId);
|
|
295
|
+
if (!dragger)
|
|
296
|
+
return false;
|
|
297
|
+
const targetRect = {
|
|
298
|
+
col: target.col,
|
|
299
|
+
row: target.row,
|
|
300
|
+
w: dragger.w,
|
|
301
|
+
h: dragger.h,
|
|
302
|
+
};
|
|
303
|
+
const { dx, dy } = directionStep(dir);
|
|
304
|
+
const safety = 10000;
|
|
305
|
+
for (let iter = 0; iter < safety; iter++) {
|
|
306
|
+
const overlap = grid.tilesIn(targetRect, new Set([tileId]));
|
|
307
|
+
if (overlap.length === 0) {
|
|
308
|
+
grid._setTilePos(tileId, target);
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
const queue = overlap.map((t) => ({ ...t }));
|
|
312
|
+
while (queue.length > 0) {
|
|
313
|
+
const victim = queue.shift();
|
|
314
|
+
const cur = grid.getTile(victim.id);
|
|
315
|
+
if (!cur)
|
|
316
|
+
continue;
|
|
317
|
+
const newRect = {
|
|
318
|
+
col: cur.col + dx,
|
|
319
|
+
row: cur.row + dy,
|
|
320
|
+
w: cur.w,
|
|
321
|
+
h: cur.h,
|
|
322
|
+
};
|
|
323
|
+
grid._setTilePos(victim.id, { col: newRect.col, row: newRect.row });
|
|
324
|
+
const collides = grid.tilesIn(newRect, new Set([victim.id, tileId]));
|
|
325
|
+
for (const c of collides) {
|
|
326
|
+
if (!queue.find((q) => q.id === c.id))
|
|
327
|
+
queue.push(c);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=movement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"movement.js","sourceRoot":"","sources":["../src/movement.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CellPos } from './types.js';
|
|
2
|
+
export interface PackTile {
|
|
3
|
+
id: string;
|
|
4
|
+
w: number;
|
|
5
|
+
h: number;
|
|
6
|
+
}
|
|
7
|
+
export interface PackComputation {
|
|
8
|
+
placements: Map<string, CellPos>;
|
|
9
|
+
/** Bounding box of the packed layout, in cells. */
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
/** Empty cells left inside the bounding box (0 = perfectly dense). */
|
|
13
|
+
holes: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function computePack(tiles: PackTile[], maxCols: number): PackComputation | null;
|
|
16
|
+
//# sourceMappingURL=packing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packing.d.ts","sourceRoot":"","sources":["../src/packing.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAetF"}
|
package/dist/packing.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// packing.ts — dense repacking for loop mode.
|
|
2
|
+
//
|
|
3
|
+
// Loop mode repeats the content's bounding box, so any hole inside it repeats
|
|
4
|
+
// too. `computePack` arranges tiles into the tightest layout it can find:
|
|
5
|
+
//
|
|
6
|
+
// 1. Exact search: for each candidate width W (widest first) whose W x H
|
|
7
|
+
// rectangle exactly matches the total tile area, run a bounded
|
|
8
|
+
// backtracking tiler (cover the topmost-leftmost empty cell at each step).
|
|
9
|
+
// If it succeeds the layout has ZERO holes.
|
|
10
|
+
// 2. Fallback: a gap-filling greedy — walk cells in reading order and drop
|
|
11
|
+
// the largest remaining tile that fits at each empty cell. Minimizes holes
|
|
12
|
+
// but cannot always reach zero (not every tile mix tiles a rectangle).
|
|
13
|
+
//
|
|
14
|
+
// Rectangle packing is NP-hard in general; the exact search is capped by a
|
|
15
|
+
// node budget so worst-case inputs degrade to the greedy instead of hanging.
|
|
16
|
+
const EXACT_NODE_BUDGET = 50000;
|
|
17
|
+
export function computePack(tiles, maxCols) {
|
|
18
|
+
if (tiles.length === 0 || maxCols <= 0)
|
|
19
|
+
return null;
|
|
20
|
+
const area = tiles.reduce((s, t) => s + t.w * t.h, 0);
|
|
21
|
+
const maxW = Math.max(...tiles.map((t) => t.w));
|
|
22
|
+
const maxH = Math.max(...tiles.map((t) => t.h));
|
|
23
|
+
for (let w = Math.min(maxCols, area); w >= maxW; w--) {
|
|
24
|
+
if (area % w !== 0)
|
|
25
|
+
continue;
|
|
26
|
+
const h = area / w;
|
|
27
|
+
if (h < maxH)
|
|
28
|
+
continue;
|
|
29
|
+
const exact = exactPack(tiles, w, h);
|
|
30
|
+
if (exact)
|
|
31
|
+
return { placements: exact, width: w, height: h, holes: 0 };
|
|
32
|
+
}
|
|
33
|
+
return greedyPack(tiles, Math.min(maxCols, area));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Bounded backtracking tiler: every step covers the topmost-leftmost empty
|
|
37
|
+
* cell, trying each distinct unused tile size there. Returns null when no
|
|
38
|
+
* complete tiling is found (or the node budget runs out).
|
|
39
|
+
*/
|
|
40
|
+
function exactPack(tiles, w, h) {
|
|
41
|
+
const order = [...tiles].sort((a, b) => b.w * b.h - a.w * a.h || b.h - a.h);
|
|
42
|
+
const n = order.length;
|
|
43
|
+
const occ = new Uint8Array(w * h);
|
|
44
|
+
const used = new Array(n).fill(false);
|
|
45
|
+
const placements = new Map();
|
|
46
|
+
let nodes = 0;
|
|
47
|
+
const fits = (c, r, tw, th) => {
|
|
48
|
+
if (c + tw > w || r + th > h)
|
|
49
|
+
return false;
|
|
50
|
+
for (let y = r; y < r + th; y++) {
|
|
51
|
+
for (let x = c; x < c + tw; x++) {
|
|
52
|
+
if (occ[y * w + x])
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
};
|
|
58
|
+
const mark = (c, r, tw, th, v) => {
|
|
59
|
+
for (let y = r; y < r + th; y++) {
|
|
60
|
+
for (let x = c; x < c + tw; x++)
|
|
61
|
+
occ[y * w + x] = v;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const rec = (scanFrom) => {
|
|
65
|
+
if (++nodes > EXACT_NODE_BUDGET)
|
|
66
|
+
return false;
|
|
67
|
+
let idx = scanFrom;
|
|
68
|
+
while (idx < w * h && occ[idx])
|
|
69
|
+
idx++;
|
|
70
|
+
if (idx >= w * h)
|
|
71
|
+
return true;
|
|
72
|
+
const c = idx % w;
|
|
73
|
+
const r = (idx - c) / w;
|
|
74
|
+
// Identical-size tiles are interchangeable; trying one per size is enough.
|
|
75
|
+
const triedSizes = new Set();
|
|
76
|
+
for (let i = 0; i < n; i++) {
|
|
77
|
+
if (used[i])
|
|
78
|
+
continue;
|
|
79
|
+
const t = order[i];
|
|
80
|
+
const sizeKey = `${t.w}x${t.h}`;
|
|
81
|
+
if (triedSizes.has(sizeKey))
|
|
82
|
+
continue;
|
|
83
|
+
triedSizes.add(sizeKey);
|
|
84
|
+
if (!fits(c, r, t.w, t.h))
|
|
85
|
+
continue;
|
|
86
|
+
used[i] = true;
|
|
87
|
+
mark(c, r, t.w, t.h, 1);
|
|
88
|
+
placements.set(t.id, { col: c, row: r });
|
|
89
|
+
if (rec(idx + 1))
|
|
90
|
+
return true;
|
|
91
|
+
used[i] = false;
|
|
92
|
+
mark(c, r, t.w, t.h, 0);
|
|
93
|
+
placements.delete(t.id);
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
};
|
|
97
|
+
return rec(0) ? placements : null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Gap-filling greedy: walk cells in reading order; at each empty cell place
|
|
101
|
+
* the largest remaining tile that fits, otherwise leave the cell as a hole
|
|
102
|
+
* and move on. Never widens the layout to skip a fillable gap.
|
|
103
|
+
*/
|
|
104
|
+
function greedyPack(tiles, w) {
|
|
105
|
+
const remaining = [...tiles].sort((a, b) => b.w * b.h - a.w * a.h || b.h - a.h);
|
|
106
|
+
const placements = new Map();
|
|
107
|
+
const occ = [];
|
|
108
|
+
const fits = (c, r, tw, th) => {
|
|
109
|
+
if (c + tw > w)
|
|
110
|
+
return false;
|
|
111
|
+
for (let y = r; y < r + th; y++) {
|
|
112
|
+
const row = occ[y];
|
|
113
|
+
if (!row)
|
|
114
|
+
continue;
|
|
115
|
+
for (let x = c; x < c + tw; x++) {
|
|
116
|
+
if (row[x])
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
};
|
|
122
|
+
const mark = (c, r, tw, th) => {
|
|
123
|
+
for (let y = r; y < r + th; y++) {
|
|
124
|
+
let row = occ[y];
|
|
125
|
+
if (!row) {
|
|
126
|
+
row = new Array(w).fill(false);
|
|
127
|
+
occ[y] = row;
|
|
128
|
+
}
|
|
129
|
+
for (let x = c; x < c + tw; x++)
|
|
130
|
+
row[x] = true;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
let idx = 0;
|
|
134
|
+
while (remaining.length > 0) {
|
|
135
|
+
const c = idx % w;
|
|
136
|
+
const r = (idx - c) / w;
|
|
137
|
+
if (!occ[r]?.[c]) {
|
|
138
|
+
const i = remaining.findIndex((t) => fits(c, r, t.w, t.h));
|
|
139
|
+
if (i >= 0) {
|
|
140
|
+
const t = remaining.splice(i, 1)[0];
|
|
141
|
+
placements.set(t.id, { col: c, row: r });
|
|
142
|
+
mark(c, r, t.w, t.h);
|
|
143
|
+
}
|
|
144
|
+
// else: unfillable hole — leave it and keep scanning.
|
|
145
|
+
}
|
|
146
|
+
idx++;
|
|
147
|
+
}
|
|
148
|
+
let width = 0;
|
|
149
|
+
let height = 0;
|
|
150
|
+
let area = 0;
|
|
151
|
+
for (const t of tiles) {
|
|
152
|
+
const p = placements.get(t.id);
|
|
153
|
+
width = Math.max(width, p.col + t.w);
|
|
154
|
+
height = Math.max(height, p.row + t.h);
|
|
155
|
+
area += t.w * t.h;
|
|
156
|
+
}
|
|
157
|
+
return { placements, width, height, holes: width * height - area };
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=packing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packing.js","sourceRoot":"","sources":["../src/packing.ts"],"names":[],"mappings":"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"}
|
package/dist/pan.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface CameraState {
|
|
2
|
+
/** Unbounded camera offset, px. */
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
/** Velocity estimate, px/s. */
|
|
6
|
+
vx: number;
|
|
7
|
+
vy: number;
|
|
8
|
+
/** True while the camera is still easing/coasting toward its target. */
|
|
9
|
+
isMoving: boolean;
|
|
10
|
+
/** True between dragStart and dragEnd. */
|
|
11
|
+
isDragging: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface PanPhysicsOptions {
|
|
14
|
+
/** Inertia velocity decay rate after release, 1/s. Default 4. */
|
|
15
|
+
friction?: number;
|
|
16
|
+
/** Camera approach rate toward the target, 1/s. Default 12. */
|
|
17
|
+
ease?: number;
|
|
18
|
+
/** Fling velocity clamp, px/s. Default 6000. */
|
|
19
|
+
maxVelocity?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class PanController {
|
|
22
|
+
private friction;
|
|
23
|
+
private ease;
|
|
24
|
+
private maxVelocity;
|
|
25
|
+
private x;
|
|
26
|
+
private y;
|
|
27
|
+
private targetX;
|
|
28
|
+
private targetY;
|
|
29
|
+
private vx;
|
|
30
|
+
private vy;
|
|
31
|
+
private dragging;
|
|
32
|
+
private lastPointer;
|
|
33
|
+
private samples;
|
|
34
|
+
private lastTick;
|
|
35
|
+
constructor(physics?: PanPhysicsOptions);
|
|
36
|
+
setPhysics(physics: PanPhysicsOptions): void;
|
|
37
|
+
state(): CameraState;
|
|
38
|
+
/** Begin a pan gesture at pointer position (px, py), in any stable pixel space. */
|
|
39
|
+
dragStart(px: number, py: number, now: number): void;
|
|
40
|
+
/** Pointer moved during a pan gesture. */
|
|
41
|
+
dragMove(px: number, py: number, now: number): void;
|
|
42
|
+
/** End the pan gesture, converting recent pointer motion into a fling. */
|
|
43
|
+
dragEnd(now: number): void;
|
|
44
|
+
/** Abort a drag without inertia. */
|
|
45
|
+
dragCancel(): void;
|
|
46
|
+
/** External scroll delta (native scroll / wheel). Applied directly. */
|
|
47
|
+
scrollBy(dx: number, dy: number): void;
|
|
48
|
+
/** Jump the camera (and target) to an absolute offset. Kills motion. */
|
|
49
|
+
moveTo(x: number, y: number): void;
|
|
50
|
+
/** Stop all motion at the current offset. */
|
|
51
|
+
stop(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Advance the simulation to time `now` (ms). Returns the camera state.
|
|
54
|
+
* Call once per animation frame.
|
|
55
|
+
*/
|
|
56
|
+
tick(now: number): CameraState;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=pan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pan.d.ts","sourceRoot":"","sources":["../src/pan.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAYD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,EAAE,CAAK;IAEf,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,QAAQ,CAAuB;gBAE3B,OAAO,GAAE,iBAAsB;IAM3C,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAM5C,KAAK,IAAI,WAAW;IAgBpB,mFAAmF;IACnF,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAWpD,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAYnD,0EAA0E;IAC1E,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAuB1B,oCAAoC;IACpC,UAAU,IAAI,IAAI;IAQlB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAOtC,wEAAwE;IACxE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IASlC,6CAA6C;IAC7C,IAAI,IAAI,IAAI;IAOZ;;;OAGG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW;CAqC/B"}
|