@coopdigital/react 0.45.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/Expandable/Expandable.js +2 -2
- package/dist/components/Field/Field.js +4 -4
- package/dist/components/Pill/Pill.js +2 -2
- package/dist/components/Radio/Radio.d.ts +18 -0
- package/dist/components/{RadioButton/RadioButton.js → Radio/Radio.js} +3 -3
- 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} +4 -4
- package/dist/components/Searchbox/index.d.ts +4 -0
- package/dist/components/TextInput/TextInput.d.ts +1 -1
- package/dist/{utils/slots.d.ts → hooks/useSlots.d.ts} +1 -1
- package/dist/{utils/slots.js → hooks/useSlots.js} +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +3 -3
- package/src/components/Button/Button.tsx +10 -14
- package/src/components/Card/Card.tsx +2 -3
- package/src/components/Expandable/Expandable.tsx +2 -2
- package/src/components/Field/Field.tsx +4 -4
- package/src/components/Pill/Pill.tsx +2 -2
- package/src/components/{RadioButton/RadioButton.tsx → Radio/Radio.tsx} +10 -11
- package/src/components/Radio/index.ts +5 -0
- package/src/components/{SearchBox/SearchBox.tsx → Searchbox/Searchbox.tsx} +11 -11
- package/src/components/Searchbox/index.ts +5 -0
- package/src/components/TextInput/TextInput.tsx +13 -1
- package/src/{utils/slots.ts → hooks/useSlots.ts} +1 -1
- package/src/index.ts +2 -2
- package/dist/components/RadioButton/RadioButton.d.ts +0 -18
- package/dist/components/RadioButton/index.d.ts +0 -4
- package/dist/components/SearchBox/index.d.ts +0 -4
- package/src/components/RadioButton/index.ts +0 -5
- package/src/components/SearchBox/index.ts +0 -5
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ButtonHTMLAttributes, ForwardRefExoticComponent, JSX, Ref } from "react";
|
|
2
2
|
import React from "react";
|
|
3
3
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
4
|
/** **(Optional)** Specify a custom element to override default `a` or `button`. */
|
|
5
|
-
as?: React.FC<
|
|
5
|
+
as?: React.FC<any> | ForwardRefExoticComponent<any> | string;
|
|
6
6
|
/** **(Optional)** Main content inside the component. It can be any valid JSX or string. */
|
|
7
7
|
children?: React.ReactNode;
|
|
8
8
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
@@ -18,11 +18,13 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
18
18
|
/** **(Optional)** Specify text to show when the Button is in a loading state. */
|
|
19
19
|
loadingText?: string;
|
|
20
20
|
/** **(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. */
|
|
21
|
-
onClick?:
|
|
21
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;
|
|
22
|
+
/** **(Optional)** Specify a custom React ref for this component. */
|
|
23
|
+
ref?: Ref<HTMLButtonElement | HTMLAnchorElement>;
|
|
22
24
|
/** **(Optional)** Specify the Button size. */
|
|
23
25
|
size?: "sm" | "md" | "lg";
|
|
24
26
|
/** **(Optional)** Specify the Button variant. */
|
|
25
27
|
variant?: "green" | "blue" | "white" | "grey" | "green-ghost" | "blue-ghost" | "white-ghost" | "grey-ghost" | "text";
|
|
26
28
|
}
|
|
27
|
-
export declare const Button: ({ as, children, className, href, isDisabled, isFullWidth, isLoading, loadingText, onClick, size, variant, ...props }: ButtonProps) => JSX.Element;
|
|
29
|
+
export declare const Button: ({ as, children, className, href, isDisabled, isFullWidth, isLoading, loadingText, onClick, ref, size, variant, ...props }: ButtonProps) => JSX.Element;
|
|
28
30
|
export default Button;
|
|
@@ -5,11 +5,8 @@ import clsx from 'clsx';
|
|
|
5
5
|
import React, { useState, useCallback } from 'react';
|
|
6
6
|
import { LoadingIcon } from '../Icon/LoadingIcon.js';
|
|
7
7
|
|
|
8
|
-
const Button = ({ as, children, className, href, isDisabled = false, isFullWidth = false, isLoading = false, loadingText = "Loading", onClick, size = "md", variant = "green", ...props }) => {
|
|
9
|
-
|
|
10
|
-
if (as) {
|
|
11
|
-
element = as;
|
|
12
|
-
}
|
|
8
|
+
const Button = ({ as, children, className, href, isDisabled = false, isFullWidth = false, isLoading = false, loadingText = "Loading", onClick, ref, size = "md", variant = "green", ...props }) => {
|
|
9
|
+
const element = as !== null && as !== void 0 ? as : (href ? "a" : "button");
|
|
13
10
|
const [isPending, setIsPending] = useState(false);
|
|
14
11
|
const handleClick = useCallback(async (event) => {
|
|
15
12
|
if (isPending || !onClick)
|
|
@@ -31,7 +28,8 @@ const Button = ({ as, children, className, href, isDisabled = false, isFullWidth
|
|
|
31
28
|
"data-variant": variant !== "text" ? variant : undefined,
|
|
32
29
|
"data-width": isFullWidth ? "full" : undefined,
|
|
33
30
|
href,
|
|
34
|
-
onClick: handleClick,
|
|
31
|
+
onClick: onClick ? handleClick : undefined,
|
|
32
|
+
ref,
|
|
35
33
|
...props,
|
|
36
34
|
};
|
|
37
35
|
const finalChildren = isPending || isLoading ? (jsxs(Fragment, { children: [loadingText, jsx(LoadingIcon, {})] })) : (children);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { useSlots } from '../../hooks/useSlots.js';
|
|
5
5
|
import { ChevronRightIcon } from '../Icon/ChevronRightIcon.js';
|
|
6
6
|
import { Image } from '../Image/Image.js';
|
|
7
7
|
|
|
@@ -24,7 +24,7 @@ function getCardLinkElement(as, href) {
|
|
|
24
24
|
}
|
|
25
25
|
const Card = ({ chevron = false, children, className, href, hrefAs, imagePosition = "left", orientation = "vertical", ...props }) => {
|
|
26
26
|
const { element: linkElement, props: linkProps } = getCardLinkElement(hrefAs, href);
|
|
27
|
-
const slots =
|
|
27
|
+
const slots = { ...useSlots(componentSlots, children) };
|
|
28
28
|
const innerProps = { className: "coop-card--inner" };
|
|
29
29
|
const hasLinkWrapper = href && !slots.CardHeading;
|
|
30
30
|
const componentProps = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
|
+
import { useSlots } from '../../hooks/useSlots.js';
|
|
3
4
|
import { hasUserBg, bgClassToColor } from '../../utils/index.js';
|
|
4
|
-
import { getSlots } from '../../utils/slots.js';
|
|
5
5
|
import 'react';
|
|
6
6
|
import { ChevronDownIcon } from '../Icon/ChevronDownIcon.js';
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ const componentSlots = {
|
|
|
10
10
|
ExpandableSummary: null,
|
|
11
11
|
};
|
|
12
12
|
const Expandable = ({ children, className, ...props }) => {
|
|
13
|
-
const slots =
|
|
13
|
+
const slots = useSlots(componentSlots, children);
|
|
14
14
|
const componentProps = {
|
|
15
15
|
className: clsx("coop-expandable", !hasUserBg(className) && "bg-tint-grey", className),
|
|
16
16
|
...props,
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { useId } from '../../hooks/useId.js';
|
|
5
|
-
import {
|
|
5
|
+
import { useSlots } from '../../hooks/useSlots.js';
|
|
6
6
|
import { Error } from '../FieldMarkers/Error.js';
|
|
7
7
|
import { Hint } from '../FieldMarkers/Hint.js';
|
|
8
8
|
import { Label } from '../FieldMarkers/Label.js';
|
|
@@ -14,15 +14,15 @@ const componentSlots = {
|
|
|
14
14
|
FieldError: null,
|
|
15
15
|
FieldHint: null,
|
|
16
16
|
FieldLabel: null,
|
|
17
|
-
|
|
17
|
+
Radio: null,
|
|
18
18
|
Textarea: null,
|
|
19
19
|
TextInput: null,
|
|
20
20
|
};
|
|
21
21
|
const standardFields = ["Children", "FieldError", "FieldHint", "FieldLabel"];
|
|
22
|
-
const inlineFields = ["Checkbox", "
|
|
22
|
+
const inlineFields = ["Checkbox", "Radio"];
|
|
23
23
|
const Root = ({ boxed = false, children, className, error = false, hideErrorBar = false, ...props }) => {
|
|
24
24
|
var _a, _b, _c, _d, _e, _f;
|
|
25
|
-
const slots =
|
|
25
|
+
const slots = { ...useSlots(componentSlots, children) };
|
|
26
26
|
const slotsArray = Object.entries(slots);
|
|
27
27
|
const uid = useId();
|
|
28
28
|
const isInlineControl = slotsArray.some((s) => s[1] !== null && inlineFields.includes(s[0]));
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import React from 'react';
|
|
4
|
+
import { useSlots } from '../../hooks/useSlots.js';
|
|
4
5
|
import { hasUserBg } from '../../utils/index.js';
|
|
5
|
-
import { getSlots } from '../../utils/slots.js';
|
|
6
6
|
|
|
7
7
|
const componentSlots = {
|
|
8
8
|
Children: null,
|
|
@@ -10,7 +10,7 @@ const componentSlots = {
|
|
|
10
10
|
};
|
|
11
11
|
const Pill = ({ as, children, className, href, size = "md", ...props }) => {
|
|
12
12
|
let element = href ? "a" : "span";
|
|
13
|
-
const slots =
|
|
13
|
+
const slots = useSlots(componentSlots, children);
|
|
14
14
|
if (as) {
|
|
15
15
|
element = as;
|
|
16
16
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type InputHTMLAttributes, type JSX } from "react";
|
|
2
|
+
import { StandardSizes } from "src/types";
|
|
3
|
+
export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
4
|
+
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
5
|
+
className?: string;
|
|
6
|
+
/** **(Optional)** Specify whether the Radio should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
/** **(Optional)** Specify the Radio error state. */
|
|
9
|
+
error?: boolean;
|
|
10
|
+
/** **(Optional)** Specify the Radio id. Will be auto-generated if not set. */
|
|
11
|
+
id?: string;
|
|
12
|
+
/** Specify the Radio name. */
|
|
13
|
+
name: string;
|
|
14
|
+
/** **(Optional)** Specify the Radio size. */
|
|
15
|
+
size?: StandardSizes;
|
|
16
|
+
}
|
|
17
|
+
export declare const Radio: ({ className, disabled, error, id, name, size, ...props }: RadioProps) => JSX.Element;
|
|
18
|
+
export default Radio;
|
|
@@ -2,11 +2,11 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { useId } from 'react';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const Radio = ({ className, disabled, error = false, id, name, size = "md", ...props }) => {
|
|
6
6
|
const internalId = useId();
|
|
7
7
|
id = id !== null && id !== void 0 ? id : internalId;
|
|
8
8
|
const componentProps = {
|
|
9
|
-
className: clsx("coop-radio
|
|
9
|
+
className: clsx("coop-radio", className),
|
|
10
10
|
"data-error": error || undefined,
|
|
11
11
|
"data-size": size.length && size !== "md" ? size : undefined,
|
|
12
12
|
disabled,
|
|
@@ -19,4 +19,4 @@ const RadioButton = ({ className, disabled, error = false, id, name, size = "md"
|
|
|
19
19
|
return jsx("input", { ...componentProps });
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
export {
|
|
22
|
+
export { Radio, Radio as default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { InputHTMLAttributes, JSX } from "react";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { StandardSizes } from "
|
|
3
|
+
import { StandardSizes } from "../../types";
|
|
4
4
|
import { type ButtonProps } from "../Button";
|
|
5
|
-
export interface
|
|
5
|
+
export interface SearchboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
6
6
|
/** **(Optional)** Specify a server endpoint to submit the form. Will be ignored if onSubmit is also set. */
|
|
7
7
|
action?: string;
|
|
8
8
|
/** **(Optional)** Specify props to forward to the Button element. Use `label` to set Button text. */
|
|
@@ -19,14 +19,14 @@ export interface SearchBoxProps extends Omit<InputHTMLAttributes<HTMLInputElemen
|
|
|
19
19
|
labelVisible?: boolean;
|
|
20
20
|
/** **(Optional)** Specify the TextInput name, also used as the URL search parameter. Defaults to `query`. */
|
|
21
21
|
name?: string;
|
|
22
|
-
/** **(Optional)** Callback to run when the form is submitted. If this is an async function, it will be awaited and the
|
|
22
|
+
/** **(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. */
|
|
23
23
|
onSubmit?: React.FormEventHandler<HTMLElement> | undefined;
|
|
24
24
|
/** **(Optional)** Specify the TextInput placeholder text Do not use in place of a form label. */
|
|
25
25
|
placeholder?: string;
|
|
26
|
-
/** **(Optional)** Specify the
|
|
26
|
+
/** **(Optional)** Specify the Searchbox size. */
|
|
27
27
|
size?: StandardSizes;
|
|
28
|
-
/** **(Optional)** Specify the
|
|
28
|
+
/** **(Optional)** Specify the Searchbox variant. */
|
|
29
29
|
variant?: "green" | "blue" | "white" | "grey" | "green-ghost" | "blue-ghost" | "white-ghost" | "grey-ghost";
|
|
30
30
|
}
|
|
31
|
-
export declare const
|
|
32
|
-
export default
|
|
31
|
+
export declare const Searchbox: ({ action, "aria-placeholder": ariaPlaceholder, autoCapitalize, autoComplete, button, className, id, label, labelVisible, name, onSubmit, placeholder, size, variant, ...props }: SearchboxProps) => JSX.Element;
|
|
32
|
+
export default Searchbox;
|
|
@@ -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,7 +31,7 @@ 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-
|
|
34
|
+
className: clsx("coop-searchbox", className),
|
|
35
35
|
"data-size": size && size !== "md" ? size : undefined,
|
|
36
36
|
"data-variant": variant.length && variant !== "green" ? variant : undefined,
|
|
37
37
|
onSubmit: onSubmit ? handleSubmit : undefined,
|
|
@@ -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(Label, { htmlFor: id, isVisible: labelVisible, children: label })), jsxs("div", { className: "coop-
|
|
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 };
|
|
@@ -20,7 +20,7 @@ export interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElemen
|
|
|
20
20
|
/** **(Optional)** Specify the suffix. It can be any valid JSX or string. */
|
|
21
21
|
suffix?: React.ReactNode;
|
|
22
22
|
/** **(Optional)** Specify the TextInput type. */
|
|
23
|
-
type?: "text" | "email" | "number" | "password" | "search" | "tel" | "url";
|
|
23
|
+
type?: "text" | "email" | "number" | "password" | "search" | "tel" | "url" | "date" | "datetime-local" | "week" | "month" | "time";
|
|
24
24
|
}
|
|
25
25
|
export declare const TextInput: ({ "aria-placeholder": ariaPlaceholder, className, disabled, error, id, name, placeholder, prefix, size, suffix, type, ...props }: TextInputProps) => JSX.Element;
|
|
26
26
|
export default TextInput;
|
|
@@ -2,7 +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
6
|
collect?: string[];
|
|
7
7
|
}): Slots<T>;
|
|
8
8
|
export {};
|
|
@@ -8,7 +8,7 @@ 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
13
|
var _a;
|
|
14
14
|
const slotName = getSlotName(child);
|
|
@@ -27,4 +27,4 @@ function getSlots(componentSlots, children, options) {
|
|
|
27
27
|
}, { ...componentSlots });
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export { getSlotName,
|
|
30
|
+
export { getSlotName, isKey, useSlots };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,9 +9,9 @@ export * from "./components/Fieldset";
|
|
|
9
9
|
export * from "./components/Flourish";
|
|
10
10
|
export * from "./components/Image";
|
|
11
11
|
export * from "./components/Pill";
|
|
12
|
-
export * from "./components/
|
|
12
|
+
export * from "./components/Radio";
|
|
13
13
|
export * from "./components/RootSVG";
|
|
14
|
-
export * from "./components/
|
|
14
|
+
export * from "./components/Searchbox";
|
|
15
15
|
export * from "./components/Signpost";
|
|
16
16
|
export * from "./components/SkipNav";
|
|
17
17
|
export * from "./components/Squircle";
|
package/dist/index.js
CHANGED
|
@@ -9,9 +9,9 @@ export { Fieldset, FieldsetFields } from './components/Fieldset/Fieldset.js';
|
|
|
9
9
|
export { Flourish } from './components/Flourish/Flourish.js';
|
|
10
10
|
export { Image } from './components/Image/Image.js';
|
|
11
11
|
export { Pill } from './components/Pill/Pill.js';
|
|
12
|
-
export {
|
|
12
|
+
export { Radio } from './components/Radio/Radio.js';
|
|
13
13
|
export { RootSVG } from './components/RootSVG/RootSVG.js';
|
|
14
|
-
export {
|
|
14
|
+
export { Searchbox } from './components/Searchbox/Searchbox.js';
|
|
15
15
|
export { Signpost } from './components/Signpost/Signpost.js';
|
|
16
16
|
export { SkipNav } from './components/SkipNav/SkipNav.js';
|
|
17
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"
|
|
@@ -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
|
|
|
@@ -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),
|
|
@@ -4,7 +4,7 @@ import clsx from "clsx"
|
|
|
4
4
|
import React from "react"
|
|
5
5
|
|
|
6
6
|
import { useId } from "../../hooks/useId"
|
|
7
|
-
import {
|
|
7
|
+
import { useSlots } from "../../hooks/useSlots"
|
|
8
8
|
import { Error as BaseError, type ErrorProps } from "../FieldMarkers/Error"
|
|
9
9
|
import { Hint as BaseHint, type HintProps } from "../FieldMarkers/Hint"
|
|
10
10
|
import { Label as BaseLabel, type LabelProps } from "../FieldMarkers/Label"
|
|
@@ -16,13 +16,13 @@ const componentSlots = {
|
|
|
16
16
|
FieldError: null,
|
|
17
17
|
FieldHint: null,
|
|
18
18
|
FieldLabel: null,
|
|
19
|
-
|
|
19
|
+
Radio: null,
|
|
20
20
|
Textarea: null,
|
|
21
21
|
TextInput: null,
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const standardFields = ["Children", "FieldError", "FieldHint", "FieldLabel"]
|
|
25
|
-
const inlineFields = ["Checkbox", "
|
|
25
|
+
const inlineFields = ["Checkbox", "Radio"]
|
|
26
26
|
|
|
27
27
|
interface FieldProps extends HTMLAttributes<HTMLDivElement> {
|
|
28
28
|
/** **(Optional)** Specify whether the Field should render inside a box. */
|
|
@@ -47,7 +47,7 @@ const Root = ({
|
|
|
47
47
|
hideErrorBar = false,
|
|
48
48
|
...props
|
|
49
49
|
}: FieldProps) => {
|
|
50
|
-
const slots =
|
|
50
|
+
const slots = { ...useSlots(componentSlots, children) }
|
|
51
51
|
const slotsArray = Object.entries(slots)
|
|
52
52
|
|
|
53
53
|
const uid = useId()
|
|
@@ -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
|
|
@@ -2,23 +2,22 @@ import clsx from "clsx"
|
|
|
2
2
|
import { type InputHTMLAttributes, type JSX, useId } from "react"
|
|
3
3
|
import { StandardSizes } from "src/types"
|
|
4
4
|
|
|
5
|
-
export interface
|
|
6
|
-
extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
5
|
+
export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
7
6
|
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
8
7
|
className?: string
|
|
9
|
-
/** **(Optional)** Specify whether the
|
|
8
|
+
/** **(Optional)** Specify whether the Radio should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
10
9
|
disabled?: boolean
|
|
11
|
-
/** **(Optional)** Specify the
|
|
10
|
+
/** **(Optional)** Specify the Radio error state. */
|
|
12
11
|
error?: boolean
|
|
13
|
-
/** **(Optional)** Specify the
|
|
12
|
+
/** **(Optional)** Specify the Radio id. Will be auto-generated if not set. */
|
|
14
13
|
id?: string
|
|
15
|
-
/** Specify the
|
|
14
|
+
/** Specify the Radio name. */
|
|
16
15
|
name: string
|
|
17
|
-
/** **(Optional)** Specify the
|
|
16
|
+
/** **(Optional)** Specify the Radio size. */
|
|
18
17
|
size?: StandardSizes
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
export const
|
|
20
|
+
export const Radio = ({
|
|
22
21
|
className,
|
|
23
22
|
disabled,
|
|
24
23
|
error = false,
|
|
@@ -26,13 +25,13 @@ export const RadioButton = ({
|
|
|
26
25
|
name,
|
|
27
26
|
size = "md",
|
|
28
27
|
...props
|
|
29
|
-
}:
|
|
28
|
+
}: RadioProps): JSX.Element => {
|
|
30
29
|
const internalId = useId()
|
|
31
30
|
|
|
32
31
|
id = id ?? internalId
|
|
33
32
|
|
|
34
33
|
const componentProps = {
|
|
35
|
-
className: clsx("coop-radio
|
|
34
|
+
className: clsx("coop-radio", className),
|
|
36
35
|
"data-error": error || undefined,
|
|
37
36
|
"data-size": size.length && size !== "md" ? size : undefined,
|
|
38
37
|
disabled,
|
|
@@ -45,4 +44,4 @@ export const RadioButton = ({
|
|
|
45
44
|
return <input {...componentProps} />
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
export default
|
|
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
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,12 +45,12 @@ 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",
|
|
@@ -67,7 +67,7 @@ export const SearchBox = ({
|
|
|
67
67
|
size = "md",
|
|
68
68
|
variant = "green",
|
|
69
69
|
...props
|
|
70
|
-
}:
|
|
70
|
+
}: SearchboxProps): JSX.Element => {
|
|
71
71
|
const [isPending, setIsPending] = useState(false)
|
|
72
72
|
const internalId = useId()
|
|
73
73
|
|
|
@@ -92,7 +92,7 @@ export const SearchBox = ({
|
|
|
92
92
|
|
|
93
93
|
const formProps = {
|
|
94
94
|
action: action ?? undefined,
|
|
95
|
-
className: clsx("coop-
|
|
95
|
+
className: clsx("coop-searchbox", className),
|
|
96
96
|
"data-size": size && size !== "md" ? size : undefined,
|
|
97
97
|
"data-variant": variant.length && variant !== "green" ? variant : undefined,
|
|
98
98
|
onSubmit: onSubmit ? handleSubmit : undefined,
|
|
@@ -125,7 +125,7 @@ export const SearchBox = ({
|
|
|
125
125
|
{label}
|
|
126
126
|
</FieldLabel>
|
|
127
127
|
)}
|
|
128
|
-
<div className="coop-
|
|
128
|
+
<div className="coop-searchbox--inner">
|
|
129
129
|
<TextInput {...inputProps} />
|
|
130
130
|
|
|
131
131
|
<Button {...buttonProps}>{button.label}</Button>
|
|
@@ -134,4 +134,4 @@ export const SearchBox = ({
|
|
|
134
134
|
)
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
export default
|
|
137
|
+
export default Searchbox
|
|
@@ -26,7 +26,19 @@ export interface TextInputProps
|
|
|
26
26
|
/** **(Optional)** Specify the suffix. It can be any valid JSX or string. */
|
|
27
27
|
suffix?: React.ReactNode
|
|
28
28
|
/** **(Optional)** Specify the TextInput type. */
|
|
29
|
-
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"
|
|
30
42
|
}
|
|
31
43
|
|
|
32
44
|
export const TextInput = ({
|
package/src/index.ts
CHANGED
|
@@ -9,9 +9,9 @@ export * from "./components/Fieldset"
|
|
|
9
9
|
export * from "./components/Flourish"
|
|
10
10
|
export * from "./components/Image"
|
|
11
11
|
export * from "./components/Pill"
|
|
12
|
-
export * from "./components/
|
|
12
|
+
export * from "./components/Radio"
|
|
13
13
|
export * from "./components/RootSVG"
|
|
14
|
-
export * from "./components/
|
|
14
|
+
export * from "./components/Searchbox"
|
|
15
15
|
export * from "./components/Signpost"
|
|
16
16
|
export * from "./components/SkipNav"
|
|
17
17
|
export * from "./components/Squircle"
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { type InputHTMLAttributes, type JSX } from "react";
|
|
2
|
-
import { StandardSizes } from "src/types";
|
|
3
|
-
export interface RadioButtonProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
4
|
-
/** **(Optional)** Specify additional CSS classes to be applied to the component. */
|
|
5
|
-
className?: string;
|
|
6
|
-
/** **(Optional)** Specify whether the RadioButton should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
|
|
7
|
-
disabled?: boolean;
|
|
8
|
-
/** **(Optional)** Specify the RadioButton error state. */
|
|
9
|
-
error?: boolean;
|
|
10
|
-
/** **(Optional)** Specify the RadioButton id. Will be auto-generated if not set. */
|
|
11
|
-
id?: string;
|
|
12
|
-
/** Specify the RadioButton name. */
|
|
13
|
-
name: string;
|
|
14
|
-
/** **(Optional)** Specify the RadioButton size. */
|
|
15
|
-
size?: StandardSizes;
|
|
16
|
-
}
|
|
17
|
-
export declare const RadioButton: ({ className, disabled, error, id, name, size, ...props }: RadioButtonProps) => JSX.Element;
|
|
18
|
-
export default RadioButton;
|