@sakura-ui/sakura-ui 0.0.15 → 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.
Files changed (107) hide show
  1. package/README.md +8 -7
  2. package/package.json +3 -3
  3. package/packages/{react → core}/package.json +3 -3
  4. package/packages/{react → core}/src/components/Button.tsx +2 -2
  5. package/packages/{react → core}/src/components/Card.tsx +2 -2
  6. package/packages/{react → core}/src/components/Code.tsx +2 -2
  7. package/packages/{react → core}/src/components/Heading.tsx +18 -18
  8. package/packages/{react → core}/src/components/Icon.tsx +2 -2
  9. package/packages/{react → core}/src/components/IconButton.tsx +2 -2
  10. package/packages/{react → core}/src/components/InfoCard.tsx +4 -4
  11. package/packages/{react → core}/src/components/Link.tsx +6 -6
  12. package/packages/{react → core}/src/components/List.tsx +4 -4
  13. package/packages/{react → core}/src/components/Pre.tsx +2 -2
  14. package/packages/{react → core}/src/components/Table.tsx +14 -14
  15. package/packages/core/tsconfig.json +11 -0
  16. package/packages/forms/coverage/clover.xml +209 -0
  17. package/packages/forms/coverage/coverage-final.json +18 -0
  18. package/packages/forms/coverage/lcov-report/base.css +224 -0
  19. package/packages/forms/coverage/lcov-report/block-navigation.js +87 -0
  20. package/packages/forms/coverage/lcov-report/favicon.png +0 -0
  21. package/packages/forms/coverage/lcov-report/index.html +161 -0
  22. package/packages/forms/coverage/lcov-report/prettify.css +1 -0
  23. package/packages/forms/coverage/lcov-report/prettify.js +2 -0
  24. package/packages/forms/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  25. package/packages/forms/coverage/lcov-report/sorter.js +196 -0
  26. package/packages/forms/coverage/lcov-report/src/components/Checkbox.tsx.html +295 -0
  27. package/packages/forms/coverage/lcov-report/src/components/FieldsetControl.tsx.html +295 -0
  28. package/packages/forms/coverage/lcov-report/src/components/LabelControl.tsx.html +289 -0
  29. package/packages/forms/coverage/lcov-report/src/components/Radio.tsx.html +262 -0
  30. package/packages/forms/coverage/lcov-report/src/components/Select.tsx.html +253 -0
  31. package/packages/forms/coverage/lcov-report/src/components/Text.tsx.html +217 -0
  32. package/packages/forms/coverage/lcov-report/src/components/Textarea.tsx.html +226 -0
  33. package/packages/forms/coverage/lcov-report/src/components/context.ts.html +133 -0
  34. package/packages/forms/coverage/lcov-report/src/components/controlled/CheckboxGroup.tsx.html +244 -0
  35. package/packages/forms/coverage/lcov-report/src/components/controlled/RadioGroup.tsx.html +265 -0
  36. package/packages/forms/coverage/lcov-report/src/components/controlled/SelectControl.tsx.html +205 -0
  37. package/packages/forms/coverage/lcov-report/src/components/controlled/TextControl.tsx.html +202 -0
  38. package/packages/forms/coverage/lcov-report/src/components/controlled/TextareaControl.tsx.html +205 -0
  39. package/packages/forms/coverage/lcov-report/src/components/controlled/index.html +191 -0
  40. package/packages/forms/coverage/lcov-report/src/components/controlled/index.ts.html +100 -0
  41. package/packages/forms/coverage/lcov-report/src/components/index.html +236 -0
  42. package/packages/forms/coverage/lcov-report/src/components/index.ts.html +106 -0
  43. package/packages/forms/coverage/lcov-report/src/index.html +116 -0
  44. package/packages/forms/coverage/lcov-report/src/index.ts.html +136 -0
  45. package/packages/forms/coverage/lcov-report/src/utils/index.html +116 -0
  46. package/packages/forms/coverage/lcov-report/src/utils/index.ts.html +88 -0
  47. package/packages/forms/coverage/lcov.info +426 -0
  48. package/packages/forms/dist/index.cjs.js +24 -27
  49. package/packages/forms/dist/index.cjs.js.map +1 -1
  50. package/packages/forms/dist/index.es.js +605 -378
  51. package/packages/forms/dist/index.es.js.map +1 -1
  52. package/packages/forms/jest.config.ts +14 -0
  53. package/packages/forms/node_modules/.bin/ts-jest +2 -2
  54. package/packages/forms/package.json +6 -1
  55. package/packages/forms/src/components/Checkbox.tsx +31 -13
  56. package/packages/forms/src/components/FieldsetControl.tsx +70 -0
  57. package/packages/forms/src/components/LabelControl.tsx +65 -0
  58. package/packages/forms/src/components/Radio.tsx +24 -7
  59. package/packages/forms/src/components/Select.tsx +24 -25
  60. package/packages/forms/src/components/Text.tsx +15 -21
  61. package/packages/forms/src/components/Textarea.tsx +19 -20
  62. package/packages/forms/src/components/context.ts +16 -0
  63. package/packages/forms/src/components/controlled/CheckboxGroup.tsx +53 -0
  64. package/packages/forms/src/components/controlled/RadioGroup.tsx +60 -0
  65. package/packages/forms/src/components/controlled/SelectControl.tsx +40 -0
  66. package/packages/forms/src/components/controlled/TextControl.tsx +39 -0
  67. package/packages/forms/src/components/controlled/TextareaControl.tsx +40 -0
  68. package/packages/forms/src/components/controlled/index.ts +5 -0
  69. package/packages/forms/src/components/index.ts +2 -2
  70. package/packages/forms/src/index.ts +11 -3
  71. package/packages/forms/tests/FieldsetControl.test.tsx +54 -0
  72. package/packages/forms/tests/LabelControl.test.tsx +50 -0
  73. package/packages/forms/tests/Radio.test.tsx +99 -0
  74. package/packages/forms/tests/Text.test.tsx +96 -0
  75. package/packages/forms/tsconfig.json +1 -17
  76. package/packages/forms/dist/components/Checkbox.d.ts +0 -5
  77. package/packages/forms/dist/components/Checkbox.d.ts.map +0 -1
  78. package/packages/forms/dist/components/CheckboxGroup.d.ts +0 -9
  79. package/packages/forms/dist/components/CheckboxGroup.d.ts.map +0 -1
  80. package/packages/forms/dist/components/InputItem.d.ts +0 -5
  81. package/packages/forms/dist/components/InputItem.d.ts.map +0 -1
  82. package/packages/forms/dist/components/Radio.d.ts +0 -5
  83. package/packages/forms/dist/components/Radio.d.ts.map +0 -1
  84. package/packages/forms/dist/components/RadioGroup.d.ts +0 -9
  85. package/packages/forms/dist/components/RadioGroup.d.ts.map +0 -1
  86. package/packages/forms/dist/components/Select.d.ts +0 -6
  87. package/packages/forms/dist/components/Select.d.ts.map +0 -1
  88. package/packages/forms/dist/components/Text.d.ts +0 -6
  89. package/packages/forms/dist/components/Text.d.ts.map +0 -1
  90. package/packages/forms/dist/components/Textarea.d.ts +0 -6
  91. package/packages/forms/dist/components/Textarea.d.ts.map +0 -1
  92. package/packages/forms/dist/components/index.d.ts +0 -8
  93. package/packages/forms/dist/components/index.d.ts.map +0 -1
  94. package/packages/forms/dist/index.d.ts +0 -2
  95. package/packages/forms/dist/index.d.ts.map +0 -1
  96. package/packages/forms/dist/utils/index.d.ts +0 -2
  97. package/packages/forms/dist/utils/index.d.ts.map +0 -1
  98. package/packages/forms/src/components/CheckboxGroup.tsx +0 -35
  99. package/packages/forms/src/components/RadioGroup.tsx +0 -36
  100. package/packages/forms/src/vite-env.d.ts +0 -1
  101. package/packages/react/tsconfig.json +0 -27
  102. /package/packages/{react → core}/src/components/index.ts +0 -0
  103. /package/packages/{react → core}/src/index.ts +0 -0
  104. /package/packages/{react → core}/src/utils/index.ts +0 -0
  105. /package/packages/{react → core}/tsconfig.node.json +0 -0
  106. /package/packages/{react → core}/vite.config.ts +0 -0
  107. /package/packages/forms/src/components/{InputItem.ts → controlled/InputItem.ts} +0 -0
@@ -0,0 +1,70 @@
1
+ import React from 'react'
2
+ import { cx } from '../utils'
3
+ import { ControllerContext } from './context'
4
+
5
+ export interface FieldsetControlProps
6
+ extends React.ComponentPropsWithoutRef<'fieldset'> {
7
+ labelText: string
8
+ helperText?: string
9
+ errorMessage?: string
10
+ isInvalid?: boolean
11
+ isRequired?: boolean
12
+ direction?: 'flex-col' | 'flex-row'
13
+ }
14
+
15
+ export const FieldsetControl = React.forwardRef<
16
+ HTMLFieldSetElement,
17
+ FieldsetControlProps
18
+ >((props, ref) => {
19
+ const id = React.useId()
20
+ const {
21
+ labelText,
22
+ className,
23
+ helperText,
24
+ errorMessage,
25
+ isInvalid,
26
+ isRequired,
27
+ direction,
28
+ children,
29
+ ...restProps
30
+ } = props
31
+
32
+ const groupName = restProps.name ?? `group-${id}`
33
+
34
+ const context = {
35
+ groupName: groupName,
36
+ helperTextId: `helper-text-${id}`,
37
+ errorMessageId: `error-message-${id}`,
38
+ isInvalid: isInvalid ?? false,
39
+ isRequired: isRequired ?? false
40
+ }
41
+
42
+ const styleDirection = direction ?? 'flex-col'
43
+
44
+ return (
45
+ <ControllerContext.Provider value={context}>
46
+ <fieldset className={cx('mb-4', className)} ref={ref} {...restProps}>
47
+ <legend>
48
+ <p className={cx('block mb-2', isInvalid && 'text-sun-800')}>
49
+ {labelText}
50
+ {isRequired && <span className="text-sun-800">&nbsp;*</span>}
51
+ </p>
52
+ </legend>
53
+ <div className={cx('inline-flex', styleDirection)}>{children}</div>
54
+ {helperText && (
55
+ <p id={context.helperTextId} className="text-sm text-sumi-700 mt-2">
56
+ {helperText}
57
+ </p>
58
+ )}
59
+ {isInvalid && (
60
+ <p
61
+ id={context.errorMessageId}
62
+ className={cx('text-sm text-sun-800', helperText ? 'mt-1' : 'mt-2')}
63
+ >
64
+ {errorMessage}
65
+ </p>
66
+ )}
67
+ </fieldset>
68
+ </ControllerContext.Provider>
69
+ )
70
+ })
@@ -0,0 +1,65 @@
1
+ import React from 'react'
2
+ import { cx } from '../utils'
3
+ import { ControllerContext } from './context'
4
+
5
+ export interface LabelControlProps
6
+ extends React.ComponentPropsWithoutRef<'div'> {
7
+ labelText: string
8
+ helperText?: string
9
+ errorMessage?: string
10
+ isInvalid?: boolean
11
+ isRequired?: boolean
12
+ }
13
+
14
+ export const LabelControl = React.forwardRef<HTMLDivElement, LabelControlProps>(
15
+ (props, ref) => {
16
+ const id = React.useId()
17
+ const {
18
+ labelText,
19
+ className,
20
+ helperText,
21
+ errorMessage,
22
+ isInvalid,
23
+ isRequired,
24
+ children,
25
+ ...restProps
26
+ } = props
27
+
28
+ const context = {
29
+ helperTextId: `helper-text-${id}`,
30
+ errorMessageId: `error-message-${id}`,
31
+ isInvalid: isInvalid ?? false,
32
+ isRequired: isRequired ?? false
33
+ }
34
+
35
+ return (
36
+ <ControllerContext.Provider value={context}>
37
+ <div className={cx('mb-4', className)} ref={ref} {...restProps}>
38
+ <label>
39
+ <span className={cx('block mb-2', isInvalid && 'text-sun-800')}>
40
+ {labelText}
41
+ {isRequired && <span className="text-sun-800">&nbsp;*</span>}
42
+ </span>
43
+ {children}
44
+ </label>
45
+ {helperText && (
46
+ <p id={context.helperTextId} className="text-sm text-sumi-700 mt-2">
47
+ {helperText}
48
+ </p>
49
+ )}
50
+ {isInvalid && (
51
+ <p
52
+ id={context.errorMessageId}
53
+ className={cx(
54
+ 'text-sm text-sun-800',
55
+ helperText ? 'mt-1' : 'mt-2'
56
+ )}
57
+ >
58
+ {errorMessage}
59
+ </p>
60
+ )}
61
+ </div>
62
+ </ControllerContext.Provider>
63
+ )
64
+ }
65
+ )
@@ -1,17 +1,25 @@
1
1
  import React from 'react'
2
2
  import { cx } from '../utils'
3
+ import { ControllerContext } from './context'
3
4
 
4
- export interface Props extends React.ComponentProps<'input'> {}
5
+ export interface Props extends React.ComponentPropsWithoutRef<'input'> {}
5
6
 
6
7
  export const Radio = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
7
8
  const { className, children, ...newProps } = props
9
+ const ctx = React.useContext(ControllerContext)
10
+ if (ctx.isRequired) {
11
+ newProps.required = true
12
+ }
13
+ if (ctx.groupName) {
14
+ newProps.name = ctx.groupName
15
+ }
8
16
 
9
17
  const style = `
10
- flex
11
- items-center
18
+ inline-block
12
19
  text-sm
13
20
  cursor-pointer
14
21
  py-2
22
+ mr-4
15
23
  `
16
24
  const styleInput = `
17
25
  hidden
@@ -19,7 +27,6 @@ export const Radio = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
19
27
  `
20
28
 
21
29
  const styleRadio = `
22
- inline-block
23
30
  bg-clip-content
24
31
  w-6 h-6
25
32
  ml-1
@@ -34,9 +41,19 @@ export const Radio = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
34
41
  `
35
42
  return (
36
43
  <label htmlFor={newProps.id} className={cx(style, className)}>
37
- <input className={styleInput} type="radio" {...newProps} ref={ref} />
38
- <span className={styleRadio}></span>
39
- {children}
44
+ <span className="flex items-center">
45
+ <input
46
+ className={styleInput}
47
+ type="radio"
48
+ aria-describedby={ctx.helperTextId}
49
+ aria-errormessage={ctx.errorMessageId}
50
+ aria-invalid={ctx.isInvalid ?? false}
51
+ {...newProps}
52
+ ref={ref}
53
+ />
54
+ <span className={styleRadio}></span>
55
+ {children}
56
+ </span>
40
57
  </label>
41
58
  )
42
59
  })
@@ -1,22 +1,27 @@
1
1
  import React from 'react'
2
2
  import { cx } from '../utils'
3
+ import { ControllerContext } from './context'
3
4
 
4
- export interface SelectProps extends React.ComponentPropsWithoutRef<'select'> {
5
- label?: string
6
- }
5
+ export interface SelectProps extends React.ComponentPropsWithoutRef<'select'> {}
7
6
 
8
7
  export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
9
8
  (props, ref) => {
10
- const { label, className, children, ...newProps } = props
9
+ const { className, children, ...newProps } = props
10
+ const ctx = React.useContext(ControllerContext)
11
+ if (ctx.isRequired) {
12
+ newProps.required = true
13
+ }
14
+
15
+ const invalidStyle = ctx.isInvalid ? 'border-sun-800' : 'border-sumi-900'
11
16
 
12
17
  const style = `
18
+ cursor-pointer
13
19
  appearance-none
14
20
  text-base
15
21
  w-full
16
22
  bg-white-100
17
23
  border
18
24
  border-solid
19
- border-sumi-900
20
25
  py-4 px-4 pr-8
21
26
  rounded-[8px]
22
27
  focus:outline
@@ -24,12 +29,19 @@ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
24
29
  focus:outline-wood-500
25
30
  `
26
31
 
27
- const elem = (
28
- <div className="inline-block relative">
29
- <select className={cx(style, props.className)} {...newProps} ref={ref}>
30
- {props.children}
32
+ return (
33
+ <span className="inline-block relative">
34
+ <select
35
+ className={cx(style, invalidStyle, props.className)}
36
+ aria-describedby={ctx.helperTextId}
37
+ aria-errormessage={ctx.errorMessageId}
38
+ aria-invalid={ctx.isInvalid ?? false}
39
+ {...newProps}
40
+ ref={ref}
41
+ >
42
+ {children}
31
43
  </select>
32
- <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2">
44
+ <span className="flex items-center absolute inset-y-0 right-0 px-2 pointer-events-none">
33
45
  <svg
34
46
  xmlns="http://www.w3.org/2000/svg"
35
47
  className="fill-sumi-900"
@@ -38,21 +50,8 @@ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
38
50
  >
39
51
  <path d="M12 15.05 6.35 9.4 7.4 8.35l4.6 4.6 4.6-4.6 1.05 1.05Z" />
40
52
  </svg>
41
- </div>
42
- </div>
43
- )
44
-
45
- return (
46
- <>
47
- {label ? (
48
- <label>
49
- <span className="block mb-2">{label}</span>
50
- {elem}
51
- </label>
52
- ) : (
53
- elem
54
- )}
55
- </>
53
+ </span>
54
+ </span>
56
55
  )
57
56
  }
58
57
  )
@@ -1,20 +1,24 @@
1
1
  import React from 'react'
2
2
  import { cx } from '../utils'
3
+ import { ControllerContext } from './context'
3
4
 
4
- export interface TextProps extends React.ComponentPropsWithoutRef<'input'> {
5
- label?: string
6
- }
5
+ export interface TextProps extends React.ComponentPropsWithoutRef<'input'> {}
7
6
 
8
7
  export const Text = React.forwardRef<HTMLInputElement, TextProps>(
9
8
  (props, ref) => {
10
- const { label, className, ...newProps } = props
9
+ const { className, ...restProps } = props
10
+ const ctx = React.useContext(ControllerContext)
11
+ if (ctx.isRequired) {
12
+ restProps.required = true
13
+ }
14
+
15
+ const invalidStyle = ctx.isInvalid ? 'border-sun-800' : 'border-sumi-900'
11
16
 
12
17
  const style = `
13
18
  p-4
14
19
  rounded-lg
15
20
  border
16
21
  border-solid
17
- border-sumi-900
18
22
  focus:outline
19
23
  focus:outline-2
20
24
  focus:outline-wood-500
@@ -25,26 +29,16 @@ export const Text = React.forwardRef<HTMLInputElement, TextProps>(
25
29
  disabled:border-sumi-500
26
30
  `
27
31
 
28
- const elem = (
32
+ return (
29
33
  <input
30
34
  type="text"
31
- className={cx(style, className)}
32
- {...newProps}
35
+ className={cx(style, invalidStyle, className)}
36
+ aria-describedby={ctx.helperTextId}
37
+ aria-errormessage={ctx.errorMessageId}
38
+ aria-invalid={ctx.isInvalid ?? false}
39
+ {...restProps}
33
40
  ref={ref}
34
41
  />
35
42
  )
36
-
37
- return (
38
- <>
39
- {label ? (
40
- <label>
41
- <div className="mb-2">{label}</div>
42
- {elem}
43
- </label>
44
- ) : (
45
- elem
46
- )}
47
- </>
48
- )
49
43
  }
50
44
  )
@@ -1,21 +1,26 @@
1
1
  import React from 'react'
2
2
  import { cx } from '../utils'
3
+ import { ControllerContext } from './context'
3
4
 
4
5
  export interface TextareaProps
5
- extends React.ComponentPropsWithoutRef<'textarea'> {
6
- label?: string
7
- }
6
+ extends React.ComponentPropsWithoutRef<'textarea'> {}
8
7
 
9
8
  export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
10
9
  (props, ref) => {
11
- const { label, className, children, ...newProps } = props
10
+ const { className, children, ...restProps } = props
11
+
12
+ const ctx = React.useContext(ControllerContext)
13
+ if (ctx.isRequired) {
14
+ restProps.required = true
15
+ }
16
+
17
+ const invalidStyle = ctx.isInvalid ? 'border-sun-800' : 'border-sumi-900'
12
18
 
13
19
  const style = `
14
20
  p-4
15
21
  rounded-lg
16
22
  border
17
23
  border-solid
18
- border-sumi-900
19
24
  focus:outline
20
25
  focus:outline-2
21
26
  focus:outline-wood-500
@@ -26,23 +31,17 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
26
31
  disabled:border-sumi-500
27
32
  `
28
33
 
29
- const elem = (
30
- <textarea className={cx(style, className)} {...newProps} ref={ref}>
34
+ return (
35
+ <textarea
36
+ className={cx(style, invalidStyle, className)}
37
+ aria-describedby={ctx.helperTextId}
38
+ aria-errormessage={ctx.errorMessageId}
39
+ aria-invalid={ctx.isInvalid ?? false}
40
+ {...restProps}
41
+ ref={ref}
42
+ >
31
43
  {children}
32
44
  </textarea>
33
45
  )
34
-
35
- return (
36
- <>
37
- {label ? (
38
- <label>
39
- <div className="mb-2">{label}</div>
40
- {elem}
41
- </label>
42
- ) : (
43
- elem
44
- )}
45
- </>
46
- )
47
46
  }
48
47
  )
@@ -0,0 +1,16 @@
1
+ import React from 'react'
2
+
3
+ export interface ControllerContextType {
4
+ groupName?: string
5
+ helperTextId: string
6
+ errorMessageId: string
7
+ isInvalid: boolean
8
+ isRequired?: boolean
9
+ }
10
+
11
+ export const ControllerContext = React.createContext<ControllerContextType>({
12
+ helperTextId: '',
13
+ errorMessageId: '',
14
+ isInvalid: false,
15
+ isRequired: false
16
+ })
@@ -0,0 +1,53 @@
1
+ import React from 'react'
2
+ import { Checkbox } from '../Checkbox'
3
+ import { FieldsetControl } from '../FieldsetControl'
4
+ import { InputItem } from './InputItem'
5
+
6
+ export interface CheckboxGroupProps
7
+ extends Omit<React.ComponentPropsWithoutRef<'fieldset'>, 'onChange'> {
8
+ items: InputItem[]
9
+ onChange: React.ChangeEventHandler<HTMLInputElement>
10
+ labelText: string
11
+ helperText?: string
12
+ errorMessage?: string
13
+ isInvalid?: boolean
14
+ isRequired?: boolean
15
+ }
16
+
17
+ export const CheckboxGroup = React.forwardRef<
18
+ HTMLFieldSetElement,
19
+ CheckboxGroupProps
20
+ >((props, ref) => {
21
+ const {
22
+ items,
23
+ onChange,
24
+ className,
25
+ labelText,
26
+ helperText,
27
+ errorMessage,
28
+ isInvalid,
29
+ isRequired,
30
+ ...restProps
31
+ } = props
32
+
33
+ return (
34
+ <FieldsetControl
35
+ className={className}
36
+ labelText={labelText}
37
+ helperText={helperText}
38
+ errorMessage={errorMessage}
39
+ isInvalid={isInvalid}
40
+ isRequired={isRequired}
41
+ ref={ref}
42
+ {...restProps}
43
+ >
44
+ {items.map(({ label, value }, index) => {
45
+ return (
46
+ <Checkbox key={index} value={value} onChange={onChange}>
47
+ {label}
48
+ </Checkbox>
49
+ )
50
+ })}
51
+ </FieldsetControl>
52
+ )
53
+ })
@@ -0,0 +1,60 @@
1
+ import React from 'react'
2
+ import { Radio } from '../Radio'
3
+ import { FieldsetControl } from '../FieldsetControl'
4
+ import { InputItem } from './InputItem'
5
+
6
+ export interface RadioGroupProps
7
+ extends Omit<React.ComponentPropsWithoutRef<'fieldset'>, 'onChange'> {
8
+ items: InputItem[]
9
+ onChange: React.ChangeEventHandler<HTMLInputElement>
10
+ labelText: string
11
+ helperText?: string
12
+ errorMessage?: string
13
+ isInvalid?: boolean
14
+ isRequired?: boolean
15
+ defaultValue?: string
16
+ }
17
+
18
+ export const RadioGroup = React.forwardRef<
19
+ HTMLFieldSetElement,
20
+ RadioGroupProps
21
+ >((props, ref) => {
22
+ const {
23
+ items,
24
+ onChange,
25
+ className,
26
+ labelText,
27
+ helperText,
28
+ errorMessage,
29
+ isInvalid,
30
+ isRequired,
31
+ defaultValue,
32
+ ...restProps
33
+ } = props
34
+
35
+ return (
36
+ <FieldsetControl
37
+ className={className}
38
+ labelText={labelText}
39
+ helperText={helperText}
40
+ errorMessage={errorMessage}
41
+ isInvalid={isInvalid}
42
+ isRequired={isRequired}
43
+ ref={ref}
44
+ {...restProps}
45
+ >
46
+ {items.map(({ label, value }, index) => {
47
+ return (
48
+ <Radio
49
+ key={index}
50
+ value={value}
51
+ onChange={onChange}
52
+ defaultChecked={defaultValue === value}
53
+ >
54
+ {label}
55
+ </Radio>
56
+ )
57
+ })}
58
+ </FieldsetControl>
59
+ )
60
+ })
@@ -0,0 +1,40 @@
1
+ import React from 'react'
2
+ import { LabelControl } from '../LabelControl'
3
+ import { Select } from '../Select'
4
+
5
+ export interface SelectControlProps
6
+ extends React.ComponentPropsWithoutRef<'select'> {
7
+ labelText: string
8
+ helperText?: string
9
+ errorMessage?: string
10
+ isInvalid?: boolean
11
+ isRequired?: boolean
12
+ }
13
+
14
+ export const SelectControl = React.forwardRef<
15
+ HTMLSelectElement,
16
+ SelectControlProps
17
+ >((props, ref) => {
18
+ const {
19
+ className,
20
+ labelText,
21
+ helperText,
22
+ errorMessage,
23
+ isInvalid,
24
+ isRequired,
25
+ ...restProps
26
+ } = props
27
+
28
+ return (
29
+ <LabelControl
30
+ className={className}
31
+ labelText={labelText}
32
+ helperText={helperText}
33
+ errorMessage={errorMessage}
34
+ isInvalid={isInvalid}
35
+ isRequired={isRequired}
36
+ >
37
+ <Select ref={ref} {...restProps} />
38
+ </LabelControl>
39
+ )
40
+ })
@@ -0,0 +1,39 @@
1
+ import React from 'react'
2
+ import { LabelControl } from '../LabelControl'
3
+ import { Text } from '../Text'
4
+
5
+ export interface TextControlProps
6
+ extends React.ComponentPropsWithoutRef<'input'> {
7
+ labelText: string
8
+ helperText?: string
9
+ errorMessage?: string
10
+ isInvalid?: boolean
11
+ isRequired?: boolean
12
+ }
13
+
14
+ export const TextControl = React.forwardRef<HTMLInputElement, TextControlProps>(
15
+ (props, ref) => {
16
+ const {
17
+ className,
18
+ labelText,
19
+ helperText,
20
+ errorMessage,
21
+ isInvalid,
22
+ isRequired,
23
+ ...restProps
24
+ } = props
25
+
26
+ return (
27
+ <LabelControl
28
+ className={className}
29
+ labelText={labelText}
30
+ helperText={helperText}
31
+ errorMessage={errorMessage}
32
+ isInvalid={isInvalid}
33
+ isRequired={isRequired}
34
+ >
35
+ <Text ref={ref} {...restProps} />
36
+ </LabelControl>
37
+ )
38
+ }
39
+ )
@@ -0,0 +1,40 @@
1
+ import React from 'react'
2
+ import { LabelControl } from '../LabelControl'
3
+ import { Textarea } from '../Textarea'
4
+
5
+ export interface TextareaControlProps
6
+ extends React.ComponentPropsWithoutRef<'textarea'> {
7
+ labelText: string
8
+ helperText?: string
9
+ errorMessage?: string
10
+ isInvalid?: boolean
11
+ isRequired?: boolean
12
+ }
13
+
14
+ export const TextareaControl = React.forwardRef<
15
+ HTMLTextAreaElement,
16
+ TextareaControlProps
17
+ >((props, ref) => {
18
+ const {
19
+ className,
20
+ labelText,
21
+ helperText,
22
+ errorMessage,
23
+ isInvalid,
24
+ isRequired,
25
+ ...restProps
26
+ } = props
27
+
28
+ return (
29
+ <LabelControl
30
+ className={className}
31
+ labelText={labelText}
32
+ helperText={helperText}
33
+ errorMessage={errorMessage}
34
+ isInvalid={isInvalid}
35
+ isRequired={isRequired}
36
+ >
37
+ <Textarea ref={ref} {...restProps} />
38
+ </LabelControl>
39
+ )
40
+ })
@@ -0,0 +1,5 @@
1
+ export { CheckboxGroup } from './CheckboxGroup'
2
+ export { RadioGroup } from './RadioGroup'
3
+ export { SelectControl } from './SelectControl'
4
+ export { TextControl } from './TextControl'
5
+ export { TextareaControl } from './TextareaControl'
@@ -1,7 +1,7 @@
1
1
  export { Checkbox } from './Checkbox'
2
- export { CheckboxGroup } from './CheckboxGroup'
3
2
  export { Radio } from './Radio'
4
- export { RadioGroup } from './RadioGroup'
5
3
  export { Select } from './Select'
6
4
  export { Text } from './Text'
7
5
  export { Textarea } from './Textarea'
6
+ export { LabelControl } from './LabelControl'
7
+ export { FieldsetControl } from './FieldsetControl'
@@ -1,9 +1,17 @@
1
1
  export {
2
2
  Checkbox,
3
- CheckboxGroup,
4
3
  Radio,
5
- RadioGroup,
6
4
  Select,
7
5
  Text,
8
- Textarea
6
+ Textarea,
7
+ LabelControl,
8
+ FieldsetControl
9
9
  } from './components'
10
+
11
+ export {
12
+ CheckboxGroup,
13
+ RadioGroup,
14
+ SelectControl,
15
+ TextControl,
16
+ TextareaControl
17
+ } from './components/controlled'