/** * Responsive / breakpoint / orientation / volume-slider concern for the * desktop UI plugin. * * Owns: * - `wireOrientation` — portrait/landscape MediaQueryList listener * - `wireNoHover` — touch-only device detection * - `wireResponsive` — ResizeObserver → `applyAllVisibilityRules` * - `wireVolumeSlider` — horizontal / vertical / auto volume slider mode * - `applyAllVisibilityRules` — the four-rule button visibility pass * - `shouldShowButton` / `buttonFootprint` — per-button fit helpers * - `initButtonMap` — builds the key→element lookup after DOM is ready * - `resolveBreakpoints` — derives the active breakpoint progression from opts * * Integration: called from `DesktopUiPlugin.use()` after `buildDom()`. * All mutable state is held in `ResponsiveState`; the plugin stores one * instance and passes it to every call here. * * Exported constants (`DEFAULT_PRIORITY`, `DEFAULT_BREAKPOINTS`, * `PORTRAIT_HIDDEN`, `BUTTON_WIDTH`, `VOL_SLIDER_EXPANDED_WIDTH`) replace the * former `static readonly` members on the plugin class. */ import type { Breakpoint, ButtonPriorityList, DesktopUiButtonOptions, DesktopUiOptions, LayoutBreakpointPayload } from '../index.js'; export declare const BUTTON_WIDTH = 40; export declare const VOL_SLIDER_EXPANDED_WIDTH = 96; /** * Default set forced off in portrait regardless of width. * * A default, not a rule: override it per consumer with * `DesktopUiOptions.portraitHidden`. A phone viewer who wants to skip an intro * or jump to the next episode shouldn't have to rotate the device, but which * controls earn that scarce row is the app's call, not the library's. */ export declare const PORTRAIT_HIDDEN: ReadonlySet; /** Default priority list — most essential first, least essential last. */ export declare const DEFAULT_PRIORITY: ButtonPriorityList; /** * Default breakpoint progression: * - xs (≤ 320): play + mute only (rank 0–1) * - sm (≤ 480): play / mute / fullscreen / settings (rank 0–4) * - md (≤ 720): + nav + chapter buttons (rank 0–8) * - lg (≤ 1024): + theater / pip / speed (rank 0–13) * - xl (> 1024): all buttons visible */ export declare const DEFAULT_BREAKPOINTS: ReadonlyArray; export interface ResponsiveState { isPortrait: boolean; isNoHover: boolean; lastContainerWidth: number; currentBreakpointName: string; buttonMap: Record | null; resizeObserver: ResizeObserver | null; volSliderVerticalOpen: boolean; } export declare function makeResponsiveState(): ResponsiveState; export interface ResponsiveButtonRefs { playBtn: HTMLButtonElement; volBtn: HTMLButtonElement; fsBtn: HTMLButtonElement; settingsBtn: HTMLButtonElement; nextBtn: HTMLButtonElement; prevBtn: HTMLButtonElement; rewindBtn: HTMLButtonElement; forwardBtn: HTMLButtonElement; chapBackBtn: HTMLButtonElement; chapFwdBtn: HTMLButtonElement; theaterBtn: HTMLButtonElement; pipBtn: HTMLButtonElement; speedBtn: HTMLButtonElement; qualityBtn: HTMLButtonElement; subsBtn: HTMLButtonElement; audioBtn: HTMLButtonElement; aspectRatioBtn: HTMLButtonElement; playlistBtn: HTMLButtonElement; } /** Resolve the active breakpoint progression from consumer options. */ export declare function resolveBreakpoints(opts: DesktopUiOptions | undefined): ReadonlyArray; /** Estimated pixel footprint of a button in the bottom row. */ export declare function buttonFootprint(key: keyof DesktopUiButtonOptions, isNoHover: boolean): number; /** * Returns `true` when the button should be visible at the given accumulated * width. Applies the four-rule composition: * 1. Consumer opt-out * 3. Orientation (portrait hides a fixed set) * 4. Container fit * Rule 2 (content-gating) is checked by the caller before calling this. */ export declare function shouldShowButton(key: keyof DesktopUiButtonOptions, accumulatedWidth: number, containerWidth: number, isPortrait: boolean, isNoHover: boolean, buttonOpts: DesktopUiButtonOptions | undefined, portraitHidden?: ReadonlySet): boolean; /** Resolves the consumer's portrait override, falling back to the default set. */ export declare function resolvePortraitHidden(opts: DesktopUiOptions | undefined): ReadonlySet; /** Build the key→element map once the DOM is ready. */ export declare function initButtonMap(refs: ResponsiveButtonRefs): Record; /** * Primary visibility pass: walk the priority list most-important first, * accumulate widths, hide any button that doesn't fit. Also emits * `layout:breakpoint` for backwards-compat subscribers. */ export declare function applyAllVisibilityRules(state: ResponsiveState, opts: DesktopUiOptions | undefined, containerWidth: number, emitBreakpoint: (payload: LayoutBreakpointPayload) => void, container: HTMLElement): void; /** * Wire orientation changes. Sets `data-orientation` on the container and * re-evaluates visibility whenever the device rotates. */ export declare function wireOrientation(state: ResponsiveState, container: HTMLElement, opts: DesktopUiOptions | undefined, listen: (target: EventTarget, event: string, fn: (event: Event) => void) => void, emitBreakpoint: (payload: LayoutBreakpointPayload) => void): void; /** * Wire touch-device detection. On `(hover: none) and (pointer: coarse)` * devices the volume slider never expands so we must not reserve space for * it. */ export declare function wireNoHover(state: ResponsiveState, container: HTMLElement, opts: DesktopUiOptions | undefined, listen: (target: EventTarget, event: string, fn: (event: Event) => void) => void, emitBreakpoint: (payload: LayoutBreakpointPayload) => void): void; /** * Wire the ResizeObserver that drives button-fit visibility on every resize. */ export declare function wireResponsive(state: ResponsiveState, refs: ResponsiveButtonRefs, container: HTMLElement, opts: DesktopUiOptions | undefined, addCleanup: (fn: () => void) => void, emitBreakpoint: (payload: LayoutBreakpointPayload) => void): void; /** * Wire the volume slider — horizontal (CSS-only expand on hover), vertical * (click-popup), or auto (ResizeObserver picks based on container width and * hover capability). * * Decides at construction time (before ResizeObserver fires) whether to render * the horizontal expand-on-hover slider or the vertical click-popup. */ export declare function wireVolumeSlider(state: ResponsiveState, opts: DesktopUiOptions | undefined, playerContainer: HTMLElement, volContainer: HTMLElement, vertPop: HTMLDivElement, vertInput: HTMLInputElement, volBtn: HTMLButtonElement, volPopupMuteBtn: HTMLButtonElement | null, listen: (target: EventTarget, event: string, fn: (event: Event) => void) => void, getVolume: () => number, setVolume: (level: number) => void, toggleMute: () => void, addCleanup: (fn: () => void) => void): void;