Skip to content

Commit

Permalink
refactor: add helpers for duplications (#421)
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelass authored Dec 23, 2022
1 parent ba18147 commit 0e32293
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 60 deletions.
3 changes: 0 additions & 3 deletions src/__tests__/stickyroll.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,11 @@ describe("Stickyroll", () => {
cy.get(`[data-cy="stickyroll"]`).should("have.class", CLASS_NAMES.above);
cy.get(`[data-cy="stickyroll"]`).should("have.class", CLASS_NAMES.page(-1));
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.sticky);
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.scrolling);
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.below);
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.page(0));
cy.scrollTo(0, 201);
cy.wait(100);
cy.get(`[data-cy="stickyroll"]`).should("have.class", CLASS_NAMES.sticky);
cy.get(`[data-cy="stickyroll"]`).should("have.class", CLASS_NAMES.scrolling);
cy.get(`[data-cy="stickyroll"]`).should("have.class", CLASS_NAMES.page(0));
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.nonSticky);
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.above);
Expand All @@ -68,7 +66,6 @@ describe("Stickyroll", () => {
cy.get(`[data-cy="stickyroll"]`).should("have.class", CLASS_NAMES.below);
cy.get(`[data-cy="stickyroll"]`).should("have.class", CLASS_NAMES.page(0));
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.sticky);
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.scrolling);
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.above);
cy.get(`[data-cy="stickyroll"]`).should("not.have.class", CLASS_NAMES.page(-1));
});
Expand Down
1 change: 0 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export const CSS_VARS = {
export const CLASS_NAMES = {
root: "Stickyroll_root",
above: "Stickyroll_above",
scrolling: "Stickyroll_scrolling",
below: "Stickyroll_below",
sticky: "Stickyroll_sticky",
nonSticky: "Stickyroll_nonSticky",
Expand Down
118 changes: 62 additions & 56 deletions src/use-stickyroll.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
import type { RefObject } from "react";
import { useEffect, useRef } from "react";
import type { Except } from "type-fest";

import { CLASS_NAMES, CSS_VARS } from "./constants";
import type { UseStickyrollOptions } from "./types";

function removeClassNames<T extends HTMLElement>(
element: T,
classNames: (keyof Except<typeof CLASS_NAMES, "page">)[],
pages = 0
) {
element.classList.remove(
...classNames.map(className => CLASS_NAMES[className]),
...Array.from({ length: pages ? pages + 1 : 0 }, (_, index) => CLASS_NAMES.page(index - 1))
);
}

function addClassNames<T extends HTMLElement>(
element: T,
classNames: (keyof Except<typeof CLASS_NAMES, "page">)[],
page?: number
) {
element.classList.add(...classNames.map(className => CLASS_NAMES[className]));
if (page !== undefined) {
element.classList.add(CLASS_NAMES.page(page));
}
}

function setCSSVariables<T extends HTMLElement>(
element: T,
record: Partial<Record<keyof typeof CSS_VARS, string | number>>
) {
Object.entries(record).forEach(([key, value]) => {
element.style.setProperty(CSS_VARS[key], value.toString());
});
}

/**
*
* @param ref
Expand Down Expand Up @@ -38,20 +70,16 @@ export default function useStickyroll<T extends HTMLElement>(
let started = false;
let ended = false;
let page = -1;
ref.current.style.setProperty(
CSS_VARS.height,
`calc(${pages * factor + 1} * var(--100vh, 100vh))`
);
ref.current.style.setProperty(CSS_VARS.pages, pages.toString());
ref.current.style.setProperty(CSS_VARS.factor, factor.toString());
ref.current.style.setProperty(CSS_VARS.progress, "0");
ref.current.style.setProperty(CSS_VARS.page, "0");
ref.current.classList.add(
CLASS_NAMES.root,
CLASS_NAMES.above,
CLASS_NAMES.nonSticky,
CLASS_NAMES.page(-1)
);

setCSSVariables(ref.current, {
height: `calc(${pages * factor + 1} * var(--100vh, 100vh))`,
pages,
factor,
progress: 0,
page: -1,
});
addClassNames(ref.current, ["root"]);

function eventHandler() {
const { innerHeight } = window;
const end = innerHeight * (pages * factor) * -1;
Expand All @@ -69,20 +97,13 @@ export default function useStickyroll<T extends HTMLElement>(
// Approaching sticky box
if (top > 0 && !started) {
const time = Math.max(-1, (top / innerHeight) * -1);
ref.current.style.setProperty(CSS_VARS.progress, time.toString());
ref.current.style.setProperty(CSS_VARS.page, "-1");
ref.current.classList.remove(
CLASS_NAMES.sticky,
CLASS_NAMES.scrolling,
CLASS_NAMES.below,
CLASS_NAMES.page(-1),
...Array.from({ length: pages }, (_, index) => CLASS_NAMES.page(index))
);
ref.current.classList.add(
CLASS_NAMES.nonSticky,
CLASS_NAMES.above,
CLASS_NAMES.page(-1)
);

setCSSVariables(ref.current, {
progress: time,
page: -1,
});
removeClassNames(ref.current, ["sticky", "below"], pages);
addClassNames(ref.current, ["nonSticky", "above"], -1);
}

// During the sticky phase
Expand All @@ -97,20 +118,12 @@ export default function useStickyroll<T extends HTMLElement>(
started = true;
page = nextPageIndex;

ref.current.style.setProperty(CSS_VARS.progress, nextProgress.toString());
ref.current.style.setProperty(CSS_VARS.page, nextPageIndex.toString());
ref.current.classList.remove(
CLASS_NAMES.nonSticky,
CLASS_NAMES.above,
CLASS_NAMES.below,
CLASS_NAMES.page(-1),
...Array.from({ length: pages }, (_, index) => CLASS_NAMES.page(index))
);
ref.current.classList.add(
CLASS_NAMES.sticky,
CLASS_NAMES.scrolling,
CLASS_NAMES.page(nextPageIndex)
);
setCSSVariables(ref.current, {
progress: nextProgress,
page: nextPageIndex,
});
removeClassNames(ref.current, ["nonSticky", "above", "below"], pages);
addClassNames(ref.current, ["sticky"], nextPageIndex);

if (firstRun && handlers.current.onStart) {
handlers.current.onStart();
Expand All @@ -130,20 +143,13 @@ export default function useStickyroll<T extends HTMLElement>(
if (top < end && !ended) {
ended = true;
page = pages;
ref.current.style.setProperty(CSS_VARS.progress, "1");
ref.current.style.setProperty(CSS_VARS.page, (pages - 1).toString());
ref.current.classList.remove(
CLASS_NAMES.sticky,
CLASS_NAMES.scrolling,
CLASS_NAMES.above,
CLASS_NAMES.page(-1),
...Array.from({ length: pages }, (_, index) => CLASS_NAMES.page(index))
);
ref.current.classList.add(
CLASS_NAMES.nonSticky,
CLASS_NAMES.below,
CLASS_NAMES.page(pages - 1)
);

setCSSVariables(ref.current, {
progress: 1,
page: pages - 1,
});
removeClassNames(ref.current, ["sticky", "above"], pages);
addClassNames(ref.current, ["nonSticky", "below"], pages - 1);

if (handlers.current.onEnd) {
handlers.current.onEnd();
Expand Down

1 comment on commit 0e32293

@vercel
Copy link

@vercel vercel bot commented on 0e32293 Dec 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react-stickyroll – ./

react-stickyroll-pixelass.vercel.app
react-stickyroll-git-main-pixelass.vercel.app
react-stickyroll.vercel.app

Please sign in to comment.