@saas-ui/forms 2.0.0-next.2 → 2.0.0-next.20
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 +188 -0
- package/README.md +53 -6
- package/dist/ajv/index.d.ts +24 -11
- package/dist/ajv/index.js +7 -9
- package/dist/ajv/index.js.map +1 -1
- package/dist/ajv/index.mjs +7 -10
- package/dist/ajv/index.mjs.map +1 -1
- package/dist/index.d.ts +519 -280
- package/dist/index.js +777 -696
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +756 -676
- package/dist/index.mjs.map +1 -1
- package/dist/yup/index.d.ts +525 -21
- package/dist/yup/index.js +21 -9
- package/dist/yup/index.js.map +1 -1
- package/dist/yup/index.mjs +21 -10
- package/dist/yup/index.mjs.map +1 -1
- package/dist/zod/index.d.ts +525 -12
- package/dist/zod/index.js +21 -1
- package/dist/zod/index.js.map +1 -1
- package/dist/zod/index.mjs +21 -3
- package/dist/zod/index.mjs.map +1 -1
- package/package.json +33 -10
- package/src/array-field.tsx +88 -48
- package/src/auto-form.tsx +7 -3
- package/src/base-field.tsx +54 -0
- package/src/create-field.tsx +144 -0
- package/src/create-form.tsx +68 -0
- package/src/create-step-form.tsx +100 -0
- package/src/default-fields.tsx +163 -0
- package/src/display-field.tsx +9 -11
- package/src/display-if.tsx +20 -13
- package/src/field-resolver.ts +10 -8
- package/src/field.tsx +18 -445
- package/src/fields-context.tsx +23 -0
- package/src/fields.tsx +34 -21
- package/src/form-context.tsx +84 -0
- package/src/form.tsx +77 -55
- package/src/index.ts +58 -4
- package/src/input-right-button/input-right-button.stories.tsx +1 -1
- package/src/input-right-button/input-right-button.tsx +0 -2
- package/src/layout.tsx +16 -11
- package/src/number-input/number-input.tsx +9 -5
- package/src/object-field.tsx +35 -13
- package/src/password-input/password-input.stories.tsx +23 -2
- package/src/password-input/password-input.tsx +6 -6
- package/src/pin-input/pin-input.tsx +1 -5
- package/src/radio/radio-input.stories.tsx +1 -1
- package/src/radio/radio-input.tsx +12 -10
- package/src/select/native-select.tsx +1 -4
- package/src/select/select-context.tsx +130 -0
- package/src/select/select.stories.tsx +116 -85
- package/src/select/select.test.tsx +1 -1
- package/src/select/select.tsx +162 -146
- package/src/step-form.tsx +76 -76
- package/src/submit-button.tsx +5 -1
- package/src/types.ts +149 -0
- package/src/use-array-field.tsx +9 -3
- package/src/use-step-form.tsx +54 -9
- package/src/utils.ts +23 -1
- package/src/watch-field.tsx +2 -6
- /package/src/radio/{radio.test.tsx → radio-input.test.tsx} +0 -0
package/src/form.tsx
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
import * as React from 'react'
|
2
2
|
|
3
3
|
import { chakra, HTMLChakraProps, forwardRef } from '@chakra-ui/react'
|
4
|
-
import { cx, runIfFn
|
4
|
+
import { FocusableElement, cx, runIfFn } from '@chakra-ui/utils'
|
5
5
|
|
6
6
|
import {
|
7
7
|
useForm,
|
8
|
-
FormProvider,
|
9
8
|
UseFormProps,
|
10
9
|
UseFormReturn,
|
11
10
|
FieldValues,
|
@@ -15,27 +14,44 @@ import {
|
|
15
14
|
ResolverResult,
|
16
15
|
WatchObserver,
|
17
16
|
} from 'react-hook-form'
|
18
|
-
import {
|
17
|
+
import { FormProvider } from './form-context'
|
18
|
+
import { FieldResolver } from './field-resolver'
|
19
19
|
import { MaybeRenderProp } from '@chakra-ui/react-utils'
|
20
20
|
|
21
21
|
export type { UseFormReturn, FieldValues, SubmitHandler }
|
22
22
|
|
23
|
-
import {
|
23
|
+
import { FieldProps, DefaultFieldOverrides } from './types'
|
24
24
|
|
25
|
-
|
25
|
+
import { Field as DefaultField } from './field'
|
26
|
+
import { FormLayout } from './layout'
|
27
|
+
import { AutoFields } from './fields'
|
28
|
+
import { SubmitButton } from './submit-button'
|
29
|
+
import { DisplayIf, DisplayIfProps } from './display-if'
|
30
|
+
import { ArrayField, ArrayFieldProps } from './array-field'
|
31
|
+
import { ObjectField, ObjectFieldProps } from './object-field'
|
32
|
+
import { UseArrayFieldReturn } from './use-array-field'
|
33
|
+
|
34
|
+
export interface FormRenderContext<
|
26
35
|
TFieldValues extends FieldValues = FieldValues,
|
27
|
-
TContext extends object = object
|
36
|
+
TContext extends object = object,
|
37
|
+
TFieldTypes = FieldProps<TFieldValues>
|
28
38
|
> extends UseFormReturn<TFieldValues, TContext> {
|
29
|
-
Field: React.FC<
|
39
|
+
Field: React.FC<TFieldTypes & React.RefAttributes<FocusableElement>>
|
40
|
+
DisplayIf: React.FC<DisplayIfProps<TFieldValues>>
|
41
|
+
ArrayField: React.FC<
|
42
|
+
ArrayFieldProps<TFieldValues> & React.RefAttributes<UseArrayFieldReturn>
|
43
|
+
>
|
44
|
+
ObjectField: React.FC<ObjectFieldProps<TFieldValues>>
|
30
45
|
}
|
31
46
|
|
32
47
|
interface FormOptions<
|
48
|
+
TSchema = unknown,
|
33
49
|
TFieldValues extends FieldValues = FieldValues,
|
34
50
|
TContext extends object = object,
|
35
|
-
|
51
|
+
TFieldTypes = FieldProps<TFieldValues>
|
36
52
|
> {
|
37
53
|
/**
|
38
|
-
* The form schema
|
54
|
+
* The form schema.
|
39
55
|
*/
|
40
56
|
schema?: TSchema
|
41
57
|
/**
|
@@ -57,32 +73,51 @@ interface FormOptions<
|
|
57
73
|
/**
|
58
74
|
* The form children, can be a render prop or a ReactNode.
|
59
75
|
*/
|
60
|
-
children?: MaybeRenderProp<
|
76
|
+
children?: MaybeRenderProp<
|
77
|
+
FormRenderContext<TFieldValues, TContext, TFieldTypes>
|
78
|
+
>
|
79
|
+
/**
|
80
|
+
* The field resolver, used to resolve the fields from schemas.
|
81
|
+
*/
|
82
|
+
fieldResolver?: FieldResolver
|
83
|
+
/**
|
84
|
+
* Field overrides
|
85
|
+
*/
|
86
|
+
fields?: DefaultFieldOverrides
|
61
87
|
}
|
62
88
|
|
63
89
|
export interface FormProps<
|
90
|
+
TSchema = unknown,
|
64
91
|
TFieldValues extends FieldValues = FieldValues,
|
65
92
|
TContext extends object = object,
|
66
|
-
|
93
|
+
TFieldTypes = FieldProps<TFieldValues>
|
67
94
|
> extends UseFormProps<TFieldValues, TContext>,
|
68
95
|
Omit<
|
69
96
|
HTMLChakraProps<'form'>,
|
70
97
|
'children' | 'onChange' | 'onSubmit' | 'onError'
|
71
98
|
>,
|
72
|
-
FormOptions<TFieldValues, TContext,
|
99
|
+
FormOptions<TSchema, TFieldValues, TContext, TFieldTypes> {}
|
73
100
|
|
101
|
+
/**
|
102
|
+
* The wrapper component provides context, state, and focus management.
|
103
|
+
*
|
104
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/form
|
105
|
+
*/
|
74
106
|
export const Form = forwardRef(
|
75
107
|
<
|
108
|
+
TSchema = any,
|
76
109
|
TFieldValues extends FieldValues = FieldValues,
|
77
110
|
TContext extends object = object,
|
78
|
-
|
111
|
+
TFieldTypes = FieldProps<TFieldValues>
|
79
112
|
>(
|
80
|
-
props: FormProps<TFieldValues, TContext,
|
113
|
+
props: FormProps<TSchema, TFieldValues, TContext, TFieldTypes>,
|
81
114
|
ref: React.ForwardedRef<HTMLFormElement>
|
82
115
|
) => {
|
83
116
|
const {
|
84
117
|
mode = 'all',
|
85
118
|
resolver,
|
119
|
+
fieldResolver,
|
120
|
+
fields,
|
86
121
|
reValidateMode,
|
87
122
|
shouldFocusError,
|
88
123
|
shouldUnregister,
|
@@ -117,10 +152,6 @@ export const Form = forwardRef(
|
|
117
152
|
resetOptions,
|
118
153
|
}
|
119
154
|
|
120
|
-
if (schema && !resolver) {
|
121
|
-
form.resolver = Form.getResolver?.(schema)
|
122
|
-
}
|
123
|
-
|
124
155
|
const methods = useForm<TFieldValues, TContext>(form)
|
125
156
|
const { handleSubmit } = methods
|
126
157
|
|
@@ -135,73 +166,64 @@ export const Form = forwardRef(
|
|
135
166
|
return () => subscription?.unsubscribe()
|
136
167
|
}, [methods, onChange])
|
137
168
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
169
|
+
let _children = children
|
170
|
+
if (!_children && fieldResolver) {
|
171
|
+
_children = (
|
172
|
+
<FormLayout>
|
173
|
+
<AutoFields />
|
174
|
+
<SubmitButton {...fields?.submit} />
|
175
|
+
</FormLayout>
|
176
|
+
)
|
177
|
+
}
|
142
178
|
|
143
179
|
return (
|
144
|
-
<FormProvider
|
180
|
+
<FormProvider
|
181
|
+
{...methods}
|
182
|
+
schema={schema}
|
183
|
+
fieldResolver={fieldResolver}
|
184
|
+
fields={fields}
|
185
|
+
>
|
145
186
|
<chakra.form
|
146
187
|
ref={ref}
|
147
188
|
onSubmit={handleSubmit(onSubmit, onError)}
|
148
189
|
{...rest}
|
149
190
|
className={cx('sui-form', props.className)}
|
150
191
|
>
|
151
|
-
{runIfFn(
|
152
|
-
Field,
|
192
|
+
{runIfFn(_children, {
|
193
|
+
Field: DefaultField as any,
|
194
|
+
DisplayIf: DisplayIf as any,
|
195
|
+
ArrayField: ArrayField as any,
|
196
|
+
ObjectField: ObjectField as any,
|
153
197
|
...methods,
|
154
198
|
})}
|
155
199
|
</chakra.form>
|
156
200
|
</FormProvider>
|
157
201
|
)
|
158
202
|
}
|
159
|
-
) as
|
160
|
-
|
203
|
+
) as FormComponent
|
204
|
+
|
205
|
+
export type FormComponent = (<
|
206
|
+
TSchema = unknown,
|
207
|
+
TFieldValues extends FieldValues = FieldValues,
|
161
208
|
TContext extends object = object,
|
162
|
-
|
209
|
+
TFieldTypes = FieldProps<TFieldValues>
|
163
210
|
>(
|
164
|
-
props: FormProps<TFieldValues, TContext,
|
211
|
+
props: FormProps<TSchema, TFieldValues, TContext, TFieldTypes> & {
|
165
212
|
ref?: React.ForwardedRef<HTMLFormElement>
|
166
213
|
}
|
167
214
|
) => React.ReactElement) & {
|
168
215
|
displayName?: string
|
169
|
-
getResolver?: GetResolver
|
170
|
-
getFieldResolver: GetFieldResolver
|
171
216
|
}
|
172
217
|
|
173
|
-
Form.getFieldResolver = objectFieldResolver
|
174
|
-
|
175
218
|
Form.displayName = 'Form'
|
176
219
|
|
177
220
|
export type GetResolver = <
|
178
221
|
TFieldValues extends FieldValues,
|
179
222
|
TContext extends object
|
180
223
|
>(
|
181
|
-
schema:
|
224
|
+
schema: unknown
|
182
225
|
) => (
|
183
226
|
values: TFieldValues,
|
184
227
|
context: TContext | undefined,
|
185
228
|
options: ResolverOptions<TFieldValues>
|
186
229
|
) => Promise<ResolverResult<TFieldValues>>
|
187
|
-
|
188
|
-
export type GetFieldResolver = (schema: any) => FieldResolver
|
189
|
-
|
190
|
-
export interface CreateFormProps {
|
191
|
-
resolver?: GetResolver
|
192
|
-
}
|
193
|
-
|
194
|
-
export function createForm<Schema = any>({ resolver }: CreateFormProps) {
|
195
|
-
const CreateForm = <
|
196
|
-
TFieldValues extends FieldValues,
|
197
|
-
TContext extends object = object,
|
198
|
-
TSchema extends Schema = Schema
|
199
|
-
>(
|
200
|
-
props: FormProps<TFieldValues, TContext, TSchema>
|
201
|
-
) => {
|
202
|
-
const { schema, ...rest } = props
|
203
|
-
return <Form resolver={resolver?.(props.schema)} {...rest} />
|
204
|
-
}
|
205
|
-
|
206
|
-
return CreateForm
|
207
|
-
}
|
package/src/index.ts
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
export * from './display-field'
|
2
2
|
export * from './field'
|
3
3
|
export * from './fields'
|
4
|
-
export * from './
|
5
|
-
export * from './auto-form'
|
4
|
+
export * from './fields-context'
|
5
|
+
// export * from './auto-form'
|
6
6
|
export * from './layout'
|
7
7
|
export * from './submit-button'
|
8
8
|
export * from './array-field'
|
@@ -16,6 +16,62 @@ export * from './watch-field'
|
|
16
16
|
export * from './input-right-button'
|
17
17
|
export * from './select'
|
18
18
|
export * from './password-input'
|
19
|
+
export * from './radio'
|
20
|
+
|
21
|
+
export * from './base-field'
|
22
|
+
|
23
|
+
export {
|
24
|
+
CheckboxField,
|
25
|
+
InputField,
|
26
|
+
NativeSelectField,
|
27
|
+
NumberInputField,
|
28
|
+
PasswordInputField,
|
29
|
+
PinField,
|
30
|
+
RadioField,
|
31
|
+
SelectField,
|
32
|
+
SwitchField,
|
33
|
+
TextareaField,
|
34
|
+
defaultFieldTypes,
|
35
|
+
type DefaultFields,
|
36
|
+
type InputFieldProps,
|
37
|
+
type NumberInputFieldProps,
|
38
|
+
type PinFieldProps,
|
39
|
+
} from './default-fields'
|
40
|
+
|
41
|
+
export type {
|
42
|
+
FieldProps,
|
43
|
+
WithFields,
|
44
|
+
BaseFieldProps,
|
45
|
+
FieldOptions,
|
46
|
+
DefaultFieldOverrides,
|
47
|
+
} from './types'
|
48
|
+
|
49
|
+
export { createForm, type CreateFormProps, type FormType } from './create-form'
|
50
|
+
export { createField, type CreateFieldOptions } from './create-field'
|
51
|
+
|
52
|
+
export { Form as BaseForm } from './form'
|
53
|
+
export type { FormProps, FormRenderContext, FormComponent } from './form'
|
54
|
+
|
55
|
+
export { FormProvider, useFormContext } from './form-context'
|
56
|
+
|
57
|
+
import { createForm } from './create-form'
|
58
|
+
import { createStepForm } from './create-step-form'
|
59
|
+
|
60
|
+
/**
|
61
|
+
* Form component.
|
62
|
+
*
|
63
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/form
|
64
|
+
*/
|
65
|
+
export const Form = createForm()
|
66
|
+
|
67
|
+
export { createStepForm } from './create-step-form'
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Multi-step form component.
|
71
|
+
*
|
72
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/step-form
|
73
|
+
*/
|
74
|
+
export const StepForm = createStepForm()
|
19
75
|
|
20
76
|
export type {
|
21
77
|
BatchFieldArrayUpdate,
|
@@ -120,9 +176,7 @@ export {
|
|
120
176
|
useController,
|
121
177
|
useFieldArray,
|
122
178
|
useForm,
|
123
|
-
useFormContext,
|
124
179
|
useFormState,
|
125
180
|
useWatch,
|
126
181
|
Controller,
|
127
|
-
FormProvider,
|
128
182
|
} from 'react-hook-form'
|
package/src/layout.tsx
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
import * as React from 'react'
|
2
2
|
|
3
|
-
import {
|
4
|
-
|
3
|
+
import {
|
4
|
+
chakra,
|
5
|
+
ResponsiveValue,
|
6
|
+
SimpleGrid,
|
7
|
+
SimpleGridProps,
|
8
|
+
useTheme,
|
9
|
+
} from '@chakra-ui/react'
|
10
|
+
import { cx } from '@chakra-ui/utils'
|
5
11
|
|
6
|
-
export
|
12
|
+
export interface FormLayoutProps extends SimpleGridProps {}
|
7
13
|
|
8
14
|
interface FormLayoutItemProps {
|
9
15
|
children: React.ReactNode
|
@@ -13,20 +19,21 @@ const FormLayoutItem: React.FC<FormLayoutItemProps> = ({ children }) => {
|
|
13
19
|
return <chakra.div>{children}</chakra.div>
|
14
20
|
}
|
15
21
|
|
16
|
-
|
17
|
-
FormLayoutItem.displayName = 'FormLayoutItem'
|
18
|
-
}
|
22
|
+
FormLayoutItem.displayName = 'FormLayoutItem'
|
19
23
|
|
20
24
|
/**
|
21
|
-
*
|
25
|
+
* Create consistent field spacing and positioning.
|
26
|
+
*
|
22
27
|
*
|
23
28
|
* Renders form items in a `SimpleGrid`
|
24
29
|
* @see https://chakra-ui.com/docs/layout/simple-grid
|
30
|
+
*
|
31
|
+
* @see https://saas-ui.dev/docs/components/forms/form
|
25
32
|
*/
|
26
33
|
export const FormLayout = ({ children, ...props }: FormLayoutProps) => {
|
27
34
|
const theme = useTheme()
|
28
35
|
|
29
|
-
const defaultProps = theme.components?.
|
36
|
+
const defaultProps = theme.components?.SuiFormLayout?.defaultProps ?? {
|
30
37
|
spacing: 4,
|
31
38
|
}
|
32
39
|
|
@@ -50,6 +57,4 @@ export const FormLayout = ({ children, ...props }: FormLayoutProps) => {
|
|
50
57
|
)
|
51
58
|
}
|
52
59
|
|
53
|
-
|
54
|
-
FormLayout.displayName = 'FormLayout'
|
55
|
-
}
|
60
|
+
FormLayout.displayName = 'FormLayout'
|
@@ -9,7 +9,8 @@ import {
|
|
9
9
|
NumberDecrementStepper,
|
10
10
|
NumberInputProps as ChakraNumberInputProps,
|
11
11
|
} from '@chakra-ui/react'
|
12
|
-
|
12
|
+
|
13
|
+
import { ChevronDownIcon, ChevronUpIcon } from '@saas-ui/core'
|
13
14
|
|
14
15
|
interface NumberInputOptions {
|
15
16
|
/**
|
@@ -31,7 +32,12 @@ export interface NumberInputProps
|
|
31
32
|
NumberInputOptions {}
|
32
33
|
|
33
34
|
export const NumberInput = forwardRef<NumberInputProps, 'div'>((props, ref) => {
|
34
|
-
const {
|
35
|
+
const {
|
36
|
+
hideStepper,
|
37
|
+
incrementIcon = <ChevronUpIcon />,
|
38
|
+
decrementIcon = <ChevronDownIcon />,
|
39
|
+
...rest
|
40
|
+
} = props
|
35
41
|
|
36
42
|
return (
|
37
43
|
<ChakraNumberInput {...rest} ref={ref}>
|
@@ -51,6 +57,4 @@ NumberInput.defaultProps = {
|
|
51
57
|
hideStepper: false,
|
52
58
|
}
|
53
59
|
|
54
|
-
|
55
|
-
NumberInput.displayName = 'NumberInput'
|
56
|
-
}
|
60
|
+
NumberInput.displayName = 'NumberInput'
|
package/src/object-field.tsx
CHANGED
@@ -6,15 +6,19 @@ import {
|
|
6
6
|
ResponsiveValue,
|
7
7
|
useStyleConfig,
|
8
8
|
} from '@chakra-ui/react'
|
9
|
-
import { __DEV__ } from '@chakra-ui/utils'
|
10
9
|
|
11
10
|
import { FormLayout } from './layout'
|
12
|
-
import {
|
11
|
+
import { BaseFieldProps } from './types'
|
13
12
|
|
14
13
|
import { mapNestedFields } from './utils'
|
14
|
+
import { FieldPath, FieldValues } from 'react-hook-form'
|
15
|
+
import { useFieldProps } from './form-context'
|
15
16
|
|
16
|
-
export interface ObjectFieldProps
|
17
|
-
|
17
|
+
export interface ObjectFieldProps<
|
18
|
+
TFieldValues extends FieldValues = FieldValues,
|
19
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
20
|
+
> extends BaseFieldProps {
|
21
|
+
name: TName
|
18
22
|
children: React.ReactNode
|
19
23
|
columns?: ResponsiveValue<number>
|
20
24
|
spacing?: ResponsiveValue<string | number>
|
@@ -24,21 +28,39 @@ export const FormLegend = (props: FormLabelProps) => {
|
|
24
28
|
const styles = useStyleConfig('SuiFormLegend')
|
25
29
|
return <FormLabel as="legend" sx={styles} {...props} />
|
26
30
|
}
|
27
|
-
|
31
|
+
/**
|
32
|
+
* The object field component.
|
33
|
+
*
|
34
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/object-field
|
35
|
+
*/
|
28
36
|
export const ObjectField: React.FC<ObjectFieldProps> = (props) => {
|
29
|
-
const {
|
30
|
-
|
37
|
+
const {
|
38
|
+
name,
|
39
|
+
label,
|
40
|
+
hideLabel: hideLabelProp,
|
41
|
+
children,
|
42
|
+
columns: columnsProp,
|
43
|
+
spacing: spacingProp,
|
44
|
+
...fieldProps
|
45
|
+
} = props
|
46
|
+
|
47
|
+
const { hideLabel, columns, spacing, ...overrides } = useFieldProps(
|
48
|
+
name
|
49
|
+
) as Omit<ObjectFieldProps, 'name'>
|
31
50
|
|
32
51
|
return (
|
33
|
-
<FormControl name={name} as="fieldset" {...fieldProps}>
|
34
|
-
<FormLegend display={hideLabel ? 'none' : 'block'}>
|
35
|
-
|
52
|
+
<FormControl name={name} as="fieldset" {...fieldProps} {...overrides}>
|
53
|
+
<FormLegend display={hideLabelProp || hideLabel ? 'none' : 'block'}>
|
54
|
+
{label}
|
55
|
+
</FormLegend>
|
56
|
+
<FormLayout
|
57
|
+
columns={columnsProp || columns}
|
58
|
+
gridGap={spacingProp || spacing}
|
59
|
+
>
|
36
60
|
{mapNestedFields(name, children)}
|
37
61
|
</FormLayout>
|
38
62
|
</FormControl>
|
39
63
|
)
|
40
64
|
}
|
41
65
|
|
42
|
-
|
43
|
-
ObjectField.displayName = 'ObjectField'
|
44
|
-
}
|
66
|
+
ObjectField.displayName = 'ObjectField'
|
@@ -1,8 +1,15 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
Container,
|
3
|
+
FormControl,
|
4
|
+
FormLabel,
|
5
|
+
Icon,
|
6
|
+
InputLeftAddon,
|
7
|
+
InputLeftElement,
|
8
|
+
} from '@chakra-ui/react'
|
2
9
|
import { Story } from '@storybook/react'
|
3
10
|
import * as React from 'react'
|
4
11
|
|
5
|
-
import { FiEye, FiEyeOff } from 'react-icons/fi'
|
12
|
+
import { FiEye, FiEyeOff, FiLock } from 'react-icons/fi'
|
6
13
|
|
7
14
|
import { PasswordInput } from './password-input'
|
8
15
|
|
@@ -48,3 +55,17 @@ export const CustomWidth: Story = () => (
|
|
48
55
|
<PasswordInput name="password" width="200px" />
|
49
56
|
</FormControl>
|
50
57
|
)
|
58
|
+
|
59
|
+
export const LeftAddon: Story = () => (
|
60
|
+
<FormControl>
|
61
|
+
<FormLabel>Password</FormLabel>
|
62
|
+
<PasswordInput
|
63
|
+
name="password"
|
64
|
+
leftAddon={
|
65
|
+
<InputLeftElement>
|
66
|
+
<FiLock />
|
67
|
+
</InputLeftElement>
|
68
|
+
}
|
69
|
+
/>
|
70
|
+
</FormControl>
|
71
|
+
)
|
@@ -1,14 +1,15 @@
|
|
1
1
|
import React, { useState } from 'react'
|
2
2
|
|
3
3
|
import { forwardRef, InputGroup, Input, InputProps } from '@chakra-ui/react'
|
4
|
-
|
5
|
-
import { ViewIcon, ViewOffIcon } from '@
|
4
|
+
|
5
|
+
import { ViewIcon, ViewOffIcon } from '@saas-ui/core/icons'
|
6
6
|
|
7
7
|
import { InputRightButton } from '../input-right-button'
|
8
8
|
|
9
9
|
interface PasswordOptions {
|
10
10
|
viewIcon?: React.ReactNode
|
11
11
|
viewOffIcon?: React.ReactNode
|
12
|
+
leftAddon?: React.ReactNode
|
12
13
|
}
|
13
14
|
|
14
15
|
export interface PasswordInputProps extends InputProps, PasswordOptions {}
|
@@ -23,6 +24,7 @@ export const PasswordInput = forwardRef<PasswordInputProps, 'div'>(
|
|
23
24
|
width,
|
24
25
|
size,
|
25
26
|
variant,
|
27
|
+
leftAddon,
|
26
28
|
...inputProps
|
27
29
|
} = props
|
28
30
|
const [show, setShow] = useState(false)
|
@@ -45,13 +47,13 @@ export const PasswordInput = forwardRef<PasswordInputProps, 'div'>(
|
|
45
47
|
|
46
48
|
return (
|
47
49
|
<InputGroup {...groupProps}>
|
50
|
+
{leftAddon}
|
48
51
|
<Input
|
49
52
|
{...inputProps}
|
50
53
|
ref={ref}
|
51
54
|
type={show ? 'text' : 'password'}
|
52
55
|
autoComplete={show ? 'off' : autoComplete}
|
53
56
|
/>
|
54
|
-
|
55
57
|
<InputRightButton
|
56
58
|
onClick={handleClick}
|
57
59
|
aria-label={label}
|
@@ -64,6 +66,4 @@ export const PasswordInput = forwardRef<PasswordInputProps, 'div'>(
|
|
64
66
|
}
|
65
67
|
)
|
66
68
|
|
67
|
-
|
68
|
-
PasswordInput.displayName = 'PasswordInput'
|
69
|
-
}
|
69
|
+
PasswordInput.displayName = 'PasswordInput'
|
@@ -8,8 +8,6 @@ import {
|
|
8
8
|
SystemProps,
|
9
9
|
} from '@chakra-ui/react'
|
10
10
|
|
11
|
-
import { __DEV__ } from '@chakra-ui/utils'
|
12
|
-
|
13
11
|
interface PinInputOptions {
|
14
12
|
/**
|
15
13
|
* The pin length.
|
@@ -45,6 +43,4 @@ PinInput.defaultProps = {
|
|
45
43
|
pinLength: 4,
|
46
44
|
}
|
47
45
|
|
48
|
-
|
49
|
-
PinInput.displayName = 'PinInput'
|
50
|
-
}
|
46
|
+
PinInput.displayName = 'PinInput'
|
@@ -10,15 +10,17 @@ import {
|
|
10
10
|
SystemProps,
|
11
11
|
StackDirection,
|
12
12
|
} from '@chakra-ui/react'
|
13
|
-
import {
|
13
|
+
import { FieldOptions, FieldOption } from '../types'
|
14
|
+
import { mapOptions } from '../utils'
|
14
15
|
|
15
|
-
interface
|
16
|
-
value
|
17
|
-
|
18
|
-
|
16
|
+
export interface RadioOption
|
17
|
+
extends Omit<RadioProps, 'value' | 'label'>,
|
18
|
+
FieldOption {}
|
19
|
+
|
20
|
+
export type RadioOptions = FieldOptions<RadioOption>
|
19
21
|
|
20
22
|
interface RadioInputOptions {
|
21
|
-
options:
|
23
|
+
options: RadioOptions
|
22
24
|
spacing?: SystemProps['margin']
|
23
25
|
direction?: StackDirection
|
24
26
|
}
|
@@ -28,9 +30,11 @@ export interface RadioInputProps
|
|
28
30
|
RadioInputOptions {}
|
29
31
|
|
30
32
|
export const RadioInput = forwardRef<RadioInputProps, 'div'>(
|
31
|
-
({ options, spacing, direction, ...props }, ref) => {
|
33
|
+
({ options: optionsProp, spacing, direction, ...props }, ref) => {
|
32
34
|
const { onBlur, onChange, ...groupProps } = props
|
33
35
|
|
36
|
+
const options = mapOptions(optionsProp)
|
37
|
+
|
34
38
|
return (
|
35
39
|
<RadioGroup onChange={onChange} {...groupProps}>
|
36
40
|
<Stack spacing={spacing} direction={direction}>
|
@@ -53,6 +57,4 @@ export const RadioInput = forwardRef<RadioInputProps, 'div'>(
|
|
53
57
|
}
|
54
58
|
)
|
55
59
|
|
56
|
-
|
57
|
-
RadioInput.displayName = 'RadioInput'
|
58
|
-
}
|
60
|
+
RadioInput.displayName = 'RadioInput'
|
@@ -5,7 +5,6 @@ import {
|
|
5
5
|
Select as ChakraSelect,
|
6
6
|
SelectProps as ChakraSelectProps,
|
7
7
|
} from '@chakra-ui/react'
|
8
|
-
import { __DEV__ } from '@chakra-ui/utils'
|
9
8
|
|
10
9
|
interface Option {
|
11
10
|
value: string
|
@@ -37,6 +36,4 @@ export const NativeSelect = forwardRef<NativeSelectProps, 'select'>(
|
|
37
36
|
}
|
38
37
|
)
|
39
38
|
|
40
|
-
|
41
|
-
NativeSelect.displayName = 'NativeSelect'
|
42
|
-
}
|
39
|
+
NativeSelect.displayName = 'NativeSelect'
|