@@ -16,14 +16,12 @@ import {
1616import { Virtualizer , useVirtualizer } from "@tanstack/react-virtual" ;
1717import React , {
1818 FC ,
19- ReactElement ,
2019 StrictMode ,
2120 useCallback ,
2221 useEffect ,
2322 useLayoutEffect ,
2423 useMemo ,
2524 useRef ,
26- useState ,
2725} from "react" ;
2826import { Root , createRoot } from "react-dom/client" ;
2927import { ErrorsMessageValue } from "rstudio-shiny/srcts/types/src/shiny/shinyapp" ;
@@ -36,12 +34,13 @@ import type { CellSelection, SelectionModesProp } from "./selection";
3634import { SelectionModes , initSelectionModes , useSelection } from "./selection" ;
3735import { SortingState , useSort } from "./sort" ;
3836import { SortArrow } from "./sort-arrows" ;
37+ import { StyleInfo , getCellStyle , useStyleInfoMap } from "./style-info" ;
3938import css from "./styles.scss" ;
4039import { useTabindexGroup } from "./tabindex-group" ;
4140import { useSummary } from "./table-summary" ;
42- import { EditModeEnum , PandasData , PatchInfo , TypeHint } from "./types" ;
41+ import { PandasData , PatchInfo , TypeHint } from "./types" ;
4342
44- // TODO-barret set selected cell as input! (Might be a followup?)
43+ // TODO-barret-future set selected cell as input! (Might be a followup?)
4544
4645// TODO-barret; Type support
4746// export interface PandasData<TIndex> {
@@ -109,7 +108,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
109108 const {
110109 columns,
111110 typeHints,
112- data : rowData ,
111+ data : tableDataProp ,
113112 options : payloadOptions ,
114113 } = payload ;
115114 const { width, height, fill, filters : withFilters } = payloadOptions ;
@@ -118,10 +117,42 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
118117 const theadRef = useRef < HTMLTableSectionElement > ( null ) ;
119118 const tbodyRef = useRef < HTMLTableSectionElement > ( null ) ;
120119
121- const { cellEditMap, setCellEditMapAtLoc } = useCellEditMap ( ) ;
122-
120+ const _useStyleInfo = useStyleInfoMap ( {
121+ initStyleInfos : payloadOptions [ "styles" ] ,
122+ nrow : tableDataProp . length ,
123+ ncol : columns . length ,
124+ } ) ;
125+ /**
126+ * Contains all style information for the full table.
127+ *
128+ * Currently only the "data" location is supported.
129+ */
130+ const styleInfoMap = _useStyleInfo . styleInfoMap ;
131+ const { resetStyleInfos, setStyleInfos } = _useStyleInfo ;
132+
133+ const _cellEditMap = useCellEditMap ( ) ;
134+ /**
135+ * Contains all cell state and edit information
136+ *
137+ * If a cell's state is not in this map, it is assumed to be in the default display state.
138+ */
139+ const cellEditMap = _cellEditMap . cellEditMap ;
140+ /**
141+ * Set a cell's state or edit value in the `cellEditMap`
142+ */
143+ const setCellEditMapAtLoc = _cellEditMap . setCellEditMapAtLoc ;
144+
145+ /**
146+ * Determines if the user is allowed to edit cells in the table.
147+ */
123148 const editCellsIsAllowed = payloadOptions [ "editable" ] === true ;
149+ ( "Barret" ) ;
124150
151+ /**
152+ * Determines if any cell is currently being edited
153+ *
154+ * This is currently being used to prevent row selection when a cell is being edited.
155+ */
125156 const isEditingCell = useMemo < boolean > ( ( ) => {
126157 for ( const cellEdit of cellEditMap . values ( ) ) {
127158 if ( cellEdit . isEditing ) {
@@ -131,6 +162,9 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
131162 return false ;
132163 } , [ cellEditMap ] ) ;
133164
165+ /**
166+ * Column definitions for the table
167+ */
134168 const coldefs = useMemo < ColumnDef < unknown [ ] , unknown > [ ] > (
135169 ( ) =>
136170 columns . map ( ( colname , colIndex ) => {
@@ -179,16 +213,30 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
179213 // }
180214 // const [autoResetPageIndex, skipAutoResetPageIndex] = useSkipper();
181215
182- const dataOriginal = useMemo ( ( ) => rowData , [ rowData ] ) ;
183- const [ dataState , setData ] = useImmer ( rowData ) ;
216+ /**
217+ * Copy of the original data
218+ */
219+ const dataOriginal = useMemo ( ( ) => tableDataProp , [ tableDataProp ] ) ;
220+
221+ const _tableData = useImmer ( tableDataProp ) ;
222+ /** Up-to-date data for the table */
223+ const tableData = _tableData [ 0 ] ;
224+ /** Function to update the data in the table */
225+ const setTableData = _tableData [ 1 ] ;
184226
185227 const getColDefs = ( ) : ColumnDef < unknown [ ] , unknown > [ ] => {
186228 return coldefs ;
187229 } ;
188230
189- const { sorting, sortState, sortingTableOptions, setSorting } = useSort ( {
190- getColDefs,
191- } ) ;
231+ const _sort = useSort ( { getColDefs } ) ;
232+ /** Sorting state of the table */
233+ const sorting = _sort . sorting ;
234+ /** Table options specific for sorting */
235+ const sortTableStateOptions = _sort . sortTableStateOptions ;
236+ /** Sorting state of the table */
237+ const sortTableOptions = _sort . sortTableOptions ;
238+ /** Set the sorting state of the table */
239+ const setSorting = _sort . setSorting ;
192240
193241 const {
194242 columnFilters,
@@ -198,14 +246,14 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
198246 } = useFilters < unknown [ ] > ( withFilters ) ;
199247
200248 const options : TableOptions < unknown [ ] > = {
201- data : dataState ,
249+ data : tableData ,
202250 columns : coldefs ,
203251 state : {
204- ...sortState ,
252+ ...sortTableStateOptions ,
205253 ...columnFiltersState ,
206254 } ,
207255 getCoreRowModel : getCoreRowModel ( ) ,
208- ...sortingTableOptions ,
256+ ...sortTableOptions ,
209257 ...filtersTableOptions ,
210258 // debugAll: true,
211259 // Provide our updateCellsData function to our table meta
@@ -366,7 +414,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
366414 handleCellSelection as EventListener
367415 ) ;
368416 } ;
369- } , [ id , selection , rowData ] ) ;
417+ } , [ id , selection , tableData ] ) ;
370418
371419 useEffect ( ( ) => {
372420 const handleColumnSort = (
@@ -436,6 +484,28 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
436484 } ;
437485 } , [ columns , id , setColumnFilters ] ) ;
438486
487+ useEffect ( ( ) => {
488+ const handleStyles = ( event : CustomEvent < { styles : StyleInfo [ ] } > ) => {
489+ const styles = event . detail . styles ;
490+ resetStyleInfos ( ) ;
491+ setStyleInfos ( styles ) ;
492+ } ;
493+
494+ if ( ! id ) return ;
495+
496+ const element = document . getElementById ( id ) ;
497+ if ( ! element ) return ;
498+
499+ element . addEventListener ( "updateStyles" , handleStyles as EventListener ) ;
500+
501+ return ( ) => {
502+ element . removeEventListener (
503+ "updateStyles" ,
504+ handleStyles as EventListener
505+ ) ;
506+ } ;
507+ } , [ setStyleInfos ] ) ;
508+
439509 useEffect ( ( ) => {
440510 if ( ! id ) return ;
441511 let shinyValue : CellSelection | null = null ;
@@ -569,7 +639,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
569639 const headerRowCount = table . getHeaderGroups ( ) . length ;
570640
571641 // Assume we're scrolling until proven otherwise
572- let scrollingClass = rowData . length > 0 ? "scrolling" : "" ;
642+ let scrollingClass = tableData . length > 0 ? "scrolling" : "" ;
573643 const scrollHeight = containerRef . current ?. scrollHeight ;
574644 const clientHeight = containerRef . current ?. clientHeight ;
575645 if ( scrollHeight && clientHeight && scrollHeight <= clientHeight ) {
@@ -601,7 +671,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
601671 >
602672 < table
603673 className = { tableClass + ( withFilters ? " filtering" : "" ) }
604- aria-rowcount = { dataState . length }
674+ aria-rowcount = { tableData . length }
605675 aria-multiselectable = { canMultiRowSelect }
606676 style = { {
607677 width : width === null || width === "auto" ? undefined : "100%" ,
@@ -693,6 +763,12 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
693763 rowIndex ,
694764 columnIndex
695765 ) ;
766+ const cellStyle = getCellStyle (
767+ styleInfoMap ,
768+ "body" ,
769+ rowIndex ,
770+ columnIndex
771+ ) ;
696772
697773 return (
698774 < TableBodyCell
@@ -708,7 +784,8 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
708784 columnIndex = { columnIndex }
709785 getSortedRowModel = { table . getSortedRowModel }
710786 cellEditInfo = { cellEditInfo }
711- setData = { setData }
787+ cellStyle = { cellStyle }
788+ setData = { setTableData }
712789 setCellEditMapAtLoc = { setCellEditMapAtLoc }
713790 selection = { selection }
714791 > </ TableBodyCell >
0 commit comments