import type { EntityContext } from '#blokkli/types'; import type { UiProvider } from './ui.js'; import { type ComputedRef } from '#imports'; import type { DebugProvider } from './debug.js'; import type { Rectangle } from '../types/geometry.js'; import type { BlokkliDirectiveType } from '#blokkli/types/directives'; export type ValueElementType = 'iframe'; type ValueElementEntry = { uuid: string; type: ValueElementType; value: string; }; type EditableFieldData = EntityContext & { key: string; fieldName: string; directiveType: BlokkliDirectiveType; isComponent: boolean; getValue?: () => string; }; type DroppableFieldElementData = EditableFieldData & { element: HTMLElement; }; export type DirectiveProvider = { /** * Initialize the directive provider. * * Starts the IntersectionObserver to track directive element visibility and positions. */ init: () => void; /** * Register a directive element for tracking. * * Starts observing the element with IntersectionObserver to track visibility and position. * For 'editable' directives on blocks, also indexes by UUID for quick lookup. * * @param el - The HTML element with the directive * @param fieldName - The field name * @param entity - The entity context (type, bundle, UUID) * @param type - The directive type ('editable' or 'droppable') * @param isComponent - Whether this is a component-based field * @param getValue - Optional function to get the current field value */ registerDirectiveElement: (el: HTMLElement, fieldName: string, entity: EntityContext, type: BlokkliDirectiveType, isComponent: boolean, getValue?: () => string) => void; /** * Unregister a directive element from tracking. * * Stops observing the element and removes it from all tracking maps. * * @param el - The HTML element to unregister * @param fieldName - The field name * @param entity - The entity context * @param type - The directive type */ unregisterDirectiveElement: (el: HTMLElement, fieldName: string, entity: EntityContext, type: BlokkliDirectiveType) => void; /** * Get rectangles for all visible directives of a specific type. * * Only includes directives currently in the viewport. * * @param directiveType - The directive type to filter by * @returns Array of rectangles for visible directives */ getVisible: (directiveType: BlokkliDirectiveType) => Rectangle[]; /** * Find the editable field at a specific screen coordinate. * * Converts screen coordinates to artboard space and checks if any visible * editable field contains the point. * * @param x - Screen X coordinate * @param y - Screen Y coordinate * @returns The editable field data at that point, or undefined */ getEditableAtPoint: (x: number, y: number) => EditableFieldData | undefined; /** * Find the droppable field at a specific screen coordinate. * * Converts screen coordinates to artboard space and checks if any visible * droppable field contains the point. * * @param x - Screen X coordinate * @param y - Screen Y coordinate * @returns The droppable field data at that point, or undefined */ getDroppableAtPoint: (x: number, y: number) => EditableFieldData | undefined; /** * Get all editable fields for a specific block. * * Only returns 'editable' type directives on block entities. * * @param uuid - The block UUID * @returns Array of editable fields for the block */ getEditablesForBlock: (uuid: string) => EditableFieldData[]; /** * Get all currently registered editable fields, across both the host entity * and all blocks. Intended for debug/test tooling that needs to enumerate * every editable on the page. * * @returns Array of all 'editable' type directive fields */ getAllEditables: () => EditableFieldData[]; /** * Get all droppable field elements. * * Returns fields with the 'droppable' directive type along with their HTML elements. * * @returns Array of droppable field data with elements */ getDroppableElements: () => DroppableFieldElementData[]; /** * Find the HTML element for an editable field. * * @param fieldName - The field name * @param host - The host entity context * @returns The field's HTML element, or undefined if not found */ findEditableElement: (fieldName: string, host: EntityContext) => HTMLElement | undefined; /** * Find the editable field data. * * @param fieldName - The field name * @param host - The host entity context * @returns The editable field data, or undefined if not found */ findEditable: (fieldName: string, host: EntityContext) => EditableFieldData | undefined; /** * Register a value element for a block. * * Used by companion components (e.g. BlokkliIframe) to make runtime values * available to option editors during editing. */ registerValueElement: (uuid: string, type: ValueElementType, value: string) => void; /** * Unregister a value element for a block. */ unregisterValueElement: (uuid: string, type: ValueElementType) => void; /** * Get the registered value for a specific block and type. */ getValueElement: (uuid: string, type: ValueElementType) => string | undefined; /** * Get all registered values for a given type. */ getValueElements: (type: ValueElementType) => ValueElementEntry[]; /** * Whether the directive provider is ready. * * Ready when IntersectionObserver is initialized and initial measurements are complete. */ isReady: ComputedRef; /** * Settlement key that increments after directive changes settle. * * Useful for triggering reactivity after directives are registered/unregistered. */ settleKey: ComputedRef; }; export default function (debug: DebugProvider, ui: UiProvider): DirectiveProvider; export {};