react-instagram-stories 1.0.3 → 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 +170 -259
- package/dist/index.cjs +9 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -5
- package/dist/index.d.ts +24 -5
- package/dist/index.js +9 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -5,71 +5,165 @@ A high-performance, fully customizable Instagram-style Stories component for Rea
|
|
|
5
5
|
[](https://www.npmjs.com/package/react-instagram-stories)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
26
|
+
npm install react-instagram-stories
|
|
26
27
|
# or
|
|
27
|
-
yarn add react-instagram-stories
|
|
28
|
+
yarn add react-instagram-stories
|
|
28
29
|
# or
|
|
29
|
-
pnpm add react-instagram-stories
|
|
30
|
+
pnpm add react-instagram-stories
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
**Note**:
|
|
33
|
+
**Note**: No additional dependencies required! Works without react-router-dom.
|
|
33
34
|
|
|
34
|
-
##
|
|
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
|
-
<
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
98
|
+
## API Reference
|
|
56
99
|
|
|
57
100
|
### `<Stories />` Component
|
|
58
101
|
|
|
59
|
-
The
|
|
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
|
-
|
|
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
|
-
###
|
|
114
|
+
### `<StoryViewer />` Component
|
|
69
115
|
|
|
70
|
-
The
|
|
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
|
-
####
|
|
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
|
-
|
|
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
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
190
|
+
- Audio enabled by default
|
|
191
|
+
- Progress bar pauses during buffering
|
|
192
|
+
- Auto-detects video duration
|
|
99
193
|
|
|
100
|
-
|
|
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
|
-
|
|
207
|
+
### 4. Custom Component Story
|
|
114
208
|
|
|
115
|
-
|
|
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
|
-
##
|
|
243
|
+
## Custom Component Examples
|
|
150
244
|
|
|
151
245
|
Build interactive experiences! Here are examples included in `demoUsers`:
|
|
152
246
|
|
|
153
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
|
420
|
+
### Controlled Mode (Without URL)
|
|
507
421
|
|
|
508
|
-
If you don't
|
|
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
|
-
##
|
|
451
|
+
## Keyboard Controls
|
|
538
452
|
|
|
539
453
|
- `←` `→` - Navigate stories
|
|
540
454
|
- `Space` - Pause/Resume
|
|
541
455
|
- `Esc` - Close viewer
|
|
542
456
|
|
|
543
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
498
|
+
## Package Exports
|
|
585
499
|
|
|
586
500
|
```tsx
|
|
587
|
-
//
|
|
588
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
526
|
+
## Performance
|
|
610
527
|
|
|
611
|
-
- **Bundle Size**:
|
|
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
|
-
##
|
|
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
|
-
-
|
|
539
|
+
- Native Browser History API (no router needed)
|
|
629
540
|
- tsup (bundler)
|
|
630
541
|
|
|
631
|
-
##
|
|
542
|
+
## Contributing
|
|
632
543
|
|
|
633
544
|
Contributions welcome! Open an issue or PR.
|
|
634
545
|
|
|
635
|
-
##
|
|
546
|
+
## License
|
|
636
547
|
|
|
637
548
|
MIT © [Ankit Jangir](https://github.com/ankit64jangir)
|
|
638
549
|
|
|
639
|
-
##
|
|
550
|
+
## Support
|
|
640
551
|
|
|
641
|
-
-
|
|
642
|
-
-
|
|
643
|
-
-
|
|
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
|
|
558
|
+
Made with love by Ankit Jangir
|