Socket
Socket
Sign inDemoInstall

@appnest/masonry-layout

Package Overview
Dependencies
Maintainers
2
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@appnest/masonry-layout - npm Package Compare versions

Comparing version 2.0.2 to 2.0.3

3

masonry-helpers.d.ts

@@ -10,5 +10,2 @@ export declare const DEFAULT_MAX_COL_WIDTH = 400;

export declare type MasonryCols = number | "auto";
export declare type MasonryItemCachedRead = {
height: number;
};
/**

@@ -15,0 +12,0 @@ * Returns a number attribute from an element.

14

masonry-layout.d.ts

@@ -1,2 +0,1 @@

import { MasonryItemCachedRead } from "./masonry-helpers";
declare type ResizeObserverEntries = {

@@ -59,5 +58,5 @@ contentRect: {

private debounceId;
private cachedReads;
private $unsetElementsSlot;
private ro;
private currentRequestAnimationFrameCallback;
/**

@@ -95,17 +94,10 @@ * Attach the shadow DOM.

/**
* Caches a read for an element.
* @param $elem
*/
cacheRead($elem: HTMLElement): MasonryItemCachedRead;
/**
* Schedules a layout.
* @param ms
* @param invalidateCache
*/
scheduleLayout(ms?: number, invalidateCache?: boolean): void;
scheduleLayout(ms?: number): void;
/**
* Layouts the elements.
* @param invalidateCache
*/
layout(invalidateCache?: boolean): void;
layout(): void;
}

@@ -112,0 +104,0 @@ declare global {

@@ -59,6 +59,6 @@ import { COL_COUNT_CSS_VAR_NAME, debounce, DEFAULT_COLS, DEFAULT_DEBOUNCE_MS, DEFAULT_GAP_PX, DEFAULT_MAX_COL_WIDTH, ELEMENT_NODE_TYPE, findSmallestColIndex, GAP_CSS_VAR_NAME, getColCount, getNumberAttribute } from "./masonry-helpers";

this.debounceId = `layout_${Math.random()}`;
// Prepare a weakmap for the cache
this.cachedReads = new WeakMap();
// Resize observer that layouts when necessary
this.ro = undefined;
// The current request animation frame callback
this.currentRequestAnimationFrameCallback = undefined;
const shadow = this.attachShadow({ mode: "open" });

@@ -167,3 +167,4 @@ shadow.appendChild($template.content.cloneNode(true));

// Grab unset elements
const $unsetElements = this.$unsetElementsSlot.assignedNodes().filter(node => node.nodeType === ELEMENT_NODE_TYPE);
const $unsetElements = this.$unsetElementsSlot.assignedNodes()
.filter(node => node.nodeType === ELEMENT_NODE_TYPE);
// If there are more items not yet set layout straight awy to avoid the item being delayed in its render.

@@ -187,5 +188,5 @@ if ($unsetElements.length > 0) {

// Compare the amount of columns we should have to the current amount of columns.
// Schedule a layout that invalidates the cache if they are no longer the same.
// Schedule a layout if they are no longer the same.
if (colCount !== this.$columns.length) {
this.scheduleLayout(this.debounce, true);
this.scheduleLayout();
}

@@ -225,32 +226,23 @@ }

/**
* Caches a read for an element.
* @param $elem
*/
cacheRead($elem) {
// Read properties of the element
const value = {
height: $elem.getBoundingClientRect().height
};
// Cache the read of the element
this.cachedReads.set($elem, value);
return value;
}
/**
* Schedules a layout.
* @param ms
* @param invalidateCache
*/
scheduleLayout(ms = this.debounce, invalidateCache = false) {
debounce(() => this.layout(invalidateCache), ms, this.debounceId);
scheduleLayout(ms = this.debounce) {
debounce(this.layout, ms, this.debounceId);
}
/**
* Layouts the elements.
* @param invalidateCache
*/
layout(invalidateCache = false) {
requestAnimationFrame(() => {
layout() {
// Cancel the current animation frame callback
if (this.currentRequestAnimationFrameCallback != null) {
window.cancelAnimationFrame(this.currentRequestAnimationFrameCallback);
}
// Layout in the next animationframe
this.currentRequestAnimationFrameCallback = requestAnimationFrame(() => {
// console.time("layout");
// Compute relevant values we are going to use for layouting the elements.
const gap = this.gap;
const $elements = Array.from(this.children).filter(node => node.nodeType === ELEMENT_NODE_TYPE);
const $elements = Array.from(this.children)
.filter(node => node.nodeType === ELEMENT_NODE_TYPE);
const colCount = getColCount(this.offsetWidth, this.cols, this.maxColWidth);

@@ -262,7 +254,6 @@ // Have an array that keeps track of the highest col height.

// Go through all elements and figure out what column (aka slot) they should be put in.
// We only do reads in this for loop and postpone the writes
for (const $elem of $elements) {
// Get the read data of the item (either, pick the cached value or cache it while reading it).
let { height } = invalidateCache || !this.cachedReads.has($elem)
? this.cacheRead($elem)
: this.cachedReads.get($elem);
// Read the height of the element
const height = $elem.getBoundingClientRect().height;
// Find the currently smallest column

@@ -269,0 +260,0 @@ let smallestColIndex = findSmallestColIndex(colHeights);

{
"name": "@appnest/masonry-layout",
"version": "2.0.2",
"version": "2.0.3",
"license": "MIT",

@@ -5,0 +5,0 @@ "module": "index.js",

@@ -29,3 +29,3 @@ <h1 align="center">@appnest/masonry-layout</h1>

* **User friendly:** Automatically re-distribute items when the size of the grid changes or new elements are added
* **Performant:** Efficient & fast (10.000 items takes 40ms for the initial layout and 10ms for the subsequent ones)
* **Performant:** Efficient & fast - Build with performance in mind

@@ -32,0 +32,0 @@

@@ -1,4 +0,1 @@

declare type MasonryItemCachedRead = {
height: number;
};
declare type ResizeObserverEntries = {

@@ -53,5 +50,5 @@ contentRect: {

private debounceId;
private cachedReads;
private $unsetElementsSlot;
private ro;
private currentRequestAnimationFrameCallback;
/**

@@ -89,18 +86,11 @@ * Attach the shadow DOM.

/**
* Caches a read for an element.
* @param $elem
*/
cacheRead($elem: HTMLElement): MasonryItemCachedRead;
/**
* Schedules a layout.
* @param ms
* @param invalidateCache
*/
scheduleLayout(ms?: number, invalidateCache?: boolean): void;
scheduleLayout(ms?: number): void;
/**
* Layouts the elements.
* @param invalidateCache
*/
layout(invalidateCache?: boolean): void;
layout(): void;
}
export { MasonryLayout };

@@ -1,1 +0,1 @@

!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self)["masonry-layout"]={})}(this,(function(t){"use strict";const e=400,n="auto",s=300,o=24,i="--_masonry-layout-col-count",h="--_masonry-layout-gap",l=1,a=new Map;function r(t,e,n){const s=parseFloat(t.getAttribute(e)||"");return isNaN(s)?n:s}function c(t,e,n){return isNaN(e)?Math.max(1,Math.floor(t/n)):e}function d(t){let e=0,n=1/0;return t.forEach((t,s)=>{t<n&&(n=t,e=s)}),e}const u=document.createElement("template");u.innerHTML=`\n <style>\n :host {\n display: flex;\n align-items: flex-start;\n justify-content: stretch;\n }\n\n .column {\n width: calc((100% / var(${i}, 1)) - var(${h}, ${o}px));\n flex: 1;\n display: flex;\n flex-direction: column;\n }\n\n .column:not(:last-child) {\n margin-right: var(${h}, ${o}px);\n }\n\n .column ::slotted(*) {\n margin-bottom: var(${h}, ${o}px);\n box-sizing: border-box;\n }\n\n /* Hide the items that has not yet found the correct slot */\n #unset-items {\n opacity: 0;\n position: absolute;\n pointer-events: none;\n }\n </style>\n <div id="unset-items">\n <slot></slot>\n </div>\n`,window.ShadyCSS&&window.ShadyCSS.prepareTemplateStyles(u,"masonry-layout");class m extends HTMLElement{constructor(){super(),this.debounceId=`layout_${Math.random()}`,this.cachedReads=new WeakMap,this.ro=void 0,this.attachShadow({mode:"open"}).appendChild(u.content.cloneNode(!0)),this.onSlotChange=this.onSlotChange.bind(this),this.onResize=this.onResize.bind(this),this.layout=this.layout.bind(this),this.$unsetElementsSlot=this.shadowRoot.querySelector("#unset-items > slot")}static get observedAttributes(){return["maxcolwidth","gap","cols"]}set maxColWidth(t){this.setAttribute("maxcolwidth",t.toString())}get maxColWidth(){return r(this,"maxcolwidth",e)}set cols(t){this.setAttribute("cols",t.toString())}get cols(){return r(this,"cols",n)}set gap(t){this.setAttribute("gap",t.toString())}get gap(){return r(this,"gap",o)}set debounce(t){this.setAttribute("debounce",t.toString())}get debounce(){return r(this,"debounce",s)}get $columns(){return Array.from(this.shadowRoot.querySelectorAll(".column"))}connectedCallback(){this.$unsetElementsSlot.addEventListener("slotchange",this.onSlotChange),"ResizeObserver"in window?(this.ro=new ResizeObserver(this.onResize),this.ro.observe(this)):window.addEventListener("resize",this.onResize)}disconnectedCallback(){this.$unsetElementsSlot.removeEventListener("slotchange",this.onSlotChange),window.removeEventListener("resize",this.onResize),null!=this.ro&&this.ro.unobserve(this)}attributeChangedCallback(t){switch(t){case"gap":this.style.setProperty(`${h}`,`${this.gap}px`)}this.scheduleLayout()}onSlotChange(){this.$unsetElementsSlot.assignedNodes().filter(t=>t.nodeType===l).length>0&&this.layout()}onResize(t){const{width:e}=null!=t&&t.length>0?t[0].contentRect:{width:this.offsetWidth};c(e,this.cols,this.maxColWidth)!==this.$columns.length&&this.scheduleLayout(this.debounce,!0)}renderCols(t){const e=this.$columns;if(e.length!==t){for(const t of e)t.remove();for(let e=0;e<t;e++){const t=document.createElement("div");t.classList.add("column"),t.setAttribute("part",`column column-${e}`);const n=document.createElement("slot");n.setAttribute("name",e.toString()),t.appendChild(n),this.shadowRoot.appendChild(t)}this.style.setProperty(`${i}`,t.toString())}}cacheRead(t){const e={height:t.getBoundingClientRect().height};return this.cachedReads.set(t,e),e}scheduleLayout(t=this.debounce,e=!1){!function(t,e,n){const s=a.get(n);null!=s&&window.clearTimeout(s),a.set(n,window.setTimeout(t,e))}(()=>this.layout(e),t,this.debounceId)}layout(t=!1){requestAnimationFrame(()=>{const e=this.gap,n=Array.from(this.children).filter(t=>t.nodeType===l),s=c(this.offsetWidth,this.cols,this.maxColWidth),o=Array(s).fill(0),i=[];for(const s of n){let{height:n}=t||!this.cachedReads.has(s)?this.cacheRead(s):this.cachedReads.get(s),h=d(o);o[h]+=n+e;const l=h.toString();s.slot!==l&&i.push(()=>s.slot=l)}for(const t of i)t();this.renderCols(s),window.ShadyCSS&&window.ShadyCSS.styleElement(this)})}}customElements.define("masonry-layout",m),t.MasonryLayout=m,Object.defineProperty(t,"__esModule",{value:!0})}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self)["masonry-layout"]={})}(this,(function(t){"use strict";const e=400,n="auto",o=300,s=24,i="--_masonry-layout-col-count",l="--_masonry-layout-gap",r=1,a=new Map;function h(t,e,n){const o=parseFloat(t.getAttribute(e)||"");return isNaN(o)?n:o}function c(t,e,n){return isNaN(e)?Math.max(1,Math.floor(t/n)):e}function u(t){let e=0,n=1/0;return t.forEach((t,o)=>{t<n&&(n=t,e=o)}),e}const d=document.createElement("template");d.innerHTML=`\n <style>\n :host {\n display: flex;\n align-items: flex-start;\n justify-content: stretch;\n }\n\n .column {\n width: calc((100% / var(${i}, 1)) - var(${l}, ${s}px));\n flex: 1;\n display: flex;\n flex-direction: column;\n }\n\n .column:not(:last-child) {\n margin-right: var(${l}, ${s}px);\n }\n\n .column ::slotted(*) {\n margin-bottom: var(${l}, ${s}px);\n box-sizing: border-box;\n }\n\n /* Hide the items that has not yet found the correct slot */\n #unset-items {\n opacity: 0;\n position: absolute;\n pointer-events: none;\n }\n </style>\n <div id="unset-items">\n <slot></slot>\n </div>\n`,window.ShadyCSS&&window.ShadyCSS.prepareTemplateStyles(d,"masonry-layout");class m extends HTMLElement{constructor(){super(),this.debounceId=`layout_${Math.random()}`,this.ro=void 0,this.currentRequestAnimationFrameCallback=void 0,this.attachShadow({mode:"open"}).appendChild(d.content.cloneNode(!0)),this.onSlotChange=this.onSlotChange.bind(this),this.onResize=this.onResize.bind(this),this.layout=this.layout.bind(this),this.$unsetElementsSlot=this.shadowRoot.querySelector("#unset-items > slot")}static get observedAttributes(){return["maxcolwidth","gap","cols"]}set maxColWidth(t){this.setAttribute("maxcolwidth",t.toString())}get maxColWidth(){return h(this,"maxcolwidth",e)}set cols(t){this.setAttribute("cols",t.toString())}get cols(){return h(this,"cols",n)}set gap(t){this.setAttribute("gap",t.toString())}get gap(){return h(this,"gap",s)}set debounce(t){this.setAttribute("debounce",t.toString())}get debounce(){return h(this,"debounce",o)}get $columns(){return Array.from(this.shadowRoot.querySelectorAll(".column"))}connectedCallback(){this.$unsetElementsSlot.addEventListener("slotchange",this.onSlotChange),"ResizeObserver"in window?(this.ro=new ResizeObserver(this.onResize),this.ro.observe(this)):window.addEventListener("resize",this.onResize)}disconnectedCallback(){this.$unsetElementsSlot.removeEventListener("slotchange",this.onSlotChange),window.removeEventListener("resize",this.onResize),null!=this.ro&&this.ro.unobserve(this)}attributeChangedCallback(t){switch(t){case"gap":this.style.setProperty(`${l}`,`${this.gap}px`)}this.scheduleLayout()}onSlotChange(){this.$unsetElementsSlot.assignedNodes().filter(t=>t.nodeType===r).length>0&&this.layout()}onResize(t){const{width:e}=null!=t&&t.length>0?t[0].contentRect:{width:this.offsetWidth};c(e,this.cols,this.maxColWidth)!==this.$columns.length&&this.scheduleLayout()}renderCols(t){const e=this.$columns;if(e.length!==t){for(const t of e)t.remove();for(let e=0;e<t;e++){const t=document.createElement("div");t.classList.add("column"),t.setAttribute("part",`column column-${e}`);const n=document.createElement("slot");n.setAttribute("name",e.toString()),t.appendChild(n),this.shadowRoot.appendChild(t)}this.style.setProperty(`${i}`,t.toString())}}scheduleLayout(t=this.debounce){!function(t,e,n){const o=a.get(n);null!=o&&window.clearTimeout(o),a.set(n,window.setTimeout(t,e))}(this.layout,t,this.debounceId)}layout(){null!=this.currentRequestAnimationFrameCallback&&window.cancelAnimationFrame(this.currentRequestAnimationFrameCallback),this.currentRequestAnimationFrameCallback=requestAnimationFrame(()=>{const t=this.gap,e=Array.from(this.children).filter(t=>t.nodeType===r),n=c(this.offsetWidth,this.cols,this.maxColWidth),o=Array(n).fill(0),s=[];for(const n of e){const e=n.getBoundingClientRect().height;let i=u(o);o[i]+=e+t;const l=i.toString();n.slot!==l&&s.push(()=>n.slot=l)}for(const t of s)t();this.renderCols(n),window.ShadyCSS&&window.ShadyCSS.styleElement(this)})}}customElements.define("masonry-layout",m),t.MasonryLayout=m,Object.defineProperty(t,"__esModule",{value:!0})}));

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc