@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.
Files changed (59) hide show
  1. package/build/index.esm.js +425 -368
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +425 -366
  4. package/build/index.js.map +1 -1
  5. package/build/main.css +1 -1
  6. package/build/styles/inputs/Input.css +1 -1
  7. package/build/styles/inputs/SelectInput.css +1 -1
  8. package/build/styles/inputs/TextArea.css +1 -1
  9. package/build/styles/instructionsList/InstructionsList.css +1 -1
  10. package/build/styles/main.css +1 -1
  11. package/build/styles/stepper/Stepper.css +1 -1
  12. package/build/styles/tooltip/Tooltip.css +1 -1
  13. package/build/types/button/Button.d.ts.map +1 -1
  14. package/build/types/common/polymorphicWithOverrides/PolymorphicWithOverrides.d.ts +13 -0
  15. package/build/types/common/polymorphicWithOverrides/PolymorphicWithOverrides.d.ts.map +1 -0
  16. package/build/types/index.d.ts +2 -2
  17. package/build/types/index.d.ts.map +1 -1
  18. package/build/types/inputs/SelectInput.d.ts +18 -6
  19. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  20. package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
  21. package/build/types/inputs/_Popover.d.ts.map +1 -1
  22. package/build/types/instructionsList/InstructionsList.d.ts +10 -3
  23. package/build/types/instructionsList/InstructionsList.d.ts.map +1 -1
  24. package/build/types/processIndicator/ProcessIndicator.d.ts +1 -1
  25. package/build/types/tooltip/Tooltip.d.ts +2 -1
  26. package/build/types/tooltip/Tooltip.d.ts.map +1 -1
  27. package/package.json +4 -3
  28. package/src/button/Button.story.tsx +6 -0
  29. package/src/button/Button.tsx +6 -1
  30. package/src/common/polymorphicWithOverrides/PolymorphicWithOverrides.tsx +19 -0
  31. package/src/index.ts +9 -1
  32. package/src/inputs/Input.css +1 -1
  33. package/src/inputs/SelectInput.css +1 -1
  34. package/src/inputs/SelectInput.less +20 -5
  35. package/src/inputs/SelectInput.story.tsx +85 -35
  36. package/src/inputs/SelectInput.tsx +176 -106
  37. package/src/inputs/TextArea.css +1 -1
  38. package/src/inputs/_BottomSheet.tsx +47 -37
  39. package/src/inputs/_Popover.less +1 -1
  40. package/src/inputs/_Popover.tsx +30 -27
  41. package/src/inputs/_common.less +6 -0
  42. package/src/inputs/_common.ts +4 -4
  43. package/src/instructionsList/InstructionList.story.tsx +39 -0
  44. package/src/instructionsList/InstructionsList.css +1 -1
  45. package/src/instructionsList/InstructionsList.less +3 -15
  46. package/src/instructionsList/InstructionsList.spec.tsx +35 -0
  47. package/src/instructionsList/InstructionsList.tsx +40 -25
  48. package/src/main.css +1 -1
  49. package/src/processIndicator/ProcessIndicator.js +2 -2
  50. package/src/ssr.spec.js +1 -0
  51. package/src/stepper/Stepper.css +1 -1
  52. package/src/stepper/Stepper.less +1 -1
  53. package/src/tooltip/Tooltip.css +1 -1
  54. package/src/tooltip/Tooltip.less +13 -0
  55. package/src/tooltip/Tooltip.spec.tsx +97 -29
  56. package/src/tooltip/Tooltip.tsx +24 -31
  57. package/src/tooltip/__snapshots__/Tooltip.spec.tsx.snap +31 -0
  58. package/src/instructionsList/InstructionList.story.js +0 -27
  59. 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 { SelectInput, type SelectInputItem, SelectInputOptionContent } from './SelectInput';
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, compact) => (
90
+ renderValue={(month, withinTrigger) => (
82
91
  <SelectInputOptionContent
83
92
  title={month.name}
84
93
  note="Note"
85
- description={compact ? undefined : `Month #${month.id}`}
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>(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
- <div className="d-flex flex-column">
230
- <SelectInput
231
- items={[
232
- {
233
- type: 'group',
234
- label: 'Popular currencies',
235
- options: popularCurrencies.map((currency) => currencyOption(currency)),
236
- },
237
- {
238
- type: 'group',
239
- label: 'All currencies',
240
- options: allCurrencies.map((currency) => currencyOption(currency)),
241
- },
242
- ]}
243
- value={selectedCurrency}
244
- renderValue={(currency) => (
245
- <SelectInputOptionContent
246
- title={currency.code}
247
- note={currency.name}
248
- icon={<Flag code={currency.code} intrinsicSize={24} />}
249
- />
250
- )}
251
- filterable
252
- filterPlaceholder="Type a currency / country"
253
- onChange={(currency) => {
254
- setSelectedCurrency(currency);
255
- onChange(currency);
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 { createContext, useState, useRef, forwardRef, useEffect, useMemo, useContext } from 'react';
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, type ButtonInputProps } from './_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
- const SelectInputOptionContentCompactContext = createContext(false);
42
-
43
- interface SelectInputOptionItem<T = string> {
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
- export function SelectInput<T>({
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
- <InputGroup
166
- addonEnd={{
167
- content: (
168
- <span
169
- className={classNames(
170
- 'np-select-input-addon-container',
171
- uiDisabled && 'disabled',
172
- )}
173
- >
174
- {onClear != null && value != null ? (
175
- <>
176
- <button
177
- type="button"
178
- aria-label={intl.formatMessage(messages.ariaLabel)}
179
- disabled={uiDisabled}
180
- className="np-select-input-addon np-select-input-addon--interactive"
181
- onClick={(event) => {
182
- event.preventDefault();
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
- <Cross size={16} />
188
- </button>
189
- <span className="np-select-input-addon-separator" />
190
- </>
191
- ) : null}
192
-
193
- <span className="np-select-input-addon">
194
- <ChevronDown size={16} />
195
- </span>
196
- </span>
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
- <OptionsOverlay
203
- open={open}
204
- renderTrigger={({ ref, getInteractionProps }) => (
205
- <ListboxBase.Button
206
- ref={mergeRefs([ref, triggerRef])}
207
- as={SelectInputButton}
208
- overrides={getInteractionProps()}
209
- onClick={() => {
210
- setOpen((prev) => !prev);
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
- interface SelectInputButtonProps extends ButtonInputProps {
245
- overrides?: { [key: string]: unknown };
246
- }
292
+ export type SelectInputTriggerButtonProps<T extends React.ComponentType | 'button' = 'button'> = {
293
+ as?: T;
294
+ } & React.ComponentPropsWithoutRef<T>;
247
295
 
248
- const SelectInputButton = forwardRef(function SelectInputButton(
249
- { overrides, ...restProps }: SelectInputButtonProps,
250
- ref: React.ForwardedRef<HTMLButtonElement>,
251
- ) {
252
- return <ButtonInput ref={ref} {...restProps} {...overrides} />;
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>({ item, renderValue, needle }: SelectInputItemViewProps<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" aria-hidden />;
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={16}
499
- className={classNames(!selected && 'np-select-input-option-check--not-selected')}
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 compact = useContext(SelectInputOptionContentCompactContext);
587
+ const withinTrigger = useContext(SelectInputOptionContentWithinTriggerContext);
523
588
 
524
589
  return (
525
- <div className="np-select-input-option-content-container np-text-body-large">
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
- !compact && 'np-select-input-option-content-icon--not-compact',
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
- compact && 'np-select-input-option-content-text-compact',
611
+ withinTrigger && 'np-select-input-option-content-text-within-trigger',
542
612
  )}
543
613
  >
544
- <h4 className="d-inline np-text-body-large">{title}</h4>
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
- compact && 'np-select-input-option-content-text-compact',
626
+ withinTrigger && 'np-select-input-option-content-text-within-trigger',
557
627
  )}
558
628
  >
559
629
  {description}
@@ -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)}