/**
 * @license MIT
 * author: Cube Dev Team
 * @cube-dev/ui-kit v0.0.0-canary-2305ece
 * Released under the MIT license.
 */

import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext, useMemo, useRef, useState, } from 'react';
import { useEvent } from '../../../_internal/hooks/index.js';
export const LayoutRefsContext = createContext(null);
export function useLayoutRefsContext() {
    return useContext(LayoutRefsContext);
}
export const LayoutActionsContext = createContext(null);
export const LayoutStateContext = createContext(null);
export function useLayoutActionsContext() {
    return useContext(LayoutActionsContext);
}
export function useLayoutStateContext() {
    return useContext(LayoutStateContext);
}
/**
 * Combined hook that returns all layout context values.
 * Convenience wrapper around the individual context hooks.
 * Returns null if used outside of a Layout component.
 */
export function useLayoutContext() {
    const actions = useLayoutActionsContext();
    const state = useLayoutStateContext();
    const refs = useLayoutRefsContext();
    if (!actions || !state || !refs) {
        return null;
    }
    return { ...actions, ...state, ...refs };
}
export function LayoutProvider({ children, hasTransition = false, }) {
    const registeredPanels = useRef(new Set());
    const overlayPanelCallbacks = useRef(new Set());
    const panelContainerRef = useRef(null);
    const [isPanelContainerReady, setIsPanelContainerReady] = useState(false);
    // Callback ref for panel container - triggers re-render when container mounts
    const setPanelContainer = useEvent((element) => {
        panelContainerRef.current = element;
        setIsPanelContainerReady(element !== null);
    });
    const [panelSizes, setPanelSizes] = useState({
        left: 0,
        top: 0,
        right: 0,
        bottom: 0,
    });
    const [isDragging, setIsDragging] = useState(false);
    const [isReady, setIsReady] = useState(false);
    const [hasOverlayPanels, setHasOverlayPanels] = useState(false);
    const updatePanelSize = useEvent((side, size) => {
        setPanelSizes((prev) => {
            if (prev[side] === size)
                return prev;
            return { ...prev, [side]: size };
        });
    });
    const registerPanel = useEvent((side, size) => {
        if (registeredPanels.current.has(side)) {
            throw new Error(`Layout: Only one panel per side is allowed. ` +
                `A panel is already registered on the "${side}" side.`);
        }
        // Check for axis conflict
        const isHorizontal = side === 'left' || side === 'right';
        const conflictingSides = isHorizontal
            ? ['top', 'bottom']
            : ['left', 'right'];
        for (const conflictSide of conflictingSides) {
            if (registeredPanels.current.has(conflictSide)) {
                throw new Error(`Layout: Panels from different axes cannot be combined. ` +
                    `Cannot register "${side}" panel when "${conflictSide}" panel exists. ` +
                    `Use either horizontal (left/right) or vertical (top/bottom) panels.`);
            }
        }
        registeredPanels.current.add(side);
        updatePanelSize(side, size);
    });
    const unregisterPanel = useEvent((side) => {
        registeredPanels.current.delete(side);
        updatePanelSize(side, 0);
    });
    const setDragging = useEvent((dragging) => {
        setIsDragging(dragging);
    });
    const markReady = useEvent(() => {
        setIsReady(true);
    });
    const registerOverlayPanel = useEvent((dismiss) => {
        overlayPanelCallbacks.current.add(dismiss);
        setHasOverlayPanels(true);
        // Return unregister function
        return () => {
            overlayPanelCallbacks.current.delete(dismiss);
            setHasOverlayPanels(overlayPanelCallbacks.current.size > 0);
        };
    });
    const dismissOverlayPanels = useEvent(() => {
        overlayPanelCallbacks.current.forEach((dismiss) => dismiss());
    });
    // Actions context - stable because all callbacks use useEvent
    const actionsValue = useMemo(() => ({
        registerPanel,
        unregisterPanel,
        updatePanelSize,
        setDragging,
        markReady,
        hasTransition,
        registerOverlayPanel,
        dismissOverlayPanels,
    }), 
    // Only hasTransition can change - all other values are stable useEvent callbacks
    [hasTransition]);
    // State context - changes when state updates
    const stateValue = useMemo(() => ({
        panelSizes,
        isDragging,
        isReady,
        hasOverlayPanels,
    }), [panelSizes, isDragging, isReady, hasOverlayPanels]);
    // Refs context - includes container ready state
    const refsValue = useMemo(() => ({
        panelContainerRef,
        isPanelContainerReady,
        setPanelContainer,
    }), [isPanelContainerReady]);
    return (_jsx(LayoutRefsContext.Provider, { value: refsValue, children: _jsx(LayoutActionsContext.Provider, { value: actionsValue, children: _jsx(LayoutStateContext.Provider, { value: stateValue, children: children }) }) }));
}
/**
 * Provider that resets the layout context for sub-components.
 * Used to prevent panels in nested Layouts from affecting parent layouts.
 */
export function LayoutContextReset({ children }) {
    return (_jsx(LayoutRefsContext.Provider, { value: null, children: _jsx(LayoutActionsContext.Provider, { value: null, children: _jsx(LayoutStateContext.Provider, { value: null, children: children }) }) }));
}
export const LayoutPanelContext = createContext(null);
export function useLayoutPanelContext() {
    return useContext(LayoutPanelContext);
}

        