@saas-ui/forms 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/Field.d.ts +79 -0
- package/dist/Field.d.ts.map +1 -0
- package/dist/array-field.d.ts +48 -0
- package/dist/array-field.d.ts.map +1 -0
- package/dist/auto-form.d.ts +10 -0
- package/dist/auto-form.d.ts.map +1 -0
- package/dist/display-field.d.ts +7 -0
- package/dist/display-field.d.ts.map +1 -0
- package/dist/fields.d.ts +6 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/form.d.ts +16 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.modern.js +2 -0
- package/dist/index.modern.js.map +1 -0
- package/dist/layout.d.ts +5 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/object-field.d.ts +11 -0
- package/dist/object-field.d.ts.map +1 -0
- package/dist/resolvers/yup.d.ts +12 -0
- package/dist/resolvers/yup.d.ts.map +1 -0
- package/dist/submit-button.d.ts +3 -0
- package/dist/submit-button.d.ts.map +1 -0
- package/dist/use-array-field.d.ts +95 -0
- package/dist/use-array-field.d.ts.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +75 -0
- package/src/array-field.tsx +196 -0
- package/src/auto-form.tsx +35 -0
- package/src/display-field.tsx +31 -0
- package/src/field.tsx +295 -0
- package/src/fields.tsx +51 -0
- package/src/form.tsx +49 -0
- package/src/index.ts +14 -0
- package/src/layout.tsx +37 -0
- package/src/object-field.tsx +25 -0
- package/src/resolvers/yup.ts +81 -0
- package/src/submit-button.tsx +25 -0
- package/src/use-array-field.tsx +152 -0
- package/src/utils.ts +13 -0
package/dist/layout.d.ts
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
/// <reference types="react" />
|
2
|
+
import { SimpleGridProps } from '@chakra-ui/react';
|
3
|
+
export declare type FormLayoutProps = SimpleGridProps;
|
4
|
+
export declare const FormLayout: ({ children, ...props }: FormLayoutProps) => JSX.Element;
|
5
|
+
//# sourceMappingURL=layout.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAsB,eAAe,EAAY,MAAM,kBAAkB,CAAA;AAEhF,oBAAY,eAAe,GAAG,eAAe,CAAA;AAU7C,eAAO,MAAM,UAAU,2BAA4B,eAAe,gBAsBjE,CAAA"}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { ResponsiveValue } from '@chakra-ui/system';
|
3
|
+
import { FieldProps } from './field';
|
4
|
+
export interface ObjectFieldProps extends FieldProps {
|
5
|
+
name: string;
|
6
|
+
children: React.ReactNode;
|
7
|
+
columns?: ResponsiveValue<number>;
|
8
|
+
spacing?: ResponsiveValue<string | number>;
|
9
|
+
}
|
10
|
+
export declare const ObjectField: React.FC<ObjectFieldProps>;
|
11
|
+
//# sourceMappingURL=object-field.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"object-field.d.ts","sourceRoot":"","sources":["../src/object-field.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,OAAO,EAAa,UAAU,EAAE,MAAM,SAAS,CAAA;AAI/C,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAA;IACjC,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;CAC3C;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CASlD,CAAA"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { SchemaOf, AnySchema } from 'yup';
|
2
|
+
import { FieldProps } from '../Field';
|
3
|
+
export declare const resolver: import("@hookform/resolvers/yup").Resolver;
|
4
|
+
/**
|
5
|
+
* A helper function to render forms automatically based on a Yup schema
|
6
|
+
*
|
7
|
+
* @param schema The Yup schema
|
8
|
+
* @returns {FieldProps[]}
|
9
|
+
*/
|
10
|
+
export declare const getFieldsFromSchema: (schema: SchemaOf<AnySchema>) => FieldProps[];
|
11
|
+
export declare const getNestedSchema: (schema: SchemaOf<AnySchema>, path: string) => any;
|
12
|
+
//# sourceMappingURL=yup.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"yup.d.ts","sourceRoot":"","sources":["../../src/resolvers/yup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAS,MAAM,KAAK,CAAA;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAErC,eAAO,MAAM,QAAQ,4CAAc,CAAA;AAmCnC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,WACtB,SAAS,SAAS,CAAC,KAC1B,UAAU,EA4BZ,CAAA;AAED,eAAO,MAAM,eAAe,WAAY,SAAS,SAAS,CAAC,QAAQ,MAAM,QAExE,CAAA"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"submit-button.d.ts","sourceRoot":"","sources":["../src/submit-button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAU,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAIrD,eAAO,MAAM,YAAY,oEAgBxB,CAAA"}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { UseFieldArrayReturn } from 'react-hook-form';
|
3
|
+
export interface UseArrayFieldReturn extends UseFieldArrayReturn {
|
4
|
+
/**
|
5
|
+
* The array field name
|
6
|
+
*/
|
7
|
+
name: string;
|
8
|
+
/**
|
9
|
+
* The default value for new items
|
10
|
+
*/
|
11
|
+
defaultValue: Record<string, any>;
|
12
|
+
/**
|
13
|
+
* Min amount of items
|
14
|
+
*/
|
15
|
+
min?: number;
|
16
|
+
/**
|
17
|
+
* Max amount of items
|
18
|
+
*/
|
19
|
+
max?: number;
|
20
|
+
}
|
21
|
+
export declare const ArrayFieldProvider: React.Provider<UseArrayFieldReturn>, useArrayFieldContext: () => UseArrayFieldReturn;
|
22
|
+
export interface UseArrayFieldRowReturn {
|
23
|
+
/**
|
24
|
+
* Name of the array field including the index, eg 'field.0'
|
25
|
+
*/
|
26
|
+
name: string;
|
27
|
+
/**
|
28
|
+
* The field index
|
29
|
+
*/
|
30
|
+
index: number;
|
31
|
+
/**
|
32
|
+
* Remove this array item
|
33
|
+
*/
|
34
|
+
remove: () => void;
|
35
|
+
/**
|
36
|
+
* True if this is the first item
|
37
|
+
*/
|
38
|
+
isFirst: boolean;
|
39
|
+
/**
|
40
|
+
* True if this is the last item
|
41
|
+
*/
|
42
|
+
isLast: boolean;
|
43
|
+
}
|
44
|
+
export declare const ArrayFieldRowProvider: React.Provider<UseArrayFieldRowReturn>, useArrayFieldRowContext: () => UseArrayFieldRowReturn;
|
45
|
+
export interface ArrayFieldOptions {
|
46
|
+
/**
|
47
|
+
* The field name
|
48
|
+
*/
|
49
|
+
name: string;
|
50
|
+
/**
|
51
|
+
* Default value for new values in the array
|
52
|
+
*/
|
53
|
+
defaultValue?: Record<string, any>;
|
54
|
+
/**
|
55
|
+
* Default key name for rows, change this if your data uses 'id'
|
56
|
+
* @default "id"
|
57
|
+
*/
|
58
|
+
keyName?: string;
|
59
|
+
min?: number;
|
60
|
+
max?: number;
|
61
|
+
}
|
62
|
+
export declare const useArrayField: ({ name, defaultValue, keyName, min, max, }: ArrayFieldOptions) => {
|
63
|
+
name: string;
|
64
|
+
defaultValue: Record<string, any>;
|
65
|
+
min: number | undefined;
|
66
|
+
max: number | undefined;
|
67
|
+
swap: (indexA: number, indexB: number) => void;
|
68
|
+
move: (indexA: number, indexB: number) => void;
|
69
|
+
prepend: (value: Partial<unknown> | Partial<unknown>[], options?: import("react-hook-form").FieldArrayMethodProps | undefined) => void;
|
70
|
+
append: (value: Partial<unknown> | Partial<unknown>[], options?: import("react-hook-form").FieldArrayMethodProps | undefined) => void;
|
71
|
+
remove: (index?: number | number[] | undefined) => void;
|
72
|
+
insert: (index: number, value: Partial<unknown> | Partial<unknown>[], options?: import("react-hook-form").FieldArrayMethodProps | undefined) => void;
|
73
|
+
update: (index: number, value: Partial<unknown>) => void;
|
74
|
+
replace: (value: Partial<unknown> | Partial<unknown>[]) => void;
|
75
|
+
fields: Record<string, string>[];
|
76
|
+
};
|
77
|
+
export interface UseArrayFieldRowProps {
|
78
|
+
index: number;
|
79
|
+
}
|
80
|
+
export declare const useArrayFieldRow: ({ index }: UseArrayFieldRowProps) => {
|
81
|
+
index: number;
|
82
|
+
isFirst: boolean;
|
83
|
+
isLast: boolean;
|
84
|
+
name: string;
|
85
|
+
remove: () => void;
|
86
|
+
};
|
87
|
+
export declare const useArrayFieldRemoveButton: () => {
|
88
|
+
onClick: () => void;
|
89
|
+
isDisabled: boolean;
|
90
|
+
};
|
91
|
+
export declare const useArrayFieldAddButton: () => {
|
92
|
+
onClick: () => void;
|
93
|
+
isDisabled: boolean;
|
94
|
+
};
|
95
|
+
//# sourceMappingURL=use-array-field.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"use-array-field.d.ts","sourceRoot":"","sources":["../src/use-array-field.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAGL,mBAAmB,EACpB,MAAM,iBAAiB,CAAA;AAIxB,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACjC;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,eAAO,MAAO,kBAAkB,uCAAE,oBAAoB,2BAGlD,CAAA;AAEJ,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,eAAO,MAAO,qBAAqB,0CAAE,uBAAuB,8BAGxD,CAAA;AAEJ,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,eAAO,MAAM,aAAa,+CAMvB,iBAAiB;;;;;;;;;;;;;;CAenB,CAAA;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;CACd;AAED,eAAO,MAAM,gBAAgB,cAAe,qBAAqB;;;;;;CAmBhE,CAAA;AAED,eAAO,MAAM,yBAAyB;;;CAUrC,CAAA;AAED,eAAO,MAAM,sBAAsB;;;CAYlC,CAAA"}
|
package/dist/utils.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,eAAO,MAAM,eAAe,SAAU,MAAM,YAAY,MAAM,SAAS,4BAUtE,CAAA"}
|
package/package.json
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
{
|
2
|
+
"name": "@saas-ui/forms",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"description": "Theme and components agnostic SaasProvider",
|
5
|
+
"source": "src/index.ts",
|
6
|
+
"exports": {
|
7
|
+
"require": "./dist/index.js",
|
8
|
+
"development": "./src/index.ts",
|
9
|
+
"default": "./dist/index.modern.js"
|
10
|
+
},
|
11
|
+
"main": "./dist/index.js",
|
12
|
+
"module": "./dist/index.modern.js",
|
13
|
+
"types": "./dist/index.d.ts",
|
14
|
+
"scripts": {
|
15
|
+
"clean": "rimraf --no-glob ./dist",
|
16
|
+
"build": "yarn clean && cross-env NODE_ENV=production microbundle --tsconfig ./tsconfig.json --jsx React.createElement --jsxFragment React.Fragment -f cjs,modern --compress",
|
17
|
+
"lint": "eslint src --ext .ts,.tsx,.js,.jsx --config ../../.eslintrc.js",
|
18
|
+
"lint:staged": "lint-staged --allow-empty --config ../../lint-staged.config.js",
|
19
|
+
"typecheck": "tsc --noEmit"
|
20
|
+
},
|
21
|
+
"files": [
|
22
|
+
"dist",
|
23
|
+
"src"
|
24
|
+
],
|
25
|
+
"sideEffects": false,
|
26
|
+
"publishConfig": {
|
27
|
+
"access": "public"
|
28
|
+
},
|
29
|
+
"author": "Eelco Wiersma <eelco@appulse.nl>",
|
30
|
+
"license": "MIT",
|
31
|
+
"homepage": "https://saas-ui.dev/",
|
32
|
+
"repository": {
|
33
|
+
"type": "git",
|
34
|
+
"url": "https://github.com/AppulseSoftware/saas-ui",
|
35
|
+
"directory": "packages/saas-ui-forms"
|
36
|
+
},
|
37
|
+
"keywords": [
|
38
|
+
"react",
|
39
|
+
"ui",
|
40
|
+
"chakra-ui",
|
41
|
+
"design-system",
|
42
|
+
"react-components",
|
43
|
+
"uikit",
|
44
|
+
"accessible",
|
45
|
+
"components",
|
46
|
+
"emotion",
|
47
|
+
"library",
|
48
|
+
"design-system",
|
49
|
+
"forms",
|
50
|
+
"react-hook-form"
|
51
|
+
],
|
52
|
+
"storybook": {
|
53
|
+
"title": "Saas UI",
|
54
|
+
"url": "https://storybook.saas-ui.dev"
|
55
|
+
},
|
56
|
+
"dependencies": {
|
57
|
+
"@hookform/resolvers": "^2.8.3",
|
58
|
+
"@saas-ui/button": "workspace:*",
|
59
|
+
"@saas-ui/input-right-button": "workspace:*",
|
60
|
+
"@saas-ui/number-input": "workspace:*",
|
61
|
+
"@saas-ui/password-input": "workspace:*",
|
62
|
+
"@saas-ui/pin-input": "workspace:*",
|
63
|
+
"@saas-ui/radio": "workspace:*",
|
64
|
+
"@saas-ui/select": "workspace:*",
|
65
|
+
"react-hook-form": "^7.22.0"
|
66
|
+
},
|
67
|
+
"peerDependencies": {
|
68
|
+
"@chakra-ui/react": ">=1.7.0",
|
69
|
+
"@chakra-ui/system": ">=1.0.0",
|
70
|
+
"react": ">=16.8.6"
|
71
|
+
},
|
72
|
+
"optionalDependencies": {
|
73
|
+
"yup": "^0.32.11"
|
74
|
+
}
|
75
|
+
}
|
@@ -0,0 +1,196 @@
|
|
1
|
+
import * as React from 'react'
|
2
|
+
|
3
|
+
import { chakra, ResponsiveValue } from '@chakra-ui/system'
|
4
|
+
|
5
|
+
import { AddIcon, MinusIcon } from '@chakra-ui/icons'
|
6
|
+
import { IconButton, ButtonProps } from '@saas-ui/button'
|
7
|
+
|
8
|
+
import { FormLayout } from './layout'
|
9
|
+
import { BaseField, FieldProps } from './field'
|
10
|
+
|
11
|
+
import { mapNestedFields } from './utils'
|
12
|
+
|
13
|
+
import {
|
14
|
+
useArrayField,
|
15
|
+
useArrayFieldRow,
|
16
|
+
useArrayFieldContext,
|
17
|
+
ArrayFieldProvider,
|
18
|
+
ArrayFieldOptions,
|
19
|
+
ArrayFieldRowProvider,
|
20
|
+
useArrayFieldRowContext,
|
21
|
+
useArrayFieldRemoveButton,
|
22
|
+
useArrayFieldAddButton,
|
23
|
+
} from './use-array-field'
|
24
|
+
|
25
|
+
interface ArrayField {
|
26
|
+
id: string
|
27
|
+
[key: string]: unknown
|
28
|
+
}
|
29
|
+
|
30
|
+
interface ArrayFieldRowProps {
|
31
|
+
/**
|
32
|
+
* Amount of field columns
|
33
|
+
*/
|
34
|
+
columns?: ResponsiveValue<number>
|
35
|
+
/**
|
36
|
+
* Spacing between fields
|
37
|
+
*/
|
38
|
+
spacing?: ResponsiveValue<string | number>
|
39
|
+
/**
|
40
|
+
* The array index
|
41
|
+
*/
|
42
|
+
index: number
|
43
|
+
}
|
44
|
+
|
45
|
+
export const ArrayFieldRow: React.FC<ArrayFieldRowProps> = ({
|
46
|
+
children,
|
47
|
+
columns,
|
48
|
+
spacing,
|
49
|
+
index,
|
50
|
+
}) => {
|
51
|
+
return (
|
52
|
+
<ArrayFieldRowContainer index={index}>
|
53
|
+
<ArrayFieldRowFields columns={columns} spacing={spacing}>
|
54
|
+
{children}
|
55
|
+
</ArrayFieldRowFields>
|
56
|
+
<ArrayFieldRemoveButton />
|
57
|
+
</ArrayFieldRowContainer>
|
58
|
+
)
|
59
|
+
}
|
60
|
+
|
61
|
+
export interface ArrayFieldRowFieldsProps {
|
62
|
+
/**
|
63
|
+
* Amount of field columns
|
64
|
+
*/
|
65
|
+
columns?: ResponsiveValue<number>
|
66
|
+
/**
|
67
|
+
* Spacing between fields
|
68
|
+
*/
|
69
|
+
spacing?: ResponsiveValue<string | number>
|
70
|
+
}
|
71
|
+
|
72
|
+
export const ArrayFieldRowFields: React.FC<ArrayFieldRowFieldsProps> = ({
|
73
|
+
children,
|
74
|
+
columns,
|
75
|
+
spacing,
|
76
|
+
...layoutProps
|
77
|
+
}) => {
|
78
|
+
const { name } = useArrayFieldRowContext()
|
79
|
+
return (
|
80
|
+
<FormLayout
|
81
|
+
flex="1"
|
82
|
+
columns={columns}
|
83
|
+
gridGap={spacing}
|
84
|
+
mr="2"
|
85
|
+
{...layoutProps}
|
86
|
+
>
|
87
|
+
{mapNestedFields(name, children)}
|
88
|
+
</FormLayout>
|
89
|
+
)
|
90
|
+
}
|
91
|
+
|
92
|
+
export const ArrayFieldRowContainer: React.FC<ArrayFieldRowProps> = ({
|
93
|
+
children,
|
94
|
+
index,
|
95
|
+
}) => {
|
96
|
+
const context = useArrayFieldRow({ index })
|
97
|
+
|
98
|
+
const styles = {
|
99
|
+
display: 'flex',
|
100
|
+
flexDirection: 'row',
|
101
|
+
alignItems: 'flex-end',
|
102
|
+
width: '100%',
|
103
|
+
mb: 4,
|
104
|
+
}
|
105
|
+
|
106
|
+
return (
|
107
|
+
<ArrayFieldRowProvider value={context}>
|
108
|
+
<chakra.div __css={styles}>{children}</chakra.div>
|
109
|
+
</ArrayFieldRowProvider>
|
110
|
+
)
|
111
|
+
}
|
112
|
+
|
113
|
+
export const ArrayFieldRemoveButton: React.FC<ButtonProps> = (props) => {
|
114
|
+
return (
|
115
|
+
<IconButton
|
116
|
+
icon={<MinusIcon />}
|
117
|
+
aria-label="Remove row"
|
118
|
+
{...useArrayFieldRemoveButton()}
|
119
|
+
{...props}
|
120
|
+
/>
|
121
|
+
)
|
122
|
+
}
|
123
|
+
|
124
|
+
export const ArrayFieldAddButton: React.FC<ButtonProps> = (props) => {
|
125
|
+
return (
|
126
|
+
<IconButton
|
127
|
+
icon={<AddIcon />}
|
128
|
+
aria-label="Add row"
|
129
|
+
float="right"
|
130
|
+
{...useArrayFieldAddButton()}
|
131
|
+
{...props}
|
132
|
+
/>
|
133
|
+
)
|
134
|
+
}
|
135
|
+
|
136
|
+
export interface ArrayFieldProps
|
137
|
+
extends ArrayFieldOptions,
|
138
|
+
Omit<FieldProps, 'defaultValue'> {}
|
139
|
+
|
140
|
+
export const ArrayField: React.FC<ArrayFieldProps> = (props) => {
|
141
|
+
const { children, ...containerProps } = props
|
142
|
+
|
143
|
+
return (
|
144
|
+
<ArrayFieldContainer {...containerProps}>
|
145
|
+
<ArrayFieldRows>
|
146
|
+
{(fields: ArrayField[]) => (
|
147
|
+
<>
|
148
|
+
{fields.map(({ id }, index: number) => (
|
149
|
+
<ArrayFieldRow key={id} index={index}>
|
150
|
+
{children}
|
151
|
+
</ArrayFieldRow>
|
152
|
+
))}
|
153
|
+
</>
|
154
|
+
)}
|
155
|
+
</ArrayFieldRows>
|
156
|
+
<ArrayFieldAddButton />
|
157
|
+
</ArrayFieldContainer>
|
158
|
+
)
|
159
|
+
}
|
160
|
+
|
161
|
+
export interface ArrayFieldRowsProps {
|
162
|
+
children: (fields: ArrayField[]) => React.ReactElement | null
|
163
|
+
}
|
164
|
+
|
165
|
+
export const ArrayFieldRows = ({
|
166
|
+
children,
|
167
|
+
}: ArrayFieldRowsProps): React.ReactElement | null => {
|
168
|
+
const { fields } = useArrayFieldContext()
|
169
|
+
return children(fields)
|
170
|
+
}
|
171
|
+
|
172
|
+
export const ArrayFieldContainer: React.FC<ArrayFieldProps> = ({
|
173
|
+
name,
|
174
|
+
defaultValue,
|
175
|
+
keyName,
|
176
|
+
min,
|
177
|
+
max,
|
178
|
+
children,
|
179
|
+
...fieldProps
|
180
|
+
}) => {
|
181
|
+
const context = useArrayField({
|
182
|
+
name,
|
183
|
+
defaultValue,
|
184
|
+
keyName,
|
185
|
+
min,
|
186
|
+
max,
|
187
|
+
})
|
188
|
+
|
189
|
+
return (
|
190
|
+
<ArrayFieldProvider value={context}>
|
191
|
+
<BaseField name={name} {...fieldProps}>
|
192
|
+
{children}
|
193
|
+
</BaseField>
|
194
|
+
</ArrayFieldProvider>
|
195
|
+
)
|
196
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import * as React from 'react'
|
2
|
+
|
3
|
+
import { forwardRef } from '@chakra-ui/react'
|
4
|
+
|
5
|
+
import { Form, FormProps } from './form'
|
6
|
+
|
7
|
+
import { FormLayout } from './layout'
|
8
|
+
import { Fields } from './fields'
|
9
|
+
import { SubmitButton } from './submit-button'
|
10
|
+
|
11
|
+
interface AutoFormOptions {
|
12
|
+
schema: any
|
13
|
+
submitLabel?: false | string
|
14
|
+
}
|
15
|
+
|
16
|
+
export interface AutoFormProps
|
17
|
+
extends Omit<FormProps, 'schema'>,
|
18
|
+
AutoFormOptions {}
|
19
|
+
|
20
|
+
export const AutoForm = forwardRef<AutoFormProps, 'form'>(
|
21
|
+
({ schema, submitLabel, ...props }, ref) => {
|
22
|
+
return (
|
23
|
+
<Form {...props} schema={schema} ref={ref}>
|
24
|
+
<FormLayout>
|
25
|
+
{<Fields schema={schema} />}
|
26
|
+
{submitLabel && <SubmitButton label={submitLabel} />}
|
27
|
+
</FormLayout>
|
28
|
+
</Form>
|
29
|
+
)
|
30
|
+
}
|
31
|
+
)
|
32
|
+
|
33
|
+
AutoForm.defaultProps = {
|
34
|
+
submitLabel: 'Submit',
|
35
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import * as React from 'react'
|
2
|
+
import { useFormContext } from 'react-hook-form'
|
3
|
+
|
4
|
+
import {
|
5
|
+
Text,
|
6
|
+
FormControl,
|
7
|
+
FormControlProps,
|
8
|
+
FormLabel,
|
9
|
+
} from '@chakra-ui/react'
|
10
|
+
|
11
|
+
import { FieldProps } from './Field'
|
12
|
+
|
13
|
+
export interface DisplayFieldProps
|
14
|
+
extends FormControlProps,
|
15
|
+
Omit<FieldProps, 'type' | 'label'> {}
|
16
|
+
|
17
|
+
export const DisplayField: React.FC<DisplayFieldProps> = ({
|
18
|
+
name,
|
19
|
+
label,
|
20
|
+
placeholder,
|
21
|
+
...props
|
22
|
+
}) => {
|
23
|
+
const { getValues } = useFormContext()
|
24
|
+
|
25
|
+
return (
|
26
|
+
<FormControl {...props}>
|
27
|
+
{label ? <FormLabel htmlFor={name}>{label}</FormLabel> : null}
|
28
|
+
<Text fontSize="md">{getValues(name)}</Text>
|
29
|
+
</FormControl>
|
30
|
+
)
|
31
|
+
}
|