1.1.5 • Published 3 years ago

@lumberyard/react-doomsday v1.1.5

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

react-doomsday

npm bundle size NPM npm

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

\ is a \ 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 \'s native props, so whatever \ takes, so does \

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.

proptypedescription
doomsdayDoomsdayCreatorobject containing default doomsday's calculations
isHerebooleanflag 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

proptypedefaultdescription
datedayjs.ConfigTypedayjs().endOf('year')This prop takes any date you might want to throw into dayjs(). It only takes dates from the future
formatstring'DD/MM/YYYY HH:mm:ss'You can set the date's format using strings from dayjs
playbooleantrueThis prop lets you programatically decide when to initialise the countdown
showDefaultsbooleantrueIf you use one of the RenderUnit props, a corresponding default will be overwritten. This turns the defaults off
goodbyeReact.ReactElementundefinedgoodbye renders the component you wish to show when the countdown is finished
renderRenderDoomsdayundefinedThis 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...
renderAllbooleanfalse...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, secondsRenderUnitundefinedreturns a function that passes DoomsdayUnit object as its prop and takes a JSX component that gets rendered inside <Doomsday/>'s wrapper

DoomsdayCreator

proptypedefaultdescription
nowdayjs.Dayjsdayjs()now captured by dayjs
targetdayjs.Dayjsdayjs(date)date passed as a prop used as an argument for dayjs
nowTimestampnumbernow.valueOf()timestamp of now
targetTimestampnumbertarget.valueOf()timestamp of target
diffTimestampnumbertarget - nowtimestamp of a difference between targetTimestamp and nowTimestamp
datestring'DD/MM/YYYY HH:mm:ss'date in a given dayjs format
endOfTimeSequenceUnits-returns an object with calculations per unit indicating logical sequence of time units until target is met
endOfTimeFloatUnits-returns time left per unit after subtracting endOfTime years
endOfTimeUnits-returns units left until target
endOfYearUnits-returns units left until end of year, if it's short, it returns 0
endOfMonthUnits-same story, different end
endOfDayUnits-you get the gist
endOfHourUnits-...
endOfMinuteUnits-...

Units

proptypedescription
yearsnumberyears it will take to reach the end of unit
monthsnumbermonths until the end of unit
daysnumber...
hoursnumber...
minutesnumber...
secondsnumber...

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 \ instead of returning the entire DoomsdayCreator, you get only endOfs for that specific unit.

proptypedescription
typeUnitTypestring indicating which unit is selected
label(endOf: number, text?: string) => string;slice(0, -1) on UnitType or text removing plural 's'
endOfTimeSequencenumberendOfTimeSequence in selected UnitType
endOfTimeFloatnumber...
endOfTimenumber...
endOfYearnumber...
endOfMonthnumber...
endOfDaynumber...
endOfHournumber...
endOfMinutenumber...

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

1.1.1

3 years ago

1.1.0

3 years ago

1.1.5

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

0.9.0

3 years ago