@lumberyard/react-doomsday
v1.1.5
Published
A nifty countdown component for React
Downloads
6
Maintainers
Readme
react-doomsday
A nifty countdown component for React
Doomsday is a component written originally for one of my projects. I needed something that would be very flexible at displaying time countdown and existing solutions required hacking around to make the countdown behave as I intended, so I wrote my own and decided to publish it. Maybe someone finds it useful.
react-doomsday is written with TypeScript and uses dayjs in the background. It's sole purpose is to count time from now until some date in the future.
Menu
Usage
import * as React from 'react'
import Doomsday from '@lumberyard/react-doomsday'
const Example: React.FC = () => {
const date = "2029-05-25T02:23:35.000Z" // or use dayjs or native or timestamp
return (
...
<Doomsday date={date} />
...
)
}
Install
yarn add @lumberyard/react-doomsday
npm install --save @lumberyard/react-doomsday
Demo
Codesandbox
Doomsday component
<Doomsday/> is a <div> wrapper around logic based on dayjs
. The component gives you a bunch of ways of displaying the date. Each unit of time (eg. month, minute, etc.) is separate from the rest and works independently.
Props
All <Doomsday/>
props are optional, however, bear in mind that this component has only bare minimum of styling. You can use style
, className
or any other popular CSS-in-JS solution to style it. DoomsdayProps are extended by <div>'s native props, so whatever <div> takes, so does <Doomsday/>
Default styles of the component can be overwritten.
const defaultStyles = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
See DoomsdayProps
Examples
import * as React from 'react'
import Doomsday from '@lumberyard/react-doomsday'
const Example: React.FC = () => {
return (
...
<Doomsday
date="2029-05-25T02:23:35.000Z"
format="[YYYYescape] YYYY-MM-DDTHH:mm:ssZ[Z]"
render={(doom) => ({
// `doom.date` will be in a format passed above
<div>
<h3>{doom.date}</h3>
<p>{doom.endOfTimeSequence.months} months</p>
<p>{doom.endOfTimeSequence.minutes} minutes</p>
<p>{doom.endOfTimeSequence.seconds} seconds</p>
</div>
})}
/>
...
)
}
import * as React from 'react'
import Doomsday from '@lumberyard/react-doomsday'
const Example: React.FC = () => {
const [play, setPlay] = React.useState(true)
return (
...
<Doomsday
play={play}
showDefaults={false} // hides default units
goodbye={<div>KAPUT!</div>}
date="2029-05-25T02:23:35.000Z"
years={({ label, endOfTimeSequence }) => (
// label() displays the unit's label ('years' in this case) and cuts the plural form when necessary
<div>
<span>{endOfTimeSequence}</span>
<span>{label(endOfTimeSequence)}</span>
</div>
)}
months={({ type, endOfTimeSequence }) => (
// label() also takes a second string argument that gets singu/pluralized
<div>
<span>{endOfTimeSequence}</span>
<span>{label(endOfTimeSequence, 'pidgeons')}</span>
</div>
)}
days={(to) => (
// type shows the unit's label
<div>
<span>{to.endOfTimeSequence}</span>
<span>{type}</span>
</div>
)}
hours={(to) => (
<div>
<span>{to.endOfTimeSequence}</span>
<span>Is this a real life...</span>
</div>
)}
minutes={(to) => (
<div>
<span>{to.endOfTimeSequence}</span>
<span>...or just a fantasy?</span>
</div>
)}
seconds={(to) => (
<div>
<span>{to.endOfTimeSequence}</span>
<span>What does the fox say?</span>
</div>
)}
/>
...
)
}
Doomsday hook
The hook is used inside the
<Doomsday/>
wrapper, so don't use both in the same component.
Use the hook in the very last child of the parent tree
If you want more freedom (but keep the default calculations), you can import a useDoomsday
hook instead of <Doomsday/>
component. This function is the ticker written using setInterval()
. I didn't use window.requestAnimationFrame()
because I know setInterval()
better and didn't have time to learn and understand how the other works - I'll probably rewrite it at some point. There shouldn't be any breaking changes.
The hook takes a date
and an optional play
argument and returns a doomsday
object and an isHere
flag.
| prop | type | description | | -------- | ----------------------------------- | ------------------------------------------------- | | doomsday | DoomsdayCreator | object containing default doomsday's calculations | | isHere | boolean | flag indicating countdown's completion |
import * as React from 'react'
import { useDoomsday } from '@lumberyard/react-doomsday'
const Example: React.FC = () => {
const [play, setPlay] = React.useState(true);
const date = "2029-05-25T02:23:35.000Z";
const { doomsday, isHere } = useDoomsday(date, play);
if (isHere) return <div>KAPUT!</div>
return (
...
<div>{doomsday.endOfTime.months}</div>
...
)
}
Doomsday types
Since react-doomsday is written with TypeScript I am going to list typings instead of your regular props.
DoomsdayProps
| prop | type | default | description |
| -------------------------------------------- | --------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| date | dayjs.ConfigType | dayjs().endOf('year') | This prop takes any date you might want to throw into dayjs()
. It only takes dates from the future |
| format | string | 'DD/MM/YYYY HH:mm:ss' | You can set the date's format using strings from dayjs |
| play | boolean | true | This prop lets you programatically decide when to initialise the countdown |
| showDefaults | boolean | true | If you use one of the RenderUnit props, a corresponding default will be overwritten. This turns the defaults off |
| goodbye | React.ReactElement | undefined | goodbye
renders the component you wish to show when the countdown is finished |
| render | RenderDoomsday | undefined | This prop returns DoomsdayCreator object. It basically is an inner wraper around plugin's logic that gives you access to all date calculations. It overwrites RenderUnits, so it's either this or the rest... |
| renderAll | boolean | false | ...unless this prop is set to true
, which will display component passed with render
as a last child (after) seconds
|
| years, months, days, hours, minutes, seconds | RenderUnit | undefined | returns a function that passes DoomsdayUnit object as its prop and takes a JSX component that gets rendered inside <Doomsday/>
's wrapper |
DoomsdayCreator
| prop | type | default | description |
| ----------------- | --------------- | --------------------- | ------------------------------------------------------------------------------------------------------------ |
| now | dayjs.Dayjs | dayjs() | now captured by dayjs |
| target | dayjs.Dayjs | dayjs(date
) | date
passed as a prop used as an argument for dayjs |
| nowTimestamp | number | now.valueOf() | timestamp of now
|
| targetTimestamp | number | target.valueOf() | timestamp of target
|
| diffTimestamp | number | target - now | timestamp of a difference between targetTimestamp
and nowTimestamp
|
| date | string | 'DD/MM/YYYY HH:mm:ss' | date in a given dayjs format |
| endOfTimeSequence | Units | - | returns an object with calculations per unit indicating logical sequence of time units until target
is met |
| endOfTimeFloat | Units | - | returns time left per unit after subtracting endOfTime
years |
| endOfTime | Units | - | returns units left until target |
| endOfYear | Units | - | returns units left until end of year, if it's short, it returns 0 |
| endOfMonth | Units | - | same story, different end |
| endOfDay | Units | - | you get the gist |
| endOfHour | Units | - | ... |
| endOfMinute | Units | - | ... |
Units
| prop | type | description | | ------- | ------ | ------------------------------------------- | | years | number | years it will take to reach the end of unit | | months | number | months until the end of unit | | days | number | ... | | hours | number | ... | | minutes | number | ... | | seconds | number | ... |
RenderUnit
(to: DoomsdayUnit) => React.ReactElement
RenderDoomsday
(doom: DoomsdayCreator) => React.ReactElement
DoomsdayUnit
This is DoomsdayCreator in (sort of) reverse. Depending on which RenderUnit you render in <Doomsday/> instead of returning the entire DoomsdayCreator, you get only endOfs for that specific unit.
| prop | type | description |
| ----------------- | ----------------------------------------- | -------------------------------------------------------- |
| type | UnitType | string indicating which unit is selected |
| label | (endOf: number, text?: string) => string; | slice(0, -1)
on UnitType or text
removing plural 's' |
| endOfTimeSequence | number | endOfTimeSequence
in selected UnitType |
| endOfTimeFloat | number | ... |
| endOfTime | number | ... |
| endOfYear | number | ... |
| endOfMonth | number | ... |
| endOfDay | number | ... |
| endOfHour | number | ... |
| endOfMinute | number | ... |
UnitType
"seconds" | "minutes" | "hours" | "days" | "months" | "years"
Stuff
If you feel the docs are missing something, or some stuff isn't clear, feel free to open an issue. I feel this plugin is simple enough to get by without unit tests. TS is here to keep an eye on things. As for the Code of Conduct, there is none. Just be humane to humans and non-humans alike.
License
MIT © MatulaDesign