@transferwise/components 45.21.3 → 45.23.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 +103 -77
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +103 -77
  4. package/build/index.js.map +1 -1
  5. package/build/main.css +1 -1
  6. package/build/styles/flowNavigation/FlowNavigation.css +1 -1
  7. package/build/styles/flowNavigation/animatedLabel/AnimatedLabel.css +1 -1
  8. package/build/styles/header/Header.css +1 -1
  9. package/build/styles/inputs/SelectInput.css +1 -1
  10. package/build/styles/main.css +1 -1
  11. package/build/styles/overlayHeader/OverlayHeader.css +1 -1
  12. package/build/types/common/flowHeader/FlowHeader.d.ts.map +1 -1
  13. package/build/types/flowNavigation/FlowNavigation.d.ts.map +1 -1
  14. package/build/types/flowNavigation/animatedLabel/AnimatedLabel.d.ts +1 -2
  15. package/build/types/flowNavigation/animatedLabel/AnimatedLabel.d.ts.map +1 -1
  16. package/build/types/flowNavigation/backButton/BackButton.d.ts +10 -11
  17. package/build/types/flowNavigation/backButton/BackButton.d.ts.map +1 -1
  18. package/build/types/header/Header.d.ts +1 -1
  19. package/build/types/header/Header.d.ts.map +1 -1
  20. package/build/types/inputs/SelectInput.d.ts +5 -1
  21. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  22. package/build/types/overlayHeader/OverlayHeader.d.ts.map +1 -1
  23. package/build/types/title/Title.d.ts +1 -1
  24. package/build/types/title/Title.d.ts.map +1 -1
  25. package/package.json +1 -1
  26. package/src/common/flowHeader/FlowHeader.tsx +4 -22
  27. package/src/common/flowHeader/__snapshots__/FlowHeader.spec.js.snap +6 -22
  28. package/src/flowNavigation/FlowNavigation.css +1 -1
  29. package/src/flowNavigation/FlowNavigation.less +0 -9
  30. package/src/flowNavigation/FlowNavigation.spec.js +3 -3
  31. package/src/flowNavigation/FlowNavigation.story.js +22 -189
  32. package/src/flowNavigation/FlowNavigation.tsx +22 -27
  33. package/src/flowNavigation/__snapshots__/FlowNavigation.spec.js.snap +18 -26
  34. package/src/flowNavigation/animatedLabel/AnimatedLabel.css +1 -1
  35. package/src/flowNavigation/animatedLabel/AnimatedLabel.less +0 -6
  36. package/src/flowNavigation/animatedLabel/AnimatedLabel.spec.js +7 -21
  37. package/src/flowNavigation/animatedLabel/AnimatedLabel.tsx +8 -17
  38. package/src/flowNavigation/animatedLabel/__snapshots__/AnimatedLabel.spec.js.snap +4 -4
  39. package/src/flowNavigation/backButton/BackButton.js +14 -9
  40. package/src/flowNavigation/backButton/BackButton.spec.js +3 -2
  41. package/src/flowNavigation/backButton/__snapshots__/BackButton.spec.js.snap +28 -21
  42. package/src/header/Header.css +1 -1
  43. package/src/header/Header.less +5 -0
  44. package/src/header/Header.tsx +21 -2
  45. package/src/inputs/SelectInput.css +1 -1
  46. package/src/inputs/SelectInput.less +7 -10
  47. package/src/inputs/SelectInput.spec.tsx +40 -0
  48. package/src/inputs/SelectInput.story.tsx +18 -0
  49. package/src/inputs/SelectInput.tsx +46 -12
  50. package/src/inputs/_BottomSheet.less +1 -1
  51. package/src/inputs/_Popover.less +1 -0
  52. package/src/main.css +1 -1
  53. package/src/overlayHeader/OverlayHeader.css +1 -1
  54. package/src/overlayHeader/OverlayHeader.js +6 -4
  55. package/src/overlayHeader/OverlayHeader.less +0 -8
  56. package/src/overlayHeader/OverlayHeader.spec.js +1 -1
  57. package/src/overlayHeader/__snapshots__/OverlayHeader.spec.js.snap +10 -14
  58. package/src/title/Title.tsx +1 -1
  59. package/src/flowNavigation/animatedLabel/AnimatedLabel.story.js +0 -22
@@ -135,6 +135,10 @@ export interface SelectInputProps<T = string> {
135
135
  | (keyof NonNullable<T> & string)
136
136
  | ((a: T | undefined, b: T | undefined) => boolean);
137
137
  renderValue?: (value: NonNullable<T>, withinTrigger: boolean) => React.ReactNode;
138
+ renderFooter?: (args: {
139
+ resultsEmpty: boolean;
140
+ normalizedQuery: string | null | undefined;
141
+ }) => React.ReactNode;
138
142
  renderTrigger?: (args: {
139
143
  content: React.ReactNode;
140
144
  placeholderShown: boolean;
@@ -211,6 +215,7 @@ export function SelectInput<T = string>({
211
215
  value: controlledValue,
212
216
  compareValues,
213
217
  renderValue = wrapInFragment,
218
+ renderFooter,
214
219
  renderTrigger = defaultRenderTrigger,
215
220
  filterable,
216
221
  filterPlaceholder,
@@ -296,6 +301,7 @@ export function SelectInput<T = string>({
296
301
  <SelectInputOptions
297
302
  items={items}
298
303
  renderValue={renderValue}
304
+ renderFooter={renderFooter}
299
305
  filterable={filterable}
300
306
  filterPlaceholder={filterPlaceholder}
301
307
  searchInputRef={searchInputRef}
@@ -351,17 +357,22 @@ const SelectInputOptionsContainer = forwardRef(function SelectInputOptionsContai
351
357
  }, [ariaActiveDescendant, handleAriaActiveDescendantChange]);
352
358
 
353
359
  return (
354
- // eslint-disable-next-line jsx-a11y/no-static-element-interactions
355
360
  <div
356
361
  ref={ref}
362
+ role="none"
357
363
  onKeyDown={(event) => {
358
- // Prevent absorbing dismissal requests too early
359
- if (event.key === 'Escape') {
364
+ // Prevent confirmation close without an active item
365
+ if (event.key === 'Enter' && ariaActiveDescendant == null) {
360
366
  return;
361
367
  }
362
368
 
363
- // Prevent confirmation close without an active item
364
- if (event.key === 'Enter' && ariaActiveDescendant == null) {
369
+ // Prevent absorbing actions early
370
+ if (event.key === 'Escape' || event.key === 'Tab') {
371
+ onKeyDown?.({
372
+ ...event,
373
+ preventDefault: () => {},
374
+ stopPropagation: () => {},
375
+ });
365
376
  return;
366
377
  }
367
378
 
@@ -373,7 +384,10 @@ const SelectInputOptionsContainer = forwardRef(function SelectInputOptionsContai
373
384
  });
374
385
 
375
386
  interface SelectInputOptionsProps<T = string>
376
- extends Pick<SelectInputProps<T>, 'items' | 'renderValue' | 'filterable' | 'filterPlaceholder'> {
387
+ extends Pick<
388
+ SelectInputProps<T>,
389
+ 'items' | 'renderValue' | 'renderFooter' | 'filterable' | 'filterPlaceholder'
390
+ > {
377
391
  searchInputRef: React.RefObject<HTMLInputElement>;
378
392
  listboxRef: React.RefObject<HTMLDivElement>;
379
393
  }
@@ -381,6 +395,7 @@ interface SelectInputOptionsProps<T = string>
381
395
  function SelectInputOptions<T = string>({
382
396
  items,
383
397
  renderValue = wrapInFragment,
398
+ renderFooter,
384
399
  filterable = false,
385
400
  filterPlaceholder,
386
401
  searchInputRef,
@@ -397,7 +412,7 @@ function SelectInputOptions<T = string>({
397
412
  }
398
413
  return undefined;
399
414
  }, [filterable, query]);
400
- const empty = needle != null && filterSelectInputItems(items, needle).length === 0;
415
+ const resultsEmpty = needle != null && filterSelectInputItems(items, needle).length === 0;
401
416
 
402
417
  const listboxContainerRef = useRef<HTMLDivElement>(null);
403
418
  useEffect(() => {
@@ -409,7 +424,7 @@ function SelectInputOptions<T = string>({
409
424
  }
410
425
  }, []);
411
426
 
412
- const showStatus = empty;
427
+ const showStatus = resultsEmpty;
413
428
  const statusId = useId();
414
429
  const listboxId = useId();
415
430
 
@@ -451,7 +466,7 @@ function SelectInputOptions<T = string>({
451
466
  </div>
452
467
  ) : null}
453
468
 
454
- <div
469
+ <section
455
470
  ref={listboxContainerRef}
456
471
  className={classNames(
457
472
  'np-select-input-listbox-container',
@@ -459,7 +474,7 @@ function SelectInputOptions<T = string>({
459
474
  'np-select-input-listbox-container--has-group',
460
475
  )}
461
476
  >
462
- {empty ? (
477
+ {resultsEmpty ? (
463
478
  <div id={statusId} className="np-select-input-options-status">
464
479
  <CrossCircle size={16} className="np-select-input-options-status-icon" />
465
480
  {intl.formatMessage(messages.noResultsFound)}
@@ -484,7 +499,26 @@ function SelectInputOptions<T = string>({
484
499
  />
485
500
  ))}
486
501
  </div>
487
- </div>
502
+
503
+ {renderFooter != null ? (
504
+ <footer className="np-select-input-footer">
505
+ <div
506
+ role="none"
507
+ onKeyDown={(event) => {
508
+ // Prevent interfering with Headless UI
509
+ if (event.key !== 'Escape') {
510
+ event.stopPropagation();
511
+ }
512
+ }}
513
+ >
514
+ {renderFooter({
515
+ resultsEmpty,
516
+ normalizedQuery: needle,
517
+ })}
518
+ </div>
519
+ </footer>
520
+ ) : null}
521
+ </section>
488
522
  </ListboxBase.Options>
489
523
  );
490
524
  }
@@ -547,7 +581,7 @@ function SelectInputGroupItemView<T = string>({
547
581
  {needle == null ? (
548
582
  <header
549
583
  id={headerId}
550
- role="presentation"
584
+ role="none"
551
585
  className="np-select-input-group-item-header np-text-title-group"
552
586
  >
553
587
  {item.label}
@@ -7,7 +7,7 @@
7
7
  &--enter, &--leave {
8
8
  transition-property: opacity;
9
9
  transition-timing-function: ease-out;
10
- transition-duration: 150ms;
10
+ transition-duration: 300ms;
11
11
  }
12
12
 
13
13
  &--enter-from, &--leave-to {
@@ -5,6 +5,7 @@
5
5
  width: var(--width);
6
6
  min-width: 20rem;
7
7
  flex-direction: column;
8
+ overflow: hidden;
8
9
  border-radius: var(--radius-small);
9
10
  background-color: var(--color-background-elevated);
10
11
  box-shadow: 0 0 40px rgb(69 71 69 / 0.2);