GithubHelp home page GithubHelp logo

omer73364 / lazy-load-list Goto Github PK

View Code? Open in Web Editor NEW
31.0 2.0 7.0 67 KB

Lazy Load List is a lightweight web package that loads items in lazy way..

JavaScript 35.05% Svelte 25.57% Vue 30.51% CSS 8.87%
web packages js javascript svelte vue list virtual lazy load

lazy-load-list's Introduction

Lazy Load List

# Stand With Palestine ๐Ÿ‡ต๐Ÿ‡ธ

Lazy Load List is a lightweight web package that loads items in lazy way to achieve high performance and better UX in large lists.

Rendering large lists makes the first load slow especially if items contain images, so this package split the list to small lists then it renders them one by one when scrolling to the end of the list..

you can notice the deference here:

loading performance deference

Features

  • Fast Loading ๐Ÿš€
  • Lightweight package
  • Better user experience
  • Supports most loved JS frameworks
  • Supports SSR & SSG

Demo

you can find the source code of examples in examples folder

Lazy Load List 1.2 is here ๐ŸŽ‰

what's new?

  • support React js
  • auto loading items when container can contain more
  • better performance
  • explain using custom loading element

Supported Frameworks

| svelte logo | Svete js     | โœ…
| vue logo | Vue js (2,3) | โœ…
| react logo | React js     | โœ…

Installation

install the package using npm or yarn:

install using npm

$ npm i lazy-load-list

or using yarn

$ yarn add lazy-load-list

Usage

โš  you must wrap the list by div and specify the height and width in the wrapper div.

  • svelte logo svelte js:
import LazyList from 'lazy-load-list/svelte'

<div  class="container">
	<LazyList
		data={colors}
		itemsPerRender={15}
		containerClasses="list"
		defaultLoadingColor="#222"
		let:item={item}
	>
		<h1>{ item }</h1>
	</LazyList>
</div>
  • vue logo vue js:
<div class="container">
	<LazyList
		:data="items"
		:itemsPerRender="15"
		containerClasses="list"
		defaultLoadingColor="#222"
	>
		<template v-slot="{item}">
		    <h1>{{ item }}</h1>
		</template>
	</LazyList>
</div>

// script
import LazyList from 'lazy-load-list/vue'
..
components: { LazyList } // don't forget to define it in the components
  • react logo react js:
import  LazyList  from  'lazy-load-list/react'

const renderItem = ({item, index}) => (
	<h1 key={index}>{ item }</h1>
)

<div className="container">
	<LazyList
		data={colors}
		itemsPerRender={15}
		containerClasses="list"
		defaultLoadingColor="#222"
		renderItem={renderItem}
	/>
</div>

Props

prop supported framework description required type default value
data all the item array yes array []
itemsPerRender all items to be rendered per load yes number 3
containerClasses all list container classes for CSS no string ''
defaultLoading all to show the default loading or not no bool true
defaultLoadingColor all color of the default loading no string '#18191A'
renderItem React js element to be render for each item yes React component () => null
loadingComponent React js custom loading component no React component () => null

Using custom loading element

you can specify the loading element color using (defaultLoadingColor) prop.. but if you don't like the default loading element, you can use custom one:

  • in svelte logo svelte js & vue logo vue js (just use slot name "loading like this):
<img slot="loading" src="loading.svg" width="16" alt="loading"/>
  • react logo react js (use loadingComponent props to pass the element):
	..
		loadingComponent={loadingElementHere}
	/>

lazy-load-list's People

Contributors

omer73364 avatar salemkode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

lazy-load-list's Issues

Missing lib/Loading.css

Description

After npm install, the following error appears:

ERROR  Failed to compile with 1 error  

This relative module was not found:
* ../lib/loading.css in ./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/vue-loader-v16/dist??ref--1-1!./node_modules/lazy-load-list/vue/LazyList.vue?vue&type=script&lang=js

As the error suggests, the loading.css file is missing from the lib directory. Judging from older versions of this, the code used to be in the Loading modules but was moved to an independent file which was never added to git.

Suggested fix

Create a new file called lib/loading.css with the following:

.dots {
    width: 3.5em;
    display: flex;
    flex-flow: row nowrap;
    align-items: center;
    justify-content: space-between;
}

.dots div {
    width: 0.8em;
    height: 0.8em;
    border-radius: 50%;
    animation: fade 0.8s ease-in-out alternate infinite;
}

.dots div:nth-of-type(1) {
    animation-delay: -0.4s;
}

.dots div:nth-of-type(2) {
    animation-delay: -0.2s;
}

@keyframes fade {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}

[Error] You may need an appropriate loader to handle this file type

Hello, Mr. Omar
Thanks for your hard work, But I have a little problem.

I tried to use 'lazy-load-list' in electron app (with nextron), And I got this error
Screenshot_20220404_023527

After some search, I think this to be related to webpack.
So, Is there anything which can I do to solve this problem?

Code :

import LazyList from "lazy-load-list/react";
import { useState, useEffect, useRef } from "react";

import {
	Alert,
	AlertIcon,
	AlertTitle,
	AlertDescription,
	Button,
	IconButton,
	Box,
	Tooltip,
	Flex,
	Spinner,
	HStack,
	Stack,
	Input,
	InputRightElement,
	InputGroup,
	Heading,
	Select,
} from "@chakra-ui/react";

import {
	HiTrash,
	HiRefresh,
	HiOutlineInformationCircle,
	HiSearch,
	HiX,
} from "react-icons/hi";
import LogsProvider, { useLogs } from "@Context/logs";

const NUMBER_OF_MESSAGES = 100;

function Logs() {
	const { logs, GetLogs, ClearLogs, isLoading } = useLogs();

	const [StatusFilter, setStatusFilter] = useState("all");
	const [LogsAfterFiltering, setLogsAfterFiltering] = useState(
		logs?.lines ?? [],
	);

	const [search, setSearch] = useState({ bool: false, value: "" });
	useEffect(() => GetLogs(), []); // * Get Logs when user open the modal

	useEffect(() => {
		setLogsAfterFiltering(
			logs?.lines?.filter((line) => {
				if (StatusFilter === "all") return true;
				return line.status === StatusFilter && line;
			}),
		);
	}, [StatusFilter, logs]);

	useEffect(() => {
		setLogsAfterFiltering(
			logs?.lines.filter(
				(line) =>
					line.content.toLowerCase().includes(search.value.toLowerCase()) &&
					(line.status === StatusFilter || StatusFilter === "all"),
			),
		);
	}, [search.value, logs]);

	// useEffect(() => console.log("search update to", search), [search]); // ! For Debugging
	// useEffect(() => console.log("logs update to", logs), [logs]); // ! For Debugging
	// useEffect(() => console.log("LogsAfterFiltering update to", LogsAfterFiltering), [LogsAfterFiltering]); // ! For Debugging

	return (
		<>
			<Flex w='full' justify='space-between' my={3}>
				<HStack>
					<Tooltip
						hasArrow
						placement='right'
						label={`Logs stored in ${logs.path}`}>
						<IconButton
							variant='ghost'
							cursor='default'
							icon={<HiOutlineInformationCircle size='1.3em' />}
						/>
					</Tooltip>
				</HStack>

				<HStack justify='end' spacing={3}>
					<Select
						maxW='150px'
						value={StatusFilter}
						variant='filled'
						onChange={(e) => setStatusFilter(e.target.value)}>
						<option value='all'>All {logs?.lines?.length}</option>
						<option value='info'>
							Info{" "}
							{logs?.lines?.filter((line) => line.status === "info").length}
						</option>
						<option value='warning'>
							Warning{" "}
							{logs?.lines?.filter((line) => line.status === "warning").length}
						</option>
						<option value='error'>
							Error{" "}
							{logs?.lines?.filter((line) => line.status === "error").length}
						</option>
					</Select>
					{search.bool ? (
						<InputGroup w='200px'>
							<Input
								placeholder='Search'
								variant='filled'
								value={search.value}
								onChange={(e) =>
									setSearch({ ...search, value: e.target.value })
								}
							/>
							<InputRightElement>
								{search.value ? (
									<IconButton
										variant='none'
										icon={<HiX size='1.4em' />}
										onClick={() => setSearch({ ...search, value: "" })}
									/>
								) : (
									<IconButton
										variant='none'
										icon={<HiSearch size='1.4em' />}
										onClick={() => setSearch({ ...search, bool: !search.bool })}
									/>
								)}
							</InputRightElement>
						</InputGroup>
					) : (
						<Tooltip label='Search in logs'>
							<IconButton
								variant='ghost'
								icon={<HiSearch size='1.4em' />}
								onClick={() => setSearch({ ...search, bool: !search.bool })}
							/>
						</Tooltip>
					)}

					<Button leftIcon={<HiRefresh />} onClick={() => GetLogs()}>
						Refresh
					</Button>
					<Button
						leftIcon={<HiTrash />}
						colorScheme='red'
						onClick={() => ClearLogs()}>
						Clear All
					</Button>
				</HStack>
			</Flex>
			<Stack spacing={1}>
				{isLoading ? (
					<Spinner
						size='xl'
						color='green'
						alignSelf='center'
						justifySelf='center'
					/>
				) : !(LogsAfterFiltering.length > 0) ? (
					<Heading size='md' alignSelf='center'>
						No logs found
					</Heading>
				) : (
					<LogRows
						data={LogsAfterFiltering.slice(
							0,
							Math.min(LogsAfterFiltering.length, NUMBER_OF_MESSAGES),
						)}
					/>
				)}
			</Stack>
		</>
	);
}

function LogAlert({ item, index }) {
	const { status, date, content } = item;
	const availableTypes = ["warning", "error", "info"];

	return (
		<Alert
			key={index}
			status={availableTypes.includes(status) ? status : "warning"}>
			<AlertIcon />
			<Box flex={1}>
				<AlertTitle mr={2}>{date}</AlertTitle>{" "}
				<AlertDescription>{content}</AlertDescription>
			</Box>
		</Alert>
	);
}

const LogRows = ({ data }) => {
	const listRef = useRef(null);
	const ref = useRef(null);



	return (
		<Box ref={ref}>
			<LazyList
				data={data}
				itemsPerRender={15}
				defaultLoadingColor='#222'
				renderItem={LogAlert}
			/>
			
		</Box>
	);
};

function LogsComponent() {
	return (
		<LogsProvider>
			<Logs />
		</LogsProvider>
	);
}

export default LogsComponent;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.