masonry-snap-grid-layout 1.0.7 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,25 @@
1
+
1
2
  # masonry-snap-grid-layout
2
3
 
3
4
  [![npm version](https://img.shields.io/npm/v/masonry-snap-grid-layout?color=brightgreen)](https://www.npmjs.com/package/masonry-snap-grid-layout)
4
5
  [![CI/CD](https://github.com/khachatryan-dev/masonry-snap-grid-layout/actions/workflows/publish.yml/badge.svg)](https://github.com/khachatryan-dev/masonry-snap-grid-layout/actions)
6
+ [![Demo Vanilla JS](https://img.shields.io/badge/demo-vanilla%20js-blue)](https://codesandbox.io/p/sandbox/l9xl7s)
7
+ [![Demo React](https://img.shields.io/badge/demo-react-blue)](https://codesandbox.io/p/sandbox/rgxsxp)
5
8
 
6
9
  A performant masonry grid layout library with smooth animations, customizable gutter, columns, and dynamic item content.
7
10
 
11
+ ![Masonry Grid Demo](https://i.imgur.com/JQZ4L7C.gif)
12
+
8
13
  ---
9
14
 
10
15
  ## 🚀 Features
11
16
 
12
- * **Dynamic Columns & Gutter**: Automatically adapts to container width.
13
- * **Smooth Animations**: Transitions when layout changes or items shuffle.
14
- * **Customizable Item Content**: Pass your own HTML or render functions.
15
- * **Lightweight & Dependency-Free**: Vanilla TypeScript for easy integration.
16
- * **Responsive & Accessible**: Works well on all screen sizes.
17
+ - **Dynamic Columns & Gutter**: Automatically adapts to container width
18
+ - **Smooth Animations**: CSS-powered transitions when layout changes
19
+ - **Customizable Items**: Render any content with gradient backgrounds and emojis
20
+ - **Lightweight**: Zero dependencies, pure TypeScript
21
+ - **React & Vanilla JS**: Works with both React and plain JavaScript
22
+ - **Responsive**: Perfect for galleries, dashboards, and card layouts
17
23
 
18
24
  ---
19
25
 
@@ -23,138 +29,168 @@ A performant masonry grid layout library with smooth animations, customizable gu
23
29
  npm install masonry-snap-grid-layout
24
30
  # or
25
31
  yarn add masonry-snap-grid-layout
26
- ````
32
+ # or
33
+ pnpm add masonry-snap-grid-layout
34
+ ```
27
35
 
28
36
  ---
29
37
 
30
- ## 💡 Usage Example (Vanilla JS)
38
+ ## 💡 Usage Examples
39
+
40
+ ### Vanilla JavaScript (Live Demo)
31
41
 
32
- ```ts
42
+ ```javascript
33
43
  import MasonrySnapGridLayout from 'masonry-snap-grid-layout';
34
- import 'masonry-snap-grid-layout/dist/index.css'; // Import the CSS!
44
+ import 'masonry-snap-grid-layout/dist/index.css';
45
+
46
+ const container = document.getElementById('masonry-container');
47
+ const items = [
48
+ { id: 1, title: "Sunset", emoji: "🌅", color: "#FF9A9E" },
49
+ { id: 2, title: "Ocean", emoji: "🌊", color: "#A1C4FD" },
50
+ // ... more items
51
+ ];
35
52
 
36
- const container = document.getElementById('masonry-container')!;
37
53
  const masonry = new MasonrySnapGridLayout(container, {
38
- gutter: 12,
54
+ gutter: 16,
39
55
  minColWidth: 200,
40
- initialItems: 20,
41
56
  animate: true,
42
- transitionDuration: 350,
43
- itemContent: (index) => {
57
+ transitionDuration: 300,
58
+ items: items,
59
+ renderItem: (item) => {
44
60
  const div = document.createElement('div');
45
- div.textContent = `Custom Item #${index + 1}`;
61
+ div.style.height = `${120 + Math.random() * 200}px`;
62
+ div.style.background = `linear-gradient(135deg, ${item.color} 0%, #FFFFFF 100%)`;
63
+ div.style.borderRadius = '12px';
64
+ div.style.padding = '16px';
65
+ div.style.color = '#333';
66
+ div.innerHTML = `
67
+ <div style="font-size: 2rem">${item.emoji}</div>
68
+ <h3 style="margin: 8px 0">${item.title}</h3>
69
+ `;
46
70
  return div;
47
- },
71
+ }
48
72
  });
49
73
  ```
50
74
 
51
- In your HTML:
52
-
53
- ```html
54
- <div id="masonry-container" style="position: relative; width: 100%;"></div>
55
- ```
75
+ [![Open Vanilla Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/l9xl7s)
56
76
 
57
77
  ---
58
78
 
59
- ## 💙 React Usage Example
60
-
61
- ```tsx
62
- 'use client';
79
+ ### React (Live Demo)
63
80
 
64
- import React from 'react';
81
+ ```jsx
65
82
  import MasonrySnapGrid from 'masonry-snap-grid-layout/react';
66
- import 'masonry-snap-grid-layout/dist/index.css'; // Import the CSS!
83
+ import 'masonry-snap-grid-layout/dist/index.css';
67
84
 
68
- export default function MasonryGrid() {
69
- const items = Array.from({ length: 25 }, (_, i) => i);
85
+ const items = Array.from({ length: 20 }, (_, i) => ({
86
+ id: i,
87
+ title: `Item ${i + 1}`,
88
+ emoji: ['🌻', '🌈', '🍕', '🎸', '🚀'][Math.floor(Math.random() * 5)],
89
+ height: 120 + Math.random() * 200
90
+ }));
70
91
 
92
+ export default function Gallery() {
71
93
  return (
72
94
  <MasonrySnapGrid
73
95
  items={items}
74
- options={{
75
- gutter: 16,
76
- minColWidth: 220,
77
- animate: true,
78
- transitionDuration: 400,
79
- }}
80
- renderItem={(item, index) => (
81
- <div>
82
- React Item #{index + 1}
96
+ gutter={16}
97
+ minColWidth={220}
98
+ animate
99
+ transitionDuration={400}
100
+ renderItem={(item) => (
101
+ <div style={{
102
+ height: `${item.height}px`,
103
+ background: `linear-gradient(135deg,
104
+ hsl(${Math.random() * 360}, 70%, 70%) 0%,
105
+ hsl(${Math.random() * 360}, 70%, 80%) 100%)`,
106
+ borderRadius: '12px',
107
+ padding: '16px',
108
+ color: 'white'
109
+ }}>
110
+ <div style={{ fontSize: '2rem' }}>{item.emoji}</div>
111
+ <h3 style={{ margin: '8px 0' }}>{item.title}</h3>
112
+ <small>Height: {Math.round(item.height)}px</small>
83
113
  </div>
84
114
  )}
85
- className="my-masonry-container"
86
- style={{ position: 'relative', width: '100%' }}
87
115
  />
88
116
  );
89
117
  }
90
118
  ```
91
119
 
92
- ---
120
+ [![Open React Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rgxsxp)
93
121
 
94
- ## ⚙️ API
122
+ ---
95
123
 
96
- ### Constructor
124
+ ## 🛠️ API Reference
97
125
 
98
- ```ts
99
- new MasonrySnapGridLayout(container: HTMLElement, options?: MasonrySnapGridLayoutOptions)
100
- ```
126
+ ### Configuration Options
101
127
 
102
- * **container** The container element where items are rendered.
103
- * **options** — Configuration options (optional).
128
+ | Option | Type | Default | Description |
129
+ |----------------------|---------------------------|---------|--------------------------------------|
130
+ | `gutter` | `number` | `16` | Spacing between items (px) |
131
+ | `minColWidth` | `number` | `250` | Minimum column width (px) |
132
+ | `animate` | `boolean` | `true` | Enable/disable animations |
133
+ | `transitionDuration` | `number` | `400` | Animation duration (ms) |
134
+ | `items` | `Array<T>` | `[]` | Your data items |
135
+ | `renderItem` | `(item: T) => HTMLElement`| - | Function to render each item |
136
+ | `classNames` | `Object` | - | Custom CSS class names |
104
137
 
105
138
  ### Methods
106
139
 
107
- * `shuffleItems(): void` Shuffle items randomly with animation.
108
- * `addItems(count: number): void` Add more items dynamically.
109
- * `destroy(): void` — Clean up and remove all items and event listeners.
140
+ - `updateItems(newItems: T[])`: Refresh with new items
141
+ - `shuffleItems()`: Randomize item positions
142
+ - `destroy()`: Clean up the instance
110
143
 
111
144
  ---
112
145
 
113
- ## 🛠️ Options
146
+ ## 🎨 Customization Tips
114
147
 
115
- | Option | Type | Default | Description |
116
- | -------------------- | ----------------------------------------------------------------------- | ------------------- | ------------------------------------------------ |
117
- | `gutter` | `number` | `16` | Spacing between items in pixels. |
118
- | `minColWidth` | `number` | `250` | Minimum column width in pixels. |
119
- | `animate` | `boolean` | `true` | Enable/disable animations. |
120
- | `transitionDuration` | `number` | `400` | Animation duration in milliseconds. |
121
- | `initialItems` | `number` | `30` | Number of items generated initially. |
122
- | `classNames` | `Partial<MasonrySnapGridLayoutClassNames>` | Default CSS classes | Override CSS class names for styling. |
123
- | `itemContent` | `string` \| `HTMLElement` \| `(index: number) => HTMLElement \| string` | `null` | Content or content generator callback for items. |
148
+ **1. Gradient Backgrounds**
149
+ Use CSS gradients for beautiful card backgrounds:
124
150
 
125
- ---
126
-
127
- ## 🎨 Styling & Animations
151
+ ```css
152
+ background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
153
+ ```
128
154
 
129
- You can customize styles by overriding the CSS classes or providing your own via the `classNames` option.
155
+ **2. Random Emojis**
156
+ Add personality with emojis:
130
157
 
131
- The layout uses smooth `transform` transitions with `cubic-bezier(0.4, 0, 0.2, 1)` easing for a polished, natural animation effect.
158
+ ```javascript
159
+ const emojis = ['🌻', '🌈', '🍕', '🎸', '🚀'];
160
+ const randomEmoji = emojis[Math.floor(Math.random() * emojis.length)];
161
+ ```
132
162
 
133
- ---
163
+ **3. Responsive Breakpoints**
164
+ Adjust columns based on screen size:
134
165
 
135
- ## 🔁 CI/CD
166
+ ```javascript
167
+ minColWidth: window.innerWidth < 768 ? 150 : 250
168
+ ```
136
169
 
137
- This package uses **GitHub Actions** to automatically publish new versions to **npm** when you push a version tag like `v1.0.0`.
170
+ ---
138
171
 
139
- To use it:
172
+ ## 📦 Package Structure
140
173
 
141
- ```bash
142
- npm version patch
143
- git push origin main --tags
144
174
  ```
145
-
146
- Make sure your `NPM_TOKEN` is saved in GitHub Secrets for automatic publishing.
175
+ dist/
176
+ ├── index.js # Vanilla JS bundle
177
+ ├── react.js # React component
178
+ ├── index.d.ts # TypeScript types
179
+ └── index.css # Base styles
180
+ ```
147
181
 
148
182
  ---
149
183
 
150
- ## 📦 npm Package
184
+ ## 🤝 Contributing
151
185
 
152
- 📌 [View on npm](https://www.npmjs.com/package/masonry-snap-grid-layout)
186
+ 1. Fork the repository
187
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
188
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
189
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
190
+ 5. Open a Pull Request
153
191
 
154
192
  ---
155
193
 
156
194
  ## 📄 License
157
195
 
158
- MIT © [Aram Khachatryan](https://github.com/khachatryan-dev)
159
-
160
- ---
196
+ MIT © [Aram Khachatryan](https://github.com/khachatryan-dev)
package/dist/esm/react.js CHANGED
@@ -2,8 +2,7 @@
2
2
  import {
3
3
  useEffect,
4
4
  useRef,
5
- forwardRef,
6
- useImperativeHandle
5
+ forwardRef
7
6
  } from "react";
8
7
  import ReactDOM from "react-dom/client";
9
8
 
@@ -86,13 +85,13 @@ var MasonrySnapGridLayout = class {
86
85
 
87
86
  // src/react.tsx
88
87
  import { jsx } from "react/jsx-runtime";
89
- function MasonrySnapGridInner({
88
+ var MasonrySnapGridInner = ({
90
89
  items,
91
90
  renderItem,
92
91
  className,
93
92
  style,
94
93
  ...options
95
- }, ref) {
94
+ }, ref) => {
96
95
  const containerRef = useRef(null);
97
96
  const masonryRef = useRef(null);
98
97
  const rootsRef = useRef(/* @__PURE__ */ new Map());
@@ -110,7 +109,10 @@ function MasonrySnapGridInner({
110
109
  }
111
110
  });
112
111
  return () => {
113
- rootsRef.current.forEach((root) => root.unmount());
112
+ rootsRef.current.forEach((root, div) => {
113
+ root.unmount();
114
+ div.remove();
115
+ });
114
116
  rootsRef.current.clear();
115
117
  masonryRef.current?.destroy();
116
118
  masonryRef.current = null;
@@ -121,9 +123,6 @@ function MasonrySnapGridInner({
121
123
  masonryRef.current.updateItems(items);
122
124
  }
123
125
  }, [items]);
124
- useImperativeHandle(ref, () => ({
125
- layout: masonryRef.current
126
- }));
127
126
  return /* @__PURE__ */ jsx(
128
127
  "div",
129
128
  {
@@ -132,9 +131,9 @@ function MasonrySnapGridInner({
132
131
  style: { position: "relative", width: "100%", ...style }
133
132
  }
134
133
  );
135
- }
134
+ };
136
135
  var MasonrySnapGrid = forwardRef(MasonrySnapGridInner);
137
- var react_default = MasonrySnapGridInner;
136
+ var react_default = MasonrySnapGrid;
138
137
  export {
139
138
  react_default as default
140
139
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react.tsx","../../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\r\n useEffect,\r\n useRef,\r\n forwardRef,\r\n useImperativeHandle,\r\n} from 'react';\r\nimport ReactDOM from 'react-dom/client';\r\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\r\nimport {\r\n MasonrySnapGridLayoutOptions,\r\n MasonrySnapGridRef,\r\n} from './types';\r\n\r\ninterface MasonrySnapGridProps<T>\r\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\r\n items: T[];\r\n renderItem: (item: T) => React.ReactNode;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nfunction MasonrySnapGridInner<T>(\r\n {\r\n items,\r\n renderItem,\r\n className,\r\n style,\r\n ...options\r\n }: MasonrySnapGridProps<T>,\r\n ref: React.Ref<MasonrySnapGridRef>\r\n) {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\r\n\r\n // React roots storage to prevent memory leaks\r\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\r\n\r\n // Initialize masonry layout\r\n useEffect(() => {\r\n if (!containerRef.current) return;\r\n\r\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\r\n ...options,\r\n items,\r\n renderItem: (item) => {\r\n const div = document.createElement('div');\r\n const root = ReactDOM.createRoot(div);\r\n root.render(renderItem(item));\r\n rootsRef.current.set(div, root);\r\n return div;\r\n },\r\n });\r\n\r\n return () => {\r\n // Unmount all React roots to avoid memory leaks\r\n rootsRef.current.forEach((root) => root.unmount());\r\n rootsRef.current.clear();\r\n\r\n masonryRef.current?.destroy();\r\n masonryRef.current = null;\r\n };\r\n }, [options, renderItem]); // include renderItem if it's not memoized\r\n\r\n // Update items on change\r\n useEffect(() => {\r\n if (masonryRef.current) {\r\n masonryRef.current.updateItems(items);\r\n }\r\n }, [items]);\r\n\r\n // Expose layout instance through ref\r\n useImperativeHandle(ref, () => ({\r\n layout: masonryRef.current!,\r\n }));\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={className}\r\n style={{ position: 'relative', width: '100%', ...style }}\r\n />\r\n );\r\n}\r\n\r\n// Apply generic type correctly to forwardRef\r\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\r\n props: MasonrySnapGridProps<T> & { ref?: React.Ref<MasonrySnapGridRef> }\r\n) => ReturnType<typeof MasonrySnapGridInner>;\r\n\r\nexport default MasonrySnapGridInner\r\n","import { MasonrySnapGridLayoutOptions } from './types';\r\n\r\nexport default class MasonrySnapGridLayout<T = any> {\r\n private readonly container: HTMLElement;\r\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\r\n private items: HTMLElement[] = [];\r\n private columnHeights: number[] = [];\r\n private resizeObserver: ResizeObserver | undefined;\r\n private rafId: number | null = null;\r\n\r\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\r\n this.container = container;\r\n this.options = {\r\n gutter: 16,\r\n minColWidth: 250,\r\n animate: true,\r\n transitionDuration: 400,\r\n classNames: {\r\n container: 'masonry-snap-grid-container',\r\n item: 'masonry-snap-grid-item',\r\n },\r\n ...options,\r\n };\r\n\r\n // Apply container class\r\n this.container.classList.add(this.options.classNames.container || \"\");\r\n\r\n // Initialize\r\n this.renderItems();\r\n this.setupResizeObserver();\r\n }\r\n\r\n private renderItems() {\r\n // Clear existing items\r\n this.items.forEach(item => item.remove());\r\n this.items = [];\r\n\r\n // Create fragment for batch DOM insertion\r\n const fragment = document.createDocumentFragment();\r\n\r\n // Create and append items\r\n this.options.items.forEach(itemData => {\r\n const itemElement = this.options.renderItem(itemData);\r\n itemElement.classList.add(this.options.classNames.item|| \"\");\r\n fragment.appendChild(itemElement);\r\n this.items.push(itemElement);\r\n });\r\n\r\n this.container.appendChild(fragment);\r\n this.updateLayout();\r\n }\r\n\r\n private setupResizeObserver() {\r\n this.resizeObserver = new ResizeObserver(() => {\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.rafId = requestAnimationFrame(() => this.updateLayout());\r\n });\r\n this.resizeObserver.observe(this.container);\r\n }\r\n\r\n private updateLayout() {\r\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\r\n const containerWidth = this.container.clientWidth;\r\n\r\n // Calculate columns\r\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\r\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\r\n\r\n // Reset column heights\r\n this.columnHeights = new Array(columns).fill(0);\r\n\r\n // Position items\r\n this.items.forEach((item) => {\r\n const height = item.offsetHeight;\r\n const minCol = this.findShortestColumn();\r\n const x = minCol * (colWidth + gutter);\r\n const y = this.columnHeights[minCol];\r\n\r\n // Apply position and size\r\n item.style.width = `${colWidth}px`;\r\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\r\n item.style.transition = animate\r\n ? `transform ${transitionDuration}ms ease`\r\n : 'none';\r\n\r\n // Update column height\r\n this.columnHeights[minCol] += height + gutter;\r\n });\r\n\r\n // Set container height\r\n const maxHeight = Math.max(...this.columnHeights);\r\n this.container.style.height = `${maxHeight}px`;\r\n }\r\n\r\n private findShortestColumn(): number {\r\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\r\n }\r\n\r\n public updateItems(newItems: T[]) {\r\n this.options.items = newItems;\r\n this.renderItems();\r\n }\r\n\r\n public destroy() {\r\n this.resizeObserver?.disconnect();\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.container.innerHTML = '';\r\n this.container.removeAttribute('style');\r\n this.container.classList.remove(this.options.classNames.container || \"\");\r\n }\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/react.tsx","../../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\r\n useEffect,\r\n useRef,\r\n forwardRef,\r\n useImperativeHandle,\r\n} from 'react';\r\nimport ReactDOM from 'react-dom/client';\r\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\r\nimport {\r\n MasonrySnapGridLayoutOptions,\r\n MasonrySnapGridRef,\r\n} from './types';\r\n\r\ninterface MasonrySnapGridProps<T>\r\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\r\n items: T[];\r\n renderItem: (item: T) => React.ReactNode;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nconst MasonrySnapGridInner = <T,>(\r\n {\r\n items,\r\n renderItem,\r\n className,\r\n style,\r\n ...options\r\n }: MasonrySnapGridProps<T>,\r\n ref: React.ForwardedRef<MasonrySnapGridRef>\r\n) => {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\r\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\r\n\r\n // Initialize masonry layout\r\n useEffect(() => {\r\n if (!containerRef.current) return;\r\n\r\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\r\n ...options,\r\n items,\r\n renderItem: (item) => {\r\n const div = document.createElement('div');\r\n const root = ReactDOM.createRoot(div);\r\n root.render(renderItem(item));\r\n rootsRef.current.set(div, root);\r\n return div;\r\n },\r\n });\r\n\r\n return () => {\r\n // Proper cleanup\r\n rootsRef.current.forEach((root, div) => {\r\n root.unmount();\r\n div.remove();\r\n });\r\n rootsRef.current.clear();\r\n masonryRef.current?.destroy();\r\n masonryRef.current = null;\r\n };\r\n }, [options, renderItem]);\r\n\r\n // Update items on change\r\n useEffect(() => {\r\n if (masonryRef.current) {\r\n masonryRef.current.updateItems(items);\r\n }\r\n }, [items]);\r\n\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={className}\r\n style={{ position: 'relative', width: '100%', ...style }}\r\n />\r\n );\r\n};\r\n\r\n// Properly typed forwardRef component\r\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\r\n props: MasonrySnapGridProps<T> & { ref?: React.ForwardedRef<MasonrySnapGridRef> }\r\n) => ReturnType<typeof MasonrySnapGridInner>;\r\n\r\nexport default MasonrySnapGrid;","import { MasonrySnapGridLayoutOptions } from './types';\r\n\r\nexport default class MasonrySnapGridLayout<T = any> {\r\n private readonly container: HTMLElement;\r\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\r\n private items: HTMLElement[] = [];\r\n private columnHeights: number[] = [];\r\n private resizeObserver: ResizeObserver | undefined;\r\n private rafId: number | null = null;\r\n\r\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\r\n this.container = container;\r\n this.options = {\r\n gutter: 16,\r\n minColWidth: 250,\r\n animate: true,\r\n transitionDuration: 400,\r\n classNames: {\r\n container: 'masonry-snap-grid-container',\r\n item: 'masonry-snap-grid-item',\r\n },\r\n ...options,\r\n };\r\n\r\n // Apply container class\r\n this.container.classList.add(this.options.classNames.container || \"\");\r\n\r\n // Initialize\r\n this.renderItems();\r\n this.setupResizeObserver();\r\n }\r\n\r\n private renderItems() {\r\n // Clear existing items\r\n this.items.forEach(item => item.remove());\r\n this.items = [];\r\n\r\n // Create fragment for batch DOM insertion\r\n const fragment = document.createDocumentFragment();\r\n\r\n // Create and append items\r\n this.options.items.forEach(itemData => {\r\n const itemElement = this.options.renderItem(itemData);\r\n itemElement.classList.add(this.options.classNames.item|| \"\");\r\n fragment.appendChild(itemElement);\r\n this.items.push(itemElement);\r\n });\r\n\r\n this.container.appendChild(fragment);\r\n this.updateLayout();\r\n }\r\n\r\n private setupResizeObserver() {\r\n this.resizeObserver = new ResizeObserver(() => {\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.rafId = requestAnimationFrame(() => this.updateLayout());\r\n });\r\n this.resizeObserver.observe(this.container);\r\n }\r\n\r\n private updateLayout() {\r\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\r\n const containerWidth = this.container.clientWidth;\r\n\r\n // Calculate columns\r\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\r\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\r\n\r\n // Reset column heights\r\n this.columnHeights = new Array(columns).fill(0);\r\n\r\n // Position items\r\n this.items.forEach((item) => {\r\n const height = item.offsetHeight;\r\n const minCol = this.findShortestColumn();\r\n const x = minCol * (colWidth + gutter);\r\n const y = this.columnHeights[minCol];\r\n\r\n // Apply position and size\r\n item.style.width = `${colWidth}px`;\r\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\r\n item.style.transition = animate\r\n ? `transform ${transitionDuration}ms ease`\r\n : 'none';\r\n\r\n // Update column height\r\n this.columnHeights[minCol] += height + gutter;\r\n });\r\n\r\n // Set container height\r\n const maxHeight = Math.max(...this.columnHeights);\r\n this.container.style.height = `${maxHeight}px`;\r\n }\r\n\r\n private findShortestColumn(): number {\r\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\r\n }\r\n\r\n public updateItems(newItems: T[]) {\r\n this.options.items = newItems;\r\n this.renderItems();\r\n }\r\n\r\n public destroy() {\r\n this.resizeObserver?.disconnect();\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.container.innerHTML = '';\r\n this.container.removeAttribute('style');\r\n this.container.classList.remove(this.options.classNames.container || \"\");\r\n }\r\n}"],"mappings":"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","names":[]}
package/dist/react.d.cts CHANGED
@@ -8,6 +8,9 @@ interface MasonrySnapGridProps<T> extends Omit<MasonrySnapGridLayoutOptions<T>,
8
8
  className?: string;
9
9
  style?: React.CSSProperties;
10
10
  }
11
- declare function MasonrySnapGridInner<T>({ items, renderItem, className, style, ...options }: MasonrySnapGridProps<T>, ref: React.Ref<MasonrySnapGridRef>): react_jsx_runtime.JSX.Element;
11
+ declare const MasonrySnapGridInner: <T>({ items, renderItem, className, style, ...options }: MasonrySnapGridProps<T>, ref: React.ForwardedRef<MasonrySnapGridRef>) => react_jsx_runtime.JSX.Element;
12
+ declare const MasonrySnapGrid: <T>(props: MasonrySnapGridProps<T> & {
13
+ ref?: React.ForwardedRef<MasonrySnapGridRef>;
14
+ }) => ReturnType<typeof MasonrySnapGridInner>;
12
15
 
13
- export { MasonrySnapGridInner as default };
16
+ export { MasonrySnapGrid as default };
package/dist/react.d.ts CHANGED
@@ -8,6 +8,9 @@ interface MasonrySnapGridProps<T> extends Omit<MasonrySnapGridLayoutOptions<T>,
8
8
  className?: string;
9
9
  style?: React.CSSProperties;
10
10
  }
11
- declare function MasonrySnapGridInner<T>({ items, renderItem, className, style, ...options }: MasonrySnapGridProps<T>, ref: React.Ref<MasonrySnapGridRef>): react_jsx_runtime.JSX.Element;
11
+ declare const MasonrySnapGridInner: <T>({ items, renderItem, className, style, ...options }: MasonrySnapGridProps<T>, ref: React.ForwardedRef<MasonrySnapGridRef>) => react_jsx_runtime.JSX.Element;
12
+ declare const MasonrySnapGrid: <T>(props: MasonrySnapGridProps<T> & {
13
+ ref?: React.ForwardedRef<MasonrySnapGridRef>;
14
+ }) => ReturnType<typeof MasonrySnapGridInner>;
12
15
 
13
- export { MasonrySnapGridInner as default };
16
+ export { MasonrySnapGrid as default };
package/dist/react.js CHANGED
@@ -115,13 +115,13 @@ var MasonrySnapGridLayout = class {
115
115
 
116
116
  // src/react.tsx
117
117
  var import_jsx_runtime = require("react/jsx-runtime");
118
- function MasonrySnapGridInner({
118
+ var MasonrySnapGridInner = ({
119
119
  items,
120
120
  renderItem,
121
121
  className,
122
122
  style,
123
123
  ...options
124
- }, ref) {
124
+ }, ref) => {
125
125
  const containerRef = (0, import_react.useRef)(null);
126
126
  const masonryRef = (0, import_react.useRef)(null);
127
127
  const rootsRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
@@ -139,7 +139,10 @@ function MasonrySnapGridInner({
139
139
  }
140
140
  });
141
141
  return () => {
142
- rootsRef.current.forEach((root) => root.unmount());
142
+ rootsRef.current.forEach((root, div) => {
143
+ root.unmount();
144
+ div.remove();
145
+ });
143
146
  rootsRef.current.clear();
144
147
  masonryRef.current?.destroy();
145
148
  masonryRef.current = null;
@@ -150,9 +153,6 @@ function MasonrySnapGridInner({
150
153
  masonryRef.current.updateItems(items);
151
154
  }
152
155
  }, [items]);
153
- (0, import_react.useImperativeHandle)(ref, () => ({
154
- layout: masonryRef.current
155
- }));
156
156
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
157
157
  "div",
158
158
  {
@@ -161,7 +161,7 @@ function MasonrySnapGridInner({
161
161
  style: { position: "relative", width: "100%", ...style }
162
162
  }
163
163
  );
164
- }
164
+ };
165
165
  var MasonrySnapGrid = (0, import_react.forwardRef)(MasonrySnapGridInner);
166
- var react_default = MasonrySnapGridInner;
166
+ var react_default = MasonrySnapGrid;
167
167
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.tsx","../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\r\n useEffect,\r\n useRef,\r\n forwardRef,\r\n useImperativeHandle,\r\n} from 'react';\r\nimport ReactDOM from 'react-dom/client';\r\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\r\nimport {\r\n MasonrySnapGridLayoutOptions,\r\n MasonrySnapGridRef,\r\n} from './types';\r\n\r\ninterface MasonrySnapGridProps<T>\r\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\r\n items: T[];\r\n renderItem: (item: T) => React.ReactNode;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nfunction MasonrySnapGridInner<T>(\r\n {\r\n items,\r\n renderItem,\r\n className,\r\n style,\r\n ...options\r\n }: MasonrySnapGridProps<T>,\r\n ref: React.Ref<MasonrySnapGridRef>\r\n) {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\r\n\r\n // React roots storage to prevent memory leaks\r\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\r\n\r\n // Initialize masonry layout\r\n useEffect(() => {\r\n if (!containerRef.current) return;\r\n\r\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\r\n ...options,\r\n items,\r\n renderItem: (item) => {\r\n const div = document.createElement('div');\r\n const root = ReactDOM.createRoot(div);\r\n root.render(renderItem(item));\r\n rootsRef.current.set(div, root);\r\n return div;\r\n },\r\n });\r\n\r\n return () => {\r\n // Unmount all React roots to avoid memory leaks\r\n rootsRef.current.forEach((root) => root.unmount());\r\n rootsRef.current.clear();\r\n\r\n masonryRef.current?.destroy();\r\n masonryRef.current = null;\r\n };\r\n }, [options, renderItem]); // include renderItem if it's not memoized\r\n\r\n // Update items on change\r\n useEffect(() => {\r\n if (masonryRef.current) {\r\n masonryRef.current.updateItems(items);\r\n }\r\n }, [items]);\r\n\r\n // Expose layout instance through ref\r\n useImperativeHandle(ref, () => ({\r\n layout: masonryRef.current!,\r\n }));\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={className}\r\n style={{ position: 'relative', width: '100%', ...style }}\r\n />\r\n );\r\n}\r\n\r\n// Apply generic type correctly to forwardRef\r\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\r\n props: MasonrySnapGridProps<T> & { ref?: React.Ref<MasonrySnapGridRef> }\r\n) => ReturnType<typeof MasonrySnapGridInner>;\r\n\r\nexport default MasonrySnapGridInner\r\n","import { MasonrySnapGridLayoutOptions } from './types';\r\n\r\nexport default class MasonrySnapGridLayout<T = any> {\r\n private readonly container: HTMLElement;\r\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\r\n private items: HTMLElement[] = [];\r\n private columnHeights: number[] = [];\r\n private resizeObserver: ResizeObserver | undefined;\r\n private rafId: number | null = null;\r\n\r\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\r\n this.container = container;\r\n this.options = {\r\n gutter: 16,\r\n minColWidth: 250,\r\n animate: true,\r\n transitionDuration: 400,\r\n classNames: {\r\n container: 'masonry-snap-grid-container',\r\n item: 'masonry-snap-grid-item',\r\n },\r\n ...options,\r\n };\r\n\r\n // Apply container class\r\n this.container.classList.add(this.options.classNames.container || \"\");\r\n\r\n // Initialize\r\n this.renderItems();\r\n this.setupResizeObserver();\r\n }\r\n\r\n private renderItems() {\r\n // Clear existing items\r\n this.items.forEach(item => item.remove());\r\n this.items = [];\r\n\r\n // Create fragment for batch DOM insertion\r\n const fragment = document.createDocumentFragment();\r\n\r\n // Create and append items\r\n this.options.items.forEach(itemData => {\r\n const itemElement = this.options.renderItem(itemData);\r\n itemElement.classList.add(this.options.classNames.item|| \"\");\r\n fragment.appendChild(itemElement);\r\n this.items.push(itemElement);\r\n });\r\n\r\n this.container.appendChild(fragment);\r\n this.updateLayout();\r\n }\r\n\r\n private setupResizeObserver() {\r\n this.resizeObserver = new ResizeObserver(() => {\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.rafId = requestAnimationFrame(() => this.updateLayout());\r\n });\r\n this.resizeObserver.observe(this.container);\r\n }\r\n\r\n private updateLayout() {\r\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\r\n const containerWidth = this.container.clientWidth;\r\n\r\n // Calculate columns\r\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\r\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\r\n\r\n // Reset column heights\r\n this.columnHeights = new Array(columns).fill(0);\r\n\r\n // Position items\r\n this.items.forEach((item) => {\r\n const height = item.offsetHeight;\r\n const minCol = this.findShortestColumn();\r\n const x = minCol * (colWidth + gutter);\r\n const y = this.columnHeights[minCol];\r\n\r\n // Apply position and size\r\n item.style.width = `${colWidth}px`;\r\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\r\n item.style.transition = animate\r\n ? `transform ${transitionDuration}ms ease`\r\n : 'none';\r\n\r\n // Update column height\r\n this.columnHeights[minCol] += height + gutter;\r\n });\r\n\r\n // Set container height\r\n const maxHeight = Math.max(...this.columnHeights);\r\n this.container.style.height = `${maxHeight}px`;\r\n }\r\n\r\n private findShortestColumn(): number {\r\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\r\n }\r\n\r\n public updateItems(newItems: T[]) {\r\n this.options.items = newItems;\r\n this.renderItems();\r\n }\r\n\r\n public destroy() {\r\n this.resizeObserver?.disconnect();\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.container.innerHTML = '';\r\n this.container.removeAttribute('style');\r\n this.container.classList.remove(this.options.classNames.container || \"\");\r\n }\r\n}"],"mappings":"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","names":["ReactDOM"]}
1
+ {"version":3,"sources":["../src/react.tsx","../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\r\n useEffect,\r\n useRef,\r\n forwardRef,\r\n useImperativeHandle,\r\n} from 'react';\r\nimport ReactDOM from 'react-dom/client';\r\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\r\nimport {\r\n MasonrySnapGridLayoutOptions,\r\n MasonrySnapGridRef,\r\n} from './types';\r\n\r\ninterface MasonrySnapGridProps<T>\r\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\r\n items: T[];\r\n renderItem: (item: T) => React.ReactNode;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n}\r\n\r\nconst MasonrySnapGridInner = <T,>(\r\n {\r\n items,\r\n renderItem,\r\n className,\r\n style,\r\n ...options\r\n }: MasonrySnapGridProps<T>,\r\n ref: React.ForwardedRef<MasonrySnapGridRef>\r\n) => {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\r\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\r\n\r\n // Initialize masonry layout\r\n useEffect(() => {\r\n if (!containerRef.current) return;\r\n\r\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\r\n ...options,\r\n items,\r\n renderItem: (item) => {\r\n const div = document.createElement('div');\r\n const root = ReactDOM.createRoot(div);\r\n root.render(renderItem(item));\r\n rootsRef.current.set(div, root);\r\n return div;\r\n },\r\n });\r\n\r\n return () => {\r\n // Proper cleanup\r\n rootsRef.current.forEach((root, div) => {\r\n root.unmount();\r\n div.remove();\r\n });\r\n rootsRef.current.clear();\r\n masonryRef.current?.destroy();\r\n masonryRef.current = null;\r\n };\r\n }, [options, renderItem]);\r\n\r\n // Update items on change\r\n useEffect(() => {\r\n if (masonryRef.current) {\r\n masonryRef.current.updateItems(items);\r\n }\r\n }, [items]);\r\n\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={className}\r\n style={{ position: 'relative', width: '100%', ...style }}\r\n />\r\n );\r\n};\r\n\r\n// Properly typed forwardRef component\r\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\r\n props: MasonrySnapGridProps<T> & { ref?: React.ForwardedRef<MasonrySnapGridRef> }\r\n) => ReturnType<typeof MasonrySnapGridInner>;\r\n\r\nexport default MasonrySnapGrid;","import { MasonrySnapGridLayoutOptions } from './types';\r\n\r\nexport default class MasonrySnapGridLayout<T = any> {\r\n private readonly container: HTMLElement;\r\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\r\n private items: HTMLElement[] = [];\r\n private columnHeights: number[] = [];\r\n private resizeObserver: ResizeObserver | undefined;\r\n private rafId: number | null = null;\r\n\r\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\r\n this.container = container;\r\n this.options = {\r\n gutter: 16,\r\n minColWidth: 250,\r\n animate: true,\r\n transitionDuration: 400,\r\n classNames: {\r\n container: 'masonry-snap-grid-container',\r\n item: 'masonry-snap-grid-item',\r\n },\r\n ...options,\r\n };\r\n\r\n // Apply container class\r\n this.container.classList.add(this.options.classNames.container || \"\");\r\n\r\n // Initialize\r\n this.renderItems();\r\n this.setupResizeObserver();\r\n }\r\n\r\n private renderItems() {\r\n // Clear existing items\r\n this.items.forEach(item => item.remove());\r\n this.items = [];\r\n\r\n // Create fragment for batch DOM insertion\r\n const fragment = document.createDocumentFragment();\r\n\r\n // Create and append items\r\n this.options.items.forEach(itemData => {\r\n const itemElement = this.options.renderItem(itemData);\r\n itemElement.classList.add(this.options.classNames.item|| \"\");\r\n fragment.appendChild(itemElement);\r\n this.items.push(itemElement);\r\n });\r\n\r\n this.container.appendChild(fragment);\r\n this.updateLayout();\r\n }\r\n\r\n private setupResizeObserver() {\r\n this.resizeObserver = new ResizeObserver(() => {\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.rafId = requestAnimationFrame(() => this.updateLayout());\r\n });\r\n this.resizeObserver.observe(this.container);\r\n }\r\n\r\n private updateLayout() {\r\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\r\n const containerWidth = this.container.clientWidth;\r\n\r\n // Calculate columns\r\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\r\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\r\n\r\n // Reset column heights\r\n this.columnHeights = new Array(columns).fill(0);\r\n\r\n // Position items\r\n this.items.forEach((item) => {\r\n const height = item.offsetHeight;\r\n const minCol = this.findShortestColumn();\r\n const x = minCol * (colWidth + gutter);\r\n const y = this.columnHeights[minCol];\r\n\r\n // Apply position and size\r\n item.style.width = `${colWidth}px`;\r\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\r\n item.style.transition = animate\r\n ? `transform ${transitionDuration}ms ease`\r\n : 'none';\r\n\r\n // Update column height\r\n this.columnHeights[minCol] += height + gutter;\r\n });\r\n\r\n // Set container height\r\n const maxHeight = Math.max(...this.columnHeights);\r\n this.container.style.height = `${maxHeight}px`;\r\n }\r\n\r\n private findShortestColumn(): number {\r\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\r\n }\r\n\r\n public updateItems(newItems: T[]) {\r\n this.options.items = newItems;\r\n this.renderItems();\r\n }\r\n\r\n public destroy() {\r\n this.resizeObserver?.disconnect();\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.container.innerHTML = '';\r\n this.container.removeAttribute('style');\r\n this.container.classList.remove(this.options.classNames.container || \"\");\r\n }\r\n}"],"mappings":"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","names":["ReactDOM"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "masonry-snap-grid-layout",
3
- "version": "1.0.7",
3
+ "version": "1.0.10",
4
4
  "description": "A performant, responsive masonry layout library with smooth animations, dynamic columns, and zero dependencies.",
5
5
  "keywords": [
6
6
  "masonry",