Skip to content

Commit

Permalink
chore: move components to folders
Browse files Browse the repository at this point in the history
  • Loading branch information
jscottsmith committed Nov 28, 2021
1 parent 902c095 commit f662288
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 213 deletions.
15 changes: 15 additions & 0 deletions src/components/Parallax/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ParallaxController } from 'parallax-controller';
import { useEffect } from 'react';

export function useVerifyController(controller: ParallaxController) {
useEffect(() => {
// Make sure the provided controller is an instance of the Parallax Controller
const isInstance = controller instanceof ParallaxController;
// Throw if neither context or global is available
if (!controller && !isInstance) {
throw new Error(
"Must wrap your application's <Parallax /> components in a <ParallaxProvider />."
);
}
}, [controller]);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { PropsWithChildren } from 'react';
import { ParallaxController, ScrollAxis } from 'parallax-controller';
import { render } from '@testing-library/react';
import { Parallax } from './Parallax';
import { ParallaxProvider } from './ParallaxProvider';
import { Parallax } from '.';
import { ParallaxProvider } from '../ParallaxProvider';

import { MockProvider } from '../testUtils/MockProvider';
import expectRenderError from '../testUtils/expectRenderError';
import { MockProvider } from '../../testUtils/MockProvider';
import expectRenderError from '../../testUtils/expectRenderError';

const consoleLog = global.console.log;

Expand Down
112 changes: 112 additions & 0 deletions src/components/Parallax/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, { PropsWithChildren, useEffect, useRef, useState } from 'react';
import { CreateElementOptions, Element } from 'parallax-controller';
import { useController } from '../../hooks/useController';
import { removeUndefinedObjectKeys } from '../../utils/removeUndefinedObjectKeys';
import { ParallaxProps } from './types';
import { useVerifyController } from './hooks';

export function Parallax(props: PropsWithChildren<ParallaxProps>) {
const controller = useController();
const refInner = useRef<HTMLElement>();
const refOuter = useRef<HTMLElement>();

useVerifyController(controller);

function _getElementOptions(): CreateElementOptions {
const useSpeedProp = typeof props.speed !== 'undefined';
const isHorizontal = controller.scrollAxis == 'horizontal';
const isVertical = controller.scrollAxis == 'vertical';

let translateX = props.translateX;
let translateY = props.translateY;

if (useSpeedProp && isHorizontal) {
translateX = [
`${(props.speed || 0) * 10}px`,
`${(props.speed || 0) * -10}px`,
];
}

if (useSpeedProp && isVertical) {
translateY = [
`${(props.speed || 0) * 10}px`,
`${(props.speed || 0) * -10}px`,
];
}

return {
elInner: refInner.current,
elOuter: refOuter.current,
props: removeUndefinedObjectKeys({
disabled: props.disabled,
translateX,
translateY,
rotate: props.rotate,
rotateX: props.rotateX,
rotateY: props.rotateY,
rotateZ: props.rotateZ,
scale: props.scale,
scaleX: props.scaleX,
scaleY: props.scaleY,
scaleZ: props.scaleZ,
}),
};
}

const [element, setElement] = useState<Element>();

// create element
useEffect(() => {
const newElement = controller.createElement(_getElementOptions());
setElement(newElement);

return () => controller.removeElementById(newElement.id);
}, []);

// update element
useEffect(() => {
if (element) {
if (props.disabled) {
controller.resetElementStyles(element);
} else {
controller.updateElementPropsById(
element.id,
_getElementOptions().props
);
}
}
}, [
props.disabled,
props.translateX,
props.translateY,
props.rotate,
props.rotateX,
props.rotateY,
props.rotateZ,
props.scale,
props.scaleX,
props.scaleY,
props.scaleZ,
props.speed,
]);

const Outer = props.tagOuter;
const Inner = props.tagInner;

const rootClass =
'parallax-outer' + (props.className ? ` ${props.className}` : '');

return (
<Outer className={rootClass} ref={refOuter} style={props.styleOuter}>
<Inner className="parallax-inner" ref={refInner} style={props.styleInner}>
{props.children}
</Inner>
</Outer>
);
}

Parallax.defaultProps = {
disabled: false,
tagInner: 'div',
tagOuter: 'div',
};
128 changes: 0 additions & 128 deletions src/components/Parallax.tsx → src/components/Parallax/types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
import React, { PropsWithChildren, useEffect, useRef, useState } from 'react';
import {
CreateElementOptions,
ParallaxController,
Element,
} from 'parallax-controller';
import { useController } from '../hooks/useController';
import { removeUndefinedObjectKeys } from '../utils/removeUndefinedObjectKeys';

export interface ParallaxProps {
/**
* A number to slowdown `n < 0` or speed up `n > 0` the scroll speed of an element
Expand Down Expand Up @@ -154,122 +145,3 @@ export interface ParallaxProps {
*/
tagOuter?: any;
}

function useVerifyController(controller: ParallaxController) {
useEffect(() => {
// Make sure the provided controller is an instance of the Parallax Controller
const isInstance = controller instanceof ParallaxController;
// Throw if neither context or global is available
if (!controller && !isInstance) {
throw new Error(
"Must wrap your application's <Parallax /> components in a <ParallaxProvider />."
);
}
}, [controller]);
}

export function Parallax(props: PropsWithChildren<ParallaxProps>) {
const controller = useController();
const refInner = useRef<HTMLElement>();
const refOuter = useRef<HTMLElement>();

useVerifyController(controller);

function _getElementOptions(): CreateElementOptions {
const useSpeedProp = typeof props.speed !== 'undefined';
const isHorizontal = controller.scrollAxis == 'horizontal';
const isVertical = controller.scrollAxis == 'vertical';

let translateX = props.translateX;
let translateY = props.translateY;

if (useSpeedProp && isHorizontal) {
translateX = [
`${(props.speed || 0) * 10}px`,
`${(props.speed || 0) * -10}px`,
];
}

if (useSpeedProp && isVertical) {
translateY = [
`${(props.speed || 0) * 10}px`,
`${(props.speed || 0) * -10}px`,
];
}

return {
elInner: refInner.current,
elOuter: refOuter.current,
props: removeUndefinedObjectKeys({
disabled: props.disabled,
translateX,
translateY,
rotate: props.rotate,
rotateX: props.rotateX,
rotateY: props.rotateY,
rotateZ: props.rotateZ,
scale: props.scale,
scaleX: props.scaleX,
scaleY: props.scaleY,
scaleZ: props.scaleZ,
}),
};
}

const [element, setElement] = useState<Element>();

// create element
useEffect(() => {
const newElement = controller.createElement(_getElementOptions());
setElement(newElement);

return () => controller.removeElementById(newElement.id);
}, []);

// update element
useEffect(() => {
if (element) {
if (props.disabled) {
controller.resetElementStyles(element);
} else {
controller.updateElementPropsById(
element.id,
_getElementOptions().props
);
}
}
}, [
props.disabled,
props.translateX,
props.translateY,
props.rotate,
props.rotateX,
props.rotateY,
props.rotateZ,
props.scale,
props.scaleX,
props.scaleY,
props.scaleZ,
props.speed,
]);

const Outer = props.tagOuter;
const Inner = props.tagInner;

const rootClass =
'parallax-outer' + (props.className ? ` ${props.className}` : '');

return (
<Outer className={rootClass} ref={refOuter} style={props.styleOuter}>
<Inner className="parallax-inner" ref={refInner} style={props.styleInner}>
{props.children}
</Inner>
</Outer>
);
}

Parallax.defaultProps = {
disabled: false,
tagInner: 'div',
tagOuter: 'div',
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from 'react';
import ReactDOM from 'react-dom';
// @ts-ignore
import renderer from 'react-test-renderer';
import createNodeMock from '../testUtils/createNodeMock';
import { ParallaxBanner } from './ParallaxBanner';
import { ParallaxProvider } from './ParallaxProvider';
import createNodeMock from '../../testUtils/createNodeMock';
import { ParallaxBanner } from '.';
import { ParallaxProvider } from '../ParallaxProvider';

describe('Expect the <ParallaxBanner> component', () => {
afterEach(() => {});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { PropsWithChildren } from 'react';
import { Parallax } from './Parallax';
import { Parallax } from '../Parallax';
import { ParallaxBannerProps } from './types';

const containerStyle = {
position: 'relative',
Expand All @@ -16,50 +17,6 @@ const absoluteStyle = {
left: 0,
};

export interface BannerLayer {
/**
* A value from `-1` to `1` that represents the vertical offset to be applied to the current
* layer, `0.1` would equal a `10%` offset on the top and bottom.
*/
amount: number;
/**
* Custom layer children provided as a React element, for example `<Video />`
*/
children?: any;
/**
* Indicate if the layer should be expanded with negative top/bottom margins so the edges will
* never be visible.
*/
expanded?: boolean;
/**
* Image source that will be applied as a CSS background image on the layer.
*/
image?: string;
/*
* Props to apply to the layer element.
*/
props?: any;
}

export interface ParallaxBannerProps {
/**
* Optionally pass additional class names to be added to the outermost parallax banner element.
*/
className?: string;
/**
* Determines if the internal parallax layers will have offsets applied.
*/
disabled?: boolean;
/**
* A required Array of Objects with layer properties: `[{ amount: 0.1, image: 'foo.jpg' }]`.
*/
layers: BannerLayer[];
/**
* Optionally pass a style object to be added to the outermost parallax banner element.
*/
style?: any;
}

export const ParallaxBanner = ({
children,
className,
Expand Down
43 changes: 43 additions & 0 deletions src/components/ParallaxBanner/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export interface BannerLayer {
/**
* A value from `-1` to `1` that represents the vertical offset to be applied to the current
* layer, `0.1` would equal a `10%` offset on the top and bottom.
*/
amount: number;
/**
* Custom layer children provided as a React element, for example `<Video />`
*/
children?: any;
/**
* Indicate if the layer should be expanded with negative top/bottom margins so the edges will
* never be visible.
*/
expanded?: boolean;
/**
* Image source that will be applied as a CSS background image on the layer.
*/
image?: string;
/*
* Props to apply to the layer element.
*/
props?: any;
}

export interface ParallaxBannerProps {
/**
* Optionally pass additional class names to be added to the outermost parallax banner element.
*/
className?: string;
/**
* Determines if the internal parallax layers will have offsets applied.
*/
disabled?: boolean;
/**
* A required Array of Objects with layer properties: `[{ amount: 0.1, image: 'foo.jpg' }]`.
*/
layers: BannerLayer[];
/**
* Optionally pass a style object to be added to the outermost parallax banner element.
*/
style?: any;
}
Loading

0 comments on commit f662288

Please sign in to comment.