@variantlab/react 0.1.0 → 0.1.2
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 +169 -5
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,11 +1,175 @@
|
|
|
1
1
|
# @variantlab/react
|
|
2
2
|
|
|
3
|
-
React hooks and components for variantlab.
|
|
3
|
+
> React hooks and components for variantlab — the universal, zero-dependency A/B testing toolkit.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
|
+

|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Install
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
```bash
|
|
11
|
+
npm install @variantlab/core@alpha @variantlab/react@alpha
|
|
12
|
+
```
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
**Peer dependencies:** `react ^18.2.0 || ^19.0.0`
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
### 1. Create the engine and wrap your app
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { createEngine } from "@variantlab/core";
|
|
22
|
+
import { VariantLabProvider } from "@variantlab/react";
|
|
23
|
+
import experiments from "./experiments.json";
|
|
24
|
+
|
|
25
|
+
const engine = createEngine(experiments);
|
|
26
|
+
|
|
27
|
+
export default function App() {
|
|
28
|
+
return (
|
|
29
|
+
<VariantLabProvider engine={engine}>
|
|
30
|
+
<YourApp />
|
|
31
|
+
</VariantLabProvider>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 2. Use hooks
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { useVariant, useVariantValue } from "@variantlab/react";
|
|
40
|
+
|
|
41
|
+
function HeroSection() {
|
|
42
|
+
// Get the assigned variant ID
|
|
43
|
+
const variant = useVariant("hero-layout"); // "centered" | "split"
|
|
44
|
+
|
|
45
|
+
return variant === "split" ? <SplitHero /> : <CenteredHero />;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function CheckoutButton() {
|
|
49
|
+
// Get a value experiment's value directly
|
|
50
|
+
const copy = useVariantValue<string>("cta-copy"); // "Buy now" | "Get started"
|
|
51
|
+
|
|
52
|
+
return <button>{copy}</button>;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 3. Or use components
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { Variant, VariantValue } from "@variantlab/react";
|
|
60
|
+
|
|
61
|
+
function HeroSection() {
|
|
62
|
+
return (
|
|
63
|
+
<Variant experimentId="hero-layout" fallback={<CenteredHero />}>
|
|
64
|
+
{{
|
|
65
|
+
centered: <CenteredHero />,
|
|
66
|
+
split: <SplitHero />,
|
|
67
|
+
}}
|
|
68
|
+
</Variant>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function CheckoutButton() {
|
|
73
|
+
return (
|
|
74
|
+
<VariantValue experimentId="cta-copy">
|
|
75
|
+
{(value) => <button>{value}</button>}
|
|
76
|
+
</VariantValue>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Hooks API
|
|
82
|
+
|
|
83
|
+
### `useVariant(experimentId)`
|
|
84
|
+
|
|
85
|
+
Returns the assigned variant ID for a render experiment.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const variantId = useVariant("hero-layout"); // "centered" | "split"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `useVariantValue<T>(experimentId)`
|
|
92
|
+
|
|
93
|
+
Returns the value of a value experiment.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
const copy = useVariantValue<string>("cta-copy"); // "Buy now"
|
|
97
|
+
const price = useVariantValue<number>("pricing"); // 9.99
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `useExperiment(experimentId)`
|
|
101
|
+
|
|
102
|
+
Returns the full experiment state including metadata.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
const { variantId, experiment, isOverridden } = useExperiment("hero-layout");
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### `useSetVariant()`
|
|
109
|
+
|
|
110
|
+
Returns a function to override variant assignments (useful for debug UIs).
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
const setVariant = useSetVariant();
|
|
114
|
+
setVariant("hero-layout", "split"); // force split variant
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### `useVariantLabEngine()`
|
|
118
|
+
|
|
119
|
+
Returns the engine instance directly.
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
const engine = useVariantLabEngine();
|
|
123
|
+
engine.resetAll();
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `useRouteExperiments()`
|
|
127
|
+
|
|
128
|
+
Returns experiments that target the current route.
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
const experiments = useRouteExperiments();
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Components
|
|
135
|
+
|
|
136
|
+
### `<Variant>`
|
|
137
|
+
|
|
138
|
+
Renders the matching variant child by ID.
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<Variant experimentId="hero-layout" fallback={<Default />}>
|
|
142
|
+
{{
|
|
143
|
+
centered: <CenteredHero />,
|
|
144
|
+
split: <SplitHero />,
|
|
145
|
+
}}
|
|
146
|
+
</Variant>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `<VariantValue>`
|
|
150
|
+
|
|
151
|
+
Render-prop component for value experiments.
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
<VariantValue experimentId="cta-copy">
|
|
155
|
+
{(value) => <span>{value}</span>}
|
|
156
|
+
</VariantValue>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `<VariantErrorBoundary>`
|
|
160
|
+
|
|
161
|
+
Error boundary with crash-rollback integration. If a variant crashes N times, the engine auto-reverts to the default variant.
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<VariantErrorBoundary experimentId="hero-layout" fallback={<ErrorFallback />}>
|
|
165
|
+
<HeroSection />
|
|
166
|
+
</VariantErrorBoundary>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Type safety with codegen
|
|
170
|
+
|
|
171
|
+
Run `npx variantlab generate` to generate TypeScript types from your `experiments.json`. Experiment IDs and variant IDs become literal types — typos become compile errors.
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
[MIT](./LICENSE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@variantlab/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "React hooks and components for variantlab.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -40,18 +40,18 @@
|
|
|
40
40
|
],
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/
|
|
43
|
+
"url": "git+https://github.com/Minhaj-Rabby/variantlab.git",
|
|
44
44
|
"directory": "packages/react"
|
|
45
45
|
},
|
|
46
46
|
"bugs": {
|
|
47
|
-
"url": "https://github.com/
|
|
47
|
+
"url": "https://github.com/Minhaj-Rabby/variantlab/issues"
|
|
48
48
|
},
|
|
49
|
-
"homepage": "https://github.com/
|
|
49
|
+
"homepage": "https://github.com/Minhaj-Rabby/variantlab#readme",
|
|
50
50
|
"engines": {
|
|
51
51
|
"node": ">=18.17"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@variantlab/core": "0.1.
|
|
54
|
+
"@variantlab/core": "0.1.2"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"react": "^18.2.0 || ^19.0.0"
|