npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

svelte-muuri

v0.0.1

Published

A Svelte wrapper around the Muuri layout engine for creating responsive, draggable and resizable grid layouts

Readme

Svelte-Muuri

License

This project is licensed under the MIT License.

A W.I.P Svelte wrapper around the Muuri layout engine

Getting Started

Install the svelte-muuri package with your default package manager

npm i svelte-muuri

Basic Usage

<script>
  import { Grid, GridItem } from "svelte-muuri";

  const items = Array.from({ length: 10 });
</script>

<Grid class="w-[80%] h-min-[60%] border-2 border-black">
  {#each items as _, i}
    <GridItem width={100} height={100}>
      Item {i}
    </GridItem>
  {/each}
</Grid>

<Grid/>

The Grid component is what will initialize Muuri and act as the layout engine. It takes only a few props.

The Grid component accepts the following props:

  • dragEnabled (optional, boolean): When set to false, it disables the ability to drag items within the grid.
  • muuriConfig (optional, GridOptions): An object that follows the Muuri Grid Options specification, allowing you to customize the grid's behavior.
  • class (optional, string): CSS classes to apply to the grid container.
  • children (Snippet): The grid items to be rendered inside the grid.

The only default style Grid has is position: relative; which as far as I'm aware is required for Muuri to function properly.

<GridItem/>

This is the wrapper component for your grid items that allows Muuri to control their position.

  • class (optional, string): CSS Classes to apply to the GridItem
  • width & Height(optional, number, default: 100): The default width and height for your GridItem, these values are overriden when resized.
  • resizeable (optional, boolean, default: true): Toggles resizing on the grid item
  • aspectRatio (optional, number): If an aspect ratio is provided the GridItem will always enforce it when resizing. Example value: 1.7777777778 (16:9)
  • children (required, Snippet): Elements to be rendered inside the GridItem container.
  • resizeHandler (optional, function of type ResizeHandler): A custom callback function to be called when the GridItem is resized. More info below.
  • resizeHandle (optional, Snippet): A snippet that will act as the resizeHandle, this is purely visual, the resize logic is automatically attached.
  • lockedDimensions (optional, object: { width: boolean, height: boolean }, default: {width: false, height: false}): A way to prevent either width or height from being resized.

ResizeHandler()

export type ResizeHandler = ( from: Dimensions, to: Dimensions) => Dimensions;

This prop allows you to add some custom resizing logic, it takes the current dimensions of the GridItem as well as the target dimensions that the resizeHandle is requesting.

Here's an example use case. You have a GridItem component that you want to have a minimum aspect ratio of 4:3 and a maximum aspect ratio of 21:9

    resizeHandler={(from, to) => {
      // Example use case of a custom resize handler with min/max aspect ratios
      const minAspect = 4/3;
      const maxAspect = 21 / 9;
      
      const currentAspect = from.width / from.height;
      
      if (currentAspect < minAspect) {
        // Current aspect is too narrow, need to widen or shorten
        if (from.width === to.width) {
          // Width is locked, adjust height to achieve minimum aspect
          return {
            width: from.width,
            height: from.width / minAspect
          };
        } else {
          // Height is locked or neither is locked, adjust width
          return {
            width: from.height * minAspect,
            height: from.height
          };
        }
      }
      
      if (currentAspect > maxAspect) {
        // Current aspect is too wide, need to narrow or lengthen
        if (from.width === to.width) {
          // Width is locked, adjust height to achieve maximum aspect
          return {
            width: from.width,
            height: from.width / maxAspect
          };
        } else {
          // Height is locked or neither is locked, adjust width
          return {
            width: from.height * maxAspect,
            height: from.height
          };
        }
      }
      
      return from;
    }}

How it works with AspectRatio

Regardless of the output dimensions from resizeHandler, the locked dimensions and aspect ratio will always be enforced. So if you had an aspectRatio prop of 1.77 and your resizeHandler returned the object below

const from = { width: 1920, height: 1080 }; // 16:9
return { width: 1080, height: 2560 }; // 9:21

the aspect ratio enforcer would make the final dimensions result to { width: 4551, height: 2560 } (assuming no dimensions are locked)

How it Works With lockedDimensions

When a dimension is locked it simply will not change no matter what. So if resizeHandler was given {width:100, height:100} and output {width:200, height:200} if your width was locked then the final dimensions would be {width:100, height:200}.

Locking is enforced even before the target dimensions are passed to the resizeHandler, so you can detect if a dimension is locked like so

if (from.width === to.width) {
	console.log("width locked");
};
if (from.height === to.height) {
	console.log("height locked");
};

If you needed some more complex resize logic and the default locking behavior interferes with this, you must account for it in your resizeHandler like the example further up this README.