@transferwise/components 45.17.1 → 45.19.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 +425 -368
- package/build/index.esm.js.map +1 -1
- package/build/index.js +425 -366
- package/build/index.js.map +1 -1
- package/build/main.css +1 -1
- package/build/styles/inputs/Input.css +1 -1
- package/build/styles/inputs/SelectInput.css +1 -1
- package/build/styles/inputs/TextArea.css +1 -1
- package/build/styles/instructionsList/InstructionsList.css +1 -1
- package/build/styles/main.css +1 -1
- package/build/styles/stepper/Stepper.css +1 -1
- package/build/styles/tooltip/Tooltip.css +1 -1
- package/build/types/button/Button.d.ts.map +1 -1
- package/build/types/common/polymorphicWithOverrides/PolymorphicWithOverrides.d.ts +13 -0
- package/build/types/common/polymorphicWithOverrides/PolymorphicWithOverrides.d.ts.map +1 -0
- package/build/types/index.d.ts +2 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/inputs/SelectInput.d.ts +18 -6
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
- package/build/types/inputs/_Popover.d.ts.map +1 -1
- package/build/types/instructionsList/InstructionsList.d.ts +10 -3
- package/build/types/instructionsList/InstructionsList.d.ts.map +1 -1
- package/build/types/processIndicator/ProcessIndicator.d.ts +1 -1
- package/build/types/tooltip/Tooltip.d.ts +2 -1
- package/build/types/tooltip/Tooltip.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/button/Button.story.tsx +6 -0
- package/src/button/Button.tsx +6 -1
- package/src/common/polymorphicWithOverrides/PolymorphicWithOverrides.tsx +19 -0
- package/src/index.ts +9 -1
- package/src/inputs/Input.css +1 -1
- package/src/inputs/SelectInput.css +1 -1
- package/src/inputs/SelectInput.less +20 -5
- package/src/inputs/SelectInput.story.tsx +85 -35
- package/src/inputs/SelectInput.tsx +176 -106
- package/src/inputs/TextArea.css +1 -1
- package/src/inputs/_BottomSheet.tsx +47 -37
- package/src/inputs/_Popover.less +1 -1
- package/src/inputs/_Popover.tsx +30 -27
- package/src/inputs/_common.less +6 -0
- package/src/inputs/_common.ts +4 -4
- package/src/instructionsList/InstructionList.story.tsx +39 -0
- package/src/instructionsList/InstructionsList.css +1 -1
- package/src/instructionsList/InstructionsList.less +3 -15
- package/src/instructionsList/InstructionsList.spec.tsx +35 -0
- package/src/instructionsList/InstructionsList.tsx +40 -25
- package/src/main.css +1 -1
- package/src/processIndicator/ProcessIndicator.js +2 -2
- package/src/ssr.spec.js +1 -0
- package/src/stepper/Stepper.css +1 -1
- package/src/stepper/Stepper.less +1 -1
- package/src/tooltip/Tooltip.css +1 -1
- package/src/tooltip/Tooltip.less +13 -0
- package/src/tooltip/Tooltip.spec.tsx +97 -29
- package/src/tooltip/Tooltip.tsx +24 -31
- package/src/tooltip/__snapshots__/Tooltip.spec.tsx.snap +31 -0
- package/src/instructionsList/InstructionList.story.js +0 -27
- package/src/instructionsList/InstructionsList.spec.js +0 -29
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Calendar } from '@transferwise/icons';
|
|
2
|
+
import { Calendar, ChevronDown } from '@transferwise/icons';
|
|
3
3
|
import { Flag } from '@wise/art';
|
|
4
|
+
import classNames from 'classnames';
|
|
4
5
|
import { useState } from 'react';
|
|
5
6
|
|
|
6
7
|
import { getMonthNames } from '../common/dateUtils';
|
|
7
8
|
import Drawer from '../drawer';
|
|
8
9
|
import Modal from '../modal';
|
|
10
|
+
import { within, userEvent } from '../test-utils';
|
|
9
11
|
|
|
10
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
SelectInput,
|
|
14
|
+
type SelectInputItem,
|
|
15
|
+
SelectInputOptionContent,
|
|
16
|
+
SelectInputTriggerButton,
|
|
17
|
+
} from './SelectInput';
|
|
11
18
|
|
|
12
19
|
export default {
|
|
13
20
|
component: SelectInput,
|
|
@@ -38,6 +45,7 @@ export const Basic: StoryObj<{
|
|
|
38
45
|
clearable: boolean;
|
|
39
46
|
invalid: boolean;
|
|
40
47
|
disabled: boolean;
|
|
48
|
+
size: 'md' | 'lg';
|
|
41
49
|
onChange: (value: TestMonth | null) => void;
|
|
42
50
|
onClear: () => void;
|
|
43
51
|
}> = {
|
|
@@ -46,6 +54,7 @@ export const Basic: StoryObj<{
|
|
|
46
54
|
filterPlaceholder,
|
|
47
55
|
clearable,
|
|
48
56
|
disabled,
|
|
57
|
+
size,
|
|
49
58
|
onChange,
|
|
50
59
|
onClear,
|
|
51
60
|
}) {
|
|
@@ -78,16 +87,17 @@ export const Basic: StoryObj<{
|
|
|
78
87
|
])
|
|
79
88
|
.slice(0, -1)}
|
|
80
89
|
value={selectedMonth}
|
|
81
|
-
renderValue={(month,
|
|
90
|
+
renderValue={(month, withinTrigger) => (
|
|
82
91
|
<SelectInputOptionContent
|
|
83
92
|
title={month.name}
|
|
84
93
|
note="Note"
|
|
85
|
-
description={
|
|
94
|
+
description={withinTrigger ? undefined : `Month #${month.id}`}
|
|
86
95
|
icon={<Calendar size={24} />}
|
|
87
96
|
/>
|
|
88
97
|
)}
|
|
89
98
|
filterable={filterable}
|
|
90
99
|
filterPlaceholder={filterPlaceholder}
|
|
100
|
+
size={size}
|
|
91
101
|
disabled={disabled}
|
|
92
102
|
onChange={(month) => {
|
|
93
103
|
setSelectedMonth(month);
|
|
@@ -111,6 +121,7 @@ export const Basic: StoryObj<{
|
|
|
111
121
|
clearable: true,
|
|
112
122
|
invalid: false,
|
|
113
123
|
disabled: false,
|
|
124
|
+
size: 'md',
|
|
114
125
|
},
|
|
115
126
|
argTypes: {
|
|
116
127
|
onChange: {
|
|
@@ -137,7 +148,7 @@ export const Months: StoryObj<{
|
|
|
137
148
|
onClear: () => void;
|
|
138
149
|
}> = {
|
|
139
150
|
render: function Story({ onChange, onClear }) {
|
|
140
|
-
const [selectedMonth, setSelectedMonth] = useState<Month | null>(
|
|
151
|
+
const [selectedMonth, setSelectedMonth] = useState<Month | null>(months[0]);
|
|
141
152
|
|
|
142
153
|
return (
|
|
143
154
|
<div className="d-flex flex-column">
|
|
@@ -171,6 +182,11 @@ export const Months: StoryObj<{
|
|
|
171
182
|
},
|
|
172
183
|
};
|
|
173
184
|
|
|
185
|
+
Months.play = ({ canvasElement }) => {
|
|
186
|
+
const canvas = within(canvasElement);
|
|
187
|
+
userEvent.click(canvas.getByText('January'));
|
|
188
|
+
};
|
|
189
|
+
|
|
174
190
|
interface Currency {
|
|
175
191
|
code: string;
|
|
176
192
|
name: string;
|
|
@@ -226,36 +242,35 @@ export const Currencies: StoryObj<{
|
|
|
226
242
|
const [selectedCurrency, setSelectedCurrency] = useState<Currency>(popularCurrencies[0]);
|
|
227
243
|
|
|
228
244
|
return (
|
|
229
|
-
<
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
</div>
|
|
245
|
+
<SelectInput
|
|
246
|
+
items={[
|
|
247
|
+
{
|
|
248
|
+
type: 'group',
|
|
249
|
+
label: 'Popular currencies',
|
|
250
|
+
options: popularCurrencies.map((currency) => currencyOption(currency)),
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
type: 'group',
|
|
254
|
+
label: 'All currencies',
|
|
255
|
+
options: allCurrencies.map((currency) => currencyOption(currency)),
|
|
256
|
+
},
|
|
257
|
+
]}
|
|
258
|
+
value={selectedCurrency}
|
|
259
|
+
renderValue={(currency, withinTrigger) => (
|
|
260
|
+
<SelectInputOptionContent
|
|
261
|
+
title={currency.code}
|
|
262
|
+
note={withinTrigger ? undefined : currency.name}
|
|
263
|
+
icon={<Flag code={currency.code} intrinsicSize={24} />}
|
|
264
|
+
/>
|
|
265
|
+
)}
|
|
266
|
+
filterable
|
|
267
|
+
filterPlaceholder="Type a currency / country"
|
|
268
|
+
size="lg"
|
|
269
|
+
onChange={(currency) => {
|
|
270
|
+
setSelectedCurrency(currency);
|
|
271
|
+
onChange(currency);
|
|
272
|
+
}}
|
|
273
|
+
/>
|
|
259
274
|
);
|
|
260
275
|
},
|
|
261
276
|
argTypes: {
|
|
@@ -265,6 +280,41 @@ export const Currencies: StoryObj<{
|
|
|
265
280
|
},
|
|
266
281
|
};
|
|
267
282
|
|
|
283
|
+
export const CustomTrigger: StoryObj = {
|
|
284
|
+
render: function Story() {
|
|
285
|
+
return (
|
|
286
|
+
<div>
|
|
287
|
+
<SelectInput
|
|
288
|
+
placeholder="Month"
|
|
289
|
+
items={months.map((month) => ({
|
|
290
|
+
type: 'option',
|
|
291
|
+
value: month,
|
|
292
|
+
}))}
|
|
293
|
+
renderValue={(month, withinTrigger) =>
|
|
294
|
+
withinTrigger ? month.name : <SelectInputOptionContent title={month.name} />
|
|
295
|
+
}
|
|
296
|
+
renderTrigger={({ content, className }) => (
|
|
297
|
+
<SelectInputTriggerButton
|
|
298
|
+
className={classNames(
|
|
299
|
+
className,
|
|
300
|
+
'btn-unstyled np-text-link-large align-items-center',
|
|
301
|
+
)}
|
|
302
|
+
style={{ display: 'inline-flex', columnGap: '0.25rem' }}
|
|
303
|
+
>
|
|
304
|
+
{content}
|
|
305
|
+
<ChevronDown size={16} />
|
|
306
|
+
</SelectInputTriggerButton>
|
|
307
|
+
)}
|
|
308
|
+
/>
|
|
309
|
+
</div>
|
|
310
|
+
);
|
|
311
|
+
},
|
|
312
|
+
play: ({ canvasElement }) => {
|
|
313
|
+
const triggerButton = within(canvasElement).getByRole('button');
|
|
314
|
+
userEvent.click(triggerButton);
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
|
|
268
318
|
export const WithinDrawer: StoryObj<{
|
|
269
319
|
onChange: (value: Currency) => void;
|
|
270
320
|
}> = {
|
|
@@ -2,12 +2,14 @@ import { Listbox as ListboxBase } from '@headlessui/react';
|
|
|
2
2
|
import { useId } from '@radix-ui/react-id';
|
|
3
3
|
import { Check, ChevronDown, Cross } from '@transferwise/icons';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
|
-
import
|
|
5
|
+
import mergeProps from 'merge-props';
|
|
6
|
+
import { createContext, forwardRef, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
7
|
import { useIntl } from 'react-intl';
|
|
7
8
|
import mergeRefs from 'react-merge-refs';
|
|
8
9
|
|
|
9
10
|
import { useEffectEvent } from '../common/hooks/useEffectEvent';
|
|
10
11
|
import { useScreenSize } from '../common/hooks/useScreenSize';
|
|
12
|
+
import { PolymorphicWithOverrides } from '../common/polymorphicWithOverrides/PolymorphicWithOverrides';
|
|
11
13
|
import { Breakpoint } from '../common/propsValues/breakpoint';
|
|
12
14
|
import messages from '../dateLookup/dateTrigger/DateTrigger.messages';
|
|
13
15
|
import { wrapInFragment } from '../utilities/wrapInFragment';
|
|
@@ -15,7 +17,7 @@ import { wrapInFragment } from '../utilities/wrapInFragment';
|
|
|
15
17
|
import { InputGroup } from './InputGroup';
|
|
16
18
|
import { SearchInput } from './SearchInput';
|
|
17
19
|
import { BottomSheet } from './_BottomSheet';
|
|
18
|
-
import { ButtonInput
|
|
20
|
+
import { ButtonInput } from './_ButtonInput';
|
|
19
21
|
import { Popover } from './_Popover';
|
|
20
22
|
|
|
21
23
|
function searchableString(value: string) {
|
|
@@ -37,23 +39,27 @@ function inferSearchableStrings(value: unknown) {
|
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
const SelectInputHasValueContext = createContext(false);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const SelectInputTriggerButtonPropsContext = createContext<{
|
|
43
|
+
ref?: React.ForwardedRef<HTMLButtonElement>;
|
|
44
|
+
onClick?: () => void;
|
|
45
|
+
[key: string]: unknown;
|
|
46
|
+
}>({});
|
|
47
|
+
const SelectInputOptionContentWithinTriggerContext = createContext(false);
|
|
48
|
+
|
|
49
|
+
export interface SelectInputOptionItem<T = string> {
|
|
44
50
|
type: 'option';
|
|
45
51
|
value: T;
|
|
46
52
|
filterMatchers?: readonly string[];
|
|
47
53
|
disabled?: boolean;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
interface SelectInputGroupItem<T = string> {
|
|
56
|
+
export interface SelectInputGroupItem<T = string> {
|
|
51
57
|
type: 'group';
|
|
52
58
|
label: string;
|
|
53
59
|
options: readonly SelectInputOptionItem<T>[];
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
interface SelectInputSeparatorItem {
|
|
62
|
+
export interface SelectInputSeparatorItem {
|
|
57
63
|
type: 'separator';
|
|
58
64
|
}
|
|
59
65
|
|
|
@@ -106,35 +112,95 @@ export interface SelectInputProps<T = string> {
|
|
|
106
112
|
items: readonly SelectInputItem<NonNullable<T>>[];
|
|
107
113
|
defaultValue?: T;
|
|
108
114
|
value?: T;
|
|
109
|
-
renderValue?: (value: NonNullable<T>, compact: boolean) => React.ReactNode;
|
|
110
115
|
compareValues?:
|
|
111
116
|
| (keyof NonNullable<T> & string)
|
|
112
117
|
| ((a: T | undefined, b: T | undefined) => boolean);
|
|
118
|
+
renderValue?: (value: NonNullable<T>, withinTrigger: boolean) => React.ReactNode;
|
|
119
|
+
renderTrigger?: (args: {
|
|
120
|
+
content: React.ReactNode;
|
|
121
|
+
placeholderShown: boolean;
|
|
122
|
+
clear: (() => void) | undefined;
|
|
123
|
+
disabled: boolean;
|
|
124
|
+
size: 'md' | 'lg';
|
|
125
|
+
className: string | undefined;
|
|
126
|
+
}) => React.ReactNode;
|
|
113
127
|
filterable?: boolean;
|
|
114
128
|
filterPlaceholder?: string;
|
|
115
129
|
disabled?: boolean;
|
|
130
|
+
size?: 'md' | 'lg';
|
|
116
131
|
className?: string;
|
|
117
132
|
onChange?: (value: T) => void;
|
|
118
133
|
onClear?: () => void;
|
|
119
134
|
}
|
|
120
135
|
|
|
121
|
-
|
|
136
|
+
const defaultRenderTrigger = (({ content, placeholderShown, clear, disabled, size, className }) => (
|
|
137
|
+
<InputGroup
|
|
138
|
+
addonEnd={{
|
|
139
|
+
content: (
|
|
140
|
+
<span className={classNames('np-select-input-addon-container', disabled && 'disabled')}>
|
|
141
|
+
{clear != null && !placeholderShown ? (
|
|
142
|
+
<>
|
|
143
|
+
<SelectInputClearButton
|
|
144
|
+
onClick={(event) => {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
clear();
|
|
147
|
+
}}
|
|
148
|
+
/>
|
|
149
|
+
<span className="np-select-input-addon-separator" />
|
|
150
|
+
</>
|
|
151
|
+
) : null}
|
|
152
|
+
|
|
153
|
+
<span className="np-select-input-addon">
|
|
154
|
+
<ChevronDown size={16} />
|
|
155
|
+
</span>
|
|
156
|
+
</span>
|
|
157
|
+
),
|
|
158
|
+
padding: 'sm',
|
|
159
|
+
}}
|
|
160
|
+
disabled={disabled}
|
|
161
|
+
className={className}
|
|
162
|
+
>
|
|
163
|
+
<SelectInputTriggerButton as={ButtonInput} size={size}>
|
|
164
|
+
{placeholderShown ? <span className="np-select-input-placeholder"> {content}</span> : content}
|
|
165
|
+
</SelectInputTriggerButton>
|
|
166
|
+
</InputGroup>
|
|
167
|
+
)) satisfies SelectInputProps['renderTrigger'];
|
|
168
|
+
|
|
169
|
+
interface SelectInputClearButtonProps
|
|
170
|
+
extends Pick<React.ComponentPropsWithoutRef<'button'>, 'className' | 'onClick'> {}
|
|
171
|
+
|
|
172
|
+
function SelectInputClearButton({ className, onClick }: SelectInputClearButtonProps) {
|
|
173
|
+
const intl = useIntl();
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<button
|
|
177
|
+
type="button"
|
|
178
|
+
aria-label={intl.formatMessage(messages.ariaLabel)}
|
|
179
|
+
className={classNames(className, 'np-select-input-addon np-select-input-addon--interactive')}
|
|
180
|
+
onClick={onClick}
|
|
181
|
+
>
|
|
182
|
+
<Cross size={16} />
|
|
183
|
+
</button>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function SelectInput<T = string>({
|
|
122
188
|
name,
|
|
123
189
|
placeholder,
|
|
124
190
|
items,
|
|
125
191
|
defaultValue,
|
|
126
192
|
value: controlledValue,
|
|
127
|
-
renderValue = wrapInFragment,
|
|
128
193
|
compareValues,
|
|
194
|
+
renderValue = wrapInFragment,
|
|
195
|
+
renderTrigger = defaultRenderTrigger,
|
|
129
196
|
filterable,
|
|
130
197
|
filterPlaceholder,
|
|
131
198
|
disabled,
|
|
199
|
+
size = 'md',
|
|
132
200
|
className,
|
|
133
201
|
onChange,
|
|
134
202
|
onClear,
|
|
135
203
|
}: SelectInputProps<T>) {
|
|
136
|
-
const intl = useIntl();
|
|
137
|
-
|
|
138
204
|
const [open, setOpen] = useState(false);
|
|
139
205
|
|
|
140
206
|
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
@@ -162,95 +228,86 @@ export function SelectInput<T>({
|
|
|
162
228
|
>
|
|
163
229
|
{({ disabled: uiDisabled, value }) => (
|
|
164
230
|
<SelectInputHasValueContext.Provider value={value != null}>
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
231
|
+
<OptionsOverlay
|
|
232
|
+
open={open}
|
|
233
|
+
renderTrigger={({ ref, getInteractionProps }) => (
|
|
234
|
+
<SelectInputTriggerButtonPropsContext.Provider
|
|
235
|
+
// eslint-disable-next-line react/jsx-no-constructed-context-values
|
|
236
|
+
value={{
|
|
237
|
+
ref: mergeRefs([ref, triggerRef]),
|
|
238
|
+
...mergeProps(
|
|
239
|
+
{
|
|
240
|
+
onClick: () => {
|
|
241
|
+
setOpen((prev) => !prev);
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
getInteractionProps(),
|
|
245
|
+
),
|
|
246
|
+
}}
|
|
247
|
+
>
|
|
248
|
+
{renderTrigger({
|
|
249
|
+
content:
|
|
250
|
+
value != null ? (
|
|
251
|
+
<SelectInputOptionContentWithinTriggerContext.Provider value>
|
|
252
|
+
{renderValue(value, true)}
|
|
253
|
+
</SelectInputOptionContentWithinTriggerContext.Provider>
|
|
254
|
+
) : (
|
|
255
|
+
placeholder
|
|
256
|
+
),
|
|
257
|
+
placeholderShown: value == null,
|
|
258
|
+
clear:
|
|
259
|
+
onClear != null
|
|
260
|
+
? () => {
|
|
183
261
|
onClear();
|
|
184
262
|
triggerRef.current?.focus({ preventScroll: true });
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
),
|
|
198
|
-
padding: 'sm',
|
|
263
|
+
}
|
|
264
|
+
: undefined,
|
|
265
|
+
disabled: uiDisabled,
|
|
266
|
+
size,
|
|
267
|
+
className,
|
|
268
|
+
})}
|
|
269
|
+
</SelectInputTriggerButtonPropsContext.Provider>
|
|
270
|
+
)}
|
|
271
|
+
initialFocusRef={controllerRef}
|
|
272
|
+
padding="none"
|
|
273
|
+
onClose={() => {
|
|
274
|
+
setOpen(false);
|
|
199
275
|
}}
|
|
200
|
-
className={className}
|
|
201
276
|
>
|
|
202
|
-
<
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}}
|
|
212
|
-
>
|
|
213
|
-
{value != null ? (
|
|
214
|
-
<SelectInputOptionContentCompactContext.Provider value>
|
|
215
|
-
{renderValue(value, true)}
|
|
216
|
-
</SelectInputOptionContentCompactContext.Provider>
|
|
217
|
-
) : (
|
|
218
|
-
<span className="np-select-input-placeholder">{placeholder}</span>
|
|
219
|
-
)}
|
|
220
|
-
</ListboxBase.Button>
|
|
221
|
-
)}
|
|
222
|
-
initialFocusRef={controllerRef}
|
|
223
|
-
padding="none"
|
|
224
|
-
onClose={() => {
|
|
225
|
-
setOpen(false);
|
|
226
|
-
}}
|
|
227
|
-
>
|
|
228
|
-
<SelectInputOptions
|
|
229
|
-
items={items}
|
|
230
|
-
renderValue={renderValue}
|
|
231
|
-
filterable={filterable}
|
|
232
|
-
filterPlaceholder={filterPlaceholder}
|
|
233
|
-
searchInputRef={searchInputRef}
|
|
234
|
-
listboxRef={listboxRef}
|
|
235
|
-
/>
|
|
236
|
-
</OptionsOverlay>
|
|
237
|
-
</InputGroup>
|
|
277
|
+
<SelectInputOptions
|
|
278
|
+
items={items}
|
|
279
|
+
renderValue={renderValue}
|
|
280
|
+
filterable={filterable}
|
|
281
|
+
filterPlaceholder={filterPlaceholder}
|
|
282
|
+
searchInputRef={searchInputRef}
|
|
283
|
+
listboxRef={listboxRef}
|
|
284
|
+
/>
|
|
285
|
+
</OptionsOverlay>
|
|
238
286
|
</SelectInputHasValueContext.Provider>
|
|
239
287
|
)}
|
|
240
288
|
</ListboxBase>
|
|
241
289
|
);
|
|
242
290
|
}
|
|
243
291
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
292
|
+
export type SelectInputTriggerButtonProps<T extends React.ComponentType | 'button' = 'button'> = {
|
|
293
|
+
as?: T;
|
|
294
|
+
} & React.ComponentPropsWithoutRef<T>;
|
|
247
295
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
) {
|
|
252
|
-
|
|
253
|
-
|
|
296
|
+
export function SelectInputTriggerButton<T extends React.ComponentType | 'button' = 'button'>({
|
|
297
|
+
as = 'button' as T,
|
|
298
|
+
...restProps
|
|
299
|
+
}: SelectInputTriggerButtonProps<T>) {
|
|
300
|
+
const { ref, onClick, ...interactionProps } = useContext(SelectInputTriggerButtonPropsContext);
|
|
301
|
+
|
|
302
|
+
return (
|
|
303
|
+
<ListboxBase.Button
|
|
304
|
+
ref={ref}
|
|
305
|
+
as={PolymorphicWithOverrides}
|
|
306
|
+
__overrides={{ as, ...interactionProps }}
|
|
307
|
+
{...mergeProps({ onClick }, restProps)}
|
|
308
|
+
/>
|
|
309
|
+
);
|
|
310
|
+
}
|
|
254
311
|
|
|
255
312
|
interface SelectInputOptionsContainerProps extends React.ComponentPropsWithRef<'div'> {
|
|
256
313
|
onAriaActiveDescendantChange: (value: React.AriaAttributes['aria-activedescendant']) => void;
|
|
@@ -294,7 +351,7 @@ interface SelectInputOptionsProps<T = string>
|
|
|
294
351
|
listboxRef: React.RefObject<HTMLDivElement>;
|
|
295
352
|
}
|
|
296
353
|
|
|
297
|
-
function SelectInputOptions<T>({
|
|
354
|
+
function SelectInputOptions<T = string>({
|
|
298
355
|
items,
|
|
299
356
|
renderValue = wrapInFragment,
|
|
300
357
|
filterable,
|
|
@@ -395,7 +452,11 @@ interface SelectInputItemViewProps<
|
|
|
395
452
|
needle: string | null;
|
|
396
453
|
}
|
|
397
454
|
|
|
398
|
-
function SelectInputItemView<T
|
|
455
|
+
function SelectInputItemView<T = string>({
|
|
456
|
+
item,
|
|
457
|
+
renderValue,
|
|
458
|
+
needle,
|
|
459
|
+
}: SelectInputItemViewProps<T>) {
|
|
399
460
|
switch (item.type) {
|
|
400
461
|
case 'option': {
|
|
401
462
|
if (
|
|
@@ -418,7 +479,7 @@ function SelectInputItemView<T>({ item, renderValue, needle }: SelectInputItemVi
|
|
|
418
479
|
}
|
|
419
480
|
case 'separator': {
|
|
420
481
|
if (needle == null) {
|
|
421
|
-
return <hr className="np-select-input-separator-item"
|
|
482
|
+
return <hr className="np-select-input-separator-item" />;
|
|
422
483
|
}
|
|
423
484
|
break;
|
|
424
485
|
}
|
|
@@ -429,7 +490,7 @@ function SelectInputItemView<T>({ item, renderValue, needle }: SelectInputItemVi
|
|
|
429
490
|
interface SelectInputGroupItemViewProps<T = string>
|
|
430
491
|
extends SelectInputItemViewProps<T, SelectInputGroupItem<T | undefined>> {}
|
|
431
492
|
|
|
432
|
-
function SelectInputGroupItemView<T>({
|
|
493
|
+
function SelectInputGroupItemView<T = string>({
|
|
433
494
|
item,
|
|
434
495
|
renderValue,
|
|
435
496
|
needle,
|
|
@@ -472,7 +533,7 @@ interface SelectInputOptionProps<T = string> {
|
|
|
472
533
|
children?: React.ReactNode;
|
|
473
534
|
}
|
|
474
535
|
|
|
475
|
-
function SelectInputOption<T>({ value, disabled, children }: SelectInputOptionProps<T>) {
|
|
536
|
+
function SelectInputOption<T = string>({ value, disabled, children }: SelectInputOptionProps<T>) {
|
|
476
537
|
const parentHasValue = useContext(SelectInputHasValueContext);
|
|
477
538
|
|
|
478
539
|
// Avoid flash during exit transition
|
|
@@ -483,23 +544,27 @@ function SelectInputOption<T>({ value, disabled, children }: SelectInputOptionPr
|
|
|
483
544
|
as="div"
|
|
484
545
|
value={value}
|
|
485
546
|
disabled={disabled}
|
|
486
|
-
className={({ active, disabled: uiDisabled }) =>
|
|
547
|
+
className={({ active, selected, disabled: uiDisabled }) =>
|
|
487
548
|
classNames(
|
|
488
549
|
'np-select-input-option-container np-text-body-large',
|
|
489
550
|
active && 'np-select-input-option-container--active',
|
|
551
|
+
selected && 'np-select-input-option-container--selected',
|
|
490
552
|
uiDisabled && 'np-select-input-option-container--disabled',
|
|
491
553
|
)
|
|
492
554
|
}
|
|
493
555
|
>
|
|
494
556
|
{({ selected }) => (
|
|
495
557
|
<>
|
|
558
|
+
<div className="np-select-input-option">{children}</div>
|
|
496
559
|
{cachedParentHasValue ? (
|
|
497
560
|
<Check
|
|
498
|
-
size={
|
|
499
|
-
className={classNames(
|
|
561
|
+
size={24}
|
|
562
|
+
className={classNames(
|
|
563
|
+
'np-select-input-option-check',
|
|
564
|
+
!selected && 'np-select-input-option-check--not-selected',
|
|
565
|
+
)}
|
|
500
566
|
/>
|
|
501
567
|
) : null}
|
|
502
|
-
<div className="np-select-input-option">{children}</div>
|
|
503
568
|
</>
|
|
504
569
|
)}
|
|
505
570
|
</ListboxBase.Option>
|
|
@@ -519,15 +584,20 @@ export function SelectInputOptionContent({
|
|
|
519
584
|
description,
|
|
520
585
|
icon,
|
|
521
586
|
}: SelectInputOptionContentProps) {
|
|
522
|
-
const
|
|
587
|
+
const withinTrigger = useContext(SelectInputOptionContentWithinTriggerContext);
|
|
523
588
|
|
|
524
589
|
return (
|
|
525
|
-
<div
|
|
590
|
+
<div
|
|
591
|
+
className={classNames(
|
|
592
|
+
'np-select-input-option-content-container',
|
|
593
|
+
(note || description) && 'np-text-body-large',
|
|
594
|
+
)}
|
|
595
|
+
>
|
|
526
596
|
{icon ? (
|
|
527
597
|
<div
|
|
528
598
|
className={classNames(
|
|
529
599
|
'np-select-input-option-content-icon',
|
|
530
|
-
!
|
|
600
|
+
!withinTrigger && 'np-select-input-option-content-icon--not-within-trigger',
|
|
531
601
|
)}
|
|
532
602
|
>
|
|
533
603
|
{icon}
|
|
@@ -538,10 +608,10 @@ export function SelectInputOptionContent({
|
|
|
538
608
|
<div
|
|
539
609
|
className={classNames(
|
|
540
610
|
'np-select-input-option-content-text-line-1',
|
|
541
|
-
|
|
611
|
+
withinTrigger && 'np-select-input-option-content-text-within-trigger',
|
|
542
612
|
)}
|
|
543
613
|
>
|
|
544
|
-
<h4 className="
|
|
614
|
+
<h4 className="np-select-input-option-content-text-primary d-inline">{title}</h4>
|
|
545
615
|
{note ? (
|
|
546
616
|
<span className="np-select-input-option-content-text-secondary np-text-body-default">
|
|
547
617
|
{note}
|
|
@@ -553,7 +623,7 @@ export function SelectInputOptionContent({
|
|
|
553
623
|
<div
|
|
554
624
|
className={classNames(
|
|
555
625
|
'np-select-input-option-content-text-secondary np-text-body-default',
|
|
556
|
-
|
|
626
|
+
withinTrigger && 'np-select-input-option-content-text-within-trigger',
|
|
557
627
|
)}
|
|
558
628
|
>
|
|
559
629
|
{description}
|
package/src/inputs/TextArea.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.np-form-control{--ring-width:1px;--ring-color:var(--color-interactive-secondary);background-color:transparent;border:none;box-shadow:inset 0 0 0 var(--ring-width) var(--ring-color);color:#37517e;color:var(--color-content-primary);min-height:0;padding-left:16px;padding-left:var(--size-16);padding-right:16px;padding-right:var(--size-16);transition-duration:.3s;transition-property:color,opacity,box-shadow;transition-timing-function:ease-in-out}.np-form-control:focus-visible{outline:none}.np-form-control[aria-invalid=true]{--ring-width:2px;--ring-color:var(--color-sentiment-negative)!important}.np-form-control:hover:enabled{--ring-width:2px;--ring-color:var(--color-interactive-secondary-hover)}.np-form-control:focus:enabled{--ring-width:3px;--ring-color:var(--color-interactive-primary)}.np-form-control--size-auto{padding-bottom:12px;padding-bottom:var(--size-12);padding-top:12px;padding-top:var(--size-12)}.np-form-control--size-lg,.np-form-control--size-md,.np-form-control--size-sm{padding-bottom:0!important;padding-top:0!important}.np-form-control--size-sm{height:32px!important;height:var(--size-32)!important}.np-form-control--size-md{height:48px!important;height:var(--size-48)!important}.np-form-control--size-lg{height:72px!important;height:var(--size-72)!important}.np-text-area{border-radius:10px!important;border-radius:var(--radius-small)!important;min-height:72px;min-height:var(--size-72);overscroll-behavior:none;scroll-padding-bottom:8px;scroll-padding-bottom:var(--size-8);scroll-padding-top:8px;scroll-padding-top:var(--size-8)}.np-text-area::-moz-placeholder{color:#768e9c;color:var(--color-content-tertiary)}.np-text-area::placeholder{color:#768e9c;color:var(--color-content-tertiary)}
|
|
1
|
+
.np-form-control{--ring-width:1px;--ring-color:var(--color-interactive-secondary);background-color:transparent;border:none;box-shadow:inset 0 0 0 var(--ring-width) var(--ring-color);color:#37517e;color:var(--color-content-primary);min-height:0;padding-left:16px;padding-left:var(--size-16);padding-right:16px;padding-right:var(--size-16);transition-duration:.3s;transition-property:color,opacity,box-shadow;transition-timing-function:ease-in-out}.np-form-control:focus-visible{outline:none}.np-form-control[aria-invalid=true]{--ring-width:2px;--ring-color:var(--color-sentiment-negative)!important}.np-form-control:hover:enabled{--ring-width:2px;--ring-color:var(--color-interactive-secondary-hover)}.np-form-control:focus:enabled{--ring-width:3px;--ring-color:var(--color-interactive-primary)}.np-form-control--size-auto{font-size:1rem;font-size:var(--font-size-16);font-weight:400;font-weight:var(--font-weight-regular);letter-spacing:-.011em;line-height:150%;padding-bottom:12px;padding-bottom:var(--size-12);padding-top:12px;padding-top:var(--size-12)}.np-form-control--size-lg,.np-form-control--size-md,.np-form-control--size-sm{padding-bottom:0!important;padding-top:0!important}.np-form-control--size-sm{font-size:1rem;font-size:var(--font-size-16);font-size:.875rem;font-size:var(--font-size-14);height:32px!important;height:var(--size-32)!important;letter-spacing:-.006em;line-height:1.5;line-height:var(--line-height-body);line-height:155%}.np-form-control--size-md,.np-form-control--size-sm{font-weight:400;font-weight:var(--font-weight-regular)}.np-form-control--size-md{font-size:1rem;font-size:var(--font-size-16);height:48px!important;height:var(--size-48)!important;letter-spacing:-.011em;line-height:150%}.np-form-control--size-lg{color:#37517e;color:var(--color-content-primary);font-size:1.375rem;font-size:var(--font-size-22);font-weight:600;font-weight:var(--font-weight-semi-bold);height:72px!important;height:var(--size-72)!important;letter-spacing:0;letter-spacing:-.018em;line-height:1.2;line-height:var(--line-height-title);line-height:125%;margin:0}.np-form-control--size-lg+ol:not(.list-unstyled),.np-form-control--size-lg+p,.np-form-control--size-lg+ul:not(.list-unstyled){margin-top:8px;margin-top:var(--size-8)}.np-text-area{border-radius:10px!important;border-radius:var(--radius-small)!important;min-height:72px;min-height:var(--size-72);overscroll-behavior:none;scroll-padding-bottom:8px;scroll-padding-bottom:var(--size-8);scroll-padding-top:8px;scroll-padding-top:var(--size-8)}.np-text-area::-moz-placeholder{color:#768e9c;color:var(--color-content-tertiary)}.np-text-area::placeholder{color:#768e9c;color:var(--color-content-tertiary)}
|