UNPKG

@proveanything/smartlinks-form-renderer

Version:

SmartLinks form renderer and editor — render forms from JSON schema or build them with the visual editor

357 lines (281 loc) 8.95 kB
# SmartLinks Forms A flexible React package for rendering and editing forms from JSON schema with conditional logic, validation, table fields, storage configuration, and a visual editor. ## Installation ```bash npm install @proveanything/smartlinks-forms ``` ## Subpath Imports ```tsx // Full package (renderer + editor + types) import { SchemaFormRenderer, useFormEditorState } from '@proveanything/smartlinks-forms'; // Renderer only (lean, public-facing) import { SchemaFormRenderer } from '@proveanything/smartlinks-forms/renderer'; // Editor only (admin-facing) import { useFormEditorState, useFormEditorActions } from '@proveanything/smartlinks-forms/editor'; ``` --- ## Form Renderer ### Basic Usage ```tsx import { SchemaFormRenderer, SchemaFormConfig } from '@proveanything/smartlinks-forms'; const formConfig: SchemaFormConfig = { title: "Contact Form", description: "Fill in your details", schema: { type: "object", properties: { name: { type: "string", title: "Full Name" }, email: { type: "string", format: "email", title: "Email" }, }, required: ["name", "email"] }, uiSchema: { name: { "ui:placeholder": "Enter your full name" }, email: { "ui:placeholder": "you@example.com" }, }, storage: { name: "public", email: "private" }, settings: { allowMultipleSubmissions: false, requireAuthentication: false, showProgressBar: false, submitButtonText: "Submit", successMessage: "Form submitted successfully!" }, styling: { theme: "default", primaryColor: "#007bff", backgroundColor: "#ffffff" }, fieldOrder: ["name", "email"] }; function MyForm() { return ( <SchemaFormRenderer config={formConfig} onSubmit={(data) => console.log('Submitted:', data)} initialData={{ name: "John Doe" }} /> ); } ``` ### Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `config` | `SchemaFormConfig` | Required | The form configuration object | | `onSubmit` | `(data: Record<string, any>) => void` | Required | Called on valid submission | | `isSubmitting` | `boolean` | `false` | Disables submit button | | `className` | `string` | `""` | Additional CSS classes | | `initialData` | `Record<string, any>` | `{}` | Pre-populate fields (overrides schema defaults) | | `components` | `object` | `{}` | Custom component overrides | --- ## Field Types & Formats ### String Fields - `text` (default), `email`, `textarea`, `select`, `radio`, `checkboxes`, `multiselect`, `combobox`, `file`, `date`, `date-time` ### Boolean Fields - `checkbox` (default), `switch` ### Number / Integer Fields - Standard number input with `minimum`/`maximum` validation ### Table Fields - Dynamic table with typed columns, row add/remove, `minRows`/`maxRows` --- ## Validation The renderer enforces validation **at submit time** with inline error messages. Both HTML attributes and JavaScript-level checks are used. ### Supported Constraints | Constraint | Applies To | Description | |------------|-----------|-------------| | `required` | All types | Field must have a value (set via `schema.required[]`) | | `minLength` | `string` | Minimum character length | | `maxLength` | `string` | Maximum character length | | `pattern` | `string` | Regex pattern the value must match | | `minimum` | `number`, `integer` | Minimum numeric value | | `maximum` | `number`, `integer` | Maximum numeric value | | `minRows` | `table` | Minimum number of table rows | | `maxRows` | `table` | Maximum number of table rows | ### Example ```tsx { age: { type: "integer", title: "Age", minimum: 18, maximum: 120 }, bio: { type: "string", format: "textarea", title: "Bio", minLength: 10, maxLength: 500 } } ``` --- ## Enum Labels (`enumNames`) Use `enumNames` as a parallel array to `enum` for human-readable labels: ```tsx { country: { type: "string", format: "select", title: "Country", enum: ["us", "gb", "de"], enumNames: ["United States", "United Kingdom", "Germany"] } } ``` `enum[i]` is the stored value, `enumNames[i]` is the display label. Works with `select`, `radio`, `checkboxes`, `multiselect`, and `combobox` formats. --- ## UI Schema Control presentation without changing the data schema: ```tsx uiSchema: { bio: { "ui:placeholder": "Tell us about yourself...", "ui:help": "This will be shown on your profile", "ui:options": { rows: 6 }, "ui:disabled": true // Read-only field }, avatar: { "ui:options": { accept: "image/*" } } } ``` ### Available UI Properties | Property | Type | Description | |----------|------|-------------| | `ui:placeholder` | `string` | Placeholder text | | `ui:help` | `string` | Help text below the field | | `ui:disabled` | `boolean` | Disables the field (read-only) | | `ui:widget` | `string` | Override auto-detected widget | | `ui:options.rows` | `number` | Textarea row count | | `ui:options.accept` | `string` | File input accept filter | | `ui:options.label` | `boolean` | Show/hide label | --- ## Conditional Logic Show/hide fields based on other field values: ```tsx { preferences: { type: "string", format: "select", title: "Preferences", enum: ["daily", "weekly"], conditions: [ { targetFieldId: "subscribe", operator: "equals", value: true } ], showWhen: "all" // or "any" } } ``` ### Operators | Operator | Description | Needs `value`? | |----------|-------------|---------------| | `equals` | Strict equality | Yes | | `not_equals` | Not equal | Yes | | `contains` | String contains | Yes | | `not_contains` | String doesn't contain | Yes | | `greater_than` | Numeric comparison | Yes | | `less_than` | Numeric comparison | Yes | | `is_empty` | Value is empty/null | No | | `is_not_empty` | Value has content | No | | `is_true` | Value is `true` | No | | `is_false` | Value is `false`/`null`/`undefined` | No | --- ## Field Ordering ```tsx const config: SchemaFormConfig = { fieldOrder: ["name", "email", "phone", "address"], // ... }; ``` If `fieldOrder` is not specified, fields appear in `schema.properties` insertion order. --- ## Table Fields ```tsx { items: { type: "table", title: "Line Items", columns: [ { id: "name", title: "Item", type: "string", required: true }, { id: "qty", title: "Quantity", type: "number", required: true }, { id: "active", title: "Active", type: "boolean" }, { id: "date", title: "Added", type: "date" } ], minRows: 1, maxRows: 10 } } ``` --- ## Custom Components Override default UI primitives: ```tsx <SchemaFormRenderer config={formConfig} onSubmit={handleSubmit} components={{ Button: MyButton, Input: MyInput, Textarea: MyTextarea, Select: MySelect, Checkbox: MyCheckbox, RadioGroup: MyRadioGroup, Switch: MySwitch, Label: MyLabel, TableInput: MyTableInput, }} /> ``` --- ## Storage Configuration Define privacy levels per field: ```tsx storage: { name: "public", // Publicly visible email: "private", // Private to user ssn: "proof", // Cryptographic proof only notes: "personal" // Personal notes } ``` --- ## Form Editor (Admin) The editor hooks provide headless state management for building a form editor UI: ```tsx import { useFormEditorState, useFormEditorActions } from '@proveanything/smartlinks-forms/editor'; function FormEditor() { const editor = useFormEditorState({ isCreating: true }); const actions = useFormEditorActions({ formConfig: editor.formConfig, setFormConfig: editor.setFormConfig, }); // editor.addField(), editor.updateField(), editor.removeField(), etc. // actions.exportSchema(), actions.importSchema() } ``` --- ## Configuration Reference ### SchemaFormConfig | Property | Type | Description | |----------|------|-------------| | `id` | `string?` | Unique identifier | | `title` | `string` | Form title | | `description` | `string` | Form description | | `schema` | `object` | JSON Schema definition | | `uiSchema` | `object` | UI configuration | | `storage` | `object` | Per-field storage levels | | `settings` | `object` | Form behavior settings | | `styling` | `object` | Theme and colours | | `fieldOrder` | `string[]?` | Field display order | --- ## TypeScript ```tsx import type { SchemaFormConfig, SchemaFormField, SchemaFormRendererProps, SchemaFormUIConfig, SchemaFormFieldCondition, TableColumn, FormEditorState, FormEditorActions, } from '@proveanything/smartlinks-forms'; ``` ## License MIT