npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@theuiteam/continuous-container

v2.0.1

Published

State container with the known past, present, and the future

Downloads

5,793

Readme

Idea

This is almost react transition group, but for state management...

Why people react transition group? Because it 1) takes a pause between steps letting classNames be applied and 2) keeps children after you remove them, to perform a fade animation.

We are doing the same, but using state.

It's all about tracking what the value would be, what is right now, and what it was. We call this ContinuousState

ContinuousState

  • future - the next value. The value you just set.
  • present - to be synchronized with the future "later"
  • past - to be synchronized with the present "later"

and

  • defined - an indication that any of future, past or present are truthy.

API

useContinuousState(value, options)

  • value - a value to assign to the future
  • options
    • delayPresent - time in ms between future becoming present
    • delayPast - time in ms between present becoming past. For transitions, it usually equals to exist animation duration
    • initialValue - a value to be set as initial to the past and present. future is always equal to the value given as a first arg

useScatteredContinuousState(value, options)

Call signature is equal to useContinuousState, returns an object with extra property DefinePresent. See example below.

Usage

Problem statement

Let's imagine you have a switch. Which controls visibility of something, but you also want to add some animation.

Let's handle these cases separately:

const App = () => {
    const [on, setOn] = useState(false);

    return (
        <div>
            <button onClick={() => setOn(on => !on)}>Toggle</button>
            // would be instanly hidden and shown
            {on && <Content/>}
            // would be animated, but would be ALWAYS rendered
            <ContentWithAnimation visible={on}/>}
        </div>
    );
};

Now let's imagine you want to not render Content when it's not visible and not required.

Ok, "when is this when"?

  • render ContentWithAnimation when it is about to be displayed
  • render ContentWithAnimation when it is displayed
  • render ContentWithAnimation when it is no longer visible, but still animating toward hidden state
import { ContinuousContainer, useContinuousState } from '@theuiteam/continuous-container';

const App = () => {
  const [on, setOn] = useState(false);
  const continuousState = useContinuousState(on);

  return (
    <div>
      <button onClick={() => setOn((on) => !on)}>Toggle</button>
      {/*render if any of past/preset/future is set to true*/}
      {continuousState.defined && (
        <ContentWithAnimation visible={continuousState.present} />
        // wire the "present" state
      )}
      {/* or */}
      <ContinuousContainer value={on} timeout={300}>
        {
          (past, present, future) => (past || present || future) && <ContentWithAnimation visible={present} />
          // ^^ use the "present" value
        }
      </ContinuousContainer>
    </div>
  );
};

Scattered

There are more sophisticated situations, when setting up something to display does not mean "display". Lazy loading is a good case

const App = () => {
  const continuousState = useContinuousState(on);
  return continuousState.defined && <LazyLoadedContentWithAnimation visible={continuousState.present} />;
};

In such case ContinuousState will update from future to present before LazyLoadedContentWithAnimation component is loaded, breaking a connection between states.

In order to handle this problem one might need to tap into rendering process using useScatteredContinuousState

const continuousState = useScatteredContinuousState(on);
return (
  continuousState.defined && (
    <Suspense>
      <LazyLoadedContentWithAnimation visible={continuousState.present}>
        <continuousState.DefinePresent />
        {/*this component will advance ContinuousState once rendered*/}
      </LazyLoadedContentWithAnimation>
    </Suspense>
  )
);

For readability purposes we recommend putting DefinePresent to a separate slot different from children.

<LazyLoadedContentWithAnimation visible={continuousState.present} effector={<continuousState.DefinePresent />} />
⚠️⚠️⚠️⚠️⚠️⚠️⚠️

The following code will NOT work as DefinePresent will be rendered instantly, even if suspense will be in fallback

<Suspense>
  // will not be rendred until ready
  <LazyLoadedContentWithAnimation visible={continuousState.present} />
  // will be rendered too early
  <continuousState.DefinePresent />
</Suspense>

See also

  • Phased Container from a recondition library

License

MIT