@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
package/dist/pan.js ADDED
@@ -0,0 +1,174 @@
1
+ // PanController — headless camera for loop mode. No DOM, no timers.
2
+ //
3
+ // The controller owns an unbounded 2D camera offset. Three inputs move it:
4
+ // - dragStart/dragMove/dragEnd: pointer-driven panning. While dragging, the
5
+ // target follows the pointer 1:1 (inverted — content follows the finger)
6
+ // and a velocity estimate is kept; on release the target keeps coasting
7
+ // under exponential friction (inertia/fling).
8
+ // - scrollBy: external deltas (wheel/trackpad). Applied directly to both
9
+ // camera and target — the browser already smooths these.
10
+ // - tick(now): advances easing + inertia. Adapters call this from their rAF
11
+ // loop and apply the camera to the plane's CSS transform.
12
+ //
13
+ // All rates are per-second (exponential, frame-rate independent).
14
+ const SETTLE_DISTANCE = 0.1; // px
15
+ const SETTLE_VELOCITY = 5; // px/s
16
+ const VELOCITY_WINDOW_MS = 100;
17
+ export class PanController {
18
+ constructor(physics = {}) {
19
+ this.x = 0;
20
+ this.y = 0;
21
+ this.targetX = 0;
22
+ this.targetY = 0;
23
+ this.vx = 0;
24
+ this.vy = 0;
25
+ this.dragging = false;
26
+ this.lastPointer = null;
27
+ this.samples = [];
28
+ this.lastTick = null;
29
+ this.friction = physics.friction ?? 4;
30
+ this.ease = physics.ease ?? 12;
31
+ this.maxVelocity = physics.maxVelocity ?? 6000;
32
+ }
33
+ setPhysics(physics) {
34
+ if (physics.friction !== undefined)
35
+ this.friction = physics.friction;
36
+ if (physics.ease !== undefined)
37
+ this.ease = physics.ease;
38
+ if (physics.maxVelocity !== undefined)
39
+ this.maxVelocity = physics.maxVelocity;
40
+ }
41
+ state() {
42
+ const settled = Math.abs(this.targetX - this.x) < SETTLE_DISTANCE &&
43
+ Math.abs(this.targetY - this.y) < SETTLE_DISTANCE &&
44
+ Math.abs(this.vx) < SETTLE_VELOCITY &&
45
+ Math.abs(this.vy) < SETTLE_VELOCITY;
46
+ return {
47
+ x: this.x,
48
+ y: this.y,
49
+ vx: this.vx,
50
+ vy: this.vy,
51
+ isMoving: this.dragging || !settled,
52
+ isDragging: this.dragging,
53
+ };
54
+ }
55
+ /** Begin a pan gesture at pointer position (px, py), in any stable pixel space. */
56
+ dragStart(px, py, now) {
57
+ this.dragging = true;
58
+ this.lastPointer = { x: px, y: py };
59
+ this.samples = [{ t: now, x: px, y: py }];
60
+ // Grabbing the plane stops any in-flight coast.
61
+ this.vx = 0;
62
+ this.vy = 0;
63
+ this.targetX = this.x;
64
+ this.targetY = this.y;
65
+ }
66
+ /** Pointer moved during a pan gesture. */
67
+ dragMove(px, py, now) {
68
+ if (!this.dragging || !this.lastPointer)
69
+ return;
70
+ // Content follows the finger: camera moves opposite the pointer delta.
71
+ this.targetX -= px - this.lastPointer.x;
72
+ this.targetY -= py - this.lastPointer.y;
73
+ this.lastPointer = { x: px, y: py };
74
+ this.samples.push({ t: now, x: px, y: py });
75
+ while (this.samples.length > 2 && now - this.samples[0].t > VELOCITY_WINDOW_MS) {
76
+ this.samples.shift();
77
+ }
78
+ }
79
+ /** End the pan gesture, converting recent pointer motion into a fling. */
80
+ dragEnd(now) {
81
+ if (!this.dragging)
82
+ return;
83
+ this.dragging = false;
84
+ this.lastPointer = null;
85
+ const first = this.samples[0];
86
+ const last = this.samples[this.samples.length - 1];
87
+ if (first && last && last.t > first.t) {
88
+ const dt = (last.t - first.t) / 1000;
89
+ // Pointer velocity, inverted into camera space.
90
+ let vx = -(last.x - first.x) / dt;
91
+ let vy = -(last.y - first.y) / dt;
92
+ const speed = Math.hypot(vx, vy);
93
+ if (speed > this.maxVelocity) {
94
+ const s = this.maxVelocity / speed;
95
+ vx *= s;
96
+ vy *= s;
97
+ }
98
+ this.vx = vx;
99
+ this.vy = vy;
100
+ }
101
+ this.samples = [];
102
+ }
103
+ /** Abort a drag without inertia. */
104
+ dragCancel() {
105
+ this.dragging = false;
106
+ this.lastPointer = null;
107
+ this.samples = [];
108
+ this.vx = 0;
109
+ this.vy = 0;
110
+ }
111
+ /** External scroll delta (native scroll / wheel). Applied directly. */
112
+ scrollBy(dx, dy) {
113
+ this.x += dx;
114
+ this.y += dy;
115
+ this.targetX += dx;
116
+ this.targetY += dy;
117
+ }
118
+ /** Jump the camera (and target) to an absolute offset. Kills motion. */
119
+ moveTo(x, y) {
120
+ this.x = x;
121
+ this.y = y;
122
+ this.targetX = x;
123
+ this.targetY = y;
124
+ this.vx = 0;
125
+ this.vy = 0;
126
+ }
127
+ /** Stop all motion at the current offset. */
128
+ stop() {
129
+ this.targetX = this.x;
130
+ this.targetY = this.y;
131
+ this.vx = 0;
132
+ this.vy = 0;
133
+ }
134
+ /**
135
+ * Advance the simulation to time `now` (ms). Returns the camera state.
136
+ * Call once per animation frame.
137
+ */
138
+ tick(now) {
139
+ const last = this.lastTick ?? now;
140
+ this.lastTick = now;
141
+ let dt = (now - last) / 1000;
142
+ if (dt <= 0)
143
+ return this.state();
144
+ if (dt > 0.1)
145
+ dt = 0.1; // clamp long gaps (tab switch) to avoid jumps
146
+ if (!this.dragging) {
147
+ // Inertia: the target coasts and the velocity decays exponentially.
148
+ const decay = Math.exp(-this.friction * dt);
149
+ if (Math.abs(this.vx) > SETTLE_VELOCITY || Math.abs(this.vy) > SETTLE_VELOCITY) {
150
+ // Integrate v over the step: x += v/friction * (1 - decay)
151
+ const integral = this.friction > 0 ? (1 - decay) / this.friction : dt;
152
+ this.targetX += this.vx * integral;
153
+ this.targetY += this.vy * integral;
154
+ this.vx *= decay;
155
+ this.vy *= decay;
156
+ }
157
+ else {
158
+ this.vx = 0;
159
+ this.vy = 0;
160
+ }
161
+ }
162
+ // Ease the camera toward the target (frame-rate independent lerp).
163
+ const k = 1 - Math.exp(-this.ease * dt);
164
+ this.x += (this.targetX - this.x) * k;
165
+ this.y += (this.targetY - this.y) * k;
166
+ if (Math.abs(this.targetX - this.x) < SETTLE_DISTANCE &&
167
+ Math.abs(this.targetY - this.y) < SETTLE_DISTANCE) {
168
+ this.x = this.targetX;
169
+ this.y = this.targetY;
170
+ }
171
+ return this.state();
172
+ }
173
+ }
174
+ //# sourceMappingURL=pan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pan.js","sourceRoot":"","sources":["../src/pan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import type { GridConfig, Tile } from './types.js';
2
+ /**
3
+ * Whether a tile participates in grid layout. `static`, `relative`, `sticky`,
4
+ * and tiles with no `position` set are all in flow. `absolute` and `fixed`
5
+ * tiles are not.
6
+ */
7
+ export declare function isInFlow(tile: Tile): boolean;
8
+ /** True for tiles that the engine should ignore for collisions and displacement. */
9
+ export declare function isOutOfFlow(tile: Tile): boolean;
10
+ /**
11
+ * Convert `pinned` (in the configured `pinUnits`) to raw pixels. Used by
12
+ * adapters to compute `left/top` for absolute and fixed tiles.
13
+ */
14
+ export declare function pinnedToPixels(pinned: {
15
+ x: number;
16
+ y: number;
17
+ }, config: GridConfig): {
18
+ x: number;
19
+ y: number;
20
+ };
21
+ /** Inverse of `pinnedToPixels`. Convert pixels back to the configured pin-unit space. */
22
+ export declare function pixelsToPin(pixels: {
23
+ x: number;
24
+ y: number;
25
+ }, config: GridConfig): {
26
+ x: number;
27
+ y: number;
28
+ };
29
+ /**
30
+ * Convert `offset` (in the configured `relativeUnits`) to raw pixels. Used by
31
+ * adapters to compute the visual nudge for `relative` tiles.
32
+ */
33
+ export declare function offsetToPixels(offset: {
34
+ x: number;
35
+ y: number;
36
+ }, config: GridConfig): {
37
+ x: number;
38
+ y: number;
39
+ };
40
+ /** Inverse of `offsetToPixels`. */
41
+ export declare function pixelsToOffset(pixels: {
42
+ x: number;
43
+ y: number;
44
+ }, config: GridConfig): {
45
+ x: number;
46
+ y: number;
47
+ };
48
+ /**
49
+ * Inputs to `computeTileLayout`. The adapter supplies live viewport/scroll
50
+ * values so sticky and fixed tiles can react to scrolling.
51
+ */
52
+ export interface TileLayoutInput {
53
+ tile: {
54
+ col: number;
55
+ row: number;
56
+ w: number;
57
+ h: number;
58
+ position?: import('./types.js').TilePosition;
59
+ pinned?: {
60
+ x: number;
61
+ y: number;
62
+ };
63
+ offset?: {
64
+ x: number;
65
+ y: number;
66
+ };
67
+ sticky?: import('./types.js').StickyConfig;
68
+ };
69
+ config: import('./types.js').GridConfig;
70
+ scrollX: number;
71
+ scrollY: number;
72
+ viewportWidth: number;
73
+ viewportHeight: number;
74
+ }
75
+ export interface TileLayout {
76
+ /** Left edge in pixels relative to the scroll content origin. */
77
+ left: number;
78
+ /** Top edge in pixels relative to the scroll content origin. */
79
+ top: number;
80
+ /** Rendered width in pixels (derived from w + cellSize + gap). */
81
+ width: number;
82
+ /** Rendered height in pixels. */
83
+ height: number;
84
+ /** Optional CSS transform — currently used for `relative` offsets. */
85
+ transform?: string;
86
+ /** Stacking hint. Static tiles 1, sticky 40, absolute 30, fixed 50. */
87
+ zIndex: number;
88
+ /**
89
+ * The effective position mode that was applied (after honoring
90
+ * `enablePositioning`). Useful for adapters that want to add classes.
91
+ */
92
+ effective: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky';
93
+ }
94
+ /**
95
+ * Compute where a tile should render in the scroll content, given current
96
+ * scroll/viewport state. Encapsulates the math for relative offsets, absolute
97
+ * pinned coords (in the configured pinUnits), fixed (anchored to the
98
+ * scrollable viewport via `pinned + scroll` math), and sticky (pins at an
99
+ * edge once scrolled past `threshold`). When `GridConfig.enablePositioning`
100
+ * is false, every tile is treated as `static`.
101
+ */
102
+ export declare function computeTileLayout(input: TileLayoutInput): TileLayout;
103
+ /**
104
+ * Adjust pre-computed layouts so multiple sticky tiles pinned to the same edge
105
+ * stack instead of overlapping — the natural CSS-sticky behavior where, as you
106
+ * scroll, a later sticky element pushes the previous one off-screen by taking
107
+ * its pinned spot.
108
+ *
109
+ * Pass the array of {tile, layout} pairs (in any order); this mutates the
110
+ * `layout.left`/`layout.top` values for sticky tiles in place. Run it AFTER
111
+ * `computeTileLayout` and BEFORE rendering. Non-sticky entries are skipped.
112
+ */
113
+ export declare function resolveStickyStacking(entries: {
114
+ tile: TileLayoutInput['tile'];
115
+ layout: TileLayout;
116
+ }[]): void;
117
+ //# sourceMappingURL=positioning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positioning.d.ts","sourceRoot":"","sources":["../src/positioning.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,251 @@
1
+ // Positioning helpers — pure functions, no state.
2
+ //
3
+ // Tiles can opt out of grid flow by setting `position: 'absolute'` or `'fixed'`.
4
+ // Out-of-flow tiles keep their `col/row/w/h` fields (so they can fall back to
5
+ // in-flow if the user toggles position back to 'static') but the layout engine
6
+ // ignores them — they don't displace neighbors and they don't get displaced.
7
+ //
8
+ // Coordinate translation between the configured unit space (pixels / subcell /
9
+ // cells) and raw pixels lives here so adapters and engine share one source of
10
+ // truth.
11
+ /**
12
+ * Whether a tile participates in grid layout. `static`, `relative`, `sticky`,
13
+ * and tiles with no `position` set are all in flow. `absolute` and `fixed`
14
+ * tiles are not.
15
+ */
16
+ export function isInFlow(tile) {
17
+ const p = tile.position;
18
+ return !p || p === 'static' || p === 'relative' || p === 'sticky';
19
+ }
20
+ /** True for tiles that the engine should ignore for collisions and displacement. */
21
+ export function isOutOfFlow(tile) {
22
+ return !isInFlow(tile);
23
+ }
24
+ /**
25
+ * Convert `pinned` (in the configured `pinUnits`) to raw pixels. Used by
26
+ * adapters to compute `left/top` for absolute and fixed tiles.
27
+ */
28
+ export function pinnedToPixels(pinned, config) {
29
+ const colSize = config.unitWidth + (config.gap ?? 0);
30
+ const rowSize = config.unitHeight + (config.gap ?? 0);
31
+ switch (config.pinUnits ?? 'pixels') {
32
+ case 'pixels':
33
+ return { x: pinned.x, y: pinned.y };
34
+ case 'subcell':
35
+ return { x: pinned.x * colSize, y: pinned.y * rowSize };
36
+ case 'cells':
37
+ return { x: Math.round(pinned.x) * colSize, y: Math.round(pinned.y) * rowSize };
38
+ }
39
+ }
40
+ /** Inverse of `pinnedToPixels`. Convert pixels back to the configured pin-unit space. */
41
+ export function pixelsToPin(pixels, config) {
42
+ const colSize = config.unitWidth + (config.gap ?? 0);
43
+ const rowSize = config.unitHeight + (config.gap ?? 0);
44
+ switch (config.pinUnits ?? 'pixels') {
45
+ case 'pixels':
46
+ return { x: pixels.x, y: pixels.y };
47
+ case 'subcell':
48
+ return { x: pixels.x / colSize, y: pixels.y / rowSize };
49
+ case 'cells':
50
+ return { x: Math.round(pixels.x / colSize), y: Math.round(pixels.y / rowSize) };
51
+ }
52
+ }
53
+ /**
54
+ * Convert `offset` (in the configured `relativeUnits`) to raw pixels. Used by
55
+ * adapters to compute the visual nudge for `relative` tiles.
56
+ */
57
+ export function offsetToPixels(offset, config) {
58
+ const colSize = config.unitWidth + (config.gap ?? 0);
59
+ const rowSize = config.unitHeight + (config.gap ?? 0);
60
+ if ((config.relativeUnits ?? 'pixels') === 'pixels') {
61
+ return { x: offset.x, y: offset.y };
62
+ }
63
+ return { x: offset.x * colSize, y: offset.y * rowSize };
64
+ }
65
+ /** Inverse of `offsetToPixels`. */
66
+ export function pixelsToOffset(pixels, config) {
67
+ const colSize = config.unitWidth + (config.gap ?? 0);
68
+ const rowSize = config.unitHeight + (config.gap ?? 0);
69
+ if ((config.relativeUnits ?? 'pixels') === 'pixels') {
70
+ return { x: pixels.x, y: pixels.y };
71
+ }
72
+ return { x: pixels.x / colSize, y: pixels.y / rowSize };
73
+ }
74
+ /**
75
+ * Compute where a tile should render in the scroll content, given current
76
+ * scroll/viewport state. Encapsulates the math for relative offsets, absolute
77
+ * pinned coords (in the configured pinUnits), fixed (anchored to the
78
+ * scrollable viewport via `pinned + scroll` math), and sticky (pins at an
79
+ * edge once scrolled past `threshold`). When `GridConfig.enablePositioning`
80
+ * is false, every tile is treated as `static`.
81
+ */
82
+ export function computeTileLayout(input) {
83
+ const { tile, config, scrollX, scrollY, viewportWidth, viewportHeight } = input;
84
+ const gap = config.gap ?? 0;
85
+ const halfGap = gap / 2;
86
+ const colSize = config.unitWidth + gap;
87
+ const rowSize = config.unitHeight + gap;
88
+ const width = tile.w * config.unitWidth + (tile.w - 1) * gap;
89
+ const height = tile.h * config.unitHeight + (tile.h - 1) * gap;
90
+ const enabled = config.enablePositioning ?? false;
91
+ const pos = enabled ? (tile.position ?? 'static') : 'static';
92
+ if (pos === 'absolute') {
93
+ const px = pinnedToPixels(tile.pinned ?? { x: 0, y: 0 }, config);
94
+ return { left: px.x, top: px.y, width, height, zIndex: 30, effective: 'absolute' };
95
+ }
96
+ if (pos === 'fixed') {
97
+ const px = pinnedToPixels(tile.pinned ?? { x: 0, y: 0 }, config);
98
+ return {
99
+ left: px.x + scrollX,
100
+ top: px.y + scrollY,
101
+ width,
102
+ height,
103
+ zIndex: 50,
104
+ effective: 'fixed',
105
+ };
106
+ }
107
+ if (pos === 'sticky') {
108
+ const sticky = tile.sticky ?? { edge: 'top', threshold: 0 };
109
+ const threshold = sticky.threshold ?? 0;
110
+ let left = tile.col * colSize + halfGap;
111
+ let top = tile.row * rowSize + halfGap;
112
+ if (sticky.edge === 'top') {
113
+ const stickyTop = scrollY + threshold;
114
+ if (top < stickyTop)
115
+ top = stickyTop;
116
+ }
117
+ else if (sticky.edge === 'bottom') {
118
+ const stickyBottom = scrollY + viewportHeight - height - threshold;
119
+ if (top > stickyBottom)
120
+ top = stickyBottom;
121
+ }
122
+ else if (sticky.edge === 'left') {
123
+ const stickyLeft = scrollX + threshold;
124
+ if (left < stickyLeft)
125
+ left = stickyLeft;
126
+ }
127
+ else if (sticky.edge === 'right') {
128
+ const stickyRight = scrollX + viewportWidth - width - threshold;
129
+ if (left > stickyRight)
130
+ left = stickyRight;
131
+ }
132
+ return { left, top, width, height, zIndex: 40, effective: 'sticky' };
133
+ }
134
+ // static / relative — tile is centered in its cell with halfGap inset
135
+ const baseLeft = tile.col * colSize + halfGap;
136
+ const baseTop = tile.row * rowSize + halfGap;
137
+ if (pos === 'relative' && tile.offset) {
138
+ const off = offsetToPixels(tile.offset, config);
139
+ return {
140
+ left: baseLeft,
141
+ top: baseTop,
142
+ width,
143
+ height,
144
+ transform: `translate(${off.x}px, ${off.y}px)`,
145
+ zIndex: 1,
146
+ effective: 'relative',
147
+ };
148
+ }
149
+ return { left: baseLeft, top: baseTop, width, height, zIndex: 1, effective: 'static' };
150
+ }
151
+ /**
152
+ * Adjust pre-computed layouts so multiple sticky tiles pinned to the same edge
153
+ * stack instead of overlapping — the natural CSS-sticky behavior where, as you
154
+ * scroll, a later sticky element pushes the previous one off-screen by taking
155
+ * its pinned spot.
156
+ *
157
+ * Pass the array of {tile, layout} pairs (in any order); this mutates the
158
+ * `layout.left`/`layout.top` values for sticky tiles in place. Run it AFTER
159
+ * `computeTileLayout` and BEFORE rendering. Non-sticky entries are skipped.
160
+ */
161
+ export function resolveStickyStacking(entries) {
162
+ const tops = [];
163
+ const bots = [];
164
+ const lefts = [];
165
+ const rights = [];
166
+ for (const e of entries) {
167
+ if (e.layout.effective !== 'sticky')
168
+ continue;
169
+ const edge = e.tile.sticky?.edge ?? 'top';
170
+ if (edge === 'top')
171
+ tops.push(e);
172
+ else if (edge === 'bottom')
173
+ bots.push(e);
174
+ else if (edge === 'left')
175
+ lefts.push(e);
176
+ else
177
+ rights.push(e);
178
+ }
179
+ // Top: sort by natural row ascending. A later (larger-row) sticky whose
180
+ // current rendered top intrudes on an earlier one pushes it up off-screen.
181
+ tops.sort((a, b) => a.tile.row - b.tile.row);
182
+ for (let i = 0; i < tops.length; i++) {
183
+ const a = tops[i];
184
+ if (!a)
185
+ continue;
186
+ for (let j = i + 1; j < tops.length; j++) {
187
+ const b = tops[j];
188
+ if (!b)
189
+ continue;
190
+ const aBottom = a.layout.top + a.layout.height;
191
+ if (b.layout.top < aBottom) {
192
+ a.layout.top = b.layout.top - a.layout.height;
193
+ break;
194
+ }
195
+ }
196
+ }
197
+ // Bottom: mirror of top — sort by natural row descending.
198
+ bots.sort((a, b) => b.tile.row - a.tile.row);
199
+ for (let i = 0; i < bots.length; i++) {
200
+ const a = bots[i];
201
+ if (!a)
202
+ continue;
203
+ for (let j = i + 1; j < bots.length; j++) {
204
+ const b = bots[j];
205
+ if (!b)
206
+ continue;
207
+ const aTop = a.layout.top;
208
+ const bBottom = b.layout.top + b.layout.height;
209
+ if (bBottom > aTop) {
210
+ a.layout.top = bBottom;
211
+ break;
212
+ }
213
+ }
214
+ }
215
+ // Left: mirror of top along the col axis.
216
+ lefts.sort((a, b) => a.tile.col - b.tile.col);
217
+ for (let i = 0; i < lefts.length; i++) {
218
+ const a = lefts[i];
219
+ if (!a)
220
+ continue;
221
+ for (let j = i + 1; j < lefts.length; j++) {
222
+ const b = lefts[j];
223
+ if (!b)
224
+ continue;
225
+ const aRight = a.layout.left + a.layout.width;
226
+ if (b.layout.left < aRight) {
227
+ a.layout.left = b.layout.left - a.layout.width;
228
+ break;
229
+ }
230
+ }
231
+ }
232
+ // Right: mirror of bottom along the col axis.
233
+ rights.sort((a, b) => b.tile.col - a.tile.col);
234
+ for (let i = 0; i < rights.length; i++) {
235
+ const a = rights[i];
236
+ if (!a)
237
+ continue;
238
+ for (let j = i + 1; j < rights.length; j++) {
239
+ const b = rights[j];
240
+ if (!b)
241
+ continue;
242
+ const aLeft = a.layout.left;
243
+ const bRight = b.layout.left + b.layout.width;
244
+ if (bRight > aLeft) {
245
+ a.layout.left = bRight;
246
+ break;
247
+ }
248
+ }
249
+ }
250
+ }
251
+ //# sourceMappingURL=positioning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positioning.js","sourceRoot":"","sources":["../src/positioning.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,iFAAiF;AACjF,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,SAAS;AAIT;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAU;IACjC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;IACxB,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,QAAQ,CAAC;AACpE,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,WAAW,CAAC,IAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAgC,EAChC,MAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACtD,QAAQ,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;QACpC,KAAK,QAAQ;YACX,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QACtC,KAAK,SAAS;YACZ,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;QAC1D,KAAK,OAAO;YACV,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;IACpF,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,WAAW,CACzB,MAAgC,EAChC,MAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACtD,QAAQ,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;QACpC,KAAK,QAAQ;YACX,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QACtC,KAAK,SAAS;YACZ,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;QAC1D,KAAK,OAAO;YACV,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;IACpF,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAgC,EAChC,MAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;AAC1D,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,cAAc,CAC5B,MAAgC,EAChC,MAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;AAC1D,CAAC;AAmCD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAsB;IACtD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAChF,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5B,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,iBAAiB,IAAI,KAAK,CAAC;IAClD,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAE7D,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;IACrF,CAAC;IACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,MAAM,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjE,OAAO;YACL,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,OAAO;YACpB,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,OAAO;YACnB,KAAK;YACL,MAAM;YACN,MAAM,EAAE,EAAE;YACV,SAAS,EAAE,OAAO;SACnB,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QAC5D,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,OAAO,GAAG,OAAO,CAAC;QACxC,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,GAAG,OAAO,GAAG,OAAO,CAAC;QACvC,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;YACtC,IAAI,GAAG,GAAG,SAAS;gBAAE,GAAG,GAAG,SAAS,CAAC;QACvC,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,YAAY,GAAG,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;YACnE,IAAI,GAAG,GAAG,YAAY;gBAAE,GAAG,GAAG,YAAY,CAAC;QAC7C,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAClC,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;YACvC,IAAI,IAAI,GAAG,UAAU;gBAAE,IAAI,GAAG,UAAU,CAAC;QAC3C,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACnC,MAAM,WAAW,GAAG,OAAO,GAAG,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC;YAChE,IAAI,IAAI,GAAG,WAAW;gBAAE,IAAI,GAAG,WAAW,CAAC;QAC7C,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACvE,CAAC;IACD,sEAAsE;IACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,GAAG,OAAO,GAAG,OAAO,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,GAAG,OAAO,GAAG,OAAO,CAAC;IAC7C,IAAI,GAAG,KAAK,UAAU,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,GAAG,EAAE,OAAO;YACZ,KAAK;YACL,MAAM;YACN,SAAS,EAAE,aAAa,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,KAAK;YAC9C,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,UAAU;SACtB,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AACzF,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAgE;IAEhE,MAAM,IAAI,GAA4D,EAAE,CAAC;IACzE,MAAM,IAAI,GAA4D,EAAE,CAAC;IACzE,MAAM,KAAK,GAA4D,EAAE,CAAC;IAC1E,MAAM,MAAM,GAA4D,EAAE,CAAC;IAC3E,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,KAAK,QAAQ;YAAE,SAAS;QAC9C,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,KAAK,CAAC;QAC1C,IAAI,IAAI,KAAK,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aAC5B,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACpC,IAAI,IAAI,KAAK,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACnC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IAED,wEAAwE;IACxE,2EAA2E;IAC3E,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;YAC/C,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC;gBAC3B,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;gBAC9C,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YAC1B,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;YAC/C,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;gBACnB,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,OAAO,CAAC;gBACvB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACnB,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC9C,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC;gBAC3B,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC/C,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;YAC5B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC9C,IAAI,MAAM,GAAG,KAAK,EAAE,CAAC;gBACnB,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC;gBACvB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { CellPos, CellRect } from './types.js';
2
+ import type { Grid } from './grid.js';
3
+ export declare function solvePushBFS(grid: Grid, tileId: string, target: CellPos, originRect: CellRect): boolean;
4
+ //# sourceMappingURL=repack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repack.d.ts","sourceRoot":"","sources":["../src/repack.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAiBtC,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,QAAQ,GACnB,OAAO,CAoHT"}