autoforma 1.0.0 → 1.0.1
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/dist/index.cjs.js +70 -0
- package/dist/index.es.js +13532 -0
- package/dist/src/components/AutoForm.d.ts +18 -0
- package/dist/src/components/FieldRender.d.ts +16 -0
- package/dist/src/components/fields/ArrayField.d.ts +13 -0
- package/dist/src/components/fields/CheckField.d.ts +7 -0
- package/dist/src/components/fields/DateField.d.ts +6 -0
- package/dist/src/components/fields/DateTimeField.d.ts +6 -0
- package/dist/src/components/fields/NumberField.d.ts +6 -0
- package/dist/src/components/fields/ObjectField.d.ts +9 -0
- package/dist/src/components/fields/SelectField.d.ts +10 -0
- package/dist/src/components/fields/TextAreaField.d.ts +6 -0
- package/dist/src/components/fields/TextField.d.ts +6 -0
- package/dist/src/components/fields/TimeField.d.ts +6 -0
- package/{src/index.ts → dist/src/index.d.ts} +2 -3
- package/dist/src/stories/AutoForm.stories.d.ts +9 -0
- package/dist/src/stories/Fields.stories.d.ts +12 -0
- package/dist/src/theme.d.ts +141 -0
- package/dist/src/types/custom-render.d.ts +11 -0
- package/dist/src/types/field.d.ts +30 -0
- package/dist/src/types/form.d.ts +7 -0
- package/{test-utils/index.ts → dist/test-utils/index.d.ts} +1 -2
- package/dist/test-utils/render.d.ts +1 -0
- package/package.json +9 -3
- package/.github/workflows/npm_test.yml +0 -27
- package/.nvmrc +0 -1
- package/.prettierrc.mjs +0 -35
- package/.storybook/main.ts +0 -17
- package/.storybook/preview.tsx +0 -18
- package/.storybook/vitest.setup.ts +0 -9
- package/.stylelintignore +0 -1
- package/.stylelintrc.json +0 -28
- package/.yarn/releases/yarn-4.9.1.cjs +0 -948
- package/.yarnrc.yml +0 -3
- package/eslint.config.js +0 -11
- package/index.html +0 -16
- package/postcss.config.cjs +0 -14
- package/src/favicon.svg +0 -1
- package/src/stories/AutoForm.stories.tsx +0 -473
- package/src/stories/Fields.stories.tsx +0 -190
- package/src/theme.ts +0 -5
- package/src/vite-env.d.ts +0 -1
- package/storybook-static/assets/AutoForm-CEr4m2za.js +0 -53
- package/storybook-static/assets/AutoForm.stories-CtOmRKOV.js +0 -164
- package/storybook-static/assets/Color-YHDXOIA2-pc5-Ao7n.js +0 -1
- package/storybook-static/assets/DocsRenderer-CFRXHY34-D-_1VvMG.js +0 -575
- package/storybook-static/assets/Fields.stories-CoRkpMbJ.js +0 -29
- package/storybook-static/assets/chunk-XP5HYGXS-BpfKkqn7.js +0 -1
- package/storybook-static/assets/entry-preview-CkHoqRUh.js +0 -2
- package/storybook-static/assets/entry-preview-docs-hFR7sEJd.js +0 -46
- package/storybook-static/assets/get-contrast-color-Db6nT3bs.js +0 -1
- package/storybook-static/assets/iframe-CzpwBD2i.js +0 -211
- package/storybook-static/assets/index-B8rYRX2K.js +0 -1
- package/storybook-static/assets/index-BQQLSK9g.js +0 -1
- package/storybook-static/assets/index-CXQShRbs.js +0 -8
- package/storybook-static/assets/index-D4lIrffr.js +0 -9
- package/storybook-static/assets/index-Domkg0jQ.js +0 -240
- package/storybook-static/assets/index-DrFu-skq.js +0 -6
- package/storybook-static/assets/index-DsJinFGm.js +0 -9
- package/storybook-static/assets/jsx-runtime-D_zvdyIk.js +0 -9
- package/storybook-static/assets/preview-B8lJiyuQ.js +0 -34
- package/storybook-static/assets/preview-BBWR9nbA.js +0 -1
- package/storybook-static/assets/preview-BOfrPh1e.js +0 -2
- package/storybook-static/assets/preview-BWzBA1C2.js +0 -396
- package/storybook-static/assets/preview-C2Qr78FS.js +0 -4
- package/storybook-static/assets/preview-CvbIS5ZJ.js +0 -1
- package/storybook-static/assets/preview-DD_OYowb.js +0 -1
- package/storybook-static/assets/preview-DGUiP6tS.js +0 -7
- package/storybook-static/assets/preview-DioFdWiE.css +0 -1
- package/storybook-static/assets/preview-Dyg8NwXV.js +0 -1
- package/storybook-static/assets/react-18-Dhjvimrl.js +0 -25
- package/storybook-static/assets/test-utils--_O2wM1y.js +0 -9
- package/storybook-static/favicon.svg +0 -1
- package/storybook-static/iframe.html +0 -666
- package/storybook-static/index.html +0 -181
- package/storybook-static/index.json +0 -1
- package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/project.json +0 -1
- package/storybook-static/sb-addons/chromatic-com-storybook-9/manager-bundle.js +0 -331
- package/storybook-static/sb-addons/chromatic-com-storybook-9/manager-bundle.js.LEGAL.txt +0 -51
- package/storybook-static/sb-addons/docs-11/manager-bundle.js +0 -242
- package/storybook-static/sb-addons/essentials-actions-2/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-backgrounds-3/manager-bundle.js +0 -12
- package/storybook-static/sb-addons/essentials-controls-1/manager-bundle.js +0 -402
- package/storybook-static/sb-addons/essentials-measure-6/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-outline-7/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-toolbars-5/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/essentials-viewport-4/manager-bundle.js +0 -3
- package/storybook-static/sb-addons/onboarding-8/manager-bundle.js +0 -127
- package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +0 -3
- package/storybook-static/sb-addons/storybook-experimental-addon-test-10/manager-bundle.js +0 -223
- package/storybook-static/sb-common-assets/favicon.svg +0 -1
- package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/sb-manager/globals-module-info.js +0 -1051
- package/storybook-static/sb-manager/globals-runtime.js +0 -41591
- package/storybook-static/sb-manager/globals.js +0 -48
- package/storybook-static/sb-manager/runtime.js +0 -12048
- package/test-utils/render.tsx +0 -11
- package/text +0 -64
- package/tsconfig.json +0 -25
- package/vite.config.mjs +0 -19
- package/vitest.setup.mjs +0 -29
- package/vitest.shims.d.ts +0 -1
- package/vitest.workspace.js +0 -30
package/.yarnrc.yml
DELETED
package/eslint.config.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import mantine from 'eslint-config-mantine';
|
|
2
|
-
import tseslint from 'typescript-eslint';
|
|
3
|
-
|
|
4
|
-
export default tseslint.config(
|
|
5
|
-
...mantine,
|
|
6
|
-
{ ignores: ['**/*.{mjs,cjs,js,d.ts,d.mts}', './.storybook/main.ts'] },
|
|
7
|
-
{
|
|
8
|
-
files: ['**/*.story.tsx'],
|
|
9
|
-
rules: { 'no-console': 'off' },
|
|
10
|
-
}
|
|
11
|
-
);
|
package/index.html
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
|
6
|
-
<meta
|
|
7
|
-
name="viewport"
|
|
8
|
-
content="minimum-scale=1, initial-scale=1, width=device-width, user-scalable=no"
|
|
9
|
-
/>
|
|
10
|
-
<title>Vite + Mantine App</title>
|
|
11
|
-
</head>
|
|
12
|
-
<body>
|
|
13
|
-
<div id="root"></div>
|
|
14
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
15
|
-
</body>
|
|
16
|
-
</html>
|
package/postcss.config.cjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
plugins: {
|
|
3
|
-
'postcss-preset-mantine': {},
|
|
4
|
-
'postcss-simple-vars': {
|
|
5
|
-
variables: {
|
|
6
|
-
'mantine-breakpoint-xs': '36em',
|
|
7
|
-
'mantine-breakpoint-sm': '48em',
|
|
8
|
-
'mantine-breakpoint-md': '62em',
|
|
9
|
-
'mantine-breakpoint-lg': '75em',
|
|
10
|
-
'mantine-breakpoint-xl': '88em',
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
};
|
package/src/favicon.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 163 163"><path fill="#339AF0" d="M162.162 81.5c0-45.011-36.301-81.5-81.08-81.5C36.301 0 0 36.489 0 81.5 0 126.51 36.301 163 81.081 163s81.081-36.49 81.081-81.5z"/><path fill="#fff" d="M65.983 43.049a6.234 6.234 0 00-.336 6.884 6.14 6.14 0 001.618 1.786c9.444 7.036 14.866 17.794 14.866 29.52 0 11.726-5.422 22.484-14.866 29.52a6.145 6.145 0 00-1.616 1.786 6.21 6.21 0 00-.694 4.693 6.21 6.21 0 001.028 2.186 6.151 6.151 0 006.457 2.319 6.154 6.154 0 002.177-1.035 50.083 50.083 0 007.947-7.39h17.493c3.406 0 6.174-2.772 6.174-6.194s-2.762-6.194-6.174-6.194h-9.655a49.165 49.165 0 004.071-19.69 49.167 49.167 0 00-4.07-19.692h9.66c3.406 0 6.173-2.771 6.173-6.194 0-3.422-2.762-6.193-6.173-6.193H82.574a50.112 50.112 0 00-7.952-7.397 6.15 6.15 0 00-4.578-1.153 6.189 6.189 0 00-4.055 2.438h-.006z"/><path fill="#fff" fill-rule="evenodd" d="M56.236 79.391a9.342 9.342 0 01.632-3.608 9.262 9.262 0 011.967-3.077 9.143 9.143 0 012.994-2.063 9.06 9.06 0 017.103 0 9.145 9.145 0 012.995 2.063 9.262 9.262 0 011.967 3.077 9.339 9.339 0 01-2.125 10.003 9.094 9.094 0 01-6.388 2.63 9.094 9.094 0 01-6.39-2.63 9.3 9.3 0 01-2.755-6.395z" clip-rule="evenodd"/></svg>
|
|
@@ -1,473 +0,0 @@
|
|
|
1
|
-
import AutoForm from '@/components/AutoForm';
|
|
2
|
-
import FieldRender, { getArrayOptions } from '@/components/FieldRender';
|
|
3
|
-
import { CustomFieldRender } from '@/types/custom-render';
|
|
4
|
-
import { FieldSchema } from '@/types/field';
|
|
5
|
-
import { Accordion, Button, Grid, Group, Modal, Table, Text } from '@mantine/core';
|
|
6
|
-
import { useDisclosure } from '@mantine/hooks';
|
|
7
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
8
|
-
|
|
9
|
-
// ------------------------------
|
|
10
|
-
// Schema Definitions
|
|
11
|
-
// ------------------------------
|
|
12
|
-
|
|
13
|
-
const schema: FieldSchema[] = [
|
|
14
|
-
{
|
|
15
|
-
type: 'check',
|
|
16
|
-
label: 'Enabled',
|
|
17
|
-
name: 'enabled',
|
|
18
|
-
initialValue: true,
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
type: 'object',
|
|
22
|
-
name: 'personalInformation',
|
|
23
|
-
label: 'Personal Information',
|
|
24
|
-
fields: [
|
|
25
|
-
{
|
|
26
|
-
type: 'text',
|
|
27
|
-
name: 'firstName',
|
|
28
|
-
label: 'First Name',
|
|
29
|
-
initialValue: 'Saji',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
type: 'text',
|
|
33
|
-
name: 'lastName',
|
|
34
|
-
label: 'Last Name',
|
|
35
|
-
initialValue: 'Nael',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
type: 'select',
|
|
39
|
-
name: 'gender',
|
|
40
|
-
label: 'Gender',
|
|
41
|
-
data: [
|
|
42
|
-
{ label: 'Male', value: 'male' },
|
|
43
|
-
{ label: 'Female', value: 'female' },
|
|
44
|
-
],
|
|
45
|
-
initialValue: 'male',
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
type: 'object',
|
|
51
|
-
name: 'accountInformation',
|
|
52
|
-
label: 'Account Information',
|
|
53
|
-
fields: [
|
|
54
|
-
{
|
|
55
|
-
type: 'text',
|
|
56
|
-
name: 'username',
|
|
57
|
-
label: 'Username',
|
|
58
|
-
initialValue: 'saji-nael',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
type: 'text',
|
|
62
|
-
name: 'email',
|
|
63
|
-
label: 'Email',
|
|
64
|
-
initialValue: 'saji.nael.98@gmail.com',
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
type: 'date',
|
|
68
|
-
name: 'dateOfJoin',
|
|
69
|
-
label: 'Date Of Join',
|
|
70
|
-
initialValue: new Date(),
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
type: 'object',
|
|
76
|
-
name: 'contactInformation',
|
|
77
|
-
label: 'Contact Information',
|
|
78
|
-
fields: [
|
|
79
|
-
{
|
|
80
|
-
type: 'array',
|
|
81
|
-
name: 'phones',
|
|
82
|
-
label: 'Phones',
|
|
83
|
-
fields: [
|
|
84
|
-
{
|
|
85
|
-
type: 'text',
|
|
86
|
-
name: 'phoneNo',
|
|
87
|
-
label: 'Phone NO',
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
],
|
|
92
|
-
},
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
const schemaWithValidation: FieldSchema[] = [
|
|
96
|
-
...schema.slice(0, 3),
|
|
97
|
-
{
|
|
98
|
-
...schema[3],
|
|
99
|
-
fields: [
|
|
100
|
-
{
|
|
101
|
-
...schema[3].fields[0],
|
|
102
|
-
required: true,
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
},
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
// ------------------------------
|
|
109
|
-
// Storybook Meta
|
|
110
|
-
// ------------------------------
|
|
111
|
-
|
|
112
|
-
const meta: Meta<typeof AutoForm> = {
|
|
113
|
-
title: 'components/AutoForm',
|
|
114
|
-
component: AutoForm,
|
|
115
|
-
tags: ['autodocs'],
|
|
116
|
-
args: {
|
|
117
|
-
onSubmit: (values) => alert(JSON.stringify(values, null, 2)),
|
|
118
|
-
schema,
|
|
119
|
-
container: (form, onSubmit, readOnly) => (
|
|
120
|
-
<>
|
|
121
|
-
<Grid>{form}</Grid>
|
|
122
|
-
{!readOnly && (
|
|
123
|
-
<Group justify="flex-end">
|
|
124
|
-
<Button onClick={onSubmit}>Submit</Button>
|
|
125
|
-
</Group>
|
|
126
|
-
)}
|
|
127
|
-
</>
|
|
128
|
-
),
|
|
129
|
-
fieldContainer: (field, fieldSchema) => (
|
|
130
|
-
<Grid.Col span={{ base: 12, md: fieldSchema.type === 'object' ? 12 : 6 }}>{field}</Grid.Col>
|
|
131
|
-
),
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
argTypes: {
|
|
135
|
-
values: {
|
|
136
|
-
description: 'Initial form values. Useful for editing or setting default values.',
|
|
137
|
-
control: false,
|
|
138
|
-
},
|
|
139
|
-
schema: {
|
|
140
|
-
description:
|
|
141
|
-
'Array of field definitions used to render the form. Each item defines one input field.',
|
|
142
|
-
control: false,
|
|
143
|
-
},
|
|
144
|
-
onSubmit: {
|
|
145
|
-
description: 'Function called with form values when the form is submitted.',
|
|
146
|
-
control: false,
|
|
147
|
-
},
|
|
148
|
-
container: {
|
|
149
|
-
description:
|
|
150
|
-
'Function that receives the rendered form and the onSubmit handler. Used to wrap the form with layout and controls.',
|
|
151
|
-
control: false,
|
|
152
|
-
},
|
|
153
|
-
fieldContainer: {
|
|
154
|
-
description: 'Optional function to wrap each individual field with custom layout or styling.',
|
|
155
|
-
control: false,
|
|
156
|
-
},
|
|
157
|
-
customRender: {
|
|
158
|
-
description:
|
|
159
|
-
'Optional custom render function to override the default field rendering based on field type.',
|
|
160
|
-
control: false,
|
|
161
|
-
},
|
|
162
|
-
validate: {
|
|
163
|
-
description:
|
|
164
|
-
'Optional validation logic. Receives values and returns an object with field errors or nulls.',
|
|
165
|
-
control: false,
|
|
166
|
-
},
|
|
167
|
-
readOnly: {
|
|
168
|
-
description: 'If true, all fields will be rendered in read-only mode.',
|
|
169
|
-
control: { type: 'boolean' },
|
|
170
|
-
},
|
|
171
|
-
onFieldChange: {
|
|
172
|
-
description:
|
|
173
|
-
'Optional function triggered on field change. You can return modified values dynamically.',
|
|
174
|
-
control: false,
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
parameters: {
|
|
178
|
-
docs: {
|
|
179
|
-
description: {
|
|
180
|
-
component: `
|
|
181
|
-
### 📄 AutoForm
|
|
182
|
-
|
|
183
|
-
\`AutoForm\` is a dynamic, schema-driven form component designed for full control and customization.
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
### 🧩 AutoFormProps Overview
|
|
188
|
-
|
|
189
|
-
| Prop | Type | Description |
|
|
190
|
-
|------------------|----------------------------------------------------------------------|-------------|
|
|
191
|
-
| \`schema\` | \`FieldSchema[]\` | Array of field definitions |
|
|
192
|
-
| \`onSubmit\` | \`(values: Record<string, any>) => void\` | Called when form is submitted |
|
|
193
|
-
| \`values\` | \`Record<string, any>\` | Initial values |
|
|
194
|
-
| \`readOnly\` | \`true?\` | Makes the form non-editable |
|
|
195
|
-
| \`validate\` | \`FormValidateInput<Record<string, any>>\` | Optional validation function |
|
|
196
|
-
| \`onFieldChange\` | \`(name, value, values) => Record<string, any>\` | Callback when a field changes |
|
|
197
|
-
| \`container\` | \`(formNode, onSubmit, readOnly) => React.ReactNode\` | Customize the outer layout of the form |
|
|
198
|
-
| \`fieldContainer\` | \`(fieldNode, fieldSchema) => React.ReactNode\` | Customize how each field is rendered |
|
|
199
|
-
| \`customRender\` | \`(field, value, error, onChange, values, options, readOnly) => JSX\` | Advanced per-field rendering |
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
### 🧱 Layout Customization
|
|
204
|
-
|
|
205
|
-
#### 🔲 \`container\`
|
|
206
|
-
|
|
207
|
-
Use the \`container\` prop to wrap the full form, including layout, submit buttons, etc.
|
|
208
|
-
|
|
209
|
-
#### 🔳 \`fieldContainer\`
|
|
210
|
-
|
|
211
|
-
With \`fieldContainer\`, you can wrap **each field** with your own layout:
|
|
212
|
-
|
|
213
|
-
\`\`\`tsx
|
|
214
|
-
fieldContainer: (field, fieldSchema) => (
|
|
215
|
-
<Grid.Col span={{ base: 12, md: fieldSchema.type === 'object' ? 12 : 6 }}>
|
|
216
|
-
{field}
|
|
217
|
-
</Grid.Col>
|
|
218
|
-
)
|
|
219
|
-
\`\`\`
|
|
220
|
-
|
|
221
|
-
This allows **full control per field** — spacing, layout, responsiveness, etc.
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
### 🧠 Advanced Rendering with \`customRender\`
|
|
226
|
-
|
|
227
|
-
\`customRender\` gives you full control over how a field is rendered.
|
|
228
|
-
|
|
229
|
-
#### 📦 Example
|
|
230
|
-
|
|
231
|
-
\`\`\`tsx
|
|
232
|
-
customRender: (field, objValue, error, onObjChange, formValues, options, readOnly) => {
|
|
233
|
-
if (field.type === 'object') {
|
|
234
|
-
return (
|
|
235
|
-
<Accordion defaultValue={field.name}>
|
|
236
|
-
<Accordion.Item value={field.name}>
|
|
237
|
-
<Accordion.Control>{field.label}</Accordion.Control>
|
|
238
|
-
<Accordion.Panel>
|
|
239
|
-
<Grid>
|
|
240
|
-
{field.fields?.map((childField) => {
|
|
241
|
-
function onChange(name: string, value: any) {
|
|
242
|
-
objValue[name] = value;
|
|
243
|
-
onObjChange(field.name, objValue);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (childField.name === 'phones') {
|
|
247
|
-
return (
|
|
248
|
-
<CustomPhoneList
|
|
249
|
-
key={childField.name}
|
|
250
|
-
field={childField}
|
|
251
|
-
value={objValue[childField.name]}
|
|
252
|
-
onChange={onChange}
|
|
253
|
-
error={error}
|
|
254
|
-
formValues={formValues}
|
|
255
|
-
options={options}
|
|
256
|
-
readOnly={readOnly}
|
|
257
|
-
/>
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return (
|
|
262
|
-
<Grid.Col key={childField.name} span={6}>
|
|
263
|
-
<FieldRender
|
|
264
|
-
field={childField}
|
|
265
|
-
formValues={formValues}
|
|
266
|
-
value={objValue[childField.name]}
|
|
267
|
-
onChange={onChange}
|
|
268
|
-
readOnly={readOnly}
|
|
269
|
-
/>
|
|
270
|
-
</Grid.Col>
|
|
271
|
-
);
|
|
272
|
-
})}
|
|
273
|
-
</Grid>
|
|
274
|
-
</Accordion.Panel>
|
|
275
|
-
</Accordion.Item>
|
|
276
|
-
</Accordion>
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
return null;
|
|
280
|
-
}
|
|
281
|
-
\`\`\`
|
|
282
|
-
|
|
283
|
-
You can use this to:
|
|
284
|
-
- Nest fields inside custom layouts
|
|
285
|
-
- Open modals, drawers, or complex editors
|
|
286
|
-
- Show/hide fields dynamically
|
|
287
|
-
- Render fields as fully custom components
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
`,
|
|
291
|
-
},
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
export default meta;
|
|
297
|
-
|
|
298
|
-
// ------------------------------
|
|
299
|
-
// Stories
|
|
300
|
-
// ------------------------------
|
|
301
|
-
|
|
302
|
-
type Story = StoryObj<typeof AutoForm>;
|
|
303
|
-
|
|
304
|
-
export const Standard: Story = {};
|
|
305
|
-
|
|
306
|
-
export const ReadOnly: Story = {
|
|
307
|
-
args: { readOnly: true },
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
export const FormValidation: Story = {
|
|
311
|
-
args: {
|
|
312
|
-
schema: schemaWithValidation,
|
|
313
|
-
validate: {
|
|
314
|
-
contactInformation: {
|
|
315
|
-
phones: {
|
|
316
|
-
phoneNo: (value: string) => {
|
|
317
|
-
const regex = /^(059|056)\d{7}$/;
|
|
318
|
-
return regex.test(value)
|
|
319
|
-
? null
|
|
320
|
-
: "Invalid phone number. It must be exactly 10 digits long and start with '059' or '056'.";
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
export const CustomizedForm: Story = {
|
|
329
|
-
args: {
|
|
330
|
-
schema,
|
|
331
|
-
customRender: (field, objValue, error, onObjChange, formValues, options, readOnly) => {
|
|
332
|
-
if (field.type === 'object') {
|
|
333
|
-
return (
|
|
334
|
-
<Grid.Col span={12}>
|
|
335
|
-
<Accordion defaultValue={field.name} variant="contained">
|
|
336
|
-
<Accordion.Item value={field.name}>
|
|
337
|
-
<Accordion.Control>{field.label}</Accordion.Control>
|
|
338
|
-
<Accordion.Panel>
|
|
339
|
-
<Grid>
|
|
340
|
-
{field.fields?.map((field) => {
|
|
341
|
-
const onChange = (name: string, value: any) => {
|
|
342
|
-
objValue[name] = value;
|
|
343
|
-
onObjChange(field.name, objValue);
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
if (field.name === 'phones') {
|
|
347
|
-
return (
|
|
348
|
-
<CustomPhoneList
|
|
349
|
-
key={field.name}
|
|
350
|
-
error={error}
|
|
351
|
-
field={field}
|
|
352
|
-
formValues={formValues}
|
|
353
|
-
onChange={onChange}
|
|
354
|
-
value={objValue[field.name]}
|
|
355
|
-
options={options}
|
|
356
|
-
readOnly={readOnly}
|
|
357
|
-
/>
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return (
|
|
362
|
-
<Grid.Col
|
|
363
|
-
key={field.name}
|
|
364
|
-
span={{ base: 12, md: field.type === 'object' ? 12 : 6 }}
|
|
365
|
-
>
|
|
366
|
-
<FieldRender
|
|
367
|
-
field={field}
|
|
368
|
-
formValues={formValues}
|
|
369
|
-
value={objValue[field.name]}
|
|
370
|
-
error={undefined}
|
|
371
|
-
readOnly={readOnly}
|
|
372
|
-
onChange={onChange}
|
|
373
|
-
/>
|
|
374
|
-
</Grid.Col>
|
|
375
|
-
);
|
|
376
|
-
})}
|
|
377
|
-
</Grid>
|
|
378
|
-
</Accordion.Panel>
|
|
379
|
-
</Accordion.Item>
|
|
380
|
-
</Accordion>
|
|
381
|
-
</Grid.Col>
|
|
382
|
-
);
|
|
383
|
-
}
|
|
384
|
-
return null;
|
|
385
|
-
},
|
|
386
|
-
},
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
// ------------------------------
|
|
390
|
-
// Custom Field Renderer
|
|
391
|
-
// ------------------------------
|
|
392
|
-
|
|
393
|
-
const CustomPhoneList: React.FC<CustomFieldRender> = (props) => {
|
|
394
|
-
const [visible, { open, close }] = useDisclosure(false);
|
|
395
|
-
const { error, field, formValues, onChange, value, options, readOnly } = props;
|
|
396
|
-
|
|
397
|
-
const arrayOptions = getArrayOptions(field.name, onChange, value);
|
|
398
|
-
|
|
399
|
-
return (
|
|
400
|
-
<>
|
|
401
|
-
<FieldRender
|
|
402
|
-
field={field}
|
|
403
|
-
formValues={formValues}
|
|
404
|
-
onChange={onChange}
|
|
405
|
-
value={value}
|
|
406
|
-
error={error}
|
|
407
|
-
readOnly={readOnly}
|
|
408
|
-
customRender={() => (
|
|
409
|
-
<>
|
|
410
|
-
<Modal title="Add Phone" onClose={close} opened={visible}>
|
|
411
|
-
<AutoForm
|
|
412
|
-
schema={field.fields as FieldSchema[]}
|
|
413
|
-
fieldContainer={(field, fieldSchema) => (
|
|
414
|
-
<Grid.Col span={{ base: 12, md: fieldSchema.type === 'object' ? 12 : 6 }}>
|
|
415
|
-
{field}
|
|
416
|
-
</Grid.Col>
|
|
417
|
-
)}
|
|
418
|
-
container={(form, onSubmit, readOnly) => (
|
|
419
|
-
<>
|
|
420
|
-
<Grid>{form}</Grid>
|
|
421
|
-
{!readOnly && (
|
|
422
|
-
<Group justify="flex-end">
|
|
423
|
-
<Button onClick={onSubmit}>Submit</Button>
|
|
424
|
-
</Group>
|
|
425
|
-
)}
|
|
426
|
-
</>
|
|
427
|
-
)}
|
|
428
|
-
onSubmit={(values) => {
|
|
429
|
-
arrayOptions?.addElement(values);
|
|
430
|
-
close();
|
|
431
|
-
}}
|
|
432
|
-
/>
|
|
433
|
-
</Modal>
|
|
434
|
-
|
|
435
|
-
<Button onClick={open} mb="md">
|
|
436
|
-
Add Phone
|
|
437
|
-
</Button>
|
|
438
|
-
|
|
439
|
-
{value.length > 0 ? (
|
|
440
|
-
<Table withColumnBorders withRowBorders withTableBorder striped>
|
|
441
|
-
<Table.Thead>
|
|
442
|
-
<Table.Tr>
|
|
443
|
-
<Table.Th>Phone NO.</Table.Th>
|
|
444
|
-
<Table.Th>Action</Table.Th>
|
|
445
|
-
</Table.Tr>
|
|
446
|
-
</Table.Thead>
|
|
447
|
-
<Table.Tbody>
|
|
448
|
-
{value.map((phone, index) => (
|
|
449
|
-
<Table.Tr key={index}>
|
|
450
|
-
<Table.Td>{phone.phoneNo}</Table.Td>
|
|
451
|
-
<Table.Td>
|
|
452
|
-
<Button
|
|
453
|
-
variant="light"
|
|
454
|
-
size="xs"
|
|
455
|
-
color="red"
|
|
456
|
-
onClick={() => arrayOptions.removeElement(index)}
|
|
457
|
-
>
|
|
458
|
-
Delete
|
|
459
|
-
</Button>
|
|
460
|
-
</Table.Td>
|
|
461
|
-
</Table.Tr>
|
|
462
|
-
))}
|
|
463
|
-
</Table.Tbody>
|
|
464
|
-
</Table>
|
|
465
|
-
) : (
|
|
466
|
-
<Text>No phones are inserted</Text>
|
|
467
|
-
)}
|
|
468
|
-
</>
|
|
469
|
-
)}
|
|
470
|
-
/>
|
|
471
|
-
</>
|
|
472
|
-
);
|
|
473
|
-
};
|