import * as _angular_core from '@angular/core'; import { InjectionToken, Signal, Provider } from '@angular/core'; import * as forty_cdk_core from 'forty-cdk/core'; import { WritingDirection } from 'forty-cdk/core'; import * as forty_cdk_scroll_area from 'forty-cdk/scroll-area'; type ForScrollAreaType = 'auto' | 'always' | 'scroll' | 'hover'; type ForScrollbarOrientation = 'horizontal' | 'vertical'; /** * What a primary-button press on bare scrollbar track does: * - `'page'` — step one page toward the press and auto-repeat while held, * stopping when the thumb reaches the pointer (platform default). * - `'jump'` — centre the thumb on the press point, then scrub while held. * - `'none'` — the library ignores track presses entirely. */ type ForScrollAreaTrackPress = 'none' | 'page' | 'jump'; /** Read surface `[forScrollArea]` publishes through {@link FOR_SCROLL_AREA_CONTEXT}. */ interface ForScrollAreaContext { readonly type: Signal; readonly scrollHideDelay: Signal; readonly dir: Signal; /** Behaviour of a primary-button press on bare scrollbar track. */ readonly trackPress: Signal; /** ms a `trackPress="page"` hold waits before the first auto-repeat step. */ readonly trackPressRepeatDelay: Signal; /** ms between auto-repeat steps of a held `trackPress="page"` gesture. */ readonly trackPressRepeatInterval: Signal; /** The scrolling element (registered by `ForScrollAreaViewport`). */ readonly viewport: Signal; /** The content element (registered by `ForScrollAreaContent`, observed by the viewport). */ readonly content: Signal; /** Live scroll offset of the viewport. */ readonly scrollLeft: Signal; readonly scrollTop: Signal; /** Live size measurements of the viewport. */ readonly clientWidth: Signal; readonly clientHeight: Signal; readonly scrollWidth: Signal; readonly scrollHeight: Signal; /** True while the user is hovering anywhere on the root (for `type="hover"`). */ readonly hovering: Signal; /** True for a short window after the most recent scroll (for `type="scroll"`). */ readonly scrolling: Signal; registerViewport(el: HTMLElement | null): void; registerContent(el: HTMLElement): void; unregisterContent(el: HTMLElement): void; reportScroll(left: number, top: number): void; reportSize(clientW: number, clientH: number, scrollW: number, scrollH: number): void; noteUserScroll(): void; } declare const FOR_SCROLL_AREA_CONTEXT: InjectionToken; /** * Root of the custom-scrollbar primitive. Owns the viewport reference, * scroll geometry signals, and visibility state for the synthetic * scrollbars. * * Native scrollbars on the inner viewport are hidden via styles injected * by `[forScrollAreaViewport]` (the only place in forty-cdk that * imperatively touches CSS); the consumer styles `[forScrollAreaThumb]` * however they like. * * @example * ```html *
*
*
… long content …
*
*
*
*
*
*
*
*
*
* ``` */ declare class ForScrollArea implements ForScrollAreaContext { #private; /** * When the synthetic scrollbars are visible: * - `auto`: shown whenever the axis overflows, regardless of interaction; * self-hides when the content fits. * - `always`: the scrollbar (and corner) stay mounted and * `data-state="visible"` regardless of overflow — a stable, always-painted * track. When the axis does not overflow the thumb fills * the full track and dragging is a no-op. The library is headless and does * not own layout, so to actually *reserve* the gutter (no content shift * when crossing the overflow boundary) the consumer lays the scrollbar out * in flow — see the ScrollArea README's grid example. * - `scroll`: shown during scroll, faded after `scrollHideDelay` ms. * - `hover`: shown while the cursor is over the area (and during scroll). */ readonly type: _angular_core.InputSignal; /** * ms after the most recent scroll before scrollbars fade (only * `type="scroll"` and `"hover"`). The default is read from * `provideForScrollAreaDefaults` for the surrounding scope. */ readonly scrollHideDelay: _angular_core.InputSignalWithTransform; /** * What a primary-button press on bare scrollbar track does: * - `page`: step one page toward the press and auto-repeat while held, * stopping once the thumb reaches the pointer (platform behaviour). * - `jump`: centre the thumb on the press point, then scrub while held. * - `none`: the library ignores track presses, leaving the gesture to the * consumer (the scrollbar's `scrollToTrackPoint` / `pageBy` commands stay * available for a hand-rolled handler). * * A track press never moves focus. The default is read from * `provideForScrollAreaDefaults` for the surrounding scope. */ readonly trackPress: _angular_core.InputSignal; /** * ms a held `trackPress="page"` gesture waits before the first auto-repeat * page step. The default is read from `provideForScrollAreaDefaults` for the * surrounding scope. */ readonly trackPressRepeatDelay: _angular_core.InputSignalWithTransform; /** * ms between auto-repeat page steps of a held `trackPress="page"` gesture, * once `trackPressRepeatDelay` has elapsed. The default is read from * `provideForScrollAreaDefaults` for the surrounding scope. */ readonly trackPressRepeatInterval: _angular_core.InputSignalWithTransform; /** * Writing direction. When unset (default `null`), the inherited ambient * direction is resolved from the nearest ancestor carrying a `dir` attribute * (or ``), defaulting to `'ltr'`. An explicit `[dir]` always wins. * The resolved value is reflected to the host `dir` attribute and positions * the vertical scrollbar on the left in RTL. */ readonly _dirInput: _angular_core.InputSignal; readonly dir: _angular_core.Signal; readonly viewport: _angular_core.Signal; readonly content: _angular_core.Signal; readonly scrollLeft: _angular_core.Signal; readonly scrollTop: _angular_core.Signal; readonly clientWidth: _angular_core.Signal; readonly clientHeight: _angular_core.Signal; readonly scrollWidth: _angular_core.Signal; readonly scrollHeight: _angular_core.Signal; readonly hovering: _angular_core.Signal; readonly scrolling: _angular_core.Signal; registerViewport(el: HTMLElement | null): void; registerContent(el: HTMLElement): void; unregisterContent(el: HTMLElement): void; reportScroll(left: number, top: number): void; reportSize(clientW: number, clientH: number, scrollW: number, scrollH: number): void; noteUserScroll(): void; protected onPointerEnter(): void; protected onPointerLeave(): void; constructor(); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * The actually-scrolling element. Hides native scrollbars (the only place * in forty-cdk that ships CSS — see README), tracks scroll position, and * reports geometry to the root so the synthetic scrollbar can render. * * Focusable by default (`tabindex="0"`) so a scroll area whose content has no * focusable children is still reachable and keyboard-scrollable — the browser * gives a focused overflow container native arrow / PageUp / PageDown / Home / * End / Space scrolling. Consumers whose content is already keyboard-focusable * can drop the extra tab stop with `[focusable]="false"`. */ declare class ForScrollAreaViewport { #private; /** * Whether the viewport is a keyboard tab stop. Defaults to `true`, emitting * `tabindex="0"` so the scroll container is focusable and gets native * keyboard scrolling (arrows / PageUp / PageDown / Home / End / Space) even * when its content holds no focusable elements. Set `false` to remove the * extra tab stop when the projected content is already keyboard-focusable. */ readonly focusable: _angular_core.InputSignalWithTransform; constructor(); protected onScroll(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Marks the content element inside `[forScrollAreaViewport]`. The viewport * observes this element with a `ResizeObserver` so `scrollWidth` / * `scrollHeight` updates when content reflows. * * Required for the synthetic scrollbar to react to content resizes — without * it, the viewport falls back to no observation and scrollbars stay sized to * whatever the layout reported on first render. */ declare class ForScrollAreaContent { #private; constructor(); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Synthetic scrollbar track. Reflects `data-orientation`, `data-state` * (`visible` / `hidden`), owns the track / thumb geometry the thumb renders * from, and handles a press on bare track (`trackPress` on the root). * * The element is fully removed (`hidden`) when the corresponding axis has * no overflow *and* `type` is not `'always'` — there is no scrollbar to * render. Under `type="always"` the track stays painted regardless of * overflow, so the consumer's reserved gutter is never empty. * Visibility is enforced with an inline `display: none` (which beats any * author `display` rule a consumer applies via a class) in addition to the * `hidden` attribute that removes it from the a11y tree. */ declare class ForScrollAreaScrollbar { #private; /** * Axis this scrollbar controls. */ readonly orientation: _angular_core.InputSignal; readonly ctx: forty_cdk_scroll_area.ForScrollAreaContext; readonly host: HTMLElement; readonly size: _angular_core.Signal; /** Track length along this scrollbar's axis, in CSS pixels. */ readonly trackLength: _angular_core.Signal; /** * Maximum scroll offset of this axis (`scrollSize - clientSize`), floored at * `0`. Epsilon-free — unlike `hasOverflow`, which keeps a 1px * threshold because it gates the track's self-removal. */ readonly maxScroll: _angular_core.Signal; /** * Rendered thumb length in CSS pixels — the viewport / content ratio applied * to the track, floored at a `8px` minimum so a very long content still * leaves a grabbable thumb. */ readonly thumbSize: _angular_core.Signal; /** Travel available to the thumb along the track, floored at `0`. */ readonly usableTrack: _angular_core.Signal; /** * Scroll offset of this axis normalised to a start-edge-origin (left / top) * value in `[0, maxScroll]`. * * On the vertical axis this is just `scrollTop`. On the horizontal axis, LTR * `scrollLeft` is already left-origin, but in RTL the browser reports * `scrollLeft` in the negative model (`0` at rest with the content's right * edge flush, `-maxScroll` when scrolled fully left), so a left-origin * position is `scrollLeft + maxScroll` — `maxScroll` at rest (thumb pinned to * the right) down to `0` when scrolled forward. Every other geometry member * (and `scrollToPosition`) works in this one space, so RTL is absorbed here * and nowhere else. */ readonly scrollPosition: _angular_core.Signal; /** * Thumb offset from the track's start edge in CSS pixels, in the same * start-edge-origin space as `scrollPosition` (so in RTL the thumb rests at * `usableTrack`, flush with the track's right edge). */ readonly thumbOffset: _angular_core.Signal; /** * One page step in scroll pixels — `max(client * 0.875, client - 40, 1)`, * mirroring the platform's page step so a paged track press keeps a sliver of * the previous page in view instead of stepping a full viewport. */ readonly pageStep: _angular_core.Signal; /** True while the thumb is being dragged. Pins the track visible / painted. */ readonly dragging: _angular_core.Signal; /** True while a track press is in flight. Pins the track visible / painted. */ readonly pressing: _angular_core.Signal; /** The registered `[forScrollAreaThumb]` element, when one is mounted. */ readonly thumb: _angular_core.Signal; constructor(); /** * Marks the track as actively dragged so an in-flight drag is never aborted * by the scrollbar self-hiding (`type="hover"` / `"scroll"` fading the track, * or a consumer `display:none` on `data-state="hidden"`). Called by the thumb * on pointer-down / drag-end. */ setDragging(dragging: boolean): void; /** * Registers the thumb element so the track handler can tell a press that * originated on the thumb (the thumb owns that gesture) from a bare-track * press. Called by `[forScrollAreaThumb]` on construction. */ registerThumb(el: HTMLElement): void; /** * Clears the registered thumb, guarded on identity so a late teardown of an * old thumb doesn't blow away a freshly registered replacement. */ unregisterThumb(el: HTMLElement): void; readonly hasOverflow: _angular_core.Signal; /** * Whether the track is rendered at all. `'always'` keeps it painted * unconditionally (a stable, always-present track); every * other `type` paints only the axis that actually overflows. An in-flight * thumb drag or track press also pins it painted so the gesture is never * aborted by the track self-removing. Gates both the `hidden` attribute and * the inline `display: none` self-removal. */ readonly painted: _angular_core.Signal; /** * `'visible' | 'hidden'`. An in-flight thumb drag or track press forces * `'visible'` so a consumer fade on `data-state="hidden"` can't hide the * track mid-gesture. Otherwise: `'always'` resolves to `'visible'` regardless * of overflow — the track is permanently present. `'auto'` shows whenever the * axis overflows; `'hover'` / `'scroll'` additionally gate on the interaction * signals. A non-overflowing axis is `'hidden'` for every mode except * `'always'`. */ readonly state: _angular_core.Signal<"visible" | "hidden">; /** * Scrolls the viewport so this axis rests at `position`, given in the * start-edge-origin space of `scrollPosition` and clamped into * `[0, maxScroll]`. RTL's negative `scrollLeft` model is applied here. * * Writes plain `scrollLeft` / `scrollTop` — the library ships no * `behavior: 'smooth'`, so motion (and its `prefers-reduced-motion` gate) is * the consumer's `scroll-behavior` on `[forScrollAreaViewport]`. */ scrollToPosition(position: number): void; /** * Offset of a pointer event from the track's start edge along this axis, in * CSS pixels. The horizontal reading is measured from `rect.left` in **both** * writing directions, because `thumbOffset` is left-origin in RTL too — RTL * is absorbed once, in `scrollPosition` / `scrollToPosition`. */ trackPointFromEvent(event: PointerEvent): number; /** * Scrolls so the thumb is centred on `trackPx` (an offset from the track's * start edge). A no-op when the axis cannot scroll or the thumb fills the * track. */ scrollToTrackPoint(trackPx: number): void; /** * Steps the viewport one `pageStep` forward (`1`) or backward (`-1`) along * this axis, clamped to the scroll range. A no-op when the axis cannot scroll * or is already at that end. */ pageBy(direction: -1 | 1): void; protected onTrackPointerDown(event: PointerEvent): void; protected onLostPointerCapture(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * The draggable thumb inside a `[forScrollAreaScrollbar]`. Sizes itself * proportionally to viewport / content and translates along the track * based on `scrollLeft` / `scrollTop`. Pointer-drag scrolls the viewport * proportionally. */ declare class ForScrollAreaThumb { #private; readonly scrollbar: ForScrollAreaScrollbar; constructor(); protected widthPx(): number | null; protected heightPx(): number | null; protected leftPx(): number | null; protected topPx(): number | null; protected transformValue(): string; protected onPointerDown(event: PointerEvent): void; protected onLostPointerCapture(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Filler in the corner where horizontal and vertical scrollbars meet. * Shown when both axes overflow, or unconditionally under `type="always"` * (both tracks are permanently present then). Visibility is enforced with an * inline `display: none` (which beats any author `display` rule a consumer * applies via a class) in addition to the `hidden` attribute that removes it * from the a11y tree. */ declare class ForScrollAreaCorner { protected readonly ctx: forty_cdk_scroll_area.ForScrollAreaContext; protected readonly visible: _angular_core.Signal; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Defaults inherited by descendant scroll areas in the surrounding injector * scope. Configure with `provideForScrollAreaDefaults` either at the * application root or in any component's `providers` array; partial * overrides merge with the parent scope. */ interface ForScrollAreaDefaults { /** * Milliseconds after the most recent scroll before the synthetic * scrollbars fade. Applies when `type` is `'scroll'` or `'hover'`. */ scrollHideDelay: number; /** * What a primary-button press on bare scrollbar track does: page toward the * press (with auto-repeat while held), jump the thumb to the press point, or * nothing at all. */ trackPress: ForScrollAreaTrackPress; /** * Milliseconds a held `trackPress="page"` gesture waits before the first * auto-repeat page step. */ trackPressRepeatDelay: number; /** * Milliseconds between auto-repeat page steps of a held `trackPress="page"` * gesture, after `trackPressRepeatDelay` has elapsed. */ trackPressRepeatInterval: number; } /** Token holding the resolved scroll-area defaults for the current scope. */ declare const FOR_SCROLL_AREA_DEFAULTS: _angular_core.InjectionToken; /** * Configures forty-cdk scroll-area defaults for this injector scope. Partial * overrides inherit unspecified keys from the parent scope (or library * defaults at the root). */ declare function provideForScrollAreaDefaults(defaults?: Partial): Provider[]; export { FOR_SCROLL_AREA_CONTEXT, FOR_SCROLL_AREA_DEFAULTS, ForScrollArea, ForScrollAreaContent, ForScrollAreaCorner, ForScrollAreaScrollbar, ForScrollAreaThumb, ForScrollAreaViewport, provideForScrollAreaDefaults }; export type { ForScrollAreaContext, ForScrollAreaDefaults, ForScrollAreaTrackPress, ForScrollAreaType, ForScrollbarOrientation };