@westpac/ui 1.1.2 → 1.2.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/.agents/skills/creating-gel-component/SKILL.md +13 -9
- package/.agents/skills/reviewing-gel-component/SKILL.md +19 -9
- package/.agents/skills/writing-gel-tests/SKILL.md +10 -6
- package/CHANGELOG.md +13 -0
- package/dist/component-type.json +1 -1
- package/dist/components/autocomplete/autocomplete.component.js +2 -2
- package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.component.d.ts +1 -1
- package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.component.js +2 -2
- package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.types.d.ts +1 -0
- package/dist/components/multi-select/components/multi-select-list-box/multi-select-list-box.component.js +2 -2
- package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.component.d.ts +1 -1
- package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.component.js +3 -2
- package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.d.ts +42 -39
- package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.js +15 -14
- package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.d.ts +1 -0
- package/dist/components/multi-select/components/multi-select-popover/multi-select-popover.component.js +13 -5
- package/dist/components/multi-select/multi-select.component.d.ts +1 -1
- package/dist/components/multi-select/multi-select.component.js +19 -6
- package/dist/components/multi-select/multi-select.types.d.ts +22 -1
- package/package.json +4 -4
- package/src/components/autocomplete/autocomplete.component.tsx +2 -2
- package/src/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.component.tsx +4 -1
- package/src/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.types.ts +1 -0
- package/src/components/multi-select/components/multi-select-list-box/multi-select-list-box.component.tsx +2 -2
- package/src/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.component.tsx +2 -0
- package/src/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.ts +14 -14
- package/src/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.ts +1 -0
- package/src/components/multi-select/components/multi-select-popover/multi-select-popover.component.tsx +20 -4
- package/src/components/multi-select/multi-select.component.tsx +18 -3
- package/src/components/multi-select/multi-select.types.ts +23 -1
|
@@ -18,4 +18,5 @@ export type MultiSelectListBoxTriggerProps<T> = {
|
|
|
18
18
|
selectedKeys?: ListProps<T>['selectedKeys'];
|
|
19
19
|
showSingleSectionTitle?: MultiSelectProps<T>['showSingleSectionTitle'];
|
|
20
20
|
triggerProps: AriaButtonProps<'button'>;
|
|
21
|
+
width?: ResponsiveVariants<Variants['width']>;
|
|
21
22
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React, { useContext, useMemo } from 'react';
|
|
3
|
+
import React, { useContext, useLayoutEffect, useMemo } from 'react';
|
|
4
4
|
import { DismissButton, mergeProps, Overlay, usePopover } from 'react-aria';
|
|
5
5
|
|
|
6
6
|
import { MultiSelectContext } from '../../multi-select.component.js';
|
|
@@ -13,10 +13,21 @@ export function MultiSelectPopover({ children, className, ...props }: MultiSelec
|
|
|
13
13
|
const { overlayState, overlayProps, popoverRef, buttonRef, placement, portalContainer } =
|
|
14
14
|
useContext(MultiSelectContext);
|
|
15
15
|
|
|
16
|
+
const [isPopoverSmaller, setIsPopoverSmaller] = React.useState(false);
|
|
17
|
+
|
|
18
|
+
useLayoutEffect(() => {
|
|
19
|
+
if (buttonRef.current && popoverRef.current) {
|
|
20
|
+
const buttonWidth = buttonRef.current.getBoundingClientRect().width;
|
|
21
|
+
const popoverWidth = popoverRef.current.getBoundingClientRect().width;
|
|
22
|
+
setIsPopoverSmaller(popoverWidth < buttonWidth);
|
|
23
|
+
}
|
|
24
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
16
27
|
const { popoverProps } = usePopover(
|
|
17
28
|
{
|
|
18
29
|
...props,
|
|
19
|
-
placement,
|
|
30
|
+
placement: placement,
|
|
20
31
|
popoverRef,
|
|
21
32
|
triggerRef: buttonRef,
|
|
22
33
|
isNonModal: true,
|
|
@@ -38,7 +49,6 @@ export function MultiSelectPopover({ children, className, ...props }: MultiSelec
|
|
|
38
49
|
}
|
|
39
50
|
}, []);
|
|
40
51
|
|
|
41
|
-
const width = buttonRef.current?.getBoundingClientRect().width;
|
|
42
52
|
const styles = popoverStyles();
|
|
43
53
|
|
|
44
54
|
return (
|
|
@@ -47,7 +57,13 @@ export function MultiSelectPopover({ children, className, ...props }: MultiSelec
|
|
|
47
57
|
{...mergeProps(popoverProps, overlayProps)}
|
|
48
58
|
ref={popoverRef}
|
|
49
59
|
className={styles.overlay({ className })}
|
|
50
|
-
style={{
|
|
60
|
+
style={{
|
|
61
|
+
...popoverProps.style,
|
|
62
|
+
width: isPopoverSmaller ? buttonRef.current?.getBoundingClientRect().width : undefined,
|
|
63
|
+
maxWidth: brandContainer
|
|
64
|
+
? brandContainer.getBoundingClientRect().width - (parseInt(popoverProps.style?.left as string) || 0)
|
|
65
|
+
: undefined,
|
|
66
|
+
}}
|
|
51
67
|
onBlur={e => {
|
|
52
68
|
const related = e.relatedTarget as Element | null;
|
|
53
69
|
if (!popoverRef?.current) return;
|
|
@@ -27,6 +27,7 @@ export const MultiSelectContext = createContext<MultiSelectContextProps>({
|
|
|
27
27
|
inputRef: { current: null },
|
|
28
28
|
filterText: '',
|
|
29
29
|
overlayProps: {},
|
|
30
|
+
hideSelectAll: false,
|
|
30
31
|
});
|
|
31
32
|
|
|
32
33
|
export function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({
|
|
@@ -37,9 +38,12 @@ export function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({
|
|
|
37
38
|
onSelectionChange,
|
|
38
39
|
placeholder = 'Select',
|
|
39
40
|
showSingleSectionTitle = false,
|
|
40
|
-
placement,
|
|
41
|
+
placement = 'bottom left',
|
|
41
42
|
portalContainer,
|
|
42
43
|
id,
|
|
44
|
+
hideFilter = false,
|
|
45
|
+
hideSelectAll = false,
|
|
46
|
+
width = 'full',
|
|
43
47
|
...props
|
|
44
48
|
}: MultiSelectProps<T>) {
|
|
45
49
|
const [filterText, setFilterText] = useState('');
|
|
@@ -67,7 +71,14 @@ export function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({
|
|
|
67
71
|
onOpenChange: isOpen => {
|
|
68
72
|
if (isOpen) {
|
|
69
73
|
requestAnimationFrame(() => {
|
|
70
|
-
|
|
74
|
+
if (!hideFilter) {
|
|
75
|
+
inputRef.current?.focus();
|
|
76
|
+
} else if (selectionMode === 'multiple' && !hideSelectAll) {
|
|
77
|
+
selectAllRef.current?.focus();
|
|
78
|
+
} else {
|
|
79
|
+
const firstItem = listBoxRef.current?.querySelector('[data-key]') as HTMLElement;
|
|
80
|
+
firstItem?.focus();
|
|
81
|
+
}
|
|
71
82
|
});
|
|
72
83
|
}
|
|
73
84
|
if (!isOpen) {
|
|
@@ -94,6 +105,7 @@ export function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({
|
|
|
94
105
|
inputRef,
|
|
95
106
|
overlayProps,
|
|
96
107
|
portalContainer,
|
|
108
|
+
hideSelectAll,
|
|
97
109
|
}}
|
|
98
110
|
>
|
|
99
111
|
<div className={styles.root()}>
|
|
@@ -103,8 +115,11 @@ export function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({
|
|
|
103
115
|
showSingleSectionTitle={showSingleSectionTitle}
|
|
104
116
|
triggerProps={triggerProps}
|
|
105
117
|
id={id}
|
|
118
|
+
width={width}
|
|
106
119
|
/>
|
|
107
|
-
{overlayState.isOpen &&
|
|
120
|
+
{overlayState.isOpen && (
|
|
121
|
+
<MultiSelectDropdown setFilterText={setFilterText} hideFilter={hideFilter} {...listBoxProps} />
|
|
122
|
+
)}
|
|
108
123
|
</div>
|
|
109
124
|
</MultiSelectContext.Provider>
|
|
110
125
|
);
|
|
@@ -2,9 +2,15 @@ import { DOMProps } from '@react-types/shared';
|
|
|
2
2
|
import { Key, ReactNode, RefObject } from 'react';
|
|
3
3
|
import { AriaListBoxOptions, AriaPopoverProps } from 'react-aria';
|
|
4
4
|
import { ItemProps, ListProps, ListState, OverlayTriggerState } from 'react-stately';
|
|
5
|
+
import { VariantProps } from 'tailwind-variants';
|
|
5
6
|
|
|
7
|
+
import { ResponsiveVariants } from '../../types/responsive-variants.types.js';
|
|
8
|
+
|
|
9
|
+
import { styles as triggerStyles } from './components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.js';
|
|
6
10
|
import { MultiSelectSize } from './components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.js';
|
|
7
11
|
|
|
12
|
+
type Variants = VariantProps<typeof triggerStyles>;
|
|
13
|
+
|
|
8
14
|
export type MultiSelectContextProps<T extends object = object> = {
|
|
9
15
|
size?: MultiSelectSize;
|
|
10
16
|
overlayState: OverlayTriggerState;
|
|
@@ -18,6 +24,7 @@ export type MultiSelectContextProps<T extends object = object> = {
|
|
|
18
24
|
overlayProps: DOMProps;
|
|
19
25
|
placement?: AriaPopoverProps['placement'];
|
|
20
26
|
portalContainer?: Element;
|
|
27
|
+
hideSelectAll?: boolean;
|
|
21
28
|
};
|
|
22
29
|
|
|
23
30
|
export type MultiSelectItemProps<T extends object = object> = { description?: string } & ItemProps<T>;
|
|
@@ -26,6 +33,16 @@ export type MultiSelectItemProps<T extends object = object> = { description?: st
|
|
|
26
33
|
export type MultiSelectValue = { textValue?: string; content?: ReactNode; key: Key; description?: string };
|
|
27
34
|
|
|
28
35
|
export type MultiSelectProps<T> = {
|
|
36
|
+
/**
|
|
37
|
+
* Whether to hide the filter input in the dropdown
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
40
|
+
hideFilter?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to hide the "Select All" option in the dropdown for multiple selection multi-selects
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
hideSelectAll?: boolean;
|
|
29
46
|
/**
|
|
30
47
|
* Props for the list box within the multi-select
|
|
31
48
|
*/
|
|
@@ -40,7 +57,7 @@ export type MultiSelectProps<T> = {
|
|
|
40
57
|
placeholder?: string;
|
|
41
58
|
/**
|
|
42
59
|
* Manual placement of the dropdown, will flip automatically if there is not enough space
|
|
43
|
-
* @default bottom
|
|
60
|
+
* @default 'bottom left'
|
|
44
61
|
*/
|
|
45
62
|
placement?: AriaPopoverProps['placement'];
|
|
46
63
|
/**
|
|
@@ -57,4 +74,9 @@ export type MultiSelectProps<T> = {
|
|
|
57
74
|
* @default medium
|
|
58
75
|
*/
|
|
59
76
|
size?: MultiSelectSize;
|
|
77
|
+
/**
|
|
78
|
+
* Width of the multi-select, can be a fixed width or full width
|
|
79
|
+
* @default full
|
|
80
|
+
*/
|
|
81
|
+
width?: ResponsiveVariants<Variants['width']>;
|
|
60
82
|
} & ListProps<T>;
|