Skip to content

Commit 102af4c

Browse files
committed
feat: more precise in state dependencies, clarify type names
1 parent aaed0df commit 102af4c

File tree

1 file changed

+62
-21
lines changed
  • electron/renderer/components/grid

1 file changed

+62
-21
lines changed

electron/renderer/components/grid/grid.tsx

+62-21
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,68 @@ import {
1010
useRef,
1111
useState,
1212
} from 'react';
13-
import type { Layout } from 'react-grid-layout';
13+
// To me, the "layout" is the collection of grid items and their positions.
14+
// To the react-grid-layout component, a "layout" is a single item's positions.
15+
// To help with terminology, aliasing the type here, redefining it below.
16+
import type { Layout as GridLayoutItem } from 'react-grid-layout';
1417
import GridLayout from 'react-grid-layout';
18+
import { useLogger } from '../../hooks/logger';
1519
import { LocalStorage } from '../../lib/local-storage';
20+
import type { GridItemProps } from './grid-item';
1621
import { GridItem } from './grid-item';
1722

23+
// See comment above about terminology.
24+
type Layout = Array<GridLayoutItem>;
25+
1826
export interface GridProps {
27+
/**
28+
* The dimension for the grid.
29+
*/
1930
dimensions: {
31+
/**
32+
* The max height of the grid in pixels.
33+
*/
2034
height: number;
35+
/**
36+
* The max width of the grid in pixels.
37+
*/
2138
width: number;
2239
};
40+
/**
41+
* The items to display in the grid.
42+
*/
2343
items: Array<{
24-
itemId: string;
25-
title: string;
26-
content: ReactNode;
44+
/**
45+
* The unique identifier for the grid item.
46+
*/
47+
itemId: GridItemProps['itemId'];
48+
/**
49+
* Text to display in the title bar of the grid item.
50+
*/
51+
title: GridItemProps['titleBarText'];
52+
/**
53+
* Content to show inside the grid item.
54+
*/
55+
content: GridItemProps['children'];
2756
}>;
2857
}
2958

3059
export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
3160
const { dimensions, items } = props;
3261

62+
const { logger } = useLogger('grid');
63+
64+
const { height, width } = dimensions;
65+
3366
const { euiTheme } = useEuiTheme();
3467

3568
const [gridLayoutStyles, setGridLayoutStyles] = useState<SerializedStyles>();
3669

3770
useEffect(() => {
3871
setGridLayoutStyles(css`
3972
${css({
40-
height: dimensions.height,
41-
width: dimensions.width,
73+
height,
74+
width,
4275
})}
4376
.react-grid-item.react-grid-placeholder {
4477
${css({
@@ -56,7 +89,7 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
5689
})}
5790
}
5891
`);
59-
}, [dimensions, euiTheme]);
92+
}, [height, width, euiTheme]);
6093

6194
/**
6295
* When grid items are resized the increment is based on the the layout size.
@@ -92,24 +125,30 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
92125
// so that the layout always fits the window exactly.
93126
// This allows the user to drag grid items anywhere within the window.
94127
const [gridMaxRows, setGridMaxRows] = useState<number>(1);
95-
const [gridMaxWidthPx, setGridMaxWidth] = useState<number>(dimensions.width);
128+
const [gridMaxWidthPx, setGridMaxWidth] = useState<number>(width);
96129

97130
useEffect(() => {
98-
const { height, width } = dimensions;
99-
if (height) {
100-
const newMaxRows = Math.floor(height / gridRowHeightWithMarginPx);
101-
setGridMaxRows(newMaxRows);
131+
// Note, when first rendering the UI, the received dimensions may be <= 0.
132+
// Once things start to flesh out in the UI then true dimensions come in.
133+
// So only adjust the grid rows/cols if we received true dimensions.
134+
if (height <= 0 || width <= 0) {
135+
logger.debug('received invalid dimensions, not resizing grid', {
136+
height,
137+
width,
138+
});
139+
return;
102140
}
103-
if (width) {
141+
142+
const newMaxRows = Math.floor(height / gridRowHeightWithMarginPx);
143+
setGridMaxRows(newMaxRows);
104144
setGridMaxWidth(width);
105-
}
106-
}, [dimensions, gridRowHeightWithMarginPx]);
145+
}, [logger, height, width, gridRowHeightWithMarginPx]);
107146

108147
/**
109148
* Load the layout from storage or build a default layout.
110149
*/
111-
const buildDefaultLayout = useCallback((): Array<Layout> => {
112-
let layout = LocalStorage.get<Array<Layout>>('layout');
150+
const buildDefaultLayout = useCallback((): Layout => {
151+
let layout = LocalStorage.get<Layout>('layout');
113152

114153
if (layout) {
115154
// Discard any old layout items that are not in the grid's items list.
@@ -147,7 +186,7 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
147186
// and column spans for the x-index. It's weird.
148187
let colOffset = 0;
149188

150-
layout = items.map((item, index): Layout => {
189+
layout = items.map((item, index): GridLayoutItem => {
151190
// If time to move to next row then adjust the offsets.
152191
if (index > 0 && index % maxItemsPerRow === 0) {
153192
// Only increase the offset by an item's row height (without margin)
@@ -157,7 +196,7 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
157196
colOffset = 0;
158197
}
159198

160-
const newItem = {
199+
const newItem: GridLayoutItem = {
161200
i: item.itemId, // unique identifier for the grid item
162201
x: defaultCols * colOffset, // which column to start at, not pixels
163202
y: rowOffset, // pixels (row # x row height px without margin)
@@ -175,10 +214,10 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
175214
return layout;
176215
}, [items]);
177216

178-
const [layout, setLayout] = useState<Array<Layout>>(buildDefaultLayout);
217+
const [layout, setLayout] = useState<Layout>(buildDefaultLayout);
179218

180219
// Save the layout when it changes in the grid.
181-
const onLayoutChange = useCallback((newLayout: Array<Layout>) => {
220+
const onLayoutChange = useCallback((newLayout: Layout) => {
182221
setLayout(newLayout);
183222
LocalStorage.set('layout', newLayout);
184223
}, []);
@@ -275,6 +314,8 @@ export const Grid: React.FC<GridProps> = (props: GridProps): ReactNode => {
275314
compactType={null}
276315
// Prevent items from overlapping or being pushed.
277316
preventCollision={true}
317+
// Prevent items from being dragged over each other.
318+
allowOverlap={false}
278319
// Prevent items from being dragged outside the grid.
279320
isBounded={true}
280321
// Allow items to be dragged around the grid.

0 commit comments

Comments
 (0)