@mieweb/forms-editor 0.1.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,256 @@
1
+ # @mieweb/forms-editor
2
+
3
+ Embeddable questionnaire editor component with drag-and-drop, FHIR export, and conditional logic support.
4
+
5
+ ## 📦 Installation
6
+
7
+ ```bash
8
+ npm install @mieweb/forms-editor
9
+ ```
10
+
11
+ ### Peer Dependencies
12
+
13
+ Ensure you have React 18+ installed:
14
+
15
+ ```bash
16
+ npm install react react-dom
17
+ ```
18
+
19
+ ### Automatic Dependencies
20
+
21
+ The following are installed automatically:
22
+
23
+ - `@mieweb/forms-engine` - Core form state and field components
24
+ - `framer-motion` - Animations
25
+ - `js-yaml` - YAML import/export
26
+
27
+ ## 🚀 Quick Start
28
+
29
+ ### 1. Import Styles
30
+
31
+ ```jsx
32
+ import '@mieweb/forms-editor/styles.css';
33
+ ```
34
+
35
+ ### 2. Basic Usage
36
+
37
+ ```jsx
38
+ import { QuestionnaireEditor } from '@mieweb/forms-editor';
39
+
40
+ function App() {
41
+ const handleChange = (fields) => {
42
+ console.log('Form updated:', fields);
43
+ };
44
+
45
+ return (
46
+ <QuestionnaireEditor
47
+ onChange={handleChange}
48
+ />
49
+ );
50
+ }
51
+ ```
52
+
53
+ ### 3. With Initial Data
54
+
55
+ ```jsx
56
+ import { QuestionnaireEditor } from '@mieweb/forms-editor';
57
+
58
+ const initialFields = [
59
+ {
60
+ id: '1',
61
+ fieldType: 'input',
62
+ question: 'What is your name?',
63
+ answer: ''
64
+ },
65
+ {
66
+ id: '2',
67
+ fieldType: 'radio',
68
+ question: 'Select your role',
69
+ options: ['Developer', 'Designer', 'Manager'],
70
+ selected: null
71
+ }
72
+ ];
73
+
74
+ function App() {
75
+ return (
76
+ <QuestionnaireEditor
77
+ initialFields={initialFields}
78
+ onChange={(fields) => console.log(fields)}
79
+ />
80
+ );
81
+ }
82
+ ```
83
+
84
+ ## 📖 Props
85
+
86
+ ### `QuestionnaireEditor`
87
+
88
+ | Prop | Type | Default | Description |
89
+ |------|------|---------|-------------|
90
+ | `initialFields` | `Array` | `[]` | Initial questionnaire fields |
91
+ | `onChange` | `Function` | `undefined` | Callback when fields change: `(fields) => void` |
92
+ | `className` | `String` | `''` | Additional CSS classes |
93
+ | `showHeader` | `Boolean` | `true` | Show/hide the header with actions |
94
+ | `showMobileToolbar` | `Boolean` | `true` | Show/hide mobile toolbar |
95
+ | `startInPreview` | `Boolean` | `false` | Start in preview mode |
96
+
97
+ ## ✨ Features
98
+
99
+ ### 🎨 Add & Edit Fields
100
+
101
+ Add fields from the toolbar:
102
+ - **Text Input** - Single-line text
103
+ - **Radio Buttons** - Single choice
104
+ - **Checkboxes** - Multiple choice
105
+ - **Dropdown** - Select menu
106
+ - **Section** - Group fields together
107
+
108
+ ### 🔄 Import/Export
109
+
110
+ Built-in support for:
111
+ - **JSON** - Questionnaire data format
112
+ - **FHIR** - FHIR Questionnaire standard
113
+ - **YAML** - Human-readable format
114
+
115
+ ```jsx
116
+ import { useFormStore } from '@mieweb/forms-engine';
117
+
118
+ function ExportButtons() {
119
+ const fields = useFormStore(state => state.flatArray());
120
+
121
+ const exportJSON = () => {
122
+ const json = JSON.stringify(fields, null, 2);
123
+ // Download or save
124
+ };
125
+
126
+ return <button onClick={exportJSON}>Export JSON</button>;
127
+ }
128
+ ```
129
+
130
+ ### 🔀 Conditional Logic (enableWhen)
131
+
132
+ Show/hide fields based on answers to other fields:
133
+
134
+ 1. Select a field
135
+ 2. Click "Logic" in the edit panel
136
+ 3. Add conditions (e.g., "Show when Question 1 equals 'Yes'")
137
+
138
+ ### 📱 Mobile Responsive
139
+
140
+ - Desktop: Side-by-side editor and preview
141
+ - Mobile: Swipeable modal for field editing
142
+
143
+ ### 🎭 Preview Mode
144
+
145
+ Toggle preview mode to see how the form looks to end users:
146
+
147
+ ```jsx
148
+ <QuestionnaireEditor startInPreview={true} />
149
+ ```
150
+
151
+ ## 🎯 Advanced Usage
152
+
153
+ ### Custom Styling
154
+
155
+ ```jsx
156
+ <QuestionnaireEditor
157
+ className="my-custom-editor"
158
+ onChange={handleChange}
159
+ />
160
+ ```
161
+
162
+ ```css
163
+ .my-custom-editor {
164
+ --primary-color: #3b82f6;
165
+ --border-radius: 0.5rem;
166
+ }
167
+ ```
168
+
169
+ ### Controlled State
170
+
171
+ ```jsx
172
+ import { QuestionnaireEditor } from '@mieweb/forms-editor';
173
+ import { useFormStore } from '@mieweb/forms-engine';
174
+ import { useEffect } from 'react';
175
+
176
+ function ControlledEditor() {
177
+ const [savedFields, setSavedFields] = useState([]);
178
+
179
+ const handleChange = (fields) => {
180
+ setSavedFields(fields);
181
+ localStorage.setItem('questionnaire', JSON.stringify(fields));
182
+ };
183
+
184
+ return (
185
+ <QuestionnaireEditor
186
+ initialFields={savedFields}
187
+ onChange={handleChange}
188
+ />
189
+ );
190
+ }
191
+ ```
192
+
193
+ ### Accessing Internal State
194
+
195
+ ```jsx
196
+ import { useFormStore, useUIStore } from '@mieweb/forms-engine';
197
+
198
+ function EditorWithStatus() {
199
+ const fieldCount = useFormStore(state => Object.keys(state.byId).length);
200
+ const isPreview = useUIStore(state => state.preview);
201
+
202
+ return (
203
+ <div>
204
+ <p>{fieldCount} fields | Mode: {isPreview ? 'Preview' : 'Edit'}</p>
205
+ <QuestionnaireEditor />
206
+ </div>
207
+ );
208
+ }
209
+ ```
210
+
211
+ ## 🔧 Field Structure
212
+
213
+ Each field follows this structure:
214
+
215
+ ```js
216
+ {
217
+ id: 'unique-id', // Required: unique identifier
218
+ fieldType: 'input', // Required: 'input', 'radio', 'check', 'dropdown', 'section'
219
+ question: 'Your question?', // Required: field label
220
+ answer: '', // For input fields
221
+ options: ['A', 'B', 'C'], // For radio/check/dropdown
222
+ selected: null, // For radio (single choice)
223
+ selectedOptions: [], // For check (multiple choice)
224
+ fields: [], // For section (nested fields)
225
+ enableWhen: [ // Optional: conditional logic
226
+ {
227
+ question: 'field-id',
228
+ operator: 'equals',
229
+ answer: 'Yes'
230
+ }
231
+ ]
232
+ }
233
+ ```
234
+
235
+ ## 📦 Bundle Size
236
+
237
+ - **48.13 KB** (ESM, uncompressed)
238
+ - **489 B** CSS
239
+
240
+ ## 🎨 Theming
241
+
242
+ The editor uses Tailwind CSS under the hood. Import your own Tailwind config or override classes:
243
+
244
+ ```jsx
245
+ import '@mieweb/forms-editor/styles.css';
246
+ import './my-overrides.css'; // Your custom styles
247
+ ```
248
+
249
+ ## 🔗 Related Packages
250
+
251
+ - **@mieweb/forms-engine** - Core form primitives (auto-installed)
252
+ - **@mieweb/forms-renderer** - Read-only renderer for filled forms
253
+
254
+ ## 📄 License
255
+
256
+ MIT
package/dist/index.css ADDED
@@ -0,0 +1,6 @@
1
+ @import "https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap";
2
+ @import "tailwindcss";
3
+
4
+ /* src/index.css */
5
+ @theme { --font-titillium: "Titillium Web", sans-serif; }
6
+ @utility custom-scrollbar { @apply [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:rounded-full [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-gray-500 }