vlist 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -28
- package/dist/internals.js +1 -60
- package/package.json +1 -1
- package/dist/constants.js +0 -83
- package/dist/core/create.js +0 -740
- package/dist/core/dom.js +0 -47
- package/dist/core/hooks.js +0 -67
- package/dist/core/index.js +0 -13
- package/dist/core/pipeline.js +0 -307
- package/dist/core/pool.js +0 -42
- package/dist/core/scroll.js +0 -137
- package/dist/core/sizes.js +0 -6
- package/dist/core/state.js +0 -56
- package/dist/core/types.js +0 -7
- package/dist/core/velocity.js +0 -33
- package/dist/events/emitter.js +0 -60
- package/dist/events/index.js +0 -6
- package/dist/plugins/a11y/index.js +0 -1
- package/dist/plugins/a11y/plugin.js +0 -259
- package/dist/plugins/async/index.js +0 -12
- package/dist/plugins/async/manager.js +0 -568
- package/dist/plugins/async/placeholder.js +0 -154
- package/dist/plugins/async/plugin.js +0 -311
- package/dist/plugins/async/sparse.js +0 -540
- package/dist/plugins/autosize/index.js +0 -4
- package/dist/plugins/autosize/plugin.js +0 -185
- package/dist/plugins/grid/index.js +0 -5
- package/dist/plugins/grid/layout.js +0 -275
- package/dist/plugins/grid/plugin.js +0 -347
- package/dist/plugins/grid/renderer.js +0 -525
- package/dist/plugins/grid/types.js +0 -11
- package/dist/plugins/groups/async-bridge.js +0 -246
- package/dist/plugins/groups/index.js +0 -13
- package/dist/plugins/groups/layout.js +0 -294
- package/dist/plugins/groups/plugin.js +0 -571
- package/dist/plugins/groups/sticky.js +0 -255
- package/dist/plugins/groups/types.js +0 -12
- package/dist/plugins/masonry/index.js +0 -6
- package/dist/plugins/masonry/layout.js +0 -261
- package/dist/plugins/masonry/plugin.js +0 -381
- package/dist/plugins/masonry/renderer.js +0 -354
- package/dist/plugins/masonry/types.js +0 -9
- package/dist/plugins/page/index.js +0 -5
- package/dist/plugins/page/plugin.js +0 -166
- package/dist/plugins/scale/index.js +0 -4
- package/dist/plugins/scale/plugin.js +0 -507
- package/dist/plugins/scrollbar/controller.js +0 -574
- package/dist/plugins/scrollbar/index.js +0 -6
- package/dist/plugins/scrollbar/plugin.js +0 -93
- package/dist/plugins/scrollbar/scrollbar.js +0 -556
- package/dist/plugins/selection/index.js +0 -7
- package/dist/plugins/selection/plugin.js +0 -601
- package/dist/plugins/selection/state.js +0 -332
- package/dist/plugins/snapshots/index.js +0 -5
- package/dist/plugins/snapshots/plugin.js +0 -301
- package/dist/plugins/sortable/index.js +0 -6
- package/dist/plugins/sortable/plugin.js +0 -753
- package/dist/plugins/table/header.js +0 -501
- package/dist/plugins/table/index.js +0 -12
- package/dist/plugins/table/layout.js +0 -211
- package/dist/plugins/table/plugin.js +0 -391
- package/dist/plugins/table/renderer.js +0 -625
- package/dist/plugins/table/types.js +0 -12
- package/dist/plugins/transition/index.js +0 -5
- package/dist/plugins/transition/plugin.js +0 -405
- package/dist/rendering/aria.js +0 -23
- package/dist/rendering/index.js +0 -18
- package/dist/rendering/measured.js +0 -98
- package/dist/rendering/renderer.js +0 -586
- package/dist/rendering/scale.js +0 -267
- package/dist/rendering/scroll.js +0 -71
- package/dist/rendering/sizes.js +0 -193
- package/dist/rendering/sort.js +0 -65
- package/dist/rendering/viewport.js +0 -268
- package/dist/types.js +0 -5
- package/dist/utils/padding.js +0 -49
- package/dist/utils/stats.js +0 -124
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vlist v2 — Masonry Plugin
|
|
3
|
-
*
|
|
4
|
-
* Switches from list layout to masonry/Pinterest-style layout with
|
|
5
|
-
* shortest-lane placement. Each item is positioned in the shortest
|
|
6
|
-
* column, creating an organic packed layout.
|
|
7
|
-
*
|
|
8
|
-
* Priority 10 — runs before selection (50) so layout is ready.
|
|
9
|
-
*
|
|
10
|
-
* Restrictions:
|
|
11
|
-
* - Cannot be combined with grid or table plugins
|
|
12
|
-
* - Cannot be combined with reverse: true
|
|
13
|
-
*/
|
|
14
|
-
import { createMasonryLayout } from "./layout";
|
|
15
|
-
import { createMasonryRenderer } from "./renderer";
|
|
16
|
-
// =============================================================================
|
|
17
|
-
// Constants
|
|
18
|
-
// =============================================================================
|
|
19
|
-
const OVERSCAN_PX_PER_UNIT = 100;
|
|
20
|
-
const EMPTY_ID_SET = new Set();
|
|
21
|
-
// =============================================================================
|
|
22
|
-
// Factory
|
|
23
|
-
// =============================================================================
|
|
24
|
-
export function masonry(config) {
|
|
25
|
-
if (!config.columns || config.columns < 1) {
|
|
26
|
-
throw new Error("[vlist] masonry: columns must be >= 1");
|
|
27
|
-
}
|
|
28
|
-
let layout;
|
|
29
|
-
let renderer = null;
|
|
30
|
-
let engineState;
|
|
31
|
-
let storedCtx = null;
|
|
32
|
-
let hz;
|
|
33
|
-
let classPrefix;
|
|
34
|
-
let overscanPx;
|
|
35
|
-
let cachedPlacements = [];
|
|
36
|
-
let lastScrollPosition = -1;
|
|
37
|
-
let lastContainerSize = -1;
|
|
38
|
-
let forceNextRender = true;
|
|
39
|
-
let lastLayoutTotal = -1;
|
|
40
|
-
// Reusable masonry context for size function
|
|
41
|
-
const masonryCtx = {
|
|
42
|
-
columnWidth: 0,
|
|
43
|
-
columns: 0,
|
|
44
|
-
gap: 0,
|
|
45
|
-
containerWidth: 0,
|
|
46
|
-
};
|
|
47
|
-
// Persistent getItem closure — avoids per-render allocation
|
|
48
|
-
let cachedItems = [];
|
|
49
|
-
const getItem = (index) => cachedItems[index];
|
|
50
|
-
// Selection method references (resolved lazily)
|
|
51
|
-
let selectedIdsGetter = null;
|
|
52
|
-
let focusedIndexGetter = null;
|
|
53
|
-
let selectionResolved = false;
|
|
54
|
-
function resolveSelectionMethods() {
|
|
55
|
-
if (selectionResolved || !storedCtx)
|
|
56
|
-
return;
|
|
57
|
-
selectionResolved = true;
|
|
58
|
-
selectedIdsGetter = storedCtx.getMethod("_getSelectedIds") ?? null;
|
|
59
|
-
focusedIndexGetter = storedCtx.getMethod("_getFocusedIndex") ?? null;
|
|
60
|
-
}
|
|
61
|
-
// ── Per-lane navigation index ──
|
|
62
|
-
let laneItems = [];
|
|
63
|
-
let itemLanePos = new Int32Array(0);
|
|
64
|
-
let laneYCenters = [];
|
|
65
|
-
function rebuildLaneIndex() {
|
|
66
|
-
const cols = layout.columns;
|
|
67
|
-
const total = cachedPlacements.length;
|
|
68
|
-
laneItems = new Array(cols);
|
|
69
|
-
for (let c = 0; c < cols; c++)
|
|
70
|
-
laneItems[c] = [];
|
|
71
|
-
if (itemLanePos.length < total) {
|
|
72
|
-
itemLanePos = new Int32Array(total);
|
|
73
|
-
}
|
|
74
|
-
for (let i = 0; i < total; i++) {
|
|
75
|
-
const p = cachedPlacements[i];
|
|
76
|
-
const pos = laneItems[p.lane].length;
|
|
77
|
-
laneItems[p.lane].push(i);
|
|
78
|
-
itemLanePos[i] = pos;
|
|
79
|
-
}
|
|
80
|
-
laneYCenters = new Array(cols);
|
|
81
|
-
for (let c = 0; c < cols; c++) {
|
|
82
|
-
const items = laneItems[c];
|
|
83
|
-
const yc = new Float64Array(items.length);
|
|
84
|
-
for (let j = 0; j < items.length; j++) {
|
|
85
|
-
const p = cachedPlacements[items[j]];
|
|
86
|
-
yc[j] = p.y + p.size * 0.5;
|
|
87
|
-
}
|
|
88
|
-
laneYCenters[c] = yc;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
function bsNearest(arr, target) {
|
|
92
|
-
const len = arr.length;
|
|
93
|
-
if (!len)
|
|
94
|
-
return -1;
|
|
95
|
-
let lo = 0;
|
|
96
|
-
let hi = len - 1;
|
|
97
|
-
while (lo < hi) {
|
|
98
|
-
const mid = (lo + hi) >> 1;
|
|
99
|
-
if (arr[mid] < target)
|
|
100
|
-
lo = mid + 1;
|
|
101
|
-
else
|
|
102
|
-
hi = mid;
|
|
103
|
-
}
|
|
104
|
-
if (lo > 0 && Math.abs(arr[lo - 1] - target) <= Math.abs(arr[lo] - target)) {
|
|
105
|
-
return lo - 1;
|
|
106
|
-
}
|
|
107
|
-
return lo;
|
|
108
|
-
}
|
|
109
|
-
function navigate(currentIndex, key, total) {
|
|
110
|
-
const placement = cachedPlacements[currentIndex];
|
|
111
|
-
if (!placement)
|
|
112
|
-
return currentIndex;
|
|
113
|
-
const lane = placement.lane;
|
|
114
|
-
const cols = layout.columns;
|
|
115
|
-
const posInLane = itemLanePos[currentIndex];
|
|
116
|
-
const myLane = laneItems[lane];
|
|
117
|
-
const k = hz
|
|
118
|
-
? key === "ArrowDown" ? "ArrowRight"
|
|
119
|
-
: key === "ArrowUp" ? "ArrowLeft"
|
|
120
|
-
: key === "ArrowRight" ? "ArrowDown"
|
|
121
|
-
: key === "ArrowLeft" ? "ArrowUp"
|
|
122
|
-
: key
|
|
123
|
-
: key;
|
|
124
|
-
switch (k) {
|
|
125
|
-
case "ArrowDown":
|
|
126
|
-
if (posInLane + 1 < myLane.length)
|
|
127
|
-
return myLane[posInLane + 1];
|
|
128
|
-
return currentIndex;
|
|
129
|
-
case "ArrowUp":
|
|
130
|
-
if (posInLane > 0)
|
|
131
|
-
return myLane[posInLane - 1];
|
|
132
|
-
return currentIndex;
|
|
133
|
-
case "ArrowRight": {
|
|
134
|
-
if (lane >= cols - 1)
|
|
135
|
-
return currentIndex;
|
|
136
|
-
const targetLane = lane + 1;
|
|
137
|
-
const yCenter = placement.y + placement.size * 0.5;
|
|
138
|
-
const targetItems = laneItems[targetLane];
|
|
139
|
-
if (!targetItems.length)
|
|
140
|
-
return currentIndex;
|
|
141
|
-
const pos = bsNearest(laneYCenters[targetLane], yCenter);
|
|
142
|
-
return pos >= 0 ? targetItems[pos] : currentIndex;
|
|
143
|
-
}
|
|
144
|
-
case "ArrowLeft": {
|
|
145
|
-
if (lane <= 0)
|
|
146
|
-
return currentIndex;
|
|
147
|
-
const targetLane = lane - 1;
|
|
148
|
-
const yCenter = placement.y + placement.size * 0.5;
|
|
149
|
-
const targetItems = laneItems[targetLane];
|
|
150
|
-
if (!targetItems.length)
|
|
151
|
-
return currentIndex;
|
|
152
|
-
const pos = bsNearest(laneYCenters[targetLane], yCenter);
|
|
153
|
-
return pos >= 0 ? targetItems[pos] : currentIndex;
|
|
154
|
-
}
|
|
155
|
-
case "Home":
|
|
156
|
-
return 0;
|
|
157
|
-
case "End":
|
|
158
|
-
return total - 1;
|
|
159
|
-
case "PageDown": {
|
|
160
|
-
const containerSize = engineState.containerSize;
|
|
161
|
-
const itemSize = placement.size > 0 ? placement.size : 150;
|
|
162
|
-
const jump = Math.max(1, Math.floor(containerSize / itemSize));
|
|
163
|
-
const target = Math.min(posInLane + jump, myLane.length - 1);
|
|
164
|
-
return myLane[target];
|
|
165
|
-
}
|
|
166
|
-
case "PageUp": {
|
|
167
|
-
const containerSize = engineState.containerSize;
|
|
168
|
-
const itemSize = placement.size > 0 ? placement.size : 150;
|
|
169
|
-
const jump = Math.max(1, Math.floor(containerSize / itemSize));
|
|
170
|
-
const target = Math.max(0, posInLane - jump);
|
|
171
|
-
return myLane[target];
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return currentIndex;
|
|
175
|
-
}
|
|
176
|
-
let rawSizeSpec = null;
|
|
177
|
-
function getSizeFn() {
|
|
178
|
-
if (config.size) {
|
|
179
|
-
return (index) => config.size(index, masonryCtx);
|
|
180
|
-
}
|
|
181
|
-
if (rawSizeSpec !== null && typeof rawSizeSpec === "function") {
|
|
182
|
-
return (index) => rawSizeSpec(index, masonryCtx);
|
|
183
|
-
}
|
|
184
|
-
return (index) => storedCtx.sizeCache.getSize(index);
|
|
185
|
-
}
|
|
186
|
-
function updateMasonryContext() {
|
|
187
|
-
const cols = layout.columns;
|
|
188
|
-
const g = layout.gap;
|
|
189
|
-
masonryCtx.containerWidth = layout.containerSize;
|
|
190
|
-
masonryCtx.columns = cols;
|
|
191
|
-
masonryCtx.gap = g;
|
|
192
|
-
masonryCtx.columnWidth = Math.max(0, (layout.containerSize - (cols - 1) * g) / cols);
|
|
193
|
-
}
|
|
194
|
-
function calculateLayout() {
|
|
195
|
-
if (!storedCtx)
|
|
196
|
-
return;
|
|
197
|
-
updateMasonryContext();
|
|
198
|
-
const totalItems = engineState.totalItems;
|
|
199
|
-
cachedPlacements = layout.calculateLayout(totalItems, getSizeFn());
|
|
200
|
-
lastLayoutTotal = totalItems;
|
|
201
|
-
rebuildLaneIndex();
|
|
202
|
-
const totalSize = layout.getTotalSize(cachedPlacements);
|
|
203
|
-
storedCtx.updateContentSize(totalSize);
|
|
204
|
-
}
|
|
205
|
-
function masonryRenderIfNeeded() {
|
|
206
|
-
if (engineState.destroyed || !storedCtx || !renderer)
|
|
207
|
-
return;
|
|
208
|
-
// Recalculate layout if data changed
|
|
209
|
-
if (engineState.totalItems !== lastLayoutTotal) {
|
|
210
|
-
calculateLayout();
|
|
211
|
-
}
|
|
212
|
-
resolveSelectionMethods();
|
|
213
|
-
const scrollPosition = engineState.scrollPosition;
|
|
214
|
-
const containerSize = engineState.containerSize;
|
|
215
|
-
if (!forceNextRender && scrollPosition === lastScrollPosition && containerSize === lastContainerSize) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
lastScrollPosition = scrollPosition;
|
|
219
|
-
lastContainerSize = containerSize;
|
|
220
|
-
forceNextRender = false;
|
|
221
|
-
if (containerSize <= 0 || cachedPlacements.length === 0)
|
|
222
|
-
return;
|
|
223
|
-
const mainAxisStart = Math.max(0, scrollPosition - overscanPx);
|
|
224
|
-
const mainAxisEnd = scrollPosition + containerSize + overscanPx;
|
|
225
|
-
const visiblePlacements = layout.getVisibleItems(cachedPlacements, mainAxisStart, mainAxisEnd);
|
|
226
|
-
const selectedIds = selectedIdsGetter?.() ?? EMPTY_ID_SET;
|
|
227
|
-
const focusedIndex = focusedIndexGetter?.() ?? -1;
|
|
228
|
-
cachedItems = storedCtx.getItems();
|
|
229
|
-
renderer.render(getItem, visiblePlacements, selectedIds, focusedIndex);
|
|
230
|
-
// Update engine state for other plugins
|
|
231
|
-
const vLen = visiblePlacements.length;
|
|
232
|
-
const firstIndex = vLen > 0 ? visiblePlacements[0].index : 0;
|
|
233
|
-
const lastIndex = vLen > 0 ? visiblePlacements[vLen - 1].index : 0;
|
|
234
|
-
engineState.prevRangeStart = firstIndex;
|
|
235
|
-
engineState.prevRangeEnd = lastIndex;
|
|
236
|
-
engineState.renderPending = false;
|
|
237
|
-
// Fill EngineState buffers for plugins that read them
|
|
238
|
-
const count = Math.min(vLen, engineState.capacity);
|
|
239
|
-
engineState.visibleCount = count;
|
|
240
|
-
engineState.startIndex = firstIndex;
|
|
241
|
-
for (let i = 0; i < count; i++) {
|
|
242
|
-
const p = visiblePlacements[i];
|
|
243
|
-
engineState.visibleIndices[i] = p.index;
|
|
244
|
-
engineState.visibleOffsets[i] = p.y;
|
|
245
|
-
engineState.visibleSizes[i] = p.size;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
function masonryForceRender() {
|
|
249
|
-
if (engineState.destroyed)
|
|
250
|
-
return;
|
|
251
|
-
calculateLayout();
|
|
252
|
-
engineState.prevRangeStart = -1;
|
|
253
|
-
engineState.prevRangeEnd = -1;
|
|
254
|
-
engineState.renderPending = true;
|
|
255
|
-
forceNextRender = true;
|
|
256
|
-
masonryRenderIfNeeded();
|
|
257
|
-
}
|
|
258
|
-
return {
|
|
259
|
-
name: "masonry",
|
|
260
|
-
priority: 10,
|
|
261
|
-
conflicts: ["grid", "table"],
|
|
262
|
-
setup(ctx) {
|
|
263
|
-
storedCtx = ctx;
|
|
264
|
-
engineState = ctx.getState();
|
|
265
|
-
rawSizeSpec = ctx.rawSizeSpec;
|
|
266
|
-
hz = ctx.config.horizontal;
|
|
267
|
-
classPrefix = ctx.config.classPrefix;
|
|
268
|
-
overscanPx = ctx.config.overscan * OVERSCAN_PX_PER_UNIT;
|
|
269
|
-
if (ctx.config.reverse) {
|
|
270
|
-
throw new Error("[vlist] masonry: cannot be combined with reverse mode");
|
|
271
|
-
}
|
|
272
|
-
const containerCrossSize = engineState.crossSize;
|
|
273
|
-
layout = createMasonryLayout({
|
|
274
|
-
columns: config.columns,
|
|
275
|
-
gap: config.gap ?? 0,
|
|
276
|
-
containerSize: containerCrossSize,
|
|
277
|
-
});
|
|
278
|
-
renderer = createMasonryRenderer(ctx.dom.content, ctx.template, classPrefix, hz, () => engineState.totalItems, undefined, undefined, ctx.config.interactive);
|
|
279
|
-
ctx.dom.root.classList.add(`${classPrefix}--masonry`);
|
|
280
|
-
// Replace render pipeline
|
|
281
|
-
ctx.setRenderFn(masonryRenderIfNeeded, masonryForceRender);
|
|
282
|
-
// Initial layout
|
|
283
|
-
calculateLayout();
|
|
284
|
-
// ── Public methods ─────────────────────────────────────────
|
|
285
|
-
ctx.registerMethod("getMasonryLayout", () => layout);
|
|
286
|
-
ctx.registerMethod("updateMasonry", (newConfig) => {
|
|
287
|
-
if (newConfig.columns !== undefined && newConfig.columns < 1) {
|
|
288
|
-
throw new Error("[vlist] updateMasonry: columns must be >= 1");
|
|
289
|
-
}
|
|
290
|
-
if (newConfig.gap !== undefined && newConfig.gap < 0) {
|
|
291
|
-
throw new Error("[vlist] updateMasonry: gap must be >= 0");
|
|
292
|
-
}
|
|
293
|
-
const updates = {};
|
|
294
|
-
if (newConfig.columns !== undefined)
|
|
295
|
-
updates.columns = newConfig.columns;
|
|
296
|
-
if (newConfig.gap !== undefined)
|
|
297
|
-
updates.gap = newConfig.gap;
|
|
298
|
-
layout.update(updates);
|
|
299
|
-
renderer?.clear();
|
|
300
|
-
masonryForceRender();
|
|
301
|
-
});
|
|
302
|
-
// scrollToIndex: map item index to its placement position
|
|
303
|
-
ctx.registerMethod("scrollToIndex", (index, alignOrOptions = "start") => {
|
|
304
|
-
const placement = cachedPlacements[index];
|
|
305
|
-
if (!placement)
|
|
306
|
-
return;
|
|
307
|
-
const align = typeof alignOrOptions === "string" ? alignOrOptions : (alignOrOptions.align ?? "start");
|
|
308
|
-
const behavior = typeof alignOrOptions === "object" ? alignOrOptions.behavior : undefined;
|
|
309
|
-
const duration = typeof alignOrOptions === "object" ? alignOrOptions.duration : undefined;
|
|
310
|
-
const containerSize = engineState.containerSize;
|
|
311
|
-
const totalSize = layout.getTotalSize(cachedPlacements);
|
|
312
|
-
const maxScroll = Math.max(0, totalSize - containerSize);
|
|
313
|
-
let pos = placement.y;
|
|
314
|
-
if (align === "center") {
|
|
315
|
-
pos = placement.y - containerSize / 2 + placement.size / 2;
|
|
316
|
-
}
|
|
317
|
-
else if (align === "end") {
|
|
318
|
-
pos = placement.y - containerSize + placement.size;
|
|
319
|
-
if (index >= engineState.totalItems - 1 && placement.y + placement.size > maxScroll) {
|
|
320
|
-
pos = maxScroll;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
pos = Math.max(0, Math.min(pos, maxScroll));
|
|
324
|
-
if (behavior === "smooth" && duration && duration > 0) {
|
|
325
|
-
ctx.smoothScrollTo(pos, duration);
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
ctx.scrollTo(pos);
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
// Placement-based scroll into view (used by selection focus)
|
|
332
|
-
ctx.registerMethod("_scrollItemIntoView", (index) => {
|
|
333
|
-
const placement = cachedPlacements[index];
|
|
334
|
-
if (!placement)
|
|
335
|
-
return;
|
|
336
|
-
const scrollPos = engineState.scrollPosition;
|
|
337
|
-
const containerSize = engineState.containerSize;
|
|
338
|
-
const itemTop = placement.y;
|
|
339
|
-
const itemBottom = itemTop + placement.size;
|
|
340
|
-
if (itemTop < scrollPos) {
|
|
341
|
-
ctx.scrollTo(Math.max(0, itemTop));
|
|
342
|
-
}
|
|
343
|
-
else if (itemBottom > scrollPos + containerSize) {
|
|
344
|
-
ctx.scrollTo(itemBottom - containerSize);
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
// ── Lane-aware 2D keyboard navigation ─────────────────────
|
|
348
|
-
ctx.setNavConfig({
|
|
349
|
-
total: () => engineState.totalItems,
|
|
350
|
-
navigate,
|
|
351
|
-
});
|
|
352
|
-
// ── Cleanup ────────────────────────────────────────────────
|
|
353
|
-
ctx.registerDestroyHandler(() => {
|
|
354
|
-
renderer?.destroy();
|
|
355
|
-
renderer = null;
|
|
356
|
-
ctx.dom.root.classList.remove(`${classPrefix}--masonry`);
|
|
357
|
-
});
|
|
358
|
-
},
|
|
359
|
-
hooks: {
|
|
360
|
-
onResize(_width, _height) {
|
|
361
|
-
if (!layout || !storedCtx)
|
|
362
|
-
return;
|
|
363
|
-
const newCross = engineState.crossSize;
|
|
364
|
-
if (Math.abs(newCross - layout.containerSize) < 1)
|
|
365
|
-
return;
|
|
366
|
-
layout.update({ containerSize: newCross });
|
|
367
|
-
renderer?.clear();
|
|
368
|
-
masonryForceRender();
|
|
369
|
-
},
|
|
370
|
-
onIdle() {
|
|
371
|
-
renderer?.sortDOM();
|
|
372
|
-
},
|
|
373
|
-
},
|
|
374
|
-
destroy() {
|
|
375
|
-
renderer?.destroy();
|
|
376
|
-
renderer = null;
|
|
377
|
-
cachedPlacements = [];
|
|
378
|
-
storedCtx = null;
|
|
379
|
-
},
|
|
380
|
-
};
|
|
381
|
-
}
|