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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@declarative-gridstack/react

v0.1.5

Published

gridstack.js as React components. Use gridstack.js in a declarative way to build complex applications with ease.

Downloads

8

Readme

@declarative-gridstack/react

gridstack.js as React components. Use gridstack.js in a declarative way to build complex applications with ease.

Note:

If you have a React application scaffolded with CRA (create-react-app), it is recommended to remove the <React.StrictMode> component from the index.js file.

<React.StrictMode>
  <App />
</React.StrictMode>

with

<App />

Core concepts

What are Gridstack containers?

Gridstack containers can hold Gridstack items. These items can be resized and repositioned either using @declarative-gridstack/react's API or manually using mouse dragging.

const [layout, setLayout] = useState([
  {
    id: "3",
    x: 1,
    y: 0,
    w: 9,
    h: 1,
    data: {
      type: "weather",
      title: "A weather widget",
      data: "Chennai, Tamil Nadu, India",
    },
  },
  {
    id: "4",
    x: 1,
    y: 1,
    w: 8,
    h: 1,
    data: {
      type: "map",
      title: "A map widget",
      data: "Chennai, Tamil Nadu, India",
    },
  },
]);

The array mentioned above is a model for a master grid that contains two Gridstack items.

What are gridstack items?

A Gridstack item is an object that must contain these properties.

  • id: A unique identifier for the item.
  • x: The x-coordinate of the item's position within the container.
  • y: The y-coordinate of the item's position within the container.
  • w: The width of the item, specified in terms of the number of grid columns it occupies.
  • h: The height of the item, specified in terms of the number of grid rows it occupies.

These properties are necessary for an item to be correctly positioned and sized within a Gridstack container.

Arbitary properties,

  • data (can be named arbitrarily and should be a valid JavaScript identifier): configuration information or other relevant details that the widget component requires in order to determine how it should look and function. This property will be passed to the widget component as props.

The master Gridstack container and the Gridstack subgrids both have the capability to hold Gridstack items.

const [widget, setWidget] = useState({
  widget: {
    id: 3,
    x: 6,
    y: 0,
    w: 6,
    h: 3,
    data: {
      title: "I am a Grid item",
      ability: "I can be moved around and resized.",
    },
  },
});

The object given above is a model for a Gridstack item.

What are Gridstack subgrids?

Each subgrid is itself a Gridstack item that has a Gridstack container within it. This container can hold other Gridstack items, allowing for more complex and nested layouts.

const [subgridLayout, setSubgridLayout] = useState([
  {
    id: 2,
    x: 3,
    y: 4,
    w: 6,
    h: 4,
    children: [
      {
        id: 3,
        x: 6,
        y: 0,
        w: 6,
        h: 3,
        data: {
          message: "My ID is 3",
        },
      },
      {
        id: 4,
        x: 0,
        y: 0,
        w: 6,
        h: 3,
        data: {
          ability: "I can be moved around!",
        },
      },
    ],
  },
]);

Based on the model provided above, the layout can be described as having a master container that includes a Gridstack item that serves as a subgrid. This subgrid, in turn, contains two additional Gridstack items.

How it works?

When an Gridstack item present in a Gridstack container is repositioned, resized or removed, etc. the model is automatically updated.

import {
  GridstackItem,
  GridstackContainer,
  GridstackSubgrid,
} from "@declarative-gridstack/react";

const Widget = (props) => {
  const { data } = props;
  return (
    <div>
      <h1>{data.title}</h1>
      <div>{data.ability}</div>
    </div>
  );
};
const Page = () => {
  const [layout, setLayout] = useState([
    {
      id: 3,
      x: 6,
      y: 0,
      w: 6,
      h: 3,
      data: {
        title: "I am a Grid item",
        ability: "I can be moved around and resized.",
      },
    },
  ]);

  const [widget] = layout ?? [];

  return (
    <GridstackContainer items={layout} setLayout={setLayout}>
      <GridstackItem
        id={widget.id}
        x={widget.x}
        y={widget.y}
        w={widget.w}
        h={widget.h}
      >
        <Widget data={widget.data}></Widget>
      </GridstackItem>
    </GridstackContainer>
  );
};

The code snippet shows a simple Gridstack container containing a single item. If the user resizes the item by dragging its resize handle, the library automatically updates the item's size information in the model.

A live example would help to clarify this concept more effectively.

The model of a specifc Gridstack layout could then be saved to an HTTP API.

const [layout, setLayout] = useState([
  {
    id: 3,
    x: 6,
    y: 0,
    w: 6,
    h: 3,
    data: {
      title: "I am a Grid item",
      ability: "I can be moved around and resized.",
    },
  },
]);

const saveLayout = () => {
  axios.post("/save-layout", layout).then(() => {});
};

The saved model could then be retrieved from an HTTP API... To construct the back layout again.

useEffect(() => {
  const [layout, setLayout] = useState([]);
  axios.get("/get-layout").then(({ data }) => {
    setLayout(data);
  });
});

Drag and drop

What are DND items?

DND (drag and drop) items are html elements (gridstack items that resides out of a gridstack grid) that could be dragged and dropped into a gridstack grid.

How are DND items different from normal html elements?

DND items are normal html elements that have the class 'grid-stack-item' in the outer tag and 'grid-stack-item-content' in the inner tag. To ensure proper identification of the items in the DOM, each outer element should also have a unique class ('gs-dnd-item' in the example below) and a 'gs-dnd-item-id' attribute with a unique value. The example below shows two unique DND items:

<div class="gs-dnd-item grid-stack-item" gs-dnd-item-id="-1">
  <div class="grid-stack-item-content" style="padding: 5px">
    I am vue gridstack DND item! With ID - 2
  </div>
</div>
<div class="gs-dnd-item grid-stack-item" gs-dnd-item-id="-2">
  <div class="grid-stack-item-content" style="padding: 5px">
    I am vue gridstack DND item! With ID - 2
  </div>
</div>

Registering DND items with the Gridstack grid

Now that we have a couple of Gridstack DND items in the DOM, we need to register them with the Gridstack grid so that they can be accepted when a user drags and drops the DND item into the grid. To do that, follow these steps:

const WidgetContainer = (props) => {
  const { children } = props;
  return (
    <div>
      <div>*** Widget Container ***</div>
      <div>{children}</div>
    </div>
  );
};

const Widget = (props) => {
  const { data } = props;
  return (
    <div>
      <h1>{data.title}</h1>
      <div>{data.ability}</div>
    </div>
  );
};

const Page = () => {
  const uid = useRef(-1);
  const uidGenerator = () => {
    return uid.current--; // Returns a unique number when called.
  };

  const [layout, setLayout] = useState([
    {
      id: 3,
      x: 6,
      y: 0,
      w: 6,
      h: 3,
      data: {
        title: "I am a Grid item",
        ability: "I can be moved around and resized.",
      },
    },
  ]);

  return (
    <GridstackContainer
      items={layout}
      setLayout={setLayout}
      // Register dnd items to the grid container.
      dnd={{
        class: "gs-dnd-item",
        dndItems: [
          { id: "-1", data: "I am vue gridstack DND item! With ID -1" },
          { id: "-2", data: "I am vue gridstack DND item! With ID -2" },
        ],
        uidGenerator: uidGenerator,
      }}
    >
      {layout.map((widget) => {
        return (
          <GridstackItem
            id={widget.id}
            x={widget.x}
            y={widget.y}
            w={widget.w}
            h={widget.h}
          >
            <WidgetContainer>
              <Widget data={widget}></Widget>
            </WidgetContainer>
          </GridstackItem>
        );
      })}
    </GridstackContainer>
  );
};
  1. Specify the class used by the DND items ('gs-dnd-item' in our case).
  2. Pass the DND items as an array.
  3. Provide a unique ID generator callback function to the grid so that when a new item is dropped into the grid from outside, the new item gets a unique ID that is unique among all the gridItems present in the master and the sub-grids.

Live example of DND items. Click here to view code.