/** * Shared element processing for structural directives. * * @remarks * Provides a unified way to process directives on elements created by * structural directives like g-if and g-for. Supports scope reuse for * state preservation across re-renders. * * All descendant processing uses registry-based discovery via * {@link processSubtree} and {@link processDiscoveredElement}, which * handles ALL directive types in both client and server modes. * * @packageDocumentation */ import { Mode, Expression, Directive, DirectiveOptions, TemplateOption, Context } from './types.js'; import { ContextKey } from './context-registry.js'; import { ServiceRegistry } from './resolver-config.js'; /** Attribute used to mark elements processed by g-for */ export declare const FOR_PROCESSED_ATTR = "data-g-for-processed"; /** Attribute used to mark elements processed by structural directives */ export declare const PROCESSED_ATTR = "data-g-processed"; /** * Options for processing element directives. */ export interface ProcessOptions { /** * Existing scope to use instead of creating a new one. * Use this to preserve state across re-renders (e.g., g-if toggle). */ existingScope?: Record; /** * Additional properties to add to the scope. * Used by g-for to add item/index variables. */ scopeAdditions?: Record; /** * Skip processing structural directives (g-for, g-if). * Set to true when processing content inside a structural directive * to avoid infinite recursion. */ skipStructural?: boolean; } /** * Provide the service registry for process.ts to use during directive resolution. * * @remarks * Called by hydrate.ts during init() so that directives invoked through * processElementTree can resolve service dependencies. * * @param services - The global service registry */ export declare function setProcessServices(services: ServiceRegistry): void; /** * Matched directive info for an element. * * @internal */ interface DirectiveMatch { fullName: string; directive: Directive; expr: string; options: DirectiveOptions; } /** * Options for invoking a single directive. */ export interface InvokeDirectiveOptions { fn: Directive; expr: Expression | string; el: Element; scope: Record; mode: Mode; using?: ContextKey[]; rootState?: Record; services?: ServiceRegistry; ctx?: Context; } /** * Invoke a directive: resolve DI, call fn, register provider. * * @remarks * Single shared path for directive invocation used by all processing * paths (client, server, structural clones). Handles dependency * resolution, function invocation, and provider registration. * * @param options - Invocation configuration * @returns The directive's return value (void or Promise) */ export declare function invokeDirective(options: InvokeDirectiveOptions): void | Promise; /** * Resolve and render a template option into an element. * * @param el - The target element * @param template - Template string or function * @returns Promise if the template function is async */ export declare function renderDirectiveTemplate(el: Element, template: TemplateOption): Promise; /** * Result of preparing an element for directive processing. * * @remarks * Contains scope, context, and matched directives. All processing paths * (processDiscoveredElement, setupRootScope, hydrate processElement, * render.ts per-element) use this to avoid duplicating preprocessing logic. * * g-bind:* is NOT applied here — it runs after the directive loop so that * directives that detach the element (like g-for/g-if) naturally prevent * g-bind from running on the original. */ export interface PreparedElement { scope: Record; ctx: Context; directives: DirectiveMatch[]; } /** * Options for prepareElementScope. */ export interface PrepareOptions { /** Existing scope to reuse (e.g., persistent scope from g-if toggle) */ existingScope?: Record; /** Additional properties to merge into scope (e.g., g-for item/index) */ scopeAdditions?: Record; /** Pre-discovered directive names (render.ts passes these from indexTree) */ directiveNames?: string[]; /** Decode HTML entities in g-scope expressions (server mode) */ decodeEntities?: boolean; } /** * Canonical preprocessing for an element before directive execution. * * @remarks * Handles scope creation, assigns, DI providers, element scope storage, * context creation, and g-scope evaluation. Returns null when the element * has nothing to process (no directives, no g-scope, no g-bind). * * g-bind:* is intentionally NOT processed here. Callers apply g-bind * after the directive loop, so directives that detach the element * (any priority level) naturally prevent stale bindings. * * @param el - The element to prepare * @param parentScope - Scope inherited from parent * @param mode - Execution mode * @param options - Configuration for scope source and directive discovery * @returns Preprocessing result, or null if nothing to process */ export declare function prepareElementScope(el: Element, parentScope: Record, mode: Mode, options?: PrepareOptions): PreparedElement | null; /** * Apply g-bind:* attribute bindings on an element. * * @remarks * Must be called AFTER the directive loop. If a directive detached the * element (e.g., g-for removes and replaces with clones), the caller * skips this — the directive handles bindings on its clones via * processElementTree. * * In CLIENT mode, uses reactive effects. In SERVER mode, evaluates once. * * @param el - The element to apply bindings on * @param ctx - The evaluation context * @param mode - Execution mode */ export declare function applyElementBindings(el: Element, ctx: Context, mode: Mode): void; /** * Execute the directive loop for an element. * * @remarks * Processes directives in priority order (already sorted). After each * synchronous directive, checks if the element was detached from its parent. * If so, the loop breaks — the directive took ownership and lower-priority * directives run on whatever replacement the directive created (via * processElementTree). * * This makes the system agnostic about "structural" directives: any * directive at any priority that detaches the element naturally stops * the loop. * * @param el - The element being processed * @param scope - The element's scope * @param mode - Execution mode * @param ctx - The evaluation context * @param directives - Matched directives sorted by priority * @returns Whether the element was detached, and any async chain */ export declare function executeDirectiveLoop(el: Element, scope: Record, mode: Mode, ctx: Context, directives: DirectiveMatch[]): { detached: boolean; chain?: Promise; }; /** * Result from processDiscoveredElement. */ export interface ProcessElementResult { scope: Record; detached: boolean; chain?: Promise; } /** * Process a single element with full directive support via global registry. * * @remarks * The single processing path for all descendant elements in processElementTree. * Also used by hydrate.ts processElement for client-side processing. * * Handles native slots, g-scope, g-bind:*, ALL registered directives, * scope creation, DI resolution, provider registration, and element * detachment detection. * * g-bind:* attributes are applied after the directive loop. If a directive * detached the element (e.g., g-for removes and replaces with clones), * g-bind is skipped — the directive handles bindings on its replacements. * * @param el - The element to process * @param parentScope - The scope inherited from the parent element * @param mode - Execution mode * @returns Result with scope, detachment flag, and async chain; or null if skipped * * @internal */ export declare function processDiscoveredElement(el: Element, parentScope: Record, mode: Mode): ProcessElementResult | null; /** * Process an element tree (element and all descendants). * * @remarks * Sets up the root element's scope (handling existingScope/scopeAdditions * from ProcessOptions), then discovers and processes ALL directive-bearing * descendants via {@link processSubtree} using the global directive registry. * * Uses the same processing path for both client and server modes. * The individual directives handle mode differences internally. * * @param el - The root element to process * @param parentScope - The parent scope * @param mode - Server or client mode * @param options - Processing options (existingScope only applies to root element) */ export declare function processElementTree(el: Element, parentScope: Record, mode: Mode, options?: ProcessOptions): void; export {};