Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Commit

Permalink
[WINDOW]: enabled pinned rows top and bottom for the grid. (#171)
Browse files Browse the repository at this point in the history
  • Loading branch information
leebeydoun committed Feb 26, 2022
1 parent b93fc87 commit 18efba3
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/loud-cars-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@resembli/react-virtualized-window": patch
---

Added support for pinned rows top and bottom
7 changes: 6 additions & 1 deletion packages/react-virtualized-window/src/ScrollDiv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ import type { PropsWithChildren } from "react"

interface ScrollDivProps {
disableSticky?: boolean
style?: React.CSSProperties
leftOffset: number
topOffset: number
top: number
}

export function ScrollDiv({
disableSticky,
style,
leftOffset,
topOffset,
top,
children,
}: PropsWithChildren<ScrollDivProps>) {
return (
Expand All @@ -20,8 +24,9 @@ export function ScrollDiv({
transform: `translate3d(${disableSticky ? 0 : -leftOffset}px, ${
disableSticky ? 0 : -topOffset
}px, 0px)`,
top: 0,
top,
willChange: "transform",
...style,
}}
>
{children}
Expand Down
94 changes: 89 additions & 5 deletions packages/react-virtualized-window/src/components/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export function Grid<T>({
height: sizingHeight,

onScroll: userOnScroll,

pinnedTopCount = 0,
pinnedBottomCount = 0,
}: GridProps<T>) {
const windowRef = React.useRef<HTMLDivElement>(null)
useWindowApi(windowRef, apiRef)
Expand All @@ -46,6 +49,14 @@ export function Grid<T>({
userOnScroll,
})

const [topData, botData, scrollData] = React.useMemo(() => {
return [
data.slice(0, pinnedTopCount),
data.slice(pinnedTopCount, pinnedTopCount + pinnedBottomCount),
data.slice(pinnedTopCount + pinnedBottomCount),
]
}, [data, pinnedBottomCount, pinnedTopCount])

const [adjustedWidth, adjustedHeight] = useScrollAdjustWindowDims({
height,
width,
Expand All @@ -58,19 +69,33 @@ export function Grid<T>({
})

const [dataHeights, innerHeight] = useDataDimension({
count: data.length,
count: scrollData.length,
defaultDimension: defaultRowHeight,
windowDim: adjustedHeight,
dimensions: rowHeights,
})

const [dataWidths, innerWidth] = useDataDimension({
count: data[0]?.length ?? 0,
count: scrollData[0]?.length ?? 0,
defaultDimension: defaultColumnWidth,
windowDim: adjustedWidth,
dimensions: columnWidths,
})

const [topHeights, totalTopHeight] = useDataDimension({
count: topData.length,
defaultDimension: defaultRowHeight,
windowDim: adjustedHeight,
dimensions: rowHeights,
})

const [botHeights, totalBotHeight] = useDataDimension({
count: botData.length,
defaultDimension: defaultRowHeight,
windowDim: adjustedHeight,
dimensions: rowHeights,
})

const [vertStart, vertEnd, runningHeight] = useIndicesForDimensions({
itemDimensions: dataHeights,
offset: topOffset,
Expand All @@ -87,7 +112,7 @@ export function Grid<T>({

const scrollableItems = useScrollItems({
children,
data,
data: scrollData,
dataHeights,
dataWidths,
getKey,
Expand All @@ -99,6 +124,34 @@ export function Grid<T>({
vertStart,
})

const topItems = useScrollItems({
children,
data: topData,
dataHeights: topHeights,
dataWidths,
getKey,
horiStart,
horiEnd,
runningHeight: 0,
runningWidth,
vertStart: 0,
vertEnd: topData.length,
})

const botItems = useScrollItems({
children,
data: botData,
dataHeights: botHeights,
dataWidths,
getKey,
horiStart,
horiEnd,
runningHeight: 0,
runningWidth,
vertStart: 0,
vertEnd: topData.length,
})

return (
<SizingDiv
width={sizingWidth}
Expand All @@ -122,17 +175,48 @@ export function Grid<T>({
<div
style={{
width: innerWidth,
height: innerHeight,
height: innerHeight + totalTopHeight + totalBotHeight,
}}
>
<StickyDiv
disabled={disableSticky ?? false}
height={adjustedHeight}
width={adjustedWidth}
>
<ScrollDiv disableSticky={disableSticky} topOffset={topOffset} leftOffset={leftOffset}>
<ScrollDiv
disableSticky={disableSticky}
topOffset={topOffset}
leftOffset={leftOffset}
top={totalTopHeight}
>
{scrollableItems}
</ScrollDiv>
<div
style={{
position: "sticky",
top: 0,
left: 0,
}}
>
<ScrollDiv
top={0}
topOffset={0}
leftOffset={leftOffset}
disableSticky={disableSticky}
>
{topItems}
</ScrollDiv>
</div>
<div style={{ position: "sticky", top: adjustedHeight - totalBotHeight, left: 0 }}>
<ScrollDiv
top={0}
leftOffset={leftOffset}
topOffset={0}
disableSticky={disableSticky}
>
{botItems}
</ScrollDiv>
</div>
</StickyDiv>
</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions packages/react-virtualized-window/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export interface VirtualWindowBaseProps<T> {
width?: React.CSSProperties["width"]
height?: React.CSSProperties["height"]

pinnedTopCount?: number
pinnedBottomCount?: number

"data-testid"?: string
}

Expand Down
17 changes: 2 additions & 15 deletions playgrounds/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,6 @@ const data = Array.from({ length: 1000 }, (_, row) => {
})
})

const pinnedLeft = [
Array.from({ length: 1000 }, (_, row) => [row, -1]),
Array.from({ length: 1000 }, (_, row) => [row, -2]),
Array.from({ length: 1000 }, (_, row) => [row, -3]),
]

const pinnedRight = [
Array.from({ length: 1000 }, (_, row) => [row, "R1"]),
Array.from({ length: 1000 }, (_, row) => [row, "R2"]),
Array.from({ length: 1000 }, (_, row) => [row, "R2"]),
]

function App() {
const [disableSticky, setStickyDisabled] = useState(false)

Expand All @@ -71,9 +59,8 @@ function App() {
width="70%"
height="70%"
disableSticky={disableSticky}
pinnedRight={pinnedRight}
pinnedLeft={pinnedLeft}
gap={20}
pinnedTopCount={2}
pinnedBottomCount={2}
>
{({ data, style, cellMeta }) => (
<div
Expand Down

0 comments on commit 18efba3

Please sign in to comment.