@reactfast/forms 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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jonathon McClendon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,439 @@
1
+ # 🎛️ @reactfast/forms
2
+
3
+ **Dynamic React forms powered by JSON schemas, modifiers, and subforms.**
4
+ Create complex, adaptive form systems without boilerplate — designed for scale, simplicity, and composability.
5
+
6
+ [![npm version](https://img.shields.io/npm/v/@reactfast/forms.svg)](https://www.npmjs.com/package/@reactfast/forms)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
+ [![Build](https://github.com/jonathonmcclendon/NovaForms/actions/workflows/build.yml/badge.svg)](https://github.com/jonathonmcclendon/NovaForms/actions)
9
+ [![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg)](https://github.com/jonathonmcclendon/NovaForms/issues)
10
+
11
+ ### 📚 [**View Live Documentation**](https://nova-forms-next.vercel.app/) 📚
12
+
13
+ ---
14
+
15
+ ## ⚙️ Installation
16
+
17
+ ```bash
18
+ npm install @reactfast/forms
19
+ # or
20
+ yarn add @reactfast/forms
21
+ ```
22
+
23
+ CtrlForm requires **React 18+** and **React DOM 18+** as peer dependencies.
24
+
25
+ ---
26
+
27
+ ## 🚀 Quick Start
28
+
29
+ The simplest way to get started:
30
+
31
+ ```jsx
32
+ import { useState } from "react";
33
+ import { Form, createFormHandler } from "@reactfast/forms";
34
+
35
+ const fields = [
36
+ { name: "firstName", title: "First Name", type: "string", width: 50 },
37
+ { name: "lastName", title: "Last Name", type: "string", width: 50 },
38
+ { name: "email", title: "Email", type: "email", width: 100 },
39
+ { name: "subscribe", title: "Subscribe?", type: "boolean", width: 100 },
40
+ ];
41
+
42
+ export default function App() {
43
+ const [formData, setFormData] = useState({});
44
+
45
+ const handleChange = createFormHandler({
46
+ fields,
47
+ setState: setFormData,
48
+ });
49
+
50
+ return (
51
+ <Form
52
+ fields={fields}
53
+ onChange={handleChange}
54
+ formData={formData}
55
+ />
56
+ );
57
+ }
58
+ ```
59
+
60
+ ---
61
+
62
+ ## ✨ Features
63
+
64
+ - ⚡ **Controlled forms** — simple `value`/`onChange` pattern like React inputs
65
+ - 🧩 **Composable** — each field is a reusable React component
66
+ - 🔄 **Advanced conditional logic** — dynamic show/hide, disable, and field dependencies
67
+ - 📱 **Responsive layout** — automatic width handling with Tailwind classes
68
+ - 🧱 **Subforms & arrays** — nested or repeated field groups are first-class citizens
69
+ - 🎨 **Theming-ready** — customize UI with Tailwind or your own design system
70
+ - 🔌 **Extensible** — register your own field components via `registerField()`
71
+ - 🧠 **Smart rules system** — powerful top-level rules with field-level triggers
72
+ - 🔢 **Math operations** — automatic calculations with add, subtract, multiply, divide
73
+ - 📝 **String operations** — concatenation and text manipulation
74
+ - ✅ **Pattern validation** — client-side regex validation with custom messages
75
+ - 🎯 **Multiple field types** — 20+ built-in field types from text to file uploads
76
+
77
+ ---
78
+
79
+ ## 🎯 Built-in Field Types
80
+
81
+ Nova Forms comes with 20+ field types ready to use:
82
+
83
+ | Type | Description | Example |
84
+ |------|-------------|---------|
85
+ | `string` | Text input | `{ type: "string", title: "Name" }` |
86
+ | `text` | Textarea | `{ type: "text", title: "Description" }` |
87
+ | `email` | Email input with validation | `{ type: "email", title: "Email" }` |
88
+ | `tel` | Phone number input | `{ type: "tel", title: "Phone" }` |
89
+ | `url` | URL input | `{ type: "url", title: "Website" }` |
90
+ | `number` | Number input | `{ type: "number", title: "Age" }` |
91
+ | `boolean` | Checkbox | `{ type: "boolean", title: "Subscribe" }` |
92
+ | `toggle` | Toggle switch | `{ type: "toggle", title: "Enable" }` |
93
+ | `date` | Date picker | `{ type: "date", title: "Birth Date" }` |
94
+ | `datetime` | Date and time picker | `{ type: "datetime", title: "Event Time" }` |
95
+ | `time` | Time picker | `{ type: "time", title: "Start Time" }` |
96
+ | `color` | Color picker | `{ type: "color", title: "Theme Color" }` |
97
+ | `select` | Single select dropdown | `{ type: "select", options: [...] }` |
98
+ | `multiselect` | Multi-select dropdown | `{ type: "multiselect", options: [...] }` |
99
+ | `radio` | Radio button group | `{ type: "radio", options: [...] }` |
100
+ | `file` | File upload | `{ type: "file", title: "Upload" }` |
101
+ | `fileV2` | Enhanced file upload | `{ type: "fileV2", title: "Photo" }` |
102
+ | `uploadToBase` | Base64 image upload | `{ type: "uploadToBase", title: "Avatar" }` |
103
+ | `array` | Dynamic subform/array | `{ type: "array", fields: [...] }` |
104
+ | `subForm` | Nested form group | `{ type: "subForm", fields: [...] }` |
105
+ | `signature` | Signature pad | `{ type: "signature", title: "Signature" }` |
106
+ | `rating` | Star rating | `{ type: "rating", title: "Rating" }` |
107
+ | `scale` | Likert scale | `{ type: "scale", title: "Satisfaction" }` |
108
+ | `captcha` | reCAPTCHA | `{ type: "captcha" }` |
109
+ | `header` | Section header | `{ type: "header", title: "Section" }` |
110
+ | `paragraph` | Static text | `{ type: "paragraph", content: "Text" }` |
111
+ | `image` | Static image | `{ type: "image", image: { src: "..." } }` |
112
+
113
+ ---
114
+
115
+ ## 🧩 Example: Registering Custom Fields
116
+
117
+ You can extend Nova Forms with your own field types:
118
+
119
+ ```jsx
120
+ import { registerField } from "@reactfast/forms";
121
+
122
+ function QRCodeScannerField({ field, value, onChange }) {
123
+ return (
124
+ <div>
125
+ <p>Scan QR Code for {field.title}</p>
126
+ {/* Your scanner logic */}
127
+ </div>
128
+ );
129
+ }
130
+
131
+ registerField("qrScanner", QRCodeScannerField);
132
+ ```
133
+
134
+ Now use it in your fields array:
135
+
136
+ ```jsx
137
+ const fields = [
138
+ {
139
+ name: "eventCheckIn",
140
+ title: "Check In",
141
+ type: "qrScanner",
142
+ width: 100
143
+ }
144
+ ];
145
+ ```
146
+
147
+ ---
148
+
149
+ ## 🧠 API Overview
150
+
151
+ ### `Form`
152
+
153
+ Renders a form based on your field array with integrated modifiers and conditions.
154
+
155
+ | Prop | Type | Description |
156
+ | -------------- | --------------------- | ----------------------------------------------- |
157
+ | `fields` | `array` | Array of field definitions |
158
+ | `onChange` | `function` | Change handler (from createFormHandler) |
159
+ | `formData` | `object` | Form data object from parent state |
160
+ | `theme` | `object` _(optional)_ | Custom theme overrides |
161
+ | `isMobileView` | `boolean` _(optional)_ | Force mobile layout (full width) |
162
+
163
+ ### `createFormHandler`
164
+
165
+ Creates a change handler that manages state and applies modifiers.
166
+
167
+ | Prop | Type | Description |
168
+ | -------------- | --------------------- | ----------------------------------------------- |
169
+ | `fields` | `array` | Array of field definitions |
170
+ | `setState` | `function` | React setState function |
171
+ | `rules` | `array` _(optional)_ | Top-level rules referenced by field triggers |
172
+
173
+ ### Field Schema
174
+
175
+ Each field object supports:
176
+
177
+ | Property | Type | Description |
178
+ |----------|------|-------------|
179
+ | `name` | `string` | Field name (required) |
180
+ | `type` | `string` | Field type (string, email, boolean, etc.) |
181
+ | `title` | `string` | Display label (preferred over `label`) |
182
+ | `label` | `string` | Display label (legacy, use `title`) |
183
+ | `width` | `number` | Width percentage (25, 50, 75, 100) |
184
+ | `default` | `any` | Default value |
185
+ | `readOnly` | `boolean` | Make field read-only |
186
+ | `required` | `boolean` | Mark field as required |
187
+ | `placeholder` | `string` | Placeholder text |
188
+ | `description` | `string` | Help text below field |
189
+ | `helper` | `string` | Additional help text |
190
+ | `error` | `string` | Error message to display |
191
+ | `leadingIcon` | `Component` | Icon component before input |
192
+ | `trailingIcon` | `Component` | Icon component after input |
193
+ | `modifiers` | `array` | (Legacy) field-local modifiers for values |
194
+ | `triggers` | `array` | Triggers that reference top-level rules |
195
+ | `conditions.hiddenWhen` | `array or object` | Conditions to hide (rendered with `hidden` class) |
196
+ | `conditions.hiddenMode` | `any or all` | Mode for hidden conditions (default any) |
197
+ | `conditions.readOnlyWhen` | `array or object` | Conditions to set readOnly |
198
+ | `conditions.readOnlyMode` | `any or all` | Mode for readOnly conditions (default any) |
199
+ | `pattern` | `RegExp \| string \| Array<{ regex, message } \| string>` | Client-side pattern checks with messages |
200
+ | `options` | `array` | Options for select, radio, multiselect fields |
201
+ | `fields` | `array` | Sub-fields for array/subForm types |
202
+
203
+ ### Modifiers (legacy)
204
+
205
+ Field-local modifiers automatically update dependent field values. These are still supported for backward compatibility, but the preferred approach is to use top-level rules and field-level triggers.
206
+
207
+ ```jsx
208
+ {
209
+ name: "firstName",
210
+ type: "string",
211
+ modifiers: [
212
+ {
213
+ target: "fullName",
214
+ type: "concat",
215
+ when: "true",
216
+ value: " " // adds space
217
+ }
218
+ ]
219
+ }
220
+ ```
221
+
222
+ ### Conditions
223
+
224
+ Control field visibility and state:
225
+
226
+ ```jsx
227
+ {
228
+ name: "subscribe",
229
+ type: "boolean",
230
+ conditions: {
231
+ hiddenWhen: {
232
+ field: "age",
233
+ when: "less than",
234
+ value: 18
235
+ }
236
+ }
237
+ }
238
+ ```
239
+
240
+ ---
241
+
242
+ ### Rules & Triggers
243
+
244
+ - Rules live at the top level and have unique names. A rule contains one or more effects that target a field and either change its value or attributes.
245
+ - Triggers live on fields and reference a rule by name. When the trigger's conditions match, the rule's effects are applied.
246
+ - Value effects are applied inside `createFormHandler`. Attribute effects (e.g., `hidden`, `readOnly`, `title`) are applied in `NovaForm`.
247
+
248
+ Rules shape:
249
+
250
+ ```js
251
+ const rules = [
252
+ {
253
+ name: "fullNameRule",
254
+ effects: [
255
+ { targetField: "displayName", prop: "value", type: "concat", kind: "string", value: " " },
256
+ { targetField: "age", prop: "readOnly", value: true },
257
+ ],
258
+ },
259
+ ];
260
+ ```
261
+
262
+ Trigger shape on a field:
263
+
264
+ ```js
265
+ {
266
+ name: "firstName",
267
+ type: "string",
268
+ triggers: [
269
+ {
270
+ rule: "fullNameRule",
271
+ when: [
272
+ { field: "firstName", when: "not empty" },
273
+ { field: "lastName", when: "not empty" },
274
+ ],
275
+ mode: "all", // all = AND, any = OR (default)
276
+ },
277
+ ],
278
+ }
279
+ ```
280
+
281
+ Pass `rules` to both `createFormHandler` and `Form`:
282
+
283
+ ```jsx
284
+ const handleChange = createFormHandler({ fields, rules, setState: setFormData });
285
+
286
+ <Form fields={fields} rules={rules} onChange={handleChange} formData={formData} />
287
+ ```
288
+
289
+ Hidden fields remain mounted and use Tailwind's `hidden` class so values still update.
290
+
291
+ ---
292
+
293
+ ## 🧱 Architecture Overview
294
+
295
+ Nova Forms is organized for **extensibility** and **maintainability**:
296
+
297
+ ```
298
+ src/
299
+ ├── core/ → field registry and evaluation
300
+ ├── formFields/ → built-in field components
301
+ ├── handlers/ → form handlers and modifiers
302
+ ├── utils/ → shared utilities
303
+ ├── NovaForm.jsx → main form component
304
+ └── returnFields.jsx → field renderer
305
+ ```
306
+
307
+ ---
308
+
309
+ ## 🔄 Migration from Manual Field Mapping
310
+
311
+ If you're currently mapping fields manually:
312
+
313
+ **Before:**
314
+ ```jsx
315
+ import { ReturnFieldsV2, createFormHandler, initializeFormData } from "@reactfast/forms";
316
+
317
+ const [formData, setFormData] = useState(() => initializeFormData(fields));
318
+ const handleChange = createFormHandler({ fields, setState: setFormData });
319
+
320
+ return (
321
+ <div className="-mx-2 flex flex-wrap">
322
+ {fields.map((field) => (
323
+ <div key={field.name} className={`${getWidthClass(field.width)} mb-4 px-2`}>
324
+ <ReturnFieldsV2
325
+ field={field}
326
+ value={formData[field.name]}
327
+ onChange={handleChange}
328
+ />
329
+ </div>
330
+ ))}
331
+ </div>
332
+ );
333
+ ```
334
+
335
+ **After:**
336
+ ```jsx
337
+ import { Form, createFormHandler } from "@reactfast/forms";
338
+
339
+ const [formData, setFormData] = useState({});
340
+ const handleChange = createFormHandler({ fields, setState: setFormData });
341
+
342
+ return (
343
+ <Form
344
+ fields={fields}
345
+ onChange={handleChange}
346
+ formData={formData}
347
+ />
348
+ );
349
+ ```
350
+
351
+ ---
352
+
353
+ ## 📚 Documentation
354
+
355
+ For comprehensive guides and examples, see our documentation:
356
+
357
+ - **Live Documentation**: [nova-forms-next.vercel.app](https://nova-forms-next.vercel.app/)
358
+ - **Docs Repository**: [jonathonmcclen/NovaForms-Next](https://github.com/jonathonmcclen/NovaForms-Next)
359
+
360
+ - **[Introduction](documentation/intro.md)** - Complete overview of Nova Forms
361
+ - **[Quick Start](documentation/quickstart.md)** - Get up and running quickly
362
+ - **[createFormHandler](documentation/createFormHandler.md)** - Understanding the form handler system
363
+ - **[Fields & Schemas](documentation/fields-schemas.md)** - Complete field reference and schema guide
364
+ - **[Rules System](documentation/rules.md)** - Advanced rules and effects
365
+ - **[Triggers & Conditions](documentation/triggers.md)** - Conditional logic and triggers
366
+ - **[Dynamic Hide](documentation/dynamic-hide.md)** - Show/hide fields dynamically
367
+ - **[Dynamic Disable](documentation/dynamic-disable.md)** - Enable/disable fields dynamically
368
+ - **[Custom Fields](documentation/custom-fields.md)** - Creating and registering custom field types
369
+ - **[Styling with Tailwind](documentation/styling-tailwind.md)** - Tailwind CSS integration
370
+ - **[Theme Styling](documentation/styling-theme.md)** - Custom theming system
371
+
372
+ ---
373
+
374
+ ## 🤝 Contributing
375
+
376
+ We welcome pull requests and feature suggestions!
377
+
378
+ 1. Fork the repo
379
+ 2. Create a feature branch
380
+
381
+ ```bash
382
+ git checkout -b feature/your-feature
383
+ ```
384
+
385
+ 3. Commit your changes
386
+
387
+ ```bash
388
+ git commit -m "Add new feature"
389
+ ```
390
+
391
+ 4. Push to your branch
392
+
393
+ ```bash
394
+ git push origin feature/your-feature
395
+ ```
396
+
397
+ 5. Open a pull request
398
+
399
+ > 🔒 Only approved code owners can merge to main.
400
+ > See `.github/CODEOWNERS` for details.
401
+
402
+ ---
403
+
404
+ ## 🪪 License
405
+
406
+ Licensed under the [MIT License](LICENSE).
407
+ Copyright © 2025 [Jonathon McClendon](https://github.com/jonathonmcclendon)
408
+
409
+ ---
410
+
411
+ ## 💡 Maintained by
412
+
413
+ **Jonathon McClendon**
414
+ Creator of Nova Forms — building high-performance tools for scalable React ecosystems.
415
+
416
+ ---
417
+
418
+ ### 🌟 Support the Project
419
+
420
+ If Nova Forms helps you ship faster or cleaner React code:
421
+
422
+ - ⭐ Star the repo
423
+ - 🐛 Open an issue for bugs or feature ideas
424
+ - 💬 Share it with other developers
425
+
426
+ ---
427
+
428
+ > _"A form library that feels invisible — flexible, composable, and future-proof."_
429
+
430
+ ---
431
+
432
+ ### 🧭 Next Steps (Roadmap Ideas)
433
+
434
+ - [ ] Advanced validation layer (Yup / Zod integration)
435
+ - [ ] Enhanced theming system (context-aware)
436
+ - [ ] Multi-Step Forms / Wizard support
437
+ - [ ] TypeScript definitions (optional)
438
+
439
+ ---