@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
|
@@ -4,7 +4,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
4
4
|
import clsx from 'clsx';
|
|
5
5
|
import React, { useState, useId, useCallback } from 'react';
|
|
6
6
|
import { Button } from '../Button/Button.js';
|
|
7
|
-
import {
|
|
7
|
+
import { Label } from '../FieldMarkers/Label.js';
|
|
8
8
|
import { SearchIcon } from '../Icon/SearchIcon.js';
|
|
9
9
|
import { TextInput } from '../TextInput/TextInput.js';
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ const defaultButtonProps = {
|
|
|
12
12
|
label: React.createElement(SearchIcon, { alt: "Search", stroke: "currentColor", strokeWidth: 2 }),
|
|
13
13
|
loadingText: "",
|
|
14
14
|
};
|
|
15
|
-
const
|
|
15
|
+
const Searchbox = ({ action, "aria-placeholder": ariaPlaceholder, autoCapitalize = "off", autoComplete = "off", button = defaultButtonProps, className, id, label, labelVisible = false, name = "query", onSubmit, placeholder, size = "md", variant = "green", ...props }) => {
|
|
16
16
|
var _a, _b;
|
|
17
17
|
const [isPending, setIsPending] = useState(false);
|
|
18
18
|
const internalId = useId();
|
|
@@ -31,8 +31,8 @@ const SearchBox = ({ action, "aria-placeholder": ariaPlaceholder, autoCapitalize
|
|
|
31
31
|
}, [onSubmit, isPending]);
|
|
32
32
|
const formProps = {
|
|
33
33
|
action: action !== null && action !== void 0 ? action : undefined,
|
|
34
|
-
className: clsx("coop-
|
|
35
|
-
|
|
34
|
+
className: clsx("coop-searchbox", className),
|
|
35
|
+
"data-size": size && size !== "md" ? size : undefined,
|
|
36
36
|
"data-variant": variant.length && variant !== "green" ? variant : undefined,
|
|
37
37
|
onSubmit: onSubmit ? handleSubmit : undefined,
|
|
38
38
|
};
|
|
@@ -54,7 +54,7 @@ const SearchBox = ({ action, "aria-placeholder": ariaPlaceholder, autoCapitalize
|
|
|
54
54
|
type: "search",
|
|
55
55
|
...props,
|
|
56
56
|
};
|
|
57
|
-
return (jsxs("form", { ...formProps, children: [label && (jsx(
|
|
57
|
+
return (jsxs("form", { ...formProps, children: [label && (jsx(Label, { htmlFor: id, isVisible: labelVisible, children: label })), jsxs("div", { className: "coop-searchbox--inner", children: [jsx(TextInput, { ...inputProps }), jsx(Button, { ...buttonProps, children: button.label })] })] }));
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
-
export {
|
|
60
|
+
export { Searchbox, Searchbox as default };
|
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
import type { InputHTMLAttributes, JSX } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { StandardSizes } from "../../../src/types";
|
|
3
3
|
export interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "prefix" | "size" | "type"> {
|
|
4
4
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
5
5
|
className?: string;
|
|
6
6
|
/** **(Optional)** Specify whether the TextInput should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
7
7
|
disabled?: boolean;
|
|
8
|
-
/** **(Optional)** Specify the TextInput error state.
|
|
9
|
-
|
|
10
|
-
* 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.
|
|
11
|
-
*/
|
|
12
|
-
error?: FormFieldError;
|
|
13
|
-
/** **(Optional)** Specify the TextInput hint.
|
|
14
|
-
*
|
|
15
|
-
* This text is rendered under the label to provide further guidance for users.
|
|
16
|
-
*/
|
|
17
|
-
hint?: string;
|
|
8
|
+
/** **(Optional)** Specify the TextInput error state. */
|
|
9
|
+
error?: boolean;
|
|
18
10
|
/** **(Optional)** Specify the TextInput id. Will be auto-generated if not set. */
|
|
19
11
|
id?: string;
|
|
20
|
-
/** **(Optional)** Specify the TextInput label.
|
|
21
|
-
*
|
|
22
|
-
* This property is optional in case you need to render your own label, but all form elements *must* provide a label. */
|
|
23
|
-
label?: string;
|
|
24
|
-
/** **(Optional)** Specify whether the label should be visible to humans or screen readers. */
|
|
25
|
-
labelVisible?: boolean;
|
|
26
12
|
/** Specify the TextInput name. */
|
|
27
13
|
name: string;
|
|
28
14
|
/** **(Optional)** Specify the TextInput placeholder text. Do not use in place of a form label. */
|
|
@@ -34,7 +20,7 @@ export interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElemen
|
|
|
34
20
|
/** **(Optional)** Specify the suffix. It can be any valid JSX or string. */
|
|
35
21
|
suffix?: React.ReactNode;
|
|
36
22
|
/** **(Optional)** Specify the TextInput type. */
|
|
37
|
-
type?: "text" | "email" | "number" | "password" | "search" | "tel" | "url";
|
|
23
|
+
type?: "text" | "email" | "number" | "password" | "search" | "tel" | "url" | "date" | "datetime-local" | "week" | "month" | "time";
|
|
38
24
|
}
|
|
39
|
-
export declare const TextInput: ({ "aria-placeholder": ariaPlaceholder, className, disabled, error,
|
|
25
|
+
export declare const TextInput: ({ "aria-placeholder": ariaPlaceholder, className, disabled, error, id, name, placeholder, prefix, size, suffix, type, ...props }: TextInputProps) => JSX.Element;
|
|
40
26
|
export default TextInput;
|
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import { useId } from '
|
|
4
|
-
import { FieldError } from '../FieldError/FieldError.js';
|
|
5
|
-
import { FieldHint } from '../FieldHint/FieldHint.js';
|
|
6
|
-
import { FieldLabel } from '../FieldLabel/FieldLabel.js';
|
|
3
|
+
import { useId } from '../../hooks/useId.js';
|
|
7
4
|
|
|
8
|
-
const TextInput = ({ "aria-placeholder": ariaPlaceholder, className, disabled, error = false,
|
|
5
|
+
const TextInput = ({ "aria-placeholder": ariaPlaceholder, className, disabled, error = false, id, name, placeholder, prefix, size = "md", suffix, type = "text", ...props }) => {
|
|
9
6
|
var _a;
|
|
10
|
-
const
|
|
11
|
-
id = id !== null && id !== void 0 ? id : internalId;
|
|
7
|
+
const uid = useId(id);
|
|
12
8
|
const componentProps = {
|
|
13
9
|
"aria-placeholder": (_a = placeholder !== null && placeholder !== void 0 ? placeholder : ariaPlaceholder) !== null && _a !== void 0 ? _a : undefined,
|
|
14
10
|
className: clsx("coop-text-input", className),
|
|
15
|
-
"data-error": error
|
|
11
|
+
"data-error": error || undefined,
|
|
16
12
|
"data-size": size.length && size !== "md" ? size : undefined,
|
|
17
13
|
disabled,
|
|
18
|
-
id,
|
|
14
|
+
id: uid,
|
|
19
15
|
name,
|
|
20
16
|
placeholder,
|
|
21
17
|
type,
|
|
22
18
|
...props,
|
|
23
19
|
};
|
|
24
|
-
const formItemProps = { "aria-disabled": disabled ? true : undefined }
|
|
25
|
-
return (jsxs("div", { className: "coop-
|
|
20
|
+
//const formItemProps = { "aria-disabled": disabled ? true : undefined }
|
|
21
|
+
return (jsxs("div", { className: "coop-text-input-wrapper", children: [prefix && jsx("span", { className: "coop-text-input--prefix", children: prefix }), jsx("input", { ...componentProps }), suffix && jsx("span", { className: "coop-text-input--suffix", children: suffix })] }));
|
|
26
22
|
};
|
|
27
23
|
|
|
28
24
|
export { TextInput, TextInput as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JSX, TextareaHTMLAttributes } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { StandardSizes } from "../../types";
|
|
3
3
|
export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
4
4
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
5
5
|
className?: string;
|
|
@@ -16,24 +16,10 @@ export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElemen
|
|
|
16
16
|
cutoff?: boolean;
|
|
17
17
|
/** **(Optional)** Specify whether the Textarea should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
18
18
|
disabled?: boolean;
|
|
19
|
-
/** **(Optional)** Specify the Textarea error state
|
|
20
|
-
|
|
21
|
-
* 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.
|
|
22
|
-
*/
|
|
23
|
-
error?: FormFieldError;
|
|
24
|
-
/** **(Optional)** Specify the Textarea hint.
|
|
25
|
-
*
|
|
26
|
-
* This text is rendered under the label to provide further guidance for users.
|
|
27
|
-
*/
|
|
28
|
-
hint?: string;
|
|
19
|
+
/** **(Optional)** Specify the Textarea error state */
|
|
20
|
+
error?: boolean;
|
|
29
21
|
/** **(Optional)** Specify the Textarea id. Will be auto-generated if not set. */
|
|
30
22
|
id?: string;
|
|
31
|
-
/** **(Optional)** Specify the Textarea label.
|
|
32
|
-
*
|
|
33
|
-
* This property is optional in case you need to render your own label, but all form elements *must* provide a label. */
|
|
34
|
-
label?: string;
|
|
35
|
-
/** **(Optional)** Specify whether the label should be visible to humans or screen readers. */
|
|
36
|
-
labelVisible?: boolean;
|
|
37
23
|
/** **(Optional)** Specify the Textarea maxLength. This is the maximum number of characters users can enter. */
|
|
38
24
|
maxLength?: number;
|
|
39
25
|
/** Specify the Textarea name. */
|
|
@@ -45,5 +31,5 @@ export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElemen
|
|
|
45
31
|
/** **(Optional)** Specify the Textarea size. */
|
|
46
32
|
size?: StandardSizes;
|
|
47
33
|
}
|
|
48
|
-
export declare const Textarea: ({ "aria-placeholder": ariaPlaceholder, className, cols, counter, cutoff, disabled, error,
|
|
34
|
+
export declare const Textarea: ({ "aria-placeholder": ariaPlaceholder, className, cols, counter, cutoff, disabled, error, id, maxLength, name, onChange: userOnChange, placeholder, rows, size, ...props }: TextareaProps) => JSX.Element;
|
|
49
35
|
export default Textarea;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import { useState } from 'react';
|
|
4
4
|
import { useDebounce } from '../../hooks/useDebounce.js';
|
|
5
|
-
import {
|
|
6
|
-
import { FieldHint } from '../FieldHint/FieldHint.js';
|
|
7
|
-
import { FieldLabel } from '../FieldLabel/FieldLabel.js';
|
|
5
|
+
import { useId } from '../../hooks/useId.js';
|
|
8
6
|
|
|
9
7
|
const DEBOUNCE_DELAY = 750;
|
|
10
8
|
const charCountMessage = (remaining) => {
|
|
11
9
|
return `You have ${Math.abs(remaining).toLocaleString()} ${Math.abs(remaining) === 1 ? "character" : "characters"} ${remaining < 0 ? "too many" : "remaining"}`;
|
|
12
10
|
};
|
|
13
|
-
const Textarea = ({ "aria-placeholder": ariaPlaceholder, className, cols = 30, counter = false, cutoff = false, disabled = false, error = false,
|
|
11
|
+
const Textarea = ({ "aria-placeholder": ariaPlaceholder, className, cols = 30, counter = false, cutoff = false, disabled = false, error = false, id, maxLength, name, onChange: userOnChange = undefined, placeholder, rows = 4, size = "md", ...props }) => {
|
|
14
12
|
var _a;
|
|
15
13
|
const internalId = useId();
|
|
16
14
|
id = id !== null && id !== void 0 ? id : internalId;
|
|
@@ -18,7 +16,7 @@ const Textarea = ({ "aria-placeholder": ariaPlaceholder, className, cols = 30, c
|
|
|
18
16
|
"aria-placeholder": (_a = placeholder !== null && placeholder !== void 0 ? placeholder : ariaPlaceholder) !== null && _a !== void 0 ? _a : undefined,
|
|
19
17
|
className: clsx("coop-textarea", className),
|
|
20
18
|
cols,
|
|
21
|
-
"data-error": error ?
|
|
19
|
+
"data-error": error !== null && error !== void 0 ? error : undefined,
|
|
22
20
|
"data-size": size.length && size !== "md" ? size : undefined,
|
|
23
21
|
disabled,
|
|
24
22
|
id,
|
|
@@ -30,14 +28,15 @@ const Textarea = ({ "aria-placeholder": ariaPlaceholder, className, cols = 30, c
|
|
|
30
28
|
};
|
|
31
29
|
const [remaining, setRemaining] = useState(maxLength);
|
|
32
30
|
const debouncedRemaining = useDebounce(remaining, DEBOUNCE_DELAY);
|
|
31
|
+
const showCounter = !disabled && counter && maxLength && remaining != null && debouncedRemaining != null;
|
|
33
32
|
const handleChange = (e) => {
|
|
34
33
|
maxLength && e.target && setRemaining(maxLength - e.target.value.length);
|
|
35
34
|
};
|
|
36
|
-
const formItemProps = { "aria-disabled": disabled ? true : undefined }
|
|
37
|
-
return (jsxs("div", { className: "coop-
|
|
35
|
+
// const formItemProps = { "aria-disabled": disabled ? true : undefined }
|
|
36
|
+
return (jsxs("div", { className: "coop-textarea-wrapper", children: [jsx("textarea", { ...componentProps, onChange: (e) => {
|
|
38
37
|
userOnChange === null || userOnChange === void 0 ? void 0 : userOnChange(e);
|
|
39
38
|
handleChange(e);
|
|
40
|
-
} }),
|
|
39
|
+
} }), showCounter && (jsxs(Fragment, { children: [jsx("small", { "aria-hidden": "true", className: "coop-textarea-counter", ...(remaining < 0 && { "data-error": true }), children: charCountMessage(remaining) }), jsx("span", { "aria-live": "polite", className: "sr-only", children: charCountMessage(debouncedRemaining) })] }))] }));
|
|
41
40
|
};
|
|
42
41
|
|
|
43
42
|
export { Textarea, Textarea as default };
|
|
@@ -2,5 +2,7 @@ import React from "react";
|
|
|
2
2
|
type Slots<T> = Record<keyof T, React.ReactNode>;
|
|
3
3
|
export declare function isKey<T extends object>(x: T, k: PropertyKey): k is keyof T;
|
|
4
4
|
export declare function getSlotName(node: React.ReactNode): string | false;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function useSlots<T>(componentSlots: Slots<T>, children: React.ReactNode, options?: {
|
|
6
|
+
collect?: string[];
|
|
7
|
+
}): Slots<T>;
|
|
6
8
|
export {};
|
|
@@ -8,11 +8,17 @@ function getSlotName(node) {
|
|
|
8
8
|
? node.type.name
|
|
9
9
|
: false;
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function useSlots(componentSlots, children, options) {
|
|
12
12
|
return React.Children.toArray(children).reduce((slots, child) => {
|
|
13
|
+
var _a;
|
|
13
14
|
const slotName = getSlotName(child);
|
|
14
15
|
if (child && slotName && isKey(componentSlots, slotName)) {
|
|
15
|
-
|
|
16
|
+
if ((_a = void 0 ) === null || _a === void 0 ? void 0 : _a.includes(slotName)) {
|
|
17
|
+
slots[slotName] = slots[slotName] ? [...[slots[slotName]].flat(), child] : [child];
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
slots[slotName] = child;
|
|
21
|
+
}
|
|
16
22
|
}
|
|
17
23
|
else if ("Children" in slots) {
|
|
18
24
|
slots.Children = slots.Children ? [...[slots.Children].flat(), child] : [child];
|
|
@@ -21,4 +27,4 @@ function getSlots(componentSlots, children) {
|
|
|
21
27
|
}, { ...componentSlots });
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
export { getSlotName,
|
|
30
|
+
export { getSlotName, isKey, useSlots };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,15 +5,13 @@ export * from "./components/Card";
|
|
|
5
5
|
export * from "./components/Checkbox";
|
|
6
6
|
export * from "./components/Expandable";
|
|
7
7
|
export * from "./components/Field";
|
|
8
|
-
export * from "./components/
|
|
9
|
-
export * from "./components/FieldHint";
|
|
10
|
-
export * from "./components/FieldLabel";
|
|
8
|
+
export * from "./components/Fieldset";
|
|
11
9
|
export * from "./components/Flourish";
|
|
12
10
|
export * from "./components/Image";
|
|
13
11
|
export * from "./components/Pill";
|
|
14
|
-
export * from "./components/
|
|
12
|
+
export * from "./components/Radio";
|
|
15
13
|
export * from "./components/RootSVG";
|
|
16
|
-
export * from "./components/
|
|
14
|
+
export * from "./components/Searchbox";
|
|
17
15
|
export * from "./components/Signpost";
|
|
18
16
|
export * from "./components/SkipNav";
|
|
19
17
|
export * from "./components/Squircle";
|
package/dist/index.js
CHANGED
|
@@ -3,19 +3,15 @@ export { Author } from './components/Author/Author.js';
|
|
|
3
3
|
export { Button } from './components/Button/Button.js';
|
|
4
4
|
export { Card } from './components/Card/Card.js';
|
|
5
5
|
export { Checkbox } from './components/Checkbox/Checkbox.js';
|
|
6
|
-
export { CheckboxGroup } from './components/Checkbox/CheckboxGroup.js';
|
|
7
6
|
export { Expandable } from './components/Expandable/Expandable.js';
|
|
8
|
-
export { Field } from './components/Field/Field.js';
|
|
9
|
-
export {
|
|
10
|
-
export { FieldHint } from './components/FieldHint/FieldHint.js';
|
|
11
|
-
export { FieldLabel } from './components/FieldLabel/FieldLabel.js';
|
|
7
|
+
export { Field, FieldControl } from './components/Field/Field.js';
|
|
8
|
+
export { Fieldset, FieldsetFields } from './components/Fieldset/Fieldset.js';
|
|
12
9
|
export { Flourish } from './components/Flourish/Flourish.js';
|
|
13
10
|
export { Image } from './components/Image/Image.js';
|
|
14
11
|
export { Pill } from './components/Pill/Pill.js';
|
|
15
|
-
export {
|
|
16
|
-
export { RadioButtonGroup } from './components/RadioButton/RadioButtonGroup.js';
|
|
12
|
+
export { Radio } from './components/Radio/Radio.js';
|
|
17
13
|
export { RootSVG } from './components/RootSVG/RootSVG.js';
|
|
18
|
-
export {
|
|
14
|
+
export { Searchbox } from './components/Searchbox/Searchbox.js';
|
|
19
15
|
export { Signpost } from './components/Signpost/Signpost.js';
|
|
20
16
|
export { SkipNav } from './components/SkipNav/SkipNav.js';
|
|
21
17
|
export { Squircle } from './components/Squircle/Squircle.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coopdigital/react",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.46.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -57,18 +57,18 @@
|
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@axe-core/playwright": "^4.11.0",
|
|
59
59
|
"@playwright/test": "^1.56.1",
|
|
60
|
-
"@storybook/addon-a11y": "^10.0.
|
|
61
|
-
"@storybook/addon-docs": "^10.0.
|
|
62
|
-
"@storybook/addon-onboarding": "^10.0.
|
|
63
|
-
"@storybook/react-vite": "^10.0.
|
|
60
|
+
"@storybook/addon-a11y": "^10.0.7",
|
|
61
|
+
"@storybook/addon-docs": "^10.0.7",
|
|
62
|
+
"@storybook/addon-onboarding": "^10.0.7",
|
|
63
|
+
"@storybook/react-vite": "^10.0.7",
|
|
64
64
|
"@testing-library/jest-dom": "^6.9.1",
|
|
65
65
|
"@testing-library/react": "^16.3.0",
|
|
66
|
-
"@types/react": "^19.2.
|
|
67
|
-
"@types/react-dom": "^19.2.
|
|
66
|
+
"@types/react": "^19.2.4",
|
|
67
|
+
"@types/react-dom": "^19.2.3",
|
|
68
68
|
"react": "^19.2.0",
|
|
69
69
|
"react-dom": "^19.2.0",
|
|
70
70
|
"serve": "^14.2.5",
|
|
71
|
-
"storybook": "^10.0.
|
|
71
|
+
"storybook": "^10.0.7"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"react": "^19.1.0",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"storybook": "$storybook"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@coopdigital/styles": "^0.
|
|
81
|
+
"@coopdigital/styles": "^0.40.0",
|
|
82
82
|
"clsx": "^2.1.1"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "9020e79195ead8270e9a2c39209142a02160bae5"
|
|
85
85
|
}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
AnchorHTMLAttributes,
|
|
5
|
-
ButtonHTMLAttributes,
|
|
6
|
-
ForwardRefExoticComponent,
|
|
7
|
-
JSX,
|
|
8
|
-
} from "react"
|
|
3
|
+
import type { ButtonHTMLAttributes, ForwardRefExoticComponent, JSX, Ref } from "react"
|
|
9
4
|
|
|
10
5
|
import clsx from "clsx"
|
|
11
6
|
import React, { useCallback, useState } from "react"
|
|
@@ -15,7 +10,7 @@ import { LoadingIcon } from "../Icon"
|
|
|
15
10
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
16
11
|
/** **(Optional)** Specify a custom element to override default `a` or `button`. */
|
|
17
12
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
-
as?: React.FC<
|
|
13
|
+
as?: React.FC<any> | ForwardRefExoticComponent<any> | string
|
|
19
14
|
/** **(Optional)** Main content inside the component. It can be any valid JSX or string. */
|
|
20
15
|
children?: React.ReactNode
|
|
21
16
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
@@ -31,7 +26,9 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
31
26
|
/** **(Optional)** Specify text to show when the Button is in a loading state. */
|
|
32
27
|
loadingText?: string
|
|
33
28
|
/** **(Optional)** Callback to run when the button is pressed. If this is an async function, it will be awaited and the button will be in a pending state until the promise is resolved. */
|
|
34
|
-
onClick?:
|
|
29
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>
|
|
30
|
+
/** **(Optional)** Specify a custom React ref for this component. */
|
|
31
|
+
ref?: Ref<HTMLButtonElement | HTMLAnchorElement>
|
|
35
32
|
/** **(Optional)** Specify the Button size. */
|
|
36
33
|
size?: "sm" | "md" | "lg"
|
|
37
34
|
/** **(Optional)** Specify the Button variant. */
|
|
@@ -61,14 +58,12 @@ export const Button = ({
|
|
|
61
58
|
isLoading = false,
|
|
62
59
|
loadingText = "Loading",
|
|
63
60
|
onClick,
|
|
61
|
+
ref,
|
|
64
62
|
size = "md",
|
|
65
63
|
variant = "green",
|
|
66
64
|
...props
|
|
67
65
|
}: ButtonProps): JSX.Element => {
|
|
68
|
-
|
|
69
|
-
if (as) {
|
|
70
|
-
element = as
|
|
71
|
-
}
|
|
66
|
+
const element: ButtonProps["as"] = as ?? (href ? "a" : "button")
|
|
72
67
|
|
|
73
68
|
const [isPending, setIsPending] = useState(false)
|
|
74
69
|
|
|
@@ -79,7 +74,7 @@ export const Button = ({
|
|
|
79
74
|
setIsPending(true)
|
|
80
75
|
|
|
81
76
|
try {
|
|
82
|
-
await Promise.resolve(onClick(event
|
|
77
|
+
await Promise.resolve(onClick(event))
|
|
83
78
|
} finally {
|
|
84
79
|
setIsPending(false)
|
|
85
80
|
}
|
|
@@ -96,7 +91,8 @@ export const Button = ({
|
|
|
96
91
|
"data-variant": variant !== "text" ? variant : undefined,
|
|
97
92
|
"data-width": isFullWidth ? "full" : undefined,
|
|
98
93
|
href,
|
|
99
|
-
onClick: handleClick,
|
|
94
|
+
onClick: onClick ? handleClick : undefined,
|
|
95
|
+
ref,
|
|
100
96
|
...props,
|
|
101
97
|
}
|
|
102
98
|
|
|
@@ -3,7 +3,7 @@ import type { ForwardRefExoticComponent, HTMLAttributes, JSX } from "react"
|
|
|
3
3
|
import clsx from "clsx"
|
|
4
4
|
import React from "react"
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { useSlots } from "../../hooks/useSlots"
|
|
7
7
|
import { ChevronRightIcon } from "../Icon/ChevronRightIcon"
|
|
8
8
|
import { Image, ImageProps } from "../Image"
|
|
9
9
|
|
|
@@ -91,8 +91,7 @@ export const Card = ({
|
|
|
91
91
|
}: CardProps): JSX.Element => {
|
|
92
92
|
const { element: linkElement, props: linkProps } = getCardLinkElement(hrefAs, href)
|
|
93
93
|
|
|
94
|
-
const slots =
|
|
95
|
-
|
|
94
|
+
const slots = { ...useSlots(componentSlots, children) }
|
|
96
95
|
const innerProps = { className: "coop-card--inner" }
|
|
97
96
|
const hasLinkWrapper = href && !slots.CardHeading
|
|
98
97
|
|
|
@@ -1,13 +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"
|
|
10
|
-
import Tag from "../Tag"
|
|
5
|
+
import { StandardSizes } from "../../../src/types"
|
|
6
|
+
import { useId } from "../../hooks/useId"
|
|
11
7
|
|
|
12
8
|
export interface CheckboxProps
|
|
13
9
|
extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
@@ -15,89 +11,37 @@ export interface CheckboxProps
|
|
|
15
11
|
className?: string
|
|
16
12
|
/** **(Optional)** Specify whether the Checkbox should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
17
13
|
disabled?: boolean
|
|
18
|
-
/** **(Optional)** Specify the Checkbox error state.
|
|
19
|
-
|
|
20
|
-
* 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.
|
|
21
|
-
*/
|
|
22
|
-
error?: FormFieldError
|
|
23
|
-
/** **(Optional)** Specify the Checkbox hint.
|
|
24
|
-
*
|
|
25
|
-
* This text is rendered under the label to provide further guidance for users.
|
|
26
|
-
*/
|
|
27
|
-
hint?: string
|
|
14
|
+
/** **(Optional)** Specify the Checkbox error state. */
|
|
15
|
+
error?: boolean
|
|
28
16
|
/** **(Optional)** Specify the Checkbox id. Will be auto-generated if not set. */
|
|
29
17
|
id?: string
|
|
30
|
-
/** **(Optional)** Specify the Checkbox label.
|
|
31
|
-
*
|
|
32
|
-
* This property is optional in case you need to render your own label, but all form elements *must* provide a label. */
|
|
33
|
-
label: string
|
|
34
|
-
/** **(Optional)** Specify whether the label should be visible to humans or screen readers. */
|
|
35
|
-
labelVisible?: boolean
|
|
36
18
|
/** Specify the Checkbox name. */
|
|
37
19
|
name: string
|
|
38
20
|
/** **(Optional)** Specify the Checkbox size. */
|
|
39
21
|
size?: StandardSizes
|
|
40
|
-
/** **(Optional)** Specify the Checkbox tag text. */
|
|
41
|
-
tag?: string
|
|
42
|
-
/** **(Optional)** Specify the Checkbox tag className. */
|
|
43
|
-
tagClassName?: string
|
|
44
|
-
/** **(Optional)** Specify the Checkbox variant. */
|
|
45
|
-
variant?: "default" | "boxed"
|
|
46
22
|
}
|
|
47
23
|
|
|
48
24
|
export const Checkbox = ({
|
|
49
25
|
className,
|
|
50
26
|
disabled,
|
|
51
27
|
error = false,
|
|
52
|
-
hint,
|
|
53
28
|
id,
|
|
54
|
-
label,
|
|
55
|
-
labelVisible = true,
|
|
56
29
|
name,
|
|
57
30
|
size = "md",
|
|
58
|
-
tag,
|
|
59
|
-
tagClassName,
|
|
60
|
-
variant = "default",
|
|
61
31
|
...props
|
|
62
32
|
}: CheckboxProps): JSX.Element => {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
id = id ?? internalId
|
|
66
|
-
|
|
33
|
+
const uid = useId(id)
|
|
67
34
|
const componentProps = {
|
|
68
35
|
className: clsx("coop-checkbox", className),
|
|
69
|
-
"data-error": error
|
|
36
|
+
"data-error": error || undefined,
|
|
70
37
|
"data-size": size.length && size !== "md" ? size : undefined,
|
|
71
|
-
"data-variant": variant !== "default" ? variant : undefined,
|
|
72
38
|
disabled,
|
|
73
|
-
id,
|
|
39
|
+
id: uid,
|
|
74
40
|
name,
|
|
75
41
|
type: "checkbox",
|
|
76
42
|
...props,
|
|
77
43
|
}
|
|
78
|
-
|
|
79
|
-
return (
|
|
80
|
-
<div className="coop-form-item" {...formItemProps}>
|
|
81
|
-
<div className="coop-checkbox-wrapper">
|
|
82
|
-
<div className="coop-checkbox-input-wrapper">
|
|
83
|
-
<input {...componentProps} />
|
|
84
|
-
|
|
85
|
-
{label && (
|
|
86
|
-
<FieldLabel htmlFor={id} isVisible={labelVisible}>
|
|
87
|
-
<span>{label}</span>{" "}
|
|
88
|
-
{tag && (
|
|
89
|
-
<Tag className={tagClassName} size="sm">
|
|
90
|
-
{tag}
|
|
91
|
-
</Tag>
|
|
92
|
-
)}
|
|
93
|
-
</FieldLabel>
|
|
94
|
-
)}
|
|
95
|
-
</div>
|
|
96
|
-
{hint && <FieldHint>{hint}</FieldHint>}
|
|
97
|
-
</div>
|
|
98
|
-
{typeof error === "object" && error?.message && <FieldError>{error.message}</FieldError>}
|
|
99
|
-
</div>
|
|
100
|
-
)
|
|
44
|
+
return <input {...componentProps} />
|
|
101
45
|
}
|
|
102
46
|
|
|
103
47
|
export default Checkbox
|
|
@@ -2,8 +2,8 @@ import type { DetailsHTMLAttributes, HTMLAttributes, JSX } from "react"
|
|
|
2
2
|
|
|
3
3
|
import { clsx } from "clsx"
|
|
4
4
|
|
|
5
|
+
import { useSlots } from "../../hooks/useSlots"
|
|
5
6
|
import { bgClassToColor, hasUserBg } from "../../utils"
|
|
6
|
-
import { getSlots } from "../../utils/slots"
|
|
7
7
|
import { ChevronDownIcon } from "../Icon"
|
|
8
8
|
|
|
9
9
|
export interface ExpandableProps extends DetailsHTMLAttributes<HTMLDetailsElement> {
|
|
@@ -26,7 +26,7 @@ const componentSlots = {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export const Expandable = ({ children, className, ...props }: ExpandableProps): JSX.Element => {
|
|
29
|
-
const slots =
|
|
29
|
+
const slots = useSlots(componentSlots, children)
|
|
30
30
|
|
|
31
31
|
const componentProps = {
|
|
32
32
|
className: clsx("coop-expandable", !hasUserBg(className) && "bg-tint-grey", className),
|