@saas-ui/forms 2.3.12 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,7 +19,7 @@ export { yupResolver } from '@hookform/resolvers/yup';
19
19
 
20
20
  interface NumberInputOptions {
21
21
  /**
22
- * Hide the stepper.
22
+ * Hide the stepper. This will be true when `rightAddon` is provided.
23
23
  */
24
24
  hideStepper?: boolean;
25
25
  /**
@@ -38,6 +38,14 @@ interface NumberInputOptions {
38
38
  * Props to pass to the NumberInputField component.
39
39
  */
40
40
  fieldProps?: NumberInputFieldProps$1;
41
+ /**
42
+ * Either `InputLeftAddon` or `InputLeftElement`
43
+ */
44
+ leftAddon?: React$1.ReactNode;
45
+ /**
46
+ * Either `InputRightAddon` or `InputRightElement`
47
+ */
48
+ rightAddon?: React$1.ReactNode;
41
49
  }
42
50
  interface NumberInputProps extends NumberInputProps$1, NumberInputOptions {
43
51
  }
@@ -19,7 +19,7 @@ export { zodResolver } from '@hookform/resolvers/zod';
19
19
 
20
20
  interface NumberInputOptions {
21
21
  /**
22
- * Hide the stepper.
22
+ * Hide the stepper. This will be true when `rightAddon` is provided.
23
23
  */
24
24
  hideStepper?: boolean;
25
25
  /**
@@ -38,6 +38,14 @@ interface NumberInputOptions {
38
38
  * Props to pass to the NumberInputField component.
39
39
  */
40
40
  fieldProps?: NumberInputFieldProps$1;
41
+ /**
42
+ * Either `InputLeftAddon` or `InputLeftElement`
43
+ */
44
+ leftAddon?: React$1.ReactNode;
45
+ /**
46
+ * Either `InputRightAddon` or `InputRightElement`
47
+ */
48
+ rightAddon?: React$1.ReactNode;
41
49
  }
42
50
  interface NumberInputProps extends NumberInputProps$1, NumberInputOptions {
43
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saas-ui/forms",
3
- "version": "2.3.12",
3
+ "version": "2.4.0",
4
4
  "description": "Fully functional forms for Chakra UI.",
5
5
  "source": "src/index.ts",
6
6
  "exports": {
@@ -104,7 +104,7 @@
104
104
  "@chakra-ui/react-utils": "^2.0.12",
105
105
  "@chakra-ui/utils": "^2.0.15",
106
106
  "@hookform/resolvers": "^3.3.4",
107
- "@saas-ui/core": "2.3.6",
107
+ "@saas-ui/core": "2.4.0",
108
108
  "react-hook-form": "^7.50.1"
109
109
  },
110
110
  "peerDependencies": {
package/src/auto-form.tsx CHANGED
@@ -27,8 +27,11 @@ interface AutoFormOptions {
27
27
 
28
28
  export interface AutoFormProps<
29
29
  TFieldValues extends FieldValues,
30
- TContext extends object = object
31
- > extends Omit<FormProps<TFieldValues, TContext>, 'schema' | 'children'>,
30
+ TContext extends object = object,
31
+ > extends Omit<
32
+ FormProps<TFieldValues, TContext>,
33
+ 'schema' | 'children' | 'fieldResolver'
34
+ >,
32
35
  AutoFormOptions {
33
36
  children?: React.ReactNode
34
37
  }
@@ -40,7 +43,7 @@ export interface AutoFormProps<
40
43
  export const AutoForm = forwardRef(
41
44
  <
42
45
  TFieldValues extends FieldValues = FieldValues,
43
- TContext extends object = object
46
+ TContext extends object = object,
44
47
  >(
45
48
  props: AutoFormProps<TFieldValues, TContext>,
46
49
  ref: React.ForwardedRef<HTMLFormElement>
@@ -31,9 +31,11 @@ import {
31
31
  NativeSelectProps,
32
32
  SelectButtonProps,
33
33
  SelectListProps,
34
+ SelectOption,
34
35
  } from './select'
35
36
 
36
37
  import { createField } from './create-field'
38
+ import { FieldOption, FieldOptions } from './types'
37
39
 
38
40
  export interface InputFieldProps extends InputProps {
39
41
  type?: string
@@ -95,6 +97,7 @@ export interface SelectFieldProps extends SelectProps {
95
97
  export const SelectField = createField<SelectFieldProps>(
96
98
  forwardRef((props, ref) => {
97
99
  const { buttonProps, listProps, ...rest } = props
100
+
98
101
  return (
99
102
  <Select ref={ref} {...rest}>
100
103
  <SelectButton {...buttonProps} />
@@ -1,6 +1,9 @@
1
- import { BaseFieldProps } from './types'
1
+ import { BaseFieldProps, ValueOf } from './types'
2
2
 
3
3
  import { get } from '@chakra-ui/utils'
4
+ import { ArrayFieldProps } from './array-field'
5
+ import { ObjectFieldProps } from './object-field'
6
+ import { DefaultFields } from './default-fields'
4
7
 
5
8
  export type FieldResolver = {
6
9
  getFields(): BaseFieldProps[]
@@ -9,16 +12,32 @@ export type FieldResolver = {
9
12
 
10
13
  export type GetFieldResolver<TSchema = any> = (schema: TSchema) => FieldResolver
11
14
 
12
- interface SchemaField extends BaseFieldProps {
13
- items?: SchemaField[]
14
- properties?: Record<string, SchemaField>
15
- }
15
+ type FieldTypes<FieldDefs = DefaultFields> = ValueOf<{
16
+ [K in keyof FieldDefs]: FieldDefs[K] extends React.FC<infer Props>
17
+ ? { type?: K } & Omit<Props, 'name'>
18
+ : never
19
+ }>
20
+
21
+ type SchemaField<FieldDefs = DefaultFields> =
22
+ | FieldTypes<FieldDefs>
23
+ | (Omit<ObjectFieldProps, 'name' | 'children'> & {
24
+ type: 'object'
25
+ properties?: Record<string, SchemaField<FieldDefs>>
26
+ })
27
+ | (Omit<ArrayFieldProps, 'name' | 'children'> & {
28
+ type: 'array'
29
+ items?: SchemaField<FieldDefs>
30
+ })
16
31
 
17
- export type ObjectSchema = Record<string, SchemaField>
32
+ export type ObjectSchema<FieldDefs = DefaultFields> = Record<
33
+ string,
34
+ SchemaField<FieldDefs>
35
+ >
18
36
 
19
37
  const mapFields = (schema: ObjectSchema): BaseFieldProps[] =>
20
38
  schema &&
21
- Object.entries(schema).map(([name, { items, label, title, ...field }]) => {
39
+ Object.entries(schema).map(([name, props]) => {
40
+ const { items, label, title, ...field } = props as any
22
41
  return {
23
42
  ...field,
24
43
  name,
@@ -1,4 +1,10 @@
1
- import { Container } from '@chakra-ui/react'
1
+ import {
2
+ Container,
3
+ InputLeftAddon,
4
+ InputLeftElement,
5
+ InputRightAddon,
6
+ InputRightElement,
7
+ } from '@chakra-ui/react'
2
8
  import * as React from 'react'
3
9
  import { Story, Meta } from '@storybook/react'
4
10
 
@@ -6,6 +12,7 @@ import { NumberInput } from '.'
6
12
 
7
13
  export default {
8
14
  title: 'Components/Forms/NumberInput',
15
+ component: NumberInput,
9
16
  decorators: [
10
17
  (Story: any) => (
11
18
  <Container mt="40px">
@@ -15,25 +22,39 @@ export default {
15
22
  ],
16
23
  } as Meta
17
24
 
18
- const Template: Story = (args) => <NumberInput aria-label="Number" {...args} />
25
+ export const Basic = {}
19
26
 
20
- export const Basic = Template.bind({})
21
- Basic.args = {}
27
+ export const HideStepper = {
28
+ args: {
29
+ hideStepper: true,
30
+ },
31
+ }
22
32
 
23
- export const HideStepper = Template.bind({})
24
- HideStepper.args = {
25
- hideStepper: true,
33
+ export const MinMax = {
34
+ args: {
35
+ defaultValue: 5,
36
+ min: 0,
37
+ max: 10,
38
+ },
39
+ }
40
+ export const WithFormatter = {
41
+ args: {
42
+ format: (value: any) => `$${value}`, // use any currency formatter here
43
+ parse: (value: any) => value.replace('$', ''),
44
+ },
26
45
  }
27
46
 
28
- export const MinMax = Template.bind({})
29
- MinMax.args = {
30
- defaultValue: 5,
31
- min: 0,
32
- max: 10,
47
+ export const WithAddons = {
48
+ args: {
49
+ leftAddon: <InputLeftAddon>$</InputLeftAddon>,
50
+ rightAddon: <InputRightAddon>USD</InputRightAddon>,
51
+ hideStepper: true,
52
+ },
33
53
  }
34
54
 
35
- export const WithFormatter = Template.bind({})
36
- WithFormatter.args = {
37
- format: (value: any) => `$${value}`, // use any currency formatter here
38
- parse: (value: any) => value.replace('$', ''),
55
+ export const WithElements = {
56
+ args: {
57
+ leftAddon: <InputLeftElement>$</InputLeftElement>,
58
+ rightAddon: <InputRightElement>USD</InputRightElement>,
59
+ },
39
60
  }
@@ -9,13 +9,18 @@ import {
9
9
  NumberDecrementStepper,
10
10
  NumberInputProps as ChakraNumberInputProps,
11
11
  NumberInputFieldProps,
12
+ InputGroup,
13
+ InputLeftAddon,
14
+ InputRightAddon,
15
+ InputLeftElement,
16
+ InputRightElement,
12
17
  } from '@chakra-ui/react'
13
18
 
14
19
  import { ChevronDownIcon, ChevronUpIcon } from '@saas-ui/core'
15
20
 
16
21
  interface NumberInputOptions {
17
22
  /**
18
- * Hide the stepper.
23
+ * Hide the stepper. This will be true when `rightAddon` is provided.
19
24
  */
20
25
  hideStepper?: boolean
21
26
  /**
@@ -34,8 +39,22 @@ interface NumberInputOptions {
34
39
  * Props to pass to the NumberInputField component.
35
40
  */
36
41
  fieldProps?: NumberInputFieldProps
42
+ /**
43
+ * Either `InputLeftAddon` or `InputLeftElement`
44
+ */
45
+ leftAddon?: React.ReactNode
46
+ /**
47
+ * Either `InputRightAddon` or `InputRightElement`
48
+ */
49
+ rightAddon?: React.ReactNode
37
50
  }
38
51
 
52
+ const Input = forwardRef<NumberInputFieldProps, 'input'>((props, ref) => (
53
+ <NumberInputField ref={ref} {...props} />
54
+ ))
55
+ Input.displayName = 'NumberInputField'
56
+ Input.id = 'Input'
57
+
39
58
  export interface NumberInputProps
40
59
  extends ChakraNumberInputProps,
41
60
  NumberInputOptions {}
@@ -45,6 +64,8 @@ export const NumberInput = forwardRef<NumberInputProps, 'div'>((props, ref) => {
45
64
  hideStepper = false,
46
65
  incrementIcon = <ChevronUpIcon />,
47
66
  decrementIcon = <ChevronDownIcon />,
67
+ leftAddon,
68
+ rightAddon,
48
69
  placeholder,
49
70
  fieldProps: _fieldProps,
50
71
  ...rest
@@ -54,14 +75,17 @@ export const NumberInput = forwardRef<NumberInputProps, 'div'>((props, ref) => {
54
75
 
55
76
  return (
56
77
  <ChakraNumberInput {...rest} ref={ref}>
57
- <NumberInputField {...fieldProps} />
58
-
59
- {!hideStepper && (
78
+ <InputGroup>
79
+ {leftAddon}
80
+ <Input {...fieldProps} />
81
+ {rightAddon}
82
+ </InputGroup>
83
+ {!hideStepper && !rightAddon ? (
60
84
  <NumberInputStepper>
61
85
  <NumberIncrementStepper children={incrementIcon} />
62
86
  <NumberDecrementStepper children={decrementIcon} />
63
87
  </NumberInputStepper>
64
- )}
88
+ ) : null}
65
89
  </ChakraNumberInput>
66
90
  )
67
91
  })