@transferwise/components 0.0.0-experimental-2825d2d → 0.0.0-experimental-1413ac0
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/zh-HK.json +2 -2
- package/build/index.esm.js +186 -277
- package/build/index.esm.js.map +1 -1
- package/build/index.js +159 -250
- package/build/index.js.map +1 -1
- package/build/types/body/Body.d.ts +1 -1
- package/build/types/common/commonProps.d.ts +1 -1
- package/build/types/common/commonProps.d.ts.map +1 -1
- package/build/types/common/dateUtils/getDayNames/getDayNames.d.ts +1 -1
- package/build/types/common/dateUtils/getDayNames/getDayNames.d.ts.map +1 -1
- package/build/types/common/dateUtils/getDayNames/index.d.ts +1 -1
- package/build/types/common/dateUtils/getDayNames/index.d.ts.map +1 -1
- package/build/types/common/dateUtils/getMonthNames/getMonthNames.d.ts +1 -1
- package/build/types/common/dateUtils/getMonthNames/getMonthNames.d.ts.map +1 -1
- package/build/types/common/dateUtils/getMonthNames/index.d.ts +1 -1
- package/build/types/common/dateUtils/getMonthNames/index.d.ts.map +1 -1
- package/build/types/common/dateUtils/index.d.ts +6 -6
- package/build/types/common/dateUtils/index.d.ts.map +1 -1
- package/build/types/common/dateUtils/isDateValid/index.d.ts +1 -1
- package/build/types/common/dateUtils/isDateValid/index.d.ts.map +1 -1
- package/build/types/common/dateUtils/isDateValid/isDateValid.d.ts +2 -2
- package/build/types/common/dateUtils/isDateValid/isDateValid.d.ts.map +1 -1
- package/build/types/common/dateUtils/isMonthAndYearFormat/index.d.ts +1 -1
- package/build/types/common/dateUtils/isMonthAndYearFormat/index.d.ts.map +1 -1
- package/build/types/common/dateUtils/isMonthAndYearFormat/isMonthAndYearFormat.d.ts +1 -1
- package/build/types/common/dateUtils/isMonthAndYearFormat/isMonthAndYearFormat.d.ts.map +1 -1
- package/build/types/common/dateUtils/isWithinRange/index.d.ts +1 -1
- package/build/types/common/dateUtils/isWithinRange/index.d.ts.map +1 -1
- package/build/types/common/dateUtils/isWithinRange/isWithinRange.d.ts +1 -1
- package/build/types/common/dateUtils/isWithinRange/isWithinRange.d.ts.map +1 -1
- package/build/types/common/dateUtils/moveToWithinRange/index.d.ts +1 -1
- package/build/types/common/dateUtils/moveToWithinRange/index.d.ts.map +1 -1
- package/build/types/common/dateUtils/moveToWithinRange/moveToWithinRange.d.ts +1 -1
- package/build/types/common/dateUtils/moveToWithinRange/moveToWithinRange.d.ts.map +1 -1
- package/build/types/common/panel/Panel.d.ts +1 -1
- package/build/types/common/responsivePanel/ResponsivePanel.d.ts +1 -1
- package/build/types/dateInput/DateInput.d.ts +41 -35
- package/build/types/dateInput/DateInput.d.ts.map +1 -1
- package/build/types/dateInput/DateInput.messages.d.ts +33 -24
- package/build/types/dateInput/DateInput.messages.d.ts.map +1 -1
- package/build/types/dateInput/index.d.ts +1 -1
- package/build/types/dateInput/index.d.ts.map +1 -1
- package/build/types/dateInput/utils/convertToLocalMidnight/convertToLocalMidnight.d.ts +1 -1
- package/build/types/dateInput/utils/convertToLocalMidnight/convertToLocalMidnight.d.ts.map +1 -1
- package/build/types/dateInput/utils/convertToLocalMidnight/index.d.ts +1 -1
- package/build/types/dateInput/utils/convertToLocalMidnight/index.d.ts.map +1 -1
- package/build/types/dateInput/utils/explodeDate/explodeDate.d.ts +5 -2
- package/build/types/dateInput/utils/explodeDate/explodeDate.d.ts.map +1 -1
- package/build/types/dateInput/utils/explodeDate/index.d.ts +1 -1
- package/build/types/dateInput/utils/explodeDate/index.d.ts.map +1 -1
- package/build/types/dateInput/utils/index.d.ts +2 -2
- package/build/types/dateInput/utils/index.d.ts.map +1 -1
- package/build/types/decision/Decision.d.ts +39 -52
- package/build/types/decision/Decision.d.ts.map +1 -1
- package/build/types/decision/index.d.ts +1 -2
- package/build/types/decision/index.d.ts.map +1 -1
- package/build/types/dimmer/Dimmer.d.ts +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/promoCard/PromoCard.d.ts +1 -2
- package/build/types/promoCard/PromoCard.d.ts.map +1 -1
- package/build/types/select/searchBox/SearchBox.d.ts +1 -1
- package/package.json +1 -1
- package/src/common/commonProps.ts +1 -1
- package/src/common/dateUtils/getDayNames/{getDayNames.ts → getDayNames.js} +2 -5
- package/src/common/dateUtils/getMonthNames/{getMonthNames.ts → getMonthNames.js} +3 -5
- package/src/common/dateUtils/getMonthNames/getMonthNames.spec.js +8 -9
- package/src/common/dateUtils/isDateValid/isDateValid.js +6 -0
- package/src/common/dateUtils/isDateValid/{isDateValid.spec.ts → isDateValid.spec.js} +2 -2
- package/src/common/dateUtils/isMonthAndYearFormat/{isMonthAndYearFormat.ts → isMonthAndYearFormat.js} +1 -1
- package/src/common/dateUtils/isMonthAndYearFormat/isMonthAndYearFormat.spec.js +7 -3
- package/src/common/dateUtils/isWithinRange/{isWithinRange.ts → isWithinRange.js} +1 -1
- package/src/common/dateUtils/isWithinRange/{isWithinRange.spec.ts → isWithinRange.spec.js} +6 -6
- package/src/common/dateUtils/moveToWithinRange/{moveToWithinRange.ts → moveToWithinRange.js} +2 -2
- package/src/dateInput/{DateInput.tsx → DateInput.js} +97 -120
- package/src/dateInput/DateInput.spec.js +55 -6
- package/src/dateInput/DateInput.story.tsx +7 -9
- package/src/dateInput/utils/convertToLocalMidnight/{convertToLocalMidnight.ts → convertToLocalMidnight.js} +1 -1
- package/src/dateInput/utils/explodeDate/{explodeDate.ts → explodeDate.js} +1 -3
- package/src/dateLookup/dayCalendar/table/DayCalendarTable.js +0 -1
- package/src/decision/Decision.spec.js +53 -59
- package/src/decision/{Decision.story.js → Decision.story.tsx} +5 -5
- package/src/decision/Decision.tsx +136 -0
- package/src/decision/index.ts +1 -0
- package/src/i18n/zh-HK.json +2 -2
- package/src/index.ts +1 -0
- package/src/promoCard/PromoCard.tsx +1 -2
- package/src/tile/Tile.js +1 -1
- package/build/types/decision/decisionEnums.d.ts +0 -9
- package/build/types/decision/decisionEnums.d.ts.map +0 -1
- package/build/types/sizeSwapper/SizeSwapper.d.ts +0 -3
- package/build/types/sizeSwapper/SizeSwapper.d.ts.map +0 -1
- package/build/types/sizeSwapper/index.d.ts +0 -2
- package/build/types/sizeSwapper/index.d.ts.map +0 -1
- package/src/common/dateUtils/isDateValid/isDateValid.ts +0 -13
- package/src/decision/Decision.js +0 -148
- package/src/decision/decisionEnums.ts +0 -11
- package/src/decision/index.js +0 -2
- package/src/sizeSwapper/SizeSwapper.js +0 -69
- package/src/sizeSwapper/SizeSwapper.spec.js +0 -100
- package/src/sizeSwapper/SizeSwapper.story.js +0 -34
- package/src/sizeSwapper/index.js +0 -1
- /package/src/common/dateUtils/getDayNames/{index.ts → index.js} +0 -0
- /package/src/common/dateUtils/getMonthNames/{index.ts → index.js} +0 -0
- /package/src/common/dateUtils/{index.ts → index.js} +0 -0
- /package/src/common/dateUtils/isDateValid/{index.ts → index.js} +0 -0
- /package/src/common/dateUtils/isMonthAndYearFormat/{index.ts → index.js} +0 -0
- /package/src/common/dateUtils/isWithinRange/{index.ts → index.js} +0 -0
- /package/src/common/dateUtils/moveToWithinRange/{index.ts → index.js} +0 -0
- /package/src/dateInput/{DateInput.messages.ts → DateInput.messages.js} +0 -0
- /package/src/dateInput/{index.ts → index.js} +0 -0
- /package/src/dateInput/utils/convertToLocalMidnight/{convertToLocalMidnight.spec.ts → convertToLocalMidnight.spec.js} +0 -0
- /package/src/dateInput/utils/convertToLocalMidnight/{index.ts → index.js} +0 -0
- /package/src/dateInput/utils/explodeDate/{explodeDate.spec.ts → explodeDate.spec.js} +0 -0
- /package/src/dateInput/utils/explodeDate/{index.ts → index.js} +0 -0
- /package/src/dateInput/utils/{index.ts → index.js} +0 -0
|
@@ -4,12 +4,44 @@ import { useIntl } from 'react-intl';
|
|
|
4
4
|
import { DateInput, Input } from '..';
|
|
5
5
|
import { mockMatchMedia, mockResizeObserver } from '../test-utils';
|
|
6
6
|
|
|
7
|
+
const MONTHS_FR = [
|
|
8
|
+
'janvier',
|
|
9
|
+
'février',
|
|
10
|
+
'mars',
|
|
11
|
+
'avril',
|
|
12
|
+
'mai',
|
|
13
|
+
'juin',
|
|
14
|
+
'juillet',
|
|
15
|
+
'août',
|
|
16
|
+
'septembre',
|
|
17
|
+
'octobre',
|
|
18
|
+
'novembre',
|
|
19
|
+
'décembre',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const MONTHS_EN = [
|
|
23
|
+
'January',
|
|
24
|
+
'February',
|
|
25
|
+
'March',
|
|
26
|
+
'April',
|
|
27
|
+
'May',
|
|
28
|
+
'June',
|
|
29
|
+
'July',
|
|
30
|
+
'August',
|
|
31
|
+
'September',
|
|
32
|
+
'October',
|
|
33
|
+
'November',
|
|
34
|
+
'December',
|
|
35
|
+
];
|
|
36
|
+
|
|
7
37
|
const LOCALES = {
|
|
38
|
+
fr: 'fr-FR',
|
|
8
39
|
jp: 'ja-JP',
|
|
9
40
|
};
|
|
41
|
+
|
|
10
42
|
const DEFAULT_LOCALE = 'en-GB';
|
|
11
|
-
|
|
12
|
-
const
|
|
43
|
+
|
|
44
|
+
const FEBRUARY_OPTION = { value: MONTHS_EN[1] };
|
|
13
45
|
|
|
14
46
|
const DAY_SELECTOR = 'ForwardRef(Input)[name="day"]';
|
|
15
47
|
const MONTH_SELECTOR = 'SelectInput';
|
|
@@ -41,6 +73,12 @@ jest.mock('./DateInput.messages', () => ({
|
|
|
41
73
|
}));
|
|
42
74
|
|
|
43
75
|
jest.mock('react-intl');
|
|
76
|
+
jest.mock('@transferwise/formatting', () => {
|
|
77
|
+
return {
|
|
78
|
+
formatDate: (month, locale) =>
|
|
79
|
+
locale === LOCALES.fr ? MONTHS_FR[month.getMonth()] : MONTHS_EN[month.getMonth()],
|
|
80
|
+
};
|
|
81
|
+
});
|
|
44
82
|
|
|
45
83
|
describe('Date Input Component', () => {
|
|
46
84
|
let selectMonth;
|
|
@@ -105,7 +143,7 @@ describe('Date Input Component', () => {
|
|
|
105
143
|
inputYear = component.find(YEAR_SELECTOR);
|
|
106
144
|
|
|
107
145
|
expect(inputDay.prop('value')).toBe(1);
|
|
108
|
-
expect(selectMonth.prop('value')).toBe(
|
|
146
|
+
expect(selectMonth.prop('value').label).toBe(FEBRUARY_OPTION.value);
|
|
109
147
|
expect(inputYear.prop('value')).toBe(1971);
|
|
110
148
|
});
|
|
111
149
|
});
|
|
@@ -119,7 +157,7 @@ describe('Date Input Component', () => {
|
|
|
119
157
|
inputYear = component.find(YEAR_SELECTOR);
|
|
120
158
|
|
|
121
159
|
expect(inputDay.prop('value')).toBe(22);
|
|
122
|
-
expect(selectMonth.prop('value')).toBe(
|
|
160
|
+
expect(selectMonth.prop('value').label).toBe(MONTHS_EN[7]);
|
|
123
161
|
expect(inputYear.prop('value')).toBe(1990);
|
|
124
162
|
});
|
|
125
163
|
});
|
|
@@ -133,7 +171,7 @@ describe('Date Input Component', () => {
|
|
|
133
171
|
inputYear = component.find(YEAR_SELECTOR);
|
|
134
172
|
|
|
135
173
|
expect(inputDay.prop('value')).toBe('');
|
|
136
|
-
expect(selectMonth.prop('value')).toBe(
|
|
174
|
+
expect(selectMonth.prop('value').label).toBe(MONTHS_EN[7]);
|
|
137
175
|
expect(inputYear.prop('value')).toBe(1990);
|
|
138
176
|
});
|
|
139
177
|
});
|
|
@@ -147,7 +185,7 @@ describe('Date Input Component', () => {
|
|
|
147
185
|
inputYear = component.find(YEAR_SELECTOR);
|
|
148
186
|
|
|
149
187
|
expect(inputDay.prop('value')).toBe(28);
|
|
150
|
-
expect(selectMonth.prop('value')).toBe(
|
|
188
|
+
expect(selectMonth.prop('value').label).toBe(FEBRUARY_OPTION.value);
|
|
151
189
|
expect(inputYear.prop('value')).toBe(1990);
|
|
152
190
|
});
|
|
153
191
|
});
|
|
@@ -182,6 +220,17 @@ describe('Date Input Component', () => {
|
|
|
182
220
|
});
|
|
183
221
|
|
|
184
222
|
describe('when locale is provided', () => {
|
|
223
|
+
it('updates selectMonth based on locale', () => {
|
|
224
|
+
useIntl.mockReturnValue({
|
|
225
|
+
locale: LOCALES.fr,
|
|
226
|
+
formatMessage: (message) => message.defaultMessage,
|
|
227
|
+
});
|
|
228
|
+
component = shallow(<DateInput {...props} />);
|
|
229
|
+
selectMonth = component.find(MONTH_SELECTOR);
|
|
230
|
+
|
|
231
|
+
expect(selectMonth.props().items[0].value.label).toStrictEqual(MONTHS_FR[0]);
|
|
232
|
+
});
|
|
233
|
+
|
|
185
234
|
it('shows day before month if locale not US', () => {
|
|
186
235
|
component = shallow(<DateInput {...props} />);
|
|
187
236
|
|
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { userEvent, within } from '@storybook/test';
|
|
3
|
-
import React from 'react';
|
|
4
3
|
|
|
5
|
-
import { DateInput,
|
|
4
|
+
import { DateInput, Info, InlineAlert, Title, Typography } from '..';
|
|
6
5
|
import { lorem10, storyConfig } from '../test-utils';
|
|
7
6
|
|
|
8
|
-
import { DateInputProps } from './DateInput';
|
|
9
|
-
|
|
10
7
|
export default {
|
|
11
8
|
component: DateInput,
|
|
12
9
|
title: 'Forms/DateInput',
|
|
13
10
|
args: {
|
|
14
11
|
dayLabel: 'Day input',
|
|
15
12
|
dayAutoComplete: 'bday-day',
|
|
16
|
-
value: null,
|
|
17
13
|
monthLabel: 'Month select',
|
|
18
14
|
yearLabel: 'Year input',
|
|
19
15
|
yearAutoComplete: 'bday-year',
|
|
20
16
|
selectProps: {
|
|
21
|
-
|
|
17
|
+
buttonProps: {
|
|
18
|
+
'aria-label': 'Select month',
|
|
19
|
+
},
|
|
22
20
|
},
|
|
23
21
|
},
|
|
24
22
|
tags: ['autodocs'],
|
|
25
23
|
} satisfies Meta<typeof DateInput>;
|
|
26
24
|
|
|
27
|
-
type Story = StoryObj<
|
|
25
|
+
type Story = StoryObj<typeof DateInput>;
|
|
28
26
|
|
|
29
|
-
export const Basic:
|
|
27
|
+
export const Basic: Story = {};
|
|
30
28
|
|
|
31
29
|
Basic.play = async ({ canvasElement }) => {
|
|
32
30
|
const canvas = within(canvasElement);
|
|
@@ -58,7 +56,7 @@ export const WithLabel: Story = {
|
|
|
58
56
|
{label}{' '}
|
|
59
57
|
<Info aria-label="Fast transfer hint" title="Fast transfer hint" content={lorem10} />
|
|
60
58
|
</div>
|
|
61
|
-
<DateInput {...args}
|
|
59
|
+
<DateInput {...args} aria-label={label} />
|
|
62
60
|
|
|
63
61
|
<br />
|
|
64
62
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const convertToLocalMidnight = (date
|
|
1
|
+
export const convertToLocalMidnight = (date) => {
|
|
2
2
|
const utcDate = new Date(date.split('T')[0]); // using YYYY-MM-DD creates UTC date
|
|
3
3
|
|
|
4
4
|
return new Date(utcDate.getUTCFullYear(), utcDate.getUTCMonth(), utcDate.getUTCDate());
|
|
@@ -3,16 +3,16 @@ import '@testing-library/jest-dom';
|
|
|
3
3
|
|
|
4
4
|
import Avatar from '../avatar';
|
|
5
5
|
import { Breakpoint, Size } from '../common';
|
|
6
|
-
import {
|
|
6
|
+
import { mockMatchMedia } from '../mocks';
|
|
7
|
+
import { render, fireEvent, screen } from '../test-utils';
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
import Decision from '.';
|
|
9
|
+
import Decision, { DecisionPresentation, DecisionType } from '.';
|
|
11
10
|
|
|
12
11
|
jest.mock('lodash.throttle', () => jest.fn((fn) => fn));
|
|
12
|
+
mockMatchMedia(jest);
|
|
13
13
|
|
|
14
14
|
describe('Decision', () => {
|
|
15
|
-
const
|
|
15
|
+
const commonProps = {
|
|
16
16
|
options: [
|
|
17
17
|
{
|
|
18
18
|
media: {
|
|
@@ -25,112 +25,106 @@ describe('Decision', () => {
|
|
|
25
25
|
onClick: jest.fn(),
|
|
26
26
|
},
|
|
27
27
|
],
|
|
28
|
-
presentation:
|
|
29
|
-
type:
|
|
28
|
+
presentation: DecisionPresentation.LIST_BLOCK,
|
|
29
|
+
type: DecisionType.NAVIGATION,
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
const initialInnerWidth = window.innerWidth;
|
|
32
33
|
const resetClientWidth = (width) => {
|
|
33
|
-
|
|
34
|
-
configurable: true,
|
|
35
|
-
value: width,
|
|
36
|
-
});
|
|
34
|
+
window.innerWidth = width;
|
|
37
35
|
};
|
|
38
36
|
|
|
39
37
|
afterAll(() => {
|
|
40
|
-
|
|
41
|
-
HTMLElement.prototype,
|
|
42
|
-
'clientWidth',
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
Object.defineProperty(HTMLElement.prototype, 'clientWidth', originalClientWidth);
|
|
38
|
+
window.innerWidth = initialInnerWidth;
|
|
46
39
|
});
|
|
47
40
|
|
|
48
|
-
let container;
|
|
49
41
|
beforeEach(() => {
|
|
50
42
|
resetClientWidth(Breakpoint.EXTRA_SMALL - 1);
|
|
51
43
|
});
|
|
52
44
|
|
|
53
|
-
describe(`when presentation is ${
|
|
54
|
-
|
|
55
|
-
({ container } = render(<Decision {...props} />));
|
|
56
|
-
});
|
|
45
|
+
describe(`when presentation is ${DecisionPresentation.LIST_BLOCK}`, () => {
|
|
46
|
+
const props = { ...commonProps };
|
|
57
47
|
|
|
58
48
|
it('renders only Navigation Option before first breakpoint', () => {
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
const { container } = render(<Decision {...props} />);
|
|
50
|
+
|
|
51
|
+
expect(getNavigationOption(container)).toBeInTheDocument();
|
|
52
|
+
expect(getTile(container)).not.toBeInTheDocument();
|
|
61
53
|
});
|
|
62
54
|
|
|
63
55
|
it('renders only Tile after first breakpoint', () => {
|
|
64
56
|
resetClientWidth(Breakpoint.SMALL);
|
|
65
|
-
|
|
57
|
+
const { container } = render(<Decision {...props} />);
|
|
66
58
|
|
|
67
|
-
expect(getNavigationOption()).not.toBeInTheDocument();
|
|
68
|
-
expect(getTile()).toBeInTheDocument();
|
|
69
|
-
expect(getTile()).not.toHaveClass('np-tile--small');
|
|
59
|
+
expect(getNavigationOption(container)).not.toBeInTheDocument();
|
|
60
|
+
expect(getTile(container)).toBeInTheDocument();
|
|
61
|
+
expect(getTile(container)).not.toHaveClass('np-tile--small');
|
|
70
62
|
});
|
|
71
63
|
});
|
|
72
64
|
|
|
73
|
-
describe(`when presentation is ${
|
|
74
|
-
|
|
75
|
-
({ container } = render(<Decision {...props} presentation={Presentation.LIST_BLOCK_GRID} />));
|
|
76
|
-
});
|
|
65
|
+
describe(`when presentation is ${DecisionPresentation.LIST_BLOCK_GRID}`, () => {
|
|
66
|
+
const props = { ...commonProps, presentation: DecisionPresentation.LIST_BLOCK_GRID };
|
|
77
67
|
|
|
78
68
|
it('renders only Navigation Option before first breakpoint', () => {
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
const { container } = render(<Decision {...props} />);
|
|
70
|
+
|
|
71
|
+
expect(getNavigationOption(container)).toBeInTheDocument();
|
|
72
|
+
expect(getTile(container)).not.toBeInTheDocument();
|
|
81
73
|
});
|
|
82
74
|
|
|
83
75
|
it('renders only Tile after first breakpoint', () => {
|
|
84
76
|
resetClientWidth(Breakpoint.SMALL);
|
|
85
|
-
|
|
77
|
+
const { container } = render(<Decision {...props} />);
|
|
86
78
|
|
|
87
|
-
expect(getNavigationOption()).not.toBeInTheDocument();
|
|
88
|
-
expect(getTile()).toBeInTheDocument();
|
|
89
|
-
expect(getTile()).not.toHaveClass('np-tile--small');
|
|
79
|
+
expect(getNavigationOption(container)).not.toBeInTheDocument();
|
|
80
|
+
expect(getTile(container)).toBeInTheDocument();
|
|
81
|
+
expect(getTile(container)).not.toHaveClass('np-tile--small');
|
|
90
82
|
});
|
|
91
83
|
|
|
92
84
|
it('renders container as a grid', () => {
|
|
93
85
|
resetClientWidth(Breakpoint.SMALL);
|
|
94
|
-
|
|
86
|
+
const { container } = render(<Decision {...props} />);
|
|
95
87
|
|
|
96
88
|
expect(container.querySelector('.np-decision')).toHaveClass('np-decision--grid');
|
|
97
89
|
expect(container.querySelector('.np-size-swapper')).toHaveClass('flex-wrap');
|
|
98
90
|
});
|
|
99
91
|
});
|
|
100
92
|
|
|
101
|
-
describe(`when presentation is ${
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
93
|
+
describe(`when presentation is ${DecisionPresentation.LIST_BLOCK} and size is Small`, () => {
|
|
94
|
+
const props = {
|
|
95
|
+
...commonProps,
|
|
96
|
+
presentation: DecisionPresentation.LIST_BLOCK,
|
|
97
|
+
size: Size.SMALL,
|
|
98
|
+
};
|
|
107
99
|
|
|
108
100
|
it('renders only Navigation Option before breakpoint', () => {
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
const { container } = render(<Decision {...props} />);
|
|
102
|
+
|
|
103
|
+
expect(getNavigationOption(container)).toBeInTheDocument();
|
|
104
|
+
expect(getTile(container)).not.toBeInTheDocument();
|
|
111
105
|
});
|
|
112
106
|
|
|
113
107
|
it('renders Small Tile after breakpoint', () => {
|
|
114
108
|
resetClientWidth(Breakpoint.EXTRA_SMALL);
|
|
115
|
-
|
|
109
|
+
const { container } = render(<Decision {...props} />);
|
|
116
110
|
|
|
117
|
-
expect(getNavigationOption()).not.toBeInTheDocument();
|
|
118
|
-
expect(getTile()).toBeInTheDocument();
|
|
119
|
-
expect(getTile()).toHaveClass('np-tile--small');
|
|
111
|
+
expect(getNavigationOption(container)).not.toBeInTheDocument();
|
|
112
|
+
expect(getTile(container)).toBeInTheDocument();
|
|
113
|
+
expect(getTile(container)).toHaveClass('np-tile--small');
|
|
120
114
|
});
|
|
121
115
|
});
|
|
122
116
|
|
|
123
|
-
describe(`when presentation is ${
|
|
124
|
-
|
|
125
|
-
({ container } = render(<Decision {...props} presentation={Presentation.LIST} />));
|
|
126
|
-
});
|
|
117
|
+
describe(`when presentation is ${DecisionPresentation.LIST}`, () => {
|
|
118
|
+
const props = { ...commonProps, presentation: DecisionPresentation.LIST };
|
|
127
119
|
|
|
128
120
|
it('renders Navigation Option before breakpoint', () => {
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
const { container } = render(<Decision {...props} />);
|
|
122
|
+
|
|
123
|
+
expect(getNavigationOption(container)).toBeInTheDocument();
|
|
124
|
+
expect(getTile(container)).not.toBeInTheDocument();
|
|
131
125
|
});
|
|
132
126
|
});
|
|
133
127
|
|
|
134
|
-
const getNavigationOption = () => container.querySelector('.np-navigation-option');
|
|
135
|
-
const getTile = () => container.querySelector('.np-tile');
|
|
128
|
+
const getNavigationOption = (container) => container.querySelector('.np-navigation-option');
|
|
129
|
+
const getTile = (container) => container.querySelector('.np-tile');
|
|
136
130
|
});
|
|
@@ -21,7 +21,7 @@ export const Basic = () => {
|
|
|
21
21
|
const disabled = boolean('disabled', false);
|
|
22
22
|
const showMediaCircleInList = boolean('showMediaCircleInList', true);
|
|
23
23
|
const isContainerAligned = boolean('isContainerAligned', false);
|
|
24
|
-
const size = select('size', [Size.MEDIUM, Size.SMALL]);
|
|
24
|
+
const size = select('size', [Size.MEDIUM, Size.SMALL], Size.MEDIUM);
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<>
|
|
@@ -33,7 +33,7 @@ export const Basic = () => {
|
|
|
33
33
|
href: '#href1',
|
|
34
34
|
disabled,
|
|
35
35
|
media: {
|
|
36
|
-
block: <Illustration name="globe" alt=""
|
|
36
|
+
block: <Illustration name="globe" alt="" disablePadding />,
|
|
37
37
|
list: (
|
|
38
38
|
<Avatar size="md" type="initials">
|
|
39
39
|
HM
|
|
@@ -49,7 +49,7 @@ export const Basic = () => {
|
|
|
49
49
|
disabled,
|
|
50
50
|
href: '#href2',
|
|
51
51
|
media: {
|
|
52
|
-
block: <Illustration name="confetti" alt=""
|
|
52
|
+
block: <Illustration name="confetti" alt="" disablePadding />,
|
|
53
53
|
list: (
|
|
54
54
|
<Avatar size="md" type="initials">
|
|
55
55
|
HM
|
|
@@ -61,7 +61,7 @@ export const Basic = () => {
|
|
|
61
61
|
{
|
|
62
62
|
description: "I'm disabled and don't require an onClick or href.",
|
|
63
63
|
media: {
|
|
64
|
-
block: <Illustration name="briefcase" alt=""
|
|
64
|
+
block: <Illustration name="briefcase" alt="" disablePadding />,
|
|
65
65
|
list: (
|
|
66
66
|
<img
|
|
67
67
|
src="https://wise.com/public-resources/assets/illustrations/business_account_web_small.svg"
|
|
@@ -91,7 +91,7 @@ export const grid = () => {
|
|
|
91
91
|
DecisionPresentation.LIST_BLOCK_GRID,
|
|
92
92
|
);
|
|
93
93
|
const disabled = boolean('disabled', false);
|
|
94
|
-
const size = select('size', [Size.MEDIUM, Size.SMALL]);
|
|
94
|
+
const size = select('size', [Size.MEDIUM, Size.SMALL], Size.MEDIUM);
|
|
95
95
|
|
|
96
96
|
return (
|
|
97
97
|
<>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
|
|
3
|
+
import { Size, Breakpoint, SizeSmall, SizeMedium } from '../common';
|
|
4
|
+
import { useScreenSize } from '../common/hooks/useScreenSize';
|
|
5
|
+
import NavigationOption from '../navigationOption';
|
|
6
|
+
import Tile from '../tile';
|
|
7
|
+
|
|
8
|
+
interface DecisionOption {
|
|
9
|
+
description?: React.ReactNode;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
href?: string;
|
|
12
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
13
|
+
media: {
|
|
14
|
+
block: React.ReactNode;
|
|
15
|
+
list: React.ReactNode;
|
|
16
|
+
};
|
|
17
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
18
|
+
title: React.ReactNode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export enum DecisionPresentation {
|
|
22
|
+
LIST = 'LIST',
|
|
23
|
+
LIST_BLOCK = 'LIST_BLOCK',
|
|
24
|
+
LIST_BLOCK_GRID = 'LIST_BLOCK_GRID',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export enum DecisionType {
|
|
28
|
+
NAVIGATION = 'NAVIGATION',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface DecisionProps {
|
|
32
|
+
/** A list of elements to be rendered */
|
|
33
|
+
options: DecisionOption[];
|
|
34
|
+
/** Handles the display mode of the component */
|
|
35
|
+
presentation?: `${DecisionPresentation}`;
|
|
36
|
+
/** Size currently affects only Tile dimension */
|
|
37
|
+
size?: SizeSmall | SizeMedium;
|
|
38
|
+
/** Decide which kind of element type needs to be rendered ex: Navigation Options or in the future Radio or Checkbox Options */
|
|
39
|
+
type?: `${DecisionType}`;
|
|
40
|
+
|
|
41
|
+
/** Display media in a circle in list presentation */
|
|
42
|
+
showMediaCircleInList?: boolean;
|
|
43
|
+
|
|
44
|
+
/** Sets navigation options to be aligned with the parent container */
|
|
45
|
+
isContainerAligned?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const Decision = ({
|
|
49
|
+
options,
|
|
50
|
+
presentation = DecisionPresentation.LIST,
|
|
51
|
+
size = Size.MEDIUM,
|
|
52
|
+
type = DecisionType.NAVIGATION,
|
|
53
|
+
showMediaCircleInList = true,
|
|
54
|
+
isContainerAligned = false,
|
|
55
|
+
}: DecisionProps) => {
|
|
56
|
+
const screenXs = useScreenSize(Breakpoint.EXTRA_SMALL);
|
|
57
|
+
const screenSm = useScreenSize(Breakpoint.SMALL);
|
|
58
|
+
|
|
59
|
+
if (type === DecisionType.NAVIGATION) {
|
|
60
|
+
const renderedOptions = options.map(
|
|
61
|
+
({ title, description, disabled, href, target, media: { list }, onClick }, key) => (
|
|
62
|
+
<NavigationOption
|
|
63
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
64
|
+
key={`nav-${key}`}
|
|
65
|
+
complex={false}
|
|
66
|
+
content={description}
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
href={href}
|
|
69
|
+
target={target}
|
|
70
|
+
media={list}
|
|
71
|
+
showMediaAtAllSizes
|
|
72
|
+
showMediaCircle={showMediaCircleInList}
|
|
73
|
+
isContainerAligned={isContainerAligned}
|
|
74
|
+
title={title}
|
|
75
|
+
onClick={onClick}
|
|
76
|
+
/>
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
if (
|
|
81
|
+
presentation === DecisionPresentation.LIST_BLOCK ||
|
|
82
|
+
presentation === DecisionPresentation.LIST_BLOCK_GRID
|
|
83
|
+
) {
|
|
84
|
+
const isSmall = size === Size.SMALL;
|
|
85
|
+
const breakpoint = isSmall ? screenXs : screenSm;
|
|
86
|
+
|
|
87
|
+
const isGrid = presentation === DecisionPresentation.LIST_BLOCK_GRID;
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
className={classNames('np-decision', {
|
|
92
|
+
'np-decision--small': isSmall,
|
|
93
|
+
'np-decision--grid': isGrid,
|
|
94
|
+
})}
|
|
95
|
+
>
|
|
96
|
+
<div
|
|
97
|
+
className={classNames(
|
|
98
|
+
'np-size-swapper d-flex',
|
|
99
|
+
breakpoint ? isGrid && 'flex-wrap' : 'flex-column',
|
|
100
|
+
)}
|
|
101
|
+
>
|
|
102
|
+
{breakpoint
|
|
103
|
+
? options.map(
|
|
104
|
+
(
|
|
105
|
+
{ description, disabled, href, target, media: { block }, onClick, title },
|
|
106
|
+
key,
|
|
107
|
+
) => (
|
|
108
|
+
<Tile
|
|
109
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
110
|
+
key={`tile-${key}`}
|
|
111
|
+
className={classNames(`np-decision__tile${isSmall ? '--small' : ''}`, {
|
|
112
|
+
'np-decision__tile--fixed-width': isGrid,
|
|
113
|
+
})}
|
|
114
|
+
description={description}
|
|
115
|
+
disabled={disabled}
|
|
116
|
+
href={href}
|
|
117
|
+
target={target}
|
|
118
|
+
media={block}
|
|
119
|
+
size={isSmall ? Size.SMALL : Size.MEDIUM}
|
|
120
|
+
title={title}
|
|
121
|
+
onClick={onClick}
|
|
122
|
+
/>
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
: renderedOptions}
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
// LIST
|
|
131
|
+
return <>{renderedOptions}</>;
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export default Decision;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, DecisionPresentation, DecisionType } from './Decision';
|
package/src/i18n/zh-HK.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"neptune.ClearButton.ariaLabel": "清除",
|
|
5
5
|
"neptune.CloseButton.ariaLabel": "關閉",
|
|
6
6
|
"neptune.DateInput.day.label": "日",
|
|
7
|
-
"neptune.DateInput.day.placeholder": "
|
|
7
|
+
"neptune.DateInput.day.placeholder": "DD",
|
|
8
8
|
"neptune.DateInput.month.label": "月",
|
|
9
9
|
"neptune.DateInput.year.label": "年",
|
|
10
|
-
"neptune.DateInput.year.placeholder": "
|
|
10
|
+
"neptune.DateInput.year.placeholder": "YYYY",
|
|
11
11
|
"neptune.DateLookup.day": "日",
|
|
12
12
|
"neptune.DateLookup.goTo20YearView": "切換至20年視圖",
|
|
13
13
|
"neptune.DateLookup.month": "月",
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Types
|
|
3
3
|
*/
|
|
4
|
+
export type { DecisionProps } from './decision/Decision';
|
|
4
5
|
export type { InputProps } from './inputs/Input';
|
|
5
6
|
export type { InputWithDisplayFormatProps } from './inputWithDisplayFormat';
|
|
6
7
|
export type { InputGroupProps } from './inputs/InputGroup';
|
|
@@ -13,7 +13,6 @@ import { usePromoCardContext } from './PromoCardContext';
|
|
|
13
13
|
import PromoCardIndicator, { PromoCardIndicatorProps } from './PromoCardIndicator';
|
|
14
14
|
|
|
15
15
|
export type ReferenceType = React.Ref<HTMLInputElement>;
|
|
16
|
-
export type LinkTarget = '_blank' | '_parent' | '_self' | '_top';
|
|
17
16
|
export type RelatedTypes =
|
|
18
17
|
| ''
|
|
19
18
|
| 'alternate'
|
|
@@ -98,7 +97,7 @@ export interface PromoCardLinkProps extends PromoCardCommonProps, Omit<CardProps
|
|
|
98
97
|
rel?: RelatedTypes;
|
|
99
98
|
|
|
100
99
|
/** Optional prop to to display where the linked URL will show */
|
|
101
|
-
target?:
|
|
100
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
102
101
|
|
|
103
102
|
/** Only applies to role="radio" or "checkbox" */
|
|
104
103
|
defaultChecked?: never;
|
package/src/tile/Tile.js
CHANGED
|
@@ -65,7 +65,7 @@ Tile.propTypes = {
|
|
|
65
65
|
className: PropTypes.string,
|
|
66
66
|
description: PropTypes.node,
|
|
67
67
|
disabled: PropTypes.bool,
|
|
68
|
-
href: PropTypes.string
|
|
68
|
+
href: PropTypes.string,
|
|
69
69
|
target: PropTypes.oneOf(['_self', '_blank', '_parent', '_top']),
|
|
70
70
|
/** Accepts only Avatar and images */
|
|
71
71
|
media: PropTypes.node.isRequired,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decisionEnums.d.ts","sourceRoot":"","sources":["../../../src/decision/decisionEnums.ts"],"names":[],"mappings":"AACA,oBAAY,YAAY;IACtB,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,eAAe,oBAAoB;CACpC;AAGD,oBAAY,IAAI;IACd,UAAU,eAAe;CAC1B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SizeSwapper.d.ts","sourceRoot":"","sources":["../../../src/sizeSwapper/SizeSwapper.js"],"names":[],"mappings":";AASA,yGAqCG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sizeSwapper/index.js"],"names":[],"mappings":""}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const isDateValid = (date: Date | string | null) => {
|
|
2
|
-
if (date === null) {
|
|
3
|
-
return false;
|
|
4
|
-
} else if (date instanceof Date) {
|
|
5
|
-
return validDateObject(date);
|
|
6
|
-
} else {
|
|
7
|
-
return validDateString(date);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const validDateString = (dateString: string) => validDateObject(new Date(dateString));
|
|
12
|
-
|
|
13
|
-
const validDateObject = (dateObject: Date) => !isNaN(dateObject.getTime());
|