@flagify/react 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/README.md ADDED
@@ -0,0 +1,352 @@
1
+ <p align="center">
2
+ <a href="https://flagify.dev">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://flagify.dev/logo-white.svg" />
5
+ <source media="(prefers-color-scheme: light)" srcset="https://flagify.dev/logo-color.svg" />
6
+ <img alt="Flagify" src="https://flagify.dev/logo-color.svg" width="280" />
7
+ </picture>
8
+ </a>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <strong>Feature flags for modern teams</strong>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a href="https://www.npmjs.com/package/@flagify/react"><img src="https://img.shields.io/npm/v/@flagify/react.svg?style=flat-square&color=0D80F9" alt="npm version" /></a>
17
+ <a href="https://www.npmjs.com/package/@flagify/react"><img src="https://img.shields.io/npm/dm/@flagify/react.svg?style=flat-square&color=0D80F9" alt="npm downloads" /></a>
18
+ <a href="https://github.com/flagifyhq/react-sdk/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@flagify/react.svg?style=flat-square&color=0D80F9" alt="license" /></a>
19
+ <a href="https://github.com/flagifyhq/react-sdk"><img src="https://img.shields.io/github/stars/flagifyhq/react-sdk?style=flat-square&color=0D80F9" alt="github stars" /></a>
20
+ </p>
21
+
22
+ <p align="center">
23
+ <a href="https://flagify.dev/docs">Documentation</a> &middot;
24
+ <a href="https://flagify.dev/docs/sdks/react">SDK Reference</a> &middot;
25
+ <a href="https://github.com/flagifyhq/react-sdk/issues">Issues</a> &middot;
26
+ <a href="https://flagify.dev">Website</a>
27
+ </p>
28
+
29
+ ---
30
+
31
+ ## Overview
32
+
33
+ `@flagify/react` is the official React SDK for [Flagify](https://flagify.dev). Idiomatic hooks and a context provider for feature flag evaluation in React applications.
34
+
35
+ - **Hooks-first** -- `useFlag`, `useVariant`, `useFlagValue` for every use case
36
+ - **Type-safe** -- Full TypeScript generics for flag values
37
+ - **Zero config** -- Wrap with `<FlagifyProvider>`, use hooks anywhere
38
+ - **Lightweight** -- Thin wrapper over [`@flagify/node`](https://github.com/flagifyhq/node-sdk)
39
+ - **React 18+** -- Built for modern React
40
+ - **React Native ready** -- Works in React Native and Expo with zero additional setup
41
+
42
+ ## Table of contents
43
+
44
+ - [Installation](#installation)
45
+ - [Quick start](#quick-start)
46
+ - [Provider](#provider)
47
+ - [Hooks](#hooks)
48
+ - [`useFlag`](#useflagflagkey-string-boolean)
49
+ - [`useVariant`](#usevariantflagkey-string-string--undefined)
50
+ - [`useFlagValue`](#useflagvaluetflagkey-string-t--undefined)
51
+ - [`useFlagifyClient`](#useflagifyclient-flagify)
52
+ - [Examples](#examples)
53
+ - [API reference](#api-reference)
54
+ - [Contributing](#contributing)
55
+ - [License](#license)
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ # pnpm
61
+ pnpm add @flagify/react
62
+
63
+ # npm
64
+ npm install @flagify/react
65
+
66
+ # yarn
67
+ yarn add @flagify/react
68
+ ```
69
+
70
+ > **Peer dependency:** React 18+ is required.
71
+
72
+ ## React Native / Expo
73
+
74
+ `@flagify/react` is fully compatible with React Native (0.64+) and Expo (SDK 44+). No separate package or polyfills needed.
75
+
76
+ ```bash
77
+ npx expo install @flagify/react
78
+ ```
79
+
80
+ Wrap your root with `<FlagifyProvider>` and use hooks anywhere. For a full getting-started guide, see the [React Native documentation](https://flagify.dev/docs/sdks/react-native).
81
+
82
+ ## Quick start
83
+
84
+ **1. Wrap your app with the provider**
85
+
86
+ ```tsx
87
+ import { FlagifyProvider } from '@flagify/react'
88
+
89
+ function App() {
90
+ return (
91
+ <FlagifyProvider projectKey="proj_xxx" publicKey="pk_xxx">
92
+ <YourApp />
93
+ </FlagifyProvider>
94
+ )
95
+ }
96
+ ```
97
+
98
+ **2. Use hooks in any component**
99
+
100
+ ```tsx
101
+ import { useFlag } from '@flagify/react'
102
+
103
+ function Navbar() {
104
+ const showBanner = useFlag('promo-banner')
105
+
106
+ return (
107
+ <nav>
108
+ {showBanner && <PromoBanner />}
109
+ </nav>
110
+ )
111
+ }
112
+ ```
113
+
114
+ ## Provider
115
+
116
+ ### `<FlagifyProvider>`
117
+
118
+ Initializes the Flagify client and provides it to all child components via React context.
119
+
120
+ ```tsx
121
+ <FlagifyProvider
122
+ projectKey="proj_xxx"
123
+ publicKey="pk_xxx"
124
+ options={{
125
+ apiUrl: 'https://api.flagify.dev',
126
+ staleTimeMs: 300_000,
127
+ user: {
128
+ id: 'user_123',
129
+ email: 'mario@example.com',
130
+ role: 'admin',
131
+ geolocation: { country: 'US' },
132
+ },
133
+ }}
134
+ >
135
+ {children}
136
+ </FlagifyProvider>
137
+ ```
138
+
139
+ #### Props
140
+
141
+ All props from [`FlagifyOptions`](https://github.com/flagifyhq/node-sdk#configuration-options) are supported:
142
+
143
+ | Prop | Type | Required | Description |
144
+ |------|------|----------|-------------|
145
+ | `projectKey` | `string` | Yes | Project identifier from your Flagify workspace |
146
+ | `publicKey` | `string` | Yes | Client-safe publishable API key |
147
+ | `secretKey` | `string` | No | Server-side secret key |
148
+ | `options` | `object` | No | Additional configuration (apiUrl, staleTimeMs, user, realtime) |
149
+ | `children` | `ReactNode` | Yes | Your application tree |
150
+
151
+ #### Context value
152
+
153
+ The provider exposes the following context:
154
+
155
+ | Property | Type | Description |
156
+ |----------|------|-------------|
157
+ | `client` | `Flagify \| null` | The underlying Flagify client instance |
158
+ | `isReady` | `boolean` | `true` once the client has been initialized |
159
+
160
+ ## Hooks
161
+
162
+ ### `useFlag(flagKey: string): boolean`
163
+
164
+ Evaluates a boolean feature flag. Returns `false` if the flag doesn't exist or is disabled.
165
+
166
+ ```tsx
167
+ function Dashboard() {
168
+ const isNew = useFlag('new-dashboard')
169
+
170
+ if (!isNew) return <LegacyDashboard />
171
+ return <NewDashboard />
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ### `useVariant(flagKey: string): string | undefined`
178
+
179
+ Returns the string variant of a multivariate flag. Ideal for A/B tests and experiments.
180
+
181
+ ```tsx
182
+ function Onboarding() {
183
+ const variant = useVariant('onboarding-flow')
184
+
185
+ switch (variant) {
186
+ case 'control': return <OnboardingClassic />
187
+ case 'variant-a': return <OnboardingShort />
188
+ case 'variant-b': return <OnboardingGuided />
189
+ default: return <OnboardingClassic />
190
+ }
191
+ }
192
+ ```
193
+
194
+ ---
195
+
196
+ ### `useFlagValue<T>(flagKey: string): T | undefined`
197
+
198
+ Returns a typed flag value with full TypeScript generics. Supports `number`, `string`, `boolean`, and `JSON` values.
199
+
200
+ ```tsx
201
+ interface ListConfig {
202
+ maxItems: number
203
+ showPagination: boolean
204
+ }
205
+
206
+ function ItemList() {
207
+ const config = useFlagValue<ListConfig>('list-config')
208
+
209
+ return (
210
+ <ul>
211
+ {items.slice(0, config?.maxItems ?? 10).map(item => (
212
+ <li key={item.id}>{item.name}</li>
213
+ ))}
214
+ </ul>
215
+ )
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ### `useFlagifyClient(): Flagify`
222
+
223
+ Direct access to the underlying [`Flagify`](https://github.com/flagifyhq/node-sdk) client instance. Throws if used outside of `<FlagifyProvider>`.
224
+
225
+ ```tsx
226
+ function FeatureGate({ flagKey, children }: { flagKey: string; children: ReactNode }) {
227
+ const client = useFlagifyClient()
228
+
229
+ if (!client.isEnabled(flagKey)) return null
230
+ return <>{children}</>
231
+ }
232
+ ```
233
+
234
+ ## Examples
235
+
236
+ ### Feature gate component
237
+
238
+ ```tsx
239
+ import { useFlag } from '@flagify/react'
240
+ import type { ReactNode } from 'react'
241
+
242
+ function FeatureGate({ flag, children, fallback }: {
243
+ flag: string
244
+ children: ReactNode
245
+ fallback?: ReactNode
246
+ }) {
247
+ const isEnabled = useFlag(flag)
248
+ return <>{isEnabled ? children : fallback}</>
249
+ }
250
+
251
+ // Usage
252
+ <FeatureGate flag="premium-features" fallback={<UpgradePrompt />}>
253
+ <PremiumDashboard />
254
+ </FeatureGate>
255
+ ```
256
+
257
+ ### A/B test with analytics
258
+
259
+ ```tsx
260
+ import { useVariant } from '@flagify/react'
261
+ import { useEffect } from 'react'
262
+
263
+ function PricingPage() {
264
+ const variant = useVariant('pricing-layout')
265
+
266
+ useEffect(() => {
267
+ analytics.track('pricing_viewed', { variant })
268
+ }, [variant])
269
+
270
+ return variant === 'variant-a'
271
+ ? <PricingCards />
272
+ : <PricingTable />
273
+ }
274
+ ```
275
+
276
+ ### Remote config
277
+
278
+ ```tsx
279
+ import { useFlagValue } from '@flagify/react'
280
+
281
+ interface ThemeConfig {
282
+ primaryColor: string
283
+ borderRadius: number
284
+ fontFamily: string
285
+ }
286
+
287
+ function ThemeProvider({ children }: { children: ReactNode }) {
288
+ const theme = useFlagValue<ThemeConfig>('theme-config')
289
+
290
+ const style = {
291
+ '--primary': theme?.primaryColor ?? '#0D80F9',
292
+ '--radius': `${theme?.borderRadius ?? 8}px`,
293
+ '--font': theme?.fontFamily ?? 'Inter',
294
+ } as React.CSSProperties
295
+
296
+ return <div style={style}>{children}</div>
297
+ }
298
+ ```
299
+
300
+ ## API reference
301
+
302
+ | Export | Type | Description |
303
+ |--------|------|-------------|
304
+ | `FlagifyProvider` | Component | Context provider -- wraps your app |
305
+ | `FlagifyContext` | `React.Context` | Raw context (advanced usage) |
306
+ | `useFlag` | Hook | Boolean flag evaluation |
307
+ | `useVariant` | Hook | String variant evaluation |
308
+ | `useFlagValue` | Hook | Typed value evaluation with generics |
309
+ | `useFlagifyClient` | Hook | Direct client access |
310
+ | `FlagifyProviderProps` | Type | Props for `FlagifyProvider` |
311
+ | `FlagifyContextValue` | Type | Shape of the context value |
312
+
313
+ Types re-exported from `@flagify/node`:
314
+
315
+ | Export | Description |
316
+ |--------|-------------|
317
+ | `FlagifyOptions` | Client configuration |
318
+ | `FlagifyUser` | User context for targeting |
319
+ | `FlagifyFlaggy` | Flag data structure |
320
+ | `IFlagifyClient` | Client interface |
321
+
322
+ ## Contributing
323
+
324
+ We welcome contributions. Please open an issue first to discuss what you'd like to change.
325
+
326
+ ```bash
327
+ # Clone
328
+ git clone https://github.com/flagifyhq/react-sdk.git
329
+ cd react-sdk
330
+
331
+ # Install
332
+ pnpm install
333
+
334
+ # Development (watch mode)
335
+ pnpm run dev
336
+
337
+ # Build
338
+ pnpm run build
339
+
340
+ # Generate barrel exports
341
+ pnpm run generate
342
+ ```
343
+
344
+ ## License
345
+
346
+ MIT -- see [LICENSE](./LICENSE) for details.
347
+
348
+ ---
349
+
350
+ <p align="center">
351
+ <sub>Built with care by the <a href="https://flagify.dev">Flagify</a> team</sub>
352
+ </p>
@@ -0,0 +1,32 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as react from 'react';
3
+ import { ReactNode } from 'react';
4
+ import * as _flagify_node from '@flagify/node';
5
+ import { FlagifyOptions, Flagify } from '@flagify/node';
6
+
7
+ interface FlagifyProviderProps extends FlagifyOptions {
8
+ children: ReactNode;
9
+ }
10
+ declare function FlagifyProvider({ children, ...config }: FlagifyProviderProps): react_jsx_runtime.JSX.Element;
11
+
12
+ interface FlagifyContextValue {
13
+ client: Flagify | null;
14
+ isReady: boolean;
15
+ /** Increments on every SSE flag_change event to trigger re-renders */
16
+ version: number;
17
+ }
18
+ /** Sentinel value — when context equals this, no provider exists */
19
+ declare const NO_PROVIDER: FlagifyContextValue;
20
+ declare const FlagifyContext: react.Context<FlagifyContextValue>;
21
+
22
+ declare function useFlag(flagKey: string): boolean;
23
+
24
+ declare function useFlagValue<T>(flagKey: string, fallback: T): T;
25
+
26
+ declare function useFlagifyClient(): _flagify_node.Flagify | null;
27
+
28
+ declare function useIsReady(): boolean;
29
+
30
+ declare function useVariant(flagKey: string, fallback: string): string;
31
+
32
+ export { FlagifyContext, type FlagifyContextValue, FlagifyProvider, type FlagifyProviderProps, NO_PROVIDER, useFlag, useFlagValue, useFlagifyClient, useIsReady, useVariant };
@@ -0,0 +1,32 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as react from 'react';
3
+ import { ReactNode } from 'react';
4
+ import * as _flagify_node from '@flagify/node';
5
+ import { FlagifyOptions, Flagify } from '@flagify/node';
6
+
7
+ interface FlagifyProviderProps extends FlagifyOptions {
8
+ children: ReactNode;
9
+ }
10
+ declare function FlagifyProvider({ children, ...config }: FlagifyProviderProps): react_jsx_runtime.JSX.Element;
11
+
12
+ interface FlagifyContextValue {
13
+ client: Flagify | null;
14
+ isReady: boolean;
15
+ /** Increments on every SSE flag_change event to trigger re-renders */
16
+ version: number;
17
+ }
18
+ /** Sentinel value — when context equals this, no provider exists */
19
+ declare const NO_PROVIDER: FlagifyContextValue;
20
+ declare const FlagifyContext: react.Context<FlagifyContextValue>;
21
+
22
+ declare function useFlag(flagKey: string): boolean;
23
+
24
+ declare function useFlagValue<T>(flagKey: string, fallback: T): T;
25
+
26
+ declare function useFlagifyClient(): _flagify_node.Flagify | null;
27
+
28
+ declare function useIsReady(): boolean;
29
+
30
+ declare function useVariant(flagKey: string, fallback: string): string;
31
+
32
+ export { FlagifyContext, type FlagifyContextValue, FlagifyProvider, type FlagifyProviderProps, NO_PROVIDER, useFlag, useFlagValue, useFlagifyClient, useIsReady, useVariant };
package/dist/index.js ADDED
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ FlagifyContext: () => FlagifyContext,
24
+ FlagifyProvider: () => FlagifyProvider,
25
+ NO_PROVIDER: () => NO_PROVIDER,
26
+ useFlag: () => useFlag,
27
+ useFlagValue: () => useFlagValue,
28
+ useFlagifyClient: () => useFlagifyClient,
29
+ useIsReady: () => useIsReady,
30
+ useVariant: () => useVariant
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+
34
+ // src/FlagifyProvider.tsx
35
+ var import_react2 = require("react");
36
+ var import_node = require("@flagify/node");
37
+
38
+ // src/context.ts
39
+ var import_react = require("react");
40
+ var NO_PROVIDER = {
41
+ client: null,
42
+ isReady: false,
43
+ version: -1
44
+ };
45
+ var FlagifyContext = (0, import_react.createContext)(NO_PROVIDER);
46
+
47
+ // src/FlagifyProvider.tsx
48
+ var import_jsx_runtime = require("react/jsx-runtime");
49
+ function FlagifyProvider({ children, ...config }) {
50
+ const [client, setClient] = (0, import_react2.useState)(null);
51
+ const [isReady, setIsReady] = (0, import_react2.useState)(false);
52
+ const [version, setVersion] = (0, import_react2.useState)(0);
53
+ const clientRef = (0, import_react2.useRef)(null);
54
+ const bumpVersion = (0, import_react2.useCallback)(() => {
55
+ setVersion((v) => v + 1);
56
+ }, []);
57
+ (0, import_react2.useEffect)(() => {
58
+ const instance = new import_node.Flagify(config);
59
+ clientRef.current = instance;
60
+ instance.onFlagChange = bumpVersion;
61
+ instance.ready().then(() => {
62
+ if (clientRef.current === instance) {
63
+ setClient(instance);
64
+ setIsReady(true);
65
+ }
66
+ });
67
+ return () => {
68
+ clientRef.current = null;
69
+ instance.onFlagChange = null;
70
+ instance.destroy();
71
+ };
72
+ }, [config.projectKey, config.publicKey]);
73
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FlagifyContext.Provider, { value: { client, isReady, version }, children });
74
+ }
75
+
76
+ // src/useFlag.ts
77
+ var import_react4 = require("react");
78
+
79
+ // src/useFlagifyClient.ts
80
+ var import_react3 = require("react");
81
+ function useFlagifyClient() {
82
+ const ctx = (0, import_react3.useContext)(FlagifyContext);
83
+ if (ctx === NO_PROVIDER) {
84
+ throw new Error(
85
+ "useFlagifyClient must be used within a <FlagifyProvider>. Wrap your app with <FlagifyProvider client={client}>."
86
+ );
87
+ }
88
+ return ctx.client;
89
+ }
90
+
91
+ // src/useFlag.ts
92
+ function useFlag(flagKey) {
93
+ const { version } = (0, import_react4.useContext)(FlagifyContext);
94
+ const client = useFlagifyClient();
95
+ void version;
96
+ return client?.isEnabled(flagKey) ?? false;
97
+ }
98
+
99
+ // src/useFlagValue.ts
100
+ var import_react5 = require("react");
101
+ function useFlagValue(flagKey, fallback) {
102
+ const { version } = (0, import_react5.useContext)(FlagifyContext);
103
+ const client = useFlagifyClient();
104
+ void version;
105
+ return client?.getValue(flagKey, fallback) ?? fallback;
106
+ }
107
+
108
+ // src/useIsReady.ts
109
+ var import_react6 = require("react");
110
+ function useIsReady() {
111
+ const { isReady } = (0, import_react6.useContext)(FlagifyContext);
112
+ return isReady;
113
+ }
114
+
115
+ // src/useVariant.ts
116
+ var import_react7 = require("react");
117
+ function useVariant(flagKey, fallback) {
118
+ const { version } = (0, import_react7.useContext)(FlagifyContext);
119
+ const client = useFlagifyClient();
120
+ void version;
121
+ return client?.getVariant(flagKey, fallback) ?? fallback;
122
+ }
123
+ // Annotate the CommonJS export names for ESM import in node:
124
+ 0 && (module.exports = {
125
+ FlagifyContext,
126
+ FlagifyProvider,
127
+ NO_PROVIDER,
128
+ useFlag,
129
+ useFlagValue,
130
+ useFlagifyClient,
131
+ useIsReady,
132
+ useVariant
133
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,99 @@
1
+ // src/FlagifyProvider.tsx
2
+ import { useState, useEffect, useRef, useCallback } from "react";
3
+ import { Flagify } from "@flagify/node";
4
+
5
+ // src/context.ts
6
+ import { createContext } from "react";
7
+ var NO_PROVIDER = {
8
+ client: null,
9
+ isReady: false,
10
+ version: -1
11
+ };
12
+ var FlagifyContext = createContext(NO_PROVIDER);
13
+
14
+ // src/FlagifyProvider.tsx
15
+ import { jsx } from "react/jsx-runtime";
16
+ function FlagifyProvider({ children, ...config }) {
17
+ const [client, setClient] = useState(null);
18
+ const [isReady, setIsReady] = useState(false);
19
+ const [version, setVersion] = useState(0);
20
+ const clientRef = useRef(null);
21
+ const bumpVersion = useCallback(() => {
22
+ setVersion((v) => v + 1);
23
+ }, []);
24
+ useEffect(() => {
25
+ const instance = new Flagify(config);
26
+ clientRef.current = instance;
27
+ instance.onFlagChange = bumpVersion;
28
+ instance.ready().then(() => {
29
+ if (clientRef.current === instance) {
30
+ setClient(instance);
31
+ setIsReady(true);
32
+ }
33
+ });
34
+ return () => {
35
+ clientRef.current = null;
36
+ instance.onFlagChange = null;
37
+ instance.destroy();
38
+ };
39
+ }, [config.projectKey, config.publicKey]);
40
+ return /* @__PURE__ */ jsx(FlagifyContext.Provider, { value: { client, isReady, version }, children });
41
+ }
42
+
43
+ // src/useFlag.ts
44
+ import { useContext as useContext2 } from "react";
45
+
46
+ // src/useFlagifyClient.ts
47
+ import { useContext } from "react";
48
+ function useFlagifyClient() {
49
+ const ctx = useContext(FlagifyContext);
50
+ if (ctx === NO_PROVIDER) {
51
+ throw new Error(
52
+ "useFlagifyClient must be used within a <FlagifyProvider>. Wrap your app with <FlagifyProvider client={client}>."
53
+ );
54
+ }
55
+ return ctx.client;
56
+ }
57
+
58
+ // src/useFlag.ts
59
+ function useFlag(flagKey) {
60
+ const { version } = useContext2(FlagifyContext);
61
+ const client = useFlagifyClient();
62
+ void version;
63
+ return client?.isEnabled(flagKey) ?? false;
64
+ }
65
+
66
+ // src/useFlagValue.ts
67
+ import { useContext as useContext3 } from "react";
68
+ function useFlagValue(flagKey, fallback) {
69
+ const { version } = useContext3(FlagifyContext);
70
+ const client = useFlagifyClient();
71
+ void version;
72
+ return client?.getValue(flagKey, fallback) ?? fallback;
73
+ }
74
+
75
+ // src/useIsReady.ts
76
+ import { useContext as useContext4 } from "react";
77
+ function useIsReady() {
78
+ const { isReady } = useContext4(FlagifyContext);
79
+ return isReady;
80
+ }
81
+
82
+ // src/useVariant.ts
83
+ import { useContext as useContext5 } from "react";
84
+ function useVariant(flagKey, fallback) {
85
+ const { version } = useContext5(FlagifyContext);
86
+ const client = useFlagifyClient();
87
+ void version;
88
+ return client?.getVariant(flagKey, fallback) ?? fallback;
89
+ }
90
+ export {
91
+ FlagifyContext,
92
+ FlagifyProvider,
93
+ NO_PROVIDER,
94
+ useFlag,
95
+ useFlagValue,
96
+ useFlagifyClient,
97
+ useIsReady,
98
+ useVariant
99
+ };
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@flagify/react",
3
+ "version": "1.0.0",
4
+ "description": "React SDK for Flagify — hooks and provider for feature flag evaluation.",
5
+ "author": "Mario Campbell R <mario@mariocampbellr.com>",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "module": "dist/index.mjs",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "peerDependencies": {
21
+ "react": ">=18.0.0"
22
+ },
23
+ "dependencies": {
24
+ "@flagify/node": "1.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@testing-library/jest-dom": "^6.9.1",
28
+ "@testing-library/react": "^14",
29
+ "@types/react": "^18.2.0",
30
+ "jsdom": "^29.0.1",
31
+ "react": "^18.2.0",
32
+ "react-dom": "18"
33
+ },
34
+ "keywords": [
35
+ "feature-flags",
36
+ "flagify",
37
+ "react",
38
+ "hooks"
39
+ ],
40
+ "homepage": "https://flagify.dev",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/flagifyhq/javascript",
44
+ "directory": "packages/react"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/flagifyhq/javascript/issues"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "scripts": {
53
+ "generate": "barrelsby -c ./barrelsby.json",
54
+ "build": "pnpm run generate && tsup src/index.ts --format esm,cjs --dts",
55
+ "dev": "tsup src/index.ts --format esm,cjs --dts --watch",
56
+ "test": "vitest run",
57
+ "lint": "tsc --noEmit",
58
+ "clean": "rm -rf dist"
59
+ }
60
+ }