@popsure/dirty-swan 0.48.1 → 0.49.2
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 +79 -64
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/components/comparisonTable/components/Row/index.d.ts +1 -0
- package/dist/cjs/lib/components/comparisonTable/components/TableRowHeader/index.d.ts +1 -1
- package/dist/cjs/lib/components/comparisonTable/hooks/useComparisonTable.d.ts +3 -2
- package/dist/cjs/lib/components/comparisonTable/index.d.ts +14 -4
- package/dist/cjs/lib/components/dateSelector/index.d.ts +2 -0
- package/dist/esm/components/comparisonTable/components/AccordionItem/AccordionItem.js +2 -2
- package/dist/esm/components/comparisonTable/components/AccordionItem/AccordionItem.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/Row/index.js +11 -4
- package/dist/esm/components/comparisonTable/components/Row/index.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableArrows/index.js +4 -2
- package/dist/esm/components/comparisonTable/components/TableArrows/index.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableButton/index.js +9 -4
- package/dist/esm/components/comparisonTable/components/TableButton/index.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableButton/index.test.js +13 -7
- package/dist/esm/components/comparisonTable/components/TableButton/index.test.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js +1 -1
- package/dist/esm/components/comparisonTable/components/TableInfoButton/index.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableRowHeader/index.js +9 -2
- package/dist/esm/components/comparisonTable/components/TableRowHeader/index.js.map +1 -1
- package/dist/esm/components/comparisonTable/components/TableRowHeader/index.test.js +20 -17
- package/dist/esm/components/comparisonTable/components/TableRowHeader/index.test.js.map +1 -1
- package/dist/esm/components/comparisonTable/index.js +28 -33
- package/dist/esm/components/comparisonTable/index.js.map +1 -1
- package/dist/esm/components/dateSelector/index.js +23 -15
- package/dist/esm/components/dateSelector/index.js.map +1 -1
- package/dist/esm/components/dateSelector/index.test.js +36 -2
- package/dist/esm/components/dateSelector/index.test.js.map +1 -1
- package/dist/esm/lib/components/comparisonTable/components/Row/index.d.ts +1 -0
- package/dist/esm/lib/components/comparisonTable/components/TableRowHeader/index.d.ts +1 -1
- package/dist/esm/lib/components/comparisonTable/hooks/useComparisonTable.d.ts +3 -2
- package/dist/esm/lib/components/comparisonTable/index.d.ts +14 -4
- package/dist/esm/lib/components/dateSelector/index.d.ts +2 -0
- package/package.json +3 -3
- package/src/lib/components/comparisonTable/components/AccordionItem/AccordionItem.module.scss +3 -5
- package/src/lib/components/comparisonTable/components/AccordionItem/AccordionItem.tsx +2 -2
- package/src/lib/components/comparisonTable/components/Row/index.tsx +16 -13
- package/src/lib/components/comparisonTable/components/Row/style.module.scss +13 -9
- package/src/lib/components/comparisonTable/components/TableArrows/index.tsx +2 -0
- package/src/lib/components/comparisonTable/components/TableArrows/style.module.scss +4 -0
- package/src/lib/components/comparisonTable/components/TableButton/index.test.tsx +7 -8
- package/src/lib/components/comparisonTable/components/TableButton/index.tsx +9 -9
- package/src/lib/components/comparisonTable/components/TableButton/style.module.scss +7 -24
- package/src/lib/components/comparisonTable/components/TableInfoButton/index.tsx +1 -0
- package/src/lib/components/comparisonTable/components/TableRowHeader/index.test.tsx +18 -22
- package/src/lib/components/comparisonTable/components/TableRowHeader/index.tsx +16 -9
- package/src/lib/components/comparisonTable/hooks/useComparisonTable.ts +8 -18
- package/src/lib/components/comparisonTable/index.stories.mdx +55 -25
- package/src/lib/components/comparisonTable/index.tsx +64 -25
- package/src/lib/components/comparisonTable/style.module.scss +23 -8
- package/src/lib/components/dateSelector/index.test.tsx +32 -2
- package/src/lib/components/dateSelector/index.tsx +40 -21
|
@@ -47,16 +47,27 @@ export interface ComparisonTableProps<T> {
|
|
|
47
47
|
headers: Array<TableHeader<T>>;
|
|
48
48
|
data: Array<T>;
|
|
49
49
|
hideDetails?: boolean;
|
|
50
|
+
hideDetailsCaption?: string;
|
|
51
|
+
showDetailsCaption?: string;
|
|
50
52
|
hideScrollBars?: boolean;
|
|
53
|
+
hideScrollBarsMobile?: boolean;
|
|
51
54
|
collapsibleSections?: boolean;
|
|
52
55
|
cellWidth?: number;
|
|
53
56
|
firstColumnWidth?: number;
|
|
54
57
|
stickyHeaderTopOffset?: number;
|
|
55
58
|
growContent?: boolean;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
classNameOverrides?: ClassNameOverrides;
|
|
60
|
+
onSelectionChanged?: (selectedIndex: number) => void;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface ClassNameOverrides {
|
|
64
|
+
header?: string;
|
|
65
|
+
container?: string;
|
|
66
|
+
cell?: string;
|
|
67
|
+
headerCell?: string;
|
|
68
|
+
collapsibleSection?: string;
|
|
69
|
+
section?: string;
|
|
70
|
+
hideDetailsButton?: string;
|
|
60
71
|
}
|
|
61
72
|
|
|
62
73
|
const ComparisonTable = <T extends { id: number }>(
|
|
@@ -66,13 +77,17 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
66
77
|
headers,
|
|
67
78
|
data,
|
|
68
79
|
hideDetails,
|
|
69
|
-
|
|
80
|
+
hideDetailsCaption = 'Hide details',
|
|
81
|
+
showDetailsCaption = 'Show details',
|
|
82
|
+
classNameOverrides,
|
|
70
83
|
hideScrollBars,
|
|
84
|
+
hideScrollBarsMobile,
|
|
71
85
|
collapsibleSections,
|
|
72
86
|
cellWidth,
|
|
73
87
|
firstColumnWidth,
|
|
74
88
|
stickyHeaderTopOffset,
|
|
75
89
|
growContent,
|
|
90
|
+
onSelectionChanged,
|
|
76
91
|
} = props;
|
|
77
92
|
|
|
78
93
|
const {
|
|
@@ -85,8 +100,7 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
85
100
|
handleArrowsClick,
|
|
86
101
|
toggleMoreRows,
|
|
87
102
|
showMore,
|
|
88
|
-
|
|
89
|
-
} = useComparisonTable();
|
|
103
|
+
} = useComparisonTable({ onSelectionChanged });
|
|
90
104
|
|
|
91
105
|
const cssVariablesStyle = {
|
|
92
106
|
'--tableWidth': `${headerWidth}px`,
|
|
@@ -101,16 +115,19 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
101
115
|
} as React.CSSProperties;
|
|
102
116
|
|
|
103
117
|
return (
|
|
104
|
-
<ScrollSync
|
|
105
|
-
<div
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
<ScrollSync>
|
|
119
|
+
<div
|
|
120
|
+
style={cssVariablesStyle}
|
|
121
|
+
className={classNames({
|
|
122
|
+
[baseStyles.noScrollBars]: hideScrollBars,
|
|
123
|
+
[baseStyles.noScrollBarsMobile]: hideScrollBarsMobile,
|
|
124
|
+
})}
|
|
125
|
+
>
|
|
126
|
+
<div
|
|
127
|
+
className={classNames(baseStyles.header, classNameOverrides?.header)}
|
|
128
|
+
>
|
|
129
|
+
<ScrollSyncPane innerRef={scrollContainerCallbackRef}>
|
|
130
|
+
<div className={classNames(baseStyles.container)}>
|
|
114
131
|
<div className={classNames(baseStyles['overflow-container'])}>
|
|
115
132
|
<div className={baseStyles['group-container']}>
|
|
116
133
|
<TableArrows
|
|
@@ -126,6 +143,7 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
126
143
|
cell={headers[0].cells[0]}
|
|
127
144
|
data={data}
|
|
128
145
|
isRowHeader
|
|
146
|
+
cellClassName={classNameOverrides?.headerCell}
|
|
129
147
|
/>
|
|
130
148
|
</div>
|
|
131
149
|
</div>
|
|
@@ -148,7 +166,13 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
148
166
|
if (index === 0 && headerGroupIndex === 0) return null;
|
|
149
167
|
|
|
150
168
|
return (
|
|
151
|
-
<Row<T>
|
|
169
|
+
<Row<T>
|
|
170
|
+
key={rowId}
|
|
171
|
+
rowId={rowId}
|
|
172
|
+
cell={cell}
|
|
173
|
+
data={data}
|
|
174
|
+
cellClassName={classNameOverrides?.cell}
|
|
175
|
+
/>
|
|
152
176
|
);
|
|
153
177
|
});
|
|
154
178
|
|
|
@@ -158,7 +182,10 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
158
182
|
<Fragment key={idString}>
|
|
159
183
|
{headerGroup.label && collapsibleSections ? (
|
|
160
184
|
<AccordionItem
|
|
161
|
-
className=
|
|
185
|
+
className={classNames(
|
|
186
|
+
'mt16',
|
|
187
|
+
classNameOverrides?.collapsibleSection
|
|
188
|
+
)}
|
|
162
189
|
label={headerGroup.label}
|
|
163
190
|
headerClassName="p24 br8"
|
|
164
191
|
isOpen={selectedSection === idString}
|
|
@@ -169,7 +196,8 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
169
196
|
<div
|
|
170
197
|
className={classNames(
|
|
171
198
|
baseStyles.container,
|
|
172
|
-
|
|
199
|
+
'pb16',
|
|
200
|
+
classNameOverrides?.container,
|
|
173
201
|
{
|
|
174
202
|
[baseStyles.noScrollBars]: hideScrollBars,
|
|
175
203
|
}
|
|
@@ -188,12 +216,19 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
188
216
|
</ScrollSyncPane>
|
|
189
217
|
</AccordionItem>
|
|
190
218
|
) : (
|
|
191
|
-
<
|
|
219
|
+
<section
|
|
220
|
+
key={idString}
|
|
221
|
+
className={classNames(
|
|
222
|
+
baseStyles.section,
|
|
223
|
+
classNameOverrides?.section
|
|
224
|
+
)}
|
|
225
|
+
>
|
|
192
226
|
<ScrollSyncPane>
|
|
193
227
|
<div
|
|
194
228
|
className={classNames(
|
|
195
229
|
baseStyles.container,
|
|
196
|
-
|
|
230
|
+
'pb16',
|
|
231
|
+
classNameOverrides?.container,
|
|
197
232
|
{
|
|
198
233
|
[baseStyles.noScrollBars]: hideScrollBars,
|
|
199
234
|
}
|
|
@@ -224,7 +259,7 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
224
259
|
</div>
|
|
225
260
|
</div>
|
|
226
261
|
</ScrollSyncPane>
|
|
227
|
-
</
|
|
262
|
+
</section>
|
|
228
263
|
)}
|
|
229
264
|
</Fragment>
|
|
230
265
|
);
|
|
@@ -239,11 +274,15 @@ const ComparisonTable = <T extends { id: number }>(
|
|
|
239
274
|
>
|
|
240
275
|
<div>
|
|
241
276
|
<button
|
|
242
|
-
className={
|
|
277
|
+
className={classNames(
|
|
278
|
+
'w100 d-flex p-a p-h4 c-pointer',
|
|
279
|
+
baseStyles['show-details-button'],
|
|
280
|
+
classNameOverrides?.hideDetailsButton
|
|
281
|
+
)}
|
|
243
282
|
onClick={toggleMoreRows}
|
|
244
283
|
type="button"
|
|
245
284
|
>
|
|
246
|
-
{showMore ?
|
|
285
|
+
{showMore ? hideDetailsCaption : showDetailsCaption}
|
|
247
286
|
<Chevron
|
|
248
287
|
className={showMore ? '' : baseStyles['icon-inverted']}
|
|
249
288
|
/>
|
|
@@ -21,9 +21,30 @@
|
|
|
21
21
|
width: 0;
|
|
22
22
|
height: 0;
|
|
23
23
|
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.noScrollBarsMobile {
|
|
27
|
+
@include p-size-mobile {
|
|
28
|
+
* {
|
|
29
|
+
// Disable the scrollbar in all browsers
|
|
30
|
+
scrollbar-width: none; /* Firefox */
|
|
31
|
+
-ms-overflow-style: none; /* Internet Explorer 10+ */
|
|
32
|
+
-webkit-scrollbar {
|
|
33
|
+
/* WebKit */
|
|
34
|
+
width: 0;
|
|
35
|
+
height: 0;
|
|
36
|
+
display: none;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.section + .section {
|
|
43
|
+
margin-top: 48px;
|
|
24
44
|
|
|
25
|
-
|
|
26
|
-
|
|
45
|
+
@include p-size-tablet {
|
|
46
|
+
margin-top: 72px;
|
|
47
|
+
}
|
|
27
48
|
}
|
|
28
49
|
|
|
29
50
|
.overflow-container {
|
|
@@ -44,16 +65,10 @@
|
|
|
44
65
|
background-color: $ds-grey-100;
|
|
45
66
|
border-radius: 8px;
|
|
46
67
|
|
|
47
|
-
margin-top: 48px;
|
|
48
|
-
|
|
49
68
|
& > h4 {
|
|
50
69
|
padding: 24px;
|
|
51
70
|
display: inline-block;
|
|
52
71
|
}
|
|
53
|
-
|
|
54
|
-
@include p-size-tablet {
|
|
55
|
-
margin-top: 72px;
|
|
56
|
-
}
|
|
57
72
|
}
|
|
58
73
|
|
|
59
74
|
.sticky {
|
|
@@ -52,14 +52,44 @@ describe('DateSelector component', () => {
|
|
|
52
52
|
expect(callback).toHaveBeenCalledWith('2023-07-03');
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
it('should call onChange
|
|
55
|
+
it('should not call onChange when there is an invalid date that has not been completely filled', async () => {
|
|
56
56
|
const callback = jest.fn();
|
|
57
57
|
const { getByLabelText, user } = setup(undefined, callback);
|
|
58
58
|
|
|
59
59
|
await user.type(getByLabelText('Day'), '5');
|
|
60
60
|
|
|
61
61
|
expect(getByLabelText('Day')).toHaveValue('5');
|
|
62
|
-
expect(callback).
|
|
62
|
+
expect(callback).not.toHaveBeenCalled();
|
|
63
|
+
|
|
64
|
+
await user.type(getByLabelText('Month'), '4');
|
|
65
|
+
|
|
66
|
+
expect(getByLabelText('Month')).toHaveValue('4');
|
|
67
|
+
expect(callback).not.toHaveBeenCalled();
|
|
68
|
+
|
|
69
|
+
await user.type(getByLabelText('Year'), '2020');
|
|
70
|
+
|
|
71
|
+
expect(getByLabelText('Year')).toHaveValue('2020');
|
|
72
|
+
expect(callback).toHaveBeenCalledWith("2020-04-05");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should show error boundaries error for min date onChange empty when year out of boundaries', async () => {
|
|
76
|
+
const callback = jest.fn();
|
|
77
|
+
const date = '2010-01-01';
|
|
78
|
+
const { getByTestId } = setup(date, callback);
|
|
79
|
+
|
|
80
|
+
expect(getByTestId('date-error-message')).toBeVisible();
|
|
81
|
+
expect(getByTestId('date-error-message')).toHaveTextContent('Please choose a date after 2019');
|
|
82
|
+
expect(callback).not.toHaveBeenCalled();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should show error boundaries error for ,ax date onChange empty when year out of boundaries', async () => {
|
|
86
|
+
const callback = jest.fn();
|
|
87
|
+
const date = '2100-01-01';
|
|
88
|
+
const { getByTestId } = setup(date, callback);
|
|
89
|
+
|
|
90
|
+
expect(getByTestId('date-error-message')).toBeVisible();
|
|
91
|
+
expect(getByTestId('date-error-message')).toHaveTextContent('Please choose a date before 2026');
|
|
92
|
+
expect(callback).not.toHaveBeenCalled();
|
|
63
93
|
});
|
|
64
94
|
|
|
65
95
|
it('should call onChange empty when year out of boundaries', async () => {
|
|
@@ -37,6 +37,8 @@ export interface DateSelectorProps {
|
|
|
37
37
|
year?: string;
|
|
38
38
|
yearFormat?: string;
|
|
39
39
|
error?: string;
|
|
40
|
+
errorBeforeMinYear?: string;
|
|
41
|
+
errorAfterMaxYear?: string;
|
|
40
42
|
};
|
|
41
43
|
firstDayOfWeek?: number;
|
|
42
44
|
inputProps?: (key: keyof CalendarDate) => Partial<DateSelectorInputProps>;
|
|
@@ -52,34 +54,37 @@ const defaultPlaceholders: DateSelectorProps["placeholders"] = {
|
|
|
52
54
|
error: "Please enter a valid date"
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
type
|
|
57
|
+
type ErrorType = 'afterMax' | 'beforeMin' | 'default';
|
|
56
58
|
|
|
57
59
|
const isDateValid = (
|
|
58
60
|
date: string | undefined,
|
|
59
|
-
yearBoundaries: DateSelectorProps["yearBoundaries"]
|
|
61
|
+
yearBoundaries: DateSelectorProps["yearBoundaries"],
|
|
62
|
+
dateObject: Partial<CalendarDate>,
|
|
60
63
|
): {
|
|
61
64
|
isValid: boolean;
|
|
62
|
-
|
|
65
|
+
errorType?: ErrorType;
|
|
63
66
|
} => {
|
|
64
67
|
const { min = 0, max = 0 } = yearBoundaries;
|
|
65
|
-
|
|
68
|
+
|
|
66
69
|
if (!date) {
|
|
67
|
-
return { isValid: false,
|
|
70
|
+
return { isValid: false, errorType: 'default' };
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
const isValidYear = dateObject?.year && String(dateObject?.year).length === 4;
|
|
74
|
+
|
|
70
75
|
if (max && dayjs(date).isAfter(`${max}-01-01`, 'year')) {
|
|
71
|
-
return { isValid: false,
|
|
76
|
+
return { isValid: false, errorType: isValidYear ? 'afterMax' : 'default' };
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
if (min && dayjs(date).isBefore(`${min}-01-01`, 'year')) {
|
|
75
|
-
return { isValid: false,
|
|
80
|
+
return { isValid: false, errorType: isValidYear ? 'beforeMin' : 'default' };
|
|
76
81
|
}
|
|
77
82
|
|
|
78
|
-
const
|
|
83
|
+
const isValidDate = dayjs(date, COLLECTABLE_DATE_FORMAT, true).isValid();
|
|
79
84
|
|
|
80
85
|
return {
|
|
81
|
-
isValid:
|
|
82
|
-
|
|
86
|
+
isValid: isValidDate,
|
|
87
|
+
errorType: 'default'
|
|
83
88
|
};
|
|
84
89
|
}
|
|
85
90
|
|
|
@@ -100,7 +105,7 @@ export const DateSelector = ({
|
|
|
100
105
|
|
|
101
106
|
const itemsRef = useRef<HTMLInputElement[]>([]);
|
|
102
107
|
const [isDirty, setIsDirty] = useState(false);
|
|
103
|
-
const [hasError, setHasError] = useState<
|
|
108
|
+
const [hasError, setHasError] = useState<ErrorType>();
|
|
104
109
|
const [isCalendarOpen, setIsCalendarOpen] = useState(false);
|
|
105
110
|
const [internalValue, setInternalValue] = useState<Partial<CalendarDate>>({});
|
|
106
111
|
|
|
@@ -108,9 +113,9 @@ export const DateSelector = ({
|
|
|
108
113
|
const calendarDateValue = value ? isoStringtoCalendarDate(value) : undefined;
|
|
109
114
|
|
|
110
115
|
if(value !== calendarDateValue && calendarDateValue?.day && calendarDateValue?.month && calendarDateValue?.year) {
|
|
111
|
-
const { isValid,
|
|
116
|
+
const { isValid, errorType } = isDateValid(value, yearBoundaries, calendarDateValue)
|
|
112
117
|
setInternalValue(calendarDateValue)
|
|
113
|
-
setHasError(isValid ? undefined :
|
|
118
|
+
setHasError(isValid ? undefined : errorType);
|
|
114
119
|
setIsDirty(true);
|
|
115
120
|
}
|
|
116
121
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -127,15 +132,19 @@ export const DateSelector = ({
|
|
|
127
132
|
year: tempValue.year || 0,
|
|
128
133
|
})
|
|
129
134
|
|
|
130
|
-
const { isValid,
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
const { isValid, errorType } = isDateValid(formattedDate, yearBoundaries, tempValue);
|
|
136
|
+
const isDateInValidFormat = dayjs(formattedDate, COLLECTABLE_DATE_FORMAT, true).isValid();
|
|
137
|
+
|
|
138
|
+
if (isDateInValidFormat) {
|
|
133
139
|
setIsDirty(true);
|
|
134
140
|
}
|
|
135
141
|
|
|
136
|
-
setHasError(isValid ? undefined :
|
|
137
|
-
onChange(isValid ? formattedDate : "");
|
|
142
|
+
setHasError(isValid ? undefined : errorType);
|
|
138
143
|
setIsCalendarOpen(false);
|
|
144
|
+
|
|
145
|
+
if (isDateInValidFormat || isDirty) {
|
|
146
|
+
onChange(isValid ? formattedDate : "");
|
|
147
|
+
}
|
|
139
148
|
};
|
|
140
149
|
|
|
141
150
|
const handleOnKeyDown = (event: KeyboardEvent<HTMLInputElement>, index: number) => {
|
|
@@ -212,7 +221,7 @@ export const DateSelector = ({
|
|
|
212
221
|
placeholder: placeholders?.[`${key}Format` as FormatPlaceholder] ?? "",
|
|
213
222
|
labelInsideInput: true,
|
|
214
223
|
value: internalValue[key] ?? '',
|
|
215
|
-
error:
|
|
224
|
+
error: hasError && isDirty,
|
|
216
225
|
type: "text",
|
|
217
226
|
inputMode: "numeric",
|
|
218
227
|
ref: (el: HTMLInputElement) => { itemsRef.current[index] = el },
|
|
@@ -249,8 +258,18 @@ export const DateSelector = ({
|
|
|
249
258
|
</div>
|
|
250
259
|
|
|
251
260
|
{hasError && isDirty && (
|
|
252
|
-
<p
|
|
253
|
-
{
|
|
261
|
+
<p
|
|
262
|
+
className={classNames(
|
|
263
|
+
hasError && isDirty ? 'd-block' : 'd-none',
|
|
264
|
+
"p-p--small tc-red-500 w100 mt8"
|
|
265
|
+
)}
|
|
266
|
+
data-testid="date-error-message"
|
|
267
|
+
>
|
|
268
|
+
{{
|
|
269
|
+
default: placeholders.error,
|
|
270
|
+
afterMax: placeholders.errorAfterMaxYear || `Please choose a date before ${yearBoundaries.max + 1}`,
|
|
271
|
+
beforeMin: placeholders.errorBeforeMinYear || `Please choose a date after ${yearBoundaries.min - 1}`,
|
|
272
|
+
}[hasError || "default"]}
|
|
254
273
|
</p>
|
|
255
274
|
)}
|
|
256
275
|
</div>
|