@transferwise/components 0.0.0-experimental-cbe9617 → 0.0.0-experimental-26bc819

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 (80) hide show
  1. package/build/field/Field.js +10 -0
  2. package/build/field/Field.js.map +1 -1
  3. package/build/field/Field.mjs +10 -0
  4. package/build/field/Field.mjs.map +1 -1
  5. package/build/index.js +2 -0
  6. package/build/index.js.map +1 -1
  7. package/build/index.mjs +1 -0
  8. package/build/index.mjs.map +1 -1
  9. package/build/inputs/SelectInput.js +5 -10
  10. package/build/inputs/SelectInput.js.map +1 -1
  11. package/build/inputs/SelectInput.mjs +6 -11
  12. package/build/inputs/SelectInput.mjs.map +1 -1
  13. package/build/inputs/_BottomSheet.js +2 -5
  14. package/build/inputs/_BottomSheet.js.map +1 -1
  15. package/build/inputs/_BottomSheet.mjs +3 -6
  16. package/build/inputs/_BottomSheet.mjs.map +1 -1
  17. package/build/inputs/_Popover.js +0 -2
  18. package/build/inputs/_Popover.js.map +1 -1
  19. package/build/inputs/_Popover.mjs +0 -2
  20. package/build/inputs/_Popover.mjs.map +1 -1
  21. package/build/listItem/Prompt/ListItemPrompt.js +10 -0
  22. package/build/listItem/Prompt/ListItemPrompt.js.map +1 -1
  23. package/build/listItem/Prompt/ListItemPrompt.mjs +10 -0
  24. package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -1
  25. package/build/main.css +30 -1
  26. package/build/prompt/ActionPrompt/ActionPrompt.js +123 -0
  27. package/build/prompt/ActionPrompt/ActionPrompt.js.map +1 -0
  28. package/build/prompt/ActionPrompt/ActionPrompt.mjs +118 -0
  29. package/build/prompt/ActionPrompt/ActionPrompt.mjs.map +1 -0
  30. package/build/prompt/PrimitivePrompt/PrimitivePrompt.js +13 -11
  31. package/build/prompt/PrimitivePrompt/PrimitivePrompt.js.map +1 -1
  32. package/build/prompt/PrimitivePrompt/PrimitivePrompt.mjs +14 -12
  33. package/build/prompt/PrimitivePrompt/PrimitivePrompt.mjs.map +1 -1
  34. package/build/styles/main.css +30 -1
  35. package/build/styles/prompt/ActionPrompt/ActionPrompt.css +20 -0
  36. package/build/styles/prompt/PrimitivePrompt/PrimitivePrompt.css +10 -1
  37. package/build/typeahead/Typeahead.js +10 -0
  38. package/build/typeahead/Typeahead.js.map +1 -1
  39. package/build/typeahead/Typeahead.mjs +10 -0
  40. package/build/typeahead/Typeahead.mjs.map +1 -1
  41. package/build/types/index.d.ts +2 -2
  42. package/build/types/index.d.ts.map +1 -1
  43. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  44. package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
  45. package/build/types/inputs/_Popover.d.ts.map +1 -1
  46. package/build/types/prompt/ActionPrompt/ActionPrompt.d.ts +26 -0
  47. package/build/types/prompt/ActionPrompt/ActionPrompt.d.ts.map +1 -0
  48. package/build/types/prompt/ActionPrompt/ActionPrompt.test.d.ts +2 -0
  49. package/build/types/prompt/ActionPrompt/ActionPrompt.test.d.ts.map +1 -0
  50. package/build/types/prompt/ActionPrompt/index.d.ts +3 -0
  51. package/build/types/prompt/ActionPrompt/index.d.ts.map +1 -0
  52. package/build/types/prompt/InlinePrompt/InlinePrompt.test.d.ts +2 -0
  53. package/build/types/prompt/InlinePrompt/InlinePrompt.test.d.ts.map +1 -0
  54. package/build/types/prompt/PrimitivePrompt/PrimitivePrompt.d.ts.map +1 -1
  55. package/build/types/prompt/PrimitivePrompt/PrimitivePrompt.test.d.ts +2 -0
  56. package/build/types/prompt/PrimitivePrompt/PrimitivePrompt.test.d.ts.map +1 -0
  57. package/build/types/prompt/index.d.ts +2 -0
  58. package/build/types/prompt/index.d.ts.map +1 -1
  59. package/package.json +5 -6
  60. package/src/index.ts +2 -2
  61. package/src/inputs/SelectInput.spec.tsx +7 -78
  62. package/src/inputs/SelectInput.tsx +10 -21
  63. package/src/inputs/_BottomSheet.tsx +4 -7
  64. package/src/inputs/_Popover.tsx +0 -2
  65. package/src/main.css +30 -1
  66. package/src/main.less +1 -0
  67. package/src/moneyInput/MoneyInput.spec.tsx +7 -26
  68. package/src/prompt/ActionPrompt/ActionPrompt.css +20 -0
  69. package/src/prompt/ActionPrompt/ActionPrompt.less +22 -0
  70. package/src/prompt/ActionPrompt/ActionPrompt.story.tsx +189 -0
  71. package/src/prompt/ActionPrompt/ActionPrompt.test.tsx +256 -0
  72. package/src/prompt/ActionPrompt/ActionPrompt.tsx +129 -0
  73. package/src/prompt/ActionPrompt/index.ts +2 -0
  74. package/src/prompt/InlinePrompt/{InlinePrompt.spec.tsx → InlinePrompt.test.tsx} +3 -38
  75. package/src/prompt/PrimitivePrompt/PrimitivePrompt.css +10 -1
  76. package/src/prompt/PrimitivePrompt/PrimitivePrompt.less +11 -1
  77. package/src/prompt/PrimitivePrompt/PrimitivePrompt.test.tsx +161 -0
  78. package/src/prompt/PrimitivePrompt/PrimitivePrompt.tsx +15 -11
  79. package/src/prompt/index.ts +3 -0
  80. package/src/ssr.spec.tsx +1 -0
@@ -0,0 +1,26 @@
1
+ import { ReactNode } from 'react';
2
+ import { AvatarViewProps } from '../../avatarView';
3
+ import { ButtonProps } from '../../button/Button.types';
4
+ import { PrimitivePromptProps } from '../PrimitivePrompt';
5
+ import { BadgeAssetsProps } from '../../badge';
6
+ export type ActionPromptProps = {
7
+ title: ReactNode;
8
+ description?: ReactNode;
9
+ media?: {
10
+ imgSrc?: string;
11
+ avatar?: Pick<AvatarViewProps, 'imgSrc' | 'profileName' | 'profileType'> & {
12
+ asset?: AvatarViewProps['children'];
13
+ badge?: Pick<BadgeAssetsProps, 'flagCode'>;
14
+ };
15
+ 'aria-label'?: string;
16
+ };
17
+ actionPrimary: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {
18
+ label: ButtonProps['children'];
19
+ };
20
+ actionSecondary?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {
21
+ label: ButtonProps['children'];
22
+ };
23
+ } & Pick<PrimitivePromptProps, 'id' | 'className' | 'data-testid' | 'sentiment' | 'onDismiss'>;
24
+ export declare const ActionPrompt: ({ sentiment, title, description, onDismiss, media, actionPrimary, actionSecondary, id, className, "data-testid": testId, }: ActionPromptProps) => import("react").JSX.Element;
25
+ export default ActionPrompt;
26
+ //# sourceMappingURL=ActionPrompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionPrompt.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ActionPrompt/ActionPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOlC,OAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAI/C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,aAAa,GAAG,aAAa,CAAC,GAAG;YACzE,KAAK,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;YACpC,KAAK,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;SAC5C,CAAC;QACF,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,aAAa,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC,GAAG;QAChE,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;KAChC,CAAC;IACF,eAAe,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC,GAAG;QACnE,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;KAChC,CAAC;CACH,GAAG,IAAI,CAAC,oBAAoB,EAAE,IAAI,GAAG,WAAW,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;AAE/F,eAAO,MAAM,YAAY,GAAI,4HAW1B,iBAAiB,gCAiFnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ActionPrompt.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionPrompt.test.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ActionPrompt/ActionPrompt.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export type { ActionPromptProps } from './ActionPrompt';
2
+ export { ActionPrompt } from './ActionPrompt';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ActionPrompt/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=InlinePrompt.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InlinePrompt.test.d.ts","sourceRoot":"","sources":["../../../../src/prompt/InlinePrompt/InlinePrompt.test.tsx"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PrimitivePrompt.d.ts","sourceRoot":"","sources":["../../../../src/prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"names":[],"mappings":"AAEA,OAAyB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAIrE,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;8GAE8G;AAC9G,eAAO,MAAM,eAAe,GAAI,6EAQ7B,oBAAoB,gCA0BtB,CAAC"}
1
+ {"version":3,"file":"PrimitivePrompt.d.ts","sourceRoot":"","sources":["../../../../src/prompt/PrimitivePrompt/PrimitivePrompt.tsx"],"names":[],"mappings":"AAEA,OAAyB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAIrE,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;8GAE8G;AAC9G,eAAO,MAAM,eAAe,GAAI,6EAQ7B,oBAAoB,gCA8BtB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=PrimitivePrompt.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrimitivePrompt.test.d.ts","sourceRoot":"","sources":["../../../../src/prompt/PrimitivePrompt/PrimitivePrompt.test.tsx"],"names":[],"mappings":""}
@@ -1,3 +1,5 @@
1
1
  export type { InlinePromptProps } from './InlinePrompt';
2
2
  export { InlinePrompt } from './InlinePrompt';
3
+ export type { ActionPromptProps } from './ActionPrompt';
4
+ export { ActionPrompt } from './ActionPrompt';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/prompt/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/prompt/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "0.0.0-experimental-cbe9617",
3
+ "version": "0.0.0-experimental-26bc819",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -56,7 +56,7 @@
56
56
  "@storybook/react-webpack5": "10.3.0-alpha.0",
57
57
  "@testing-library/dom": "^10.4.1",
58
58
  "@testing-library/jest-dom": "^6.9.1",
59
- "@testing-library/react": "^16.3.2",
59
+ "@testing-library/react": "^16.3.1",
60
60
  "@testing-library/user-event": "^14.6.1",
61
61
  "@transferwise/icons": "^4.0.2",
62
62
  "@tsconfig/recommended": "^1.0.13",
@@ -78,7 +78,6 @@
78
78
  "jest": "^30.2.0",
79
79
  "jest-environment-jsdom": "^29.7.0",
80
80
  "jest-fetch-mock": "^3.0.3",
81
- "jsdom-testing-mocks": "^1.16.0",
82
81
  "lodash.times": "^4.3.2",
83
82
  "react-intl": "^7.1.11",
84
83
  "rollup": "^4.54.0",
@@ -103,8 +102,8 @@
103
102
  },
104
103
  "dependencies": {
105
104
  "@babel/runtime": "^7.28.4",
106
- "@floating-ui/react": "^0.27.17",
107
- "@headlessui/react": "^2.2.9",
105
+ "@floating-ui/react": "^0.27.16",
106
+ "@headlessui/react": "^1.7.19",
108
107
  "@popperjs/core": "^2.11.8",
109
108
  "@react-aria/focus": "^3.21.3",
110
109
  "@react-aria/overlays": "^3.31.0",
@@ -120,7 +119,7 @@
120
119
  "merge-props": "^6.0.0",
121
120
  "react-popper": "^2.3.0",
122
121
  "react-transition-group": "^4.4.5",
123
- "virtua": "^0.48.5"
122
+ "virtua": "^0.48.3"
124
123
  },
125
124
  "publishConfig": {
126
125
  "access": "public",
package/src/index.ts CHANGED
@@ -35,7 +35,7 @@ export type { HeaderProps } from './header';
35
35
  export type { EmphasisProps } from './emphasis';
36
36
  export type { FieldProps } from './field/Field';
37
37
  export type { InfoProps } from './info';
38
- export type { InlinePromptProps } from './prompt';
38
+ export type { InlinePromptProps, ActionPromptProps } from './prompt';
39
39
  export type { InputWithDisplayFormatProps } from './inputWithDisplayFormat';
40
40
  export type { InputProps } from './inputs/Input';
41
41
  export type { InputGroupProps } from './inputs/InputGroup';
@@ -171,7 +171,7 @@ export { default as Header } from './header';
171
171
  export { default as Image } from './image';
172
172
  export { default as Info } from './info';
173
173
  export { default as InlineAlert } from './inlineAlert';
174
- export { InlinePrompt } from './prompt';
174
+ export { InlinePrompt, ActionPrompt } from './prompt';
175
175
  export { default as InputWithDisplayFormat } from './inputWithDisplayFormat';
176
176
  export { Input } from './inputs/Input';
177
177
  export { InputGroup } from './inputs/InputGroup';
@@ -1,15 +1,19 @@
1
1
  import { screen, waitFor, within } from '@testing-library/react';
2
2
  import { userEvent } from '@testing-library/user-event';
3
- import { mockAnimationsApi } from 'jsdom-testing-mocks';
4
3
 
5
- import { render, mockMatchMedia, mockResizeObserver } from '../test-utils';
4
+ import {
5
+ render,
6
+ mockMatchMedia,
7
+ mockResizeObserver,
8
+ mockRequestAnimationFrame,
9
+ } from '../test-utils';
6
10
 
7
11
  import { SelectInput, type SelectInputOptionItem, type SelectInputProps } from './SelectInput';
8
12
  import { Field } from '../field/Field';
9
13
 
10
14
  mockMatchMedia();
11
15
  mockResizeObserver();
12
- mockAnimationsApi();
16
+ mockRequestAnimationFrame();
13
17
 
14
18
  describe('SelectInput', () => {
15
19
  it('renders placeholder', () => {
@@ -63,81 +67,6 @@ describe('SelectInput', () => {
63
67
  expect(footer).toHaveTextContent(/‘ur’$/);
64
68
  });
65
69
 
66
- it('allows navigating the listbox with cursors', async () => {
67
- render(
68
- <SelectInput
69
- items={[
70
- { type: 'option', value: 'GBP' },
71
- { type: 'option', value: 'EUR' },
72
- { type: 'option', value: 'USD' },
73
- ]}
74
- renderFooter={({ queryNormalized: normalizedQuery }) => (
75
- <button type="button">Footer button</button>
76
- )}
77
- filterable
78
- />,
79
- );
80
-
81
- // opened the dropbox, with search focused
82
- await userEvent.tab();
83
- await userEvent.keyboard(' ');
84
- expect(screen.getByRole('combobox')).toHaveFocus();
85
-
86
- // search still focused but listbox can be navigated via keyboard
87
- await userEvent.keyboard('{ArrowDown}');
88
- expect(screen.getByRole('combobox')).toHaveFocus();
89
- expect(screen.getByRole('option', { name: 'EUR' })).toHaveClass(
90
- 'np-select-input-option-container--active',
91
- );
92
-
93
- // tab moves focus to listbox
94
- await userEvent.tab();
95
- expect(screen.getByRole('listbox')).toHaveFocus();
96
- expect(screen.getByRole('combobox')).not.toHaveFocus();
97
-
98
- // arrows still navigate within listbox
99
- await userEvent.keyboard('{ArrowDown}');
100
- expect(screen.getByRole('option', { name: 'USD' })).toHaveClass(
101
- 'np-select-input-option-container--active',
102
- );
103
-
104
- // tab moves focus to footer but highlighted option is retained
105
- await userEvent.tab();
106
- expect(screen.getByRole('listbox')).not.toHaveFocus();
107
- expect(screen.getByRole('combobox')).not.toHaveFocus();
108
- expect(screen.getByText('Footer button')).toHaveFocus();
109
- expect(screen.getByRole('option', { name: 'USD' })).toHaveClass(
110
- 'np-select-input-option-container--active',
111
- );
112
-
113
- // shift+tab moves focus back to listbox
114
- await userEvent.tab({ shift: true });
115
- expect(screen.getByRole('listbox')).toHaveFocus();
116
- expect(screen.getByRole('combobox')).not.toHaveFocus();
117
- expect(screen.getByText('Footer button')).not.toHaveFocus();
118
-
119
- // previously highlighted option is still active within listbox
120
- expect(screen.getByRole('option', { name: 'USD' })).toHaveClass(
121
- 'np-select-input-option-container--active',
122
- );
123
-
124
- // arrows continue to navigate within listbox
125
- await userEvent.keyboard('{ArrowUp}');
126
- expect(screen.getByRole('option', { name: 'EUR' })).toHaveClass(
127
- 'np-select-input-option-container--active',
128
- );
129
-
130
- // shift+tab moves focus back to search input
131
- await userEvent.tab({ shift: true });
132
- expect(screen.getByRole('combobox')).toHaveFocus();
133
-
134
- // arrows continue to navigate within listbox
135
- await userEvent.keyboard('{ArrowUp}');
136
- expect(screen.getByRole('option', { name: 'GBP' })).toHaveClass(
137
- 'np-select-input-option-container--active',
138
- );
139
- });
140
-
141
70
  it('shows item selected via mouse', async () => {
142
71
  const handleClose = jest.fn();
143
72
 
@@ -1,9 +1,4 @@
1
- import {
2
- Listbox as ListboxBase,
3
- ListboxButton,
4
- ListboxOption,
5
- ListboxOptions,
6
- } from '@headlessui/react';
1
+ import { Listbox as ListboxBase } from '@headlessui/react';
7
2
  import { Check, ChevronDown, Cross, CrossCircle } from '@transferwise/icons';
8
3
  import { clsx } from 'clsx';
9
4
  import mergeProps from 'merge-props';
@@ -432,8 +427,8 @@ export function SelectInput<T = string, M extends boolean = false>({
432
427
  <ListboxBase
433
428
  name={name}
434
429
  multiple={multiple}
435
- defaultValue={defaultValue as M extends true ? T[] : T}
436
- value={controlledValue as M extends true ? T[] : T}
430
+ defaultValue={defaultValue}
431
+ value={controlledValue}
437
432
  by={compareValues}
438
433
  disabled={disabled}
439
434
  onChange={
@@ -581,7 +576,7 @@ export function SelectInputTriggerButton<T extends SelectInputTriggerButtonEleme
581
576
  );
582
577
 
583
578
  return (
584
- <ListboxButton
579
+ <ListboxBase.Button
585
580
  ref={ref}
586
581
  as={PolymorphicWithOverrides}
587
582
  role="combobox"
@@ -622,13 +617,8 @@ const SelectInputOptionsContainer = forwardRef(function SelectInputOptionsContai
622
617
  return;
623
618
  }
624
619
 
625
- // Required to make ListBox focusable
626
- if (event.key === 'Tab') {
627
- return;
628
- }
629
-
630
- // Prevent absorbing Escape early
631
- if (event.key === 'Escape') {
620
+ // Prevent absorbing actions early
621
+ if (event.key === 'Escape' || event.key === 'Tab') {
632
622
  onKeyDown?.({
633
623
  ...event,
634
624
  preventDefault: () => {},
@@ -827,8 +817,7 @@ function SelectInputOptions<T = string>({
827
817
  };
828
818
 
829
819
  return (
830
- <ListboxOptions
831
- modal
820
+ <ListboxBase.Options
832
821
  as={SelectInputOptionsContainer}
833
822
  static
834
823
  className="np-select-input-options-container"
@@ -985,7 +974,7 @@ function SelectInputOptions<T = string>({
985
974
  </footer>
986
975
  ) : null}
987
976
  </section>
988
- </ListboxOptions>
977
+ </ListboxBase.Options>
989
978
  );
990
979
  }
991
980
 
@@ -1094,7 +1083,7 @@ function SelectInputOption<T = string>({ value, disabled, children }: SelectInpu
1094
1083
  const itemsCount = useContext(SelectInputItemsCountContext);
1095
1084
  const itemPosition = useContext(SelectInputItemPositionContext);
1096
1085
  return (
1097
- <ListboxOption
1086
+ <ListboxBase.Option
1098
1087
  as="div"
1099
1088
  value={value}
1100
1089
  aria-setsize={itemsCount}
@@ -1120,7 +1109,7 @@ function SelectInputOption<T = string>({ value, disabled, children }: SelectInpu
1120
1109
  />
1121
1110
  </>
1122
1111
  )}
1123
- </ListboxOption>
1112
+ </ListboxBase.Option>
1124
1113
  );
1125
1114
  }
1126
1115
 
@@ -6,7 +6,7 @@ import {
6
6
  useInteractions,
7
7
  useRole,
8
8
  } from '@floating-ui/react';
9
- import { Transition, TransitionChild } from '@headlessui/react';
9
+ import { Transition } from '@headlessui/react';
10
10
  import { FocusScope } from '@react-aria/focus';
11
11
  import { ThemeProvider, useTheme } from '@wise/components-theming';
12
12
  import { clsx } from 'clsx';
@@ -73,7 +73,6 @@ export function BottomSheet({
73
73
  <FloatingPortal>
74
74
  <ThemeProvider theme="personal" screenMode={theme === 'personal' ? screenMode : 'light'}>
75
75
  <Transition
76
- as="div"
77
76
  show={open}
78
77
  className="np-bottom-sheet-v2-container"
79
78
  beforeEnter={() => {
@@ -81,8 +80,7 @@ export function BottomSheet({
81
80
  }}
82
81
  afterLeave={onCloseEnd}
83
82
  >
84
- <TransitionChild
85
- as="div"
83
+ <Transition.Child
86
84
  className="np-bottom-sheet-v2-backdrop"
87
85
  enterFrom="np-bottom-sheet-v2-backdrop--closed"
88
86
  leaveTo="np-bottom-sheet-v2-backdrop--closed"
@@ -94,9 +92,8 @@ export function BottomSheet({
94
92
  <Fragment
95
93
  key={floatingKey} // Force inner state invalidation on open
96
94
  >
97
- <TransitionChild
95
+ <Transition.Child
98
96
  ref={refs.setFloating}
99
- as="div"
100
97
  className="np-bottom-sheet-v2-content"
101
98
  enterFrom="np-bottom-sheet-v2-content--closed"
102
99
  leaveTo="np-bottom-sheet-v2-content--closed"
@@ -124,7 +121,7 @@ export function BottomSheet({
124
121
  {children}
125
122
  </div>
126
123
  </div>
127
- </TransitionChild>
124
+ </Transition.Child>
128
125
  </Fragment>
129
126
  </FloatingFocusManager>
130
127
  </FocusScope>
@@ -51,7 +51,6 @@ export function Popover({
51
51
  onCloseEnd,
52
52
  }: PopoverProps) {
53
53
  const { refs, floatingStyles, context } = useFloating<Element>({
54
- strategy: 'fixed',
55
54
  placement,
56
55
  middleware: [
57
56
  offset(8),
@@ -93,7 +92,6 @@ export function Popover({
93
92
  <FloatingPortal>
94
93
  <ThemeProvider theme="personal" screenMode={theme === 'personal' ? screenMode : 'light'}>
95
94
  <Transition
96
- as="div"
97
95
  show={open}
98
96
  leave="transition-opacity"
99
97
  leaveTo="opacity-0"
package/src/main.css CHANGED
@@ -5339,6 +5339,8 @@ html:not([dir="rtl"]) .np-navigation-option {
5339
5339
  border-radius: 10px;
5340
5340
  border-radius: var(--radius-small);
5341
5341
  display: flex;
5342
+ gap: 16px;
5343
+ gap: var(--Prompt-gap, var(--size-16));
5342
5344
  word-wrap: break-word;
5343
5345
  padding: 8px;
5344
5346
  padding: var(--Prompt-padding, var(--padding-x-small));
@@ -5354,6 +5356,9 @@ html:not([dir="rtl"]) .np-navigation-option {
5354
5356
  grid-template-columns: auto 1fr;
5355
5357
  width: 100%;
5356
5358
  }
5359
+ .wds-prompt__content-wrapper--with-dismiss {
5360
+ grid-template-columns: auto 1fr auto;
5361
+ }
5357
5362
  .wds-prompt__media-wrapper {
5358
5363
  align-self: flex-start;
5359
5364
  padding-top: calc(4px - 1px);
@@ -5369,12 +5374,16 @@ html:not([dir="rtl"]) .np-navigation-option {
5369
5374
  gap: 8px;
5370
5375
  gap: var(--Prompt-actions-gap, var(--size-8));
5371
5376
  grid-column-start: 2;
5377
+ grid-column-end: 3;
5372
5378
  }
5373
- @media (max-width: 991px) {
5379
+ @media (max-width: 767px) {
5374
5380
  .wds-prompt__actions-wrapper {
5375
5381
  grid-column: span 2;
5376
5382
  width: 100%;
5377
5383
  }
5384
+ .wds-prompt__content-wrapper--with-dismiss .wds-prompt__actions-wrapper {
5385
+ grid-column: span 3;
5386
+ }
5378
5387
  }
5379
5388
  .wds-inline-prompt {
5380
5389
  --Prompt-gap: calc(var(--size-12) / 2);
@@ -7423,3 +7432,23 @@ html:not([dir="rtl"]) .np-navigation-option {
7423
7432
  .np-list-item__action {
7424
7433
  flex-shrink: 0;
7425
7434
  }
7435
+ .wds-action-prompt {
7436
+ --Prompt-padding: var(--size-16);
7437
+ --Prompt-actions-gap: var(--size-8);
7438
+ --Prompt-gap: var(--size-10) var(--size-16);
7439
+ }
7440
+ .wds-action-prompt--media-image {
7441
+ width: 48px;
7442
+ width: var(--size-48);
7443
+ height: 48px;
7444
+ height: var(--size-48);
7445
+ -o-object-fit: contain;
7446
+ object-fit: contain;
7447
+ }
7448
+ @media (max-width: 767px) {
7449
+ .wds-action-prompt--with-two-actions .wds-prompt__actions-wrapper .wds-Button {
7450
+ flex: 1 1 calc(50% - (var(--Prompt-actions-gap) / 2));
7451
+ min-width: -moz-fit-content;
7452
+ min-width: fit-content;
7453
+ }
7454
+ }
package/src/main.less CHANGED
@@ -86,6 +86,7 @@
86
86
  @import "./progress/Progress.less";
87
87
  @import "./progressBar/ProgressBar.less";
88
88
  @import "./legacylistItem/LegacyListItem.less";
89
+ @import "./prompt/ActionPrompt/ActionPrompt.less";
89
90
 
90
91
  // List all less files in src in alphabetical order: find -s src -type f -name '*.less' ! -name 'main.less'
91
92
  // Make sure you are not referencing main.less itself in this file!
@@ -1,21 +1,20 @@
1
- import { mockAnimationsApi } from 'jsdom-testing-mocks';
2
1
  import {
3
2
  mockMatchMedia,
3
+ mockRequestAnimationFrame,
4
4
  mockResizeObserver,
5
5
  render,
6
6
  screen,
7
7
  userEvent,
8
- waitFor,
9
- within,
10
8
  } from '../test-utils';
11
9
 
12
10
  import { MoneyInput, CurrencyItem, CurrencyOptionItem, Field } from '..';
13
11
  import { MoneyInputPropsWithInputAttributes } from './MoneyInput';
12
+ import { within } from '@testing-library/react';
14
13
  import messages from './MoneyInput.messages';
15
14
 
16
15
  mockMatchMedia();
17
16
  mockResizeObserver();
18
- mockAnimationsApi();
17
+ mockRequestAnimationFrame();
19
18
 
20
19
  describe('Money Input', () => {
21
20
  const popularCurrencies: CurrencyOptionItem[] = [
@@ -115,30 +114,12 @@ describe('Money Input', () => {
115
114
  it('calls onCurrencyChange when the user selects a different currency', async () => {
116
115
  customRender();
117
116
  await openDropdown();
118
- await userEvent.keyboard('eur');
119
- await waitFor(() => {
120
- expect(screen.getAllByRole('option')).toHaveLength(1);
121
- });
122
- await userEvent.keyboard('{Enter}');
123
-
124
- await waitFor(() => {
125
- expect(initialProps.onCurrencyChange).toHaveBeenCalledTimes(1);
126
- });
117
+ await userEvent.keyboard('eur{Enter}');
118
+ expect(initialProps.onCurrencyChange).toHaveBeenCalledTimes(1);
127
119
  expect(initialProps.onCurrencyChange).toHaveBeenCalledWith(popularCurrencies[0]);
128
-
129
- await waitFor(() => {
130
- expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
131
- });
132
120
  await openDropdown();
133
- await userEvent.keyboard('gbp');
134
- await waitFor(() => {
135
- expect(screen.getAllByRole('option')).toHaveLength(1);
136
- });
137
- await userEvent.keyboard('{Enter}');
138
-
139
- await waitFor(() => {
140
- expect(initialProps.onCurrencyChange).toHaveBeenCalledTimes(2);
141
- });
121
+ await userEvent.keyboard('gbp{Enter}');
122
+ expect(initialProps.onCurrencyChange).toHaveBeenCalledTimes(2);
142
123
  expect(initialProps.onCurrencyChange).toHaveBeenCalledWith(popularCurrencies[2]);
143
124
  });
144
125
 
@@ -0,0 +1,20 @@
1
+ .wds-action-prompt {
2
+ --Prompt-padding: var(--size-16);
3
+ --Prompt-actions-gap: var(--size-8);
4
+ --Prompt-gap: var(--size-10) var(--size-16);
5
+ }
6
+ .wds-action-prompt--media-image {
7
+ width: 48px;
8
+ width: var(--size-48);
9
+ height: 48px;
10
+ height: var(--size-48);
11
+ -o-object-fit: contain;
12
+ object-fit: contain;
13
+ }
14
+ @media (max-width: 767px) {
15
+ .wds-action-prompt--with-two-actions .wds-prompt__actions-wrapper .wds-Button {
16
+ flex: 1 1 calc(50% - (var(--Prompt-actions-gap) / 2));
17
+ min-width: -moz-fit-content;
18
+ min-width: fit-content;
19
+ }
20
+ }
@@ -0,0 +1,22 @@
1
+ .wds-action-prompt {
2
+ --Prompt-padding: var(--size-16);
3
+ --Prompt-actions-gap: var(--size-8);
4
+ --Prompt-gap: var(--size-10) var(--size-16);
5
+
6
+ &--media-image {
7
+ width: var(--size-48);
8
+ height: var(--size-48);
9
+ object-fit: contain;
10
+ }
11
+
12
+ &--with-two-actions {
13
+ @media (--screen-sm-max) {
14
+ .wds-prompt__actions-wrapper {
15
+ .wds-Button {
16
+ flex: 1 1 calc(50% - (var(--Prompt-actions-gap) / 2));
17
+ min-width: fit-content;
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }