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 🙏

© 2026 – Pkg Stats / Ryan Hefner

ecloud-spark

v1.1.2

Published

The spark that will light your projects

Readme

Spark

Introduction

Spark is our React component library.

Installation

Run npm i ecloud-spark

Folder Structure

  • /src: @ecloudHub/spark's raw code.

Spark in use

Components

Most of the components work with ScrollTrigger from GSAP so check their docs for detailed info.

Menu

interface Menu {
  // Element to toggle the menu state
  button?: React.ReactElement;
  // Menu content
  children: ReactNode;
  // Menu will be visible or hidden based on isOpen value. Default: false.
  isOpen?: boolean;
  // To show or hide the overlay. Default: false.
  withOverlay?: boolean;
  // To close menu on overlay click. Default: true.
  closeOnOverlayClick?: boolean;
  // For customization purposes you can pass classes to the menu container. Default: ''.
  menuClass?: string;
  // For customization purposes you can pass classes to the body. Default: ''.
  bodyClass?: string;
  // For customization purposes you can pass classes to the overlay. Default: ''.
  overlayClass?: string;
  // Menu alignment. Default: 'left'.
  alignment?: "left" | "right";
  // The function the overlay will execute on click
  onClose: Dispatch<SetStateAction<boolean>>;
}

Button

Just a default button

type Button = {
  children?: React.ReactNode;
  className?: string;
  // Choose between button and a element. Default: button.
  as?:
    | (JSX.IntrinsicElements["a"] & { as?: "a" })
    | (JSX.IntrinsicElements["button"] & { as: "button" });
};

Magnetic Button

When the cursor is near the button this one will follow it a little.

type MagneticButton = {
  children?: React.ReactNode;
  className?: string;
  // Choose between button and a elements.
  as?:
    | (JSX.IntrinsicElements["a"] & { as?: "a" })
    | (JSX.IntrinsicElements["button"] & { as: "button" });
  // If you want to use another button. Otherwise it will use the Button component.
  button?: React.ReactElement;
  // To determine how much it will move. Default: 0.5.
  movement?: number;
};

Elastic Button

A button with an "elastic" movement on hover.

type ElasticButton = {
  children?: React.ReactNode;
  className?: string;
  // Choose between button and a elements.
  as?:
    | (JSX.IntrinsicElements["a"] & { as?: "a" })
    | (JSX.IntrinsicElements["button"] & { as: "button" });
  // If you want to use another button. Otherwise it will use the Button component look & feel.
  button?: React.ReactElement;
  // Custom html. Default: <div class="spark-elastic__icon"></div>.
  icon?: React.ReactElement;
};

Ribbons

Two ribbons sliding non-stop.

interface Ribbons {
  // The children rendered inside each ribbon
  children: ReactNode | ReactNode[];
  // The direction the ribbon at the top slides. Default: right.
  topDirection?: RibbonDir;
  // The direction the ribbon at the bottom slides. Default: left.
  bottomDirection?: RibbonDir;
  // Ribbon speed calculated as pixels/second. Default: 50.
  speed?: number;
  // Whether to pause the ribbon when hovered
  pauseOnHover?: boolean;
  // Container class for customization purposes
  containerClass?: string;
  // Each ribbon class for customization purposes
  ribbonClass?: string;
}

Text Reader

Display text gradually as user scroll.

interface TextReader {
  // The text you want to display gradually.
  text: string;
  // The color of the text
  textColor?: string;
  // The color of the text before being read
  textColorIdle?: string;
  // Pin section. Default: true.
  pin?: boolean;
  // The element that will be pinned.
  pinRef: RefObject<HTMLDivElement>;
  // String | Number | Function - Determines the starting position of the ScrollTrigger. Default: "top 30%".
  start?: string | number | StartEndFunc;
  // String | Number | Function - Determines the ending position of the ScrollTrigger. Default: "bottom top".
  end?: string | number | StartEndFunc;
  // If true it will animate on both desktop and mobile otherwise it will animate only on desktop. Default: true.
  responsive?: boolean;
  // Change the animation style. If true the component will not be pinned. Default: true.
  withMask?: boolean;
  // A callback for when the progress has completed.
  onComplete?: Dispatch<SetStateAction<boolean>>;
}

Text Reveal

Display text with a fancy animation when it's inside the current viewport.

interface TextReveal {
  // Headings, paragraph tags or just text
  children: ReactNode;
  // The duration of the animation in seconds. Default: 3.
  duration?: number | string;
  // String | Number | Function - Determines the starting position of the ScrollTrigger. Default: "top 90%".
  start?: string | number | StartEndFunc;
  // Boolean | Number - Links the progress of the animation directly to the scrollbar so it acts like a scrubber. Default: false.
  scrub?: boolean | number;
  // String - Determines how the linked animation is controlled at the 4 distinct toggle places - onEnter, onLeave, onEnterBack, onLeaveBack, in that order. Default: "play none none none".
  toggleActions?: string;
  // Amount of delay in seconds before the animation should begin. Default: 0;
  delay?: number;
}

HPin

Pin a section and move content horizontally.

interface HPin {
  // Each child element will be put in row.
  children: React.ReactNode;
  // To choose which element will be pinned. Default: the component itself.
  triggerRef?: RefObject<HTMLDivElement>;
  // String | Number | Function - Determines the starting position of the ScrollTrigger.
  start?: string | number | StartEndFunc;
  // String | Number | Function - Determines the ending position of the ScrollTrigger. Default: "bottom top".
  end?: string | number | StartEndFunc;
  // Pin section. Default: true.
  pin?: boolean;
  // Boolean | Number - Links the progress of the animation directly to the scrollbar so it acts like a scrubber.
  scrub?: boolean | number;
  // Spacing between each child element.
  spacing?: string;
  // The space at each side of the component. Will be used to calculate padding and margin on mobile.
  sideSpacing?: string;
  // Starting position of the first element.
  startPos?: string | number;
  // The space left between the last element and the end of the viewport horizontally.
  endPos?: number;
}

VPin

Pin a section and move content vertically.

interface VPin {
  // this will be the content at the left such as a title with a text.
  children: React.ReactNode;
  // Each item will be put vertically in a column.
  items: React.ReactElement;
  // The space between each item. Default: "1rem".
  itemsSpacing?: string;
  // The minimum space between the children elements and the items. Default: "2rem".
  contentGap?: string;
  // The space between the pinned content and the top of the viewport. Default: 6.25rem;
  topGap?: string;
}

VOverlap

Overlap images while scrolling through blocks of content

interface VOverlap {
  // Array of images to be displayed on the side. Each position must have a object with at least an "url" property.
  images: Img[];
  // An array with each element to be displayed on the right.
  content: React.ReactElement[];
  // You can change images wrapper styles using the class "spark-voverlap-img-wrapper" or another one by changing this option.
  imagesWrapperClass?: string;
  // In order to hide content images on mobile and show them on desktop you can do it by adding the "voverlap-content-img" class to each image or whatever you want changing this option
  contentImgClass?: string;
  // String | Number | Function - Determines the starting position of the ScrollTrigger. Default: "top 70%".
  start?: string | number | StartEndFunc;
  // Space between each item: the first position is for desktop the other one for mobile.
  gap?: [number, number];
}

Hooks

This library also expose some useful hooks:

useIsomorphicLayoutEffect

A helper hook for scheduling a layout effect with a fallback to a regular effect for environments where layout effects should not be used.

useIsomorphicLayoutEffect(() => {}, []);

useWindowSize

It returns window width and height. The values are updated on window change and resize events.

const { windowWidth, windowHeight } = useWindowSize();

useMediQuery

A React hook that detects whether a media query is true or false.

const isDesktop = useMediaQuery(`(min-width: 992px)`);

Authors

This toolkit is curated and maintained by the ecloud team: