flagmint-react-sdk 0.7.10 → 0.7.12
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 +609 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
# flagmint-react-sdk
|
|
2
|
+
|
|
3
|
+
A React wrapper for [flagmint-js-sdk](https://www.npmjs.com/package/flagmint-js-sdk) that provides React-specific hooks and context with fine-grained reactivity powered by Zustand.
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Fine-grained reactivity** - Only components using specific flags re-render when those flags change
|
|
8
|
+
- 🚀 **SSR-safe** - No global state leakage between server requests
|
|
9
|
+
- 📦 **TypeScript support** - Full type safety with generics for flag values and context
|
|
10
|
+
- 🔀 **Dual export strategy** - Separate server-safe types and client-only hooks
|
|
11
|
+
- ⚡ **Auto-initialization** - Direct integration with FlagClient from flagmint-js-sdk
|
|
12
|
+
- 🔐 **Deferred initialization** - Perfect for authentication flows
|
|
13
|
+
- 📱 **Framework agnostic** - Works with Next.js, Remix, Vite, and more
|
|
14
|
+
|
|
15
|
+
## 📦 Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install react-flagmint flagmint-js-sdk
|
|
19
|
+
# or
|
|
20
|
+
pnpm add react-flagmint flagmint-js-sdk
|
|
21
|
+
# or
|
|
22
|
+
yarn add react-flagmint flagmint-js-sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 🚀 Quick Start
|
|
26
|
+
|
|
27
|
+
### 1. Basic Setup
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
// app/providers.tsx (Next.js App Router)
|
|
31
|
+
'use client'
|
|
32
|
+
import { FlagmintProvider } from 'react-flagmint/client'
|
|
33
|
+
|
|
34
|
+
export default function Providers({ children }: { children: React.ReactNode }) {
|
|
35
|
+
return (
|
|
36
|
+
<FlagmintProvider
|
|
37
|
+
options={{
|
|
38
|
+
apiKey: process.env.NEXT_PUBLIC_FLAGMINT_API_KEY!,
|
|
39
|
+
transportMode: 'websocket',
|
|
40
|
+
context: {
|
|
41
|
+
userId: 'user-123',
|
|
42
|
+
plan: 'premium'
|
|
43
|
+
}
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</FlagmintProvider>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
// app/layout.tsx
|
|
54
|
+
import Providers from './providers'
|
|
55
|
+
|
|
56
|
+
export default function RootLayout({
|
|
57
|
+
children,
|
|
58
|
+
}: {
|
|
59
|
+
children: React.ReactNode
|
|
60
|
+
}) {
|
|
61
|
+
return (
|
|
62
|
+
<html>
|
|
63
|
+
<body>
|
|
64
|
+
<Providers>
|
|
65
|
+
{children}
|
|
66
|
+
</Providers>
|
|
67
|
+
</body>
|
|
68
|
+
</html>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Using Flags in Components
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// components/FeatureComponent.tsx
|
|
77
|
+
'use client'
|
|
78
|
+
import { useFlag, useFlags, useFlagmintReady } from 'react-flagmint/client'
|
|
79
|
+
|
|
80
|
+
export default function FeatureComponent() {
|
|
81
|
+
const showNewFeature = useFlag('new-dashboard', false)
|
|
82
|
+
const userPlan = useFlag('user-plan', 'free')
|
|
83
|
+
const isReady = useFlagmintReady()
|
|
84
|
+
|
|
85
|
+
if (!isReady) {
|
|
86
|
+
return <div>Loading flags...</div>
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div>
|
|
91
|
+
{showNewFeature && <NewDashboard />}
|
|
92
|
+
<div>Current plan: {userPlan}</div>
|
|
93
|
+
</div>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 📚 API Reference
|
|
99
|
+
|
|
100
|
+
### FlagmintProvider
|
|
101
|
+
|
|
102
|
+
The provider component that initializes the FlagClient and provides flag context to your app.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<FlagmintProvider
|
|
106
|
+
options={FlagClientOptions}
|
|
107
|
+
initialFlags={{}}
|
|
108
|
+
deferInitialization={false}
|
|
109
|
+
>
|
|
110
|
+
{children}
|
|
111
|
+
</FlagmintProvider>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### Props
|
|
115
|
+
|
|
116
|
+
| Prop | Type | Default | Description |
|
|
117
|
+
|------|------|---------|-------------|
|
|
118
|
+
| `options` | `FlagClientOptions` | Required | Configuration for the FlagClient |
|
|
119
|
+
| `initialFlags` | `Flags` | `{}` | Initial flag values for SSR/hydration |
|
|
120
|
+
| `deferInitialization` | `boolean` | `false` | If true, wait for manual initialization |
|
|
121
|
+
|
|
122
|
+
#### FlagClientOptions
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
interface FlagClientOptions<C extends Record<string, any> = Record<string, any>> {
|
|
126
|
+
apiKey: string
|
|
127
|
+
context?: C
|
|
128
|
+
transportMode?: 'auto' | 'websocket' | 'long-polling'
|
|
129
|
+
enableOfflineCache?: boolean
|
|
130
|
+
persistContext?: boolean
|
|
131
|
+
onError?: (error: Error) => void
|
|
132
|
+
previewMode?: boolean
|
|
133
|
+
rawFlags?: Record<string, FlagValue>
|
|
134
|
+
deferInitialization?: boolean
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Hooks
|
|
139
|
+
|
|
140
|
+
#### useFlag(key, fallback?)
|
|
141
|
+
|
|
142
|
+
Get a specific flag value with fine-grained reactivity.
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
const showFeature = useFlag('feature-name', false)
|
|
146
|
+
const userTier = useFlag('user-tier', 'free')
|
|
147
|
+
const config = useFlag('app-config', { theme: 'light' })
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Parameters:**
|
|
151
|
+
- `key: string` - The flag key
|
|
152
|
+
- `fallback?: T` - Default value if flag is not found
|
|
153
|
+
|
|
154
|
+
**Returns:** The flag value or fallback
|
|
155
|
+
|
|
156
|
+
#### useFlags()
|
|
157
|
+
|
|
158
|
+
Get all currently loaded flags.
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
const allFlags = useFlags()
|
|
162
|
+
console.log(allFlags) // { 'feature-a': true, 'user-tier': 'pro' }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Returns:** Object containing all loaded flags
|
|
166
|
+
|
|
167
|
+
#### useFlagmint()
|
|
168
|
+
|
|
169
|
+
Get access to the FlagClient instance and utilities.
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
const { client, isReady, isInitialized, updateContext } = useFlagmint()
|
|
173
|
+
|
|
174
|
+
// Update user context
|
|
175
|
+
await updateContext({ userId: 'new-user', plan: 'enterprise' })
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Returns:**
|
|
179
|
+
```tsx
|
|
180
|
+
{
|
|
181
|
+
client: FlagClient | null
|
|
182
|
+
isReady: boolean
|
|
183
|
+
isInitialized: boolean
|
|
184
|
+
updateContext: (context: Record<string, any>) => Promise<void>
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### useFlagmintReady()
|
|
189
|
+
|
|
190
|
+
Check if the FlagClient is ready to serve flags.
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
const isReady = useFlagmintReady()
|
|
194
|
+
|
|
195
|
+
if (!isReady) {
|
|
196
|
+
return <LoadingSpinner />
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### useFlagClient()
|
|
201
|
+
|
|
202
|
+
Get direct access to the FlagClient instance.
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
const client = useFlagClient<MyFlagTypes>()
|
|
206
|
+
const specificFlag = client?.getFlag('feature-x', false)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## 🔧 Usage Patterns
|
|
210
|
+
|
|
211
|
+
### 1. Auto-initialization (Default)
|
|
212
|
+
|
|
213
|
+
Best when user context is available immediately:
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
function App() {
|
|
217
|
+
return (
|
|
218
|
+
<FlagmintProvider
|
|
219
|
+
options={{
|
|
220
|
+
apiKey: 'your-api-key',
|
|
221
|
+
context: {
|
|
222
|
+
userId: getCurrentUser().id,
|
|
223
|
+
plan: getCurrentUser().plan
|
|
224
|
+
}
|
|
225
|
+
}}
|
|
226
|
+
>
|
|
227
|
+
<Dashboard />
|
|
228
|
+
</FlagmintProvider>
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### 2. Deferred Initialization
|
|
234
|
+
|
|
235
|
+
Perfect for authentication flows:
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
// Provider with deferred initialization
|
|
239
|
+
<FlagmintProvider
|
|
240
|
+
options={{
|
|
241
|
+
apiKey: 'your-api-key',
|
|
242
|
+
context: {} // Empty initially
|
|
243
|
+
}}
|
|
244
|
+
deferInitialization={true}
|
|
245
|
+
>
|
|
246
|
+
<App />
|
|
247
|
+
</FlagmintProvider>
|
|
248
|
+
|
|
249
|
+
// Login component
|
|
250
|
+
function LoginPage() {
|
|
251
|
+
const { updateContext } = useFlagmint()
|
|
252
|
+
|
|
253
|
+
const handleLogin = async (user) => {
|
|
254
|
+
// First update context with user info
|
|
255
|
+
await updateContext({
|
|
256
|
+
userId: user.id,
|
|
257
|
+
plan: user.plan,
|
|
258
|
+
locale: user.locale
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
// Flags are now available with user context
|
|
262
|
+
navigate('/dashboard')
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return <LoginForm onLogin={handleLogin} />
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 3. TypeScript Usage
|
|
270
|
+
|
|
271
|
+
Define your flag types for better type safety:
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
// types/flags.ts
|
|
275
|
+
export interface AppFlags {
|
|
276
|
+
'show-beta-feature': boolean
|
|
277
|
+
'user-plan': 'free' | 'pro' | 'enterprise'
|
|
278
|
+
'theme-config': {
|
|
279
|
+
primaryColor: string
|
|
280
|
+
darkMode: boolean
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export interface UserContext {
|
|
285
|
+
userId: string
|
|
286
|
+
plan: string
|
|
287
|
+
locale: string
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// components/TypedComponent.tsx
|
|
291
|
+
import { useFlag } from 'react-flagmint/client'
|
|
292
|
+
import type { AppFlags } from '../types/flags'
|
|
293
|
+
|
|
294
|
+
export default function TypedComponent() {
|
|
295
|
+
// TypeScript knows this returns boolean
|
|
296
|
+
const showBeta = useFlag<AppFlags['show-beta-feature']>('show-beta-feature', false)
|
|
297
|
+
|
|
298
|
+
// TypeScript knows this returns the union type
|
|
299
|
+
const plan = useFlag<AppFlags['user-plan']>('user-plan', 'free')
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<div>
|
|
303
|
+
{showBeta && <BetaFeature />}
|
|
304
|
+
<div>Plan: {plan}</div>
|
|
305
|
+
</div>
|
|
306
|
+
)
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### 4. Server-Side Rendering (SSR)
|
|
311
|
+
|
|
312
|
+
#### Next.js App Router
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
// app/providers.tsx
|
|
316
|
+
'use client'
|
|
317
|
+
import { FlagmintProvider } from 'react-flagmint/client'
|
|
318
|
+
|
|
319
|
+
export default function Providers({ children, initialFlags = {} }) {
|
|
320
|
+
return (
|
|
321
|
+
<FlagmintProvider
|
|
322
|
+
options={{
|
|
323
|
+
apiKey: process.env.NEXT_PUBLIC_FLAGMINT_API_KEY!,
|
|
324
|
+
transportMode: 'websocket'
|
|
325
|
+
}}
|
|
326
|
+
initialFlags={initialFlags}
|
|
327
|
+
>
|
|
328
|
+
{children}
|
|
329
|
+
</FlagmintProvider>
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// app/page.tsx
|
|
334
|
+
import { FlagClient } from 'flagmint-js-sdk'
|
|
335
|
+
import Providers from './providers'
|
|
336
|
+
import ClientComponent from './ClientComponent'
|
|
337
|
+
|
|
338
|
+
export default async function Page() {
|
|
339
|
+
// Optionally preload flags on server
|
|
340
|
+
let initialFlags = {}
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
const serverClient = new FlagClient({
|
|
344
|
+
apiKey: process.env.FLAGMINT_API_KEY!,
|
|
345
|
+
context: { server: true }
|
|
346
|
+
})
|
|
347
|
+
await serverClient.ready()
|
|
348
|
+
initialFlags = await serverClient.getFlags() // If this method exists
|
|
349
|
+
} catch (error) {
|
|
350
|
+
console.warn('Failed to load initial flags:', error)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return (
|
|
354
|
+
<Providers initialFlags={initialFlags}>
|
|
355
|
+
<ClientComponent />
|
|
356
|
+
</Providers>
|
|
357
|
+
)
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### 5. Context Updates
|
|
362
|
+
|
|
363
|
+
Update user context dynamically:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
function UserSettings() {
|
|
367
|
+
const { updateContext } = useFlagmint()
|
|
368
|
+
const currentTheme = useFlag('user-theme', 'light')
|
|
369
|
+
|
|
370
|
+
const handleThemeChange = async (newTheme: string) => {
|
|
371
|
+
// Update context - flags will be re-evaluated
|
|
372
|
+
await updateContext({ theme: newTheme })
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const handlePlanUpgrade = async (newPlan: string) => {
|
|
376
|
+
await updateContext({ plan: newPlan })
|
|
377
|
+
// Component will re-render with new plan-based flags
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return (
|
|
381
|
+
<div>
|
|
382
|
+
<ThemeSelector onChange={handleThemeChange} />
|
|
383
|
+
<PlanUpgrade onUpgrade={handlePlanUpgrade} />
|
|
384
|
+
</div>
|
|
385
|
+
)
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### 6. Loading States
|
|
390
|
+
|
|
391
|
+
Handle loading states gracefully:
|
|
392
|
+
|
|
393
|
+
```tsx
|
|
394
|
+
function FeaturePage() {
|
|
395
|
+
const isReady = useFlagmintReady()
|
|
396
|
+
const showPremiumFeature = useFlag('premium-feature', false)
|
|
397
|
+
|
|
398
|
+
if (!isReady) {
|
|
399
|
+
return (
|
|
400
|
+
<div className="loading-container">
|
|
401
|
+
<Spinner />
|
|
402
|
+
<p>Loading personalized features...</p>
|
|
403
|
+
</div>
|
|
404
|
+
)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return (
|
|
408
|
+
<div>
|
|
409
|
+
<h1>Features</h1>
|
|
410
|
+
{showPremiumFeature ? (
|
|
411
|
+
<PremiumFeature />
|
|
412
|
+
) : (
|
|
413
|
+
<UpgradeBanner />
|
|
414
|
+
)}
|
|
415
|
+
</div>
|
|
416
|
+
)
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### 7. Error Handling
|
|
421
|
+
|
|
422
|
+
```tsx
|
|
423
|
+
<FlagmintProvider
|
|
424
|
+
options={{
|
|
425
|
+
apiKey: 'your-api-key',
|
|
426
|
+
onError: (error) => {
|
|
427
|
+
console.error('Flagmint error:', error)
|
|
428
|
+
// Send to error reporting service
|
|
429
|
+
errorReporting.captureException(error)
|
|
430
|
+
}
|
|
431
|
+
}}
|
|
432
|
+
>
|
|
433
|
+
<App />
|
|
434
|
+
</FlagmintProvider>
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## 🏗️ Framework Examples
|
|
438
|
+
|
|
439
|
+
### Next.js (App Router)
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
// app/layout.tsx
|
|
443
|
+
import Providers from './providers'
|
|
444
|
+
|
|
445
|
+
export default function RootLayout({ children }) {
|
|
446
|
+
return (
|
|
447
|
+
<html lang="en">
|
|
448
|
+
<body>
|
|
449
|
+
<Providers>{children}</Providers>
|
|
450
|
+
</body>
|
|
451
|
+
</html>
|
|
452
|
+
)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// app/providers.tsx
|
|
456
|
+
'use client'
|
|
457
|
+
import { FlagmintProvider } from 'react-flagmint/client'
|
|
458
|
+
|
|
459
|
+
export default function Providers({ children }) {
|
|
460
|
+
return (
|
|
461
|
+
<FlagmintProvider
|
|
462
|
+
options={{
|
|
463
|
+
apiKey: process.env.NEXT_PUBLIC_FLAGMINT_API_KEY!,
|
|
464
|
+
transportMode: 'long-polling'
|
|
465
|
+
}}
|
|
466
|
+
>
|
|
467
|
+
{children}
|
|
468
|
+
</FlagmintProvider>
|
|
469
|
+
)
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Vite + React
|
|
474
|
+
|
|
475
|
+
```tsx
|
|
476
|
+
// src/main.tsx
|
|
477
|
+
import React from 'react'
|
|
478
|
+
import ReactDOM from 'react-dom/client'
|
|
479
|
+
import { FlagmintProvider } from 'react-flagmint/client'
|
|
480
|
+
import App from './App'
|
|
481
|
+
|
|
482
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
483
|
+
<React.StrictMode>
|
|
484
|
+
<FlagmintProvider
|
|
485
|
+
options={{
|
|
486
|
+
apiKey: import.meta.env.VITE_FLAGMINT_API_KEY,
|
|
487
|
+
transportMode: 'websocket'
|
|
488
|
+
}}
|
|
489
|
+
>
|
|
490
|
+
<App />
|
|
491
|
+
</FlagmintProvider>
|
|
492
|
+
</React.StrictMode>
|
|
493
|
+
)
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Remix
|
|
497
|
+
|
|
498
|
+
```tsx
|
|
499
|
+
// app/root.tsx
|
|
500
|
+
import { FlagmintProvider } from 'react-flagmint/client'
|
|
501
|
+
|
|
502
|
+
export default function App() {
|
|
503
|
+
return (
|
|
504
|
+
<html>
|
|
505
|
+
<head>
|
|
506
|
+
<Meta />
|
|
507
|
+
<Links />
|
|
508
|
+
</head>
|
|
509
|
+
<body>
|
|
510
|
+
<FlagmintProvider
|
|
511
|
+
options={{
|
|
512
|
+
apiKey: process.env.FLAGMINT_API_KEY!,
|
|
513
|
+
transportMode: 'long-polling'
|
|
514
|
+
}}
|
|
515
|
+
>
|
|
516
|
+
<Outlet />
|
|
517
|
+
</FlagmintProvider>
|
|
518
|
+
<Scripts />
|
|
519
|
+
</body>
|
|
520
|
+
</html>
|
|
521
|
+
)
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## ⚡ Performance
|
|
526
|
+
|
|
527
|
+
### Fine-grained Reactivity
|
|
528
|
+
|
|
529
|
+
Only components that use specific flags will re-render when those flags change:
|
|
530
|
+
|
|
531
|
+
```tsx
|
|
532
|
+
// ✅ Good: Only re-renders when 'feature-a' changes
|
|
533
|
+
function ComponentA() {
|
|
534
|
+
const featureA = useFlag('feature-a', false)
|
|
535
|
+
return <div>{featureA && <FeatureA />}</div>
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// ✅ Good: Only re-renders when 'feature-b' changes
|
|
539
|
+
function ComponentB() {
|
|
540
|
+
const featureB = useFlag('feature-b', false)
|
|
541
|
+
return <div>{featureB && <FeatureB />}</div>
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// ❌ Avoid: Re-renders when ANY flag changes
|
|
545
|
+
function ComponentAll() {
|
|
546
|
+
const allFlags = useFlags()
|
|
547
|
+
return <div>{allFlags['feature-a'] && <FeatureA />}</div>
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Bundle Size
|
|
552
|
+
|
|
553
|
+
- **react-flagmint**: ~3KB gzipped
|
|
554
|
+
- **zustand**: ~2KB gzipped
|
|
555
|
+
- **Total overhead**: ~5KB gzipped
|
|
556
|
+
|
|
557
|
+
## 🔧 Development
|
|
558
|
+
|
|
559
|
+
### Local Development
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
# Clone the monorepo
|
|
563
|
+
git clone <repo-url>
|
|
564
|
+
cd flagmint-monorepo
|
|
565
|
+
|
|
566
|
+
# Install dependencies
|
|
567
|
+
pnpm install
|
|
568
|
+
|
|
569
|
+
# Build the library
|
|
570
|
+
pnpm --filter react-flagmint build
|
|
571
|
+
|
|
572
|
+
# Run the Next.js example
|
|
573
|
+
pnpm dev:next
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Testing
|
|
577
|
+
|
|
578
|
+
```bash
|
|
579
|
+
# Run tests
|
|
580
|
+
pnpm test
|
|
581
|
+
|
|
582
|
+
# Type checking
|
|
583
|
+
pnpm typecheck
|
|
584
|
+
|
|
585
|
+
# Lint
|
|
586
|
+
pnpm lint
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
## 📄 License
|
|
590
|
+
|
|
591
|
+
MIT
|
|
592
|
+
|
|
593
|
+
## 🤝 Contributing
|
|
594
|
+
|
|
595
|
+
1. Fork the repository
|
|
596
|
+
2. Create a feature branch
|
|
597
|
+
3. Make your changes
|
|
598
|
+
4. Add tests
|
|
599
|
+
5. Submit a pull request
|
|
600
|
+
|
|
601
|
+
## 📞 Support
|
|
602
|
+
|
|
603
|
+
- 📧 Email: support@flagmint.com
|
|
604
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/jtad009/flagmint-react-sdk/issues)
|
|
605
|
+
- 📖 Docs: [Documentation](https://docs.flagmint.com)
|
|
606
|
+
|
|
607
|
+
---
|
|
608
|
+
|
|
609
|
+
**Made with ❤️ by the Flagmint team**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flagmint-react-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.12",
|
|
4
4
|
"description": "React wrapper for flagmint-js-sdk",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"react-dom": ">=18.0.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"flagmint-js-sdk": "^1.2.
|
|
34
|
+
"flagmint-js-sdk": "^1.2.5",
|
|
35
35
|
"zustand": "^4.4.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|