Add masonry layout functionality
This commit is contained in:
parent
17c8071de9
commit
ab0b11cc92
3 changed files with 67 additions and 0 deletions
52
internal/assets/static/js/masonry.js
Normal file
52
internal/assets/static/js/masonry.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { clamp } from "./utils.js";
|
||||
|
||||
export function setupMasonries(options = {}, selector = ".masonry") {
|
||||
options = {
|
||||
minColumnWidth: 300,
|
||||
maxColumns: 6,
|
||||
...options
|
||||
};
|
||||
|
||||
const masonryContainers = document.querySelectorAll(selector);
|
||||
|
||||
for (let i = 0; i < masonryContainers.length; i++) {
|
||||
const container = masonryContainers[i];
|
||||
const items = Array.from(container.children);
|
||||
let previousColumnsCount = 0;
|
||||
|
||||
const render = function() {
|
||||
const columnsCount = clamp(
|
||||
Math.floor(container.offsetWidth / options.minColumnWidth),
|
||||
1,
|
||||
Math.min(options.maxColumns, items.length)
|
||||
);
|
||||
|
||||
if (columnsCount === previousColumnsCount) {
|
||||
return;
|
||||
} else {
|
||||
container.textContent = "";
|
||||
previousColumnsCount = columnsCount;
|
||||
}
|
||||
|
||||
const columnsFragment = document.createDocumentFragment();
|
||||
|
||||
for (let i = 0; i < columnsCount; i++) {
|
||||
const column = document.createElement("div");
|
||||
column.className = "masonry-column";
|
||||
columnsFragment.append(column);
|
||||
}
|
||||
|
||||
// poor man's masonry
|
||||
// TODO: add an option that allows placing items in the
|
||||
// shortest column instead of iterating the columns in order
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
columnsFragment.children[i % columnsCount].appendChild(items[i]);
|
||||
}
|
||||
|
||||
container.append(columnsFragment);
|
||||
};
|
||||
|
||||
const observer = new ResizeObserver(() => requestAnimationFrame(render));
|
||||
observer.observe(container);
|
||||
}
|
||||
}
|
|
@ -23,3 +23,7 @@ export function throttledDebounce(callback, maxDebounceTimes, debounceDelay) {
|
|||
export function isElementVisible(element) {
|
||||
return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
|
||||
}
|
||||
|
||||
export function clamp(value, min, max) {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
|
|
@ -440,6 +440,17 @@ kbd:active {
|
|||
box-shadow: 0 0 0 0 var(--color-widget-background-highlight);
|
||||
}
|
||||
|
||||
.masonry {
|
||||
display: flex;
|
||||
gap: var(--widget-gap);
|
||||
}
|
||||
|
||||
.masonry-column {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.popover-container, [data-popover-html] {
|
||||
display: none;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue