diff --git a/showcase/src/constants/displayBoxNotes.js b/showcase/src/constants/displayBoxNotes.js index 6553856..61c4eb1 100644 --- a/showcase/src/constants/displayBoxNotes.js +++ b/showcase/src/constants/displayBoxNotes.js @@ -1,4 +1 @@ -export const NOTES = { - '1': 'Animated via an HOC', - '2': 'Animated via a hook 💪' -} +export const NOTES = {} diff --git a/showcase/src/patterns/01.js b/showcase/src/patterns/01.js index a4a5ae5..8ce2b8d 100644 --- a/showcase/src/patterns/01.js +++ b/showcase/src/patterns/01.js @@ -1,20 +1,31 @@ import React, { Component, useState } from 'react' import mojs from 'mo-js' -import { generateRandomNumber } from '../utils/generateRandomNumber' import styles from './index.css' -/** ==================================== - * 🔰HOC -Higher Order Component for Animation -==================================== **/ +const initialState = { + count: 0, + countTotal: 267, + isClicked: false +} + +/** + * Higher Order Component + */ const withClapAnimation = WrappedComponent => { class WithClapAnimation extends Component { + animationTimeline = new mojs.Timeline() state = { - animationTimeline: new mojs.Timeline() + animationTimeline: this.animationTimeline } componentDidMount () { const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: '#clap', + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out + }) const triangleBurst = new mojs.Burst({ parent: '#clap', @@ -24,8 +35,7 @@ const withClapAnimation = WrappedComponent => { children: { shape: 'polygon', radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', + stroke: 'rgba(211,54,0,0.5)', strokeWidth: 2, angle: 210, delay: 30, @@ -42,7 +52,7 @@ const withClapAnimation = WrappedComponent => { duration: tlDuration, children: { shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', + fill: 'rgba(149,165,166,0.5)', delay: 30, speed: 0.2, radius: { 3: 0 }, @@ -52,10 +62,8 @@ const withClapAnimation = WrappedComponent => { const countAnimation = new mojs.Html({ el: '#clapCount', - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, opacity: { 0: 1 }, + y: { 0: -30 }, duration: tlDuration }).then({ opacity: { 1: 0 }, @@ -65,76 +73,52 @@ const withClapAnimation = WrappedComponent => { const countTotalAnimation = new mojs.Html({ el: '#clapCountTotal', - isShowStart: false, - isShowEnd: true, opacity: { 0: 1 }, delay: (3 * tlDuration) / 2, duration: tlDuration, y: { 0: -3 } }) - const scaleButton = new mojs.Html({ - el: '#clap', - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) - const clap = document.getElementById('clap') - clap.style.transform = 'scale(1, 1)' - this.state.animationTimeline.add([ - countAnimation, - countTotalAnimation, + clap.style.transform = 'scale(1,1)' + + const newAnimationTimeline = this.animationTimeline.add([ scaleButton, - circleBurst, - triangleBurst + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst ]) + this.setState({ animationTimeline: newAnimationTimeline }) } render () { return ( ) } } - - WithClapAnimation.displayName = `WithClapAnimation(${getDisplayName( - WrappedComponent - )})` - return WithClapAnimation } -function getDisplayName (WrappedComponent) { - return WrappedComponent.displayName || WrappedComponent.name || 'Component' -} - -/** ==================================== - * 🔰 MediumClap -==================================== **/ -const initialState = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false -} - const MediumClap = ({ animationTimeline }) => { const MAXIMUM_USER_CLAP = 50 const [clapState, setClapState] = useState(initialState) const { count, countTotal, isClicked } = clapState const handleClapClick = () => { - // 👉 prop from HOC animationTimeline.replay() - - setClapState({ + setClapState(prevState => ({ + isClicked: true, count: Math.min(count + 1, MAXIMUM_USER_CLAP), - countTotal: count < MAXIMUM_USER_CLAP ? countTotal + 1 : countTotal, - isClicked: true - }) + countTotal: + count < MAXIMUM_USER_CLAP + ? prevState.countTotal + 1 + : prevState.countTotal + })) } return ( @@ -146,16 +130,14 @@ const MediumClap = ({ animationTimeline }) => { ) } -/** ==================================== - * 🔰SubComponents -Smaller Component used by -==================================== **/ +/** + * subcomponents + */ const ClapIcon = ({ isClicked }) => { return ( { const ClapCount = ({ count }) => { return ( - +{count} + + {count} ) } + const CountTotal = ({ countTotal }) => { return ( @@ -181,11 +164,9 @@ const CountTotal = ({ countTotal }) => { ) } -/** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API -==================================== **/ +/** + * Usage + */ const Usage = () => { const AnimatedMediumClap = withClapAnimation(MediumClap) diff --git a/showcase/src/patterns/02.js b/showcase/src/patterns/02.js index fb18d7d..d3056cc 100644 --- a/showcase/src/patterns/02.js +++ b/showcase/src/patterns/02.js @@ -1,137 +1,107 @@ -import React, { - useState, - useCallback, - useLayoutEffect, - useContext, - useMemo, - createContext -} from 'react' - +import React, { useState, useLayoutEffect, useCallback } from 'react' import mojs from 'mo-js' -import { generateRandomNumber } from '../utils/generateRandomNumber' import styles from './index.css' -/** ==================================== - * 🔰Hook - Hook for Animation - ==================================== **/ - -const useClapAnimation = ({ - duration: tlDuration, - bounceEl, - fadeEl, - burstEl -}) => { +const initialState = { + count: 0, + countTotal: 267, + isClicked: false +} + +/** + * Custom Hook for animation + */ +const useClapAnimation = ({ clapEl, countEl, clapTotalEl }) => { const [animationTimeline, setAnimationTimeline] = useState( - new mojs.Timeline() + () => new mojs.Timeline() ) - useLayoutEffect( - () => { - if (!bounceEl || !fadeEl || !burstEl) { - return - } + useLayoutEffect(() => { + if (!clapEl || !countEl || !clapTotalEl) { + return + } - const triangleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 95 }, - count: 5, - angle: 30, - children: { - shape: 'polygon', - radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', - strokeWidth: 2, - angle: 210, - delay: 30, - speed: 0.2, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1), - duration: tlDuration - } - }) - - const circleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 75 }, - angle: 25, - duration: tlDuration, - children: { - shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', - delay: 30, - speed: 0.2, - radius: { 3: 0 }, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1) - } - }) - - const countAnimation = new mojs.Html({ - el: bounceEl, - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, - opacity: { 0: 1 }, + const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: clapEl, + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out + }) + + const triangleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 95 }, + count: 5, + angle: 30, + children: { + shape: 'polygon', + radius: { 6: 0 }, + stroke: 'rgba(211,54,0,0.5)', + strokeWidth: 2, + angle: 210, + delay: 30, + speed: 0.2, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1), duration: tlDuration - }).then({ - opacity: { 1: 0 }, - y: -80, - delay: tlDuration / 2 - }) - - const countTotalAnimation = new mojs.Html({ - el: fadeEl, - isShowStart: false, - isShowEnd: true, - opacity: { 0: 1 }, - delay: (3 * tlDuration) / 2, - duration: tlDuration, - y: { 0: -3 } - }) - - const scaleButton = new mojs.Html({ - el: burstEl, - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) - - if (typeof burstEl === 'string') { - clap.style.transform = 'scale(1, 1)' - const el = document.getElementById(id) - el.style.transform = 'scale(1, 1)' - } else { - burstEl.style.transform = 'scale(1, 1)' } + }) - const updatedAnimationTimeline = animationTimeline.add([ - countAnimation, - countTotalAnimation, - scaleButton, - circleBurst, - triangleBurst - ]) - - setAnimationTimeline(updatedAnimationTimeline) - }, - [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl] - ) + const circleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 75 }, + angle: 25, + duration: tlDuration, + children: { + shape: 'circle', + fill: 'rgba(149,165,166,0.5)', + delay: 30, + speed: 0.2, + radius: { 3: 0 }, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1) + } + }) + + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) + + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) + + if (typeof clapEl === 'string') { + const clap = document.getElementById('clap') + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' + } + + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) return animationTimeline } -/** ==================================== - * 🔰 MediumClap - ==================================== **/ -const initialState = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false -} -const MediumClapContext = createContext() -const { Provider } = MediumClapContext - -const MediumClap = ({ children }) => { +const MediumClap = () => { const MAXIMUM_USER_CLAP = 50 const [clapState, setClapState] = useState(initialState) const { count, countTotal, isClicked } = clapState @@ -139,68 +109,52 @@ const MediumClap = ({ children }) => { const [{ clapRef, clapCountRef, clapTotalRef }, setRefState] = useState({}) const setRef = useCallback(node => { - if (node !== null) { - setRefState(prevRefState => ({ - ...prevRefState, - [node.dataset.refkey]: node - })) - } + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) }, []) const animationTimeline = useClapAnimation({ - duration: 300, - bounceEl: clapCountRef, - fadeEl: clapTotalRef, - burstEl: clapRef + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef }) const handleClapClick = () => { animationTimeline.replay() - - setClapState({ + setClapState(prevState => ({ + isClicked: true, count: Math.min(count + 1, MAXIMUM_USER_CLAP), - countTotal: count < MAXIMUM_USER_CLAP ? countTotal + 1 : countTotal, - isClicked: true - }) + countTotal: + count < MAXIMUM_USER_CLAP + ? prevState.countTotal + 1 + : prevState.countTotal + })) } - const memoizedValue = useMemo( - () => ({ - count, - countTotal, - isClicked, - setRef - }), - [count, countTotal, isClicked, setRef] - ) - return ( - - - + ) } -/** ==================================== - * 🔰SubComponents - Smaller Component used by - ==================================== **/ +/** + * subcomponents + */ -const ClapIcon = () => { - const { isClicked } = useContext(MediumClapContext) +const ClapIcon = ({ isClicked }) => { return ( { ) } -const ClapCount = () => { - const { count, setRef } = useContext(MediumClapContext) +const ClapCount = ({ count, setRef }) => { return ( - +{count} + + {count} ) } -const CountTotal = () => { - const { countTotal, setRef } = useContext(MediumClapContext) + +const CountTotal = ({ countTotal, setRef }) => { return ( {countTotal} @@ -228,11 +181,9 @@ const CountTotal = () => { ) } -/** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API - ==================================== **/ +/** + * Usage + */ const Usage = () => { return diff --git a/showcase/src/patterns/03.js b/showcase/src/patterns/03.js index 2809f8f..73e6d0e 100644 --- a/showcase/src/patterns/03.js +++ b/showcase/src/patterns/03.js @@ -1,119 +1,114 @@ import React, { useState, - useEffect, - useContext, + useLayoutEffect, + useCallback, + createContext, useMemo, - useRef, - createContext + useContext, + useEffect, + useRef } from 'react' - import mojs from 'mo-js' -import wordConverter from 'number-to-words' -import { generateRandomNumber } from '../utils/generateRandomNumber' import styles from './index.css' -/** ==================================== - * 🔰Hook - Hook for Animation -==================================== **/ +const initialState = { + count: 0, + countTotal: 267, + isClicked: false +} -const useClapAnimation = ({ duration: tlDuration }) => { +/** + * Custom Hook for animation + */ +const useClapAnimation = ({ clapEl, countEl, clapTotalEl }) => { const [animationTimeline, setAnimationTimeline] = useState( - new mojs.Timeline() + () => new mojs.Timeline() ) - useEffect( - () => { - const triangleBurst = new mojs.Burst({ - parent: '#clap', - radius: { 50: 95 }, - count: 5, - angle: 30, - children: { - shape: 'polygon', - radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', - strokeWidth: 2, - angle: 210, - delay: 30, - speed: 0.2, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1), - duration: tlDuration - } - }) - - const circleBurst = new mojs.Burst({ - parent: '#clap', - radius: { 50: 75 }, - angle: 25, - duration: tlDuration, - children: { - shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', - delay: 30, - speed: 0.2, - radius: { 3: 0 }, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1) - } - }) - - const countAnimation = new mojs.Html({ - el: '#clapCount', - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, - opacity: { 0: 1 }, + useLayoutEffect(() => { + if (!clapEl || !countEl || !clapTotalEl) { + return + } + + const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: clapEl, + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out + }) + + const triangleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 95 }, + count: 5, + angle: 30, + children: { + shape: 'polygon', + radius: { 6: 0 }, + stroke: 'rgba(211,54,0,0.5)', + strokeWidth: 2, + angle: 210, + delay: 30, + speed: 0.2, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1), duration: tlDuration - }).then({ - opacity: { 1: 0 }, - y: -80, - delay: tlDuration / 2 - }) - - const countTotalAnimation = new mojs.Html({ - el: '#clapCountTotal', - isShowStart: false, - isShowEnd: true, - opacity: { 0: 1 }, - delay: (3 * tlDuration) / 2, - duration: tlDuration, - y: { 0: -3 } - }) - - const scaleButton = new mojs.Html({ - el: '#clap', - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) + } + }) + + const circleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 75 }, + angle: 25, + duration: tlDuration, + children: { + shape: 'circle', + fill: 'rgba(149,165,166,0.5)', + delay: 30, + speed: 0.2, + radius: { 3: 0 }, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1) + } + }) + + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) + + if (typeof clapEl === 'string') { const clap = document.getElementById('clap') - clap.style.transform = 'scale(1, 1)' - - const updatedAnimationTimeline = animationTimeline.add([ - countAnimation, - countTotalAnimation, - scaleButton, - circleBurst, - triangleBurst - ]) - - setAnimationTimeline(updatedAnimationTimeline) - }, - [tlDuration, animationTimeline] - ) + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' + } + + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) return animationTimeline } -/** ==================================== - * 🔰 MediumClap -==================================== **/ -const initialState = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false -} const MediumClapContext = createContext() const { Provider } = MediumClapContext @@ -121,61 +116,75 @@ const { Provider } = MediumClapContext const MediumClap = ({ children, onClap }) => { const MAXIMUM_USER_CLAP = 50 const [clapState, setClapState] = useState(initialState) - const { count, countTotal, isClicked } = clapState + const { count } = clapState - const animationTimeline = useClapAnimation({ duration: 300 }) - const handleClapClick = () => { - // 👉 prop from HOC - animationTimeline.replay() + const [{ clapRef, clapCountRef, clapTotalRef }, setRefState] = useState({}) - setClapState({ - count: Math.min(count + 1, MAXIMUM_USER_CLAP), - countTotal: count < MAXIMUM_USER_CLAP ? countTotal + 1 : countTotal, - isClicked: true - }) - } + const setRef = useCallback(node => { + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) + }, []) + + const animationTimeline = useClapAnimation({ + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef + }) const componentJustMounted = useRef(true) + useEffect(() => { + if (!componentJustMounted.current) { + console.log('onClap was called!!!') + onClap && onClap(clapState) + } + componentJustMounted.current = false + }, [count]) - useEffect( - () => { - if (!componentJustMounted.current) { - onClap(clapState) - } - componentJustMounted.current = false - }, - [count, onClap] - ) + const handleClapClick = () => { + animationTimeline.replay() + setClapState(prevState => ({ + isClicked: true, + count: Math.min(count + 1, MAXIMUM_USER_CLAP), + countTotal: + count < MAXIMUM_USER_CLAP + ? prevState.countTotal + 1 + : prevState.countTotal + })) + } const memoizedValue = useMemo( () => ({ - count, - countTotal, - isClicked + ...clapState, + setRef }), - [count, countTotal, isClicked] + [clapState, setRef] ) return ( - ) } -/** ==================================== - * 🔰SubComponents -Smaller Component used by -==================================== **/ +/** + * subcomponents + */ const ClapIcon = () => { const { isClicked } = useContext(MediumClapContext) return ( { ) } const ClapCount = () => { - const { count } = useContext(MediumClapContext) + const { count, setRef } = useContext(MediumClapContext) return ( - - +{count} + + + {count} ) } + const CountTotal = () => { - const { countTotal } = useContext(MediumClapContext) + const { countTotal, setRef } = useContext(MediumClapContext) return ( - + {countTotal} ) } -const ClapInfo = ({ info }) => { - const { countTotal } = useContext(MediumClapContext) - return ( -
- {info || wordConverter.toWords(countTotal)} claps! -
- ) -} - MediumClap.Icon = ClapIcon MediumClap.Count = ClapCount MediumClap.Total = CountTotal -MediumClap.Info = ClapInfo - -/** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API -==================================== **/ +/** + * Usage + */ +// import MediumClap from 'medium-clap' const Usage = () => { - const [total, setTotal] = useState(0) - - const onClap = ({ countTotal }) => { - setTotal(countTotal) + const [count, setCount] = useState(0) + const handleClap = clapState => { + setCount(clapState.count) } - return ( - - - - - - +
+ + + + + + {!!count && ( +
{`You have clapped ${count} times`}
+ )} +
) } diff --git a/showcase/src/patterns/04.js b/showcase/src/patterns/04.js index 4dabdcc..b84af10 100644 --- a/showcase/src/patterns/04.js +++ b/showcase/src/patterns/04.js @@ -1,136 +1,115 @@ import React, { useState, - useEffect, - useCallback, useLayoutEffect, - useContext, + useCallback, + createContext, useMemo, - useRef, - createContext + useContext, + useEffect, + useRef } from 'react' - import mojs from 'mo-js' -import wordConverter from 'number-to-words' -import { generateRandomNumber } from '../utils/generateRandomNumber' import styles from './index.css' -import userStyles from './usage.css' +import userCustomStyles from './usage.css' -/** ==================================== - * 🔰Hook - Hook for Animation -==================================== **/ +const initialState = { + count: 0, + countTotal: 267, + isClicked: false +} -const useClapAnimation = ({ - duration: tlDuration, - bounceEl, - fadeEl, - burstEl -}) => { +/** + * Custom Hook for animation + */ +const useClapAnimation = ({ clapEl, countEl, clapTotalEl }) => { const [animationTimeline, setAnimationTimeline] = useState( - new mojs.Timeline() + () => new mojs.Timeline() ) - useLayoutEffect( - () => { - if (!bounceEl || !fadeEl || !burstEl) { - return - } - - const triangleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 95 }, - count: 5, - angle: 30, - children: { - shape: 'polygon', - radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', - strokeWidth: 2, - angle: 210, - delay: 30, - speed: 0.2, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1), - duration: tlDuration - } - }) + useLayoutEffect(() => { + if (!clapEl || !countEl || !clapTotalEl) { + return + } - const circleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 75 }, - angle: 25, - duration: tlDuration, - children: { - shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', - delay: 30, - speed: 0.2, - radius: { 3: 0 }, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1) - } - }) + const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: clapEl, + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out + }) - const countAnimation = new mojs.Html({ - el: bounceEl, - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, - opacity: { 0: 1 }, + const triangleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 95 }, + count: 5, + angle: 30, + children: { + shape: 'polygon', + radius: { 6: 0 }, + stroke: 'rgba(211,54,0,0.5)', + strokeWidth: 2, + angle: 210, + delay: 30, + speed: 0.2, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1), duration: tlDuration - }).then({ - opacity: { 1: 0 }, - y: -80, - delay: tlDuration / 2 - }) + } + }) - const countTotalAnimation = new mojs.Html({ - el: fadeEl, - isShowStart: false, - isShowEnd: true, - opacity: { 0: 1 }, - delay: (3 * tlDuration) / 2, - duration: tlDuration, - y: { 0: -3 } - }) + const circleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 75 }, + angle: 25, + duration: tlDuration, + children: { + shape: 'circle', + fill: 'rgba(149,165,166,0.5)', + delay: 30, + speed: 0.2, + radius: { 3: 0 }, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1) + } + }) - const scaleButton = new mojs.Html({ - el: burstEl, - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) - if (typeof burstEl === 'string') { - clap.style.transform = 'scale(1, 1)' - const el = document.getElementById(id) - el.style.transform = 'scale(1, 1)' - } else { - burstEl.style.transform = 'scale(1, 1)' - } + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) - const updatedAnimationTimeline = animationTimeline.add([ - countAnimation, - countTotalAnimation, - scaleButton, - circleBurst, - triangleBurst - ]) + if (typeof clapEl === 'string') { + const clap = document.getElementById('clap') + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' + } - setAnimationTimeline(updatedAnimationTimeline) - }, - [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl] - ) + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) return animationTimeline } -/** ==================================== - * 🔰 MediumClap -==================================== **/ -const initialState = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false -} const MediumClapContext = createContext() const { Provider } = MediumClapContext @@ -138,60 +117,55 @@ const { Provider } = MediumClapContext const MediumClap = ({ children, onClap, - className = '', - style: userStyles = {} + style: userStyles = {}, + className }) => { const MAXIMUM_USER_CLAP = 50 const [clapState, setClapState] = useState(initialState) - const { count, countTotal, isClicked } = clapState + const { count } = clapState const [{ clapRef, clapCountRef, clapTotalRef }, setRefState] = useState({}) + const setRef = useCallback(node => { - if (node !== null) { - setRefState(prevRefState => ({ - ...prevRefState, - [node.dataset.refkey]: node - })) - } + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) }, []) const animationTimeline = useClapAnimation({ - duration: 300, - bounceEl: clapCountRef, - fadeEl: clapTotalRef, - burstEl: clapRef + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef }) + const componentJustMounted = useRef(true) + useEffect(() => { + if (!componentJustMounted.current) { + console.log('onClap was called!!!') + onClap && onClap(clapState) + } + componentJustMounted.current = false + }, [count]) + const handleClapClick = () => { animationTimeline.replay() - - setClapState({ + setClapState(prevState => ({ + isClicked: true, count: Math.min(count + 1, MAXIMUM_USER_CLAP), - countTotal: count < MAXIMUM_USER_CLAP ? countTotal + 1 : countTotal, - isClicked: true - }) + countTotal: + count < MAXIMUM_USER_CLAP + ? prevState.countTotal + 1 + : prevState.countTotal + })) } - const componentJustMounted = useRef(true) - - useEffect( - () => { - if (!componentJustMounted.current) { - onClap(clapState) - } - componentJustMounted.current = false - }, - [count, onClap] - ) - const memoizedValue = useMemo( () => ({ - count, - countTotal, - isClicked, + ...clapState, setRef }), - [count, countTotal, isClicked, setRef] + [clapState, setRef] ) const classNames = [styles.clap, className].join(' ').trim() @@ -201,9 +175,8 @@ const MediumClap = ({ - ) - } - ) - - const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { - const classNames = [styles.icon, isClicked ? styles.checked : '', className] - .join(' ') - .trim() - - return ( - - - - - - - ) - } - - const ClapCount = forwardRef( - ({ count, className = '', style: userStyles = {}, ...restProps }, ref) => { - const classNames = [styles.count, className].join(' ').trim() - - return ( - - +{count} - - ) + + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) + + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) + + if (typeof clapEl === 'string') { + const clap = document.getElementById('clap') + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' } - ) - - const CountTotal = forwardRef( - ( - { countTotal, className = '', style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.total, className].join(' ').trim() - - return ( - - {countTotal} - - ) + + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) + + return animationTimeline +} + +/** + * useDOMRef Hook + */ +const useDOMRef = () => { + const [DOMRef, setRefState] = useState({}) + + const setRef = useCallback(node => { + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) + }, []) + + return [DOMRef, setRef] +} + +/** + * custom hook for useClapState + */ +const useClapState = (initialState = INITIAL_STATE) => { + const MAXIMUM_USER_CLAP = 50 + const [clapState, setClapState] = useState(initialState) + const { count, countTotal } = clapState + + const updateClapState = useCallback(() => { + setClapState(({ count, countTotal }) => ({ + isClicked: true, + count: Math.min(count + 1, MAXIMUM_USER_CLAP), + countTotal: count < MAXIMUM_USER_CLAP ? countTotal + 1 : countTotal + })) + }, [count, countTotal]) + + return [clapState, updateClapState] +} + +/** + * custom useEffectAfterMount hook + */ +const useEffectAfterMount = (cb, deps) => { + const componentJustMounted = useRef(true) + useEffect(() => { + if (!componentJustMounted.current) { + return cb() } + componentJustMounted.current = false + }, deps) +} + +const MediumClap = () => { + const [clapState, updateClapState] = useClapState() + const { count, countTotal, isClicked } = clapState + + const [{ clapRef, clapCountRef, clapTotalRef }, setRef] = useDOMRef() + + const animationTimeline = useClapAnimation({ + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef + }) + + useEffectAfterMount(() => { + animationTimeline.replay() + }, [count]) + + return ( + ) - - /** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API - ==================================== **/ - - const CupBowl = () => { - // Credit: Created by Kieu Thi Kim Cuong from the Noun Project - return ( +} + +/** + * subcomponents + */ + +const ClapIcon = ({ isClicked }) => { + return ( + - - - + + - ) - } - - const CupHandle = () => { - // Credit: Created by Kieu Thi Kim Cuong from the Noun Project - return ( - - - - - - ) - } - - const Stream = () => { - // Credit: Created by Kieu Thi Kim Cuong from the Noun Project - return ( - - - - - - ) - } - - const CupBase = () => { - // Credit: Created by Kieu Thi Kim Cuong from the Noun Project - return ( - - - - - - ) - } - - const Usage = () => { - const animationTimeline = useClapAnimation({ - duration: 300, - bounceEl: '#stream', - fadeEl: '#cupHandle', - burstEl: '#coffee' - }) - - const handleClick = () => { - animationTimeline.replay() - } - - return ( -
-
- -
-
- coffee -
-
- - -
-
- -
-
- -
-
- ) - } - - export default Usage \ No newline at end of file +
+ ) +} +const ClapCount = ({ count, setRef }) => { + return ( + + + {count} + + ) +} + +const CountTotal = ({ countTotal, setRef }) => { + return ( + + {countTotal} + + ) +} + +/** + * Usage + */ + +const Usage = () => { + return +} + +export default Usage diff --git a/showcase/src/patterns/07.js b/showcase/src/patterns/07.js index e1ea07e..2b7bec0 100644 --- a/showcase/src/patterns/07.js +++ b/showcase/src/patterns/07.js @@ -1,244 +1,195 @@ import React, { useState, - useEffect, - useCallback, useLayoutEffect, - forwardRef, - useRef + useCallback, + useRef, + useEffect } from 'react' - import mojs from 'mo-js' -import { generateRandomNumber } from '../utils/generateRandomNumber' import styles from './index.css' -import userStyles from './usage.css' -/** ==================================== - * 🔰Hook - Hook for Animation - ==================================== **/ +const INITIAL_STATE = { + count: 0, + countTotal: 267, + isClicked: false +} -const useClapAnimation = ({ - duration: tlDuration, - bounceEl, - fadeEl, - burstEl -}) => { +/** + * Custom Hook for animation + */ +const useClapAnimation = ({ clapEl, countEl, clapTotalEl }) => { const [animationTimeline, setAnimationTimeline] = useState( - new mojs.Timeline() + () => new mojs.Timeline() ) - useLayoutEffect( - () => { - if (!bounceEl || !fadeEl || !burstEl) { - return - } - - const triangleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 95 }, - count: 5, - angle: 30, - children: { - shape: 'polygon', - radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', - strokeWidth: 2, - angle: 210, - delay: 30, - speed: 0.2, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1), - duration: tlDuration - } - }) - - const circleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 75 }, - angle: 25, - duration: tlDuration, - children: { - shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', - delay: 30, - speed: 0.2, - radius: { 3: 0 }, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1) - } - }) + useLayoutEffect(() => { + if (!clapEl || !countEl || !clapTotalEl) { + return + } - const countAnimation = new mojs.Html({ - el: bounceEl, - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, - opacity: { 0: 1 }, + const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: clapEl, + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out + }) + + const triangleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 95 }, + count: 5, + angle: 30, + children: { + shape: 'polygon', + radius: { 6: 0 }, + stroke: 'rgba(211,54,0,0.5)', + strokeWidth: 2, + angle: 210, + delay: 30, + speed: 0.2, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1), duration: tlDuration - }).then({ - opacity: { 1: 0 }, - y: -80, - delay: tlDuration / 2 - }) - - const countTotalAnimation = new mojs.Html({ - el: fadeEl, - isShowStart: false, - isShowEnd: true, - opacity: { 0: 1 }, - delay: (3 * tlDuration) / 2, - duration: tlDuration, - y: { 0: -3 } - }) - - const scaleButton = new mojs.Html({ - el: burstEl, - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) - - if (typeof burstEl === 'string') { - const id = burstEl.slice(1, burstEl.length) - const el = document.getElementById(id) - el.style.transform = 'scale(1, 1)' - } else { - burstEl.style.transform = 'scale(1, 1)' } + }) + + const circleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 75 }, + angle: 25, + duration: tlDuration, + children: { + shape: 'circle', + fill: 'rgba(149,165,166,0.5)', + delay: 30, + speed: 0.2, + radius: { 3: 0 }, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1) + } + }) + + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) + + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) + + if (typeof clapEl === 'string') { + const clap = document.getElementById('clap') + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' + } - const updatedAnimationTimeline = animationTimeline.add([ - countAnimation, - countTotalAnimation, - scaleButton, - circleBurst, - triangleBurst - ]) - - setAnimationTimeline(updatedAnimationTimeline) - }, - [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl] - ) + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) return animationTimeline } -/** ==================================== - * 🔰Hook - Hook for Clap State - ==================================== **/ -const MAX_CLAP = 50 -const INIT_STATE = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false +/** + * useDOMRef Hook + */ +const useDOMRef = () => { + const [DOMRef, setRefState] = useState({}) + + const setRef = useCallback(node => { + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) + }, []) + + return [DOMRef, setRef] } -const useClapState = ({ initialState = INIT_STATE } = {}) => { +/** + * custom hook for useClapState + */ +const useClapState = (initialState = INITIAL_STATE) => { + const MAXIMUM_USER_CLAP = 50 const [clapState, setClapState] = useState(initialState) const { count, countTotal } = clapState - const handleClapClick = useCallback( - () => { - setClapState({ - count: Math.min(count + 1, MAX_CLAP), - countTotal: count < MAX_CLAP ? countTotal + 1 : countTotal, - isClicked: true - }) - }, - [count, countTotal] - ) + const updateClapState = useCallback(() => { + setClapState(({ count, countTotal }) => ({ + isClicked: true, + count: Math.min(count + 1, MAXIMUM_USER_CLAP), + countTotal: count < MAXIMUM_USER_CLAP ? countTotal + 1 : countTotal + })) + }, [count, countTotal]) const togglerProps = { - onClick: handleClapClick, + onClick: updateClapState, 'aria-pressed': clapState.isClicked } const counterProps = { count, - 'aria-valuemax': MAX_CLAP, + 'aria-valuemax': MAXIMUM_USER_CLAP, 'aria-valuemin': 0, 'aria-valuenow': count } - return { - clapState, - togglerProps, - counterProps - } + return { clapState, updateClapState, togglerProps, counterProps } } -/** ==================================== - * 🔰Hook - useEffectAfterMount - ==================================== **/ - -function useEffectAfterMount (cb, deps) { +/** + * custom useEffectAfterMount hook + */ +const useEffectAfterMount = (cb, deps) => { const componentJustMounted = useRef(true) useEffect(() => { if (!componentJustMounted.current) { return cb() } componentJustMounted.current = false - // eslint-disable-next-line react-hooks/exhaustive-deps }, deps) } -/** ==================================== - * 🔰Hook - useDOMRef - ==================================== **/ -const useDOMRef = () => { - const [DOMRef, setDOMRef] = useState({}) - const setRef = useCallback(node => { - if (node !== null) { - setDOMRef(prevDOMRefs => ({ - ...prevDOMRefs, - [node.dataset.refkey]: node - })) - } - }, []) +/** + * subcomponents + */ - return [DOMRef, setRef] +const ClapContainer = ({ children, setRef, handleClick, ...restProps }) => { + return ( + + ) } - -/** ==================================== - * 🔰SubComponents - Smaller Component used by - ==================================== **/ - -const ClapContainer = forwardRef( - ( - { children, handleClick, className, style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.clap, className].join(' ').trim() - - return ( - - ) - } -) - -const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { - const classNames = [styles.icon, isClicked ? styles.checked : '', className] - .join(' ') - .trim() - +const ClapIcon = ({ isClicked }) => { return ( @@ -246,75 +197,50 @@ const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { ) } +const ClapCount = ({ count, setRef, ...restProps }) => { + return ( + + + {count} + + ) +} -const ClapCount = forwardRef( - ({ count, className = '', style: userStyles = {}, ...restProps }, ref) => { - const classNames = [styles.count, className].join(' ').trim() - - return ( - - +{count} - - ) - } -) - -const CountTotal = forwardRef( - ( - { countTotal, className = '', style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.total, className].join(' ').trim() - - return ( - - {countTotal} - - ) - } -) - -/** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API - ==================================== **/ +const CountTotal = ({ countTotal, setRef, ...restProps }) => { + return ( + + {countTotal} + + ) +} +/** + * Usage + */ const Usage = () => { const { clapState, togglerProps, counterProps } = useClapState() + const { count, countTotal, isClicked } = clapState - const [ - { clapContainerRef, clapCountRef, countTotalRef }, - setRef - ] = useDOMRef() + const [{ clapRef, clapCountRef, clapTotalRef }, setRef] = useDOMRef() const animationTimeline = useClapAnimation({ - duration: 300, - bounceEl: clapCountRef, - fadeEl: countTotalRef, - burstEl: clapContainerRef + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef }) - useEffectAfterMount( - () => { - animationTimeline.replay() - }, - [count] - ) + useEffectAfterMount(() => { + animationTimeline.replay() + }, [count]) return ( - + - + ) diff --git a/showcase/src/patterns/08.js b/showcase/src/patterns/08.js index be75d84..7de7c07 100644 --- a/showcase/src/patterns/08.js +++ b/showcase/src/patterns/08.js @@ -1,249 +1,202 @@ import React, { useState, - useEffect, - useCallback, useLayoutEffect, - forwardRef, - useRef + useCallback, + useRef, + useEffect } from 'react' - import mojs from 'mo-js' -import { generateRandomNumber } from '../utils/generateRandomNumber' import styles from './index.css' -import userStyles from './usage.css' -/** ==================================== - * 🔰Hook - Hook for Animation - ==================================== **/ +const INITIAL_STATE = { + count: 0, + countTotal: 267, + isClicked: false +} -const useClapAnimation = ({ - duration: tlDuration, - bounceEl, - fadeEl, - burstEl -}) => { +/** + * Custom Hook for animation + */ +const useClapAnimation = ({ clapEl, countEl, clapTotalEl }) => { const [animationTimeline, setAnimationTimeline] = useState( - new mojs.Timeline() + () => new mojs.Timeline() ) - useLayoutEffect( - () => { - if (!bounceEl || !fadeEl || !burstEl) { - return - } - - const triangleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 95 }, - count: 5, - angle: 30, - children: { - shape: 'polygon', - radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', - strokeWidth: 2, - angle: 210, - delay: 30, - speed: 0.2, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1), - duration: tlDuration - } - }) - - const circleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 75 }, - angle: 25, - duration: tlDuration, - children: { - shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', - delay: 30, - speed: 0.2, - radius: { 3: 0 }, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1) - } - }) + useLayoutEffect(() => { + if (!clapEl || !countEl || !clapTotalEl) { + return + } - const countAnimation = new mojs.Html({ - el: bounceEl, - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, - opacity: { 0: 1 }, + const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: clapEl, + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out + }) + + const triangleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 95 }, + count: 5, + angle: 30, + children: { + shape: 'polygon', + radius: { 6: 0 }, + stroke: 'rgba(211,54,0,0.5)', + strokeWidth: 2, + angle: 210, + delay: 30, + speed: 0.2, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1), duration: tlDuration - }).then({ - opacity: { 1: 0 }, - y: -80, - delay: tlDuration / 2 - }) - - const countTotalAnimation = new mojs.Html({ - el: fadeEl, - isShowStart: false, - isShowEnd: true, - opacity: { 0: 1 }, - delay: (3 * tlDuration) / 2, - duration: tlDuration, - y: { 0: -3 } - }) - - const scaleButton = new mojs.Html({ - el: burstEl, - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) - - if (typeof burstEl === 'string') { - const id = burstEl.slice(1, burstEl.length) - const el = document.getElementById(id) - el.style.transform = 'scale(1, 1)' - } else { - burstEl.style.transform = 'scale(1, 1)' } + }) + + const circleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 75 }, + angle: 25, + duration: tlDuration, + children: { + shape: 'circle', + fill: 'rgba(149,165,166,0.5)', + delay: 30, + speed: 0.2, + radius: { 3: 0 }, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1) + } + }) + + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) + + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) + + if (typeof clapEl === 'string') { + const clap = document.getElementById('clap') + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' + } - const updatedAnimationTimeline = animationTimeline.add([ - countAnimation, - countTotalAnimation, - scaleButton, - circleBurst, - triangleBurst - ]) - - setAnimationTimeline(updatedAnimationTimeline) - }, - [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl] - ) + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) return animationTimeline } -/** ==================================== - * 🔰Hook - Hook for Clap State - ==================================== **/ -const MAX_CLAP = 50 -const INIT_STATE = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false -} +/** + * useDOMRef Hook + */ +const useDOMRef = () => { + const [DOMRef, setRefState] = useState({}) + + const setRef = useCallback(node => { + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) + }, []) -const callFnsInSequence = (...fns) => (...args) => + return [DOMRef, setRef] +} +// const handleClick = (evt) => { ... } +// + ) } - -/** ==================================== - * 🔰SubComponents - Smaller Component used by - ==================================== **/ - -const ClapContainer = forwardRef( - ( - { children, handleClick, className, style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.clap, className].join(' ').trim() - - return ( - - ) - } -) - -const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { - const classNames = [styles.icon, isClicked ? styles.checked : '', className] - .join(' ') - .trim() - +const ClapIcon = ({ isClicked }) => { return ( @@ -251,95 +204,68 @@ const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { ) } +const ClapCount = ({ count, setRef, ...restProps }) => { + return ( + + + {count} + + ) +} -const ClapCount = forwardRef( - ({ count, className = '', style: userStyles = {}, ...restProps }, ref) => { - const classNames = [styles.count, className].join(' ').trim() - - return ( - - +{count} - - ) - } -) - -const CountTotal = forwardRef( - ( - { countTotal, className = '', style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.total, className].join(' ').trim() - - return ( - - {countTotal} - - ) - } -) - -/** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API - ==================================== **/ +const CountTotal = ({ countTotal, setRef, ...restProps }) => { + return ( + + {countTotal} + + ) +} +/** + * Usage + */ const Usage = () => { const { clapState, getTogglerProps, getCounterProps } = useClapState() - const { count, countTotal, isClicked } = clapState - const [ - { clapContainerRef, clapCountRef, countTotalRef }, - setRef - ] = useDOMRef() + const { count, countTotal } = clapState + + const [{ clapRef, clapCountRef, clapTotalRef }, setRef] = useDOMRef() const animationTimeline = useClapAnimation({ - duration: 300, - bounceEl: clapCountRef, - fadeEl: countTotalRef, - burstEl: clapContainerRef + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef }) - const onClick = () => { + useEffectAfterMount(() => { animationTimeline.replay() + }, [count]) + + const handleClick = () => { + console.log('CLICKED!!!!') } return ( -
- - - - - -
- {!isClicked ? 'No recommendations :(' : `Recommended ${count} times 🔥`} -
-
+ + {/* */} + 🇳🇬 + + + ) } - export default Usage diff --git a/showcase/src/patterns/09.js b/showcase/src/patterns/09.js index b515497..8ed86fb 100644 --- a/showcase/src/patterns/09.js +++ b/showcase/src/patterns/09.js @@ -1,190 +1,183 @@ import React, { useState, - useEffect, - useCallback, useLayoutEffect, - forwardRef, - useRef + useCallback, + useRef, + useEffect } from 'react' - import mojs from 'mo-js' -import { generateRandomNumber } from '../utils/generateRandomNumber' import styles from './index.css' import userStyles from './usage.css' -/** ==================================== - * 🔰Hook - Hook for Holding Previous Vals - ==================================== **/ -function usePrevious (value) { - const ref = useRef() - useEffect(() => { - ref.current = value - }) - return ref.current === undefined ? null : ref.current +const INITIAL_STATE = { + count: 0, + countTotal: 267, + isClicked: false } -/** ==================================== - * 🔰Hook - Hook for Animation - ==================================== **/ - -const useClapAnimation = ({ - duration: tlDuration, - bounceEl, - fadeEl, - burstEl -}) => { +/** + * Custom Hook for animation + */ +const useClapAnimation = ({ clapEl, countEl, clapTotalEl }) => { const [animationTimeline, setAnimationTimeline] = useState( - new mojs.Timeline() + () => new mojs.Timeline() ) - useLayoutEffect( - () => { - if (!bounceEl || !fadeEl || !burstEl) { - return - } + useLayoutEffect(() => { + if (!clapEl || !countEl || !clapTotalEl) { + return + } - const triangleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 95 }, - count: 5, - angle: 30, - children: { - shape: 'polygon', - radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', - strokeWidth: 2, - angle: 210, - delay: 30, - speed: 0.2, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1), - duration: tlDuration - } - }) - - const circleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 75 }, - angle: 25, - duration: tlDuration, - children: { - shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', - delay: 30, - speed: 0.2, - radius: { 3: 0 }, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1) - } - }) - - const countAnimation = new mojs.Html({ - el: bounceEl, - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, - opacity: { 0: 1 }, + const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: clapEl, + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out + }) + + const triangleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 95 }, + count: 5, + angle: 30, + children: { + shape: 'polygon', + radius: { 6: 0 }, + stroke: 'rgba(211,54,0,0.5)', + strokeWidth: 2, + angle: 210, + delay: 30, + speed: 0.2, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1), duration: tlDuration - }).then({ - opacity: { 1: 0 }, - y: -80, - delay: tlDuration / 2 - }) - - const countTotalAnimation = new mojs.Html({ - el: fadeEl, - isShowStart: false, - isShowEnd: true, - opacity: { 0: 1 }, - delay: (3 * tlDuration) / 2, - duration: tlDuration, - y: { 0: -3 } - }) - - const scaleButton = new mojs.Html({ - el: burstEl, - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) - - if (typeof burstEl === 'string') { - const id = burstEl.slice(1, burstEl.length) - const el = document.getElementById(id) - el.style.transform = 'scale(1, 1)' - } else { - burstEl.style.transform = 'scale(1, 1)' } + }) + + const circleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 75 }, + angle: 25, + duration: tlDuration, + children: { + shape: 'circle', + fill: 'rgba(149,165,166,0.5)', + delay: 30, + speed: 0.2, + radius: { 3: 0 }, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1) + } + }) + + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) + + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) + + if (typeof clapEl === 'string') { + const clap = document.getElementById('clap') + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' + } - const updatedAnimationTimeline = animationTimeline.add([ - countAnimation, - countTotalAnimation, - scaleButton, - circleBurst, - triangleBurst - ]) - - setAnimationTimeline(updatedAnimationTimeline) - }, - [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl] - ) + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) return animationTimeline } -/** ==================================== - * 🔰Hook - Hook for Clap State - ==================================== **/ -const MAX_CLAP = 50 -const INIT_STATE = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false +/** + * useDOMRef Hook + */ +const useDOMRef = () => { + const [DOMRef, setRefState] = useState({}) + + const setRef = useCallback(node => { + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) + }, []) + + return [DOMRef, setRef] +} +/** + * + * custom hook for getting preivous prop/state + */ +const usePrevious = value => { + const ref = useRef() + useEffect(() => { + ref.current = value + }) + return ref.current } -const callFnsInSequence = (...fns) => (...args) => +// const handleClick = (evt) => { ... } +// + ) } - -/** ==================================== - * 🔰SubComponents - Smaller Component used by - ==================================== **/ - -const ClapContainer = forwardRef( - ( - { children, handleClick, className, style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.clap, className].join(' ').trim() - - return ( - - ) - } -) - -const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { - const classNames = [styles.icon, isClicked ? styles.checked : '', className] - .join(' ') - .trim() - +const ClapIcon = ({ isClicked }) => { return ( @@ -279,41 +236,31 @@ const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { ) } +const ClapCount = ({ count, setRef, ...restProps }) => { + return ( + + + {count} + + ) +} -const ClapCount = forwardRef( - ({ count, className = '', style: userStyles = {}, ...restProps }, ref) => { - const classNames = [styles.count, className].join(' ').trim() - - return ( - - +{count} - - ) - } -) - -const CountTotal = forwardRef( - ( - { countTotal, className = '', style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.total, className].join(' ').trim() - - return ( - - {countTotal} - - ) - } -) +const CountTotal = ({ countTotal, setRef, ...restProps }) => { + return ( + + {countTotal} + + ) +} -/** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API - ==================================== **/ +/** + * Usage + */ +const userInitialState = { + count: 0, + countTotal: 1000, + isClicked: false +} -const initialState = { count: 10, countTotal: 22, isClicked: false } const Usage = () => { const { clapState, @@ -321,80 +268,71 @@ const Usage = () => { getCounterProps, reset, resetDep - } = useClapState({ initialState }) + } = useClapState(userInitialState) + const { count, countTotal, isClicked } = clapState - const [ - { clapContainerRef, clapCountRef, countTotalRef }, - setRef - ] = useDOMRef() + const [{ clapRef, clapCountRef, clapTotalRef }, setRef] = useDOMRef() const animationTimeline = useClapAnimation({ - duration: 300, - bounceEl: clapCountRef, - fadeEl: countTotalRef, - burstEl: clapContainerRef + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef }) - const onClick = () => { + useEffectAfterMount(() => { animationTimeline.replay() - } + }, [count]) - // Side effect after reset has occured. const [uploadingReset, setUpload] = useState(false) - useEffectAfterMount( - () => { - setUpload(true) - - const id = setTimeout(() => { - setUpload(false) - console.log('RESET COMPLETE!!!') - }, 3000) - - return () => clearTimeout(id) - }, - [resetDep] - ) + useEffectAfterMount(() => { + setUpload(true) + + const id = setTimeout(() => { + setUpload(false) + }, 3000) + + return () => clearTimeout(id) + }, [resetDep]) + + const handleClick = () => { + console.log('CLICKED!!!!') + } return ( -
+
-
 {JSON.stringify({ count, countTotal, isClicked })}
 
-
- {uploadingReset ? `uploading reset ${resetDep}...` : ''}
+ 
+ {uploadingReset ? `uploading reset ${resetDep} ...` : ''}
 
) } - export default Usage diff --git a/showcase/src/patterns/10.js b/showcase/src/patterns/10.js index a2ffb36..40bba52 100644 --- a/showcase/src/patterns/10.js +++ b/showcase/src/patterns/10.js @@ -1,427 +1,372 @@ import React, { - useReducer, - useState, - useEffect, - useCallback, - useLayoutEffect, - forwardRef, - useRef - } from 'react' - - import mojs from 'mo-js' - import { generateRandomNumber } from '../utils/generateRandomNumber' - import styles from './index.css' - import userStyles from './usage.css' - - /** ==================================== - * 🔰Hook - Hook for Holding Previous Vals - ==================================== **/ - function usePrevious (value) { - const ref = useRef() - useEffect(() => { - ref.current = value - }) - return ref.current === undefined ? null : ref.current - } - - /** ==================================== - * 🔰Hook - Hook for Animation - ==================================== **/ - - const useClapAnimation = ({ - duration: tlDuration, - bounceEl, - fadeEl, - burstEl - }) => { - const [animationTimeline, setAnimationTimeline] = useState( - new mojs.Timeline() - ) - - useLayoutEffect( - () => { - if (!bounceEl || !fadeEl || !burstEl) { - return - } - - const triangleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 95 }, - count: 5, - angle: 30, - children: { - shape: 'polygon', - radius: { 6: 0 }, - scale: 1, - stroke: 'rgba(211,84,0 ,0.5)', - strokeWidth: 2, - angle: 210, - delay: 30, - speed: 0.2, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1), - duration: tlDuration - } - }) - - const circleBurst = new mojs.Burst({ - parent: burstEl, - radius: { 50: 75 }, - angle: 25, - duration: tlDuration, - children: { - shape: 'circle', - fill: 'rgba(149,165,166 ,0.5)', - delay: 30, - speed: 0.2, - radius: { 3: 0 }, - easing: mojs.easing.bezier(0.1, 1, 0.3, 1) - } - }) - - const countAnimation = new mojs.Html({ - el: bounceEl, - isShowStart: false, - isShowEnd: true, - y: { 0: -30 }, - opacity: { 0: 1 }, - duration: tlDuration - }).then({ - opacity: { 1: 0 }, - y: -80, - delay: tlDuration / 2 - }) - - const countTotalAnimation = new mojs.Html({ - el: fadeEl, - isShowStart: false, - isShowEnd: true, - opacity: { 0: 1 }, - delay: (3 * tlDuration) / 2, - duration: tlDuration, - y: { 0: -3 } - }) - - const scaleButton = new mojs.Html({ - el: burstEl, - duration: tlDuration, - scale: { 1.3: 1 }, - easing: mojs.easing.out - }) - - if (typeof burstEl === 'string') { - const id = burstEl.slice(1, burstEl.length) - const el = document.getElementById(id) - el.style.transform = 'scale(1, 1)' - } else { - burstEl.style.transform = 'scale(1, 1)' - } - - const updatedAnimationTimeline = animationTimeline.add([ - countAnimation, - countTotalAnimation, - scaleButton, - circleBurst, - triangleBurst - ]) - - setAnimationTimeline(updatedAnimationTimeline) - }, - [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl] - ) - - return animationTimeline - } - - /** ==================================== - * 🔰Hook - Hook for Clap State - ==================================== **/ - const MAX_CLAP = 50 - const INIT_STATE = { - count: 0, - countTotal: generateRandomNumber(500, 10000), - isClicked: false - } - - const callFnsInSequence = (...fns) => (...args) => - fns.forEach(fn => fn && fn(...args)) - - const clapReducer = (state, { type, payload }) => { - const { count, countTotal } = state - - switch (type) { - case useClapState.types.clap: - return { - count: count + 1, - countTotal: countTotal + 1, - isClicked: true - } - case useClapState.types.reset: - return payload - default: - return state + useState, + useLayoutEffect, + useCallback, + useRef, + useEffect, + useReducer +} from 'react' +import mojs from 'mo-js' +import styles from './index.css' +import userStyles from './usage.css' + +const INITIAL_STATE = { + count: 0, + countTotal: 267, + isClicked: false +} + +/** + * Custom Hook for animation + */ +const useClapAnimation = ({ clapEl, countEl, clapTotalEl }) => { + const [animationTimeline, setAnimationTimeline] = useState( + () => new mojs.Timeline() + ) + + useLayoutEffect(() => { + if (!clapEl || !countEl || !clapTotalEl) { + return } - } - - const useClapState = ({ - initialState = INIT_STATE, - reducer = clapReducer - } = {}) => { - const initialStateRef = useRef(initialState) - const [clapState, dispatch] = useReducer(reducer, initialStateRef.current) - const { count } = clapState - - const handleClapClick = () => dispatch({ type: 'clap' }) - - const resetRef = useRef(0) - // reset only if there's a change. It's possible to check changes to other state values e.g. countTotal & isClicked - const reset = useCallback(() => { - dispatch({ type: 'reset', payload: initialStateRef.current }) - ++resetRef.current - }, []) - - const getTogglerProps = ({ onClick, ...otherProps } = {}) => ({ - onClick: callFnsInSequence(handleClapClick, onClick), - 'aria-pressed': clapState.isClicked, - ...otherProps + + const tlDuration = 300 + const scaleButton = new mojs.Html({ + el: clapEl, + duration: tlDuration, + scale: { 1.3: 1 }, + easing: mojs.easing.ease.out }) - - const getCounterProps = ({ ...otherProps }) => ({ - count, - 'aria-valuemax': MAX_CLAP, - 'aria-valuemin': 0, - 'aria-valuenow': count, - ...otherProps + + const triangleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 95 }, + count: 5, + angle: 30, + children: { + shape: 'polygon', + radius: { 6: 0 }, + stroke: 'rgba(211,54,0,0.5)', + strokeWidth: 2, + angle: 210, + delay: 30, + speed: 0.2, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1), + duration: tlDuration + } }) - - return { - clapState, - getTogglerProps, - getCounterProps, - reset, - resetDep: resetRef.current + + const circleBurst = new mojs.Burst({ + parent: clapEl, + radius: { 50: 75 }, + angle: 25, + duration: tlDuration, + children: { + shape: 'circle', + fill: 'rgba(149,165,166,0.5)', + delay: 30, + speed: 0.2, + radius: { 3: 0 }, + easing: mojs.easing.bezier(0.1, 1, 0.3, 1) + } + }) + + const countAnimation = new mojs.Html({ + el: countEl, + opacity: { 0: 1 }, + y: { 0: -30 }, + duration: tlDuration + }).then({ + opacity: { 1: 0 }, + y: -80, + delay: tlDuration / 2 + }) + + const countTotalAnimation = new mojs.Html({ + el: clapTotalEl, + opacity: { 0: 1 }, + delay: (3 * tlDuration) / 2, + duration: tlDuration, + y: { 0: -3 } + }) + + if (typeof clapEl === 'string') { + const clap = document.getElementById('clap') + clap.style.transform = 'scale(1,1)' + } else { + clapEl.style.transform = 'scale(1,1)' } - } - - useClapState.reducer = clapReducer - useClapState.types = { - clap: 'clap', - reset: 'reset' - } - - /** ==================================== - * 🔰Hook - useEffectAfterMount - ==================================== **/ - - function useEffectAfterMount (cb, deps) { - const componentJustMounted = useRef(true) - useEffect(() => { - if (!componentJustMounted.current) { - return cb() + + const newAnimationTimeline = animationTimeline.add([ + scaleButton, + countTotalAnimation, + countAnimation, + triangleBurst, + circleBurst + ]) + setAnimationTimeline(newAnimationTimeline) + }, [clapEl, countEl, clapTotalEl]) + + return animationTimeline +} + +/** + * useDOMRef Hook + */ +const useDOMRef = () => { + const [DOMRef, setRefState] = useState({}) + + const setRef = useCallback(node => { + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) + }, []) + + return [DOMRef, setRef] +} +/** + * + * custom hook for getting preivous prop/state + */ +const usePrevious = value => { + const ref = useRef() + useEffect(() => { + ref.current = value + }) + return ref.current +} + +// const handleClick = (evt) => { ... } +// - ) +} + +useClapState.reducer = internalReducer +useClapState.types = { + clap: 'clap', + reset: 'reset' +} + +/** + * custom useEffectAfterMount hook + */ +const useEffectAfterMount = (cb, deps) => { + const componentJustMounted = useRef(true) + useEffect(() => { + if (!componentJustMounted.current) { + return cb() } + componentJustMounted.current = false + }, deps) +} + +/** + * subcomponents + */ + +const ClapContainer = ({ children, setRef, handleClick, ...restProps }) => { + return ( + ) - - const ClapIcon = ({ className = '', style: userStyles = {}, isClicked }) => { - const classNames = [styles.icon, isClicked ? styles.checked : '', className] - .join(' ') - .trim() - - return ( - - - - - - - ) - } - - const ClapCount = forwardRef( - ({ count, className = '', style: userStyles = {}, ...restProps }, ref) => { - const classNames = [styles.count, className].join(' ').trim() - - return ( - - +{count} - - ) - } +} +const ClapIcon = ({ isClicked }) => { + return ( + + + + + + ) - - const CountTotal = forwardRef( - ( - { countTotal, className = '', style: userStyles = {}, ...restProps }, - ref - ) => { - const classNames = [styles.total, className].join(' ').trim() - - return ( - - {countTotal} - - ) - } +} +const ClapCount = ({ count, setRef, ...restProps }) => { + return ( + + + {count} + ) - - /** ==================================== - * 🔰USAGE - Below's how a potential user - may consume the component API - ==================================== **/ - - const initialState = { count: 10, countTotal: 22, isClicked: false } - const Usage = () => { - const [timesClapped, setTimeClapped] = useState(0) - const clappedTooMuch = timesClapped>= 7 - - const reducer = (state, action) => { - if (action.type === useClapState.types.clap && clappedTooMuch) { - return state - } - return useClapState.reducer(state, action) - } - - const { - clapState, - getTogglerProps, - getCounterProps, - reset, - resetDep - } = useClapState({ initialState, reducer }) - const { count, countTotal, isClicked } = clapState - - const [ - { clapContainerRef, clapCountRef, countTotalRef }, - setRef - ] = useDOMRef() - - const animationTimeline = useClapAnimation({ - duration: 300, - bounceEl: clapCountRef, - fadeEl: countTotalRef, - burstEl: clapContainerRef - }) - - const onClick = () => { - setTimeClapped(t => t + 1) - !clappedTooMuch && animationTimeline.replay() +} + +const CountTotal = ({ countTotal, setRef, ...restProps }) => { + return ( + + {countTotal} + + ) +} + +/** + * Usage + */ +const userInitialState = { + count: 0, + countTotal: 1000, + isClicked: false +} + +const Usage = () => { + const [timesClapped, setTimeClapped] = useState(0) + const isClappedTooMuch = timesClapped>= 7 // true/false + const reducer = (state, action) => { + if (action.type === useClapState.types.clap && isClappedTooMuch) { + return state } - - // Side effect after reset has occured. - const [uploadingReset, setUpload] = useState(false) - useEffectAfterMount( - () => { - setTimeClapped(0) - setUpload(true) - - const id = setTimeout(() => { - setUpload(false) - console.log('RESET COMPLETE!!!') - }, 3000) - - return () => clearTimeout(id) - }, - [resetDep] - ) - - return ( -
- - - - - -
- -
- {JSON.stringify({ timesClapped, count, countTotal })}
- 
-
- {uploadingReset ? `uploading reset ${resetDep}...` : ''}
- 
-
+ return useClapState.reducer(state, action) + } + + const { + clapState, + getTogglerProps, + getCounterProps, + reset, + resetDep + } = useClapState(userInitialState, reducer) + + const { count, countTotal, isClicked } = clapState + + const [{ clapRef, clapCountRef, clapTotalRef }, setRef] = useDOMRef() + + const animationTimeline = useClapAnimation({ + clapEl: clapRef, + countEl: clapCountRef, + clapTotalEl: clapTotalRef + }) + + useEffectAfterMount(() => { + animationTimeline.replay() + }, [count]) + + const [uploadingReset, setUpload] = useState(false) + useEffectAfterMount(() => { + setUpload(true) + setTimeClapped(0) + + const id = setTimeout(() => { + setUpload(false) + }, 3000) + + return () => clearTimeout(id) + }, [resetDep]) + + const handleClick = () => { + setTimeClapped(t => t + 1) + } + + return ( +
+ + + + + +
+ +
+ {JSON.stringify({ timesClapped, count, countTotal })}
+ 
+
+ {uploadingReset ? `uploading reset ${resetDep} ...` : ''}
+ 
- {clappedTooMuch ? `You clapped too much. Don't be so generous!` : ''}
+ {isClappedTooMuch
+ ? `You have clapped too much. Don't be so generous!`
+ : ''}
 
-
- ) - } - - export default Usage \ No newline at end of file + +
+ ) +} +export default Usage diff --git a/showcase/src/patterns/index.css b/showcase/src/patterns/index.css index baa6240..8427f45 100644 --- a/showcase/src/patterns/index.css +++ b/showcase/src/patterns/index.css @@ -10,7 +10,7 @@ user-select: none; } .clap:after { - content: ""; + content: ''; position: absolute; top: 0; left: 0; @@ -82,8 +82,6 @@ /* Clap Info */ .info { -position: absolute; -left: -20px; -right: -20px; -bottom: -50px; -} \ No newline at end of file + position: relative; + top: 47px; +} diff --git a/showcase/src/patterns/usage.css b/showcase/src/patterns/usage.css index a345649..1005afc 100644 --- a/showcase/src/patterns/usage.css +++ b/showcase/src/patterns/usage.css @@ -1,56 +1,60 @@ /** total **/ .total { - color: #896EAF; + color: white; + background: #896eaf; } - /* count */ +/* count */ .count { - background: #896EAF; + background: #896eaf; } - /* clap */ +/* clap */ .clap { - border: 1px solid #896EAF; + border: 1px solid #896eaf; } .clap:hover { - border: 1px solid #896EAF; + border: 1px solid #896eaf; +} +/* icon */ +.icon { } .cupContainer { - width: 100px; - min-height: 100px; - text-align: center; + width: 100px; + min-height: 100px; + text-align: center; } .cupBody { - display: flex; + display: flex; } -.cupStream> svg{ - height: 40px; +.cupStream> svg { + height: 40px; } .cupBody> svg { - min-height: 50px; + min-height: 50px; } /* 1. cup handle 2. cup bowl*/ .cupBody> svg:nth-child(1) { - width: 20%; + width: 20%; } .cupBody> svg:nth-child(2) { - width: 80%; - position: relative; - right: 10px; + width: 80%; + position: relative; + right: 10px; } .resetBtn { - border-bottom: 1px solid #bdc3c7; - color: '#27ae60'; - margin-top: 30px; - padding: 10px 20px; - border-radius: 20px; - outline: 0; - display: block; - width: 100%; + border-bottom: 1px solid #bdc3c7; + color: '#27ae60'; + margin-top: 30px; + padding: 10px 20px; + border-radius: 20px; + outline: 0; + display: block; + width: 100%; } .resetMsg { - color: black; -} \ No newline at end of file + color: black; +} diff --git a/showcase/webpack.config.base.js b/showcase/webpack.config.base.js index 085c1a0..f375cdb 100644 --- a/showcase/webpack.config.base.js +++ b/showcase/webpack.config.base.js @@ -5,7 +5,8 @@ module.exports = { entry: './src/index.js', output: { filename: 'app.bundle.js', - path: path.join(__dirname, 'dist') + path: path.join(__dirname, 'dist'), + publicPath: '/' }, module: { rules: [ diff --git a/showcase/webpack.config.dev.js b/showcase/webpack.config.dev.js index cc41701..c8f056e 100644 --- a/showcase/webpack.config.dev.js +++ b/showcase/webpack.config.dev.js @@ -5,11 +5,12 @@ module.exports = merge(baseConfig, { mode: 'development', devServer: { port: 4646, - open: 'Google Chrome', + open: true, overlay: { warnings: true, errors: true }, + historyApiFallback: true, hot: true }, devtool: 'source-map'

AltStyle によって変換されたページ (->オリジナル) /