@ycw-side-projects/dynamic-form-kit-react
Version:
A personal dynamic form kit for React.
274 lines (217 loc) • 9.55 kB
Markdown
# `dynamic-form-kit-react`
> This project is for demonstration purposes only.
> If you need a fully functional form package for real applications, please consider using a more comprehensive and actively maintained form component library, and integrate it with other dynamic form solutions.
> website: [dynamic-form-kit-react](https://chunwei.dev/en/projects/dynamic-form-kit-react)
<!-- LANG-TABLE-START -->
| **Language** | **README** |
|----------|------|
| **English** | [English README](README.md) |
| **繁體中文** | [繁體中文 README](README.zh-Hant.md) |
<!-- LANG-TABLE-END -->
## Overview
This is a `React` package for quickly generating form UIs using `TypeScript`.
- Generate a `Dynamic Form` through `Dynamic Form Setting`, with `IntelliSense` support during editing in IDEs such as `VSCode`.
- Generate `Static Form` files via commands. The UI behavior is consistent with the `Dynamic Form`, and it removes dependency on the package.
- Use the `Dynamic Form Setting Editor` to create and configure `Dynamic Form Settings`.
Overview Diagram:

## Terminology List
### General
| Term | Description |
|---|---|
| `Dynamic Form` | A form UI generated dynamically through configuration |
| `Static Form` | A form UI with fixed components, not generated dynamically through configuration |
| `Dynamic Form Setting` | Configuration for dynamic forms, including assigned form components and related parameters for each field |
### Package Components
| Term | Description |
|---|---|
| `Dynamic Form Component Setting` | Component configuration for form fields |
| `Dynamic Form Validator Setting` | Validator configuration for form fields |
| `Dynamic Form Builder` | A component that generates the form UI dynamically based on configuration |
| `Form Component Library` | A centralized collection of form components |
### Package User Interface
| Term | Description |
|---|---|
| `Static Form Generator Commands` | Command set for generating static forms |
| `Dynamic Form Setting Editor` | UI for editing dynamic form settings |
| `Dynamic Form Setting Template` | A preset configuration set for fields, used in the settings editor |
## Package Architecture
### Application Diagram:

### `Dynamic Form Component Setting`
#### Syntax
```ts
export const #objectName# = createDynamicFormComponentSetting<
#FormInterface#,
#ComponentLibraryObject(optional)#
>()((d) => ({
#fieldSettings(optional)#
}));
```
`#fieldSettings(optional)#` Syntax
Each field uses the following syntax:
```ts
"#fieldName#": d({
componentName: #componentName#,
componentProps: #componentProps#
}),
```
Supports IntelliSense suggestions for:
- `#fieldName#`
- `#componentName#`
- `#componentProps#`: Component property settings
Custom Form Data Example:

Configuration Example:

`VS Code IntelliSense` Example:

### `Dynamic Form Validator Setting`
#### Syntax
```ts
const #objectName#: DynamicFormValidatorSetting<#FormInterface#> = {
#fieldSettings(optional)#
};
```
`#fieldSettings(optional)#` Syntax
Each field uses the following syntax:
```ts
"#fieldName#": {
validator: (fieldValue, parentObject, fieldKey, form) => {
// Validation logic ...
return {
isError: boolean,
message: string
};
},
validGroupId?: string // Optional validation group ID
}
```
> If multiple fields share the same `validGroupId`, triggering validation in one field will validate all fields in that group.
Supports IntelliSense suggestions for:
- `#fieldName#`
Configuration Example:

`VS Code IntelliSense` Example:

### `Dynamic Form Builder`
#### Syntax
```ts
const #objectName# = <DynamicFormBuilder<#FormInterface#>
formData={...}
onChange={...}
componentSetting={...}
validatorSetting={...}
actionButtons={...} // Optional: submit, reset, etc.
componentLibrary={...} // Optional: custom component library
/>
```
Simple Example:

Simple Example UI:


### `Form Component Library`
A centralized collection of form components.
Built-in component library included.

#### Custom Extended Component Library
##### Syntax
```ts
const #objectName# = {
#customComponentName#: #componentDefinition#,
// ...more components
}
```
- `#objectName#`: Name of the custom component library
- `#customComponentName#`: The unique identifier for this component within the custom extended component library, used in the `Dynamic Form Component Setting`
Example:

#### Custom Form Component
##### Syntax
```ts
export const #objectName# = createDynamicFormComponentForLib<#CustomComponentProps#>()({
component: #CustomComponent#,
props: {} as #CustomComponentProps#,
propsKeys: #keys for generator#,
demo: #DemoComponent#,
propsEditor: #PropsEditorComponent#, // Optional
icon: #icon# // Optional
})
```
| Field Name | Purpose | Required |
|----------------|---------|----------|
| `component` | The actual React component used for rendering | Yes |
| `props` | Component props type for IntelliSense | Yes |
| `propsKeys` | Key props for `Static Form` generation (e.g. `value`, `onChange`, `validation`) | Yes |
| `demo` | Demo component shown in `Dynamic Form Setting Editor` | Yes |
| `propsEditor` | Custom props editor for configuring component props in `Dynamic Form Setting Editor` | Optional |
| `icon` | Custom icon shown in `Dynamic Form Setting Editor` | Optional |
`propsEditor` specification: Use `DynamicFormComponentStandardPropsEditor`, `DynamicFormComponentDynamicPropsTextEditor`, or a custom React component with compatible type.
Example:

### Multi-language (i18n)
### Syntax
```ts
const getI18nLang_fromUrl = (): I18nLangType | null => { /* return I18nLangType|null */ };
const setI18nLang_toUrl = (lang: I18nLangType | null) => { /* custom code */ };
const TextProviderContent = () => {
const controller = useI18nController();
return <I18nTextProvider controller={controller}>
<#App# controller={controller} />
</I18nTextProvider>;
};
const ControllerProviderContent = () => {
return <I18nControllerProvider
useControllerHook={useDefaultI18nLangController} // Can be replaced with a custom hook
options={{
localStorageKey: '#custom key#',
defaultLang: "en", // Custom default
usingUrlLang: { getUrlLang: getI18nLang_fromUrl, setUrlLang: setI18nLang_toUrl } // Optional
}}
>
<TextProviderContent />
</I18nControllerProvider>;
};
```
| Block | Purpose |
|--------|---------|
| `getI18nLang_fromUrl` / `setI18nLang_toUrl` | Custom URL read/write for language synchronization |
| `<I18nControllerProvider>` | Creates a global i18n controller (language state, localStorage, URL sync) |
| `useControllerHook` | Specifies the language controller hook |
| `options.localStorageKey` | Key used in localStorage for language settings |
| `options.defaultLang` | Default language using `I18nLangType` (e.g. `"en"`) |
| `options.usingUrlLang` | Optional URL-based language sync mechanism |
| `<I18nTextProvider>` | Provides actual text mappings (dictionary lookup) |
| `controller` | Language controller, required for `I18nTextProvider`, `Dynamic Form Setting Editor`, and `Static Form` |
- `useControllerHook`: There is a default `useDefaultI18nLangController` that can be used.
Example:

### `Dynamic Form Setting Editor`
Using the editor:
Use `<DynamicFormHome #componentLibMap(optional)# />` to open the editor.
- `#componentLibMap#`: Object in `Map<string, ComponentLibForEditor>` format. Use `getDefaultMapComponentLibForEditor()` to get default libraries.
#### Syntax
```ts
const #objectName# = <DynamicFormHome
componentLibMap={#Component Library Map#}
langController={#II18nLangController#}
/>
```
- `#Component Library Map#`: A `Map` object that maps `string` to `Form Component Library`
- `#II18nLangController#`: `II18nLangController` object
Example:

`Dynamic Form Setting Editor` UI description:
- See in the UI
### `Static Form Generator Commands`
Generate static forms:
```bash
npx gen-static-form --source "#source dir#" --target "#target dir#"
```
- `"#source dir#"`: Top folder containing `Dynamic Form Component Setting`
- `"#target dir#"`: Target folder for generated `Static Form`, will overwrite but not delete
Example:

## Notes
- IDE used: `VS Code`; other IDEs are not tested.