masonry-snap-grid-layout 1.0.19 → 1.1.2

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,223 +1,199 @@
1
-
2
- # masonry-snap-grid-layout
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)
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)
8
-
9
- A **performant, SSR-friendly** masonry grid layout library with smooth animations, customizable gutter, columns, and dynamic item content.
10
-
11
- ---
12
-
13
- ## ✨ What's New (v1.0.19)
14
- ✅ **SSR-Ready Rendering** — On the server, items are rendered as plain HTML so your grid is SEO-friendly and instantly visible.
15
- ✅ **Hydration Takeover** — On the client, the library recalculates and animates the masonry layout after hydration.
16
- **Zero Dependencies** — Written in TypeScript, works with React and Vanilla JS.
17
-
18
- ---
19
-
20
- ## 📺 Demo Video
21
-
22
- [![Watch the video](https://img.youtube.com/vi/mHK_6z9WEWs/hqdefault.jpg)](https://www.youtube.com/watch?v=mHK_6z9WEWs)
23
-
24
- ---
25
-
26
- ## 🚀 Features
27
-
28
- - **SSR Friendly (React)**: Server renders static layout client hydrates masonry positions are recalculated
29
- - **Dynamic Columns & Gutter**: Adapts automatically to container width
30
- - **Smooth Animations**: CSS-powered transitions when layout changes
31
- - **Customizable Items**: Works with any DOM or React elements
32
- - **Lightweight**: Zero dependencies
33
- - **React & Vanilla JS Support**
34
- - **Responsive**: Great for galleries, dashboards, and card layouts
35
-
36
- ---
37
-
38
- ## 🖼 How SSR Works in React Version
39
-
40
- ```
41
-
42
- ┌───────────────┐ Server Render Phase
43
- │ Static HTML │ ← React renders all items normally (SEO-friendly)
44
- └──────┬────────┘
45
-
46
-
47
- ┌───────────────┐ Client Hydration Phase
48
- Remove static │ ← JavaScript clears SSR content
49
- │ HTML items │
50
- └──────┬────────┘
51
-
52
-
53
- ┌───────────────┐ Masonry Layout Phase
54
- Masonry grid │ ← Library re-renders items and calculates positions
55
- with animation│
56
- └───────────────┘
57
-
58
- ````
59
-
60
- ---
61
-
62
- ## 🔧 Installation
63
-
64
- ```bash
65
- npm install masonry-snap-grid-layout
66
- # or
67
- yarn add masonry-snap-grid-layout
68
- # or
69
- pnpm add masonry-snap-grid-layout
70
- ````
71
-
72
- ---
73
-
74
- ## 💡 Usage Examples
75
-
76
- ### Vanilla JavaScript (Live Demo)
77
-
78
- ```javascript
79
- import MasonrySnapGridLayout from 'masonry-snap-grid-layout';
80
- import 'masonry-snap-grid-layout/dist/index.css';
81
-
82
- const container = document.getElementById('masonry-container');
83
- const items = [
84
- { id: 1, title: "Sunset", emoji: "🌅", color: "#FF9A9E" },
85
- { id: 2, title: "Ocean", emoji: "🌊", color: "#A1C4FD" },
86
- ];
87
-
88
- const masonry = new MasonrySnapGridLayout(container, {
89
- gutter: 16,
90
- minColWidth: 200,
91
- animate: true,
92
- transitionDuration: 300,
93
- items,
94
- renderItem: (item) => {
95
- const div = document.createElement('div');
96
- div.style.height = `${120 + Math.random() * 200}px`;
97
- div.style.background = `linear-gradient(135deg, ${item.color} 0%, #FFFFFF 100%)`;
98
- div.style.borderRadius = '12px';
99
- div.style.padding = '16px';
100
- div.innerHTML = `<div style="font-size: 2rem">${item.emoji}</div>
101
- <h3>${item.title}</h3>`;
102
- return div;
103
- }
104
- });
105
- ```
106
-
107
- [![Open Vanilla Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/l9xl7s)
108
-
109
- ---
110
-
111
- ### React (SSR-Friendly, Live Demo)
112
-
113
- ```jsx
114
- import MasonrySnapGrid from 'masonry-snap-grid-layout/react';
115
- import 'masonry-snap-grid-layout/dist/index.css';
116
-
117
- const items = Array.from({ length: 20 }, (_, i) => ({
118
- id: i,
119
- title: `Item ${i + 1}`,
120
- emoji: ['🌻', '🌈', '🍕', '🎸', '🚀'][Math.floor(Math.random() * 5)],
121
- height: 120 + Math.random() * 200
122
- }));
123
-
124
- export default function Gallery() {
125
- return (
126
- <MasonrySnapGrid
127
- items={items}
128
- gutter={16}
129
- minColWidth={220}
130
- animate
131
- transitionDuration={400}
132
- renderItem={(item) => (
133
- <div style={{
134
- height: `${item.height}px`,
135
- background: `linear-gradient(135deg,
136
- hsl(${Math.random() * 360}, 70%, 70%) 0%,
137
- hsl(${Math.random() * 360}, 70%, 80%) 100%)`,
138
- borderRadius: '12px',
139
- padding: '16px',
140
- color: 'white'
141
- }}>
142
- <div style={{ fontSize: '2rem' }}>{item.emoji}</div>
143
- <h3>{item.title}</h3>
144
- </div>
145
- )}
146
- />
147
- );
148
- }
149
- ```
150
-
151
- [![Open React Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rgxsxp)
152
-
153
- ---
154
-
155
- ## 🛠️ API Reference
156
-
157
- | Option | Type | Default | Description |
158
- | -------------------- | -------------------------- | ------- | ---------------------------- |
159
- | `gutter` | `number` | `16` | Spacing between items (px) |
160
- | `minColWidth` | `number` | `250` | Minimum column width (px) |
161
- | `animate` | `boolean` | `true` | Enable/disable animations |
162
- | `transitionDuration` | `number` | `400` | Animation duration (ms) |
163
- | `items` | `Array<T>` | `[]` | Your data items |
164
- | `renderItem` | `(item: T) => HTMLElement` | - | Function to render each item |
165
- | `classNames` | `Object` | - | Custom CSS class names |
166
-
167
- **Methods**
168
-
169
- * `updateItems(newItems: T[])`: Refresh with new items
170
- * `shuffleItems()`: Randomize positions
171
- * `destroy()`: Clean up the instance
172
-
173
- ---
174
-
175
- ## 🎨 Customization Tips
176
-
177
- * **Gradient Backgrounds**
178
-
179
- ```css
180
- background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
181
- ```
182
-
183
- * **Random Emojis**
184
-
185
- ```js
186
- const emojis = ['🌻', '🌈', '🍕', '🎸', '🚀'];
187
- ```
188
-
189
- * **Responsive Breakpoints**
190
-
191
- ```js
192
- minColWidth: window.innerWidth < 768 ? 150 : 250
193
- ```
194
-
195
- ---
196
-
197
- ## 📦 Package Structure
198
-
199
- ```
200
- dist/
201
- ├── index.js # Vanilla JS bundle
202
- ├── react.js # React component (SSR-friendly)
203
- ├── index.d.ts # TypeScript types
204
- └── index.css # Base styles
205
- ```
206
-
207
- ---
208
-
209
- ## 🤝 Contributing
210
-
211
- 1. Fork this repo
212
- 2. Create a feature branch (`git checkout -b feature/awesome-feature`)
213
- 3. Commit your changes
214
- 4. Push to the branch
215
- 5. Open a PR
216
-
217
- ---
218
-
219
- ## 📄 License
220
-
221
- MIT © [Aram Khachatryan](https://github.com/khachatryan-dev)
222
-
223
-
1
+ # masonry-snap-grid-layout
2
+
3
+ [![npm version](https://img.shields.io/npm/v/masonry-snap-grid-layout?color=brightgreen)](https://www.npmjs.com/package/masonry-snap-grid-layout)
4
+ [![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)
5
+ [![Demo Vanilla JS](https://img.shields.io/badge/demo-vanilla%20js-blue)](https://codesandbox.io/p/sandbox/l9xl7s)
6
+ [![Demo React](https://img.shields.io/badge/demo-react-blue)](https://codesandbox.io/p/sandbox/rgxsxp)
7
+ [![Angular Core Usage](https://img.shields.io/badge/demo-angular-red)](#angular-service-based-integration)
8
+ [![Vue 3 Wrapper](https://img.shields.io/badge/demo-vue%203-green)](#vue-3-wrapper-drop-in-component)
9
+
10
+ A **performant, SSR-friendly** masonry grid layout library with smooth animations, customizable gutter, columns, and dynamic item content.
11
+
12
+ > **Next-generation, SSR-safe Masonry layout library** for **Vanilla JS**, **React**, **Vue 3**, and **Angular**, with zero dependencies and smooth animations.
13
+
14
+ ---
15
+
16
+ # 🌟 Highlights
17
+
18
+ | Feature | Description |
19
+ | ---------------------- | --------------------------------------------------------------------- |
20
+ | CSS-First Masonry | Uses native browser CSS masonry if available for **best performance** |
21
+ | ✅ JS Fallback Engine | Battle-tested JS layout engine for unsupported browsers |
22
+ | SSR-Friendly React | Server renders static HTML, client hydrates smoothly |
23
+ | ✅ Vue 3 Drop-in | Scoped slot support for full flexibility |
24
+ | ✅ Angular Lifecycle | Works inside `ngAfterViewInit` |
25
+ | ✅ Zero Dependencies | Lightweight, fast, and modern |
26
+ | TypeScript-First | Full type safety |
27
+ | ✅ Smooth Animations | Works with dynamic content and transitions |
28
+ | Responsive & Dynamic | Automatic columns & gutter based on container width |
29
+
30
+ ---
31
+
32
+ # 🎬 Demo Video
33
+
34
+ [![Watch Demo](https://img.youtube.com/vi/mHK_6z9WEWs/hqdefault.jpg)](https://www.youtube.com/watch?v=mHK_6z9WEWs)
35
+
36
+ ---
37
+
38
+ # 🖼 Live Demos
39
+
40
+ | Vanilla JS | React | Vue 3 |
41
+ | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
42
+ | [![Vanilla Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/l9xl7s) | [![React Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/rgxsxp) | [![Vue Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/xyz123) |
43
+
44
+ ---
45
+
46
+ # 🚀 Quick Start
47
+
48
+ ### Install
49
+
50
+ ```bash
51
+ npm install masonry-snap-grid-layout
52
+ # or
53
+ yarn add masonry-snap-grid-layout
54
+ # or
55
+ pnpm add masonry-snap-grid-layout
56
+ ```
57
+
58
+ ---
59
+
60
+ ### Vanilla JS Example
61
+
62
+ ```js
63
+ import MasonrySnapGridLayout from 'masonry-snap-grid-layout';
64
+ import 'masonry-snap-grid-layout/dist/index.css';
65
+
66
+ const masonry = new MasonrySnapGridLayout(container, {
67
+ layoutMode: 'auto',
68
+ gutter: 16,
69
+ minColWidth: 240,
70
+ animate: true,
71
+ items,
72
+ renderItem: (item) => {
73
+ const el = document.createElement('div');
74
+ el.style.height = item.height + 'px';
75
+ el.style.background = `linear-gradient(135deg, ${item.color} 0%, #fff 100%)`;
76
+ el.textContent = item.title;
77
+ return el;
78
+ },
79
+ });
80
+ ```
81
+
82
+ ---
83
+
84
+ ### React (SSR-Friendly)
85
+
86
+ ```tsx
87
+ import MasonrySnapGrid from 'masonry-snap-grid-layout/react';
88
+ import 'masonry-snap-grid-layout/dist/index.css';
89
+
90
+ <MasonrySnapGrid
91
+ items={items}
92
+ layoutMode="auto"
93
+ gutter={16}
94
+ minColWidth={240}
95
+ animate
96
+ renderItem={(item) => (
97
+ <div style={{ height: item.height, borderRadius: '12px', padding: '16px' }}>
98
+ {item.title}
99
+ </div>
100
+ )}
101
+ />
102
+ ```
103
+
104
+ ---
105
+
106
+ ### Vue 3 Drop-in Component
107
+
108
+ ```vue
109
+ <template>
110
+ <MasonrySnapGrid :items="items" :gutter="16" :minColWidth="240">
111
+ <template #default="{ item }">
112
+ <div :style="{ height: item.height + 'px', borderRadius: '12px', padding: '16px' }">
113
+ {{ item.title }}
114
+ </div>
115
+ </template>
116
+ </MasonrySnapGrid>
117
+ </template>
118
+
119
+ <script setup lang="ts">
120
+ import MasonrySnapGrid from 'masonry-snap-grid-layout/vue';
121
+ </script>
122
+ ```
123
+
124
+
125
+ ---
126
+
127
+ # ⚡ Engine Comparison
128
+
129
+ | Feature | CSS Masonry | JS Masonry |
130
+ | ----------------- | ----------- | ---------- |
131
+ | Browser Native | ✅ | ❌ |
132
+ | Animation Support | Limited | ✅ Smooth |
133
+ | SSR Support | ✅ (React) | ✅ |
134
+ | Zero Dependencies | ✅ | ✅ |
135
+ | Performance | ⚡ Fast | ⚡ Fast |
136
+
137
+ ---
138
+
139
+ # 🧩 API Overview
140
+
141
+ | Option | Type | Default | Description |
142
+ | -------------------- | -------------------------- | -------- | -------------------- |
143
+ | `layoutMode` | `'auto' \| 'css' \| 'js'` | `'auto'` | Engine strategy |
144
+ | `gutter` | `number` | 16 | Space between items |
145
+ | `minColWidth` | `number` | 250 | Minimum column width |
146
+ | `animate` | `boolean` | true | Enable JS animations |
147
+ | `transitionDuration` | `number` | 400 | Duration (ms) |
148
+ | `items` | `Array<T>` | required | Data items |
149
+ | `renderItem` | `(item: T) => HTMLElement` | required | Render function |
150
+
151
+ **Methods**:
152
+
153
+ ```ts
154
+ updateItems(newItems: T[])
155
+ destroy()
156
+ ```
157
+
158
+ ---
159
+
160
+ # 🧪 Testing
161
+
162
+ Built with **Vitest**. Covers:
163
+
164
+ * Core layout engine
165
+ * React SSR hydration
166
+ * Vue 3 wrapper
167
+ * Lifecycle & Angular usage
168
+ * Zero-width container handling
169
+
170
+ ``` bash
171
+ npm test
172
+ ```
173
+
174
+ ---
175
+
176
+ # 📈 Performance & Best Practices
177
+
178
+ * Minimal DOM thrashing using `transform`
179
+ * `ResizeObserver` for responsive layout
180
+ * Optimized for dashboards, galleries, and dynamic content
181
+ * Handles zero-width containers gracefully
182
+
183
+ ---
184
+
185
+ # 🤝 Contributing
186
+
187
+ 1. Fork the repo
188
+ 2. Create a feature branch (`git checkout -b feature/awesome-feature`)
189
+ 3. Commit your changes
190
+ 4. Open a Pull Request
191
+
192
+ ---
193
+
194
+ # 📄 License
195
+
196
+ MIT © [Aram Khachatryan](https://github.com/khachatryan-dev)
197
+
198
+ ---
199
+
@@ -0,0 +1,34 @@
1
+ interface MasonrySnapGridLayoutClassNames {
2
+ container?: string;
3
+ item?: string;
4
+ }
5
+ interface MasonrySnapGridLayoutOptions<T = unknown> {
6
+ gutter?: number;
7
+ minColWidth?: number;
8
+ animate?: boolean;
9
+ transitionDuration?: number;
10
+ items: T[];
11
+ renderItem: (item: T) => HTMLElement;
12
+ classNames?: MasonrySnapGridLayoutClassNames;
13
+ }
14
+ interface MasonrySnapGridRef {
15
+ layout: MasonrySnapGridLayout | null;
16
+ }
17
+
18
+ declare class MasonrySnapGridLayout<T = any> {
19
+ private readonly container;
20
+ private readonly options;
21
+ private items;
22
+ private columnHeights;
23
+ private resizeObserver;
24
+ private rafId;
25
+ constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>);
26
+ private renderItems;
27
+ private setupResizeObserver;
28
+ private updateLayout;
29
+ private findShortestColumn;
30
+ updateItems(newItems: T[]): void;
31
+ destroy(): void;
32
+ }
33
+
34
+ export { MasonrySnapGridLayout as M, type MasonrySnapGridLayoutOptions as a, type MasonrySnapGridRef as b };
@@ -0,0 +1,34 @@
1
+ interface MasonrySnapGridLayoutClassNames {
2
+ container?: string;
3
+ item?: string;
4
+ }
5
+ interface MasonrySnapGridLayoutOptions<T = unknown> {
6
+ gutter?: number;
7
+ minColWidth?: number;
8
+ animate?: boolean;
9
+ transitionDuration?: number;
10
+ items: T[];
11
+ renderItem: (item: T) => HTMLElement;
12
+ classNames?: MasonrySnapGridLayoutClassNames;
13
+ }
14
+ interface MasonrySnapGridRef {
15
+ layout: MasonrySnapGridLayout | null;
16
+ }
17
+
18
+ declare class MasonrySnapGridLayout<T = any> {
19
+ private readonly container;
20
+ private readonly options;
21
+ private items;
22
+ private columnHeights;
23
+ private resizeObserver;
24
+ private rafId;
25
+ constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>);
26
+ private renderItems;
27
+ private setupResizeObserver;
28
+ private updateLayout;
29
+ private findShortestColumn;
30
+ updateItems(newItems: T[]): void;
31
+ destroy(): void;
32
+ }
33
+
34
+ export { MasonrySnapGridLayout as M, type MasonrySnapGridLayoutOptions as a, type MasonrySnapGridRef as b };
@@ -3,6 +3,7 @@
3
3
  position: relative;
4
4
  width: 100%;
5
5
  transition: height 0.4s ease-out;
6
+ overflow: hidden;
6
7
  }
7
8
  .masonry-snap-grid-item {
8
9
  position: absolute;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.css"],"sourcesContent":["/*\n====================================================================\nMasonrySnapGridLayout - Base Styles\n====================================================================\nThese styles define the core visual and positional behavior of the\nmasonry grid container and its items. They are minimal to allow\nflexibility for custom themes while ensuring smooth layout animations.\n====================================================================\n*/\n\n/*\nContainer styles:\n- Acts as the positioning context for masonry items (position: relative).\n- Takes full available width.\n- Smoothly animates height changes when items reflow.\n- Hides overflow to prevent content from spilling outside the layout.\n*/\n.masonry-snap-grid-container {\n position: relative;\n width: 100%;\n transition: height 0.4s ease-out;\n}\n\n/*\nItem styles:\n- Absolutely positioned within the container.\n- Animates transform changes for smooth reordering.\n- Uses GPU-accelerated transform optimizations (`will-change`, `backface-visibility`).\n- Sets `box-sizing: border-box` for consistent sizing with padding/border.\n- `transform-origin` ensures scaling/rotation pivot from the top-left corner.\n- `perspective` enables subtle 3D rendering improvements on some browsers.\n*/\n.masonry-snap-grid-item {\n position: absolute;\n transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n will-change: transform;\n box-sizing: border-box;\n transform-origin: top left;\n backface-visibility: hidden;\n perspective: 1000px;\n}\n"],"mappings":";AAiBA,CAAC;AACG,YAAU;AACV,SAAO;AACP,cAAY,OAAO,KAAK;AAC5B;AAWA,CAAC;AACG,YAAU;AACV,cAAY,UAAU,KAAK,aAAa,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE;AACrD,eAAa;AACb,cAAY;AACZ,oBAAkB,IAAI;AACtB,uBAAqB;AACrB,eAAa;AACjB;","names":[]}
1
+ {"version":3,"sources":["../../src/index.css"],"sourcesContent":[".masonry-snap-grid-container {\r\n position: relative;\r\n width: 100%;\r\n transition: height 0.4s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n.masonry-snap-grid-item {\r\n position: absolute;\r\n transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);\r\n will-change: transform;\r\n box-sizing: border-box;\r\n transform-origin: top left;\r\n backface-visibility: hidden;\r\n perspective: 1000px;\r\n}"],"mappings":";AAAA,CAAC;AACG,YAAU;AACV,SAAO;AACP,cAAY,OAAO,KAAK;AACxB,YAAU;AACd;AAEA,CAAC;AACG,YAAU;AACV,cAAY,UAAU,KAAK,aAAa,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE;AACrD,eAAa;AACb,cAAY;AACZ,oBAAkB,IAAI;AACtB,uBAAqB;AACrB,eAAa;AACjB;","names":[]}