change prop names for clarity

This commit is contained in:
Sudev Kiyada 2026-01-09 12:22:01 +05:30
parent 83ab2f9224
commit db16e6630d
Failed to extract signature
6 changed files with 63 additions and 60 deletions

View file

@ -48,7 +48,7 @@
let normalisedScrollProgress = $derived( let normalisedScrollProgress = $derived(
map( map(
componentState.scrollProgress, componentState.mappedProgress,
componentState.clampStart ?? 0, componentState.clampStart ?? 0,
componentState.clampEnd ?? 1, componentState.clampEnd ?? 1,
0, 0,
@ -58,7 +58,7 @@
let normalisedProgress = $derived( let normalisedProgress = $derived(
map( map(
componentState.progress, componentState.easedProgress,
componentState.clampStart ?? 0, componentState.clampStart ?? 0,
componentState.clampEnd ?? 1, componentState.clampEnd ?? 1,
0, 0,
@ -120,22 +120,21 @@
</summary> </summary>
<div class="state-debug"> <div class="state-debug">
<!-- --> <!-- -->
<p>Raw progress:</p> <p>Progress:</p>
<div style="display: flex; flex-direction: column; gap: 4px;"> <div style="display: flex; flex-direction: column; gap: 4px;">
<p class="state-value"> <p class="state-value">
<span class="tag">{componentState.rawProgress}</span> {componentState.progress}
</p> </p>
</div> </div>
<!-- --> <!-- -->
<!-- --> <p>Mapped progress:</p>
<p>Scroll progress:</p>
<div style="display: flex; flex-direction: column; gap: 4px;"> <div style="display: flex; flex-direction: column; gap: 4px;">
<p class="state-value progress-value"> <p class="state-value progress-value">
{@render triggerPoints()} {@render triggerPoints()}
<span <span
class="progress-stop" class="progress-stop"
style={`left: ${normalisedScrollProgress * 100}%; transform: translateX(-50%);`} style={`left: ${normalisedScrollProgress * 100}%; transform: translateX(-50%);`}
>{fmt.format(componentState.scrollProgress)}</span >{fmt.format(componentState.mappedProgress)}</span
> >
&nbsp; &nbsp;
</p> </p>
@ -146,7 +145,7 @@
</div> </div>
</div> </div>
<!-- --> <!-- -->
<p>Progress:</p> <p>Eased Progress:</p>
<div style="display: flex; flex-direction: column; gap: 4px;"> <div style="display: flex; flex-direction: column; gap: 4px;">
<p class="state-value progress-value"> <p class="state-value progress-value">
{#if componentState.stops.length > 0} {#if componentState.stops.length > 0}
@ -159,7 +158,7 @@
<span <span
class="progress-stop" class="progress-stop"
style={`left: ${normalisedProgress * 100}%; transform: translateX(-50%);`} style={`left: ${normalisedProgress * 100}%; transform: translateX(-50%);`}
>{fmt.format(componentState.progress)}</span >{fmt.format(componentState.easedProgress)}</span
> >
&nbsp; &nbsp;
</p> </p>

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. > 💡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 `Raw progress` indicates the vertical progress with values in the range 0...1 indicating the content being locked. The `Scroll Progress` value indicates the vertical progress mapped to clampStart and clampEnd values. By default these are 0 and 1 respectively. Finally, the `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).
[Demo](?path=/story/components-graphics-horizontalscroller--demo) [Demo](?path=/story/components-graphics-horizontalscroller--demo)
@ -323,7 +323,7 @@ You can also integrate HorizontalScroller with `ScrollerBase` for a horizontal s
width="fluid" width="fluid"
height="100lvh" height="100lvh"
direction="right" direction="right"
bind:scrollProgress={progress} bind:progress
scrubbed scrubbed
stops={[0.5]} stops={[0.5]}
handleScroll={false} handleScroll={false}

View file

@ -49,8 +49,8 @@
args={{ args={{
children: DemoSnippet, children: DemoSnippet,
height: '200lvh', height: '200lvh',
clampStart: -0.5, mappedStart: -0.5,
clampEnd: 1.5, mappedEnd: 1.5,
showDebugInfo: true, showDebugInfo: true,
scrubbed: true, scrubbed: true,
stops: [0, 1], stops: [0, 1],

View file

@ -13,7 +13,7 @@
/** Height of the scroller container in CSS `vh` units. Set it to `100lvh` when using inside ScrollerBase. */ /** Height of the scroller container in CSS `vh` units. Set it to `100lvh` when using inside ScrollerBase. */
height?: string; height?: string;
/** Bindable progress value. Ideal range: `[0-1]`. Bind ScrollerBase's progress to this prop. */ /** Bindable progress value. Ideal range: `[0-1]`. Bind ScrollerBase's progress to this prop. */
scrollProgress?: number; progress?: number;
/** Direction of movement*/ /** Direction of movement*/
direction?: 'left' | 'right'; direction?: 'left' | 'right';
/** Content to scroll*/ /** Content to scroll*/
@ -31,9 +31,9 @@
/** Whether to show debug info */ /** Whether to show debug info */
showDebugInfo?: boolean; showDebugInfo?: boolean;
/** Modified starting scale. Default is 0 */ /** Modified starting scale. Default is 0 */
clampStart?: number; mappedStart?: number;
/** Modified ending scale. Default is 1 */ /** Modified ending scale. Default is 1 */
clampEnd?: number; mappedEnd?: number;
} }
let { let {
@ -41,9 +41,9 @@
class: cls = '', class: cls = '',
height = '200lvh', height = '200lvh',
direction = 'right', direction = 'right',
scrollProgress = $bindable(0), progress = $bindable(0),
clampStart = 0, mappedStart = 0,
clampEnd = 1, mappedEnd = 1,
children, children,
stops = [], stops = [],
handleScroll = true, handleScroll = true,
@ -54,22 +54,22 @@
}: Props = $props(); }: Props = $props();
let componentState = $derived.by(() => ({ let componentState = $derived.by(() => ({
scrollProgress, progress,
progress: progressTween.current, mappedProgress,
easedProgress: easedProgress.current,
direction, direction,
clampStart, mappedStart,
clampEnd, mappedEnd,
triggerStops: scrubbed ? stops : divisions, triggerStops: scrubbed ? stops : divisions,
stops: stops, stops: stops,
handleScroll, handleScroll,
scrubbed, scrubbed,
easing: ease, easing: ease,
duration, duration,
rawProgress,
})); }));
let progressTween: Tween<number> = $state( let easedProgress: Tween<number> = $state(
new Tween(clampStart, { duration, easing: ease }) new Tween(mappedStart, { duration, easing: ease })
); );
let container: HTMLDivElement | undefined = $state(undefined); let container: HTMLDivElement | undefined = $state(undefined);
let containerHeight: number = $state(0); let containerHeight: number = $state(0);
@ -78,19 +78,23 @@
let contentWidth: number = $state(0); let contentWidth: number = $state(0);
let screenHeight: number = $state(0); let screenHeight: number = $state(0);
let divisions: number[] = $derived( let divisions: number[] = $derived(
[...stops, clampStart, clampEnd].sort((a, b) => a - b) [...stops, mappedStart, mappedEnd].sort((a, b) => a - b)
); );
let divisionsCount: number = $derived.by(() => divisions.length - 1); let divisionsCount: number = $derived.by(() => divisions.length - 1);
let rawProgress: number | 'user defined' = $state(0); let mappedProgress: number = $state(0);
// handles horizontal translation of the content // handles horizontal translation of the content
let translateX: number = $derived.by(() => { let translateX: number = $derived.by(() => {
let processedProgress = clamp(progressTween.current, clampStart, clampEnd); let processedProgress = clamp(
easedProgress.current,
mappedStart,
mappedEnd
);
let normalisedProgress = processedProgress; let normalisedProgress = processedProgress;
normalisedProgress = normalisedProgress =
direction === 'right' ? processedProgress : clampEnd - processedProgress; direction === 'right' ? processedProgress : mappedEnd - processedProgress;
const translate = -(contentWidth - containerWidth) * normalisedProgress; const translate = -(contentWidth - containerWidth) * normalisedProgress;
@ -98,8 +102,8 @@
}); });
onMount(() => { onMount(() => {
// Initialize scrollProgress to clampStart on mount // Initialize progress to mappedStart on mount
scrollProgress = clampStart; progress = mappedStart;
}); });
const scrollListener: Action = () => { const scrollListener: Action = () => {
@ -108,9 +112,9 @@
passive: true, passive: true,
}); });
} else { } else {
// set rawProgress to user defined when handleScroll is false // set mappedProgress to user defined when handleScroll is false
rawProgress = 'user defined'; // mappedProgress = 'user defined';
window.addEventListener('scroll', () => handleStops(scrollProgress), { window.addEventListener('scroll', () => handleStops(progress), {
passive: true, passive: true,
}); });
} }
@ -120,19 +124,19 @@
function handleScrollFunction() { function handleScrollFunction() {
if (!container) return; if (!container) return;
rawProgress = progress =
(-container?.offsetTop + window?.scrollY) / (-container?.offsetTop + window?.scrollY) /
(containerHeight - screenHeight); (containerHeight - screenHeight);
handleStops(rawProgress); handleStops(progress);
} }
// updates progressTween based on stops and scrubbed settings // updates easedProgress based on stops and scrubbed settings
function handleStops(rawProgress: number) { function handleStops(rawProgress: number) {
scrollProgress = map(rawProgress, 0, 1, clampStart, clampEnd); mappedProgress = map(rawProgress, 0, 1, mappedStart, mappedEnd);
if (!stops || stops.length === 0) { if (!stops || stops.length === 0) {
progressTween.set(ease(map(rawProgress, 0, 1, clampStart, clampEnd)), { easedProgress.set(ease(map(rawProgress, 0, 1, mappedStart, mappedEnd)), {
duration: 0, duration: 0,
}); });
return; return;
@ -141,8 +145,8 @@
if (!scrubbed) { if (!scrubbed) {
for (let i = 0; i < divisions.length; i++) { for (let i = 0; i < divisions.length; i++) {
if ( if (
scrollProgress > divisions[i] && mappedProgress > divisions[i] &&
scrollProgress <= mappedProgress <=
(divisions[i + 1] ?? divisions[divisions.length - 1]) (divisions[i + 1] ?? divisions[divisions.length - 1])
) { ) {
const midPoint = const midPoint =
@ -151,27 +155,27 @@
divisions[i]) * divisions[i]) *
0.5; 0.5;
if ( if (
scrollProgress >= midPoint && mappedProgress >= midPoint &&
progressTween.target !== easedProgress.target !==
(divisions[i + 1] ?? divisions[divisions.length - 1]) (divisions[i + 1] ?? divisions[divisions.length - 1])
) { ) {
progressTween.set( easedProgress.set(
divisions[i + 1] ?? divisions[divisions.length - 1] divisions[i + 1] ?? divisions[divisions.length - 1]
); );
return; return;
} else if ( } else if (
scrollProgress < midPoint && mappedProgress < midPoint &&
progressTween.target !== divisions[i] easedProgress.target !== divisions[i]
) { ) {
progressTween.set(divisions[i]); easedProgress.set(divisions[i]);
return; return;
} }
} else if ( } else if (
scrollProgress < mappedProgress <
divisions[0] + (divisions[1] ?? clampStart) * 0.5 divisions[0] + (divisions[1] ?? mappedStart) * 0.5
) { ) {
if (progressTween.target !== divisions[0]) { if (easedProgress.target !== divisions[0]) {
progressTween.set(divisions[0]); easedProgress.set(divisions[0]);
return; return;
} }
} else { } else {
@ -182,19 +186,19 @@
for (let i = 0; i < divisions.length; i++) { for (let i = 0; i < divisions.length; i++) {
let oneByDivCount = 1 / divisionsCount; let oneByDivCount = 1 / divisionsCount;
let normalStart = i == 0 ? clampStart : oneByDivCount * i; let normalStart = i == 0 ? mappedStart : oneByDivCount * i;
let normalEnd = let normalEnd =
i == divisionsCount - 1 ? clampEnd : oneByDivCount * (i + 1); i == divisionsCount - 1 ? mappedEnd : oneByDivCount * (i + 1);
if (scrollProgress >= normalStart && scrollProgress < normalEnd) { if (mappedProgress >= normalStart && mappedProgress < normalEnd) {
let stopStart = divisions[i]; let stopStart = divisions[i];
let stopEnd = divisions[i + 1] ?? clampEnd; let stopEnd = divisions[i + 1] ?? mappedEnd;
let newProgressVal = let newProgressVal =
stopStart + stopStart +
ease(map(scrollProgress, normalStart, normalEnd, 0, 1)) * ease(map(mappedProgress, normalStart, normalEnd, 0, 1)) *
(stopEnd - stopStart); (stopEnd - stopStart);
progressTween.set(newProgressVal, { duration: 0 }); easedProgress.set(newProgressVal, { duration: 0 });
return; return;
} else { } else {
continue; continue;

View file

@ -1,6 +1,6 @@
<div style="width: 400vw; height: 100lvh;"> <div style="width: 400vw; height: 100lvh;">
<img <img
src="https://picsum.photos/1200/640?t=1" src="https://picsum.photos/2400/1200?t=1"
alt="Sample" alt="Sample"
style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0; background-color: #ccc;" style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0; background-color: #ccc;"
/> />

View file

@ -35,7 +35,7 @@
<HorizontalScroller <HorizontalScroller
height="100lvh" height="100lvh"
direction="right" direction="right"
bind:scrollProgress={progress} bind:progress
scrubbed scrubbed
stops={[0.5]} stops={[0.5]}
handleScroll={false} handleScroll={false}