Skip to content

Commit

Permalink
Cleanup API
Browse files Browse the repository at this point in the history
  • Loading branch information
jassmith committed Feb 5, 2024
1 parent 6e3697a commit 6d5402e
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 71 deletions.
4 changes: 2 additions & 2 deletions packages/core/src/data-editor/data-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ import {
} from "../internal/data-grid/event-args.js";
import { type Keybinds, useKeybindingsWithDefaults } from "./data-editor-keybindings.js";
import type { Highlight } from "../internal/data-grid/render/data-grid-render.cells.js";
import { useRowGrouping, type RowGroupingOptions } from "./row-grouping.js";
import { useRowGroupingInner, type RowGroupingOptions } from "./row-grouping.js";

const DataGridOverlayEditor = React.lazy(
async () => await import("../internal/data-grid-overlay-editor/data-grid-overlay-editor.js")
Expand Down Expand Up @@ -872,7 +872,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
effectiveRows: rows,
getCellContent,
rowNumberMapper,
} = useRowGrouping(rowGrouping, rowsIn, getCellContentIn);
} = useRowGroupingInner(rowGrouping, rowsIn, getCellContentIn);

const rowMarkerWidth = rowMarkerWidthRaw ?? (rowsIn > 10_000 ? 48 : rowsIn > 1000 ? 44 : rowsIn > 100 ? 36 : 32);
const hasRowMarkers = rowMarkers !== "none";
Expand Down
115 changes: 80 additions & 35 deletions packages/core/src/data-editor/row-grouping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,17 @@ function flattenRowGroups(rowGrouping: RowGroupingOptions, rows: number): Flatte
return flattened;
}

export interface UseRowGroupingResult {
export interface UseRowGroupingInnerResult {
readonly effectiveRows: number;
readonly getCellContent: (cell: Item) => GridCell;
readonly rowNumberMapper: (row: number) => number | undefined;
}

export function useRowGrouping(
export function useRowGroupingInner(
options: RowGroupingOptions | undefined,
rows: number,
getCellContent: DataEditorCoreProps["getCellContent"]
): UseRowGroupingResult {
): UseRowGroupingInnerResult {
const flattenedRowGroups = React.useMemo(
() => (options === undefined ? undefined : flattenRowGroups(options, rows)),
[options, rows]
Expand Down Expand Up @@ -231,48 +231,93 @@ export function useRowGrouping(
};
}

type PathMapper = (row: number) => { path: readonly number[]; sourceRow: number };
type RowGroupingMapper = (itemOrRow: Item | number) => {
path: readonly number[];
sourceRow: number;
isGroupHeader: boolean;
};

interface UseRowGroupingResult {
readonly mapper: RowGroupingMapper;
readonly updateRowGroupingByPath: (
rowGrouping: readonly RowGroup[],
path: readonly number[],
update: Partial<RowGroup>
) => readonly RowGroup[];
readonly getRowGroupingForPath: (rowGrouping: readonly RowGroup[], path: readonly number[]) => RowGroup;
}

export function usePathMapper(options: RowGroupingOptions | undefined, rows: number): PathMapper {
export function useRowGrouping(options: RowGroupingOptions | undefined, rows: number): UseRowGroupingResult {
const flattenedRowGroups = React.useMemo(
() => (options === undefined ? undefined : flattenRowGroups(options, rows)),
[options, rows]
);

return React.useCallback(
(row: number) => {
if (flattenedRowGroups === undefined)
return {
path: [row],
sourceRow: row,
};

let toGo = row;
let sourceRow = 0;
for (const group of flattenedRowGroups) {
if (toGo === 0)
return {
getRowGroupingForPath,
updateRowGroupingByPath,
mapper: React.useCallback(
(itemOrRow: Item | number) => {
itemOrRow = typeof itemOrRow === "number" ? itemOrRow : itemOrRow[1];
if (flattenedRowGroups === undefined)
return {
path: [...group.path, -1],
sourceRow,
path: [itemOrRow],
sourceRow: itemOrRow,
isGroupHeader: false,
};
toGo--;
sourceRow++;
if (!group.isCollapsed) {
if (toGo < group.rows)

let toGo = itemOrRow;
let sourceRow = 0;
for (const group of flattenedRowGroups) {
if (toGo === 0)
return {
path: [...group.path, toGo],
sourceRow: sourceRow + toGo,
path: [...group.path, -1],
sourceRow,
isGroupHeader: true,
};
toGo -= group.rows;
toGo--;
sourceRow++;
if (!group.isCollapsed) {
if (toGo < group.rows)
return {
path: [...group.path, toGo],
sourceRow: sourceRow + toGo,
isGroupHeader: false,
};
toGo -= group.rows;
}
sourceRow += group.rows;
}
sourceRow += group.rows;
}
// this shouldn't happen
return {
path: [row],
sourceRow: row,
};
},
[flattenedRowGroups]
// this shouldn't happen
return {
path: [itemOrRow],
sourceRow: itemOrRow,
isGroupHeader: false,
};
},
[flattenedRowGroups]
),
};
}

function updateRowGroupingByPath(
rowGrouping: readonly RowGroup[],
path: readonly number[],
update: Partial<RowGroup>
): readonly RowGroup[] {
const [index, ...rest] = path;
if (rest[0] === -1) {
return rowGrouping.map((group, i) => (i === index ? { ...group, ...update } : group));
}
return rowGrouping.map((group, i) =>
i === index ? { ...group, subGroups: updateRowGroupingByPath(group.subGroups ?? [], rest, update) } : group
);
}

function getRowGroupingForPath(rowGrouping: readonly RowGroup[], path: readonly number[]): RowGroup {
const [index, ...rest] = path;
if (rest[0] === -1) {
return rowGrouping[index];
}
return getRowGroupingForPath(rowGrouping[index].subGroups ?? [], rest);
}
43 changes: 10 additions & 33 deletions packages/core/src/docs/examples/row-grouping.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import {
} from "../../data-editor/stories/utils.js";
import { SimpleThemeWrapper } from "../../stories/story-utils.js";
import { GridCellKind, type Item } from "../../internal/data-grid/data-grid-types.js";
import { usePathMapper } from "../../index.js";
import { type RowGroupingOptions, type RowGroup } from "../../data-editor/row-grouping.js";
import { type RowGroupingOptions, useRowGrouping } from "../../data-editor/row-grouping.js";

export default {
title: "Glide-Data-Grid/DataEditor Demos",
Expand All @@ -33,28 +32,6 @@ export default {
],
};

function updateRowGrouping(
rowGrouping: readonly RowGroup[],
path: readonly number[],
update: Partial<RowGroup>
): readonly RowGroup[] {
const [index, ...rest] = path;
if (rest[0] === -1) {
return rowGrouping.map((group, i) => (i === index ? { ...group, ...update } : group));
}
return rowGrouping.map((group, i) =>
i === index ? { ...group, subGroups: updateRowGrouping(group.subGroups ?? [], rest, update) } : group
);
}

function getRowGroupForPath(rowGrouping: readonly RowGroup[], path: readonly number[]): RowGroup {
const [index, ...rest] = path;
if (rest[0] === -1) {
return rowGrouping[index];
}
return getRowGroupForPath(rowGrouping[index].subGroups ?? [], rest);
}

export const RowGrouping: React.VFC<any> = (p: { freezeColumns: number }) => {
const { cols, getCellContent } = useMockDataGenerator(100);
const rows = 1000;
Expand Down Expand Up @@ -87,39 +64,39 @@ export const RowGrouping: React.VFC<any> = (p: { freezeColumns: number }) => {
height: 32,
}));

const pathMapper = usePathMapper(rowGrouping, rows);
const { mapper, getRowGroupingForPath, updateRowGroupingByPath } = useRowGrouping(rowGrouping, rows);

const onCellClicked = React.useCallback(
(item: Item) => {
const { path } = pathMapper(item[1]);
const { path, isGroupHeader } = mapper(item);

if (path.slice(-1)[0] === -1) {
const group = getRowGroupForPath(rowGrouping.groups, path);
if (isGroupHeader) {
const group = getRowGroupingForPath(rowGrouping.groups, path);

setRowGrouping(prev => {
const result: RowGroupingOptions = {
...prev,
groups: updateRowGrouping(prev.groups, path, { isCollapsed: !group.isCollapsed }),
groups: updateRowGroupingByPath(prev.groups, path, { isCollapsed: !group.isCollapsed }),
};

return result;
});
}
},
[pathMapper, rowGrouping.groups]
[getRowGroupingForPath, mapper, rowGrouping.groups, updateRowGroupingByPath]
);

const getCellContentMangled = React.useCallback<DataEditorAllProps["getCellContent"]>(
item => {
const { path, sourceRow } = pathMapper(item[1]);
const { path, sourceRow, isGroupHeader } = mapper(item);
if (item[0] === 0) {
return {
kind: GridCellKind.Text,
data: `Row ${JSON.stringify(path)}`,
displayData: `Row ${JSON.stringify(path)}`,
allowOverlay: false,
};
} else if (path.slice(-1)[0] === -1) {
} else if (isGroupHeader) {
return {
kind: GridCellKind.Loading,
allowOverlay: false,
Expand All @@ -129,7 +106,7 @@ export const RowGrouping: React.VFC<any> = (p: { freezeColumns: number }) => {

return getCellContent([item[0], sourceRow]);
},
[cols.length, getCellContent, pathMapper]
[cols.length, getCellContent, mapper]
);

return (
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export { AllCellRenderers } from "./cells/index.js";
export { sprites } from "./internal/data-grid/sprites.js";
export { default as ImageWindowLoaderImpl } from "./common/image-window-loader.js";
export * from "./data-editor/copy-paste.js";
export { usePathMapper } from "./data-editor/row-grouping.js";
export { useRowGrouping as usePathMapper } from "./data-editor/row-grouping.js";

/**
* @category DataEditor
Expand Down

0 comments on commit 6d5402e

Please sign in to comment.