Skip to content

Commit ad9177d

Browse files
committed
refactor: rename LanesGapVirtualizer to LanesVirtualizer and improve grid styling
1 parent d792ffc commit ad9177d

File tree

1 file changed

+184
-100
lines changed

1 file changed

+184
-100
lines changed

examples/react/lanes/src/main.tsx

Lines changed: 184 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ function App() {
1010
return (
1111
<div>
1212
<p>
13-
<strong>Lanes</strong> are useful when you are trying to draw a grid of items, where
14-
each row is split into multiple columns.
13+
<strong>Lanes</strong> are useful when you are trying to draw a grid of
14+
items, where each row is split into multiple columns.
1515
</p>
1616
<br />
1717
<br />
1818

1919
<h3>Lanes</h3>
20-
<LanesGapVirtualizer />
20+
<LanesVirtualizer />
2121
<br />
2222
<br />
2323
<h3>Lanes Gaps</h3>
@@ -41,7 +41,7 @@ function App() {
4141
)
4242
}
4343

44-
function LanesGapVirtualizer() {
44+
function LanesVirtualizer() {
4545
const [numLanes, setNumLanes] = React.useState(4)
4646
const parentRef = React.useRef(null)
4747

@@ -55,18 +55,32 @@ function LanesGapVirtualizer() {
5555

5656
return (
5757
<>
58-
<div style={{ display: 'grid', gridTemplateColumns: '80px 200px', gap: '10px' }}>
58+
<div
59+
style={{
60+
display: 'grid',
61+
gridTemplateColumns: '80px 200px',
62+
gap: '10px',
63+
}}
64+
>
5965
<label htmlFor="numLanes1">Num Lanes</label>
60-
<input type="number" id="numLanes1" value={numLanes} onChange={(e) => {setNumLanes(Number(e.target.value)); rowVirtualizer.measure()}} />
66+
<input
67+
type="number"
68+
id="numLanes1"
69+
value={numLanes}
70+
onChange={(e) => {
71+
setNumLanes(Number(e.target.value))
72+
rowVirtualizer.measure()
73+
}}
74+
/>
6175
</div>
6276
<br />
6377
<div
6478
ref={parentRef}
6579
className="List"
6680
style={{
67-
height: "200px",
68-
width: "400px",
69-
overflow: "auto",
81+
height: '200px',
82+
width: '400px',
83+
overflow: 'auto',
7084
}}
7185
>
7286
<div
@@ -115,23 +129,56 @@ function GapVirtualizer() {
115129

116130
return (
117131
<>
118-
<div style={{ display: 'grid', gridTemplateColumns: '80px 200px', gap: '10px' }}>
132+
<div
133+
style={{
134+
display: 'grid',
135+
gridTemplateColumns: '80px 200px',
136+
gap: '10px',
137+
}}
138+
>
119139
<label htmlFor="numLanes2">Num Lanes</label>
120-
<input type="number" id="numLanes2" value={numLanes} onChange={(e) => {setNumLanes(Number(e.target.value)); rowVirtualizer.measure()}} />
121-
<label htmlFor="rowGap" >Row Gap</label>
122-
<input type="number" id="rowGap" value={rowGap} onChange={(e) => {setRowGap(Number(e.target.value)); rowVirtualizer.measure()}} />
140+
<input
141+
type="number"
142+
id="numLanes2"
143+
value={numLanes}
144+
readOnly
145+
onChange={(e) => {
146+
setNumLanes(Number(e.target.value))
147+
rowVirtualizer.measure()
148+
}}
149+
/>
150+
<label htmlFor="rowGap">Row Gap</label>
151+
<input
152+
type="number"
153+
id="rowGap"
154+
value={rowGap}
155+
onChange={(e) => {
156+
setRowGap(Number(e.target.value))
157+
rowVirtualizer.measure()
158+
}}
159+
/>
123160
<label htmlFor="columnGap">Column Gap</label>
124-
<input type="number" id="columnGap" value={columnGap} onChange={(e) => {setColumnGap(Number(e.target.value)); rowVirtualizer.measure()}} />
161+
<input
162+
type="number"
163+
id="columnGap"
164+
value={columnGap}
165+
onChange={(e) => {
166+
setColumnGap(Number(e.target.value))
167+
rowVirtualizer.measure()
168+
}}
169+
/>
125170
</div>
126171
<br />
127-
172+
128173
<div
129174
ref={parentRef}
130175
className="List"
131176
style={{
132-
height: "200px",
133-
width: "400px",
134-
overflow: "auto",
177+
height: '200px',
178+
width: '400px',
179+
overflow: 'auto',
180+
minWidth: CELL_WIDTH,
181+
minHeight: '35px',
135182
}}
136183
>
137184
<div
@@ -143,21 +190,26 @@ function GapVirtualizer() {
143190
>
144191
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
145192
return (
146-
<div
147-
key={virtualRow.index}
148-
className={virtualRow.index % 2 ? 'ListItemOdd' : 'ListItemEven'}
149-
style={{
150-
position: 'absolute',
151-
top: 0,
152-
"--start-ratio": `calc(mod(${virtualRow.index}, ${numLanes}) / ${numLanes})`,
153-
left: `calc((var(--start-ratio) * 100%) + (${columnGap}px * var(--start-ratio)))`,
154-
height: `${virtualRow.size}px`,
155-
transform: `translateY(${virtualRow.start}px)`,
156-
outline: '1px solid red',
157-
} as React.CSSProperties}
158-
>
159-
Cell {virtualRow.index}
160-
</div>
193+
<div
194+
key={virtualRow.index}
195+
className={
196+
virtualRow.index % 2 ? 'ListItemOdd' : 'ListItemEven'
197+
}
198+
style={
199+
{
200+
position: 'absolute',
201+
top: 0,
202+
'--start-ratio': `calc(mod(${virtualRow.index}, ${numLanes}) / ${numLanes})`,
203+
left: `calc((var(--start-ratio) * 100%) + (${columnGap}px * var(--start-ratio)))`,
204+
width: `calc((100% / ${numLanes}) - (${columnGap}px * (${numLanes} - 1) / ${numLanes}))`,
205+
height: `${virtualRow.size}px`,
206+
transform: `translateY(${virtualRow.start}px)`,
207+
outline: '1px solid red',
208+
} as React.CSSProperties
209+
}
210+
>
211+
Cell {virtualRow.index}
212+
</div>
161213
)
162214
})}
163215
</div>
@@ -183,82 +235,114 @@ function ResizeVirtualizer() {
183235
})
184236

185237
React.useEffect(() => {
186-
if (!parentRef.current) return
187-
// debounce not necessary
188-
const debouncedOnResize = debounce((entries: Array<ResizeObserverEntry>) => {
189-
const rect = entries.at(0)?.contentRect
190-
if (!rect) return
191-
const { width } = rect
192-
setNumLanes(Math.floor(width / CELL_WIDTH))
193-
rowVirtualizer.measure()
194-
}, {
195-
wait: 50,
196-
197-
})
198-
const resizeObserver = new ResizeObserver((entries) => {
199-
debouncedOnResize(entries)
200-
})
201-
resizeObserver.observe(parentRef.current)
202-
return () => {
203-
resizeObserver.disconnect()
204-
}
238+
if (!parentRef.current) return
239+
// debounce not necessary
240+
const debouncedOnResize = debounce(
241+
(entries: Array<ResizeObserverEntry>) => {
242+
const rect = entries.at(0)?.contentRect
243+
if (!rect) return
244+
const { width } = rect
245+
setNumLanes(Math.floor(width / CELL_WIDTH))
246+
rowVirtualizer.measure()
247+
},
248+
{
249+
wait: 50,
250+
},
251+
)
252+
const resizeObserver = new ResizeObserver((entries) => {
253+
debouncedOnResize(entries)
254+
})
255+
resizeObserver.observe(parentRef.current)
256+
return () => {
257+
resizeObserver.disconnect()
258+
}
205259
}, [rowVirtualizer])
206260

207-
208-
209261
return (
210262
<>
211-
<div style={{ display: 'grid', gridTemplateColumns: '80px 200px', gap: '10px' }}>
212-
<label htmlFor="numLanes2">Num Lanes</label>
213-
<input type="number" id="numLanes2" value={numLanes} readOnly disabled/>
214-
<label htmlFor="rowGap" >Row Gap</label>
215-
<input type="number" id="rowGap" value={rowGap} onChange={(e) => {setRowGap(Number(e.target.value)); rowVirtualizer.measure()}} />
216-
<label htmlFor="columnGap">Column Gap</label>
217-
<input type="number" id="columnGap" value={columnGap} onChange={(e) => {setColumnGap(Number(e.target.value)); rowVirtualizer.measure()}} />
218-
</div>
219-
<br />
220-
221-
<div
222-
ref={parentRef}
223-
className="List"
224-
style={{
225-
height: "200px",
226-
width: "400px",
227-
overflow: "auto",
228-
minWidth: CELL_WIDTH,
229-
minHeight: "35px",
230-
resize: 'horizontal',
231-
}}
232-
>
233263
<div
234264
style={{
235-
height: `${rowVirtualizer.getTotalSize()}px`,
236-
width: '100%',
237-
position: 'relative',
265+
display: 'grid',
266+
gridTemplateColumns: '80px 200px',
267+
gap: '10px',
238268
}}
239269
>
240-
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
241-
return (
242-
<div
243-
key={virtualRow.index}
244-
className={virtualRow.index % 2 ? 'ListItemOdd' : 'ListItemEven'}
245-
style={{
246-
position: 'absolute',
247-
top: 0,
248-
"--start-ratio": `calc(mod(${virtualRow.index}, ${numLanes}) / ${numLanes})`,
249-
left: `calc((var(--start-ratio) * 100%) + (${columnGap}px * var(--start-ratio)))`,
250-
width: `calc((100% / ${numLanes}) - (${columnGap}px * (${numLanes} - 1) / ${numLanes}))`,
251-
height: `${virtualRow.size}px`,
252-
transform: `translateY(${virtualRow.start}px)`,
253-
outline: '1px solid red',
254-
} as React.CSSProperties}
255-
>
256-
Cell {virtualRow.index}
257-
</div>
258-
)
259-
})}
270+
<label htmlFor="numLanes2">Num Lanes</label>
271+
<input
272+
type="number"
273+
id="numLanes2"
274+
value={numLanes}
275+
readOnly
276+
disabled
277+
/>
278+
<label htmlFor="rowGap">Row Gap</label>
279+
<input
280+
type="number"
281+
id="rowGap"
282+
value={rowGap}
283+
onChange={(e) => {
284+
setRowGap(Number(e.target.value))
285+
rowVirtualizer.measure()
286+
}}
287+
/>
288+
<label htmlFor="columnGap">Column Gap</label>
289+
<input
290+
type="number"
291+
id="columnGap"
292+
value={columnGap}
293+
onChange={(e) => {
294+
setColumnGap(Number(e.target.value))
295+
rowVirtualizer.measure()
296+
}}
297+
/>
298+
</div>
299+
<br />
300+
301+
<div
302+
ref={parentRef}
303+
className="List"
304+
style={{
305+
height: '200px',
306+
width: '400px',
307+
overflow: 'auto',
308+
minWidth: CELL_WIDTH,
309+
minHeight: '35px',
310+
resize: 'horizontal',
311+
}}
312+
>
313+
<div
314+
style={{
315+
height: `${rowVirtualizer.getTotalSize()}px`,
316+
width: '100%',
317+
position: 'relative',
318+
}}
319+
>
320+
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
321+
return (
322+
<div
323+
key={virtualRow.index}
324+
className={
325+
virtualRow.index % 2 ? 'ListItemOdd' : 'ListItemEven'
326+
}
327+
style={
328+
{
329+
position: 'absolute',
330+
top: 0,
331+
'--start-ratio': `calc(mod(${virtualRow.index}, ${numLanes}) / ${numLanes})`,
332+
left: `calc((var(--start-ratio) * 100%) + (${columnGap}px * var(--start-ratio)))`,
333+
width: `calc((100% / ${numLanes}) - (${columnGap}px * (${numLanes} - 1) / ${numLanes}))`,
334+
height: `${virtualRow.size}px`,
335+
transform: `translateY(${virtualRow.start}px)`,
336+
outline: '1px solid red',
337+
} as React.CSSProperties
338+
}
339+
>
340+
Cell {virtualRow.index}
341+
</div>
342+
)
343+
})}
344+
</div>
260345
</div>
261-
</div>
262346
</>
263347
)
264348
}

0 commit comments

Comments
 (0)