import type { Fn } from '../@aileron/declare/index.js';
import type { ModalNode } from '../core/index.js';
/**
* Hook that counts the number of active modals based on a validation function.
*
* Provides a reactive count of modals that match specific criteria. By default,
* counts visible modals, but can be customized with any validation logic.
* Useful for managing overlays, z-index stacking, or conditional UI based on modal count.
*
* @param validate - Function to determine if a modal should be counted (default: checks visibility)
* @param refreshKey - Optional key to force recalculation when changed
* @returns Number of modals that pass the validation
*
* @example
* Basic usage - count visible modals:
* ```tsx
* function ModalOverlay() {
* const activeCount = useActiveModalCount();
*
* if (activeCount === 0) return null;
*
* return (
*
* );
* }
* ```
*
* @example
* Count modals by type:
* ```tsx
* function ModalStats() {
* const alertCount = useActiveModalCount(
* (modal) => modal?.type === 'alert' && modal.visible
* );
*
* const confirmCount = useActiveModalCount(
* (modal) => modal?.type === 'confirm' && modal.visible
* );
*
* const promptCount = useActiveModalCount(
* (modal) => modal?.type === 'prompt' && modal.visible
* );
*
* return (
*
*
Alerts: {alertCount}
*
Confirms: {confirmCount}
*
Prompts: {promptCount}
*
* );
* }
* ```
*
* @example
* Prevent interactions when modals are active:
* ```tsx
* function App() {
* const hasActiveModals = useActiveModalCount() > 0;
*
* return (
*
*
* Navigate
*
*
* // Main content
*
*
* );
* }
* ```
*
* @example
* Count alive modals (including hidden ones):
* ```tsx
* function ModalMemoryMonitor() {
* const aliveCount = useActiveModalCount(
* (modal) => modal?.alive === true
* );
*
* const hiddenCount = useActiveModalCount(
* (modal) => modal?.alive && !modal.visible
* );
*
* return (
*
*
Total alive modals: {aliveCount}
*
Hidden (animating out): {hiddenCount}
*
* Cleanup Hidden Modals
*
*
* );
* }
* ```
*
* @example
* Dynamic refresh with dependencies:
* ```tsx
* function FilteredModalCount({ filter }) {
* const [refreshKey, setRefreshKey] = useState(0);
*
* // Count modals matching dynamic filter
* const count = useActiveModalCount(
* (modal) => {
* if (!modal?.visible) return false;
* if (filter.type && modal.type !== filter.type) return false;
* if (filter.group && modal.group !== filter.group) return false;
* return true;
* },
* refreshKey // Force recalculation when key changes
* );
*
* // Refresh count when filter changes
* useEffect(() => {
* setRefreshKey(prev => prev + 1);
* }, [filter]);
*
* return Matching modals: {count}
;
* }
* ```
*
* @example
* Limit modal stacking:
* ```tsx
* function LimitedModalProvider({ children, maxModals = 3 }) {
* const activeCount = useActiveModalCount();
*
* const openModal = useCallback((modalConfig) => {
* if (activeCount >= maxModals) {
* alert({
* title: 'Too Many Modals',
* content: `Maximum of ${maxModals} modals can be open at once.`,
* subtype: 'warning',
* });
* return Promise.reject(new Error('Modal limit exceeded'));
* }
*
* return originalOpenModal(modalConfig);
* }, [activeCount, maxModals]);
*
* return (
*
* {children}
*
* );
* }
* ```
*
* @remarks
* - Recalculates whenever modal list changes or refreshKey updates
* - Default validation counts visible modals only
* - Custom validation can check any modal properties
* - Efficient memoization prevents unnecessary recalculations
* - Use refreshKey to force updates based on external dependencies
*/
export declare const useActiveModalCount: (validate?: Fn<[node?: ModalNode], boolean | undefined>, refreshKey?: string | number) => number;