diff --git a/showcase/src/patterns/index.js b/showcase/src/patterns/index.js index 2809f8f..4dabdcc 100644 --- a/showcase/src/patterns/index.js +++ b/showcase/src/patterns/index.js @@ -1,6 +1,8 @@ import React, { useState, useEffect, + useCallback, + useLayoutEffect, useContext, useMemo, useRef, @@ -11,21 +13,31 @@ 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' /** ==================================== * 🔰Hook Hook for Animation ==================================== **/ -const useClapAnimation = ({ duration: tlDuration }) => { +const useClapAnimation = ({ + duration: tlDuration, + bounceEl, + fadeEl, + burstEl +}) => { const [animationTimeline, setAnimationTimeline] = useState( new mojs.Timeline() ) - useEffect( + useLayoutEffect( () => { + if (!bounceEl || !fadeEl || !burstEl) { + return + } + const triangleBurst = new mojs.Burst({ - parent: '#clap', + parent: burstEl, radius: { 50: 95 }, count: 5, angle: 30, @@ -44,7 +56,7 @@ const useClapAnimation = ({ duration: tlDuration }) => { }) const circleBurst = new mojs.Burst({ - parent: '#clap', + parent: burstEl, radius: { 50: 75 }, angle: 25, duration: tlDuration, @@ -59,7 +71,7 @@ const useClapAnimation = ({ duration: tlDuration }) => { }) const countAnimation = new mojs.Html({ - el: '#clapCount', + el: bounceEl, isShowStart: false, isShowEnd: true, y: { 0: -30 }, @@ -72,7 +84,7 @@ const useClapAnimation = ({ duration: tlDuration }) => { }) const countTotalAnimation = new mojs.Html({ - el: '#clapCountTotal', + el: fadeEl, isShowStart: false, isShowEnd: true, opacity: { 0: 1 }, @@ -82,14 +94,19 @@ const useClapAnimation = ({ duration: tlDuration }) => { }) const scaleButton = new mojs.Html({ - el: '#clap', + el: burstEl, duration: tlDuration, scale: { 1.3: 1 }, easing: mojs.easing.out }) - const clap = document.getElementById('clap') - clap.style.transform = 'scale(1, 1)' + 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, @@ -101,7 +118,7 @@ const useClapAnimation = ({ duration: tlDuration }) => { setAnimationTimeline(updatedAnimationTimeline) }, - [tlDuration, animationTimeline] + [tlDuration, animationTimeline, bounceEl, fadeEl, burstEl] ) return animationTimeline @@ -118,14 +135,34 @@ const initialState = { const MediumClapContext = createContext() const { Provider } = MediumClapContext -const MediumClap = ({ children, onClap }) => { +const MediumClap = ({ + children, + onClap, + className = '', + style: userStyles = {} +}) => { const MAXIMUM_USER_CLAP = 50 const [clapState, setClapState] = useState(initialState) const { count, countTotal, isClicked } = clapState - const animationTimeline = useClapAnimation({ duration: 300 }) + const [{ clapRef, clapCountRef, clapTotalRef }, setRefState] = useState({}) + const setRef = useCallback(node => { + if (node !== null) { + setRefState(prevRefState => ({ + ...prevRefState, + [node.dataset.refkey]: node + })) + } + }, []) + + const animationTimeline = useClapAnimation({ + duration: 300, + bounceEl: clapCountRef, + fadeEl: clapTotalRef, + burstEl: clapRef + }) + const handleClapClick = () => { - // 👉 prop from HOC animationTimeline.replay() setClapState({ @@ -151,14 +188,24 @@ const MediumClap = ({ children, onClap }) => { () => ({ count, countTotal, - isClicked + isClicked, + setRef }), - [count, countTotal, isClicked] + [count, countTotal, isClicked, setRef] ) + const classNames = [styles.clap, className].join(' ').trim() + return ( - @@ -170,15 +217,20 @@ const MediumClap = ({ children, onClap }) => { Smaller Component used by ==================================== **/ -const ClapIcon = () => { +const ClapIcon = ({ className = '', style: userStyles = {} }) => { const { isClicked } = useContext(MediumClapContext) + const classNames = [styles.icon, isClicked ? styles.checked : '', className] + .join(' ') + .trim() + return ( @@ -186,18 +238,32 @@ const ClapIcon = () => { ) } -const ClapCount = () => { - const { count } = useContext(MediumClapContext) +const ClapCount = ({ className = '', style: userStyles = {} }) => { + const { count, setRef } = useContext(MediumClapContext) + const classNames = [styles.count, className].join(' ').trim() + return ( - + +{count} ) } -const CountTotal = () => { - const { countTotal } = useContext(MediumClapContext) +const CountTotal = ({ className = '', style: userStyles = {} }) => { + const { countTotal, setRef } = useContext(MediumClapContext) + const classNames = [styles.total, className].join(' ').trim() + return ( - + {countTotal} ) @@ -231,10 +297,10 @@ const Usage = () => { } return ( - - - - + + + + ) diff --git a/showcase/src/patterns/usage.css b/showcase/src/patterns/usage.css new file mode 100644 index 0000000..bafb86d --- /dev/null +++ b/showcase/src/patterns/usage.css @@ -0,0 +1,18 @@ +/** total **/ + +.total { + color: #896EAF; +} + + /* count */ +.count { + background: #896EAF; +} + + /* clap */ +.clap { + border: 1px solid #896EAF; +} +.clap:hover { + border: 1px solid #896EAF; +} \ No newline at end of file