@westpac/ui 1.14.0 → 1.15.1
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 +12 -0
- package/dist/component-type.json +1 -1
- package/dist/components/flyout/components/flyout-backdrop/flyout-backdrop.component.d.ts +5 -0
- package/dist/components/flyout/components/flyout-backdrop/flyout-backdrop.component.js +39 -0
- package/dist/components/flyout/components/flyout-backdrop/flyout-backdrop.styles.d.ts +34 -0
- package/dist/components/flyout/components/flyout-backdrop/flyout-backdrop.styles.js +16 -0
- package/dist/components/flyout/components/flyout-backdrop/flyout-backdrop.types.d.ts +30 -0
- package/dist/components/flyout/components/flyout-backdrop/flyout-backdrop.types.js +1 -0
- package/dist/components/flyout/components/flyout-backdrop/index.d.ts +2 -0
- package/dist/components/flyout/components/flyout-backdrop/index.js +1 -0
- package/dist/components/flyout/components/flyout-dialog/flyout-dialog.component.d.ts +5 -0
- package/dist/components/flyout/components/flyout-dialog/flyout-dialog.component.js +67 -0
- package/dist/components/flyout/components/flyout-dialog/flyout-dialog.styles.d.ts +82 -0
- package/dist/components/flyout/components/flyout-dialog/flyout-dialog.styles.js +66 -0
- package/dist/components/flyout/components/flyout-dialog/flyout-dialog.types.d.ts +40 -0
- package/dist/components/flyout/components/flyout-dialog/flyout-dialog.types.js +1 -0
- package/dist/components/flyout/components/flyout-dialog/index.d.ts +2 -0
- package/dist/components/flyout/components/flyout-dialog/index.js +1 -0
- package/dist/components/flyout/components/index.d.ts +2 -0
- package/dist/components/flyout/components/index.js +2 -0
- package/dist/components/flyout/flyout.component.d.ts +2 -0
- package/dist/components/flyout/flyout.component.js +26 -0
- package/dist/components/flyout/flyout.types.d.ts +7 -0
- package/dist/components/flyout/flyout.types.js +1 -0
- package/dist/components/flyout/index.d.ts +2 -0
- package/dist/components/flyout/index.js +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/input-group/input-group.component.js +2 -1
- package/dist/css/westpac-ui.css +43 -0
- package/dist/css/westpac-ui.min.css +43 -0
- package/package.json +4 -1
- package/src/components/flyout/components/flyout-backdrop/flyout-backdrop.component.tsx +49 -0
- package/src/components/flyout/components/flyout-backdrop/flyout-backdrop.styles.ts +17 -0
- package/src/components/flyout/components/flyout-backdrop/flyout-backdrop.types.ts +32 -0
- package/src/components/flyout/components/flyout-backdrop/index.ts +2 -0
- package/src/components/flyout/components/flyout-dialog/flyout-dialog.component.tsx +86 -0
- package/src/components/flyout/components/flyout-dialog/flyout-dialog.styles.ts +59 -0
- package/src/components/flyout/components/flyout-dialog/flyout-dialog.types.ts +44 -0
- package/src/components/flyout/components/flyout-dialog/index.ts +2 -0
- package/src/components/flyout/components/index.ts +2 -0
- package/src/components/flyout/flyout.component.tsx +53 -0
- package/src/components/flyout/flyout.types.ts +9 -0
- package/src/components/flyout/index.ts +2 -0
- package/src/components/index.ts +1 -0
- package/src/components/input-group/input-group.component.tsx +3 -2
|
@@ -769,6 +769,9 @@
|
|
|
769
769
|
.h-8 {
|
|
770
770
|
height: calc(0.375rem * 8);
|
|
771
771
|
}
|
|
772
|
+
.h-9 {
|
|
773
|
+
height: calc(0.375rem * 9);
|
|
774
|
+
}
|
|
772
775
|
.h-10 {
|
|
773
776
|
height: calc(0.375rem * 10);
|
|
774
777
|
}
|
|
@@ -781,6 +784,9 @@
|
|
|
781
784
|
.h-30 {
|
|
782
785
|
height: calc(0.375rem * 30);
|
|
783
786
|
}
|
|
787
|
+
.h-50 {
|
|
788
|
+
height: calc(0.375rem * 50);
|
|
789
|
+
}
|
|
784
790
|
.h-\[0\.625rem\] {
|
|
785
791
|
height: 0.625rem;
|
|
786
792
|
}
|
|
@@ -979,6 +985,12 @@
|
|
|
979
985
|
.w-23 {
|
|
980
986
|
width: calc(0.375rem * 23);
|
|
981
987
|
}
|
|
988
|
+
.w-50 {
|
|
989
|
+
width: calc(0.375rem * 50);
|
|
990
|
+
}
|
|
991
|
+
.w-70 {
|
|
992
|
+
width: calc(0.375rem * 70);
|
|
993
|
+
}
|
|
982
994
|
.w-\[1\.81ex\] {
|
|
983
995
|
width: 1.81ex;
|
|
984
996
|
}
|
|
@@ -1348,6 +1360,14 @@
|
|
|
1348
1360
|
.shrink-0 {
|
|
1349
1361
|
flex-shrink: 0;
|
|
1350
1362
|
}
|
|
1363
|
+
.-translate-x-full {
|
|
1364
|
+
--tw-translate-x: -100%;
|
|
1365
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1366
|
+
}
|
|
1367
|
+
.translate-x-0 {
|
|
1368
|
+
--tw-translate-x: calc(0.375rem * 0);
|
|
1369
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1370
|
+
}
|
|
1351
1371
|
.translate-x-\[-2\.5px\] {
|
|
1352
1372
|
--tw-translate-x: -2.5px;
|
|
1353
1373
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
@@ -1360,6 +1380,10 @@
|
|
|
1360
1380
|
--tw-translate-x: 14px;
|
|
1361
1381
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1362
1382
|
}
|
|
1383
|
+
.translate-x-full {
|
|
1384
|
+
--tw-translate-x: 100%;
|
|
1385
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1386
|
+
}
|
|
1363
1387
|
.-translate-y-1\/2 {
|
|
1364
1388
|
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
|
|
1365
1389
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
@@ -1542,6 +1566,13 @@
|
|
|
1542
1566
|
margin-inline-end: calc(calc(0.375rem * 1) * calc(1 - var(--tw-space-x-reverse)));
|
|
1543
1567
|
}
|
|
1544
1568
|
}
|
|
1569
|
+
.space-x-4 {
|
|
1570
|
+
:where(& > :not(:last-child)) {
|
|
1571
|
+
--tw-space-x-reverse: 0;
|
|
1572
|
+
margin-inline-start: calc(calc(0.375rem * 4) * var(--tw-space-x-reverse));
|
|
1573
|
+
margin-inline-end: calc(calc(0.375rem * 4) * calc(1 - var(--tw-space-x-reverse)));
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1545
1576
|
.divide-y {
|
|
1546
1577
|
:where(& > :not(:last-child)) {
|
|
1547
1578
|
--tw-divide-y-reverse: 0;
|
|
@@ -3150,6 +3181,10 @@
|
|
|
3150
3181
|
--tw-shadow: 0 0.375rem 0.75rem var(--tw-shadow-color, rgba(0,0,0,0.175));
|
|
3151
3182
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
3152
3183
|
}
|
|
3184
|
+
.shadow-\[0_2px_5px_rgba\(0\,0\,0\,0\.3\)\] {
|
|
3185
|
+
--tw-shadow: 0 2px 5px var(--tw-shadow-color, rgba(0,0,0,0.3));
|
|
3186
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
3187
|
+
}
|
|
3153
3188
|
.shadow-\[0_2px_12px_rgba\(0\,0\,0\,0\.2\)\] {
|
|
3154
3189
|
--tw-shadow: 0 2px 12px var(--tw-shadow-color, rgba(0,0,0,0.2));
|
|
3155
3190
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
@@ -3309,6 +3344,10 @@
|
|
|
3309
3344
|
--tw-duration: 300ms;
|
|
3310
3345
|
transition-duration: 300ms;
|
|
3311
3346
|
}
|
|
3347
|
+
.duration-500 {
|
|
3348
|
+
--tw-duration: 500ms;
|
|
3349
|
+
transition-duration: 500ms;
|
|
3350
|
+
}
|
|
3312
3351
|
.duration-\[\.3s\] {
|
|
3313
3352
|
--tw-duration: .3s;
|
|
3314
3353
|
transition-duration: .3s;
|
|
@@ -3317,6 +3356,10 @@
|
|
|
3317
3356
|
--tw-duration: .6s;
|
|
3318
3357
|
transition-duration: .6s;
|
|
3319
3358
|
}
|
|
3359
|
+
.ease-\[cubic-bezier\(0\.23\,1\,0\.32\,1\)\] {
|
|
3360
|
+
--tw-ease: cubic-bezier(0.23,1,0.32,1);
|
|
3361
|
+
transition-timing-function: cubic-bezier(0.23,1,0.32,1);
|
|
3362
|
+
}
|
|
3320
3363
|
.ease-\[cubic-bezier\(0\.25\,0\.1\,0\.25\,1\)\] {
|
|
3321
3364
|
--tw-ease: cubic-bezier(0.25,0.1,0.25,1);
|
|
3322
3365
|
transition-timing-function: cubic-bezier(0.25,0.1,0.25,1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@westpac/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -88,6 +88,9 @@
|
|
|
88
88
|
"./flexi-cell": {
|
|
89
89
|
"default": "./dist/components/flexi-cell/index.js"
|
|
90
90
|
},
|
|
91
|
+
"./flyout": {
|
|
92
|
+
"default": "./dist/components/flyout/index.js"
|
|
93
|
+
},
|
|
91
94
|
"./footer": {
|
|
92
95
|
"default": "./dist/components/footer/index.js"
|
|
93
96
|
},
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useExitAnimation } from '@react-aria/utils';
|
|
4
|
+
import React, { useMemo, useRef } from 'react';
|
|
5
|
+
import { Overlay, useModalOverlay } from 'react-aria';
|
|
6
|
+
|
|
7
|
+
import { styles as backdropStyles } from './flyout-backdrop.styles.js';
|
|
8
|
+
import { type FlyoutBackdropProps } from './flyout-backdrop.types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @private
|
|
12
|
+
*/
|
|
13
|
+
export function FlyoutBackdrop({
|
|
14
|
+
children,
|
|
15
|
+
className,
|
|
16
|
+
isDismissable = true,
|
|
17
|
+
portalContainer,
|
|
18
|
+
state,
|
|
19
|
+
zIndex = 100,
|
|
20
|
+
...props
|
|
21
|
+
}: FlyoutBackdropProps) {
|
|
22
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
23
|
+
const isExiting = useExitAnimation(ref, state.isOpen);
|
|
24
|
+
const styles = backdropStyles({ isOpen: state.isOpen });
|
|
25
|
+
const { modalProps, underlayProps } = useModalOverlay({ isDismissable, ...props }, state, ref);
|
|
26
|
+
|
|
27
|
+
// This is required so branding applies correctly by default due to portal location, can be overridden with portalContainer prop
|
|
28
|
+
const brandContainer = useMemo(() => {
|
|
29
|
+
if (typeof window !== 'undefined') {
|
|
30
|
+
return (
|
|
31
|
+
document.querySelector('[data-brand]') ||
|
|
32
|
+
document.querySelector('[class^="theme-"], [class*=" theme-"]') ||
|
|
33
|
+
document.body
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
if (!state.isOpen && !isExiting) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Overlay isExiting={isExiting} portalContainer={portalContainer || brandContainer}>
|
|
44
|
+
<div className={styles.base({ className })} style={{ zIndex }} {...underlayProps}>
|
|
45
|
+
{children({ flyoutRef: ref, modalProps })}
|
|
46
|
+
</div>
|
|
47
|
+
</Overlay>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
export const styles = tv({
|
|
4
|
+
slots: {
|
|
5
|
+
base: 'fixed inset-0',
|
|
6
|
+
},
|
|
7
|
+
variants: {
|
|
8
|
+
isOpen: {
|
|
9
|
+
true: {
|
|
10
|
+
base: 'animate-fadeIn bg-black/65',
|
|
11
|
+
},
|
|
12
|
+
false: {
|
|
13
|
+
base: 'pointer-events-none',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ReactNode, type RefObject } from 'react';
|
|
2
|
+
import { type AriaModalOverlayProps, type useModalOverlay } from 'react-aria';
|
|
3
|
+
import { type OverlayTriggerState } from 'react-stately';
|
|
4
|
+
|
|
5
|
+
export type FlyoutBackdropRenderProps = {
|
|
6
|
+
flyoutRef: RefObject<HTMLDivElement>;
|
|
7
|
+
modalProps: ReturnType<typeof useModalOverlay>['modalProps'];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type FlyoutBackdropProps = {
|
|
11
|
+
/**
|
|
12
|
+
* Function that renders the flyout dialog within the backdrop
|
|
13
|
+
*/
|
|
14
|
+
children: (props: FlyoutBackdropRenderProps) => ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* Additional class name for the backdrop
|
|
17
|
+
*/
|
|
18
|
+
className?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Element where the backdrop will be rendered
|
|
21
|
+
*/
|
|
22
|
+
portalContainer?: Element;
|
|
23
|
+
/**
|
|
24
|
+
* The flyout opening and closing state
|
|
25
|
+
*/
|
|
26
|
+
state: OverlayTriggerState;
|
|
27
|
+
/**
|
|
28
|
+
* z-index of the backdrop
|
|
29
|
+
* @default 100
|
|
30
|
+
*/
|
|
31
|
+
zIndex?: number;
|
|
32
|
+
} & AriaModalOverlayProps;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEnterAnimation } from '@react-aria/utils';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
6
|
+
import { mergeProps, useDialog } from 'react-aria';
|
|
7
|
+
|
|
8
|
+
import { Button } from '../../../button/index.js';
|
|
9
|
+
import { CloseIcon } from '../../../icon/index.js';
|
|
10
|
+
|
|
11
|
+
import { styles as dialogStyles } from './flyout-dialog.styles.js';
|
|
12
|
+
import { type FlyoutDialogInternalProps } from './flyout-dialog.types.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
export function FlyoutDialog({
|
|
18
|
+
children,
|
|
19
|
+
className,
|
|
20
|
+
closeAssistiveText = 'Close flyout',
|
|
21
|
+
flyoutRef,
|
|
22
|
+
heading,
|
|
23
|
+
headingTag: HeadingTag = 'h2',
|
|
24
|
+
isOpen,
|
|
25
|
+
modalProps,
|
|
26
|
+
onClose,
|
|
27
|
+
position = 'right',
|
|
28
|
+
...props
|
|
29
|
+
}: FlyoutDialogInternalProps) {
|
|
30
|
+
const isEntering = useEnterAnimation(flyoutRef);
|
|
31
|
+
const styles = dialogStyles({ isEntering, isOpen, position });
|
|
32
|
+
const { dialogProps, titleProps } = useDialog(props, flyoutRef);
|
|
33
|
+
const [scrolled, setScrolled] = useState<boolean>(false);
|
|
34
|
+
const listRef = useRef<HTMLDivElement>(null);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const element = listRef.current;
|
|
38
|
+
if (!element) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const listener = () => {
|
|
42
|
+
const y = listRef.current?.scrollTop || 0;
|
|
43
|
+
setScrolled(y > 0);
|
|
44
|
+
};
|
|
45
|
+
listRef?.current?.addEventListener('scroll', listener);
|
|
46
|
+
return () => {
|
|
47
|
+
listRef?.current?.removeEventListener('scroll', listener);
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
{...mergeProps(modalProps, dialogProps, props)}
|
|
54
|
+
aria-hidden={!isOpen || undefined}
|
|
55
|
+
className={styles.base({ className })}
|
|
56
|
+
ref={flyoutRef}
|
|
57
|
+
>
|
|
58
|
+
<div className={styles.content()}>
|
|
59
|
+
<div
|
|
60
|
+
className={clsx(styles.header(), {
|
|
61
|
+
'shadow-[0_2px_5px_rgba(0,0,0,0.3)]': scrolled,
|
|
62
|
+
})}
|
|
63
|
+
>
|
|
64
|
+
{heading && (
|
|
65
|
+
<HeadingTag {...titleProps} className={styles.heading()}>
|
|
66
|
+
{heading}
|
|
67
|
+
</HeadingTag>
|
|
68
|
+
)}
|
|
69
|
+
{onClose && (
|
|
70
|
+
<Button
|
|
71
|
+
aria-label={closeAssistiveText}
|
|
72
|
+
className={styles.button()}
|
|
73
|
+
iconAfter={() => <CloseIcon color="primary" size="medium" aria-hidden />}
|
|
74
|
+
look="link"
|
|
75
|
+
onClick={onClose}
|
|
76
|
+
type="button"
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
<div className={styles.body()} ref={listRef}>
|
|
81
|
+
{children}
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
export const styles = tv({
|
|
4
|
+
slots: {
|
|
5
|
+
base: 'fixed inset-y-0 flex w-50 flex-col bg-background-white transition-transform duration-500 ease-[cubic-bezier(0.23,1,0.32,1)]',
|
|
6
|
+
body: 'min-h-0 flex-1 overflow-auto',
|
|
7
|
+
button: 'ml-auto shrink-0',
|
|
8
|
+
content: 'flex h-full flex-col',
|
|
9
|
+
header: 'flex h-9 w-full shrink-0 items-center pl-2',
|
|
10
|
+
heading: 'min-w-0 typography-body-10 font-bold text-text-body',
|
|
11
|
+
},
|
|
12
|
+
variants: {
|
|
13
|
+
isEntering: {
|
|
14
|
+
true: {},
|
|
15
|
+
},
|
|
16
|
+
isOpen: {
|
|
17
|
+
true: {
|
|
18
|
+
base: 'translate-x-0',
|
|
19
|
+
},
|
|
20
|
+
false: {
|
|
21
|
+
content: 'hidden',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
position: {
|
|
25
|
+
left: {
|
|
26
|
+
base: 'left-0 border-r border-border-muted-soft',
|
|
27
|
+
},
|
|
28
|
+
right: {
|
|
29
|
+
base: 'right-0 border-l border-border-muted-soft',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
compoundSlots: [
|
|
34
|
+
{
|
|
35
|
+
slots: ['base'],
|
|
36
|
+
isOpen: false,
|
|
37
|
+
position: 'left',
|
|
38
|
+
className: '-translate-x-full',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
slots: ['base'],
|
|
42
|
+
isOpen: false,
|
|
43
|
+
position: 'right',
|
|
44
|
+
className: 'translate-x-full',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
slots: ['base'],
|
|
48
|
+
isEntering: true,
|
|
49
|
+
position: 'left',
|
|
50
|
+
className: '-translate-x-full',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
slots: ['base'],
|
|
54
|
+
isEntering: true,
|
|
55
|
+
position: 'right',
|
|
56
|
+
className: 'translate-x-full',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode, type RefObject } from 'react';
|
|
2
|
+
import { type AriaDialogProps, type useModalOverlay } from 'react-aria';
|
|
3
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
4
|
+
|
|
5
|
+
import { styles } from './flyout-dialog.styles.js';
|
|
6
|
+
|
|
7
|
+
type Variants = VariantProps<typeof styles>;
|
|
8
|
+
|
|
9
|
+
export type FlyoutDialogProps = {
|
|
10
|
+
/**
|
|
11
|
+
* Flyout content
|
|
12
|
+
*/
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* Assistive text for the close button
|
|
16
|
+
* @default Close flyout
|
|
17
|
+
*/
|
|
18
|
+
closeAssistiveText?: string;
|
|
19
|
+
/**
|
|
20
|
+
* The heading of the flyout
|
|
21
|
+
*/
|
|
22
|
+
heading?: ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* The flyout heading tag may be overridden for semantic reasons
|
|
25
|
+
* @default h2
|
|
26
|
+
*/
|
|
27
|
+
headingTag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
28
|
+
/**
|
|
29
|
+
* Called when the close button is pressed
|
|
30
|
+
*/
|
|
31
|
+
onClose?: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Side of the page from which the flyout opens
|
|
34
|
+
* @default right
|
|
35
|
+
*/
|
|
36
|
+
position?: Variants['position'];
|
|
37
|
+
} & AriaDialogProps &
|
|
38
|
+
HTMLAttributes<HTMLDivElement>;
|
|
39
|
+
|
|
40
|
+
export type FlyoutDialogInternalProps = FlyoutDialogProps & {
|
|
41
|
+
flyoutRef: RefObject<HTMLDivElement>;
|
|
42
|
+
isOpen: boolean;
|
|
43
|
+
modalProps: ReturnType<typeof useModalOverlay>['modalProps'];
|
|
44
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { FlyoutBackdrop, FlyoutDialog } from './components/index.js';
|
|
6
|
+
import { type FlyoutProps } from './flyout.types.js';
|
|
7
|
+
|
|
8
|
+
export function Flyout({
|
|
9
|
+
backdropClassName,
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
closeAssistiveText,
|
|
13
|
+
heading,
|
|
14
|
+
headingTag,
|
|
15
|
+
isDismissable = true,
|
|
16
|
+
isKeyboardDismissDisabled,
|
|
17
|
+
portalContainer,
|
|
18
|
+
position = 'right',
|
|
19
|
+
shouldCloseOnInteractOutside,
|
|
20
|
+
state,
|
|
21
|
+
zIndex,
|
|
22
|
+
...props
|
|
23
|
+
}: FlyoutProps) {
|
|
24
|
+
return (
|
|
25
|
+
<FlyoutBackdrop
|
|
26
|
+
className={backdropClassName}
|
|
27
|
+
isDismissable={isDismissable}
|
|
28
|
+
isKeyboardDismissDisabled={isKeyboardDismissDisabled}
|
|
29
|
+
portalContainer={portalContainer}
|
|
30
|
+
shouldCloseOnInteractOutside={shouldCloseOnInteractOutside}
|
|
31
|
+
state={state}
|
|
32
|
+
zIndex={zIndex}
|
|
33
|
+
>
|
|
34
|
+
{({ flyoutRef, modalProps }) => (
|
|
35
|
+
<FlyoutDialog
|
|
36
|
+
{...props}
|
|
37
|
+
className={className}
|
|
38
|
+
closeAssistiveText={closeAssistiveText}
|
|
39
|
+
flyoutRef={flyoutRef}
|
|
40
|
+
heading={heading}
|
|
41
|
+
headingTag={headingTag}
|
|
42
|
+
isOpen={state.isOpen}
|
|
43
|
+
modalProps={modalProps}
|
|
44
|
+
onClose={isDismissable ? () => state.close() : undefined}
|
|
45
|
+
position={position}
|
|
46
|
+
key={position}
|
|
47
|
+
>
|
|
48
|
+
{children}
|
|
49
|
+
</FlyoutDialog>
|
|
50
|
+
)}
|
|
51
|
+
</FlyoutBackdrop>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type FlyoutBackdropProps, type FlyoutDialogProps } from './components/index.js';
|
|
2
|
+
|
|
3
|
+
export type FlyoutProps = Omit<FlyoutBackdropProps, 'children' | 'className'> &
|
|
4
|
+
Omit<FlyoutDialogProps, 'onClose'> & {
|
|
5
|
+
/**
|
|
6
|
+
* Additional class name for the backdrop
|
|
7
|
+
*/
|
|
8
|
+
backdropClassName?: string;
|
|
9
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import React, {
|
|
|
10
10
|
useId,
|
|
11
11
|
useMemo,
|
|
12
12
|
} from 'react';
|
|
13
|
+
import { twMerge } from 'tailwind-merge';
|
|
13
14
|
|
|
14
15
|
import { useBreakpoint } from '../../hook/breakpoints.hook.js';
|
|
15
16
|
import { resolveResponsiveVariant } from '../../utils/breakpoint.util.js';
|
|
@@ -94,14 +95,14 @@ export function InputGroup({
|
|
|
94
95
|
|
|
95
96
|
const renderChildren = useCallback(() => {
|
|
96
97
|
return Children.map<ReactNode, ReactNode>(children, child => {
|
|
97
|
-
if (isValidElement(child)) {
|
|
98
|
+
if (isValidElement<{ className?: string }>(child)) {
|
|
98
99
|
return cloneElement(child, {
|
|
99
100
|
size: resolvedSize,
|
|
100
101
|
id: propID || id,
|
|
101
102
|
'aria-labelledby': ariaLabelledBy,
|
|
102
103
|
'aria-describedby': ariaDescribedBy || ariaDescribedByValue,
|
|
103
104
|
'aria-label': ariaLabel,
|
|
104
|
-
className: 'focus:z-10', // for focus ring visibility
|
|
105
|
+
className: twMerge('focus:z-10', child.props.className), // for focus ring visibility
|
|
105
106
|
...(resolvedWidth !== 'full' ? { width: resolvedWidth } : {}),
|
|
106
107
|
} as Partial<unknown> & Attributes);
|
|
107
108
|
}
|