@transferwise/components 46.54.1 → 46.56.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/README.md +0 -8
- package/build/button/Button.js.map +1 -1
- package/build/button/Button.mjs.map +1 -1
- package/build/common/panel/Panel.js +1 -2
- package/build/common/panel/Panel.js.map +1 -1
- package/build/common/panel/Panel.mjs +1 -2
- package/build/common/panel/Panel.mjs.map +1 -1
- package/build/select/Select.js +39 -123
- package/build/select/Select.js.map +1 -1
- package/build/select/Select.mjs +39 -119
- package/build/select/Select.mjs.map +1 -1
- package/build/snackbar/Snackbar.js +2 -1
- package/build/snackbar/Snackbar.js.map +1 -1
- package/build/snackbar/Snackbar.mjs +2 -1
- package/build/snackbar/Snackbar.mjs.map +1 -1
- package/build/types/button/Button.d.ts +2 -2
- package/build/types/button/Button.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/select/Select.d.ts +64 -94
- package/build/types/select/Select.d.ts.map +1 -1
- package/build/types/select/index.d.ts +2 -2
- package/build/types/select/index.d.ts.map +1 -1
- package/build/types/select/option/index.d.ts +1 -1
- package/build/types/select/option/index.d.ts.map +1 -1
- package/build/types/select/searchBox/index.d.ts +1 -1
- package/build/types/select/searchBox/index.d.ts.map +1 -1
- package/build/types/snackbar/Snackbar.d.ts.map +1 -1
- package/build/types/upload/steps/uploadImageStep/uploadImageStep.d.ts.map +1 -1
- package/build/upload/steps/uploadImageStep/uploadImageStep.js +2 -0
- package/build/upload/steps/uploadImageStep/uploadImageStep.js.map +1 -1
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs +2 -0
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs.map +1 -1
- package/package.json +3 -5
- package/src/button/Button.tsx +2 -2
- package/src/index.ts +6 -0
- package/src/select/{Select.spec.js → Select.spec.tsx} +8 -6
- package/src/select/{Select.js → Select.tsx} +135 -153
- package/src/select/index.ts +7 -0
- package/src/snackbar/Snackbar.tsx +7 -1
- package/src/upload/Upload.story.tsx +1 -0
- package/src/upload/steps/uploadImageStep/uploadImageStep.tsx +5 -1
- package/build/select/index.js +0 -8
- package/build/select/index.js.map +0 -1
- package/build/select/index.mjs +0 -6
- package/build/select/index.mjs.map +0 -1
- package/src/select/index.js +0 -3
- /package/src/select/option/{index.js → index.ts} +0 -0
- /package/src/select/searchBox/{SearchBox.spec.js → SearchBox.spec.tsx} +0 -0
- /package/src/select/searchBox/{index.js → index.ts} +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { useTheme } from '@wise/components-theming';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
|
-
import PropTypes from 'prop-types';
|
|
4
3
|
import { useState, useEffect, useRef, useMemo, useId } from 'react';
|
|
5
4
|
import { useIntl } from 'react-intl';
|
|
6
5
|
|
|
7
|
-
import Button from '../button';
|
|
6
|
+
import Button, { ButtonProps } from '../button';
|
|
8
7
|
import Chevron from '../chevron';
|
|
9
|
-
import { Position } from '../common';
|
|
8
|
+
import { Position, Size } from '../common';
|
|
10
9
|
import BottomSheet from '../common/bottomSheet';
|
|
11
10
|
import { stopPropagation } from '../common/domHelpers';
|
|
12
11
|
import { useLayout } from '../common/hooks';
|
|
@@ -21,35 +20,56 @@ import SearchBox from './searchBox';
|
|
|
21
20
|
const DEFAULT_SEARCH_VALUE = '';
|
|
22
21
|
const DEFAULT_OPTIONS_PAGE_SIZE = 1000;
|
|
23
22
|
|
|
24
|
-
const includesString = (string1, string2) =>
|
|
23
|
+
const includesString = (string1: string, string2: string) =>
|
|
24
|
+
string1.toLowerCase().includes(string2.toLowerCase());
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
export interface SelectOptionItem {
|
|
27
|
+
value: any;
|
|
28
|
+
label?: React.ReactNode;
|
|
29
|
+
icon?: React.ReactNode;
|
|
30
|
+
currency?: string;
|
|
31
|
+
note?: React.ReactNode;
|
|
32
|
+
secondary?: React.ReactNode;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SelectItem extends Partial<SelectOptionItem> {
|
|
36
|
+
header?: React.ReactNode;
|
|
37
|
+
separator?: boolean;
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
searchStrings?: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface SelectItemWithPlaceholder extends SelectItem {
|
|
43
|
+
placeholder?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function defaultFilterFunction(option: SelectItemWithPlaceholder, searchValue: string) {
|
|
27
47
|
if (isPlaceholderOption(option)) {
|
|
28
48
|
return true;
|
|
29
49
|
}
|
|
30
50
|
const { label, note, secondary, currency, searchStrings } = option;
|
|
31
51
|
return (
|
|
32
|
-
(
|
|
33
|
-
(
|
|
34
|
-
(
|
|
52
|
+
(typeof label === 'string' && includesString(label, searchValue)) ||
|
|
53
|
+
(typeof note === 'string' && includesString(note, searchValue)) ||
|
|
54
|
+
(typeof secondary === 'string' && includesString(secondary, searchValue)) ||
|
|
35
55
|
(!!currency && includesString(currency, searchValue)) ||
|
|
36
56
|
(!!searchStrings && searchStrings.some((string) => includesString(string, searchValue)))
|
|
37
57
|
);
|
|
38
58
|
}
|
|
39
59
|
|
|
40
|
-
function isActionableOption(option) {
|
|
60
|
+
function isActionableOption(option: SelectItem) {
|
|
41
61
|
return !option.header && !option.separator && !option.disabled;
|
|
42
62
|
}
|
|
43
63
|
|
|
44
|
-
function isHeaderOption(option) {
|
|
64
|
+
function isHeaderOption(option: SelectItem | null) {
|
|
45
65
|
return option != null && 'header' in option;
|
|
46
66
|
}
|
|
47
67
|
|
|
48
|
-
function isSeparatorOption(option) {
|
|
68
|
+
function isSeparatorOption(option: SelectItem | null) {
|
|
49
69
|
return option != null && 'separator' in option;
|
|
50
70
|
}
|
|
51
71
|
|
|
52
|
-
function clamp(from, to, value) {
|
|
72
|
+
function clamp(from: number, to: number, value: number) {
|
|
53
73
|
return Math.max(Math.min(to, value), from);
|
|
54
74
|
}
|
|
55
75
|
|
|
@@ -58,24 +78,62 @@ function clamp(from, to, value) {
|
|
|
58
78
|
*/
|
|
59
79
|
const DEFAULT_SELECTED_OPTION = null;
|
|
60
80
|
|
|
61
|
-
function isPlaceholderOption(option) {
|
|
81
|
+
function isPlaceholderOption(option: SelectItemWithPlaceholder | null) {
|
|
62
82
|
return option === DEFAULT_SELECTED_OPTION || 'placeholder' in option;
|
|
63
83
|
}
|
|
64
84
|
|
|
65
|
-
function isSearchableOption(option) {
|
|
85
|
+
function isSearchableOption(option: SelectItemWithPlaceholder | null) {
|
|
66
86
|
return !isHeaderOption(option) && !isSeparatorOption(option) && !isPlaceholderOption(option);
|
|
67
87
|
}
|
|
68
88
|
|
|
69
|
-
const getUniqueIdForOption = (parentId
|
|
89
|
+
const getUniqueIdForOption = (parentId: string | undefined, option: SelectItem | null) => {
|
|
70
90
|
if (option == null) {
|
|
71
91
|
return undefined;
|
|
72
92
|
}
|
|
73
93
|
|
|
74
|
-
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
95
|
+
const uniqueOptionId =
|
|
96
|
+
option.value || (typeof option.label === 'string' ? option.label.replace(/\s/g, '') : '');
|
|
75
97
|
|
|
76
|
-
return `option-${parentId}-${uniqueOptionId}`;
|
|
98
|
+
return `option-${parentId ?? ''}-${uniqueOptionId}`;
|
|
77
99
|
};
|
|
78
100
|
|
|
101
|
+
export interface SelectProps {
|
|
102
|
+
placeholder?: string;
|
|
103
|
+
id?: string;
|
|
104
|
+
required?: boolean;
|
|
105
|
+
disabled?: boolean;
|
|
106
|
+
inverse?: boolean;
|
|
107
|
+
dropdownRight?: `${Size.EXTRA_SMALL | Size.SMALL | Size.MEDIUM | Size.LARGE | Size.EXTRA_LARGE}`;
|
|
108
|
+
dropdownWidth?: `${Size.SMALL | Size.MEDIUM | Size.LARGE}`;
|
|
109
|
+
size?: `${Size.SMALL | Size.MEDIUM | Size.LARGE}`;
|
|
110
|
+
block?: boolean;
|
|
111
|
+
selected?: SelectOptionItem;
|
|
112
|
+
/**
|
|
113
|
+
* Search toggle
|
|
114
|
+
* if `true` default search functionality being enabled (not case sensitive search in option labels & currency props)
|
|
115
|
+
* if `function` you can define your own search function to implement custom search experience. This search function used while filtering the options array.
|
|
116
|
+
*/
|
|
117
|
+
search?: boolean | ((option: SelectItemWithPlaceholder, searchValue: string) => boolean);
|
|
118
|
+
options: SelectItem[];
|
|
119
|
+
searchValue?: string;
|
|
120
|
+
searchPlaceholder?: string;
|
|
121
|
+
classNames?: Record<string, string>;
|
|
122
|
+
dropdownUp?: boolean;
|
|
123
|
+
buttonProps?: Extract<ButtonProps, { as?: 'button' }>;
|
|
124
|
+
dropdownProps?: React.ComponentPropsWithoutRef<'ul'>;
|
|
125
|
+
onChange: (value: SelectItem | typeof DEFAULT_SELECTED_OPTION) => void;
|
|
126
|
+
onFocus?: React.FocusEventHandler<HTMLDivElement>;
|
|
127
|
+
onBlur?: React.FocusEventHandler<HTMLDivElement>;
|
|
128
|
+
/**
|
|
129
|
+
* To have full control of your search value and response use `onSearchChange` function combined with `searchValue` and custom filtering on the options array.
|
|
130
|
+
* DO NOT USE TOGETHER WITH `search` PROPERTY
|
|
131
|
+
*/
|
|
132
|
+
onSearchChange?: (value: string) => void;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const defaultClassNames = {};
|
|
136
|
+
|
|
79
137
|
/**
|
|
80
138
|
* @deprecated Use `SelectInput` instead (https://neptune.wise.design/blog/2023-11-28-adopting-our-new-selectinput)
|
|
81
139
|
*/
|
|
@@ -86,8 +144,8 @@ export default function Select({
|
|
|
86
144
|
disabled,
|
|
87
145
|
inverse,
|
|
88
146
|
dropdownWidth,
|
|
89
|
-
size,
|
|
90
|
-
block,
|
|
147
|
+
size = 'md',
|
|
148
|
+
block = true,
|
|
91
149
|
selected,
|
|
92
150
|
search,
|
|
93
151
|
onChange,
|
|
@@ -95,29 +153,28 @@ export default function Select({
|
|
|
95
153
|
onBlur,
|
|
96
154
|
options: defaultOptions,
|
|
97
155
|
onSearchChange,
|
|
98
|
-
searchValue: initSearchValue,
|
|
156
|
+
searchValue: initSearchValue = '',
|
|
99
157
|
searchPlaceholder,
|
|
100
|
-
|
|
101
|
-
classNames: classNamesProp,
|
|
158
|
+
classNames: classNamesProp = defaultClassNames,
|
|
102
159
|
dropdownUp,
|
|
103
160
|
dropdownProps,
|
|
104
161
|
buttonProps,
|
|
105
|
-
}) {
|
|
162
|
+
}: SelectProps) {
|
|
106
163
|
const inputAttributes = useInputAttributes();
|
|
107
164
|
|
|
108
165
|
const { formatMessage } = useIntl();
|
|
109
166
|
const { isModern } = useTheme();
|
|
110
|
-
const s = (className) => classNamesProp[className] || className;
|
|
167
|
+
const s = (className: string) => classNamesProp[className] || className;
|
|
111
168
|
const [open, setOpen] = useState(false);
|
|
112
169
|
const [searchValue, setSearchValue] = useState(DEFAULT_SEARCH_VALUE);
|
|
113
|
-
const [keyboardFocusedOptionIndex, setKeyboardFocusedOptionIndex] = useState(
|
|
114
|
-
const keyboardFocusedReference = useRef();
|
|
115
|
-
const previousKeyboardFocusedOptionIndex = useRef();
|
|
170
|
+
const [keyboardFocusedOptionIndex, setKeyboardFocusedOptionIndex] = useState(-1);
|
|
171
|
+
const keyboardFocusedReference = useRef<HTMLLIElement>(null);
|
|
172
|
+
const previousKeyboardFocusedOptionIndex = useRef(-1);
|
|
116
173
|
const [numberOfOptionsShown, setNumberOfOptionsShown] = useState(DEFAULT_OPTIONS_PAGE_SIZE);
|
|
117
|
-
const searchBoxReference = useRef(null);
|
|
118
|
-
const selectReference = useRef(null);
|
|
119
|
-
const dropdownButtonReference = useRef(null);
|
|
120
|
-
const optionsListReference = useRef(null);
|
|
174
|
+
const searchBoxReference = useRef<HTMLInputElement>(null);
|
|
175
|
+
const selectReference = useRef<HTMLDivElement>(null);
|
|
176
|
+
const dropdownButtonReference = useRef<HTMLButtonElement>(null);
|
|
177
|
+
const optionsListReference = useRef<HTMLUListElement>(null);
|
|
121
178
|
const isSearchEnabled = !!onSearchChange || !!search;
|
|
122
179
|
const isDropdownAutoWidth = dropdownWidth == null;
|
|
123
180
|
|
|
@@ -145,7 +202,7 @@ export default function Select({
|
|
|
145
202
|
const { isMobile } = useLayout();
|
|
146
203
|
|
|
147
204
|
useEffect(() => {
|
|
148
|
-
let cancelled;
|
|
205
|
+
let cancelled = false;
|
|
149
206
|
|
|
150
207
|
if (keyboardFocusedOptionIndex >= 0) {
|
|
151
208
|
requestAnimationFrame(() => {
|
|
@@ -168,42 +225,40 @@ export default function Select({
|
|
|
168
225
|
setOpen(true);
|
|
169
226
|
};
|
|
170
227
|
|
|
171
|
-
const handleTouchStart = (event) => {
|
|
228
|
+
const handleTouchStart: React.TouchEventHandler<HTMLDivElement> = (event) => {
|
|
172
229
|
if (event.currentTarget === event.target && open) {
|
|
173
230
|
handleCloseOptions();
|
|
174
231
|
}
|
|
175
232
|
};
|
|
176
233
|
|
|
177
|
-
const handleOnFocus = (event) => {
|
|
178
|
-
|
|
179
|
-
onFocus(event);
|
|
180
|
-
}
|
|
234
|
+
const handleOnFocus: React.FocusEventHandler<HTMLDivElement> = (event) => {
|
|
235
|
+
onFocus?.(event);
|
|
181
236
|
};
|
|
182
237
|
|
|
183
|
-
const handleOnBlur = (event) => {
|
|
238
|
+
const handleOnBlur: React.FocusEventHandler<HTMLDivElement> = (event) => {
|
|
184
239
|
const { nativeEvent } = event;
|
|
185
240
|
if (nativeEvent) {
|
|
186
241
|
const elementReceivingFocus = nativeEvent.relatedTarget;
|
|
187
242
|
const select = event.currentTarget;
|
|
188
|
-
if (
|
|
243
|
+
if (
|
|
244
|
+
select &&
|
|
245
|
+
elementReceivingFocus instanceof Node &&
|
|
246
|
+
select.contains(elementReceivingFocus)
|
|
247
|
+
) {
|
|
189
248
|
return;
|
|
190
249
|
}
|
|
191
250
|
}
|
|
192
251
|
|
|
193
|
-
|
|
194
|
-
onBlur(event);
|
|
195
|
-
}
|
|
252
|
+
onBlur?.(event);
|
|
196
253
|
};
|
|
197
254
|
|
|
198
|
-
const handleSearchChange = (event) => {
|
|
255
|
+
const handleSearchChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
|
199
256
|
setNumberOfOptionsShown(DEFAULT_OPTIONS_PAGE_SIZE);
|
|
200
257
|
setSearchValue(event.target.value);
|
|
201
|
-
|
|
202
|
-
onSearchChange(event.target.value);
|
|
203
|
-
}
|
|
258
|
+
onSearchChange?.(event.target.value);
|
|
204
259
|
};
|
|
205
260
|
|
|
206
|
-
const handleKeyDown = (event) => {
|
|
261
|
+
const handleKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event) => {
|
|
207
262
|
switch (event.key) {
|
|
208
263
|
case 'ArrowUp':
|
|
209
264
|
case 'ArrowDown':
|
|
@@ -247,25 +302,25 @@ export default function Select({
|
|
|
247
302
|
};
|
|
248
303
|
|
|
249
304
|
function selectKeyboardFocusedOption() {
|
|
250
|
-
if (keyboardFocusedOptionIndex
|
|
305
|
+
if (keyboardFocusedOptionIndex >= 0 && selectableOptions.length > 0) {
|
|
251
306
|
selectOption(selectableOptions[keyboardFocusedOptionIndex]);
|
|
252
307
|
}
|
|
253
308
|
}
|
|
254
309
|
|
|
255
|
-
function moveFocusWithDifference(difference) {
|
|
310
|
+
function moveFocusWithDifference(difference: number) {
|
|
256
311
|
const selectedOptionIndex = selectableOptions.reduce((optionIndex, current, index) => {
|
|
257
|
-
if (optionIndex
|
|
312
|
+
if (optionIndex >= 0) {
|
|
258
313
|
return optionIndex;
|
|
259
314
|
}
|
|
260
315
|
if (isOptionSelected(selected, current)) {
|
|
261
316
|
return index;
|
|
262
317
|
}
|
|
263
|
-
return
|
|
264
|
-
},
|
|
265
|
-
const previousFocusedIndex = previousKeyboardFocusedOptionIndex.current
|
|
318
|
+
return -1;
|
|
319
|
+
}, -1);
|
|
320
|
+
const previousFocusedIndex = previousKeyboardFocusedOptionIndex.current;
|
|
266
321
|
let indexToStartMovingFrom = previousFocusedIndex;
|
|
267
|
-
if (previousFocusedIndex
|
|
268
|
-
if (selectedOptionIndex
|
|
322
|
+
if (previousFocusedIndex < 0) {
|
|
323
|
+
if (selectedOptionIndex < 0) {
|
|
269
324
|
setKeyboardFocusedOptionIndex(0);
|
|
270
325
|
} else {
|
|
271
326
|
indexToStartMovingFrom = selectedOptionIndex;
|
|
@@ -287,8 +342,7 @@ export default function Select({
|
|
|
287
342
|
if (
|
|
288
343
|
!isSearchEnabled &&
|
|
289
344
|
optionsListReference.current &&
|
|
290
|
-
|
|
291
|
-
Number.isNaN(previousKeyboardFocusedOptionIndex.current))
|
|
345
|
+
previousKeyboardFocusedOptionIndex.current < 0
|
|
292
346
|
) {
|
|
293
347
|
optionsListReference.current.focus();
|
|
294
348
|
}
|
|
@@ -296,31 +350,31 @@ export default function Select({
|
|
|
296
350
|
|
|
297
351
|
previousKeyboardFocusedOptionIndex.current = keyboardFocusedOptionIndex;
|
|
298
352
|
} else {
|
|
299
|
-
previousKeyboardFocusedOptionIndex.current =
|
|
353
|
+
previousKeyboardFocusedOptionIndex.current = -1;
|
|
300
354
|
}
|
|
301
355
|
}, [open, searchValue, isSearchEnabled, isMobile, keyboardFocusedOptionIndex]);
|
|
302
356
|
|
|
303
357
|
const handleCloseOptions = () => {
|
|
304
358
|
setOpen(false);
|
|
305
|
-
setKeyboardFocusedOptionIndex(
|
|
359
|
+
setKeyboardFocusedOptionIndex(-1);
|
|
306
360
|
if (dropdownButtonReference.current) {
|
|
307
361
|
dropdownButtonReference.current.focus();
|
|
308
362
|
}
|
|
309
363
|
};
|
|
310
364
|
|
|
311
|
-
function createSelectHandlerForOption(option) {
|
|
312
|
-
return (event) => {
|
|
365
|
+
function createSelectHandlerForOption(option: SelectItemWithPlaceholder) {
|
|
366
|
+
return (event: React.SyntheticEvent) => {
|
|
313
367
|
stopPropagation(event);
|
|
314
368
|
selectOption(option);
|
|
315
369
|
};
|
|
316
370
|
}
|
|
317
371
|
|
|
318
|
-
function selectOption(option) {
|
|
372
|
+
function selectOption(option: SelectItemWithPlaceholder) {
|
|
319
373
|
onChange(isPlaceholderOption(option) ? DEFAULT_SELECTED_OPTION : option);
|
|
320
374
|
handleCloseOptions();
|
|
321
375
|
}
|
|
322
376
|
|
|
323
|
-
function renderOptionsList({ className } = {}) {
|
|
377
|
+
function renderOptionsList({ className = '' } = {}) {
|
|
324
378
|
const dropdownClass = clsx(
|
|
325
379
|
s('np-dropdown-menu'),
|
|
326
380
|
{
|
|
@@ -337,8 +391,8 @@ export default function Select({
|
|
|
337
391
|
id={listboxId}
|
|
338
392
|
role="listbox"
|
|
339
393
|
aria-orientation="vertical"
|
|
340
|
-
aria-activedescendant={getUniqueIdForOption(id, selected)}
|
|
341
|
-
tabIndex=
|
|
394
|
+
aria-activedescendant={getUniqueIdForOption(id, selected ?? null)}
|
|
395
|
+
tabIndex={-1}
|
|
342
396
|
className={dropdownClass}
|
|
343
397
|
{...dropdownProps}
|
|
344
398
|
>
|
|
@@ -362,7 +416,7 @@ export default function Select({
|
|
|
362
416
|
}
|
|
363
417
|
|
|
364
418
|
function ShowMoreOption() {
|
|
365
|
-
function handleOnClick(event) {
|
|
419
|
+
function handleOnClick(event: React.SyntheticEvent<HTMLLIElement>) {
|
|
366
420
|
stopPropagation(event);
|
|
367
421
|
setNumberOfOptionsShown(numberOfOptionsShown + DEFAULT_OPTIONS_PAGE_SIZE);
|
|
368
422
|
}
|
|
@@ -400,7 +454,7 @@ export default function Select({
|
|
|
400
454
|
}
|
|
401
455
|
|
|
402
456
|
// eslint-disable-next-line react/prop-types
|
|
403
|
-
function HeaderOption({ children }) {
|
|
457
|
+
function HeaderOption({ children }: { children?: React.ReactNode }) {
|
|
404
458
|
return (
|
|
405
459
|
<li // eslint-disable-line jsx-a11y/no-noninteractive-element-interactions
|
|
406
460
|
className={clsx(s('np-dropdown-header'), s('np-text-title-group'))}
|
|
@@ -412,11 +466,11 @@ export default function Select({
|
|
|
412
466
|
);
|
|
413
467
|
}
|
|
414
468
|
|
|
415
|
-
function isOptionSelected(selected, option) {
|
|
469
|
+
function isOptionSelected(selected: SelectOptionItem | undefined, option: SelectItem) {
|
|
416
470
|
return selected?.value === option?.value;
|
|
417
471
|
}
|
|
418
472
|
|
|
419
|
-
const renderOption = (option, index) => {
|
|
473
|
+
const renderOption = (option: SelectItem, index: number) => {
|
|
420
474
|
const separatorOption = option;
|
|
421
475
|
if (isSeparatorOption(separatorOption) && separatorOption?.separator) {
|
|
422
476
|
return <SeparatorOption key={index} />;
|
|
@@ -454,20 +508,25 @@ export default function Select({
|
|
|
454
508
|
aria-selected={isActive}
|
|
455
509
|
aria-disabled={option.disabled}
|
|
456
510
|
role="option"
|
|
457
|
-
tabIndex=
|
|
511
|
+
tabIndex={-1}
|
|
458
512
|
className={className}
|
|
459
513
|
onClick={handleOnClick}
|
|
460
514
|
onKeyPress={handleOnClick}
|
|
461
515
|
>
|
|
462
516
|
{/* @ts-expect-error options needs DOM refactoring */}
|
|
463
517
|
<a disabled={selectOption.disabled}>
|
|
464
|
-
<Option
|
|
518
|
+
<Option
|
|
519
|
+
label={undefined}
|
|
520
|
+
value={undefined}
|
|
521
|
+
{...selectOption}
|
|
522
|
+
classNames={classNamesProp}
|
|
523
|
+
/>
|
|
465
524
|
</a>
|
|
466
525
|
</li>
|
|
467
526
|
);
|
|
468
527
|
};
|
|
469
528
|
|
|
470
|
-
function getIndexWithoutHeadersForIndexWithHeaders(index) {
|
|
529
|
+
function getIndexWithoutHeadersForIndexWithHeaders(index: number) {
|
|
471
530
|
return options.reduce((sum, option, currentIndex) => {
|
|
472
531
|
if (currentIndex < index && isActionableOption(option)) {
|
|
473
532
|
return sum + 1;
|
|
@@ -478,11 +537,11 @@ export default function Select({
|
|
|
478
537
|
|
|
479
538
|
const hasActiveOptions = !!defaultOptions.length;
|
|
480
539
|
if (open && (initSearchValue || searchValue)) {
|
|
481
|
-
if (hasActiveOptions && keyboardFocusedOptionIndex
|
|
540
|
+
if (hasActiveOptions && keyboardFocusedOptionIndex < 0) {
|
|
482
541
|
setKeyboardFocusedOptionIndex(0);
|
|
483
542
|
}
|
|
484
|
-
if (!hasActiveOptions && keyboardFocusedOptionIndex
|
|
485
|
-
setKeyboardFocusedOptionIndex(
|
|
543
|
+
if (!hasActiveOptions && keyboardFocusedOptionIndex >= 0) {
|
|
544
|
+
setKeyboardFocusedOptionIndex(-1);
|
|
486
545
|
}
|
|
487
546
|
}
|
|
488
547
|
|
|
@@ -517,7 +576,7 @@ export default function Select({
|
|
|
517
576
|
{...buttonProps}
|
|
518
577
|
>
|
|
519
578
|
{selected ? (
|
|
520
|
-
<Option {...selected} classNames={classNamesProp} selected />
|
|
579
|
+
<Option label={undefined} {...selected} classNames={classNamesProp} selected />
|
|
521
580
|
) : (
|
|
522
581
|
<span className={s('form-control-placeholder')}>{placeholder}</span>
|
|
523
582
|
)}
|
|
@@ -562,80 +621,3 @@ export default function Select({
|
|
|
562
621
|
</div>
|
|
563
622
|
);
|
|
564
623
|
}
|
|
565
|
-
|
|
566
|
-
Select.propTypes = {
|
|
567
|
-
placeholder: PropTypes.string,
|
|
568
|
-
id: PropTypes.string,
|
|
569
|
-
required: PropTypes.bool,
|
|
570
|
-
disabled: PropTypes.bool,
|
|
571
|
-
inverse: PropTypes.bool,
|
|
572
|
-
dropdownRight: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
|
|
573
|
-
dropdownWidth: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
574
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
575
|
-
block: PropTypes.bool,
|
|
576
|
-
selected: PropTypes.shape({
|
|
577
|
-
value: PropTypes.any.isRequired,
|
|
578
|
-
label: PropTypes.node,
|
|
579
|
-
icon: PropTypes.node,
|
|
580
|
-
currency: PropTypes.string,
|
|
581
|
-
note: PropTypes.node,
|
|
582
|
-
secondary: PropTypes.node,
|
|
583
|
-
}),
|
|
584
|
-
/**
|
|
585
|
-
* Search toggle
|
|
586
|
-
* if `true` default search functionality being enabled (not case sensitive search in option labels & currency props)
|
|
587
|
-
* if `function` you can define your own search function to implement custom search experience. This search function used while filtering the options array. The custom search function takes two parameters. First is the option the second is the keyword.
|
|
588
|
-
*/
|
|
589
|
-
search: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
|
|
590
|
-
options: PropTypes.arrayOf(
|
|
591
|
-
PropTypes.shape({
|
|
592
|
-
value: PropTypes.any,
|
|
593
|
-
label: PropTypes.node,
|
|
594
|
-
header: PropTypes.node,
|
|
595
|
-
icon: PropTypes.node,
|
|
596
|
-
currency: PropTypes.string,
|
|
597
|
-
note: PropTypes.node,
|
|
598
|
-
secondary: PropTypes.node,
|
|
599
|
-
separator: PropTypes.bool,
|
|
600
|
-
disabled: PropTypes.bool,
|
|
601
|
-
searchStrings: PropTypes.arrayOf(PropTypes.string),
|
|
602
|
-
}),
|
|
603
|
-
).isRequired,
|
|
604
|
-
searchValue: PropTypes.string,
|
|
605
|
-
searchPlaceholder: PropTypes.string,
|
|
606
|
-
classNames: PropTypes.objectOf(PropTypes.string),
|
|
607
|
-
dropdownUp: PropTypes.bool,
|
|
608
|
-
buttonProps: PropTypes.object,
|
|
609
|
-
dropdownProps: PropTypes.object,
|
|
610
|
-
onChange: PropTypes.func.isRequired,
|
|
611
|
-
onFocus: PropTypes.func,
|
|
612
|
-
onBlur: PropTypes.func,
|
|
613
|
-
/**
|
|
614
|
-
* To have full control of your search value and response use `onSearchChange` function combined with `searchValue` and custom filtering on the options array.
|
|
615
|
-
* DO NOT USE TOGETHER WITH `search` PROPERTY
|
|
616
|
-
*/
|
|
617
|
-
onSearchChange: PropTypes.func,
|
|
618
|
-
};
|
|
619
|
-
|
|
620
|
-
Select.defaultProps = {
|
|
621
|
-
id: undefined,
|
|
622
|
-
placeholder: undefined,
|
|
623
|
-
size: 'md',
|
|
624
|
-
dropdownRight: null,
|
|
625
|
-
dropdownWidth: null,
|
|
626
|
-
inverse: false,
|
|
627
|
-
required: false,
|
|
628
|
-
disabled: false,
|
|
629
|
-
block: true,
|
|
630
|
-
selected: null,
|
|
631
|
-
onFocus: null,
|
|
632
|
-
onBlur: null,
|
|
633
|
-
onSearchChange: undefined,
|
|
634
|
-
search: false,
|
|
635
|
-
searchValue: '',
|
|
636
|
-
searchPlaceholder: undefined,
|
|
637
|
-
classNames: {},
|
|
638
|
-
dropdownUp: false,
|
|
639
|
-
buttonProps: {},
|
|
640
|
-
dropdownProps: {},
|
|
641
|
-
};
|
|
@@ -107,7 +107,13 @@ export class Snackbar extends Component<SnackbarProps, SnackbarState> {
|
|
|
107
107
|
}}
|
|
108
108
|
unmountOnExit
|
|
109
109
|
>
|
|
110
|
-
<Body
|
|
110
|
+
<Body
|
|
111
|
+
ref={this.bodyRef}
|
|
112
|
+
as="span"
|
|
113
|
+
className="snackbar__text"
|
|
114
|
+
role="status"
|
|
115
|
+
aria-live="assertive"
|
|
116
|
+
>
|
|
111
117
|
{text}
|
|
112
118
|
{action ? (
|
|
113
119
|
<ActionButton className="snackbar__text__action" onClick={action.onClick}>
|
|
@@ -64,7 +64,11 @@ export default class UploadImageStep extends PureComponent<UploadImageStepProps>
|
|
|
64
64
|
<div className="m-b-3">{this.getImage()}</div>
|
|
65
65
|
{usLabel && <h4 className="np-text-title-body m-b-1">{usLabel}</h4>}
|
|
66
66
|
{usPlaceholder && <p className="np-text-body-large m-b-3">{String(usPlaceholder)}</p>}
|
|
67
|
-
<label
|
|
67
|
+
<label
|
|
68
|
+
className={`btn btn-primary btn-md ${usDisabled ? 'disabled' : ''}`}
|
|
69
|
+
role="button"
|
|
70
|
+
aria-disabled={usDisabled}
|
|
71
|
+
>
|
|
68
72
|
{usButtonText ? (
|
|
69
73
|
<span>{usButtonText}</span>
|
|
70
74
|
) : (
|
package/build/select/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
package/build/select/index.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/src/select/index.js
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|