@mieweb/forms-renderer 0.1.4 → 0.1.6
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 +95 -83
- package/dist/index.js +387 -373
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @mieweb/forms-renderer
|
|
1
|
+
# @mieweb/forms-renderer `v0.1.5`
|
|
2
2
|
|
|
3
3
|
Read-only questionnaire renderer for displaying and filling out forms. Produces FHIR QuestionnaireResponse output.
|
|
4
4
|
|
|
@@ -8,9 +8,9 @@ Read-only questionnaire renderer for displaying and filling out forms. Produces
|
|
|
8
8
|
npm install @mieweb/forms-renderer
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
### Peer Dependencies
|
|
11
|
+
### Peer Dependencies (Required)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
You must install React 18+ in your project:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
npm install react react-dom
|
|
@@ -24,34 +24,77 @@ The following is installed automatically:
|
|
|
24
24
|
|
|
25
25
|
## 🚀 Quick Start
|
|
26
26
|
|
|
27
|
-
###
|
|
27
|
+
### Basic Usage
|
|
28
28
|
|
|
29
29
|
```jsx
|
|
30
30
|
import { QuestionnaireRenderer } from '@mieweb/forms-renderer';
|
|
31
|
+
import { createRoot } from 'react-dom/client';
|
|
32
|
+
import './index.css';
|
|
31
33
|
|
|
32
|
-
function App(
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Send to your backend
|
|
40
|
-
};
|
|
34
|
+
function App() {
|
|
35
|
+
const [fields] = React.useState([
|
|
36
|
+
{ id: 'sec-1', fieldType: 'section', title: 'Personal Info', fields: [] },
|
|
37
|
+
{ id: 'q-name', fieldType: 'input', question: 'What is your name?', answer: '' },
|
|
38
|
+
{ id: 'q-gender', fieldType: 'radio', question: 'Gender', options: [{ value: 'Male' }, { value: 'Female' }], selected: null },
|
|
39
|
+
]);
|
|
40
|
+
const [submitted, setSubmitted] = React.useState(null);
|
|
41
41
|
|
|
42
42
|
return (
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
<div className="w-full h-dvh bg-slate-100">
|
|
44
|
+
<div className="absolute inset-0 overflow-auto p-4 max-w-4xl mx-auto w-full">
|
|
45
|
+
<QuestionnaireRenderer
|
|
46
|
+
questionnaireId="demo-1"
|
|
47
|
+
fields={fields}
|
|
48
|
+
onSubmit={(qr) => setSubmitted(qr)}
|
|
49
|
+
/>
|
|
50
|
+
{submitted && (
|
|
51
|
+
<pre className="mt-4 bg-neutral-100 p-4">{JSON.stringify(submitted, null, 2)}</pre>
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
50
55
|
);
|
|
51
56
|
}
|
|
57
|
+
|
|
58
|
+
createRoot(document.getElementById('root')).render(<App />);
|
|
52
59
|
```
|
|
53
60
|
|
|
54
|
-
###
|
|
61
|
+
### Loading from API
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
function App() {
|
|
65
|
+
const [fields, setFields] = React.useState([]);
|
|
66
|
+
const [loading, setLoading] = React.useState(true);
|
|
67
|
+
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
fetch('/api/questionnaire/123')
|
|
70
|
+
.then(res => res.json())
|
|
71
|
+
.then(data => {
|
|
72
|
+
setFields(data.fields);
|
|
73
|
+
setLoading(false);
|
|
74
|
+
});
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
77
|
+
if (loading) return <div>Loading...</div>;
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div className="absolute inset-0 overflow-auto p-4">
|
|
81
|
+
<QuestionnaireRenderer
|
|
82
|
+
questionnaireId="patient-intake-v1"
|
|
83
|
+
subjectId="patient-12345"
|
|
84
|
+
fields={fields}
|
|
85
|
+
onSubmit={async (fhirResponse) => {
|
|
86
|
+
await fetch('/api/responses', {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
headers: { 'Content-Type': 'application/json' },
|
|
89
|
+
body: JSON.stringify(fhirResponse)
|
|
90
|
+
});
|
|
91
|
+
alert('Submitted!');
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
55
98
|
|
|
56
99
|
The `fields` prop accepts any data source (API, database, local storage) that matches this JSON structure:
|
|
57
100
|
|
|
@@ -122,6 +165,8 @@ The `fields` prop accepts any data source (API, database, local storage) that ma
|
|
|
122
165
|
|
|
123
166
|
**Any JSON object matching this structure works** - whether from your backend API, a database query, local storage, or a CMS.
|
|
124
167
|
|
|
168
|
+
---
|
|
169
|
+
|
|
125
170
|
## 📖 Props
|
|
126
171
|
|
|
127
172
|
### `QuestionnaireRenderer`
|
|
@@ -211,41 +256,9 @@ On submit, generates a standard FHIR R4 QuestionnaireResponse:
|
|
|
211
256
|
}
|
|
212
257
|
```
|
|
213
258
|
|
|
214
|
-
## 🎯 Usage
|
|
259
|
+
## 🎯 Advanced Usage
|
|
215
260
|
|
|
216
|
-
###
|
|
217
|
-
|
|
218
|
-
```jsx
|
|
219
|
-
import { QuestionnaireRenderer } from '@mieweb/forms-renderer';
|
|
220
|
-
import { useState } from 'react';
|
|
221
|
-
|
|
222
|
-
function FormPage() {
|
|
223
|
-
const [responses, setResponses] = useState([]);
|
|
224
|
-
|
|
225
|
-
const handleSubmit = async (fhirResponse) => {
|
|
226
|
-
// Save to backend
|
|
227
|
-
await fetch('/api/responses', {
|
|
228
|
-
method: 'POST',
|
|
229
|
-
headers: { 'Content-Type': 'application/json' },
|
|
230
|
-
body: JSON.stringify(fhirResponse)
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
setResponses([...responses, fhirResponse]);
|
|
234
|
-
alert('Form submitted successfully!');
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
return (
|
|
238
|
-
<QuestionnaireRenderer
|
|
239
|
-
fields={fields}
|
|
240
|
-
onSubmit={handleSubmit}
|
|
241
|
-
questionnaireId="patient-intake"
|
|
242
|
-
subjectId="patient-67890"
|
|
243
|
-
/>
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### Pre-filled Form
|
|
261
|
+
### Pre-filled Responses
|
|
249
262
|
|
|
250
263
|
```jsx
|
|
251
264
|
const prefilledFields = [
|
|
@@ -259,42 +272,37 @@ const prefilledFields = [
|
|
|
259
272
|
id: '2',
|
|
260
273
|
fieldType: 'radio',
|
|
261
274
|
question: 'Gender',
|
|
262
|
-
options: ['Male', 'Female', 'Other'],
|
|
263
|
-
selected: 'Female' // Pre-filled
|
|
275
|
+
options: [{ value: 'Male' }, { value: 'Female' }, { value: 'Other' }],
|
|
276
|
+
selected: { value: 'Female' } // Pre-filled
|
|
264
277
|
}
|
|
265
278
|
];
|
|
266
279
|
|
|
267
|
-
<QuestionnaireRenderer
|
|
280
|
+
<QuestionnaireRenderer
|
|
281
|
+
fields={prefilledFields}
|
|
282
|
+
questionnaireId="follow-up-visit"
|
|
283
|
+
subjectId="patient-67890"
|
|
284
|
+
/>
|
|
268
285
|
```
|
|
269
286
|
|
|
270
|
-
###
|
|
287
|
+
### Track Form Changes
|
|
271
288
|
|
|
272
289
|
```jsx
|
|
273
|
-
function
|
|
274
|
-
const [
|
|
275
|
-
|
|
276
|
-
const handleChange = (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
fields.forEach(field => {
|
|
280
|
-
if (field.required && !field.answer && !field.selected) {
|
|
281
|
-
newErrors[field.id] = 'This field is required';
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
setErrors(newErrors);
|
|
290
|
+
function App() {
|
|
291
|
+
const [fields, setFields] = React.useState(initialFields);
|
|
292
|
+
|
|
293
|
+
const handleChange = (updatedFields) => {
|
|
294
|
+
setFields(updatedFields);
|
|
295
|
+
console.log('User updated:', updatedFields);
|
|
286
296
|
};
|
|
287
297
|
|
|
288
298
|
return (
|
|
289
|
-
<
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
))}
|
|
297
|
-
</div>
|
|
299
|
+
<QuestionnaireRenderer
|
|
300
|
+
fields={fields}
|
|
301
|
+
onChange={handleChange}
|
|
302
|
+
onSubmit={(fhirResponse) => {
|
|
303
|
+
console.log('Submitting:', fhirResponse);
|
|
304
|
+
}}
|
|
305
|
+
/>
|
|
298
306
|
);
|
|
299
307
|
}
|
|
300
308
|
```
|
|
@@ -319,8 +327,12 @@ Fields use the same structure as `@mieweb/forms-editor`:
|
|
|
319
327
|
|
|
320
328
|
## 📦 Bundle Size
|
|
321
329
|
|
|
322
|
-
- **
|
|
323
|
-
-
|
|
330
|
+
- **ESM format** with tree-shaking support
|
|
331
|
+
- **TypeScript definitions** included
|
|
332
|
+
- **Very lightweight** - perfect for embedding in patient portals
|
|
333
|
+
- **CSS automatically injected** via `@mieweb/forms-engine` dependency
|
|
334
|
+
- Dependencies: `@mieweb/forms-engine` (auto-installed)
|
|
335
|
+
- Peer dependencies: React 18+
|
|
324
336
|
|
|
325
337
|
## 🎨 Styling
|
|
326
338
|
|