@saas-ui/forms 1.5.2 → 2.0.0-next.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 +15 -0
- package/dist/ajv/index.d.ts +21 -2
- package/dist/ajv/index.js +31 -2
- package/dist/ajv/index.js.map +1 -1
- package/dist/ajv/index.mjs +25 -0
- package/dist/ajv/index.mjs.map +1 -0
- package/dist/index.d.ts +606 -19
- package/dist/index.js +1251 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1140 -0
- package/dist/index.mjs.map +1 -0
- package/dist/yup/index.d.ts +41 -2
- package/dist/yup/index.js +95 -2
- package/dist/yup/index.js.map +1 -1
- package/dist/yup/index.mjs +86 -0
- package/dist/yup/index.mjs.map +1 -0
- package/dist/zod/index.d.ts +38 -2
- package/dist/zod/index.js +95 -2
- package/dist/zod/index.js.map +1 -1
- package/dist/zod/index.mjs +85 -0
- package/dist/zod/index.mjs.map +1 -0
- package/package.json +18 -28
- package/src/array-field.tsx +20 -13
- package/src/auto-form.tsx +13 -19
- package/src/field-resolver.ts +1 -1
- package/src/field.tsx +4 -9
- package/src/fields.tsx +1 -3
- package/src/form.tsx +70 -26
- package/src/index.ts +3 -1
- package/src/input-right-button/index.ts +1 -0
- package/src/input-right-button/input-right-button.stories.tsx +47 -0
- package/src/input-right-button/input-right-button.test.tsx +12 -0
- package/src/input-right-button/input-right-button.tsx +26 -0
- package/src/layout.tsx +1 -1
- package/src/number-input/index.ts +1 -0
- package/src/number-input/number-input.stories.tsx +39 -0
- package/src/number-input/number-input.test.tsx +6 -0
- package/src/number-input/number-input.tsx +56 -0
- package/src/object-field.tsx +1 -1
- package/src/password-input/index.ts +1 -0
- package/src/password-input/password-input.stories.tsx +50 -0
- package/src/password-input/password-input.test.tsx +20 -0
- package/src/password-input/password-input.tsx +69 -0
- package/src/pin-input/index.ts +1 -0
- package/src/pin-input/pin-input.stories.tsx +38 -0
- package/src/pin-input/pin-input.test.tsx +6 -0
- package/src/pin-input/pin-input.tsx +50 -0
- package/src/radio/index.ts +1 -0
- package/src/radio/radio-input.stories.tsx +45 -0
- package/src/radio/radio-input.tsx +58 -0
- package/src/radio/radio.test.tsx +6 -0
- package/src/select/index.ts +2 -0
- package/src/select/native-select.tsx +42 -0
- package/src/select/select.stories.tsx +144 -0
- package/src/select/select.test.tsx +8 -0
- package/src/select/select.tsx +185 -0
- package/src/step-form.tsx +24 -13
- package/src/submit-button.tsx +32 -38
- package/src/use-step-form.tsx +1 -1
- package/ajv/package.json +0 -28
- package/dist/ajv/ajv-resolver.d.ts +0 -11
- package/dist/ajv/ajv-resolver.d.ts.map +0 -1
- package/dist/ajv/index.d.ts.map +0 -1
- package/dist/ajv/index.modern.mjs +0 -2
- package/dist/ajv/index.modern.mjs.map +0 -1
- package/dist/array-field.d.ts +0 -64
- package/dist/array-field.d.ts.map +0 -1
- package/dist/auto-form.d.ts +0 -32
- package/dist/auto-form.d.ts.map +0 -1
- package/dist/display-field.d.ts +0 -10
- package/dist/display-field.d.ts.map +0 -1
- package/dist/display-if.d.ts +0 -15
- package/dist/display-if.d.ts.map +0 -1
- package/dist/field-resolver.d.ts +0 -13
- package/dist/field-resolver.d.ts.map +0 -1
- package/dist/field.d.ts +0 -147
- package/dist/field.d.ts.map +0 -1
- package/dist/fields.d.ts +0 -9
- package/dist/fields.d.ts.map +0 -1
- package/dist/form.d.ts +0 -44
- package/dist/form.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.modern.mjs +0 -2
- package/dist/index.modern.mjs.map +0 -1
- package/dist/layout.d.ts +0 -14
- package/dist/layout.d.ts.map +0 -1
- package/dist/object-field.d.ts +0 -12
- package/dist/object-field.d.ts.map +0 -1
- package/dist/step-form.d.ts +0 -38
- package/dist/step-form.d.ts.map +0 -1
- package/dist/submit-button.d.ts +0 -20
- package/dist/submit-button.d.ts.map +0 -1
- package/dist/use-array-field.d.ts +0 -95
- package/dist/use-array-field.d.ts.map +0 -1
- package/dist/use-step-form.d.ts +0 -40
- package/dist/use-step-form.d.ts.map +0 -1
- package/dist/utils.d.ts +0 -3
- package/dist/utils.d.ts.map +0 -1
- package/dist/watch-field.d.ts +0 -11
- package/dist/watch-field.d.ts.map +0 -1
- package/dist/yup/index.d.ts.map +0 -1
- package/dist/yup/index.modern.mjs +0 -2
- package/dist/yup/index.modern.mjs.map +0 -1
- package/dist/yup/yup-resolver.d.ts +0 -29
- package/dist/yup/yup-resolver.d.ts.map +0 -1
- package/dist/zod/index.d.ts.map +0 -1
- package/dist/zod/index.modern.mjs +0 -2
- package/dist/zod/index.modern.mjs.map +0 -1
- package/dist/zod/zod-resolver.d.ts +0 -35
- package/dist/zod/zod-resolver.d.ts.map +0 -1
- package/yup/package.json +0 -26
- package/zod/package.json +0 -27
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Container,
|
|
3
|
+
Icon,
|
|
4
|
+
MenuItemOption,
|
|
5
|
+
Tag,
|
|
6
|
+
Wrap,
|
|
7
|
+
WrapItem,
|
|
8
|
+
} from '@chakra-ui/react'
|
|
9
|
+
import * as React from 'react'
|
|
10
|
+
|
|
11
|
+
import { ComponentStory } from '@storybook/react'
|
|
12
|
+
|
|
13
|
+
import { Select } from '../src/select'
|
|
14
|
+
import { NativeSelect } from '../src/native-select'
|
|
15
|
+
|
|
16
|
+
import { FiSmile } from 'react-icons/fi'
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
title: 'Components/Forms/Select',
|
|
20
|
+
decorators: [
|
|
21
|
+
(Story: any) => (
|
|
22
|
+
<Container mt="40px" maxW="320px">
|
|
23
|
+
<Story />
|
|
24
|
+
</Container>
|
|
25
|
+
),
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getOptions = (length = 6) =>
|
|
30
|
+
Array.from({ length }).map((_node, index) => ({
|
|
31
|
+
value: String(index),
|
|
32
|
+
label: `Option ${index + 1}`,
|
|
33
|
+
}))
|
|
34
|
+
|
|
35
|
+
const options = getOptions()
|
|
36
|
+
|
|
37
|
+
const Template: ComponentStory<typeof Select> = (args) => (
|
|
38
|
+
<Select placeholder="Select an option..." {...args} />
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
export const Basic = Template.bind({})
|
|
42
|
+
Basic.args = {
|
|
43
|
+
name: 'select',
|
|
44
|
+
options,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const DefaultValue = Template.bind({})
|
|
48
|
+
DefaultValue.args = {
|
|
49
|
+
name: 'select',
|
|
50
|
+
options,
|
|
51
|
+
defaultValue: 1,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const Placeholder = Template.bind({})
|
|
55
|
+
Placeholder.args = {
|
|
56
|
+
name: 'select',
|
|
57
|
+
options,
|
|
58
|
+
placeholder: 'Select an option...',
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const Disabled = Template.bind({})
|
|
62
|
+
Disabled.args = {
|
|
63
|
+
name: 'select',
|
|
64
|
+
options,
|
|
65
|
+
placeholder: 'Disabled.',
|
|
66
|
+
isDisabled: true,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const Multi = Template.bind({})
|
|
70
|
+
Multi.args = {
|
|
71
|
+
name: 'select',
|
|
72
|
+
options,
|
|
73
|
+
placeholder: 'Multiple.',
|
|
74
|
+
multiple: true,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const MultiWithDefaultValue = Template.bind({})
|
|
78
|
+
MultiWithDefaultValue.args = {
|
|
79
|
+
name: 'select',
|
|
80
|
+
options,
|
|
81
|
+
placeholder: 'Select an option...',
|
|
82
|
+
multiple: true,
|
|
83
|
+
defaultValue: ['1'],
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const MultiWithTags = Template.bind({})
|
|
87
|
+
MultiWithTags.args = {
|
|
88
|
+
name: 'select',
|
|
89
|
+
options,
|
|
90
|
+
placeholder: 'Select options...',
|
|
91
|
+
multiple: true,
|
|
92
|
+
renderValue: (selected) => {
|
|
93
|
+
if (selected?.length) {
|
|
94
|
+
return (
|
|
95
|
+
<Wrap py="1">
|
|
96
|
+
{selected.map((value) => (
|
|
97
|
+
<WrapItem>
|
|
98
|
+
<Tag>{value}</Tag>
|
|
99
|
+
</WrapItem>
|
|
100
|
+
))}
|
|
101
|
+
</Wrap>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const WithIcons = Template.bind({})
|
|
108
|
+
WithIcons.args = {
|
|
109
|
+
name: 'select',
|
|
110
|
+
options,
|
|
111
|
+
value: 1,
|
|
112
|
+
leftIcon: <Icon as={FiSmile} />,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export const MaxHeight = Template.bind({})
|
|
116
|
+
MaxHeight.args = {
|
|
117
|
+
name: 'select',
|
|
118
|
+
options: getOptions(100),
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export const WithChildren = () => {
|
|
122
|
+
return (
|
|
123
|
+
<Select name="select" value="1">
|
|
124
|
+
<MenuItemOption value="1">Option 1</MenuItemOption>
|
|
125
|
+
<MenuItemOption value="2">Option 1</MenuItemOption>
|
|
126
|
+
</Select>
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export const WithEmptyOption = () => {
|
|
131
|
+
return (
|
|
132
|
+
<Select name="select" value="1">
|
|
133
|
+
<MenuItemOption value="">None</MenuItemOption>
|
|
134
|
+
<MenuItemOption value="1">Option 1</MenuItemOption>
|
|
135
|
+
<MenuItemOption value="2">Option 1</MenuItemOption>
|
|
136
|
+
</Select>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const WithNativeSelect = () => (
|
|
141
|
+
<>
|
|
142
|
+
<NativeSelect name="select" options={options} aria-label="Select" />
|
|
143
|
+
</>
|
|
144
|
+
)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
chakra,
|
|
5
|
+
forwardRef,
|
|
6
|
+
Menu,
|
|
7
|
+
MenuProps,
|
|
8
|
+
MenuButton,
|
|
9
|
+
MenuList,
|
|
10
|
+
MenuListProps,
|
|
11
|
+
MenuItemOption,
|
|
12
|
+
MenuOptionGroup,
|
|
13
|
+
MenuOptionGroupProps,
|
|
14
|
+
Button,
|
|
15
|
+
ButtonProps,
|
|
16
|
+
omitThemingProps,
|
|
17
|
+
useMultiStyleConfig,
|
|
18
|
+
SystemStyleObject,
|
|
19
|
+
useFormControl,
|
|
20
|
+
HTMLChakraProps,
|
|
21
|
+
} from '@chakra-ui/react'
|
|
22
|
+
import { ChevronDownIcon } from '@chakra-ui/icons'
|
|
23
|
+
import { cx, __DEV__ } from '@chakra-ui/utils'
|
|
24
|
+
|
|
25
|
+
interface Option {
|
|
26
|
+
value: string
|
|
27
|
+
label?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface SelectOptions {
|
|
31
|
+
/**
|
|
32
|
+
* An array of options
|
|
33
|
+
* If you leave this empty the children prop will be rendered.
|
|
34
|
+
*/
|
|
35
|
+
options?: Option[]
|
|
36
|
+
/**
|
|
37
|
+
* Props passed to the MenuList.
|
|
38
|
+
*/
|
|
39
|
+
menuListProps?: MenuListProps
|
|
40
|
+
/**
|
|
41
|
+
* Customize how the value is rendered.
|
|
42
|
+
* @type (value?: string[]) => React.ReactElement
|
|
43
|
+
*/
|
|
44
|
+
renderValue?: (value?: string[]) => React.ReactElement | undefined
|
|
45
|
+
/**
|
|
46
|
+
* Enable multiple select.
|
|
47
|
+
*/
|
|
48
|
+
multiple?: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SelectProps
|
|
52
|
+
extends Omit<MenuProps, 'children'>,
|
|
53
|
+
Pick<ButtonProps, 'isDisabled' | 'leftIcon' | 'rightIcon'>,
|
|
54
|
+
Pick<MenuOptionGroupProps, 'onChange'>,
|
|
55
|
+
SelectOptions {}
|
|
56
|
+
|
|
57
|
+
const SelectButton = forwardRef((props, ref) => {
|
|
58
|
+
const styles = useMultiStyleConfig('Input', props)
|
|
59
|
+
|
|
60
|
+
/* @ts-ignore */
|
|
61
|
+
const focusStyles = styles.field._focusVisible
|
|
62
|
+
|
|
63
|
+
const height = styles.field.h || styles.field.height
|
|
64
|
+
|
|
65
|
+
const buttonStyles: SystemStyleObject = {
|
|
66
|
+
fontWeight: 'normal',
|
|
67
|
+
textAlign: 'left',
|
|
68
|
+
color: 'inherit',
|
|
69
|
+
_active: {
|
|
70
|
+
bg: 'transparent',
|
|
71
|
+
},
|
|
72
|
+
minH: height,
|
|
73
|
+
_focus: focusStyles,
|
|
74
|
+
_expanded: focusStyles,
|
|
75
|
+
...styles.field,
|
|
76
|
+
h: 'auto',
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Using a Button, so we can simply use leftIcon and rightIcon
|
|
80
|
+
return <MenuButton as={Button} {...props} ref={ref} sx={buttonStyles} />
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
if (__DEV__) {
|
|
84
|
+
SelectButton.displayName = 'SelectButton'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const Select = forwardRef<SelectProps, 'select'>((props, ref) => {
|
|
88
|
+
const {
|
|
89
|
+
name,
|
|
90
|
+
options,
|
|
91
|
+
children,
|
|
92
|
+
onChange,
|
|
93
|
+
defaultValue,
|
|
94
|
+
value,
|
|
95
|
+
placeholder,
|
|
96
|
+
isDisabled,
|
|
97
|
+
leftIcon,
|
|
98
|
+
rightIcon = <ChevronDownIcon />,
|
|
99
|
+
multiple,
|
|
100
|
+
size,
|
|
101
|
+
variant,
|
|
102
|
+
menuListProps,
|
|
103
|
+
renderValue = (value) => value?.join(', '),
|
|
104
|
+
...rest
|
|
105
|
+
} = props
|
|
106
|
+
const menuProps = omitThemingProps(rest)
|
|
107
|
+
|
|
108
|
+
const [currentValue, setCurrentValue] = React.useState(value || defaultValue)
|
|
109
|
+
|
|
110
|
+
const controlProps = useFormControl({ name } as HTMLChakraProps<'input'>)
|
|
111
|
+
|
|
112
|
+
const handleChange = (value: string | string[]) => {
|
|
113
|
+
setCurrentValue(value)
|
|
114
|
+
onChange?.(value)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const buttonProps = {
|
|
118
|
+
isDisabled,
|
|
119
|
+
leftIcon,
|
|
120
|
+
rightIcon,
|
|
121
|
+
size,
|
|
122
|
+
variant,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const getDisplayValue = React.useCallback(
|
|
126
|
+
(value: string) => {
|
|
127
|
+
if (!options) {
|
|
128
|
+
return value
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const option of options) {
|
|
132
|
+
if (option.label && option.value === value) {
|
|
133
|
+
return option.label
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return value
|
|
138
|
+
},
|
|
139
|
+
[options]
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
const displayValue = currentValue
|
|
143
|
+
? (Array.isArray(currentValue) ? currentValue : [currentValue]).map(
|
|
144
|
+
getDisplayValue
|
|
145
|
+
)
|
|
146
|
+
: []
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<Menu {...menuProps} closeOnSelect={!multiple}>
|
|
150
|
+
<chakra.div className={cx('sui-select')}>
|
|
151
|
+
<SelectButton ref={ref} {...buttonProps}>
|
|
152
|
+
{renderValue(displayValue) || placeholder}
|
|
153
|
+
</SelectButton>
|
|
154
|
+
<MenuList maxH="60vh" overflowY="auto" {...menuListProps}>
|
|
155
|
+
<MenuOptionGroup
|
|
156
|
+
defaultValue={
|
|
157
|
+
(defaultValue || value) as string | string[] | undefined
|
|
158
|
+
}
|
|
159
|
+
onChange={handleChange}
|
|
160
|
+
type={multiple ? 'checkbox' : 'radio'}
|
|
161
|
+
>
|
|
162
|
+
{options
|
|
163
|
+
? options.map(({ value, label, ...rest }, i) => (
|
|
164
|
+
<MenuItemOption key={i} value={value} {...rest}>
|
|
165
|
+
{label || value}
|
|
166
|
+
</MenuItemOption>
|
|
167
|
+
))
|
|
168
|
+
: children}
|
|
169
|
+
</MenuOptionGroup>
|
|
170
|
+
</MenuList>
|
|
171
|
+
<chakra.input
|
|
172
|
+
{...controlProps}
|
|
173
|
+
name={name}
|
|
174
|
+
type="hidden"
|
|
175
|
+
value={currentValue}
|
|
176
|
+
className="saas-select__input"
|
|
177
|
+
/>
|
|
178
|
+
</chakra.div>
|
|
179
|
+
</Menu>
|
|
180
|
+
)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
if (__DEV__) {
|
|
184
|
+
Select.displayName = 'Select'
|
|
185
|
+
}
|
package/src/step-form.tsx
CHANGED
|
@@ -2,7 +2,13 @@ import * as React from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { FieldValues, UseFormReturn } from 'react-hook-form'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
chakra,
|
|
7
|
+
Button,
|
|
8
|
+
ButtonProps,
|
|
9
|
+
HTMLChakraProps,
|
|
10
|
+
ThemingProps,
|
|
11
|
+
} from '@chakra-ui/react'
|
|
6
12
|
|
|
7
13
|
import { callAllHandlers, runIfFn, cx, __DEV__ } from '@chakra-ui/utils'
|
|
8
14
|
|
|
@@ -14,8 +20,7 @@ import {
|
|
|
14
20
|
useStepperContext,
|
|
15
21
|
StepperContainer,
|
|
16
22
|
StepperProps,
|
|
17
|
-
} from '@saas-ui/
|
|
18
|
-
import { Button, ButtonProps } from '@saas-ui/button'
|
|
23
|
+
} from '@saas-ui/core'
|
|
19
24
|
|
|
20
25
|
import { Form } from './form'
|
|
21
26
|
import { SubmitButton } from './submit-button'
|
|
@@ -28,13 +33,18 @@ import {
|
|
|
28
33
|
FormStepSubmitHandler,
|
|
29
34
|
} from './use-step-form'
|
|
30
35
|
|
|
31
|
-
export interface StepFormProps<
|
|
32
|
-
extends
|
|
36
|
+
export interface StepFormProps<
|
|
37
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
38
|
+
TContext extends object = object
|
|
39
|
+
> extends UseStepFormProps<TFieldValues> {}
|
|
33
40
|
|
|
34
41
|
export const StepForm = React.forwardRef(
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
<
|
|
43
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
44
|
+
TContext extends object = object
|
|
45
|
+
>(
|
|
46
|
+
props: StepFormProps<TFieldValues, TContext>,
|
|
47
|
+
ref: React.ForwardedRef<HTMLFormElement>
|
|
38
48
|
) => {
|
|
39
49
|
const { children, ...rest } = props
|
|
40
50
|
|
|
@@ -56,7 +66,7 @@ export const StepForm = React.forwardRef(
|
|
|
56
66
|
}
|
|
57
67
|
) as <TFieldValues extends FieldValues>(
|
|
58
68
|
props: StepFormProps<TFieldValues> & {
|
|
59
|
-
ref?: React.ForwardedRef<
|
|
69
|
+
ref?: React.ForwardedRef<HTMLFormElement>
|
|
60
70
|
}
|
|
61
71
|
) => React.ReactElement
|
|
62
72
|
|
|
@@ -138,7 +148,7 @@ export const FormStep: React.FC<FormStepProps> = (props) => {
|
|
|
138
148
|
const { isActive } = step
|
|
139
149
|
|
|
140
150
|
return isActive ? (
|
|
141
|
-
<chakra.div {...rest} className={cx('
|
|
151
|
+
<chakra.div {...rest} className={cx('sui-form__step', className)}>
|
|
142
152
|
{children}
|
|
143
153
|
</chakra.div>
|
|
144
154
|
) : null
|
|
@@ -156,7 +166,7 @@ export const PrevButton: React.FC<ButtonProps> = (props) => {
|
|
|
156
166
|
isDisabled={isFirstStep || isCompleted}
|
|
157
167
|
label="Back"
|
|
158
168
|
{...props}
|
|
159
|
-
className={cx('
|
|
169
|
+
className={cx('sui-form__prev-button', props.className)}
|
|
160
170
|
onClick={callAllHandlers(props.onClick, prevStep)}
|
|
161
171
|
/>
|
|
162
172
|
)
|
|
@@ -166,8 +176,9 @@ if (__DEV__) {
|
|
|
166
176
|
PrevButton.displayName = 'PrevButton'
|
|
167
177
|
}
|
|
168
178
|
|
|
169
|
-
export interface NextButtonProps extends ButtonProps {
|
|
179
|
+
export interface NextButtonProps extends Omit<ButtonProps, 'children'> {
|
|
170
180
|
submitLabel?: string
|
|
181
|
+
label?: string
|
|
171
182
|
}
|
|
172
183
|
|
|
173
184
|
export const NextButton: React.FC<NextButtonProps> = (props) => {
|
|
@@ -178,7 +189,7 @@ export const NextButton: React.FC<NextButtonProps> = (props) => {
|
|
|
178
189
|
<SubmitButton
|
|
179
190
|
{...rest}
|
|
180
191
|
isDisabled={isCompleted}
|
|
181
|
-
className={cx('
|
|
192
|
+
className={cx('sui-form__next-button', props.className)}
|
|
182
193
|
>
|
|
183
194
|
{isLastStep || isCompleted ? submitLabel : label}
|
|
184
195
|
</SubmitButton>
|
package/src/submit-button.tsx
CHANGED
|
@@ -2,9 +2,7 @@ import * as React from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { useFormContext } from 'react-hook-form'
|
|
4
4
|
|
|
5
|
-
import { Button, ButtonProps } from '@
|
|
6
|
-
|
|
7
|
-
import { __DEV__ } from '@chakra-ui/utils'
|
|
5
|
+
import { Button, ButtonProps, forwardRef } from '@chakra-ui/react'
|
|
8
6
|
|
|
9
7
|
export interface SubmitButtonProps extends ButtonProps {
|
|
10
8
|
/**
|
|
@@ -23,45 +21,41 @@ export interface SubmitButtonProps extends ButtonProps {
|
|
|
23
21
|
disableIfInvalid?: boolean
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
export const SubmitButton =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
})
|
|
24
|
+
export const SubmitButton = forwardRef<SubmitButtonProps, 'button'>(
|
|
25
|
+
(props, ref) => {
|
|
26
|
+
const {
|
|
27
|
+
children = 'Submit',
|
|
28
|
+
disableIfUntouched,
|
|
29
|
+
disableIfInvalid,
|
|
30
|
+
isDisabled: isDisabledProp,
|
|
31
|
+
isLoading,
|
|
32
|
+
...rest
|
|
33
|
+
} = props
|
|
34
|
+
const { formState } = useFormContext()
|
|
35
|
+
|
|
36
|
+
const isDisabled =
|
|
37
|
+
(disableIfUntouched && !formState.isDirty) ||
|
|
38
|
+
(disableIfInvalid && !formState.isValid) ||
|
|
39
|
+
isDisabledProp
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Button
|
|
43
|
+
{...rest}
|
|
44
|
+
ref={ref}
|
|
45
|
+
type="submit"
|
|
46
|
+
isLoading={formState.isSubmitting || isLoading}
|
|
47
|
+
isDisabled={isDisabled}
|
|
48
|
+
>
|
|
49
|
+
{children}
|
|
50
|
+
</Button>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
)
|
|
57
54
|
|
|
58
55
|
SubmitButton.defaultProps = {
|
|
59
56
|
variant: 'primary',
|
|
60
|
-
children: 'Submit',
|
|
61
57
|
disableIfUntouched: false,
|
|
62
58
|
disableIfInvalid: false,
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
SubmitButton.displayName = 'SubmitButton'
|
|
67
|
-
}
|
|
61
|
+
SubmitButton.displayName = 'SubmitButton'
|
package/src/use-step-form.tsx
CHANGED
package/ajv/package.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ajv-resolver",
|
|
3
|
-
"description": "Saas UI Forms field resolver: ajv",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"private": true,
|
|
6
|
-
"exports": {
|
|
7
|
-
".": {
|
|
8
|
-
"require": "./../dist/ajv/index.js",
|
|
9
|
-
"import": "./../dist/ajv/index.modern.mjs"
|
|
10
|
-
},
|
|
11
|
-
"./src": {
|
|
12
|
-
"default": "./src/index.ts"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"source": "./src/index.ts",
|
|
16
|
-
"main": "../dist/ajv/index.js",
|
|
17
|
-
"module": "../dist/ajv/index.modern.mjs",
|
|
18
|
-
"types": "../dist/ajv/index.d.ts",
|
|
19
|
-
"author": "Eelco Wiersma <eelco@appulse.nl>",
|
|
20
|
-
"license": "MIT",
|
|
21
|
-
"peerDependencies": {
|
|
22
|
-
"@chakra-ui/utils": "^2.0.2",
|
|
23
|
-
"@saas-ui/forms": "^1.4.2",
|
|
24
|
-
"@hookform/resolvers": "^2.9.3",
|
|
25
|
-
"react-hook-form": "^7.33.1",
|
|
26
|
-
"ajv": "^8.11.0"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { ajvResolver } from '@hookform/resolvers/ajv';
|
|
2
|
-
import { FieldResolver } from '@saas-ui/forms';
|
|
3
|
-
import { JSONSchemaType } from 'ajv';
|
|
4
|
-
interface JsonSchemaFormReturn {
|
|
5
|
-
schema: JSONSchemaType<unknown>;
|
|
6
|
-
fieldResolver: FieldResolver;
|
|
7
|
-
resolver: ReturnType<typeof ajvResolver>;
|
|
8
|
-
}
|
|
9
|
-
export declare const jsonSchemaForm: (schema: JSONSchemaType<unknown>) => JsonSchemaFormReturn;
|
|
10
|
-
export {};
|
|
11
|
-
//# sourceMappingURL=ajv-resolver.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ajv-resolver.d.ts","sourceRoot":"","sources":["../../ajv/src/ajv-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAuB,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAMpC,UAAU,oBAAoB;IAC5B,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;IAC/B,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;CACzC;AAED,eAAO,MAAM,cAAc,WACjB,eAAe,OAAO,CAAC,KAC9B,oBAMF,CAAA"}
|
package/dist/ajv/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ajv/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.modern.mjs","sources":["../../ajv/src/ajv-resolver.ts"],"sourcesContent":["import { ajvResolver } from '@hookform/resolvers/ajv'\nimport { objectFieldResolver, FieldResolver } from '@saas-ui/forms'\n\nimport { JSONSchemaType } from 'ajv'\n\nconst jsonSchemaFieldResolver = (schema: JSONSchemaType<unknown>) => {\n return objectFieldResolver(schema.properties)\n}\n\ninterface JsonSchemaFormReturn {\n schema: JSONSchemaType<unknown>\n fieldResolver: FieldResolver\n resolver: ReturnType<typeof ajvResolver>\n}\n\nexport const jsonSchemaForm = (\n schema: JSONSchemaType<unknown>\n): JsonSchemaFormReturn => {\n return {\n schema,\n fieldResolver: jsonSchemaFieldResolver(schema),\n resolver: ajvResolver(schema),\n }\n}\n"],"names":["jsonSchemaFieldResolver","schema","objectFieldResolver","properties","jsonSchemaForm","fieldResolver","resolver","ajvResolver"],"mappings":"2GAKA,MAAMA,EAA2BC,GACxBC,EAAoBD,EAAOE,YASvBC,EACXH,IAEO,CACLA,SACAI,cAAeL,EAAwBC,GACvCK,SAAUC,EAAYN"}
|
package/dist/array-field.d.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { ResponsiveValue } from '@chakra-ui/system';
|
|
3
|
-
import { ButtonProps } from '@saas-ui/button';
|
|
4
|
-
import { FormLayoutProps } from './layout';
|
|
5
|
-
import { FieldProps } from './field';
|
|
6
|
-
import { ArrayFieldOptions, UseArrayFieldReturn } from './use-array-field';
|
|
7
|
-
interface ArrayField {
|
|
8
|
-
id: string;
|
|
9
|
-
[key: string]: unknown;
|
|
10
|
-
}
|
|
11
|
-
interface ArrayFieldRowProps extends FormLayoutProps {
|
|
12
|
-
/**
|
|
13
|
-
* Amount of field columns
|
|
14
|
-
*/
|
|
15
|
-
columns?: ResponsiveValue<number>;
|
|
16
|
-
/**
|
|
17
|
-
* Spacing between fields
|
|
18
|
-
*/
|
|
19
|
-
spacing?: ResponsiveValue<string | number>;
|
|
20
|
-
/**
|
|
21
|
-
* The array index
|
|
22
|
-
*/
|
|
23
|
-
index: number;
|
|
24
|
-
/**
|
|
25
|
-
* The fields
|
|
26
|
-
*/
|
|
27
|
-
children: React.ReactNode;
|
|
28
|
-
}
|
|
29
|
-
export declare const ArrayFieldRow: React.FC<ArrayFieldRowProps>;
|
|
30
|
-
export interface ArrayFieldRowFieldsProps extends FormLayoutProps {
|
|
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 fields
|
|
41
|
-
*/
|
|
42
|
-
children: React.ReactNode;
|
|
43
|
-
}
|
|
44
|
-
export declare const ArrayFieldRowFields: React.FC<ArrayFieldRowFieldsProps>;
|
|
45
|
-
export declare const ArrayFieldRowContainer: React.FC<ArrayFieldRowProps>;
|
|
46
|
-
export declare const ArrayFieldRemoveButton: React.FC<ButtonProps>;
|
|
47
|
-
export declare const ArrayFieldAddButton: React.FC<ButtonProps>;
|
|
48
|
-
export interface ArrayFieldProps extends ArrayFieldOptions, Omit<FieldProps, 'defaultValue'> {
|
|
49
|
-
}
|
|
50
|
-
export declare const ArrayField: ((props: ArrayFieldProps & {
|
|
51
|
-
ref?: React.ForwardedRef<UseArrayFieldReturn>;
|
|
52
|
-
}) => React.ReactElement) & {
|
|
53
|
-
displayName: string;
|
|
54
|
-
};
|
|
55
|
-
export interface ArrayFieldRowsProps {
|
|
56
|
-
children: (fields: ArrayField[]) => React.ReactElement | null;
|
|
57
|
-
}
|
|
58
|
-
export declare const ArrayFieldRows: {
|
|
59
|
-
({ children, }: ArrayFieldRowsProps): React.ReactElement | null;
|
|
60
|
-
displayName: string;
|
|
61
|
-
};
|
|
62
|
-
export declare const ArrayFieldContainer: React.ForwardRefExoticComponent<ArrayFieldProps & React.RefAttributes<UseArrayFieldReturn>>;
|
|
63
|
-
export {};
|
|
64
|
-
//# sourceMappingURL=array-field.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"array-field.d.ts","sourceRoot":"","sources":["../src/array-field.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,eAAe,EAAc,MAAM,mBAAmB,CAAA;AAGvE,OAAO,EAAc,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAEzD,OAAO,EAAc,eAAe,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAa,UAAU,EAAE,MAAM,SAAS,CAAA;AAI/C,OAAO,EAKL,iBAAiB,EAKjB,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAE1B,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,UAAU,kBAAmB,SAAQ,eAAe;IAClD;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAA;IACjC;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;IAC1C;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAWtD,CAAA;AAMD,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC/D;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAA;IACjC;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;IAC1C;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAUlE,CAAA;AAMD,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAmB/D,CAAA;AAMD,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CASxD,CAAA;AAMD,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAUrD,CAAA;AAMD,MAAM,WAAW,eACf,SAAQ,iBAAiB,EACvB,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC;CAAG;AAEvC,eAAO,MAAM,UAAU,WAsBd,eAAe,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,YAAY,CAAC,mBAAmB,CAAC,CAAA;CAC9C,KACE,MAAM,YAAY;iBACR,MAAM;CACpB,CAAA;AAMD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,KAAK,CAAC,YAAY,GAAG,IAAI,CAAA;CAC9D;AAED,eAAO,MAAM,cAAc;oBAExB,mBAAmB,GAAG,MAAM,YAAY,GAAG,IAAI;;CAGjD,CAAA;AAMD,eAAO,MAAM,mBAAmB,6FAgC/B,CAAA"}
|
package/dist/auto-form.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { FieldValues, UseFormReturn } from 'react-hook-form';
|
|
3
|
-
import { FormProps } from './form';
|
|
4
|
-
import { FieldResolver } from '.';
|
|
5
|
-
interface AutoFormOptions {
|
|
6
|
-
/**
|
|
7
|
-
* The submit button label.
|
|
8
|
-
* Pass `null` to render no submit button.
|
|
9
|
-
*/
|
|
10
|
-
submitLabel?: React.ReactNode;
|
|
11
|
-
/**
|
|
12
|
-
* The schema.
|
|
13
|
-
* Supports object schema, Zod, Yup or Ajv (JSON Schema).
|
|
14
|
-
* @see https://www.saas-ui.dev/docs/forms/auto-form
|
|
15
|
-
*/
|
|
16
|
-
schema: any;
|
|
17
|
-
/**
|
|
18
|
-
* The field resolver.
|
|
19
|
-
*/
|
|
20
|
-
fieldResolver?: any;
|
|
21
|
-
}
|
|
22
|
-
export interface AutoFormProps<TFieldValues extends FieldValues> extends Omit<FormProps<TFieldValues>, 'schema' | 'children'>, AutoFormOptions {
|
|
23
|
-
children?: React.ReactNode;
|
|
24
|
-
}
|
|
25
|
-
export declare const AutoForm: (<TFieldValues extends FieldValues>(props: AutoFormProps<TFieldValues> & {
|
|
26
|
-
ref?: React.ForwardedRef<UseFormReturn<TFieldValues, any>> | undefined;
|
|
27
|
-
}) => React.ReactElement) & {
|
|
28
|
-
displayName?: string | undefined;
|
|
29
|
-
getFieldResolver?: ((schema: any) => FieldResolver) | undefined;
|
|
30
|
-
};
|
|
31
|
-
export {};
|
|
32
|
-
//# sourceMappingURL=auto-form.d.ts.map
|