├── .github └── workflows │ └── npm-publish.yml ├── .gitignore ├── README.md ├── index.tsx ├── package.json └── yarn.lock /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 16 18 | - run: yarn install --frozen-lockfile 19 | # - run: npm test 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v3 26 | - uses: actions/setup-node@v3 27 | with: 28 | node-version: 16 29 | registry-url: https://registry.npmjs.org/ 30 | - run: yarn install --frozen-lockfile 31 | - run: yarn publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | yarn-error.log 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # solid-infinite-scroll 2 | 3 | Infinite scrolling / Dynamic list loading library for SolidJS 4 | 5 | ### Installation 6 | 7 | First, install the library from the npm registry: 8 | 9 | ```sh 10 | yarn add -D solid-infinite-scroll 11 | ``` 12 | 13 | Second, import it in the tsx component you're working on: 14 | 15 | ```tsx 16 | import InfiniteScroll from 'solid-infinite-scroll'; 17 | ``` 18 | 19 | ### Usage 20 | 21 | To use the infinite scroll module, you would need a signal/resource for data storage, and implement two functions: 22 | 23 | * `each` should return the currently stored data array, this is similar to the SolidJS `` component 24 | * `hasMore` should return true if more data is available 25 | * `next` should load more data into the array stored by `each` and return nothing 26 | 27 | For example, if you want to load all data at once but only display e.g. 50 at a time, you can do: 28 | 29 | ```tsx 30 | const fetchApi = async () => await (await fetch("https://api.example.com/list").json() as string[] 31 | 32 | export default function App() { 33 | const [api] = createResource(fetchApi) 34 | 35 | const [scrollIndex, setScrollIndex] = createSignal(50) 36 | const scrollNext = () => setScrollIndex(Math.min(scrollIndex() + 50, api().length)) 37 | 38 | return ( 39 | 42 | {(item, index) => 43 |
{item}
44 | } 45 |
46 | ) 47 | } 48 | ``` 49 | -------------------------------------------------------------------------------- /index.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Accessor, 3 | createEffect, 4 | createSignal, 5 | For, 6 | JSX, 7 | onCleanup, 8 | onMount, 9 | Show, 10 | } from "solid-js"; 11 | 12 | export default function InfiniteScroll(props: { 13 | each: readonly T[] | undefined | null | false; 14 | children: (item: T, index: Accessor) => U; 15 | next: () => any; 16 | hasMore: boolean; 17 | loadingMessage?: JSX.Element; 18 | endMessage?: JSX.Element; 19 | scrollTreshold?: number; 20 | }) { 21 | let observerRef: any; 22 | 23 | const [loading, setLoading] = createSignal(false); 24 | 25 | onMount(() => { 26 | const observer = new IntersectionObserver((entries) => { 27 | if (entries[0].isIntersecting) { 28 | if (props.hasMore) { 29 | setLoading(true); 30 | props.next(); 31 | } 32 | } else { 33 | setLoading(false); 34 | } 35 | }); 36 | 37 | observer.observe(observerRef); 38 | 39 | onCleanup(() => { 40 | observer.unobserve(observerRef); 41 | }); 42 | }); 43 | 44 | const observerObjectHeight = !props.scrollTreshold 45 | ? "50px" 46 | : props.scrollTreshold + "px"; 47 | 48 | createEffect(() => { 49 | if (!props.hasMore) { 50 | setLoading(false); 51 | } 52 | }); 53 | 54 | return ( 55 | <> 56 | 57 |
65 | Loading...
} 68 | /> 69 | 70 | 71 | ); 72 | } 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solid-infinite-scroll", 3 | "version": "1.0.1", 4 | "description": "infinite scroll library for solid-js", 5 | "main": "index.js", 6 | "scripts": {}, 7 | "repository": { 8 | "type": "git", 9 | "url": "git@github.com:azzzub/solid-infinite-scroll.git" 10 | }, 11 | "keywords": [ 12 | "solidjs", 13 | "scroll", 14 | "infinite scroll", 15 | "dynamic" 16 | ], 17 | "author": "azzzub", 18 | "license": "ISC", 19 | "dependencies": { 20 | "solid-js": "^1.4.7" 21 | } 22 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | csstype@^3.1.0: 6 | version "3.1.1" 7 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" 8 | integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== 9 | 10 | solid-js@^1.4.7: 11 | version "1.6.11" 12 | resolved "https://registry.yarnpkg.com/solid-js/-/solid-js-1.6.11.tgz#263a512bf94efd89245a77f58dc18c195302237f" 13 | integrity sha512-JquQQHPArGq+i2PLURxJ99Pcz2/1docpbycSio/cKSA0SeI3z5zRjy0TNcH4NRYvbOLrcini+iovXwnexKabyw== 14 | dependencies: 15 | csstype "^3.1.0" 16 | --------------------------------------------------------------------------------