-
Notifications
You must be signed in to change notification settings - Fork 2
[1] Context passing table #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,5 +59,8 @@ | |
| "extends": [ | ||
| "plugin:storybook/recommended" | ||
| ] | ||
| }, | ||
| "dependencies": { | ||
| "react-icons": "^5.5.0" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import React, { createContext, useContext } from "react"; | ||
| import { MRT_ColumnDef, MRT_RowData, MRT_TableInstance, useMaterialReactTable } from "material-react-table"; | ||
| import { MaterialReactTableProps } from "material-react-table"; | ||
|
|
||
| // Create context with a type that can be cast to any table instance | ||
| export const SmartMRTContext = createContext<any>(null); | ||
|
|
||
| export const useTableContext = <T extends MRT_RowData>(): MRT_TableInstance<T> => { | ||
| const context = useContext(SmartMRTContext); | ||
| if (!context) { | ||
| throw new Error('useTableContext must be used within a TableContextProvider'); | ||
| } | ||
| return context as MRT_TableInstance<T>; | ||
| } | ||
|
|
||
| export const TableContextProvider = <T extends MRT_RowData>({ | ||
| children, | ||
| tableProps, | ||
| table | ||
| }: { | ||
| children: React.ReactNode, | ||
| tableProps: Omit<MaterialReactTableProps<T>, 'columns' | 'data'> & { | ||
| columns: MRT_ColumnDef<T>[]; | ||
| data: T[]; | ||
| }, | ||
| table?: MRT_TableInstance<T> | ||
|
Comment on lines
+22
to
+26
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its either of both right?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, updating |
||
| }) => { | ||
| const { columns, data, ...tablePropsWithoutColumnsAndData } = tableProps; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why remove columns, data, seperately?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changing |
||
| const tableInstance = table || useMaterialReactTable<T>({ | ||
| columns, | ||
| data, | ||
| globalFilterModeOptions: ['fuzzy', 'startsWith'], | ||
| ...tablePropsWithoutColumnsAndData | ||
| }); | ||
|
|
||
| return ( | ||
| <SmartMRTContext.Provider value={{...tableInstance}}> | ||
| {children} | ||
| </SmartMRTContext.Provider> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,22 @@ | ||
| import { MaterialReactTableProps, MRT_RowData } from "material-react-table"; | ||
| import { SmartReportMRT } from "../smart_report_mrt"; | ||
|
|
||
| import { MaterialReactTableProps, MRT_RowData, MRT_ColumnDef, MRT_TableInstance } from "material-react-table"; | ||
| import { TableContextProvider } from "../../TableContextProvider"; | ||
| import { SmartReportMRT } from "../smart_report_mrt/smart_report_mrt"; | ||
| type SmartReportProps<T extends MRT_RowData> = { | ||
| children: React.ReactNode; | ||
| tableProps?: never; | ||
| } | { | ||
| children?: never; | ||
| tableProps: MaterialReactTableProps<T>; | ||
| tableProps: Omit<MaterialReactTableProps<T>, 'columns' | 'data'> & { | ||
| columns: MRT_ColumnDef<T>[]; | ||
| data: T[]; | ||
| }; | ||
| table?: MRT_TableInstance<T>; | ||
| } | ||
|
|
||
| export const SmartReport = <T extends MRT_RowData>({children, tableProps}:SmartReportProps<T>) => { | ||
| if (children) { | ||
| return <>{children}</>; | ||
| } | ||
|
|
||
| if (!tableProps) { | ||
| return null; | ||
| } | ||
| export const SmartReport = <T extends MRT_RowData>({ | ||
| tableProps, | ||
| table | ||
| }: SmartReportProps<T>) => { | ||
|
|
||
| return <SmartReportMRT {...tableProps} />; | ||
| } | ||
| return ( | ||
| <TableContextProvider tableProps={tableProps} table={table}> | ||
| <SmartReportMRT /> | ||
| </TableContextProvider> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| /* --- Responsive Table CSS --- */ | ||
|
|
||
| .responsive-card-table { | ||
| width: 100%; | ||
| border-collapse: collapse; | ||
| } | ||
|
|
||
| /* Default Table Cell Padding (Example) */ | ||
| .responsive-card-table th, | ||
| .responsive-card-table td { | ||
| padding: 8px 12px; /* Adjust to match default MRT/MUI padding */ | ||
| text-align: left; | ||
| border-bottom: 1px solid #ddd; /* Default row separator */ | ||
| } | ||
| .responsive-card-table th { | ||
| font-weight: bold; | ||
| } | ||
| /* Remove bottom border from last row */ | ||
| .responsive-card-table tr:last-child td { | ||
| border-bottom: none; | ||
| } | ||
|
|
||
|
|
||
| /* --- Mobile Card View (Default Responsive) --- */ | ||
| /* @media screen and (max-width: 767px) { */ | ||
|
|
||
| /* Hide header by default in mobile */ | ||
| .responsive-card-table:not(.force-table-view) thead { | ||
| display: none; | ||
| } | ||
|
|
||
| /* Apply card styles only when NOT forced into table view */ | ||
| .responsive-card-table:not(.force-table-view) { | ||
| border: none; | ||
| box-shadow: none; | ||
| } | ||
|
|
||
| .responsive-card-table:not(.force-table-view) tbody, | ||
| .responsive-card-table:not(.force-table-view) tr, | ||
| .responsive-card-table:not(.force-table-view) td { | ||
| display: block; | ||
| width: 100% !important; | ||
| box-sizing: border-box; | ||
| } | ||
|
|
||
| .responsive-card-table:not(.force-table-view) tr { | ||
| margin-bottom: 1.5rem; | ||
| border: 1px solid #ddd; | ||
| border-radius: 5px; | ||
| overflow: hidden; | ||
| box-shadow: 0 2px 5px rgba(0,0,0,0.1); | ||
| background-color: #fff; | ||
| } | ||
|
|
||
| .responsive-card-table:not(.force-table-view) tr.MuiTableRow-root { | ||
| background-color: transparent; | ||
| } | ||
|
|
||
|
|
||
| .responsive-card-table:not(.force-table-view) td { | ||
| text-align: right; | ||
| padding-left: 50%; | ||
| padding-top: 10px; | ||
| padding-bottom: 10px; | ||
| position: relative; | ||
| border: none; | ||
| border-bottom: 1px solid #eee; | ||
| min-height: 30px; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: flex-end; | ||
| } | ||
|
|
||
| .responsive-card-table:not(.force-table-view) tr td:last-child { | ||
| border-bottom: none; | ||
| } | ||
|
|
||
| .responsive-card-table:not(.force-table-view) td::before { | ||
| content: attr(data-label); | ||
| position: absolute; | ||
| left: 10px; | ||
| top: 50%; | ||
| transform: translateY(-50%); | ||
| width: calc(50% - 20px); | ||
| padding-right: 10px; | ||
| font-weight: bold; | ||
| text-align: left; | ||
| white-space: nowrap; | ||
| overflow: hidden; | ||
| text-overflow: ellipsis; | ||
| color: #555; | ||
| } | ||
|
|
||
| /* --- Overrides when .force-table-view is active on mobile --- */ | ||
|
|
||
| /* IMPORTANT: Show header when table view is forced */ | ||
| .responsive-card-table.force-table-view thead { | ||
| display: table-header-group !important; /* Or initial */ | ||
| } | ||
|
|
||
| /* Reset row display */ | ||
| .responsive-card-table.force-table-view tr { | ||
| display: table-row !important; | ||
| /* Reset card styles */ | ||
| margin-bottom: 0 !important; | ||
| border: none !important; | ||
| border-radius: 0 !important; | ||
| box-shadow: none !important; | ||
| background-color: transparent !important; | ||
| overflow: visible !important; | ||
| } | ||
|
|
||
| /* Reset cell display and styles */ | ||
| .responsive-card-table.force-table-view td { | ||
| display: table-cell !important; | ||
| width: auto !important; /* Allow table layout */ | ||
| /* Reset card cell styles */ | ||
| text-align: left !important; /* Default alignment */ | ||
| padding: 8px 12px !important; /* Restore original padding */ | ||
| position: static !important; | ||
| border: none !important; /* Remove card border */ | ||
| border-bottom: 1px solid #ddd !important; /* Restore row border */ | ||
| min-height: auto !important; | ||
| } | ||
|
|
||
| /* Hide the generated labels when table view is forced */ | ||
| .responsive-card-table.force-table-view td::before { | ||
| display: none !important; | ||
| } | ||
|
|
||
| /* Ensure last row border is correctly removed in forced table view */ | ||
| .responsive-card-table.force-table-view tr:last-child td { | ||
| border-bottom: none !important; | ||
| } | ||
|
|
||
| /* } */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,27 @@ | ||
| import TableViewIcon from '@mui/icons-material/TableView'; | ||
| import ViewModuleIcon from '@mui/icons-material/ViewModule'; | ||
| import { Button } from "@mui/material"; | ||
| import { MaterialReactTable, MaterialReactTableProps, MRT_RowData } from "material-react-table"; | ||
| import { MaterialReactTable } from "material-react-table"; | ||
| import { useState } from "react"; | ||
| import "./smart_report_mrt.css"; | ||
| import "./smart_mrt.css"; | ||
| import { FaFilePdf } from 'react-icons/fa'; | ||
| import { useTableContext } from '../../TableContextProvider'; | ||
|
|
||
| /* | ||
| TODO: (Responsive Card View) | ||
| - Add a field `showInCardView` to the column definition. Default to false. | ||
| - Show columns that have `showInCardView` set to true in card view. | ||
| - When user toggles visibility of a column in card view, update the `showInCardView` field. | ||
| */ | ||
| export const SmartReportMRT = <T extends MRT_RowData>(props: MaterialReactTableProps<T>) => { | ||
| export const SmartReportMRT = () => { | ||
| // Get table instance from context | ||
| const table = useTableContext(); | ||
|
|
||
| // State to control the view mode override. Default to table view on desktop & card view on mobile. | ||
| const [forceTableView, setForceTableView] = useState(window.innerWidth >= 500); | ||
|
|
||
| return ( | ||
| <MaterialReactTable | ||
| // Add props to the main table element (<table>) | ||
| muiTableProps = {{ | ||
| // Conditionally add the 'force-table-view' class | ||
| className: `responsive-card-table ${forceTableView ? 'force-table-view' : ''}`, | ||
| sx: { | ||
| maxWidth: forceTableView ? '100%' : '500px', | ||
| maxWidth: forceTableView ? '100%' : '500px', | ||
| } | ||
| }} | ||
| // Add props to the table body cells (<td>) | ||
|
|
@@ -31,16 +31,29 @@ export const SmartReportMRT = <T extends MRT_RowData>(props: MaterialReactTableP | |
| })} | ||
| renderTopToolbar = {() => ( | ||
| <div className="top-toolbar"> | ||
| <Button | ||
| <Button | ||
| onClick={() => setForceTableView(!forceTableView)} | ||
| startIcon={forceTableView ? <ViewModuleIcon /> : <TableViewIcon />} | ||
| > | ||
| {forceTableView ? 'Switch to Card View' : null} | ||
| {forceTableView ? 'Card View' : 'Table View'} | ||
| </Button> | ||
| <Button variant="outlined" style={{ height:'100%'}} startIcon={<FaFilePdf />}> | ||
| View PDF | ||
| </Button> | ||
| </div> | ||
| )} | ||
|
|
||
| {...props} | ||
| // Use table instance from context instead of props | ||
| state={table.getState()} | ||
| columns={table.options.columns} | ||
| data={table.options.data} | ||
| enableColumnFilters={table.options.enableColumnFilters} | ||
| enableGlobalFilter={table.options.enableGlobalFilter} | ||
| enableColumnOrdering={table.options.enableColumnOrdering} | ||
| enableGrouping={table.options.enableGrouping} | ||
| enablePagination={table.options.enablePagination} | ||
| enableSorting={table.options.enableSorting} | ||
| // Add more table props as needed | ||
|
Comment on lines
+47
to
+56
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What the hell is this!?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. passing table = {table} is overriding the pdf button and other props we pass. This way buttons are showing, but from table actions we can't change table state, it has to be done via api. How to solve this?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. passing table = {table} is overriding the pdf button and other props we pass. This way buttons are showing, but from table actions we can't change table state, it has to be done via api. How to solve this? |
||
| /> | ||
| ); | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldnt this be dev-dependency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, updating