Remove Locomotive (#6)

This commit is contained in:
Nazareno Oviedo 2022-03-30 23:13:51 -03:00 committed by GitHub
parent 208217009b
commit 4917256435
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 52 additions and 445 deletions

1
index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
// declare module 'gsap/dist/ScrollSmoother'

View File

@ -19,7 +19,7 @@
"@juggle/resize-observer": "^3.3.1",
"@radix-ui/react-polymorphic": "^0.0.14",
"clsx": "^1.1.1",
"gsap": "https://basement.studio/gsap/bonus-0.0.12.tgz",
"gsap": "./src/lib/gsap/gsap-bonus.tgz",
"keen-slider": "^6.6.5",
"locomotive-scroll": "^4.1.4",
"next": "12.1.3",

View File

@ -2,12 +2,12 @@ import * as React from 'react'
import { Footer } from '~/components/common/footer'
import { Header } from '~/components/common/header'
import { LocomotiveScrollProvider } from '~/lib/locomotive-scroll/provider'
import { CUSTOM_EASE, DURATION, ScrollSmoother } from '~/lib/gsap'
type Props = {
children?: React.ReactNode
extras?: React.ReactNode
locomotiveScroll?: boolean
smoothScroll?: boolean
}
const ContentMemo = React.memo(({ children, extras }: Props) => {
@ -22,11 +22,26 @@ const ContentMemo = React.memo(({ children, extras }: Props) => {
})
export const PageLayout = (props: Props) => {
if (props.locomotiveScroll) {
if (props.smoothScroll) {
const contentRef = React.useRef<HTMLDivElement>(null)
const wrapperRef = React.useRef<HTMLDivElement>(null)
React.useEffect(() => {
ScrollSmoother.create({
content: contentRef.current,
effects: true,
ignoreMobileResize: true,
normalizeScroll: true,
smooth: DURATION * 2,
ease: CUSTOM_EASE,
wrapper: wrapperRef.current
})
}, [])
return (
<LocomotiveScrollProvider>
<ContentMemo {...props} />
</LocomotiveScrollProvider>
<div ref={wrapperRef}>
<div ref={contentRef}>
<ContentMemo {...props} />
</div>
</div>
)
} else {
return <ContentMemo {...props} />

View File

@ -24,11 +24,10 @@ export const useDeviceDetect = () => {
React.useEffect(() => {
set({
isDesktop: ReactDeviceDetect.isDesktop,
// window.isMobileOrTablet comes from locomotive-scroll
isMobile: window.isMobileOrTablet ?? ReactDeviceDetect.isMobile,
isMobile: ReactDeviceDetect.isMobile,
isMobileOnly: ReactDeviceDetect.isMobileOnly,
isMobileSafari: ReactDeviceDetect.isMobileSafari,
isTablet: window.isMobileOrTablet ?? ReactDeviceDetect.isTablet,
isTablet: ReactDeviceDetect.isTablet,
isChrome: ReactDeviceDetect.isChrome,
isFirefox: ReactDeviceDetect.isFirefox,
isSafari: ReactDeviceDetect.isSafari,

View File

@ -1,39 +1,20 @@
import { EventHandler } from 'locomotive-scroll'
import * as React from 'react'
import { useLocomotiveScroll } from '~/lib/locomotive-scroll/provider'
export type ScrollListenerHandlers = {
smoothHandler: EventHandler
nativeHandler: (e: Event) => void
}
export const useScrollListener = ({
smoothHandler,
nativeHandler
}: ScrollListenerHandlers) => {
const { scroll, isSmooth } = useLocomotiveScroll()
React.useEffect(() => {
if (!scroll) return
if (isSmooth) {
const handler: EventHandler = (args) => {
smoothHandler(args)
}
scroll.on('scroll', handler)
return () => {
scroll.off('scroll', handler)
}
} else {
const handler = (event: Event) => {
nativeHandler(event)
}
window.addEventListener('scroll', handler)
return () => {
window.removeEventListener('scroll', handler)
}
const handler = (event: Event) => {
nativeHandler(event)
}
}, [isSmooth, nativeHandler, scroll, smoothHandler])
window.addEventListener('scroll', handler)
return () => {
window.removeEventListener('scroll', handler)
}
}, [nativeHandler])
}

View File

@ -1,7 +1,6 @@
import * as React from 'react'
import { gsap } from '~/lib/gsap'
import { useLocomotiveScroll } from '~/lib/locomotive-scroll/provider'
import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect'
@ -30,13 +29,11 @@ export const useTimelineEffect = (
dependencies: React.DependencyList,
options?: { autoKill?: boolean; autoPlay?: boolean }
) => {
const { isReady } = useLocomotiveScroll()
const [timeline] = React.useState(() =>
gsap.timeline({ paused: options?.autoPlay ? false : true })
)
useIsomorphicLayoutEffect(() => {
if (!isReady) return
const cleanup = callback?.(timeline)
return () => {
cleanup?.()
@ -44,7 +41,7 @@ export const useTimelineEffect = (
timeline.kill()
}
}
}, [isReady, callback, timeline, options, ...(dependencies || [])])
}, [callback, timeline, options, ...(dependencies || [])])
return { timeline }
}

BIN
src/lib/gsap/gsap-bonus.tgz Normal file

Binary file not shown.

View File

@ -1,9 +1,17 @@
import gsap from 'gsap'
import { CSSRulePlugin } from 'gsap/dist/CSSRulePlugin'
import { CustomEase } from 'gsap/dist/CustomEase'
import { ScrollSmoother } from 'gsap/dist/ScrollSmoother'
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'
import { SplitText } from 'gsap/dist/SplitText'
gsap.registerPlugin(CSSRulePlugin, CustomEase, SplitText)
gsap.registerPlugin(
CSSRulePlugin,
CustomEase,
ScrollSmoother,
ScrollTrigger,
SplitText
)
const GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2
const RECIPROCAL_GR = 1 / GOLDEN_RATIO
@ -148,4 +156,12 @@ gsap.registerEffect({
}
})
export { CSSRulePlugin, CUSTOM_EASE, DURATION, gsap, SplitText }
export {
CSSRulePlugin,
CUSTOM_EASE,
DURATION,
gsap,
ScrollSmoother,
ScrollTrigger,
SplitText
}

View File

@ -1,106 +0,0 @@
import type { Scroll } from 'locomotive-scroll'
import * as React from 'react'
import mergeRefs from 'react-merge-refs'
import { useMeasure } from '~/hooks/use-measure'
import { LocomotiveScrollScripts } from './scripts'
// Scroll lerp value
export const lerpScroll = 0.09708
export interface Context {
/**
* LocomotiveScroll instance
*/
scroll: Scroll | null
/**
* If LocomotiveScroll is mounted
*/
isReady: boolean
/**
* If isMobile, isSmooth will be false and native behaviour will kick in.
*/
isSmooth: boolean | undefined
}
const LocomotiveScrollContext = React.createContext<Context | undefined>(
undefined
)
type Props = {
children?: React.ReactNode
}
export const LocomotiveScrollProvider = ({ children }: Props) => {
const [isReady, setIsReady] = React.useState(false)
const locomotiveScrollRef = React.useRef<Scroll | null>(null)
const scrollContainerRef = React.useRef<HTMLDivElement>(null)
const [ref, { height, width }] = useMeasure({ debounce: 100 })
const [isSmooth, setIsSmooth] = React.useState<boolean>()
React.useEffect(() => {
;(async () => {
try {
const isMobileOrTablet = window.isMobileOrTablet
if (isMobileOrTablet) {
setIsSmooth(false)
return
}
if (!scrollContainerRef.current) {
setIsSmooth(false)
return
}
const LocomotiveScroll = (await import('locomotive-scroll')).default
const locoScroll = new LocomotiveScroll({
el: scrollContainerRef.current,
smooth: true,
lerp: lerpScroll,
firefoxMultiplier: 100
})
locomotiveScrollRef.current = locoScroll
setIsSmooth(true)
} catch (e) {
console.error(e)
} finally {
setIsReady(true) // Re-render the context
}
})()
return () => {
locomotiveScrollRef.current?.destroy()
}
}, [])
React.useEffect(() => {
locomotiveScrollRef.current?.update()
}, [height, width])
return (
<LocomotiveScrollContext.Provider
value={{ scroll: locomotiveScrollRef.current, isSmooth, isReady }}
>
<div
ref={mergeRefs([scrollContainerRef, ref])}
className="bg-black-200 scroll-container"
data-scroll-container
>
<LocomotiveScrollScripts />
{children}
</div>
</LocomotiveScrollContext.Provider>
)
}
export const useLocomotiveScroll = () => {
const ctx = React.useContext(LocomotiveScrollContext)
if (ctx === undefined) {
throw new Error('useLocomotiveScroll: Context not found')
}
return ctx
}

View File

@ -1,36 +0,0 @@
/* eslint-disable no-useless-escape */
import Script from 'next/script'
import * as React from 'react'
export const tabletBreakpoint = 1024
declare global {
interface Window {
isMobileOrTablet: boolean
}
}
export const LocomotiveScrollScripts = React.memo(() => (
<>
<Script
dangerouslySetInnerHTML={{
__html: `
function checkIfMobileOrTablet() {
const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) || window.innerWidth < ${tabletBreakpoint};
const isTablet = isMobile && window.innerWidth >= ${tabletBreakpoint};
const testSubject = navigator.userAgent||navigator.vendor||window.opera
const reg1 = new RegExp("(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk")
const reg2 = new RegExp("1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-")
return isMobile || isTablet || reg1.test(testSubject) || reg2.test(testSubject.substr(0,4))
};
window.isMobileOrTablet = checkIfMobileOrTablet();
if(!window.isMobileOrTablet) {
document.documentElement.classList.add('has-scroll-smooth')
}
`
}}
/>
</>
))

View File

@ -1,16 +0,0 @@
import * as React from 'react'
export const ScrollSectionBox = React.forwardRef<
HTMLDivElement,
JSX.IntrinsicElements['div'] & { disabled?: boolean }
>(({ children, disabled, ...rest }, ref) => {
return (
<div
{...rest}
{...(!disabled ? { 'data-scroll-section': true } : {})}
ref={ref}
>
{children}
</div>
)
})

View File

@ -1,228 +0,0 @@
declare module 'locomotive-scroll' {
export function getParents(elem: Element): Element[]
export function queryClosestParent(
elem: Element,
selector: string
): Element | null
export function transform(el: Element, transformValue: string): void
export function getTranslate(el: Element): Vector2
export type Vector2 = {
x: number
y: number
}
interface ScrollToOptions {
/**
* Defines an offset from your target. E.g. -100 if you want to scroll 100 pixels above your target.
*/
offset?: number | string
/**
* Defines the duration of the scroll animation in milliseconds. Defaults to 1000.
*/
duration?: number
/**
* An array of 4 floats between 0 and 1 defining the bezier curve for the animation's easing.
*
* Defaults to `[0.25, 0.00, 0.35, 1.00]`
*
* See http://greweb.me/bezier-easing-editor/example/
*
* Keep in mind this will also be affected by the lerp unless you set `disableLerp` to `true`.
*/
easing?: [number, number, number, number]
/**
* Lerp effect won't be applied if set to true.
*/
disableLerp?: boolean
/**
* Called when scrollTo completes (note that it won't wait for lerp to stabilize).
*/
callback?: () => void
}
export interface LocomotiveScrollOptions {
/** Scroll container element. */
el?: Element
/** Data attribute prefix (data-scroll-xxxx). */
name?: string
elMobile?: Element
/**
* Global in-view trigger offset : [bottom,top]
* Use a string with % to use a percentage of the viewport height.
* Use a numeric value for absolute pixels unit.
*/
offset?: [number, number]
/**
* Repeat in-view detection.
*/
repeat?: boolean
/**
* Smooth scrolling.
*/
smooth?: boolean
/**
* An object defining the initial scroll coordinates on a smooth instance. For example: { x: 0, y: 1000 }
*/
initPosition?: { x: number; y: number }
/**
* Scroll direction: vertical or horizontal.
*/
direction?: 'vertical' | 'horizontal'
/**
* Linear interpolation (lerp) intensity. Float between 0 and 1.
* This defines the "smoothness" intensity. The closer to 0, the smoother.
*/
lerp?: number
/**
* Add direction to scroll event.
*/
getDirection?: boolean
/**
* Add speed to scroll event.
*/
getSpeed?: boolean
/**
* Element in-view class.
*/
class?: string
/**
* Initialize class.
*/
initClass?: string
/**
* Is scrolling class.
*/
scrollingClass?: string
/**
* Is dragging class.
*/
draggingClass?: string
/**
* Has smooth scrolling class.
*/
smoothClass?: string
/**
* Scrollbar element class.
*/
scrollbarClass?: string
/**
* Specifies the container element for the scrollbar to be appended in. If false, scrollbar will be appended to the body.
*/
scrollbarContainer?: Element | false
/**
* Factor applied to the scroll delta, allowing to boost/reduce scrolling speed (regardless of the platform).
*/
multiplier?: number
/**
* Boost scrolling speed of Firefox on Windows.
*/
firefoxMultiplier?: number
/**
* Multiply touch action to scroll faster than finger movement.
*/
touchMultiplier?: number
/**
* By default locomotive-scroll listens for scroll events only on the scroll container (`el` option). With this option set to true, it listens on the whole document instead.
*/
scrollFromAnywhere?: boolean
/**
* Defines which gesture direction(s) scrolls in your instance. You can use:
* - `vertical`
* - `horizontal`
* - `both`
*/
gestureDirection?: 'vertical' | 'horizontal' | 'both'
/**
* Object allowing to override some options for a particular context. You can specify:
* - `smooth`
* - `direction`
* - `horizontalGesture`
*
* For tablet context you can also define breakpoint (integer, defaults to 1024) to set the max-width breakpoint for tablets.
*/
tablet?: {
smooth?: boolean
direction?: 'vertical' | 'horizontal'
horizontalGesture?: boolean
breakpoint?: number
}
/**
* Object allowing to override some options for a particular context. You can specify:
* - `smooth`
* - `direction`
* - `horizontalGesture`
*
* For tablet context you can also define breakpoint (integer, defaults to 1024) to set the max-width breakpoint for tablets.
*/
smartphone?: {
smooth?: boolean
direction?: 'vertical' | 'horizontal'
horizontalGesture?: boolean
}
/**
* Allows to reload the page when switching between `desktop`, `tablet` and `smartphone` contexts. It can be useful if your page changes a lot between contexts and you want to reset everything.
*/
reloadOnContextChange?: boolean
/**
* Sets `history.scrollRestoration = 'manual'` and calls `window.scrollTo(0, 0)` on locomotive-scroll init in Native Class. Useful if you use transitions with native scrolling, otherwise we advise to set it to `false` if you don't want to break History API's scroll restoration feature.
*/
resetNativeScroll?: boolean
}
export type EventHandler = (data: {
currentElements: Record<string, unknown>
delta: { x: number; y: number }
limit: { x: number; y: number }
scroll: { x: number; y: number }
speed: number
}) => void
export default class LocomotiveScroll implements LocomotiveScrollOptions {
constructor(options?: LocomotiveScrollOptions)
/**
* Reinitializes the scroll.
*/
init(): void
/**
* Scroller element.
*/
el: HTMLElement
/**
* Updates all element positions.
*/
update(): void
/**
* Destroys the scroll events.
*/
destroy(): void
/**
* Restarts the scroll events.
*/
start(): void
/**
* Stops the scroll events.
*/
stop(): void
/**
* Scroll to a target.
* @param target Defines where you want to scroll.
* @param options Settings object.
*/
scrollTo(
target: Node | string | 'top' | 'bottom' | number,
options?: ScrollToOptions
): void
/**
* todo, type this
*/
on(event: 'scroll', handler: EventHandler): void
/**
* todo, type this
*/
off(event: 'scroll', handler: EventHandler): void
}
export { LocomotiveScroll as Scroll }
}

View File

@ -1,16 +0,0 @@
type ParallaxPresets = 'up' | 'down'
export function parallax(speed: number | ParallaxPresets) {
let speedValue = speed
switch (speed) {
case 'up':
speedValue = 0.6
break
case 'down':
speedValue = -0.6
break
default:
break
}
return { 'data-scroll': true, 'data-scroll-speed': speedValue }
}