masonry-snap-grid-layout 1.0.2 → 1.0.4

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.
@@ -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 };
@@ -1,45 +1,17 @@
1
- /* src/masonry-snap-grid-layout.css */
2
- :root {
3
- --gutter: 16px;
4
- --columns: 4;
5
- --min-col-width: 250px;
6
- --transition-duration: 0.4s;
7
- --primary-color: #6b73ff;
8
- --secondary-color: #000dff;
9
- --text-color: #fff;
10
- --shadow-color: rgba(0, 0, 0, 0.1);
11
- --item-radius: 8px;
12
- }
13
- .masonry-snap-grid-layout-container {
1
+ /* src/index.css */
2
+ .masonry-snap-grid-container {
14
3
  position: relative;
15
4
  width: 100%;
16
- max-width: 1200px;
17
- margin: 0 auto;
18
- transition: height var(--transition-duration) ease-out;
5
+ transition: height 0.4s ease-out;
6
+ overflow: hidden;
19
7
  }
20
- .masonry-snap-grid-layout-item {
8
+ .masonry-snap-grid-item {
21
9
  position: absolute;
22
- color: var(--text-color);
23
- border-radius: var(--item-radius);
24
- font-size: 1rem;
25
- box-shadow: 0 6px 12px var(--shadow-color);
26
- user-select: none;
27
- cursor: grab;
10
+ transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
28
11
  will-change: transform;
29
- transition:
30
- transform var(--transition-duration) cubic-bezier(0.4, 0, 0.2, 1),
31
- box-shadow 0.3s ease,
32
- background 0.4s ease;
33
- overflow: hidden;
34
- z-index: 1;
35
- }
36
- .masonry-snap-grid-layout-item:hover {
37
- box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
38
- transform: translateY(-2px);
39
- }
40
- .masonry-snap-grid-layout-item:active {
41
- cursor: grabbing;
42
- box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
43
- z-index: 10;
12
+ box-sizing: border-box;
13
+ transform-origin: top left;
14
+ backface-visibility: hidden;
15
+ perspective: 1000px;
44
16
  }
45
17
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/masonry-snap-grid-layout.css"],"sourcesContent":["/*\r\n Masonry Snap Grid Layout Styles\r\n\r\n CSS variables for easy customization:\r\n --gutter: spacing between items\r\n --columns: number of columns (calculated dynamically)\r\n --min-col-width: minimum width of columns\r\n --transition-duration: animation timing\r\n --primary-color, --secondary-color: gradient colors for items\r\n --text-color: color for text inside items\r\n --shadow-color: shadow color for item depth\r\n --item-radius: border-radius for rounded corners\r\n*/\r\n\r\n/* Root CSS variables for theming */\r\n:root {\r\n --gutter: 16px;\r\n --columns: 4;\r\n --min-col-width: 250px;\r\n --transition-duration: 0.4s;\r\n --primary-color: #6b73ff;\r\n --secondary-color: #000dff;\r\n --text-color: #fff;\r\n --shadow-color: rgba(0, 0, 0, 0.1);\r\n --item-radius: 8px;\r\n}\r\n\r\n/* Container for masonry grid — relative positioning for absolute item placement */\r\n.masonry-snap-grid-layout-container {\r\n position: relative;\r\n width: 100%;\r\n max-width: 1200px;\r\n margin: 0 auto;\r\n transition: height var(--transition-duration) ease-out;\r\n}\r\n\r\n/* Each item absolutely positioned within container */\r\n.masonry-snap-grid-layout-item {\r\n position: absolute;\r\n color: var(--text-color);\r\n border-radius: var(--item-radius);\r\n font-size: 1rem;\r\n box-shadow: 0 6px 12px var(--shadow-color);\r\n user-select: none;\r\n cursor: grab;\r\n will-change: transform;\r\n transition:\r\n transform var(--transition-duration) cubic-bezier(0.4, 0, 0.2, 1),\r\n box-shadow 0.3s ease,\r\n background 0.4s ease;\r\n overflow: hidden;\r\n z-index: 1;\r\n}\r\n\r\n/* Hover state for better UX */\r\n.masonry-snap-grid-layout-item:hover {\r\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);\r\n transform: translateY(-2px);\r\n}\r\n\r\n/* Active / grabbing state */\r\n.masonry-snap-grid-layout-item:active {\r\n cursor: grabbing;\r\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);\r\n z-index: 10;\r\n}\r\n\r\n"],"mappings":";AAeA;AACI,YAAU;AACV,aAAW;AACX,mBAAiB;AACjB,yBAAuB;AACvB,mBAAiB;AACjB,qBAAmB;AACnB,gBAAc;AACd,kBAAgB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAC9B,iBAAe;AACnB;AAGA,CAAC;AACG,YAAU;AACV,SAAO;AACP,aAAW;AACX,UAAQ,EAAE;AACV,cAAY,OAAO,IAAI,uBAAuB;AAClD;AAGA,CAAC;AACG,YAAU;AACV,SAAO,IAAI;AACX,iBAAe,IAAI;AACnB,aAAW;AACX,cAAY,EAAE,IAAI,KAAK,IAAI;AAC3B,eAAa;AACb,UAAQ;AACR,eAAa;AACb;AAAA,IACQ,UAAU,IAAI,uBAAuB,aAAa,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;AAAA,IACjE,WAAW,KAAK,IAAI;AAAA,IACpB,WAAW,KAAK;AACxB,YAAU;AACV,WAAS;AACb;AAGA,CAlBC,6BAkB6B;AAC1B,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACrC,aAAW,WAAW;AAC1B;AAGA,CAxBC,6BAwB6B;AAC1B,UAAQ;AACR,cAAY,EAAE,KAAK,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACtC,WAAS;AACb;","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":[]}
package/dist/esm/index.js CHANGED
@@ -1,203 +1,81 @@
1
1
  // src/MasonrySnapGridLayout.ts
2
2
  var MasonrySnapGridLayout = class {
3
- constructor(container2, options = {}) {
3
+ constructor(container, options) {
4
4
  this.items = [];
5
- this.positions = [];
6
5
  this.columnHeights = [];
7
- this.columns = 0;
8
- this.lastPositions = [];
9
- this.resizeRaf = null;
10
- this.resizeObserver = null;
11
- this.boundResizeHandler = this.handleResize.bind(this);
12
- this.container = container2;
13
- this.classNames = {
14
- container: "masonry-snap-grid-container",
15
- item: "masonry-snap-grid-item",
16
- itemContent: "masonry-snap-grid-item-content",
17
- itemHeader: "masonry-snap-grid-item-header",
18
- itemTitle: "masonry-snap-grid-item-title",
19
- itemId: "masonry-snap-grid-item-id",
20
- itemBody: "masonry-snap-grid-item-body",
21
- progressBar: "masonry-snap-grid-progress-bar",
22
- progress: "masonry-snap-grid-progress",
23
- itemFooter: "masonry-snap-grid-item-footer",
24
- ...options.classNames || {}
25
- };
6
+ this.rafId = null;
7
+ this.container = container;
26
8
  this.options = {
27
9
  gutter: 16,
28
10
  minColWidth: 250,
29
11
  animate: true,
30
12
  transitionDuration: 400,
31
- initialItems: 0,
32
- itemContent: null,
33
- classNames: this.classNames,
13
+ classNames: {
14
+ container: "masonry-snap-grid-container",
15
+ item: "masonry-snap-grid-item"
16
+ },
34
17
  ...options
35
18
  };
36
- this.container.classList.add(this.classNames.container);
37
- this.init();
38
- }
39
- init() {
40
- this.setupEventListeners();
41
- this.generateItems(this.options.initialItems);
42
- this.calculateLayout();
43
- this.applyLayout(false);
44
- }
45
- setupEventListeners() {
46
- this.resizeObserver = new ResizeObserver(() => this.handleResize());
47
- this.resizeObserver.observe(this.container);
48
- window.addEventListener("resize", this.boundResizeHandler);
19
+ this.container.classList.add(this.options.classNames.container || "");
20
+ this.renderItems();
21
+ this.setupResizeObserver();
49
22
  }
50
- generateItems(count) {
51
- if (count < this.items.length) {
52
- this.items.slice(count).forEach((item) => item.remove());
53
- this.items = this.items.slice(0, count);
54
- return;
55
- }
56
- const startIndex = this.items.length;
23
+ renderItems() {
24
+ this.items.forEach((item) => item.remove());
25
+ this.items = [];
57
26
  const fragment = document.createDocumentFragment();
58
- for (let i = startIndex; i < count; i++) {
59
- const item = this.createItem(i);
60
- fragment.appendChild(item);
61
- this.items.push(item);
62
- }
27
+ this.options.items.forEach((itemData) => {
28
+ const itemElement = this.options.renderItem(itemData);
29
+ itemElement.classList.add(this.options.classNames.item || "");
30
+ fragment.appendChild(itemElement);
31
+ this.items.push(itemElement);
32
+ });
63
33
  this.container.appendChild(fragment);
34
+ this.updateLayout();
64
35
  }
65
- createItem(index) {
66
- const div = document.createElement("div");
67
- div.className = this.classNames.item;
68
- const contentOption = this.options.itemContent;
69
- let content;
70
- if (typeof contentOption === "function") {
71
- content = contentOption(index);
72
- } else if (contentOption instanceof HTMLElement || typeof contentOption === "string") {
73
- content = contentOption;
74
- } else {
75
- content = `Item ${index + 1}`;
76
- }
77
- if (typeof content === "string") {
78
- div.textContent = content;
79
- } else {
80
- div.appendChild(content);
81
- }
82
- const height = 120 + Math.floor(Math.random() * 100);
83
- div.style.height = `${height}px`;
84
- return div;
36
+ setupResizeObserver() {
37
+ this.resizeObserver = new ResizeObserver(() => {
38
+ if (this.rafId) cancelAnimationFrame(this.rafId);
39
+ this.rafId = requestAnimationFrame(() => this.updateLayout());
40
+ });
41
+ this.resizeObserver.observe(this.container);
85
42
  }
86
- calculateLayout() {
87
- const { gutter, minColWidth } = this.options;
43
+ updateLayout() {
44
+ const { gutter, minColWidth, animate, transitionDuration } = this.options;
88
45
  const containerWidth = this.container.clientWidth;
89
- this.columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));
90
- const colWidth = (containerWidth - (this.columns - 1) * gutter) / this.columns;
91
- this.lastPositions = [...this.positions];
92
- this.columnHeights = new Array(this.columns).fill(0);
93
- this.positions = [];
94
- this.items.forEach((item, i) => {
46
+ const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));
47
+ const colWidth = (containerWidth - (columns - 1) * gutter) / columns;
48
+ this.columnHeights = new Array(columns).fill(0);
49
+ this.items.forEach((item) => {
95
50
  const height = item.offsetHeight;
96
- let minCol = 0;
97
- for (let c = 1; c < this.columns; c++) {
98
- if (this.columnHeights[c] < this.columnHeights[minCol]) {
99
- minCol = c;
100
- }
101
- }
51
+ const minCol = this.findShortestColumn();
102
52
  const x = minCol * (colWidth + gutter);
103
53
  const y = this.columnHeights[minCol];
104
- this.positions[i] = { x, y, width: colWidth, height };
54
+ item.style.width = `${colWidth}px`;
55
+ item.style.transform = `translate3d(${x}px, ${y}px, 0)`;
56
+ item.style.transition = animate ? `transform ${transitionDuration}ms ease` : "none";
105
57
  this.columnHeights[minCol] += height + gutter;
106
58
  });
107
59
  const maxHeight = Math.max(...this.columnHeights);
108
60
  this.container.style.height = `${maxHeight}px`;
109
61
  }
110
- applyLayout(animate = false) {
111
- const duration = this.options.transitionDuration;
112
- this.items.forEach((item, i) => {
113
- const pos = this.positions[i] || { x: 0, y: 0, width: 0 };
114
- const lastPos = this.lastPositions[i] || { x: 0, y: 0 };
115
- item.style.width = `${pos.width}px`;
116
- if (animate) {
117
- const dx = lastPos.x - pos.x;
118
- const dy = lastPos.y - pos.y;
119
- item.style.transition = "none";
120
- item.style.transform = `translate3d(${pos.x + dx}px, ${pos.y + dy}px, 0)`;
121
- void item.offsetHeight;
122
- item.style.transition = `transform ${duration}ms ease`;
123
- item.style.transform = `translate3d(${pos.x}px, ${pos.y}px, 0)`;
124
- } else {
125
- item.style.transition = "none";
126
- item.style.transform = `translate3d(${pos.x}px, ${pos.y}px, 0)`;
127
- }
128
- });
129
- }
130
- handleResize() {
131
- if (this.resizeRaf) cancelAnimationFrame(this.resizeRaf);
132
- this.resizeRaf = requestAnimationFrame(() => {
133
- this.calculateLayout();
134
- this.applyLayout(true);
135
- });
136
- }
137
- shuffleItems() {
138
- for (let i = this.items.length - 1; i > 0; i--) {
139
- const j = Math.floor(Math.random() * (i + 1));
140
- [this.items[i], this.items[j]] = [this.items[j], this.items[i]];
141
- }
142
- const fragment = document.createDocumentFragment();
143
- this.items.forEach((item) => fragment.appendChild(item));
144
- this.container.appendChild(fragment);
145
- this.calculateLayout();
146
- this.applyLayout(true);
62
+ findShortestColumn() {
63
+ return this.columnHeights.indexOf(Math.min(...this.columnHeights));
147
64
  }
148
- addItems(count) {
149
- const newCount = this.items.length + count;
150
- this.generateItems(newCount);
151
- this.calculateLayout();
152
- this.applyLayout(true);
65
+ updateItems(newItems) {
66
+ this.options.items = newItems;
67
+ this.renderItems();
153
68
  }
154
69
  destroy() {
155
- if (this.resizeObserver) {
156
- this.resizeObserver.disconnect();
157
- this.resizeObserver = null;
158
- }
159
- window.removeEventListener("resize", this.boundResizeHandler);
160
- if (this.resizeRaf) {
161
- cancelAnimationFrame(this.resizeRaf);
162
- this.resizeRaf = null;
163
- }
70
+ this.resizeObserver?.disconnect();
71
+ if (this.rafId) cancelAnimationFrame(this.rafId);
164
72
  this.container.innerHTML = "";
165
73
  this.container.removeAttribute("style");
166
- this.container.classList.remove(this.classNames.container);
167
- this.items = [];
168
- this.positions = [];
169
- this.columnHeights = [];
170
- this.columns = 0;
171
- this.lastPositions = [];
74
+ this.container.classList.remove(this.options.classNames.container || "");
172
75
  }
173
76
  };
174
77
 
175
78
  // src/index.ts
176
- var container = document.getElementById("masonry");
177
- if (container) {
178
- const masonry = new MasonrySnapGridLayout(container, {
179
- gutter: 20,
180
- minColWidth: 200,
181
- animate: true,
182
- initialItems: 40,
183
- // Custom item content example
184
- itemContent: (index) => {
185
- const div = document.createElement("div");
186
- div.textContent = `Custom Item ${index + 1}`;
187
- div.style.color = "#fff";
188
- div.style.fontWeight = "bold";
189
- div.style.textAlign = "center";
190
- div.style.padding = "1rem";
191
- return div;
192
- },
193
- classNames: {
194
- container: "masonry-snap-grid-layout-container",
195
- item: "masonry-snap-grid-layout-item"
196
- }
197
- });
198
- masonry.addItems(5);
199
- masonry.shuffleItems();
200
- }
201
79
  var index_default = MasonrySnapGridLayout;
202
80
  export {
203
81
  MasonrySnapGridLayout,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/MasonrySnapGridLayout.ts","../../src/index.ts"],"sourcesContent":["import { MasonrySnapGridLayoutClassNames, MasonrySnapGridLayoutOptions } from './types';\r\n\r\nexport default class MasonrySnapGridLayout {\r\n private readonly container: HTMLElement;\r\n private readonly options: Required<MasonrySnapGridLayoutOptions>;\r\n private classNames: Required<MasonrySnapGridLayoutClassNames>;\r\n\r\n private items: HTMLElement[] = [];\r\n private positions: { x: number; y: number; width: number; height: number }[] = [];\r\n private columnHeights: number[] = [];\r\n private columns: number = 0;\r\n private lastPositions: typeof this.positions = [];\r\n private resizeRaf: number | null = null;\r\n\r\n private resizeObserver: ResizeObserver | null = null;\r\n private boundResizeHandler = this.handleResize.bind(this);\r\n\r\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions = {}) {\r\n this.container = container;\r\n this.classNames = {\r\n container: 'masonry-snap-grid-container',\r\n item: 'masonry-snap-grid-item',\r\n itemContent: 'masonry-snap-grid-item-content',\r\n itemHeader: 'masonry-snap-grid-item-header',\r\n itemTitle: 'masonry-snap-grid-item-title',\r\n itemId: 'masonry-snap-grid-item-id',\r\n itemBody: 'masonry-snap-grid-item-body',\r\n progressBar: 'masonry-snap-grid-progress-bar',\r\n progress: 'masonry-snap-grid-progress',\r\n itemFooter: 'masonry-snap-grid-item-footer',\r\n ...(options.classNames || {}),\r\n }\r\n this.options = {\r\n gutter: 16,\r\n minColWidth: 250,\r\n animate: true,\r\n transitionDuration: 400,\r\n initialItems: 0,\r\n itemContent: null,\r\n classNames: this.classNames,\r\n ...options,\r\n };\r\n\r\n\r\n this.container.classList.add(this.classNames.container);\r\n this.init();\r\n }\r\n\r\n private init() {\r\n this.setupEventListeners();\r\n this.generateItems(this.options.initialItems);\r\n this.calculateLayout();\r\n this.applyLayout(false);\r\n }\r\n\r\n private setupEventListeners() {\r\n this.resizeObserver = new ResizeObserver(() => this.handleResize());\r\n this.resizeObserver.observe(this.container);\r\n\r\n window.addEventListener('resize', this.boundResizeHandler);\r\n }\r\n\r\n public generateItems(count: number) {\r\n if (count < this.items.length) {\r\n this.items.slice(count).forEach((item) => item.remove());\r\n this.items = this.items.slice(0, count);\r\n return;\r\n }\r\n\r\n const startIndex = this.items.length;\r\n const fragment = document.createDocumentFragment();\r\n\r\n for (let i = startIndex; i < count; i++) {\r\n const item = this.createItem(i);\r\n fragment.appendChild(item);\r\n this.items.push(item);\r\n }\r\n\r\n this.container.appendChild(fragment);\r\n }\r\n\r\n private createItem(index: number): HTMLElement {\r\n const div = document.createElement('div');\r\n div.className = this.classNames.item;\r\n\r\n const contentOption = this.options.itemContent;\r\n let content: HTMLElement | string;\r\n\r\n if (typeof contentOption === 'function') {\r\n content = contentOption(index);\r\n } else if (contentOption instanceof HTMLElement || typeof contentOption === 'string') {\r\n content = contentOption;\r\n } else {\r\n content = `Item ${index + 1}`;\r\n }\r\n\r\n if (typeof content === 'string') {\r\n div.textContent = content;\r\n } else {\r\n div.appendChild(content);\r\n }\r\n\r\n // Assigning height dynamically for layout simulation (no styles applied)\r\n const height = 120 + Math.floor(Math.random() * 100);\r\n div.style.height = `${height}px`;\r\n\r\n return div;\r\n }\r\n\r\n public calculateLayout() {\r\n const { gutter, minColWidth } = this.options;\r\n const containerWidth = this.container.clientWidth;\r\n\r\n this.columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\r\n const colWidth = (containerWidth - (this.columns - 1) * gutter) / this.columns;\r\n\r\n this.lastPositions = [...this.positions];\r\n this.columnHeights = new Array(this.columns).fill(0);\r\n this.positions = [];\r\n\r\n this.items.forEach((item, i) => {\r\n const height = item.offsetHeight;\r\n\r\n let minCol = 0;\r\n for (let c = 1; c < this.columns; c++) {\r\n if (this.columnHeights[c] < this.columnHeights[minCol]) {\r\n minCol = c;\r\n }\r\n }\r\n\r\n const x = minCol * (colWidth + gutter);\r\n const y = this.columnHeights[minCol];\r\n\r\n this.positions[i] = { x, y, width: colWidth, height };\r\n this.columnHeights[minCol] += height + gutter;\r\n });\r\n\r\n const maxHeight = Math.max(...this.columnHeights);\r\n this.container.style.height = `${maxHeight}px`;\r\n }\r\n\r\n applyLayout(animate: boolean = false) {\r\n const duration = this.options.transitionDuration;\r\n\r\n this.items.forEach((item, i) => {\r\n const pos = this.positions[i] || { x: 0, y: 0, width: 0 };\r\n const lastPos = this.lastPositions[i] || { x: 0, y: 0 };\r\n\r\n item.style.width = `${pos.width}px`;\r\n\r\n if (animate) {\r\n const dx = lastPos.x - pos.x;\r\n const dy = lastPos.y - pos.y;\r\n\r\n item.style.transition = 'none';\r\n item.style.transform = `translate3d(${pos.x + dx}px, ${pos.y + dy}px, 0)`;\r\n void item.offsetHeight;\r\n\r\n item.style.transition = `transform ${duration}ms ease`;\r\n item.style.transform = `translate3d(${pos.x}px, ${pos.y}px, 0)`;\r\n } else {\r\n item.style.transition = 'none';\r\n item.style.transform = `translate3d(${pos.x}px, ${pos.y}px, 0)`;\r\n }\r\n });\r\n }\r\n\r\n private handleResize() {\r\n if (this.resizeRaf) cancelAnimationFrame(this.resizeRaf);\r\n this.resizeRaf = requestAnimationFrame(() => {\r\n this.calculateLayout();\r\n this.applyLayout(true);\r\n });\r\n }\r\n\r\n public shuffleItems() {\r\n for (let i = this.items.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1));\r\n [this.items[i], this.items[j]] = [this.items[j], this.items[i]];\r\n }\r\n\r\n const fragment = document.createDocumentFragment();\r\n this.items.forEach((item) => fragment.appendChild(item));\r\n this.container.appendChild(fragment);\r\n\r\n this.calculateLayout();\r\n this.applyLayout(true);\r\n }\r\n\r\n public addItems(count: number) {\r\n const newCount = this.items.length + count;\r\n this.generateItems(newCount);\r\n this.calculateLayout();\r\n this.applyLayout(true);\r\n }\r\n\r\n public destroy(): void {\r\n if (this.resizeObserver) {\r\n this.resizeObserver.disconnect();\r\n this.resizeObserver = null;\r\n }\r\n\r\n window.removeEventListener('resize', this.boundResizeHandler);\r\n\r\n if (this.resizeRaf) {\r\n cancelAnimationFrame(this.resizeRaf);\r\n this.resizeRaf = null;\r\n }\r\n\r\n this.container.innerHTML = '';\r\n this.container.removeAttribute('style');\r\n this.container.classList.remove(this.classNames.container);\r\n\r\n this.items = [];\r\n this.positions = [];\r\n this.columnHeights = [];\r\n this.columns = 0;\r\n this.lastPositions = [];\r\n }\r\n}","import './masonry-snap-grid-layout.css';\r\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\r\nimport {MasonrySnapGridLayoutOptions} from './types';\r\n\r\nconst container = document.getElementById('masonry');\r\nif (container) {\r\n const masonry = new MasonrySnapGridLayout(container, {\r\n gutter: 20,\r\n minColWidth: 200,\r\n animate: true,\r\n initialItems: 40,\r\n\r\n // Custom item content example\r\n itemContent: (index) => {\r\n const div = document.createElement('div');\r\n div.textContent = `Custom Item ${index + 1}`;\r\n div.style.color = '#fff';\r\n div.style.fontWeight = 'bold';\r\n div.style.textAlign = 'center';\r\n div.style.padding = '1rem';\r\n return div;\r\n },\r\n\r\n classNames: {\r\n container: 'masonry-snap-grid-layout-container',\r\n item: 'masonry-snap-grid-layout-item',\r\n },\r\n });\r\n\r\n // Example to update count later\r\n masonry.addItems(5);\r\n\r\n // Example to shuffle items\r\n masonry.shuffleItems();\r\n}\r\n\r\nexport default MasonrySnapGridLayout;\r\nexport { MasonrySnapGridLayout, MasonrySnapGridLayoutOptions };"],"mappings":"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","names":["container"]}
1
+ {"version":3,"sources":["../../src/MasonrySnapGridLayout.ts","../../src/index.ts"],"sourcesContent":["import { MasonrySnapGridLayoutOptions } from './types';\r\n\r\nexport default class MasonrySnapGridLayout<T = any> {\r\n private readonly container: HTMLElement;\r\n private readonly options: Required<MasonrySnapGridLayoutOptions<T>>;\r\n private items: HTMLElement[] = [];\r\n private columnHeights: number[] = [];\r\n private resizeObserver: ResizeObserver | undefined;\r\n private rafId: number | null = null;\r\n\r\n constructor(container: HTMLElement, options: MasonrySnapGridLayoutOptions<T>) {\r\n this.container = container;\r\n this.options = {\r\n gutter: 16,\r\n minColWidth: 250,\r\n animate: true,\r\n transitionDuration: 400,\r\n classNames: {\r\n container: 'masonry-snap-grid-container',\r\n item: 'masonry-snap-grid-item',\r\n },\r\n ...options,\r\n };\r\n\r\n // Apply container class\r\n this.container.classList.add(this.options.classNames.container || \"\");\r\n\r\n // Initialize\r\n this.renderItems();\r\n this.setupResizeObserver();\r\n }\r\n\r\n private renderItems() {\r\n // Clear existing items\r\n this.items.forEach(item => item.remove());\r\n this.items = [];\r\n\r\n // Create fragment for batch DOM insertion\r\n const fragment = document.createDocumentFragment();\r\n\r\n // Create and append items\r\n this.options.items.forEach(itemData => {\r\n const itemElement = this.options.renderItem(itemData);\r\n itemElement.classList.add(this.options.classNames.item|| \"\");\r\n fragment.appendChild(itemElement);\r\n this.items.push(itemElement);\r\n });\r\n\r\n this.container.appendChild(fragment);\r\n this.updateLayout();\r\n }\r\n\r\n private setupResizeObserver() {\r\n this.resizeObserver = new ResizeObserver(() => {\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.rafId = requestAnimationFrame(() => this.updateLayout());\r\n });\r\n this.resizeObserver.observe(this.container);\r\n }\r\n\r\n private updateLayout() {\r\n const { gutter, minColWidth, animate, transitionDuration } = this.options;\r\n const containerWidth = this.container.clientWidth;\r\n\r\n // Calculate columns\r\n const columns = Math.max(1, Math.floor((containerWidth + gutter) / (minColWidth + gutter)));\r\n const colWidth = (containerWidth - (columns - 1) * gutter) / columns;\r\n\r\n // Reset column heights\r\n this.columnHeights = new Array(columns).fill(0);\r\n\r\n // Position items\r\n this.items.forEach((item) => {\r\n const height = item.offsetHeight;\r\n const minCol = this.findShortestColumn();\r\n const x = minCol * (colWidth + gutter);\r\n const y = this.columnHeights[minCol];\r\n\r\n // Apply position and size\r\n item.style.width = `${colWidth}px`;\r\n item.style.transform = `translate3d(${x}px, ${y}px, 0)`;\r\n item.style.transition = animate\r\n ? `transform ${transitionDuration}ms ease`\r\n : 'none';\r\n\r\n // Update column height\r\n this.columnHeights[minCol] += height + gutter;\r\n });\r\n\r\n // Set container height\r\n const maxHeight = Math.max(...this.columnHeights);\r\n this.container.style.height = `${maxHeight}px`;\r\n }\r\n\r\n private findShortestColumn(): number {\r\n return this.columnHeights.indexOf(Math.min(...this.columnHeights));\r\n }\r\n\r\n public updateItems(newItems: T[]) {\r\n this.options.items = newItems;\r\n this.renderItems();\r\n }\r\n\r\n public destroy() {\r\n this.resizeObserver?.disconnect();\r\n if (this.rafId) cancelAnimationFrame(this.rafId);\r\n this.container.innerHTML = '';\r\n this.container.removeAttribute('style');\r\n this.container.classList.remove(this.options.classNames.container || \"\");\r\n }\r\n}","import './index.css';\r\nimport MasonrySnapGridLayout from './MasonrySnapGridLayout';\r\nimport {MasonrySnapGridLayoutOptions} from './types';\r\n\r\nexport default MasonrySnapGridLayout;\r\nexport { MasonrySnapGridLayout, MasonrySnapGridLayoutOptions };"],"mappings":";AAEA,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;;;AC1GA,IAAO,gBAAQ;","names":[]}