mirror of
https://github.com/dzeiocom/components.git
synced 2025-07-31 09:01:57 +00:00
19
src/Loader/Loader.module.styl
Normal file
19
src/Loader/Loader.module.styl
Normal file
@@ -0,0 +1,19 @@
|
||||
@import '../config'
|
||||
|
||||
.div
|
||||
position fixed
|
||||
left 0
|
||||
width 100%
|
||||
height 7px
|
||||
pointer-events none
|
||||
z-index 200
|
||||
|
||||
top 0
|
||||
&.hide
|
||||
transition top .5s ease-in-out
|
||||
top -7px
|
||||
div
|
||||
&:not([style="width: 0px;"])
|
||||
transition width 50ms ease-in-out
|
||||
background rgba($main, .7)
|
||||
height 100%
|
21
src/Loader/Loader.stories.tsx
Normal file
21
src/Loader/Loader.stories.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Meta, Story } from '@storybook/react/types-6-0'
|
||||
import React from 'react'
|
||||
import { Zap } from 'lucide-react'
|
||||
import Component from '.'
|
||||
|
||||
export default {
|
||||
title: 'DZEIO/Loader',
|
||||
component: Component,
|
||||
parameters: {
|
||||
layout: 'fullscreen'
|
||||
}
|
||||
} as Meta
|
||||
|
||||
export const Basic: Story<any> = (args: any) => <Component {...args} />
|
||||
|
||||
let tmp = Basic.bind({})
|
||||
tmp.args = {
|
||||
auto: {interval : [10, 100], increment: [0, 5]}
|
||||
}
|
||||
|
||||
export const Auto = tmp
|
97
src/Loader/index.tsx
Normal file
97
src/Loader/index.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import { Router } from 'next/router'
|
||||
import React from 'react'
|
||||
import { buildClassName } from '../Util'
|
||||
import css from './Loader.module.styl'
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* The new Percentage (if you calculate it yourself)
|
||||
*/
|
||||
percent?: number
|
||||
|
||||
/**
|
||||
* Auto random loader
|
||||
*/
|
||||
auto?: {
|
||||
/**
|
||||
* the minimum and maximum interval between two increment
|
||||
*/
|
||||
interval: [number, number]
|
||||
/**
|
||||
* the minimum and maximum incrementation (MUST be an integer)
|
||||
*/
|
||||
increment: [number, number]
|
||||
}
|
||||
}
|
||||
|
||||
interface State {
|
||||
percent?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a simple loading animation at the top of the page
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
export default class Loader extends React.Component<Props, State> {
|
||||
|
||||
public state: State = {}
|
||||
|
||||
private interval?: NodeJS.Timeout
|
||||
|
||||
public componentDidMount() {
|
||||
if (this.props.auto) {
|
||||
Router.events.on('routeChangeComplete', this.routeChangeComplete)
|
||||
Router.events.on('routeChangeStart', this.routeChangeStart)
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.props.auto) {
|
||||
Router.events.off('routeChangeComplete', this.routeChangeComplete)
|
||||
Router.events.off('routeChangeStart', this.routeChangeStart)
|
||||
}
|
||||
}
|
||||
|
||||
public render = () => (
|
||||
<div className={buildClassName(css.div, [css.hide, (this.props.percent || this.state.percent) === 100])}>
|
||||
<div style={{width: (this.props.percent || this.state.percent) ? `${(this.props.percent || this.state.percent)}%` : 0}}></div>
|
||||
</div>
|
||||
)
|
||||
|
||||
private routeChangeComplete = () => {
|
||||
if (this.interval) {
|
||||
clearTimeout(this.interval)
|
||||
this.interval = undefined
|
||||
}
|
||||
this.setState({percent: 100})
|
||||
}
|
||||
|
||||
private routeChangeStart = () => {
|
||||
if (this.interval) {
|
||||
clearTimeout(this.interval)
|
||||
}
|
||||
this.setState({percent: 0}, () => {
|
||||
if (!this.props.auto) {return}
|
||||
this.interval = setTimeout(this.timeoutFn, this.randomInt(this.props.auto.interval[0], this.props.auto.interval[1]))
|
||||
})
|
||||
}
|
||||
|
||||
private timeoutFn = () => {
|
||||
if (!this.props.auto) {return}
|
||||
const p = this.state.percent || 0
|
||||
this.setState({
|
||||
percent: Math.min(
|
||||
99,
|
||||
p >= 80 ? p + Math.random() : p + this.randomInt(this.props.auto.increment[0], this.props.auto.increment[1])
|
||||
)
|
||||
})
|
||||
this.interval = setTimeout(this.timeoutFn, this.randomInt(this.props.auto.interval[0], this.props.auto.interval[1]))
|
||||
}
|
||||
|
||||
private randomInt(min = 0, max = 10) {
|
||||
min = Math.ceil(min)
|
||||
max = Math.floor(max)
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user