clamp to mapped props

This commit is contained in:
Sudev Kiyada 2026-01-09 12:42:51 +05:30
parent db16e6630d
commit 5e807ad333
Failed to extract signature
5 changed files with 63 additions and 32 deletions

View file

@ -49,8 +49,8 @@
let normalisedScrollProgress = $derived(
map(
componentState.mappedProgress,
componentState.clampStart ?? 0,
componentState.clampEnd ?? 1,
componentState.mappedStart ?? 0,
componentState.mappedEnd ?? 1,
0,
1
)
@ -59,8 +59,8 @@
let normalisedProgress = $derived(
map(
componentState.easedProgress,
componentState.clampStart ?? 0,
componentState.clampEnd ?? 1,
componentState.mappedStart ?? 0,
componentState.mappedEnd ?? 1,
0,
1
)
@ -69,8 +69,8 @@
function mappedStop(stop: number): number {
return map(
stop,
componentState.clampStart ?? 0,
componentState.clampEnd ?? 1,
componentState.mappedStart ?? 0,
componentState.mappedEnd ?? 1,
0,
1
);

View file

@ -18,7 +18,7 @@ To use the `HorizontalScroller` component, import it and provide the children co
> 💡TIP: Use `lvh` or `svh` units instead of `vh` unit for the height, as [these units](https://www.w3.org/TR/css-values-4/#large-viewport-size) are more reliable on mobile or other devices where elements such as the address bar toggle between being shown and hidden.
Use `showDebugInfo` prop to visualize the scroll progress and other useful debug information. The `Progress` indicates the vertical progress with values in the range 0...1 indicating the content being locked or a user-fed value to control the horizontal scroll position. The `Mapped Progress` value indicates the vertical progress mapped to mappedStart and mappedEnd values. By default these are 0 and 1 respectively. Finally, the `Eased Progress` value indicates the horizontal scroll progress after applying stops and easing (if any).
Use `showDebugInfo` prop to visualize the scroll progress and other useful debug information. The `Progress` indicates the vertical progress with values in the range 0...1 indicating the content being locked or a user-fed value to control the horizontal scroll position. The `Mapped Progress` value indicates the vertical progress mapped to mappedStart and mappedEnd values. By default these are 0 and 1 respectively. Finally, the `Eased Progress` value indicates the horizontal scroll progress after applying stops and easing (if any). `Eased Progress` accurately reflects the transition of horizontal scroll position.
[Demo](?path=/story/components-graphics-horizontalscroller--demo)
@ -61,7 +61,6 @@ Feel free to toggle `scrubbed` prop here to see the difference.
import { quartInOut } from 'svelte/easing';
</script>
<!-- Optionally set `height` to adjust scroll height -->
<HorizontalScroller
height="200lvh"
stops={[0.2, 0.5, 0.6, 0.7]}
@ -83,6 +82,40 @@ Feel free to toggle `scrubbed` prop here to see the difference.
</HorizontalScroller>
```
## Extended boundary
`HorizontalScroller` also provides `mappedStart` and `mappedEnd` props to extend the horizontal scroll boundaries beyond the default 0 to 1 range. This is useful when you want to create an overscroll effect or have more control over the horizontal scroll range. By default these values are set to 0 and 1 respectively.
[Demo](?path=/story/components-graphics-horizontalscroller--extended-boundary)
```svelte
<script lang="ts">
import { HorizontalScroller } from '@reuters-graphics/graphics-components';
import { quartInOut } from 'svelte/easing';
</script>
<HorizontalScroller
height="200lvh"
mappedStart={-0.5}
mappedEnd={1.5}
stops={[0, 1]}
scrubbed={true}
easing={quartInOut}
direction="right"
showDebugInfo
>
<div style="width: 200vw; height: 100lvh;">
<!-- Content wider than 100vw -->
<!-- Only the top 100lvh will be visible -->
<img
src="path/to/wide-image.jpg"
alt="alt text"
style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0;"
/>
</div>
</HorizontalScroller>
```
## With custom child components
You can create a horizontal stack of any components and pass it as children to the `HorizontalScroller`. Here's an example of using `DatawrapperChart`, `Headline` and ai2svelte components inside the scroller.

View file

@ -44,24 +44,6 @@
{/snippet}
</Story>
<Story
name="Extended boundaries"
args={{
children: DemoSnippet,
height: '200lvh',
mappedStart: -0.5,
mappedEnd: 1.5,
showDebugInfo: true,
scrubbed: true,
stops: [0, 1],
easing: quartInOut,
}}
>
{#snippet children(args)}
<DemoComponent {...args}></DemoComponent>
{/snippet}
</Story>
<Story
name="With stops"
args={{
@ -82,6 +64,24 @@
{/snippet}
</Story>
<Story
name="Extended boundary"
args={{
children: DemoSnippet,
height: '200lvh',
mappedStart: -0.5,
mappedEnd: 1.5,
showDebugInfo: true,
scrubbed: true,
stops: [0, 1],
easing: quartInOut,
}}
>
{#snippet children(args)}
<DemoComponent {...args}></DemoComponent>
{/snippet}
</Story>
<Story
name="Custom children"
args={{

View file

@ -102,8 +102,8 @@
});
onMount(() => {
// Initialize progress to mappedStart on mount
progress = mappedStart;
// Initialize mappedProgress to mappedStart on mount
mappedProgress = mappedStart;
});
const scrollListener: Action = () => {
@ -112,8 +112,6 @@
passive: true,
});
} else {
// set mappedProgress to user defined when handleScroll is false
// mappedProgress = 'user defined';
window.addEventListener('scroll', () => handleStops(progress), {
passive: true,
});

View file

@ -1,7 +1,7 @@
<div style="width: 400vw; height: 100lvh;">
<img
src="https://picsum.photos/2400/1200?t=1"
alt="Sample"
src="https://images.unsplash.com/photo-1533282960533-51328aa49826?q=80&w=3642&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt="An ultra wide scenic view of cityscape"
style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0; background-color: #ccc;"
/>
</div>