@transferwise/components 46.6.0 → 46.8.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/build/index.esm.js +290 -346
- package/build/index.esm.js.map +1 -1
- package/build/index.js +290 -345
- package/build/index.js.map +1 -1
- package/build/main.css +107 -17
- package/build/styles/inputs/Input.css +0 -4
- package/build/styles/inputs/SelectInput.css +6 -1
- package/build/styles/inputs/TextArea.css +0 -4
- package/build/styles/main.css +107 -17
- package/build/styles/segmentedControl/SegmentedControl.css +101 -0
- package/build/styles/select/Select.css +0 -4
- package/build/types/common/locale/index.d.ts +26 -43
- package/build/types/common/locale/index.d.ts.map +1 -1
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/inputs/SelectInput.d.ts +6 -5
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts +22 -27
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/data/countries.d.ts +5 -10
- package/build/types/phoneNumberInput/data/countries.d.ts.map +1 -1
- package/build/types/phoneNumberInput/index.d.ts +1 -1
- package/build/types/phoneNumberInput/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts +8 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts +8 -4
- package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts +2 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/index.d.ts +11 -13
- package/build/types/phoneNumberInput/utils/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts +6 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts +2 -1
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts +7 -1
- package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts.map +1 -1
- package/build/types/segmentedControl/SegmentedControl.d.ts +31 -0
- package/build/types/segmentedControl/SegmentedControl.d.ts.map +1 -0
- package/build/types/segmentedControl/index.d.ts +3 -0
- package/build/types/segmentedControl/index.d.ts.map +1 -0
- package/package.json +7 -17
- package/src/common/locale/{index.spec.js → index.spec.ts} +4 -4
- package/src/common/locale/index.ts +96 -0
- package/src/index.ts +3 -0
- package/src/inputs/Input.css +0 -4
- package/src/inputs/SelectInput.css +6 -1
- package/src/inputs/SelectInput.less +8 -1
- package/src/inputs/SelectInput.spec.tsx +26 -0
- package/src/inputs/SelectInput.story.tsx +73 -1
- package/src/inputs/SelectInput.tsx +104 -85
- package/src/inputs/TextArea.css +0 -4
- package/src/main.css +107 -17
- package/src/main.less +1 -0
- package/src/phoneNumberInput/PhoneNumberInput.spec.js +18 -22
- package/src/phoneNumberInput/PhoneNumberInput.tsx +193 -0
- package/src/phoneNumberInput/data/{countries.js → countries.ts} +9 -1
- package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.ts +3 -0
- package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.spec.js → excludeCountries.spec.ts} +1 -1
- package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.js → excludeCountries.ts} +6 -5
- package/src/phoneNumberInput/utils/explodeNumberModel/{explodeNumberModel.spec.js → explodeNumberModel.spec.ts} +1 -1
- package/src/phoneNumberInput/utils/explodeNumberModel/index.ts +24 -0
- package/src/phoneNumberInput/utils/findCountryByCode/{findCountryByCode.spec.js → findCountryByCode.spec.ts} +0 -1
- package/src/phoneNumberInput/utils/findCountryByCode/index.ts +12 -0
- package/src/phoneNumberInput/utils/findCountryByPrefix/index.ts +12 -0
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.ts +102 -0
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.ts +12 -0
- package/src/phoneNumberInput/utils/{index.js → index.ts} +0 -2
- package/src/phoneNumberInput/utils/isStringNumeric/{isStringNumeric.spec.js → isStringNumeric.spec.ts} +0 -1
- package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.ts +1 -0
- package/src/phoneNumberInput/utils/isValidPhoneNumber/{isValidPhoneNumber.spec.js → isValidPhoneNumber.spec.ts} +1 -1
- package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.ts +7 -0
- package/src/phoneNumberInput/utils/longestMatchingPrefix/index.ts +4 -0
- package/src/phoneNumberInput/utils/setDefaultPrefix/index.ts +20 -0
- package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.ts +6 -0
- package/src/segmentedControl/SegmentedControl.css +101 -0
- package/src/segmentedControl/SegmentedControl.less +101 -0
- package/src/segmentedControl/SegmentedControl.spec.tsx +106 -0
- package/src/segmentedControl/SegmentedControl.story.tsx +55 -0
- package/src/segmentedControl/SegmentedControl.tsx +175 -0
- package/src/segmentedControl/index.ts +2 -0
- package/src/select/Select.css +0 -4
- package/src/ssr.spec.js +17 -0
- package/src/withDisplayFormat/WithDisplayFormat.spec.js +1 -1
- package/src/withDisplayFormat/WithDisplayFormat.tsx +1 -1
- package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts +0 -2
- package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts.map +0 -1
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts +0 -2
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts.map +0 -1
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts +0 -3
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts.map +0 -1
- package/build/types/utilities/wrapInFragment.d.ts +0 -3
- package/build/types/utilities/wrapInFragment.d.ts.map +0 -1
- package/src/common/locale/index.js +0 -139
- package/src/phoneNumberInput/PhoneNumberInput.js +0 -210
- package/src/phoneNumberInput/data/countries.spec.js +0 -12
- package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.js +0 -4
- package/src/phoneNumberInput/utils/explodeNumberModel/index.js +0 -27
- package/src/phoneNumberInput/utils/filterOptionsForQuery/filterOptionsForQuery.spec.js +0 -36
- package/src/phoneNumberInput/utils/filterOptionsForQuery/index.js +0 -11
- package/src/phoneNumberInput/utils/findCountryByCode/index.js +0 -10
- package/src/phoneNumberInput/utils/findCountryByPrefix/index.js +0 -11
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.js +0 -26
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.js +0 -67
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/index.js +0 -1
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.js +0 -25
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.spec.js +0 -66
- package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.js +0 -1
- package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js +0 -10
- package/src/phoneNumberInput/utils/longestMatchingPrefix/index.js +0 -2
- package/src/phoneNumberInput/utils/setDefaultPrefix/index.js +0 -25
- package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.js +0 -3
- package/src/utilities/wrapInFragment.tsx +0 -3
- /package/src/phoneNumberInput/{PhoneNumberInput.story.js → PhoneNumberInput.story.tsx} +0 -0
- /package/src/phoneNumberInput/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/cleanNumber/{cleanNumber.spec.js → cleanNumber.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/cleanNumber/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/excludeCountries/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/findCountryByPrefix/{findCountryByPrefix.spec.js → findCountryByPrefix.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/groupCountriesByPrefix/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/isStringNumeric/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/isValidPhoneNumber/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/longestMatchingPrefix/{longestMatchingPrefix.spec.js → longestMatchingPrefix.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/setDefaultPrefix/{setDefaultPrefix.spec.js → setDefaultPrefix.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/sortArrayByProperty/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/sortArrayByProperty/{sortArrayByProperty.spec.js → sortArrayByProperty.spec.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export type {
|
|
|
15
15
|
SelectInputTriggerButtonProps,
|
|
16
16
|
} from './inputs/SelectInput';
|
|
17
17
|
export type { TextAreaProps } from './inputs/TextArea';
|
|
18
|
+
export type { PhoneNumberInputProps } from './phoneNumberInput/PhoneNumberInput';
|
|
18
19
|
export type { TextareaWithDisplayFormatProps } from './textareaWithDisplayFormat';
|
|
19
20
|
export type { UploadedFile, UploadError, UploadResponse } from './uploadInput/types';
|
|
20
21
|
export type { ModalProps } from './modal';
|
|
@@ -32,6 +33,7 @@ export type {
|
|
|
32
33
|
LinkTypes,
|
|
33
34
|
DisplayTypes,
|
|
34
35
|
} from './common';
|
|
36
|
+
export type { SegmentedControlProps } from './segmentedControl';
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
39
|
* Components
|
|
@@ -106,6 +108,7 @@ export { default as RadioGroup } from './radioGroup';
|
|
|
106
108
|
export { default as RadioOption } from './radioOption';
|
|
107
109
|
export { default as Section } from './section';
|
|
108
110
|
export { default as Select } from './select';
|
|
111
|
+
export { default as SegmentedControl } from './segmentedControl';
|
|
109
112
|
export { default as SlidingPanel } from './slidingPanel';
|
|
110
113
|
export { default as SnackbarPortal } from './snackbar/Snackbar';
|
|
111
114
|
export { default as SnackbarProvider } from './snackbar/SnackbarProvider';
|
package/src/inputs/Input.css
CHANGED
|
@@ -47,10 +47,6 @@
|
|
|
47
47
|
padding-top: 0 !important;
|
|
48
48
|
padding-bottom: 0 !important;
|
|
49
49
|
}.np-form-control--size-sm {
|
|
50
|
-
line-height: 1.5;
|
|
51
|
-
line-height: var(--line-height-body);
|
|
52
|
-
font-size: 1rem;
|
|
53
|
-
font-size: var(--font-size-16);
|
|
54
50
|
font-size: 0.875rem;
|
|
55
51
|
font-size: var(--font-size-14);
|
|
56
52
|
line-height: 155%;
|
|
@@ -158,10 +158,12 @@
|
|
|
158
158
|
color: #5d7079;
|
|
159
159
|
color: var(--color-content-secondary);
|
|
160
160
|
}
|
|
161
|
-
.np-select-input-
|
|
161
|
+
.np-select-input-content {
|
|
162
162
|
overflow: hidden;
|
|
163
163
|
text-overflow: ellipsis;
|
|
164
164
|
white-space: nowrap;
|
|
165
|
+
}
|
|
166
|
+
.np-select-input-placeholder {
|
|
165
167
|
color: #768e9c;
|
|
166
168
|
color: var(--color-content-tertiary);
|
|
167
169
|
}
|
|
@@ -269,6 +271,9 @@
|
|
|
269
271
|
padding: var(--size-12) var(--size-16);
|
|
270
272
|
color: var(--color-interactive-primary);
|
|
271
273
|
}
|
|
274
|
+
.np-select-input-option-container:focus {
|
|
275
|
+
outline: none;
|
|
276
|
+
}
|
|
272
277
|
.np-select-input-option-container--active {
|
|
273
278
|
box-shadow: inset 0 0 0 1px #c9cbce;
|
|
274
279
|
box-shadow: inset 0 0 0 1px var(--color-interactive-secondary);
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
@import "./_Popover.less";
|
|
4
4
|
@import (reference) "../../node_modules/@transferwise/neptune-css/src/less/ring.less";
|
|
5
5
|
|
|
6
|
-
.np-select-input-
|
|
6
|
+
.np-select-input-content {
|
|
7
7
|
overflow: hidden;
|
|
8
8
|
text-overflow: ellipsis;
|
|
9
9
|
white-space: nowrap;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.np-select-input-placeholder {
|
|
10
13
|
color: var(--color-content-tertiary);
|
|
11
14
|
}
|
|
12
15
|
|
|
@@ -100,6 +103,10 @@
|
|
|
100
103
|
padding: var(--size-12) var(--size-16);
|
|
101
104
|
color: var(--color-interactive-primary);
|
|
102
105
|
|
|
106
|
+
&:focus {
|
|
107
|
+
outline: none;
|
|
108
|
+
}
|
|
109
|
+
|
|
103
110
|
&--active {
|
|
104
111
|
box-shadow: inset 0 0 0 1px var(--color-interactive-secondary);
|
|
105
112
|
}
|
|
@@ -182,4 +182,30 @@ describe('SelectInput', () => {
|
|
|
182
182
|
const listbox = screen.getByRole('listbox');
|
|
183
183
|
expect(within(listbox).getAllByRole('option')).toHaveLength(2);
|
|
184
184
|
});
|
|
185
|
+
|
|
186
|
+
it('selects multiple options', async () => {
|
|
187
|
+
render(
|
|
188
|
+
<SelectInput
|
|
189
|
+
multiple
|
|
190
|
+
items={[
|
|
191
|
+
{ type: 'option', value: 'USD' },
|
|
192
|
+
{ type: 'option', value: 'EUR' },
|
|
193
|
+
]}
|
|
194
|
+
/>,
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const trigger = screen.getAllByRole('button')[0];
|
|
198
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
199
|
+
await act(async () => {
|
|
200
|
+
userEvent.click(trigger);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const listbox = screen.getByRole('listbox');
|
|
204
|
+
const options = within(listbox).getAllByRole('option');
|
|
205
|
+
options.forEach((option) => {
|
|
206
|
+
userEvent.click(option);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
expect(trigger).toHaveTextContent('USD, EUR');
|
|
210
|
+
});
|
|
185
211
|
});
|
|
@@ -242,7 +242,7 @@ export const Currencies: StoryObj<{
|
|
|
242
242
|
onChange: (value: Currency) => void;
|
|
243
243
|
}> = {
|
|
244
244
|
render: function Story({ onChange }) {
|
|
245
|
-
const [selectedCurrency, setSelectedCurrency] = useState
|
|
245
|
+
const [selectedCurrency, setSelectedCurrency] = useState(popularCurrencies[0]);
|
|
246
246
|
|
|
247
247
|
return (
|
|
248
248
|
<SelectInput
|
|
@@ -301,6 +301,78 @@ export const Currencies: StoryObj<{
|
|
|
301
301
|
},
|
|
302
302
|
};
|
|
303
303
|
|
|
304
|
+
export const MultipleCurrencies: StoryObj<{
|
|
305
|
+
onChange: (value: Currency[]) => void;
|
|
306
|
+
}> = {
|
|
307
|
+
render: function Story({ onChange }) {
|
|
308
|
+
const [selectedCurrencies, setSelectedCurrencies] = useState<readonly Currency[]>([
|
|
309
|
+
popularCurrencies[0],
|
|
310
|
+
]);
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<SelectInput
|
|
314
|
+
multiple
|
|
315
|
+
placeholder="Choose currencies…"
|
|
316
|
+
items={[
|
|
317
|
+
{
|
|
318
|
+
type: 'group',
|
|
319
|
+
label: 'Popular currencies',
|
|
320
|
+
options: popularCurrencies.map((currency) => currencyOption(currency)),
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
type: 'group',
|
|
324
|
+
label: 'All currencies',
|
|
325
|
+
options: allCurrencies.map((currency) => currencyOption(currency)),
|
|
326
|
+
},
|
|
327
|
+
]}
|
|
328
|
+
value={selectedCurrencies}
|
|
329
|
+
renderValue={(currency, withinTrigger) =>
|
|
330
|
+
withinTrigger ? (
|
|
331
|
+
currency.code
|
|
332
|
+
) : (
|
|
333
|
+
<SelectInputOptionContent
|
|
334
|
+
title={currency.code}
|
|
335
|
+
note={currency.name}
|
|
336
|
+
icon={<Flag code={currency.code} intrinsicSize={24} />}
|
|
337
|
+
/>
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
// eslint-disable-next-line sonarjs/no-identical-functions
|
|
341
|
+
renderFooter={({ resultsEmpty, queryNormalized: normalizedQuery }) =>
|
|
342
|
+
resultsEmpty && normalizedQuery != null && /^[a-z]{3}$/u.test(normalizedQuery) ? (
|
|
343
|
+
<>
|
|
344
|
+
It’s not possible use {normalizedQuery.toUpperCase()} yet.{' '}
|
|
345
|
+
<a href="#_" className="np-text-link-default">
|
|
346
|
+
Email me when it’s available.
|
|
347
|
+
</a>
|
|
348
|
+
</>
|
|
349
|
+
) : (
|
|
350
|
+
<>
|
|
351
|
+
Can’t find it?{' '}
|
|
352
|
+
<a href="#_" className="np-text-link-default">
|
|
353
|
+
Request the currency you need,
|
|
354
|
+
</a>{' '}
|
|
355
|
+
and we’ll notify you once it’s available.
|
|
356
|
+
</>
|
|
357
|
+
)
|
|
358
|
+
}
|
|
359
|
+
filterable
|
|
360
|
+
filterPlaceholder="Type a currency / country"
|
|
361
|
+
size="lg"
|
|
362
|
+
onChange={(currency) => {
|
|
363
|
+
setSelectedCurrencies(currency);
|
|
364
|
+
onChange(currency);
|
|
365
|
+
}}
|
|
366
|
+
/>
|
|
367
|
+
);
|
|
368
|
+
},
|
|
369
|
+
argTypes: {
|
|
370
|
+
onChange: {
|
|
371
|
+
action: 'changed',
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
|
|
304
376
|
export const CustomTrigger: StoryObj = {
|
|
305
377
|
render: function Story() {
|
|
306
378
|
return (
|
|
@@ -12,7 +12,6 @@ import { useScreenSize } from '../common/hooks/useScreenSize';
|
|
|
12
12
|
import { PolymorphicWithOverrides } from '../common/polymorphicWithOverrides/PolymorphicWithOverrides';
|
|
13
13
|
import { Breakpoint } from '../common/propsValues/breakpoint';
|
|
14
14
|
import dateTriggerMessages from '../dateLookup/dateTrigger/DateTrigger.messages';
|
|
15
|
-
import { wrapInFragment } from '../utilities/wrapInFragment';
|
|
16
15
|
import { Merge } from '../utils';
|
|
17
16
|
|
|
18
17
|
import { InputGroup } from './InputGroup';
|
|
@@ -125,13 +124,13 @@ function filterSelectInputItems<T>(items: readonly SelectInputItem<T>[], needle:
|
|
|
125
124
|
});
|
|
126
125
|
}
|
|
127
126
|
|
|
128
|
-
export interface SelectInputProps<T = string> {
|
|
127
|
+
export interface SelectInputProps<T = string, M extends boolean = false> {
|
|
129
128
|
name?: string;
|
|
129
|
+
multiple?: M;
|
|
130
130
|
placeholder?: string;
|
|
131
|
-
// TODO: multiple?: boolean;
|
|
132
131
|
items: readonly SelectInputItem<NonNullable<T>>[];
|
|
133
|
-
defaultValue?: T;
|
|
134
|
-
value?: T;
|
|
132
|
+
defaultValue?: M extends true ? readonly T[] : T;
|
|
133
|
+
value?: M extends true ? readonly T[] : T;
|
|
135
134
|
compareValues?:
|
|
136
135
|
| (keyof NonNullable<T> & string)
|
|
137
136
|
| ((a: T | undefined, b: T | undefined) => boolean);
|
|
@@ -154,7 +153,7 @@ export interface SelectInputProps<T = string> {
|
|
|
154
153
|
size?: 'sm' | 'md' | 'lg';
|
|
155
154
|
className?: string;
|
|
156
155
|
onFilterChange?: (args: { query: string; queryNormalized: string | null }) => void;
|
|
157
|
-
onChange?: (value: T) => void;
|
|
156
|
+
onChange?: (value: M extends true ? T[] : T) => void;
|
|
158
157
|
onClear?: () => void;
|
|
159
158
|
}
|
|
160
159
|
|
|
@@ -186,7 +185,14 @@ const defaultRenderTrigger = (({ content, placeholderShown, clear, disabled, siz
|
|
|
186
185
|
className={className}
|
|
187
186
|
>
|
|
188
187
|
<SelectInputTriggerButton as={ButtonInput} size={size}>
|
|
189
|
-
|
|
188
|
+
<span
|
|
189
|
+
className={classNames(
|
|
190
|
+
'np-select-input-content',
|
|
191
|
+
placeholderShown && 'np-select-input-placeholder',
|
|
192
|
+
)}
|
|
193
|
+
>
|
|
194
|
+
{content}
|
|
195
|
+
</span>
|
|
190
196
|
</SelectInputTriggerButton>
|
|
191
197
|
</InputGroup>
|
|
192
198
|
)) satisfies SelectInputProps['renderTrigger'];
|
|
@@ -211,14 +217,15 @@ function SelectInputClearButton({ className, onClick }: SelectInputClearButtonPr
|
|
|
211
217
|
|
|
212
218
|
const noop = () => {};
|
|
213
219
|
|
|
214
|
-
export function SelectInput<T = string>({
|
|
220
|
+
export function SelectInput<T = string, M extends boolean = false>({
|
|
215
221
|
name,
|
|
222
|
+
multiple,
|
|
216
223
|
placeholder,
|
|
217
224
|
items,
|
|
218
225
|
defaultValue,
|
|
219
226
|
value: controlledValue,
|
|
220
227
|
compareValues,
|
|
221
|
-
renderValue =
|
|
228
|
+
renderValue = String,
|
|
222
229
|
renderFooter,
|
|
223
230
|
renderTrigger = defaultRenderTrigger,
|
|
224
231
|
filterable,
|
|
@@ -229,7 +236,7 @@ export function SelectInput<T = string>({
|
|
|
229
236
|
onFilterChange = noop,
|
|
230
237
|
onChange,
|
|
231
238
|
onClear,
|
|
232
|
-
}: SelectInputProps<T>) {
|
|
239
|
+
}: SelectInputProps<T, M>) {
|
|
233
240
|
const [open, setOpen] = useState(false);
|
|
234
241
|
|
|
235
242
|
const [filterQuery, _setFilterQuery] = useState('');
|
|
@@ -253,94 +260,106 @@ export function SelectInput<T = string>({
|
|
|
253
260
|
return (
|
|
254
261
|
<ListboxBase
|
|
255
262
|
name={name}
|
|
263
|
+
multiple={multiple}
|
|
256
264
|
defaultValue={defaultValue}
|
|
257
265
|
value={controlledValue}
|
|
258
266
|
// TODO: Remove assertion when upgrading TypeScript to v5
|
|
259
267
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
260
268
|
by={compareValues as any}
|
|
261
269
|
disabled={disabled}
|
|
262
|
-
onChange={
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
270
|
+
onChange={
|
|
271
|
+
((value) => {
|
|
272
|
+
if (!multiple) {
|
|
273
|
+
setOpen(false);
|
|
274
|
+
}
|
|
275
|
+
onChange?.(value);
|
|
276
|
+
}) satisfies SelectInputProps<T, M>['onChange']
|
|
277
|
+
}
|
|
266
278
|
>
|
|
267
|
-
{({ disabled: uiDisabled, value }) =>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
event.key === ' ' ||
|
|
284
|
-
event.key === 'Enter' ||
|
|
285
|
-
event.key === 'ArrowDown' ||
|
|
286
|
-
event.key === 'ArrowUp'
|
|
287
|
-
) {
|
|
279
|
+
{({ disabled: uiDisabled, value }) => {
|
|
280
|
+
const placeholderShown =
|
|
281
|
+
multiple && Array.isArray(value) ? value.length === 0 : value == null;
|
|
282
|
+
return (
|
|
283
|
+
<OptionsOverlay
|
|
284
|
+
placement="bottom-start"
|
|
285
|
+
open={open}
|
|
286
|
+
renderTrigger={({ ref, getInteractionProps }) => (
|
|
287
|
+
<SelectInputTriggerButtonPropsContext.Provider
|
|
288
|
+
// eslint-disable-next-line react/jsx-no-constructed-context-values
|
|
289
|
+
value={{
|
|
290
|
+
ref: mergeRefs([ref, triggerRef]),
|
|
291
|
+
...mergeProps(
|
|
292
|
+
{
|
|
293
|
+
onClick: () => {
|
|
288
294
|
setOpen((prev) => !prev);
|
|
289
|
-
}
|
|
295
|
+
},
|
|
296
|
+
onKeyDown: (event: React.KeyboardEvent) => {
|
|
297
|
+
if (
|
|
298
|
+
event.key === ' ' ||
|
|
299
|
+
event.key === 'Enter' ||
|
|
300
|
+
event.key === 'ArrowDown' ||
|
|
301
|
+
event.key === 'ArrowUp'
|
|
302
|
+
) {
|
|
303
|
+
setOpen((prev) => !prev);
|
|
304
|
+
}
|
|
305
|
+
},
|
|
290
306
|
},
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
content:
|
|
298
|
-
value != null ? (
|
|
307
|
+
getInteractionProps(),
|
|
308
|
+
),
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
{renderTrigger({
|
|
312
|
+
content: !placeholderShown ? (
|
|
299
313
|
<SelectInputOptionContentWithinTriggerContext.Provider value>
|
|
300
|
-
{
|
|
314
|
+
{multiple && Array.isArray(value)
|
|
315
|
+
? value
|
|
316
|
+
.map((option: NonNullable<T>) => renderValue(option, true))
|
|
317
|
+
.join(', ')
|
|
318
|
+
: renderValue(value as NonNullable<T>, true)}
|
|
301
319
|
</SelectInputOptionContentWithinTriggerContext.Provider>
|
|
302
320
|
) : (
|
|
303
321
|
placeholder
|
|
304
322
|
),
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
323
|
+
placeholderShown,
|
|
324
|
+
clear:
|
|
325
|
+
onClear != null
|
|
326
|
+
? () => {
|
|
327
|
+
onClear();
|
|
328
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
329
|
+
}
|
|
330
|
+
: undefined,
|
|
331
|
+
disabled: uiDisabled,
|
|
332
|
+
size,
|
|
333
|
+
className,
|
|
334
|
+
})}
|
|
335
|
+
</SelectInputTriggerButtonPropsContext.Provider>
|
|
336
|
+
)}
|
|
337
|
+
initialFocusRef={controllerRef}
|
|
338
|
+
size={filterable ? 'lg' : 'md'}
|
|
339
|
+
padding="none"
|
|
340
|
+
onClose={() => {
|
|
341
|
+
setOpen(false);
|
|
342
|
+
}}
|
|
343
|
+
onCloseEnd={() => {
|
|
344
|
+
if (filterQuery !== '') {
|
|
345
|
+
setFilterQuery('');
|
|
346
|
+
}
|
|
347
|
+
}}
|
|
348
|
+
>
|
|
349
|
+
<SelectInputOptions
|
|
350
|
+
items={items}
|
|
351
|
+
renderValue={renderValue}
|
|
352
|
+
renderFooter={renderFooter}
|
|
353
|
+
filterable={filterable}
|
|
354
|
+
filterPlaceholder={filterPlaceholder}
|
|
355
|
+
searchInputRef={searchInputRef}
|
|
356
|
+
listboxRef={listboxRef}
|
|
357
|
+
filterQuery={filterQuery}
|
|
358
|
+
onFilterChange={setFilterQuery}
|
|
359
|
+
/>
|
|
360
|
+
</OptionsOverlay>
|
|
361
|
+
);
|
|
362
|
+
}}
|
|
344
363
|
</ListboxBase>
|
|
345
364
|
);
|
|
346
365
|
}
|
|
@@ -430,7 +449,7 @@ interface SelectInputOptionsProps<T = string>
|
|
|
430
449
|
|
|
431
450
|
function SelectInputOptions<T = string>({
|
|
432
451
|
items,
|
|
433
|
-
renderValue =
|
|
452
|
+
renderValue = String,
|
|
434
453
|
renderFooter,
|
|
435
454
|
filterable = false,
|
|
436
455
|
filterPlaceholder,
|
package/src/inputs/TextArea.css
CHANGED
|
@@ -47,10 +47,6 @@
|
|
|
47
47
|
padding-top: 0 !important;
|
|
48
48
|
padding-bottom: 0 !important;
|
|
49
49
|
}.np-form-control--size-sm {
|
|
50
|
-
line-height: 1.5;
|
|
51
|
-
line-height: var(--line-height-body);
|
|
52
|
-
font-size: 1rem;
|
|
53
|
-
font-size: var(--font-size-16);
|
|
54
50
|
font-size: 0.875rem;
|
|
55
51
|
font-size: var(--font-size-14);
|
|
56
52
|
line-height: 155%;
|
package/src/main.css
CHANGED
|
@@ -74,14 +74,6 @@ div.critical-comms .critical-comms-body {
|
|
|
74
74
|
flex-wrap: wrap;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
.tw-date-lookup-calendar > tbody > tr > td.weekend button {
|
|
78
|
-
font-weight: 400;
|
|
79
|
-
font-weight: var(--font-weight-regular);line-height: 1.5;line-height: var(--line-height-body);
|
|
80
|
-
}
|
|
81
|
-
.tw-date-lookup-calendar > tbody > tr > td.weekend button {
|
|
82
|
-
font-size: 1rem;
|
|
83
|
-
font-size: var(--font-size-16);
|
|
84
|
-
}
|
|
85
77
|
.tw-date-lookup-calendar > tbody > tr > td.weekend button {
|
|
86
78
|
font-size: 0.875rem;
|
|
87
79
|
font-size: var(--font-size-14);line-height: 155%;letter-spacing: -0.006em;font-weight: 400;font-weight: var(--font-weight-regular);
|
|
@@ -2226,10 +2218,6 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
2226
2218
|
padding-bottom: 0 !important;
|
|
2227
2219
|
}
|
|
2228
2220
|
.np-form-control--size-sm {
|
|
2229
|
-
line-height: 1.5;
|
|
2230
|
-
line-height: var(--line-height-body);
|
|
2231
|
-
font-size: 1rem;
|
|
2232
|
-
font-size: var(--font-size-16);
|
|
2233
2221
|
font-size: 0.875rem;
|
|
2234
2222
|
font-size: var(--font-size-14);
|
|
2235
2223
|
line-height: 155%;
|
|
@@ -2511,10 +2499,12 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
2511
2499
|
color: #5d7079;
|
|
2512
2500
|
color: var(--color-content-secondary);
|
|
2513
2501
|
}
|
|
2514
|
-
.np-select-input-
|
|
2502
|
+
.np-select-input-content {
|
|
2515
2503
|
overflow: hidden;
|
|
2516
2504
|
text-overflow: ellipsis;
|
|
2517
2505
|
white-space: nowrap;
|
|
2506
|
+
}
|
|
2507
|
+
.np-select-input-placeholder {
|
|
2518
2508
|
color: #768e9c;
|
|
2519
2509
|
color: var(--color-content-tertiary);
|
|
2520
2510
|
}
|
|
@@ -2622,6 +2612,9 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
2622
2612
|
padding: var(--size-12) var(--size-16);
|
|
2623
2613
|
color: var(--color-interactive-primary);
|
|
2624
2614
|
}
|
|
2615
|
+
.np-select-input-option-container:focus {
|
|
2616
|
+
outline: none;
|
|
2617
|
+
}
|
|
2625
2618
|
.np-select-input-option-container--active {
|
|
2626
2619
|
box-shadow: inset 0 0 0 1px #c9cbce;
|
|
2627
2620
|
box-shadow: inset 0 0 0 1px var(--color-interactive-secondary);
|
|
@@ -4455,10 +4448,6 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
4455
4448
|
border-radius: var(--radius-small);
|
|
4456
4449
|
color: #37517e;
|
|
4457
4450
|
color: var(--color-content-primary);
|
|
4458
|
-
line-height: 1.5;
|
|
4459
|
-
line-height: var(--line-height-body);
|
|
4460
|
-
font-size: 1rem;
|
|
4461
|
-
font-size: var(--font-size-16);
|
|
4462
4451
|
font-size: 0.875rem;
|
|
4463
4452
|
font-size: var(--font-size-14);
|
|
4464
4453
|
line-height: 155%;
|
|
@@ -4640,6 +4629,107 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
4640
4629
|
.np-theme-personal .np-dropdown-menu .np-dropdown-item--focused {
|
|
4641
4630
|
box-shadow: inset 0 0 0 2px var(--color-interactive-primary);
|
|
4642
4631
|
}
|
|
4632
|
+
.segmented-control {
|
|
4633
|
+
box-sizing: border-box;
|
|
4634
|
+
--segment-highlight-width: 0;
|
|
4635
|
+
--segment-highlight-x: var(--size-4);
|
|
4636
|
+
}
|
|
4637
|
+
.segmented-control__segments {
|
|
4638
|
+
display: inline-flex;
|
|
4639
|
+
position: relative;
|
|
4640
|
+
padding: 4px;
|
|
4641
|
+
padding: var(--size-4);
|
|
4642
|
+
width: 100%;
|
|
4643
|
+
justify-content: center;
|
|
4644
|
+
align-items: center;
|
|
4645
|
+
background: rgba(134,167,189,0.10196);
|
|
4646
|
+
background: var(--color-background-neutral);
|
|
4647
|
+
border-radius: 24px;
|
|
4648
|
+
border-radius: var(--size-24);
|
|
4649
|
+
transition: outline 300ms;
|
|
4650
|
+
outline: 2px solid transparent;
|
|
4651
|
+
}
|
|
4652
|
+
.segmented-control--input:has(:focus-visible) > .segmented-control__segments::after {
|
|
4653
|
+
outline: 2px solid var(--color-interactive-primary);
|
|
4654
|
+
}
|
|
4655
|
+
.segmented-control__segments::after {
|
|
4656
|
+
content: "";
|
|
4657
|
+
position: absolute;
|
|
4658
|
+
width: var(--segment-highlight-width);
|
|
4659
|
+
top: 4px;
|
|
4660
|
+
top: var(--size-4);
|
|
4661
|
+
bottom: 4px;
|
|
4662
|
+
bottom: var(--size-4);
|
|
4663
|
+
left: var(--segment-highlight-x);
|
|
4664
|
+
z-index: 0;
|
|
4665
|
+
background: #ffffff;
|
|
4666
|
+
background: var(--color-background-screen);
|
|
4667
|
+
border-radius: 24px;
|
|
4668
|
+
border-radius: var(--size-24);
|
|
4669
|
+
transition: left 300ms;
|
|
4670
|
+
}
|
|
4671
|
+
.segmented-control__segments--no-animate::after {
|
|
4672
|
+
transition: none !important;
|
|
4673
|
+
}
|
|
4674
|
+
.segmented-control__segment {
|
|
4675
|
+
position: relative;
|
|
4676
|
+
flex: 1 1 100%;
|
|
4677
|
+
flex-flow: column;
|
|
4678
|
+
padding: 8px 16px;
|
|
4679
|
+
padding: var(--size-8) var(--size-16);
|
|
4680
|
+
margin: 0 0 0 4px;
|
|
4681
|
+
margin: 0 0 0 var(--size-4);
|
|
4682
|
+
min-width: 0;
|
|
4683
|
+
line-height: inherit;
|
|
4684
|
+
align-items: center;
|
|
4685
|
+
text-align: center;
|
|
4686
|
+
vertical-align: middle;
|
|
4687
|
+
border-radius: 24px;
|
|
4688
|
+
border-radius: var(--size-24);
|
|
4689
|
+
z-index: 1;
|
|
4690
|
+
cursor: pointer;
|
|
4691
|
+
transition: background 300ms;
|
|
4692
|
+
color: var(--color-interactive-primary);
|
|
4693
|
+
}
|
|
4694
|
+
.segmented-control__segment:first-child {
|
|
4695
|
+
margin-left: 0;
|
|
4696
|
+
}
|
|
4697
|
+
.segmented-control__segment:hover {
|
|
4698
|
+
background: rgba(0,0,0,0.10196);
|
|
4699
|
+
background: var(--color-background-overlay);
|
|
4700
|
+
}
|
|
4701
|
+
.segmented-control__radio-input {
|
|
4702
|
+
position: fixed;
|
|
4703
|
+
opacity: 0;
|
|
4704
|
+
pointer-events: none;
|
|
4705
|
+
}
|
|
4706
|
+
.segmented-control__button {
|
|
4707
|
+
width: 100%;
|
|
4708
|
+
height: 100%;
|
|
4709
|
+
background: none;
|
|
4710
|
+
-webkit-appearance: none;
|
|
4711
|
+
-moz-appearance: none;
|
|
4712
|
+
appearance: none;
|
|
4713
|
+
border: none;
|
|
4714
|
+
outline: none;
|
|
4715
|
+
font: inherit;
|
|
4716
|
+
outline: 2px solid transparent;
|
|
4717
|
+
}
|
|
4718
|
+
.segmented-control__button:focus {
|
|
4719
|
+
outline-offset: 0px;
|
|
4720
|
+
}
|
|
4721
|
+
.segmented-control__button:focus-visible {
|
|
4722
|
+
outline-color: var(--color-interactive-primary);
|
|
4723
|
+
}
|
|
4724
|
+
.segmented-control__selected-segment:hover {
|
|
4725
|
+
background: transparent;
|
|
4726
|
+
}
|
|
4727
|
+
.segmented-control__text {
|
|
4728
|
+
word-wrap: break-word;
|
|
4729
|
+
word-break: break-word;
|
|
4730
|
+
color: var(--color-interactive-primary);
|
|
4731
|
+
transition: font-weight 300ms;
|
|
4732
|
+
}
|
|
4643
4733
|
.np-summary {
|
|
4644
4734
|
min-width: 280px;
|
|
4645
4735
|
}
|
package/src/main.less
CHANGED
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
@import "./statusIcon/StatusIcon.less";
|
|
54
54
|
@import "./stepper/Stepper.less";
|
|
55
55
|
@import "./select/Select.less";
|
|
56
|
+
@import "./segmentedControl/SegmentedControl.less";
|
|
56
57
|
@import "./summary/Summary.less";
|
|
57
58
|
@import "./switch/Switch.less";
|
|
58
59
|
@import "./tabs/Tabs.less";
|