@transferwise/components 0.0.0-experimental-c68416c → 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 +3 -4
  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
@@ -1,6 +1,7 @@
1
1
  .wds-prompt {
2
2
  border-radius: var(--radius-small);
3
3
  display: flex;
4
+ gap: var(--Prompt-gap, var(--size-16));
4
5
  overflow-wrap: break-word;
5
6
  padding: var(--Prompt-padding, var(--padding-x-small));
6
7
  text-align: left;
@@ -11,6 +12,10 @@
11
12
  gap: var(--Prompt-gap, var(--size-16));
12
13
  grid-template-columns: auto 1fr;
13
14
  width: 100%;
15
+
16
+ &--with-dismiss {
17
+ grid-template-columns: auto 1fr auto;
18
+ }
14
19
  }
15
20
 
16
21
  &__media-wrapper {
@@ -28,10 +33,15 @@
28
33
  flex-wrap: wrap;
29
34
  gap: var(--Prompt-actions-gap, var(--size-8));
30
35
  grid-column-start: 2;
36
+ grid-column-end: 3;
31
37
 
32
- @media (--screen-md-max) {
38
+ @media (--screen-sm-max) {
33
39
  grid-column: span 2;
34
40
  width: 100%;
41
+
42
+ .wds-prompt__content-wrapper--with-dismiss & {
43
+ grid-column: span 3;
44
+ }
35
45
  }
36
46
  }
37
47
  }
@@ -0,0 +1,161 @@
1
+ import { mockMatchMedia, render, screen, within } from '../../test-utils';
2
+ import { PrimitivePrompt, PrimitivePromptProps } from './PrimitivePrompt';
3
+ import { userEvent } from '@testing-library/user-event';
4
+
5
+ mockMatchMedia();
6
+
7
+ describe('PrimitivePrompt', () => {
8
+ const defaultProps: PrimitivePromptProps = {
9
+ media: <span data-testid="test-media">Media</span>,
10
+ children: <div>Test content</div>,
11
+ };
12
+
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ });
16
+
17
+ describe('Basic rendering', () => {
18
+ it('renders children content', () => {
19
+ render(<PrimitivePrompt {...defaultProps} />);
20
+ expect(screen.getByText('Test content')).toBeInTheDocument();
21
+ });
22
+
23
+ it('renders media', () => {
24
+ render(<PrimitivePrompt {...defaultProps} />);
25
+ expect(screen.getByTestId('test-media')).toBeInTheDocument();
26
+ });
27
+
28
+ it('renders actions when provided', () => {
29
+ render(
30
+ <PrimitivePrompt
31
+ {...defaultProps}
32
+ actions={<button type="button">Action Button</button>}
33
+ />,
34
+ );
35
+
36
+ expect(screen.getByText('Action Button')).toBeInTheDocument();
37
+ });
38
+
39
+ it('does not render actions wrapper when actions not provided', () => {
40
+ render(<PrimitivePrompt {...defaultProps} data-testid="prompt" />);
41
+ const prompt = screen.getByTestId('prompt');
42
+ expect(within(prompt).queryByRole('button')).not.toBeInTheDocument();
43
+ });
44
+ });
45
+
46
+ describe('Sentiments', () => {
47
+ [
48
+ { sentiment: 'negative' as const, label: 'negative' },
49
+ { sentiment: 'warning' as const, label: 'warning' },
50
+ { sentiment: 'neutral' as const, label: 'neutral' },
51
+ { sentiment: 'success' as const, label: 'success' },
52
+ ].forEach(({ sentiment, label }) => {
53
+ it(`applies correct CSS class for ${label} sentiment`, () => {
54
+ render(<PrimitivePrompt {...defaultProps} sentiment={sentiment} data-testid="prompt" />);
55
+ const promptElement = screen.getByTestId('prompt');
56
+
57
+ expect(promptElement).toHaveClass(`wds-prompt--${label}`);
58
+ });
59
+ });
60
+
61
+ it('defaults to success sentiment', () => {
62
+ render(<PrimitivePrompt {...defaultProps} data-testid="prompt" />);
63
+ expect(screen.getByTestId('prompt')).toHaveClass('wds-prompt--success');
64
+ });
65
+
66
+ it('applies base wds-prompt class', () => {
67
+ render(<PrimitivePrompt {...defaultProps} data-testid="prompt" />);
68
+ expect(screen.getByTestId('prompt')).toHaveClass('wds-prompt');
69
+ });
70
+ });
71
+
72
+ describe('Dismiss functionality', () => {
73
+ it('renders dismiss button when onDismiss is provided', () => {
74
+ const onDismiss = jest.fn();
75
+ render(<PrimitivePrompt {...defaultProps} onDismiss={onDismiss} />);
76
+
77
+ expect(screen.getByLabelText('Close')).toBeInTheDocument();
78
+ });
79
+
80
+ it('calls onDismiss when dismiss button is clicked', async () => {
81
+ const onDismiss = jest.fn();
82
+ const user = userEvent.setup();
83
+ render(<PrimitivePrompt {...defaultProps} onDismiss={onDismiss} />);
84
+
85
+ const dismissButton = screen.getByLabelText('Close');
86
+ await user.click(dismissButton);
87
+
88
+ expect(onDismiss).toHaveBeenCalledTimes(1);
89
+ });
90
+
91
+ it('does not render dismiss button when onDismiss is not provided', () => {
92
+ render(<PrimitivePrompt {...defaultProps} />);
93
+ expect(screen.queryByLabelText('Close')).not.toBeInTheDocument();
94
+ });
95
+
96
+ it('applies with-dismiss class when onDismiss is provided', () => {
97
+ render(<PrimitivePrompt {...defaultProps} data-testid="prompt" onDismiss={() => {}} />);
98
+
99
+ const prompt = screen.getByTestId('prompt');
100
+
101
+ expect(screen.getByLabelText('Close')).toBeInTheDocument();
102
+ expect(prompt).toBeInTheDocument();
103
+ });
104
+
105
+ it('does not apply with-dismiss class when onDismiss is not provided', () => {
106
+ render(<PrimitivePrompt {...defaultProps} data-testid="prompt" />);
107
+
108
+ expect(screen.queryByLabelText('Close')).not.toBeInTheDocument();
109
+ });
110
+ });
111
+
112
+ describe('Custom attributes', () => {
113
+ it('applies custom className', () => {
114
+ render(<PrimitivePrompt {...defaultProps} className="custom-class" data-testid="prompt" />);
115
+ expect(screen.getByTestId('prompt')).toHaveClass('custom-class');
116
+ });
117
+
118
+ it('applies custom id', () => {
119
+ render(<PrimitivePrompt {...defaultProps} id="custom-id" data-testid="prompt" />);
120
+ expect(screen.getByTestId('prompt')).toHaveAttribute('id', 'custom-id');
121
+ });
122
+
123
+ it('applies custom data-testid', () => {
124
+ render(<PrimitivePrompt {...defaultProps} data-testid="custom-test-id" />);
125
+ expect(screen.getByTestId('custom-test-id')).toBeInTheDocument();
126
+ });
127
+
128
+ it('combines custom className with base classes', () => {
129
+ render(
130
+ <PrimitivePrompt
131
+ {...defaultProps}
132
+ className="custom-class"
133
+ sentiment="warning"
134
+ data-testid="prompt"
135
+ />,
136
+ );
137
+
138
+ const prompt = screen.getByTestId('prompt');
139
+
140
+ expect(prompt).toHaveClass('wds-prompt');
141
+ expect(prompt).toHaveClass('wds-prompt--warning');
142
+ expect(prompt).toHaveClass('custom-class');
143
+ });
144
+ });
145
+
146
+ describe('SentimentSurface integration', () => {
147
+ it('uses SentimentSurface for sentiment styling', () => {
148
+ render(<PrimitivePrompt {...defaultProps} sentiment="negative" data-testid="prompt" />);
149
+ const prompt = screen.getByTestId('prompt');
150
+
151
+ expect(prompt).toHaveClass('wds-sentiment-surface');
152
+ });
153
+
154
+ it('passes sentiment to SentimentSurface', () => {
155
+ render(<PrimitivePrompt {...defaultProps} sentiment="warning" data-testid="prompt" />);
156
+ const prompt = screen.getByTestId('prompt');
157
+
158
+ expect(prompt).toHaveClass('wds-prompt--warning');
159
+ });
160
+ });
161
+ });
@@ -50,21 +50,25 @@ export const PrimitivePrompt = ({
50
50
  className={clsx('wds-prompt', `wds-prompt--${sentiment}`, className)}
51
51
  {...restProps}
52
52
  >
53
- <div className="wds-prompt__content-wrapper">
53
+ <div
54
+ className={clsx('wds-prompt__content-wrapper', {
55
+ 'wds-prompt__content-wrapper--with-dismiss': !!onDismiss,
56
+ })}
57
+ >
54
58
  <div className={clsx('wds-prompt__media-wrapper')}>{media}</div>
55
59
  {children}
60
+ {onDismiss && (
61
+ <IconButton
62
+ size={24}
63
+ priority="secondary"
64
+ aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}
65
+ onClick={onDismiss}
66
+ >
67
+ <Cross />
68
+ </IconButton>
69
+ )}
56
70
  {actions && <div className="wds-prompt__actions-wrapper">{actions}</div>}
57
71
  </div>
58
- {onDismiss && (
59
- <IconButton
60
- size={24}
61
- priority="secondary"
62
- aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}
63
- onClick={onDismiss}
64
- >
65
- <Cross />
66
- </IconButton>
67
- )}
68
72
  </SentimentSurface>
69
73
  );
70
74
  };
@@ -4,3 +4,6 @@
4
4
  // InlinePrompt
5
5
  export type { InlinePromptProps } from './InlinePrompt';
6
6
  export { InlinePrompt } from './InlinePrompt';
7
+
8
+ export type { ActionPromptProps } from './ActionPrompt';
9
+ export { ActionPrompt } from './ActionPrompt';
package/src/ssr.spec.tsx CHANGED
@@ -91,6 +91,7 @@ describe('Server side rendering', () => {
91
91
 
92
92
  // stick all possible properties we might need to render all components in here
93
93
  const allProps: Record<string, unknown> = {
94
+ actionPrimary: { label: 'Action', onClick: jest.fn(), href: '#' },
94
95
  currencies: [],
95
96
  currencySelector: { options: [] },
96
97
  steps: [],