Skip to content

Commit

Permalink
Add super table enhancements (#920)
Browse files Browse the repository at this point in the history
* Add ability to restrict column span range selections

* Add ability to disable drawing focus ring when editor is open

* Change naming

* Make boolean cells not select when toggled directly

* Fix test
  • Loading branch information
jassmith authored Mar 13, 2024
1 parent f1a9b55 commit a57eda1
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 23 deletions.
53 changes: 35 additions & 18 deletions packages/core/src/cells/boolean-cell.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { FullTheme } from "../common/styles.js";
import { getSquareWidth, getSquareXPosFromAlign, getSquareBB, pointIsWithinBB } from "../common/utils.js";
import { toggleBoolean } from "../data-editor/data-editor-fns.js";
import {
Expand All @@ -6,12 +7,38 @@ import {
booleanCellIsEditable,
BooleanEmpty,
BooleanIndeterminate,
type Rectangle,
} from "../internal/data-grid/data-grid-types.js";
import { drawCheckbox } from "../internal/data-grid/render/draw-checkbox.js";
import type { BaseDrawArgs, InternalCellRenderer } from "./cell-types.js";

const defaultCellMaxSize = 20;

function isOverEditableRegion(e: {
readonly cell: BooleanCell;
readonly posX: number;
readonly posY: number;
readonly bounds: Rectangle;
readonly theme: FullTheme;
}): boolean {
const { cell, posX: pointerX, posY: pointerY, bounds, theme } = e;
const { width, height, x: cellX, y: cellY } = bounds;
const maxWidth = cell.maxSize ?? defaultCellMaxSize;
const cellCenterY = Math.floor(bounds.y + height / 2);
const checkBoxWidth = getSquareWidth(maxWidth, height, theme.cellVerticalPadding);
const posX = getSquareXPosFromAlign(
cell.contentAlign ?? "center",
cellX,
width,
theme.cellHorizontalPadding,
checkBoxWidth
);
const bb = getSquareBB(posX, cellCenterY, checkBoxWidth);
const checkBoxClicked = pointIsWithinBB(cellX + pointerX, cellY + pointerY, bb);

return booleanCellIsEditable(cell) && checkBoxClicked;
}

export const booleanCellRenderer: InternalCellRenderer<BooleanCell> = {
getAccessibilityString: c => c.data?.toString() ?? "false",
kind: GridCellKind.Boolean,
Expand All @@ -31,26 +58,16 @@ export const booleanCellRenderer: InternalCellRenderer<BooleanCell> = {
...c,
data: false,
}),
onSelect: e => {
if (isOverEditableRegion(e)) {
e.preventDefault();
}
},
onClick: e => {
const { cell, posX: pointerX, posY: pointerY, bounds, theme } = e;
const { width, height, x: cellX, y: cellY } = bounds;
const maxWidth = cell.maxSize ?? defaultCellMaxSize;
const cellCenterY = Math.floor(bounds.y + height / 2);
const checkBoxWidth = getSquareWidth(maxWidth, height, theme.cellVerticalPadding);
const posX = getSquareXPosFromAlign(
cell.contentAlign ?? "center",
cellX,
width,
theme.cellHorizontalPadding,
checkBoxWidth
);
const bb = getSquareBB(posX, cellCenterY, checkBoxWidth);
const checkBoxClicked = pointIsWithinBB(cellX + pointerX, cellY + pointerY, bb);

if (booleanCellIsEditable(cell) && checkBoxClicked) {
if (isOverEditableRegion(e)) {
return {
...cell,
data: toggleBoolean(cell.data),
...e.cell,
data: toggleBoolean(e.cell.data),
};
}
return undefined;
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/cells/loading-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const loadingCellRenderer: InternalCellRenderer<LoadingCell> = {
}

const hpad = theme.cellHorizontalPadding;
if (width + hpad * 2 >= rect.width) {
width = rect.width - hpad * 2 - 1;
}

const rectHeight = cell.skeletonHeight ?? Math.min(18, rect.height - 2 * theme.cellVerticalPadding);

roundedRect(
Expand Down
17 changes: 15 additions & 2 deletions packages/core/src/data-editor/data-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type Props = Partial<
| "clientSize"
| "columns"
| "disabledRows"
| "drawFocusRing"
| "enableGroups"
| "firstColAccessible"
| "firstColSticky"
Expand Down Expand Up @@ -395,6 +396,12 @@ export interface DataEditorProps extends Props, Pick<DataGridSearchProps, "image
*/
readonly rowSelect?: "none" | "single" | "multi";

/** Controls if range selection is allowed to span columns.
* @group Selection
* @defaultValue `true`
*/
readonly rangeSelectionColumnSpanning?: boolean;

/** Sets the initial scroll Y offset.
* @see {@link scrollOffsetX}
* @group Advanced
Expand Down Expand Up @@ -667,6 +674,8 @@ export interface DataEditorProps extends Props, Pick<DataGridSearchProps, "image
* If set to true, the data grid will attempt to scroll to keep the selction in view
*/
readonly scrollToActiveCell?: boolean;

readonly drawFocusRing?: boolean | "no-editor";
}

type ScrollToFn = (
Expand Down Expand Up @@ -764,6 +773,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
editorBloom,
onHeaderClicked,
onColumnProposeMove,
rangeSelectionColumnSpanning = true,
spanRangeBehavior = "default",
onGroupHeaderClicked,
onCellContextMenu,
Expand Down Expand Up @@ -828,7 +838,6 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
onColumnResizeStart: onColumnResizeStartIn,
customRenderers: additionalRenderers,
fillHandle,
drawFocusRing = true,
experimental,
fixedShadowX,
fixedShadowY,
Expand All @@ -855,8 +864,11 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
renderers,
resizeIndicator,
scrollToActiveCell = true,
drawFocusRing: drawFocusRingIn = true,
} = p;

const drawFocusRing = drawFocusRingIn === "no-editor" ? overlay === undefined : drawFocusRingIn;

const rowMarkersObj = typeof p.rowMarkers === "string" ? undefined : p.rowMarkers;

const rowMarkers = rowMarkersObj?.kind ?? (p.rowMarkers as RowMarkerOptions["kind"]) ?? "none";
Expand Down Expand Up @@ -1033,7 +1045,8 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
rangeSelectionBlending,
columnSelectionBlending,
rowSelectionBlending,
rangeSelect
rangeSelect,
rangeSelectionColumnSpanning
);

const mergedTheme = React.useMemo(() => {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/docs/examples/add-data.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const AddData: React.VFC = () => {
{...defaultProps}
getCellContent={getCellContent}
columns={cols}
rangeSelectionColumnSpanning={false}
rowMarkers={"both"}
onPaste={true} // we want to allow paste to just call onCellEdited
onCellEdited={setCellValue} // Sets the mock cell content
Expand Down
25 changes: 23 additions & 2 deletions packages/core/src/internal/data-grid/use-selection-behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export function useSelectionBehavior(
rangeBehavior: SelectionBlending,
columnBehavior: SelectionBlending,
rowBehavior: SelectionBlending,
rangeSelect: "none" | "cell" | "rect" | "multi-cell" | "multi-rect"
rangeSelect: "none" | "cell" | "rect" | "multi-cell" | "multi-rect",
rangeSelectionColumnSpanning: boolean
) {
// if append is true, the current range will be added to the rangeStack
const setCurrent = React.useCallback(
Expand All @@ -34,6 +35,18 @@ export function useSelectionBehavior(
},
};
}

if (!rangeSelectionColumnSpanning && value !== undefined && value.range.width > 1) {
value = {
...value,
range: {
...value.range,
width: 1,
x: value.cell[0],
},
};
}

const rangeMixable = rangeBehavior === "mixed" && (append || trigger === "drag");
const allowColumnCoSelect = columnBehavior === "mixed" && rangeMixable;
const allowRowCoSelect = rowBehavior === "mixed" && rangeMixable;
Expand Down Expand Up @@ -61,7 +74,15 @@ export function useSelectionBehavior(
}
setGridSelection(newVal, expand);
},
[columnBehavior, gridSelection, rangeBehavior, rangeSelect, rowBehavior, setGridSelection]
[
columnBehavior,
gridSelection,
rangeBehavior,
rangeSelect,
rangeSelectionColumnSpanning,
rowBehavior,
setGridSelection,
]
);

const setSelectedRows = React.useCallback(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/data-editor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ describe("data-editor", () => {

const canvas = screen.getByTestId("data-grid-canvas");
sendClick(canvas, {
clientX: 850, // Col Boolean
clientX: 830, // Col Boolean
clientY: 36 * 2 + 32 + 16, // Row 2 (0 indexed)
});

Expand Down

0 comments on commit a57eda1

Please sign in to comment.