import React from 'react';
import { CompatibleModule } from '../utils/configurator-utils.js';
import { CarouselDisplayMode, CarouselLayout, VariantDisplayMode, VariantDisplayStyleOverlay } from '../types/config-enums.js';
import type { BedPartSizeFilterFlags, OnChangePayload, UnifiedPricePayload } from '../types/inject-config.js';
import type { StringReplacementsConfig } from '../types/string-replacements.js';
import { type ConfiguratorIframeScreenRect } from '../utils/configurator-dom-queries.js';
import { type StringInterpolationVars } from '../lib/strings/resolve-string-replacement.js';
export type DrawerSizes = 'closed' | 'small' | 'large';
export type AnimationState = 'unavailable' | 'open' | 'close' | 'loop' | 'stop';
export type TransitionProxyMode = 'opening' | 'closing' | null;
export interface ProductFilters {
    [optionName: string]: {
        [filterKey: string]: Array<{
            value: string;
            checked: boolean;
        }>;
    };
}
export interface Product {
    id: string;
    name: string;
    price: number;
    discount: number;
    lowestPrice: number;
    metadata: any;
}
export interface Selection {
    id: string;
    name: string;
    sku?: string;
    thumbnail?: string;
    miniThumbnails?: {
        small: string;
        medium: string;
        large: string;
    };
    price: number;
    blurHash: string;
    groupId?: string;
    filter?: {
        [key: string]: string[];
    };
    swatch?: Swatch;
    isVisible?: boolean;
    metadata?: {
        bedSize?: string;
    };
}
export interface Group {
    id: string;
    name: string;
    selections: Selection[];
    isVisible?: boolean;
}
export interface Option {
    id: string;
    name: string;
    groups: Group[];
    hasNonOption?: boolean;
    isVisible?: boolean;
}
export interface ConfiguratorState {
    options: Option[];
    selectedSelections: Array<{
        optionId: string;
        groupId: string;
        selectionId: string;
    }>;
    configuratorSettings: {
        swatchSettings: SwatchRulesData;
        availableProductFilters: {
            [key: string]: string[];
        };
    };
    snap2Objects: any[];
}
export interface SizeOption {
    id: 'size';
    name: 'size';
    groups: [
        {
            id: 'size-group';
            selections: Array<{
                id: string;
                name: string;
                price: number;
                thumbnail?: string;
            }>;
        }
    ];
    hasNonOption?: boolean;
}
export interface Discount {
    percentage: number;
    amount: number;
    formattedAmount: string;
}
export interface Swatch {
    name: string;
    option: string;
    manufacturerId: string;
    description: string;
    sku: string;
    thumbnail: {
        blurHash: string;
        thumbnail: string;
        miniThumbnails: {
            large: string;
            medium: string;
            small: string;
        };
    };
}
export type SwatchRulesData = {
    freeSwatchLimit: number;
    canExeedFreeLimit: boolean;
    pricePerSwatch: number;
    minSwatches: number;
    maxSwatches: number;
    enabled: boolean;
};
interface OV25UIContextType {
    shadowDOMs?: {
        mobileDrawer?: ShadowRoot;
        snap2CheckoutSheet?: ShadowRoot;
        configuratorViewControls?: ShadowRoot;
        popoverPortal?: ShadowRoot;
        modalPortal?: ShadowRoot;
        swatchbookPortal?: ShadowRoot;
    };
    cssString?: string;
    products: Product[];
    currentProductId?: string;
    configuratorState?: ConfiguratorState;
    selectedSelections: Array<{
        optionId: string;
        groupId?: string;
        selectionId: string;
    }>;
    activeOptionId: string | null;
    quantity: number;
    price: number;
    subtotal: number;
    formattedPrice: string;
    formattedSubtotal: string;
    discount: Discount;
    galleryIndex: number;
    currentSku: any;
    range: any;
    drawerSize: DrawerSizes;
    isVariantsOpen: boolean;
    isDrawerOrDialogOpen: boolean;
    galleryCarouselFullscreenImage: string | null;
    setGalleryCarouselFullscreenImage: React.Dispatch<React.SetStateAction<string | null>>;
    /** Last frame from the iframe shown in the gallery slot while the iframe moves to sheet/modal. */
    configuratorTransitionProxyBitmap: ImageBitmap | null;
    configuratorTransitionProxyMode: TransitionProxyMode;
    /** Captured sheet/modal iframe bounds; closing proxy is portaled here and slides/fades with the shell. */
    configuratorClosingProxyRect: ConfiguratorIframeScreenRect | null;
    useInstantIframeCloseRestore: boolean;
    setConfiguratorTransitionProxyBitmap: (bitmap: ImageBitmap | null) => void;
    setConfiguratorTransitionProxyMode: (mode: TransitionProxyMode) => void;
    setConfiguratorClosingProxyRect: (rect: ConfiguratorIframeScreenRect | null) => void;
    setUseInstantIframeCloseRestore: React.Dispatch<React.SetStateAction<boolean>>;
    releaseConfiguratorTransitionProxy: () => void;
    /** Stacked gallery: next close sync should skip the legacy 500ms wait (instant iframe restore). Set in useIframePositioning; consumed in ProductGallery. */
    stackedGalleryCloseSyncImmediateRef: React.MutableRefObject<boolean>;
    arPreviewLink: string | null;
    error: Error | null;
    canAnimate: boolean;
    animationState: AnimationState;
    iframeRef: React.RefObject<HTMLIFrameElement>;
    isMobile: boolean;
    deferThreeD: boolean;
    /** True when gallery mounts in the hidden preload container (no page slot): modal open should not wait on iframe ImageBitmap. */
    configuratorGalleryIsDeferred: boolean;
    showOptional: boolean;
    hidePricing: boolean;
    disableAddToCart: boolean;
    hideAr: boolean;
    productLink: string | null;
    apiKey: string;
    configurationUuid: string | null;
    stringReplacements?: StringReplacementsConfig;
    /** OV25 bed iframe: `bedAllowNone` query segment (omit when all parts may use None). */
    bedAllowNoneQueryValue?: string;
    /** Dining iframe display option. Omitted unless explicitly false. */
    diningShowAttachmentPoints?: boolean;
    /** Bed iframe: latest size from `CURRENT_BED_SIZE` postMessage (`null` until first message or non-bed). */
    currentBedSize: string | null;
    /** When true for a part, selections in that option hide if `metadata.bedSize` ≠ {@link currentBedSize}. */
    bedFilterSelectionsByCurrentSize: BedPartSizeFilterFlags;
    /** Display symbol for prices; see inject `flags.currencySymbol`. */
    currencySymbol: string;
    buyNowFunction: (payload?: OnChangePayload) => void;
    addToBasketFunction: (payload?: OnChangePayload) => void;
    buySwatches: () => void;
    images?: string[];
    logoURL?: string;
    hideLogo: boolean;
    isProductGalleryStacked: boolean;
    carouselLayout: CarouselLayout;
    carouselLayoutMobile: CarouselLayout;
    carouselMaxImagesDesktop?: number;
    carouselMaxImagesMobile?: number;
    showCarousel: boolean;
    mobileLogoURL?: string;
    uniqueId?: string;
    initialiseMenuUsesExternalSelector?: boolean;
    currentProduct?: Product;
    sizeOption: SizeOption;
    activeOption?: Option;
    availableProductFilters?: ProductFilters;
    optionHasVisibleFilters: (option: {
        id: string;
        name: string;
    }) => boolean;
    showFilters?: boolean;
    allOptions: (Option | SizeOption)[];
    allOptionsWithoutModules: (Option | SizeOption)[];
    variantPanelOptions: (Option | SizeOption)[];
    galleryIndexToUse: number;
    filteredActiveOption?: Option | null;
    searchQueries: {
        [optionId: string]: string;
    };
    selectedSwatches: Swatch[];
    swatchRulesData: SwatchRulesData;
    isSwatchBookOpen: boolean;
    swatchBookFlash: 'destructive' | 'cta' | null;
    setSwatchBookFlash: React.Dispatch<React.SetStateAction<'destructive' | 'cta' | null>>;
    hasSelectionsWithSwatches: boolean;
    availableCameras: Array<{
        id: string;
        displayName: string;
    }>;
    availableLights: Array<{
        id: string;
        displayName: string;
    }>;
    isSnap2Mode: boolean;
    /** Latest normalized price payload from CURRENT_PRICE; drives Snap2 checkout sheet line items. */
    commercePriceSnapshot: UnifiedPricePayload | null;
    isSnap2CheckoutSheetOpen: boolean;
    setIsSnap2CheckoutSheetOpen: React.Dispatch<React.SetStateAction<boolean>>;
    snap2SaveResponse: {
        success: boolean;
        shareUrl?: string;
        error?: string;
    } | null;
    isModalOpen: boolean;
    controlsHidden: boolean;
    hasConfigureButton: boolean;
    useInlineVariantControls: boolean;
    configuratorDisplayMode: 'inline' | 'sheet' | 'drawer' | 'variants-only-sheet' | 'modal' | 'inline-sheet';
    configuratorDisplayModeMobile: 'inline' | 'drawer' | 'modal' | 'variants-only-sheet';
    useSimpleVariantsSelector: boolean;
    /** Drawer trigger: single Configure button or per-option buttons (ProductOptionsGroup). */
    configuratorTriggerStyle: 'single-button' | 'split-buttons';
    variantDisplayStyleMobile: VariantDisplayMode;
    variantDisplayStyleInline: VariantDisplayStyleOverlay;
    variantDisplayStyleInlineMobile: VariantDisplayStyleOverlay;
    variantDisplayStyleOverlay: VariantDisplayStyleOverlay;
    variantDisplayStyleOverlayMobile: VariantDisplayStyleOverlay;
    snap2VariantSheetSide: 'left' | 'right';
    snap2ModuleSheetPosition: 'left' | 'right' | 'bottom';
    snap2ModulesEmbedInVariantSheet: boolean;
    shareDialogTrigger: 'none' | 'save-button' | 'modal-close';
    skipNextDrawerCloseRef: React.MutableRefObject<boolean>;
    skipNextShareClickRef: React.MutableRefObject<boolean>;
    expandToOptionIdOnOpen: string | null;
    preloading: boolean;
    setPreloading: (preloading: boolean) => void;
    resetIframe: () => void;
    iframeResetKey: number;
    configureHandlerRef: React.MutableRefObject<(() => void) | null>;
    compatibleModules: CompatibleModule[] | null;
    isModuleSelectionLoading: boolean;
    selectedModuleType: 'all' | 'middle' | 'corner' | 'end';
    isModulePanelOpen: boolean;
    setProducts: React.Dispatch<React.SetStateAction<Product[]>>;
    setCurrentProductId: React.Dispatch<React.SetStateAction<string | undefined>>;
    setConfiguratorState: React.Dispatch<React.SetStateAction<ConfiguratorState | undefined>>;
    setSelectedSelections: React.Dispatch<React.SetStateAction<Array<{
        optionId: string;
        groupId?: string;
        selectionId: string;
    }>>>;
    setActiveOptionId: React.Dispatch<React.SetStateAction<string | null>>;
    setQuantity: React.Dispatch<React.SetStateAction<number>>;
    setPrice: React.Dispatch<React.SetStateAction<number>>;
    setSubtotal: React.Dispatch<React.SetStateAction<number>>;
    setDiscount: React.Dispatch<React.SetStateAction<Discount>>;
    setGalleryIndex: React.Dispatch<React.SetStateAction<number>>;
    setCurrentSku: React.Dispatch<React.SetStateAction<any>>;
    setRange: React.Dispatch<React.SetStateAction<any>>;
    setDrawerSize: React.Dispatch<React.SetStateAction<DrawerSizes>>;
    setIsVariantsOpen: React.Dispatch<React.SetStateAction<boolean>>;
    setIsDrawerOrDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
    setArPreviewLink: React.Dispatch<React.SetStateAction<string | null>>;
    setError: React.Dispatch<React.SetStateAction<Error | null>>;
    setCanAnimate: React.Dispatch<React.SetStateAction<boolean>>;
    setAnimationState: React.Dispatch<React.SetStateAction<AnimationState>>;
    setAvailableProductFilters: React.Dispatch<React.SetStateAction<ProductFilters>>;
    setSearchQuery: (optionId: string, query: string) => void;
    setSelectedSwatches: React.Dispatch<React.SetStateAction<Swatch[]>>;
    setSwatchRulesData: React.Dispatch<React.SetStateAction<SwatchRulesData>>;
    toggleSwatch: (swatch: Swatch) => void;
    isSwatchSelected: (swatch: Swatch) => boolean;
    setIsSwatchBookOpen: React.Dispatch<React.SetStateAction<boolean>>;
    setAvailableCameras: React.Dispatch<React.SetStateAction<Array<{
        id: string;
        displayName: string;
    }>>>;
    selectCamera: (cameraId: string) => void;
    setAvailableLights: React.Dispatch<React.SetStateAction<Array<{
        id: string;
        displayName: string;
    }>>>;
    selectLightGroup: (subGroupId: string) => void;
    setSnap2SaveResponse: React.Dispatch<React.SetStateAction<{
        success: boolean;
        shareUrl?: string;
        error?: string;
    } | null>>;
    setIsModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
    setControlsHidden: React.Dispatch<React.SetStateAction<boolean>>;
    setHasConfigureButton: React.Dispatch<React.SetStateAction<boolean>>;
    setShareDialogTrigger: React.Dispatch<React.SetStateAction<'none' | 'save-button' | 'modal-close'>>;
    toggleHideAll: () => void;
    setCompatibleModules: React.Dispatch<React.SetStateAction<CompatibleModule[] | null>>;
    setIsModuleSelectionLoading: React.Dispatch<React.SetStateAction<boolean>>;
    setSelectedModuleType: React.Dispatch<React.SetStateAction<'all' | 'middle' | 'corner' | 'end'>>;
    setIsModulePanelOpen: React.Dispatch<React.SetStateAction<boolean>>;
    handleSelectionSelect: (selection: Selection, optionId?: string) => void;
    handleOptionClick: (optionId: string) => void;
    handleNextOption: () => void;
    handlePreviousOption: () => void;
    getSelectedValue: (option: Option | SizeOption) => string;
    toggleAR: () => void;
    cleanupConfigurator: () => void;
    applySearchAndFilters: (option: Option | SizeOption, optionId: string) => Option | SizeOption;
    /** Open the variant configurator (closes swatch book, opens variants drawer). Optionally pass an option name (case insensitive) to open on that option. */
    openConfigurator: (optionName?: string) => void;
    /** Open configurator or Snap2 modal based on product type. For useSimpleVariantsSelector single button. */
    openConfiguratorOrSnap2: () => void;
    /** Close the variant configurator drawer. For use by custom buttons. */
    closeConfigurator: () => void;
    /** Open the swatch book. Exposed for custom buttons. */
    openSwatchBook: () => void;
    /** Close the swatch book. Exposed for custom buttons. */
    closeSwatchBook: () => void;
    /** Resolve a configured replacement by key. */
    getString: (key: string, vars?: StringInterpolationVars, fallback?: string) => string;
}
export declare const createUniqueContext: (uniqueId: string) => React.Context<OV25UIContextType | undefined>;
export declare const OV25UIProvider: React.FC<{
    children: React.ReactNode;
    productLink: string | null;
    apiKey: string;
    configurationUuid: string;
    stringReplacements?: StringReplacementsConfig;
    bedAllowNoneQueryValue?: string;
    diningShowAttachmentPoints?: boolean;
    bedFilterSelectionsByCurrentSize?: BedPartSizeFilterFlags;
    buyNowFunction: (payload?: OnChangePayload) => void;
    addToBasketFunction: (payload?: OnChangePayload) => void;
    buySwatchesFunction: (swatches: Swatch[], swatchRulesData: SwatchRulesData) => void;
    onChange?: (payload: OnChangePayload) => void;
    images?: string[];
    deferThreeD?: boolean;
    showOptional?: boolean;
    hidePricing?: boolean;
    disableAddToCart?: boolean;
    hideAr?: boolean;
    forceMobile?: boolean;
    logoURL?: string;
    hideLogo?: boolean;
    isProductGalleryStacked: boolean;
    carouselDisplayMode?: CarouselDisplayMode;
    carouselDisplayModeMobile?: CarouselDisplayMode;
    carouselMaxImagesDesktop?: number;
    carouselMaxImagesMobile?: number;
    /** @deprecated Use carouselDisplayMode */
    carouselLayout?: CarouselDisplayMode;
    showCarousel?: boolean;
    hasConfigureButton: boolean;
    mobileLogoURL?: string;
    uniqueId?: string;
    useInlineVariantControls?: boolean;
    useInlineVariantControlsMobile?: boolean;
    configuratorDisplayMode?: 'inline' | 'sheet' | 'drawer' | 'modal' | 'variants-only-sheet' | 'inline-sheet';
    configuratorDisplayModeMobile?: 'inline' | 'drawer' | 'modal' | 'variants-only-sheet';
    useSimpleVariantsSelector?: boolean;
    configuratorTriggerStyle?: 'single-button' | 'split-buttons';
    configuratorTriggerStyleMobile?: 'single-button' | 'split-buttons';
    variantDisplayStyle?: VariantDisplayMode;
    variantDisplayStyleMobile?: VariantDisplayMode;
    variantDisplayStyleInline?: VariantDisplayStyleOverlay;
    variantDisplayStyleInlineMobile?: VariantDisplayStyleOverlay;
    variantDisplayStyleOverlay?: VariantDisplayStyleOverlay;
    variantDisplayStyleOverlayMobile?: VariantDisplayStyleOverlay;
    /** Normalized option keys (id or name, lowercase) to hide from variant UI; defaults stay from iframe. */
    hideVariantOptions?: string[];
    shadowDOMs?: {
        mobileDrawer?: ShadowRoot;
        snap2CheckoutSheet?: ShadowRoot;
        configuratorViewControls?: ShadowRoot;
        popoverPortal?: ShadowRoot;
        modalPortal?: ShadowRoot;
        swatchbookPortal?: ShadowRoot;
    };
    cssString?: string;
    configuratorGalleryIsDeferred?: boolean;
    /** Display symbol for iframe price strings; default £. */
    currencySymbol?: string;
    snap2VariantSheetSideDesktop?: 'left' | 'right';
    snap2VariantSheetSideMobile?: 'left' | 'right';
    snap2ModulePanelPositionDesktop?: 'left' | 'right' | 'bottom';
    snap2ModulePanelPositionMobile?: 'left' | 'right' | 'bottom';
    initialiseMenuUsesExternalSelector?: boolean;
}>;
export declare const useOV25UI: () => OV25UIContextType;
export {};
