@popsure/dirty-swan 0.66.11 → 0.66.13
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 +50 -35
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/components/table/Table.d.ts +3 -1
- package/dist/cjs/lib/components/table/Table.stories.d.ts +10 -2
- package/dist/cjs/lib/components/table/components/TableCell/TableCell.d.ts +3 -1
- package/dist/cjs/lib/components/table/components/TableContents/TableContents.d.ts +2 -1
- package/dist/cjs/lib/components/table/components/TableSection/TableSection.d.ts +2 -1
- package/dist/cjs/lib/models/styles.d.ts +1 -1
- package/dist/esm/{TableSection-CEhD4eoy.js → TableSection-Cm50RX-V.js} +28 -9
- package/dist/esm/TableSection-Cm50RX-V.js.map +1 -0
- package/dist/esm/components/table/Table.js +10 -10
- package/dist/esm/components/table/Table.js.map +1 -1
- package/dist/esm/components/table/Table.stories.js +79 -6
- package/dist/esm/components/table/Table.stories.js.map +1 -1
- package/dist/esm/components/table/Table.test.js +7 -1
- package/dist/esm/components/table/Table.test.js.map +1 -1
- package/dist/esm/components/table/components/TableCell/BaseCell/BaseCell.js +1 -1
- package/dist/esm/components/table/components/TableCell/BaseCell/BaseCell.js.map +1 -1
- package/dist/esm/components/table/components/TableCell/TableCell.js +6 -4
- package/dist/esm/components/table/components/TableCell/TableCell.js.map +1 -1
- package/dist/esm/components/table/components/TableContents/TableContents.js +10 -16
- package/dist/esm/components/table/components/TableContents/TableContents.js.map +1 -1
- package/dist/esm/components/table/components/TableContents/TableContents.test.js +14 -2
- package/dist/esm/components/table/components/TableContents/TableContents.test.js.map +1 -1
- package/dist/esm/components/table/components/TableSection/TableSection.js +1 -1
- package/dist/esm/components/table/components/TableSection/TableSection.test.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/lib/components/table/Table.d.ts +3 -1
- package/dist/esm/lib/components/table/Table.stories.d.ts +10 -2
- package/dist/esm/lib/components/table/components/TableCell/TableCell.d.ts +3 -1
- package/dist/esm/lib/components/table/components/TableContents/TableContents.d.ts +2 -1
- package/dist/esm/lib/components/table/components/TableSection/TableSection.d.ts +2 -1
- package/dist/esm/lib/models/styles.d.ts +1 -1
- package/package.json +1 -1
- package/src/lib/components/table/Table.module.scss +3 -0
- package/src/lib/components/table/Table.stories.tsx +92 -1
- package/src/lib/components/table/Table.test.tsx +15 -0
- package/src/lib/components/table/Table.tsx +27 -20
- package/src/lib/components/table/components/TableCell/BaseCell/BaseCell.tsx +1 -1
- package/src/lib/components/table/components/TableCell/TableCell.module.scss +9 -3
- package/src/lib/components/table/components/TableCell/TableCell.tsx +7 -1
- package/src/lib/components/table/components/TableContents/TableContents.module.scss +23 -24
- package/src/lib/components/table/components/TableContents/TableContents.test.tsx +22 -1
- package/src/lib/components/table/components/TableContents/TableContents.tsx +42 -33
- package/src/lib/components/table/components/TableSection/TableSection.module.scss +7 -0
- package/src/lib/components/table/components/TableSection/TableSection.tsx +32 -3
- package/src/lib/models/styles.ts +1 -0
- package/dist/esm/TableSection-CEhD4eoy.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { TableProps } from './Table';
|
|
|
2
2
|
import { TableData } from './types';
|
|
3
3
|
declare const story: {
|
|
4
4
|
title: string;
|
|
5
|
-
component: ({ cellReplacements, className, collapsibleSections, hideColumns, hideDetails, hideRows, imageComponent, modalContentRenderer, onModalOpen, onSelectionChanged, scrollOnOpen, scrollTopOffset, stickyHeaderTopOffset, tableData, textOverrides: definedTextOverrides, title, activeSection: externalActiveSection, hideTableNavigation, }: TableProps) => JSX.Element;
|
|
5
|
+
component: ({ cellReplacements, className, collapsibleSections, hideColumns, hideDetails, hideRows, imageComponent, modalContentRenderer, onModalOpen, onSelectionChanged, scrollOnOpen, scrollTopOffset, stickyHeaderTopOffset, tableData, textOverrides: definedTextOverrides, title, activeSection: externalActiveSection, hideTableNavigation, hideStickyHeader, showSelectedColumn, }: TableProps) => JSX.Element;
|
|
6
6
|
argTypes: {
|
|
7
7
|
tableData: {
|
|
8
8
|
subContent: string;
|
|
@@ -22,6 +22,9 @@ declare const story: {
|
|
|
22
22
|
hideDetails: {
|
|
23
23
|
subContent: string;
|
|
24
24
|
};
|
|
25
|
+
hideStickyHeader: {
|
|
26
|
+
subContent: string;
|
|
27
|
+
};
|
|
25
28
|
stickyHeaderTopOffset: {
|
|
26
29
|
subContent: string;
|
|
27
30
|
};
|
|
@@ -69,10 +72,15 @@ declare const story: {
|
|
|
69
72
|
hideColumns: never[];
|
|
70
73
|
hideRows: never[];
|
|
71
74
|
hideTableNavigation: boolean;
|
|
75
|
+
showSelectedColumn: boolean;
|
|
72
76
|
};
|
|
73
77
|
};
|
|
74
78
|
export declare const TableStory: {
|
|
75
|
-
render: ({ collapsibleSections, scrollOnOpen, scrollTopOffset, tableData, hideColumns, hideDetails, hideRows, stickyHeaderTopOffset, textOverrides, title, activeSection, hideTableNavigation, }: TableProps) => JSX.Element;
|
|
79
|
+
render: ({ collapsibleSections, scrollOnOpen, scrollTopOffset, tableData, hideColumns, hideDetails, hideRows, stickyHeaderTopOffset, textOverrides, title, activeSection, hideTableNavigation, showSelectedColumn, }: TableProps) => JSX.Element;
|
|
80
|
+
name: string;
|
|
81
|
+
};
|
|
82
|
+
export declare const SinglePlanQuoteTable: {
|
|
83
|
+
render: () => JSX.Element;
|
|
76
84
|
name: string;
|
|
77
85
|
};
|
|
78
86
|
export declare const TableDataType: () => JSX.Element;
|
|
@@ -5,9 +5,11 @@ type ExtraTableCellProps = {
|
|
|
5
5
|
isFirstCellInRow?: boolean;
|
|
6
6
|
isTopLeftCell?: boolean;
|
|
7
7
|
isNavigation?: boolean;
|
|
8
|
+
isSelectedColumn?: boolean;
|
|
9
|
+
selectedColumnPosition?: 'top' | 'bottom' | 'middle';
|
|
8
10
|
imageComponent?: (args: any) => JSX.Element;
|
|
9
11
|
isBelowDesktop?: boolean;
|
|
10
12
|
};
|
|
11
13
|
export type TableCellProps = TableCellData & ExtraTableCellProps;
|
|
12
|
-
declare const TableCell: React.MemoExoticComponent<({ isFirstCellInRow, isHeader, isNavigation, isTopLeftCell, colSpan, isBelowDesktop, ...cellProps }: TableCellProps) => JSX.Element>;
|
|
14
|
+
declare const TableCell: React.MemoExoticComponent<({ isFirstCellInRow, isHeader, isNavigation, isSelectedColumn, selectedColumnPosition, isTopLeftCell, colSpan, isBelowDesktop, ...cellProps }: TableCellProps) => JSX.Element>;
|
|
13
15
|
export { TableCell };
|
|
@@ -16,6 +16,7 @@ export interface TableContentsProps {
|
|
|
16
16
|
title: string;
|
|
17
17
|
cellReplacements?: CellReplacements;
|
|
18
18
|
imageComponent?: (args: any) => JSX.Element;
|
|
19
|
+
selectedColumn?: number;
|
|
19
20
|
}
|
|
20
|
-
declare const TableContents: ({ className, collapsibleSections, scrollOnOpen, scrollTopOffset, stickyHeaderRef, tableData, hideColumns, hideDetails, hideRows, isMobile, openModal, shouldHideDetails, title, cellReplacements, imageComponent, }: TableContentsProps) => JSX.Element;
|
|
21
|
+
declare const TableContents: ({ className, collapsibleSections, scrollOnOpen, scrollTopOffset, stickyHeaderRef, tableData, hideColumns, hideDetails, hideRows, isMobile, openModal, shouldHideDetails, title, cellReplacements, imageComponent, selectedColumn, }: TableContentsProps) => JSX.Element;
|
|
21
22
|
export { TableContents };
|
|
@@ -10,6 +10,7 @@ export interface TableSectionProps {
|
|
|
10
10
|
width?: number | string;
|
|
11
11
|
cellReplacements?: CellReplacements;
|
|
12
12
|
imageComponent?: (args: any) => JSX.Element;
|
|
13
|
+
selectedColumn?: number;
|
|
13
14
|
}
|
|
14
|
-
declare const TableSection: ({ className, tableCellRows, hideColumns, hideRows, hideHeader, openModal, title, width, cellReplacements, imageComponent, }: TableSectionProps) => JSX.Element;
|
|
15
|
+
declare const TableSection: ({ className, tableCellRows, hideColumns, hideRows, hideHeader, openModal, title, width, cellReplacements, imageComponent, selectedColumn, }: TableSectionProps) => JSX.Element;
|
|
15
16
|
export { TableSection };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type Color = 'transparent' | 'blue-100' | 'blue-300' | 'blue-500' | 'blue-700' | 'blue-900' | 'purple-50' | 'purple-100' | 'purple-200' | 'purple-300' | 'purple-400' | 'purple-500' | 'purple-600' | 'purple-700' | 'purple-800' | 'purple-900' | 'red-100' | 'red-300' | 'red-500' | 'red-700' | 'red-900' | 'neutral-50' | 'neutral-100' | 'neutral-300' | 'neutral-400' | 'neutral-600' | 'neutral-700' | 'neutral-800' | 'neutral-900' | 'green-100' | 'green-300' | 'green-500' | 'green-700' | 'green-900' | 'yellow-100' | 'yellow-300' | 'yellow-500' | 'yellow-700' | 'yellow-900';
|
|
1
|
+
export type Color = 'transparent' | 'blue-100' | 'blue-300' | 'blue-500' | 'blue-700' | 'blue-900' | 'purple-50' | 'purple-100' | 'purple-200' | 'purple-300' | 'purple-400' | 'purple-500' | 'purple-600' | 'purple-700' | 'purple-800' | 'purple-900' | 'red-100' | 'red-300' | 'red-500' | 'red-700' | 'red-900' | 'neutral-50' | 'neutral-100' | 'neutral-300' | 'neutral-400' | 'neutral-500' | 'neutral-600' | 'neutral-700' | 'neutral-800' | 'neutral-900' | 'green-100' | 'green-300' | 'green-500' | 'green-700' | 'green-900' | 'yellow-100' | 'yellow-300' | 'yellow-500' | 'yellow-700' | 'yellow-900';
|
|
2
2
|
export type Size = 0 | 4 | 8 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 40 | 48 | 56 | 64 | 72 | 80 | 88 | 96;
|
package/package.json
CHANGED
|
@@ -118,7 +118,6 @@ const initialData: TableData = [
|
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
section: {
|
|
121
|
-
icon: <DentalPlusIcon size={20} noMargin />,
|
|
122
121
|
title: 'Dental',
|
|
123
122
|
},
|
|
124
123
|
rows: [
|
|
@@ -256,6 +255,10 @@ const story = {
|
|
|
256
255
|
hideDetails: {
|
|
257
256
|
subContent: 'This property allows to hide the details of the table.',
|
|
258
257
|
},
|
|
258
|
+
hideStickyHeader: {
|
|
259
|
+
subContent:
|
|
260
|
+
'This property allows to hide the sticky header row on desktop, e.g. for single plan tables without a plan selector.',
|
|
261
|
+
},
|
|
259
262
|
stickyHeaderTopOffset: {
|
|
260
263
|
subContent:
|
|
261
264
|
'This property allows to set the offset of the sticky header.',
|
|
@@ -308,6 +311,7 @@ const story = {
|
|
|
308
311
|
hideColumns: [],
|
|
309
312
|
hideRows: [],
|
|
310
313
|
hideTableNavigation: true,
|
|
314
|
+
showSelectedColumn: false,
|
|
311
315
|
},
|
|
312
316
|
};
|
|
313
317
|
|
|
@@ -325,6 +329,7 @@ export const TableStory = {
|
|
|
325
329
|
title,
|
|
326
330
|
activeSection,
|
|
327
331
|
hideTableNavigation,
|
|
332
|
+
showSelectedColumn,
|
|
328
333
|
}: TableProps) => {
|
|
329
334
|
const [price, setPrice] = useState(999);
|
|
330
335
|
return (
|
|
@@ -368,6 +373,7 @@ export const TableStory = {
|
|
|
368
373
|
title={title}
|
|
369
374
|
activeSection={activeSection}
|
|
370
375
|
hideTableNavigation={hideTableNavigation}
|
|
376
|
+
showSelectedColumn={showSelectedColumn}
|
|
371
377
|
/>
|
|
372
378
|
</div>
|
|
373
379
|
);
|
|
@@ -376,6 +382,91 @@ export const TableStory = {
|
|
|
376
382
|
name: 'Table',
|
|
377
383
|
};
|
|
378
384
|
|
|
385
|
+
const singlePlanData: TableData = [
|
|
386
|
+
{
|
|
387
|
+
rows: [
|
|
388
|
+
[{ text: '' }, { text: '' }],
|
|
389
|
+
[
|
|
390
|
+
{ text: 'Price' },
|
|
391
|
+
{
|
|
392
|
+
text: '€9.99',
|
|
393
|
+
description: 'With monthly cancellation',
|
|
394
|
+
fontVariant: 'PRICE',
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
[
|
|
398
|
+
{
|
|
399
|
+
text: 'Regular vet visits & medication',
|
|
400
|
+
modalContent: 'Some stories about vets',
|
|
401
|
+
},
|
|
402
|
+
{ text: 'Up to €1 million' },
|
|
403
|
+
],
|
|
404
|
+
[
|
|
405
|
+
{
|
|
406
|
+
text: 'Specialist visits',
|
|
407
|
+
modalContent: 'Some stories about specialists',
|
|
408
|
+
},
|
|
409
|
+
{ text: '4 visits per year' },
|
|
410
|
+
],
|
|
411
|
+
[{ text: 'Medication' }, { text: '80% covered' }],
|
|
412
|
+
[{ text: 'Grooming' }, { checkmarkValue: false }],
|
|
413
|
+
[{ text: 'Boarding fees' }, { checkmarkValue: false }],
|
|
414
|
+
[
|
|
415
|
+
{
|
|
416
|
+
text: 'Alternative treatments',
|
|
417
|
+
description: 'E.g. physiotherapy, hydrotherapy',
|
|
418
|
+
},
|
|
419
|
+
{ checkmarkValue: false },
|
|
420
|
+
],
|
|
421
|
+
],
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
section: {
|
|
425
|
+
title: 'Dental',
|
|
426
|
+
},
|
|
427
|
+
rows: [
|
|
428
|
+
[{ text: 'Dental cleanings' }, { text: 'Up to €500' }],
|
|
429
|
+
[{ text: 'Dental treatments' }, { text: 'Up to €500' }],
|
|
430
|
+
[{ text: 'Operations' }, { checkmarkValue: true }],
|
|
431
|
+
],
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
section: {
|
|
435
|
+
title: 'Travel',
|
|
436
|
+
},
|
|
437
|
+
rows: [
|
|
438
|
+
[{ text: 'Trips abroad' }, { checkmarkValue: true }],
|
|
439
|
+
[{ text: 'Emergency care abroad' }, { checkmarkValue: true }],
|
|
440
|
+
],
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
section: {
|
|
444
|
+
title: 'Add-ons',
|
|
445
|
+
},
|
|
446
|
+
rows: [
|
|
447
|
+
[{ text: 'Extended coverage' }, { checkmarkValue: true }],
|
|
448
|
+
[{ text: 'Equipment protection' }, { checkmarkValue: true }],
|
|
449
|
+
],
|
|
450
|
+
},
|
|
451
|
+
];
|
|
452
|
+
|
|
453
|
+
export const SinglePlanQuoteTable = {
|
|
454
|
+
render: () => (
|
|
455
|
+
<div style={{ maxWidth: 756 }}>
|
|
456
|
+
<Table
|
|
457
|
+
tableData={singlePlanData}
|
|
458
|
+
title="Single plan quote"
|
|
459
|
+
collapsibleSections
|
|
460
|
+
hideTableNavigation
|
|
461
|
+
hideStickyHeader
|
|
462
|
+
showSelectedColumn
|
|
463
|
+
/>
|
|
464
|
+
</div>
|
|
465
|
+
),
|
|
466
|
+
|
|
467
|
+
name: 'Single Plan Quote',
|
|
468
|
+
};
|
|
469
|
+
|
|
379
470
|
export const TableDataType = () => {
|
|
380
471
|
return (
|
|
381
472
|
<pre>
|
|
@@ -75,6 +75,21 @@ describe('Table', () => {
|
|
|
75
75
|
expect(screen.getByText('Hide details')).toBeVisible();
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
it('does not render the sticky header row when hideStickyHeader is true', () => {
|
|
79
|
+
const { rerender } = render(
|
|
80
|
+
<Table tableData={tableData} title="Test Table" />
|
|
81
|
+
);
|
|
82
|
+
const countWithStickyHeader = screen.getAllByText('Item 1').length;
|
|
83
|
+
|
|
84
|
+
rerender(
|
|
85
|
+
<Table tableData={tableData} hideStickyHeader title="Test Table" />
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(screen.getAllByText('Item 1')).toHaveLength(
|
|
89
|
+
countWithStickyHeader - 1
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
78
93
|
it('shows a modal when clicking on info icon', async () => {
|
|
79
94
|
const { user } = render(<Table tableData={tableData} title="Test Table" />);
|
|
80
95
|
|
|
@@ -47,6 +47,8 @@ export interface TableProps {
|
|
|
47
47
|
title: string;
|
|
48
48
|
activeSection?: number;
|
|
49
49
|
hideTableNavigation?: boolean;
|
|
50
|
+
hideStickyHeader?: boolean;
|
|
51
|
+
showSelectedColumn?: boolean;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
const defaultTextOverrides = {
|
|
@@ -73,6 +75,8 @@ const Table = ({
|
|
|
73
75
|
title,
|
|
74
76
|
activeSection: externalActiveSection,
|
|
75
77
|
hideTableNavigation = false,
|
|
78
|
+
hideStickyHeader = false,
|
|
79
|
+
showSelectedColumn = false,
|
|
76
80
|
}: TableProps) => {
|
|
77
81
|
const textOverrides = { ...defaultTextOverrides, ...definedTextOverrides };
|
|
78
82
|
const isMobile = useMediaQuery('BELOW_MOBILE');
|
|
@@ -99,7 +103,7 @@ const Table = ({
|
|
|
99
103
|
};
|
|
100
104
|
const currentActiveSection = tableData?.[0]?.rows?.[0]?.[activeSection];
|
|
101
105
|
const currentActiveSectionReplacements =
|
|
102
|
-
(currentActiveSection
|
|
106
|
+
(currentActiveSection?.cellId &&
|
|
103
107
|
cellReplacements?.[currentActiveSection.cellId]) ||
|
|
104
108
|
{};
|
|
105
109
|
|
|
@@ -133,7 +137,7 @@ const Table = ({
|
|
|
133
137
|
/>
|
|
134
138
|
)}
|
|
135
139
|
|
|
136
|
-
{!hideTableNavigation && (
|
|
140
|
+
{!hideTableNavigation && currentActiveSection && (
|
|
137
141
|
<TableControls
|
|
138
142
|
activeSection={activeSection}
|
|
139
143
|
columnsLength={columnsLength}
|
|
@@ -158,25 +162,27 @@ const Table = ({
|
|
|
158
162
|
)}
|
|
159
163
|
</>
|
|
160
164
|
) : (
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
165
|
+
!hideStickyHeader && (
|
|
166
|
+
<div
|
|
167
|
+
ref={stickyHeaderRef}
|
|
168
|
+
aria-hidden
|
|
169
|
+
className={styles.stickyHeader}
|
|
170
|
+
style={{ top: `${stickyHeaderTopOffset}px` }}
|
|
171
|
+
>
|
|
172
|
+
<div className={styles.container} ref={headerRef}>
|
|
173
|
+
<TableSection
|
|
174
|
+
cellReplacements={cellReplacements}
|
|
175
|
+
className={className}
|
|
176
|
+
hideColumns={hideColumns}
|
|
177
|
+
hideRows={hideRows}
|
|
178
|
+
openModal={handleOpenModal}
|
|
179
|
+
tableCellRows={[tableData?.[0]?.rows?.[0]]}
|
|
180
|
+
title={title}
|
|
181
|
+
imageComponent={imageComponent}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
178
184
|
</div>
|
|
179
|
-
|
|
185
|
+
)
|
|
180
186
|
)}
|
|
181
187
|
|
|
182
188
|
<div ref={containerRef} className={classNames(styles.container, 'pb8')}>
|
|
@@ -196,6 +202,7 @@ const Table = ({
|
|
|
196
202
|
openModal={handleOpenModal}
|
|
197
203
|
cellReplacements={cellReplacements}
|
|
198
204
|
imageComponent={imageComponent}
|
|
205
|
+
selectedColumn={showSelectedColumn ? activeSection : undefined}
|
|
199
206
|
/>
|
|
200
207
|
</div>
|
|
201
208
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
vertical-align: middle;
|
|
6
6
|
scroll-snap-align: end;
|
|
7
7
|
width: 50%;
|
|
8
|
+
padding: 28px 24px;
|
|
8
9
|
|
|
9
10
|
@include p-size-tablet {
|
|
10
11
|
width: auto;
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
position: sticky;
|
|
27
28
|
left: 0;
|
|
28
29
|
z-index: 2;
|
|
30
|
+
padding-left: 0;
|
|
29
31
|
|
|
30
32
|
&:after {
|
|
31
33
|
content: '';
|
|
@@ -36,10 +38,14 @@
|
|
|
36
38
|
width: 1px;
|
|
37
39
|
background-color: $ds-neutral-100;
|
|
38
40
|
}
|
|
41
|
+
}
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
.selectedColumnTop {
|
|
44
|
+
border-radius: 16px 16px 0 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.selectedColumnBottom {
|
|
48
|
+
border-radius: 0 0 16px 16px;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
.fixedCard {
|
|
@@ -13,6 +13,8 @@ type ExtraTableCellProps = {
|
|
|
13
13
|
isFirstCellInRow?: boolean;
|
|
14
14
|
isTopLeftCell?: boolean;
|
|
15
15
|
isNavigation?: boolean;
|
|
16
|
+
isSelectedColumn?: boolean;
|
|
17
|
+
selectedColumnPosition?: 'top' | 'bottom' | 'middle';
|
|
16
18
|
imageComponent?: (args: any) => JSX.Element;
|
|
17
19
|
isBelowDesktop?: boolean;
|
|
18
20
|
};
|
|
@@ -24,6 +26,8 @@ const TableCell = React.memo(
|
|
|
24
26
|
isFirstCellInRow = false,
|
|
25
27
|
isHeader = false,
|
|
26
28
|
isNavigation = false,
|
|
29
|
+
isSelectedColumn = false,
|
|
30
|
+
selectedColumnPosition,
|
|
27
31
|
isTopLeftCell = false,
|
|
28
32
|
colSpan = 0,
|
|
29
33
|
isBelowDesktop,
|
|
@@ -46,11 +50,13 @@ const TableCell = React.memo(
|
|
|
46
50
|
return (
|
|
47
51
|
<Tag
|
|
48
52
|
{...scope}
|
|
49
|
-
className={classNames('bg-
|
|
53
|
+
className={classNames(isSelectedColumn ? 'bg-orange-50' : 'bg-white', styles.th, {
|
|
50
54
|
'ta-left': isFirstCellInRow,
|
|
51
55
|
[styles.thNavigation]: isNavigation,
|
|
52
56
|
[styles.fixedCell]: isFirstCellInRow && colSpan < 1 ,
|
|
53
57
|
[styles.fixedCard]: cellProps.type === 'CARD',
|
|
58
|
+
[styles.selectedColumnTop]: selectedColumnPosition === 'top',
|
|
59
|
+
[styles.selectedColumnBottom]: selectedColumnPosition === 'bottom',
|
|
54
60
|
})}
|
|
55
61
|
colSpan={isBelowDesktop && cellProps.type === 'CARD' ? 2 : colSpan}
|
|
56
62
|
>
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
@use "../../../../scss/public/colors" as *;
|
|
2
2
|
|
|
3
|
-
.
|
|
4
|
-
height:
|
|
3
|
+
.sectionButtonWrapper {
|
|
4
|
+
height: 74px;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
.sectionButton {
|
|
8
|
+
position: absolute;
|
|
9
|
+
left: 24px;
|
|
10
|
+
right: 24px;
|
|
11
|
+
z-index: 3;
|
|
12
|
+
height: 74px;
|
|
13
|
+
border: none;
|
|
14
|
+
border-bottom: 1px solid $ds-neutral-300;
|
|
15
|
+
color: $ds-neutral-900;
|
|
16
|
+
padding: 0;
|
|
17
|
+
}
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
outline-color: transparent!important;
|
|
15
|
-
box-shadow: none!important;
|
|
16
|
-
background-color: $ds-orange-100!important;
|
|
17
|
-
}
|
|
19
|
+
button.sectionButton {
|
|
20
|
+
cursor: pointer;
|
|
18
21
|
|
|
19
|
-
&:
|
|
20
|
-
|
|
22
|
+
&:hover {
|
|
23
|
+
color: $ds-neutral-700;
|
|
24
|
+
|
|
25
|
+
:global(.p-h3) {
|
|
26
|
+
color: $ds-neutral-700;
|
|
27
|
+
}
|
|
21
28
|
}
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
left: 0;
|
|
27
|
-
right: 0;
|
|
28
|
-
z-index: 3;
|
|
31
|
+
div:last-child > .sectionButtonWrapper > .sectionButton {
|
|
32
|
+
border-bottom: none;
|
|
29
33
|
}
|
|
30
|
-
|
|
31
|
-
.cardIcon {
|
|
32
|
-
width: 20px;
|
|
33
|
-
margin-right: 8px;
|
|
34
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { render, screen } from '../../../../util/testUtils';
|
|
1
|
+
import { fireEvent, render, screen } from '../../../../util/testUtils';
|
|
2
2
|
import { TableContents, TableContentsProps } from './TableContents';
|
|
3
3
|
|
|
4
4
|
const mockData: TableContentsProps['tableData'] = [
|
|
@@ -39,6 +39,27 @@ describe('TableContents', () => {
|
|
|
39
39
|
expect(screen.getByText('Item 2.2.1')).toBeInTheDocument();
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
+
it('renders collapsible section headers as buttons and toggles them', () => {
|
|
43
|
+
render(
|
|
44
|
+
<TableContents collapsibleSections tableData={mockData} title="Table" />
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const sectionButton = screen.getByRole('button', { name: 'Section 2' });
|
|
48
|
+
expect(sectionButton).toHaveAttribute('aria-expanded', 'false');
|
|
49
|
+
|
|
50
|
+
fireEvent.click(sectionButton);
|
|
51
|
+
expect(sectionButton).toHaveAttribute('aria-expanded', 'true');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('renders section headers without a button when not collapsible', () => {
|
|
55
|
+
render(<TableContents tableData={mockData} title="Table" />);
|
|
56
|
+
|
|
57
|
+
expect(
|
|
58
|
+
screen.queryByRole('button', { name: 'Section 2' })
|
|
59
|
+
).not.toBeInTheDocument();
|
|
60
|
+
expect(screen.getByText('Section 2')).toBeInTheDocument();
|
|
61
|
+
});
|
|
62
|
+
|
|
42
63
|
it('hides the table sections when hideDetails and shouldHideDetails is true', () => {
|
|
43
64
|
render(
|
|
44
65
|
<TableContents
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { MutableRefObject, useCallback, useRef, useState } from 'react';
|
|
2
2
|
import { TableSection } from '../TableSection/TableSection';
|
|
3
3
|
import { ChevronDownIcon, ChevronUpIcon } from '../../../icon';
|
|
4
|
-
import { Card } from '../../../cards/card';
|
|
5
4
|
|
|
6
5
|
import styles from './TableContents.module.scss';
|
|
7
6
|
import classNames from 'classnames';
|
|
@@ -25,6 +24,7 @@ export interface TableContentsProps {
|
|
|
25
24
|
title: string;
|
|
26
25
|
cellReplacements?: CellReplacements;
|
|
27
26
|
imageComponent?: (args: any) => JSX.Element;
|
|
27
|
+
selectedColumn?: number;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const TableContents = ({
|
|
@@ -43,6 +43,7 @@ const TableContents = ({
|
|
|
43
43
|
title,
|
|
44
44
|
cellReplacements,
|
|
45
45
|
imageComponent,
|
|
46
|
+
selectedColumn,
|
|
46
47
|
}: TableContentsProps) => {
|
|
47
48
|
const [isSectionOpen, setOpenSection] = useState<number | null>(null);
|
|
48
49
|
const lastToggledSection = useRef<number | null>(null);
|
|
@@ -84,9 +85,9 @@ const TableContents = ({
|
|
|
84
85
|
: isSectionOpen === index || isFirstSection;
|
|
85
86
|
const isVisible = hideDetails ? !shouldHideDetails : true;
|
|
86
87
|
|
|
87
|
-
const renderedIcon = (
|
|
88
|
+
const renderedIcon = section.icon ? (
|
|
88
89
|
<IconRenderer icon={section.icon} imageComponent={imageComponent} width={20} />
|
|
89
|
-
);
|
|
90
|
+
) : null;
|
|
90
91
|
|
|
91
92
|
// Calculate section-specific hideRows based on global offset
|
|
92
93
|
const sectionHideRows = hideRows
|
|
@@ -96,35 +97,40 @@ const TableContents = ({
|
|
|
96
97
|
const result = (isFirstSection || isVisible) && (
|
|
97
98
|
<div key={index} ref={(el) => { sectionRefs.current[index] = el; }}>
|
|
98
99
|
{section?.title && (
|
|
99
|
-
<div className={styles.
|
|
100
|
-
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
100
|
+
<div className={styles.sectionButtonWrapper}>
|
|
101
|
+
{collapsibleSections ? (
|
|
102
|
+
<button
|
|
103
|
+
type="button"
|
|
104
|
+
aria-expanded={isExpanded}
|
|
105
|
+
className={classNames(
|
|
106
|
+
'd-flex ai-center jc-between ta-left bg-white',
|
|
107
|
+
styles.sectionButton
|
|
108
|
+
)}
|
|
109
|
+
onClick={() => handleToggleSection(index)}
|
|
110
|
+
>
|
|
111
|
+
<span className="d-flex ai-center gap8">
|
|
112
|
+
{renderedIcon}
|
|
113
|
+
<span className="p-h3">{section.title}</span>
|
|
114
|
+
</span>
|
|
115
|
+
{isExpanded ? (
|
|
116
|
+
<ChevronUpIcon size={20} />
|
|
117
|
+
) : (
|
|
118
|
+
<ChevronDownIcon size={20} />
|
|
119
|
+
)}
|
|
120
|
+
</button>
|
|
121
|
+
) : (
|
|
122
|
+
<div
|
|
123
|
+
className={classNames(
|
|
124
|
+
'd-flex ai-center jc-between ta-left bg-white',
|
|
125
|
+
styles.sectionButton
|
|
126
|
+
)}
|
|
127
|
+
>
|
|
128
|
+
<span className="d-flex ai-center gap8">
|
|
129
|
+
{renderedIcon}
|
|
130
|
+
<span className="p-h3">{section.title}</span>
|
|
131
|
+
</span>
|
|
132
|
+
</div>
|
|
133
|
+
)}
|
|
128
134
|
</div>
|
|
129
135
|
)}
|
|
130
136
|
|
|
@@ -133,7 +139,9 @@ const TableContents = ({
|
|
|
133
139
|
onTransitionEnd={() => handleScrollToSection(index)}
|
|
134
140
|
>
|
|
135
141
|
<TableSection
|
|
136
|
-
className={classNames(className, '
|
|
142
|
+
className={classNames(className, 'mb16', {
|
|
143
|
+
mt16: !!section?.title,
|
|
144
|
+
})}
|
|
137
145
|
tableCellRows={
|
|
138
146
|
isFirstSection ? rows : [firstHeadRow, ...rows]
|
|
139
147
|
}
|
|
@@ -147,6 +155,7 @@ const TableContents = ({
|
|
|
147
155
|
width={tableWidth}
|
|
148
156
|
cellReplacements={cellReplacements}
|
|
149
157
|
imageComponent={imageComponent}
|
|
158
|
+
selectedColumn={selectedColumn}
|
|
150
159
|
/>
|
|
151
160
|
</Collapsible>
|
|
152
161
|
</div>
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
.table {
|
|
5
5
|
border-collapse: collapse;
|
|
6
6
|
table-layout: fixed;
|
|
7
|
+
}
|
|
7
8
|
|
|
9
|
+
.tableMultiplePlans {
|
|
8
10
|
@include p-size-tablet {
|
|
9
11
|
min-width: 845px;
|
|
10
12
|
}
|
|
@@ -12,4 +14,9 @@
|
|
|
12
14
|
|
|
13
15
|
.tr {
|
|
14
16
|
min-height: 72px;
|
|
17
|
+
border-bottom: 1px solid $ds-neutral-300;
|
|
18
|
+
|
|
19
|
+
&:last-child {
|
|
20
|
+
border-bottom: none;
|
|
21
|
+
}
|
|
15
22
|
}
|