Skip to content

Commit

Permalink
Fix scroll actions
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaitanLyss committed Jul 24, 2024
1 parent cf6e8ee commit 6a47fc7
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@selenite/commons",
"version": "0.12.1",
"version": "0.12.2",
"scripts": {
"dev": "npm run wasm && vite dev",
"wasm": "wasm-pack build ./selenite-commons-rs --target web",
Expand Down
50 changes: 43 additions & 7 deletions src/lib/actions/scroll.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { clamp, debounce } from 'lodash-es';
import type { Action } from 'svelte/action';
import { tweened } from 'svelte/motion';
import { get } from 'svelte/store';

/**
* Adds horizontal scrolling to an element.
*
* This action removes the needs to press ctrl or right to scroll
* horizontally.
* @param node - The element to add horizontal scrolling to.
* @param params - The duration of the scroll animation.
* @returns svelte action
Expand All @@ -12,34 +16,66 @@ export const horizontalScroll: Action<HTMLElement, { duration?: number } | undef
node,
{ duration = 150 } = {}
) => {
let isActionScroll = false;
let scroll = tweened(node.scrollLeft, {
duration,
interpolate: (a, b) => (t) => a + (b - a) * t
});

let isFirst = true;
scroll.subscribe((value) => {
if (isFirst) {
isFirst = false;
return;
}
if (!isActionScroll)return;
node.scrollLeft = value;
});

const stopClamingScroll = debounce(() => {
isActionScroll = false;
}, duration, {leading: false, trailing: true})

const handleWheel = (e: WheelEvent) => {
if (e.deltaY === 0) return;
scroll.set(get(scroll) + e.deltaY);
isActionScroll = true;
const firstChildRect = node.firstElementChild?.getBoundingClientRect();
const lastChildRect = node.lastElementChild?.getBoundingClientRect();
if (!firstChildRect || !lastChildRect) {
console.warn("Horizontal scroll: No children found");
return
}
// Ensure offset stays valid
const maxOffset = lastChildRect.width + lastChildRect.x - firstChildRect.x;
scroll.set(clamp(node.scrollLeft + e.deltaY, 0, maxOffset));
e.preventDefault();
stopClamingScroll();
};

node.addEventListener('wheel', handleWheel, { passive: false });


node.addEventListener('scroll', (e) => {
if (!isActionScroll) {
scroll.set(node.scrollLeft);
}
})
return {
destroy() {
node.removeEventListener('wheel', handleWheel);
}
};
};


/**
/**
* Scrolls into view an element.
*/
export const scrollIntoView: Action<HTMLElement, boolean | undefined> = (node, enabled) => {
if (enabled || enabled === undefined)
node.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
}
const parent = node.parentElement;
if (!parent) return;

if (!enabled) return;

const parentRect = parent.getBoundingClientRect()
const nodeRect = node.getBoundingClientRect()
parent.scrollTo({ left: nodeRect.left - parentRect.left, top: nodeRect.top - parentRect.top, behavior: 'smooth' });
};
19 changes: 17 additions & 2 deletions src/routes/scroll/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
<script lang="ts">
import {horizontalScroll} from '$lib'
import {horizontalScroll, scrollIntoView} from '$lib'
import { range } from 'lodash-es';
</script>

<div class="w-32 flex gap-2 overflow-x-auto" use:horizontalScroll>
<div class="w-32 flex gap-2 overflow-x-auto m-auto" use:horizontalScroll>
{#each range(100) as i}
<span>{i}</span>
{/each}
</div>
<div class="w-32 flex gap-2 overflow-x-auto m-auto" use:horizontalScroll>
{#each range(100) as i}
<span use:scrollIntoView={i === 99}>{i}</span>
{/each}
</div>
<div class="w-32 flex gap-2 overflow-x-auto m-auto" use:horizontalScroll>
{#each range(100) as i}
<span use:scrollIntoView={i === 57}>{i}</span>
{/each}
</div>
<div class="w-32 flex gap-2 overflow-x-auto m-auto" use:horizontalScroll>
{#each range(100) as i}
<span use:scrollIntoView={i === 80}>{i}</span>

{/each}
</div>

0 comments on commit 6a47fc7

Please sign in to comment.