seitu
Version:
90 lines • 2.73 kB
text/typescript
import { i as Subscribable, r as ServerReadable } from "../../index-B0IeflOl.mjs";
//#region src/web/scroll-state/index.d.ts
type ScrollDirection = 'vertical' | 'horizontal' | 'both';
interface ScrollStateEdge {
reached: boolean;
remaining: number;
}
interface ScrollStateValue {
top: ScrollStateEdge;
bottom: ScrollStateEdge;
left: ScrollStateEdge;
right: ScrollStateEdge;
}
interface ScrollStateThreshold {
top?: number;
bottom?: number;
left?: number;
right?: number;
}
interface ScrollState extends Subscribable<ScrollStateValue>, ServerReadable<ScrollStateValue> {}
interface ScrollStateOptions {
/**
* Element to observe, or a getter. The getter is resolved once, when the
* first subscriber attaches; a later change to what it returns is not
* tracked. In React pass the element from a callback ref and list it in
* `deps` so the subscription is rebuilt on mount, unmount, and remount.
*/
element: Element | null | (() => Element | null);
/**
* @default 'both'
*/
direction?: ScrollDirection;
/**
* @default 0
*/
threshold?: number | ScrollStateThreshold;
}
/**
* Tracks an element's scroll position relative to each edge. Notifies on
* `scroll` and `ResizeObserver` (not inner content growth — call `'~'.notify()`
* after that). The element getter is resolved on first subscribe; recreate the
* handle if the element identity changes (React: `deps`).
*
* @example Vanilla
* ```ts twoslash
* import { createScrollState } from 'seitu/web'
*
* const scroll = createScrollState({
* element: document.querySelector('.container'),
* direction: 'vertical',
* threshold: 10,
* })
*
* scroll.subscribe(state => {
* console.log(state.top.reached)
* console.log(state.top.remaining)
* console.log(state.bottom.reached)
* console.log(state.bottom.remaining)
* })
*
* const state = scroll.get()
* console.log(state)
* ```
*
* @example React (callback ref)
* ```tsx twoslash title="page.tsx"
* 'use client'
*
* import * as React from 'react'
* import { createScrollState } from 'seitu/web'
* import { useSubscription } from 'seitu/react'
*
* function Layout() {
* const [ref, setRef] = React.useState<HTMLDivElement | null>(null)
* const state = useSubscription(() => createScrollState({
* element: ref,
* threshold: 10,
* }), { deps: [ref] })
*
* return (
* <div ref={setRef}>
* {state.top.reached ? 'at the top' : 'scrolled'}
* </div>
* )
* }
* ```
*/
declare function createScrollState(options: ScrollStateOptions): ScrollState;
//#endregion
export { ScrollDirection, ScrollState, ScrollStateEdge, ScrollStateOptions, ScrollStateThreshold, ScrollStateValue, createScrollState };