diff --git a/src/primitives/types.ts b/src/primitives/types.ts index e84b6ba5..64466285 100644 --- a/src/primitives/types.ts +++ b/src/primitives/types.ts @@ -1,5 +1,6 @@ import type { ElementNode, NodeProps, NodeStyles } from '@lightningtv/solid'; import type { KeyHandler } from '@lightningtv/core/focusManager'; + export type OnSelectedChanged = ( this: NavigableElement, selectedIndex: number, @@ -7,6 +8,7 @@ export type OnSelectedChanged = ( active: ElementNode, lastSelectedIndex?: number, ) => void; + export interface NavigableProps extends NodeProps { /** function to be called when the selected of the component changes */ onSelectedChanged?: OnSelectedChanged; @@ -40,6 +42,12 @@ export interface NavigableProps extends NodeProps { * Wrap the row so active goes back to the beginning of the row */ wrap?: boolean; + + /** function to be called when scrolled */ + onScrolled?: () => void; + + /** function to be called when unscrolled, back to its initial position */ + onUnscrolled?: () => void; } // @ts-expect-error animationSettings is not identical - weird diff --git a/src/primitives/utils/withScrolling.ts b/src/primitives/utils/withScrolling.ts index ad5dea3f..e744a18d 100644 --- a/src/primitives/utils/withScrolling.ts +++ b/src/primitives/utils/withScrolling.ts @@ -11,8 +11,11 @@ export interface ScrollableElement extends ElementNode { selected: number; offset?: number; endOffset?: number; + onScrolled?: () => void; + onUnscrolled?: () => void; _targetPosition?: number; _screenOffset?: number; + _initialPosition?: number; } // From the renderer, not exported @@ -48,6 +51,10 @@ export function withScrolling(isRow: boolean) { ) return; + if (componentRef._initialPosition === undefined) { + componentRef._initialPosition = componentRef[axis]; + } + const lng = componentRef.lng as INode; const screenSize = isRow ? lng.stage.root.width : lng.stage.root.height; // Determine if movement is incremental or decremental @@ -156,6 +163,21 @@ export function withScrolling(isRow: boolean) { // Update position if it has changed if (componentRef[axis] !== nextPosition) { + if ( + componentRef.onScrolled && + componentRef[axis] === componentRef._initialPosition + ) { + componentRef.onScrolled(); + } + + if ( + componentRef.onUnscrolled && + componentRef._targetPosition !== componentRef._initialPosition && + componentRef._initialPosition === nextPosition + ) { + componentRef.onUnscrolled(); + } + componentRef[axis] = nextPosition; // Store the new position to keep track during animations componentRef._targetPosition = nextPosition;