@feedvalue/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 +124 -33
- package/package.json +13 -14
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @feedvalue/react
|
|
2
2
|
|
|
3
|
-
React SDK for FeedValue feedback widget. Provides Provider
|
|
3
|
+
React SDK for FeedValue feedback widget. Provides Provider and Hooks for React 18+.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -55,25 +55,71 @@ export function FeedbackButton() {
|
|
|
55
55
|
}
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
###
|
|
58
|
+
### Headless Mode
|
|
59
|
+
|
|
60
|
+
For complete UI control, use headless mode. The SDK fetches config and provides all API methods but renders no trigger button or modal:
|
|
59
61
|
|
|
60
62
|
```tsx
|
|
63
|
+
// app/layout.tsx
|
|
64
|
+
import { FeedValueProvider } from '@feedvalue/react';
|
|
65
|
+
|
|
66
|
+
export default function RootLayout({ children }) {
|
|
67
|
+
return (
|
|
68
|
+
<html>
|
|
69
|
+
<body>
|
|
70
|
+
<FeedValueProvider widgetId="your-widget-id" headless>
|
|
71
|
+
{children}
|
|
72
|
+
</FeedValueProvider>
|
|
73
|
+
</body>
|
|
74
|
+
</html>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
// components/custom-feedback.tsx
|
|
61
81
|
'use client';
|
|
62
82
|
|
|
63
|
-
import {
|
|
83
|
+
import { useState } from 'react';
|
|
84
|
+
import { useFeedValue } from '@feedvalue/react';
|
|
85
|
+
|
|
86
|
+
export function CustomFeedback() {
|
|
87
|
+
const { isReady, isOpen, open, close, submit, isSubmitting, isHeadless } = useFeedValue();
|
|
88
|
+
const [message, setMessage] = useState('');
|
|
89
|
+
|
|
90
|
+
const handleSubmit = async () => {
|
|
91
|
+
await submit({ message });
|
|
92
|
+
setMessage('');
|
|
93
|
+
close();
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
if (!isReady) return null;
|
|
64
97
|
|
|
65
|
-
// Standalone widget (no Provider needed)
|
|
66
|
-
export function FeedbackWidget() {
|
|
67
98
|
return (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
99
|
+
<>
|
|
100
|
+
<button onClick={open}>Feedback</button>
|
|
101
|
+
|
|
102
|
+
{isOpen && (
|
|
103
|
+
<dialog open className="feedback-modal">
|
|
104
|
+
<textarea
|
|
105
|
+
value={message}
|
|
106
|
+
onChange={(e) => setMessage(e.target.value)}
|
|
107
|
+
placeholder="Your feedback..."
|
|
108
|
+
/>
|
|
109
|
+
<div>
|
|
110
|
+
<button onClick={handleSubmit} disabled={isSubmitting}>
|
|
111
|
+
{isSubmitting ? 'Sending...' : 'Submit'}
|
|
112
|
+
</button>
|
|
113
|
+
<button onClick={close}>Cancel</button>
|
|
114
|
+
</div>
|
|
115
|
+
</dialog>
|
|
116
|
+
)}
|
|
117
|
+
</>
|
|
72
118
|
);
|
|
73
119
|
}
|
|
74
120
|
```
|
|
75
121
|
|
|
76
|
-
### Programmatic
|
|
122
|
+
### Programmatic Submission
|
|
77
123
|
|
|
78
124
|
```tsx
|
|
79
125
|
'use client';
|
|
@@ -107,8 +153,47 @@ export function FeedbackForm() {
|
|
|
107
153
|
}
|
|
108
154
|
```
|
|
109
155
|
|
|
156
|
+
### Custom Fields
|
|
157
|
+
|
|
158
|
+
Custom fields allow you to collect structured data beyond the main feedback message. **Custom fields must be defined in your widget configuration on the FeedValue dashboard before use.**
|
|
159
|
+
|
|
160
|
+
1. Go to your widget settings in the FeedValue dashboard
|
|
161
|
+
2. Add custom fields with types: `text`, `email`, or `emoji`
|
|
162
|
+
3. Use `customFieldValues` when submitting:
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
'use client';
|
|
166
|
+
|
|
167
|
+
import { useFeedValue } from '@feedvalue/react';
|
|
168
|
+
|
|
169
|
+
export function DetailedFeedback() {
|
|
170
|
+
const { submit, isReady } = useFeedValue();
|
|
171
|
+
|
|
172
|
+
const handleSubmit = async () => {
|
|
173
|
+
await submit({
|
|
174
|
+
message: 'Detailed feedback',
|
|
175
|
+
customFieldValues: {
|
|
176
|
+
// Field IDs must match those defined in your widget configuration
|
|
177
|
+
name: 'John Doe',
|
|
178
|
+
category: 'feature',
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<button onClick={handleSubmit} disabled={!isReady}>
|
|
185
|
+
Submit Feedback
|
|
186
|
+
</button>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
> **Important**: The field IDs in `customFieldValues` must match the field IDs defined in your widget configuration on the dashboard.
|
|
192
|
+
|
|
110
193
|
### User Identification
|
|
111
194
|
|
|
195
|
+
Attach user context to feedback submissions. This data is **not shown in the widget UI** but is stored with the submission and visible in your FeedValue dashboard:
|
|
196
|
+
|
|
112
197
|
```tsx
|
|
113
198
|
'use client';
|
|
114
199
|
|
|
@@ -135,22 +220,27 @@ export function UserIdentifier({ user }) {
|
|
|
135
220
|
}
|
|
136
221
|
```
|
|
137
222
|
|
|
223
|
+
> **User Data vs Custom Fields**
|
|
224
|
+
> - **User data** (`identify`/`setData`): Hidden from users, automatically attached to submissions. Use for internal context like user IDs, subscription plans, etc.
|
|
225
|
+
> - **Custom fields** (`customFieldValues`): Shown as form inputs in the widget. Users fill these in themselves. Must be defined in widget configuration first.
|
|
226
|
+
|
|
138
227
|
## API Reference
|
|
139
228
|
|
|
140
229
|
### `<FeedValueProvider>`
|
|
141
230
|
|
|
142
231
|
Provider component for FeedValue context.
|
|
143
232
|
|
|
144
|
-
| Prop | Type | Required | Description |
|
|
145
|
-
|
|
146
|
-
| `widgetId` | `string` | Yes | Widget ID from FeedValue dashboard |
|
|
147
|
-
| `apiBaseUrl` | `string` | No | Custom API URL (for self-hosted) |
|
|
148
|
-
| `config` | `Partial<FeedValueConfig>` | No | Configuration overrides |
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
233
|
+
| Prop | Type | Required | Default | Description |
|
|
234
|
+
|------|------|----------|---------|-------------|
|
|
235
|
+
| `widgetId` | `string` | Yes | - | Widget ID from FeedValue dashboard |
|
|
236
|
+
| `apiBaseUrl` | `string` | No | Production URL | Custom API URL (for self-hosted) |
|
|
237
|
+
| `config` | `Partial<FeedValueConfig>` | No | - | Configuration overrides |
|
|
238
|
+
| `headless` | `boolean` | No | `false` | Disable all DOM rendering |
|
|
239
|
+
| `onReady` | `() => void` | No | - | Called when widget is ready |
|
|
240
|
+
| `onOpen` | `() => void` | No | - | Called when modal opens |
|
|
241
|
+
| `onClose` | `() => void` | No | - | Called when modal closes |
|
|
242
|
+
| `onSubmit` | `(feedback: FeedbackData) => void` | No | - | Called when feedback is submitted |
|
|
243
|
+
| `onError` | `(error: Error) => void` | No | - | Called on errors |
|
|
154
244
|
|
|
155
245
|
### `useFeedValue()`
|
|
156
246
|
|
|
@@ -160,11 +250,13 @@ Returns:
|
|
|
160
250
|
|
|
161
251
|
| Property | Type | Description |
|
|
162
252
|
|----------|------|-------------|
|
|
253
|
+
| `instance` | `FeedValue \| null` | Raw FeedValue instance (advanced usage) |
|
|
163
254
|
| `isReady` | `boolean` | Widget is initialized |
|
|
164
255
|
| `isOpen` | `boolean` | Modal is open |
|
|
165
256
|
| `isVisible` | `boolean` | Trigger button is visible |
|
|
166
257
|
| `error` | `Error \| null` | Current error |
|
|
167
258
|
| `isSubmitting` | `boolean` | Submission in progress |
|
|
259
|
+
| `isHeadless` | `boolean` | Running in headless mode |
|
|
168
260
|
| `open` | `() => void` | Open the modal |
|
|
169
261
|
| `close` | `() => void` | Close the modal |
|
|
170
262
|
| `toggle` | `() => void` | Toggle modal |
|
|
@@ -179,19 +271,6 @@ Returns:
|
|
|
179
271
|
|
|
180
272
|
Same as `useFeedValue()` but returns `null` if used outside provider instead of throwing.
|
|
181
273
|
|
|
182
|
-
### `<FeedValueWidget>`
|
|
183
|
-
|
|
184
|
-
Standalone widget component that doesn't require a provider.
|
|
185
|
-
|
|
186
|
-
| Prop | Type | Required | Description |
|
|
187
|
-
|------|------|----------|-------------|
|
|
188
|
-
| `widgetId` | `string` | Yes | Widget ID from FeedValue dashboard |
|
|
189
|
-
| `apiBaseUrl` | `string` | No | Custom API URL |
|
|
190
|
-
| `config` | `Partial<FeedValueConfig>` | No | Configuration overrides |
|
|
191
|
-
| `onReady` | `() => void` | No | Ready callback |
|
|
192
|
-
| `onSubmit` | `(feedback) => void` | No | Submit callback |
|
|
193
|
-
| `onError` | `(error) => void` | No | Error callback |
|
|
194
|
-
|
|
195
274
|
## Server-Side Rendering
|
|
196
275
|
|
|
197
276
|
The SDK is fully SSR-compatible. It uses `useSyncExternalStore` for concurrent mode support and returns safe default values during server rendering.
|
|
@@ -214,6 +293,18 @@ export function FeedbackButton() {
|
|
|
214
293
|
}
|
|
215
294
|
```
|
|
216
295
|
|
|
296
|
+
## Default vs Headless Mode
|
|
297
|
+
|
|
298
|
+
| Feature | Default Mode | Headless Mode |
|
|
299
|
+
|---------|--------------|---------------|
|
|
300
|
+
| Trigger button | Dashboard-styled | You build it |
|
|
301
|
+
| Modal | Dashboard-styled | You build it |
|
|
302
|
+
| API methods | Available | Available |
|
|
303
|
+
| User tracking | Available | Available |
|
|
304
|
+
| Dashboard config | Fetched | Fetched |
|
|
305
|
+
|
|
306
|
+
Use `headless={true}` when you want complete control over the UI.
|
|
307
|
+
|
|
217
308
|
## Requirements
|
|
218
309
|
|
|
219
310
|
- React 18.0.0 or higher
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feedvalue/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "FeedValue React SDK - Provider, Hooks, and Components for React 18+",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -23,12 +23,22 @@
|
|
|
23
23
|
"README.md"
|
|
24
24
|
],
|
|
25
25
|
"sideEffects": false,
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"lint": "eslint src",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"test:coverage": "vitest run --coverage",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"clean": "rm -rf dist"
|
|
35
|
+
},
|
|
26
36
|
"peerDependencies": {
|
|
27
37
|
"react": ">=18.0.0",
|
|
28
38
|
"react-dom": ">=18.0.0"
|
|
29
39
|
},
|
|
30
40
|
"dependencies": {
|
|
31
|
-
"@feedvalue/core": "
|
|
41
|
+
"@feedvalue/core": "workspace:^"
|
|
32
42
|
},
|
|
33
43
|
"devDependencies": {
|
|
34
44
|
"@testing-library/jest-dom": "^6.9.1",
|
|
@@ -36,7 +46,6 @@
|
|
|
36
46
|
"@types/react": "^19.0.0",
|
|
37
47
|
"@types/react-dom": "^19.0.0",
|
|
38
48
|
"@vitest/coverage-v8": "^2.1.0",
|
|
39
|
-
"eslint": "^9.17.0",
|
|
40
49
|
"happy-dom": "^15.11.0",
|
|
41
50
|
"react": "^19.0.0",
|
|
42
51
|
"react-dom": "^19.0.0",
|
|
@@ -68,15 +77,5 @@
|
|
|
68
77
|
],
|
|
69
78
|
"engines": {
|
|
70
79
|
"node": ">=18"
|
|
71
|
-
},
|
|
72
|
-
"scripts": {
|
|
73
|
-
"build": "tsup",
|
|
74
|
-
"dev": "tsup --watch",
|
|
75
|
-
"lint": "eslint src --ext .ts,.tsx",
|
|
76
|
-
"test": "vitest run",
|
|
77
|
-
"test:watch": "vitest",
|
|
78
|
-
"test:coverage": "vitest run --coverage",
|
|
79
|
-
"typecheck": "tsc --noEmit",
|
|
80
|
-
"clean": "rm -rf dist"
|
|
81
80
|
}
|
|
82
|
-
}
|
|
81
|
+
}
|