@westpac/ui 1.15.2 → 1.18.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/CHANGELOG.md +23 -0
- package/dist/component-type.json +1 -1
- package/dist/components/button/button.component.d.ts +2 -17
- package/dist/components/button/button.component.js +9 -4
- package/dist/components/button/button.types.d.ts +16 -6
- package/dist/components/link/link.component.d.ts +4 -12
- package/dist/components/link/link.component.js +30 -7
- package/dist/components/link/link.types.d.ts +26 -3
- package/dist/components/modal/components/modal-dialog/components/modal-dialog-footer/modal-dialog-footer.component.d.ts +1 -1
- package/dist/components/modal/components/modal-dialog/components/modal-dialog-footer/modal-dialog-footer.component.js +14 -7
- package/dist/components/modal/components/modal-dialog/components/modal-dialog-footer/modal-dialog-footer.types.d.ts +11 -0
- package/dist/components/pass-code/index.d.ts +1 -1
- package/package.json +5 -4
- package/src/components/button/button.component.tsx +10 -9
- package/src/components/button/button.types.ts +21 -8
- package/src/components/link/link.component.tsx +60 -12
- package/src/components/link/link.types.ts +31 -4
- package/src/components/modal/components/modal-dialog/components/modal-dialog-footer/modal-dialog-footer.component.tsx +16 -2
- package/src/components/modal/components/modal-dialog/components/modal-dialog-footer/modal-dialog-footer.types.ts +12 -0
- package/src/components/pass-code/index.ts +1 -1
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export declare const Button: React.ForwardRefExoticComponent<{
|
|
4
|
-
block?: import("../../types/responsive-variants.types.js").ResponsiveVariants<boolean | undefined>;
|
|
5
|
-
children?: React.ReactNode;
|
|
6
|
-
iconAfter?: (props: import("../icon/icon.types.js").IconProps) => JSX.Element;
|
|
7
|
-
iconBefore?: (props: import("../icon/icon.types.js").IconProps) => JSX.Element;
|
|
8
|
-
iconColor?: import("../icon/icon.types.js").IconProps["color"];
|
|
9
|
-
iconLook?: import("../icon/icon.types.js").IconProps["look"];
|
|
10
|
-
iconSize?: import("../icon/icon.types.js").IconProps["size"];
|
|
11
|
-
justify?: import("../../types/responsive-variants.types.js").ResponsiveVariants<boolean | undefined>;
|
|
12
|
-
look?: import("../../types/responsive-variants.types.js").ResponsiveVariants<"link" | "primary" | "hero" | "faint" | "unstyled" | undefined>;
|
|
13
|
-
removeLinkPadding?: boolean;
|
|
14
|
-
size?: import("../../types/responsive-variants.types.js").ResponsiveVariants<"small" | "xlarge" | "medium" | "large" | undefined>;
|
|
15
|
-
soft?: import("../../types/responsive-variants.types.js").ResponsiveVariants<boolean | undefined>;
|
|
16
|
-
tag?: keyof Pick<JSX.IntrinsicElements, "a" | "span" | "button" | "div">;
|
|
17
|
-
} & React.ButtonHTMLAttributes<Element> & React.AnchorHTMLAttributes<Element> & React.RefAttributes<ButtonRef>>;
|
|
1
|
+
import { ButtonComponent } from './button.types.js';
|
|
2
|
+
export declare const Button: ButtonComponent;
|
|
@@ -5,7 +5,13 @@ import { useBreakpoint } from '../../hook/breakpoints.hook.js';
|
|
|
5
5
|
import { resolveResponsiveVariant } from '../../utils/breakpoint.util.js';
|
|
6
6
|
import { styles as buttonStyles } from './button.styles.js';
|
|
7
7
|
import { getIconSize } from './button.utils.js';
|
|
8
|
-
function BaseButton({ className, size = 'medium', look = 'hero', soft, block = false, justify, tag: Tag
|
|
8
|
+
function BaseButton({ className, size = 'medium', look = 'hero', soft, block = false, justify, tag: Tag, iconBefore: IconBefore, iconAfter: IconAfter, iconLook, iconColor, iconSize, children, removeLinkPadding, ...props }, ref) {
|
|
9
|
+
var _props_type;
|
|
10
|
+
const Component = Tag !== null && Tag !== void 0 ? Tag : 'button';
|
|
11
|
+
const renderProps = Component === 'button' ? {
|
|
12
|
+
...props,
|
|
13
|
+
type: (_props_type = props.type) !== null && _props_type !== void 0 ? _props_type : 'button'
|
|
14
|
+
} : props;
|
|
9
15
|
const { isFocusVisible, focusProps } = useFocusRing();
|
|
10
16
|
const btnIconSize = useMemo(()=>iconSize || getIconSize(size), [
|
|
11
17
|
iconSize,
|
|
@@ -52,13 +58,12 @@ function BaseButton({ className, size = 'medium', look = 'hero', soft, block = f
|
|
|
52
58
|
look,
|
|
53
59
|
soft
|
|
54
60
|
]);
|
|
55
|
-
return React.createElement(
|
|
61
|
+
return React.createElement(Component, {
|
|
56
62
|
ref: ref,
|
|
57
63
|
className: styles.base({
|
|
58
64
|
className
|
|
59
65
|
}),
|
|
60
|
-
...mergeProps(
|
|
61
|
-
type: type
|
|
66
|
+
...mergeProps(renderProps, focusProps)
|
|
62
67
|
}, IconBefore && React.createElement(IconBefore, {
|
|
63
68
|
look: iconLook,
|
|
64
69
|
size: btnIconSize,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { type VariantProps } from 'tailwind-variants';
|
|
3
3
|
import { ResponsiveVariants } from '../../types/responsive-variants.types.js';
|
|
4
4
|
import { IconProps } from '../icon/index.js';
|
|
5
5
|
import { styles } from './button.styles.js';
|
|
6
6
|
type Variants = VariantProps<typeof styles>;
|
|
7
|
-
export type
|
|
8
|
-
export type ButtonProps = {
|
|
7
|
+
export type BaseButtonProps = {
|
|
9
8
|
/**
|
|
10
9
|
* Fit button width to its parent width.
|
|
11
10
|
* @default false
|
|
@@ -64,10 +63,21 @@ export type ButtonProps = {
|
|
|
64
63
|
* Removes background colour and adjusts text colour.
|
|
65
64
|
*/
|
|
66
65
|
soft?: ResponsiveVariants<Variants['soft']>;
|
|
66
|
+
};
|
|
67
|
+
export type ButtonRef<C extends React.ElementType = 'button'> = React.ComponentRef<C>;
|
|
68
|
+
export type PolymorphicRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>['ref'];
|
|
69
|
+
export type ButtonProps<C extends React.ElementType = 'button'> = BaseButtonProps & {
|
|
67
70
|
/**
|
|
68
|
-
*
|
|
71
|
+
* Type to render
|
|
69
72
|
* @default button
|
|
70
73
|
*/
|
|
71
|
-
tag?:
|
|
72
|
-
} &
|
|
74
|
+
tag?: C;
|
|
75
|
+
} & Omit<React.ComponentPropsWithoutRef<C>, keyof BaseButtonProps | 'tag'>;
|
|
76
|
+
export type ButtonImplementationProps = BaseButtonProps & {
|
|
77
|
+
className?: string;
|
|
78
|
+
tag?: React.ElementType;
|
|
79
|
+
} & Record<string, unknown>;
|
|
80
|
+
export type ButtonComponent = <C extends React.ElementType = 'button'>(props: ButtonProps<C> & {
|
|
81
|
+
ref?: PolymorphicRef<C>;
|
|
82
|
+
}) => React.ReactElement | null;
|
|
73
83
|
export {};
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
export declare function BaseLink({ className, children, href, iconBefore: IconBefore, iconAfter: IconAfter, iconSize, target, type, underline, ...
|
|
4
|
-
export declare const Link:
|
|
5
|
-
children?: React.ReactNode;
|
|
6
|
-
className?: string;
|
|
7
|
-
iconAfter?: (props: import("../icon/icon.types.js").IconProps) => JSX.Element;
|
|
8
|
-
iconBefore?: (props: import("../icon/icon.types.js").IconProps) => JSX.Element;
|
|
9
|
-
iconSize?: "xsmall" | "small" | "medium" | "large" | "xlarge";
|
|
10
|
-
type?: "inline" | "standalone";
|
|
11
|
-
underline?: boolean;
|
|
12
|
-
} & Omit<import("react-aria").AriaLinkOptions, "isDisabled" | "elementType"> & React.AnchorHTMLAttributes<Element> & React.RefAttributes<HTMLAnchorElement>>;
|
|
1
|
+
import { ForwardedRef } from 'react';
|
|
2
|
+
import { LinkComponent, LinkImplementationProps } from './link.types.js';
|
|
3
|
+
export declare function BaseLink({ className, children, href, tag: Tag, iconBefore: IconBefore, iconAfter: IconAfter, iconSize, target, type, underline, autoFocus, elementType, onBlur, onClick, onFocus, onFocusChange, onKeyDown, onKeyUp, onPress, onPressChange, onPressEnd, onPressStart, onPressUp, download, ping, referrerPolicy, rel, routerOptions, ...componentProps }: LinkImplementationProps, ref: ForwardedRef<unknown>): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare const Link: LinkComponent;
|
|
@@ -1,13 +1,35 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import React, { forwardRef } from 'react';
|
|
3
|
-
import { mergeProps, useFocusRing, useLink } from 'react-aria';
|
|
3
|
+
import { mergeProps, useFocusRing, useLink, useObjectRef } from 'react-aria';
|
|
4
4
|
import { ArrowRightIcon } from '../icon/index.js';
|
|
5
5
|
import { styles as linkStyles } from './link.styles.js';
|
|
6
|
-
export function BaseLink({ className, children, href, iconBefore: IconBefore, iconAfter: IconAfter, iconSize = 'small', target, type = 'standalone', underline = true, ...
|
|
6
|
+
export function BaseLink({ className, children, href, tag: Tag, iconBefore: IconBefore, iconAfter: IconAfter, iconSize = 'small', target, type = 'standalone', underline = true, autoFocus, elementType, onBlur, onClick, onFocus, onFocusChange, onKeyDown, onKeyUp, onPress, onPressChange, onPressEnd, onPressStart, onPressUp, download, ping, referrerPolicy, rel, routerOptions, ...componentProps }, ref) {
|
|
7
|
+
const Component = Tag !== null && Tag !== void 0 ? Tag : 'a';
|
|
8
|
+
const ariaElementType = typeof Component === 'string' ? Component : elementType !== null && elementType !== void 0 ? elementType : 'a';
|
|
9
|
+
const linkRef = useObjectRef(ref);
|
|
7
10
|
const { linkProps } = useLink({
|
|
8
|
-
...
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
...componentProps,
|
|
12
|
+
autoFocus,
|
|
13
|
+
download,
|
|
14
|
+
elementType: ariaElementType,
|
|
15
|
+
href: typeof href === 'string' ? href : undefined,
|
|
16
|
+
onBlur,
|
|
17
|
+
onClick,
|
|
18
|
+
onFocus,
|
|
19
|
+
onFocusChange,
|
|
20
|
+
onKeyDown,
|
|
21
|
+
onKeyUp,
|
|
22
|
+
onPress,
|
|
23
|
+
onPressChange,
|
|
24
|
+
onPressEnd,
|
|
25
|
+
onPressStart,
|
|
26
|
+
onPressUp,
|
|
27
|
+
ping,
|
|
28
|
+
referrerPolicy,
|
|
29
|
+
rel,
|
|
30
|
+
routerOptions,
|
|
31
|
+
target
|
|
32
|
+
}, linkRef);
|
|
11
33
|
const { isFocusVisible, focusProps } = useFocusRing();
|
|
12
34
|
const styles = linkStyles({
|
|
13
35
|
type,
|
|
@@ -17,9 +39,10 @@ export function BaseLink({ className, children, href, iconBefore: IconBefore, ic
|
|
|
17
39
|
if (type === 'standalone' && !IconBefore && !IconAfter) {
|
|
18
40
|
IconBefore = ArrowRightIcon;
|
|
19
41
|
}
|
|
20
|
-
return React.createElement(
|
|
42
|
+
return React.createElement(Component, {
|
|
43
|
+
...componentProps,
|
|
21
44
|
...mergeProps(linkProps, focusProps),
|
|
22
|
-
ref:
|
|
45
|
+
ref: linkRef,
|
|
23
46
|
href: href,
|
|
24
47
|
target: target,
|
|
25
48
|
className: styles.base({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { AriaLinkOptions } from 'react-aria';
|
|
3
3
|
import { IconProps } from '../icon/index.js';
|
|
4
|
-
export type
|
|
4
|
+
export type BaseLinkProps = {
|
|
5
5
|
/**
|
|
6
6
|
* Link text or component
|
|
7
7
|
*/
|
|
@@ -33,4 +33,27 @@ export type LinkProps = {
|
|
|
33
33
|
* @default true
|
|
34
34
|
*/
|
|
35
35
|
underline?: boolean;
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Specifies DOM element rendered by a custom component
|
|
38
|
+
* Required when the custom component does not render an '<a>' element
|
|
39
|
+
* @default 'a'
|
|
40
|
+
*/
|
|
41
|
+
elementType?: AriaLinkOptions['elementType'];
|
|
42
|
+
} & Omit<AriaLinkOptions, 'elementType' | 'href' | 'isDisabled'>;
|
|
43
|
+
export type LinkRef<C extends React.ElementType = 'a'> = React.ComponentRef<C>;
|
|
44
|
+
export type PolymorphicRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>['ref'];
|
|
45
|
+
export type LinkProps<C extends React.ElementType = 'a'> = BaseLinkProps & {
|
|
46
|
+
/**
|
|
47
|
+
* Type to render
|
|
48
|
+
* @default a
|
|
49
|
+
*/
|
|
50
|
+
tag?: C;
|
|
51
|
+
} & Omit<React.ComponentPropsWithoutRef<C>, keyof BaseLinkProps | 'tag'>;
|
|
52
|
+
export type LinkImplementationProps = BaseLinkProps & {
|
|
53
|
+
className?: string;
|
|
54
|
+
href?: unknown;
|
|
55
|
+
tag?: React.ElementType;
|
|
56
|
+
} & Record<string, unknown>;
|
|
57
|
+
export type LinkComponent = <C extends React.ElementType = 'a'>(props: LinkProps<C> & {
|
|
58
|
+
ref?: PolymorphicRef<C>;
|
|
59
|
+
}) => React.ReactElement | null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type ModalDialogFooterProps } from './modal-dialog-footer.types.js';
|
|
2
|
-
export declare function ModalDialogFooter({ className, primaryLabel, primaryOnClick, secondaryLabel, secondaryOnClick, ...props }: ModalDialogFooterProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function ModalDialogFooter({ className, primaryButtonProps, primaryLabel, primaryOnClick, secondaryButtonProps, secondaryLabel, secondaryOnClick, ...props }: ModalDialogFooterProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -5,7 +5,8 @@ import { resolveResponsiveVariant } from '../../../../../../utils/breakpoint.uti
|
|
|
5
5
|
import { Button } from '../../../../../button/index.js';
|
|
6
6
|
import { useModalDialogContext } from '../../modal-dialog.component.js';
|
|
7
7
|
import { styles as modalFooterStyles } from './modal-dialog-footer.styles.js';
|
|
8
|
-
export function ModalDialogFooter({ className, primaryLabel, primaryOnClick, secondaryLabel, secondaryOnClick, ...props }) {
|
|
8
|
+
export function ModalDialogFooter({ className, primaryButtonProps, primaryLabel, primaryOnClick, secondaryButtonProps, secondaryLabel, secondaryOnClick, ...props }) {
|
|
9
|
+
var _ref, _ref1, _ref2, _ref3;
|
|
9
10
|
const { size, compact, setFooterPresent } = useModalDialogContext();
|
|
10
11
|
const breakpoint = useBreakpoint();
|
|
11
12
|
const styles = modalFooterStyles({
|
|
@@ -23,14 +24,20 @@ export function ModalDialogFooter({ className, primaryLabel, primaryOnClick, sec
|
|
|
23
24
|
}),
|
|
24
25
|
...props
|
|
25
26
|
}, React.createElement(Button, {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
...primaryButtonProps,
|
|
28
|
+
look: (_ref = primaryButtonProps === null || primaryButtonProps === void 0 ? void 0 : primaryButtonProps.look) !== null && _ref !== void 0 ? _ref : 'primary',
|
|
29
|
+
size: (_ref1 = primaryButtonProps === null || primaryButtonProps === void 0 ? void 0 : primaryButtonProps.size) !== null && _ref1 !== void 0 ? _ref1 : 'large',
|
|
30
|
+
className: styles.primaryBtn({
|
|
31
|
+
className: primaryButtonProps === null || primaryButtonProps === void 0 ? void 0 : primaryButtonProps.className
|
|
32
|
+
}),
|
|
29
33
|
onClick: primaryOnClick
|
|
30
34
|
}, primaryLabel), secondaryLabel && React.createElement(Button, {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
...secondaryButtonProps,
|
|
36
|
+
look: (_ref2 = secondaryButtonProps === null || secondaryButtonProps === void 0 ? void 0 : secondaryButtonProps.look) !== null && _ref2 !== void 0 ? _ref2 : 'link',
|
|
37
|
+
size: (_ref3 = secondaryButtonProps === null || secondaryButtonProps === void 0 ? void 0 : secondaryButtonProps.size) !== null && _ref3 !== void 0 ? _ref3 : 'large',
|
|
38
|
+
className: styles.secondaryBtn({
|
|
39
|
+
className: secondaryButtonProps === null || secondaryButtonProps === void 0 ? void 0 : secondaryButtonProps.className
|
|
40
|
+
}),
|
|
34
41
|
onClick: secondaryOnClick
|
|
35
42
|
}, secondaryLabel));
|
|
36
43
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { type ButtonProps } from '../../../../../button/index.js';
|
|
3
|
+
type ModalFooterButtonProps = Omit<ButtonProps, 'children' | 'onClick'>;
|
|
2
4
|
export type ModalDialogFooterProps = {
|
|
3
5
|
/**
|
|
4
6
|
* Footer content
|
|
5
7
|
*/
|
|
6
8
|
children?: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Props passed to the primary button
|
|
11
|
+
*/
|
|
12
|
+
primaryButtonProps?: ModalFooterButtonProps;
|
|
7
13
|
/**
|
|
8
14
|
* Label for primary button
|
|
9
15
|
*/
|
|
@@ -12,6 +18,10 @@ export type ModalDialogFooterProps = {
|
|
|
12
18
|
* onClick for primary button
|
|
13
19
|
*/
|
|
14
20
|
primaryOnClick: () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Props passed to the secondary button
|
|
23
|
+
*/
|
|
24
|
+
secondaryButtonProps?: ModalFooterButtonProps;
|
|
15
25
|
/**
|
|
16
26
|
* Label for secondary button
|
|
17
27
|
*/
|
|
@@ -21,3 +31,4 @@ export type ModalDialogFooterProps = {
|
|
|
21
31
|
*/
|
|
22
32
|
secondaryOnClick?: () => void;
|
|
23
33
|
} & HTMLAttributes<HTMLElement>;
|
|
34
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { PassCode } from './pass-code.component.js';
|
|
2
|
-
export { type PassCodeProps } from './pass-code.types.js';
|
|
2
|
+
export { type PassCodeProps, type PassCodeRef } from './pass-code.types.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@westpac/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -259,10 +259,10 @@
|
|
|
259
259
|
"typescript": "^5.5.4",
|
|
260
260
|
"vite": "^7.3.5",
|
|
261
261
|
"vitest": "^3.2.6",
|
|
262
|
-
"@westpac/
|
|
263
|
-
"@westpac/ts-config": "~0.0.0",
|
|
262
|
+
"@westpac/eslint-config": "~1.1.0",
|
|
264
263
|
"@westpac/style-config": "~1.0.2",
|
|
265
|
-
"@westpac/
|
|
264
|
+
"@westpac/test-config": "~0.0.0",
|
|
265
|
+
"@westpac/ts-config": "~0.0.0"
|
|
266
266
|
},
|
|
267
267
|
"dependencies": {
|
|
268
268
|
"@internationalized/date": "^3.12.0",
|
|
@@ -280,6 +280,7 @@
|
|
|
280
280
|
},
|
|
281
281
|
"peerDependencies": {
|
|
282
282
|
"react": ">=18.2.0",
|
|
283
|
+
"react-dom": ">=18.2.0",
|
|
283
284
|
"tailwindcss": "~4.1.12"
|
|
284
285
|
},
|
|
285
286
|
"repository": {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React, {
|
|
3
|
+
import React, { ForwardedRef, forwardRef, useMemo } from 'react';
|
|
4
4
|
import { mergeProps, useFocusRing } from 'react-aria';
|
|
5
5
|
|
|
6
6
|
import { useBreakpoint } from '../../hook/breakpoints.hook.js';
|
|
7
7
|
import { resolveResponsiveVariant } from '../../utils/breakpoint.util.js';
|
|
8
8
|
|
|
9
9
|
import { styles as buttonStyles } from './button.styles.js';
|
|
10
|
-
import {
|
|
10
|
+
import { ButtonImplementationProps, ButtonComponent } from './button.types.js';
|
|
11
11
|
import { getIconSize } from './button.utils.js';
|
|
12
12
|
|
|
13
13
|
function BaseButton(
|
|
@@ -18,7 +18,7 @@ function BaseButton(
|
|
|
18
18
|
soft,
|
|
19
19
|
block = false,
|
|
20
20
|
justify,
|
|
21
|
-
tag: Tag
|
|
21
|
+
tag: Tag,
|
|
22
22
|
iconBefore: IconBefore,
|
|
23
23
|
iconAfter: IconAfter,
|
|
24
24
|
iconLook,
|
|
@@ -26,11 +26,12 @@ function BaseButton(
|
|
|
26
26
|
iconSize,
|
|
27
27
|
children,
|
|
28
28
|
removeLinkPadding,
|
|
29
|
-
type = Tag === 'button' ? 'button' : undefined,
|
|
30
29
|
...props
|
|
31
|
-
}:
|
|
32
|
-
ref:
|
|
30
|
+
}: ButtonImplementationProps,
|
|
31
|
+
ref: ForwardedRef<unknown>,
|
|
33
32
|
) {
|
|
33
|
+
const Component = Tag ?? 'button';
|
|
34
|
+
const renderProps = Component === 'button' ? { ...props, type: props.type ?? 'button' } : props;
|
|
34
35
|
const { isFocusVisible, focusProps } = useFocusRing();
|
|
35
36
|
const btnIconSize = useMemo(() => iconSize || getIconSize(size), [iconSize, size]);
|
|
36
37
|
const breakpoint = useBreakpoint();
|
|
@@ -76,7 +77,7 @@ function BaseButton(
|
|
|
76
77
|
}, [iconColor, look, soft]);
|
|
77
78
|
|
|
78
79
|
return (
|
|
79
|
-
<
|
|
80
|
+
<Component ref={ref} className={styles.base({ className })} {...mergeProps(renderProps, focusProps)}>
|
|
80
81
|
{IconBefore && (
|
|
81
82
|
<IconBefore
|
|
82
83
|
look={iconLook}
|
|
@@ -96,8 +97,8 @@ function BaseButton(
|
|
|
96
97
|
aria-hidden
|
|
97
98
|
/>
|
|
98
99
|
)}
|
|
99
|
-
</
|
|
100
|
+
</Component>
|
|
100
101
|
);
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
export const Button = forwardRef(BaseButton);
|
|
104
|
+
export const Button = forwardRef(BaseButton) as unknown as ButtonComponent;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { type VariantProps } from 'tailwind-variants';
|
|
3
3
|
|
|
4
4
|
import { ResponsiveVariants } from '../../types/responsive-variants.types.js';
|
|
@@ -8,9 +8,7 @@ import { styles } from './button.styles.js';
|
|
|
8
8
|
|
|
9
9
|
type Variants = VariantProps<typeof styles>;
|
|
10
10
|
|
|
11
|
-
export type
|
|
12
|
-
|
|
13
|
-
export type ButtonProps = {
|
|
11
|
+
export type BaseButtonProps = {
|
|
14
12
|
/**
|
|
15
13
|
* Fit button width to its parent width.
|
|
16
14
|
* @default false
|
|
@@ -69,10 +67,25 @@ export type ButtonProps = {
|
|
|
69
67
|
* Removes background colour and adjusts text colour.
|
|
70
68
|
*/
|
|
71
69
|
soft?: ResponsiveVariants<Variants['soft']>;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type ButtonRef<C extends React.ElementType = 'button'> = React.ComponentRef<C>;
|
|
73
|
+
|
|
74
|
+
export type PolymorphicRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>['ref'];
|
|
75
|
+
|
|
76
|
+
export type ButtonProps<C extends React.ElementType = 'button'> = BaseButtonProps & {
|
|
72
77
|
/**
|
|
73
|
-
*
|
|
78
|
+
* Type to render
|
|
74
79
|
* @default button
|
|
75
80
|
*/
|
|
76
|
-
tag?:
|
|
77
|
-
} &
|
|
78
|
-
|
|
81
|
+
tag?: C;
|
|
82
|
+
} & Omit<React.ComponentPropsWithoutRef<C>, keyof BaseButtonProps | 'tag'>;
|
|
83
|
+
|
|
84
|
+
export type ButtonImplementationProps = BaseButtonProps & {
|
|
85
|
+
className?: string;
|
|
86
|
+
tag?: React.ElementType;
|
|
87
|
+
} & Record<string, unknown>;
|
|
88
|
+
|
|
89
|
+
export type ButtonComponent = <C extends React.ElementType = 'button'>(
|
|
90
|
+
props: ButtonProps<C> & { ref?: PolymorphicRef<C> },
|
|
91
|
+
) => React.ReactElement | null;
|
|
@@ -1,30 +1,77 @@
|
|
|
1
|
-
// TODO: This component will not work with the Next Link component in Next.js 16+ as legacyBehavior as has been deprecated in 15. Need to find a solution.
|
|
2
1
|
'use client';
|
|
3
2
|
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
3
|
+
import { type FocusableElement } from '@react-types/shared';
|
|
4
|
+
import React, { ForwardedRef, forwardRef } from 'react';
|
|
5
|
+
import { mergeProps, useFocusRing, useLink, useObjectRef } from 'react-aria';
|
|
6
6
|
|
|
7
7
|
import { ArrowRightIcon } from '../icon/index.js';
|
|
8
8
|
|
|
9
9
|
import { styles as linkStyles } from './link.styles.js';
|
|
10
|
-
import {
|
|
10
|
+
import { LinkComponent, LinkImplementationProps } from './link.types.js';
|
|
11
11
|
|
|
12
12
|
export function BaseLink(
|
|
13
13
|
{
|
|
14
14
|
className,
|
|
15
15
|
children,
|
|
16
16
|
href,
|
|
17
|
+
tag: Tag,
|
|
17
18
|
iconBefore: IconBefore,
|
|
18
19
|
iconAfter: IconAfter,
|
|
19
20
|
iconSize = 'small',
|
|
20
21
|
target,
|
|
21
22
|
type = 'standalone',
|
|
22
23
|
underline = true,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
autoFocus,
|
|
25
|
+
elementType,
|
|
26
|
+
onBlur,
|
|
27
|
+
onClick,
|
|
28
|
+
onFocus,
|
|
29
|
+
onFocusChange,
|
|
30
|
+
onKeyDown,
|
|
31
|
+
onKeyUp,
|
|
32
|
+
onPress,
|
|
33
|
+
onPressChange,
|
|
34
|
+
onPressEnd,
|
|
35
|
+
onPressStart,
|
|
36
|
+
onPressUp,
|
|
37
|
+
download,
|
|
38
|
+
ping,
|
|
39
|
+
referrerPolicy,
|
|
40
|
+
rel,
|
|
41
|
+
routerOptions,
|
|
42
|
+
...componentProps
|
|
43
|
+
}: LinkImplementationProps,
|
|
44
|
+
ref: ForwardedRef<unknown>,
|
|
26
45
|
) {
|
|
27
|
-
const
|
|
46
|
+
const Component = Tag ?? 'a';
|
|
47
|
+
const ariaElementType = typeof Component === 'string' ? Component : (elementType ?? 'a');
|
|
48
|
+
const linkRef = useObjectRef(ref as ForwardedRef<FocusableElement>);
|
|
49
|
+
const { linkProps } = useLink(
|
|
50
|
+
{
|
|
51
|
+
...componentProps,
|
|
52
|
+
autoFocus,
|
|
53
|
+
download,
|
|
54
|
+
elementType: ariaElementType,
|
|
55
|
+
href: typeof href === 'string' ? href : undefined,
|
|
56
|
+
onBlur,
|
|
57
|
+
onClick,
|
|
58
|
+
onFocus,
|
|
59
|
+
onFocusChange,
|
|
60
|
+
onKeyDown,
|
|
61
|
+
onKeyUp,
|
|
62
|
+
onPress,
|
|
63
|
+
onPressChange,
|
|
64
|
+
onPressEnd,
|
|
65
|
+
onPressStart,
|
|
66
|
+
onPressUp,
|
|
67
|
+
ping,
|
|
68
|
+
referrerPolicy,
|
|
69
|
+
rel,
|
|
70
|
+
routerOptions,
|
|
71
|
+
target,
|
|
72
|
+
},
|
|
73
|
+
linkRef,
|
|
74
|
+
);
|
|
28
75
|
const { isFocusVisible, focusProps } = useFocusRing();
|
|
29
76
|
const styles = linkStyles({ type, underline, isFocusVisible });
|
|
30
77
|
|
|
@@ -33,9 +80,10 @@ export function BaseLink(
|
|
|
33
80
|
}
|
|
34
81
|
|
|
35
82
|
return (
|
|
36
|
-
<
|
|
83
|
+
<Component
|
|
84
|
+
{...componentProps}
|
|
37
85
|
{...mergeProps(linkProps, focusProps)}
|
|
38
|
-
ref={
|
|
86
|
+
ref={linkRef}
|
|
39
87
|
href={href}
|
|
40
88
|
target={target}
|
|
41
89
|
className={styles.base({ className })}
|
|
@@ -43,8 +91,8 @@ export function BaseLink(
|
|
|
43
91
|
{IconBefore && <IconBefore size={iconSize} color="primary" className={styles.iconBefore()} />}
|
|
44
92
|
<span>{children}</span>
|
|
45
93
|
{IconAfter && <IconAfter size={iconSize} color="primary" className={styles.iconAfter()} />}
|
|
46
|
-
</
|
|
94
|
+
</Component>
|
|
47
95
|
);
|
|
48
96
|
}
|
|
49
97
|
|
|
50
|
-
export const Link = forwardRef(BaseLink);
|
|
98
|
+
export const Link = forwardRef(BaseLink) as unknown as LinkComponent;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { AriaLinkOptions } from 'react-aria';
|
|
3
3
|
|
|
4
4
|
import { IconProps } from '../icon/index.js';
|
|
5
5
|
|
|
6
|
-
export type
|
|
6
|
+
export type BaseLinkProps = {
|
|
7
7
|
/**
|
|
8
8
|
* Link text or component
|
|
9
9
|
*/
|
|
@@ -35,5 +35,32 @@ export type LinkProps = {
|
|
|
35
35
|
* @default true
|
|
36
36
|
*/
|
|
37
37
|
underline?: boolean;
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Specifies DOM element rendered by a custom component
|
|
40
|
+
* Required when the custom component does not render an '<a>' element
|
|
41
|
+
* @default 'a'
|
|
42
|
+
*/
|
|
43
|
+
elementType?: AriaLinkOptions['elementType'];
|
|
44
|
+
} & Omit<AriaLinkOptions, 'elementType' | 'href' | 'isDisabled'>;
|
|
45
|
+
|
|
46
|
+
export type LinkRef<C extends React.ElementType = 'a'> = React.ComponentRef<C>;
|
|
47
|
+
|
|
48
|
+
export type PolymorphicRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>['ref'];
|
|
49
|
+
|
|
50
|
+
export type LinkProps<C extends React.ElementType = 'a'> = BaseLinkProps & {
|
|
51
|
+
/**
|
|
52
|
+
* Type to render
|
|
53
|
+
* @default a
|
|
54
|
+
*/
|
|
55
|
+
tag?: C;
|
|
56
|
+
} & Omit<React.ComponentPropsWithoutRef<C>, keyof BaseLinkProps | 'tag'>;
|
|
57
|
+
|
|
58
|
+
export type LinkImplementationProps = BaseLinkProps & {
|
|
59
|
+
className?: string;
|
|
60
|
+
href?: unknown;
|
|
61
|
+
tag?: React.ElementType;
|
|
62
|
+
} & Record<string, unknown>;
|
|
63
|
+
|
|
64
|
+
export type LinkComponent = <C extends React.ElementType = 'a'>(
|
|
65
|
+
props: LinkProps<C> & { ref?: PolymorphicRef<C> },
|
|
66
|
+
) => React.ReactElement | null;
|
|
@@ -12,8 +12,10 @@ import { type ModalDialogFooterProps } from './modal-dialog-footer.types.js';
|
|
|
12
12
|
|
|
13
13
|
export function ModalDialogFooter({
|
|
14
14
|
className,
|
|
15
|
+
primaryButtonProps,
|
|
15
16
|
primaryLabel,
|
|
16
17
|
primaryOnClick,
|
|
18
|
+
secondaryButtonProps,
|
|
17
19
|
secondaryLabel,
|
|
18
20
|
secondaryOnClick,
|
|
19
21
|
...props
|
|
@@ -29,11 +31,23 @@ export function ModalDialogFooter({
|
|
|
29
31
|
|
|
30
32
|
return (
|
|
31
33
|
<div className={styles.base({ className })} {...props}>
|
|
32
|
-
<Button
|
|
34
|
+
<Button
|
|
35
|
+
{...primaryButtonProps}
|
|
36
|
+
look={primaryButtonProps?.look ?? 'primary'}
|
|
37
|
+
size={primaryButtonProps?.size ?? 'large'}
|
|
38
|
+
className={styles.primaryBtn({ className: primaryButtonProps?.className })}
|
|
39
|
+
onClick={primaryOnClick}
|
|
40
|
+
>
|
|
33
41
|
{primaryLabel}
|
|
34
42
|
</Button>
|
|
35
43
|
{secondaryLabel && (
|
|
36
|
-
<Button
|
|
44
|
+
<Button
|
|
45
|
+
{...secondaryButtonProps}
|
|
46
|
+
look={secondaryButtonProps?.look ?? 'link'}
|
|
47
|
+
size={secondaryButtonProps?.size ?? 'large'}
|
|
48
|
+
className={styles.secondaryBtn({ className: secondaryButtonProps?.className })}
|
|
49
|
+
onClick={secondaryOnClick}
|
|
50
|
+
>
|
|
37
51
|
{secondaryLabel}
|
|
38
52
|
</Button>
|
|
39
53
|
)}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
+
import { type ButtonProps } from '../../../../../button/index.js';
|
|
4
|
+
|
|
5
|
+
type ModalFooterButtonProps = Omit<ButtonProps, 'children' | 'onClick'>;
|
|
6
|
+
|
|
3
7
|
export type ModalDialogFooterProps = {
|
|
4
8
|
/**
|
|
5
9
|
* Footer content
|
|
6
10
|
*/
|
|
7
11
|
children?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Props passed to the primary button
|
|
14
|
+
*/
|
|
15
|
+
primaryButtonProps?: ModalFooterButtonProps;
|
|
8
16
|
/**
|
|
9
17
|
* Label for primary button
|
|
10
18
|
*/
|
|
@@ -13,6 +21,10 @@ export type ModalDialogFooterProps = {
|
|
|
13
21
|
* onClick for primary button
|
|
14
22
|
*/
|
|
15
23
|
primaryOnClick: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Props passed to the secondary button
|
|
26
|
+
*/
|
|
27
|
+
secondaryButtonProps?: ModalFooterButtonProps;
|
|
16
28
|
/**
|
|
17
29
|
* Label for secondary button
|
|
18
30
|
*/
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { PassCode } from './pass-code.component.js';
|
|
2
|
-
export { type PassCodeProps } from './pass-code.types.js';
|
|
2
|
+
export { type PassCodeProps, type PassCodeRef } from './pass-code.types.js';
|