import { ColumnConfig as BaseColumnConfig, GridConfig as BaseGridConfig, TypeDefault as BaseTypeDefault, CellRenderContext, ColumnEditorContext, ColumnEditorSpec, ColumnViewRenderer, FrameworkAdapter, HeaderCellContext, HeaderLabelContext } from '@toolbox-web/grid'; import { Component, VNode } from 'vue'; import { registerEditorMountHook, EditorMountHook } from './editor-mount-hooks'; import { registerFeaturePropKey } from './feature-prop-keys'; import { TypeDefault, TypeDefaultsMap } from './grid-type-registry'; import { registerPostMountRefresh, PostMountRefreshHook } from './post-mount-refresh-hooks'; import { ColumnConfig, GridConfig } from './vue-column-config'; export type { GridConfig }; export { registerEditorMountHook, type EditorMountHook }; export { registerPostMountRefresh, type PostMountRefreshHook }; export { registerFeaturePropKey }; /** * Context handed to feature bridge installers so they can hook the adapter's * teleport lifecycle without depending on its private fields. * @internal */ export interface FeatureBridgeContext { /** Track a teleport key for cleanup on adapter cleanup(). */ trackTeleportKey(key: string): void; } /** * Installer signature: given a grid element + bridge context, returns the * row-renderer the adapter should expose, or undefined if no Vue template * is registered for that grid. * @internal */ export type RowRendererBridge = (gridEl: HTMLElement, ctx: FeatureBridgeContext) => ((row: TRow, rowIndex: number) => HTMLElement) | undefined; /** * Installer signature for the type-default `filterPanelRenderer` wrapper. * Receives the user's Vue render function (typed loosely as `unknown` so * the adapter does not depend on filtering types) and returns the imperative * `(container, params) => void` form required by the core grid. * @internal */ export type FilterPanelTypeDefaultBridge = (renderFn: unknown, gridEl: HTMLElement | undefined, ctx: FeatureBridgeContext) => NonNullable; /** * Install the master-detail row-renderer bridge on the Vue adapter. Called * once on import by `@toolbox-web/grid-vue/features/master-detail`. Mirrors * how core grid plugins augment the grid via `registerPlugin()`. * @internal Plugin API */ export declare function registerDetailRendererBridge(bridge: RowRendererBridge): void; /** * Install the responsive card row-renderer bridge on the Vue adapter. Called * once on import by `@toolbox-web/grid-vue/features/responsive`. * @internal Plugin API */ export declare function registerResponsiveCardRendererBridge(bridge: RowRendererBridge): void; /** * Install the type-default `filterPanelRenderer` wrapper. Called once on * import by `@toolbox-web/grid-vue/features/filtering`. Without this bridge, * type-default and grid-config-level filterPanelRenderer entries are dropped * silently — filter panels only work if the filtering feature is also * imported, which is the same precondition as the FilteringPlugin itself * (TBW031). * @internal Plugin API */ export declare function registerFilterPanelTypeDefaultBridge(bridge: FilterPanelTypeDefaultBridge): void; /** * Register a Vue cell renderer for a column element. * Called by TbwGridColumn when it has a #cell slot. */ export declare function registerColumnRenderer(element: HTMLElement, renderer: (ctx: CellRenderContext) => VNode): void; /** * Register a Vue cell editor for a column element. * Called by TbwGridColumn when it has an #editor slot. */ export declare function registerColumnEditor(element: HTMLElement, editor: (ctx: ColumnEditorContext) => VNode): void; /** * Get the renderer registered for a column element. * Falls back to field-based lookup if WeakMap lookup fails. */ export declare function getColumnRenderer(element: HTMLElement): ((ctx: CellRenderContext) => VNode) | undefined; /** * Get the editor registered for a column element. * Falls back to field-based lookup if WeakMap lookup fails. */ export declare function getColumnEditor(element: HTMLElement): ((ctx: ColumnEditorContext) => VNode) | undefined; /** * Register a Vue header-cell renderer for a column element. * Called by TbwGridColumn when it has a `#header` slot. */ export declare function registerColumnHeaderRenderer(element: HTMLElement, renderer: (ctx: HeaderCellContext) => VNode): void; /** * Register a Vue header-label renderer for a column element. * Called by TbwGridColumn when it has a `#headerLabel` slot. */ export declare function registerColumnHeaderLabelRenderer(element: HTMLElement, renderer: (ctx: HeaderLabelContext) => VNode): void; /** * Get the header renderer registered for a column element. * Falls back to field-based lookup if WeakMap lookup fails. */ export declare function getColumnHeaderRenderer(element: HTMLElement): ((ctx: HeaderCellContext) => VNode) | undefined; /** * Get the header label renderer registered for a column element. * Falls back to field-based lookup if WeakMap lookup fails. */ export declare function getColumnHeaderLabelRenderer(element: HTMLElement): ((ctx: HeaderLabelContext) => VNode) | undefined; export declare function registerTypeRenderer(element: HTMLElement, renderer: (ctx: CellRenderContext) => VNode): void; export declare function getTypeRenderer(element: HTMLElement): ((ctx: CellRenderContext) => VNode) | undefined; export declare function registerTypeEditor(element: HTMLElement, editor: (ctx: ColumnEditorContext) => VNode): void; export declare function getTypeEditor(element: HTMLElement): ((ctx: ColumnEditorContext) => VNode) | undefined; /** * Get all registered field names. * @internal - for testing only */ export declare function getRegisteredFields(): string[]; /** * Clear the field registries. * Called during adapter cleanup and in tests. * @internal */ export declare function clearFieldRegistries(): void; /** * Checks if a value is a Vue component (SFC or defineComponent result). * * Vue components are identified by: * - Having `__name` (SFC compiled marker) * - Having `setup` function (Composition API component) * - Having `render` function (Options API component) * - Being an ES6 class (class-based component) * * Regular functions `(ctx) => HTMLElement` that are already processed * will not match these checks, making this idempotent. * @since 0.3.1 */ export declare function isVueComponent(value: unknown): value is Component; /** * Framework adapter that enables Vue 3 component integration * with the grid's light DOM configuration API. * * ## Usage * * The adapter is automatically registered when using the TbwGrid component. * For advanced use cases, you can manually register: * * ```ts * import { GridElement } from '@toolbox-web/grid'; * import { GridAdapter } from '@toolbox-web/grid-vue'; * * // One-time registration * GridElement.registerAdapter(new GridAdapter()); * ``` * * ## Declarative usage with TbwGrid: * * ```vue * * * * * * ``` * @since 0.3.0 */ export declare class GridAdapter implements FrameworkAdapter { /** Teleport keys tracked for cleanup. */ private teleportKeys; /** Editor-specific teleport keys tracked separately for per-cell cleanup. */ private editorTeleportKeys; /** * Stable bridge context handed to feature installers. Bound once per * adapter so feature bridges can call `trackTeleportKey` without each * invocation creating a fresh closure. */ private readonly bridgeContext; /** * Per-editor `before-edit-close` listener teardown functions, keyed by * editor container. * * The grid's editing plugin emits `before-edit-close` on the host `` * before tearing down a row's managed editors. Vue editors commonly write * `@blur="commit"` to flush local state on click-away, but Tab / programmatic * row exit rebuilds the cell DOM synchronously without giving the focused * input a chance to fire `blur` first — so the `@blur` handler never runs * and pending input is lost. * * To bridge that gap we call native `.blur()` on the focused input inside * the editor container as soon as `before-edit-close` fires. `.blur()` * dispatches the full focus-loss chain (`blur` + `focusout`) so any editor * with `@blur="commit"` flushes before the cell DOM is torn down. * * Mirrors the React adapter's `editorBeforeCloseUnsubs` and the Angular * adapter's `BaseGridEditor.onBeforeEditClose()` hook. */ private editorBeforeCloseUnsubs; private typeDefaults; /** * Processes a Vue grid configuration, converting Vue component references * and VNode-returning render functions to DOM-returning functions. * * This is idempotent — already-processed configs pass through safely. * * @example * ```ts * import { GridAdapter, type GridConfig } from '@toolbox-web/grid-vue'; * import StatusBadge from './StatusBadge.vue'; * * const config: GridConfig = { * columns: [ * { field: 'status', renderer: StatusBadge }, * ], * }; * * const adapter = new GridAdapter(); * const processedConfig = adapter.processGridConfig(config); * ``` * * @param config - Vue grid config with possible component/VNode references * @returns Processed config with DOM-returning functions */ processGridConfig(config: GridConfig): BaseGridConfig; /** * FrameworkAdapter.processConfig implementation. * Called automatically by the grid's `set gridConfig` setter. */ processConfig(config: BaseGridConfig): BaseGridConfig; /** * Processes typeDefaults, converting Vue component/VNode references * to DOM-returning functions. * * @param typeDefaults - Vue type defaults with possible component references * @returns Processed TypeDefault record */ processTypeDefaults(typeDefaults: Record>): Record>; /** * Processes a single column configuration, converting Vue component references * and VNode-returning render functions to DOM-returning functions. * * @param column - Vue column config * @returns Processed ColumnConfig with DOM-returning functions */ processColumn(column: ColumnConfig): BaseColumnConfig; /** * Creates a DOM-returning renderer from a Vue component class. * Used for config-based renderers (not slot-based). * @internal */ private createConfigComponentRenderer; /** * Creates a DOM-returning renderer from a VNode-returning render function. * Used for config-based renderers (not slot-based). * @internal */ private createConfigVNodeRenderer; /** * Schedules a microtask that runs all registered editor-mount hooks for * `container` once it's been appended to the cell DOM (so `closest('tbw-grid, [data-tbw-grid]')` * resolves). Mirror of the same bridge inline in `createEditor` (slot path) * and the React adapter's `wrapReactEditor` / `createEditor`. * * Hooks are installed by feature secondary entries (e.g. * `@toolbox-web/grid-vue/features/editing` installs the `before-edit-close` * blur bridge). If no feature is imported, no hooks run — which matches * the corresponding plugin precondition (e.g. EditingPlugin requires the * editing feature import to even exist). * @internal */ private attachBeforeEditCloseFlush; /** * Creates a DOM-returning editor from a Vue component class. * Used for config-based editors (not slot-based). * @internal */ private createConfigComponentEditor; /** * Creates a DOM-returning editor from a VNode-returning render function. * Used for config-based editors (not slot-based). * @internal */ private createConfigVNodeEditor; /** * Creates a DOM-returning header renderer from a Vue component class. * Used for config-based headerRenderer (not slot-based). * @internal */ private createConfigComponentHeaderRenderer; /** * Creates a DOM-returning header renderer from a VNode-returning render function. * Used for config-based headerRenderer (not slot-based). * @internal */ private createConfigVNodeHeaderRenderer; /** * Creates a DOM-returning header label renderer from a Vue component class. * Used for config-based headerLabelRenderer (not slot-based). * @internal */ private createConfigComponentHeaderLabelRenderer; /** * Creates a DOM-returning header label renderer from a VNode-returning render function. * Used for config-based headerLabelRenderer (not slot-based). * @internal */ private createConfigVNodeHeaderLabelRenderer; /** * Creates a DOM-returning loading renderer from a Vue component class. * @internal */ private createComponentLoadingRenderer; /** * Creates a DOM-returning loading renderer from a VNode-returning render function. * @internal */ private createVNodeLoadingRenderer; /** * Creates a DOM-returning empty-state renderer from a Vue component class. * The component receives the {@link EmptyContext} fields as props * (`sourceRowCount`, `filteredOut`). * @internal */ private createComponentEmptyRenderer; /** * Creates a DOM-returning empty-state renderer from a render function. * * The Vue `GridConfig.emptyRenderer` type permits both a VNode-returning * function (mounted via teleport) and a vanilla * `(ctx) => HTMLElement | string` function (passed through unchanged). * Mirroring `wrapReactEmptyRenderer`, we invoke the renderer and only * teleport-mount when the result is a VNode; DOM/string results are * returned as-is so consumers can mix vanilla and Vue renderers freely. * @internal */ private createVNodeEmptyRenderer; /** * Sets the type defaults map for this adapter. * Called by TbwGrid when it receives type defaults from context. * * @internal */ setTypeDefaults(defaults: TypeDefaultsMap | null): void; /** * Determines if this adapter can handle the given element. * Checks if a renderer or editor is registered for this element. */ canHandle(element: HTMLElement): boolean; /** * Creates a view renderer function that renders a Vue component * and returns its container DOM element. */ createRenderer(element: HTMLElement): ColumnViewRenderer | undefined; /** * Creates an editor spec that renders a Vue component for cell editing. * Returns a function that creates the editor DOM element. */ createEditor(element: HTMLElement): ColumnEditorSpec | undefined; /** * Creates a DOM-returning header renderer for a `` * element that has registered a slot-based renderer via `#header`. * Returns undefined when no slot was registered, letting the grid * fall back to its built-in header. * * Reuses the same teleport/VNode infrastructure as the config-path * `headerRenderer` wrapper. */ createHeaderRenderer(element: HTMLElement): ((ctx: HeaderCellContext) => HTMLElement) | undefined; /** * Creates a DOM-returning header *label* renderer for a `` * element that has registered a slot-based renderer via `#headerLabel`. * Returns undefined when no slot was registered. */ createHeaderLabelRenderer(element: HTMLElement): ((ctx: HeaderLabelContext) => HTMLElement) | undefined; /** * Framework adapter hook called by MasterDetailPlugin during attach(). * Implementation is installed by `@toolbox-web/grid-vue/features/master-detail` * via `registerDetailRendererBridge`. Returns undefined if the * master-detail feature has not been imported, or if no TbwGridDetailPanel * was registered for this grid. */ parseDetailElement(detailElement: Element): ((row: TRow, rowIndex: number) => HTMLElement) | undefined; /** * Framework adapter hook called by ResponsivePlugin during attach(). * Implementation is installed by `@toolbox-web/grid-vue/features/responsive` * via `registerResponsiveCardRendererBridge`. Returns undefined if * the responsive feature has not been imported, or if no TbwGridResponsiveCard * was registered for this grid. */ parseResponsiveCardElement(cardElement: Element): ((row: TRow, rowIndex: number) => HTMLElement) | undefined; /** * Framework adapter hook called by the grid core when a `` * needs a renderer. Returns a function that renders Vue tool panel content * into the shell's accordion container. * * Uses a wrapper-detach pattern for the cleanup callback: the cleanup * synchronously removes a wrapper div from the container, so the shell's * subsequent `contentArea.innerHTML = ''` (during accordion collapse) sees * an empty container and cannot disturb Vue's still-attached teleport * children. Vue then unmounts asynchronously on the next microtask * against the orphaned wrapper without throwing `NotFoundError`. */ createToolPanelRenderer(element: HTMLElement): ((container: HTMLElement) => void | (() => void)) | undefined; /** * Gets type-level defaults from the type defaults map. * * This enables application-wide type defaults configured via GridTypeProvider. * The returned TypeDefault contains renderer/editor functions that render * Vue components into the grid's cells. * * @example * ```vue * * * * ``` */ getTypeDefault(type: string, _gridEl?: HTMLElement): BaseTypeDefault | undefined; /** * Creates a renderer function from a Vue render function for type defaults. * @internal */ private createTypeRenderer; /** * Creates an editor function from a Vue render function for type defaults. * @internal */ private createTypeEditor; /** * Cleanup all teleport entries. */ cleanup(): void; /** * Unmount a specific container (e.g., detail panel, tool panel). * Currently a no-op for teleport-based rendering — the TeleportManager's * prune pass handles disconnected containers automatically. */ unmount(_container: HTMLElement): void; /** * Called when a cell's content is about to be wiped. * Destroys editor teleports whose container is inside the cell. */ releaseCell(cellEl: HTMLElement): void; /** * Open a teardown batch. No-op for the Vue adapter — teleport removals * are already coalesced into a single reactive `Map` swap per microtask * by the TeleportManager (see `teleport-manager.ts`). Implemented for * {@link FrameworkAdapter} parity so grid core's bulk-teardown wrappers * work uniformly across adapters. */ beginBatch(_gridEl?: HTMLElement): void; /** * Close a teardown batch opened by {@link beginBatch}. No-op for Vue — * see {@link beginBatch}. */ endBatch(_gridEl?: HTMLElement): void; } //# sourceMappingURL=vue-grid-adapter.d.ts.map