@transferwise/components 0.0.0-experimental-e9426b6 → 0.0.0-experimental-0397551

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 (182) hide show
  1. package/build/dateInput/DateInput.js +3 -6
  2. package/build/dateInput/DateInput.js.map +1 -1
  3. package/build/dateInput/DateInput.mjs +2 -5
  4. package/build/dateInput/DateInput.mjs.map +1 -1
  5. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.js +3 -5
  6. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.js.map +1 -1
  7. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.mjs +1 -3
  8. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.mjs.map +1 -1
  9. package/build/index.js +3 -5
  10. package/build/index.js.map +1 -1
  11. package/build/index.mjs +1 -3
  12. package/build/index.mjs.map +1 -1
  13. package/build/inputs/SelectInput.js +821 -0
  14. package/build/inputs/SelectInput.js.map +1 -0
  15. package/build/inputs/SelectInput.messages.js.map +1 -0
  16. package/build/inputs/SelectInput.messages.mjs.map +1 -0
  17. package/build/inputs/SelectInput.mjs +813 -0
  18. package/build/inputs/SelectInput.mjs.map +1 -0
  19. package/build/main.css +47 -47
  20. package/build/moneyInput/MoneyInput.js +2 -5
  21. package/build/moneyInput/MoneyInput.js.map +1 -1
  22. package/build/moneyInput/MoneyInput.mjs +1 -4
  23. package/build/moneyInput/MoneyInput.mjs.map +1 -1
  24. package/build/phoneNumberInput/PhoneNumberInput.js +2 -5
  25. package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
  26. package/build/phoneNumberInput/PhoneNumberInput.mjs +1 -4
  27. package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  28. package/build/styles/main.css +47 -47
  29. package/build/types/inputs/{SelectInput/SelectInput.types.d.ts → SelectInput.d.ts} +7 -4
  30. package/build/types/inputs/SelectInput.d.ts.map +1 -0
  31. package/build/types/inputs/SelectInput.messages.d.ts.map +1 -0
  32. package/package.json +1 -1
  33. package/src/actionButton/ActionButton.story.tsx +3 -0
  34. package/src/checkbox/Checkbox.story.tsx +3 -0
  35. package/src/circularButton/CircularButton.story.tsx +3 -0
  36. package/src/common/bottomSheet/BottomSheet.story.tsx +12 -0
  37. package/src/common/circle/Circle.story.tsx +3 -0
  38. package/src/criticalBanner/CriticalCommsBanner.story.tsx +3 -0
  39. package/src/dateInput/DateInput.test.story.tsx +6 -0
  40. package/src/dateLookup/DateLookup.story.tsx +3 -0
  41. package/src/info/Info.story.tsx +6 -0
  42. package/src/inputs/{SelectInput/SelectInput.docs.mdx → SelectInput.docs.mdx} +1 -0
  43. package/src/inputs/SelectInput.less +219 -0
  44. package/src/inputs/{SelectInput/SelectInput.story.tsx → SelectInput.story.tsx} +7 -7
  45. package/src/inputs/SelectInput.tsx +1190 -0
  46. package/src/main.css +47 -47
  47. package/src/main.less +1 -1
  48. package/src/modal/Modal.story.tsx +15 -0
  49. package/src/snackbar/Snackbar.test.story.tsx +9 -0
  50. package/build/inputs/SelectInput/SelectInput.helpers.js +0 -115
  51. package/build/inputs/SelectInput/SelectInput.helpers.js.map +0 -1
  52. package/build/inputs/SelectInput/SelectInput.helpers.mjs +0 -109
  53. package/build/inputs/SelectInput/SelectInput.helpers.mjs.map +0 -1
  54. package/build/inputs/SelectInput/SelectInput.js +0 -216
  55. package/build/inputs/SelectInput/SelectInput.js.map +0 -1
  56. package/build/inputs/SelectInput/SelectInput.messages.js.map +0 -1
  57. package/build/inputs/SelectInput/SelectInput.messages.mjs.map +0 -1
  58. package/build/inputs/SelectInput/SelectInput.mjs +0 -210
  59. package/build/inputs/SelectInput/SelectInput.mjs.map +0 -1
  60. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.js +0 -26
  61. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.js.map +0 -1
  62. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.mjs +0 -24
  63. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.mjs.map +0 -1
  64. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.js +0 -54
  65. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.js.map +0 -1
  66. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.mjs +0 -52
  67. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.mjs.map +0 -1
  68. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.js +0 -50
  69. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.js.map +0 -1
  70. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.mjs +0 -48
  71. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.mjs.map +0 -1
  72. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.js +0 -47
  73. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.js.map +0 -1
  74. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.mjs +0 -45
  75. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.mjs.map +0 -1
  76. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.js +0 -45
  77. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.js.map +0 -1
  78. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.mjs +0 -41
  79. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.mjs.map +0 -1
  80. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.js +0 -41
  81. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.js.map +0 -1
  82. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.mjs +0 -38
  83. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.mjs.map +0 -1
  84. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.js +0 -270
  85. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.js.map +0 -1
  86. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.mjs +0 -268
  87. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.mjs.map +0 -1
  88. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.js +0 -48
  89. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.js.map +0 -1
  90. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.mjs +0 -46
  91. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.mjs.map +0 -1
  92. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.js +0 -41
  93. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.js.map +0 -1
  94. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.mjs +0 -34
  95. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.mjs.map +0 -1
  96. package/build/styles/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.css +0 -17
  97. package/build/styles/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.css +0 -16
  98. package/build/styles/inputs/SelectInput/components/SelectInputOption/SelectInputOption.css +0 -33
  99. package/build/styles/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.css +0 -37
  100. package/build/types/inputs/SelectInput/SelectInput.d.ts +0 -3
  101. package/build/types/inputs/SelectInput/SelectInput.d.ts.map +0 -1
  102. package/build/types/inputs/SelectInput/SelectInput.helpers.d.ts +0 -28
  103. package/build/types/inputs/SelectInput/SelectInput.helpers.d.ts.map +0 -1
  104. package/build/types/inputs/SelectInput/SelectInput.messages.d.ts.map +0 -1
  105. package/build/types/inputs/SelectInput/SelectInput.types.d.ts.map +0 -1
  106. package/build/types/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.d.ts +0 -5
  107. package/build/types/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.d.ts.map +0 -1
  108. package/build/types/inputs/SelectInput/components/SelectInputClearButton/index.d.ts +0 -2
  109. package/build/types/inputs/SelectInput/components/SelectInputClearButton/index.d.ts.map +0 -1
  110. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.d.ts +0 -9
  111. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.d.ts.map +0 -1
  112. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/index.d.ts +0 -2
  113. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/index.d.ts.map +0 -1
  114. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.d.ts +0 -9
  115. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.d.ts.map +0 -1
  116. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/index.d.ts +0 -2
  117. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/index.d.ts.map +0 -1
  118. package/build/types/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.d.ts +0 -8
  119. package/build/types/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.d.ts.map +0 -1
  120. package/build/types/inputs/SelectInput/components/SelectInputItemView/index.d.ts +0 -2
  121. package/build/types/inputs/SelectInput/components/SelectInputItemView/index.d.ts.map +0 -1
  122. package/build/types/inputs/SelectInput/components/SelectInputOption/SelectInputOption.d.ts +0 -10
  123. package/build/types/inputs/SelectInput/components/SelectInputOption/SelectInputOption.d.ts.map +0 -1
  124. package/build/types/inputs/SelectInput/components/SelectInputOption/index.d.ts +0 -2
  125. package/build/types/inputs/SelectInput/components/SelectInputOption/index.d.ts.map +0 -1
  126. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.d.ts +0 -9
  127. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.d.ts.map +0 -1
  128. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/index.d.ts +0 -3
  129. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/index.d.ts.map +0 -1
  130. package/build/types/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.d.ts +0 -15
  131. package/build/types/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.d.ts.map +0 -1
  132. package/build/types/inputs/SelectInput/components/SelectInputOptions/index.d.ts +0 -2
  133. package/build/types/inputs/SelectInput/components/SelectInputOptions/index.d.ts.map +0 -1
  134. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.d.ts +0 -6
  135. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.d.ts.map +0 -1
  136. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/index.d.ts +0 -2
  137. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/index.d.ts.map +0 -1
  138. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.d.ts +0 -15
  139. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.d.ts.map +0 -1
  140. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/index.d.ts +0 -3
  141. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/index.d.ts.map +0 -1
  142. package/build/types/inputs/SelectInput/index.d.ts +0 -5
  143. package/build/types/inputs/SelectInput/index.d.ts.map +0 -1
  144. package/src/inputs/SelectInput/SelectInput.helpers.ts +0 -152
  145. package/src/inputs/SelectInput/SelectInput.less +0 -42
  146. package/src/inputs/SelectInput/SelectInput.test.tsx +0 -606
  147. package/src/inputs/SelectInput/SelectInput.tsx +0 -247
  148. package/src/inputs/SelectInput/SelectInput.types.ts +0 -114
  149. package/src/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.tsx +0 -25
  150. package/src/inputs/SelectInput/components/SelectInputClearButton/index.ts +0 -1
  151. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.css +0 -17
  152. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.less +0 -15
  153. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.tsx +0 -56
  154. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/index.ts +0 -1
  155. package/src/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.tsx +0 -64
  156. package/src/inputs/SelectInput/components/SelectInputGroupItemView/index.ts +0 -1
  157. package/src/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.css +0 -16
  158. package/src/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.less +0 -17
  159. package/src/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.tsx +0 -55
  160. package/src/inputs/SelectInput/components/SelectInputItemView/index.ts +0 -1
  161. package/src/inputs/SelectInput/components/SelectInputOption/SelectInputOption.css +0 -33
  162. package/src/inputs/SelectInput/components/SelectInputOption/SelectInputOption.less +0 -32
  163. package/src/inputs/SelectInput/components/SelectInputOption/SelectInputOption.tsx +0 -51
  164. package/src/inputs/SelectInput/components/SelectInputOption/index.ts +0 -5
  165. package/src/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.css +0 -37
  166. package/src/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.less +0 -38
  167. package/src/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.tsx +0 -67
  168. package/src/inputs/SelectInput/components/SelectInputOptionContent/index.ts +0 -5
  169. package/src/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.less +0 -75
  170. package/src/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.tsx +0 -369
  171. package/src/inputs/SelectInput/components/SelectInputOptions/index.ts +0 -1
  172. package/src/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.tsx +0 -56
  173. package/src/inputs/SelectInput/components/SelectInputOptionsContainer/index.ts +0 -1
  174. package/src/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.tsx +0 -39
  175. package/src/inputs/SelectInput/components/SelectInputTriggerButton/index.ts +0 -5
  176. package/src/inputs/SelectInput/index.ts +0 -13
  177. package/build/inputs/{SelectInput/SelectInput.messages.js → SelectInput.messages.js} +0 -0
  178. package/build/inputs/{SelectInput/SelectInput.messages.mjs → SelectInput.messages.mjs} +0 -0
  179. package/{src/inputs/SelectInput → build/styles/inputs}/SelectInput.css +47 -47
  180. package/build/types/inputs/{SelectInput/SelectInput.messages.d.ts → SelectInput.messages.d.ts} +0 -0
  181. package/{build/styles/inputs/SelectInput → src/inputs}/SelectInput.css +47 -47
  182. /package/src/inputs/{SelectInput/SelectInput.messages.ts → SelectInput.messages.ts} +0 -0
@@ -1,32 +0,0 @@
1
- .np-select-input-option-container {
2
- display: flex;
3
- cursor: default;
4
- user-select: none;
5
- align-items: center;
6
- column-gap: var(--size-8);
7
- border-radius: var(--radius-small);
8
- padding: var(--size-12) var(--size-16);
9
- color: var(--color-interactive-primary);
10
-
11
- &:focus {
12
- outline: none;
13
- }
14
-
15
- &--active {
16
- box-shadow: inset 0 0 0 1px var(--color-interactive-secondary);
17
- }
18
-
19
- &--disabled {
20
- opacity: 0.45;
21
- }
22
- }
23
-
24
- .np-select-input-option {
25
- flex: 1;
26
- }
27
-
28
- .np-select-input-option-check {
29
- &--not-selected {
30
- visibility: hidden;
31
- }
32
- }
@@ -1,51 +0,0 @@
1
- import { ListboxOption } from '@headlessui/react';
2
- import { Check } from '@transferwise/icons';
3
- import { clsx } from 'clsx';
4
- import { useContext, createContext } from 'react';
5
-
6
- export const SelectInputItemsCountContext = createContext<number | undefined>(undefined);
7
- export const SelectInputItemPositionContext = createContext<number | undefined>(undefined);
8
-
9
- interface SelectInputOptionProps<T = string> {
10
- value: T;
11
- disabled?: boolean;
12
- children?: React.ReactNode;
13
- }
14
-
15
- export function SelectInputOption<T = string>({
16
- value,
17
- disabled,
18
- children,
19
- }: SelectInputOptionProps<T>) {
20
- const itemsCount = useContext(SelectInputItemsCountContext);
21
- const itemPosition = useContext(SelectInputItemPositionContext);
22
- return (
23
- <ListboxOption
24
- as="div"
25
- value={value}
26
- aria-setsize={itemsCount}
27
- aria-posinset={itemPosition}
28
- disabled={disabled}
29
- className={({ active, disabled: uiDisabled }) =>
30
- clsx(
31
- 'np-select-input-option-container np-text-body-large',
32
- active && 'np-select-input-option-container--active',
33
- uiDisabled && 'np-select-input-option-container--disabled',
34
- )
35
- }
36
- >
37
- {({ selected }) => (
38
- <>
39
- <div className="np-select-input-option">{children}</div>
40
- <Check
41
- size={16}
42
- className={clsx(
43
- 'np-select-input-option-check',
44
- !selected && 'np-select-input-option-check--not-selected',
45
- )}
46
- />
47
- </>
48
- )}
49
- </ListboxOption>
50
- );
51
- }
@@ -1,5 +0,0 @@
1
- export {
2
- SelectInputOption,
3
- SelectInputItemsCountContext,
4
- SelectInputItemPositionContext,
5
- } from './SelectInputOption';
@@ -1,37 +0,0 @@
1
- .np-select-input-option-content-container {
2
- display: flex;
3
- align-items: center;
4
- -moz-column-gap: 8px;
5
- column-gap: 8px;
6
- -moz-column-gap: var(--size-8);
7
- column-gap: var(--size-8);
8
- color: #37517e;
9
- color: var(--color-content-primary);
10
- }
11
- .np-select-input-option-content-icon {
12
- display: flex;
13
- }
14
- .np-select-input-option-content-icon--not-within-trigger {
15
- align-self: flex-start;
16
- }
17
- .np-select-input-option-content-text {
18
- display: flex;
19
- flex: 1;
20
- flex-direction: column;
21
- overflow: hidden;
22
- }
23
- .np-select-input-option-content-text-secondary {
24
- color: #5d7079;
25
- color: var(--color-content-secondary);
26
- }
27
- .np-select-input-option-content-text-within-trigger {
28
- overflow: hidden;
29
- text-overflow: ellipsis;
30
- white-space: nowrap;
31
- }
32
- .np-select-input-option-content-text-line-1 > :not([hidden]) ~ :not([hidden]) {
33
- margin-right: 8px;
34
- margin-right: var(--size-8);
35
- margin-left: 8px;
36
- margin-left: var(--size-8);
37
- }
@@ -1,38 +0,0 @@
1
- .np-select-input-option-content-container {
2
- display: flex;
3
- align-items: center;
4
- column-gap: var(--size-8);
5
- color: var(--color-content-primary);
6
- }
7
-
8
- .np-select-input-option-content-icon {
9
- display: flex;
10
-
11
- &--not-within-trigger {
12
- align-self: flex-start;
13
- }
14
- }
15
-
16
- .np-select-input-option-content-text {
17
- display: flex;
18
- flex: 1;
19
- flex-direction: column;
20
- overflow: hidden;
21
- }
22
-
23
- .np-select-input-option-content-text-secondary {
24
- color: var(--color-content-secondary);
25
- }
26
-
27
- .np-select-input-option-content-text-within-trigger {
28
- overflow: hidden;
29
- text-overflow: ellipsis;
30
- white-space: nowrap;
31
- }
32
-
33
- .np-select-input-option-content-text-line-1 {
34
- > :not([hidden]) ~ :not([hidden]) {
35
- margin-right: var(--size-8);
36
- margin-left: var(--size-8);
37
- }
38
- }
@@ -1,67 +0,0 @@
1
- import { clsx } from 'clsx';
2
- import { useContext, createContext } from 'react';
3
-
4
- export const SelectInputOptionContentWithinTriggerContext = createContext(false);
5
-
6
- export interface SelectInputOptionContentProps {
7
- title: string;
8
- note?: string;
9
- description?: string;
10
- icon?: React.ReactNode;
11
- }
12
-
13
- export function SelectInputOptionContent({
14
- title,
15
- note,
16
- description,
17
- icon,
18
- }: SelectInputOptionContentProps) {
19
- const withinTrigger = useContext(SelectInputOptionContentWithinTriggerContext);
20
-
21
- return (
22
- <div
23
- className={clsx(
24
- 'np-select-input-option-content-container',
25
- (note || description) && 'np-text-body-large',
26
- )}
27
- >
28
- {icon ? (
29
- <div
30
- className={clsx(
31
- 'np-select-input-option-content-icon',
32
- !withinTrigger && 'np-select-input-option-content-icon--not-within-trigger',
33
- )}
34
- >
35
- {icon}
36
- </div>
37
- ) : null}
38
-
39
- <div className="np-select-input-option-content-text">
40
- <div
41
- className={clsx(
42
- 'np-select-input-option-content-text-line-1',
43
- withinTrigger && 'np-select-input-option-content-text-within-trigger',
44
- )}
45
- >
46
- <div className="d-inline">{title}</div>
47
- {note ? (
48
- <span className="np-select-input-option-content-text-secondary np-text-body-default">
49
- {note}
50
- </span>
51
- ) : null}
52
- </div>
53
-
54
- {description ? (
55
- <div
56
- className={clsx(
57
- 'np-select-input-option-content-text-secondary np-text-body-default',
58
- withinTrigger && 'np-select-input-option-content-text-within-trigger',
59
- )}
60
- >
61
- {description}
62
- </div>
63
- ) : null}
64
- </div>
65
- </div>
66
- );
67
- }
@@ -1,5 +0,0 @@
1
- export {
2
- SelectInputOptionContent,
3
- SelectInputOptionContentWithinTriggerContext,
4
- } from './SelectInputOptionContent';
5
- export type { SelectInputOptionContentProps } from './SelectInputOptionContent';
@@ -1,75 +0,0 @@
1
- .np-select-input-options-status {
2
- display: flex;
3
- align-items: center;
4
- column-gap: var(--size-8);
5
- padding: var(--size-8) var(--size-24) 0px;
6
- }
7
-
8
- .np-select-input-options-status-icon {
9
- padding: 0 var(--size-4);
10
- color: var(--color-content-tertiary);
11
- }
12
-
13
- .np-select-input-query-container {
14
- display: flex;
15
- flex-direction: column;
16
- padding: var(--size-8);
17
- }
18
-
19
- .np-select-input-listbox-container {
20
- position: relative;
21
- height: var(--initial-height);
22
- scroll-padding-top: var(--size-8);
23
- scroll-padding-bottom: var(--size-8);
24
- overflow-y: auto;
25
-
26
- @media (--screen-sm) {
27
- & {
28
- height: auto;
29
- }
30
- }
31
-
32
- &--virtualized {
33
- /* The wrapping element shrinks this as needed */
34
- height: 100vh;
35
- }
36
-
37
- &--has-group {
38
- scroll-padding-top: var(--size-32);
39
- }
40
- }
41
-
42
- .np-select-input-listbox {
43
- border-radius: var(--radius-small);
44
- padding: var(--size-8);
45
-
46
- .focus-ring();
47
- --ring-outline-offset: calc(-1 * var(--ring-outline-width));
48
-
49
- .np-select-input-listbox-container--virtualized & {
50
- /* Adopted from `VList` in virtua: https://github.com/inokawa/virtua/blob/7f6ed5b37df6b480d4ff350f3960067c5b3519d2/src/react/VList.tsx#L113-L116 */
51
- overflow-y: auto;
52
- contain: strict;
53
- height: 100%;
54
- }
55
- }
56
-
57
- .np-select-input-options-container {
58
- display: flex;
59
- height: 100%;
60
- flex-direction: column;
61
-
62
- &:focus {
63
- outline: none;
64
- }
65
-
66
- @media (--screen-sm) {
67
- & {
68
- max-height: 28rem /* 448px */;
69
- }
70
- }
71
- }
72
-
73
- .np-select-input-footer {
74
- padding: var(--size-4) var(--size-24) var(--size-16);
75
- }
@@ -1,369 +0,0 @@
1
- import { ListboxOptions } from '@headlessui/react';
2
- import { CrossCircle } from '@transferwise/icons';
3
- import { clsx } from 'clsx';
4
- import { useEffect, useId, useMemo, useRef, useState } from 'react';
5
- import { useIntl } from 'react-intl';
6
- import { Virtualizer, type VirtualizerHandle } from 'virtua';
7
-
8
- import { SearchInput } from '../../../SearchInput';
9
- import messages from '../../SelectInput.messages';
10
- import { SelectInputProps, SelectInputOptionItem, SelectInputItem } from '../../SelectInput.types';
11
- import {
12
- searchableString,
13
- dedupeSelectInputItems,
14
- filterSelectInputItems,
15
- selectInputOptionItemIncludesNeedle,
16
- sortSelectInputItems,
17
- } from '../../SelectInput.helpers';
18
-
19
- import { SelectInputOptionsContainer } from '../SelectInputOptionsContainer';
20
- import { SelectInputItemView } from '../SelectInputItemView';
21
- import { SelectInputItemsCountContext, SelectInputItemPositionContext } from '../SelectInputOption';
22
-
23
- const MAX_ITEMS_WITHOUT_VIRTUALIZATION = 50;
24
-
25
- interface SelectInputOptionsProps<T = string> extends Pick<
26
- SelectInputProps<T>,
27
- | 'items'
28
- | 'renderValue'
29
- | 'renderFooter'
30
- | 'filterable'
31
- | 'filterPlaceholder'
32
- | 'id'
33
- | 'parentId'
34
- | 'compareValues'
35
- | 'sortFilteredOptions'
36
- > {
37
- searchInputRef: React.MutableRefObject<HTMLInputElement | null>;
38
- listboxRef: React.MutableRefObject<HTMLDivElement | null>;
39
- filterQuery: string;
40
- onFilterChange: (query: string) => void;
41
- listBoxLabel?: string;
42
- listBoxLabelledBy?: string;
43
- autocomplete?: string;
44
- name?: string;
45
- onAutocompleteSelect?: (value: T) => void;
46
- }
47
-
48
- export function SelectInputOptions<T = string>({
49
- id,
50
- parentId,
51
- items,
52
- compareValues: compareValuesProp,
53
- renderValue = String,
54
- renderFooter,
55
- filterable = false,
56
- filterPlaceholder,
57
- sortFilteredOptions,
58
- searchInputRef,
59
- listboxRef,
60
- filterQuery,
61
- onFilterChange,
62
- listBoxLabel,
63
- listBoxLabelledBy,
64
- autocomplete,
65
- name,
66
- onAutocompleteSelect,
67
- }: SelectInputOptionsProps<T>) {
68
- const intl = useIntl();
69
- const virtualiserHandlerRef = useRef<VirtualizerHandle>(null);
70
- const controllerRef = filterable ? searchInputRef : listboxRef;
71
- const [initialRender, setInitialRender] = useState(true);
72
-
73
- const needle = useMemo(() => {
74
- if (filterable) {
75
- return filterQuery ? searchableString(filterQuery) : null;
76
- }
77
- return undefined;
78
- }, [filterQuery, filterable]);
79
-
80
- useEffect(() => {
81
- if (needle) {
82
- // Ensure having an active option while filtering.
83
- // Without `requestAnimationFrame` upon which React depends for scheduling
84
- // updates, the active status would only show for a split second and then
85
- // disappear inadvertently.
86
- requestAnimationFrame(() => {
87
- if (
88
- controllerRef.current != null &&
89
- !controllerRef.current.hasAttribute('aria-activedescendant')
90
- ) {
91
- // Activate first option via synthetic key press
92
- controllerRef.current.dispatchEvent(
93
- new KeyboardEvent('keydown', { key: 'Home', bubbles: true }),
94
- );
95
- }
96
- });
97
- }
98
- }, [controllerRef, needle]);
99
-
100
- const compareValues = useMemo(() => {
101
- if (!compareValuesProp) {
102
- return undefined;
103
- }
104
-
105
- if (typeof compareValuesProp === 'function') {
106
- return (a: NonNullable<T>, b: NonNullable<T>) => compareValuesProp(a, b);
107
- }
108
-
109
- const key = compareValuesProp;
110
- return (a: NonNullable<T>, b: NonNullable<T>) => {
111
- if (typeof a === 'object' && a != null && typeof b === 'object' && b != null) {
112
- return (a as Record<string, unknown>)[key] === (b as Record<string, unknown>)[key];
113
- }
114
- return a === b;
115
- };
116
- }, [compareValuesProp]);
117
-
118
- const filteredItems: readonly SelectInputItem<NonNullable<T> | undefined>[] = useMemo(() => {
119
- if (needle == null) {
120
- return items;
121
- }
122
-
123
- const filtered = filterSelectInputItems(dedupeSelectInputItems(items, compareValues), (item) =>
124
- selectInputOptionItemIncludesNeedle(item, needle),
125
- );
126
-
127
- if (sortFilteredOptions) {
128
- return sortSelectInputItems(filtered, sortFilteredOptions, filterQuery);
129
- }
130
-
131
- return filtered;
132
- // eslint-disable-next-line react-hooks/exhaustive-deps
133
- }, [needle, items, compareValues]);
134
- const resultsEmpty = needle != null && filteredItems.length === 0;
135
-
136
- const virtualized = filteredItems.length > MAX_ITEMS_WITHOUT_VIRTUALIZATION;
137
-
138
- // Items shown once shall be kept mounted until the needle changes, otherwise
139
- // the scroll position may jump around inadvertently. Pattern adopted from:
140
- // https://inokawa.github.io/virtua/?path=/story/advanced-keep-offscreen-items--append-only
141
- const [mountedIndexes, setMountedIndexes] = useState<number[]>([]);
142
- useEffect(() => {
143
- // Ensure the 'End' key works as intended by keeping the last item mounted
144
- setMountedIndexes((prevMountedIndexes) => {
145
- const indexes = new Set(prevMountedIndexes);
146
- indexes.add(filteredItems.length - 1);
147
- return [...indexes]; // Sorting is redundant by nature here
148
- });
149
- }, [
150
- needle, // Needed as `filteredItems.length` may be equal between two updates
151
- filteredItems.length,
152
- ]);
153
-
154
- const listboxContainerRef = useRef<HTMLDivElement>(null);
155
- useEffect(() => {
156
- if (listboxContainerRef.current != null) {
157
- listboxContainerRef.current.style.setProperty(
158
- '--initial-height',
159
- `${listboxContainerRef.current.offsetHeight}px`,
160
- );
161
- }
162
- }, []);
163
-
164
- useEffect(() => {
165
- setInitialRender(false);
166
- }, []);
167
-
168
- const showStatus = resultsEmpty;
169
- const statusId = useId();
170
- const listboxId = useId();
171
-
172
- const getItemNode = (index: number) => {
173
- const item = filteredItems[index];
174
- return (
175
- <SelectInputItemView key={index} item={item} renderValue={renderValue} needle={needle} />
176
- );
177
- };
178
-
179
- const findMatchingItem = (autocompleteValue: string): T | null => {
180
- const flatOptions = items
181
- .flatMap((item) =>
182
- item.type === 'group' ? item.options : item.type === 'option' ? [item] : [],
183
- )
184
- .filter(
185
- (item): item is SelectInputOptionItem<NonNullable<T>> =>
186
- item.type === 'option' && item.value != null,
187
- );
188
-
189
- const exactMatch = flatOptions.find(
190
- (option) =>
191
- String(option.value) === autocompleteValue ||
192
- option.filterMatchers?.some((matcher) => matcher === autocompleteValue),
193
- );
194
-
195
- if (exactMatch) {
196
- return exactMatch.value;
197
- }
198
-
199
- const fuzzyMatch = flatOptions.find((option) =>
200
- option.filterMatchers?.some((matcher) =>
201
- matcher.toLowerCase().includes(autocompleteValue.toLowerCase()),
202
- ),
203
- );
204
-
205
- return fuzzyMatch ? fuzzyMatch.value : null;
206
- };
207
-
208
- return (
209
- <ListboxOptions
210
- modal
211
- as={SelectInputOptionsContainer}
212
- static
213
- className="np-select-input-options-container"
214
- onAriaActiveDescendantChange={(value: React.AriaAttributes['aria-activedescendant']) => {
215
- if (controllerRef.current != null) {
216
- if (!initialRender && value != null) {
217
- controllerRef.current.setAttribute('aria-activedescendant', value);
218
- } else {
219
- controllerRef.current.removeAttribute('aria-activedescendant');
220
- }
221
- }
222
- }}
223
- >
224
- {filterable ? (
225
- <div className="np-select-input-query-container">
226
- <SearchInput
227
- ref={searchInputRef}
228
- id={id}
229
- name={name}
230
- autoComplete={autocomplete}
231
- role="combobox"
232
- shape="rectangle"
233
- placeholder={filterPlaceholder}
234
- aria-label={filterPlaceholder}
235
- defaultValue={filterQuery}
236
- aria-autocomplete="list"
237
- aria-expanded
238
- aria-controls={listboxId}
239
- aria-describedby={showStatus ? statusId : undefined}
240
- onKeyDown={(event) => {
241
- // Prevent interfering with the matcher of Headless UI
242
- // https://mathiasbynens.be/notes/javascript-unicode#regex
243
- if (/^.$/u.test(event.key)) {
244
- event.stopPropagation();
245
- }
246
- }}
247
- onChange={(event) => {
248
- // Free up resources and ensure not to go out of bounds when the
249
- // resulting item count is less than before
250
- const inputValue = event.currentTarget.value;
251
-
252
- // Free up resources and ensure not to go out of bounds
253
- setMountedIndexes([]);
254
- onFilterChange(inputValue);
255
- }}
256
- onInput={(event) => {
257
- const inputValue = event.currentTarget.value;
258
- const inputElement = event.currentTarget;
259
-
260
- if (autocomplete && onAutocompleteSelect && inputValue) {
261
- setTimeout(() => {
262
- if (inputElement.value === inputValue && inputValue.length > 2) {
263
- const matchedValue = findMatchingItem(inputValue);
264
- if (matchedValue !== null) {
265
- onAutocompleteSelect(matchedValue);
266
- }
267
- }
268
- }, 50);
269
- }
270
- }}
271
- />
272
- </div>
273
- ) : null}
274
-
275
- <section
276
- ref={listboxContainerRef}
277
- tabIndex={-1}
278
- className={clsx(
279
- 'np-select-input-listbox-container',
280
- virtualized && 'np-select-input-listbox-container--virtualized',
281
- needle == null && // Groups aren't shown when filtering
282
- items.some((item) => item.type === 'group') &&
283
- 'np-select-input-listbox-container--has-group',
284
- )}
285
- data-wds-parent={parentId ?? undefined}
286
- >
287
- {resultsEmpty ? (
288
- <div id={statusId} className="np-select-input-options-status">
289
- <CrossCircle size={16} className="np-select-input-options-status-icon" />
290
- {intl.formatMessage(messages.noResultsFound)}
291
- </div>
292
- ) : null}
293
-
294
- <div
295
- ref={listboxRef}
296
- id={listboxId}
297
- role="listbox"
298
- aria-orientation="vertical"
299
- aria-label={listBoxLabel}
300
- aria-labelledby={listBoxLabelledBy}
301
- tabIndex={0}
302
- className="np-select-input-listbox"
303
- >
304
- {!virtualized ? (
305
- filteredItems.map((_, index) => getItemNode(index))
306
- ) : (
307
- <Virtualizer
308
- ref={virtualiserHandlerRef}
309
- key={needle}
310
- data={filteredItems}
311
- keepMounted={mountedIndexes}
312
- scrollRef={listboxRef} // `VList` doesn't expose this
313
- onScroll={async () => {
314
- if (!virtualiserHandlerRef.current) return;
315
-
316
- const startIndex = virtualiserHandlerRef.current.findItemIndex(
317
- virtualiserHandlerRef.current.scrollOffset,
318
- );
319
- const endIndex = virtualiserHandlerRef.current.findItemIndex(
320
- virtualiserHandlerRef.current.scrollOffset +
321
- virtualiserHandlerRef.current.viewportSize,
322
- );
323
-
324
- setMountedIndexes((prevMountedIndexes) => {
325
- const indexes = new Set(prevMountedIndexes);
326
-
327
- for (let index = startIndex; index <= endIndex; index += 1) {
328
- indexes.add(index);
329
- }
330
-
331
- return [...indexes].sort((a, b) => a - b);
332
- });
333
- }}
334
- >
335
- {(item, index) => (
336
- // The position of each item can't be inferred by browsers when
337
- // virtualizing, as some of the items may not be in the DOM
338
- <SelectInputItemsCountContext.Provider value={filteredItems.length}>
339
- <SelectInputItemPositionContext.Provider value={index + 1}>
340
- {getItemNode(index)}
341
- </SelectInputItemPositionContext.Provider>
342
- </SelectInputItemsCountContext.Provider>
343
- )}
344
- </Virtualizer>
345
- )}
346
- </div>
347
-
348
- {renderFooter != null ? (
349
- <footer className="np-select-input-footer">
350
- <div
351
- role="none"
352
- onKeyDown={(event) => {
353
- // Prevent interfering with Headless UI
354
- if (event.key !== 'Escape') {
355
- event.stopPropagation();
356
- }
357
- }}
358
- >
359
- {renderFooter({
360
- resultsEmpty,
361
- queryNormalized: needle,
362
- })}
363
- </div>
364
- </footer>
365
- ) : null}
366
- </section>
367
- </ListboxOptions>
368
- );
369
- }
@@ -1 +0,0 @@
1
- export { SelectInputOptions } from './SelectInputOptions';