import { HookableCore } from 'hookable';
import { t as GenericScript, aN as ScriptHttpEvents, D as DataKeys, a1 as MaybeEventFnHandlers, z as HttpEventAttributes, aK as SchemaAugmentations, v as HeadTag, aw as ResolvableHead, aX as TagPosition, aY as TagPriority, ar as ProcessesTemplateParams, aJ as ResolvesDuplicates, a_ as TemplateParams } from './unhead.Bz11580x.js';

type UseScriptStatus = 'awaitingLoad' | 'loading' | 'loaded' | 'error' | 'removed';
type UseScriptContext<T extends Record<symbol | string, any>> = ScriptInstance<T>;
/**
 * Either a string source for the script or full script properties.
 */
type UseScriptResolvedInput = Omit<GenericScript, 'src' | keyof ScriptHttpEvents> & {
    src: string;
} & DataKeys & MaybeEventFnHandlers<HttpEventAttributes> & SchemaAugmentations['script'];
type BaseScriptApi = Record<symbol | string, any>;
type HasDiscriminatedParameters<T> = T extends {
    (first: infer A, ...rest1: any[]): any;
    (first: infer B, ...rest2: any[]): any;
} ? A extends B ? B extends A ? false : true : true : false;
type HasDifferentParameterCounts<T> = T extends {
    (...args: infer A): any;
} & {
    (...args: infer B): any;
} ? A['length'] extends B['length'] ? B['length'] extends A['length'] ? false : true : true : false;
type IsOverloadedFunction<T> = HasDiscriminatedParameters<T> extends true ? true : HasDifferentParameterCounts<T> extends true ? true : false;
type AsVoidFunctions<T extends BaseScriptApi> = {
    [K in keyof T]: T[K] extends any[] ? T[K] : T[K] extends (...args: infer A) => any ? IsOverloadedFunction<T[K]> extends true ? T[K] : (...args: A) => void : T[K] extends Record<any, any> ? AsVoidFunctions<T[K]> : never;
};
type UseScriptInput = string | UseScriptResolvedInput;
type UseFunctionType<T, U> = T extends {
    use: infer V;
} ? V extends (...args: any) => any ? ReturnType<V> : U : U;
type WarmupStrategy = false | 'preload' | 'preconnect' | 'dns-prefetch';
interface ScriptInstance<T extends BaseScriptApi> {
    proxy: AsVoidFunctions<T>;
    instance?: T;
    id: string;
    status: Readonly<UseScriptStatus>;
    entry?: ActiveHeadEntry<any>;
    load: () => Promise<T>;
    warmup: (rel: WarmupStrategy) => ActiveHeadEntry<any>;
    remove: () => boolean;
    setupTriggerHandler: (trigger: UseScriptOptions['trigger']) => void;
    onLoaded: (fn: (instance: T) => void | Promise<void>, options?: EventHandlerOptions) => void;
    onError: (fn: (err?: Error) => void | Promise<void>, options?: EventHandlerOptions) => void;
    /**
     * @internal
     */
    _warmupStrategy?: string;
    /**
     * @internal
     */
    _loadPromise: Promise<T | false>;
    /**
     * @internal
     */
    _warmupEl: any;
    /**
     * @internal
     */
    _triggerAbortController?: AbortController | null;
    /**
     * @internal
     */
    _triggerAbortControllers?: Set<AbortController>;
    /**
     * @internal
     */
    _triggerPromises?: Promise<void>[];
    /**
     * @internal
     */
    _cbs: {
        loaded: null | ((instance: T) => void | Promise<void>)[];
        error: null | ((err?: Error) => void | Promise<void>)[];
    };
}
interface EventHandlerOptions {
    /**
     * Used to dedupe the event, allowing you to have an event run only a single time.
     */
    key?: string;
}
type RecordingEntry = {
    type: 'get';
    key: string | symbol;
    args?: any[];
    value?: any;
} | {
    type: 'apply';
    key: string | symbol;
    args: any[];
};
interface UseScriptOptions<T extends BaseScriptApi = Record<string, any>> extends HeadEntryOptions {
    /**
     * Resolve the script instance from the window.
     */
    use?: () => T | undefined | null;
    /**
     * The trigger to load the script:
     * - `undefined` | `client` - (Default) Load the script on the client when this js is loaded.
     * - `manual` - Load the script manually by calling `$script.load()`, exists only on the client.
     * - `Promise` - Load the script when the promise resolves, exists only on the client.
     * - `Function` - Register a callback function to load the script, exists only on the client.
     * - `server` - Have the script injected on the server.
     */
    trigger?: 'client' | 'server' | 'manual' | Promise<boolean | void> | ((fn: any) => any) | null;
    /**
     * Add a preload or preconnect link tag before the script is loaded.
     */
    warmupStrategy?: WarmupStrategy;
    /**
     * Context to run events with. This is useful in Vue to attach the current instance context before
     * calling the event, allowing the event to be reactive.
     */
    eventContext?: any;
    /**
     * Called before the script is initialized. Will not be triggered when the script is already loaded. This means
     * this is guaranteed to be called only once, unless the script is removed and re-added.
     */
    beforeInit?: () => void;
}
type UseScriptReturn<T extends Record<symbol | string, any>> = UseScriptContext<UseFunctionType<UseScriptOptions<T>, T>>;

type HookResult = Promise<void> | void;
type SyncHookResult = void;
interface SSRHeadPayload {
    headTags: string;
    bodyTags: string;
    bodyTagsOpen: string;
    htmlAttrs: string;
    bodyAttrs: string;
}
interface RenderSSRHeadOptions {
    omitLineBreaks?: boolean;
    resolvedTags?: HeadTag[];
    tagWeight?: (tag: HeadTag) => number;
}
interface EntryResolveCtx<T> {
    tags: HeadTag[];
    entries: HeadEntry<T>[];
}
interface DomBeforeRenderCtx extends ShouldRenderContext {
    tags: HeadTag[];
}
interface ShouldRenderContext {
    shouldRender: boolean;
}
interface DomRenderTagContext {
    tag: HeadTag;
    id: string;
    $el?: Element;
    shouldRender: boolean;
}
interface SSRRenderContext {
    tags: HeadTag[];
    html: SSRHeadPayload;
}
interface TagResolveContext {
    tagMap: Map<string, HeadTag>;
    tags: HeadTag[];
}
interface CoreHeadHooks {
    'entries:updated': (ctx: Unhead<any>) => HookResult;
    'entries:resolve': (ctx: EntryResolveCtx<any>) => SyncHookResult;
    'entries:normalize': (ctx: {
        tags: HeadTag[];
        entry: HeadEntry<any>;
    }) => SyncHookResult;
    'tag:normalise': (ctx: {
        tag: HeadTag;
        entry: HeadEntry<any>;
        resolvedOptions: CreateClientHeadOptions;
    }) => SyncHookResult;
    'tags:beforeResolve': (ctx: TagResolveContext) => SyncHookResult;
    'tags:resolve': (ctx: TagResolveContext) => SyncHookResult;
    'tags:afterResolve': (ctx: TagResolveContext) => SyncHookResult;
    'script:updated': (ctx: {
        script: ScriptInstance<any>;
    }) => void | Promise<void>;
}
interface DOMHeadHooks {
    'dom:beforeRender': (ctx: DomBeforeRenderCtx) => SyncHookResult;
    /** @deprecated Not called internally. Will be removed in v4. */
    'dom:renderTag': (ctx: DomRenderTagContext, document: Document, track: (id: string, scope: string, fn: () => void) => void) => HookResult;
    /** @deprecated Will be removed in v4. DOM rendering is synchronous; run post-render logic after calling `renderDOMHead()` directly. */
    'dom:rendered': (ctx: {
        renders: DomRenderTagContext[];
    }) => HookResult;
}
interface SSRHeadHooks {
    'ssr:beforeRender': (ctx: ShouldRenderContext) => HookResult;
    'ssr:render': (ctx: {
        tags: HeadTag[];
        options: RenderSSRHeadOptions;
    }) => HookResult;
    'ssr:rendered': (ctx: SSRRenderContext) => HookResult;
}
type ClientHeadHooks = CoreHeadHooks & DOMHeadHooks;
type ServerHeadHooks = CoreHeadHooks & SSRHeadHooks;
type HeadHooks = CoreHeadHooks & DOMHeadHooks & SSRHeadHooks;

/**
 * Side effects are mapped with a key and their cleanup function.
 *
 * For example, `meta:data-h-4h46h465`: () => { document.querySelector('meta[data-h-4h46h465]').remove() }
 */
type SideEffectsRecord = Record<string, () => void>;
interface HeadEntry<Input> {
    /**
     * User provided input for the entry.
     */
    input: Input;
    options?: {
        /**
         * Default tag position.
         *
         * @internal
         */
        tagPosition?: TagPosition['tagPosition'];
        /**
         * Default tag priority.
         *
         * @internal
         */
        tagPriority?: TagPriority['tagPriority'];
        /**
         * Default tag duplicate strategy.
         *
         * @internal
         */
        tagDuplicateStrategy?: HeadTag['tagDuplicateStrategy'];
        /**
         * @internal
         */
        _safe?: boolean;
    };
    /**
     * Head entry index
     *
     * @internal
     */
    _i: number;
    /**
     * Resolved tags
     *
     * @internal
     */
    _tags?: HeadTag[];
    /**
     * Pending patch to apply on next render (client-only)
     * @internal
     */
    _pending?: Input;
    /**
     * @internal
     */
    _o?: Input;
    /**
     * @internal
     */
    _promisesProcessed?: boolean;
}
interface HeadPluginOptions extends CreateHeadOptions {
    hooks?: Record<string, (...args: any[]) => any>;
}
type HeadPluginInput = (HeadPluginOptions & {
    key: string;
}) | ((head: Unhead) => HeadPluginOptions & {
    key: string;
});
type HeadPlugin = HeadPluginOptions & {
    key: string;
};
/**
 * An active head entry provides an API to manipulate it.
 */
interface ActiveHeadEntry<Input> {
    /**
     * Updates the entry with new input.
     *
     * Will first clear any side effects for previous input.
     */
    patch: (input: Input) => void;
    /**
     * Dispose the entry, removing it from the active head.
     *
     * Will queue side effects for removal.
     */
    dispose: () => void;
    /**
     * @internal
     */
    _i: number;
}
type PropResolver = (key?: string, value?: any, tag?: HeadTag) => any;
interface CreateHeadOptions {
    document?: Document;
    /**
     * Initial head input that should be added.
     *
     * Any tags here are added with low priority.
     */
    init?: (ResolvableHead | undefined | false)[];
    /**
     * Prop resolvers for tags.
     */
    propResolvers?: PropResolver[];
    /**
     * @experimental
     * Key used for window attachment during streaming SSR.
     * Allows multiple Unhead instances on the same page.
     * @default '__unhead__'
     */
    experimentalStreamKey?: string;
    /**
     * @internal
     */
    _tagWeight?: (tag: HeadTag) => number;
}
interface CreateServerHeadOptions extends CreateHeadOptions {
    plugins?: HeadPluginInput[];
    hooks?: Partial<ServerHeadHooks>;
    /**
     * Custom tag weight function for controlling `<head>` tag ordering.
     *
     * By default, tags are sorted using CAPO weights optimised for the browser preload scanner.
     * Override this to change the ordering — for example, to prioritise SEO meta tags for bot requests.
     *
     * @example
     * ```ts
     * import { capoTagWeight } from 'unhead/server'
     *
     * createHead({
     *   tagWeight(tag) {
     *     // Promote SEO meta above styles for bots
     *     if (isBot && tag.tag === 'meta' && tag.props.property?.startsWith('og:'))
     *       return 55 // just above styles (60)
     *     return capoTagWeight(tag)
     *   }
     * })
     * ```
     */
    tagWeight?: (tag: HeadTag) => number;
    /**
     * Should default important tags be skipped.
     *
     * Adds the following tags with low priority:
     * - <html lang="en">
     * - <meta charset="utf-8">
     * - <meta name="viewport" content="width=device-width, initial-scale=1">
     */
    disableDefaults?: boolean;
    /**
     * Omit line breaks between rendered tags, producing a single line of output.
     *
     * Only removes the separators *between* tags; newlines inside inline
     * `<script>`/`<style>`/JSON-LD content are preserved.
     *
     * @deprecated Prefer `MinifyPlugin` from `unhead/plugins`, which minifies the
     * inline content itself (where the real bytes are) rather than only dropping
     * separators.
     */
    omitLineBreaks?: boolean;
}
interface CreateStreamableServerHeadOptions extends Omit<CreateServerHeadOptions, 'experimentalStreamKey'> {
    /**
     * Key used for window attachment during streaming SSR.
     * Allows multiple Unhead instances on the same page.
     * @default '__unhead__'
     */
    streamKey?: string;
}
interface CreateClientHeadOptions extends CreateHeadOptions {
    plugins?: HeadPluginInput[];
    hooks?: Partial<ClientHeadHooks>;
    /**
     * Custom render function for DOM updates.
     */
    render?: (head: Unhead<any>) => boolean | void;
}
interface HeadEntryOptions extends TagPosition, TagPriority, ProcessesTemplateParams, ResolvesDuplicates {
    head?: Unhead;
    /**
     * Called after unhead has finished applying DOM updates.
     *
     * Useful for synchronising external tools (e.g. analytics) with the current document head.
     *
     * Only called on the client — ignored during SSR.
     *
     * @example
     * useHead({ title: 'My Page' }, {
     *   onRendered({ renders }) {
     *     amplitude.track('Page View', { title: document.title })
     *   }
     * })
     */
    onRendered?: (ctx: {
        renders: DomRenderTagContext[];
    }) => void | Promise<void>;
    /**
     * @internal
     */
    _safe?: boolean;
    /**
     * @internal
     */
    _index?: number;
    /**
     * Source location for devtools tracing.
     * @internal
     */
    _source?: string;
}
type HeadRenderer<T = unknown> = (head: Unhead<any, any>) => T;
interface Unhead<Input = ResolvableHead, RenderResult = unknown> {
    /**
     * Render the head tags using the configured renderer.
     */
    render: () => RenderResult;
    /**
     * Registered plugins.
     */
    plugins: Map<string, HeadPlugin>;
    /**
     * The head entries.
     */
    entries: Map<number, HeadEntry<Input>>;
    /**
     * Create a new head entry.
     */
    push: (entry: Input, options?: HeadEntryOptions) => ActiveHeadEntry<Input>;
    /**
     * Exposed hooks for easier extension.
     */
    hooks?: HookableCore<HeadHooks>;
    /**
     * Resolved options
     */
    resolvedOptions: CreateHeadOptions;
    /**
     * Use a head plugin, loads the plugins hooks.
     */
    use: (plugin: HeadPluginInput) => void;
    /**
     * Is it a server-side render context.
     */
    ssr: boolean;
    /**
     * @internal
     */
    _entryCount: number;
    /**
     * @internal
     */
    dirty?: boolean;
    /**
     * Invalidate all entries and re-queue them for normalization.
     * @internal
     */
    invalidate?: () => void;
    /**
     * @internal
     */
    _dom?: DomState;
    /**
     * @internal
     */
    _du?: boolean;
    /**
     * @internal
     */
    _scripts?: Record<string, any>;
    /**
     * @internal
     */
    _templateParams?: TemplateParams;
    /**
     * @internal
     */
    _separator?: string;
    /**
     * @internal
     */
    _title?: string;
    /**
     * @internal
     */
    _titleTemplate?: string;
    /**
     * @internal
     */
    _ssrPayload?: ResolvableHead;
    /**
     * @internal
     */
    _rootStreamedTags?: Record<string, HeadTag>;
}
interface DomState {
    /**
     * @internal
     */
    _t: string;
    /**
     * @internal
     */
    _p: SideEffectsRecord;
    /**
     * @internal
     */
    _s: SideEffectsRecord;
    /**
     * @internal
     */
    _e: Map<string, Element>;
}

export type { ActiveHeadEntry as A, UseScriptContext as B, ClientHeadHooks as C, DOMHeadHooks as D, EntryResolveCtx as E, UseScriptInput as F, UseScriptOptions as G, HeadEntry as H, UseScriptResolvedInput as I, UseScriptReturn as J, UseScriptStatus as K, PropResolver as P, RecordingEntry as R, SSRHeadHooks as S, Unhead as U, WarmupStrategy as W, AsVoidFunctions as a, CoreHeadHooks as b, CreateClientHeadOptions as c, CreateHeadOptions as d, CreateServerHeadOptions as e, CreateStreamableServerHeadOptions as f, DomBeforeRenderCtx as g, DomRenderTagContext as h, DomState as i, EventHandlerOptions as j, HeadEntryOptions as k, HeadHooks as l, HeadPlugin as m, HeadPluginInput as n, HeadPluginOptions as o, HeadRenderer as p, HookResult as q, RenderSSRHeadOptions as r, SSRHeadPayload as s, SSRRenderContext as t, ScriptInstance as u, ServerHeadHooks as v, ShouldRenderContext as w, SideEffectsRecord as x, SyncHookResult as y, UseFunctionType as z };
