@dmsi/wedgekit-react 0.0.369 → 0.0.371
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/{chunk-RLLQRVM7.js → chunk-2H35FETR.js} +18 -10
- package/dist/chunk-2IKT6IHB.js +190 -0
- package/dist/chunk-4UNWXB4A.js +89 -0
- package/dist/chunk-5IFPG6TS.js +17 -0
- package/dist/{chunk-6GAYJCFE.js → chunk-6DPFKSCT.js} +1 -1
- package/dist/{chunk-ZFOANBWG.js → chunk-AG43RS4Q.js} +2 -1
- package/dist/chunk-AJ5M6MVX.js +7 -0
- package/dist/chunk-AT4AWD6B.js +44 -0
- package/dist/chunk-BQNPOGD5.js +105 -0
- package/dist/chunk-CQFPNZTN.js +172 -0
- package/dist/chunk-EJSPFQCY.js +29 -0
- package/dist/chunk-ER6RCOH3.js +97 -0
- package/dist/{chunk-4VER5OEU.js → chunk-FBE2HGEF.js} +35 -11
- package/dist/chunk-HPQWEZJL.js +45 -0
- package/dist/{chunk-URCLLHO5.js → chunk-IBX6DVHU.js} +376 -102
- package/dist/{chunk-I3WFZOFY.js → chunk-J5V2JRIK.js} +1 -1
- package/dist/chunk-JGJUVJKD.js +283 -0
- package/dist/chunk-KEMCFN4U.js +78 -0
- package/dist/chunk-M6TSTDNZ.js +22 -0
- package/dist/chunk-M7INAUAJ.js +140 -0
- package/dist/chunk-MBZ55T2D.js +51 -0
- package/dist/chunk-N6PNLLNS.js +77 -0
- package/dist/{chunk-ZA5E7ZYM.js → chunk-NXGUDYRR.js} +1 -1
- package/dist/chunk-P36QKH26.js +143 -0
- package/dist/chunk-PTRZHGHA.js +89 -0
- package/dist/chunk-QVWYTQKL.js +29 -0
- package/dist/{chunk-6CPGOW6J.js → chunk-T36HX6QY.js} +6 -4
- package/dist/chunk-U6PUOGG4.js +114 -0
- package/dist/{chunk-NQXZBWDZ.js → chunk-V6U7LU6M.js} +15 -6
- package/dist/chunk-VJVY6NPF.js +32 -0
- package/dist/chunk-VVXPGI2P.js +61 -0
- package/dist/{chunk-ARQBSR3I.js → chunk-YCKRVNJ3.js} +4 -4
- package/dist/chunk-YYHQLQDQ.js +68 -0
- package/dist/components/Accordion.cjs +47 -14
- package/dist/components/Accordion.js +2 -2
- package/dist/components/CalendarRange.cjs +700 -46
- package/dist/components/CalendarRange.css +186 -3
- package/dist/components/CalendarRange.js +43 -11
- package/dist/components/CompactImagesPreview.cjs +485 -0
- package/dist/components/CompactImagesPreview.js +13 -0
- package/dist/components/ContentTabs.cjs +3 -2
- package/dist/components/ContentTabs.js +3 -2
- package/dist/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.cjs +4687 -0
- package/dist/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.css +5051 -0
- package/dist/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.js +62 -0
- package/dist/components/DataGrid/ColumnSelectorHeaderCell/index.cjs +4687 -0
- package/dist/components/DataGrid/ColumnSelectorHeaderCell/index.css +5051 -0
- package/dist/components/DataGrid/ColumnSelectorHeaderCell/index.js +62 -0
- package/dist/components/DataGrid/PinnedColumns.cjs +4687 -0
- package/dist/components/DataGrid/PinnedColumns.css +5051 -0
- package/dist/components/DataGrid/PinnedColumns.js +62 -0
- package/dist/components/DataGrid/TableBody/LoadingCell.cjs +4689 -0
- package/dist/components/DataGrid/TableBody/LoadingCell.css +5051 -0
- package/dist/components/DataGrid/TableBody/LoadingCell.js +62 -0
- package/dist/components/DataGrid/TableBody/TableBodyRow.cjs +4689 -0
- package/dist/components/DataGrid/TableBody/TableBodyRow.css +5051 -0
- package/dist/components/DataGrid/TableBody/TableBodyRow.js +62 -0
- package/dist/components/DataGrid/TableBody/index.cjs +4689 -0
- package/dist/components/DataGrid/TableBody/index.css +5051 -0
- package/dist/components/DataGrid/TableBody/index.js +62 -0
- package/dist/components/DataGrid/index.cjs +4692 -0
- package/dist/components/DataGrid/index.css +5051 -0
- package/dist/components/DataGrid/index.js +65 -0
- package/dist/components/DataGrid/utils.cjs +4687 -0
- package/dist/components/DataGrid/utils.css +5051 -0
- package/dist/components/DataGrid/utils.js +62 -0
- package/dist/components/DataGridCell.js +6 -6
- package/dist/components/DateInput.cjs +721 -67
- package/dist/components/DateInput.css +186 -3
- package/dist/components/DateInput.js +45 -13
- package/dist/components/DateRangeInput.cjs +721 -67
- package/dist/components/DateRangeInput.css +186 -3
- package/dist/components/DateRangeInput.js +45 -13
- package/dist/components/FilterGroup.js +3 -3
- package/dist/components/Grid.cjs +3 -1
- package/dist/components/Grid.js +3 -92
- package/dist/components/ImagePlaceholder.cjs +65 -0
- package/dist/components/ImagePlaceholder.js +7 -0
- package/dist/components/Input.js +2 -2
- package/dist/components/MenuOption.js +2 -2
- package/dist/components/MobileDataGrid/ColumnList.cjs +845 -0
- package/dist/components/MobileDataGrid/ColumnList.js +17 -0
- package/dist/components/MobileDataGrid/ColumnSelector/index.cjs +4797 -0
- package/dist/components/MobileDataGrid/ColumnSelector/index.css +5051 -0
- package/dist/components/MobileDataGrid/ColumnSelector/index.js +62 -0
- package/dist/components/MobileDataGrid/GridContextProvider/GridContext.cjs +31 -0
- package/dist/components/MobileDataGrid/GridContextProvider/GridContext.js +7 -0
- package/dist/components/MobileDataGrid/GridContextProvider/index.cjs +177 -0
- package/dist/components/MobileDataGrid/GridContextProvider/index.js +8 -0
- package/dist/components/MobileDataGrid/MobileDataGridCard/MobileDataGridColumn.cjs +269 -0
- package/dist/components/MobileDataGrid/MobileDataGridCard/MobileDataGridColumn.js +9 -0
- package/dist/components/MobileDataGrid/MobileDataGridCard/index.cjs +790 -0
- package/dist/components/MobileDataGrid/MobileDataGridCard/index.js +16 -0
- package/dist/components/MobileDataGrid/MobileDataGridHeader.cjs +5059 -0
- package/dist/components/MobileDataGrid/MobileDataGridHeader.css +5051 -0
- package/dist/components/MobileDataGrid/MobileDataGridHeader.js +62 -0
- package/dist/components/MobileDataGrid/RowDetailModalProvider/ModalContent.cjs +509 -0
- package/dist/components/MobileDataGrid/RowDetailModalProvider/ModalContent.js +13 -0
- package/dist/components/MobileDataGrid/RowDetailModalProvider/index.cjs +1261 -0
- package/dist/components/MobileDataGrid/RowDetailModalProvider/index.js +27 -0
- package/dist/components/MobileDataGrid/index.cjs +5521 -0
- package/dist/components/MobileDataGrid/index.css +5051 -0
- package/dist/components/MobileDataGrid/index.js +62 -0
- package/dist/components/Modal.cjs +24 -13
- package/dist/components/Modal.js +3 -3
- package/dist/components/ModalHeader.cjs +6 -4
- package/dist/components/ModalHeader.js +1 -1
- package/dist/components/ModalScrim.cjs +2 -1
- package/dist/components/ModalScrim.js +1 -1
- package/dist/components/NestedMenu.js +4 -4
- package/dist/components/Notification.cjs +15 -6
- package/dist/components/Notification.js +1 -1
- package/dist/components/PDFViewer/DownloadIcon.cjs +394 -0
- package/dist/components/PDFViewer/DownloadIcon.js +10 -0
- package/dist/components/PDFViewer/PDFElement.cjs +515 -0
- package/dist/components/PDFViewer/PDFElement.js +11 -0
- package/dist/components/{MobileDataGrid.cjs → PDFViewer/PDFNavigation.cjs} +318 -402
- package/dist/components/PDFViewer/PDFNavigation.js +13 -0
- package/dist/components/PDFViewer/PDFPage.cjs +56 -0
- package/dist/components/PDFViewer/PDFPage.js +7 -0
- package/dist/components/{PDFViewer.cjs → PDFViewer/index.cjs} +290 -202
- package/dist/components/PDFViewer/index.js +29 -0
- package/dist/components/Password.js +2 -2
- package/dist/components/ProductImagePreview/CarouselPagination.cjs +75 -0
- package/dist/components/ProductImagePreview/CarouselPagination.js +7 -0
- package/dist/components/ProductImagePreview/MobileImageCarousel.cjs +214 -0
- package/dist/components/ProductImagePreview/MobileImageCarousel.js +7 -0
- package/dist/components/ProductImagePreview/ProductPrimaryImage.cjs +255 -0
- package/dist/components/ProductImagePreview/ProductPrimaryImage.js +9 -0
- package/dist/components/ProductImagePreview/Thumbnail.cjs +105 -0
- package/dist/components/ProductImagePreview/Thumbnail.js +8 -0
- package/dist/components/ProductImagePreview/ZoomWindow.cjs +198 -0
- package/dist/components/ProductImagePreview/ZoomWindow.js +8 -0
- package/dist/components/ProductImagePreview/index.cjs +1369 -0
- package/dist/components/ProductImagePreview/index.js +22 -0
- package/dist/components/Search.js +3 -3
- package/dist/components/Select.js +3 -3
- package/dist/components/SideMenuGroup.cjs +15 -6
- package/dist/components/SideMenuGroup.js +1 -1
- package/dist/components/SideMenuItem.cjs +15 -6
- package/dist/components/SideMenuItem.js +1 -1
- package/dist/components/SkeletonParagraph.cjs +33 -0
- package/dist/components/SkeletonParagraph.js +10 -0
- package/dist/components/Stack.cjs +15 -6
- package/dist/components/Stack.js +1 -1
- package/dist/components/Stepper.cjs +61 -53
- package/dist/components/Stepper.js +63 -55
- package/dist/components/Surface.js +3 -39
- package/dist/components/Swatch.cjs +15 -6
- package/dist/components/Swatch.js +4 -4
- package/dist/components/Time.cjs +15 -6
- package/dist/components/Time.js +5 -5
- package/dist/components/Upload.cjs +15 -6
- package/dist/components/Upload.js +1 -1
- package/dist/components/index.cjs +2559 -14
- package/dist/components/index.css +186 -3
- package/dist/components/index.js +57 -14
- package/dist/index.css +186 -3
- package/package.json +1 -1
- package/src/components/Accordion.tsx +23 -4
- package/src/components/CompactImagesPreview.tsx +99 -0
- package/src/components/ContentTabs.tsx +3 -1
- package/src/components/DataGrid/types.ts +5 -0
- package/src/components/Grid.tsx +2 -0
- package/src/components/ImagePlaceholder.tsx +22 -0
- package/src/components/MobileDataGrid/ColumnList.tsx +66 -0
- package/src/components/MobileDataGrid/ColumnSelector/index.tsx +97 -0
- package/src/components/MobileDataGrid/GridContextProvider/GridContext.tsx +25 -0
- package/src/components/MobileDataGrid/GridContextProvider/index.tsx +132 -0
- package/src/components/MobileDataGrid/GridContextProvider/useGridContext.ts +10 -0
- package/src/components/MobileDataGrid/MobileDataGridCard/MobileDataGridColumn.tsx +20 -0
- package/src/components/MobileDataGrid/MobileDataGridCard/index.tsx +129 -0
- package/src/components/MobileDataGrid/MobileDataGridHeader.tsx +80 -0
- package/src/components/MobileDataGrid/RowDetailModalProvider/ModalContent.tsx +42 -0
- package/src/components/MobileDataGrid/RowDetailModalProvider/index.tsx +68 -0
- package/src/components/MobileDataGrid/dataGridReducer.ts +55 -0
- package/src/components/MobileDataGrid/index.tsx +92 -0
- package/src/components/MobileDataGrid/types.ts +4 -0
- package/src/components/Modal.tsx +31 -12
- package/src/components/ModalButtons.tsx +1 -1
- package/src/components/ModalHeader.tsx +5 -2
- package/src/components/ModalScrim.tsx +3 -2
- package/src/components/PDFViewer/DownloadIcon.tsx +22 -0
- package/src/components/PDFViewer/PDFElement.tsx +90 -0
- package/src/components/PDFViewer/PDFNavigation.tsx +68 -0
- package/src/components/PDFViewer/PDFPage.tsx +34 -0
- package/src/components/PDFViewer/index.tsx +128 -0
- package/src/components/ProductImagePreview/CarouselPagination.tsx +54 -0
- package/src/components/ProductImagePreview/MobileImageCarousel.tsx +226 -0
- package/src/components/ProductImagePreview/ProductPrimaryImage.tsx +218 -0
- package/src/components/ProductImagePreview/Thumbnail.tsx +49 -0
- package/src/components/ProductImagePreview/ZoomWindow.tsx +136 -0
- package/src/components/ProductImagePreview/index.tsx +182 -0
- package/src/components/ProductImagePreview/useProductImagePreview.ts +211 -0
- package/src/components/SkeletonParagraph.tsx +5 -0
- package/src/components/Stack.tsx +29 -6
- package/src/components/Stepper.tsx +5 -1
- package/src/components/index.ts +4 -0
- package/src/types.ts +2 -1
- package/dist/components/MobileDataGrid.js +0 -150
- package/dist/components/PDFViewer.js +0 -250
- package/src/components/MobileDataGrid.tsx +0 -163
- package/src/components/PDFViewer.tsx +0 -264
- package/dist/{chunk-OXSBIBGT.js → chunk-CKQNJNU3.js} +3 -3
- package/dist/{chunk-RJUN52HJ.js → chunk-ZL5X7KP6.js} +3 -3
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
import { Button, Icon, Menu } from "../..";
|
|
3
|
+
import { Checkbox, MenuOption } from "../..";
|
|
4
|
+
import { useGridContext } from "../GridContextProvider/useGridContext";
|
|
5
|
+
|
|
6
|
+
export function ColumnSelector<T>() {
|
|
7
|
+
const context = useGridContext<T>();
|
|
8
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
9
|
+
const [show, setShow] = useState(false);
|
|
10
|
+
const {
|
|
11
|
+
columns,
|
|
12
|
+
id,
|
|
13
|
+
testid,
|
|
14
|
+
visibleColumns,
|
|
15
|
+
numberOfColumnsToShow,
|
|
16
|
+
primaryKey,
|
|
17
|
+
resetColumnVisibility,
|
|
18
|
+
dispatch,
|
|
19
|
+
} = context;
|
|
20
|
+
|
|
21
|
+
const toggleColumnVisibility = useCallback(
|
|
22
|
+
(index: number, visible: boolean) => {
|
|
23
|
+
dispatch({ type: "UPDATE", index, payload: { meta: { visible } } });
|
|
24
|
+
},
|
|
25
|
+
[dispatch],
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div
|
|
30
|
+
id={id ? `${id}-column-selector` : undefined}
|
|
31
|
+
data-testid={testid}
|
|
32
|
+
className="text-text-secondary-normal border-l border-brand-200 p-mobile-container-padding"
|
|
33
|
+
ref={ref}
|
|
34
|
+
>
|
|
35
|
+
<Button
|
|
36
|
+
id={id ? `${id}-button` : undefined}
|
|
37
|
+
testid={testid ? `${testid}-button` : undefined}
|
|
38
|
+
onClick={() => setShow((prev) => !prev)}
|
|
39
|
+
variant="navigation"
|
|
40
|
+
iconOnly
|
|
41
|
+
size={24}
|
|
42
|
+
leftIcon={<Icon name="tune" />}
|
|
43
|
+
></Button>
|
|
44
|
+
<Menu
|
|
45
|
+
id={id ? `${id}-menu` : undefined}
|
|
46
|
+
testid={testid ? `${testid}-menu` : undefined}
|
|
47
|
+
positionTo={ref}
|
|
48
|
+
position="bottom-right"
|
|
49
|
+
show={show}
|
|
50
|
+
setShow={setShow}
|
|
51
|
+
calculateMinMaxHeight
|
|
52
|
+
>
|
|
53
|
+
<Button
|
|
54
|
+
id={id ? `${id}-reset-button` : undefined}
|
|
55
|
+
testid={testid ? `${testid}-reset-button` : undefined}
|
|
56
|
+
variant="tertiary"
|
|
57
|
+
onClick={() => {
|
|
58
|
+
resetColumnVisibility();
|
|
59
|
+
setShow(false);
|
|
60
|
+
}}
|
|
61
|
+
>
|
|
62
|
+
Reset to default
|
|
63
|
+
</Button>
|
|
64
|
+
{columns
|
|
65
|
+
.filter((x) => x.meta?.inVisibilityMenu)
|
|
66
|
+
.map((column) => (
|
|
67
|
+
<MenuOption
|
|
68
|
+
key={id ? `${id}-option-${column.id}` : undefined}
|
|
69
|
+
testid={testid ? `${testid}-option-${column.id}` : undefined}
|
|
70
|
+
>
|
|
71
|
+
<Checkbox
|
|
72
|
+
id={id ? `${id}-checkbox-${column.id}` : undefined}
|
|
73
|
+
testid={testid ? `${testid}-checkbox-${column.id}` : undefined}
|
|
74
|
+
label={column.header?.toString()}
|
|
75
|
+
checked={
|
|
76
|
+
!!column.meta?.visible || column.id === String(primaryKey)
|
|
77
|
+
}
|
|
78
|
+
disabled={
|
|
79
|
+
(typeof numberOfColumnsToShow !== "undefined" &&
|
|
80
|
+
// account for header+link occupying one slot
|
|
81
|
+
visibleColumns.length >= numberOfColumnsToShow - 1 &&
|
|
82
|
+
column.meta?.visible !== true) ||
|
|
83
|
+
column.id === String(primaryKey)
|
|
84
|
+
}
|
|
85
|
+
onChange={(e) => {
|
|
86
|
+
toggleColumnVisibility(
|
|
87
|
+
columns.findIndex(({ id }) => id === column.id),
|
|
88
|
+
e.target.checked,
|
|
89
|
+
);
|
|
90
|
+
}}
|
|
91
|
+
/>
|
|
92
|
+
</MenuOption>
|
|
93
|
+
))}
|
|
94
|
+
</Menu>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ColumnDef } from "@tanstack/react-table";
|
|
2
|
+
import { createContext, Dispatch } from "react";
|
|
3
|
+
import { Action } from "../dataGridReducer";
|
|
4
|
+
|
|
5
|
+
export type GridContextType<T = unknown> = {
|
|
6
|
+
columns: ColumnDef<T>[];
|
|
7
|
+
selectedRowIds: (string | number)[];
|
|
8
|
+
data: T[];
|
|
9
|
+
dispatch: Dispatch<Action<T>>;
|
|
10
|
+
getId: (data: T) => string | number | undefined;
|
|
11
|
+
resetColumnVisibility: () => void;
|
|
12
|
+
handleRowSelect: (item: T) => void;
|
|
13
|
+
handleRowSelectAll: () => void;
|
|
14
|
+
id?: string;
|
|
15
|
+
testid?: string;
|
|
16
|
+
numberOfColumnsToShow?: number;
|
|
17
|
+
visibleColumns: ColumnDef<T>[];
|
|
18
|
+
primaryKey?: keyof T;
|
|
19
|
+
isRowDetailOpen: boolean;
|
|
20
|
+
currentRow: T | null;
|
|
21
|
+
openRowDetail: (row: T) => void;
|
|
22
|
+
closeRowDetail: () => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const GridContext = createContext<GridContextType | null>(null);
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { useCallback, useMemo, useReducer, useState } from "react";
|
|
2
|
+
import { dataGridReducer } from "../dataGridReducer";
|
|
3
|
+
import { GridContext, GridContextType } from "./GridContext";
|
|
4
|
+
import { ColumnDef } from "@tanstack/react-table";
|
|
5
|
+
|
|
6
|
+
type GridContextProps<T> = {
|
|
7
|
+
initialColumns: ColumnDef<T>[];
|
|
8
|
+
data: T[];
|
|
9
|
+
getId: (data: T) => string | number | undefined;
|
|
10
|
+
id?: string;
|
|
11
|
+
testid?: string;
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
onRowSelect?: (row: T, selectedIds: (string | number)[]) => void;
|
|
14
|
+
numberOfColumnsToShow?: number;
|
|
15
|
+
primaryKey?: keyof T;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function GridContextProvider<T>(props: GridContextProps<T>) {
|
|
19
|
+
const {
|
|
20
|
+
initialColumns,
|
|
21
|
+
id,
|
|
22
|
+
testid,
|
|
23
|
+
children,
|
|
24
|
+
data,
|
|
25
|
+
numberOfColumnsToShow,
|
|
26
|
+
primaryKey,
|
|
27
|
+
getId,
|
|
28
|
+
onRowSelect,
|
|
29
|
+
} = props;
|
|
30
|
+
const [columns, dispatch] = useReducer(dataGridReducer<T>, initialColumns);
|
|
31
|
+
const [selectedRowIds, setSelectedRowIds] = useState<(string | number)[]>([]);
|
|
32
|
+
const [currentRow, setCurrentRow] = useState<T | null>(null);
|
|
33
|
+
|
|
34
|
+
const resetColumnVisibility = useCallback(() => {
|
|
35
|
+
// use initialColumns' meta?.visible data in columns.
|
|
36
|
+
const newColumns = columns.map((column) => {
|
|
37
|
+
const initialColumn = initialColumns.find((c) => c.id === column.id);
|
|
38
|
+
return {
|
|
39
|
+
...column,
|
|
40
|
+
meta: {
|
|
41
|
+
...column.meta,
|
|
42
|
+
visible: initialColumn?.meta?.visible,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
dispatch({ type: "SET", payload: newColumns });
|
|
47
|
+
}, [columns, initialColumns]);
|
|
48
|
+
|
|
49
|
+
const handleRowSelect = useCallback(
|
|
50
|
+
(item: T) => {
|
|
51
|
+
const rowId = getId(item) ?? "";
|
|
52
|
+
if (!rowId) return;
|
|
53
|
+
const nextSelected = selectedRowIds.includes(rowId)
|
|
54
|
+
? selectedRowIds.filter((id) => id !== rowId)
|
|
55
|
+
: [...selectedRowIds, rowId];
|
|
56
|
+
|
|
57
|
+
setSelectedRowIds(nextSelected);
|
|
58
|
+
if (onRowSelect) onRowSelect(item, nextSelected);
|
|
59
|
+
},
|
|
60
|
+
[getId, onRowSelect, selectedRowIds],
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const handleRowSelectAll = useCallback(() => {
|
|
64
|
+
setSelectedRowIds((prev) => {
|
|
65
|
+
if (prev.length === data.length) {
|
|
66
|
+
// Select none
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
// Select all
|
|
70
|
+
return data.map(getId).filter((id) => id !== undefined);
|
|
71
|
+
});
|
|
72
|
+
}, [data, getId]);
|
|
73
|
+
|
|
74
|
+
const openRowDetail = useCallback((row: T) => {
|
|
75
|
+
setCurrentRow(row);
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
78
|
+
const closeRowDetail = useCallback(() => {
|
|
79
|
+
setCurrentRow(null);
|
|
80
|
+
}, []);
|
|
81
|
+
|
|
82
|
+
const visibleColumns = useMemo(() => {
|
|
83
|
+
// header+link counts as the first column when limiting
|
|
84
|
+
const effectiveLimit =
|
|
85
|
+
typeof numberOfColumnsToShow === "number"
|
|
86
|
+
? Math.max(numberOfColumnsToShow - 1, 0)
|
|
87
|
+
: undefined;
|
|
88
|
+
if (primaryKey) {
|
|
89
|
+
const pkColumn = columns.find((col) => col.id === String(primaryKey));
|
|
90
|
+
const otherColumns = columns.filter(
|
|
91
|
+
(col) => col.id !== String(primaryKey),
|
|
92
|
+
);
|
|
93
|
+
const orderedColumns = pkColumn
|
|
94
|
+
? [pkColumn, ...otherColumns]
|
|
95
|
+
: [...otherColumns];
|
|
96
|
+
return orderedColumns
|
|
97
|
+
.filter((x) => x.meta?.visible !== false)
|
|
98
|
+
.slice(0, effectiveLimit);
|
|
99
|
+
}
|
|
100
|
+
return columns
|
|
101
|
+
.filter((x) => x.meta?.visible !== false)
|
|
102
|
+
.slice(0, effectiveLimit);
|
|
103
|
+
}, [columns, numberOfColumnsToShow, primaryKey]);
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<GridContext.Provider
|
|
107
|
+
value={
|
|
108
|
+
{
|
|
109
|
+
columns,
|
|
110
|
+
testid,
|
|
111
|
+
id,
|
|
112
|
+
data,
|
|
113
|
+
selectedRowIds,
|
|
114
|
+
visibleColumns,
|
|
115
|
+
numberOfColumnsToShow,
|
|
116
|
+
primaryKey,
|
|
117
|
+
dispatch,
|
|
118
|
+
getId,
|
|
119
|
+
resetColumnVisibility,
|
|
120
|
+
handleRowSelect,
|
|
121
|
+
handleRowSelectAll,
|
|
122
|
+
isRowDetailOpen: !!currentRow,
|
|
123
|
+
currentRow,
|
|
124
|
+
openRowDetail,
|
|
125
|
+
closeRowDetail,
|
|
126
|
+
} as GridContextType<unknown> | null
|
|
127
|
+
}
|
|
128
|
+
>
|
|
129
|
+
{children}
|
|
130
|
+
</GridContext.Provider>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { GridContext, GridContextType } from "./GridContext";
|
|
3
|
+
|
|
4
|
+
export function useGridContext<T>() {
|
|
5
|
+
const ctx = useContext(GridContext) as GridContextType<T> | null;
|
|
6
|
+
if (!ctx) {
|
|
7
|
+
throw new Error("useGridContext must be used within GridContextProvider");
|
|
8
|
+
}
|
|
9
|
+
return ctx;
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Paragraph } from "../../Paragraph";
|
|
2
|
+
import { ColumnDef } from "@tanstack/react-table";
|
|
3
|
+
|
|
4
|
+
export function MobileDataGridColumn<T extends Record<string, unknown>>(props: {
|
|
5
|
+
column: ColumnDef<T>;
|
|
6
|
+
data: T;
|
|
7
|
+
}) {
|
|
8
|
+
const { column, data } = props;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div className="mb-2 grid grid-cols-2 gap-2 px-3 flex-1">
|
|
12
|
+
<Paragraph color="text-secondary-normal" className="text-left">
|
|
13
|
+
{column.header?.toString()}:
|
|
14
|
+
</Paragraph>{" "}
|
|
15
|
+
{column.id && data[column.id]
|
|
16
|
+
? (data[column.id] as React.ReactNode)
|
|
17
|
+
: null}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Icon } from "../../Icon";
|
|
2
|
+
import { Paragraph } from "../../Paragraph";
|
|
3
|
+
import { Stack } from "../../Stack";
|
|
4
|
+
import { useGridContext } from "../GridContextProvider/useGridContext";
|
|
5
|
+
import { Checkbox } from "../../Checkbox";
|
|
6
|
+
import clsx from "clsx";
|
|
7
|
+
import { MobileDataGridColumn } from "./MobileDataGridColumn";
|
|
8
|
+
import { Subheader } from "../../Subheader";
|
|
9
|
+
import { RowActions } from "../types";
|
|
10
|
+
|
|
11
|
+
export function MobileDataGridCard<T extends Record<string, unknown>>({
|
|
12
|
+
renderLink,
|
|
13
|
+
renderChevron = true,
|
|
14
|
+
data,
|
|
15
|
+
enableRowSelection,
|
|
16
|
+
selected,
|
|
17
|
+
rowActions,
|
|
18
|
+
}: {
|
|
19
|
+
renderLink?: (data: T) => React.ReactNode;
|
|
20
|
+
renderChevron?: boolean;
|
|
21
|
+
data: T;
|
|
22
|
+
enableRowSelection?: boolean;
|
|
23
|
+
selected?: boolean;
|
|
24
|
+
rowActions?: RowActions<T>;
|
|
25
|
+
}) {
|
|
26
|
+
const context = useGridContext<T>();
|
|
27
|
+
const { id, testid, visibleColumns, getId, handleRowSelect, openRowDetail } =
|
|
28
|
+
context;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<li
|
|
32
|
+
id={id ? `${id}-card-${getId(data)}` : undefined}
|
|
33
|
+
data-testid={testid ? `${testid}-card-${getId(data)}` : undefined}
|
|
34
|
+
className={clsx(
|
|
35
|
+
"hover:bg-action-100 cursor-pointer list-none",
|
|
36
|
+
selected ? "bg-action-100" : "bg-background-grouped-primary-normal",
|
|
37
|
+
)}
|
|
38
|
+
onClick={() => openRowDetail(data)}
|
|
39
|
+
>
|
|
40
|
+
<Stack sizing="component">
|
|
41
|
+
<Stack horizontal horizontalMobile items="center" justify="between">
|
|
42
|
+
{enableRowSelection && (
|
|
43
|
+
<Stack
|
|
44
|
+
sizing="component"
|
|
45
|
+
padding
|
|
46
|
+
width="fit"
|
|
47
|
+
onClick={(e) => e.stopPropagation()}
|
|
48
|
+
>
|
|
49
|
+
<Checkbox
|
|
50
|
+
id={id ? `${id}-${getId(data)}-select-checkbox` : undefined}
|
|
51
|
+
testid={
|
|
52
|
+
testid
|
|
53
|
+
? `${testid}-${getId(data)}-select-checkbox`
|
|
54
|
+
: undefined
|
|
55
|
+
}
|
|
56
|
+
checked={selected}
|
|
57
|
+
onChange={() => handleRowSelect(data)}
|
|
58
|
+
/>
|
|
59
|
+
</Stack>
|
|
60
|
+
)}
|
|
61
|
+
<Stack
|
|
62
|
+
sizing="component"
|
|
63
|
+
padding
|
|
64
|
+
onClick={(e) => e.stopPropagation()}
|
|
65
|
+
>
|
|
66
|
+
{renderLink ? (
|
|
67
|
+
renderLink(data)
|
|
68
|
+
) : (
|
|
69
|
+
<Subheader>
|
|
70
|
+
{String(data[context.primaryKey as string] ?? "")}
|
|
71
|
+
</Subheader>
|
|
72
|
+
)}
|
|
73
|
+
</Stack>
|
|
74
|
+
<Stack
|
|
75
|
+
horizontal
|
|
76
|
+
horizontalMobile
|
|
77
|
+
items="center"
|
|
78
|
+
justify="end"
|
|
79
|
+
sizing="component"
|
|
80
|
+
onClick={(e) => e.stopPropagation()}
|
|
81
|
+
>
|
|
82
|
+
{rowActions &&
|
|
83
|
+
(typeof rowActions === "function"
|
|
84
|
+
? rowActions(data)
|
|
85
|
+
: rowActions)}
|
|
86
|
+
</Stack>
|
|
87
|
+
</Stack>
|
|
88
|
+
|
|
89
|
+
<Stack sizing="layout-group">
|
|
90
|
+
{visibleColumns
|
|
91
|
+
.filter((x) => x.meta?.visible !== false && !x.id?.startsWith("__"))
|
|
92
|
+
.map((column, index) =>
|
|
93
|
+
column.meta?.useCustomRenderer &&
|
|
94
|
+
column.meta.mobileCell &&
|
|
95
|
+
column.id ? (
|
|
96
|
+
<div
|
|
97
|
+
key={`${column.id}-${index}`}
|
|
98
|
+
className="mb-2 grid grid-cols-2 gap-2 px-3 items-center flex-1"
|
|
99
|
+
>
|
|
100
|
+
<Paragraph
|
|
101
|
+
color="text-secondary-normal"
|
|
102
|
+
className="text-left"
|
|
103
|
+
>
|
|
104
|
+
{column.header?.toString()}:
|
|
105
|
+
</Paragraph>{" "}
|
|
106
|
+
<column.meta.mobileCell
|
|
107
|
+
column={column}
|
|
108
|
+
row={data}
|
|
109
|
+
cellValue={data[column.id]}
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
) : (
|
|
113
|
+
<MobileDataGridColumn
|
|
114
|
+
key={`${column.id}-${index}`}
|
|
115
|
+
column={column}
|
|
116
|
+
data={data}
|
|
117
|
+
/>
|
|
118
|
+
),
|
|
119
|
+
)}
|
|
120
|
+
</Stack>
|
|
121
|
+
</Stack>
|
|
122
|
+
{renderChevron && (
|
|
123
|
+
<Stack items="center" justify="center" horizontal horizontalMobile>
|
|
124
|
+
<Icon name="keyboard_arrow_down" />
|
|
125
|
+
</Stack>
|
|
126
|
+
)}
|
|
127
|
+
</li>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Checkbox } from "../Checkbox";
|
|
2
|
+
import { Heading3 } from "../Heading";
|
|
3
|
+
import { Stack } from "../Stack";
|
|
4
|
+
import { Theme } from "../Theme";
|
|
5
|
+
import { ColumnSelector } from "./ColumnSelector";
|
|
6
|
+
import { GridContextType } from "./GridContextProvider/GridContext";
|
|
7
|
+
import { useGridContext } from "./GridContextProvider/useGridContext";
|
|
8
|
+
|
|
9
|
+
export function MobileDataGridHeader<T>({
|
|
10
|
+
header: Header,
|
|
11
|
+
enableColumnSelector,
|
|
12
|
+
enableRowSelection,
|
|
13
|
+
}: {
|
|
14
|
+
header?: string | ((ctx: GridContextType<T>) => React.ReactNode);
|
|
15
|
+
enableColumnSelector?: boolean;
|
|
16
|
+
enableRowSelection?: boolean;
|
|
17
|
+
}) {
|
|
18
|
+
const ctx = useGridContext<T>();
|
|
19
|
+
const {
|
|
20
|
+
id,
|
|
21
|
+
testid,
|
|
22
|
+
selectedRowIds,
|
|
23
|
+
data,
|
|
24
|
+
primaryKey,
|
|
25
|
+
columns,
|
|
26
|
+
handleRowSelectAll,
|
|
27
|
+
} = ctx;
|
|
28
|
+
|
|
29
|
+
if (typeof Header === "undefined" && !primaryKey) return null;
|
|
30
|
+
if (typeof Header === "function") return <Header {...ctx} />;
|
|
31
|
+
if (typeof Header === "string" || primaryKey)
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
id={id ? `${id}-header` : undefined}
|
|
35
|
+
data-testid={testid ? `${testid}-header` : undefined}
|
|
36
|
+
className="sticky top-0"
|
|
37
|
+
>
|
|
38
|
+
<Theme theme="brand">
|
|
39
|
+
<Stack
|
|
40
|
+
horizontal
|
|
41
|
+
horizontalMobile
|
|
42
|
+
items="center"
|
|
43
|
+
justify="between"
|
|
44
|
+
backgroundColor="background-primary-normal"
|
|
45
|
+
>
|
|
46
|
+
{enableRowSelection && (
|
|
47
|
+
<div className="p-mobile-component-padding border-r border-brand-200 max-w-fit h-full">
|
|
48
|
+
<Checkbox
|
|
49
|
+
id={id ? `${id}-select-all-checkbox` : undefined}
|
|
50
|
+
testid={testid ? `${testid}-select-all-checkbox` : undefined}
|
|
51
|
+
checked={selectedRowIds.length === data.length}
|
|
52
|
+
indeterminate={
|
|
53
|
+
!!selectedRowIds.length &&
|
|
54
|
+
selectedRowIds.length !== data.length
|
|
55
|
+
}
|
|
56
|
+
onChange={handleRowSelectAll}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
<Stack
|
|
61
|
+
horizontal
|
|
62
|
+
horizontalMobile
|
|
63
|
+
items="center"
|
|
64
|
+
sizing="component"
|
|
65
|
+
padding
|
|
66
|
+
>
|
|
67
|
+
<Heading3 as="span" color="text-primary-normal">
|
|
68
|
+
{typeof Header === "string"
|
|
69
|
+
? Header
|
|
70
|
+
: columns
|
|
71
|
+
.find((col) => col.id === primaryKey)
|
|
72
|
+
?.header?.toString()}
|
|
73
|
+
</Heading3>
|
|
74
|
+
</Stack>
|
|
75
|
+
{enableColumnSelector && <ColumnSelector />}
|
|
76
|
+
</Stack>
|
|
77
|
+
</Theme>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Paragraph } from "../../Paragraph";
|
|
2
|
+
import { Stack } from "../../Stack";
|
|
3
|
+
import { useGridContext } from "../GridContextProvider/useGridContext";
|
|
4
|
+
import { MobileDataGridColumn } from "../MobileDataGridCard/MobileDataGridColumn";
|
|
5
|
+
|
|
6
|
+
export function ModalContent() {
|
|
7
|
+
const context = useGridContext<Record<string, unknown>>();
|
|
8
|
+
const { columns, currentRow } = context;
|
|
9
|
+
|
|
10
|
+
if (!currentRow) return null;
|
|
11
|
+
return (
|
|
12
|
+
<Stack sizing="layout-group">
|
|
13
|
+
{columns
|
|
14
|
+
.filter((x) => !x.id?.startsWith("__"))
|
|
15
|
+
.map((column, index) =>
|
|
16
|
+
column.meta?.useCustomRenderer &&
|
|
17
|
+
column.meta.mobileCell &&
|
|
18
|
+
column.id ? (
|
|
19
|
+
<div
|
|
20
|
+
key={`${column.id}-${index}`}
|
|
21
|
+
className="mb-2 grid grid-cols-2 gap-2 px-3 items-center flex-1"
|
|
22
|
+
>
|
|
23
|
+
<Paragraph color="text-secondary-normal" className="text-left">
|
|
24
|
+
{column.header?.toString()}:
|
|
25
|
+
</Paragraph>{" "}
|
|
26
|
+
<column.meta.mobileCell
|
|
27
|
+
column={column}
|
|
28
|
+
row={currentRow}
|
|
29
|
+
cellValue={currentRow?.[column.id as string]}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
) : (
|
|
33
|
+
<MobileDataGridColumn
|
|
34
|
+
key={`${column.id}-${index}`}
|
|
35
|
+
column={column}
|
|
36
|
+
data={currentRow}
|
|
37
|
+
/>
|
|
38
|
+
),
|
|
39
|
+
)}
|
|
40
|
+
</Stack>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Button } from "../../Button";
|
|
2
|
+
import { Heading2 } from "../../Heading";
|
|
3
|
+
import { Icon } from "../../Icon";
|
|
4
|
+
import { Modal } from "../../Modal";
|
|
5
|
+
import { Stack } from "../../Stack";
|
|
6
|
+
import { useGridContext } from "../GridContextProvider/useGridContext";
|
|
7
|
+
import { ModalContent } from "./ModalContent";
|
|
8
|
+
|
|
9
|
+
export function RowDetailModalProvider() {
|
|
10
|
+
const context = useGridContext<Record<string, unknown>>();
|
|
11
|
+
const {
|
|
12
|
+
id,
|
|
13
|
+
testid,
|
|
14
|
+
isRowDetailOpen,
|
|
15
|
+
currentRow,
|
|
16
|
+
primaryKey,
|
|
17
|
+
closeRowDetail,
|
|
18
|
+
} = context;
|
|
19
|
+
|
|
20
|
+
// TODO: implement modal UI later
|
|
21
|
+
// Also verify if modal is opening in orders screen.doesn't seem to work in storybooks
|
|
22
|
+
return (
|
|
23
|
+
<Modal
|
|
24
|
+
fixedHeightScrolling
|
|
25
|
+
open={isRowDetailOpen}
|
|
26
|
+
onClose={closeRowDetail}
|
|
27
|
+
hideCloseIcon
|
|
28
|
+
size="medium"
|
|
29
|
+
className="!p-0"
|
|
30
|
+
headerIcon={
|
|
31
|
+
<Stack
|
|
32
|
+
horizontal
|
|
33
|
+
horizontalMobile
|
|
34
|
+
items="center"
|
|
35
|
+
justify="between"
|
|
36
|
+
width="full"
|
|
37
|
+
>
|
|
38
|
+
<Heading2>
|
|
39
|
+
{(currentRow?.[primaryKey ?? "id"] as string | undefined) ??
|
|
40
|
+
"Grid Detail"}
|
|
41
|
+
</Heading2>
|
|
42
|
+
<Button
|
|
43
|
+
id={id ? `${id}-open-in-new-button` : undefined}
|
|
44
|
+
testid={testid ? `${testid}-open-in-new-button` : undefined}
|
|
45
|
+
iconOnly
|
|
46
|
+
variant="tertiary"
|
|
47
|
+
onClick={closeRowDetail}
|
|
48
|
+
leftIcon={
|
|
49
|
+
<span className="text-icon-primary-normal contents">
|
|
50
|
+
<Icon name="open_in_new" size={24} />
|
|
51
|
+
</span>
|
|
52
|
+
}
|
|
53
|
+
/>
|
|
54
|
+
</Stack>
|
|
55
|
+
}
|
|
56
|
+
customActions={
|
|
57
|
+
<Button onClick={closeRowDetail} className="w-full">
|
|
58
|
+
Close
|
|
59
|
+
</Button>
|
|
60
|
+
}
|
|
61
|
+
showButtons
|
|
62
|
+
>
|
|
63
|
+
<div className="bg-white max-h-full flex flex-col flex-grow-1">
|
|
64
|
+
<ModalContent />
|
|
65
|
+
</div>
|
|
66
|
+
</Modal>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ColumnDef } from "@tanstack/react-table";
|
|
2
|
+
|
|
3
|
+
export type Action<T> =
|
|
4
|
+
| {
|
|
5
|
+
payload: ColumnDef<T>[];
|
|
6
|
+
type: "SET";
|
|
7
|
+
}
|
|
8
|
+
| {
|
|
9
|
+
type: "INSERT";
|
|
10
|
+
pos: "LEADING" | "TRAILING";
|
|
11
|
+
payload: ColumnDef<T>;
|
|
12
|
+
}
|
|
13
|
+
| { type: "INSERT"; pos: "INDEX"; index: number; payload: ColumnDef<T> }
|
|
14
|
+
| {
|
|
15
|
+
type: "UPDATE";
|
|
16
|
+
index?: number;
|
|
17
|
+
id?: string | number;
|
|
18
|
+
payload: Partial<ColumnDef<T>>;
|
|
19
|
+
};
|
|
20
|
+
export function dataGridReducer<T>(
|
|
21
|
+
state: ColumnDef<T>[],
|
|
22
|
+
action: Action<T>,
|
|
23
|
+
): ColumnDef<T>[] {
|
|
24
|
+
const { type, payload } = action;
|
|
25
|
+
|
|
26
|
+
let itemIndex: number | null = null;
|
|
27
|
+
if (action.type === "INSERT" && action.pos === "INDEX")
|
|
28
|
+
itemIndex = action.index;
|
|
29
|
+
if (action.type === "UPDATE")
|
|
30
|
+
itemIndex =
|
|
31
|
+
action.index ??
|
|
32
|
+
state.filter(({ id }) => !!id).findIndex(({ id }) => id === action.id);
|
|
33
|
+
switch (type) {
|
|
34
|
+
case "SET":
|
|
35
|
+
return [...payload];
|
|
36
|
+
case "UPDATE":
|
|
37
|
+
if (typeof itemIndex !== "number" || itemIndex < 0)
|
|
38
|
+
throw new Error("action.(id | index) must be provided.");
|
|
39
|
+
|
|
40
|
+
return [
|
|
41
|
+
...state.slice(0, itemIndex),
|
|
42
|
+
{
|
|
43
|
+
...state[itemIndex],
|
|
44
|
+
...payload,
|
|
45
|
+
meta: {
|
|
46
|
+
...(state[itemIndex].meta ?? {}),
|
|
47
|
+
...(payload.meta ?? {}),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
...state.slice(itemIndex + 1),
|
|
51
|
+
] as ColumnDef<T>[];
|
|
52
|
+
default:
|
|
53
|
+
throw new Error("Action type not implemented.");
|
|
54
|
+
}
|
|
55
|
+
}
|