@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.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -0
  3. package/dist/compaction.d.ts +3 -0
  4. package/dist/compaction.d.ts.map +1 -0
  5. package/dist/compaction.js +85 -0
  6. package/dist/compaction.js.map +1 -0
  7. package/dist/drag.d.ts +52 -0
  8. package/dist/drag.d.ts.map +1 -0
  9. package/dist/drag.js +120 -0
  10. package/dist/drag.js.map +1 -0
  11. package/dist/events.d.ts +9 -0
  12. package/dist/events.d.ts.map +1 -0
  13. package/dist/events.js +22 -0
  14. package/dist/events.js.map +1 -0
  15. package/dist/geometry.d.ts +33 -0
  16. package/dist/geometry.d.ts.map +1 -0
  17. package/dist/geometry.js +164 -0
  18. package/dist/geometry.js.map +1 -0
  19. package/dist/grid.d.ts +100 -0
  20. package/dist/grid.d.ts.map +1 -0
  21. package/dist/grid.js +539 -0
  22. package/dist/grid.js.map +1 -0
  23. package/dist/group-drag.d.ts +41 -0
  24. package/dist/group-drag.d.ts.map +1 -0
  25. package/dist/group-drag.js +97 -0
  26. package/dist/group-drag.js.map +1 -0
  27. package/dist/index.d.ts +12 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +11 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/loop.d.ts +99 -0
  32. package/dist/loop.d.ts.map +1 -0
  33. package/dist/loop.js +188 -0
  34. package/dist/loop.js.map +1 -0
  35. package/dist/movement.d.ts +17 -0
  36. package/dist/movement.d.ts.map +1 -0
  37. package/dist/movement.js +333 -0
  38. package/dist/movement.js.map +1 -0
  39. package/dist/packing.d.ts +16 -0
  40. package/dist/packing.d.ts.map +1 -0
  41. package/dist/packing.js +159 -0
  42. package/dist/packing.js.map +1 -0
  43. package/dist/pan.d.ts +58 -0
  44. package/dist/pan.d.ts.map +1 -0
  45. package/dist/pan.js +174 -0
  46. package/dist/pan.js.map +1 -0
  47. package/dist/positioning.d.ts +117 -0
  48. package/dist/positioning.d.ts.map +1 -0
  49. package/dist/positioning.js +251 -0
  50. package/dist/positioning.js.map +1 -0
  51. package/dist/repack.d.ts +4 -0
  52. package/dist/repack.d.ts.map +1 -0
  53. package/dist/repack.js +179 -0
  54. package/dist/repack.js.map +1 -0
  55. package/dist/types.d.ts +236 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +4 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/virtualize.d.ts +27 -0
  60. package/dist/virtualize.d.ts.map +1 -0
  61. package/dist/virtualize.js +53 -0
  62. package/dist/virtualize.js.map +1 -0
  63. package/package.json +55 -0
  64. package/src/compaction.ts +80 -0
  65. package/src/drag.ts +146 -0
  66. package/src/events.ts +25 -0
  67. package/src/geometry.ts +199 -0
  68. package/src/grid.ts +578 -0
  69. package/src/group-drag.ts +120 -0
  70. package/src/index.ts +78 -0
  71. package/src/loop.ts +246 -0
  72. package/src/movement.ts +363 -0
  73. package/src/packing.ts +169 -0
  74. package/src/pan.ts +217 -0
  75. package/src/positioning.ts +292 -0
  76. package/src/repack.ts +212 -0
  77. package/src/types.ts +262 -0
  78. package/src/virtualize.ts +77 -0
@@ -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":"AAAA,gEAAgE;AAChE,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;AAC9E,0BAA0B;AAC1B,EAAE;AACF,iBAAiB;AACjB,iDAAiD;AACjD,+EAA+E;AAC/E,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,+CAA+C;AAC/C,6EAA6E;AAC7E,2EAA2E;AAC3E,4EAA4E;AAC5E,6EAA6E;AAC7E,6CAA6C;AAI7C,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAW3C;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAU,EACV,MAAc,EACd,MAAe,EACf,OAAoB,EAAE;IAEtB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAExB,MAAM,UAAU,GAAa,IAAI,CAAC,aAAa,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,UAAU,GAAa,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;IAExF,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAEjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAE5D,sBAAsB;IACtB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,IACE,OAAO,CAAC,MAAM,KAAK,CAAC;QACpB,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC;QAChD,eAAe,CAAC,OAAO,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,EAClC,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QAC1B,MAAM,QAAQ,GAAY,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAY,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,CAAC;QACxE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oEAAoE;IACpE,EAAE;IACF,wEAAwE;IACxE,uEAAuE;IACvE,wEAAwE;IACxE,yEAAyE;IACzE,yEAAyE;IACzE,yEAAyE;IACzE,gEAAgE;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACxD,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3D,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QAChF,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,SAAS,GAAG,KAAK,CAAC;YAAC,MAAM;QAAC,CAAC;IAC3C,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE5B,4DAA4D;IAC5D,oFAAoF;IACpF,uFAAuF;IACvF,MAAM,UAAU,GAAG,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC/D,IAAI,mBAAmB,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC;QAC1C,IAAI,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACrE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED,yCAAyC;IACzC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CACxB,IAAU,EACV,QAAgB,EAChB,YAA0B,EAC1B,UAAoB,EACpB,MAA2B;IAE3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEpC,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAEtC,IAAI,OAAO,GAAG,QAAQ,CAAC;QACvB,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YACX,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;aAAM,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,OAAO,GAAG,QAAQ,CAAC;QACvB,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YACX,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;aAAM,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,CAAS,CAAC;QACd,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;YAAE,SAAS;aAC9B,IAAI,EAAE,KAAK,CAAC;YAAE,CAAC,GAAG,OAAO,CAAC;aAC1B,IAAI,EAAE,KAAK,CAAC;YAAE,CAAC,GAAG,OAAO,CAAC;;YAC1B,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEpC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAE3B,MAAM,SAAS,GAAa;YAC1B,GAAG,EAAE,UAAU,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE;YAC5B,GAAG,EAAE,UAAU,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE;YAC5B,CAAC,EAAE,MAAM,CAAC,CAAC;YACX,CAAC,EAAE,MAAM,CAAC,CAAC;SACZ,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;YAAE,SAAS;QAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QACjC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;YACvE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAU,EAAE,GAAe;IACtD,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,kBAAkB,CACzB,IAAU,EACV,SAAiB,EACjB,UAAoB,EACpB,GAAe;IAEf,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACtE,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,gBAAgB;IAE9D,8EAA8E;IAC9E,wEAAwE;IACxE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,kCAAkC;IAC3E,MAAM,KAAK,GAAgC,EAAE,CAAC;IAE9C,SAAS,kBAAkB,CAAC,MAAY,EAAE,SAAmB;QAC3D,IAAI,EAAE,GAAG,QAAQ,CAAC;QAClB,IAAI,EAAE,GAAG,CAAC;YAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;aAClE,IAAI,EAAE,GAAG,CAAC;YAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QACzE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAClB,IAAI,EAAE,GAAG,CAAC;YAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;aAClE,IAAI,EAAE,GAAG,CAAC;YAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QACzE,IAAI,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACxB,IAAI,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,+DAA+D;IAC/D,SAAS,WAAW,CAAC,CAAO;QAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,KAAK,EAAE,GAAG,MAAM;YAAE,OAAO,KAAK,CAAC;QACnC,MAAM,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;QAC9C,2DAA2D;QAC3D,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS;gBAAE,SAAS;YACxD,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YACxC,IAAI,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,CAAC;gBACxC,2DAA2D;gBAC3D,MAAM,UAAU,GAAG,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBACtD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;oBAAE,OAAO,KAAK,CAAC;gBACxC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBACvC,0EAA0E;gBAC1E,+EAA+E;gBAC/E,0EAA0E;gBAC1E,4DAA4D;gBAC5D,MAAM,UAAU,GAAS;oBACvB,GAAG,KAAK;oBACR,GAAG,EAAE,KAAK,CAAC,GAAG,GAAG,KAAK,GAAG,EAAE;oBAC3B,GAAG,EAAE,KAAK,CAAC,GAAG,GAAG,KAAK,GAAG,EAAE;iBAC5B,CAAC;gBACF,MAAM,KAAK,GAAG,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBACtD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC;gBACnC,MAAM,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;gBAC3B,IAAI,IAAI,IAAI,KAAK;oBAAE,SAAS,CAAC,0BAA0B;gBACvD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,6EAA6E;IAC7E,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS;YAAE,SAAS;QACjC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QACjD,KAAK,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,SAAS,EAAE,CAAC;YAC7C,IAAI,OAAO,KAAK,EAAE;gBAAE,SAAS;YAC7B,IAAI,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC;gBAAE,OAAO,KAAK,CAAC;QAClD,CAAC;IACH,CAAC;IAED,UAAU;IACV,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB,CACxB,IAAU,EACV,MAAc,EACd,MAAe,EACf,GAAe;IAEf,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,UAAU,GAAa;QAC3B,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,CAAC,EAAE,OAAO,CAAC,CAAC;QACZ,CAAC,EAAE,OAAO,CAAC,CAAC;KACb,CAAC;IACF,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,KAAM,CAAC;IACtB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAW,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;YAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,MAAM,OAAO,GAAa;gBACxB,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE;gBACjB,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE;gBACjB,CAAC,EAAE,GAAG,CAAC,CAAC;gBACR,CAAC,EAAE,GAAG,CAAC,CAAC;aACT,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;YACrE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -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"}
@@ -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"}