@coopdigital/react 0.44.0 → 0.46.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/dist/components/Button/Button.d.ts +6 -4
- package/dist/components/Button/Button.js +4 -6
- package/dist/components/Card/Card.js +2 -2
- package/dist/components/Checkbox/Checkbox.d.ts +4 -24
- package/dist/components/Checkbox/Checkbox.js +7 -14
- package/dist/components/Checkbox/index.d.ts +1 -2
- package/dist/components/Expandable/Expandable.js +2 -2
- package/dist/components/Field/Field.d.ts +44 -5
- package/dist/components/Field/Field.js +68 -5
- package/dist/components/FieldMarkers/Error.d.ts +9 -0
- package/dist/components/{FieldError/FieldError.js → FieldMarkers/Error.js} +2 -2
- package/dist/components/FieldMarkers/Hint.d.ts +9 -0
- package/dist/components/{FieldHint/FieldHint.js → FieldMarkers/Hint.js} +2 -2
- package/dist/components/FieldMarkers/Label.d.ts +11 -0
- package/dist/components/FieldMarkers/Label.js +8 -0
- package/dist/components/FieldMarkers/Legend.d.ts +11 -0
- package/dist/components/FieldMarkers/Legend.js +13 -0
- package/dist/components/Fieldset/Fieldset.d.ts +54 -0
- package/dist/components/Fieldset/Fieldset.js +44 -0
- package/dist/components/Fieldset/index.d.ts +4 -0
- package/dist/components/Pill/Pill.js +2 -2
- package/dist/components/Radio/Radio.d.ts +18 -0
- package/dist/components/Radio/Radio.js +22 -0
- package/dist/components/Radio/index.d.ts +4 -0
- package/dist/components/{SearchBox/SearchBox.d.ts → Searchbox/Searchbox.d.ts} +7 -7
- package/dist/components/{SearchBox/SearchBox.js → Searchbox/Searchbox.js} +6 -6
- package/dist/components/Searchbox/index.d.ts +4 -0
- package/dist/components/TextInput/TextInput.d.ts +5 -19
- package/dist/components/TextInput/TextInput.js +7 -11
- package/dist/components/Textarea/Textarea.d.ts +4 -18
- package/dist/components/Textarea/Textarea.js +8 -9
- package/dist/hooks/useId.d.ts +2 -0
- package/dist/hooks/useId.js +8 -0
- package/dist/{utils/slots.d.ts → hooks/useSlots.d.ts} +3 -1
- package/dist/{utils/slots.js → hooks/useSlots.js} +9 -3
- package/dist/index.d.ts +3 -5
- package/dist/index.js +4 -8
- package/package.json +10 -10
- package/src/components/Button/Button.tsx +10 -14
- package/src/components/Card/Card.tsx +2 -3
- package/src/components/Checkbox/Checkbox.tsx +8 -64
- package/src/components/Checkbox/index.ts +1 -2
- package/src/components/Expandable/Expandable.tsx +2 -2
- package/src/components/Field/Field.tsx +144 -8
- package/src/components/{FieldError/FieldError.tsx → FieldMarkers/Error.tsx} +4 -4
- package/src/components/{FieldHint/FieldHint.tsx → FieldMarkers/Hint.tsx} +5 -9
- package/src/components/FieldMarkers/Label.tsx +21 -0
- package/src/components/FieldMarkers/Legend.tsx +28 -0
- package/src/components/Fieldset/Fieldset.tsx +98 -0
- package/src/components/Fieldset/index.ts +5 -0
- package/src/components/Pill/Pill.tsx +2 -2
- package/src/components/Radio/Radio.tsx +47 -0
- package/src/components/Radio/index.ts +5 -0
- package/src/components/{SearchBox/SearchBox.tsx → Searchbox/Searchbox.tsx} +15 -13
- package/src/components/Searchbox/index.ts +5 -0
- package/src/components/TextInput/TextInput.tsx +25 -46
- package/src/components/Textarea/Textarea.tsx +12 -40
- package/src/hooks/useId.ts +9 -0
- package/src/{utils/slots.ts → hooks/useSlots.ts} +10 -2
- package/src/index.ts +3 -5
- package/dist/components/Checkbox/CheckboxGroup.d.ts +0 -32
- package/dist/components/Checkbox/CheckboxGroup.js +0 -21
- package/dist/components/FieldError/FieldError.d.ts +0 -9
- package/dist/components/FieldError/index.d.ts +0 -4
- package/dist/components/FieldHint/FieldHint.d.ts +0 -9
- package/dist/components/FieldHint/index.d.ts +0 -4
- package/dist/components/FieldLabel/FieldLabel.d.ts +0 -13
- package/dist/components/FieldLabel/FieldLabel.js +0 -13
- package/dist/components/FieldLabel/index.d.ts +0 -4
- package/dist/components/RadioButton/RadioButton.d.ts +0 -36
- package/dist/components/RadioButton/RadioButton.js +0 -26
- package/dist/components/RadioButton/RadioButtonGroup.d.ts +0 -32
- package/dist/components/RadioButton/RadioButtonGroup.js +0 -21
- package/dist/components/RadioButton/index.d.ts +0 -5
- package/dist/components/SearchBox/index.d.ts +0 -4
- package/dist/components/Tag/index.js +0 -5
- package/src/components/Checkbox/CheckboxGroup.tsx +0 -73
- package/src/components/FieldError/index.ts +0 -5
- package/src/components/FieldHint/index.ts +0 -5
- package/src/components/FieldLabel/FieldLabel.tsx +0 -31
- package/src/components/FieldLabel/index.ts +0 -5
- package/src/components/RadioButton/RadioButton.tsx +0 -97
- package/src/components/RadioButton/RadioButtonGroup.tsx +0 -73
- package/src/components/RadioButton/index.ts +0 -6
- package/src/components/SearchBox/index.ts +0 -5
|
@@ -1,20 +1,156 @@
|
|
|
1
|
-
import type { HTMLAttributes,
|
|
1
|
+
import type { HTMLAttributes, HTMLProps, JSX } from "react"
|
|
2
2
|
|
|
3
3
|
import clsx from "clsx"
|
|
4
|
+
import React from "react"
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import { useId } from "../../hooks/useId"
|
|
7
|
+
import { useSlots } from "../../hooks/useSlots"
|
|
8
|
+
import { Error as BaseError, type ErrorProps } from "../FieldMarkers/Error"
|
|
9
|
+
import { Hint as BaseHint, type HintProps } from "../FieldMarkers/Hint"
|
|
10
|
+
import { Label as BaseLabel, type LabelProps } from "../FieldMarkers/Label"
|
|
11
|
+
|
|
12
|
+
const componentSlots = {
|
|
13
|
+
Checkbox: null,
|
|
14
|
+
Children: null,
|
|
15
|
+
Control: null,
|
|
16
|
+
FieldError: null,
|
|
17
|
+
FieldHint: null,
|
|
18
|
+
FieldLabel: null,
|
|
19
|
+
Radio: null,
|
|
20
|
+
Textarea: null,
|
|
21
|
+
TextInput: null,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const standardFields = ["Children", "FieldError", "FieldHint", "FieldLabel"]
|
|
25
|
+
const inlineFields = ["Checkbox", "Radio"]
|
|
26
|
+
|
|
27
|
+
interface FieldProps extends HTMLAttributes<HTMLDivElement> {
|
|
28
|
+
/** **(Optional)** Specify whether the Field should render inside a box. */
|
|
29
|
+
boxed?: boolean
|
|
30
|
+
/** Form elements inside the Field.
|
|
31
|
+
*
|
|
32
|
+
* Usually this will be a combination of `Field.Label`, `Field.Hint`, `Field.Error` and an associated control such as `TextInput` or `Checkbox`. */
|
|
33
|
+
children: React.ReactNode
|
|
8
34
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
9
|
-
|
|
35
|
+
classname?: string
|
|
36
|
+
/** **(Optional)** Specify the Field error state. Use this to apply visual styling to the field control. */
|
|
37
|
+
error?: boolean
|
|
38
|
+
/** **(Optional)** Specify whether the Field should show the left-hand error bar if it is in an error state. */
|
|
39
|
+
hideErrorBar?: boolean
|
|
10
40
|
}
|
|
11
41
|
|
|
12
|
-
|
|
42
|
+
const Root = ({
|
|
43
|
+
boxed = false,
|
|
44
|
+
children,
|
|
45
|
+
className,
|
|
46
|
+
error = false,
|
|
47
|
+
hideErrorBar = false,
|
|
48
|
+
...props
|
|
49
|
+
}: FieldProps) => {
|
|
50
|
+
const slots = { ...useSlots(componentSlots, children) }
|
|
51
|
+
const slotsArray = Object.entries(slots)
|
|
52
|
+
|
|
53
|
+
const uid = useId()
|
|
54
|
+
|
|
55
|
+
const isInlineControl = slotsArray.some((s) => s[1] !== null && inlineFields.includes(s[0]))
|
|
56
|
+
const hasFieldMarkers = !!(slots.FieldLabel ?? slots.FieldError ?? slots.FieldHint)
|
|
57
|
+
const [, control] =
|
|
58
|
+
slotsArray.find((s) => (!standardFields.includes(s[0]) && s[1] !== null ? s : null)) ?? []
|
|
59
|
+
|
|
60
|
+
let controlId = uid
|
|
61
|
+
let controlDisabled = false
|
|
62
|
+
|
|
63
|
+
if (control) {
|
|
64
|
+
if (typeof control === "object" && "props" in control) {
|
|
65
|
+
const controlProps = control.props as HTMLProps<HTMLElement>
|
|
66
|
+
controlId = controlProps.id ?? controlId
|
|
67
|
+
controlDisabled = controlProps.disabled ?? false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
slots.Control = React.cloneElement(control as React.ReactElement<HTMLInputElement>, {
|
|
71
|
+
id: controlId,
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (slots.FieldLabel && React.isValidElement(slots.FieldLabel)) {
|
|
76
|
+
slots.FieldLabel = React.cloneElement(slots.FieldLabel as React.ReactElement<LabelProps>, {
|
|
77
|
+
htmlFor: (slots.FieldLabel.props as LabelProps).htmlFor ?? controlId,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
13
81
|
const componentProps = {
|
|
14
|
-
className: clsx("coop-form-item ", className),
|
|
15
82
|
...props,
|
|
83
|
+
"aria-disabled": controlDisabled || undefined,
|
|
84
|
+
className: clsx("coop-field", isInlineControl && "coop-field-inline", className),
|
|
85
|
+
"data-boxed": boxed || undefined,
|
|
86
|
+
"data-error": error || undefined,
|
|
87
|
+
"data-hide-error": hideErrorBar || undefined,
|
|
16
88
|
}
|
|
17
|
-
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div {...componentProps}>
|
|
92
|
+
{!isInlineControl && hasFieldMarkers && (
|
|
93
|
+
<div className="coop-field-markers">
|
|
94
|
+
{slots.FieldLabel}
|
|
95
|
+
{slots.FieldHint}
|
|
96
|
+
{slots.FieldError}
|
|
97
|
+
</div>
|
|
98
|
+
)}
|
|
99
|
+
{slots.Control && (
|
|
100
|
+
<div className="coop-field-control">
|
|
101
|
+
{slots.Control}
|
|
102
|
+
{isInlineControl && hasFieldMarkers && (
|
|
103
|
+
<div className="coop-field-markers">
|
|
104
|
+
{slots.FieldLabel}
|
|
105
|
+
{slots.FieldHint}
|
|
106
|
+
{slots.FieldError}
|
|
107
|
+
</div>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
{slots.Children}
|
|
112
|
+
</div>
|
|
113
|
+
)
|
|
18
114
|
}
|
|
19
115
|
|
|
116
|
+
interface ControlProps extends HTMLAttributes<HTMLDivElement> {
|
|
117
|
+
/** **(Optional)** Elements inside the form control. */
|
|
118
|
+
children?: string | React.ReactNode
|
|
119
|
+
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
120
|
+
className?: string
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const FieldControl = ({ children, className, ...props }: ControlProps): JSX.Element => {
|
|
124
|
+
return (
|
|
125
|
+
<div className={clsx("coop-field-control ", className)} {...props}>
|
|
126
|
+
{children}
|
|
127
|
+
</div>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
FieldControl.displayName = "Field.Control"
|
|
132
|
+
|
|
133
|
+
const FieldLabel = (props: LabelProps) => <BaseLabel {...props} />
|
|
134
|
+
|
|
135
|
+
FieldLabel.displayName = "Field.Label"
|
|
136
|
+
|
|
137
|
+
const FieldHint = (props: HintProps) => <BaseHint {...props} />
|
|
138
|
+
|
|
139
|
+
FieldHint.displayName = "Field.Hint"
|
|
140
|
+
|
|
141
|
+
const FieldError = (props: ErrorProps) => <BaseError {...props} />
|
|
142
|
+
|
|
143
|
+
FieldError.displayName = "Field.Error"
|
|
144
|
+
|
|
145
|
+
export const Field = Object.assign(Root, {
|
|
146
|
+
Control: FieldControl,
|
|
147
|
+
Error: FieldError,
|
|
148
|
+
Hint: FieldHint,
|
|
149
|
+
Label: FieldLabel,
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
// Field.Label = FieldLabel
|
|
153
|
+
// Field.Hint = FieldHint
|
|
154
|
+
// Field.Error = FieldError
|
|
155
|
+
|
|
20
156
|
export default Field
|
|
@@ -2,14 +2,14 @@ import type { HTMLAttributes, JSX, ReactNode } from "react"
|
|
|
2
2
|
|
|
3
3
|
import clsx from "clsx"
|
|
4
4
|
|
|
5
|
-
export interface
|
|
6
|
-
/** **(Optional)**
|
|
5
|
+
export interface ErrorProps extends HTMLAttributes<HTMLSpanElement> {
|
|
6
|
+
/** **(Optional)** Error text for the form element. Accepts any valid JSX or string. */
|
|
7
7
|
children?: string | ReactNode
|
|
8
8
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
9
9
|
className?: string
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const Error = ({ children, className, ...props }: ErrorProps): JSX.Element => {
|
|
13
13
|
const componentProps = {
|
|
14
14
|
className: clsx("coop-field-error ", className),
|
|
15
15
|
...props,
|
|
@@ -17,4 +17,4 @@ export const FieldError = ({ children, className, ...props }: FieldErrorProps):
|
|
|
17
17
|
return <span {...componentProps}>{children}</span>
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export default
|
|
20
|
+
export default Error
|
|
@@ -2,18 +2,14 @@ import type { HTMLAttributes, JSX, ReactNode } from "react"
|
|
|
2
2
|
|
|
3
3
|
import clsx from "clsx"
|
|
4
4
|
|
|
5
|
-
export interface
|
|
6
|
-
/**
|
|
7
|
-
children
|
|
5
|
+
export interface HintProps extends HTMLAttributes<HTMLParagraphElement> {
|
|
6
|
+
/** **(Optional)** Hint text for the form element. Accepts any valid JSX or string. */
|
|
7
|
+
children?: string | ReactNode
|
|
8
8
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
9
9
|
className?: string
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export const
|
|
13
|
-
children,
|
|
14
|
-
className,
|
|
15
|
-
...props
|
|
16
|
-
}: FieldHintProps): JSX.Element | null => {
|
|
12
|
+
export const Hint = ({ children, className, ...props }: HintProps): JSX.Element | null => {
|
|
17
13
|
const componentProps = {
|
|
18
14
|
className: clsx("coop-field-hint ", className),
|
|
19
15
|
...props,
|
|
@@ -22,4 +18,4 @@ export const FieldHint = ({
|
|
|
22
18
|
return children ? <div {...componentProps}>{children}</div> : null
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
export default
|
|
21
|
+
export default Hint
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import clsx from "clsx"
|
|
2
|
+
import { LabelHTMLAttributes } from "react"
|
|
3
|
+
|
|
4
|
+
export interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {
|
|
5
|
+
/** **(Optional)** Main label for the form element. Accepts any valid JSX or string. */
|
|
6
|
+
children?: string | React.ReactNode
|
|
7
|
+
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
8
|
+
className?: string
|
|
9
|
+
/** **(Optional)** Specify whether the label is visible for humans or only for screen readers. */
|
|
10
|
+
isVisible?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const Label = ({ children, className, isVisible = true, ...props }: LabelProps) => {
|
|
14
|
+
return (
|
|
15
|
+
<label {...props} className={clsx("coop-field-label", !isVisible && "sr-only", className)}>
|
|
16
|
+
<span>{children}</span>
|
|
17
|
+
</label>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default Label
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import clsx from "clsx"
|
|
2
|
+
import { HTMLAttributes } from "react"
|
|
3
|
+
|
|
4
|
+
export interface LegendProps extends HTMLAttributes<HTMLLegendElement> {
|
|
5
|
+
/** **(Optional)** Main legend for the fieldset. Accepts any valid JSX or string. */
|
|
6
|
+
children?: string | React.ReactNode
|
|
7
|
+
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
8
|
+
className?: string
|
|
9
|
+
/** **(Optional)** Specify whether the legend should be visible to humans or screen readers. */
|
|
10
|
+
isVisible?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const Legend = ({ children, className, isVisible = true, ...props }: LegendProps) => {
|
|
14
|
+
const componentProps = {
|
|
15
|
+
"aria-hidden": true,
|
|
16
|
+
className: clsx("coop-field-label", !isVisible && "sr-only", className),
|
|
17
|
+
...props,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<legend className="sr-only">{children}</legend>
|
|
23
|
+
{isVisible && <div {...componentProps}>{children}</div>}
|
|
24
|
+
</>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default Legend
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import clsx from "clsx"
|
|
2
|
+
import { type FieldsetHTMLAttributes, type JSX } from "react"
|
|
3
|
+
|
|
4
|
+
import { StandardSizes } from "../../../src/types"
|
|
5
|
+
import { Error as BaseError, type ErrorProps } from "../FieldMarkers/Error"
|
|
6
|
+
import { Hint as BaseHint, type HintProps } from "../FieldMarkers/Hint"
|
|
7
|
+
import { Legend as BaseLegend, type LegendProps } from "../FieldMarkers/Legend"
|
|
8
|
+
|
|
9
|
+
export interface FieldsetProps extends FieldsetHTMLAttributes<HTMLFieldSetElement> {
|
|
10
|
+
/** Form elements inside the Fieldset.
|
|
11
|
+
*
|
|
12
|
+
* Usually this will be a combination of `Fieldset.Legend` and `Fieldset.Fields`. */
|
|
13
|
+
children: React.ReactNode
|
|
14
|
+
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
15
|
+
className?: string
|
|
16
|
+
/** **(Optional)** Specify whether the Fieldset, and all of its descendents, should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
17
|
+
disabled?: boolean
|
|
18
|
+
/** **(Optional)** Specify the Fieldset error state. Use this to apply visual styling to the field control. */
|
|
19
|
+
error?: boolean
|
|
20
|
+
/** **(Optional)** Specify whether the Fieldset should show the left-hand error bar if it is in an error state. */
|
|
21
|
+
hideErrorBar?: boolean
|
|
22
|
+
/** **(Optional)** Specify the size of the Fieldset and all its descendents. */
|
|
23
|
+
size?: StandardSizes
|
|
24
|
+
}
|
|
25
|
+
const Root = ({
|
|
26
|
+
children,
|
|
27
|
+
className,
|
|
28
|
+
disabled,
|
|
29
|
+
error = false,
|
|
30
|
+
hideErrorBar = false,
|
|
31
|
+
size = "md",
|
|
32
|
+
...props
|
|
33
|
+
}: FieldsetProps): JSX.Element => {
|
|
34
|
+
const componentProps = {
|
|
35
|
+
"aria-disabled": disabled,
|
|
36
|
+
className: clsx("coop-fieldset", className),
|
|
37
|
+
"data-error": error || undefined,
|
|
38
|
+
//"data-variant": variant !== "default" ? variant : undefined,
|
|
39
|
+
"data-hide-error": hideErrorBar || undefined,
|
|
40
|
+
// "data-orientation": orientation !== "vertical" ? orientation : undefined,
|
|
41
|
+
"data-size": size.length && size !== "md" ? size : undefined,
|
|
42
|
+
disabled,
|
|
43
|
+
...props,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return <fieldset {...componentProps}>{children}</fieldset>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface FieldsetFieldsProps {
|
|
50
|
+
/** **(Optional)** Specify whether all descendent Fields should render inside a box. */
|
|
51
|
+
boxed?: boolean
|
|
52
|
+
/** **(Optional)** Form elements inside the Fieldset.Fields container. */
|
|
53
|
+
children?: string | React.ReactNode
|
|
54
|
+
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
55
|
+
className?: string
|
|
56
|
+
/** **(Optional)** Specify the CheckboxGroup orientation. */
|
|
57
|
+
orientation?: "horizontal" | "vertical"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const FieldsetFields = ({
|
|
61
|
+
boxed = false,
|
|
62
|
+
children,
|
|
63
|
+
className,
|
|
64
|
+
orientation = "vertical",
|
|
65
|
+
...props
|
|
66
|
+
}: FieldsetFieldsProps): JSX.Element => {
|
|
67
|
+
const componentProps = {
|
|
68
|
+
className: clsx("coop-fieldset-fields", className),
|
|
69
|
+
"data-boxed": boxed || undefined,
|
|
70
|
+
"data-orientation": orientation !== "vertical" ? orientation : undefined,
|
|
71
|
+
...props,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return <div {...componentProps}>{children}</div>
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
FieldsetFields.displayName = "Fieldset.Fields"
|
|
78
|
+
|
|
79
|
+
const FieldsetLegend = (props: LegendProps) => <BaseLegend {...props} />
|
|
80
|
+
|
|
81
|
+
FieldsetLegend.displayName = "Fieldset.Legend"
|
|
82
|
+
|
|
83
|
+
const FieldsetHint = (props: HintProps) => <BaseHint {...props} />
|
|
84
|
+
|
|
85
|
+
FieldsetHint.displayName = "Fieldset.Hint"
|
|
86
|
+
|
|
87
|
+
const FieldsetError = (props: ErrorProps) => <BaseError {...props} />
|
|
88
|
+
|
|
89
|
+
FieldsetError.displayName = "Fieldset.Error"
|
|
90
|
+
|
|
91
|
+
export const Fieldset = Object.assign(Root, {
|
|
92
|
+
Error: FieldsetError,
|
|
93
|
+
Fields: FieldsetFields,
|
|
94
|
+
Hint: FieldsetHint,
|
|
95
|
+
Legend: FieldsetLegend,
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
export default Fieldset
|
|
@@ -4,8 +4,8 @@ import clsx from "clsx"
|
|
|
4
4
|
import React from "react"
|
|
5
5
|
import { StandardSizes } from "src/types"
|
|
6
6
|
|
|
7
|
+
import { useSlots } from "../../hooks/useSlots"
|
|
7
8
|
import { hasUserBg } from "../../utils"
|
|
8
|
-
import { getSlots } from "../../utils/slots"
|
|
9
9
|
|
|
10
10
|
export interface PillProps extends HTMLAttributes<HTMLAnchorElement> {
|
|
11
11
|
/** **(Optional)** Specify a custom element to override default `a` or `span`. */
|
|
@@ -43,7 +43,7 @@ export const Pill = ({
|
|
|
43
43
|
}: PillProps): JSX.Element => {
|
|
44
44
|
let element: PillProps["as"] = href ? "a" : "span"
|
|
45
45
|
|
|
46
|
-
const slots =
|
|
46
|
+
const slots = useSlots(componentSlots, children)
|
|
47
47
|
|
|
48
48
|
if (as) {
|
|
49
49
|
element = as
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import clsx from "clsx"
|
|
2
|
+
import { type InputHTMLAttributes, type JSX, useId } from "react"
|
|
3
|
+
import { StandardSizes } from "src/types"
|
|
4
|
+
|
|
5
|
+
export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
6
|
+
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
7
|
+
className?: string
|
|
8
|
+
/** **(Optional)** Specify whether the Radio should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
/** **(Optional)** Specify the Radio error state. */
|
|
11
|
+
error?: boolean
|
|
12
|
+
/** **(Optional)** Specify the Radio id. Will be auto-generated if not set. */
|
|
13
|
+
id?: string
|
|
14
|
+
/** Specify the Radio name. */
|
|
15
|
+
name: string
|
|
16
|
+
/** **(Optional)** Specify the Radio size. */
|
|
17
|
+
size?: StandardSizes
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const Radio = ({
|
|
21
|
+
className,
|
|
22
|
+
disabled,
|
|
23
|
+
error = false,
|
|
24
|
+
id,
|
|
25
|
+
name,
|
|
26
|
+
size = "md",
|
|
27
|
+
...props
|
|
28
|
+
}: RadioProps): JSX.Element => {
|
|
29
|
+
const internalId = useId()
|
|
30
|
+
|
|
31
|
+
id = id ?? internalId
|
|
32
|
+
|
|
33
|
+
const componentProps = {
|
|
34
|
+
className: clsx("coop-radio", className),
|
|
35
|
+
"data-error": error || undefined,
|
|
36
|
+
"data-size": size.length && size !== "md" ? size : undefined,
|
|
37
|
+
disabled,
|
|
38
|
+
id,
|
|
39
|
+
name,
|
|
40
|
+
type: "radio",
|
|
41
|
+
...props,
|
|
42
|
+
}
|
|
43
|
+
//const formItemProps = { "aria-disabled": disabled ? true : undefined }
|
|
44
|
+
return <input {...componentProps} />
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default Radio
|
|
@@ -5,13 +5,13 @@ import type { InputHTMLAttributes, JSX } from "react"
|
|
|
5
5
|
import clsx from "clsx"
|
|
6
6
|
import React, { useCallback, useId, useState } from "react"
|
|
7
7
|
|
|
8
|
-
import { StandardSizes } from "
|
|
8
|
+
import { StandardSizes } from "../../types"
|
|
9
9
|
import { Button, type ButtonProps } from "../Button"
|
|
10
|
-
import { FieldLabel } from "../
|
|
10
|
+
import { Label as FieldLabel } from "../FieldMarkers/Label"
|
|
11
11
|
import { SearchIcon } from "../Icon"
|
|
12
12
|
import TextInput, { TextInputProps } from "../TextInput"
|
|
13
13
|
|
|
14
|
-
export interface
|
|
14
|
+
export interface SearchboxProps
|
|
15
15
|
extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
16
16
|
/** **(Optional)** Specify a server endpoint to submit the form. Will be ignored if onSubmit is also set. */
|
|
17
17
|
action?: string
|
|
@@ -27,13 +27,13 @@ export interface SearchBoxProps
|
|
|
27
27
|
labelVisible?: boolean
|
|
28
28
|
/** **(Optional)** Specify the TextInput name, also used as the URL search parameter. Defaults to `query`. */
|
|
29
29
|
name?: string
|
|
30
|
-
/** **(Optional)** Callback to run when the form is submitted. If this is an async function, it will be awaited and the
|
|
30
|
+
/** **(Optional)** Callback to run when the form is submitted. If this is an async function, it will be awaited and the Searchbox will be in a pending state until the promise is resolved. */
|
|
31
31
|
onSubmit?: React.FormEventHandler<HTMLElement> | undefined
|
|
32
32
|
/** **(Optional)** Specify the TextInput placeholder text Do not use in place of a form label. */
|
|
33
33
|
placeholder?: string
|
|
34
|
-
/** **(Optional)** Specify the
|
|
34
|
+
/** **(Optional)** Specify the Searchbox size. */
|
|
35
35
|
size?: StandardSizes
|
|
36
|
-
/** **(Optional)** Specify the
|
|
36
|
+
/** **(Optional)** Specify the Searchbox variant. */
|
|
37
37
|
variant?:
|
|
38
38
|
| "green"
|
|
39
39
|
| "blue"
|
|
@@ -45,18 +45,19 @@ export interface SearchBoxProps
|
|
|
45
45
|
| "grey-ghost"
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const defaultButtonProps:
|
|
48
|
+
const defaultButtonProps: SearchboxProps["button"] = {
|
|
49
49
|
label: React.createElement(SearchIcon, { alt: "Search", stroke: "currentColor", strokeWidth: 2 }),
|
|
50
50
|
loadingText: "",
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export const
|
|
53
|
+
export const Searchbox = ({
|
|
54
54
|
action,
|
|
55
55
|
"aria-placeholder": ariaPlaceholder,
|
|
56
56
|
autoCapitalize = "off",
|
|
57
57
|
autoComplete = "off",
|
|
58
58
|
button = defaultButtonProps,
|
|
59
59
|
className,
|
|
60
|
+
|
|
60
61
|
id,
|
|
61
62
|
label,
|
|
62
63
|
labelVisible = false,
|
|
@@ -66,7 +67,7 @@ export const SearchBox = ({
|
|
|
66
67
|
size = "md",
|
|
67
68
|
variant = "green",
|
|
68
69
|
...props
|
|
69
|
-
}:
|
|
70
|
+
}: SearchboxProps): JSX.Element => {
|
|
70
71
|
const [isPending, setIsPending] = useState(false)
|
|
71
72
|
const internalId = useId()
|
|
72
73
|
|
|
@@ -91,8 +92,8 @@ export const SearchBox = ({
|
|
|
91
92
|
|
|
92
93
|
const formProps = {
|
|
93
94
|
action: action ?? undefined,
|
|
94
|
-
className: clsx("coop-
|
|
95
|
-
|
|
95
|
+
className: clsx("coop-searchbox", className),
|
|
96
|
+
"data-size": size && size !== "md" ? size : undefined,
|
|
96
97
|
"data-variant": variant.length && variant !== "green" ? variant : undefined,
|
|
97
98
|
onSubmit: onSubmit ? handleSubmit : undefined,
|
|
98
99
|
}
|
|
@@ -124,12 +125,13 @@ export const SearchBox = ({
|
|
|
124
125
|
{label}
|
|
125
126
|
</FieldLabel>
|
|
126
127
|
)}
|
|
127
|
-
<div className="coop-
|
|
128
|
+
<div className="coop-searchbox--inner">
|
|
128
129
|
<TextInput {...inputProps} />
|
|
130
|
+
|
|
129
131
|
<Button {...buttonProps}>{button.label}</Button>
|
|
130
132
|
</div>
|
|
131
133
|
</form>
|
|
132
134
|
)
|
|
133
135
|
}
|
|
134
136
|
|
|
135
|
-
export default
|
|
137
|
+
export default Searchbox
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import type { InputHTMLAttributes, JSX } from "react"
|
|
2
2
|
|
|
3
3
|
import clsx from "clsx"
|
|
4
|
-
import { useId } from "react"
|
|
5
4
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { FieldHint } from "../FieldHint"
|
|
9
|
-
import { FieldLabel } from "../FieldLabel"
|
|
5
|
+
import { StandardSizes } from "../../../src/types"
|
|
6
|
+
import { useId } from "../../hooks/useId"
|
|
10
7
|
|
|
11
8
|
export interface TextInputProps
|
|
12
9
|
extends Omit<InputHTMLAttributes<HTMLInputElement>, "prefix" | "size" | "type"> {
|
|
@@ -14,24 +11,10 @@ export interface TextInputProps
|
|
|
14
11
|
className?: string
|
|
15
12
|
/** **(Optional)** Specify whether the TextInput should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
16
13
|
disabled?: boolean
|
|
17
|
-
/** **(Optional)** Specify the TextInput error state.
|
|
18
|
-
|
|
19
|
-
* This is an instance of `FormFieldError`. You can provide either an object with a `message` key, or a boolean value if you need to render the message independently.
|
|
20
|
-
*/
|
|
21
|
-
error?: FormFieldError
|
|
22
|
-
/** **(Optional)** Specify the TextInput hint.
|
|
23
|
-
*
|
|
24
|
-
* This text is rendered under the label to provide further guidance for users.
|
|
25
|
-
*/
|
|
26
|
-
hint?: string
|
|
14
|
+
/** **(Optional)** Specify the TextInput error state. */
|
|
15
|
+
error?: boolean
|
|
27
16
|
/** **(Optional)** Specify the TextInput id. Will be auto-generated if not set. */
|
|
28
17
|
id?: string
|
|
29
|
-
/** **(Optional)** Specify the TextInput label.
|
|
30
|
-
*
|
|
31
|
-
* This property is optional in case you need to render your own label, but all form elements *must* provide a label. */
|
|
32
|
-
label?: string
|
|
33
|
-
/** **(Optional)** Specify whether the label should be visible to humans or screen readers. */
|
|
34
|
-
labelVisible?: boolean
|
|
35
18
|
/** Specify the TextInput name. */
|
|
36
19
|
name: string
|
|
37
20
|
/** **(Optional)** Specify the TextInput placeholder text. Do not use in place of a form label. */
|
|
@@ -43,7 +26,19 @@ export interface TextInputProps
|
|
|
43
26
|
/** **(Optional)** Specify the suffix. It can be any valid JSX or string. */
|
|
44
27
|
suffix?: React.ReactNode
|
|
45
28
|
/** **(Optional)** Specify the TextInput type. */
|
|
46
|
-
type?:
|
|
29
|
+
type?:
|
|
30
|
+
| "text"
|
|
31
|
+
| "email"
|
|
32
|
+
| "number"
|
|
33
|
+
| "password"
|
|
34
|
+
| "search"
|
|
35
|
+
| "tel"
|
|
36
|
+
| "url"
|
|
37
|
+
| "date"
|
|
38
|
+
| "datetime-local"
|
|
39
|
+
| "week"
|
|
40
|
+
| "month"
|
|
41
|
+
| "time"
|
|
47
42
|
}
|
|
48
43
|
|
|
49
44
|
export const TextInput = ({
|
|
@@ -51,10 +46,7 @@ export const TextInput = ({
|
|
|
51
46
|
className,
|
|
52
47
|
disabled,
|
|
53
48
|
error = false,
|
|
54
|
-
hint,
|
|
55
49
|
id,
|
|
56
|
-
label,
|
|
57
|
-
labelVisible = true,
|
|
58
50
|
name,
|
|
59
51
|
placeholder,
|
|
60
52
|
prefix,
|
|
@@ -63,39 +55,26 @@ export const TextInput = ({
|
|
|
63
55
|
type = "text",
|
|
64
56
|
...props
|
|
65
57
|
}: TextInputProps): JSX.Element => {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
id = id ?? internalId
|
|
58
|
+
const uid = useId(id)
|
|
69
59
|
|
|
70
60
|
const componentProps = {
|
|
71
61
|
"aria-placeholder": placeholder ?? ariaPlaceholder ?? undefined,
|
|
72
62
|
className: clsx("coop-text-input", className),
|
|
73
|
-
"data-error": error
|
|
63
|
+
"data-error": error || undefined,
|
|
74
64
|
"data-size": size.length && size !== "md" ? size : undefined,
|
|
75
65
|
disabled,
|
|
76
|
-
id,
|
|
66
|
+
id: uid,
|
|
77
67
|
name,
|
|
78
68
|
placeholder,
|
|
79
69
|
type,
|
|
80
70
|
...props,
|
|
81
71
|
}
|
|
82
|
-
const formItemProps = { "aria-disabled": disabled ? true : undefined }
|
|
72
|
+
//const formItemProps = { "aria-disabled": disabled ? true : undefined }
|
|
83
73
|
return (
|
|
84
|
-
<div className="coop-
|
|
85
|
-
{
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
</FieldLabel>
|
|
89
|
-
)}
|
|
90
|
-
|
|
91
|
-
{hint && <FieldHint>{hint}</FieldHint>}
|
|
92
|
-
|
|
93
|
-
{typeof error === "object" && error?.message && <FieldError>{error.message}</FieldError>}
|
|
94
|
-
<div className="coop-text-input-wrapper">
|
|
95
|
-
{prefix && <span className="coop-text-input--prefix">{prefix}</span>}
|
|
96
|
-
<input {...componentProps} />
|
|
97
|
-
{suffix && <span className="coop-text-input--suffix">{suffix}</span>}
|
|
98
|
-
</div>
|
|
74
|
+
<div className="coop-text-input-wrapper">
|
|
75
|
+
{prefix && <span className="coop-text-input--prefix">{prefix}</span>}
|
|
76
|
+
<input {...componentProps} />
|
|
77
|
+
{suffix && <span className="coop-text-input--suffix">{suffix}</span>}
|
|
99
78
|
</div>
|
|
100
79
|
)
|
|
101
80
|
}
|