@featureflip/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 +112 -0
- package/dist/__tests__/hooks.test.d.ts +2 -0
- package/dist/__tests__/hooks.test.d.ts.map +1 -0
- package/dist/__tests__/provider.test.d.ts +2 -0
- package/dist/__tests__/provider.test.d.ts.map +1 -0
- package/dist/context.d.ts +9 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/hooks.d.ts +9 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/provider.d.ts +10 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/testing-CXh0WG3c.cjs +1 -0
- package/dist/testing-D-nDtDyw.js +21 -0
- package/dist/testing.cjs +1 -0
- package/dist/testing.d.ts +8 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +2 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# @featureflip/react-sdk
|
|
2
|
+
|
|
3
|
+
React bindings for Featureflip feature flag evaluation.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @featureflip/react-sdk @featureflip/browser-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Wrap your app with `FeatureflipProvider`, then use `useFeatureFlag` in any component.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { FeatureflipProvider, useFeatureFlag } from '@featureflip/react-sdk';
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
return (
|
|
20
|
+
<FeatureflipProvider clientKey="your-client-sdk-key">
|
|
21
|
+
<Banner />
|
|
22
|
+
</FeatureflipProvider>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function Banner() {
|
|
27
|
+
const showBanner = useFeatureFlag('show-banner', false);
|
|
28
|
+
if (!showBanner) return null;
|
|
29
|
+
return <div>New feature available!</div>;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Provider Props
|
|
34
|
+
|
|
35
|
+
| Prop | Type | Default | Description |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| `clientKey` | `string` | **(required)** | Client SDK key |
|
|
38
|
+
| `context` | `Record<string, unknown>` | `undefined` | Evaluation context (user attributes) |
|
|
39
|
+
| `baseUrl` | `string` | `undefined` | Evaluation API base URL |
|
|
40
|
+
| `streaming` | `boolean` | `undefined` | Enable SSE streaming |
|
|
41
|
+
|
|
42
|
+
The provider creates a `FeatureflipClient` internally and calls `initialize()` on mount. It cleans up (calls `close()`) on unmount.
|
|
43
|
+
|
|
44
|
+
## Hooks
|
|
45
|
+
|
|
46
|
+
### `useFeatureFlag<T>(key: string, defaultValue: T): T`
|
|
47
|
+
|
|
48
|
+
Returns the evaluated value of a flag. The component re-renders automatically when the flag value changes via streaming or `identify()`. The type of `defaultValue` determines which variation method is called (`boolVariation`, `stringVariation`, `numberVariation`, or `jsonVariation`).
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
const enabled = useFeatureFlag('new-checkout', false);
|
|
52
|
+
const color = useFeatureFlag('button-color', 'blue');
|
|
53
|
+
const limit = useFeatureFlag('rate-limit', 100);
|
|
54
|
+
const config = useFeatureFlag('ui-config', { sidebar: true });
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `useFeatureflipStatus(): { isReady, isError, error }`
|
|
58
|
+
|
|
59
|
+
Returns the initialization status of the client. Useful for showing loading states.
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
function App() {
|
|
63
|
+
const { isReady, isError, error } = useFeatureflipStatus();
|
|
64
|
+
|
|
65
|
+
if (isError) return <div>Error: {error?.message}</div>;
|
|
66
|
+
if (!isReady) return <div>Loading...</div>;
|
|
67
|
+
|
|
68
|
+
return <Main />;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### `useFeatureflipClient(): FeatureflipClient`
|
|
73
|
+
|
|
74
|
+
Returns the underlying `FeatureflipClient` instance for direct access (e.g., calling `identify`).
|
|
75
|
+
|
|
76
|
+
## Identify on Login
|
|
77
|
+
|
|
78
|
+
When the context prop changes, the provider automatically calls `identify()` and re-evaluates all flags. You can also call `identify` directly.
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
function LoginPage() {
|
|
82
|
+
const client = useFeatureflipClient();
|
|
83
|
+
|
|
84
|
+
async function handleLogin(userId: string) {
|
|
85
|
+
// ... authenticate ...
|
|
86
|
+
await client.identify({ user_id: userId, plan: 'pro' });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return <button onClick={() => handleLogin('123')}>Log in</button>;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Testing
|
|
94
|
+
|
|
95
|
+
Use `TestFeatureflipProvider` to supply predetermined flag values in tests -- no network calls, no initialization delay.
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { TestFeatureflipProvider } from '@featureflip/react-sdk';
|
|
99
|
+
import { render, screen } from '@testing-library/react';
|
|
100
|
+
|
|
101
|
+
test('renders banner when flag is on', () => {
|
|
102
|
+
render(
|
|
103
|
+
<TestFeatureflipProvider flags={{ 'show-banner': true }}>
|
|
104
|
+
<Banner />
|
|
105
|
+
</TestFeatureflipProvider>,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
expect(screen.getByText('New feature available!')).toBeInTheDocument();
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`TestFeatureflipProvider` uses `FeatureflipClient.forTesting()` internally and sets `isReady: true` immediately.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/hooks.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/provider.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FeatureflipClient } from '../../browser-sdk/src';
|
|
2
|
+
export interface FeatureflipContextValue {
|
|
3
|
+
client: FeatureflipClient;
|
|
4
|
+
isReady: boolean;
|
|
5
|
+
isError: boolean;
|
|
6
|
+
error: Error | null;
|
|
7
|
+
}
|
|
8
|
+
export declare const FeatureflipContext: import('react').Context<FeatureflipContextValue | null>;
|
|
9
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,kBAAkB,yDAAsD,CAAC"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FeatureflipClient } from '../../browser-sdk/src';
|
|
2
|
+
export declare function useFeatureFlag<T>(key: string, defaultValue: T): T;
|
|
3
|
+
export declare function useFeatureflipClient(): FeatureflipClient;
|
|
4
|
+
export declare function useFeatureflipStatus(): {
|
|
5
|
+
isReady: boolean;
|
|
6
|
+
isError: boolean;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AA0B9D,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CAmDjE;AAED,wBAAgB,oBAAoB,IAAI,iBAAiB,CAGxD;AAED,wBAAgB,oBAAoB,IAAI;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAGA"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./testing-CXh0WG3c.cjs`);let t=require(`react`),n=require(`@featureflip/browser`),r=require(`react/jsx-runtime`);function i({clientKey:i,context:a,baseUrl:o,streaming:s,children:c}){let l=(0,t.useRef)(null),[u,d]=(0,t.useState)(0),[f,p]=(0,t.useState)(!1),[m,h]=(0,t.useState)(!1),[g,_]=(0,t.useState)(null),v=(0,t.useRef)(``);l.current===null&&(l.current=new n.FeatureflipClient({clientKey:i,baseUrl:o,context:a,streaming:s})),(0,t.useEffect)(()=>{l.current||(l.current=new n.FeatureflipClient({clientKey:i,baseUrl:o,context:a,streaming:s}),p(!1),h(!1),_(null),d(e=>e+1));let e=l.current,t=()=>p(!0),r=e=>{h(!0),_(e instanceof Error?e:Error(String(e)))};return e.on(`ready`,t),e.on(`error`,r),e.initialize().catch(r),()=>{e.off(`ready`,t),e.off(`error`,r),e.close(),l.current=null}},[]),(0,t.useEffect)(()=>{let e=JSON.stringify(a??{});if(v.current===``){v.current=e;return}e!==v.current&&(v.current=e,l.current?.identify(a??{}).catch(()=>{}))},[a]);let y={client:l.current,isReady:f,isError:m,error:g};return(0,r.jsx)(e.n.Provider,{value:y,children:c})}function a(){let n=(0,t.useContext)(e.n);if(n===null)throw Error(`useFeatureFlag must be used within a <FeatureflipProvider>`);return n}function o(e,t,n){switch(typeof n){case`boolean`:return e.boolVariation(t,n);case`string`:return e.stringVariation(t,n);case`number`:return e.numberVariation(t,n);default:return e.jsonVariation(t,n)}}function s(e,n){let{client:r}=a(),i=(0,t.useRef)(n);i.current=n;let s=(0,t.useRef)(void 0),c=(0,t.useRef)(void 0),l=(0,t.useCallback)(e=>{let t=()=>e();return r.on(`change`,t),()=>r.off(`change`,t)},[r]),u=(0,t.useCallback)(()=>{let t=o(r,e,i.current);if(Object.is(t,s.current))return s.current;if(typeof t!=`object`||!t)return s.current=t,t;try{let e=JSON.stringify(t);if(s.current!==void 0&&e===c.current)return s.current;s.current=t,c.current=e}catch{s.current=t}return t},[r,e]);return(0,t.useSyncExternalStore)(l,u,u)}function c(){let{client:e}=a();return e}function l(){let{isReady:e,isError:t,error:n}=a();return{isReady:e,isError:t,error:n}}exports.FeatureflipContext=e.n,exports.FeatureflipProvider=i,exports.TestFeatureflipProvider=e.t,exports.useFeatureFlag=s,exports.useFeatureflipClient=c,exports.useFeatureflipStatus=l;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { FeatureflipProvider } from './provider';
|
|
2
|
+
export type { FeatureflipProviderProps } from './provider';
|
|
3
|
+
export { useFeatureFlag, useFeatureflipClient, useFeatureflipStatus } from './hooks';
|
|
4
|
+
export { TestFeatureflipProvider } from './testing';
|
|
5
|
+
export { FeatureflipContext } from './context';
|
|
6
|
+
export type { FeatureflipContextValue } from './context';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { n as e, t } from "./testing-D-nDtDyw.js";
|
|
2
|
+
import { useCallback as n, useContext as r, useEffect as i, useRef as a, useState as o, useSyncExternalStore as s } from "react";
|
|
3
|
+
import { FeatureflipClient as c } from "@featureflip/browser";
|
|
4
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
5
|
+
//#region src/provider.tsx
|
|
6
|
+
function u({ clientKey: t, context: n, baseUrl: r, streaming: s, children: u }) {
|
|
7
|
+
let d = a(null), [f, p] = o(0), [m, h] = o(!1), [g, _] = o(!1), [v, y] = o(null), b = a("");
|
|
8
|
+
d.current === null && (d.current = new c({
|
|
9
|
+
clientKey: t,
|
|
10
|
+
baseUrl: r,
|
|
11
|
+
context: n,
|
|
12
|
+
streaming: s
|
|
13
|
+
})), i(() => {
|
|
14
|
+
d.current || (d.current = new c({
|
|
15
|
+
clientKey: t,
|
|
16
|
+
baseUrl: r,
|
|
17
|
+
context: n,
|
|
18
|
+
streaming: s
|
|
19
|
+
}), h(!1), _(!1), y(null), p((e) => e + 1));
|
|
20
|
+
let e = d.current, i = () => h(!0), a = (e) => {
|
|
21
|
+
_(!0), y(e instanceof Error ? e : Error(String(e)));
|
|
22
|
+
};
|
|
23
|
+
return e.on("ready", i), e.on("error", a), e.initialize().catch(a), () => {
|
|
24
|
+
e.off("ready", i), e.off("error", a), e.close(), d.current = null;
|
|
25
|
+
};
|
|
26
|
+
}, []), i(() => {
|
|
27
|
+
let e = JSON.stringify(n ?? {});
|
|
28
|
+
if (b.current === "") {
|
|
29
|
+
b.current = e;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
e !== b.current && (b.current = e, d.current?.identify(n ?? {}).catch(() => {}));
|
|
33
|
+
}, [n]);
|
|
34
|
+
let x = {
|
|
35
|
+
client: d.current,
|
|
36
|
+
isReady: m,
|
|
37
|
+
isError: g,
|
|
38
|
+
error: v
|
|
39
|
+
};
|
|
40
|
+
return /* @__PURE__ */ l(e.Provider, {
|
|
41
|
+
value: x,
|
|
42
|
+
children: u
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/hooks.ts
|
|
47
|
+
function d() {
|
|
48
|
+
let t = r(e);
|
|
49
|
+
if (t === null) throw Error("useFeatureFlag must be used within a <FeatureflipProvider>");
|
|
50
|
+
return t;
|
|
51
|
+
}
|
|
52
|
+
function f(e, t, n) {
|
|
53
|
+
switch (typeof n) {
|
|
54
|
+
case "boolean": return e.boolVariation(t, n);
|
|
55
|
+
case "string": return e.stringVariation(t, n);
|
|
56
|
+
case "number": return e.numberVariation(t, n);
|
|
57
|
+
default: return e.jsonVariation(t, n);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function p(e, t) {
|
|
61
|
+
let { client: r } = d(), i = a(t);
|
|
62
|
+
i.current = t;
|
|
63
|
+
let o = a(void 0), c = a(void 0), l = n((e) => {
|
|
64
|
+
let t = () => e();
|
|
65
|
+
return r.on("change", t), () => r.off("change", t);
|
|
66
|
+
}, [r]), u = n(() => {
|
|
67
|
+
let t = f(r, e, i.current);
|
|
68
|
+
if (Object.is(t, o.current)) return o.current;
|
|
69
|
+
if (typeof t != "object" || !t) return o.current = t, t;
|
|
70
|
+
try {
|
|
71
|
+
let e = JSON.stringify(t);
|
|
72
|
+
if (o.current !== void 0 && e === c.current) return o.current;
|
|
73
|
+
o.current = t, c.current = e;
|
|
74
|
+
} catch {
|
|
75
|
+
o.current = t;
|
|
76
|
+
}
|
|
77
|
+
return t;
|
|
78
|
+
}, [r, e]);
|
|
79
|
+
return s(l, u, u);
|
|
80
|
+
}
|
|
81
|
+
function m() {
|
|
82
|
+
let { client: e } = d();
|
|
83
|
+
return e;
|
|
84
|
+
}
|
|
85
|
+
function h() {
|
|
86
|
+
let { isReady: e, isError: t, error: n } = d();
|
|
87
|
+
return {
|
|
88
|
+
isReady: e,
|
|
89
|
+
isError: t,
|
|
90
|
+
error: n
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { e as FeatureflipContext, u as FeatureflipProvider, t as TestFeatureflipProvider, p as useFeatureFlag, m as useFeatureflipClient, h as useFeatureflipStatus };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface FeatureflipProviderProps {
|
|
3
|
+
clientKey: string;
|
|
4
|
+
context?: Record<string, unknown>;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
streaming?: boolean;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function FeatureflipProvider({ clientKey, context, baseUrl, streaming, children, }: FeatureflipProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIpE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,GACT,EAAE,wBAAwB,2CAmF1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let e=require(`react`),t=require(`@featureflip/browser`),n=require(`react/jsx-runtime`);var r=(0,e.createContext)(null);function i({flags:e,children:i}){let a=t.FeatureflipClient.forTesting(e);return(0,n.jsx)(r.Provider,{value:{client:a,isReady:!0,isError:!1,error:null},children:i})}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return i}});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createContext as e } from "react";
|
|
2
|
+
import { FeatureflipClient as t } from "@featureflip/browser";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
+
//#region src/context.ts
|
|
5
|
+
var r = e(null);
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/testing.tsx
|
|
8
|
+
function i({ flags: e, children: i }) {
|
|
9
|
+
let a = t.forTesting(e);
|
|
10
|
+
return /* @__PURE__ */ n(r.Provider, {
|
|
11
|
+
value: {
|
|
12
|
+
client: a,
|
|
13
|
+
isReady: !0,
|
|
14
|
+
isError: !1,
|
|
15
|
+
error: null
|
|
16
|
+
},
|
|
17
|
+
children: i
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { r as n, i as t };
|
package/dist/testing.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./testing-CXh0WG3c.cjs`);exports.TestFeatureflipProvider=e.t;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface TestFeatureflipProviderProps {
|
|
3
|
+
flags: Record<string, unknown>;
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
export declare function TestFeatureflipProvider({ flags, children }: TestFeatureflipProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,UAAU,4BAA4B;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,uBAAuB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,4BAA4B,2CAOxF"}
|
package/dist/testing.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@featureflip/react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React SDK for Featureflip - React bindings for feature flag evaluation",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./testing": {
|
|
16
|
+
"types": "./dist/testing.d.ts",
|
|
17
|
+
"import": "./dist/testing.js",
|
|
18
|
+
"require": "./dist/testing.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "vite build",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest"
|
|
28
|
+
},
|
|
29
|
+
"license": "Apache-2.0",
|
|
30
|
+
"homepage": "https://featureflip.io/docs",
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@featureflip/browser": "^1.0.0",
|
|
36
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.19.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@featureflip/browser": "file:../browser-sdk",
|
|
43
|
+
"@testing-library/react": "^16.0.0",
|
|
44
|
+
"@types/react": "^19.1.0",
|
|
45
|
+
"@types/react-dom": "^19.1.0",
|
|
46
|
+
"jsdom": "^28.0.0",
|
|
47
|
+
"react": "^19.1.0",
|
|
48
|
+
"react-dom": "^19.1.0",
|
|
49
|
+
"typescript": "^5.9.0",
|
|
50
|
+
"vite": "^8.0.0",
|
|
51
|
+
"vite-plugin-dts": "^4.0.0",
|
|
52
|
+
"vitest": "^4.1.0"
|
|
53
|
+
}
|
|
54
|
+
}
|