@sakura-ui/sakura-ui 0.0.16 → 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/README.md +8 -7
- package/package.json +3 -3
- package/packages/{react → core}/package.json +3 -3
- package/packages/{react → core}/src/components/Button.tsx +2 -2
- package/packages/{react → core}/src/components/Card.tsx +2 -2
- package/packages/{react → core}/src/components/Code.tsx +2 -2
- package/packages/{react → core}/src/components/Heading.tsx +18 -18
- package/packages/{react → core}/src/components/Icon.tsx +2 -2
- package/packages/{react → core}/src/components/IconButton.tsx +2 -2
- package/packages/{react → core}/src/components/InfoCard.tsx +4 -4
- package/packages/{react → core}/src/components/Link.tsx +6 -6
- package/packages/{react → core}/src/components/List.tsx +4 -4
- package/packages/{react → core}/src/components/Pre.tsx +2 -2
- package/packages/{react → core}/src/components/Table.tsx +14 -14
- package/packages/core/tsconfig.json +11 -0
- package/packages/forms/coverage/clover.xml +209 -0
- package/packages/forms/coverage/coverage-final.json +18 -0
- package/packages/forms/coverage/lcov-report/base.css +224 -0
- package/packages/forms/coverage/lcov-report/block-navigation.js +87 -0
- package/packages/forms/coverage/lcov-report/favicon.png +0 -0
- package/packages/forms/coverage/lcov-report/index.html +161 -0
- package/packages/forms/coverage/lcov-report/prettify.css +1 -0
- package/packages/forms/coverage/lcov-report/prettify.js +2 -0
- package/packages/forms/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/packages/forms/coverage/lcov-report/sorter.js +196 -0
- package/packages/forms/coverage/lcov-report/src/components/Checkbox.tsx.html +295 -0
- package/packages/forms/coverage/lcov-report/src/components/FieldsetControl.tsx.html +295 -0
- package/packages/forms/coverage/lcov-report/src/components/LabelControl.tsx.html +289 -0
- package/packages/forms/coverage/lcov-report/src/components/Radio.tsx.html +262 -0
- package/packages/forms/coverage/lcov-report/src/components/Select.tsx.html +253 -0
- package/packages/forms/coverage/lcov-report/src/components/Text.tsx.html +217 -0
- package/packages/forms/coverage/lcov-report/src/components/Textarea.tsx.html +226 -0
- package/packages/forms/coverage/lcov-report/src/components/context.ts.html +133 -0
- package/packages/forms/coverage/lcov-report/src/components/controlled/CheckboxGroup.tsx.html +244 -0
- package/packages/forms/coverage/lcov-report/src/components/controlled/RadioGroup.tsx.html +265 -0
- package/packages/forms/coverage/lcov-report/src/components/controlled/SelectControl.tsx.html +205 -0
- package/packages/forms/coverage/lcov-report/src/components/controlled/TextControl.tsx.html +202 -0
- package/packages/forms/coverage/lcov-report/src/components/controlled/TextareaControl.tsx.html +205 -0
- package/packages/forms/coverage/lcov-report/src/components/controlled/index.html +191 -0
- package/packages/forms/coverage/lcov-report/src/components/controlled/index.ts.html +100 -0
- package/packages/forms/coverage/lcov-report/src/components/index.html +236 -0
- package/packages/forms/coverage/lcov-report/src/components/index.ts.html +106 -0
- package/packages/forms/coverage/lcov-report/src/index.html +116 -0
- package/packages/forms/coverage/lcov-report/src/index.ts.html +136 -0
- package/packages/forms/coverage/lcov-report/src/utils/index.html +116 -0
- package/packages/forms/coverage/lcov-report/src/utils/index.ts.html +88 -0
- package/packages/forms/coverage/lcov.info +426 -0
- package/packages/forms/dist/index.cjs.js +24 -27
- package/packages/forms/dist/index.cjs.js.map +1 -1
- package/packages/forms/dist/index.es.js +593 -382
- package/packages/forms/dist/index.es.js.map +1 -1
- package/packages/forms/jest.config.ts +14 -0
- package/packages/forms/node_modules/.bin/ts-jest +2 -2
- package/packages/forms/package.json +6 -1
- package/packages/forms/src/components/Checkbox.tsx +19 -8
- package/packages/forms/src/components/FieldsetControl.tsx +70 -0
- package/packages/forms/src/components/LabelControl.tsx +65 -0
- package/packages/forms/src/components/Radio.tsx +24 -9
- package/packages/forms/src/components/Select.tsx +20 -6
- package/packages/forms/src/components/Text.tsx +13 -4
- package/packages/forms/src/components/Textarea.tsx +17 -3
- package/packages/forms/src/components/context.ts +16 -0
- package/packages/forms/src/components/controlled/CheckboxGroup.tsx +37 -15
- package/packages/forms/src/components/controlled/RadioGroup.tsx +44 -20
- package/packages/forms/src/components/controlled/SelectControl.tsx +40 -0
- package/packages/forms/src/components/controlled/TextControl.tsx +39 -0
- package/packages/forms/src/components/controlled/TextareaControl.tsx +40 -0
- package/packages/forms/src/components/controlled/index.ts +3 -3
- package/packages/forms/src/components/index.ts +2 -0
- package/packages/forms/src/index.ts +12 -4
- package/packages/forms/tests/FieldsetControl.test.tsx +54 -0
- package/packages/forms/tests/LabelControl.test.tsx +50 -0
- package/packages/forms/tests/Radio.test.tsx +99 -0
- package/packages/forms/tests/Text.test.tsx +96 -0
- package/packages/forms/tsconfig.json +1 -17
- package/packages/forms/dist/components/Checkbox.d.ts +0 -5
- package/packages/forms/dist/components/Checkbox.d.ts.map +0 -1
- package/packages/forms/dist/components/Radio.d.ts +0 -5
- package/packages/forms/dist/components/Radio.d.ts.map +0 -1
- package/packages/forms/dist/components/Select.d.ts +0 -5
- package/packages/forms/dist/components/Select.d.ts.map +0 -1
- package/packages/forms/dist/components/Text.d.ts +0 -5
- package/packages/forms/dist/components/Text.d.ts.map +0 -1
- package/packages/forms/dist/components/Textarea.d.ts +0 -5
- package/packages/forms/dist/components/Textarea.d.ts.map +0 -1
- package/packages/forms/dist/components/controlled/CheckboxGroup.d.ts +0 -9
- package/packages/forms/dist/components/controlled/CheckboxGroup.d.ts.map +0 -1
- package/packages/forms/dist/components/controlled/InputItem.d.ts +0 -5
- package/packages/forms/dist/components/controlled/InputItem.d.ts.map +0 -1
- package/packages/forms/dist/components/controlled/RadioGroup.d.ts +0 -9
- package/packages/forms/dist/components/controlled/RadioGroup.d.ts.map +0 -1
- package/packages/forms/dist/components/controlled/Select.d.ts +0 -6
- package/packages/forms/dist/components/controlled/Select.d.ts.map +0 -1
- package/packages/forms/dist/components/controlled/Text.d.ts +0 -6
- package/packages/forms/dist/components/controlled/Text.d.ts.map +0 -1
- package/packages/forms/dist/components/controlled/Textarea.d.ts +0 -6
- package/packages/forms/dist/components/controlled/Textarea.d.ts.map +0 -1
- package/packages/forms/dist/components/controlled/index.d.ts +0 -6
- package/packages/forms/dist/components/controlled/index.d.ts.map +0 -1
- package/packages/forms/dist/components/index.d.ts +0 -6
- package/packages/forms/dist/components/index.d.ts.map +0 -1
- package/packages/forms/dist/index.d.ts +0 -3
- package/packages/forms/dist/index.d.ts.map +0 -1
- package/packages/forms/dist/utils/index.d.ts +0 -2
- package/packages/forms/dist/utils/index.d.ts.map +0 -1
- package/packages/forms/src/components/controlled/Select.tsx +0 -22
- package/packages/forms/src/components/controlled/Text.tsx +0 -22
- package/packages/forms/src/components/controlled/Textarea.tsx +0 -23
- package/packages/forms/src/vite-env.d.ts +0 -1
- package/packages/react/tsconfig.json +0 -27
- /package/packages/{react → core}/src/components/index.ts +0 -0
- /package/packages/{react → core}/src/index.ts +0 -0
- /package/packages/{react → core}/src/utils/index.ts +0 -0
- /package/packages/{react → core}/tsconfig.node.json +0 -0
- /package/packages/{react → core}/vite.config.ts +0 -0
|
@@ -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"> *</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.
|
|
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
|
-
|
|
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
|
|
@@ -33,12 +40,20 @@ export const Radio = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
|
|
|
33
40
|
peer-checked:border-sea-600
|
|
34
41
|
`
|
|
35
42
|
return (
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
<input
|
|
43
|
+
<label htmlFor={newProps.id} className={cx(style, className)}>
|
|
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
|
+
/>
|
|
39
54
|
<span className={styleRadio}></span>
|
|
40
55
|
{children}
|
|
41
|
-
</
|
|
42
|
-
</
|
|
56
|
+
</span>
|
|
57
|
+
</label>
|
|
43
58
|
)
|
|
44
59
|
})
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { cx } from '../utils'
|
|
3
|
+
import { ControllerContext } from './context'
|
|
3
4
|
|
|
4
5
|
export interface SelectProps extends React.ComponentPropsWithoutRef<'select'> {}
|
|
5
6
|
|
|
6
7
|
export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
7
8
|
(props, ref) => {
|
|
8
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'
|
|
9
16
|
|
|
10
17
|
const style = `
|
|
18
|
+
cursor-pointer
|
|
11
19
|
appearance-none
|
|
12
20
|
text-base
|
|
13
21
|
w-full
|
|
14
22
|
bg-white-100
|
|
15
23
|
border
|
|
16
24
|
border-solid
|
|
17
|
-
border-sumi-900
|
|
18
25
|
py-4 px-4 pr-8
|
|
19
26
|
rounded-[8px]
|
|
20
27
|
focus:outline
|
|
@@ -23,11 +30,18 @@ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
|
23
30
|
`
|
|
24
31
|
|
|
25
32
|
return (
|
|
26
|
-
<
|
|
27
|
-
<select
|
|
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
|
+
>
|
|
28
42
|
{children}
|
|
29
43
|
</select>
|
|
30
|
-
<
|
|
44
|
+
<span className="flex items-center absolute inset-y-0 right-0 px-2 pointer-events-none">
|
|
31
45
|
<svg
|
|
32
46
|
xmlns="http://www.w3.org/2000/svg"
|
|
33
47
|
className="fill-sumi-900"
|
|
@@ -36,8 +50,8 @@ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
|
36
50
|
>
|
|
37
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" />
|
|
38
52
|
</svg>
|
|
39
|
-
</
|
|
40
|
-
</
|
|
53
|
+
</span>
|
|
54
|
+
</span>
|
|
41
55
|
)
|
|
42
56
|
}
|
|
43
57
|
)
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { cx } from '../utils'
|
|
3
|
+
import { ControllerContext } from './context'
|
|
3
4
|
|
|
4
5
|
export interface TextProps extends React.ComponentPropsWithoutRef<'input'> {}
|
|
5
6
|
|
|
6
7
|
export const Text = React.forwardRef<HTMLInputElement, TextProps>(
|
|
7
8
|
(props, ref) => {
|
|
8
|
-
const { className, ...
|
|
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'
|
|
9
16
|
|
|
10
17
|
const style = `
|
|
11
18
|
p-4
|
|
12
19
|
rounded-lg
|
|
13
20
|
border
|
|
14
21
|
border-solid
|
|
15
|
-
border-sumi-900
|
|
16
22
|
focus:outline
|
|
17
23
|
focus:outline-2
|
|
18
24
|
focus:outline-wood-500
|
|
@@ -26,8 +32,11 @@ export const Text = React.forwardRef<HTMLInputElement, TextProps>(
|
|
|
26
32
|
return (
|
|
27
33
|
<input
|
|
28
34
|
type="text"
|
|
29
|
-
className={cx(style, className)}
|
|
30
|
-
{
|
|
35
|
+
className={cx(style, invalidStyle, className)}
|
|
36
|
+
aria-describedby={ctx.helperTextId}
|
|
37
|
+
aria-errormessage={ctx.errorMessageId}
|
|
38
|
+
aria-invalid={ctx.isInvalid ?? false}
|
|
39
|
+
{...restProps}
|
|
31
40
|
ref={ref}
|
|
32
41
|
/>
|
|
33
42
|
)
|
|
@@ -1,19 +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
6
|
extends React.ComponentPropsWithoutRef<'textarea'> {}
|
|
6
7
|
|
|
7
8
|
export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
8
9
|
(props, ref) => {
|
|
9
|
-
const { className, children, ...
|
|
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'
|
|
10
18
|
|
|
11
19
|
const style = `
|
|
12
20
|
p-4
|
|
13
21
|
rounded-lg
|
|
14
22
|
border
|
|
15
23
|
border-solid
|
|
16
|
-
border-sumi-900
|
|
17
24
|
focus:outline
|
|
18
25
|
focus:outline-2
|
|
19
26
|
focus:outline-wood-500
|
|
@@ -25,7 +32,14 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
|
25
32
|
`
|
|
26
33
|
|
|
27
34
|
return (
|
|
28
|
-
<textarea
|
|
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
|
+
>
|
|
29
43
|
{children}
|
|
30
44
|
</textarea>
|
|
31
45
|
)
|
|
@@ -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
|
+
})
|
|
@@ -1,31 +1,53 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { Checkbox } from '../Checkbox'
|
|
3
|
+
import { FieldsetControl } from '../FieldsetControl'
|
|
3
4
|
import { InputItem } from './InputItem'
|
|
4
|
-
import { cx } from '../../utils'
|
|
5
5
|
|
|
6
6
|
export interface CheckboxGroupProps
|
|
7
|
-
extends Omit<React.
|
|
7
|
+
extends Omit<React.ComponentPropsWithoutRef<'fieldset'>, 'onChange'> {
|
|
8
8
|
items: InputItem[]
|
|
9
9
|
onChange: React.ChangeEventHandler<HTMLInputElement>
|
|
10
|
-
|
|
10
|
+
labelText: string
|
|
11
|
+
helperText?: string
|
|
12
|
+
errorMessage?: string
|
|
13
|
+
isInvalid?: boolean
|
|
14
|
+
isRequired?: boolean
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
export const CheckboxGroup =
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
16
32
|
|
|
17
33
|
return (
|
|
18
|
-
<
|
|
19
|
-
|
|
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
|
+
>
|
|
20
44
|
{items.map(({ label, value }, index) => {
|
|
21
45
|
return (
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
</Checkbox>
|
|
26
|
-
</div>
|
|
46
|
+
<Checkbox key={index} value={value} onChange={onChange}>
|
|
47
|
+
{label}
|
|
48
|
+
</Checkbox>
|
|
27
49
|
)
|
|
28
50
|
})}
|
|
29
|
-
</
|
|
51
|
+
</FieldsetControl>
|
|
30
52
|
)
|
|
31
|
-
}
|
|
53
|
+
})
|
|
@@ -1,36 +1,60 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { Radio } from '../Radio'
|
|
3
|
+
import { FieldsetControl } from '../FieldsetControl'
|
|
3
4
|
import { InputItem } from './InputItem'
|
|
4
|
-
import { cx } from '../../utils'
|
|
5
5
|
|
|
6
6
|
export interface RadioGroupProps
|
|
7
|
-
extends Omit<React.
|
|
7
|
+
extends Omit<React.ComponentPropsWithoutRef<'fieldset'>, 'onChange'> {
|
|
8
8
|
items: InputItem[]
|
|
9
9
|
onChange: React.ChangeEventHandler<HTMLInputElement>
|
|
10
|
-
|
|
10
|
+
labelText: string
|
|
11
|
+
helperText?: string
|
|
12
|
+
errorMessage?: string
|
|
13
|
+
isInvalid?: boolean
|
|
14
|
+
isRequired?: boolean
|
|
15
|
+
defaultValue?: string
|
|
11
16
|
}
|
|
12
17
|
|
|
13
|
-
export const RadioGroup =
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
16
34
|
|
|
17
35
|
return (
|
|
18
|
-
<
|
|
19
|
-
|
|
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
|
+
>
|
|
20
46
|
{items.map(({ label, value }, index) => {
|
|
21
47
|
return (
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
</Radio>
|
|
31
|
-
</div>
|
|
48
|
+
<Radio
|
|
49
|
+
key={index}
|
|
50
|
+
value={value}
|
|
51
|
+
onChange={onChange}
|
|
52
|
+
defaultChecked={defaultValue === value}
|
|
53
|
+
>
|
|
54
|
+
{label}
|
|
55
|
+
</Radio>
|
|
32
56
|
)
|
|
33
57
|
})}
|
|
34
|
-
</
|
|
58
|
+
</FieldsetControl>
|
|
35
59
|
)
|
|
36
|
-
}
|
|
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
|
+
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CheckboxGroup } from './CheckboxGroup'
|
|
2
2
|
export { RadioGroup } from './RadioGroup'
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
3
|
+
export { SelectControl } from './SelectControl'
|
|
4
|
+
export { TextControl } from './TextControl'
|
|
5
|
+
export { TextareaControl } from './TextareaControl'
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
Checkbox,
|
|
3
|
+
Radio,
|
|
4
|
+
Select,
|
|
5
|
+
Text,
|
|
6
|
+
Textarea,
|
|
7
|
+
LabelControl,
|
|
8
|
+
FieldsetControl
|
|
9
|
+
} from './components'
|
|
2
10
|
|
|
3
11
|
export {
|
|
4
12
|
CheckboxGroup,
|
|
5
13
|
RadioGroup,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
SelectControl,
|
|
15
|
+
TextControl,
|
|
16
|
+
TextareaControl
|
|
9
17
|
} from './components/controlled'
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom'
|
|
4
|
+
|
|
5
|
+
import { FieldsetControl } from '../src'
|
|
6
|
+
|
|
7
|
+
describe('FieldsetControl', () => {
|
|
8
|
+
test('renders FieldsetControl component vol1', async () => {
|
|
9
|
+
render(<FieldsetControl labelText="test" />)
|
|
10
|
+
|
|
11
|
+
const fieldset = screen.getByRole('group')
|
|
12
|
+
|
|
13
|
+
expect(fieldset).toBeInTheDocument()
|
|
14
|
+
|
|
15
|
+
expect(screen.getByText('test')).toBeInTheDocument()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('renders FieldsetControl component vol2', async () => {
|
|
19
|
+
render(
|
|
20
|
+
<FieldsetControl
|
|
21
|
+
labelText="test"
|
|
22
|
+
helperText="helper"
|
|
23
|
+
errorMessage="error"
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
expect(screen.getByText('helper')).toBeInTheDocument()
|
|
28
|
+
expect(screen.queryByText('error')).toBeNull()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('renders FieldsetControl component vol3', async () => {
|
|
32
|
+
render(
|
|
33
|
+
<FieldsetControl
|
|
34
|
+
labelText="test"
|
|
35
|
+
helperText="helper"
|
|
36
|
+
errorMessage="error"
|
|
37
|
+
isInvalid
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
expect(screen.getByText('helper')).toBeInTheDocument()
|
|
42
|
+
expect(screen.getByText('error')).toBeInTheDocument()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('renders FieldsetControl component vol4', async () => {
|
|
46
|
+
render(<FieldsetControl labelText="test" />)
|
|
47
|
+
|
|
48
|
+
expect(screen.queryByText('*')).toBeNull()
|
|
49
|
+
|
|
50
|
+
render(<FieldsetControl labelText="test" isRequired />)
|
|
51
|
+
|
|
52
|
+
expect(screen.getByText('*')).toBeInTheDocument()
|
|
53
|
+
})
|
|
54
|
+
})
|