Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/minht11/solid-virtual-container

Virtual list/grid for solid-js
https://github.com/minht11/solid-virtual-container

Last synced: about 1 month ago
JSON representation

Virtual list/grid for solid-js

Awesome Lists containing this project

README

        

# Virtual container for Solid-js
Efficient, single direction virtual list/grid for Solid-js

## Features
* Support for grid/list modes.
* Only render visible items, no matter how big is your list.
* Keyboard navigation and focus management out of the box.
* Option to change items size based on available space.

[Demo](https://codesandbox.io/s/minht11solid-virtual-container-demo-pk74r)

## Usage

```
npm install @minht11/solid-virtual-container
```

Create list item component.
```tsx
const ListItem = (props) => (


{props.item}


)
```
Create vertically scrolling virtual list
```tsx
import { VirtualContainer } from "@minht11/solid-virtual-container"

const App = () => {
const items = [0, 1, 2, 3]
let scrollTargetElement!: HTMLDivElement
return (



{ListItem}


)
}
```
or a virtual grid
```tsx
const App = () => {
const items = [0, 1, 2, 3]
let scrollTargetElement!: HTMLDivElement
return (

(
Math.floor(
measurements.container.cross / measurements.itemSize.cross
)
)}
>
{ListItem}


)
}
```
> You can control list items styling using regular CSS, including `width` and `height`, however properties defined using `itemSize` will take a priority.

> One dimensional lists require only main direction size be set using `itemSize`. For vertical scrolling that's `height` and for horizontal direction that's `width`. Multidimensional lists require both.
## Api
### ScrollTargetContext
If you you do not have an immediate access to the VirtualContainer, or do not want to pass props several components deep you can use context api.

```tsx
const App = () => {
const items = [0, 1, 2, 3]
let scrollTargetElement!: HTMLDivElement
return (



...

...


)
}
```
### Virtual container options
```tsx
interface VirtualContainer {
// your list data array.
items: readonly T[]
// Define elements size.
// All elements will use same size.
itemSize: VirtualItemSize
// Scrolling element, if context api is used this is not needed,
// however you must use one or the other.
scrollTarget?: HTMLElement
// Scroll direction. Default is vertical.
direction?: 'vertical' | 'horizontal'
// Number of elements to render below and above currently visible items,
// if not provided an optimal amount will be automatically picked.
overscan?: number
// Container className, if at all possible ignore this option,
// because direct styling can break virtualizing, instead wrap
// element in another div and style that.
className?: string
role?: JSX.HTMLAttributes['role']
// Function which determines how many columns in vertical mode
// or rows in horizontal to show. Default is 1.
crossAxisCount?: (
measurements: CrossAxisCountOptions,
// The same as items.length
itemsCount: number,
) => number
// List item render function.
children: (props: VirtualItemProps) => JSX.Element
}
```
If `direction` is `vertical` main axis is vertical.
If `direction` is `horizontal` main axis is horizontal.
```tsx
interface Axis {
// Main scrolling direction axis.
main: number
// Opposite axis to main.
cross: number
}
```

Parameter object used in `VirtualContainer.crossAxisCount` function.
```tsx
interface CrossAxisCountOptions {
// Scrolling element dimensions.
target: Axis
// Container element dimensions.
container: Axis
// List element dimensions.
itemSize: Axis
}
```
### Item size
```tsx
// You can use static object to define item size
interface VirtualItemSizeStatic {
width?: number
height?: number
}

// or use a function to calculate it when layout changes.
type VirtualItemSizeDynamic = (
crossAxisContentSize: number,
// Scroll direction.
isHorizontal: boolean,
) => VirtualItemSizeStatic
```
Dynamic size is useful when you want your
grid items to fill all available space
```tsx
// One possible example
const calculateItemSize = (crossAxisSize: number) => {
// Choose minimum size depending on the available space.
const minWidth = crossAxisSize > 560 ? 180 : 140

const count = Math.floor(crossAxisSize / minWidth)
const width = Math.floor(crossAxisSize / count)

return {
width,
height: width + 48
}
}

```

## Limitations
Different individual item sizes and scrolling with both directions at the same time are not and likely will never be supported by this package.

Page CSP must allow inline style sheets.