@xeito/core
Version:
Core modules for Xeito | Framework for building web applications
394 lines (369 loc) • 13.2 kB
TypeScript
import { Hole } from 'uhtml';
export { Hole, Renderable, TemplateFunction, html, render, svg } from 'uhtml';
interface PropChange {
name: string;
oldValue: string;
newValue: string;
}
interface ActionResult {
(...args: any[]): void;
}
declare class XeitoComponent extends HTMLElement {
/**
* Xeito internals object
* Will be populated by the @Component decorator
* with the component's metadata
*/
private _XeitoInternals;
private _DOMRoot;
private _template;
private _state;
private _props;
private _watchers;
private _IActionIndex;
private _actionInstances;
private _IPipeIndex;
private _pipeInstances;
private _stores;
private _storeSubscriptions;
private _dirty;
/**
* Global properties object (will be populated by the parent component or the Xeito instance)
*/
global: Record<string, any>;
/**
* Slot Content
* Will be populated by the constructor
* It will contain the slotted content of the component
* eg: <xeito-component><div slot="header">Header</div></xeito-component>
* slotContent.header will contain the div element
* This can be accessed inside the render method
* eg: html`<div>${this.slotContent.header}</div>`
*/
slotContent: Record<string, any>;
constructor();
/**
* Native connectedCallback
* Will be called when the component is connected to the DOM
*
*/
connectedCallback(): void;
/**
* Get the slotted content of the component
* @returns { Record<string, any> } Slot content object
*/
private getSlotContent;
/**
* Assign children global
* Assigns the global property to the children of the component
*/
private assignChildrenGlobal;
/**
* Bind methods
* Binds the methods of the component to the component itself
* This is done to avoid having to wrap the methods in arrow functions
* eg: onClick={this.onClick} instead of onClick={() => this.onClick()}
* NOTE: Arrow functions are still required to pass data to the method or native events
* eg: onClick={() => this.onClick(data)} or onClick={(e) => this.onClick(e)}
*/
private bindMethods;
/**
* Request an update of the component
* This will schedule an update of the template (batching updates by using a promise)
*/
requestUpdate(): void;
/**
* Force an update of the component (no batching)
* This will update the template immediately without batching
* This should be used with caution as it can cause performance issues
*/
forceUpdate(): void;
/**
* Update the component
* This will render the template and update the DOM
* It will also reset the pipe index before rendering
*/
private _update;
/**
* Sets a state value and triggers an update if needed
* @param key Key of the state to set
* @param value Value to set
* @param triggerUpdate Whether to trigger an update or not
*/
setState(key: string, value: any): void;
/**
* Returns the value of a state key
* @param key Key of the state to get
* @returns Value of the state key
*/
getState(key: string): any;
/**
* Sets a prop value and triggers an update
* @param key Key of the prop to set
* @param value Value to set
*/
setProp(key: string, value: any): void;
/**
* Returns the value of a prop key
* @param key Key of the prop to get
* @returns Value of the prop key
*/
getProp(key: string): any;
/**
* Sets a store and subscribes to it to trigger updates when it changes
* @param key Key of the property that contains the store
* @param store The store to set
*/
setStore(key: string, store: any): void;
/**
* Returns the store for the given key
* @param key Key of the property that contains the store
* @returns The store
*/
getStore(key: string): any;
/**
* Use method (Use an action inside the component)
* The 'use' method is used to provide actions to the template
* Actions have to be provided in the Component decorator options
* eg: @Component({ actions: [Action1, Action2] })
* @param selector
* @param args
* @returns
*/
use(selector: string, ...args: any[]): ActionResult | void;
/**
* Pipe method (Use a pipe inside the component)
* The 'pipe' method is used to provide pipes to the template
* Pipes have to be provided in the Component decorator options
* eg: @Component({ pipes: [Pipe1, Pipe2] })
* @param selector
* @param args
* @returns
*/
pipe(selector: string, ...args: any[]): any;
/**
* Native attributeChangedCallback
* Calls the onChanges method and requests an update of the component
* @param name
* @param oldValue
* @param newValue
*/
attributeChangedCallback(this: any, name: string, oldValue: string, newValue: string): void;
/**
* Native disconnectedCallback
* Calls the onWillUnmount method
*/
disconnectedCallback(): void;
/**
* Render method desgin to be overriden by the user
*/
render(): Hole | void;
/**
* Lifecycle methods desgin to be overriden by the user
* onInit: Called when the component is initialized (constructor)
* onWillMount: Called before the first render (connectedCallback)
* onDidMount: Called after the first render (connectedCallback)
* onUnmount: Called when the component is unmounted (disconnectedCallback)
*/
onInit(): any;
onWillMount(): any;
onDidMount(): any;
onUnmount(): any;
/**
* On changes method desgin to be overriden by the user
* Gets called when an attribute/property changes (attributeChangedCallback)
* @param { PropChange } change Prop changes object
*/
onPropChange(change: PropChange): void;
}
interface XeitoGlobal {
properties: Record<string, any>;
components: Array<typeof XeitoComponent>;
pipes: any[];
actions: any[];
}
declare class Xeito {
private _rootElement;
private plugins;
global: XeitoGlobal;
constructor(rootComponent: any);
/**
*
* @param rootElement The root element to render the root component in (can be a string selector)
*/
bootstrap(rootElement: HTMLElement | string): void;
/**
* Register a plugin to the Xeito instance
* @param plugin The plugin class to register
* @param options The options to pass to the plugin install method
*/
usePlugin(plugin: any, options?: any): void;
/**
* Attaches the global object to all the global components
* Including the root component (which is a global component)
* This is called during the bootstrap process
*/
private attachGlobal;
}
declare class XeitoPlugin {
private _xeito;
constructor(xeito: Xeito);
/**
* Install method called by Xeito when the plugin is registered
* Designed to be overriden by the plugin author
* @param {any} options The options passed to the plugin when it was registered
*/
install(options?: any): void;
/**
* Register a global action that can be used in any component
* @param {string} selector The selector of the action
* @param {any} action The action function
*/
registerGlobalAction(action: any): void;
/**
* Register a global property that can be used in any component
* @param {string} selector The selector of the property
* @param {any} property The property value
*/
registerGlobalProperty(selector: string, property: any): void;
/**
* Register a global pipe that can be used in any component
* @param {string} selector The selector of the pipe
* @param {any} pipe The pipe function
*/
registerGlobalPipe(pipe: any): void;
/**
* Register a global component that can be used in any component without importing it
*/
registerGlobalComponent(component: any): void;
}
interface ActionMetadata {
selector: string;
}
declare function Action(actionMetadata: ActionMetadata): <T extends new (...args: any[]) => {}>(constructor: T) => {
new (...args: any[]): {
selector: string;
update(element: any, ...args: any[]): void;
clean(): void;
};
} & T;
interface ComponentMetadata {
selector: string;
shadow?: boolean;
imports?: any[];
actions?: any[];
pipes?: any[];
services?: any[];
}
declare function Component(componentMetadata: ComponentMetadata): (constructor: any) => any;
interface EventConfig {
name?: string;
composed?: boolean;
bubbles?: boolean;
cancelable?: boolean;
}
/**
* Event Decorator
* Used to decorate a property on a class to create a new Event Emitter
* The Event Emitter is a class that contains a single method: emit
*
* This decorator wraps the property with a getter/setter that returns a new Event Emitter
* @param eventConfig
* @returns
*/
declare function Event(eventConfig?: EventConfig): (target: any, key: string) => void;
declare function Global(propertyName?: string): (target: any, key: string) => void;
interface PipeMetadata {
selector: string;
}
declare function Pipe(pipeMetadata: PipeMetadata): <T extends new (...args: any[]) => {}>(constructor: T) => {
new (...args: any[]): {
selector: string;
previousValue: any;
previousArgs: any[];
previousResult: any;
update(value: any, ...args: any[]): any;
clean(): void;
};
} & T;
/**
* Property decorator
* Allows the user to define a custom attribute in the component tag
* The property value will be set to the received attribute value
*/
declare function Prop(): (target: any, key: string) => void;
/**
* Ref decorator
* It only returns an object of type ElementRef which is just an object with a current property
* The current property is the element reference that gets popuplated upon rendering
*
* User could achieve the same result with an empty object declaration
* But this decorator is more readable than having an empty object declaration in the class
*
* @returns {PropertyDecorator}
*/
declare function Ref(): (target: any, key: any) => void;
/**
* State decorator
* Wraps the state property with a Proxy or a getter/setter
* This way we can detect when the state changes and trigger a re-render
*/
declare function State(): (target: any, key: string) => void;
/**
* Decorator for watching changes to reactive properties.
* Must be applied to a method of a component class.
* This decorator adds a setter to gain access to the instance.
* Then it adds the method to the list of watchers for the given property.
* The setter is removed after the first call and replaced with the original method.
* @param propertyNames Names of properties to watch for changes. (must be decorated with @State)
*
* Usage example:
* @Watch('count', 'name')
* watchCount(update: WatchUpdate) {
* // This method will be called when the value of the 'count' or 'name' property changes
* }
*/
declare function Watch(...propertyNames: string[]): (target: any, key: string, descriptor: any) => void;
/**
* Event Emitter class
* Used by the `Event` decorator to return a new Event Emitter when the property is accessed
* The event emitter contains only a single method: `emit`
* The emit method will dispatch a new `CustomEvent` with the given name and detail
* The EventConfig is set by the decorator based on the user configuration or the reflected metadata
*/
declare class Emitter<T> {
private clazz;
private eventConfig;
constructor(clazz: HTMLElement, eventConfig: EventConfig);
emit(value: T): void;
}
interface ElementRef {
current: HTMLElement | any;
}
/**
* Interface for the value of the parameter
* Received by a method decorated with @Watch
* eg:
* @Watch('$count', '$name')
* watchCount(update: WatchUpdate) {
* // update.name = '$count' or '$name'
* // update.value = the new value of the state for the given property name
* }
*/
interface WatchUpdate {
[name: string]: any;
value: any;
}
interface XeitoInternals {
selector?: string;
actions?: any[];
pipes?: any[];
imports?: any[];
services?: any[];
shadow?: boolean;
DOMRoot?: Element | HTMLElement | Node | null;
template?: Element | HTMLElement | Node | null;
global?: Record<string, any>;
componentStyleSheet?: CSSStyleSheet[];
}
export { Action, ActionMetadata, ActionResult, Component, ComponentMetadata, ElementRef, Emitter, Event, EventConfig, Global, Pipe, PipeMetadata, Prop, PropChange, Ref, State, Watch, WatchUpdate, Xeito, XeitoComponent, XeitoGlobal, XeitoInternals, XeitoPlugin };