mirror of
https://github.com/glanceapp/glance.git
synced 2025-06-21 18:31:24 +02:00
Add masonry layout functionality
This commit is contained in:
parent
17c8071de9
commit
ab0b11cc92
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) {
|
export function isElementVisible(element) {
|
||||||
return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
|
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);
|
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] {
|
.popover-container, [data-popover-html] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user