@transferwise/components 0.0.0-experimental-5a0aa47 → 0.0.0-experimental-0b80b83
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.
- package/build/i18n/ja.json +13 -13
- package/build/index.js +304 -147
- package/build/index.js.map +1 -1
- package/build/index.mjs +306 -149
- package/build/index.mjs.map +1 -1
- package/build/types/alert/Alert.d.ts +58 -47
- package/build/types/alert/Alert.d.ts.map +1 -1
- package/build/types/alert/index.d.ts +1 -2
- package/build/types/alert/index.d.ts.map +1 -1
- package/build/types/alert/withArrow/alertArrowPositions.d.ts +9 -0
- package/build/types/alert/withArrow/alertArrowPositions.d.ts.map +1 -0
- package/build/types/alert/withArrow/index.d.ts +3 -0
- package/build/types/alert/withArrow/index.d.ts.map +1 -0
- package/build/types/alert/withArrow/withArrow.d.ts +11 -0
- package/build/types/alert/withArrow/withArrow.d.ts.map +1 -0
- package/build/types/common/propsValues/sentiment.d.ts +1 -0
- package/build/types/common/propsValues/sentiment.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/inlineAlert/InlineAlert.d.ts +4 -2
- package/build/types/inlineAlert/InlineAlert.d.ts.map +1 -1
- package/build/types/provider/Provider.d.ts +1 -1
- package/build/types/provider/Provider.d.ts.map +1 -1
- package/build/types/statusIcon/StatusIcon.d.ts +1 -1
- package/build/types/statusIcon/StatusIcon.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/alert/Alert.js +196 -0
- package/src/alert/{Alert.spec.tsx → Alert.spec.js} +40 -43
- package/src/alert/Alert.story.tsx +2 -1
- package/src/alert/index.js +1 -0
- package/src/alert/withArrow/alertArrowPositions.ts +9 -0
- package/src/alert/withArrow/index.js +2 -0
- package/src/alert/withArrow/withArrow.js +50 -0
- package/src/alert/withArrow/withArrow.spec.js +51 -0
- package/src/common/propsValues/sentiment.ts +10 -0
- package/src/i18n/ja.json +13 -13
- package/src/index.ts +1 -1
- package/src/inlineAlert/InlineAlert.spec.tsx +7 -0
- package/src/inlineAlert/InlineAlert.tsx +47 -19
- package/src/provider/Provider.tsx +2 -1
- package/src/statusIcon/StatusIcon.tsx +14 -14
- package/src/alert/Alert.tsx +0 -223
- package/src/alert/index.ts +0 -2
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
InfoCircle,
|
|
4
|
+
CheckCircle,
|
|
5
|
+
AlertCircle,
|
|
6
|
+
Warning as AlertIcon,
|
|
7
|
+
HappyEmoji,
|
|
8
|
+
} from '@transferwise/icons';
|
|
3
9
|
import { ThemeProvider } from '@wise/components-theming';
|
|
4
10
|
import React from 'react';
|
|
5
11
|
|
|
6
12
|
import { Sentiment, Size, Theme, Variant } from '../common';
|
|
7
13
|
import { render, cleanup, screen, userEvent, fireEvent } from '../test-utils';
|
|
8
14
|
|
|
9
|
-
import Alert
|
|
15
|
+
import Alert from './Alert';
|
|
16
|
+
import { AlertArrowPosition } from './withArrow';
|
|
10
17
|
|
|
11
18
|
jest.mock('react', () => {
|
|
12
|
-
const originReact = jest.requireActual
|
|
19
|
+
const originReact = jest.requireActual('react');
|
|
13
20
|
const mUseReference = jest.fn();
|
|
14
21
|
return {
|
|
15
22
|
...originReact,
|
|
@@ -18,18 +25,20 @@ jest.mock('react', () => {
|
|
|
18
25
|
});
|
|
19
26
|
|
|
20
27
|
describe('Alert', () => {
|
|
21
|
-
let component
|
|
22
|
-
let container
|
|
23
|
-
let alert
|
|
24
|
-
let closeButton
|
|
25
|
-
let action
|
|
28
|
+
let component;
|
|
29
|
+
let container;
|
|
30
|
+
let alert;
|
|
31
|
+
let closeButton;
|
|
32
|
+
let action;
|
|
26
33
|
|
|
27
|
-
const
|
|
34
|
+
const renderIcon = (Icon) => render(<Icon size={24} />).container.innerHTML;
|
|
35
|
+
|
|
36
|
+
const classForType = (type) => `alert-${type}`;
|
|
28
37
|
|
|
29
38
|
const message = 'Your card is on its way.';
|
|
30
39
|
|
|
31
40
|
const origWarn = console.warn;
|
|
32
|
-
let mockedWarn
|
|
41
|
+
let mockedWarn;
|
|
33
42
|
|
|
34
43
|
beforeAll(() => {
|
|
35
44
|
mockedWarn = jest.fn();
|
|
@@ -47,11 +56,11 @@ describe('Alert', () => {
|
|
|
47
56
|
|
|
48
57
|
describe('defaults', () => {
|
|
49
58
|
beforeEach(() => {
|
|
50
|
-
container = render(
|
|
59
|
+
({ container } = render(
|
|
51
60
|
<ThemeProvider theme={Theme.LIGHT}>
|
|
52
61
|
<Alert message={message} />
|
|
53
62
|
</ThemeProvider>,
|
|
54
|
-
)
|
|
63
|
+
));
|
|
55
64
|
component = screen.getByTestId('alert');
|
|
56
65
|
});
|
|
57
66
|
|
|
@@ -61,7 +70,7 @@ describe('Alert', () => {
|
|
|
61
70
|
|
|
62
71
|
it('will be of type neutral', () => {
|
|
63
72
|
expect(component).toHaveClass(classForType(Sentiment.NEUTRAL));
|
|
64
|
-
expect(screen.getByTestId('info-icon')).toBeInTheDocument();
|
|
73
|
+
expect(screen.getByTestId('info-circle-icon')).toBeInTheDocument();
|
|
65
74
|
});
|
|
66
75
|
|
|
67
76
|
it('is not dismissible', () => {
|
|
@@ -81,9 +90,7 @@ describe('Alert', () => {
|
|
|
81
90
|
expect(component).toHaveClass('arrow');
|
|
82
91
|
expect(component).toHaveClass('arrow-bottom');
|
|
83
92
|
expect(mockedWarn).toHaveBeenCalledWith(
|
|
84
|
-
expect.stringContaining(
|
|
85
|
-
"Alert component doesn't support 'arrow' anymore, use 'InlineAlert' instead.",
|
|
86
|
-
),
|
|
93
|
+
expect.stringContaining('Alert has deprecated the use of arrow.'),
|
|
87
94
|
);
|
|
88
95
|
});
|
|
89
96
|
|
|
@@ -92,9 +99,7 @@ describe('Alert', () => {
|
|
|
92
99
|
|
|
93
100
|
expect(screen.getByText(message)).toBeInTheDocument();
|
|
94
101
|
expect(mockedWarn).toHaveBeenCalledWith(
|
|
95
|
-
expect.stringContaining(
|
|
96
|
-
"Alert component doesn't support 'children' anymore, use 'message' instead.",
|
|
97
|
-
),
|
|
102
|
+
expect.stringContaining('Alert has deprecated the use of children.'),
|
|
98
103
|
);
|
|
99
104
|
});
|
|
100
105
|
|
|
@@ -103,9 +108,7 @@ describe('Alert', () => {
|
|
|
103
108
|
|
|
104
109
|
expect(container.querySelector('button')).not.toBeInTheDocument();
|
|
105
110
|
expect(mockedWarn).toHaveBeenCalledWith(
|
|
106
|
-
expect.stringContaining(
|
|
107
|
-
"Alert component doesn't support 'dismissible' anymore, use 'onDismiss' instead.",
|
|
108
|
-
),
|
|
111
|
+
expect.stringContaining('Alert has deprecated the use of dismissible.'),
|
|
109
112
|
);
|
|
110
113
|
});
|
|
111
114
|
|
|
@@ -115,9 +118,7 @@ describe('Alert', () => {
|
|
|
115
118
|
|
|
116
119
|
expect(small.innerHTML).toStrictEqual(large.innerHTML);
|
|
117
120
|
expect(mockedWarn).toHaveBeenCalledWith(
|
|
118
|
-
expect.stringContaining(
|
|
119
|
-
"Alert component doesn't support 'size' anymore, please remove that prop.",
|
|
120
|
-
),
|
|
121
|
+
expect.stringContaining('Alert no longer supports any possible variations in size'),
|
|
121
122
|
);
|
|
122
123
|
});
|
|
123
124
|
|
|
@@ -127,9 +128,9 @@ describe('Alert', () => {
|
|
|
127
128
|
const success = screen.getByTestId('alert');
|
|
128
129
|
|
|
129
130
|
expect(success).toHaveClass(classForType(Sentiment.POSITIVE));
|
|
130
|
-
expect(screen.getByTestId('check-icon')).toBeInTheDocument();
|
|
131
|
+
expect(screen.getByTestId('check-circle-icon')).toBeInTheDocument();
|
|
131
132
|
expect(mockedWarn).toHaveBeenCalledWith(
|
|
132
|
-
|
|
133
|
+
'Alert has deprecated the success value for the `type` prop. Please update to Sentiment.POSITIVE.',
|
|
133
134
|
);
|
|
134
135
|
});
|
|
135
136
|
|
|
@@ -139,9 +140,9 @@ describe('Alert', () => {
|
|
|
139
140
|
const info = screen.getByTestId('alert');
|
|
140
141
|
|
|
141
142
|
expect(info).toHaveClass(classForType(Sentiment.NEUTRAL));
|
|
142
|
-
expect(screen.getByTestId('info-icon')).toBeInTheDocument();
|
|
143
|
+
expect(screen.getByTestId('info-circle-icon')).toBeInTheDocument();
|
|
143
144
|
expect(mockedWarn).toHaveBeenCalledWith(
|
|
144
|
-
|
|
145
|
+
'Alert has deprecated the info value for the `type` prop. Please update to Sentiment.NEUTRAL.',
|
|
145
146
|
);
|
|
146
147
|
});
|
|
147
148
|
});
|
|
@@ -152,11 +153,9 @@ describe('Alert', () => {
|
|
|
152
153
|
const error = screen.getByTestId('alert');
|
|
153
154
|
|
|
154
155
|
expect(error).toHaveClass(classForType(Sentiment.NEGATIVE));
|
|
155
|
-
expect(screen.getByTestId('cross-icon')).toBeInTheDocument();
|
|
156
|
+
expect(screen.getByTestId('cross-circle-icon')).toBeInTheDocument();
|
|
156
157
|
expect(mockedWarn).toHaveBeenCalledWith(
|
|
157
|
-
expect.stringContaining(
|
|
158
|
-
"Alert component has deprecated 'error' value for the 'type' prop. Please use 'negative' instead.",
|
|
159
|
-
),
|
|
158
|
+
expect.stringContaining('Alert has deprecated the error value for the `type` prop.'),
|
|
160
159
|
);
|
|
161
160
|
});
|
|
162
161
|
|
|
@@ -168,7 +167,7 @@ describe('Alert', () => {
|
|
|
168
167
|
};
|
|
169
168
|
render(<Alert action={action} message={message} />);
|
|
170
169
|
|
|
171
|
-
const element = screen.getByText(action.text
|
|
170
|
+
const element = screen.getByText(action.text);
|
|
172
171
|
|
|
173
172
|
expect(element).toHaveAttribute('href', action.href);
|
|
174
173
|
expect(element).not.toHaveAttribute('aria-label');
|
|
@@ -184,7 +183,7 @@ describe('Alert', () => {
|
|
|
184
183
|
};
|
|
185
184
|
render(<Alert action={action} message={message} />);
|
|
186
185
|
|
|
187
|
-
const element = screen.getByText(action.text
|
|
186
|
+
const element = screen.getByText(action.text);
|
|
188
187
|
|
|
189
188
|
expect(element).toHaveAttribute('aria-label', action['aria-label']);
|
|
190
189
|
expect(element).toHaveAttribute('target', action.target);
|
|
@@ -246,7 +245,7 @@ describe('Alert', () => {
|
|
|
246
245
|
});
|
|
247
246
|
|
|
248
247
|
describe('types', () => {
|
|
249
|
-
const getComponentWithType = (type
|
|
248
|
+
const getComponentWithType = (type) => {
|
|
250
249
|
render(<Alert type={type} message={message} />);
|
|
251
250
|
return screen.getByTestId('alert');
|
|
252
251
|
};
|
|
@@ -255,28 +254,28 @@ describe('Alert', () => {
|
|
|
255
254
|
component = getComponentWithType(Sentiment.NEUTRAL);
|
|
256
255
|
|
|
257
256
|
expect(component).toHaveClass(classForType(Sentiment.NEUTRAL));
|
|
258
|
-
expect(screen.getByTestId('info-icon')).toBeInTheDocument();
|
|
257
|
+
expect(screen.getByTestId('info-circle-icon')).toBeInTheDocument();
|
|
259
258
|
});
|
|
260
259
|
|
|
261
260
|
it('renders positive', () => {
|
|
262
261
|
component = getComponentWithType(Sentiment.POSITIVE);
|
|
263
262
|
|
|
264
263
|
expect(component).toHaveClass(classForType(Sentiment.POSITIVE));
|
|
265
|
-
expect(screen.getByTestId('check-icon')).toBeInTheDocument();
|
|
264
|
+
expect(screen.getByTestId('check-circle-icon')).toBeInTheDocument();
|
|
266
265
|
});
|
|
267
266
|
|
|
268
267
|
it('renders negative', () => {
|
|
269
268
|
component = getComponentWithType(Sentiment.NEGATIVE);
|
|
270
269
|
|
|
271
270
|
expect(component).toHaveClass(classForType(Sentiment.NEGATIVE));
|
|
272
|
-
expect(screen.getByTestId('cross-icon')).toBeInTheDocument();
|
|
271
|
+
expect(screen.getByTestId('cross-circle-icon')).toBeInTheDocument();
|
|
273
272
|
});
|
|
274
273
|
|
|
275
274
|
it('renders warning', () => {
|
|
276
275
|
component = getComponentWithType(Sentiment.WARNING);
|
|
277
276
|
|
|
278
277
|
expect(component).toHaveClass(classForType(Sentiment.WARNING));
|
|
279
|
-
expect(screen.getByTestId('
|
|
278
|
+
expect(screen.getByTestId('warning-icon')).toBeInTheDocument();
|
|
280
279
|
});
|
|
281
280
|
|
|
282
281
|
it('renders error alerts with aria-role alert', () => {
|
|
@@ -293,11 +292,9 @@ describe('Alert', () => {
|
|
|
293
292
|
const { location } = window;
|
|
294
293
|
|
|
295
294
|
beforeAll(() => {
|
|
296
|
-
jest.spyOn(window, 'open').mockImplementation();
|
|
297
|
-
// @ts-expect-error value gets set right after its deletion
|
|
298
295
|
delete window.location;
|
|
296
|
+
jest.spyOn(window, 'open').mockImplementation();
|
|
299
297
|
window.location = {
|
|
300
|
-
...window.location,
|
|
301
298
|
assign: jest.fn(),
|
|
302
299
|
};
|
|
303
300
|
});
|
|
@@ -4,7 +4,8 @@ import { ClockBorderless } from '@transferwise/icons';
|
|
|
4
4
|
|
|
5
5
|
import { Sentiment } from '../common';
|
|
6
6
|
|
|
7
|
-
import Alert
|
|
7
|
+
import Alert from './Alert';
|
|
8
|
+
import { AlertArrowPosition } from './withArrow';
|
|
8
9
|
|
|
9
10
|
export default {
|
|
10
11
|
component: Alert,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Alert';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
|
|
2
|
+
export enum ArrowPosition {
|
|
3
|
+
TOP_LEFT = 'up-left',
|
|
4
|
+
TOP = 'up-center',
|
|
5
|
+
TOP_RIGHT = 'up-right',
|
|
6
|
+
BOTTOM_LEFT = 'down-left',
|
|
7
|
+
BOTTOM = 'down-center',
|
|
8
|
+
BOTTOM_RIGHT = 'down-right',
|
|
9
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import { ArrowPosition } from './alertArrowPositions';
|
|
5
|
+
|
|
6
|
+
function withArrow(Alert, arrow) {
|
|
7
|
+
const AlertWithArrow = (props) => (
|
|
8
|
+
<Alert
|
|
9
|
+
{...props}
|
|
10
|
+
className={classNames(props.className, arrowClasses(arrow))}
|
|
11
|
+
arrow={undefined}
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
AlertWithArrow.propTypes = {
|
|
16
|
+
className: PropTypes.string,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
AlertWithArrow.defaultProps = {
|
|
20
|
+
className: undefined,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return AlertWithArrow;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function arrowClasses(arrow) {
|
|
27
|
+
if (arrow) {
|
|
28
|
+
const classes = ['arrow'];
|
|
29
|
+
const { BOTTOM, BOTTOM_LEFT, BOTTOM_RIGHT, TOP, TOP_RIGHT, TOP_LEFT } = ArrowPosition;
|
|
30
|
+
|
|
31
|
+
switch (arrow) {
|
|
32
|
+
case BOTTOM:
|
|
33
|
+
return classes.concat('arrow-bottom', 'arrow-center');
|
|
34
|
+
case BOTTOM_LEFT:
|
|
35
|
+
return classes.concat('arrow-bottom', 'arrow-left');
|
|
36
|
+
case BOTTOM_RIGHT:
|
|
37
|
+
return classes.concat('arrow-bottom', 'arrow-right');
|
|
38
|
+
case TOP:
|
|
39
|
+
return classes.concat('arrow-center');
|
|
40
|
+
case TOP_RIGHT:
|
|
41
|
+
return classes.concat('arrow-right');
|
|
42
|
+
case TOP_LEFT:
|
|
43
|
+
default:
|
|
44
|
+
return classes;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default withArrow;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { render, screen } from '../../test-utils';
|
|
2
|
+
import Alert from '../Alert';
|
|
3
|
+
|
|
4
|
+
import { ArrowPosition } from './alertArrowPositions';
|
|
5
|
+
import withArrow from './withArrow';
|
|
6
|
+
|
|
7
|
+
describe('withArrow', () => {
|
|
8
|
+
const message = 'I hope you have a nice day today';
|
|
9
|
+
|
|
10
|
+
describe('default props', () => {
|
|
11
|
+
it(`returns an arrowless alert if you don't pass an arrow`, () => {
|
|
12
|
+
const ArrowLessAlert = withArrow(Alert);
|
|
13
|
+
|
|
14
|
+
render(<ArrowLessAlert message={message} />);
|
|
15
|
+
const component = screen.getByTestId('alert');
|
|
16
|
+
|
|
17
|
+
expect(component).not.toHaveClass('arrow');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it(`ignores the arrow prop passed to the new alert`, () => {
|
|
21
|
+
const AlertTopArrow = withArrow(Alert, ArrowPosition.TOP_LEFT);
|
|
22
|
+
|
|
23
|
+
render(<AlertTopArrow message={message} arrow={ArrowPosition.BOTTOM_LEFT} />);
|
|
24
|
+
const component = screen.getByTestId('alert');
|
|
25
|
+
expect(component).toHaveClass('arrow');
|
|
26
|
+
expect(component).not.toHaveClass('arrow-bottom');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('renders arrows', () => {
|
|
31
|
+
const getPointyAlert = (arrow) => withArrow(Alert, arrow);
|
|
32
|
+
|
|
33
|
+
it(`returns an bottom arrowed alert if you pass a bottom arrow`, () => {
|
|
34
|
+
const BottomArrowAlert = getPointyAlert(ArrowPosition.BOTTOM);
|
|
35
|
+
render(<BottomArrowAlert message={message} />);
|
|
36
|
+
const component = screen.getByTestId('alert');
|
|
37
|
+
|
|
38
|
+
expect(component).toHaveClass('arrow');
|
|
39
|
+
expect(component).toHaveClass('arrow-bottom');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it(`returns an top-right arrowed alert if you pass a top right arrow`, () => {
|
|
43
|
+
const BottomArrowAlert = getPointyAlert(ArrowPosition.TOP_RIGHT);
|
|
44
|
+
render(<BottomArrowAlert message={message} />);
|
|
45
|
+
const component = screen.getByTestId('alert');
|
|
46
|
+
|
|
47
|
+
expect(component).toHaveClass('arrow');
|
|
48
|
+
expect(component).toHaveClass('arrow-right');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
package/src/i18n/ja.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"neptune.Button.loadingAriaLabel": "読み込み中…",
|
|
3
|
-
"neptune.Chips.ariaLabel": "{choice}
|
|
4
|
-
"neptune.ClearButton.ariaLabel": "
|
|
3
|
+
"neptune.Chips.ariaLabel": "{choice}を消去する",
|
|
4
|
+
"neptune.ClearButton.ariaLabel": "消去する",
|
|
5
5
|
"neptune.CloseButton.ariaLabel": "閉じる",
|
|
6
6
|
"neptune.DateInput.day.label": "日",
|
|
7
7
|
"neptune.DateInput.day.placeholder": "日",
|
|
@@ -21,19 +21,19 @@
|
|
|
21
21
|
"neptune.Link.opensInNewTab": "(新しいタブで開きます)",
|
|
22
22
|
"neptune.MoneyInput.Select.placeholder": "選択してください...",
|
|
23
23
|
"neptune.PhoneNumberInput.SelectInput.placeholder": "選択してください…",
|
|
24
|
-
"neptune.Select.searchPlaceholder": "
|
|
24
|
+
"neptune.Select.searchPlaceholder": "検索する... ",
|
|
25
25
|
"neptune.SelectInput.noResultsFound": "結果が見つかりませんでした",
|
|
26
26
|
"neptune.Summary.statusDone": "完了",
|
|
27
|
-
"neptune.Summary.statusNotDone": "
|
|
27
|
+
"neptune.Summary.statusNotDone": "未完了",
|
|
28
28
|
"neptune.Summary.statusPending": "保留中",
|
|
29
29
|
"neptune.Upload.csButtonText": "別のファイルをアップロードしますか?",
|
|
30
30
|
"neptune.Upload.csFailureText": "アップロードに失敗しました。もう一度やり直してください。",
|
|
31
31
|
"neptune.Upload.csSuccessText": "アップロードが完了しました。",
|
|
32
32
|
"neptune.Upload.csTooLargeMessage": "{maxSize}MB以下のファイルをアップロードしてください",
|
|
33
33
|
"neptune.Upload.csWrongTypeMessage": "ファイルの種類はサポートされていません。別のファイルで再度お試しください",
|
|
34
|
-
"neptune.Upload.psButtonText": "
|
|
35
|
-
"neptune.Upload.psProcessingText": "
|
|
36
|
-
"neptune.Upload.usButtonText": "
|
|
34
|
+
"neptune.Upload.psButtonText": "キャンセルする",
|
|
35
|
+
"neptune.Upload.psProcessingText": "アップロードしています…",
|
|
36
|
+
"neptune.Upload.usButtonText": "またはファイルを選択する",
|
|
37
37
|
"neptune.Upload.usDropMessage": "ファイルをドロップしてアップロードする",
|
|
38
38
|
"neptune.Upload.usPlaceholder": "{maxSize}MB以下のファイルをドラッグ&ドロップしてください",
|
|
39
39
|
"neptune.UploadButton.allFileTypes": "すべてのファイル種類",
|
|
@@ -42,16 +42,16 @@
|
|
|
42
42
|
"neptune.UploadButton.uploadFile": "ファイルをアップロードする",
|
|
43
43
|
"neptune.UploadButton.uploadFiles": "ファイルをアップロードする",
|
|
44
44
|
"neptune.UploadInput.deleteModalBody": "このファイルを削除すると、当社のシステムからも削除されます。",
|
|
45
|
-
"neptune.UploadInput.deleteModalCancelButtonText": "
|
|
46
|
-
"neptune.UploadInput.deleteModalConfirmButtonText": "
|
|
45
|
+
"neptune.UploadInput.deleteModalCancelButtonText": "キャンセルする",
|
|
46
|
+
"neptune.UploadInput.deleteModalConfirmButtonText": "削除する",
|
|
47
47
|
"neptune.UploadInput.deleteModalTitle": "このファイルを削除しますか?",
|
|
48
48
|
"neptune.UploadInput.fileIsTooLarge": "ファイルが大きすぎます。",
|
|
49
49
|
"neptune.UploadInput.fileTypeNotSupported": "このファイルの種類はサポートされていません",
|
|
50
50
|
"neptune.UploadInput.maximumFilesAlreadyUploaded": "申し訳ございませんが、このアップロードに失敗しました。一度に{maxFilesAllowed}個のファイルのみ受付可能です。",
|
|
51
|
-
"neptune.UploadItem.deleting": "
|
|
52
|
-
"neptune.UploadItem.removeFile": "{filename}
|
|
51
|
+
"neptune.UploadItem.deleting": "削除しています...",
|
|
52
|
+
"neptune.UploadItem.removeFile": "{filename}のファイルを削除する",
|
|
53
53
|
"neptune.UploadItem.uploaded": "アップロード済み",
|
|
54
54
|
"neptune.UploadItem.uploadedFile": "アップロード済みのファイル",
|
|
55
|
-
"neptune.UploadItem.uploading": "
|
|
56
|
-
"neptune.UploadItem.uploadingFailed": "
|
|
55
|
+
"neptune.UploadItem.uploading": "アップロードしています…",
|
|
56
|
+
"neptune.UploadItem.uploadingFailed": "アップロードに失敗しました"
|
|
57
57
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
export type { AccordionProps, AccordionItem } from './accordion';
|
|
5
5
|
export type { AvatarProps } from './avatar';
|
|
6
6
|
export type { ActionOptionProps } from './actionOption';
|
|
7
|
-
export type { AlertProps, AlertAction, AlertArrowPosition, AlertType } from './alert';
|
|
8
7
|
export type { BadgeProps } from './badge';
|
|
9
8
|
export type { CircularButtonProps } from './circularButton';
|
|
10
9
|
export type { DecisionProps } from './decision/Decision';
|
|
@@ -195,6 +194,7 @@ export { AvatarType } from './avatar';
|
|
|
195
194
|
export { InfoPresentation } from './info';
|
|
196
195
|
export { UploadStep } from './upload';
|
|
197
196
|
export { DecisionPresentation, DecisionType } from './decision';
|
|
197
|
+
export { AlertArrowPosition } from './alert/withArrow';
|
|
198
198
|
export { LogoType } from './logo';
|
|
199
199
|
export { FileType } from './common';
|
|
200
200
|
|
|
@@ -21,6 +21,13 @@ describe('InlineAlert', () => {
|
|
|
21
21
|
|
|
22
22
|
expect(component).toHaveClass('alert-neutral');
|
|
23
23
|
});
|
|
24
|
+
|
|
25
|
+
it('has a top left arrow', () => {
|
|
26
|
+
render(<InlineAlert>{message}</InlineAlert>);
|
|
27
|
+
const component = screen.getByRole('alert');
|
|
28
|
+
|
|
29
|
+
expect(component).toHaveClass('arrow');
|
|
30
|
+
});
|
|
24
31
|
});
|
|
25
32
|
|
|
26
33
|
describe('render with types', () => {
|
|
@@ -1,31 +1,59 @@
|
|
|
1
1
|
import { AlertCircle as AlertCircleIcon } from '@transferwise/icons';
|
|
2
|
+
import { useTheme } from '@wise/components-theming';
|
|
2
3
|
import classNames from 'classnames';
|
|
3
4
|
import { ReactNode } from 'react';
|
|
4
5
|
|
|
6
|
+
import withArrow, { AlertArrowPosition } from '../alert/withArrow';
|
|
5
7
|
import { Sentiment } from '../common';
|
|
8
|
+
import { SentimentString } from '../common/propsValues/sentiment';
|
|
6
9
|
|
|
7
10
|
export interface InlineAlertProps {
|
|
8
11
|
id?: string;
|
|
9
|
-
type?:
|
|
12
|
+
type?: Sentiment | SentimentString;
|
|
10
13
|
className?: string;
|
|
11
14
|
children: ReactNode;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}: InlineAlertProps) {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
17
|
+
const typeClassMap: Record<Sentiment.ERROR | Sentiment.NEGATIVE, string> = {
|
|
18
|
+
[Sentiment.ERROR]: 'danger',
|
|
19
|
+
[Sentiment.NEGATIVE]: 'danger',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const InlineAlert = ({ id, type = Sentiment.NEUTRAL, className, children }: InlineAlertProps) => {
|
|
23
|
+
const { isModern } = useTheme();
|
|
24
|
+
|
|
25
|
+
const typeClass = `alert-${typeClassMap[type as Sentiment.ERROR | Sentiment.NEGATIVE] || type}`;
|
|
26
|
+
|
|
27
|
+
if (isModern) {
|
|
28
|
+
return (
|
|
29
|
+
<div role="alert" id={id} className={classNames('alert alert-detach', typeClass, className)}>
|
|
30
|
+
{(type === 'error' || type === 'negative') && <AlertCircleIcon />}
|
|
31
|
+
<div>{children}</div>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const getAlertContents = ({
|
|
37
|
+
children,
|
|
38
|
+
className,
|
|
39
|
+
}: {
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
className?: string;
|
|
42
|
+
}) => {
|
|
43
|
+
return (
|
|
44
|
+
<div
|
|
45
|
+
role="alert"
|
|
46
|
+
id={id}
|
|
47
|
+
className={classNames('alert alert-detach p-x-2 p-y-1', typeClass, className)}
|
|
48
|
+
>
|
|
49
|
+
{children}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const AlertWithArrow = withArrow(getAlertContents, AlertArrowPosition.TOP_LEFT);
|
|
55
|
+
|
|
56
|
+
return <AlertWithArrow {...{ id, type, className, children }} />;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default InlineAlert;
|
|
@@ -7,7 +7,8 @@ import { DirectionProvider } from './direction';
|
|
|
7
7
|
import { LanguageProvider } from './language';
|
|
8
8
|
|
|
9
9
|
export interface ProviderProps {
|
|
10
|
-
i18n: Pick<ResolvedIntlConfig, 'locale' | 'messages'
|
|
10
|
+
i18n: Pick<ResolvedIntlConfig, 'locale' | 'messages'> &
|
|
11
|
+
Partial<Pick<ResolvedIntlConfig, 'defaultRichTextElements'>>;
|
|
11
12
|
children?: React.ReactNode;
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
|
|
4
|
-
import { SizeSmall, SizeMedium, SizeLarge, Sentiment } from '../common';
|
|
4
|
+
import { SizeSmall, SizeMedium, SizeLarge, Sentiment, Size } from '../common';
|
|
5
5
|
|
|
6
6
|
export type StatusIconProps = {
|
|
7
|
-
sentiment:
|
|
7
|
+
sentiment: Sentiment;
|
|
8
8
|
size: SizeSmall | SizeMedium | SizeLarge;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
const StatusIcon = ({ sentiment = Sentiment.NEUTRAL, size = Size.MEDIUM }: StatusIconProps) => {
|
|
12
|
+
const iconTypeMap = {
|
|
13
|
+
[Sentiment.POSITIVE]: Check,
|
|
14
|
+
[Sentiment.NEUTRAL]: Info,
|
|
15
|
+
[Sentiment.WARNING]: Alert,
|
|
16
|
+
[Sentiment.NEGATIVE]: Cross,
|
|
17
|
+
[Sentiment.PENDING]: ClockBorderless,
|
|
18
|
+
[Sentiment.INFO]: Info,
|
|
19
|
+
[Sentiment.ERROR]: Cross,
|
|
20
|
+
[Sentiment.SUCCESS]: Check,
|
|
21
|
+
};
|
|
21
22
|
|
|
22
|
-
const
|
|
23
|
+
const iconColor = [Sentiment.WARNING, Sentiment.PENDING].includes(sentiment) ? 'dark' : 'light';
|
|
23
24
|
const Icon = iconTypeMap[sentiment];
|
|
24
|
-
const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<span
|