social-masonry 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,394 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/tkana-dev/social-masonry/main/assets/logo.svg" alt="Social Masonry" width="120" />
3
+ <h1>Social Masonry</h1>
4
+ <p><strong>Beautiful masonry layout for X (Twitter) and Instagram embeds</strong></p>
5
+
6
+ [![npm version](https://img.shields.io/npm/v/social-masonry.svg)](https://www.npmjs.com/package/social-masonry)
7
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/social-masonry)](https://bundlephobia.com/package/social-masonry)
8
+ [![license](https://img.shields.io/npm/l/social-masonry.svg)](https://github.com/tkana-dev/social-masonry/blob/main/LICENSE)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
10
+
11
+ <a href="https://social-masonry.dev">Demo</a> ยท <a href="#installation">Installation</a> ยท <a href="#usage">Usage</a> ยท <a href="#api">API</a>
12
+ </div>
13
+
14
+ ---
15
+
16
+ <p align="center">
17
+ <img src="https://raw.githubusercontent.com/tkana-dev/social-masonry/main/assets/demo.gif" alt="Demo" width="100%" />
18
+ </p>
19
+
20
+ ## โœจ Features
21
+
22
+ - ๐ŸŽจ **Beautiful Cards** - Native-looking X and Instagram post cards with 5 design variants
23
+ - โšก **High Performance** - Virtual scrolling for smooth rendering of thousands of posts
24
+ - ๐Ÿ“ฑ **Responsive** - Adaptive column layouts that look great on any screen size
25
+ - ๐ŸŽญ **Themeable** - Light, dark, and auto themes with full customization
26
+ - ๐Ÿ”„ **Infinite Scroll** - Built-in load more functionality
27
+ - ๐ŸŽฏ **TypeScript** - Full type safety and excellent DX
28
+ - โš›๏ธ **React Ready** - First-class React component with hooks
29
+ - ๐Ÿชถ **Lightweight** - ~8KB gzipped with zero dependencies
30
+
31
+ ## ๐Ÿ“ฆ Installation
32
+
33
+ ```bash
34
+ # npm
35
+ npm install social-masonry
36
+
37
+ # yarn
38
+ yarn add social-masonry
39
+
40
+ # pnpm
41
+ pnpm add social-masonry
42
+ ```
43
+
44
+ ## ๐Ÿš€ Quick Start
45
+
46
+ ### Vanilla JavaScript
47
+
48
+ ```javascript
49
+ import { createSocialMasonry } from 'social-masonry';
50
+ import 'social-masonry/styles';
51
+
52
+ const masonry = createSocialMasonry({
53
+ container: '#posts',
54
+ posts: [
55
+ {
56
+ platform: 'twitter',
57
+ id: '1',
58
+ url: 'https://twitter.com/user/status/123',
59
+ author: {
60
+ username: 'johndoe',
61
+ displayName: 'John Doe',
62
+ avatarUrl: 'https://...',
63
+ verified: true,
64
+ },
65
+ content: {
66
+ text: 'Hello, world! ๐ŸŒ',
67
+ },
68
+ metrics: {
69
+ likes: 1234,
70
+ retweets: 567,
71
+ replies: 89,
72
+ },
73
+ createdAt: '2024-01-15T10:30:00Z',
74
+ },
75
+ // ... more posts
76
+ ],
77
+ });
78
+
79
+ // Add more posts
80
+ masonry.addPosts(newPosts);
81
+
82
+ // Clean up
83
+ masonry.destroy();
84
+ ```
85
+
86
+ ### React
87
+
88
+ ```tsx
89
+ import { SocialMasonry } from 'social-masonry/react';
90
+ import 'social-masonry/styles';
91
+
92
+ function App() {
93
+ const posts = usePosts();
94
+
95
+ return (
96
+ <SocialMasonry
97
+ posts={posts}
98
+ columns={[
99
+ { columns: 4, minWidth: 1200 },
100
+ { columns: 3, minWidth: 900 },
101
+ { columns: 2, minWidth: 600 },
102
+ { columns: 1, minWidth: 0 },
103
+ ]}
104
+ gap={16}
105
+ variant="elevated"
106
+ theme="auto"
107
+ onPostClick={(post) => window.open(post.url)}
108
+ />
109
+ );
110
+ }
111
+ ```
112
+
113
+ ## ๐Ÿ“– Usage
114
+
115
+ ### Post Types
116
+
117
+ #### Twitter/X Post
118
+
119
+ ```typescript
120
+ const twitterPost: TwitterPost = {
121
+ platform: 'twitter',
122
+ id: 'unique-id',
123
+ url: 'https://twitter.com/user/status/123',
124
+ author: {
125
+ username: 'johndoe',
126
+ displayName: 'John Doe',
127
+ avatarUrl: 'https://example.com/avatar.jpg',
128
+ verified: true,
129
+ },
130
+ content: {
131
+ text: 'This is my tweet! #awesome',
132
+ html: 'This is my tweet! <a href="#">#awesome</a>', // Optional: pre-rendered HTML
133
+ },
134
+ media: [
135
+ {
136
+ type: 'image',
137
+ url: 'https://example.com/image.jpg',
138
+ aspectRatio: 16 / 9,
139
+ },
140
+ ],
141
+ metrics: {
142
+ likes: 1234,
143
+ retweets: 567,
144
+ replies: 89,
145
+ views: 50000,
146
+ },
147
+ quotedPost: { /* nested TwitterPost */ }, // Optional
148
+ createdAt: '2024-01-15T10:30:00Z',
149
+ };
150
+ ```
151
+
152
+ #### Instagram Post
153
+
154
+ ```typescript
155
+ const instagramPost: InstagramPost = {
156
+ platform: 'instagram',
157
+ id: 'unique-id',
158
+ url: 'https://instagram.com/p/ABC123',
159
+ author: {
160
+ username: 'janedoe',
161
+ displayName: 'Jane Doe',
162
+ avatarUrl: 'https://example.com/avatar.jpg',
163
+ verified: false,
164
+ },
165
+ content: {
166
+ caption: 'Beautiful sunset ๐ŸŒ… #photography',
167
+ },
168
+ media: {
169
+ type: 'image', // 'image' | 'video' | 'carousel'
170
+ url: 'https://example.com/image.jpg',
171
+ aspectRatio: 1, // Square
172
+ carouselItems: [ /* for carousel type */ ],
173
+ },
174
+ metrics: {
175
+ likes: 5678,
176
+ comments: 123,
177
+ },
178
+ createdAt: '2024-01-15T10:30:00Z',
179
+ };
180
+ ```
181
+
182
+ ### Configuration Options
183
+
184
+ ```typescript
185
+ const masonry = createSocialMasonry({
186
+ // Required
187
+ container: '#posts', // Element or selector
188
+ posts: [], // Array of SocialPost
189
+
190
+ // Layout
191
+ gap: 16, // Gap between cards (px)
192
+ columns: [ // Responsive breakpoints
193
+ { columns: 4, minWidth: 1200 },
194
+ { columns: 3, minWidth: 900 },
195
+ { columns: 2, minWidth: 600 },
196
+ { columns: 1, minWidth: 0 },
197
+ ],
198
+ padding: 0, // Container padding
199
+
200
+ // Animation
201
+ animate: true,
202
+ animationDuration: 300,
203
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
204
+
205
+ // Card Styling
206
+ variant: 'default', // 'default' | 'minimal' | 'elevated' | 'bordered' | 'glass'
207
+ theme: 'auto', // 'light' | 'dark' | 'auto'
208
+ borderRadius: 12,
209
+ hoverEffect: true,
210
+
211
+ // Content
212
+ showPlatformIcon: true,
213
+ showAuthor: true,
214
+ showMetrics: true,
215
+ showTimestamp: true,
216
+
217
+ // Custom Formatters
218
+ formatDate: (date) => formatRelativeTime(date),
219
+ formatNumber: (num) => formatNumber(num),
220
+
221
+ // Image Loading
222
+ imageLoading: 'lazy', // 'lazy' | 'eager'
223
+ fallbackImage: 'https://...', // Fallback for broken images
224
+
225
+ // Virtualization (for large lists)
226
+ virtualization: {
227
+ enabled: false,
228
+ overscan: 3,
229
+ estimatedItemHeight: 400,
230
+ scrollContainer: null, // Default: window
231
+ },
232
+
233
+ // Infinite Scroll
234
+ loadMoreThreshold: 500,
235
+ showLoading: true,
236
+ loadingElement: '<div>Loading...</div>',
237
+ emptyMessage: 'No posts to display',
238
+
239
+ // Events
240
+ onPostClick: (post, event) => {},
241
+ onAuthorClick: (post, event) => {},
242
+ onMediaClick: (post, mediaIndex, event) => {},
243
+ onLayoutComplete: (positions) => {},
244
+ onLoadMore: async () => {},
245
+ onImageError: (post, error) => {},
246
+ });
247
+ ```
248
+
249
+ ### Card Variants
250
+
251
+ | Variant | Description |
252
+ |---------|-------------|
253
+ | `default` | Clean card with subtle border and shadow |
254
+ | `minimal` | No background, perfect for embedding |
255
+ | `elevated` | Floating card with prominent shadow |
256
+ | `bordered` | Strong border, no shadow |
257
+ | `glass` | Glassmorphism effect with blur |
258
+
259
+ ### API Methods
260
+
261
+ ```typescript
262
+ // Add posts to the end
263
+ masonry.addPosts(newPosts);
264
+
265
+ // Replace all posts
266
+ masonry.setPosts(posts);
267
+
268
+ // Remove a post
269
+ masonry.removePost(postId);
270
+
271
+ // Update options
272
+ masonry.setOptions({ theme: 'dark' });
273
+
274
+ // Get current state
275
+ const state = masonry.getLayoutState();
276
+ const posts = masonry.getPosts();
277
+
278
+ // Scroll to a post
279
+ masonry.scrollToPost(postId, 'smooth');
280
+
281
+ // Recalculate layout
282
+ masonry.refresh();
283
+
284
+ // Clean up
285
+ masonry.destroy();
286
+ ```
287
+
288
+ ### React Hooks
289
+
290
+ ```tsx
291
+ import { useRef } from 'react';
292
+ import { SocialMasonry, SocialMasonryRef } from 'social-masonry/react';
293
+
294
+ function App() {
295
+ const masonryRef = useRef<SocialMasonryRef>(null);
296
+
297
+ const handleAddPost = () => {
298
+ masonryRef.current?.addPosts([newPost]);
299
+ };
300
+
301
+ return (
302
+ <SocialMasonry
303
+ ref={masonryRef}
304
+ posts={posts}
305
+ // ...
306
+ />
307
+ );
308
+ }
309
+ ```
310
+
311
+ ## ๐ŸŽจ Customization
312
+
313
+ ### CSS Variables
314
+
315
+ Override the default theme using CSS variables:
316
+
317
+ ```css
318
+ :root {
319
+ /* Colors */
320
+ --sm-bg: #ffffff;
321
+ --sm-bg-hover: #f7f9fa;
322
+ --sm-text: #0f1419;
323
+ --sm-text-secondary: #536471;
324
+ --sm-text-muted: #8b98a5;
325
+ --sm-border: #eff3f4;
326
+ --sm-link: #1d9bf0;
327
+
328
+ /* Brand Colors */
329
+ --sm-twitter-primary: #1d9bf0;
330
+ --sm-instagram-primary: #e1306c;
331
+
332
+ /* Shadows */
333
+ --sm-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
334
+ --sm-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
335
+ --sm-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
336
+
337
+ /* Transitions */
338
+ --sm-transition-fast: 150ms ease;
339
+ --sm-transition-base: 200ms ease;
340
+ }
341
+ ```
342
+
343
+ ### Custom Classes
344
+
345
+ Add custom classes to cards:
346
+
347
+ ```typescript
348
+ createSocialMasonry({
349
+ className: 'my-custom-card',
350
+ // ...
351
+ });
352
+ ```
353
+
354
+ ## ๐Ÿ“Š Performance
355
+
356
+ Social Masonry is optimized for performance:
357
+
358
+ - **Virtual Scrolling**: Only renders visible cards, enabling smooth scrolling with 10,000+ posts
359
+ - **Efficient Layout**: Uses a columnar algorithm with O(n) complexity
360
+ - **Smart Updates**: Batched DOM updates and position caching
361
+ - **Lazy Loading**: Images load only when cards enter the viewport
362
+
363
+ Enable virtualization for large datasets:
364
+
365
+ ```typescript
366
+ createSocialMasonry({
367
+ virtualization: {
368
+ enabled: true,
369
+ overscan: 3, // Extra items to render above/below viewport
370
+ estimatedItemHeight: 400,
371
+ },
372
+ // ...
373
+ });
374
+ ```
375
+
376
+ ## ๐ŸŒ Browser Support
377
+
378
+ | Browser | Version |
379
+ |---------|---------|
380
+ | Chrome | 80+ |
381
+ | Firefox | 75+ |
382
+ | Safari | 14+ |
383
+ | Edge | 80+ |
384
+
385
+ ## ๐Ÿ“„ License
386
+
387
+ MIT ยฉ [tkana_dev](https://github.com/tkana-dev)
388
+
389
+ ---
390
+
391
+ <div align="center">
392
+ <p>If you find this project useful, please consider giving it a โญ๏ธ</p>
393
+ <a href="https://github.com/tkana-dev/social-masonry">GitHub</a> ยท <a href="https://www.npmjs.com/package/social-masonry">npm</a> ยท <a href="https://social-masonry.dev">Demo</a>
394
+ </div>