@popsure/dirty-swan 0.45.0-alpha → 0.47.0
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/dist/cjs/index.js +421 -362
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/components/button/index.d.ts +4 -9
- package/dist/cjs/lib/components/button/index.stories.d.ts +2 -10
- package/dist/cjs/lib/components/dateSelector/components/Calendar.d.ts +16 -0
- package/dist/cjs/lib/components/dateSelector/index.d.ts +5 -7
- package/dist/cjs/lib/components/dateSelector/index.stories.d.ts +1 -1
- package/dist/cjs/lib/components/input/currency/input.stories.d.ts +7 -0
- package/dist/cjs/lib/components/input/index.d.ts +5 -3
- package/dist/cjs/lib/components/input/input.stories.d.ts +11 -3
- package/dist/cjs/lib/components/input/stories/config.d.ts +7 -0
- package/dist/esm/{index-f0e3bc9a.js → Calendar-62c6cf21.js} +24 -150
- package/dist/esm/Calendar-62c6cf21.js.map +1 -0
- package/dist/esm/components/button/index.js +2 -3
- package/dist/esm/components/button/index.js.map +1 -1
- package/dist/esm/components/button/index.stories.js +3 -16
- package/dist/esm/components/button/index.stories.js.map +1 -1
- package/dist/esm/components/card/index.js.map +1 -1
- package/dist/esm/components/card/index.stories.js +2 -2
- package/dist/esm/components/card/index.stories.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js +7 -10
- package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js.map +1 -1
- package/dist/esm/components/comparisonTable/index.js +2 -0
- package/dist/esm/components/comparisonTable/index.js.map +1 -1
- package/dist/esm/components/dateSelector/components/Calendar.js +11 -0
- package/dist/esm/components/dateSelector/components/Calendar.js.map +1 -0
- package/dist/esm/components/dateSelector/index.js +203 -7
- package/dist/esm/components/dateSelector/index.js.map +1 -1
- package/dist/esm/components/dateSelector/index.stories.js +14 -5
- package/dist/esm/components/dateSelector/index.stories.js.map +1 -1
- package/dist/esm/components/dateSelector/index.test.js +177 -23
- package/dist/esm/components/dateSelector/index.test.js.map +1 -1
- package/dist/esm/components/icon/icons/Info.js +2 -2
- package/dist/esm/components/icon/icons/Info.js.map +1 -1
- package/dist/esm/components/icon/icons.stories.js +1 -1
- package/dist/esm/components/icon/index.stories.js +1 -1
- package/dist/esm/components/input/currency/input.stories.js +1 -1
- package/dist/esm/components/input/iban/index.js +1 -1
- package/dist/esm/components/input/iban/index.js.map +1 -1
- package/dist/esm/components/input/index.js +10 -7
- package/dist/esm/components/input/index.js.map +1 -1
- package/dist/esm/components/input/input.stories.js +3 -3
- package/dist/esm/components/input/input.stories.js.map +1 -1
- package/dist/esm/{config-56f12c98.js → config-1d276a9d.js} +7 -2
- package/dist/esm/config-1d276a9d.js.map +1 -0
- package/dist/esm/{index-03b0133a.js → index-e506c4ca.js} +3 -3
- package/dist/esm/{index-03b0133a.js.map → index-e506c4ca.js.map} +1 -1
- package/dist/esm/index.js +4 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/components/button/index.d.ts +4 -9
- package/dist/esm/lib/components/button/index.stories.d.ts +2 -10
- package/dist/esm/lib/components/dateSelector/components/Calendar.d.ts +16 -0
- package/dist/esm/lib/components/dateSelector/index.d.ts +5 -7
- package/dist/esm/lib/components/dateSelector/index.stories.d.ts +1 -1
- package/dist/esm/lib/components/input/currency/input.stories.d.ts +7 -0
- package/dist/esm/lib/components/input/index.d.ts +5 -3
- package/dist/esm/lib/components/input/input.stories.d.ts +11 -3
- package/dist/esm/lib/components/input/stories/config.d.ts +7 -0
- package/package.json +1 -1
- package/src/lib/components/button/index.stories.tsx +1 -26
- package/src/lib/components/button/index.tsx +10 -21
- package/src/lib/components/card/index.tsx +1 -1
- package/src/lib/components/comparisonTable/components/TableInfoButton/index.tsx +5 -30
- package/src/lib/components/comparisonTable/components/TableInfoButton/style.module.scss +6 -2
- package/src/lib/components/dateSelector/components/Calendar.tsx +112 -0
- package/src/lib/components/dateSelector/{datepicker.scss → components/datepicker.scss} +4 -4
- package/src/lib/components/dateSelector/components/style.module.scss +3 -0
- package/src/lib/components/dateSelector/index.stories.tsx +18 -8
- package/src/lib/components/dateSelector/index.test.tsx +118 -20
- package/src/lib/components/dateSelector/index.tsx +196 -227
- package/src/lib/components/dateSelector/style.module.scss +6 -79
- package/src/lib/components/input/iban/index.tsx +1 -1
- package/src/lib/components/input/index.tsx +13 -7
- package/src/lib/components/input/input.stories.tsx +2 -0
- package/src/lib/components/input/stories/config.ts +6 -1
- package/src/lib/components/input/style.module.scss +8 -1
- package/dist/esm/config-56f12c98.js.map +0 -1
- package/dist/esm/index-f0e3bc9a.js.map +0 -1
- package/src/lib/components/dateSelector/icons/chevron-left.svg +0 -3
- package/src/lib/components/dateSelector/icons/chevron-right.svg +0 -3
- package/src/lib/components/dateSelector/index.test.ts +0 -33
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import DayPicker from 'react-day-picker';
|
|
4
|
+
|
|
5
|
+
import { useOnClickOutside } from '../../../hooks/useOnClickOutside';
|
|
6
|
+
import { CalendarIcon } from '../../icon/icons';
|
|
7
|
+
|
|
8
|
+
import styles from './style.module.scss';
|
|
9
|
+
import './datepicker.scss';
|
|
10
|
+
import { Button } from '../../button';
|
|
11
|
+
|
|
12
|
+
export interface CalendarProps {
|
|
13
|
+
dateFormat: string;
|
|
14
|
+
value?: string;
|
|
15
|
+
onChange: (date: string) => void;
|
|
16
|
+
yearBoundaries: { min: number; max: number };
|
|
17
|
+
displayCalendar?: boolean;
|
|
18
|
+
dayjsLocale?: ILocale;
|
|
19
|
+
firstDayOfWeek?: number;
|
|
20
|
+
isOpen?: boolean;
|
|
21
|
+
setCalendarOpen: (isOpen: boolean) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const Calendar = ({
|
|
25
|
+
dateFormat,
|
|
26
|
+
value,
|
|
27
|
+
onChange,
|
|
28
|
+
yearBoundaries,
|
|
29
|
+
displayCalendar,
|
|
30
|
+
dayjsLocale,
|
|
31
|
+
firstDayOfWeek,
|
|
32
|
+
setCalendarOpen,
|
|
33
|
+
isOpen
|
|
34
|
+
}: CalendarProps) => {
|
|
35
|
+
const localeDate = dayjsLocale
|
|
36
|
+
? dayjs().locale(dayjsLocale).localeData()
|
|
37
|
+
: dayjs().locale('en').localeData();
|
|
38
|
+
|
|
39
|
+
const localizedWeekdays = localeDate.weekdays();
|
|
40
|
+
const localizedWeekdaysShort = localeDate.weekdaysShort();
|
|
41
|
+
const localizedMonths = localeDate.months();
|
|
42
|
+
|
|
43
|
+
const calendarContainerRef = useRef<HTMLDivElement | null>(null);
|
|
44
|
+
|
|
45
|
+
const calendarDefaultDate =
|
|
46
|
+
dayjs().year() >= yearBoundaries.min && dayjs().year() <= yearBoundaries.max
|
|
47
|
+
? dayjs().toDate()
|
|
48
|
+
: dayjs().set('year', yearBoundaries.max).toDate();
|
|
49
|
+
|
|
50
|
+
const selectedDateInDateType = value
|
|
51
|
+
? dayjs(value).toDate()
|
|
52
|
+
: calendarDefaultDate;
|
|
53
|
+
const dateCalendarFromMonth = dayjs(String(yearBoundaries.min))
|
|
54
|
+
.startOf('year')
|
|
55
|
+
.toDate();
|
|
56
|
+
const dateCalendarToMonth = dayjs(String(yearBoundaries.max))
|
|
57
|
+
.endOf('year')
|
|
58
|
+
.toDate();
|
|
59
|
+
|
|
60
|
+
useOnClickOutside(calendarContainerRef, () => setCalendarOpen(false));
|
|
61
|
+
|
|
62
|
+
if (!displayCalendar) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
className={`${styles.container} ml8`}
|
|
69
|
+
ref={calendarContainerRef}
|
|
70
|
+
>
|
|
71
|
+
<Button
|
|
72
|
+
onClick={() => setCalendarOpen(!isOpen)}
|
|
73
|
+
data-testid="calendar-button"
|
|
74
|
+
hideLabel
|
|
75
|
+
variant='textColor'
|
|
76
|
+
leftIcon={<CalendarIcon />}
|
|
77
|
+
>
|
|
78
|
+
Select date
|
|
79
|
+
</Button>
|
|
80
|
+
|
|
81
|
+
{isOpen && (
|
|
82
|
+
<DayPicker
|
|
83
|
+
month={selectedDateInDateType}
|
|
84
|
+
showOutsideDays={true}
|
|
85
|
+
fromMonth={dateCalendarFromMonth}
|
|
86
|
+
toMonth={dateCalendarToMonth}
|
|
87
|
+
selectedDays={selectedDateInDateType}
|
|
88
|
+
onDayClick={(date: Date) => {
|
|
89
|
+
if (
|
|
90
|
+
dayjs(date).isAfter(dateCalendarFromMonth) ||
|
|
91
|
+
dayjs(date).isBefore(dateCalendarToMonth)
|
|
92
|
+
) {
|
|
93
|
+
const selectedDate = dayjs(date).format(dateFormat);
|
|
94
|
+
onChange(selectedDate);
|
|
95
|
+
setCalendarOpen(false);
|
|
96
|
+
}
|
|
97
|
+
}}
|
|
98
|
+
pagedNavigation={true}
|
|
99
|
+
disabledDays={{
|
|
100
|
+
before: dateCalendarFromMonth,
|
|
101
|
+
after: dateCalendarToMonth,
|
|
102
|
+
}}
|
|
103
|
+
firstDayOfWeek={firstDayOfWeek}
|
|
104
|
+
locale={dayjsLocale?.name || 'en'}
|
|
105
|
+
months={localizedMonths}
|
|
106
|
+
weekdaysLong={localizedWeekdays}
|
|
107
|
+
weekdaysShort={localizedWeekdaysShort}
|
|
108
|
+
/>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
@use '
|
|
2
|
-
@use '
|
|
1
|
+
@use '../../../scss/public/grid' as *;
|
|
2
|
+
@use '../../../scss/public/colors' as *;
|
|
3
3
|
|
|
4
4
|
.DayPickerInput {
|
|
5
5
|
cursor: pointer;
|
|
@@ -281,12 +281,12 @@
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
.DayPicker-NavButton--prev {
|
|
284
|
-
background-image: url('
|
|
284
|
+
background-image: url('../../icon/assets/chevron-left.svg');
|
|
285
285
|
margin-left: 16px;
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
.DayPicker-NavButton--next {
|
|
289
|
-
background-image: url('
|
|
289
|
+
background-image: url('../../icon/assets/chevron-right.svg');
|
|
290
290
|
margin-right: 16px;
|
|
291
291
|
}
|
|
292
292
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
1
2
|
import { DateSelector, DateSelectorProps } from '.';
|
|
2
3
|
import de from 'dayjs/locale/de';
|
|
3
4
|
|
|
@@ -71,14 +72,23 @@ export const DateSelectorStory = ({
|
|
|
71
72
|
onChange,
|
|
72
73
|
yearBoundaries,
|
|
73
74
|
value
|
|
74
|
-
}: DateSelectorProps) =>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
value
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
}: DateSelectorProps) => {
|
|
76
|
+
const [newValue, setValue] = useState(value);
|
|
77
|
+
|
|
78
|
+
const handleOnChange = (value: string) => {
|
|
79
|
+
setValue(value)
|
|
80
|
+
onChange?.(value);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<DateSelector
|
|
85
|
+
onChange={handleOnChange}
|
|
86
|
+
displayCalendar={displayCalendar}
|
|
87
|
+
yearBoundaries={yearBoundaries}
|
|
88
|
+
value={newValue}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
82
92
|
|
|
83
93
|
DateSelectorStory.storyName = "DateSelector";
|
|
84
94
|
|
|
@@ -2,7 +2,7 @@ import { render } from '../../util/testUtils';
|
|
|
2
2
|
|
|
3
3
|
import { DateSelector } from '.';
|
|
4
4
|
|
|
5
|
-
const setup = (date
|
|
5
|
+
const setup = (date?: string, onChange: (date: string) => void = () => {}) => {
|
|
6
6
|
return render(
|
|
7
7
|
<DateSelector
|
|
8
8
|
value={date}
|
|
@@ -14,40 +14,138 @@ const setup = (date: string, onChange: (date: string) => void = () => {}) => {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
describe('DateSelector component', () => {
|
|
17
|
-
it('should
|
|
17
|
+
it('should show the value inside the inputs', () => {
|
|
18
|
+
const date = '2024-01-01';
|
|
19
|
+
const { getByTestId } = setup(date);
|
|
20
|
+
|
|
21
|
+
expect(getByTestId('date-selector-day')).toHaveValue('1');
|
|
22
|
+
expect(getByTestId('date-selector-month')).toHaveValue('1');
|
|
23
|
+
expect(getByTestId('date-selector-year')).toHaveValue('2024');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should call onChange with the value changed', async () => {
|
|
27
|
+
const callback = jest.fn();
|
|
28
|
+
const { getByTestId, user } = setup(undefined, callback);
|
|
29
|
+
|
|
30
|
+
await user.type(getByTestId('date-selector-day'), '5');
|
|
31
|
+
await user.type(getByTestId('date-selector-month'), '7');
|
|
32
|
+
await user.type(getByTestId('date-selector-year'), '2023');
|
|
33
|
+
|
|
34
|
+
expect(getByTestId('date-selector-day')).toHaveValue('5');
|
|
35
|
+
expect(getByTestId('date-selector-month')).toHaveValue('7');
|
|
36
|
+
expect(getByTestId('date-selector-year')).toHaveValue('2023');
|
|
37
|
+
expect(callback).toHaveBeenCalledWith('2023-07-05');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should call onChange with the value changed with initial value', async () => {
|
|
41
|
+
const callback = jest.fn();
|
|
42
|
+
const date = '2024-01-01';
|
|
43
|
+
const { getByTestId, user } = setup(date, callback);
|
|
44
|
+
|
|
45
|
+
await user.type(getByTestId('date-selector-day'), '{backspace}3');
|
|
46
|
+
await user.type(getByTestId('date-selector-month'), '{backspace}7');
|
|
47
|
+
await user.type(getByTestId('date-selector-year'), '{backspace}3');
|
|
48
|
+
|
|
49
|
+
expect(getByTestId('date-selector-day')).toHaveValue('3');
|
|
50
|
+
expect(getByTestId('date-selector-month')).toHaveValue('7');
|
|
51
|
+
expect(getByTestId('date-selector-year')).toHaveValue('2023');
|
|
52
|
+
expect(callback).toHaveBeenCalledWith('2023-07-03');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should call onChange empty when invalid date', async () => {
|
|
56
|
+
const callback = jest.fn();
|
|
57
|
+
const { getByTestId, user } = setup(undefined, callback);
|
|
58
|
+
|
|
59
|
+
await user.type(getByTestId('date-selector-day'), '5');
|
|
60
|
+
|
|
61
|
+
expect(getByTestId('date-selector-day')).toHaveValue('5');
|
|
62
|
+
expect(callback).toHaveBeenCalledWith('');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should call onChange empty when year out of boundaries', async () => {
|
|
18
66
|
const callback = jest.fn();
|
|
19
67
|
const date = '2024-01-01';
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
68
|
+
const { getByTestId, user } = setup(date, callback);
|
|
69
|
+
|
|
70
|
+
await user.type(getByTestId('date-selector-year'), '{backspace}{backspace}30');
|
|
71
|
+
|
|
72
|
+
expect(getByTestId('date-selector-year')).toHaveValue('2030');
|
|
73
|
+
expect(callback).toHaveBeenCalledWith('');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should call onChange when year in boundaries after being out of boundaries', async () => {
|
|
77
|
+
const callback = jest.fn();
|
|
78
|
+
const date = '2030-01-01';
|
|
79
|
+
const { getByTestId, user } = setup(date, callback);
|
|
23
80
|
|
|
24
|
-
await user.
|
|
81
|
+
await user.type(getByTestId('date-selector-year'), '{backspace}{backspace}23');
|
|
25
82
|
|
|
26
|
-
|
|
83
|
+
expect(getByTestId('date-selector-year')).toHaveValue('2023');
|
|
84
|
+
expect(callback).toHaveBeenCalledWith('2023-01-01');
|
|
85
|
+
});
|
|
27
86
|
|
|
28
|
-
|
|
87
|
+
it('should call onChange with the value changed', async () => {
|
|
88
|
+
const callback = jest.fn();
|
|
89
|
+
const date = '2024-01-01';
|
|
90
|
+
const { getByTestId, user } = setup(date, callback);
|
|
29
91
|
|
|
30
|
-
|
|
92
|
+
await user.type(getByTestId('date-selector-day'), '{backspace}3');
|
|
93
|
+
await user.type(getByTestId('date-selector-month'), '{backspace}7');
|
|
94
|
+
await user.type(getByTestId('date-selector-year'), '{backspace}3');
|
|
31
95
|
|
|
32
|
-
expect(
|
|
96
|
+
expect(getByTestId('date-selector-day')).toHaveValue('3');
|
|
97
|
+
expect(getByTestId('date-selector-month')).toHaveValue('7');
|
|
98
|
+
expect(callback).toHaveBeenCalledWith('2023-07-03');
|
|
33
99
|
});
|
|
34
100
|
|
|
35
|
-
it('should
|
|
101
|
+
it('should navigate inputs from day to month when day is over 3', async () => {
|
|
36
102
|
const callback = jest.fn();
|
|
37
103
|
const date = '2024-01-01';
|
|
38
|
-
const { getByTestId,
|
|
39
|
-
|
|
104
|
+
const { getByTestId, user } = setup(date, callback);
|
|
105
|
+
|
|
106
|
+
await user.type(getByTestId('date-selector-day'), '{backspace}45');
|
|
107
|
+
|
|
108
|
+
expect(getByTestId('date-selector-day')).toHaveValue('4');
|
|
109
|
+
expect(getByTestId('date-selector-month')).toHaveValue('5');
|
|
110
|
+
expect(callback).toHaveBeenCalledWith('2024-05-04');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('Calendar button', () => {
|
|
114
|
+
it('should return the selected date when clicking on the calendar', async () => {
|
|
115
|
+
const callback = jest.fn();
|
|
116
|
+
const date = '2024-01-01';
|
|
117
|
+
const expectedDate = '2024-01-17';
|
|
118
|
+
const { getByTestId, getByLabelText, user } = setup(date, callback);
|
|
119
|
+
const button = getByTestId('calendar-button');
|
|
120
|
+
|
|
121
|
+
await user.click(button);
|
|
122
|
+
|
|
123
|
+
const calendarCell = getByLabelText(/17 2024/);
|
|
124
|
+
|
|
125
|
+
await user.click(calendarCell);
|
|
126
|
+
|
|
127
|
+
expect(callback).toHaveBeenCalledWith(expectedDate);
|
|
128
|
+
|
|
129
|
+
expect(calendarCell).not.toBeVisible();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should close the calendar when clicking outside', async () => {
|
|
133
|
+
const callback = jest.fn();
|
|
134
|
+
const date = '2024-01-01';
|
|
135
|
+
const { getByTestId, getByLabelText, user } = setup(date, callback);
|
|
136
|
+
const button = getByTestId('calendar-button');
|
|
40
137
|
|
|
41
|
-
|
|
138
|
+
await user.click(button);
|
|
42
139
|
|
|
43
|
-
|
|
44
|
-
|
|
140
|
+
const calendarCell = getByLabelText(/17 2024/);
|
|
141
|
+
expect(calendarCell).toBeVisible();
|
|
45
142
|
|
|
46
|
-
|
|
47
|
-
|
|
143
|
+
// click outside the calendar
|
|
144
|
+
await user.click(document.body);
|
|
48
145
|
|
|
49
|
-
|
|
146
|
+
expect(callback).not.toHaveBeenCalled();
|
|
50
147
|
|
|
51
|
-
|
|
148
|
+
expect(calendarCell).not.toBeVisible();
|
|
149
|
+
});
|
|
52
150
|
});
|
|
53
151
|
});
|