Skip to content

Commit d64788c

Browse files
authored
Expose renderers prop to allow custom internal renderers (#969)
* expose renderers prop to allow custom internal renderers * fix react 18 test * add story and document
1 parent 62f422a commit d64788c

File tree

5 files changed

+114
-3
lines changed

5 files changed

+114
-3
lines changed

packages/core/API.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ Most data grids will want to set the majority of these props one way or another.
190190

191191
| Name | Description |
192192
| ---------------------------------- | ------------------------------------------------------ |
193-
| [customRenderers](#customRenderer) | FIXME |
193+
| [customRenderers](#customRenderer) | Custom renderers for `GridCellKind.Custom`. |
194+
| [renderers](#renderers) | Overrides built-in cell renderers. |
194195
| [drawCell](#drawcell) | Callback used to override the rendering of any cell. |
195196
| [drawHeader](#drawheader) | Callback used to override the rendering of any header. |
196197

@@ -756,6 +757,16 @@ It is possible to return `false` after rendering just a background and the regul
756757

757758
---
758759

760+
## renderers
761+
762+
```ts
763+
readonly renderers?: readonly InternalCellRenderer<InnerGridCell>[];
764+
```
765+
766+
An array of cell renderers used when drawing built-in cell types. Provide this prop to override default cell renderers. If omitted, `AllCellRenderers` is used.
767+
768+
---
769+
759770
## getGroupDetails
760771

761772
```ts

packages/core/src/data-editor-all.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { sprites } from "./internal/data-grid/sprites.js";
55
import ImageWindowLoaderImpl from "./common/image-window-loader.js";
66
import type { ImageWindowLoader } from "./internal/data-grid/image-window-loader-interface.js";
77

8-
export interface DataEditorAllProps extends Omit<DataEditorProps, "renderers" | "imageWindowLoader"> {
8+
export interface DataEditorAllProps extends Omit<DataEditorProps, "imageWindowLoader"> {
99
imageWindowLoader?: ImageWindowLoader;
1010
}
1111

@@ -14,14 +14,18 @@ const DataEditorAllImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEdito
1414
return { ...sprites, ...p.headerIcons };
1515
}, [p.headerIcons]);
1616

17+
const renderers = React.useMemo(() => {
18+
return p.renderers ?? AllCellRenderers;
19+
}, [p.renderers])
20+
1721
const imageWindowLoader = React.useMemo(() => {
1822
return p.imageWindowLoader ?? new ImageWindowLoaderImpl();
1923
}, [p.imageWindowLoader]);
2024

2125
return (
2226
<DataEditor
2327
{...p}
24-
renderers={AllCellRenderers}
28+
renderers={renderers}
2529
headerIcons={allSprites}
2630
ref={ref}
2731
imageWindowLoader={imageWindowLoader}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React from "react";
2+
import { DataEditorAll as DataEditor } from "../../data-editor-all.js";
3+
import {
4+
BeautifulWrapper,
5+
Description,
6+
PropName,
7+
defaultProps,
8+
useMockDataGenerator,
9+
} from "../../data-editor/stories/utils.js";
10+
import { SimpleThemeWrapper } from "../../stories/story-utils.js";
11+
import {
12+
markerCellRenderer,
13+
AllCellRenderers,
14+
type InternalCellRenderer,
15+
type InnerGridCell,
16+
} from "../../index.js";
17+
18+
export default {
19+
title: "Glide-Data-Grid/DataEditor Demos",
20+
decorators: [
21+
(Story: React.ComponentType) => (
22+
<SimpleThemeWrapper>
23+
<BeautifulWrapper
24+
title="Custom renderers"
25+
description={
26+
<Description>
27+
Override internal cell renderers by passing the {" "}
28+
<PropName>renderers</PropName> prop.
29+
</Description>
30+
}
31+
>
32+
<Story />
33+
</BeautifulWrapper>
34+
</SimpleThemeWrapper>
35+
),
36+
],
37+
};
38+
39+
export const OverrideMarkerRenderer: React.VFC = () => {
40+
const { cols, getCellContent } = useMockDataGenerator(100, true, true);
41+
42+
const renderers = React.useMemo<readonly InternalCellRenderer<InnerGridCell>[]>(() => {
43+
return [
44+
...AllCellRenderers,
45+
{
46+
...markerCellRenderer,
47+
draw: args => {
48+
const { ctx, rect } = args;
49+
ctx.fillStyle = "#ffe0e0";
50+
ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
51+
markerCellRenderer.draw(args as any);
52+
},
53+
} as InternalCellRenderer<InnerGridCell>,
54+
];
55+
}, []);
56+
57+
return (
58+
<DataEditor
59+
{...defaultProps}
60+
getCellContent={getCellContent}
61+
columns={cols}
62+
rows={200}
63+
rowMarkers="both"
64+
renderers={renderers}
65+
/>
66+
);
67+
};

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export { markerCellRenderer } from "./cells/marker-cell.js";
6161
export { bubbleCellRenderer } from "./cells/bubble-cell.js";
6262
export { protectedCellRenderer } from "./cells/protected-cell.js";
6363
export { rowIDCellRenderer } from "./cells/row-id-cell.js";
64+
export type { InternalCellRenderer } from "./cells/cell-types.js";
6465
export { AllCellRenderers } from "./cells/index.js";
6566
export { sprites } from "./internal/data-grid/sprites.js";
6667
export { default as ImageWindowLoaderImpl } from "./common/image-window-loader.js";

packages/core/test/data-editor.test.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import {
88
GridCellKind,
99
isSizedGridColumn,
1010
type Item,
11+
markerCellRenderer,
12+
type InnerGridCell,
13+
type InternalCellRenderer,
14+
AllCellRenderers,
1115
} from "../src/index.js";
1216
import type { CustomCell } from "../src/internal/data-grid/data-grid-types.js";
1317
import type { DataEditorRef } from "../src/data-editor/data-editor.js";
@@ -2594,6 +2598,30 @@ describe("data-editor", () => {
25942598
expect(onClickSpy).not.toBeCalled();
25952599
});
25962600

2601+
test("renderers can override internal cells", async () => {
2602+
const spy = vi.fn();
2603+
2604+
vi.useFakeTimers();
2605+
render(
2606+
<DataEditor
2607+
{...basicProps}
2608+
renderers={[
2609+
...AllCellRenderers,
2610+
{
2611+
...markerCellRenderer,
2612+
draw: spy
2613+
} as InternalCellRenderer<InnerGridCell>,
2614+
]}
2615+
rowMarkers="both"
2616+
/>,
2617+
{
2618+
wrapper: Context,
2619+
}
2620+
);
2621+
prep();
2622+
expect(spy).toHaveBeenCalledTimes(31); // Math.ceil((height - headerHeight) / rowHeight)
2623+
});
2624+
25972625
test("onCellsEdited blocks onCellEdited", async () => {
25982626
const spy = vi.fn();
25992627
vi.useFakeTimers();

0 commit comments

Comments
 (0)