improve Table code organization & fix memo issues

This commit is contained in:
Sidney Alcantara
2022-11-17 18:17:43 +11:00
parent 6f8dd8cdc5
commit 6f0873ff7d
83 changed files with 420 additions and 372 deletions

View File

@@ -29,7 +29,7 @@ import SettingsIcon from "@mui/icons-material/SettingsOutlined";
import EvalIcon from "@mui/icons-material/PlayCircleOutline";
import MenuContents, { IMenuContentsProps } from "./MenuContents";
import ColumnHeader from "@src/components/Table/Column";
import ColumnHeader from "@src/components/Table/Mock/Column";
import {
projectScope,

View File

@@ -1,5 +1,5 @@
import { useAtom } from "jotai";
import { useLocation, useParams, Link as RouterLink } from "react-router-dom";
import { useParams, Link as RouterLink } from "react-router-dom";
import { find, camelCase, uniq } from "lodash-es";
import {

View File

@@ -1,5 +1,10 @@
import { forwardRef, useRef } from "react";
import { memo, useRef } from "react";
import { useAtom, useSetAtom } from "jotai";
import type { Header } from "@tanstack/react-table";
import type {
DraggableProvided,
DraggableStateSnapshot,
} from "react-beautiful-dnd";
import {
styled,
@@ -7,8 +12,8 @@ import {
TooltipProps,
tooltipClasses,
Fade,
Grid,
GridProps,
Stack,
StackProps,
IconButton,
Typography,
} from "@mui/material";
@@ -16,21 +21,58 @@ import DropdownIcon from "@mui/icons-material/MoreHoriz";
import LockIcon from "@mui/icons-material/LockOutlined";
import ColumnHeaderSort, { SORT_STATES } from "./ColumnHeaderSort";
import ColumnHeaderDragHandle from "./ColumnHeaderDragHandle";
import ColumnHeaderResizer from "./ColumnHeaderResizer";
import { projectScope, altPressAtom } from "@src/atoms/projectScope";
import {
tableScope,
selectedCellAtom,
columnMenuAtom,
tableSortsAtom,
} from "@src/atoms/tableScope";
import { getFieldProp } from "@src/components/fields";
import { COLUMN_HEADER_HEIGHT } from "@src/components/Table/Column";
import { ColumnConfig } from "@src/types/table";
import { FieldType } from "@src/constants/fields";
import { spreadSx } from "@src/utils/ui";
import { COLUMN_HEADER_HEIGHT } from "@src/components/Table/Mock/Column";
import type { ColumnConfig } from "@src/types/table";
import type { TableRow } from "@src/types/table";
export { COLUMN_HEADER_HEIGHT };
const StyledColumnHeader = styled(Stack)(({ theme }) => ({
position: "relative",
height: "100%",
border: `1px solid ${theme.palette.divider}`,
"& + &": { borderLeftStyle: "none" },
flexDirection: "row",
alignItems: "center",
padding: theme.spacing(0, 0.5, 0, 1),
"& svg, & button": { display: "block", zIndex: 1 },
backgroundColor: theme.palette.background.default,
color: theme.palette.text.secondary,
transition: theme.transitions.create("color", {
duration: theme.transitions.duration.short,
}),
"&:hover": { color: theme.palette.text.primary },
"& .MuiIconButton-root": {
color: theme.palette.text.disabled,
transition: theme.transitions.create(
["background-color", "opacity", "color"],
{ duration: theme.transitions.duration.short }
),
},
[`&:hover .MuiIconButton-root,
&:focus .MuiIconButton-root,
&:focus-within .MuiIconButton-root,
.MuiIconButton-root:focus`]: {
color: theme.palette.text.primary,
opacity: 1,
},
}));
const LightTooltip = styled(({ className, ...props }: TooltipProps) => (
<Tooltip {...props} classes={{ popper: className }} />
))(({ theme }) => ({
@@ -44,18 +86,34 @@ const LightTooltip = styled(({ className, ...props }: TooltipProps) => (
},
}));
export interface IColumnHeaderProps extends Partial<GridProps> {
export interface IColumnHeaderProps
extends Partial<Omit<StackProps, "style" | "sx">> {
header: Header<TableRow, any>;
column: ColumnConfig;
provided: DraggableProvided;
snapshot: DraggableStateSnapshot;
width: number;
isSelectedCell: boolean;
focusInsideCell: boolean;
children: React.ReactNode;
canEditColumns: boolean;
isLastFrozen: boolean;
}
export const ColumnHeader = forwardRef(function ColumnHeader(
{ column, width, focusInsideCell, children, ...props }: IColumnHeaderProps,
ref: React.Ref<HTMLDivElement>
) {
export const ColumnHeader = memo(function ColumnHeader({
header,
column,
provided,
snapshot,
width,
isSelectedCell,
focusInsideCell,
canEditColumns,
isLastFrozen,
}: IColumnHeaderProps) {
const openColumnMenu = useSetAtom(columnMenuAtom, tableScope);
const setSelectedCell = useSetAtom(selectedCellAtom, tableScope);
const [altPress] = useAtom(altPressAtom, projectScope);
const [tableSorts] = useAtom(tableSortsAtom, tableScope);
@@ -74,11 +132,19 @@ export const ColumnHeader = forwardRef(function ColumnHeader(
: tableSorts[0]?.direction || "none";
return (
<Grid
<StyledColumnHeader
role="columnheader"
id={`column-header-${column.key}`}
ref={ref}
{...props}
ref={provided.innerRef}
{...provided.draggableProps}
data-row-id={"_rowy_header"}
data-col-id={header.id}
data-frozen={header.column.getIsPinned() || undefined}
data-frozen-last={isLastFrozen || undefined}
tabIndex={isSelectedCell ? 0 : -1}
aria-colindex={header.index + 1}
aria-readonly={!canEditColumns}
aria-selected={isSelectedCell}
aria-sort={
currentSort === "none"
? "none"
@@ -86,34 +152,40 @@ export const ColumnHeader = forwardRef(function ColumnHeader(
? "ascending"
: "descending"
}
container
alignItems="center"
wrap="nowrap"
style={{
left: header.column.getIsPinned()
? header.column.getStart()
: undefined,
zIndex: header.column.getIsPinned() ? 11 : 10,
...provided.draggableProps.style,
width,
borderLeftStyle: snapshot.isDragging ? "solid" : undefined,
}}
onContextMenu={handleOpenMenu}
sx={[
{
height: "100%",
"& svg, & button": { display: "block", zIndex: 1 },
border: (theme) => `1px solid ${theme.palette.divider}`,
backgroundColor: "background.default",
color: "text.secondary",
transition: (theme) =>
theme.transitions.create("color", {
duration: theme.transitions.duration.short,
}),
"&:hover": { color: "text.primary" },
position: "relative",
py: 0,
pr: 0.5,
pl: 1,
width: "100%",
},
...spreadSx(props.sx),
]}
onClick={(e) => {
setSelectedCell({
path: "_rowy_header",
columnKey: header.id,
focusInside: false,
});
(e.target as HTMLDivElement).focus();
}}
onDoubleClick={(e) => {
setSelectedCell({
path: "_rowy_header",
columnKey: header.id,
focusInside: true,
});
(e.target as HTMLDivElement).focus();
}}
>
{provided.dragHandleProps && (
<ColumnHeaderDragHandle
dragHandleProps={provided.dragHandleProps}
tabIndex={focusInsideCell ? 0 : -1}
/>
)}
{width > 140 && (
<Tooltip
title={
@@ -127,8 +199,7 @@ export const ColumnHeader = forwardRef(function ColumnHeader(
placement="bottom-start"
arrow
>
<Grid
item
<div
onClick={() => {
navigator.clipboard.writeText(column.key);
}}
@@ -139,96 +210,87 @@ export const ColumnHeader = forwardRef(function ColumnHeader(
) : (
getFieldProp("icon", (column as any).type)
)}
</Grid>
</div>
</Tooltip>
)}
<Grid
item
xs
sx={{ flexShrink: 1, overflow: "hidden", my: 0, ml: 0.5, mr: -30 / 8 }}
>
<LightTooltip
title={
<Typography
sx={{
typography: "caption",
fontWeight: "fontWeightMedium",
lineHeight: `${COLUMN_HEADER_HEIGHT - 2 - 4}px`,
textOverflow: "clip",
}}
color="inherit"
>
{column.name as string}
</Typography>
}
enterDelay={1000}
placement="bottom-start"
disableInteractive
TransitionComponent={Fade}
sx={{ "& .MuiTooltip-tooltip": { marginTop: "-28px !important" } }}
>
<LightTooltip
title={
<Typography
noWrap
sx={{
typography: "caption",
fontWeight: "fontWeightMedium",
lineHeight: `${COLUMN_HEADER_HEIGHT - 2 - 4}px`,
textOverflow: "clip",
position: "relative",
zIndex: 1,
}}
component="div"
color="inherit"
>
{altPress ? (
<>
{column.index} <code>{column.fieldName}</code>
</>
) : (
column.name
)}
{column.name as string}
</Typography>
</LightTooltip>
</Grid>
}
enterDelay={1000}
placement="bottom-start"
disableInteractive
TransitionComponent={Fade}
sx={{ "& .MuiTooltip-tooltip": { marginTop: "-28px !important" } }}
>
<Typography
noWrap
sx={{
typography: "caption",
fontWeight: "fontWeightMedium",
textOverflow: "clip",
position: "relative",
zIndex: 1,
flexGrow: 1,
flexShrink: 1,
overflow: "hidden",
my: 0,
ml: 0.5,
mr: -30 / 8,
}}
component="div"
color="inherit"
>
{altPress ? (
<>
{column.index} <code>{column.fieldName}</code>
</>
) : (
column.name
)}
</Typography>
</LightTooltip>
{column.type !== FieldType.id && (
<Grid item>
<ColumnHeaderSort
sortKey={sortKey}
currentSort={currentSort}
tabIndex={focusInsideCell ? 0 : -1}
/>
</Grid>
<ColumnHeaderSort
sortKey={sortKey}
currentSort={currentSort}
tabIndex={focusInsideCell ? 0 : -1}
/>
)}
<Grid item>
<Tooltip title="Column settings">
<IconButton
size="small"
aria-label={`Column settings for ${column.name as string}`}
tabIndex={focusInsideCell ? 0 : -1}
id={`column-settings-${column.key}`}
color="inherit"
onClick={handleOpenMenu}
ref={buttonRef}
sx={{
transition: (theme) =>
theme.transitions.create("color", {
duration: theme.transitions.duration.short,
}),
<Tooltip title="Column settings">
<IconButton
size="small"
tabIndex={focusInsideCell ? 0 : -1}
id={`column-settings-${column.key}`}
onClick={handleOpenMenu}
ref={buttonRef}
>
<DropdownIcon />
</IconButton>
</Tooltip>
color: "text.disabled",
"[role='columnheader']:hover &, [role='columnheader']:focus &, [role='columnheader']:focus-within &, &:focus":
{ color: "text.primary" },
}}
>
<DropdownIcon />
</IconButton>
</Tooltip>
</Grid>
{children}
</Grid>
{header.column.getCanResize() && (
<ColumnHeaderResizer
isResizing={header.column.getIsResizing()}
onMouseDown={header.getResizeHandler()}
onTouchStart={header.getResizeHandler()}
/>
)}
</StyledColumnHeader>
);
});

View File

@@ -0,0 +1,58 @@
import type { DraggableProvidedDragHandleProps } from "react-beautiful-dnd";
import { DragVertical } from "@src/assets/icons";
export interface IColumnHeaderDragHandleProps {
dragHandleProps: DraggableProvidedDragHandleProps;
tabIndex: number;
}
export default function ColumnHeaderDragHandle({
dragHandleProps,
tabIndex,
}: IColumnHeaderDragHandleProps) {
return (
<div
{...dragHandleProps}
tabIndex={tabIndex}
aria-describedby={
tabIndex > -1 ? dragHandleProps["aria-describedby"] : undefined
}
style={{
position: "absolute",
inset: 0,
zIndex: 0,
display: "flex",
alignItems: "center",
outline: "none",
}}
className="column-drag-handle"
>
<DragVertical
sx={{
opacity: 0,
borderRadius: 2,
transition: (theme) => theme.transitions.create(["opacity"]),
"[role='columnheader']:hover &, [role='columnheader']:focus-within &":
{
opacity: 0.5,
},
".column-drag-handle:hover &": {
opacity: 1,
},
".column-drag-handle:active &": {
opacity: 1,
color: "primary.main",
},
".column-drag-handle:focus &": {
opacity: 1,
color: "primary.main",
outline: "2px solid",
outlineColor: "primary.main",
},
}}
style={{ width: 8 }}
preserveAspectRatio="xMidYMid slice"
/>
</div>
);
}

View File

@@ -1,13 +1,13 @@
import { styled } from "@mui/material";
export interface IStyledResizerProps {
export interface IColumnHeaderResizerProps {
isResizing: boolean;
}
export const StyledResizer = styled("div", {
name: "StyledResizer",
export const ColumnHeaderResizer = styled("div", {
name: "ColumnHeaderResizer",
shouldForwardProp: (prop) => prop !== "isResizing",
})<IStyledResizerProps>(({ theme, isResizing }) => ({
})<IColumnHeaderResizerProps>(({ theme, isResizing }) => ({
position: "absolute",
zIndex: 5,
right: 0,
@@ -51,6 +51,6 @@ export const StyledResizer = styled("div", {
transform: isResizing ? "scaleY(1.5) !important" : undefined,
},
}));
StyledResizer.displayName = "StyledResizer";
ColumnHeaderResizer.displayName = "ColumnHeaderResizer";
export default StyledResizer;
export default ColumnHeaderResizer;

View File

@@ -1,3 +1,4 @@
import { memo } from "react";
import { useSetAtom } from "jotai";
import { colord } from "colord";
@@ -17,7 +18,7 @@ export interface IColumnHeaderSortProps {
tabIndex?: number;
}
export default function ColumnHeaderSort({
export const ColumnHeaderSort = memo(function ColumnHeaderSort({
sortKey,
currentSort,
tabIndex,
@@ -34,7 +35,7 @@ export default function ColumnHeaderSort({
return (
<Tooltip
title={nextSort === "none" ? "Unsort" : `Sort by ${nextSort}ending`}
title={nextSort === "none" ? "Remove sort" : `Sort by ${nextSort}ending`}
>
<IconButton
disableFocusRipple={true}
@@ -68,13 +69,6 @@ export default function ColumnHeaderSort({
position: "relative",
opacity: currentSort !== "none" ? 1 : 0,
"[role='columnheader']:hover &, [role='columnheader']:focus &, [role='columnheader']:focus-within &, &:focus":
{ opacity: 1 },
transition: (theme) =>
theme.transitions.create(["background-color", "opacity"], {
duration: theme.transitions.duration.short,
}),
"& .arrow": {
transition: (theme) =>
@@ -108,4 +102,6 @@ export default function ColumnHeaderSort({
</IconButton>
</Tooltip>
);
}
});
export default ColumnHeaderSort;

View File

@@ -1,6 +1,6 @@
import { memo } from "react";
import { useAtom, useSetAtom } from "jotai";
import type { ITableCellProps } from "@src/components/Table/withTableCell";
import type { IRenderedTableCellProps } from "@src/components/Table/TableCell/withRenderTableCell";
import { Stack, Tooltip, IconButton, alpha } from "@mui/material";
import { CopyCells as CopyCellsIcon } from "@src/assets/icons";
@@ -25,7 +25,7 @@ import {
export const FinalColumn = memo(function FinalColumn({
row,
focusInsideCell,
}: ITableCellProps) {
}: IRenderedTableCellProps) {
const [userRoles] = useAtom(userRolesAtom, projectScope);
const [addRowIdType] = useAtom(tableAddRowIdTypeAtom, projectScope);
const confirm = useSetAtom(confirmDialogAtom, projectScope);

View File

@@ -105,7 +105,6 @@ export const Column = forwardRef(function Column(
ml: 0.5,
}}
aria-hidden
>
{label}
</Typography>

View File

@@ -221,6 +221,7 @@ export default function Table({
canAddColumns={canAddColumns}
canEditColumns={canEditColumns}
lastFrozen={lastFrozen}
columnSizing={columnSizing}
/>
</div>
@@ -233,6 +234,7 @@ export default function Table({
rows={rows}
canEditCells={canEditCells}
lastFrozen={lastFrozen}
columnSizing={columnSizing}
/>
)}
</StyledTable>

View File

@@ -1,9 +1,10 @@
import { memo } from "react";
import { useAtom } from "jotai";
import type { Column, Row } from "@tanstack/react-table";
import type { Column, Row, ColumnSizingState } from "@tanstack/react-table";
import StyledRow from "./Styled/StyledRow";
import OutOfOrderIndicator from "./OutOfOrderIndicator";
import CellValidation from "./CellValidation";
import CellValidation from "./TableCell";
import { RowsSkeleton } from "./TableSkeleton";
import {
@@ -29,9 +30,12 @@ export interface ITableBodyProps {
canEditCells: boolean;
lastFrozen?: string;
/** Re-render when local column sizing changes */
columnSizing: ColumnSizingState;
}
export default function TableBody({
export const TableBody = memo(function TableBody({
containerRef,
leafColumns,
rows,
@@ -105,9 +109,11 @@ export default function TableBody({
: undefined
}
isSelectedCell={isSelectedCell}
focusInsideCell={isSelectedCell && selectedCell?.focusInside}
isReadOnlyCell={isReadOnlyCell}
canEditCells={canEditCells}
lastFrozen={lastFrozen}
isLastFrozen={lastFrozen === cell.column.id}
width={cell.column.getSize()}
rowHeight={tableSchema.rowHeight || DEFAULT_ROW_HEIGHT}
/>
);
@@ -127,4 +133,6 @@ export default function TableBody({
)}
</div>
);
}
});
export default TableBody;

View File

@@ -1,5 +1,5 @@
import { memo } from "react";
import { useAtom, useSetAtom } from "jotai";
import { useSetAtom } from "jotai";
import { ErrorBoundary } from "react-error-boundary";
import { flexRender } from "@tanstack/react-table";
import type { Row, Cell } from "@tanstack/react-table";
@@ -8,7 +8,7 @@ import { styled } from "@mui/material/styles";
import ErrorIcon from "@mui/icons-material/ErrorOutline";
import WarningIcon from "@mui/icons-material/WarningAmber";
import StyledCell from "./Styled/StyledCell";
import StyledCell from "@src/components/Table/Styled/StyledCell";
import { InlineErrorFallback } from "@src/components/ErrorFallback";
import RichTooltip from "@src/components/RichTooltip";
@@ -18,7 +18,7 @@ import {
contextMenuTargetAtom,
} from "@src/atoms/tableScope";
import type { TableRow } from "@src/types/table";
import type { ITableCellProps } from "./withTableCell";
import type { IRenderedTableCellProps } from "./withRenderTableCell";
const Dot = styled("div")(({ theme }) => ({
position: "absolute",
@@ -39,31 +39,34 @@ const Dot = styled("div")(({ theme }) => ({
},
}));
export interface ICellValidationProps {
export interface ITableCellProps {
row: Row<TableRow>;
cell: Cell<TableRow, any>;
index: number;
isSelectedCell: boolean;
focusInsideCell: boolean;
isReadOnlyCell: boolean;
canEditCells: boolean;
rowHeight: number;
lastFrozen?: string;
isLastFrozen: boolean;
width: number;
left?: number;
}
export const CellValidation = memo(function MemoizedCellValidation({
export const TableCell = memo(function TableCell({
row,
cell,
index,
isSelectedCell,
focusInsideCell,
isReadOnlyCell,
canEditCells,
rowHeight,
lastFrozen,
isLastFrozen,
width,
left,
}: ICellValidationProps) {
const [selectedCell, setSelectedCell] = useAtom(selectedCellAtom, tableScope);
const focusInsideCell = selectedCell?.focusInside ?? false;
}: ITableCellProps) {
const setSelectedCell = useSetAtom(selectedCellAtom, tableScope);
const setContextMenuTarget = useSetAtom(contextMenuTargetAtom, tableScope);
const value = cell.getValue();
@@ -97,10 +100,10 @@ export const CellValidation = memo(function MemoizedCellValidation({
);
}
const tableCellComponentProps: ITableCellProps = {
const tableCellComponentProps: IRenderedTableCellProps = {
...cell.getContext(),
value,
focusInsideCell: isSelectedCell && focusInsideCell,
focusInsideCell,
setFocusInsideCell: (focusInside: boolean) =>
setSelectedCell({
path: row.original._rowy_ref.path,
@@ -117,7 +120,7 @@ export const CellValidation = memo(function MemoizedCellValidation({
data-row-id={row.id}
data-col-id={cell.column.id}
data-frozen={cell.column.getIsPinned() || undefined}
data-frozen-last={lastFrozen === cell.column.id || undefined}
data-frozen-last={isLastFrozen || undefined}
role="gridcell"
tabIndex={isSelectedCell && !focusInsideCell ? 0 : -1}
aria-colindex={index + 1}
@@ -133,7 +136,7 @@ export const CellValidation = memo(function MemoizedCellValidation({
}
aria-invalid={isInvalid || isMissing}
style={{
width: cell.column.getSize(),
width,
height: rowHeight,
left,
backgroundColor:
@@ -178,4 +181,4 @@ export const CellValidation = memo(function MemoizedCellValidation({
);
});
export default CellValidation;
export default TableCell;

View File

@@ -0,0 +1,2 @@
export { default } from "./TableCell";
export * from "./TableCell";

View File

@@ -32,7 +32,7 @@ export interface ICellOptions {
popoverProps?: Partial<PopoverProps>;
}
export interface ITableCellProps<TValue = any>
export interface IRenderedTableCellProps<TValue = any>
extends CellContext<TableRow, TValue> {
value: TValue;
focusInsideCell: boolean;
@@ -60,7 +60,7 @@ export default function withTableCell(
options: ICellOptions = {}
) {
return memo(
function TableCell({
function RenderedTableCell({
row,
column,
value,
@@ -68,7 +68,7 @@ export default function withTableCell(
setFocusInsideCell,
disabled,
rowHeight,
}: ITableCellProps) {
}: IRenderedTableCellProps) {
// Render inline editor cell after timeout on mount
// to improve scroll performance
const [inlineEditorReady, setInlineEditorReady] = useState(false);

View File

@@ -2,14 +2,12 @@ import { memo } from "react";
import { useAtom } from "jotai";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import type { DropResult } from "react-beautiful-dnd";
import type { HeaderGroup } from "@tanstack/react-table";
import type { ColumnSizingState, HeaderGroup } from "@tanstack/react-table";
import type { TableRow } from "@src/types/table";
import StyledRow from "./Styled/StyledRow";
import ColumnHeader from "./ColumnHeader";
import StyledResizer from "./Styled/StyledResizer";
import FinalColumnHeader from "./FinalColumn/FinalColumnHeader";
import { DragVertical } from "@src/assets/icons";
import { tableScope, selectedCellAtom } from "@src/atoms/tableScope";
import { DEFAULT_ROW_HEIGHT } from "@src/components/Table";
@@ -20,6 +18,9 @@ export interface ITableHeaderProps {
canAddColumns: boolean;
canEditColumns: boolean;
lastFrozen?: string;
/** Re-render when local column sizing changes */
columnSizing: ColumnSizingState;
}
export const TableHeader = memo(function TableHeader({
@@ -29,8 +30,8 @@ export const TableHeader = memo(function TableHeader({
canEditColumns,
lastFrozen,
}: ITableHeaderProps) {
const [selectedCell, setSelectedCell] = useAtom(selectedCellAtom, tableScope);
const focusInsideCell = selectedCell?.focusInside ?? false;
const [selectedCell] = useAtom(selectedCellAtom, tableScope);
const focusInside = selectedCell?.focusInside ?? false;
return (
<DragDropContext onDragEnd={handleDropColumn}>
@@ -58,7 +59,7 @@ export const TableHeader = memo(function TableHeader({
data-row-id={"_rowy_header"}
data-col-id={header.id}
tabIndex={isSelectedCell ? 0 : -1}
focusInsideCell={isSelectedCell && focusInsideCell}
focusInsideCell={isSelectedCell && focusInside}
aria-colindex={header.index + 1}
aria-readonly={!canEditColumns}
aria-selected={isSelectedCell}
@@ -78,105 +79,16 @@ export const TableHeader = memo(function TableHeader({
>
{(provided, snapshot) => (
<ColumnHeader
key={header.id}
data-row-id={"_rowy_header"}
data-col-id={header.id}
data-frozen={header.column.getIsPinned() || undefined}
data-frozen-last={lastFrozen === header.id || undefined}
ref={provided.innerRef}
{...provided.draggableProps}
tabIndex={isSelectedCell ? 0 : -1}
aria-colindex={header.index + 1}
aria-readonly={!canEditColumns}
aria-selected={isSelectedCell}
header={header}
column={header.column.columnDef.meta!}
style={{
width: header.getSize(),
left: header.column.getIsPinned()
? header.column.getStart()
: undefined,
...provided.draggableProps.style,
zIndex: header.column.getIsPinned() ? 11 : 10,
}}
provided={provided}
snapshot={snapshot}
width={header.getSize()}
sx={
snapshot.isDragging
? undefined
: { "& + &": { borderLeft: "none" } }
}
onClick={(e) => {
setSelectedCell({
path: "_rowy_header",
columnKey: header.id,
focusInside: false,
});
(e.target as HTMLDivElement).focus();
}}
onDoubleClick={(e) => {
setSelectedCell({
path: "_rowy_header",
columnKey: header.id,
focusInside: true,
});
(e.target as HTMLDivElement).focus();
}}
focusInsideCell={isSelectedCell && focusInsideCell}
>
<div
{...provided.dragHandleProps}
tabIndex={isSelectedCell && focusInsideCell ? 0 : -1}
aria-describedby={
isSelectedCell && focusInsideCell
? provided.dragHandleProps?.["aria-describedby"]
: undefined
}
style={{
position: "absolute",
inset: 0,
zIndex: 0,
display: "flex",
alignItems: "center",
outline: "none",
}}
className="column-drag-handle"
>
<DragVertical
sx={{
opacity: 0,
borderRadius: 2,
transition: (theme) =>
theme.transitions.create(["opacity"]),
"[role='columnheader']:hover &, [role='columnheader']:focus-within &":
{
opacity: 0.5,
},
".column-drag-handle:hover &": {
opacity: 1,
},
".column-drag-handle:active &": {
opacity: 1,
color: "primary.main",
},
".column-drag-handle:focus &": {
opacity: 1,
color: "primary.main",
outline: "2px solid",
outlineColor: "primary.main",
},
}}
style={{ width: 8 }}
preserveAspectRatio="xMidYMid slice"
/>
</div>
{header.column.getCanResize() && (
<StyledResizer
isResizing={header.column.getIsResizing()}
onMouseDown={header.getResizeHandler()}
onTouchStart={header.getResizeHandler()}
/>
)}
</ColumnHeader>
isSelectedCell={isSelectedCell}
focusInsideCell={isSelectedCell && focusInside}
canEditColumns={canEditColumns}
isLastFrozen={lastFrozen === header.id}
/>
)}
</Draggable>
);

View File

@@ -4,7 +4,7 @@ import { colord } from "colord";
import { Fade, Stack, Skeleton, Button } from "@mui/material";
import { AddColumn as AddColumnIcon } from "@src/assets/icons";
import Column from "./Column";
import Column from "./Mock/Column";
import { projectScope, userSettingsAtom } from "@src/atoms/projectScope";
import {

View File

@@ -22,7 +22,9 @@ import { TableColumn as TableColumnIcon } from "@src/assets/icons";
import { IStepProps } from ".";
import { AirtableConfig } from "@src/components/TableModals/ImportAirtableWizard";
import FadeList from "@src/components/TableModals/ScrollableList";
import Column, { COLUMN_HEADER_HEIGHT } from "@src/components/Table/Column";
import Column, {
COLUMN_HEADER_HEIGHT,
} from "@src/components/Table/Mock/Column";
import ColumnSelect from "@src/components/Table/ColumnSelect";
import {

View File

@@ -6,8 +6,8 @@ import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import { IStepProps } from ".";
import ScrollableList from "@src/components/TableModals/ScrollableList";
import Column from "@src/components/Table/Column";
import Cell from "@src/components/Table/Cell";
import Column from "@src/components/Table/Mock/Column";
import Cell from "@src/components/Table/Mock/Cell";
import FieldsDropdown from "@src/components/ColumnModals/FieldsDropdown";
import { FieldType } from "@src/constants/fields";
import { SELECTABLE_TYPES } from "@src/components/TableModals/ImportExistingWizard/utils";

View File

@@ -2,8 +2,8 @@ import { useAtom } from "jotai";
import { find } from "lodash-es";
import { styled, Grid } from "@mui/material";
import Column from "@src/components/Table/Column";
import Cell from "@src/components/Table/Cell";
import Column from "@src/components/Table/Mock/Column";
import Cell from "@src/components/Table/Mock/Cell";
import { IStepProps } from ".";
import { tableScope, tableSchemaAtom } from "@src/atoms/tableScope";

View File

@@ -26,7 +26,9 @@ import { TableColumn as TableColumnIcon } from "@src/assets/icons";
import { IStepProps } from ".";
import { CsvConfig } from "@src/components/TableModals/ImportCsvWizard";
import FadeList from "@src/components/TableModals/ScrollableList";
import Column, { COLUMN_HEADER_HEIGHT } from "@src/components/Table/Column";
import Column, {
COLUMN_HEADER_HEIGHT,
} from "@src/components/Table/Mock/Column";
import ColumnSelect from "@src/components/Table/ColumnSelect";
import {

View File

@@ -7,8 +7,8 @@ import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import { IStepProps } from ".";
import ScrollableList from "@src/components/TableModals/ScrollableList";
import Column from "@src/components/Table/Column";
import Cell from "@src/components/Table/Cell";
import Column from "@src/components/Table/Mock/Column";
import Cell from "@src/components/Table/Mock/Cell";
import FieldsDropdown from "@src/components/ColumnModals/FieldsDropdown";
import { FieldType } from "@src/constants/fields";

View File

@@ -3,8 +3,8 @@ import { find } from "lodash-es";
import { parseJSON } from "date-fns";
import { styled, Grid } from "@mui/material";
import Column from "@src/components/Table/Column";
import Cell from "@src/components/Table/Cell";
import Column from "@src/components/Table/Mock/Column";
import Cell from "@src/components/Table/Mock/Cell";
import { IStepProps } from ".";
import { tableScope, tableSchemaAtom } from "@src/atoms/tableScope";

View File

@@ -20,7 +20,7 @@ import DragHandleIcon from "@mui/icons-material/DragHandle";
import { AddColumn as AddColumnIcon } from "@src/assets/icons";
import ScrollableList from "@src/components/TableModals/ScrollableList";
import Column from "@src/components/Table/Column";
import Column from "@src/components/Table/Mock/Column";
import EmptyState from "@src/components/EmptyState";
import { tableScope, tableRowsAtom } from "@src/atoms/tableScope";

View File

@@ -14,7 +14,9 @@ import DoneIcon from "@mui/icons-material/Done";
import { IStepProps } from ".";
import ScrollableList from "@src/components/TableModals/ScrollableList";
import Column, { COLUMN_HEADER_HEIGHT } from "@src/components/Table/Column";
import Column, {
COLUMN_HEADER_HEIGHT,
} from "@src/components/Table/Mock/Column";
export default function Step2Rename({
config,

View File

@@ -6,8 +6,8 @@ import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import { IStepProps } from ".";
import ScrollableList from "@src/components/TableModals/ScrollableList";
import Column from "@src/components/Table/Column";
import Cell from "@src/components/Table/Cell";
import Column from "@src/components/Table/Mock/Column";
import Cell from "@src/components/Table/Mock/Cell";
import FieldsDropdown from "@src/components/ColumnModals/FieldsDropdown";
import { tableScope, tableRowsAtom } from "@src/atoms/tableScope";

View File

@@ -2,8 +2,8 @@ import { useAtom } from "jotai";
import { IStepProps } from ".";
import { styled, Grid } from "@mui/material";
import Column from "@src/components/Table/Column";
import Cell from "@src/components/Table/Cell";
import Column from "@src/components/Table/Mock/Column";
import Cell from "@src/components/Table/Mock/Cell";
import { tableScope, tableRowsAtom } from "@src/atoms/tableScope";

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import ActionIcon from "@mui/icons-material/TouchAppOutlined";
import DisplayCell from "./DisplayCell";
@@ -24,7 +24,7 @@ export const config: IFieldConfig = {
icon: <ActionIcon />,
description:
"Button with pre-defined action script or triggers a Cloud Function. Optionally supports Undo and Redo.",
TableCell: withTableCell(DisplayCell, EditorCell, "inline", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "inline", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import CheckboxIcon from "@mui/icons-material/ToggleOnOutlined";
import DisplayCell from "./DisplayCell";
@@ -24,7 +24,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <CheckboxIcon />,
description: "True/false value. Default: false.",
TableCell: withTableCell(DisplayCell, EditorCell, "inline", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "inline", {
usesRowData: true,
}),
csvImportParser: (value: string) => {

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import CodeIcon from "@mui/icons-material/Code";
import DisplayCell from "./DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <CodeIcon />,
description: "Raw code edited with the Monaco Editor.",
TableCell: withTableCell(DisplayCell, SideDrawerField, "popover", {
TableCell: withRenderTableCell(DisplayCell, SideDrawerField, "popover", {
popoverProps: {
anchorOrigin: { vertical: "top", horizontal: "center" },
PaperProps: { sx: { borderRadius: 1 } },

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { toColor } from "react-color-palette";
import ColorIcon from "@mui/icons-material/Colorize";
@@ -25,7 +25,7 @@ export const config: IFieldConfig = {
icon: <ColorIcon />,
description:
"Color stored as Hex, RGB, and HSV. Edited with a visual picker.",
TableCell: withTableCell(DisplayCell, EditorCell, "popover", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "popover", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -3,7 +3,7 @@ import { IDisplayCellProps } from "@src/components/fields/types";
import { ButtonBase, Grid, Chip } from "@mui/material";
import { ChevronDown } from "@src/assets/icons";
import ChipList from "@src/components/Table/ChipList";
import ChipList from "@src/components/Table/TableCell/ChipList";
import { get } from "lodash-es";
export default function ConnectService({

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import ConnectServiceIcon from "@mui/icons-material/Http";
import DisplayCell from "./DisplayCell";
@@ -28,7 +28,7 @@ export const config: IFieldConfig = {
icon: <ConnectServiceIcon />,
description:
"Connects to an external web service to fetch a list of results.",
TableCell: withTableCell(DisplayCell, EditorCell, "popover", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "popover", {
disablePadding: true,
transparentPopover: true,
}),

View File

@@ -3,7 +3,7 @@ import { IDisplayCellProps } from "@src/components/fields/types";
import { ButtonBase, Grid, Chip } from "@mui/material";
import { ChevronDown } from "@src/assets/icons";
import ChipList from "@src/components/Table/ChipList";
import ChipList from "@src/components/Table/TableCell/ChipList";
export default function ConnectTable({
value,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { ConnectTable as ConnectTableIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -28,7 +28,7 @@ export const config: IFieldConfig = {
icon: <ConnectTableIcon />,
description:
"Connects to an existing table to fetch a snapshot of values from a row. Requires Rowy Run and Algolia setup.",
TableCell: withTableCell(DisplayCell, EditorCell, "popover", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "popover", {
disablePadding: true,
transparentPopover: true,
}),

View File

@@ -3,7 +3,7 @@ import { IDisplayCellProps } from "@src/components/fields/types";
import { ButtonBase, Grid, Chip } from "@mui/material";
import { ChevronDown } from "@src/assets/icons";
import ChipList from "@src/components/Table/ChipList";
import ChipList from "@src/components/Table/TableCell/ChipList";
import { get } from "lodash-es";
import { getLabel } from "./utils";

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import ConnectorIcon from "@mui/icons-material/Cable";
import DisplayCell from "./DisplayCell";
@@ -29,7 +29,7 @@ export const config: IFieldConfig = {
icon: <ConnectorIcon />,
description:
"Connects to any table or API to fetch a list of results based on a text query or row data.",
TableCell: withTableCell(DisplayCell, EditorCell, "popover", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "popover", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { CreatedAt as CreatedAtIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -24,7 +24,7 @@ export const config: IFieldConfig = {
initialValue: null,
icon: <CreatedAtIcon />,
description: "Displays the timestamp of when the row was created. Read-only.",
TableCell: withTableCell(DisplayCell, null),
TableCell: withRenderTableCell(DisplayCell, null),
SideDrawerField,
settings: Settings,
};

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { CreatedBy as CreatedByIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -25,7 +25,7 @@ export const config: IFieldConfig = {
icon: <CreatedByIcon />,
description:
"Displays the user that created the row and timestamp. Read-only.",
TableCell: withTableCell(DisplayCell, null),
TableCell: withRenderTableCell(DisplayCell, null),
SideDrawerField,
settings: Settings,
};

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { parse, format } from "date-fns";
import { DATE_FORMAT } from "@src/constants/dates";
@@ -28,7 +28,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <DateIcon />,
description: `Formatted date. Format is configurable, default: ${DATE_FORMAT}. Edited with a visual picker.`,
TableCell: withTableCell(DisplayCell, EditorCell, "focus", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "focus", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { parseJSON, format } from "date-fns";
import { DATE_TIME_FORMAT } from "@src/constants/dates";
@@ -36,7 +36,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <DateTimeIcon />,
description: `Formatted date & time. Format is configurable, default: ${DATE_TIME_FORMAT}. Edited with a visual picker.`,
TableCell: withTableCell(DisplayCell, EditorCell, "focus", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "focus", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,5 +1,5 @@
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Derivative as DerivativeIcon } from "@src/assets/icons";
import Settings, { settingsValidator } from "./Settings";
@@ -15,7 +15,7 @@ export const config: IFieldConfig = {
icon: <DerivativeIcon />,
description:
"Value derived from the rest of the rows values. Displayed using any other field type. Requires Rowy Run set up.",
TableCell: withTableCell(() => null, null),
TableCell: withRenderTableCell(() => null, null),
SideDrawerField: () => null as any,
contextMenuActions: ContextMenuActions,
settings: Settings,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import DurationIcon from "@mui/icons-material/TimerOutlined";
import DisplayCell from "./DisplayCell";
@@ -20,7 +20,7 @@ export const config: IFieldConfig = {
initialValue: {},
icon: <DurationIcon />,
description: "Duration calculated from two timestamps.",
TableCell: withTableCell(DisplayCell, SideDrawerField, "popover", {
TableCell: withRenderTableCell(DisplayCell, SideDrawerField, "popover", {
popoverProps: { PaperProps: { sx: { p: 1 } } },
}),
SideDrawerField,

View File

@@ -1,5 +1,5 @@
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
export default function Email(props: IEditorCellProps<string>) {
return <EditorCellTextField {...props} InputProps={{ type: "email" }} />;

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import EmailIcon from "@mui/icons-material/MailOutlined";
import DisplayCell from "@src/components/fields/ShortText/DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
icon: <EmailIcon />,
description: "Email address. Not validated.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, EditorCell),
TableCell: withRenderTableCell(DisplayCell, EditorCell),
SideDrawerField,
filter: {
operators: filterOperators,

View File

@@ -1,7 +1,7 @@
import { IDisplayCellProps } from "@src/components/fields/types";
import { Grid, Chip } from "@mui/material";
import ChipList from "@src/components/Table/ChipList";
import ChipList from "@src/components/Table/TableCell/ChipList";
import { FileIcon } from ".";
import { FileValue } from "@src/types/table";

View File

@@ -8,7 +8,7 @@ import { format } from "date-fns";
import { alpha, Stack, Grid, Tooltip, Chip, IconButton } from "@mui/material";
import { Upload as UploadIcon } from "@src/assets/icons";
import ChipList from "@src/components/Table/ChipList";
import ChipList from "@src/components/Table/TableCell/ChipList";
import CircularProgressOptical from "@src/components/CircularProgressOptical";
import { projectScope, confirmDialogAtom } from "@src/atoms/projectScope";

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import FileIcon from "@mui/icons-material/AttachFile";
import DisplayCell from "./DisplayCell";
@@ -22,7 +22,7 @@ export const config: IFieldConfig = {
initialValue: [],
icon: <FileIcon />,
description: "File uploaded to Firebase Storage. Supports any file type.",
TableCell: withTableCell(DisplayCell, EditorCell, "inline", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "inline", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,7 +1,7 @@
import { lazy } from "react";
import { GeoPoint } from "firebase/firestore";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import GeoPointIcon from "@mui/icons-material/PinDropOutlined";
import DisplayCell from "./DisplayCell";
@@ -21,7 +21,7 @@ export const config: IFieldConfig = {
initialValue: {},
icon: <GeoPointIcon />,
description: "Geo point is represented as latitude/longitude pair.",
TableCell: withTableCell(DisplayCell, SideDrawerField, "popover", {
TableCell: withRenderTableCell(DisplayCell, SideDrawerField, "popover", {
popoverProps: { PaperProps: { sx: { p: 1, pt: 0 } } },
}),
SideDrawerField,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import DisplayCell from "./DisplayCell";
import { Id as IdIcon } from "@src/assets/icons";
@@ -17,7 +17,7 @@ export const config: IFieldConfig = {
initialValue: "",
icon: <IdIcon />,
description: "Displays the rows ID. Read-only. Cannot be sorted.",
TableCell: withTableCell(DisplayCell, null),
TableCell: withRenderTableCell(DisplayCell, null),
SideDrawerField,
};
export default config;

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Image as ImageIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
icon: <ImageIcon />,
description:
"Image file uploaded to Firebase Storage. Supports JPEG, PNG, SVG, GIF, WebP, AVIF, JPEG XL.",
TableCell: withTableCell(DisplayCell, EditorCell, "inline", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "inline", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Json as JsonIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -24,7 +24,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <JsonIcon />,
description: "Object edited with a visual JSON editor.",
TableCell: withTableCell(DisplayCell, SideDrawerField, "popover", {
TableCell: withRenderTableCell(DisplayCell, SideDrawerField, "popover", {
popoverProps: { PaperProps: { sx: { p: 1 } } },
}),
csvImportParser: (value) => {

View File

@@ -1,5 +1,5 @@
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
export default function LongText(props: IEditorCellProps<string>) {
return <EditorCellTextField {...props} InputProps={{ multiline: true }} />;

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import LongTextIcon from "@mui/icons-material/Notes";
import DisplayCell from "./DisplayCell";
@@ -29,7 +29,7 @@ export const config: IFieldConfig = {
icon: <LongTextIcon />,
description: "Text displayed on multiple lines.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, EditorCell),
TableCell: withRenderTableCell(DisplayCell, EditorCell),
SideDrawerField,
settings: Settings,
filter: {

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Markdown as MarkdownIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -21,7 +21,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <MarkdownIcon />,
description: "Markdown editor with preview",
TableCell: withTableCell(DisplayCell, SideDrawerField, "popover"),
TableCell: withRenderTableCell(DisplayCell, SideDrawerField, "popover"),
SideDrawerField,
};
export default config;

View File

@@ -5,7 +5,7 @@ import WarningIcon from "@mui/icons-material/WarningAmber";
import { ChevronDown } from "@src/assets/icons";
import { sanitiseValue } from "./utils";
import ChipList from "@src/components/Table/ChipList";
import ChipList from "@src/components/Table/TableCell/ChipList";
import FormattedChip from "@src/components/FormattedChip";
export default function MultiSelect({

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { MultiSelect as MultiSelectIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -32,7 +32,7 @@ export const config: IFieldConfig = {
icon: <MultiSelectIcon />,
description:
"Multiple values from predefined options. Options are searchable and users can optionally input custom values.",
TableCell: withTableCell(DisplayCell, EditorCell, "popover", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "popover", {
disablePadding: true,
transparentPopover: false,
}),

View File

@@ -1,5 +1,5 @@
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
export default function Number_(props: IEditorCellProps<number>) {
return (

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Number as NumberIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -22,7 +22,7 @@ export const config: IFieldConfig = {
icon: <NumberIcon />,
description: "Numeric value.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, EditorCell),
TableCell: withRenderTableCell(DisplayCell, EditorCell),
SideDrawerField,
filter: {
operators: filterOperators,

View File

@@ -1,5 +1,5 @@
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
export default function Percentage(props: IEditorCellProps<number>) {
return (

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Percentage as PercentageIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -30,7 +30,7 @@ export const config: IFieldConfig = {
requireConfiguration: true,
description: "Percentage stored as a number between 0 and 1.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, EditorCell),
TableCell: withRenderTableCell(DisplayCell, EditorCell),
SideDrawerField,
settings: Settings,
filter: {

View File

@@ -1,5 +1,5 @@
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
export default function Phone(props: IEditorCellProps<string>) {
return <EditorCellTextField {...props} InputProps={{ type: "tel" }} />;

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import PhoneIcon from "@mui/icons-material/PhoneOutlined";
import DisplayCell from "@src/components/fields/ShortText/DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
icon: <PhoneIcon />,
description: "Phone number stored as text. Not validated.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, EditorCell),
TableCell: withRenderTableCell(DisplayCell, EditorCell),
SideDrawerField,
filter: {
operators: filterOperators,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import RatingIcon from "@mui/icons-material/StarBorder";
import DisplayCell from "./DisplayCell";
@@ -26,7 +26,7 @@ export const config: IFieldConfig = {
requireConfiguration: true,
description:
"Rating displayed as stars. Max stars is configurable, default: 5 stars.",
TableCell: withTableCell(DisplayCell, EditorCell, "inline"),
TableCell: withRenderTableCell(DisplayCell, EditorCell, "inline"),
settings: Settings,
SideDrawerField,
filter: {

View File

@@ -3,7 +3,7 @@ import { useAtom } from "jotai";
import { doc, deleteField } from "firebase/firestore";
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
import { InputAdornment, Tooltip } from "@mui/material";
import ErrorIcon from "@mui/icons-material/ErrorOutline";

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Reference } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <Reference />,
description: "Firestore document reference",
TableCell: withTableCell(DisplayCell, EditorCell, "focus", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "focus", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import RichTextIcon from "@mui/icons-material/TextFormat";
import DisplayCell from "./DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
icon: <RichTextIcon />,
description: "HTML edited with a rich text editor.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, SideDrawerField, "popover"),
TableCell: withRenderTableCell(DisplayCell, SideDrawerField, "popover"),
SideDrawerField,
};
export default config;

View File

@@ -1,5 +1,5 @@
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
export default function ShortText(props: IEditorCellProps<string>) {
return <EditorCellTextField {...props} />;

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import ShortTextIcon from "@mui/icons-material/ShortText";
import DisplayCell from "@src/components/fields/ShortText/DisplayCell";
@@ -30,7 +30,7 @@ export const config: IFieldConfig = {
icon: <ShortTextIcon />,
description: "Text displayed on a single line.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, EditorCell),
TableCell: withRenderTableCell(DisplayCell, EditorCell),
SideDrawerField,
settings: Settings,
filter: {

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { SingleSelect as SingleSelectIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -27,7 +27,7 @@ export const config: IFieldConfig = {
icon: <SingleSelectIcon />,
description:
"Single value from predefined options. Options are searchable and users can optionally input custom values.",
TableCell: withTableCell(DisplayCell, EditorCell, "popover", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "popover", {
disablePadding: true,
transparentPopover: true,
}),

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Slider as SliderIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -24,7 +24,7 @@ export const config: IFieldConfig = {
icon: <SliderIcon />,
requireConfiguration: true,
description: "Numeric value edited with a Slider. Range is configurable.",
TableCell: withTableCell(DisplayCell, SideDrawerField, "popover", {
TableCell: withRenderTableCell(DisplayCell, SideDrawerField, "popover", {
popoverProps: { PaperProps: { sx: { p: 1, pt: 5 } } },
}),
settings: Settings,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { Status as StatusIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -24,7 +24,7 @@ export const config: IFieldConfig = {
initializable: true,
icon: <StatusIcon />,
description: "Displays field value as custom status text.",
TableCell: withTableCell(DisplayCell, EditorCell, "popover", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "popover", {
disablePadding: true,
transparentPopover: true,
}),

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { SubTable as SubTableIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -24,7 +24,7 @@ export const config: IFieldConfig = {
settings: Settings,
description:
"Connects to a sub-table in the current row. Also displays number of rows inside the sub-table. Max sub-table depth: 100.",
TableCell: withTableCell(DisplayCell, null, "focus", {
TableCell: withRenderTableCell(DisplayCell, null, "focus", {
usesRowData: true,
disablePadding: true,
}),

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { UpdatedAt as UpdatedAtIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -25,7 +25,7 @@ export const config: IFieldConfig = {
icon: <UpdatedAtIcon />,
description:
"Displays the timestamp of the last update to the row. Read-only.",
TableCell: withTableCell(DisplayCell, null),
TableCell: withRenderTableCell(DisplayCell, null),
SideDrawerField,
settings: Settings,
};

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import { UpdatedBy as UpdatedByIcon } from "@src/assets/icons";
import DisplayCell from "./DisplayCell";
@@ -26,7 +26,7 @@ export const config: IFieldConfig = {
icon: <UpdatedByIcon />,
description:
"Displays the user that last updated the row, timestamp, and updated field key. Read-only.",
TableCell: withTableCell(DisplayCell, null),
TableCell: withRenderTableCell(DisplayCell, null),
SideDrawerField,
settings: Settings,
};

View File

@@ -1,5 +1,5 @@
import type { IEditorCellProps } from "@src/components/fields/types";
import EditorCellTextField from "@src/components/Table/EditorCellTextField";
import EditorCellTextField from "@src/components/Table/TableCell/EditorCellTextField";
export default function Url(props: IEditorCellProps<string>) {
return <EditorCellTextField {...props} InputProps={{ type: "url" }} />;

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import UrlIcon from "@mui/icons-material/Link";
import DisplayCell from "./DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
icon: <UrlIcon />,
description: "Web address. Not validated.",
contextMenuActions: BasicContextMenuActions,
TableCell: withTableCell(DisplayCell, EditorCell, "focus", {
TableCell: withRenderTableCell(DisplayCell, EditorCell, "focus", {
disablePadding: true,
}),
SideDrawerField,

View File

@@ -1,6 +1,6 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withTableCell from "@src/components/Table/withTableCell";
import withRenderTableCell from "@src/components/Table/TableCell/withRenderTableCell";
import UserIcon from "@mui/icons-material/PersonOutlined";
import DisplayCell from "./DisplayCell";
@@ -23,7 +23,7 @@ export const config: IFieldConfig = {
initialValue: null,
icon: <UserIcon />,
description: "User information and optionally, timestamp. Read-only.",
TableCell: withTableCell(DisplayCell, null),
TableCell: withRenderTableCell(DisplayCell, null),
SideDrawerField,
settings: Settings,
};

View File

@@ -1,5 +1,5 @@
import { FieldType } from "@src/constants/fields";
import type { ITableCellProps } from "@src/components/Table/withTableCell";
import type { IRenderedTableCellProps } from "@src/components/Table/TableCell/withRenderTableCell";
import type { PopoverProps } from "@mui/material";
import type {
ColumnConfig,
@@ -27,7 +27,7 @@ export interface IFieldConfig {
selectedCell: SelectedCell,
reset: () => void
) => IContextMenuItem[];
TableCell: React.ComponentType<ITableCellProps>;
TableCell: React.ComponentType<IRenderedTableCellProps>;
SideDrawerField: React.ComponentType<ISideDrawerFieldProps>;
settings?: React.ComponentType<ISettingsProps>;
settingsValidator?: (config: Record<string, any>) => Record<string, string>;

View File

@@ -1,5 +1,5 @@
import Logo from "@src/assets/Logo";
import BreadcrumbsTableRoot from "@src/components/Table/BreadcrumbsTableRoot";
import BreadcrumbsTableRoot from "@src/components/Table/Breadcrumbs/BreadcrumbsTableRoot";
import { FadeProps, Typography } from "@mui/material";
export enum ROUTES {

View File

@@ -7,7 +7,7 @@ import { useLocation, useNavigate, useParams } from "react-router-dom";
import { find, isEqual } from "lodash-es";
import Modal from "@src/components/Modal";
import BreadcrumbsSubTable from "@src/components/Table/BreadcrumbsSubTable";
import BreadcrumbsSubTable from "@src/components/Table/Breadcrumbs/BreadcrumbsSubTable";
import ErrorFallback from "@src/components/ErrorFallback";
import TableSourceFirestore from "@src/sources/TableSourceFirestore";
import TableToolbarSkeleton from "@src/components/TableToolbar/TableToolbarSkeleton";