@westpac/ui 1.1.1 → 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 +19 -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 +19 -6
- 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 +32 -5
- package/src/components/multi-select/multi-select.component.tsx +18 -3
- package/src/components/multi-select/multi-select.types.ts +23 -1
|
@@ -71,12 +71,12 @@ function Autocomplete({ size = 'medium', invalid = false, isDisabled, footer, po
|
|
|
71
71
|
const { buttonProps } = useButton(clearButtonProps, clearButtonRef);
|
|
72
72
|
const outerRef = React.useRef(null);
|
|
73
73
|
const isNoOptionPopOverOpen = useMemo(()=>{
|
|
74
|
-
return !!(noOptionsMessage && (!state.isOpen && state.isFocused && searchProps.value.length > 0 &&
|
|
74
|
+
return !!(noOptionsMessage && (!state.isOpen && state.isFocused && searchProps.value.length > 0 && state.selectedItems.length === 0 || state.collection.size === 0 && searchProps.value.length > 0));
|
|
75
75
|
}, [
|
|
76
76
|
noOptionsMessage,
|
|
77
77
|
state.isOpen,
|
|
78
78
|
state.isFocused,
|
|
79
|
-
state.
|
|
79
|
+
state.selectedItems,
|
|
80
80
|
state.collection.size,
|
|
81
81
|
searchProps.value.length
|
|
82
82
|
]);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { MultiSelectDropdownProps } from './multi-select-dropdown.types.js';
|
|
2
|
-
export declare function MultiSelectDropdown<T extends object = object>({ setFilterText, ...props }: MultiSelectDropdownProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function MultiSelectDropdown<T extends object = object>({ setFilterText, hideFilter, ...props }: MultiSelectDropdownProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,10 +4,10 @@ import { MultiSelectListBox } from '../../components/multi-select-list-box/multi
|
|
|
4
4
|
import { MultiSelectContext } from '../../multi-select.component.js';
|
|
5
5
|
import { MultiSelectPopover } from '../multi-select-popover/multi-select-popover.component.js';
|
|
6
6
|
import { MultiSelectSearchbar } from '../multi-select-searchbar/multi-select-searchbar.component.js';
|
|
7
|
-
export function MultiSelectDropdown({ setFilterText, ...props }) {
|
|
7
|
+
export function MultiSelectDropdown({ setFilterText, hideFilter, ...props }) {
|
|
8
8
|
const { filterText, listBoxRef } = useContext(MultiSelectContext);
|
|
9
9
|
const closeBtnRef = useRef(null);
|
|
10
|
-
return React.createElement(MultiSelectPopover, null, React.createElement(MultiSelectSearchbar, {
|
|
10
|
+
return React.createElement(MultiSelectPopover, null, !hideFilter && React.createElement(MultiSelectSearchbar, {
|
|
11
11
|
filterText: filterText,
|
|
12
12
|
setFilterText: setFilterText,
|
|
13
13
|
closeBtnRef: closeBtnRef
|
|
@@ -7,7 +7,7 @@ import { MultiSelectOption } from './components/multi-select-option/multi-select
|
|
|
7
7
|
import { MultiSelectSelectAllOption } from './components/multi-select-select-all-option/multi-select-select-all-option.component.js';
|
|
8
8
|
import { styles as listBoxStyles } from './multi-select-list-box.styles.js';
|
|
9
9
|
export function MultiSelectListBox({ listBoxRef, ...props }) {
|
|
10
|
-
const { listState } = useContext(MultiSelectContext);
|
|
10
|
+
const { listState, hideSelectAll } = useContext(MultiSelectContext);
|
|
11
11
|
const selectionMode = listState.selectionManager.selectionMode;
|
|
12
12
|
const { listBoxProps } = useListBox({
|
|
13
13
|
selectionMode,
|
|
@@ -19,7 +19,7 @@ export function MultiSelectListBox({ listBoxRef, ...props }) {
|
|
|
19
19
|
const styles = listBoxStyles();
|
|
20
20
|
return React.createElement("div", {
|
|
21
21
|
className: styles.container()
|
|
22
|
-
}, selectionMode === 'multiple' && stateCollection.length > 0 && React.createElement(MultiSelectSelectAllOption, null), React.createElement("ul", {
|
|
22
|
+
}, selectionMode === 'multiple' && stateCollection.length > 0 && !hideSelectAll && React.createElement(MultiSelectSelectAllOption, null), React.createElement("ul", {
|
|
23
23
|
...listBoxProps,
|
|
24
24
|
ref: listBoxRef,
|
|
25
25
|
className: styles.ul()
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { MultiSelectListBoxTriggerProps } from './multi-select-list-box-trigger.types.js';
|
|
2
|
-
export declare function MultiSelectListBoxTrigger<T>({ placeholder, showSingleSectionTitle, selectedKeys, triggerProps, id, }: MultiSelectListBoxTriggerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function MultiSelectListBoxTrigger<T>({ placeholder, showSingleSectionTitle, selectedKeys, triggerProps, id, width, }: MultiSelectListBoxTriggerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -7,7 +7,7 @@ import { DropDownIcon, ClearIcon } from '../../../icon/index.js';
|
|
|
7
7
|
import { Tooltip } from '../../../tooltip/tooltip.component.js';
|
|
8
8
|
import { MultiSelectContext } from '../../multi-select.component.js';
|
|
9
9
|
import { styles as triggerStyles } from './multi-select-list-box-trigger.styles.js';
|
|
10
|
-
export function MultiSelectListBoxTrigger({ placeholder, showSingleSectionTitle, selectedKeys, triggerProps, id }) {
|
|
10
|
+
export function MultiSelectListBoxTrigger({ placeholder, showSingleSectionTitle, selectedKeys, triggerProps, id, width }) {
|
|
11
11
|
const { size, overlayState, listState, buttonRef, inputRef } = useContext(MultiSelectContext);
|
|
12
12
|
const selectionMode = listState.selectionManager.selectionMode;
|
|
13
13
|
const breakpoint = useBreakpoint();
|
|
@@ -18,7 +18,8 @@ export function MultiSelectListBoxTrigger({ placeholder, showSingleSectionTitle,
|
|
|
18
18
|
const finalButtonProps = mergeProps(focusProps, buttonProps);
|
|
19
19
|
const styles = triggerStyles({
|
|
20
20
|
size: resolveResponsiveVariant(size, breakpoint),
|
|
21
|
-
isFocusVisible
|
|
21
|
+
isFocusVisible,
|
|
22
|
+
width: resolveResponsiveVariant(width, breakpoint)
|
|
22
23
|
});
|
|
23
24
|
const getSectionTitle = useCallback((key)=>{
|
|
24
25
|
const parentKey = key !== null && key !== void 0 ? key : '';
|
|
@@ -36,43 +36,44 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
|
|
|
36
36
|
};
|
|
37
37
|
width: {
|
|
38
38
|
full: {
|
|
39
|
-
|
|
39
|
+
selectionSpan: string;
|
|
40
|
+
buttonContainer: string;
|
|
40
41
|
};
|
|
41
42
|
1: {
|
|
42
|
-
|
|
43
|
+
selectionSpan: string;
|
|
43
44
|
};
|
|
44
45
|
2: {
|
|
45
|
-
|
|
46
|
+
selectionSpan: string;
|
|
46
47
|
};
|
|
47
48
|
3: {
|
|
48
|
-
|
|
49
|
+
selectionSpan: string;
|
|
49
50
|
};
|
|
50
51
|
4: {
|
|
51
|
-
|
|
52
|
+
selectionSpan: string;
|
|
52
53
|
};
|
|
53
54
|
5: {
|
|
54
|
-
|
|
55
|
+
selectionSpan: string;
|
|
55
56
|
};
|
|
56
57
|
6: {
|
|
57
|
-
|
|
58
|
+
selectionSpan: string;
|
|
58
59
|
};
|
|
59
60
|
7: {
|
|
60
|
-
|
|
61
|
+
selectionSpan: string;
|
|
61
62
|
};
|
|
62
63
|
8: {
|
|
63
|
-
|
|
64
|
+
selectionSpan: string;
|
|
64
65
|
};
|
|
65
66
|
9: {
|
|
66
|
-
|
|
67
|
+
selectionSpan: string;
|
|
67
68
|
};
|
|
68
69
|
10: {
|
|
69
|
-
|
|
70
|
+
selectionSpan: string;
|
|
70
71
|
};
|
|
71
72
|
20: {
|
|
72
|
-
|
|
73
|
+
selectionSpan: string;
|
|
73
74
|
};
|
|
74
75
|
30: {
|
|
75
|
-
|
|
76
|
+
selectionSpan: string;
|
|
76
77
|
};
|
|
77
78
|
};
|
|
78
79
|
}, {
|
|
@@ -122,43 +123,44 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
|
|
|
122
123
|
};
|
|
123
124
|
width: {
|
|
124
125
|
full: {
|
|
125
|
-
|
|
126
|
+
selectionSpan: string;
|
|
127
|
+
buttonContainer: string;
|
|
126
128
|
};
|
|
127
129
|
1: {
|
|
128
|
-
|
|
130
|
+
selectionSpan: string;
|
|
129
131
|
};
|
|
130
132
|
2: {
|
|
131
|
-
|
|
133
|
+
selectionSpan: string;
|
|
132
134
|
};
|
|
133
135
|
3: {
|
|
134
|
-
|
|
136
|
+
selectionSpan: string;
|
|
135
137
|
};
|
|
136
138
|
4: {
|
|
137
|
-
|
|
139
|
+
selectionSpan: string;
|
|
138
140
|
};
|
|
139
141
|
5: {
|
|
140
|
-
|
|
142
|
+
selectionSpan: string;
|
|
141
143
|
};
|
|
142
144
|
6: {
|
|
143
|
-
|
|
145
|
+
selectionSpan: string;
|
|
144
146
|
};
|
|
145
147
|
7: {
|
|
146
|
-
|
|
148
|
+
selectionSpan: string;
|
|
147
149
|
};
|
|
148
150
|
8: {
|
|
149
|
-
|
|
151
|
+
selectionSpan: string;
|
|
150
152
|
};
|
|
151
153
|
9: {
|
|
152
|
-
|
|
154
|
+
selectionSpan: string;
|
|
153
155
|
};
|
|
154
156
|
10: {
|
|
155
|
-
|
|
157
|
+
selectionSpan: string;
|
|
156
158
|
};
|
|
157
159
|
20: {
|
|
158
|
-
|
|
160
|
+
selectionSpan: string;
|
|
159
161
|
};
|
|
160
162
|
30: {
|
|
161
|
-
|
|
163
|
+
selectionSpan: string;
|
|
162
164
|
};
|
|
163
165
|
};
|
|
164
166
|
}, {
|
|
@@ -208,43 +210,44 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
|
|
|
208
210
|
};
|
|
209
211
|
width: {
|
|
210
212
|
full: {
|
|
211
|
-
|
|
213
|
+
selectionSpan: string;
|
|
214
|
+
buttonContainer: string;
|
|
212
215
|
};
|
|
213
216
|
1: {
|
|
214
|
-
|
|
217
|
+
selectionSpan: string;
|
|
215
218
|
};
|
|
216
219
|
2: {
|
|
217
|
-
|
|
220
|
+
selectionSpan: string;
|
|
218
221
|
};
|
|
219
222
|
3: {
|
|
220
|
-
|
|
223
|
+
selectionSpan: string;
|
|
221
224
|
};
|
|
222
225
|
4: {
|
|
223
|
-
|
|
226
|
+
selectionSpan: string;
|
|
224
227
|
};
|
|
225
228
|
5: {
|
|
226
|
-
|
|
229
|
+
selectionSpan: string;
|
|
227
230
|
};
|
|
228
231
|
6: {
|
|
229
|
-
|
|
232
|
+
selectionSpan: string;
|
|
230
233
|
};
|
|
231
234
|
7: {
|
|
232
|
-
|
|
235
|
+
selectionSpan: string;
|
|
233
236
|
};
|
|
234
237
|
8: {
|
|
235
|
-
|
|
238
|
+
selectionSpan: string;
|
|
236
239
|
};
|
|
237
240
|
9: {
|
|
238
|
-
|
|
241
|
+
selectionSpan: string;
|
|
239
242
|
};
|
|
240
243
|
10: {
|
|
241
|
-
|
|
244
|
+
selectionSpan: string;
|
|
242
245
|
};
|
|
243
246
|
20: {
|
|
244
|
-
|
|
247
|
+
selectionSpan: string;
|
|
245
248
|
};
|
|
246
249
|
30: {
|
|
247
|
-
|
|
250
|
+
selectionSpan: string;
|
|
248
251
|
};
|
|
249
252
|
};
|
|
250
253
|
}, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tv } from 'tailwind-variants';
|
|
2
2
|
export const styles = tv({
|
|
3
3
|
slots: {
|
|
4
|
-
buttonContainer: 'relative w-
|
|
4
|
+
buttonContainer: 'relative w-fit',
|
|
5
5
|
control: 'form-control relative box-border inline-flex w-full flex-row overflow-hidden',
|
|
6
6
|
selection: 'flex flex-1 items-center overflow-hidden pr-4.5 text-left whitespace-nowrap',
|
|
7
7
|
selectionSpan: 'w-full overflow-hidden text-ellipsis',
|
|
@@ -48,43 +48,44 @@ export const styles = tv({
|
|
|
48
48
|
},
|
|
49
49
|
width: {
|
|
50
50
|
full: {
|
|
51
|
-
|
|
51
|
+
selectionSpan: 'w-full',
|
|
52
|
+
buttonContainer: 'w-full'
|
|
52
53
|
},
|
|
53
54
|
1: {
|
|
54
|
-
|
|
55
|
+
selectionSpan: 'w-[1.81ex]'
|
|
55
56
|
},
|
|
56
57
|
2: {
|
|
57
|
-
|
|
58
|
+
selectionSpan: 'w-[3.62ex]'
|
|
58
59
|
},
|
|
59
60
|
3: {
|
|
60
|
-
|
|
61
|
+
selectionSpan: 'w-[5.43ex]'
|
|
61
62
|
},
|
|
62
63
|
4: {
|
|
63
|
-
|
|
64
|
+
selectionSpan: 'w-[7.24ex]'
|
|
64
65
|
},
|
|
65
66
|
5: {
|
|
66
|
-
|
|
67
|
+
selectionSpan: 'w-[9.05ex]'
|
|
67
68
|
},
|
|
68
69
|
6: {
|
|
69
|
-
|
|
70
|
+
selectionSpan: 'w-[10.86ex]'
|
|
70
71
|
},
|
|
71
72
|
7: {
|
|
72
|
-
|
|
73
|
+
selectionSpan: 'w-[12.67ex]'
|
|
73
74
|
},
|
|
74
75
|
8: {
|
|
75
|
-
|
|
76
|
+
selectionSpan: 'w-[14.48ex]'
|
|
76
77
|
},
|
|
77
78
|
9: {
|
|
78
|
-
|
|
79
|
+
selectionSpan: 'w-[16.29ex]'
|
|
79
80
|
},
|
|
80
81
|
10: {
|
|
81
|
-
|
|
82
|
+
selectionSpan: 'w-[18.1ex]'
|
|
82
83
|
},
|
|
83
84
|
20: {
|
|
84
|
-
|
|
85
|
+
selectionSpan: 'w-[36.2ex]'
|
|
85
86
|
},
|
|
86
87
|
30: {
|
|
87
|
-
|
|
88
|
+
selectionSpan: 'w-[54.3ex]'
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
}
|
|
@@ -12,5 +12,6 @@ export type MultiSelectListBoxTriggerProps<T> = {
|
|
|
12
12
|
selectedKeys?: ListProps<T>['selectedKeys'];
|
|
13
13
|
showSingleSectionTitle?: MultiSelectProps<T>['showSingleSectionTitle'];
|
|
14
14
|
triggerProps: AriaButtonProps<'button'>;
|
|
15
|
+
width?: ResponsiveVariants<Variants['width']>;
|
|
15
16
|
};
|
|
16
17
|
export {};
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import React, { useContext } from 'react';
|
|
2
|
+
import React, { useContext, useLayoutEffect, useMemo } from 'react';
|
|
3
3
|
import { DismissButton, mergeProps, Overlay, usePopover } from 'react-aria';
|
|
4
4
|
import { MultiSelectContext } from '../../multi-select.component.js';
|
|
5
5
|
import { styles as popoverStyles } from './multi-select-popover.styles.js';
|
|
6
6
|
export function MultiSelectPopover({ children, className, ...props }) {
|
|
7
|
-
var _buttonRef_current;
|
|
7
|
+
var _buttonRef_current, _popoverProps_style;
|
|
8
8
|
const { overlayState, overlayProps, popoverRef, buttonRef, placement, portalContainer } = useContext(MultiSelectContext);
|
|
9
|
+
const [isPopoverSmaller, setIsPopoverSmaller] = React.useState(false);
|
|
10
|
+
useLayoutEffect(()=>{
|
|
11
|
+
if (buttonRef.current && popoverRef.current) {
|
|
12
|
+
const buttonWidth = buttonRef.current.getBoundingClientRect().width;
|
|
13
|
+
const popoverWidth = popoverRef.current.getBoundingClientRect().width;
|
|
14
|
+
setIsPopoverSmaller(popoverWidth < buttonWidth);
|
|
15
|
+
}
|
|
16
|
+
}, []);
|
|
9
17
|
const { popoverProps } = usePopover({
|
|
10
18
|
...props,
|
|
11
|
-
placement,
|
|
19
|
+
placement: placement,
|
|
12
20
|
popoverRef,
|
|
13
21
|
triggerRef: buttonRef,
|
|
14
22
|
isNonModal: true,
|
|
@@ -16,11 +24,15 @@ export function MultiSelectPopover({ children, className, ...props }) {
|
|
|
16
24
|
shouldCloseOnInteractOutside: ()=>false,
|
|
17
25
|
offset: 6
|
|
18
26
|
}, overlayState);
|
|
19
|
-
const
|
|
27
|
+
const brandContainer = useMemo(()=>{
|
|
28
|
+
if (typeof window !== 'undefined') {
|
|
29
|
+
return document.querySelector('[data-theme]') || document.querySelector('[class^="theme-"], [class*=" theme-"]') || document.body;
|
|
30
|
+
}
|
|
31
|
+
}, []);
|
|
20
32
|
const styles = popoverStyles();
|
|
21
33
|
return React.createElement(Overlay, {
|
|
22
34
|
disableFocusManagement: true,
|
|
23
|
-
portalContainer: portalContainer
|
|
35
|
+
portalContainer: portalContainer || brandContainer
|
|
24
36
|
}, React.createElement("div", {
|
|
25
37
|
...mergeProps(popoverProps, overlayProps),
|
|
26
38
|
ref: popoverRef,
|
|
@@ -29,7 +41,8 @@ export function MultiSelectPopover({ children, className, ...props }) {
|
|
|
29
41
|
}),
|
|
30
42
|
style: {
|
|
31
43
|
...popoverProps.style,
|
|
32
|
-
width:
|
|
44
|
+
width: isPopoverSmaller ? (_buttonRef_current = buttonRef.current) === null || _buttonRef_current === void 0 ? void 0 : _buttonRef_current.getBoundingClientRect().width : undefined,
|
|
45
|
+
maxWidth: brandContainer ? brandContainer.getBoundingClientRect().width - (parseInt((_popoverProps_style = popoverProps.style) === null || _popoverProps_style === void 0 ? void 0 : _popoverProps_style.left) || 0) : undefined
|
|
33
46
|
},
|
|
34
47
|
onBlur: (e)=>{
|
|
35
48
|
const related = e.relatedTarget;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { MultiSelectContextProps, MultiSelectItemProps, MultiSelectProps, MultiSelectValue } from './multi-select.types.js';
|
|
3
3
|
export declare const MultiSelectContext: React.Context<MultiSelectContextProps>;
|
|
4
|
-
export declare function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({ size, listBoxProps, selectionMode, selectedKeys, onSelectionChange, placeholder, showSingleSectionTitle, placement, portalContainer, id, ...props }: MultiSelectProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({ size, listBoxProps, selectionMode, selectedKeys, onSelectionChange, placeholder, showSingleSectionTitle, placement, portalContainer, id, hideFilter, hideSelectAll, width, ...props }: MultiSelectProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
export declare const MultiSelect: React.MemoExoticComponent<typeof BaseMultiSelect>;
|
|
6
6
|
export declare const MultiSelectItem: (props: MultiSelectItemProps) => JSX.Element;
|
|
7
7
|
export { Section as MultiSelectSection } from 'react-stately';
|
|
@@ -25,9 +25,10 @@ export const MultiSelectContext = createContext({
|
|
|
25
25
|
current: null
|
|
26
26
|
},
|
|
27
27
|
filterText: '',
|
|
28
|
-
overlayProps: {}
|
|
28
|
+
overlayProps: {},
|
|
29
|
+
hideSelectAll: false
|
|
29
30
|
});
|
|
30
|
-
export function BaseMultiSelect({ size = 'medium', listBoxProps, selectionMode = 'multiple', selectedKeys, onSelectionChange, placeholder = 'Select', showSingleSectionTitle = false, placement, portalContainer, id, ...props }) {
|
|
31
|
+
export function BaseMultiSelect({ size = 'medium', listBoxProps, selectionMode = 'multiple', selectedKeys, onSelectionChange, placeholder = 'Select', showSingleSectionTitle = false, placement = 'bottom left', portalContainer, id, hideFilter = false, hideSelectAll = false, width = 'full', ...props }) {
|
|
31
32
|
const [filterText, setFilterText] = useState('');
|
|
32
33
|
const filter = useFilter({
|
|
33
34
|
sensitivity: 'base'
|
|
@@ -48,8 +49,17 @@ export function BaseMultiSelect({ size = 'medium', listBoxProps, selectionMode =
|
|
|
48
49
|
onOpenChange: (isOpen)=>{
|
|
49
50
|
if (isOpen) {
|
|
50
51
|
requestAnimationFrame(()=>{
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
if (!hideFilter) {
|
|
53
|
+
var _inputRef_current;
|
|
54
|
+
(_inputRef_current = inputRef.current) === null || _inputRef_current === void 0 ? void 0 : _inputRef_current.focus();
|
|
55
|
+
} else if (selectionMode === 'multiple' && !hideSelectAll) {
|
|
56
|
+
var _selectAllRef_current;
|
|
57
|
+
(_selectAllRef_current = selectAllRef.current) === null || _selectAllRef_current === void 0 ? void 0 : _selectAllRef_current.focus();
|
|
58
|
+
} else {
|
|
59
|
+
var _listBoxRef_current;
|
|
60
|
+
const firstItem = (_listBoxRef_current = listBoxRef.current) === null || _listBoxRef_current === void 0 ? void 0 : _listBoxRef_current.querySelector('[data-key]');
|
|
61
|
+
firstItem === null || firstItem === void 0 ? void 0 : firstItem.focus();
|
|
62
|
+
}
|
|
53
63
|
});
|
|
54
64
|
}
|
|
55
65
|
if (!isOpen) {
|
|
@@ -75,7 +85,8 @@ export function BaseMultiSelect({ size = 'medium', listBoxProps, selectionMode =
|
|
|
75
85
|
listBoxRef,
|
|
76
86
|
inputRef,
|
|
77
87
|
overlayProps,
|
|
78
|
-
portalContainer
|
|
88
|
+
portalContainer,
|
|
89
|
+
hideSelectAll
|
|
79
90
|
}
|
|
80
91
|
}, React.createElement("div", {
|
|
81
92
|
className: styles.root()
|
|
@@ -84,9 +95,11 @@ export function BaseMultiSelect({ size = 'medium', listBoxProps, selectionMode =
|
|
|
84
95
|
selectedKeys: selectedKeys,
|
|
85
96
|
showSingleSectionTitle: showSingleSectionTitle,
|
|
86
97
|
triggerProps: triggerProps,
|
|
87
|
-
id: id
|
|
98
|
+
id: id,
|
|
99
|
+
width: width
|
|
88
100
|
}), overlayState.isOpen && React.createElement(MultiSelectDropdown, {
|
|
89
101
|
setFilterText: setFilterText,
|
|
102
|
+
hideFilter: hideFilter,
|
|
90
103
|
...listBoxProps
|
|
91
104
|
})));
|
|
92
105
|
}
|
|
@@ -2,7 +2,11 @@ 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';
|
|
6
|
+
import { ResponsiveVariants } from '../../types/responsive-variants.types.js';
|
|
7
|
+
import { styles as triggerStyles } from './components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.js';
|
|
5
8
|
import { MultiSelectSize } from './components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.js';
|
|
9
|
+
type Variants = VariantProps<typeof triggerStyles>;
|
|
6
10
|
export type MultiSelectContextProps<T extends object = object> = {
|
|
7
11
|
size?: MultiSelectSize;
|
|
8
12
|
overlayState: OverlayTriggerState;
|
|
@@ -16,6 +20,7 @@ export type MultiSelectContextProps<T extends object = object> = {
|
|
|
16
20
|
overlayProps: DOMProps;
|
|
17
21
|
placement?: AriaPopoverProps['placement'];
|
|
18
22
|
portalContainer?: Element;
|
|
23
|
+
hideSelectAll?: boolean;
|
|
19
24
|
};
|
|
20
25
|
export type MultiSelectItemProps<T extends object = object> = {
|
|
21
26
|
description?: string;
|
|
@@ -27,6 +32,16 @@ export type MultiSelectValue = {
|
|
|
27
32
|
description?: string;
|
|
28
33
|
};
|
|
29
34
|
export type MultiSelectProps<T> = {
|
|
35
|
+
/**
|
|
36
|
+
* Whether to hide the filter input in the dropdown
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
hideFilter?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether to hide the "Select All" option in the dropdown for multiple selection multi-selects
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
hideSelectAll?: boolean;
|
|
30
45
|
/**
|
|
31
46
|
* Props for the list box within the multi-select
|
|
32
47
|
*/
|
|
@@ -41,7 +56,7 @@ export type MultiSelectProps<T> = {
|
|
|
41
56
|
placeholder?: string;
|
|
42
57
|
/**
|
|
43
58
|
* Manual placement of the dropdown, will flip automatically if there is not enough space
|
|
44
|
-
* @default bottom
|
|
59
|
+
* @default 'bottom left'
|
|
45
60
|
*/
|
|
46
61
|
placement?: AriaPopoverProps['placement'];
|
|
47
62
|
/**
|
|
@@ -58,4 +73,10 @@ export type MultiSelectProps<T> = {
|
|
|
58
73
|
* @default medium
|
|
59
74
|
*/
|
|
60
75
|
size?: MultiSelectSize;
|
|
76
|
+
/**
|
|
77
|
+
* Width of the multi-select, can be a fixed width or full width
|
|
78
|
+
* @default full
|
|
79
|
+
*/
|
|
80
|
+
width?: ResponsiveVariants<Variants['width']>;
|
|
61
81
|
} & ListProps<T>;
|
|
82
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@westpac/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -254,9 +254,9 @@
|
|
|
254
254
|
"vite": "^7.1.12",
|
|
255
255
|
"vitest": "^3.2.4",
|
|
256
256
|
"@westpac/eslint-config": "~1.1.0",
|
|
257
|
-
"@westpac/style-config": "~1.0.
|
|
258
|
-
"@westpac/
|
|
259
|
-
"@westpac/
|
|
257
|
+
"@westpac/style-config": "~1.0.2",
|
|
258
|
+
"@westpac/test-config": "~0.0.0",
|
|
259
|
+
"@westpac/ts-config": "~0.0.0"
|
|
260
260
|
},
|
|
261
261
|
"dependencies": {
|
|
262
262
|
"@internationalized/date": "~3.10.0",
|
|
@@ -99,14 +99,14 @@ function Autocomplete<T extends object>(
|
|
|
99
99
|
const isNoOptionPopOverOpen = useMemo(() => {
|
|
100
100
|
return !!(
|
|
101
101
|
noOptionsMessage &&
|
|
102
|
-
((!state.isOpen && state.isFocused && searchProps.value.length > 0 &&
|
|
102
|
+
((!state.isOpen && state.isFocused && searchProps.value.length > 0 && state.selectedItems.length === 0) ||
|
|
103
103
|
(state.collection.size === 0 && searchProps.value.length > 0))
|
|
104
104
|
);
|
|
105
105
|
}, [
|
|
106
106
|
noOptionsMessage,
|
|
107
107
|
state.isOpen,
|
|
108
108
|
state.isFocused,
|
|
109
|
-
state.
|
|
109
|
+
state.selectedItems,
|
|
110
110
|
state.collection.size,
|
|
111
111
|
searchProps.value.length,
|
|
112
112
|
]);
|
|
@@ -12,6 +12,7 @@ import { MultiSelectDropdownProps } from './multi-select-dropdown.types.js';
|
|
|
12
12
|
|
|
13
13
|
export function MultiSelectDropdown<T extends object = object>({
|
|
14
14
|
setFilterText,
|
|
15
|
+
hideFilter,
|
|
15
16
|
...props
|
|
16
17
|
}: MultiSelectDropdownProps<T>) {
|
|
17
18
|
const { filterText, listBoxRef } = useContext(MultiSelectContext);
|
|
@@ -19,7 +20,9 @@ export function MultiSelectDropdown<T extends object = object>({
|
|
|
19
20
|
|
|
20
21
|
return (
|
|
21
22
|
<MultiSelectPopover>
|
|
22
|
-
|
|
23
|
+
{!hideFilter && (
|
|
24
|
+
<MultiSelectSearchbar filterText={filterText} setFilterText={setFilterText} closeBtnRef={closeBtnRef} />
|
|
25
|
+
)}
|
|
23
26
|
<MultiSelectListBox {...props} aria-label="multiselect list" escapeKeyBehavior="none" listBoxRef={listBoxRef} />
|
|
24
27
|
</MultiSelectPopover>
|
|
25
28
|
);
|
|
@@ -13,7 +13,7 @@ import { styles as listBoxStyles } from './multi-select-list-box.styles.js';
|
|
|
13
13
|
import type { MultiSelectListBoxProps } from './multi-select-list-box.types.js';
|
|
14
14
|
|
|
15
15
|
export function MultiSelectListBox<T extends object = object>({ listBoxRef, ...props }: MultiSelectListBoxProps<T>) {
|
|
16
|
-
const { listState } = useContext(MultiSelectContext);
|
|
16
|
+
const { listState, hideSelectAll } = useContext(MultiSelectContext);
|
|
17
17
|
const selectionMode = listState.selectionManager.selectionMode;
|
|
18
18
|
const { listBoxProps } = useListBox({ selectionMode, ...props }, listState, listBoxRef);
|
|
19
19
|
|
|
@@ -23,7 +23,7 @@ export function MultiSelectListBox<T extends object = object>({ listBoxRef, ...p
|
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
25
|
<div className={styles.container()}>
|
|
26
|
-
{selectionMode === 'multiple' && stateCollection.length > 0 && <MultiSelectSelectAllOption />}
|
|
26
|
+
{selectionMode === 'multiple' && stateCollection.length > 0 && !hideSelectAll && <MultiSelectSelectAllOption />}
|
|
27
27
|
<ul {...listBoxProps} ref={listBoxRef} className={styles.ul()}>
|
|
28
28
|
{stateCollection.length > 0 ? (
|
|
29
29
|
stateCollection.map(item =>
|
|
@@ -17,6 +17,7 @@ export function MultiSelectListBoxTrigger<T>({
|
|
|
17
17
|
selectedKeys,
|
|
18
18
|
triggerProps,
|
|
19
19
|
id,
|
|
20
|
+
width,
|
|
20
21
|
}: MultiSelectListBoxTriggerProps<T>) {
|
|
21
22
|
const { size, overlayState, listState, buttonRef, inputRef } = useContext(MultiSelectContext);
|
|
22
23
|
const selectionMode = listState.selectionManager.selectionMode;
|
|
@@ -30,6 +31,7 @@ export function MultiSelectListBoxTrigger<T>({
|
|
|
30
31
|
const styles = triggerStyles({
|
|
31
32
|
size: resolveResponsiveVariant(size, breakpoint),
|
|
32
33
|
isFocusVisible,
|
|
34
|
+
width: resolveResponsiveVariant(width, breakpoint),
|
|
33
35
|
});
|
|
34
36
|
|
|
35
37
|
const getSectionTitle = useCallback(
|