import { Box, Point } from '@expofp/geometry';
import type { RawPoiType } from '@expofp/schema';
import type { ReactNode } from 'react';
import type { Kiosk } from '../components/Kiosk/SetKiosk';
import { type Booth } from './BoothStore';
import type { Category } from './CategoryStore';
import { EventItem, type Track } from './EventStore';
import { Exhibitor } from './ExhibitorStore';
import type { FuzzySearchResult } from './FuzzySearchEngineStore';
import type RootStore from './RootStore';
import { Route } from './RouteStore';
import { SpeakerItem } from './SpeakerStore';
import type { BannerType, InterfaceAction, ListItem, ListType, MapSettings, OverlaySize, Visibility } from './types';
interface InterfaceMetadata {
    id: string;
    className: string;
    priority: number;
    isActive: () => boolean;
    additionalClasses?: () => string[];
    searchBoxConfig?: () => {
        mode: string;
        title?: string;
        subtitle?: string;
        badge?: string | number;
        icon?: string;
    } | null;
    actions?: () => InterfaceAction[];
}
export default class UIState {
    private readonly rootStore;
    private readonly interfaceMetadata;
    list: ListType;
    details: Booth | Exhibitor | Route | Category | EventItem | SpeakerItem | null;
    hoveredExhibitor: Exhibitor | null;
    hoveredBooth: Booth | null;
    zoomBy: number | null;
    rollReset: boolean;
    moveToBooths: Booth[] | null;
    moveToRect: Box | null;
    /**
     * Breathing room the pending `moveToRect` wants, as a fraction of the viewport
     * per side. `null` leaves each renderer on its own default — the adaptive
     * 15%/25% for the legacy one, a fixed inset for the map. Fit-to-screen sets 0:
     * its rect is the framing itself, so padding it would zoom past the authored
     * viewbox.
     */
    moveToRectPaddingPercent: number | null;
    moveToLocation: boolean;
    menu: boolean;
    searchFocused: boolean;
    searchClearMode: boolean;
    printingPdf: boolean;
    screenSize: Point;
    desiredOverlaySize?: OverlaySize;
    overlayShowsAll: boolean;
    centerMap: boolean;
    zoomAfTransformK: number;
    activeListIndex: number;
    devicePixelRatio: number;
    previewExhibitor: Exhibitor | null;
    wsStarted: boolean;
    canvasStarted: boolean;
    kiosk: boolean;
    inIdle: boolean;
    modalActive: {
        share: boolean;
    };
    galleryActive: boolean;
    hideOverlay: boolean;
    searchButtonsOverride: boolean | null;
    hideCookieConsent: boolean;
    hideHeaderLogo: boolean;
    hideLogoInBooth: boolean;
    disableBookmarked: boolean;
    hideLanguage: boolean;
    monochrome: boolean;
    heatmap: boolean;
    heatmapYah: boolean;
    rootElement: HTMLDivElement | null;
    debugCircles: {
        x: number;
        y: number;
        radius: number;
        color?: string;
    }[];
    mapControlsHidden: boolean;
    floorsControlHidden: boolean;
    hideFreeOrDemo: boolean;
    freeBannerDismissed: boolean;
    currentBanner: BannerType;
    sceneDefReady: boolean;
    categoryFilterOpen: boolean;
    selectedCategoryFilters: Category[];
    selectedPoiTypeFilters: RawPoiType[];
    selectedTrack: Track | null;
    subButtonsVisible: boolean;
    searchBoxMode: 'search' | 'details' | 'interface';
    searchBoxTitle: string;
    searchBoxSubtitle?: string;
    routeTitle?: string;
    routeDescription?: string;
    isMultiPointRoute: boolean;
    tourTitle?: string;
    tourDescription?: string;
    isMultiPointTour: boolean;
    pathwayOnlyMode: boolean;
    isOverlayScrolled: boolean;
    listScrollTop: number;
    listScrollItemId: string | number | null;
    listScrollIndex: number;
    private scrollPositions;
    private scrollItemIds;
    _customUIScale: number | null;
    private readonly searchFilterHeightPx;
    private readonly searchInputHeightPx;
    private readonly overlayUISizePx;
    private readonly overlayKioskSizePx;
    private readonly overlayMediumHeightRems;
    setSelectedCategoryFilters(categories: Category[]): void;
    resetCategoryFilter(): void;
    setSearchClearMode(value: boolean): void;
    setRouteTitle(title: string): void;
    setRouteDescription(description: string): void;
    setIsMultiPointRoute(isMulti: boolean): void;
    setTourTitle(title: string): void;
    setTourDescription(description: string): void;
    setIsMultiPointTour(isMulti: boolean): void;
    setPathwayOnlyMode(value: boolean): void;
    setMultiPointTourList(tourId: string): void;
    get activePathwayLayers(): string[];
    get highlightedBooths(): ReadonlySet<string>;
    constructor(rootStore: RootStore);
    get rtl(): boolean;
    get noOverlay(): boolean;
    get overlayOnDemand(): boolean;
    get overlayHiddenNow(): boolean;
    get onBoothClick(): (e: import("..").FloorPlanBoothClickEvent) => void;
    get onMarkerClick(): (e: import("..").FloorPlanMarkerEvent) => void;
    get onBookmarkClick(): (e: import("..").FloorPlanBookmarkClickEvent) => void;
    get onVisitedClick(): (e: import("..").FloorPlanVisitedClickEvent) => void;
    get onCategoryClick(): (e: import("..").FloorPlanCategory) => void;
    get onDirection(): (e: import("..").FloorPlanDirectionEvent | null) => void;
    get onDetails(): (e: import("..").FloorPlanDetailsEvent) => void;
    get onExhibitorCustomButtonClick(): (e: import("..").FloorPlanCustomButtonEvent) => void;
    get onGetCoordsClick(): (e: import("..").FloorPlanGetCoordsEvent) => void;
    get selectedExhibitor(): Exhibitor | null;
    get selectedBooth(): Booth | null;
    get selectedCategory(): Category | null;
    get selectedRoute(): Route | null;
    get selectedSpeaker(): SpeakerItem | null;
    get uiScale(): number;
    get isGuidedToursActive(): boolean;
    get getRouteNextFloor(): string | null;
    readonly headerHeightRem = 0;
    get headerHeightPx(): number;
    get overlayPosition(): "bottom" | "left";
    get overlayCollapsed(): boolean;
    get overlaySize(): OverlaySize | undefined;
    get overlayBottom(): boolean;
    get overlayLeft(): boolean;
    get overlayWidthPx(): number;
    readonly wsImageHeightPx = 44;
    get wsPaddingPx(): number;
    get wsOccupiedHeightPx(): number;
    get wsShown(): boolean;
    get wsDesktopPosition(): "bottom" | "top";
    get wsPosition(): "bottom" | "top";
    get responsiveClass(): string;
    get mapVisibleTop(): number;
    get mapVisibleBottom(): number;
    readonly mapVisibleStart = 0;
    get searchActionsHeightPx(): number;
    get shouldShowSearchButtons(): boolean;
    get shouldShowMobileToggle(): boolean;
    get mobileToggleIsListMode(): boolean;
    get canvasVisibleRectPx(): Box;
    get shouldShiftMapRect(): boolean | Category | EventItem | Exhibitor | Route | SpeakerItem | Booth | null;
    get hasAppliedFilters(): boolean;
    get canvasVisibleRectPt(): Box;
    get canvasSizePt(): Point;
    get shouldUseBackdrop(): boolean | undefined;
    forceDim: boolean;
    setForceDim(forceDim: boolean): void;
    get dimmed(): boolean;
    get defaultSearchItems(): ListItem[];
    get searchItems(): ListItem[];
    get searchList(): ListItem[];
    get foundInDescription(): ListItem[];
    get foundInDescriptionStruct(): Record<string, string>;
    get categoryFilteredSearchList(): ListItem[];
    get fuzzySearchItems(): FuzzySearchResult<ListItem>[];
    get listItems(): ListItem[];
    get listBooths(): Set<Booth>;
    get selectedBooths(): Set<Booth>;
    get hoveredBooths(): Set<Booth>;
    get visibility(): Visibility;
    setVisibility(visibility: Visibility): void;
    toggleMapOverlay(): void;
    changeZoom(zoom: number): void;
    zoomIn(): void;
    zoomOut(): void;
    fitBounds(): void;
    get previewMode(): boolean;
    get viewerMode(): boolean;
    get selectedEventItem(): EventItem | null;
    /**
     * How the camera moves before a host says otherwise.
     *
     * Both views a plan is drawn in read these, so the plan opens at the same angle and takes the
     * same time to get there whichever view is showing.
     */
    get defaultMapSettings(): MapSettings;
    mapSettings: MapSettings;
    setMapSettings(settings: MapSettings): void;
    resetMapSettings(): void;
    /**
     * How far the camera may tilt back from top down, in degrees.
     *
     * MapLibre's own default, which both views are held to, so the plan tilts the same amount in
     * either one. Not a map setting, because a host has no reason to raise or lower it.
     */
    readonly maxPitch = 60;
    /** Whether a pitch change eases rather than cuts. Both views read it. */
    animatePitch: boolean;
    /**
     * Whether the venue shows its plan in 3D, which is its `allow3dView` flag and nothing else.
     *
     * `MaplibreStore` picks the first view mode from it, and the tilt gesture below hangs off it, so
     * a venue that never allows a tilted plan cannot be tilted by hand either.
     *
     * `hide3dMapDefault` is deliberately not read here. It asks for the flat view on load, which is a
     * starting camera rather than a venue without 3D, and narrowing this by it takes the tilt gesture
     * away from a venue that allows one.
     *
     * A plain getter, not a computed: the flag is frozen config with nothing to observe, and the map
     * store reads this from its own constructor.
     */
    get is3DView(): boolean;
    /**
     * Whether the user may tilt the plan by hand.
     *
     * The gesture only, exactly as `rollEnabled` is: a camera command still tilts the plan whatever
     * this says, in either view, so a host may open the plan at an angle with the gesture off. The
     * venue decides first through `is3DView`, and the `pitch` map parameter a host may pass
     * through the URL narrows it further.
     *
     * `keepAlive`, because `defaultMapSettings` reads it from the constructor, where there is no
     * reaction to observe it and the store is configured with `computedRequiresReaction`.
     */
    get pitchEnabled(): boolean;
    /**
     * Whether the user may turn the plan: the venue's own setting, narrowed by the `roll` map
     * parameter a host may pass through the URL.
     */
    get rollEnabled(): boolean;
    get baseQRCodeUrl(): string;
    get viewMapOnPhoneQRCodeUrl(): string;
    get routeQRCodeUrl(): string;
    get isFeaturedExhibitorActive(): boolean;
    get activeInterfaceData(): InterfaceMetadata | null;
    /** Id of the screen the search box heads — lets custom CSS target one header. */
    get activeInterfaceId(): string | undefined;
    get searchBoxConfig(): {
        mode: string;
        title?: string;
        subtitle?: string;
        badge?: string | number;
        icon?: string;
    };
    get searchBoxActions(): InterfaceAction[];
    get overlayInterfaceClasses(): string[];
    get isOverlayOpen(): boolean;
    setOverlayScrolled(isScrolled: boolean): void;
    setListScrollTop(listType: string, scrollTop: number): void;
    setListScrollItemId(listType: string, itemId: string | number): void;
    getListScrollTop(listType: string): number;
    getListScrollItemId(listType: string): string | number | null;
    clearListScroll(listType: string): void;
    get bannerType(): BannerType;
    get isBannerVisible(): boolean;
    setCurrentBanner(banner: BannerType): void;
    forceShowDetails: boolean;
    setForceShowDetails(flag: boolean): void;
    get showRouteInstantly(): boolean;
    buildRoute: boolean;
    startBuildRoute(): void;
    globalErrorMessages: {
        title: string;
        body?: ReactNode;
    }[];
    setGlobalErrorMessage(message: {
        title: string;
        body?: ReactNode;
    }): void;
    popGlobalErrorMessage(): void;
    private initializeUIScale;
    minUIScale: number;
    maxUIScale: number;
    setUIScale(scale: number | undefined, saveToStorage?: boolean): void;
    resetUIScale(): void;
    /** Drops a scale applied without saving, back to the stored one (or the default). */
    restoreUIScale(): void;
    setKioskModeEnabled: boolean;
    enableSetKioskMode(enable: boolean): void;
    kioskData: Kiosk | null;
    setKioskData(kioskData: Kiosk | null): void;
}
export {};
//# sourceMappingURL=UIState.d.ts.map