react-instagram-stories 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,71 +5,165 @@ A high-performance, fully customizable Instagram-style Stories component for Rea
5
5
  [![NPM Version](https://img.shields.io/npm/v/react-instagram-stories.svg)](https://www.npmjs.com/package/react-instagram-stories)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
- ## Features
9
-
10
- - 🎬 **Multiple Content Types**: Images, videos (with audio), text, and fully custom components
11
- - 🎨 **Fully Customizable**: Style every aspect of the stories
12
- - **High Performance**: Optimized rendering with intelligent preloading
13
- - 📱 **Touch & Gestures**: Tap, swipe, and hold interactions
14
- - ⌨️ **Keyboard Navigation**: Full keyboard support for accessibility
15
- - 🎯 **TypeScript**: Complete type definitions included
16
- - **Accessible**: ARIA labels and keyboard navigation
17
- - 📦 **Lightweight**: Only **74.8 KB** with zero runtime dependencies
18
- - 🔄 **Auto Progress**: Smart progress bar that pauses during video buffering
19
- - 🎭 **Smooth Transitions**: Beautiful animations between stories and users
20
- - 🔌 **React Router Integration**: Built-in URL-based navigation support
21
-
22
- ## 📦 Installation
8
+ ## Features
9
+
10
+ - **Multiple Content Types**: Images, videos (with audio), text, and fully custom components
11
+ - **Fully Customizable**: Style every aspect of the stories
12
+ - **High Performance**: Optimized rendering with intelligent preloading
13
+ - **Touch & Gestures**: Tap, swipe, and hold interactions
14
+ - **Keyboard Navigation**: Full keyboard support for accessibility
15
+ - **TypeScript**: Complete type definitions included
16
+ - **Accessible**: ARIA labels and keyboard navigation
17
+ - **Lightweight**: ~30 KB with zero runtime dependencies
18
+ - **No Router Required**: Works with native browser history API
19
+ - **URL Navigation**: Built-in query parameter support (`?user=userId&story=storyId`)
20
+ - **Auto Progress**: Smart progress bar that pauses during video buffering
21
+ - **Smooth Transitions**: Beautiful animations between stories and users
22
+
23
+ ## Installation
23
24
 
24
25
  ```bash
25
- npm install react-instagram-stories react-router-dom
26
+ npm install react-instagram-stories
26
27
  # or
27
- yarn add react-instagram-stories react-router-dom
28
+ yarn add react-instagram-stories
28
29
  # or
29
- pnpm add react-instagram-stories react-router-dom
30
+ pnpm add react-instagram-stories
30
31
  ```
31
32
 
32
- **Note**: `react-router-dom` is required for URL-based story navigation.
33
+ **Note**: No additional dependencies required! Works without react-router-dom.
33
34
 
34
- ## 🚀 Quick Start
35
+ ## Quick Start
36
+
37
+ ### Simple Usage (Recommended)
35
38
 
36
39
  ```tsx
37
- import { BrowserRouter, Routes, Route } from 'react-router-dom';
38
40
  import { Stories, demoUsers } from 'react-instagram-stories';
39
41
  import 'react-instagram-stories/styles.css';
40
42
 
41
43
  function App() {
44
+ return <Stories users={demoUsers} />;
45
+ }
46
+
47
+ export default App;
48
+ ```
49
+
50
+ That's it! Click on any avatar to open the story viewer. The URL automatically updates to `?user=userId&story=storyId` format.
51
+
52
+ ### Using Separate Components
53
+
54
+ ```tsx
55
+ import { AvatarList, StoryViewer, demoUsers, navigateWithParams } from 'react-instagram-stories';
56
+ import 'react-instagram-stories/styles.css';
57
+
58
+ function App() {
59
+ const handleAvatarClick = (userIndex: number) => {
60
+ const user = demoUsers[userIndex];
61
+ // Navigate using user ID and story ID
62
+ navigateWithParams({ user: user.id, story: user.stories[0].id });
63
+ };
64
+
42
65
  return (
43
- <BrowserRouter>
44
- <Routes>
45
- <Route path="/" element={<Stories users={demoUsers} />} />
46
- <Route path="/story/:storyId" element={<Stories users={demoUsers} />} />
47
- </Routes>
48
- </BrowserRouter>
66
+ <div>
67
+ <h1>My App</h1>
68
+ <AvatarList users={demoUsers} onAvatarClick={handleAvatarClick} />
69
+ <StoryViewer users={demoUsers} />
70
+ </div>
49
71
  );
50
72
  }
73
+ ```
51
74
 
52
- export default App;
75
+ ## URL Navigation
76
+
77
+ The StoryViewer supports URL-based navigation using query parameters with **user ID** and **story ID**:
78
+
79
+ | URL | Result |
80
+ |-----|--------|
81
+ | `?user=user-travel&story=travel-1` | Opens Travel user's first story |
82
+ | `?user=user-polls&story=poll-1` | Opens Interactive user's poll story |
83
+ | `?user=user-launch&story=launch-2` | Opens Events user's second story |
84
+ | No query params | Viewer stays closed |
85
+
86
+ ### Navigation Helpers
87
+
88
+ ```tsx
89
+ import { navigateWithParams, clearQueryParams } from 'react-instagram-stories';
90
+
91
+ // Open story viewer with user ID and story ID
92
+ navigateWithParams({ user: 'user-travel', story: 'travel-1' });
93
+
94
+ // Close story viewer (clear params)
95
+ clearQueryParams();
53
96
  ```
54
97
 
55
- ## 📖 API Reference
98
+ ## API Reference
56
99
 
57
100
  ### `<Stories />` Component
58
101
 
59
- The main component for displaying stories with avatar list and viewer.
102
+ The all-in-one component with avatar list and story viewer.
103
+
104
+ ```tsx
105
+ import { Stories } from 'react-instagram-stories';
60
106
 
61
- #### Props
107
+ <Stories users={myUsers} />
108
+ ```
62
109
 
63
110
  | Prop | Type | Default | Description |
64
111
  |------|------|---------|-------------|
65
112
  | `users` | `User[]` | **required** | Array of user objects with their stories |
66
- | `closeNavigateTo` | `string` | `'/'` | Navigation path when stories viewer is closed |
67
113
 
68
- ### Story Types
114
+ ### `<StoryViewer />` Component
69
115
 
70
- The component supports **4 core story types**:
116
+ The story viewer component. Supports two modes:
117
+
118
+ #### Query Param Mode (Default)
119
+ When `isOpen` is not provided, reads from URL query params:
120
+
121
+ ```tsx
122
+ <StoryViewer users={myUsers} />
123
+ ```
71
124
 
72
- #### 1. Image Story
125
+ #### Controlled Mode
126
+ When `isOpen` is provided, you control the viewer state:
127
+
128
+ ```tsx
129
+ <StoryViewer
130
+ users={myUsers}
131
+ isOpen={true}
132
+ initialUserIndex={0}
133
+ initialStoryIndex={0}
134
+ onClose={() => console.log('closed')}
135
+ onStoryChange={(userIndex, storyIndex) => console.log(userIndex, storyIndex)}
136
+ />
137
+ ```
138
+
139
+ | Prop | Type | Default | Description |
140
+ |------|------|---------|-------------|
141
+ | `users` | `User[]` | **required** | Array of user objects |
142
+ | `isOpen` | `boolean` | - | Controls viewer visibility (enables controlled mode) |
143
+ | `initialUserIndex` | `number` | `0` | Starting user index |
144
+ | `initialStoryIndex` | `number` | `0` | Starting story index |
145
+ | `onClose` | `() => void` | - | Called when viewer closes |
146
+ | `onStoryChange` | `(userIndex, storyIndex) => void` | - | Called when story changes |
147
+
148
+ ### `<AvatarList />` Component
149
+
150
+ The horizontal scrollable avatar list.
151
+
152
+ ```tsx
153
+ <AvatarList
154
+ users={myUsers}
155
+ onAvatarClick={(userIndex) => console.log(userIndex)}
156
+ />
157
+ ```
158
+
159
+ | Prop | Type | Description |
160
+ |------|------|-------------|
161
+ | `users` | `User[]` | Array of user objects |
162
+ | `onAvatarClick` | `(userIndex: number) => void` | Called when avatar is clicked |
163
+
164
+ ## Story Types
165
+
166
+ ### 1. Image Story
73
167
 
74
168
  ```tsx
75
169
  {
@@ -81,7 +175,7 @@ The component supports **4 core story types**:
81
175
  }
82
176
  ```
83
177
 
84
- #### 2. Video Story
178
+ ### 2. Video Story
85
179
 
86
180
  ```tsx
87
181
  {
@@ -93,11 +187,11 @@ The component supports **4 core story types**:
93
187
  ```
94
188
 
95
189
  **Features:**
96
- - Audio enabled by default
97
- - Progress bar pauses during buffering
98
- - Auto-detects video duration
190
+ - Audio enabled by default
191
+ - Progress bar pauses during buffering
192
+ - Auto-detects video duration
99
193
 
100
- #### 3. Text Story
194
+ ### 3. Text Story
101
195
 
102
196
  ```tsx
103
197
  {
@@ -110,9 +204,9 @@ The component supports **4 core story types**:
110
204
  }
111
205
  ```
112
206
 
113
- #### 4. Custom Component Story
207
+ ### 4. Custom Component Story
114
208
 
115
- The most powerful feature - add ANY custom React component as a story!
209
+ Add ANY custom React component as a story!
116
210
 
117
211
  ```tsx
118
212
  const MyCustomStory: React.FC<StoryItemControls> = ({
@@ -146,11 +240,11 @@ const MyCustomStory: React.FC<StoryItemControls> = ({
146
240
  - `prev()` - Go to previous story
147
241
  - `setDuration(ms: number)` - Update story duration dynamically
148
242
 
149
- ## 💡 Custom Component Examples
243
+ ## Custom Component Examples
150
244
 
151
245
  Build interactive experiences! Here are examples included in `demoUsers`:
152
246
 
153
- ### 📊 Poll Component
247
+ ### Poll Component
154
248
 
155
249
  ```tsx
156
250
  const PollComponent: React.FC<StoryItemControls> = ({ pause, resume, next }) => {
@@ -215,191 +309,11 @@ const PollComponent: React.FC<StoryItemControls> = ({ pause, resume, next }) =>
215
309
  </div>
216
310
  );
217
311
  };
218
-
219
- // Use it in your stories:
220
- {
221
- id: 'poll-1',
222
- type: 'custom_component',
223
- component: PollComponent,
224
- duration: 15000, // Extended duration for interaction
225
- }
226
312
  ```
227
313
 
228
- ### 🧠 Quiz Component
229
-
230
- ```tsx
231
- const QuizComponent: React.FC<StoryItemControls> = ({ pause, resume, next }) => {
232
- const [selected, setSelected] = React.useState<number | null>(null);
233
- const correctAnswer = 2; // Jupiter
234
- const options = ['Mars', 'Saturn', 'Jupiter', 'Neptune'];
314
+ **Tip**: All these examples are included in `demoUsers`! Import and use them to see how they work.
235
315
 
236
- React.useEffect(() => {
237
- pause();
238
- return () => resume();
239
- }, [pause, resume]);
240
-
241
- const handleAnswer = (index: number) => {
242
- setSelected(index);
243
- setTimeout(() => {
244
- resume();
245
- next();
246
- }, 2500);
247
- };
248
-
249
- return (
250
- <div style={{ /* styles */ }}>
251
- <h2>Which planet is the largest in our solar system?</h2>
252
- {options.map((option, index) => (
253
- <button
254
- key={index}
255
- onClick={() => handleAnswer(index)}
256
- disabled={selected !== null}
257
- style={{
258
- background: selected === index
259
- ? (index === correctAnswer ? '#4CAF50' : '#f44336')
260
- : 'rgba(255,255,255,0.2)'
261
- }}
262
- >
263
- {option}
264
- {selected !== null && index === correctAnswer && ' ✓'}
265
- </button>
266
- ))}
267
- {selected !== null && (
268
- <p style={{ marginTop: '20px', fontWeight: 'bold' }}>
269
- {selected === correctAnswer ? '🎉 Correct!' : '❌ Wrong! Jupiter is the largest.'}
270
- </p>
271
- )}
272
- </div>
273
- );
274
- };
275
- ```
276
-
277
- ### ⏱️ Countdown Component
278
-
279
- ```tsx
280
- const CountdownComponent: React.FC<StoryItemControls> = () => {
281
- const [timeLeft, setTimeLeft] = React.useState({
282
- days: 12,
283
- hours: 8,
284
- minutes: 45,
285
- seconds: 30,
286
- });
287
-
288
- React.useEffect(() => {
289
- const timer = setInterval(() => {
290
- setTimeLeft((prev) => {
291
- let { days, hours, minutes, seconds } = prev;
292
- seconds--;
293
- if (seconds < 0) {
294
- seconds = 59;
295
- minutes--;
296
- }
297
- if (minutes < 0) {
298
- minutes = 59;
299
- hours--;
300
- }
301
- if (hours < 0) {
302
- hours = 23;
303
- days--;
304
- }
305
- return { days, hours, minutes, seconds };
306
- });
307
- }, 1000);
308
-
309
- return () => clearInterval(timer);
310
- }, []);
311
-
312
- return (
313
- <div style={{
314
- display: 'flex',
315
- flexDirection: 'column',
316
- alignItems: 'center',
317
- justifyContent: 'center',
318
- height: '100%',
319
- background: 'linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)',
320
- padding: '20px'
321
- }}>
322
- <div style={{ fontSize: '48px', marginBottom: '15px' }}>🚀</div>
323
- <h2 style={{ color: 'white', fontSize: '24px' }}>Product Launch</h2>
324
- <p style={{ color: 'rgba(255,255,255,0.7)', marginBottom: '30px' }}>
325
- Something amazing is coming...
326
- </p>
327
-
328
- <div style={{ display: 'flex', gap: '12px' }}>
329
- {Object.entries(timeLeft).map(([key, value]) => (
330
- <div key={key} style={{ textAlign: 'center' }}>
331
- <div style={{
332
- background: 'rgba(255,255,255,0.2)',
333
- borderRadius: '12px',
334
- padding: '15px 20px',
335
- minWidth: '70px'
336
- }}>
337
- <div style={{ fontSize: '32px', fontWeight: 'bold', color: 'white' }}>
338
- {String(value).padStart(2, '0')}
339
- </div>
340
- </div>
341
- <div style={{ color: 'rgba(255,255,255,0.8)', fontSize: '12px', marginTop: '8px' }}>
342
- {key.toUpperCase()}
343
- </div>
344
- </div>
345
- ))}
346
- </div>
347
- </div>
348
- );
349
- };
350
- ```
351
-
352
- ### 🎚️ Slider Component
353
-
354
- ```tsx
355
- const SliderComponent: React.FC<StoryItemControls> = ({ pause, resume }) => {
356
- const [value, setValue] = React.useState(50);
357
-
358
- React.useEffect(() => {
359
- pause();
360
- return () => resume();
361
- }, [pause, resume]);
362
-
363
- return (
364
- <div style={{
365
- display: 'flex',
366
- flexDirection: 'column',
367
- alignItems: 'center',
368
- justifyContent: 'center',
369
- height: '100%',
370
- background: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
371
- padding: '40px'
372
- }}>
373
- <div style={{ fontSize: '48px', marginBottom: '20px' }}>🔥</div>
374
- <h2 style={{ color: 'white', fontSize: '24px', marginBottom: '10px' }}>
375
- How excited are you?
376
- </h2>
377
-
378
- <div style={{ fontSize: '64px', margin: '30px 0' }}>{value}</div>
379
-
380
- <input
381
- type="range"
382
- min="0"
383
- max="100"
384
- value={value}
385
- onChange={(e) => setValue(Number(e.target.value))}
386
- style={{
387
- width: '80%',
388
- height: '8px',
389
- borderRadius: '4px',
390
- appearance: 'none',
391
- background: 'rgba(255,255,255,0.3)',
392
- outline: 'none'
393
- }}
394
- />
395
- </div>
396
- );
397
- };
398
- ```
399
-
400
- **💡 Tip**: All these examples are included in `demoUsers`! Import and use them to see how they work.
401
-
402
- ## 🎨 Styling
316
+ ## Styling
403
317
 
404
318
  Import the default styles:
405
319
 
@@ -425,18 +339,18 @@ Override with custom CSS:
425
339
  }
426
340
 
427
341
  /* Style avatars */
428
- .avatar-list {
342
+ .story-avatar-list {
429
343
  padding: 20px;
430
344
  gap: 16px;
431
345
  }
432
346
 
433
- .avatar {
347
+ .story-avatar-image-wrapper {
434
348
  width: 80px;
435
349
  height: 80px;
436
350
  }
437
351
  ```
438
352
 
439
- ## 💡 Advanced Usage
353
+ ## Advanced Usage
440
354
 
441
355
  ### Using Demo Data
442
356
 
@@ -503,9 +417,9 @@ const myUsers: User[] = [
503
417
  ];
504
418
  ```
505
419
 
506
- ### Without React Router
420
+ ### Controlled Mode (Without URL)
507
421
 
508
- If you don't need URL navigation, use components directly:
422
+ If you don't want URL navigation, use controlled mode:
509
423
 
510
424
  ```tsx
511
425
  import { useState } from 'react';
@@ -534,20 +448,20 @@ function App() {
534
448
  }
535
449
  ```
536
450
 
537
- ## ⌨️ Keyboard Controls
451
+ ## Keyboard Controls
538
452
 
539
453
  - `←` `→` - Navigate stories
540
454
  - `Space` - Pause/Resume
541
455
  - `Esc` - Close viewer
542
456
 
543
- ## 🖱️ Mouse & Touch
457
+ ## Mouse & Touch
544
458
 
545
459
  - **Tap Left/Right** - Navigate stories
546
460
  - **Swipe Left/Right** - Change users
547
461
  - **Swipe Down** - Close
548
462
  - **Hold/Hover** - Pause
549
463
 
550
- ## 🎯 TypeScript Types
464
+ ## TypeScript Types
551
465
 
552
466
  ```tsx
553
467
  import type {
@@ -581,14 +495,20 @@ interface User {
581
495
  }
582
496
  ```
583
497
 
584
- ## 📦 Package Exports
498
+ ## Package Exports
585
499
 
586
500
  ```tsx
587
- // Main component
588
- export { Stories } from 'react-instagram-stories';
501
+ // Components
502
+ import { Stories, StoryViewer, AvatarList } from 'react-instagram-stories';
503
+
504
+ // Navigation helpers
505
+ import { navigateWithParams, clearQueryParams } from 'react-instagram-stories';
506
+
507
+ // Demo data
508
+ import { demoUsers, generateDemoUsers } from 'react-instagram-stories';
589
509
 
590
510
  // Types
591
- export type {
511
+ import type {
592
512
  User,
593
513
  StoryItem,
594
514
  StoryItemControls,
@@ -599,49 +519,40 @@ export type {
599
519
  CustomComponentStoryItem
600
520
  } from 'react-instagram-stories';
601
521
 
602
- // Utilities
603
- export { generateDemoUsers, demoUsers } from 'react-instagram-stories';
604
-
605
522
  // Styles
606
523
  import 'react-instagram-stories/styles.css';
607
524
  ```
608
525
 
609
- ## 🚀 Performance
526
+ ## Performance
610
527
 
611
- - **Bundle Size**: 74.8 KB (20 KB gzipped)
528
+ - **Bundle Size**: ~30 KB (minified)
529
+ - **Gzipped**: ~10 KB
612
530
  - **Zero Runtime Dependencies**
613
531
  - **Smart Preloading**: Preloads adjacent stories
614
532
  - **Optimized Rendering**: Uses React.memo
615
533
  - **Video Buffering Detection**: Pauses progress during buffering
616
534
 
617
- ## 📊 Package Info
618
-
619
- - **ESM**: 28.77 KB
620
- - **CJS**: 30.44 KB
621
- - **Gzipped**: ~20 KB
622
- - **Dependencies**: 0 (React is peer dep)
623
-
624
- ## 🛠️ Tech Stack
535
+ ## Tech Stack
625
536
 
626
537
  - React 18+
627
538
  - TypeScript
628
- - React Router DOM (peer dependency)
539
+ - Native Browser History API (no router needed)
629
540
  - tsup (bundler)
630
541
 
631
- ## 🤝 Contributing
542
+ ## Contributing
632
543
 
633
544
  Contributions welcome! Open an issue or PR.
634
545
 
635
- ## 📄 License
546
+ ## License
636
547
 
637
548
  MIT © [Ankit Jangir](https://github.com/ankit64jangir)
638
549
 
639
- ## 📞 Support
550
+ ## Support
640
551
 
641
- - 🐛 [Issues](https://github.com/ankit64jangir/react-instagram-stories/issues)
642
- - 💬 [Discussions](https://github.com/ankit64jangir/react-instagram-stories/discussions)
643
- - [Star](https://github.com/ankit64jangir/react-instagram-stories)
552
+ - [Issues](https://github.com/ankit64jangir/react-instagram-stories/issues)
553
+ - [Discussions](https://github.com/ankit64jangir/react-instagram-stories/discussions)
554
+ - [Star on GitHub](https://github.com/ankit64jangir/react-instagram-stories)
644
555
 
645
556
  ---
646
557
 
647
- Made with ❤️ by Ankit Jangir
558
+ Made with love by Ankit Jangir