@formhaus/react 0.3.0 → 0.4.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 +21 -0
- package/README.md +85 -0
- package/dist/index.d.ts +68 -6
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/package.json +19 -15
- package/dist/FormActions.d.ts +0 -3
- package/dist/FormActions.d.ts.map +0 -1
- package/dist/FormActions.js +0 -28
- package/dist/FormActions.js.map +0 -1
- package/dist/FormField.d.ts +0 -16
- package/dist/FormField.d.ts.map +0 -1
- package/dist/FormField.js +0 -33
- package/dist/FormField.js.map +0 -1
- package/dist/FormRenderer.d.ts +0 -3
- package/dist/FormRenderer.d.ts.map +0 -1
- package/dist/FormRenderer.js +0 -94
- package/dist/FormRenderer.js.map +0 -1
- package/dist/FormStepProgress.d.ts +0 -3
- package/dist/FormStepProgress.d.ts.map +0 -1
- package/dist/FormStepProgress.js +0 -6
- package/dist/FormStepProgress.js.map +0 -1
- package/dist/fields/CheckboxField.d.ts +0 -3
- package/dist/fields/CheckboxField.d.ts.map +0 -1
- package/dist/fields/CheckboxField.js +0 -9
- package/dist/fields/CheckboxField.js.map +0 -1
- package/dist/fields/DateField.d.ts +0 -3
- package/dist/fields/DateField.d.ts.map +0 -1
- package/dist/fields/DateField.js +0 -9
- package/dist/fields/DateField.js.map +0 -1
- package/dist/fields/FileField.d.ts +0 -3
- package/dist/fields/FileField.d.ts.map +0 -1
- package/dist/fields/FileField.js +0 -12
- package/dist/fields/FileField.js.map +0 -1
- package/dist/fields/MultiselectField.d.ts +0 -3
- package/dist/fields/MultiselectField.d.ts.map +0 -1
- package/dist/fields/MultiselectField.js +0 -20
- package/dist/fields/MultiselectField.js.map +0 -1
- package/dist/fields/RadioField.d.ts +0 -3
- package/dist/fields/RadioField.d.ts.map +0 -1
- package/dist/fields/RadioField.js +0 -13
- package/dist/fields/RadioField.js.map +0 -1
- package/dist/fields/SelectField.d.ts +0 -3
- package/dist/fields/SelectField.d.ts.map +0 -1
- package/dist/fields/SelectField.js +0 -10
- package/dist/fields/SelectField.js.map +0 -1
- package/dist/fields/SwitchField.d.ts +0 -3
- package/dist/fields/SwitchField.d.ts.map +0 -1
- package/dist/fields/SwitchField.js +0 -9
- package/dist/fields/SwitchField.js.map +0 -1
- package/dist/fields/TextField.d.ts +0 -3
- package/dist/fields/TextField.d.ts.map +0 -1
- package/dist/fields/TextField.js +0 -22
- package/dist/fields/TextField.js.map +0 -1
- package/dist/fields/TextareaField.d.ts +0 -3
- package/dist/fields/TextareaField.d.ts.map +0 -1
- package/dist/fields/TextareaField.js +0 -10
- package/dist/fields/TextareaField.js.map +0 -1
- package/dist/hooks/useFieldOptions.d.ts +0 -4
- package/dist/hooks/useFieldOptions.d.ts.map +0 -1
- package/dist/hooks/useFieldOptions.js +0 -39
- package/dist/hooks/useFieldOptions.js.map +0 -1
- package/dist/hooks/useFormEngine.d.ts +0 -3
- package/dist/hooks/useFormEngine.d.ts.map +0 -1
- package/dist/hooks/useFormEngine.js +0 -14
- package/dist/hooks/useFormEngine.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/types.d.ts +0 -55
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 formhaus contributors
|
|
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,85 @@
|
|
|
1
|
+
# @formhaus/react
|
|
2
|
+
|
|
3
|
+
React adapter for [Formhaus](https://github.com/ignsm/formhaus). Renders forms from a JSON definition with native HTML inputs by default. Drop in your own components via a `components` prop.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @formhaus/core @formhaus/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires React ≥18 and Node ≥18.
|
|
12
|
+
|
|
13
|
+
## Generating a definition
|
|
14
|
+
|
|
15
|
+
Write the form JSON by hand, or use the [`/formhaus-create-form`](https://formhaus.dev/guide/formhaus-create-form.html) Claude Code skill to generate it from a text description, a CSV table, or a screenshot of an existing form.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { FormRenderer } from '@formhaus/react';
|
|
21
|
+
import definition from './contact-form.json';
|
|
22
|
+
|
|
23
|
+
export function ContactPage() {
|
|
24
|
+
async function handleSubmit(values: Record<string, unknown>) {
|
|
25
|
+
await fetch('/api/contact', {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
body: JSON.stringify(values),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return <FormRenderer definition={definition} onSubmit={handleSubmit} />;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Custom components
|
|
36
|
+
|
|
37
|
+
Swap native HTML for your own UI kit:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import type { FieldComponentMap, FieldComponentProps } from '@formhaus/react';
|
|
41
|
+
|
|
42
|
+
function MyInput({ field, value, error, onChange, onBlur }: FieldComponentProps) {
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
<label>{field.label}</label>
|
|
46
|
+
<input
|
|
47
|
+
value={value as string}
|
|
48
|
+
onChange={(e) => onChange(e.target.value)}
|
|
49
|
+
onBlur={onBlur}
|
|
50
|
+
/>
|
|
51
|
+
{error && <span className="error">{error}</span>}
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const components: FieldComponentMap = { text: MyInput, email: MyInput };
|
|
57
|
+
|
|
58
|
+
<FormRenderer definition={definition} onSubmit={handleSubmit} components={components} />;
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Unmapped field types fall back to native HTML.
|
|
62
|
+
|
|
63
|
+
## Server-side rendering
|
|
64
|
+
|
|
65
|
+
`FormRenderer` is SSR-safe. It works with Next.js static and dynamic prerender, plus React's `renderToString`, with no `next/dynamic` wrapper required.
|
|
66
|
+
|
|
67
|
+
## Optional baseline styles
|
|
68
|
+
|
|
69
|
+
By default the React adapter renders unstyled HTML. For a sensible starting look (padding, focus states, error colour, button styles) import the shared stylesheet:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import '@formhaus/core/style.css';
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Theme via CSS custom properties (`--fh-color-primary`, `--fh-radius`, `--fh-gap`, etc.). If you bring your own components via the `components` prop (MUI, Tailwind, shadcn), the stylesheet doesn't apply to those.
|
|
76
|
+
|
|
77
|
+
## Docs
|
|
78
|
+
|
|
79
|
+
- Full guide and API reference: https://formhaus.dev
|
|
80
|
+
- Live playground: https://formhaus.dev/playground.html
|
|
81
|
+
- Source and issues: https://github.com/ignsm/formhaus
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as _formhaus_core from '@formhaus/core';
|
|
3
|
+
import { FieldType, FormAction, FormDefinition, ValidatorFn, StepValidateFn, FieldOption, FormAnalyticsEvent, FormEngineOptions, FormEngine } from '@formhaus/core';
|
|
4
|
+
import { ComponentType } from 'react';
|
|
5
|
+
|
|
6
|
+
type OptionsProvider = (values: Record<string, unknown>) => FieldOption[] | Promise<FieldOption[]>;
|
|
7
|
+
interface FieldComponentProps {
|
|
8
|
+
field: _formhaus_core.FormField;
|
|
9
|
+
value: unknown;
|
|
10
|
+
error?: string;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
onChange: (value: unknown) => void;
|
|
14
|
+
onBlur: () => void;
|
|
15
|
+
onFocus?: () => void;
|
|
16
|
+
}
|
|
17
|
+
type FieldComponentMap = Partial<Record<FieldType, ComponentType<FieldComponentProps>>>;
|
|
18
|
+
interface FormActionsProps {
|
|
19
|
+
submitAction?: FormAction;
|
|
20
|
+
backAction?: FormAction | false;
|
|
21
|
+
cancelAction?: FormAction;
|
|
22
|
+
isFirstStep: boolean;
|
|
23
|
+
isLastStep: boolean;
|
|
24
|
+
isMultiStep: boolean;
|
|
25
|
+
loading?: boolean;
|
|
26
|
+
values?: Record<string, unknown>;
|
|
27
|
+
primaryLabel?: string;
|
|
28
|
+
showBack?: boolean;
|
|
29
|
+
backLabel?: string;
|
|
30
|
+
onSubmit: () => void;
|
|
31
|
+
onNext: () => void;
|
|
32
|
+
onPrev: () => void;
|
|
33
|
+
onCancel: () => void;
|
|
34
|
+
onPrimary?: () => void;
|
|
35
|
+
}
|
|
36
|
+
interface FormStepProgressProps {
|
|
37
|
+
current: number;
|
|
38
|
+
total: number;
|
|
39
|
+
stepTitle?: string;
|
|
40
|
+
stepDescription?: string;
|
|
41
|
+
}
|
|
42
|
+
interface FormRendererProps {
|
|
43
|
+
definition: FormDefinition;
|
|
44
|
+
initialValues?: Record<string, unknown>;
|
|
45
|
+
onSubmit: (values: Record<string, unknown>) => Promise<void> | void;
|
|
46
|
+
onCancel?: () => void;
|
|
47
|
+
onStepChange?: (stepId: string, direction: 'next' | 'back') => void;
|
|
48
|
+
onFieldChange?: (key: string, value: unknown, allValues: Record<string, unknown>) => void;
|
|
49
|
+
validators?: Record<string, ValidatorFn>;
|
|
50
|
+
onStepValidate?: StepValidateFn;
|
|
51
|
+
errors?: Record<string, string>;
|
|
52
|
+
loading?: boolean;
|
|
53
|
+
components?: FieldComponentMap;
|
|
54
|
+
optionsProviders?: Record<string, OptionsProvider>;
|
|
55
|
+
ActionsComponent?: ComponentType<FormActionsProps>;
|
|
56
|
+
ProgressComponent?: ComponentType<FormStepProgressProps>;
|
|
57
|
+
onAnalyticsEvent?: (event: FormAnalyticsEvent) => void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare function FormRenderer({ definition, initialValues, onSubmit, onCancel, onStepChange, onFieldChange, validators, onStepValidate, errors: externalErrors, loading, components, optionsProviders, ActionsComponent, ProgressComponent, onAnalyticsEvent, }: FormRendererProps): react_jsx_runtime.JSX.Element;
|
|
61
|
+
|
|
62
|
+
declare function FormActions({ submitAction, backAction, cancelAction, isFirstStep, isLastStep, isMultiStep, loading, values, onSubmit, onNext, onPrev, onCancel, primaryLabel: primaryLabelProp, showBack: showBackProp, backLabel: backLabelProp, onPrimary: onPrimaryProp, }: FormActionsProps): react_jsx_runtime.JSX.Element;
|
|
63
|
+
|
|
64
|
+
declare function FormStepProgress({ current, total, stepTitle, stepDescription, }: FormStepProgressProps): react_jsx_runtime.JSX.Element;
|
|
65
|
+
|
|
66
|
+
declare function useFormEngine(definition: FormDefinition, initialValues?: Record<string, unknown>, options?: FormEngineOptions): FormEngine;
|
|
67
|
+
|
|
68
|
+
export { type FieldComponentMap, type FieldComponentProps, FormActions, type FormActionsProps, FormRenderer, type FormRendererProps, FormStepProgress, type FormStepProgressProps, useFormEngine };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
export { FormRenderer } from './FormRenderer';
|
|
2
|
-
export { FormActions } from './FormActions';
|
|
3
|
-
export { FormStepProgress } from './FormStepProgress';
|
|
4
|
-
export { useFormEngine } from './hooks/useFormEngine';
|
|
1
|
+
import {useRef,useCallback,useSyncExternalStore,useEffect,useState}from'react';import {FormEngine,evaluateCondition}from'@formhaus/core';import {jsxs,jsx}from'react/jsx-runtime';function Ie(e,r,t){return t?true:!e?.disabled||e.disabled.length===0?false:e.disabled.every(p=>evaluateCondition(p,r))}function K({submitAction:e,backAction:r,cancelAction:t,isFirstStep:p,isLastStep:d,isMultiStep:l,loading:c,values:a={},onSubmit:n,onNext:s,onPrev:i,onCancel:m,primaryLabel:u,showBack:f,backLabel:b,onPrimary:y}){let o=f??(l&&!p&&r!==false),F=b??(typeof r=="object"?r?.label??"Back":"Back"),D=u??(l&&!d?"Continue":e?.label??"Submit"),E=Ie(l&&!d?void 0:e,a,c);function L(){y?y():l&&!d?s():n();}return jsxs("div",{className:"fh-form-actions",children:[jsxs("div",{className:"fh-form-actions__secondary",children:[o&&jsx("button",{type:"button",className:"fh-form-actions__button fh-form-actions__button--text",disabled:c,onClick:i,children:F}),t&&jsx("button",{type:"button",className:"fh-form-actions__button fh-form-actions__button--text",disabled:c,onClick:m,children:t.label})]}),jsx("button",{type:"button",className:"fh-form-actions__button fh-form-actions__button--primary",disabled:E,"aria-busy":c,onClick:L,children:D})]})}function J({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-list`,i=`${e.key}-helper`,m=`${e.key}-error`,u=t?m:e.helperText?i:void 0,f=e.options??[];return jsxs("div",{className:"fh-field",children:[e.label&&jsxs("label",{className:"fh-field__label",htmlFor:n,children:[e.label,e.validation?.required&&jsx("span",{className:"fh-field__required","aria-hidden":"true",children:" *"})]}),jsx("input",{id:n,type:"text",list:s,className:"fh-field__input fh-field__input--autocomplete",value:r??"",placeholder:e.placeholder,disabled:d||p,"aria-invalid":!!t,"aria-describedby":u,autoComplete:"off",onChange:b=>l(b.target.value),onBlur:c,onFocus:a}),jsx("datalist",{id:s,children:f.map(b=>jsx("option",{value:b.value,children:b.label},b.value))}),t&&jsx("p",{id:m,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:i,className:"fh-field__helper",children:e.helperText})]})}function X({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0;return jsxs("div",{className:"fh-field fh-field--checkbox",children:[jsxs("div",{className:"fh-field__checkbox-wrapper",children:[jsx("input",{id:n,type:"checkbox",className:"fh-field__checkbox",checked:!!r,disabled:d||p,"aria-invalid":!!t,"aria-describedby":m,onChange:u=>l(u.target.checked),onBlur:c,onFocus:a}),e.label&&jsx("label",{className:"fh-field__label",htmlFor:n,children:e.label})]}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function Z({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0;return jsxs("div",{className:"fh-field",children:[e.label&&jsxs("label",{className:"fh-field__label",htmlFor:n,children:[e.label,e.validation?.required&&jsx("span",{className:"fh-field__required","aria-hidden":"true",children:" *"})]}),jsx("input",{id:n,type:"date",className:"fh-field__input fh-field__input--date",value:String(r??""),disabled:d||p,"aria-invalid":!!t,"aria-describedby":m,onChange:u=>l(u.target.value),onBlur:c,onFocus:a}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function ee({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0;return jsxs("div",{className:"fh-field",children:[e.label&&jsxs("label",{className:"fh-field__label",htmlFor:n,children:[e.label,e.validation?.required&&jsx("span",{className:"fh-field__required","aria-hidden":"true",children:" *"})]}),jsx("input",{id:n,type:"datetime-local",className:"fh-field__input fh-field__input--datetime",value:String(r??""),disabled:d||p,"aria-invalid":!!t,"aria-describedby":m,onChange:u=>l(u.target.value),onBlur:c,onFocus:a}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function oe({field:e,error:r,loading:t,disabled:p,onChange:d,onBlur:l,onFocus:c}){let a=e.key,n=`${e.key}-helper`,s=`${e.key}-error`,i=r?s:e.helperText?n:void 0;return jsxs("div",{className:"fh-field",children:[e.label&&jsxs("label",{className:"fh-field__label",htmlFor:a,children:[e.label,e.validation?.required&&jsx("span",{className:"fh-field__required","aria-hidden":"true",children:" *"})]}),jsx("input",{id:a,type:"file",className:"fh-field__input fh-field__input--file",accept:e.accept,disabled:p||t,"aria-invalid":!!r,"aria-describedby":i,onChange:m=>{let u=m.target.files;d(u&&u.length>0?u[0]:null);},onBlur:l,onFocus:c}),r&&jsx("p",{id:s,className:"fh-field__error",role:"alert",children:r}),!r&&e.helperText&&jsx("p",{id:n,className:"fh-field__helper",children:e.helperText})]})}function ne({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0,u=e.options??[],f=Array.isArray(r)?r:[];function b(y){let o=f.includes(y)?f.filter(F=>F!==y):[...f,y];l(o);}return jsxs("fieldset",{className:"fh-field fh-field--multiselect","aria-invalid":!!t||void 0,"aria-describedby":m,children:[e.label&&jsx("legend",{className:"fh-field__label",children:e.label}),jsx("div",{className:"fh-field__multiselect-group",children:u.map(y=>{let o=`${n}-${y.value}`;return jsxs("div",{className:"fh-field__multiselect-option",children:[jsx("input",{id:o,type:"checkbox",className:"fh-field__checkbox",checked:f.includes(y.value),disabled:d||p,onChange:()=>b(y.value),onBlur:c,onFocus:a}),jsx("label",{className:"fh-field__multiselect-label",htmlFor:o,children:y.label})]},y.value)})}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function le({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0,u=e.options??[];return jsxs("fieldset",{className:"fh-field fh-field--radio","aria-invalid":!!t||void 0,"aria-describedby":m,children:[e.label&&jsx("legend",{className:"fh-field__label",children:e.label}),jsx("div",{className:"fh-field__radio-group",children:u.map(f=>{let b=`${n}-${f.value}`;return jsxs("div",{className:"fh-field__radio-option",children:[jsx("input",{id:b,type:"radio",className:"fh-field__radio",name:n,value:f.value,checked:String(r)===String(f.value),disabled:d||p,onChange:()=>l(f.value),onBlur:c,onFocus:a}),jsx("label",{className:"fh-field__radio-label",htmlFor:b,children:f.label})]},f.value)})}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function ae({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0,u=e.options??[];return jsxs("div",{className:"fh-field",children:[e.label&&jsxs("label",{className:"fh-field__label",htmlFor:n,children:[e.label,e.validation?.required&&jsx("span",{className:"fh-field__required","aria-hidden":"true",children:" *"})]}),jsxs("select",{id:n,className:"fh-field__input fh-field__input--select",value:r??"",disabled:d||p,"aria-invalid":!!t,"aria-describedby":m,onChange:f=>l(f.target.value),onBlur:c,onFocus:a,children:[e.placeholder&&jsx("option",{value:"",disabled:true,children:e.placeholder}),u.map(f=>jsx("option",{value:f.value,children:f.label},f.value))]}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function pe({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0;return jsxs("div",{className:"fh-field fh-field--switch",children:[jsxs("div",{className:"fh-field__switch-wrapper",children:[jsx("input",{id:n,type:"checkbox",role:"switch",className:"fh-field__switch",checked:!!r,disabled:d||p,"aria-invalid":!!t,"aria-describedby":m,onChange:u=>l(u.target.checked),onBlur:c,onFocus:a}),e.label&&jsx("label",{className:"fh-field__label",htmlFor:n,children:e.label})]}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function N({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0,u=b=>{let y=b.target.value;l(e.type==="number"?Number(y):y);},f=e.type==="email"?"email":e.type==="phone"?"tel":e.type==="number"?"number":e.type==="password"?"password":"text";return jsxs("div",{className:"fh-field",children:[e.label&&jsxs("label",{className:"fh-field__label",htmlFor:n,children:[e.label,e.validation?.required&&jsx("span",{className:"fh-field__required","aria-hidden":"true",children:" *"})]}),jsx("input",{id:n,type:f,className:"fh-field__input",value:r!=null?String(r):"",placeholder:e.placeholder??e.mask,disabled:d||p,"aria-invalid":!!t,"aria-describedby":m,onChange:u,onBlur:c,onFocus:a}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}function me({field:e,value:r,error:t,loading:p,disabled:d,onChange:l,onBlur:c,onFocus:a}){let n=e.key,s=`${e.key}-helper`,i=`${e.key}-error`,m=t?i:e.helperText?s:void 0;return jsxs("div",{className:"fh-field",children:[e.label&&jsxs("label",{className:"fh-field__label",htmlFor:n,children:[e.label,e.validation?.required&&jsx("span",{className:"fh-field__required","aria-hidden":"true",children:" *"})]}),jsx("textarea",{id:n,className:"fh-field__input fh-field__input--textarea",value:r??"",placeholder:e.placeholder,rows:e.rows??3,disabled:d||p,"aria-invalid":!!t,"aria-describedby":m,onChange:u=>l(u.target.value),onBlur:c,onFocus:a}),t&&jsx("p",{id:i,className:"fh-field__error",role:"alert",children:t}),!t&&e.helperText&&jsx("p",{id:s,className:"fh-field__helper",children:e.helperText})]})}var Be={text:N,email:N,phone:N,number:N,password:N,select:ae,autocomplete:J,multiselect:ne,checkbox:X,radio:le,switch:pe,file:oe,date:Z,datetime:ee,textarea:me};function ue({field:e,value:r,error:t,loading:p,disabled:d,components:l,onChange:c,onBlur:a,onFocus:n}){let s=l?.[e.type]??Be[e.type];return s?jsx(s,{field:e,value:r,error:t,loading:p,disabled:d,onChange:c,onBlur:a,onFocus:n}):jsxs("div",{children:["Unsupported field type: ",e.type]})}function V({current:e,total:r,stepTitle:t,stepDescription:p}){let d=e/r*100;return jsxs("div",{className:"fh-step-progress",children:[jsx("div",{className:"fh-step-progress__bar",children:jsx("div",{className:"fh-step-progress__fill",style:{width:`${d}%`}})}),jsx("div",{className:"fh-step-progress__info",children:jsxs("span",{className:"fh-step-progress__counter",children:["Step ",e," of ",r]})}),t&&jsx("h3",{className:"fh-step-progress__title",children:t}),p&&jsx("p",{className:"fh-step-progress__description",children:p})]})}function fe(e,r,t){let[p,d]=useState({}),l=useRef(new Map);return useEffect(()=>{if(!t)return;let c=false;for(let a of e){if(!a.optionsFrom)continue;let n=t[a.optionsFrom];if(!n)continue;let s=(a.optionsDependsOn??[]).map(m=>r[m]).join("|");if(l.current.get(a.key)===s)continue;l.current.set(a.key,s);let i=n(r);Array.isArray(i)?c||d(m=>({...m,[a.key]:i})):i.then(m=>{c||d(u=>({...u,[a.key]:m}));}).catch(()=>{l.current.delete(a.key);});}return ()=>{c=true;}},[e,r,t]),p}function W(e,r,t){let p=useRef(null),d=useRef(e.id);(p.current===null||d.current!==e.id)&&(p.current=new FormEngine(e,r,t),d.current=e.id);let l=p.current,c=useCallback(n=>l.subscribe(n),[l]),a=useCallback(()=>l.getSnapshot(),[l]);return useSyncExternalStore(c,a,a),l}function Ae({definition:e,initialValues:r,onSubmit:t,onCancel:p,onStepChange:d,onFieldChange:l,validators:c,onStepValidate:a,errors:n,loading:s=false,components:i,optionsProviders:m,ActionsComponent:u,ProgressComponent:f,onAnalyticsEvent:b}){let o=W(e,r,{validators:c,onStepValidate:a}),F=fe(o.visibleFields,o.values,m);useEffect(()=>{n&&o.setErrors(n);},[n,o]);function D(h,_){o.setValue(h,_),l?.(h,_,o.values);}function E(h){b?.({type:"field_focused",fieldKey:h});}function L(h){b?.({type:"field_blurred",fieldKey:h,hasValue:o.values[h]!==void 0&&o.values[h]!==""});}function q(h){h.preventDefault();let _=o.validate();for(let[Se,Pe]of Object.entries(_))b?.({type:"field_error",fieldKey:Se,error:Pe});if(Object.keys(_).length>0)return;let P=o.getSubmitValues();b?.({type:"form_submitted",fieldCount:Object.keys(P).length}),t(P);}async function H(){let h=o.currentStep;await o.nextStepAsync()&&(h&&b?.({type:"step_completed",stepId:h.id}),o.currentStep&&(d?.(o.currentStep.id,"next"),b?.({type:"step_viewed",stepId:o.currentStep.id,stepIndex:o.currentStepIndex})));}function _e(){o.prevStep(),o.currentStep&&d?.(o.currentStep.id,"back");}function Fe(){p?.();}let ve=f??V,ge=u??K,A=o.isLastStep||!o.isMultiStep,ke=o.isMultiStep&&!A?o.currentStep?.next?.label??"Continue":e.submit?.label??"Submit",Ne=o.isMultiStep&&!o.isFirstStep&&o.currentStep?.back!==false,xe=typeof o.currentStep?.back=="object"?o.currentStep.back.label??"Back":"Back";async function Ce(){o.isMultiStep&&!A?await H():q({preventDefault:()=>{}});}return jsxs("form",{className:"fh-form",onSubmit:q,children:[o.isMultiStep&&jsx(ve,{current:o.progress.current,total:o.progress.total,stepTitle:o.currentStep?.title,stepDescription:o.currentStep?.description}),jsx("div",{className:"fh-form__fields",children:o.visibleFields.map(h=>{let _=F[h.key]?{...h,options:F[h.key]}:h;return jsx(ue,{field:_,value:o.values[h.key],error:o.errors[h.key],loading:o.fieldLoading[h.key],disabled:s,components:i,onChange:P=>D(h.key,P),onBlur:()=>L(h.key),onFocus:()=>E(h.key)},h.key)})}),o.topLevelErrors.length>0&&jsx("div",{className:"fh-form__top-errors",children:o.topLevelErrors.map(h=>jsx("p",{className:"fh-form__top-error",children:h},h))}),jsx(ge,{submitAction:e.submit,backAction:o.currentStep?.back,cancelAction:e.cancel,isFirstStep:o.isFirstStep,isLastStep:A,isMultiStep:o.isMultiStep,loading:s||o.stepValidating,values:o.values,onSubmit:()=>q({preventDefault:()=>{}}),onNext:H,onPrev:_e,onCancel:Fe,primaryLabel:ke,showBack:Ne,backLabel:xe,onPrimary:Ce})]})}export{K as FormActions,Ae as FormRenderer,V as FormStepProgress,W as useFormEngine};//# sourceMappingURL=index.js.map
|
|
5
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"sources":["../src/FormActions.tsx","../src/fields/AutocompleteField.tsx","../src/fields/CheckboxField.tsx","../src/fields/DateField.tsx","../src/fields/DateTimeField.tsx","../src/fields/FileField.tsx","../src/fields/MultiselectField.tsx","../src/fields/RadioField.tsx","../src/fields/SelectField.tsx","../src/fields/SwitchField.tsx","../src/fields/TextField.tsx","../src/fields/TextareaField.tsx","../src/FormField.tsx","../src/FormStepProgress.tsx","../src/hooks/useFieldOptions.ts","../src/hooks/useFormEngine.ts","../src/FormRenderer.tsx"],"names":["isActionDisabled","action","values","loading","c","evaluateCondition","FormActions","submitAction","backAction","cancelAction","isFirstStep","isLastStep","isMultiStep","onSubmit","onNext","onPrev","onCancel","primaryLabelProp","showBackProp","backLabelProp","onPrimaryProp","showBack","backLabel","primaryLabel","primaryDisabled","handlePrimary","jsxs","jsx","AutocompleteField","field","value","error","disabled","onChange","onBlur","onFocus","inputId","listId","helperId","errorId","describedBy","options","e","opt","CheckboxField","DateField","DateTimeField","FileField","files","MultiselectField","groupId","selected","handleToggle","optValue","next","v","optionId","RadioField","SelectField","SwitchField","TextField","handleChange","inputType","TextareaField","defaultComponents","FormField","components","Component","FormStepProgress","current","total","stepTitle","stepDescription","percent","useFieldOptions","fields","providers","resolved","setResolved","useState","lastDepsRef","useRef","useEffect","isStale","provider","depsKey","k","result","prev","useFormEngine","definition","initialValues","engineRef","definitionIdRef","FormEngine","engine","subscribe","useCallback","listener","getSnapshot","useSyncExternalStore","FormRenderer","onStepChange","onFieldChange","validators","onStepValidate","externalErrors","optionsProviders","ActionsComponent","ProgressComponent","onAnalyticsEvent","resolvedOptions","handleFieldUpdate","key","handleFieldFocus","handleFieldBlur","handleSubmit","allErrors","msg","submitValues","handleNext","prevStep","handlePrev","handleCancel","ProgressComp","ActionsComp","effectiveIsLastStep","computedPrimaryLabel","computedShowBack","computedBackLabel","fieldWithOptions"],"mappings":"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","file":"index.js","sourcesContent":["import { evaluateCondition } from '@formhaus/core';\nimport type { FormAction } from '@formhaus/core';\nimport type { FormActionsProps } from './types';\n\nfunction isActionDisabled(\n action: FormAction | undefined,\n values: Record<string, unknown>,\n loading?: boolean,\n): boolean {\n if (loading) return true;\n if (!action?.disabled || action.disabled.length === 0) return false;\n return action.disabled.every((c) => evaluateCondition(c, values));\n}\n\nexport function FormActions({\n submitAction,\n backAction,\n cancelAction,\n isFirstStep,\n isLastStep,\n isMultiStep,\n loading,\n values = {},\n onSubmit,\n onNext,\n onPrev,\n onCancel,\n primaryLabel: primaryLabelProp,\n showBack: showBackProp,\n backLabel: backLabelProp,\n onPrimary: onPrimaryProp,\n}: FormActionsProps) {\n const showBack = showBackProp ?? (isMultiStep && !isFirstStep && backAction !== false);\n const backLabel = backLabelProp ?? (typeof backAction === 'object' ? (backAction?.label ?? 'Back') : 'Back');\n const primaryLabel = primaryLabelProp ?? (isMultiStep && !isLastStep ? 'Continue' : (submitAction?.label ?? 'Submit'));\n\n const primaryDisabled = isActionDisabled(\n isMultiStep && !isLastStep ? undefined : submitAction,\n values,\n loading,\n );\n\n function handlePrimary() {\n if (onPrimaryProp) {\n onPrimaryProp();\n } else if (isMultiStep && !isLastStep) {\n onNext();\n } else {\n onSubmit();\n }\n }\n\n return (\n <div className=\"fh-form-actions\">\n <div className=\"fh-form-actions__secondary\">\n {showBack && (\n <button\n type=\"button\"\n className=\"fh-form-actions__button fh-form-actions__button--text\"\n disabled={loading}\n onClick={onPrev}\n >\n {backLabel}\n </button>\n )}\n {cancelAction && (\n <button\n type=\"button\"\n className=\"fh-form-actions__button fh-form-actions__button--text\"\n disabled={loading}\n onClick={onCancel}\n >\n {cancelAction.label}\n </button>\n )}\n </div>\n <button\n type=\"button\"\n className=\"fh-form-actions__button fh-form-actions__button--primary\"\n disabled={primaryDisabled}\n aria-busy={loading}\n onClick={handlePrimary}\n >\n {primaryLabel}\n </button>\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function AutocompleteField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const listId = `${field.key}-list`;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n const options = field.options ?? [];\n\n return (\n <div className=\"fh-field\">\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n {field.validation?.required && <span className=\"fh-field__required\" aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <input\n id={inputId}\n type=\"text\"\n list={listId}\n className=\"fh-field__input fh-field__input--autocomplete\"\n value={(value as string) ?? ''}\n placeholder={field.placeholder}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n autoComplete=\"off\"\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n <datalist id={listId}>\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </datalist>\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function CheckboxField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n\n return (\n <div className=\"fh-field fh-field--checkbox\">\n <div className=\"fh-field__checkbox-wrapper\">\n <input\n id={inputId}\n type=\"checkbox\"\n className=\"fh-field__checkbox\"\n checked={!!value}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={(e) => onChange(e.target.checked)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n </label>\n )}\n </div>\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function DateField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n\n return (\n <div className=\"fh-field\">\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n {field.validation?.required && <span className=\"fh-field__required\" aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <input\n id={inputId}\n type=\"date\"\n className=\"fh-field__input fh-field__input--date\"\n value={String(value ?? '')}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function DateTimeField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n\n return (\n <div className=\"fh-field\">\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n {field.validation?.required && <span className=\"fh-field__required\" aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <input\n id={inputId}\n type=\"datetime-local\"\n className=\"fh-field__input fh-field__input--datetime\"\n value={String(value ?? '')}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function FileField({\n field,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n\n return (\n <div className=\"fh-field\">\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n {field.validation?.required && <span className=\"fh-field__required\" aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <input\n id={inputId}\n type=\"file\"\n className=\"fh-field__input fh-field__input--file\"\n accept={field.accept}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={(e) => {\n const files = e.target.files;\n onChange(files && files.length > 0 ? files[0] : null);\n }}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function MultiselectField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const groupId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n const options = field.options ?? [];\n const selected = Array.isArray(value) ? (value as (string | number)[]) : [];\n\n function handleToggle(optValue: string) {\n const next = selected.includes(optValue)\n ? selected.filter((v) => v !== optValue)\n : [...selected, optValue];\n onChange(next);\n }\n\n return (\n <fieldset\n className=\"fh-field fh-field--multiselect\"\n aria-invalid={!!error || undefined}\n aria-describedby={describedBy}\n >\n {field.label && <legend className=\"fh-field__label\">{field.label}</legend>}\n <div className=\"fh-field__multiselect-group\">\n {options.map((opt) => {\n const optionId = `${groupId}-${opt.value}`;\n return (\n <div key={opt.value} className=\"fh-field__multiselect-option\">\n <input\n id={optionId}\n type=\"checkbox\"\n className=\"fh-field__checkbox\"\n checked={selected.includes(opt.value)}\n disabled={disabled || loading}\n onChange={() => handleToggle(opt.value)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n <label className=\"fh-field__multiselect-label\" htmlFor={optionId}>\n {opt.label}\n </label>\n </div>\n );\n })}\n </div>\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </fieldset>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function RadioField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const groupId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n const options = field.options ?? [];\n\n return (\n <fieldset\n className=\"fh-field fh-field--radio\"\n aria-invalid={!!error || undefined}\n aria-describedby={describedBy}\n >\n {field.label && <legend className=\"fh-field__label\">{field.label}</legend>}\n <div className=\"fh-field__radio-group\">\n {options.map((opt) => {\n const optionId = `${groupId}-${opt.value}`;\n return (\n <div key={opt.value} className=\"fh-field__radio-option\">\n <input\n id={optionId}\n type=\"radio\"\n className=\"fh-field__radio\"\n name={groupId}\n value={opt.value}\n checked={String(value) === String(opt.value)}\n disabled={disabled || loading}\n onChange={() => onChange(opt.value)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n <label className=\"fh-field__radio-label\" htmlFor={optionId}>\n {opt.label}\n </label>\n </div>\n );\n })}\n </div>\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </fieldset>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function SelectField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n const options = field.options ?? [];\n\n return (\n <div className=\"fh-field\">\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n {field.validation?.required && <span className=\"fh-field__required\" aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <select\n id={inputId}\n className=\"fh-field__input fh-field__input--select\"\n value={(value as string) ?? ''}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n onFocus={onFocus}\n >\n {field.placeholder && (\n <option value=\"\" disabled>\n {field.placeholder}\n </option>\n )}\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function SwitchField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n\n return (\n <div className=\"fh-field fh-field--switch\">\n <div className=\"fh-field__switch-wrapper\">\n <input\n id={inputId}\n type=\"checkbox\"\n role=\"switch\"\n className=\"fh-field__switch\"\n checked={!!value}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={(e) => onChange(e.target.checked)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n </label>\n )}\n </div>\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nexport function TextField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const v = e.target.value;\n onChange(field.type === 'number' ? Number(v) : v);\n };\n\n const inputType =\n field.type === 'email'\n ? 'email'\n : field.type === 'phone'\n ? 'tel'\n : field.type === 'number'\n ? 'number'\n : field.type === 'password'\n ? 'password'\n : 'text';\n\n return (\n <div className=\"fh-field\">\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n {field.validation?.required && <span className=\"fh-field__required\" aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <input\n id={inputId}\n type={inputType}\n className=\"fh-field__input\"\n value={value != null ? String(value) : ''}\n placeholder={field.placeholder ?? field.mask}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { FieldComponentProps } from '../types';\n\nconst DEFAULT_ROWS = 3;\n\nexport function TextareaField({\n field,\n value,\n error,\n loading,\n disabled,\n onChange,\n onBlur,\n onFocus,\n}: FieldComponentProps) {\n const inputId = field.key;\n const helperId = `${field.key}-helper`;\n const errorId = `${field.key}-error`;\n const describedBy = error ? errorId : field.helperText ? helperId : undefined;\n\n return (\n <div className=\"fh-field\">\n {field.label && (\n <label className=\"fh-field__label\" htmlFor={inputId}>\n {field.label}\n {field.validation?.required && <span className=\"fh-field__required\" aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <textarea\n id={inputId}\n className=\"fh-field__input fh-field__input--textarea\"\n value={(value as string) ?? ''}\n placeholder={field.placeholder}\n rows={field.rows ?? DEFAULT_ROWS}\n disabled={disabled || loading}\n aria-invalid={!!error}\n aria-describedby={describedBy}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n {error && (\n <p id={errorId} className=\"fh-field__error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && field.helperText && (\n <p id={helperId} className=\"fh-field__helper\">\n {field.helperText}\n </p>\n )}\n </div>\n );\n}\n","import type { DefaultFieldType, FormField as FormFieldType } from '@formhaus/core';\nimport type { ComponentType } from 'react';\nimport { AutocompleteField } from './fields/AutocompleteField';\nimport { CheckboxField } from './fields/CheckboxField';\nimport { DateField } from './fields/DateField';\nimport { DateTimeField } from './fields/DateTimeField';\nimport { FileField } from './fields/FileField';\nimport { MultiselectField } from './fields/MultiselectField';\nimport { RadioField } from './fields/RadioField';\nimport { SelectField } from './fields/SelectField';\nimport { SwitchField } from './fields/SwitchField';\nimport { TextField } from './fields/TextField';\nimport { TextareaField } from './fields/TextareaField';\nimport type { FieldComponentMap, FieldComponentProps } from './types';\n\nconst defaultComponents: Record<DefaultFieldType, ComponentType<FieldComponentProps>> = {\n text: TextField,\n email: TextField,\n phone: TextField,\n number: TextField,\n password: TextField,\n select: SelectField,\n autocomplete: AutocompleteField,\n multiselect: MultiselectField,\n checkbox: CheckboxField,\n radio: RadioField,\n switch: SwitchField,\n file: FileField,\n date: DateField,\n datetime: DateTimeField,\n textarea: TextareaField,\n};\n\ninterface FormFieldProps {\n field: FormFieldType;\n value: unknown;\n error?: string;\n loading?: boolean;\n disabled?: boolean;\n components?: FieldComponentMap;\n onChange: (value: unknown) => void;\n onBlur: () => void;\n onFocus?: () => void;\n}\n\nexport function FormField({\n field,\n value,\n error,\n loading,\n disabled,\n components,\n onChange,\n onBlur,\n onFocus,\n}: FormFieldProps) {\n const Component = components?.[field.type] ?? (defaultComponents as Record<string, ComponentType<FieldComponentProps>>)[field.type];\n\n if (!Component) {\n return <div>Unsupported field type: {field.type}</div>;\n }\n\n return (\n <Component\n field={field}\n value={value}\n error={error}\n loading={loading}\n disabled={disabled}\n onChange={onChange}\n onBlur={onBlur}\n onFocus={onFocus}\n />\n );\n}\n","import type { FormStepProgressProps } from './types';\n\nexport function FormStepProgress({\n current,\n total,\n stepTitle,\n stepDescription,\n}: FormStepProgressProps) {\n const percent = (current / total) * 100;\n\n return (\n <div className=\"fh-step-progress\">\n <div className=\"fh-step-progress__bar\">\n <div className=\"fh-step-progress__fill\" style={{ width: `${percent}%` }} />\n </div>\n <div className=\"fh-step-progress__info\">\n <span className=\"fh-step-progress__counter\">\n Step {current} of {total}\n </span>\n </div>\n {stepTitle && <h3 className=\"fh-step-progress__title\">{stepTitle}</h3>}\n {stepDescription && <p className=\"fh-step-progress__description\">{stepDescription}</p>}\n </div>\n );\n}\n","import type { FieldOption, FormField } from '@formhaus/core';\nimport { useEffect, useRef, useState } from 'react';\nimport type { OptionsProvider } from '../types';\n\nexport function useFieldOptions(\n fields: FormField[],\n values: Record<string, unknown>,\n providers?: Record<string, OptionsProvider>,\n): Record<string, FieldOption[]> {\n const [resolved, setResolved] = useState<Record<string, FieldOption[]>>({});\n const lastDepsRef = useRef<Map<string, string>>(new Map());\n\n useEffect(() => {\n if (!providers) return;\n\n let isStale = false;\n\n for (const field of fields) {\n if (!field.optionsFrom) continue;\n\n const provider = providers[field.optionsFrom];\n if (!provider) continue;\n\n const depsKey = (field.optionsDependsOn ?? []).map((k) => values[k]).join('|');\n\n if (lastDepsRef.current.get(field.key) === depsKey) continue;\n lastDepsRef.current.set(field.key, depsKey);\n\n const result = provider(values);\n\n if (Array.isArray(result)) {\n if (!isStale) setResolved((prev) => ({ ...prev, [field.key]: result }));\n } else {\n result\n .then((options) => {\n if (!isStale) setResolved((prev) => ({ ...prev, [field.key]: options }));\n })\n .catch(() => {\n lastDepsRef.current.delete(field.key);\n });\n }\n }\n\n return () => { isStale = true; };\n }, [fields, values, providers]);\n\n return resolved;\n}\n","import { FormEngine, type FormEngineOptions, type FormDefinition } from '@formhaus/core';\nimport { useCallback, useRef, useSyncExternalStore } from 'react';\n\nexport function useFormEngine(\n definition: FormDefinition,\n initialValues?: Record<string, unknown>,\n options?: FormEngineOptions,\n): FormEngine {\n const engineRef = useRef<FormEngine | null>(null);\n const definitionIdRef = useRef<string>(definition.id);\n\n if (engineRef.current === null || definitionIdRef.current !== definition.id) {\n engineRef.current = new FormEngine(definition, initialValues, options);\n definitionIdRef.current = definition.id;\n }\n\n const engine = engineRef.current;\n\n const subscribe = useCallback((listener: () => void) => engine.subscribe(listener), [engine]);\n const getSnapshot = useCallback(() => engine.getSnapshot(), [engine]);\n\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return engine;\n}\n","import type { FormEngineOptions } from '@formhaus/core';\nimport { useEffect } from 'react';\nimport { FormActions } from './FormActions';\nimport { FormField } from './FormField';\nimport { FormStepProgress } from './FormStepProgress';\nimport { useFieldOptions } from './hooks/useFieldOptions';\nimport { useFormEngine } from './hooks/useFormEngine';\nimport type { FormRendererProps } from './types';\n\nexport function FormRenderer({\n definition,\n initialValues,\n onSubmit,\n onCancel,\n onStepChange,\n onFieldChange,\n validators,\n onStepValidate,\n errors: externalErrors,\n loading = false,\n components,\n optionsProviders,\n ActionsComponent,\n ProgressComponent,\n onAnalyticsEvent,\n}: FormRendererProps) {\n const engineOptions: FormEngineOptions = { validators, onStepValidate };\n const engine = useFormEngine(definition, initialValues, engineOptions);\n const resolvedOptions = useFieldOptions(engine.visibleFields, engine.values, optionsProviders);\n\n useEffect(() => {\n if (externalErrors) {\n engine.setErrors(externalErrors);\n }\n }, [externalErrors, engine]);\n\n function handleFieldUpdate(key: string, value: unknown) {\n engine.setValue(key, value);\n onFieldChange?.(key, value, engine.values);\n }\n\n function handleFieldFocus(key: string) {\n onAnalyticsEvent?.({ type: 'field_focused', fieldKey: key });\n }\n\n function handleFieldBlur(key: string) {\n onAnalyticsEvent?.({\n type: 'field_blurred',\n fieldKey: key,\n hasValue: engine.values[key] !== undefined && engine.values[key] !== '',\n });\n }\n\n function handleSubmit(e: React.FormEvent) {\n e.preventDefault();\n const allErrors = engine.validate();\n for (const [key, msg] of Object.entries(allErrors)) {\n onAnalyticsEvent?.({ type: 'field_error', fieldKey: key, error: msg });\n }\n if (Object.keys(allErrors).length > 0) return;\n const submitValues = engine.getSubmitValues();\n onAnalyticsEvent?.({ type: 'form_submitted', fieldCount: Object.keys(submitValues).length });\n onSubmit(submitValues as Record<string, unknown>);\n }\n\n async function handleNext() {\n const prevStep = engine.currentStep;\n const success = await engine.nextStepAsync();\n if (success) {\n if (prevStep) {\n onAnalyticsEvent?.({ type: 'step_completed', stepId: prevStep.id });\n }\n if (engine.currentStep) {\n onStepChange?.(engine.currentStep.id, 'next');\n onAnalyticsEvent?.({\n type: 'step_viewed',\n stepId: engine.currentStep.id,\n stepIndex: engine.currentStepIndex,\n });\n }\n }\n }\n\n function handlePrev() {\n engine.prevStep();\n if (engine.currentStep) {\n onStepChange?.(engine.currentStep.id, 'back');\n }\n }\n\n function handleCancel() {\n onCancel?.();\n }\n\n const ProgressComp = ProgressComponent ?? FormStepProgress;\n const ActionsComp = ActionsComponent ?? FormActions;\n\n const effectiveIsLastStep = engine.isLastStep || !engine.isMultiStep;\n const computedPrimaryLabel = engine.isMultiStep && !effectiveIsLastStep\n ? (engine.currentStep?.next?.label ?? 'Continue')\n : (definition.submit?.label ?? 'Submit');\n const computedShowBack = engine.isMultiStep && !engine.isFirstStep && engine.currentStep?.back !== false;\n const computedBackLabel = typeof engine.currentStep?.back === 'object'\n ? (engine.currentStep.back.label ?? 'Back')\n : 'Back';\n\n async function handlePrimary() {\n if (engine.isMultiStep && !effectiveIsLastStep) {\n await handleNext();\n } else {\n handleSubmit({ preventDefault: () => {} } as React.FormEvent);\n }\n }\n\n return (\n <form className=\"fh-form\" onSubmit={handleSubmit}>\n {engine.isMultiStep && (\n <ProgressComp\n current={engine.progress.current}\n total={engine.progress.total}\n stepTitle={engine.currentStep?.title}\n stepDescription={engine.currentStep?.description}\n />\n )}\n\n <div className=\"fh-form__fields\">\n {engine.visibleFields.map((field) => {\n const fieldWithOptions = resolvedOptions[field.key]\n ? { ...field, options: resolvedOptions[field.key] }\n : field;\n return (\n <FormField\n key={field.key}\n field={fieldWithOptions}\n value={engine.values[field.key]}\n error={engine.errors[field.key]}\n loading={engine.fieldLoading[field.key]}\n disabled={loading}\n components={components}\n onChange={(v) => handleFieldUpdate(field.key, v)}\n onBlur={() => handleFieldBlur(field.key)}\n onFocus={() => handleFieldFocus(field.key)}\n />\n );\n })}\n </div>\n\n {engine.topLevelErrors.length > 0 && (\n <div className=\"fh-form__top-errors\">\n {engine.topLevelErrors.map((error) => (\n <p key={error} className=\"fh-form__top-error\">\n {error}\n </p>\n ))}\n </div>\n )}\n\n <ActionsComp\n submitAction={definition.submit}\n backAction={engine.currentStep?.back}\n cancelAction={definition.cancel}\n isFirstStep={engine.isFirstStep}\n isLastStep={effectiveIsLastStep}\n isMultiStep={engine.isMultiStep}\n loading={loading || engine.stepValidating}\n values={engine.values}\n onSubmit={() => handleSubmit({ preventDefault: () => {} } as React.FormEvent)}\n onNext={handleNext}\n onPrev={handlePrev}\n onCancel={handleCancel}\n primaryLabel={computedPrimaryLabel}\n showBack={computedShowBack}\n backLabel={computedBackLabel}\n onPrimary={handlePrimary}\n />\n </form>\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formhaus/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "React components for
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "React components for Formhaus forms. Define a form once in JSON, render with native HTML or your own components.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
9
10
|
"exports": {
|
|
10
11
|
".": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"dist"
|
|
17
18
|
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsc",
|
|
20
|
-
"test": "vitest run",
|
|
21
|
-
"clean": "rm -rf dist"
|
|
22
|
-
},
|
|
23
19
|
"dependencies": {
|
|
24
|
-
"@formhaus/core": "
|
|
20
|
+
"@formhaus/core": "0.4.0"
|
|
25
21
|
},
|
|
26
22
|
"peerDependencies": {
|
|
27
23
|
"react": ">=18.0.0"
|
|
@@ -33,13 +29,21 @@
|
|
|
33
29
|
"jsdom": "^29.0.2",
|
|
34
30
|
"react": "^19.2.4",
|
|
35
31
|
"react-dom": "^19.2.4",
|
|
32
|
+
"tsup": "^8.5.1",
|
|
36
33
|
"typescript": "^5.7.3",
|
|
37
34
|
"vitest": "^4.1.3"
|
|
38
35
|
},
|
|
39
36
|
"license": "MIT",
|
|
40
37
|
"repository": {
|
|
41
38
|
"type": "git",
|
|
42
|
-
"url": "https://github.com/ignsm/formhaus.git",
|
|
39
|
+
"url": "git+https://github.com/ignsm/formhaus.git",
|
|
43
40
|
"directory": "packages/react"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"test:watch": "vitest",
|
|
46
|
+
"test:resolve": "node --input-type=module -e \"import('./dist/index.js').then(m => { if (!m.FormRenderer) process.exit(1); console.log('ESM resolve OK'); })\"",
|
|
47
|
+
"clean": "rm -rf dist"
|
|
44
48
|
}
|
|
45
|
-
}
|
|
49
|
+
}
|
package/dist/FormActions.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { FormActionsProps } from './types';
|
|
2
|
-
export declare function FormActions({ submitAction, backAction, cancelAction, isFirstStep, isLastStep, isMultiStep, loading, values, onSubmit, onNext, onPrev, onCancel, primaryLabel: primaryLabelProp, showBack: showBackProp, backLabel: backLabelProp, onPrimary: onPrimaryProp, }: FormActionsProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
-
//# sourceMappingURL=FormActions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FormActions.d.ts","sourceRoot":"","sources":["../src/FormActions.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAYhD,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,OAAO,EACP,MAAW,EACX,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,aAAa,GACzB,EAAE,gBAAgB,2CAwDlB"}
|
package/dist/FormActions.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { evaluateCondition } from '@formhaus/core';
|
|
3
|
-
function isActionDisabled(action, values, loading) {
|
|
4
|
-
if (loading)
|
|
5
|
-
return true;
|
|
6
|
-
if (!action?.disabled || action.disabled.length === 0)
|
|
7
|
-
return false;
|
|
8
|
-
return action.disabled.every((c) => evaluateCondition(c, values));
|
|
9
|
-
}
|
|
10
|
-
export function FormActions({ submitAction, backAction, cancelAction, isFirstStep, isLastStep, isMultiStep, loading, values = {}, onSubmit, onNext, onPrev, onCancel, primaryLabel: primaryLabelProp, showBack: showBackProp, backLabel: backLabelProp, onPrimary: onPrimaryProp, }) {
|
|
11
|
-
const showBack = showBackProp ?? (isMultiStep && !isFirstStep && backAction !== false);
|
|
12
|
-
const backLabel = backLabelProp ?? (typeof backAction === 'object' ? (backAction?.label ?? 'Back') : 'Back');
|
|
13
|
-
const primaryLabel = primaryLabelProp ?? (isMultiStep && !isLastStep ? 'Continue' : (submitAction?.label ?? 'Submit'));
|
|
14
|
-
const primaryDisabled = isActionDisabled(isMultiStep && !isLastStep ? undefined : submitAction, values, loading);
|
|
15
|
-
function handlePrimary() {
|
|
16
|
-
if (onPrimaryProp) {
|
|
17
|
-
onPrimaryProp();
|
|
18
|
-
}
|
|
19
|
-
else if (isMultiStep && !isLastStep) {
|
|
20
|
-
onNext();
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
onSubmit();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return (_jsxs("div", { className: "fh-form-actions", children: [_jsxs("div", { className: "fh-form-actions__secondary", children: [showBack && (_jsx("button", { type: "button", className: "fh-form-actions__button fh-form-actions__button--text", disabled: loading, onClick: onPrev, children: backLabel })), cancelAction && (_jsx("button", { type: "button", className: "fh-form-actions__button fh-form-actions__button--text", disabled: loading, onClick: onCancel, children: cancelAction.label }))] }), _jsx("button", { type: "button", className: "fh-form-actions__button fh-form-actions__button--primary", disabled: primaryDisabled, "aria-busy": loading, onClick: handlePrimary, children: primaryLabel })] }));
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=FormActions.js.map
|
package/dist/FormActions.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FormActions.js","sourceRoot":"","sources":["../src/FormActions.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAInD,SAAS,gBAAgB,CACvB,MAA8B,EAC9B,MAA+B,EAC/B,OAAiB;IAEjB,IAAI,OAAO;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAC1B,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,OAAO,EACP,MAAM,GAAG,EAAE,EACX,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,aAAa,GACP;IACjB,MAAM,QAAQ,GAAG,YAAY,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,IAAI,UAAU,KAAK,KAAK,CAAC,CAAC;IACvF,MAAM,SAAS,GAAG,aAAa,IAAI,CAAC,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC7G,MAAM,YAAY,GAAG,gBAAgB,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC;IAEvH,MAAM,eAAe,GAAG,gBAAgB,CACtC,WAAW,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,EACrD,MAAM,EACN,OAAO,CACR,CAAC;IAEF,SAAS,aAAa;QACpB,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,EAAE,CAAC;QAClB,CAAC;aAAM,IAAI,WAAW,IAAI,CAAC,UAAU,EAAE,CAAC;YACtC,MAAM,EAAE,CAAC;QACX,CAAC;aAAM,CAAC;YACN,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,iBAAiB,aAC9B,eAAK,SAAS,EAAC,4BAA4B,aACxC,QAAQ,IAAI,CACX,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,uDAAuD,EACjE,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,MAAM,YAEd,SAAS,GACH,CACV,EACA,YAAY,IAAI,CACf,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,uDAAuD,EACjE,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,QAAQ,YAEhB,YAAY,CAAC,KAAK,GACZ,CACV,IACG,EACN,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,0DAA0D,EACpE,QAAQ,EAAE,eAAe,eACd,OAAO,EAClB,OAAO,EAAE,aAAa,YAErB,YAAY,GACN,IACL,CACP,CAAC;AACJ,CAAC"}
|
package/dist/FormField.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { FormField as FormFieldType } from '@formhaus/core';
|
|
2
|
-
import type { FieldComponentMap } from './types';
|
|
3
|
-
interface FormFieldProps {
|
|
4
|
-
field: FormFieldType;
|
|
5
|
-
value: unknown;
|
|
6
|
-
error?: string;
|
|
7
|
-
loading?: boolean;
|
|
8
|
-
disabled?: boolean;
|
|
9
|
-
components?: FieldComponentMap;
|
|
10
|
-
onChange: (value: unknown) => void;
|
|
11
|
-
onBlur: () => void;
|
|
12
|
-
onFocus?: () => void;
|
|
13
|
-
}
|
|
14
|
-
export declare function FormField({ field, value, error, loading, disabled, components, onChange, onBlur, onFocus, }: FormFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
-
export {};
|
|
16
|
-
//# sourceMappingURL=FormField.d.ts.map
|
package/dist/FormField.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../src/FormField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,SAAS,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAWnF,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,SAAS,CAAC;AAkBtE,UAAU,cAAc;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,KAAK,EACL,OAAO,EACP,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,MAAM,EACN,OAAO,GACR,EAAE,cAAc,2CAmBhB"}
|
package/dist/FormField.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { CheckboxField } from './fields/CheckboxField';
|
|
3
|
-
import { DateField } from './fields/DateField';
|
|
4
|
-
import { FileField } from './fields/FileField';
|
|
5
|
-
import { MultiselectField } from './fields/MultiselectField';
|
|
6
|
-
import { RadioField } from './fields/RadioField';
|
|
7
|
-
import { SelectField } from './fields/SelectField';
|
|
8
|
-
import { SwitchField } from './fields/SwitchField';
|
|
9
|
-
import { TextField } from './fields/TextField';
|
|
10
|
-
import { TextareaField } from './fields/TextareaField';
|
|
11
|
-
const defaultComponents = {
|
|
12
|
-
text: TextField,
|
|
13
|
-
email: TextField,
|
|
14
|
-
phone: TextField,
|
|
15
|
-
number: TextField,
|
|
16
|
-
password: TextField,
|
|
17
|
-
select: SelectField,
|
|
18
|
-
multiselect: MultiselectField,
|
|
19
|
-
checkbox: CheckboxField,
|
|
20
|
-
radio: RadioField,
|
|
21
|
-
switch: SwitchField,
|
|
22
|
-
file: FileField,
|
|
23
|
-
date: DateField,
|
|
24
|
-
textarea: TextareaField,
|
|
25
|
-
};
|
|
26
|
-
export function FormField({ field, value, error, loading, disabled, components, onChange, onBlur, onFocus, }) {
|
|
27
|
-
const Component = components?.[field.type] ?? defaultComponents[field.type];
|
|
28
|
-
if (!Component) {
|
|
29
|
-
return _jsxs("div", { children: ["Unsupported field type: ", field.type] });
|
|
30
|
-
}
|
|
31
|
-
return (_jsx(Component, { field: field, value: value, error: error, loading: loading, disabled: disabled, onChange: onChange, onBlur: onBlur, onFocus: onFocus }));
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=FormField.js.map
|
package/dist/FormField.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FormField.js","sourceRoot":"","sources":["../src/FormField.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,MAAM,iBAAiB,GAAiE;IACtF,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,SAAS;IACnB,MAAM,EAAE,WAAW;IACnB,WAAW,EAAE,gBAAgB;IAC7B,QAAQ,EAAE,aAAa;IACvB,KAAK,EAAE,UAAU;IACjB,MAAM,EAAE,WAAW;IACnB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,aAAa;CACxB,CAAC;AAcF,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,KAAK,EACL,OAAO,EACP,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,MAAM,EACN,OAAO,GACQ;IACf,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAK,iBAAwE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpI,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,sDAA8B,KAAK,CAAC,IAAI,IAAO,CAAC;IACzD,CAAC;IAED,OAAO,CACL,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,GAChB,CACH,CAAC;AACJ,CAAC"}
|
package/dist/FormRenderer.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { FormRendererProps } from './types';
|
|
2
|
-
export declare function FormRenderer({ schema, initialValues, onSubmit, onCancel, onStepChange, onFieldChange, validators, errors: externalErrors, loading, components, optionsProviders, ActionsComponent, ProgressComponent, onAnalyticsEvent, }: FormRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
-
//# sourceMappingURL=FormRenderer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../src/FormRenderer.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,UAAU,EACV,MAAM,EAAE,cAAc,EACtB,OAAe,EACf,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GACjB,EAAE,iBAAiB,2CAwJnB"}
|