masonry-snap-grid-layout 1.0.11 → 1.0.13
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 +4 -1
- package/dist/MasonrySnapGridLayout-CPmdhc_q.d.cts +123 -0
- package/dist/MasonrySnapGridLayout-CPmdhc_q.d.ts +123 -0
- package/dist/esm/index.css.map +1 -1
- package/dist/esm/index.js +34 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react.js +34 -0
- package/dist/esm/react.js.map +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -1
- package/dist/react.d.cts +24 -1
- package/dist/react.d.ts +24 -1
- package/dist/react.js +34 -0
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/dist/MasonrySnapGridLayout-D7ctVJaF.d.cts +0 -34
- package/dist/MasonrySnapGridLayout-D7ctVJaF.d.ts +0 -34
package/README.md
CHANGED
|
@@ -8,10 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
A performant masonry grid layout library with smooth animations, customizable gutter, columns, and dynamic item content.
|
|
10
10
|
|
|
11
|
-

|
|
12
11
|
|
|
13
12
|
---
|
|
13
|
+
## Demo Video
|
|
14
14
|
|
|
15
|
+
[](https://www.youtube.com/watch?v=mHK_6z9WEWs)
|
|
16
|
+
|
|
17
|
+
---
|
|
15
18
|
## 🚀 Features
|
|
16
19
|
|
|
17
20
|
- **Dynamic Columns & Gutter**: Automatically adapts to container width
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS class names used by MasonrySnapGridLayout for styling.
|
|
3
|
+
*/
|
|
4
|
+
interface MasonrySnapGridLayoutClassNames {
|
|
5
|
+
/** CSS class applied to the container element. */
|
|
6
|
+
container?: string;
|
|
7
|
+
/** CSS class applied to each item element. */
|
|
8
|
+
item?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Options for configuring a MasonrySnapGridLayout instance.
|
|
12
|
+
*
|
|
13
|
+
* @template T - The type of items being rendered in the masonry grid.
|
|
14
|
+
*/
|
|
15
|
+
interface MasonrySnapGridLayoutOptions<T = unknown> {
|
|
16
|
+
/**
|
|
17
|
+
* Space between grid items in pixels.
|
|
18
|
+
* @default 16
|
|
19
|
+
*/
|
|
20
|
+
gutter?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Minimum width (in pixels) of each column before layout will add another column.
|
|
23
|
+
* @default 250
|
|
24
|
+
*/
|
|
25
|
+
minColWidth?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to animate item movement when the layout changes.
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
animate?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Duration of the item movement animation (in milliseconds).
|
|
33
|
+
* Only applies if `animate` is true.
|
|
34
|
+
* @default 400
|
|
35
|
+
*/
|
|
36
|
+
transitionDuration?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Data items to be rendered in the grid.
|
|
39
|
+
*/
|
|
40
|
+
items: T[];
|
|
41
|
+
/**
|
|
42
|
+
* Function that renders a single item into a DOM element.
|
|
43
|
+
*
|
|
44
|
+
* @param item - The data item to render.
|
|
45
|
+
* @returns A DOM element representing the rendered item.
|
|
46
|
+
*/
|
|
47
|
+
renderItem: (item: T) => HTMLElement;
|
|
48
|
+
/**
|
|
49
|
+
* Optional custom class names for the container and items.
|
|
50
|
+
*/
|
|
51
|
+
classNames?: MasonrySnapGridLayoutClassNames;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Ref object shape for accessing a MasonrySnapGridLayout instance
|
|
55
|
+
* when used inside a React component.
|
|
56
|
+
*/
|
|
57
|
+
interface MasonrySnapGridRef {
|
|
58
|
+
/** Reference to the underlying MasonrySnapGridLayout instance. */
|
|
59
|
+
layout: MasonrySnapGridLayout | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* MasonrySnapGridLayout
|
|
64
|
+
*
|
|
65
|
+
* A lightweight, generic TypeScript implementation of a responsive Masonry-style grid layout
|
|
66
|
+
* with optional animations, custom rendering, and automatic re-layout on resize.
|
|
67
|
+
*
|
|
68
|
+
* @template T - The type of data items that will be rendered into grid elements.
|
|
69
|
+
*/
|
|
70
|
+
declare class MasonrySnapGridLayout<T = any> {
|
|
71
|
+
/** The container element where the Masonry grid will be rendered. */
|
|
72
|
+
private readonly container;
|
|
73
|
+
/** Fully resolved options object with defaults merged. */
|
|
74
|
+
private readonly options;
|
|
75
|
+
/** A reference to all grid item elements currently rendered. */
|
|
76
|
+
private items;
|
|
77
|
+
/** Tracks the current heights of each column to position new items. */
|
|
78
|
+
private columnHeights;
|
|
79
|
+
/** Observes container resizing to trigger re-layout. */
|
|
80
|
+
private resizeObserver;
|
|
81
|
+
/** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */
|
|
82
|
+
private rafId;
|
|
83
|
+
/**
|
|
84
|
+
* Creates a new MasonrySnapGridLayout instance.
|
|
85
|
+
*
|
|
86
|
+
* @param container - The HTML element that will act as the grid container.
|
|
87
|
+
* @param options - Partial configuration object for layout behavior and rendering.
|
|
88
|
+
*/
|
|
89
|
+
constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>);
|
|
90
|
+
/**
|
|
91
|
+
* Renders the provided items into the container.
|
|
92
|
+
* Clears previous items and re-builds DOM structure.
|
|
93
|
+
*/
|
|
94
|
+
private renderItems;
|
|
95
|
+
/**
|
|
96
|
+
* Sets up a ResizeObserver to re-calculate layout when container size changes.
|
|
97
|
+
*/
|
|
98
|
+
private setupResizeObserver;
|
|
99
|
+
/**
|
|
100
|
+
* Calculates item positions and updates their transforms.
|
|
101
|
+
* Also adjusts the container height to fit all items.
|
|
102
|
+
*/
|
|
103
|
+
private updateLayout;
|
|
104
|
+
/**
|
|
105
|
+
* Finds the index of the column with the smallest total height.
|
|
106
|
+
*
|
|
107
|
+
* @returns Index of the shortest column.
|
|
108
|
+
*/
|
|
109
|
+
private findShortestColumn;
|
|
110
|
+
/**
|
|
111
|
+
* Replaces current items with a new set and re-renders the layout.
|
|
112
|
+
*
|
|
113
|
+
* @param newItems - New set of data items to render.
|
|
114
|
+
*/
|
|
115
|
+
updateItems(newItems: T[]): void;
|
|
116
|
+
/**
|
|
117
|
+
* Cleans up event listeners, observers, and DOM modifications.
|
|
118
|
+
* This should be called before discarding the instance.
|
|
119
|
+
*/
|
|
120
|
+
destroy(): void;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export { MasonrySnapGridLayout as M, type MasonrySnapGridLayoutOptions as a, type MasonrySnapGridRef as b };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS class names used by MasonrySnapGridLayout for styling.
|
|
3
|
+
*/
|
|
4
|
+
interface MasonrySnapGridLayoutClassNames {
|
|
5
|
+
/** CSS class applied to the container element. */
|
|
6
|
+
container?: string;
|
|
7
|
+
/** CSS class applied to each item element. */
|
|
8
|
+
item?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Options for configuring a MasonrySnapGridLayout instance.
|
|
12
|
+
*
|
|
13
|
+
* @template T - The type of items being rendered in the masonry grid.
|
|
14
|
+
*/
|
|
15
|
+
interface MasonrySnapGridLayoutOptions<T = unknown> {
|
|
16
|
+
/**
|
|
17
|
+
* Space between grid items in pixels.
|
|
18
|
+
* @default 16
|
|
19
|
+
*/
|
|
20
|
+
gutter?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Minimum width (in pixels) of each column before layout will add another column.
|
|
23
|
+
* @default 250
|
|
24
|
+
*/
|
|
25
|
+
minColWidth?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to animate item movement when the layout changes.
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
animate?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Duration of the item movement animation (in milliseconds).
|
|
33
|
+
* Only applies if `animate` is true.
|
|
34
|
+
* @default 400
|
|
35
|
+
*/
|
|
36
|
+
transitionDuration?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Data items to be rendered in the grid.
|
|
39
|
+
*/
|
|
40
|
+
items: T[];
|
|
41
|
+
/**
|
|
42
|
+
* Function that renders a single item into a DOM element.
|
|
43
|
+
*
|
|
44
|
+
* @param item - The data item to render.
|
|
45
|
+
* @returns A DOM element representing the rendered item.
|
|
46
|
+
*/
|
|
47
|
+
renderItem: (item: T) => HTMLElement;
|
|
48
|
+
/**
|
|
49
|
+
* Optional custom class names for the container and items.
|
|
50
|
+
*/
|
|
51
|
+
classNames?: MasonrySnapGridLayoutClassNames;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Ref object shape for accessing a MasonrySnapGridLayout instance
|
|
55
|
+
* when used inside a React component.
|
|
56
|
+
*/
|
|
57
|
+
interface MasonrySnapGridRef {
|
|
58
|
+
/** Reference to the underlying MasonrySnapGridLayout instance. */
|
|
59
|
+
layout: MasonrySnapGridLayout | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* MasonrySnapGridLayout
|
|
64
|
+
*
|
|
65
|
+
* A lightweight, generic TypeScript implementation of a responsive Masonry-style grid layout
|
|
66
|
+
* with optional animations, custom rendering, and automatic re-layout on resize.
|
|
67
|
+
*
|
|
68
|
+
* @template T - The type of data items that will be rendered into grid elements.
|
|
69
|
+
*/
|
|
70
|
+
declare class MasonrySnapGridLayout<T = any> {
|
|
71
|
+
/** The container element where the Masonry grid will be rendered. */
|
|
72
|
+
private readonly container;
|
|
73
|
+
/** Fully resolved options object with defaults merged. */
|
|
74
|
+
private readonly options;
|
|
75
|
+
/** A reference to all grid item elements currently rendered. */
|
|
76
|
+
private items;
|
|
77
|
+
/** Tracks the current heights of each column to position new items. */
|
|
78
|
+
private columnHeights;
|
|
79
|
+
/** Observes container resizing to trigger re-layout. */
|
|
80
|
+
private resizeObserver;
|
|
81
|
+
/** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */
|
|
82
|
+
private rafId;
|
|
83
|
+
/**
|
|
84
|
+
* Creates a new MasonrySnapGridLayout instance.
|
|
85
|
+
*
|
|
86
|
+
* @param container - The HTML element that will act as the grid container.
|
|
87
|
+
* @param options - Partial configuration object for layout behavior and rendering.
|
|
88
|
+
*/
|
|
89
|
+
constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>);
|
|
90
|
+
/**
|
|
91
|
+
* Renders the provided items into the container.
|
|
92
|
+
* Clears previous items and re-builds DOM structure.
|
|
93
|
+
*/
|
|
94
|
+
private renderItems;
|
|
95
|
+
/**
|
|
96
|
+
* Sets up a ResizeObserver to re-calculate layout when container size changes.
|
|
97
|
+
*/
|
|
98
|
+
private setupResizeObserver;
|
|
99
|
+
/**
|
|
100
|
+
* Calculates item positions and updates their transforms.
|
|
101
|
+
* Also adjusts the container height to fit all items.
|
|
102
|
+
*/
|
|
103
|
+
private updateLayout;
|
|
104
|
+
/**
|
|
105
|
+
* Finds the index of the column with the smallest total height.
|
|
106
|
+
*
|
|
107
|
+
* @returns Index of the shortest column.
|
|
108
|
+
*/
|
|
109
|
+
private findShortestColumn;
|
|
110
|
+
/**
|
|
111
|
+
* Replaces current items with a new set and re-renders the layout.
|
|
112
|
+
*
|
|
113
|
+
* @param newItems - New set of data items to render.
|
|
114
|
+
*/
|
|
115
|
+
updateItems(newItems: T[]): void;
|
|
116
|
+
/**
|
|
117
|
+
* Cleans up event listeners, observers, and DOM modifications.
|
|
118
|
+
* This should be called before discarding the instance.
|
|
119
|
+
*/
|
|
120
|
+
destroy(): void;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export { MasonrySnapGridLayout as M, type MasonrySnapGridLayoutOptions as a, type MasonrySnapGridRef as b };
|
package/dist/esm/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.css"],"sourcesContent":[".masonry-snap-grid-container {\n position: relative;\n width: 100%;\n transition: height 0.4s ease-out;\n overflow: hidden;\n}\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}"],"mappings":";
|
|
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 overflow: hidden;\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;AACxB,YAAU;AACd;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":[]}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
// src/MasonrySnapGridLayout.ts
|
|
2
2
|
var MasonrySnapGridLayout = class {
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new MasonrySnapGridLayout instance.
|
|
5
|
+
*
|
|
6
|
+
* @param container - The HTML element that will act as the grid container.
|
|
7
|
+
* @param options - Partial configuration object for layout behavior and rendering.
|
|
8
|
+
*/
|
|
3
9
|
constructor(container, options) {
|
|
10
|
+
/** A reference to all grid item elements currently rendered. */
|
|
4
11
|
this.items = [];
|
|
12
|
+
/** Tracks the current heights of each column to position new items. */
|
|
5
13
|
this.columnHeights = [];
|
|
14
|
+
/** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */
|
|
6
15
|
this.rafId = null;
|
|
7
16
|
this.container = container;
|
|
8
17
|
this.options = {
|
|
@@ -20,6 +29,10 @@ var MasonrySnapGridLayout = class {
|
|
|
20
29
|
this.renderItems();
|
|
21
30
|
this.setupResizeObserver();
|
|
22
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Renders the provided items into the container.
|
|
34
|
+
* Clears previous items and re-builds DOM structure.
|
|
35
|
+
*/
|
|
23
36
|
renderItems() {
|
|
24
37
|
this.items.forEach((item) => item.remove());
|
|
25
38
|
this.items = [];
|
|
@@ -33,6 +46,9 @@ var MasonrySnapGridLayout = class {
|
|
|
33
46
|
this.container.appendChild(fragment);
|
|
34
47
|
this.updateLayout();
|
|
35
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Sets up a ResizeObserver to re-calculate layout when container size changes.
|
|
51
|
+
*/
|
|
36
52
|
setupResizeObserver() {
|
|
37
53
|
this.resizeObserver = new ResizeObserver(() => {
|
|
38
54
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
|
@@ -40,6 +56,10 @@ var MasonrySnapGridLayout = class {
|
|
|
40
56
|
});
|
|
41
57
|
this.resizeObserver.observe(this.container);
|
|
42
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Calculates item positions and updates their transforms.
|
|
61
|
+
* Also adjusts the container height to fit all items.
|
|
62
|
+
*/
|
|
43
63
|
updateLayout() {
|
|
44
64
|
const { gutter, minColWidth, animate, transitionDuration } = this.options;
|
|
45
65
|
const containerWidth = this.container.clientWidth;
|
|
@@ -59,13 +79,27 @@ var MasonrySnapGridLayout = class {
|
|
|
59
79
|
const maxHeight = Math.max(...this.columnHeights);
|
|
60
80
|
this.container.style.height = `${maxHeight}px`;
|
|
61
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Finds the index of the column with the smallest total height.
|
|
84
|
+
*
|
|
85
|
+
* @returns Index of the shortest column.
|
|
86
|
+
*/
|
|
62
87
|
findShortestColumn() {
|
|
63
88
|
return this.columnHeights.indexOf(Math.min(...this.columnHeights));
|
|
64
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Replaces current items with a new set and re-renders the layout.
|
|
92
|
+
*
|
|
93
|
+
* @param newItems - New set of data items to render.
|
|
94
|
+
*/
|
|
65
95
|
updateItems(newItems) {
|
|
66
96
|
this.options.items = newItems;
|
|
67
97
|
this.renderItems();
|
|
68
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Cleans up event listeners, observers, and DOM modifications.
|
|
101
|
+
* This should be called before discarding the instance.
|
|
102
|
+
*/
|
|
69
103
|
destroy() {
|
|
70
104
|
this.resizeObserver?.disconnect();
|
|
71
105
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/MasonrySnapGridLayout.ts","../../src/index.ts"],"sourcesContent":["import { MasonrySnapGridLayoutOptions } from './types';\n\nexport default class MasonrySnapGridLayout<T = any> {\n private readonly container: HTMLElement;\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\n private items: HTMLElement[] = [];\n private columnHeights: number[] = [];\n private resizeObserver: ResizeObserver | undefined;\n private rafId: number | null = null;\n\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\n this.container = container;\n this.options = {\n gutter: 16,\n minColWidth: 250,\n animate: true,\n transitionDuration: 400,\n classNames: {\n container: 'masonry-snap-grid-container',\n item: 'masonry-snap-grid-item',\n },\n ...options,\n };\n\n // Apply container class\n this.container.classList.add(this.options.classNames.container || \"\");\n\n //
|
|
1
|
+
{"version":3,"sources":["../../src/MasonrySnapGridLayout.ts","../../src/index.ts"],"sourcesContent":["import { MasonrySnapGridLayoutOptions } from './types';\n\n/**\n * MasonrySnapGridLayout\n *\n * A lightweight, generic TypeScript implementation of a responsive Masonry-style grid layout\n * with optional animations, custom rendering, and automatic re-layout on resize.\n *\n * @template T - The type of data items that will be rendered into grid elements.\n */\nexport default class MasonrySnapGridLayout<T = any> {\n /** The container element where the Masonry grid will be rendered. */\n private readonly container: HTMLElement;\n\n /** Fully resolved options object with defaults merged. */\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\n\n /** A reference to all grid item elements currently rendered. */\n private items: HTMLElement[] = [];\n\n /** Tracks the current heights of each column to position new items. */\n private columnHeights: number[] = [];\n\n /** Observes container resizing to trigger re-layout. */\n private resizeObserver: ResizeObserver | undefined;\n\n /** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */\n private rafId: number | null = null;\n\n /**\n * Creates a new MasonrySnapGridLayout instance.\n *\n * @param container - The HTML element that will act as the grid container.\n * @param options - Partial configuration object for layout behavior and rendering.\n */\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\n this.container = container;\n\n // Merge default settings with user-provided options\n this.options = {\n gutter: 16,\n minColWidth: 250,\n animate: true,\n transitionDuration: 400,\n classNames: {\n container: 'masonry-snap-grid-container',\n item: 'masonry-snap-grid-item',\n },\n ...options,\n };\n\n // Apply base container class for styling\n this.container.classList.add(this.options.classNames.container || \"\");\n\n // Initial rendering and layout setup\n this.renderItems();\n this.setupResizeObserver();\n }\n\n /**\n * Renders the provided items into the container.\n * Clears previous items and re-builds DOM structure.\n */\n private renderItems() {\n // Remove any previously rendered items\n this.items.forEach(item => item.remove());\n this.items = [];\n\n // Use DocumentFragment for efficient DOM updates\n const fragment = document.createDocumentFragment();\n\n // Create elements for each item and append to fragment\n this.options.items.forEach(itemData => {\n const itemElement = this.options.renderItem(itemData);\n itemElement.classList.add(this.options.classNames.item || \"\");\n fragment.appendChild(itemElement);\n this.items.push(itemElement);\n });\n\n // Append all items to container at once\n this.container.appendChild(fragment);\n\n // Trigger layout positioning\n this.updateLayout();\n }\n\n /**\n * Sets up a ResizeObserver to re-calculate layout when container size changes.\n */\n private setupResizeObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n // Throttle updates to animation frame to avoid layout thrashing\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(() => this.updateLayout());\n });\n this.resizeObserver.observe(this.container);\n }\n\n /**\n * Calculates item positions and updates their transforms.\n * Also adjusts the container height to fit all items.\n */\n private updateLayout() {\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\n const containerWidth = this.container.clientWidth;\n\n // Determine number of columns based on available width and minColWidth\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\n\n // Calculate actual column width including gutters\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\n\n // Reset heights for all columns\n this.columnHeights = new Array(columns).fill(0);\n\n // Position each item in the shortest column\n this.items.forEach((item) => {\n const height = item.offsetHeight;\n const minCol = this.findShortestColumn();\n const x = minCol * (colWidth + gutter);\n const y = this.columnHeights[minCol];\n\n // Apply positioning and animation\n item.style.width = `${colWidth}px`;\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\n item.style.transition = animate\n ? `transform ${transitionDuration}ms ease`\n : 'none';\n\n // Update column height to account for this item\n this.columnHeights[minCol] += height + gutter;\n });\n\n // Set container height to the tallest column\n const maxHeight = Math.max(...this.columnHeights);\n this.container.style.height = `${maxHeight}px`;\n }\n\n /**\n * Finds the index of the column with the smallest total height.\n *\n * @returns Index of the shortest column.\n */\n private findShortestColumn(): number {\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\n }\n\n /**\n * Replaces current items with a new set and re-renders the layout.\n *\n * @param newItems - New set of data items to render.\n */\n public updateItems(newItems: T[]) {\n this.options.items = newItems;\n this.renderItems();\n }\n\n /**\n * Cleans up event listeners, observers, and DOM modifications.\n * This should be called before discarding the instance.\n */\n public destroy() {\n this.resizeObserver?.disconnect();\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.container.innerHTML = '';\n this.container.removeAttribute('style');\n this.container.classList.remove(this.options.classNames.container || \"\");\n }\n}\n","import './index.css'; // Base CSS styles for MasonrySnapGridLayout\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\nimport { MasonrySnapGridLayoutOptions } from './types';\n\n/**\n * Entry point for the MasonrySnapGridLayout package.\n *\n * - Imports the default styles for the layout (`index.css`).\n * - Re-exports the core class and associated type definitions.\n * - This allows consumers to either:\n * - Import the default class directly.\n * - Or import named exports for more flexibility.\n */\n\nexport default MasonrySnapGridLayout;\nexport {\n MasonrySnapGridLayout,\n MasonrySnapGridLayoutOptions\n};\n"],"mappings":"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","names":[]}
|
package/dist/esm/react.js
CHANGED
|
@@ -8,9 +8,18 @@ import ReactDOM from "react-dom/client";
|
|
|
8
8
|
|
|
9
9
|
// src/MasonrySnapGridLayout.ts
|
|
10
10
|
var MasonrySnapGridLayout = class {
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new MasonrySnapGridLayout instance.
|
|
13
|
+
*
|
|
14
|
+
* @param container - The HTML element that will act as the grid container.
|
|
15
|
+
* @param options - Partial configuration object for layout behavior and rendering.
|
|
16
|
+
*/
|
|
11
17
|
constructor(container, options) {
|
|
18
|
+
/** A reference to all grid item elements currently rendered. */
|
|
12
19
|
this.items = [];
|
|
20
|
+
/** Tracks the current heights of each column to position new items. */
|
|
13
21
|
this.columnHeights = [];
|
|
22
|
+
/** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */
|
|
14
23
|
this.rafId = null;
|
|
15
24
|
this.container = container;
|
|
16
25
|
this.options = {
|
|
@@ -28,6 +37,10 @@ var MasonrySnapGridLayout = class {
|
|
|
28
37
|
this.renderItems();
|
|
29
38
|
this.setupResizeObserver();
|
|
30
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Renders the provided items into the container.
|
|
42
|
+
* Clears previous items and re-builds DOM structure.
|
|
43
|
+
*/
|
|
31
44
|
renderItems() {
|
|
32
45
|
this.items.forEach((item) => item.remove());
|
|
33
46
|
this.items = [];
|
|
@@ -41,6 +54,9 @@ var MasonrySnapGridLayout = class {
|
|
|
41
54
|
this.container.appendChild(fragment);
|
|
42
55
|
this.updateLayout();
|
|
43
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Sets up a ResizeObserver to re-calculate layout when container size changes.
|
|
59
|
+
*/
|
|
44
60
|
setupResizeObserver() {
|
|
45
61
|
this.resizeObserver = new ResizeObserver(() => {
|
|
46
62
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
|
@@ -48,6 +64,10 @@ var MasonrySnapGridLayout = class {
|
|
|
48
64
|
});
|
|
49
65
|
this.resizeObserver.observe(this.container);
|
|
50
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Calculates item positions and updates their transforms.
|
|
69
|
+
* Also adjusts the container height to fit all items.
|
|
70
|
+
*/
|
|
51
71
|
updateLayout() {
|
|
52
72
|
const { gutter, minColWidth, animate, transitionDuration } = this.options;
|
|
53
73
|
const containerWidth = this.container.clientWidth;
|
|
@@ -67,13 +87,27 @@ var MasonrySnapGridLayout = class {
|
|
|
67
87
|
const maxHeight = Math.max(...this.columnHeights);
|
|
68
88
|
this.container.style.height = `${maxHeight}px`;
|
|
69
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Finds the index of the column with the smallest total height.
|
|
92
|
+
*
|
|
93
|
+
* @returns Index of the shortest column.
|
|
94
|
+
*/
|
|
70
95
|
findShortestColumn() {
|
|
71
96
|
return this.columnHeights.indexOf(Math.min(...this.columnHeights));
|
|
72
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Replaces current items with a new set and re-renders the layout.
|
|
100
|
+
*
|
|
101
|
+
* @param newItems - New set of data items to render.
|
|
102
|
+
*/
|
|
73
103
|
updateItems(newItems) {
|
|
74
104
|
this.options.items = newItems;
|
|
75
105
|
this.renderItems();
|
|
76
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Cleans up event listeners, observers, and DOM modifications.
|
|
109
|
+
* This should be called before discarding the instance.
|
|
110
|
+
*/
|
|
77
111
|
destroy() {
|
|
78
112
|
this.resizeObserver?.disconnect();
|
|
79
113
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
package/dist/esm/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react.tsx","../../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\n useEffect,\n useRef,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport ReactDOM from 'react-dom/client';\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\nimport {\n MasonrySnapGridLayoutOptions,\n MasonrySnapGridRef,\n} from './types';\n\ninterface MasonrySnapGridProps<T>\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\n items: T[];\n renderItem: (item: T) => React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst MasonrySnapGridInner = <T,>(\n {\n items,\n renderItem,\n className,\n style,\n ...options\n }: MasonrySnapGridProps<T>,\n ref: React.ForwardedRef<MasonrySnapGridRef>\n) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\n\n // Initialize masonry layout\n useEffect(() => {\n if (!containerRef.current) return;\n\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\n ...options,\n items,\n renderItem: (item) => {\n const div = document.createElement('div');\n const root = ReactDOM.createRoot(div);\n root.render(renderItem(item));\n rootsRef.current.set(div, root);\n return div;\n },\n });\n\n return () => {\n // Proper cleanup\n rootsRef.current.forEach((root, div) => {\n root.unmount();\n div.remove();\n });\n rootsRef.current.clear();\n masonryRef.current?.destroy();\n masonryRef.current = null;\n };\n }, [options, renderItem]);\n\n // Update items on change\n useEffect(() => {\n if (masonryRef.current) {\n masonryRef.current.updateItems(items);\n }\n }, [items]);\n\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: 'relative', width: '100%', ...style }}\n />\n );\n};\n\n// Properly typed forwardRef component\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\n props: MasonrySnapGridProps<T> & { ref?: React.ForwardedRef<MasonrySnapGridRef> }\n) => ReturnType<typeof MasonrySnapGridInner>;\n\nexport default MasonrySnapGrid;","import { MasonrySnapGridLayoutOptions } from './types';\n\nexport default class MasonrySnapGridLayout<T = any> {\n private readonly container: HTMLElement;\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\n private items: HTMLElement[] = [];\n private columnHeights: number[] = [];\n private resizeObserver: ResizeObserver | undefined;\n private rafId: number | null = null;\n\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\n this.container = container;\n this.options = {\n gutter: 16,\n minColWidth: 250,\n animate: true,\n transitionDuration: 400,\n classNames: {\n container: 'masonry-snap-grid-container',\n item: 'masonry-snap-grid-item',\n },\n ...options,\n };\n\n // Apply container class\n this.container.classList.add(this.options.classNames.container || \"\");\n\n // Initialize\n this.renderItems();\n this.setupResizeObserver();\n }\n\n private renderItems() {\n // Clear existing items\n this.items.forEach(item => item.remove());\n this.items = [];\n\n // Create fragment for batch DOM insertion\n const fragment = document.createDocumentFragment();\n\n // Create and append items\n this.options.items.forEach(itemData => {\n const itemElement = this.options.renderItem(itemData);\n itemElement.classList.add(this.options.classNames.item|| \"\");\n fragment.appendChild(itemElement);\n this.items.push(itemElement);\n });\n\n this.container.appendChild(fragment);\n this.updateLayout();\n }\n\n private setupResizeObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(() => this.updateLayout());\n });\n this.resizeObserver.observe(this.container);\n }\n\n private updateLayout() {\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\n const containerWidth = this.container.clientWidth;\n\n // Calculate columns\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\n\n // Reset column heights\n this.columnHeights = new Array(columns).fill(0);\n\n // Position items\n this.items.forEach((item) => {\n const height = item.offsetHeight;\n const minCol = this.findShortestColumn();\n const x = minCol * (colWidth + gutter);\n const y = this.columnHeights[minCol];\n\n // Apply position and size\n item.style.width = `${colWidth}px`;\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\n item.style.transition = animate\n ? `transform ${transitionDuration}ms ease`\n : 'none';\n\n // Update column height\n this.columnHeights[minCol] += height + gutter;\n });\n\n // Set container height\n const maxHeight = Math.max(...this.columnHeights);\n this.container.style.height = `${maxHeight}px`;\n }\n\n private findShortestColumn(): number {\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\n }\n\n public updateItems(newItems: T[]) {\n this.options.items = newItems;\n this.renderItems();\n }\n\n public destroy() {\n this.resizeObserver?.disconnect();\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.container.innerHTML = '';\n this.container.removeAttribute('style');\n this.container.classList.remove(this.options.classNames.container || \"\");\n }\n}"],"mappings":";AAAA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OAEG;AACP,OAAO,cAAc;;;ACJrB,IAAqB,wBAArB,MAAoD;AAAA,EAQhD,YAAY,WAAwB,SAA0C;AAL9E,SAAQ,QAAuB,CAAC;AAChC,SAAQ,gBAA0B,CAAC;AAEnC,SAAQ,QAAuB;AAG3B,SAAK,YAAY;AACjB,SAAK,UAAU;AAAA,MACX,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,SAAS;AAAA,MACT,oBAAoB;AAAA,MACpB,YAAY;AAAA,QACR,WAAW;AAAA,QACX,MAAM;AAAA,MACV;AAAA,MACA,GAAG;AAAA,IACP;AAGA,SAAK,UAAU,UAAU,IAAI,KAAK,QAAQ,WAAW,aAAa,EAAE;AAGpE,SAAK,YAAY;AACjB,SAAK,oBAAoB;AAAA,EAC7B;AAAA,EAEQ,cAAc;AAElB,SAAK,MAAM,QAAQ,UAAQ,KAAK,OAAO,CAAC;AACxC,SAAK,QAAQ,CAAC;AAGd,UAAM,WAAW,SAAS,uBAAuB;AAGjD,SAAK,QAAQ,MAAM,QAAQ,cAAY;AACnC,YAAM,cAAc,KAAK,QAAQ,WAAW,QAAQ;AACpD,kBAAY,UAAU,IAAI,KAAK,QAAQ,WAAW,QAAO,EAAE;AAC3D,eAAS,YAAY,WAAW;AAChC,WAAK,MAAM,KAAK,WAAW;AAAA,IAC/B,CAAC;AAED,SAAK,UAAU,YAAY,QAAQ;AACnC,SAAK,aAAa;AAAA,EACtB;AAAA,EAEQ,sBAAsB;AAC1B,SAAK,iBAAiB,IAAI,eAAe,MAAM;AAC3C,UAAI,KAAK,MAAO,sBAAqB,KAAK,KAAK;AAC/C,WAAK,QAAQ,sBAAsB,MAAM,KAAK,aAAa,CAAC;AAAA,IAChE,CAAC;AACD,SAAK,eAAe,QAAQ,KAAK,SAAS;AAAA,EAC9C;AAAA,EAEQ,eAAe;AACnB,UAAM,EAAE,QAAQ,aAAa,SAAS,mBAAmB,IAAI,KAAK;AAClE,UAAM,iBAAiB,KAAK,UAAU;AAGtC,UAAM,UAAU,KAAK,IAAI,GAAG,KAAK,OAAO,iBAAiB,WAAW,cAAc,OAAO,CAAC;AAC1F,UAAM,YAAY,kBAAkB,UAAU,KAAK,UAAU;AAG7D,SAAK,gBAAgB,IAAI,MAAM,OAAO,EAAE,KAAK,CAAC;AAG9C,SAAK,MAAM,QAAQ,CAAC,SAAS;AACzB,YAAM,SAAS,KAAK;AACpB,YAAM,SAAS,KAAK,mBAAmB;AACvC,YAAM,IAAI,UAAU,WAAW;AAC/B,YAAM,IAAI,KAAK,cAAc,MAAM;AAGnC,WAAK,MAAM,QAAQ,GAAG,QAAQ;AAC9B,WAAK,MAAM,YAAY,eAAe,CAAC,OAAO,CAAC;AAC/C,WAAK,MAAM,aAAa,UAClB,aAAa,kBAAkB,YAC/B;AAGN,WAAK,cAAc,MAAM,KAAK,SAAS;AAAA,IAC3C,CAAC;AAGD,UAAM,YAAY,KAAK,IAAI,GAAG,KAAK,aAAa;AAChD,SAAK,UAAU,MAAM,SAAS,GAAG,SAAS;AAAA,EAC9C;AAAA,EAEQ,qBAA6B;AACjC,WAAO,KAAK,cAAc,QAAQ,KAAK,IAAI,GAAG,KAAK,aAAa,CAAC;AAAA,EACrE;AAAA,EAEO,YAAY,UAAe;AAC9B,SAAK,QAAQ,QAAQ;AACrB,SAAK,YAAY;AAAA,EACrB;AAAA,EAEO,UAAU;AACb,SAAK,gBAAgB,WAAW;AAChC,QAAI,KAAK,MAAO,sBAAqB,KAAK,KAAK;AAC/C,SAAK,UAAU,YAAY;AAC3B,SAAK,UAAU,gBAAgB,OAAO;AACtC,SAAK,UAAU,UAAU,OAAO,KAAK,QAAQ,WAAW,aAAa,EAAE;AAAA,EAC3E;AACJ;;;ADtCQ;AAnDR,IAAM,uBAAuB,CACzB;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACP,GACA,QACC;AACD,QAAM,eAAe,OAAuB,IAAI;AAChD,QAAM,aAAa,OAAwC,IAAI;AAC/D,QAAM,WAAW,OAAwC,oBAAI,IAAI,CAAC;AAGlE,YAAU,MAAM;AACZ,QAAI,CAAC,aAAa,QAAS;AAE3B,eAAW,UAAU,IAAI,sBAAsB,aAAa,SAAS;AAAA,MACjE,GAAG;AAAA,MACH;AAAA,MACA,YAAY,CAAC,SAAS;AAClB,cAAM,MAAM,SAAS,cAAc,KAAK;AACxC,cAAM,OAAO,SAAS,WAAW,GAAG;AACpC,aAAK,OAAO,WAAW,IAAI,CAAC;AAC5B,iBAAS,QAAQ,IAAI,KAAK,IAAI;AAC9B,eAAO;AAAA,MACX;AAAA,IACJ,CAAC;AAED,WAAO,MAAM;AAET,eAAS,QAAQ,QAAQ,CAAC,MAAM,QAAQ;AACpC,aAAK,QAAQ;AACb,YAAI,OAAO;AAAA,MACf,CAAC;AACD,eAAS,QAAQ,MAAM;AACvB,iBAAW,SAAS,QAAQ;AAC5B,iBAAW,UAAU;AAAA,IACzB;AAAA,EACJ,GAAG,CAAC,SAAS,UAAU,CAAC;AAGxB,YAAU,MAAM;AACZ,QAAI,WAAW,SAAS;AACpB,iBAAW,QAAQ,YAAY,KAAK;AAAA,IACxC;AAAA,EACJ,GAAG,CAAC,KAAK,CAAC;AAGV,SACI;AAAA,IAAC;AAAA;AAAA,MACG,KAAK;AAAA,MACL;AAAA,MACA,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,GAAG,MAAM;AAAA;AAAA,EAC3D;AAER;AAGA,IAAM,kBAAkB,WAAW,oBAAoB;AAIvD,IAAO,gBAAQ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/react.tsx","../../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\n useEffect,\n useRef,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport ReactDOM from 'react-dom/client';\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\nimport {\n MasonrySnapGridLayoutOptions,\n MasonrySnapGridRef,\n} from './types';\n\n/**\n * Props for the MasonrySnapGrid React component.\n *\n * @template T - The type of items in the masonry layout.\n */\ninterface MasonrySnapGridProps<T>\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\n /** Array of data items to be rendered into the masonry grid. */\n items: T[];\n\n /** Function that renders a single data item as a React node. */\n renderItem: (item: T) => React.ReactNode;\n\n /** Optional class name for the container. */\n className?: string;\n\n /** Optional inline styles for the container. */\n style?: React.CSSProperties;\n}\n\n/**\n * Internal component that bridges MasonrySnapGridLayout with React.\n *\n * - Manages lifecycle of the underlying MasonrySnapGridLayout instance.\n * - Uses ReactDOM.createRoot to render React nodes into non-React DOM elements.\n * - Handles cleanup to avoid memory leaks.\n */\nconst MasonrySnapGridInner = <T,>(\n {\n items,\n renderItem,\n className,\n style,\n ...options\n }: MasonrySnapGridProps<T>,\n ref: React.ForwardedRef<MasonrySnapGridRef>\n) => {\n /** Ref to the container DOM element where MasonrySnapGridLayout will operate. */\n const containerRef = useRef<HTMLDivElement>(null);\n\n /** Ref to the MasonrySnapGridLayout instance (non-React logic). */\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\n\n /** Tracks all mounted React roots for cleanup. */\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\n\n // Initialize masonry layout when container mounts\n useEffect(() => {\n if (!containerRef.current) return;\n\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\n ...options,\n items,\n renderItem: (item) => {\n // Create a standalone DOM element for each item\n const div = document.createElement('div');\n\n // Render React content into this element\n const root = ReactDOM.createRoot(div);\n root.render(renderItem(item));\n\n // Keep track of the React root for later cleanup\n rootsRef.current.set(div, root);\n\n return div;\n },\n });\n\n return () => {\n // Clean up all React roots and remove their DOM nodes\n rootsRef.current.forEach((root, div) => {\n root.unmount();\n div.remove();\n });\n rootsRef.current.clear();\n\n // Destroy the Masonry instance\n masonryRef.current?.destroy();\n masonryRef.current = null;\n };\n }, [options, renderItem]);\n\n // Update only the items when the data changes (avoid full re-initialization)\n useEffect(() => {\n if (masonryRef.current) {\n masonryRef.current.updateItems(items);\n }\n }, [items]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: 'relative', width: '100%', ...style }}\n />\n );\n};\n\n/**\n * MasonrySnapGrid\n *\n * React wrapper component for MasonrySnapGridLayout.\n *\n * @template T - The type of items in the masonry layout.\n */\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\n props: MasonrySnapGridProps<T> & { ref?: React.ForwardedRef<MasonrySnapGridRef> }\n) => ReturnType<typeof MasonrySnapGridInner>;\n\nexport default MasonrySnapGrid;\n","import { MasonrySnapGridLayoutOptions } from './types';\n\n/**\n * MasonrySnapGridLayout\n *\n * A lightweight, generic TypeScript implementation of a responsive Masonry-style grid layout\n * with optional animations, custom rendering, and automatic re-layout on resize.\n *\n * @template T - The type of data items that will be rendered into grid elements.\n */\nexport default class MasonrySnapGridLayout<T = any> {\n /** The container element where the Masonry grid will be rendered. */\n private readonly container: HTMLElement;\n\n /** Fully resolved options object with defaults merged. */\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\n\n /** A reference to all grid item elements currently rendered. */\n private items: HTMLElement[] = [];\n\n /** Tracks the current heights of each column to position new items. */\n private columnHeights: number[] = [];\n\n /** Observes container resizing to trigger re-layout. */\n private resizeObserver: ResizeObserver | undefined;\n\n /** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */\n private rafId: number | null = null;\n\n /**\n * Creates a new MasonrySnapGridLayout instance.\n *\n * @param container - The HTML element that will act as the grid container.\n * @param options - Partial configuration object for layout behavior and rendering.\n */\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\n this.container = container;\n\n // Merge default settings with user-provided options\n this.options = {\n gutter: 16,\n minColWidth: 250,\n animate: true,\n transitionDuration: 400,\n classNames: {\n container: 'masonry-snap-grid-container',\n item: 'masonry-snap-grid-item',\n },\n ...options,\n };\n\n // Apply base container class for styling\n this.container.classList.add(this.options.classNames.container || \"\");\n\n // Initial rendering and layout setup\n this.renderItems();\n this.setupResizeObserver();\n }\n\n /**\n * Renders the provided items into the container.\n * Clears previous items and re-builds DOM structure.\n */\n private renderItems() {\n // Remove any previously rendered items\n this.items.forEach(item => item.remove());\n this.items = [];\n\n // Use DocumentFragment for efficient DOM updates\n const fragment = document.createDocumentFragment();\n\n // Create elements for each item and append to fragment\n this.options.items.forEach(itemData => {\n const itemElement = this.options.renderItem(itemData);\n itemElement.classList.add(this.options.classNames.item || \"\");\n fragment.appendChild(itemElement);\n this.items.push(itemElement);\n });\n\n // Append all items to container at once\n this.container.appendChild(fragment);\n\n // Trigger layout positioning\n this.updateLayout();\n }\n\n /**\n * Sets up a ResizeObserver to re-calculate layout when container size changes.\n */\n private setupResizeObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n // Throttle updates to animation frame to avoid layout thrashing\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(() => this.updateLayout());\n });\n this.resizeObserver.observe(this.container);\n }\n\n /**\n * Calculates item positions and updates their transforms.\n * Also adjusts the container height to fit all items.\n */\n private updateLayout() {\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\n const containerWidth = this.container.clientWidth;\n\n // Determine number of columns based on available width and minColWidth\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\n\n // Calculate actual column width including gutters\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\n\n // Reset heights for all columns\n this.columnHeights = new Array(columns).fill(0);\n\n // Position each item in the shortest column\n this.items.forEach((item) => {\n const height = item.offsetHeight;\n const minCol = this.findShortestColumn();\n const x = minCol * (colWidth + gutter);\n const y = this.columnHeights[minCol];\n\n // Apply positioning and animation\n item.style.width = `${colWidth}px`;\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\n item.style.transition = animate\n ? `transform ${transitionDuration}ms ease`\n : 'none';\n\n // Update column height to account for this item\n this.columnHeights[minCol] += height + gutter;\n });\n\n // Set container height to the tallest column\n const maxHeight = Math.max(...this.columnHeights);\n this.container.style.height = `${maxHeight}px`;\n }\n\n /**\n * Finds the index of the column with the smallest total height.\n *\n * @returns Index of the shortest column.\n */\n private findShortestColumn(): number {\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\n }\n\n /**\n * Replaces current items with a new set and re-renders the layout.\n *\n * @param newItems - New set of data items to render.\n */\n public updateItems(newItems: T[]) {\n this.options.items = newItems;\n this.renderItems();\n }\n\n /**\n * Cleans up event listeners, observers, and DOM modifications.\n * This should be called before discarding the instance.\n */\n public destroy() {\n this.resizeObserver?.disconnect();\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.container.innerHTML = '';\n this.container.removeAttribute('style');\n this.container.classList.remove(this.options.classNames.container || \"\");\n }\n}\n"],"mappings":";AAAA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OAEG;AACP,OAAO,cAAc;;;ACIrB,IAAqB,wBAArB,MAAoD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBhD,YAAY,WAAwB,SAA0C;AAjB9E;AAAA,SAAQ,QAAuB,CAAC;AAGhC;AAAA,SAAQ,gBAA0B,CAAC;AAMnC;AAAA,SAAQ,QAAuB;AAS3B,SAAK,YAAY;AAGjB,SAAK,UAAU;AAAA,MACX,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,SAAS;AAAA,MACT,oBAAoB;AAAA,MACpB,YAAY;AAAA,QACR,WAAW;AAAA,QACX,MAAM;AAAA,MACV;AAAA,MACA,GAAG;AAAA,IACP;AAGA,SAAK,UAAU,UAAU,IAAI,KAAK,QAAQ,WAAW,aAAa,EAAE;AAGpE,SAAK,YAAY;AACjB,SAAK,oBAAoB;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAc;AAElB,SAAK,MAAM,QAAQ,UAAQ,KAAK,OAAO,CAAC;AACxC,SAAK,QAAQ,CAAC;AAGd,UAAM,WAAW,SAAS,uBAAuB;AAGjD,SAAK,QAAQ,MAAM,QAAQ,cAAY;AACnC,YAAM,cAAc,KAAK,QAAQ,WAAW,QAAQ;AACpD,kBAAY,UAAU,IAAI,KAAK,QAAQ,WAAW,QAAQ,EAAE;AAC5D,eAAS,YAAY,WAAW;AAChC,WAAK,MAAM,KAAK,WAAW;AAAA,IAC/B,CAAC;AAGD,SAAK,UAAU,YAAY,QAAQ;AAGnC,SAAK,aAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB;AAC1B,SAAK,iBAAiB,IAAI,eAAe,MAAM;AAE3C,UAAI,KAAK,MAAO,sBAAqB,KAAK,KAAK;AAC/C,WAAK,QAAQ,sBAAsB,MAAM,KAAK,aAAa,CAAC;AAAA,IAChE,CAAC;AACD,SAAK,eAAe,QAAQ,KAAK,SAAS;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe;AACnB,UAAM,EAAE,QAAQ,aAAa,SAAS,mBAAmB,IAAI,KAAK;AAClE,UAAM,iBAAiB,KAAK,UAAU;AAGtC,UAAM,UAAU,KAAK,IAAI,GAAG,KAAK,OAAO,iBAAiB,WAAW,cAAc,OAAO,CAAC;AAG1F,UAAM,YAAY,kBAAkB,UAAU,KAAK,UAAU;AAG7D,SAAK,gBAAgB,IAAI,MAAM,OAAO,EAAE,KAAK,CAAC;AAG9C,SAAK,MAAM,QAAQ,CAAC,SAAS;AACzB,YAAM,SAAS,KAAK;AACpB,YAAM,SAAS,KAAK,mBAAmB;AACvC,YAAM,IAAI,UAAU,WAAW;AAC/B,YAAM,IAAI,KAAK,cAAc,MAAM;AAGnC,WAAK,MAAM,QAAQ,GAAG,QAAQ;AAC9B,WAAK,MAAM,YAAY,eAAe,CAAC,OAAO,CAAC;AAC/C,WAAK,MAAM,aAAa,UAClB,aAAa,kBAAkB,YAC/B;AAGN,WAAK,cAAc,MAAM,KAAK,SAAS;AAAA,IAC3C,CAAC;AAGD,UAAM,YAAY,KAAK,IAAI,GAAG,KAAK,aAAa;AAChD,SAAK,UAAU,MAAM,SAAS,GAAG,SAAS;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAA6B;AACjC,WAAO,KAAK,cAAc,QAAQ,KAAK,IAAI,GAAG,KAAK,aAAa,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,YAAY,UAAe;AAC9B,SAAK,QAAQ,QAAQ;AACrB,SAAK,YAAY;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,UAAU;AACb,SAAK,gBAAgB,WAAW;AAChC,QAAI,KAAK,MAAO,sBAAqB,KAAK,KAAK;AAC/C,SAAK,UAAU,YAAY;AAC3B,SAAK,UAAU,gBAAgB,OAAO;AACtC,SAAK,UAAU,UAAU,OAAO,KAAK,QAAQ,WAAW,aAAa,EAAE;AAAA,EAC3E;AACJ;;;ADjEQ;AA/DR,IAAM,uBAAuB,CACzB;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACP,GACA,QACC;AAED,QAAM,eAAe,OAAuB,IAAI;AAGhD,QAAM,aAAa,OAAwC,IAAI;AAG/D,QAAM,WAAW,OAAwC,oBAAI,IAAI,CAAC;AAGlE,YAAU,MAAM;AACZ,QAAI,CAAC,aAAa,QAAS;AAE3B,eAAW,UAAU,IAAI,sBAAsB,aAAa,SAAS;AAAA,MACjE,GAAG;AAAA,MACH;AAAA,MACA,YAAY,CAAC,SAAS;AAElB,cAAM,MAAM,SAAS,cAAc,KAAK;AAGxC,cAAM,OAAO,SAAS,WAAW,GAAG;AACpC,aAAK,OAAO,WAAW,IAAI,CAAC;AAG5B,iBAAS,QAAQ,IAAI,KAAK,IAAI;AAE9B,eAAO;AAAA,MACX;AAAA,IACJ,CAAC;AAED,WAAO,MAAM;AAET,eAAS,QAAQ,QAAQ,CAAC,MAAM,QAAQ;AACpC,aAAK,QAAQ;AACb,YAAI,OAAO;AAAA,MACf,CAAC;AACD,eAAS,QAAQ,MAAM;AAGvB,iBAAW,SAAS,QAAQ;AAC5B,iBAAW,UAAU;AAAA,IACzB;AAAA,EACJ,GAAG,CAAC,SAAS,UAAU,CAAC;AAGxB,YAAU,MAAM;AACZ,QAAI,WAAW,SAAS;AACpB,iBAAW,QAAQ,YAAY,KAAK;AAAA,IACxC;AAAA,EACJ,GAAG,CAAC,KAAK,CAAC;AAEV,SACI;AAAA,IAAC;AAAA;AAAA,MACG,KAAK;AAAA,MACL;AAAA,MACA,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,GAAG,MAAM;AAAA;AAAA,EAC3D;AAER;AASA,IAAM,kBAAkB,WAAW,oBAAoB;AAIvD,IAAO,gBAAQ;","names":[]}
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.css"],"sourcesContent":[".masonry-snap-grid-container {\n position: relative;\n width: 100%;\n transition: height 0.4s ease-out;\n overflow: hidden;\n}\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}"],"mappings":";
|
|
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 overflow: hidden;\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;AACxB,YAAU;AACd;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":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as MasonrySnapGridLayout } from './MasonrySnapGridLayout-
|
|
2
|
-
export { a as MasonrySnapGridLayoutOptions } from './MasonrySnapGridLayout-
|
|
1
|
+
import { M as MasonrySnapGridLayout } from './MasonrySnapGridLayout-CPmdhc_q.cjs';
|
|
2
|
+
export { a as MasonrySnapGridLayoutOptions } from './MasonrySnapGridLayout-CPmdhc_q.cjs';
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as MasonrySnapGridLayout } from './MasonrySnapGridLayout-
|
|
2
|
-
export { a as MasonrySnapGridLayoutOptions } from './MasonrySnapGridLayout-
|
|
1
|
+
import { M as MasonrySnapGridLayout } from './MasonrySnapGridLayout-CPmdhc_q.js';
|
|
2
|
+
export { a as MasonrySnapGridLayoutOptions } from './MasonrySnapGridLayout-CPmdhc_q.js';
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -27,9 +27,18 @@ module.exports = __toCommonJS(index_exports);
|
|
|
27
27
|
|
|
28
28
|
// src/MasonrySnapGridLayout.ts
|
|
29
29
|
var MasonrySnapGridLayout = class {
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new MasonrySnapGridLayout instance.
|
|
32
|
+
*
|
|
33
|
+
* @param container - The HTML element that will act as the grid container.
|
|
34
|
+
* @param options - Partial configuration object for layout behavior and rendering.
|
|
35
|
+
*/
|
|
30
36
|
constructor(container, options) {
|
|
37
|
+
/** A reference to all grid item elements currently rendered. */
|
|
31
38
|
this.items = [];
|
|
39
|
+
/** Tracks the current heights of each column to position new items. */
|
|
32
40
|
this.columnHeights = [];
|
|
41
|
+
/** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */
|
|
33
42
|
this.rafId = null;
|
|
34
43
|
this.container = container;
|
|
35
44
|
this.options = {
|
|
@@ -47,6 +56,10 @@ var MasonrySnapGridLayout = class {
|
|
|
47
56
|
this.renderItems();
|
|
48
57
|
this.setupResizeObserver();
|
|
49
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Renders the provided items into the container.
|
|
61
|
+
* Clears previous items and re-builds DOM structure.
|
|
62
|
+
*/
|
|
50
63
|
renderItems() {
|
|
51
64
|
this.items.forEach((item) => item.remove());
|
|
52
65
|
this.items = [];
|
|
@@ -60,6 +73,9 @@ var MasonrySnapGridLayout = class {
|
|
|
60
73
|
this.container.appendChild(fragment);
|
|
61
74
|
this.updateLayout();
|
|
62
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Sets up a ResizeObserver to re-calculate layout when container size changes.
|
|
78
|
+
*/
|
|
63
79
|
setupResizeObserver() {
|
|
64
80
|
this.resizeObserver = new ResizeObserver(() => {
|
|
65
81
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
|
@@ -67,6 +83,10 @@ var MasonrySnapGridLayout = class {
|
|
|
67
83
|
});
|
|
68
84
|
this.resizeObserver.observe(this.container);
|
|
69
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Calculates item positions and updates their transforms.
|
|
88
|
+
* Also adjusts the container height to fit all items.
|
|
89
|
+
*/
|
|
70
90
|
updateLayout() {
|
|
71
91
|
const { gutter, minColWidth, animate, transitionDuration } = this.options;
|
|
72
92
|
const containerWidth = this.container.clientWidth;
|
|
@@ -86,13 +106,27 @@ var MasonrySnapGridLayout = class {
|
|
|
86
106
|
const maxHeight = Math.max(...this.columnHeights);
|
|
87
107
|
this.container.style.height = `${maxHeight}px`;
|
|
88
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Finds the index of the column with the smallest total height.
|
|
111
|
+
*
|
|
112
|
+
* @returns Index of the shortest column.
|
|
113
|
+
*/
|
|
89
114
|
findShortestColumn() {
|
|
90
115
|
return this.columnHeights.indexOf(Math.min(...this.columnHeights));
|
|
91
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Replaces current items with a new set and re-renders the layout.
|
|
119
|
+
*
|
|
120
|
+
* @param newItems - New set of data items to render.
|
|
121
|
+
*/
|
|
92
122
|
updateItems(newItems) {
|
|
93
123
|
this.options.items = newItems;
|
|
94
124
|
this.renderItems();
|
|
95
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Cleans up event listeners, observers, and DOM modifications.
|
|
128
|
+
* This should be called before discarding the instance.
|
|
129
|
+
*/
|
|
96
130
|
destroy() {
|
|
97
131
|
this.resizeObserver?.disconnect();
|
|
98
132
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import './index.css'
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import './index.css'; // Base CSS styles for MasonrySnapGridLayout\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\nimport { MasonrySnapGridLayoutOptions } from './types';\n\n/**\n * Entry point for the MasonrySnapGridLayout package.\n *\n * - Imports the default styles for the layout (`index.css`).\n * - Re-exports the core class and associated type definitions.\n * - This allows consumers to either:\n * - Import the default class directly.\n * - Or import named exports for more flexibility.\n */\n\nexport default MasonrySnapGridLayout;\nexport {\n MasonrySnapGridLayout,\n MasonrySnapGridLayoutOptions\n};\n","import { MasonrySnapGridLayoutOptions } from './types';\n\n/**\n * MasonrySnapGridLayout\n *\n * A lightweight, generic TypeScript implementation of a responsive Masonry-style grid layout\n * with optional animations, custom rendering, and automatic re-layout on resize.\n *\n * @template T - The type of data items that will be rendered into grid elements.\n */\nexport default class MasonrySnapGridLayout<T = any> {\n /** The container element where the Masonry grid will be rendered. */\n private readonly container: HTMLElement;\n\n /** Fully resolved options object with defaults merged. */\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\n\n /** A reference to all grid item elements currently rendered. */\n private items: HTMLElement[] = [];\n\n /** Tracks the current heights of each column to position new items. */\n private columnHeights: number[] = [];\n\n /** Observes container resizing to trigger re-layout. */\n private resizeObserver: ResizeObserver | undefined;\n\n /** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */\n private rafId: number | null = null;\n\n /**\n * Creates a new MasonrySnapGridLayout instance.\n *\n * @param container - The HTML element that will act as the grid container.\n * @param options - Partial configuration object for layout behavior and rendering.\n */\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\n this.container = container;\n\n // Merge default settings with user-provided options\n this.options = {\n gutter: 16,\n minColWidth: 250,\n animate: true,\n transitionDuration: 400,\n classNames: {\n container: 'masonry-snap-grid-container',\n item: 'masonry-snap-grid-item',\n },\n ...options,\n };\n\n // Apply base container class for styling\n this.container.classList.add(this.options.classNames.container || \"\");\n\n // Initial rendering and layout setup\n this.renderItems();\n this.setupResizeObserver();\n }\n\n /**\n * Renders the provided items into the container.\n * Clears previous items and re-builds DOM structure.\n */\n private renderItems() {\n // Remove any previously rendered items\n this.items.forEach(item => item.remove());\n this.items = [];\n\n // Use DocumentFragment for efficient DOM updates\n const fragment = document.createDocumentFragment();\n\n // Create elements for each item and append to fragment\n this.options.items.forEach(itemData => {\n const itemElement = this.options.renderItem(itemData);\n itemElement.classList.add(this.options.classNames.item || \"\");\n fragment.appendChild(itemElement);\n this.items.push(itemElement);\n });\n\n // Append all items to container at once\n this.container.appendChild(fragment);\n\n // Trigger layout positioning\n this.updateLayout();\n }\n\n /**\n * Sets up a ResizeObserver to re-calculate layout when container size changes.\n */\n private setupResizeObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n // Throttle updates to animation frame to avoid layout thrashing\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(() => this.updateLayout());\n });\n this.resizeObserver.observe(this.container);\n }\n\n /**\n * Calculates item positions and updates their transforms.\n * Also adjusts the container height to fit all items.\n */\n private updateLayout() {\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\n const containerWidth = this.container.clientWidth;\n\n // Determine number of columns based on available width and minColWidth\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\n\n // Calculate actual column width including gutters\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\n\n // Reset heights for all columns\n this.columnHeights = new Array(columns).fill(0);\n\n // Position each item in the shortest column\n this.items.forEach((item) => {\n const height = item.offsetHeight;\n const minCol = this.findShortestColumn();\n const x = minCol * (colWidth + gutter);\n const y = this.columnHeights[minCol];\n\n // Apply positioning and animation\n item.style.width = `${colWidth}px`;\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\n item.style.transition = animate\n ? `transform ${transitionDuration}ms ease`\n : 'none';\n\n // Update column height to account for this item\n this.columnHeights[minCol] += height + gutter;\n });\n\n // Set container height to the tallest column\n const maxHeight = Math.max(...this.columnHeights);\n this.container.style.height = `${maxHeight}px`;\n }\n\n /**\n * Finds the index of the column with the smallest total height.\n *\n * @returns Index of the shortest column.\n */\n private findShortestColumn(): number {\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\n }\n\n /**\n * Replaces current items with a new set and re-renders the layout.\n *\n * @param newItems - New set of data items to render.\n */\n public updateItems(newItems: T[]) {\n this.options.items = newItems;\n this.renderItems();\n }\n\n /**\n * Cleans up event listeners, observers, and DOM modifications.\n * This should be called before discarding the instance.\n */\n public destroy() {\n this.resizeObserver?.disconnect();\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.container.innerHTML = '';\n this.container.removeAttribute('style');\n this.container.classList.remove(this.options.classNames.container || \"\");\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/react.d.cts
CHANGED
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { a as MasonrySnapGridLayoutOptions, b as MasonrySnapGridRef } from './MasonrySnapGridLayout-
|
|
3
|
+
import { a as MasonrySnapGridLayoutOptions, b as MasonrySnapGridRef } from './MasonrySnapGridLayout-CPmdhc_q.cjs';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Props for the MasonrySnapGrid React component.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of items in the masonry layout.
|
|
9
|
+
*/
|
|
5
10
|
interface MasonrySnapGridProps<T> extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {
|
|
11
|
+
/** Array of data items to be rendered into the masonry grid. */
|
|
6
12
|
items: T[];
|
|
13
|
+
/** Function that renders a single data item as a React node. */
|
|
7
14
|
renderItem: (item: T) => React.ReactNode;
|
|
15
|
+
/** Optional class name for the container. */
|
|
8
16
|
className?: string;
|
|
17
|
+
/** Optional inline styles for the container. */
|
|
9
18
|
style?: React.CSSProperties;
|
|
10
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Internal component that bridges MasonrySnapGridLayout with React.
|
|
22
|
+
*
|
|
23
|
+
* - Manages lifecycle of the underlying MasonrySnapGridLayout instance.
|
|
24
|
+
* - Uses ReactDOM.createRoot to render React nodes into non-React DOM elements.
|
|
25
|
+
* - Handles cleanup to avoid memory leaks.
|
|
26
|
+
*/
|
|
11
27
|
declare const MasonrySnapGridInner: <T>({ items, renderItem, className, style, ...options }: MasonrySnapGridProps<T>, ref: React.ForwardedRef<MasonrySnapGridRef>) => react_jsx_runtime.JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* MasonrySnapGrid
|
|
30
|
+
*
|
|
31
|
+
* React wrapper component for MasonrySnapGridLayout.
|
|
32
|
+
*
|
|
33
|
+
* @template T - The type of items in the masonry layout.
|
|
34
|
+
*/
|
|
12
35
|
declare const MasonrySnapGrid: <T>(props: MasonrySnapGridProps<T> & {
|
|
13
36
|
ref?: React.ForwardedRef<MasonrySnapGridRef>;
|
|
14
37
|
}) => ReturnType<typeof MasonrySnapGridInner>;
|
package/dist/react.d.ts
CHANGED
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { a as MasonrySnapGridLayoutOptions, b as MasonrySnapGridRef } from './MasonrySnapGridLayout-
|
|
3
|
+
import { a as MasonrySnapGridLayoutOptions, b as MasonrySnapGridRef } from './MasonrySnapGridLayout-CPmdhc_q.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Props for the MasonrySnapGrid React component.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The type of items in the masonry layout.
|
|
9
|
+
*/
|
|
5
10
|
interface MasonrySnapGridProps<T> extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {
|
|
11
|
+
/** Array of data items to be rendered into the masonry grid. */
|
|
6
12
|
items: T[];
|
|
13
|
+
/** Function that renders a single data item as a React node. */
|
|
7
14
|
renderItem: (item: T) => React.ReactNode;
|
|
15
|
+
/** Optional class name for the container. */
|
|
8
16
|
className?: string;
|
|
17
|
+
/** Optional inline styles for the container. */
|
|
9
18
|
style?: React.CSSProperties;
|
|
10
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Internal component that bridges MasonrySnapGridLayout with React.
|
|
22
|
+
*
|
|
23
|
+
* - Manages lifecycle of the underlying MasonrySnapGridLayout instance.
|
|
24
|
+
* - Uses ReactDOM.createRoot to render React nodes into non-React DOM elements.
|
|
25
|
+
* - Handles cleanup to avoid memory leaks.
|
|
26
|
+
*/
|
|
11
27
|
declare const MasonrySnapGridInner: <T>({ items, renderItem, className, style, ...options }: MasonrySnapGridProps<T>, ref: React.ForwardedRef<MasonrySnapGridRef>) => react_jsx_runtime.JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* MasonrySnapGrid
|
|
30
|
+
*
|
|
31
|
+
* React wrapper component for MasonrySnapGridLayout.
|
|
32
|
+
*
|
|
33
|
+
* @template T - The type of items in the masonry layout.
|
|
34
|
+
*/
|
|
12
35
|
declare const MasonrySnapGrid: <T>(props: MasonrySnapGridProps<T> & {
|
|
13
36
|
ref?: React.ForwardedRef<MasonrySnapGridRef>;
|
|
14
37
|
}) => ReturnType<typeof MasonrySnapGridInner>;
|
package/dist/react.js
CHANGED
|
@@ -38,9 +38,18 @@ var import_client = __toESM(require("react-dom/client"), 1);
|
|
|
38
38
|
|
|
39
39
|
// src/MasonrySnapGridLayout.ts
|
|
40
40
|
var MasonrySnapGridLayout = class {
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new MasonrySnapGridLayout instance.
|
|
43
|
+
*
|
|
44
|
+
* @param container - The HTML element that will act as the grid container.
|
|
45
|
+
* @param options - Partial configuration object for layout behavior and rendering.
|
|
46
|
+
*/
|
|
41
47
|
constructor(container, options) {
|
|
48
|
+
/** A reference to all grid item elements currently rendered. */
|
|
42
49
|
this.items = [];
|
|
50
|
+
/** Tracks the current heights of each column to position new items. */
|
|
43
51
|
this.columnHeights = [];
|
|
52
|
+
/** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */
|
|
44
53
|
this.rafId = null;
|
|
45
54
|
this.container = container;
|
|
46
55
|
this.options = {
|
|
@@ -58,6 +67,10 @@ var MasonrySnapGridLayout = class {
|
|
|
58
67
|
this.renderItems();
|
|
59
68
|
this.setupResizeObserver();
|
|
60
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Renders the provided items into the container.
|
|
72
|
+
* Clears previous items and re-builds DOM structure.
|
|
73
|
+
*/
|
|
61
74
|
renderItems() {
|
|
62
75
|
this.items.forEach((item) => item.remove());
|
|
63
76
|
this.items = [];
|
|
@@ -71,6 +84,9 @@ var MasonrySnapGridLayout = class {
|
|
|
71
84
|
this.container.appendChild(fragment);
|
|
72
85
|
this.updateLayout();
|
|
73
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Sets up a ResizeObserver to re-calculate layout when container size changes.
|
|
89
|
+
*/
|
|
74
90
|
setupResizeObserver() {
|
|
75
91
|
this.resizeObserver = new ResizeObserver(() => {
|
|
76
92
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
|
@@ -78,6 +94,10 @@ var MasonrySnapGridLayout = class {
|
|
|
78
94
|
});
|
|
79
95
|
this.resizeObserver.observe(this.container);
|
|
80
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Calculates item positions and updates their transforms.
|
|
99
|
+
* Also adjusts the container height to fit all items.
|
|
100
|
+
*/
|
|
81
101
|
updateLayout() {
|
|
82
102
|
const { gutter, minColWidth, animate, transitionDuration } = this.options;
|
|
83
103
|
const containerWidth = this.container.clientWidth;
|
|
@@ -97,13 +117,27 @@ var MasonrySnapGridLayout = class {
|
|
|
97
117
|
const maxHeight = Math.max(...this.columnHeights);
|
|
98
118
|
this.container.style.height = `${maxHeight}px`;
|
|
99
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Finds the index of the column with the smallest total height.
|
|
122
|
+
*
|
|
123
|
+
* @returns Index of the shortest column.
|
|
124
|
+
*/
|
|
100
125
|
findShortestColumn() {
|
|
101
126
|
return this.columnHeights.indexOf(Math.min(...this.columnHeights));
|
|
102
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Replaces current items with a new set and re-renders the layout.
|
|
130
|
+
*
|
|
131
|
+
* @param newItems - New set of data items to render.
|
|
132
|
+
*/
|
|
103
133
|
updateItems(newItems) {
|
|
104
134
|
this.options.items = newItems;
|
|
105
135
|
this.renderItems();
|
|
106
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Cleans up event listeners, observers, and DOM modifications.
|
|
139
|
+
* This should be called before discarding the instance.
|
|
140
|
+
*/
|
|
107
141
|
destroy() {
|
|
108
142
|
this.resizeObserver?.disconnect();
|
|
109
143
|
if (this.rafId) cancelAnimationFrame(this.rafId);
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.tsx","../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\n useEffect,\n useRef,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport ReactDOM from 'react-dom/client';\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\nimport {\n MasonrySnapGridLayoutOptions,\n MasonrySnapGridRef,\n} from './types';\n\ninterface MasonrySnapGridProps<T>\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\n items: T[];\n renderItem: (item: T) => React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst MasonrySnapGridInner = <T,>(\n {\n items,\n renderItem,\n className,\n style,\n ...options\n }: MasonrySnapGridProps<T>,\n ref: React.ForwardedRef<MasonrySnapGridRef>\n) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\n\n // Initialize masonry layout\n useEffect(() => {\n if (!containerRef.current) return;\n\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\n ...options,\n items,\n renderItem: (item) => {\n const div = document.createElement('div');\n const root = ReactDOM.createRoot(div);\n root.render(renderItem(item));\n rootsRef.current.set(div, root);\n return div;\n },\n });\n\n return () => {\n // Proper cleanup\n rootsRef.current.forEach((root, div) => {\n root.unmount();\n div.remove();\n });\n rootsRef.current.clear();\n masonryRef.current?.destroy();\n masonryRef.current = null;\n };\n }, [options, renderItem]);\n\n // Update items on change\n useEffect(() => {\n if (masonryRef.current) {\n masonryRef.current.updateItems(items);\n }\n }, [items]);\n\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: 'relative', width: '100%', ...style }}\n />\n );\n};\n\n// Properly typed forwardRef component\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\n props: MasonrySnapGridProps<T> & { ref?: React.ForwardedRef<MasonrySnapGridRef> }\n) => ReturnType<typeof MasonrySnapGridInner>;\n\nexport default MasonrySnapGrid;","import { MasonrySnapGridLayoutOptions } from './types';\n\nexport default class MasonrySnapGridLayout<T = any> {\n private readonly container: HTMLElement;\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\n private items: HTMLElement[] = [];\n private columnHeights: number[] = [];\n private resizeObserver: ResizeObserver | undefined;\n private rafId: number | null = null;\n\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\n this.container = container;\n this.options = {\n gutter: 16,\n minColWidth: 250,\n animate: true,\n transitionDuration: 400,\n classNames: {\n container: 'masonry-snap-grid-container',\n item: 'masonry-snap-grid-item',\n },\n ...options,\n };\n\n // Apply container class\n this.container.classList.add(this.options.classNames.container || \"\");\n\n // Initialize\n this.renderItems();\n this.setupResizeObserver();\n }\n\n private renderItems() {\n // Clear existing items\n this.items.forEach(item => item.remove());\n this.items = [];\n\n // Create fragment for batch DOM insertion\n const fragment = document.createDocumentFragment();\n\n // Create and append items\n this.options.items.forEach(itemData => {\n const itemElement = this.options.renderItem(itemData);\n itemElement.classList.add(this.options.classNames.item|| \"\");\n fragment.appendChild(itemElement);\n this.items.push(itemElement);\n });\n\n this.container.appendChild(fragment);\n this.updateLayout();\n }\n\n private setupResizeObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(() => this.updateLayout());\n });\n this.resizeObserver.observe(this.container);\n }\n\n private updateLayout() {\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\n const containerWidth = this.container.clientWidth;\n\n // Calculate columns\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\n\n // Reset column heights\n this.columnHeights = new Array(columns).fill(0);\n\n // Position items\n this.items.forEach((item) => {\n const height = item.offsetHeight;\n const minCol = this.findShortestColumn();\n const x = minCol * (colWidth + gutter);\n const y = this.columnHeights[minCol];\n\n // Apply position and size\n item.style.width = `${colWidth}px`;\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\n item.style.transition = animate\n ? `transform ${transitionDuration}ms ease`\n : 'none';\n\n // Update column height\n this.columnHeights[minCol] += height + gutter;\n });\n\n // Set container height\n const maxHeight = Math.max(...this.columnHeights);\n this.container.style.height = `${maxHeight}px`;\n }\n\n private findShortestColumn(): number {\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\n }\n\n public updateItems(newItems: T[]) {\n this.options.items = newItems;\n this.renderItems();\n }\n\n public destroy() {\n this.resizeObserver?.disconnect();\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.container.innerHTML = '';\n this.container.removeAttribute('style');\n this.container.classList.remove(this.options.classNames.container || \"\");\n }\n}"],"mappings":"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","names":["ReactDOM"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx","../src/MasonrySnapGridLayout.ts"],"sourcesContent":["import React, {\n useEffect,\n useRef,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport ReactDOM from 'react-dom/client';\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\nimport {\n MasonrySnapGridLayoutOptions,\n MasonrySnapGridRef,\n} from './types';\n\n/**\n * Props for the MasonrySnapGrid React component.\n *\n * @template T - The type of items in the masonry layout.\n */\ninterface MasonrySnapGridProps<T>\n extends Omit<MasonrySnapGridLayoutOptions<T>, 'items' | 'renderItem'> {\n /** Array of data items to be rendered into the masonry grid. */\n items: T[];\n\n /** Function that renders a single data item as a React node. */\n renderItem: (item: T) => React.ReactNode;\n\n /** Optional class name for the container. */\n className?: string;\n\n /** Optional inline styles for the container. */\n style?: React.CSSProperties;\n}\n\n/**\n * Internal component that bridges MasonrySnapGridLayout with React.\n *\n * - Manages lifecycle of the underlying MasonrySnapGridLayout instance.\n * - Uses ReactDOM.createRoot to render React nodes into non-React DOM elements.\n * - Handles cleanup to avoid memory leaks.\n */\nconst MasonrySnapGridInner = <T,>(\n {\n items,\n renderItem,\n className,\n style,\n ...options\n }: MasonrySnapGridProps<T>,\n ref: React.ForwardedRef<MasonrySnapGridRef>\n) => {\n /** Ref to the container DOM element where MasonrySnapGridLayout will operate. */\n const containerRef = useRef<HTMLDivElement>(null);\n\n /** Ref to the MasonrySnapGridLayout instance (non-React logic). */\n const masonryRef = useRef<MasonrySnapGridLayout<T> | null>(null);\n\n /** Tracks all mounted React roots for cleanup. */\n const rootsRef = useRef<Map<HTMLElement, ReactDOM.Root>>(new Map());\n\n // Initialize masonry layout when container mounts\n useEffect(() => {\n if (!containerRef.current) return;\n\n masonryRef.current = new MasonrySnapGridLayout(containerRef.current, {\n ...options,\n items,\n renderItem: (item) => {\n // Create a standalone DOM element for each item\n const div = document.createElement('div');\n\n // Render React content into this element\n const root = ReactDOM.createRoot(div);\n root.render(renderItem(item));\n\n // Keep track of the React root for later cleanup\n rootsRef.current.set(div, root);\n\n return div;\n },\n });\n\n return () => {\n // Clean up all React roots and remove their DOM nodes\n rootsRef.current.forEach((root, div) => {\n root.unmount();\n div.remove();\n });\n rootsRef.current.clear();\n\n // Destroy the Masonry instance\n masonryRef.current?.destroy();\n masonryRef.current = null;\n };\n }, [options, renderItem]);\n\n // Update only the items when the data changes (avoid full re-initialization)\n useEffect(() => {\n if (masonryRef.current) {\n masonryRef.current.updateItems(items);\n }\n }, [items]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: 'relative', width: '100%', ...style }}\n />\n );\n};\n\n/**\n * MasonrySnapGrid\n *\n * React wrapper component for MasonrySnapGridLayout.\n *\n * @template T - The type of items in the masonry layout.\n */\nconst MasonrySnapGrid = forwardRef(MasonrySnapGridInner) as <T>(\n props: MasonrySnapGridProps<T> & { ref?: React.ForwardedRef<MasonrySnapGridRef> }\n) => ReturnType<typeof MasonrySnapGridInner>;\n\nexport default MasonrySnapGrid;\n","import { MasonrySnapGridLayoutOptions } from './types';\n\n/**\n * MasonrySnapGridLayout\n *\n * A lightweight, generic TypeScript implementation of a responsive Masonry-style grid layout\n * with optional animations, custom rendering, and automatic re-layout on resize.\n *\n * @template T - The type of data items that will be rendered into grid elements.\n */\nexport default class MasonrySnapGridLayout<T = any> {\n /** The container element where the Masonry grid will be rendered. */\n private readonly container: HTMLElement;\n\n /** Fully resolved options object with defaults merged. */\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\n\n /** A reference to all grid item elements currently rendered. */\n private items: HTMLElement[] = [];\n\n /** Tracks the current heights of each column to position new items. */\n private columnHeights: number[] = [];\n\n /** Observes container resizing to trigger re-layout. */\n private resizeObserver: ResizeObserver | undefined;\n\n /** Stores requestAnimationFrame ID for layout updates to prevent redundant calls. */\n private rafId: number | null = null;\n\n /**\n * Creates a new MasonrySnapGridLayout instance.\n *\n * @param container - The HTML element that will act as the grid container.\n * @param options - Partial configuration object for layout behavior and rendering.\n */\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\n this.container = container;\n\n // Merge default settings with user-provided options\n this.options = {\n gutter: 16,\n minColWidth: 250,\n animate: true,\n transitionDuration: 400,\n classNames: {\n container: 'masonry-snap-grid-container',\n item: 'masonry-snap-grid-item',\n },\n ...options,\n };\n\n // Apply base container class for styling\n this.container.classList.add(this.options.classNames.container || \"\");\n\n // Initial rendering and layout setup\n this.renderItems();\n this.setupResizeObserver();\n }\n\n /**\n * Renders the provided items into the container.\n * Clears previous items and re-builds DOM structure.\n */\n private renderItems() {\n // Remove any previously rendered items\n this.items.forEach(item => item.remove());\n this.items = [];\n\n // Use DocumentFragment for efficient DOM updates\n const fragment = document.createDocumentFragment();\n\n // Create elements for each item and append to fragment\n this.options.items.forEach(itemData => {\n const itemElement = this.options.renderItem(itemData);\n itemElement.classList.add(this.options.classNames.item || \"\");\n fragment.appendChild(itemElement);\n this.items.push(itemElement);\n });\n\n // Append all items to container at once\n this.container.appendChild(fragment);\n\n // Trigger layout positioning\n this.updateLayout();\n }\n\n /**\n * Sets up a ResizeObserver to re-calculate layout when container size changes.\n */\n private setupResizeObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n // Throttle updates to animation frame to avoid layout thrashing\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(() => this.updateLayout());\n });\n this.resizeObserver.observe(this.container);\n }\n\n /**\n * Calculates item positions and updates their transforms.\n * Also adjusts the container height to fit all items.\n */\n private updateLayout() {\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\n const containerWidth = this.container.clientWidth;\n\n // Determine number of columns based on available width and minColWidth\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\n\n // Calculate actual column width including gutters\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\n\n // Reset heights for all columns\n this.columnHeights = new Array(columns).fill(0);\n\n // Position each item in the shortest column\n this.items.forEach((item) => {\n const height = item.offsetHeight;\n const minCol = this.findShortestColumn();\n const x = minCol * (colWidth + gutter);\n const y = this.columnHeights[minCol];\n\n // Apply positioning and animation\n item.style.width = `${colWidth}px`;\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\n item.style.transition = animate\n ? `transform ${transitionDuration}ms ease`\n : 'none';\n\n // Update column height to account for this item\n this.columnHeights[minCol] += height + gutter;\n });\n\n // Set container height to the tallest column\n const maxHeight = Math.max(...this.columnHeights);\n this.container.style.height = `${maxHeight}px`;\n }\n\n /**\n * Finds the index of the column with the smallest total height.\n *\n * @returns Index of the shortest column.\n */\n private findShortestColumn(): number {\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\n }\n\n /**\n * Replaces current items with a new set and re-renders the layout.\n *\n * @param newItems - New set of data items to render.\n */\n public updateItems(newItems: T[]) {\n this.options.items = newItems;\n this.renderItems();\n }\n\n /**\n * Cleans up event listeners, observers, and DOM modifications.\n * This should be called before discarding the instance.\n */\n public destroy() {\n this.resizeObserver?.disconnect();\n if (this.rafId) cancelAnimationFrame(this.rafId);\n this.container.innerHTML = '';\n this.container.removeAttribute('style');\n this.container.classList.remove(this.options.classNames.container || \"\");\n }\n}\n"],"mappings":"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","names":["ReactDOM"]}
|
package/package.json
CHANGED
|
@@ -1,34 +0,0 @@
|
|
|
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 };
|
|
@@ -1,34 +0,0 @@
|
|
|
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 };
|