Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
dc9d171
First pass at making cells have styles!
schloerke Jun 21, 2024
b018c81
Use a DOM element to convert the style string from a str to an object
schloerke Jun 21, 2024
ecfe9c1
Clean up pandas warnings
schloerke Jun 21, 2024
b06b404
Update setup.cfg
schloerke Jun 21, 2024
db9d455
Update app.py
schloerke Jun 21, 2024
1c45331
lints
schloerke Jun 21, 2024
7e53a10
Add `DataTable` support to `DataGrid`
schloerke Jun 21, 2024
85bed6b
Merge branch 'main' into df-style-cell
schloerke Jun 25, 2024
4cc1838
commit code before purging `great_tables` support
schloerke Jun 26, 2024
467c901
Remove `great_tables` from deps
schloerke Jul 1, 2024
c6991c8
Add json style support for `render.DataGrid` and `render.DataTable`
schloerke Jul 1, 2024
4f6aed5
Add test for `great_tables` styling
schloerke Jul 1, 2024
65555e9
Allow for render.DataTable in addition to render.DataGrid testing
schloerke Jul 1, 2024
d1fd962
Clean up broken test with cleaner test example
schloerke Jul 1, 2024
1d7114b
Fix broken lints
schloerke Jul 1, 2024
44e59de
Test that rows an cols can be `None` in user definition. Browser will…
schloerke Jul 1, 2024
35ff978
Style text area to be same color as `--bs-body-bg`, not inherit (whic…
schloerke Jul 1, 2024
e0d2873
Update test_df_styles.py
schloerke Jul 1, 2024
ec0902b
Update _styles.py
schloerke Jul 1, 2024
a725d75
More `Required` fixes
schloerke Jul 1, 2024
cd483d3
More legacy lints
schloerke Jul 1, 2024
ede7bff
moar type lints
schloerke Jul 1, 2024
75f5b91
"I once again ask for ordered imports"
schloerke Jul 1, 2024
533d865
Merge branch 'main' into df-style-cell
schloerke Jul 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion js/data-frame/cell.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ColumnDef, RowModel, flexRender } from "@tanstack/react-table";
import { VirtualItem } from "@tanstack/react-virtual";
import { Cell } from "@tanstack/table-core";
import React, {
FC,
Expand All @@ -15,6 +14,7 @@ import React, {
import { CellEdit, SetCellEditMapAtLoc } from "./cell-edit-map";
import { updateCellsData } from "./data-update";
import { SelectionSet } from "./selection";
import { CellStyle } from "./style-info";
import type { PatchInfo } from "./types";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -82,6 +82,7 @@ interface TableBodyCellProps {
getSortedRowModel: () => RowModel<unknown[]>;
setData: (fn: (draft: unknown[][]) => void) => void;
cellEditInfo: CellEdit | undefined;
cellStyle: CellStyle | undefined;
setCellEditMapAtLoc: SetCellEditMapAtLoc;
selection: SelectionSet<string, HTMLTableRowElement>;
}
Expand All @@ -98,6 +99,7 @@ export const TableBodyCell: FC<TableBodyCellProps> = ({
editCellsIsAllowed,
getSortedRowModel,
cellEditInfo,
cellStyle,
setData,
setCellEditMapAtLoc,
selection,
Expand Down Expand Up @@ -487,6 +489,7 @@ export const TableBodyCell: FC<TableBodyCellProps> = ({
onDoubleClick={onCellDoubleClick}
title={cellTitle}
className={tableCellClass}
style={{ ...cellStyle }}
>
{editContent}
{content}
Expand Down
115 changes: 96 additions & 19 deletions js/data-frame/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ import {
import { Virtualizer, useVirtualizer } from "@tanstack/react-virtual";
import React, {
FC,
ReactElement,
StrictMode,
useCallback,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
} from "react";
import { Root, createRoot } from "react-dom/client";
import { ErrorsMessageValue } from "rstudio-shiny/srcts/types/src/shiny/shinyapp";
Expand All @@ -36,12 +34,13 @@ import type { CellSelection, SelectionModesProp } from "./selection";
import { SelectionModes, initSelectionModes, useSelection } from "./selection";
import { SortingState, useSort } from "./sort";
import { SortArrow } from "./sort-arrows";
import { StyleInfo, getCellStyle, useStyleInfoMap } from "./style-info";
import css from "./styles.scss";
import { useTabindexGroup } from "./tabindex-group";
import { useSummary } from "./table-summary";
import { EditModeEnum, PandasData, PatchInfo, TypeHint } from "./types";
import { PandasData, PatchInfo, TypeHint } from "./types";

// TODO-barret set selected cell as input! (Might be a followup?)
// TODO-barret-future set selected cell as input! (Might be a followup?)

// TODO-barret; Type support
// export interface PandasData<TIndex> {
Expand Down Expand Up @@ -109,7 +108,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
const {
columns,
typeHints,
data: rowData,
data: tableDataProp,
options: payloadOptions,
} = payload;
const { width, height, fill, filters: withFilters } = payloadOptions;
Expand All @@ -118,10 +117,42 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
const theadRef = useRef<HTMLTableSectionElement>(null);
const tbodyRef = useRef<HTMLTableSectionElement>(null);

const { cellEditMap, setCellEditMapAtLoc } = useCellEditMap();

const _useStyleInfo = useStyleInfoMap({
initStyleInfos: payloadOptions["styles"],
nrow: tableDataProp.length,
ncol: columns.length,
});
/**
* Contains all style information for the full table.
*
* Currently only the "data" location is supported.
*/
const styleInfoMap = _useStyleInfo.styleInfoMap;
const { resetStyleInfos, setStyleInfos } = _useStyleInfo;

const _cellEditMap = useCellEditMap();
/**
* Contains all cell state and edit information
*
* If a cell's state is not in this map, it is assumed to be in the default display state.
*/
const cellEditMap = _cellEditMap.cellEditMap;
/**
* Set a cell's state or edit value in the `cellEditMap`
*/
const setCellEditMapAtLoc = _cellEditMap.setCellEditMapAtLoc;

/**
* Determines if the user is allowed to edit cells in the table.
*/
const editCellsIsAllowed = payloadOptions["editable"] === true;
("Barret");

/**
* Determines if any cell is currently being edited
*
* This is currently being used to prevent row selection when a cell is being edited.
*/
const isEditingCell = useMemo<boolean>(() => {
for (const cellEdit of cellEditMap.values()) {
if (cellEdit.isEditing) {
Expand All @@ -131,6 +162,9 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
return false;
}, [cellEditMap]);

/**
* Column definitions for the table
*/
const coldefs = useMemo<ColumnDef<unknown[], unknown>[]>(
() =>
columns.map((colname, colIndex) => {
Expand Down Expand Up @@ -179,16 +213,30 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
// }
// const [autoResetPageIndex, skipAutoResetPageIndex] = useSkipper();

const dataOriginal = useMemo(() => rowData, [rowData]);
const [dataState, setData] = useImmer(rowData);
/**
* Copy of the original data
*/
const dataOriginal = useMemo(() => tableDataProp, [tableDataProp]);

const _tableData = useImmer(tableDataProp);
/** Up-to-date data for the table */
const tableData = _tableData[0];
/** Function to update the data in the table */
const setTableData = _tableData[1];

const getColDefs = (): ColumnDef<unknown[], unknown>[] => {
return coldefs;
};

const { sorting, sortState, sortingTableOptions, setSorting } = useSort({
getColDefs,
});
const _sort = useSort({ getColDefs });
/** Sorting state of the table */
const sorting = _sort.sorting;
/** Table options specific for sorting */
const sortTableStateOptions = _sort.sortTableStateOptions;
/** Sorting state of the table */
const sortTableOptions = _sort.sortTableOptions;
/** Set the sorting state of the table */
const setSorting = _sort.setSorting;

const {
columnFilters,
Expand All @@ -198,14 +246,14 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
} = useFilters<unknown[]>(withFilters);

const options: TableOptions<unknown[]> = {
data: dataState,
data: tableData,
columns: coldefs,
state: {
...sortState,
...sortTableStateOptions,
...columnFiltersState,
},
getCoreRowModel: getCoreRowModel(),
...sortingTableOptions,
...sortTableOptions,
...filtersTableOptions,
// debugAll: true,
// Provide our updateCellsData function to our table meta
Expand Down Expand Up @@ -366,7 +414,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
handleCellSelection as EventListener
);
};
}, [id, selection, rowData]);
}, [id, selection, tableData]);

useEffect(() => {
const handleColumnSort = (
Expand Down Expand Up @@ -436,6 +484,28 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
};
}, [columns, id, setColumnFilters]);

useEffect(() => {
const handleStyles = (event: CustomEvent<{ styles: StyleInfo[] }>) => {
const styles = event.detail.styles;
resetStyleInfos();
setStyleInfos(styles);
};

if (!id) return;

const element = document.getElementById(id);
if (!element) return;

element.addEventListener("updateStyles", handleStyles as EventListener);

return () => {
element.removeEventListener(
"updateStyles",
handleStyles as EventListener
);
};
}, [setStyleInfos]);

useEffect(() => {
if (!id) return;
let shinyValue: CellSelection | null = null;
Expand Down Expand Up @@ -569,7 +639,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
const headerRowCount = table.getHeaderGroups().length;

// Assume we're scrolling until proven otherwise
let scrollingClass = rowData.length > 0 ? "scrolling" : "";
let scrollingClass = tableData.length > 0 ? "scrolling" : "";
const scrollHeight = containerRef.current?.scrollHeight;
const clientHeight = containerRef.current?.clientHeight;
if (scrollHeight && clientHeight && scrollHeight <= clientHeight) {
Expand Down Expand Up @@ -601,7 +671,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
>
<table
className={tableClass + (withFilters ? " filtering" : "")}
aria-rowcount={dataState.length}
aria-rowcount={tableData.length}
aria-multiselectable={canMultiRowSelect}
style={{
width: width === null || width === "auto" ? undefined : "100%",
Expand Down Expand Up @@ -693,6 +763,12 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
rowIndex,
columnIndex
);
const cellStyle = getCellStyle(
styleInfoMap,
"body",
rowIndex,
columnIndex
);

return (
<TableBodyCell
Expand All @@ -708,7 +784,8 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
columnIndex={columnIndex}
getSortedRowModel={table.getSortedRowModel}
cellEditInfo={cellEditInfo}
setData={setData}
cellStyle={cellStyle}
setData={setTableData}
setCellEditMapAtLoc={setCellEditMapAtLoc}
selection={selection}
></TableBodyCell>
Expand Down
8 changes: 4 additions & 4 deletions js/data-frame/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ export function useSort<TData>({
}): {
sorting: SortingState;
setSorting: React.Dispatch<React.SetStateAction<SortingState>>;
sortState: { sorting: SortingState };
sortingTableOptions: SortingOptions<TData>;
sortTableStateOptions: { sorting: SortingState };
sortTableOptions: SortingOptions<TData>;
} {
const [sorting, setSorting] = useState<SortingState>([]);

return {
sorting,
sortState: {
sortTableStateOptions: {
sorting,
},
sortingTableOptions: {
sortTableOptions: {
onSortingChange: (sortUpdater: Updater<SortingState>) => {
const newSorting: SortingState =
typeof sortUpdater === "function"
Expand Down
Loading