diff --git a/src/LiveComponent/assets/dist/Component/index.d.ts b/src/LiveComponent/assets/dist/Component/index.d.ts index 9c8b44ee2eb..16cc46f9ea0 100644 --- a/src/LiveComponent/assets/dist/Component/index.d.ts +++ b/src/LiveComponent/assets/dist/Component/index.d.ts @@ -1,8 +1,24 @@ import { BackendInterface } from '../Backend/Backend'; import ValueStore from './ValueStore'; +import BackendRequest from '../Backend/BackendRequest'; import { ElementDriver } from './ElementDriver'; import { PluginInterface } from './plugins/PluginInterface'; import BackendResponse from '../Backend/BackendResponse'; +type MaybePromise = T | Promise; +export type ComponentHooks = { + 'connect': (component: Component) => MaybePromise; + 'disconnect': (component: Component) => MaybePromise; + 'request:started': (requestConfig: any) => MaybePromise; + 'render:finished': (component: Component) => MaybePromise; + 'response:error': (backendResponse: BackendResponse, controls: { + displayError: boolean; + }) => MaybePromise; + 'loading.state.started': (element: HTMLElement, request: BackendRequest) => MaybePromise; + 'loading.state.finished': (element: HTMLElement) => MaybePromise; + 'model:set': (model: string, value: any, component: Component) => MaybePromise; +}; +export type ComponentHookName = keyof ComponentHooks; +export type ComponentHookCallback = T extends ComponentHookName ? ComponentHooks[T] : (...args: any[]) => MaybePromise; export default class Component { readonly element: HTMLElement; readonly name: string; @@ -30,8 +46,8 @@ export default class Component { addPlugin(plugin: PluginInterface): void; connect(): void; disconnect(): void; - on(hookName: string, callback: (...args: any[]) => void): void; - off(hookName: string, callback: (...args: any[]) => void): void; + on(hookName: T, callback: ComponentHookCallback): void; + off(hookName: T, callback: ComponentHookCallback): void; set(model: string, value: any, reRender?: boolean, debounce?: number | boolean): Promise; getData(model: string): any; action(name: string, args?: any, debounce?: number | boolean): Promise; @@ -55,3 +71,4 @@ export default class Component { _updateFromParentProps(props: any): void; } export declare function proxifyComponent(component: Component): Component; +export {}; diff --git a/src/LiveComponent/assets/dist/HookManager.d.ts b/src/LiveComponent/assets/dist/HookManager.d.ts index 0db9a9e356f..17b0fd07618 100644 --- a/src/LiveComponent/assets/dist/HookManager.d.ts +++ b/src/LiveComponent/assets/dist/HookManager.d.ts @@ -1,6 +1,6 @@ export default class { private hooks; - register(hookName: string, callback: () => void): void; - unregister(hookName: string, callback: () => void): void; + register(hookName: string, callback: (...args: any[]) => void): void; + unregister(hookName: string, callback: (...args: any[]) => void): void; triggerHook(hookName: string, ...args: any[]): void; } diff --git a/src/LiveComponent/assets/dist/PollingDirector.d.ts b/src/LiveComponent/assets/dist/PollingDirector.d.ts index c541e0ed380..84d07d0d197 100644 --- a/src/LiveComponent/assets/dist/PollingDirector.d.ts +++ b/src/LiveComponent/assets/dist/PollingDirector.d.ts @@ -1,4 +1,3 @@ -/// import Component from './Component'; export default class { component: Component; @@ -7,7 +6,7 @@ export default class { actionName: string; duration: number; }>; - pollingIntervals: NodeJS.Timer[]; + pollingIntervals: number[]; constructor(component: Component); addPoll(actionName: string, duration: number): void; startAllPolling(): void; diff --git a/src/LiveComponent/assets/dist/live_controller.js b/src/LiveComponent/assets/dist/live_controller.js index 65a1f541f1d..773c483868a 100644 --- a/src/LiveComponent/assets/dist/live_controller.js +++ b/src/LiveComponent/assets/dist/live_controller.js @@ -2625,7 +2625,7 @@ class PollingDirector { this.component.action(actionName, {}, 0); }; } - const timer = setInterval(() => { + const timer = window.setInterval(() => { callback(); }, duration); this.pollingIntervals.push(timer); diff --git a/src/LiveComponent/assets/src/Component/index.ts b/src/LiveComponent/assets/src/Component/index.ts index 320796f58eb..68add68f913 100644 --- a/src/LiveComponent/assets/src/Component/index.ts +++ b/src/LiveComponent/assets/src/Component/index.ts @@ -14,6 +14,25 @@ import { findComponents, registerComponent, unregisterComponent } from '../Compo declare const Turbo: any; +type MaybePromise = T | Promise; + +export type ComponentHooks = { + 'connect': (component: Component) => MaybePromise, + 'disconnect': (component: Component) => MaybePromise, + 'request:started': (requestConfig: any) => MaybePromise, + 'render:finished': (component: Component) => MaybePromise, + 'response:error': (backendResponse: BackendResponse, controls: { displayError: boolean }) => MaybePromise, + 'loading.state.started': (element: HTMLElement, request: BackendRequest) => MaybePromise, + 'loading.state.finished': (element: HTMLElement) => MaybePromise, + 'model:set': (model: string, value: any, component: Component) => MaybePromise, +}; + +export type ComponentHookName = keyof ComponentHooks; + +export type ComponentHookCallback = T extends ComponentHookName + ? ComponentHooks[T] + : (...args: any[]) => MaybePromise; + export default class Component { readonly element: HTMLElement; readonly name: string; @@ -109,24 +128,11 @@ export default class Component { this.externalMutationTracker.stop(); } - /** - * Add a named hook to the component. Available hooks are: - * - * * connect (component: Component) => {} - * * disconnect (component: Component) => {} - * * request:started (requestConfig: any) => {} - * * render:started (html: string, response: BackendResponse, controls: { shouldRender: boolean }) => {} - * * render:finished (component: Component) => {} - * * response:error (backendResponse: BackendResponse, controls: { displayError: boolean }) => {} - * * loading.state:started (element: HTMLElement, request: BackendRequest) => {} - * * loading.state:finished (element: HTMLElement) => {} - * * model:set (model: string, value: any, component: Component) => {} - */ - on(hookName: string, callback: (...args: any[]) => void): void { + on(hookName: T, callback: ComponentHookCallback): void { this.hooks.register(hookName, callback); } - off(hookName: string, callback: (...args: any[]) => void): void { + off(hookName: T, callback: ComponentHookCallback): void { this.hooks.unregister(hookName, callback); } diff --git a/src/LiveComponent/assets/src/HookManager.ts b/src/LiveComponent/assets/src/HookManager.ts index 9e0dacd8312..cbf0ab5bf82 100644 --- a/src/LiveComponent/assets/src/HookManager.ts +++ b/src/LiveComponent/assets/src/HookManager.ts @@ -1,13 +1,13 @@ export default class { private hooks: Map void>> = new Map(); - register(hookName: string, callback: () => void): void { + register(hookName: string, callback: (...args: any[]) => void): void { const hooks = this.hooks.get(hookName) || []; hooks.push(callback); this.hooks.set(hookName, hooks); } - unregister(hookName: string, callback: () => void): void { + unregister(hookName: string, callback: (...args: any[]) => void): void { const hooks = this.hooks.get(hookName) || []; const index = hooks.indexOf(callback); if (index === -1) { diff --git a/src/LiveComponent/assets/src/PollingDirector.ts b/src/LiveComponent/assets/src/PollingDirector.ts index 690058e043a..d0db436046c 100644 --- a/src/LiveComponent/assets/src/PollingDirector.ts +++ b/src/LiveComponent/assets/src/PollingDirector.ts @@ -4,7 +4,7 @@ export default class { component: Component; isPollingActive = true; polls: Array<{ actionName: string; duration: number }>; - pollingIntervals: NodeJS.Timer[] = []; + pollingIntervals: number[] = []; constructor(component: Component) { this.component = component; @@ -55,7 +55,7 @@ export default class { }; } - const timer = setInterval(() => { + const timer = window.setInterval(() => { callback(); }, duration); this.pollingIntervals.push(timer);