Skip to content

Commit 228ca3e

Browse files
committed
Add Grid imperative API
1 parent 56fc34b commit 228ca3e

37 files changed

+820
-243
lines changed

generated/docs/Grid.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,45 @@
149149
]
150150
}
151151
},
152+
"gridRef": {
153+
"defaultValue": null,
154+
"description": "Ref used to interact with this component's imperative API.\n\nThis API has imperative methods for scrolling and a getter for the outermost DOM element.\n\n⚠️ The `useGridRef` hook is exported for convenience use in TypeScript projects.",
155+
"name": "gridRef",
156+
"declarations": [
157+
{
158+
"fileName": "react-window/lib/components/grid/types.ts",
159+
"name": "TypeLiteral"
160+
}
161+
],
162+
"required": false,
163+
"type": {
164+
"name": "enum",
165+
"raw": "Ref<GridImperativeAPI> | undefined",
166+
"value": [
167+
{
168+
"value": "undefined"
169+
},
170+
{
171+
"value": "null"
172+
},
173+
{
174+
"value": "(instance: GridImperativeAPI | null) => void | (() => VoidOrUndefinedOnly)",
175+
"description": "",
176+
"fullComment": "",
177+
"tags": {}
178+
},
179+
{
180+
"value": "RefObject<GridImperativeAPI | null>",
181+
"description": "Created by {@link createRef}, or {@link useRef} when passed `null`.",
182+
"fullComment": "Created by {@link createRef}, or {@link useRef} when passed `null`.\n@template T The type of the ref's value.\n@example ```tsx\nconst ref = createRef<HTMLDivElement>();\n\nref.current = document.createElement('div'); // Error\n```",
183+
"tags": {
184+
"template": "T The type of the ref's value.",
185+
"example": "```tsx\nconst ref = createRef<HTMLDivElement>();\n\nref.current = document.createElement('div'); // Error\n```"
186+
}
187+
}
188+
]
189+
}
190+
},
152191
"onCellsRendered": {
153192
"defaultValue": null,
154193
"description": "Callback notified when the range of rendered cells changes.",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
function CellComponent({ contacts, columnIndex, rowIndex, style }) {
2+
// Column and header rows shown for example purposes; (they aren't required)
3+
if (columnIndex === 0 && rowIndex === 0) {
4+
return null;
5+
} else if (rowIndex === 0) {
6+
return (
7+
<div className="text-sm font-bold" style={style}>
8+
Column {columnIndex}
9+
</div>
10+
);
11+
} else if (columnIndex === 0) {
12+
return (
13+
<div className="text-sm font-bold" style={style}>
14+
Row {rowIndex}
15+
</div>
16+
);
17+
}
18+
19+
const address = contacts[rowIndex - 1];
20+
const content = address[indexToColumn(columnIndex - 1)];
21+
22+
return (
23+
<div className="truncate" style={style}>
24+
{content}
25+
</div>
26+
);
27+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
function CellComponent({
2+
contacts,
3+
columnIndex,
4+
rowIndex,
5+
style,
6+
}: GridComponentProps<CellProps>) {
7+
// Column and header rows shown for example purposes; (they aren't required)
8+
if (columnIndex === 0 && rowIndex === 0) {
9+
return null;
10+
} else if (rowIndex === 0) {
11+
return (
12+
<div className="text-sm font-bold" style={style}>
13+
Column {columnIndex}
14+
</div>
15+
);
16+
} else if (columnIndex === 0) {
17+
return (
18+
<div className="text-sm font-bold" style={style}>
19+
Row {rowIndex}
20+
</div>
21+
);
22+
}
23+
24+
const address = contacts[rowIndex - 1];
25+
const content = address[indexToColumn(columnIndex - 1)];
26+
27+
return (
28+
<div className="truncate" style={style}>
29+
{content}
30+
</div>
31+
);
32+
}

generated/examples/Grid.example.jsx

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,12 @@ function Example({ contacts }) {
55
<Grid
66
cellComponent={CellComponent}
77
cellProps={{ contacts }}
8-
columnCount={10}
8+
columnCount={11}
99
columnWidth={columnWidth}
10-
rowCount={contacts.length}
10+
rowCount={
11+
contacts.length + 1 // Extra header row
12+
}
1113
rowHeight={25}
1214
/>
1315
);
1416
}
15-
16-
function columnWidth(index) {
17-
switch (indexToColumn(index)) {
18-
case "address": {
19-
return 250;
20-
}
21-
case "email": {
22-
return 300;
23-
}
24-
case "job_title": {
25-
return 150;
26-
}
27-
case "timezone": {
28-
return 200;
29-
}
30-
case "zipcode": {
31-
return 75;
32-
}
33-
default: {
34-
return 100;
35-
}
36-
}
37-
}
38-
39-
function CellComponent({ contacts, columnIndex, rowIndex, style }) {
40-
const address = contacts[rowIndex];
41-
const content = address[indexToColumn(columnIndex)];
42-
43-
return (
44-
<div className="truncate" style={style}>
45-
{content}
46-
</div>
47-
);
48-
}
Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Grid, type GridComponentProps } from "react-window";
1+
import { Grid } from "react-window";
22

33
type CellProps = {
44
contacts: Contact[];
@@ -9,49 +9,12 @@ function Example({ contacts }: { contacts: Contact[] }) {
99
<Grid
1010
cellComponent={CellComponent}
1111
cellProps={{ contacts }}
12-
columnCount={10}
12+
columnCount={11}
1313
columnWidth={columnWidth}
14-
rowCount={contacts.length}
14+
rowCount={
15+
contacts.length + 1 // Extra header row
16+
}
1517
rowHeight={25}
1618
/>
1719
);
18-
}
19-
20-
function columnWidth(index: number) {
21-
switch (indexToColumn(index)) {
22-
case "address": {
23-
return 250;
24-
}
25-
case "email": {
26-
return 300;
27-
}
28-
case "job_title": {
29-
return 150;
30-
}
31-
case "timezone": {
32-
return 200;
33-
}
34-
case "zipcode": {
35-
return 75;
36-
}
37-
default: {
38-
return 100;
39-
}
40-
}
41-
}
42-
43-
function CellComponent({
44-
contacts,
45-
columnIndex,
46-
rowIndex,
47-
style,
48-
}: GridComponentProps<CellProps>) {
49-
const address = contacts[rowIndex];
50-
const content = address[indexToColumn(columnIndex)];
51-
52-
return (
53-
<div className="truncate" style={style}>
54-
{content}
55-
</div>
56-
);
5720
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Grid } from "react-window";
2+
import { CellComponent } from "./Grid.example";
3+
import { columnWidth } from "./columnWidth.example";
4+
5+
export function Example({ contacts, gridRef }) {
6+
return (
7+
<Grid
8+
cellComponent={CellComponent}
9+
cellProps={{ contacts }}
10+
columnCount={10}
11+
columnWidth={columnWidth}
12+
gridRef={gridRef}
13+
rowCount={contacts.length}
14+
rowHeight={25}
15+
/>
16+
);
17+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import type { Ref } from "react";
2+
import { Grid, type GridImperativeAPI } from "react-window";
3+
import { CellComponent, type Contact } from "./Grid.example";
4+
import { columnWidth } from "./columnWidth.example";
5+
6+
export function Example({
7+
contacts,
8+
gridRef,
9+
}: {
10+
contacts: Contact[];
11+
gridRef: Ref<GridImperativeAPI>;
12+
}) {
13+
return (
14+
<Grid
15+
cellComponent={CellComponent}
16+
cellProps={{ contacts }}
17+
columnCount={10}
18+
columnWidth={columnWidth}
19+
gridRef={gridRef}
20+
rowCount={contacts.length}
21+
rowHeight={25}
22+
/>
23+
);
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function columnWidth(index) {
2+
switch (indexToColumn(index)) {
3+
case "address": {
4+
return 250;
5+
}
6+
case "email": {
7+
return 300;
8+
}
9+
case "job_title": {
10+
return 150;
11+
}
12+
case "timezone": {
13+
return 200;
14+
}
15+
case "zipcode": {
16+
return 75;
17+
}
18+
default: {
19+
return 100;
20+
}
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function columnWidth(index: number) {
2+
switch (indexToColumn(index)) {
3+
case "address": {
4+
return 250;
5+
}
6+
case "email": {
7+
return 300;
8+
}
9+
case "job_title": {
10+
return 150;
11+
}
12+
case "timezone": {
13+
return 200;
14+
}
15+
case "zipcode": {
16+
return 75;
17+
}
18+
default: {
19+
return 100;
20+
}
21+
}
22+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const onClick = () => {
2+
const grid = gridRef.current;
3+
grid?.scrollToCell({
4+
behavior: "auto", // optional
5+
columnAlign: "auto", // optional
6+
columnIndex: 10,
7+
rowAlign: "auto", // optional
8+
rowIndex: 250,
9+
});
10+
};

0 commit comments

Comments
 (0)