From 3bbff251dae7f078e9a764265436fb6145c20e72 Mon Sep 17 00:00:00 2001 From: Ilya Mitin Date: Wed, 28 Feb 2024 17:52:40 +0300 Subject: [PATCH] feat: horizontal scroll --- package.json | 2 +- src/actions/ScrollTo.ts | 12 ++++++++---- src/functions/scrolling.ts | 23 +++++++++++++---------- src/shared/scrolling.ts | 25 +++++++++++++++++++------ src/shared/smoothScroll.ts | 14 ++++++-------- src/shared/utils.ts | 5 +++-- src/types/options.ts | 12 +++++++++--- 7 files changed, 59 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 5ed2cfb..c10809b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte-scrolling", - "version": "1.3.0", + "version": "1.3.1", "description": "Scroll to given elements with smooth animation", "author": "Valmisson Grizorte", "license": "MIT", diff --git a/src/actions/ScrollTo.ts b/src/actions/ScrollTo.ts index c2af5f7..7fc135e 100644 --- a/src/actions/ScrollTo.ts +++ b/src/actions/ScrollTo.ts @@ -8,7 +8,10 @@ import scrolling from '../shared/scrolling' const elementsList = get(elements) // handle with scrolling -const handle = async (event: Event, options: ScrollToOptions): Promise => { +const handle = async ( + event: Event, + options: ScrollToOptions +): Promise => { if (!options.passive) event.preventDefault() const { ref, onDone, onStart } = options @@ -39,7 +42,8 @@ const handle = async (event: Event, options: ScrollToOptions): Promise => * @param options - The element reference or global options */ -const scrollTo = ( // eslint-disable-line @typescript-eslint/explicit-module-boundary-types +const scrollTo = ( + // eslint-disable-line @typescript-eslint/explicit-module-boundary-types node: HTMLElement, options: string | ScrollToOptions ) => { @@ -53,8 +57,8 @@ const scrollTo = ( // eslint-disable-line @typescript-eslint/explicit-module-bou } typeof options === 'string' - ? opts.ref = options - : opts = Object.assign(opts, options) + ? (opts.ref = options) + : (opts = Object.assign(opts, options)) opts.ref = sanitize(opts.ref) diff --git a/src/functions/scrolling.ts b/src/functions/scrolling.ts index 7e0a6f2..f6219ae 100644 --- a/src/functions/scrolling.ts +++ b/src/functions/scrolling.ts @@ -2,7 +2,7 @@ import { get } from 'svelte/store' import { elements } from '../store' import { getGlobalOptions } from '../internal/globalOptions' import { getElement, getPosition, sanitize } from '../shared/utils' -import type { GlobalOptions } from '../types/options' +import type { Coord, GlobalOptions } from '../types/options' import scrolling from '../shared/scrolling' const globalOptions = getGlobalOptions() @@ -17,7 +17,7 @@ export const scrollTop = async ( options?: Partial ): Promise => { const opts = Object.assign(globalOptions, options) - const endPosition = 0 + const endPosition = { x: 0, y: 0 } const { duration, offset, onStart, onDone } = opts @@ -44,13 +44,16 @@ export const scrollBottom = async ( const body = document.body const html = document.documentElement - const endPosition = Math.max( - body.scrollHeight, - body.offsetHeight, - html.scrollHeight, - html.clientHeight, - html.offsetHeight - ) + const endPosition = { + x: 0, + y: Math.max( + body.scrollHeight, + body.offsetHeight, + html.scrollHeight, + html.clientHeight, + html.offsetHeight + ) + } onStart && onStart({ offset, duration, endPosition }) @@ -103,7 +106,7 @@ export const scrollElement = async ( */ export const scrollPosition = async ( - position: number, + position: Coord, options?: Partial ): Promise => { if (!position || typeof position !== 'number') { diff --git a/src/shared/scrolling.ts b/src/shared/scrolling.ts index 3104e16..10310c2 100644 --- a/src/shared/scrolling.ts +++ b/src/shared/scrolling.ts @@ -1,20 +1,33 @@ import smoothScroll from './smoothScroll' import { getGlobalOptions } from '../internal/globalOptions' -import type { GlobalOptions } from '../types/options' +import type { Coord, GlobalOptions } from '../types/options' const globalOptions = getGlobalOptions() const scrolling = async ( - endPosition: number, + coord: Coord, opts: GlobalOptions ): Promise => { const { duration, easing, offset } = Object.assign(globalOptions, opts) - const start = window.pageYOffset - const end = endPosition + offset + const startY = window.pageYOffset + const startX = window.pageXOffset + const endX = coord.x + offset + const endY = coord.y - await smoothScroll({ start, end, duration, easing }, (position: number) => { - window.scroll(0, position) + await smoothScroll({ + start: { + x: startX, + y: startY + }, + end: { + x: endX, + y: endY + }, + duration, + easing + }, (coord: Coord) => { + window.scroll(coord.x, coord.y) }) } diff --git a/src/shared/smoothScroll.ts b/src/shared/smoothScroll.ts index 600fa37..c2ca467 100644 --- a/src/shared/smoothScroll.ts +++ b/src/shared/smoothScroll.ts @@ -1,4 +1,4 @@ -import type { SmoothOptions } from '../types/options' +import type { Coord, SmoothOptions } from '../types/options' const currentPosition = ( start: number, @@ -14,19 +14,17 @@ const currentPosition = ( const smoothScroll = async ( options: SmoothOptions, - callback: (positon: number) => void + callback: (coord: Coord) => void ): Promise => { - return new Promise(resolve => { + return new Promise((resolve) => { const { start, end, duration, easing } = options const clock = Date.now() const step = () => { const elapsed = Date.now() - clock - const position = currentPosition( - start, end, elapsed, duration, easing - ) - - callback(position) + const positionX = currentPosition(start.x, end.x, elapsed, duration, easing) + const positionY = currentPosition(start.y, end.y, elapsed, duration, easing) + callback({ x: positionX, y: positionY }) if (elapsed > duration) return resolve() diff --git a/src/shared/utils.ts b/src/shared/utils.ts index 45568ed..5bac72c 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -1,3 +1,4 @@ +import type { Coord } from 'src/types/options' import type { ElementReference } from '../types/reference' export const sanitize = (hash: string): string => { @@ -21,6 +22,6 @@ export const getElement = ( export const getPosition = ( element: HTMLElement -): number => { - return element.offsetTop +): Coord => { + return { y: element.offsetTop, x: element.offsetLeft } } diff --git a/src/types/options.ts b/src/types/options.ts index 6f738e5..942400c 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -1,8 +1,14 @@ + +export interface Coord { + x: number; + y: number +} + export interface HooksOptions { element?: HTMLElement, offset: number, duration: number, - endPosition: number + endPosition: Coord } export interface GlobalOptions { @@ -15,8 +21,8 @@ export interface GlobalOptions { } export interface SmoothOptions { - start: number - end: number + start: Coord; + end: Coord; duration: number easing: (t: number) => number }