derby
Version:
MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers.
206 lines (205 loc) • 9.21 kB
TypeScript
import { type ChildModel } from 'racer';
import { Controller } from './Controller';
import { Page } from './Page';
import derbyTemplates = require('./templates');
import { Context } from './templates/contexts';
import { Expression } from './templates/expressions';
import { Attribute, Binding } from './templates/templates';
export interface DataConstructor extends Record<string, unknown> {
new (): Record<string, unknown>;
}
type AnyVoidFunction = (...args: any[]) => void;
export interface ComponentConstructor {
new (context: Context, data: Record<string, unknown>): Component;
DataConstructor?: DataConstructor;
singleton?: undefined;
view?: ComponentViewDefinition;
}
export interface SingletonComponentConstructor {
new (): object;
singleton: true;
view?: ComponentViewDefinition;
}
export interface ComponentViewDefinition {
dependencies?: Array<ComponentConstructor | SingletonComponentConstructor>;
file?: string;
is?: string;
source?: string;
viewPartialDependencies?: Array<string | {
is: string;
}>;
}
export declare abstract class Component<T extends object = object> extends Controller<T> {
context: Context;
/**
* Unique ID assigned to the component
*/
id: string;
/**
* Whether the component instance is fully destroyed. Initially set to false.
*/
isDestroyed: boolean;
page: Page;
/**
* Reference to the containing controller
*/
parent: Controller;
singleton?: true;
_scope: string[];
view?: ComponentViewDefinition;
static DataConstructor?: DataConstructor;
constructor(context: Context, data: Record<string, unknown>);
/**
* Method called by Derby after instantiating a component and before rendering the template.
*
* This should initialize any data needed by the component, like with `this.model.start(...)`.
*
* `init()` could be called from the server and the browser, so do not use any DOM-only methods
* here. Put those in `create()` instead.
*/
init?(_model: ChildModel): void;
/**
* Method called by Derby once a component is loaded and ready in the DOM.
*
* Any model listeners (`this.model.on(...)`) and DOM listeners (`this.dom.addListener(...)`)
* should be added here.
*
* This will only be called in the browser.
*/
create?(): void;
destroy(): void;
/**
* Generate a function, bound function to the component instance's `this`.
* The returned function will no longer be invoked once the component is destroyed.
*
* @param fn - A function to be invoked with the component as its `this` value.
* @returns a bound function, similar to JavaScript's Function.bind()
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
*/
bind(fn: (...args: unknown[]) => void): (...args: any[]) => any;
/**
* Generate a function that, when passing in a numeric delay, calls the function at
* most once per that many milliseconds. Additionally, implements an interface
* intended to be used with window.requestAnimationFrame, process.nextTick, or window.setImmediate.
*
* @param fn - A function to be invoked with the component instance as its `this` value.
* @param delayArg - Amount of time (in ms) to wait until invoking `fn` again. Default '0'.
*
* When passing in a numeric delay, calls the function at most once per that
* many milliseconds. Like Underscore, the function will be called on the
* leading and the trailing edge of the delay as appropriate. Unlike Underscore,
* calls are consistently called via setTimeout and are never synchronous. This
* should be used for reducing the frequency of ongoing updates, such as scroll
* events or other continuous streams of events.
*
* Additionally, implements an interface intended to be used with
* window.requestAnimationFrame or process.nextTick. If one of these is passed,
* it will be used to create a single async call following any number of
* synchronous calls. This mode is typically used to coalesce many synchronous
* events (such as multiple model events) into a single async event.
* Like component.bind(), will no longer call back once the component is
- * destroyed, which avoids possible bugs and memory leaks.
*
* @returns a bound function
*/
throttle(fn: (...args: unknown[]) => void, delayArg?: number | ((fn: () => void) => void)): (...args: any[]) => void;
/**
* Safe wrapper around `window.requestAnimationFrame` that ensures function not invoked
* when component has been destroyed
* @param fn - A function to be invoked with the component instance as its `this` value.
*/
requestAnimationFrame(fn: () => void): void;
/**
* Safe wrapper around `process.nextTick` that ensures function not invoked
* when component has been destroyed
* @param fn - A function to be invoked with the component instance as its `this` value.
*/
nextTick(fn: () => void): void;
/**
* Suppresses calls until the function is no longer called for that many milliseconds.
* This should be used for delaying updates triggered by user input or typing text.
*
* @param fn - A function to be invoked with the component instance as its `this` value.
* @param delay - Amount of time (in ms) to wait until invoking `fn`. Default '0'.
*
* @returns a bound function
*/
debounce<F extends AnyVoidFunction>(fn: (...args: Parameters<F>) => void, delay?: number): (...args: Parameters<F>) => void;
/**
* Like debounce(), suppresses calls until the function is no longer called for
* that many milliseconds. In addition, suppresses calls while the callback
* function is running. In other words, the callback will not be called again
* until the supplied done() argument is called. When the debounced function is
* called while the callback is running, the callback will be called again
* immediately after done() is called. Thus, the callback will always receive
* the last value passed to the debounced function.
*
* This avoids the potential for multiple callbacks to execute in parallel and
* complete out of order. It also acts as an adaptive rate limiter. Use this
* method to debounce any field that triggers an async call as the user types.
*
* Like component.bind(), will no longer call back once the component is
* destroyed, which avoids possible bugs and memory leaks.
*
* Forked from: https://github.com/juliangruber/async-debounce
*
* @param fn - A function to be invoked with the component instance as its `this` value.
* @param delay - Amount of time (in ms) to wait until invoking `fn`. Default '0'.
*
* @returns a bound function
*/
debounceAsync<F extends AnyVoidFunction>(fn: (...args: Parameters<F>) => void, delay?: number): (...args: Parameters<F>) => void;
get(viewName: string, unescaped: boolean): any;
getFragment(viewName: string, _ns?: string): any;
getView(viewName: string, _ns?: string): any;
/**
* Retrieve the appropriate view attribute's value for a given view instance.
* If the value is a template, it will be rendered prior to being returned.
*
* @param attrName the name of the view attribute used with a component instance
* @returns any of the possible values that can be expressed with a view attribute
*
* @see https://derbyjs.github.io/derby/views/template-syntax/view-attributes
*/
getAttribute<T>(attrName: string): T;
setAttribute(key: string, value: Attribute): void;
setNullAttribute(key: string, value: Attribute): void;
}
export declare class ComponentAttribute {
expression: Expression;
model: ChildModel;
key: string;
constructor(expression: Expression, model: ChildModel, key: string);
update(context: Context, binding: Binding): void;
}
export declare class ComponentAttributeBinding extends Binding {
template: any;
context: Context;
condition: any;
constructor(expression: Expression, model: any, key: any, context: Context);
}
export declare function createFactory(constructor: ComponentConstructor | SingletonComponentConstructor): SingletonComponentFactory | ComponentFactory;
export declare class ComponentModelData {
id: string;
$controller: Controller;
$element: any;
$event: any;
[key: string]: unknown;
}
export declare class ComponentFactory {
constructorFn: ComponentConstructor;
constructor(constructorFn: ComponentConstructor);
init(context: Context): derbyTemplates.contexts.Context;
create(context: any): void;
}
declare class SingletonComponentFactory {
constructorFn: SingletonComponentConstructor;
isSingleton: true;
component: Component;
constructor(constructorFn: any);
init(context: any): any;
create(): void;
}
export declare function extendComponent(constructor: SingletonComponentConstructor | ComponentConstructor): void;
export {};