import { ISignal } from "../internals";
export declare const PulseViewFactory: unique symbol;
export declare const PulseView: unique symbol;
export interface ViewFactory
{
[PulseViewFactory]: true;
(): View
;
(props: P): View
;
(children: Children): View
;
(props: P, children: Children): View
;
styles(css: string): ViewFactory
;
}
export type Children = () => void | string | number | ISignal | any;
export type RenderableChildren = () => void | string | number | ISignal;
export type ViewHooks = {
onDispose: (callback: Function) => void;
};
export type DomBuilder = (props: P, children: Children, api: ViewHooks) => void;
export interface CssRecord {
[property: string]: string | number | CssRecord | Partial;
}
export type CustomCSS = (Partial & CssRecord) | string;
export type CustomStyleCSS = Partial | string;
export type ElementBuilder = {
(props: P, children: Children): ElementModifiers;
(props: P): ElementModifiers;
(children: Children): ElementModifiers;
(): ElementModifiers;
extend(css: CustomCSS): ElementBuilder;
extend(modifiers: ModifierBuilder): ElementBuilder;
extend(css: CustomCSS, modifiers: ModifierBuilder): ElementBuilder;
};
export type ModifierBuilder = (modifiers: BaseModifiers, context: ModifierBuilderContext) => N;
export type ModifierBuilderContext = {
element: E;
onDispose: (callback: Function) => void;
bindValue: (value: ReactiveValue, callback: ReactiveCallback) => void;
bindEvent: (event: T, callback: (e: HTMLElementEventMap[T]) => void) => void;
};
export type BaseModifiers = {
/**
* Adds a class name to the element.
*/
className: (...args: any[]) => BaseModifiers;
/**
* Adds a style to the element.
*/
css: (styles: CustomStyleCSS) => BaseModifiers;
/**
* Sets the element as `inert` (not interactive).
*/
inert: (freeze?: ReactiveValue) => BaseModifiers;
/**
* Adds an event listener to the element that's automatically cleaned up.
*/
on: (event: keyof HTMLElementEventMap, callback: (e: Event | CustomEvent) => void) => BaseModifiers;
/**
* Sets the element's transition name. (Used for animations)
*/
transitionName: (name: string) => BaseModifiers;
/**
* Applies a directive to the element.
*/
use: (callback: (element: E, helpers: ModifierBuilderContext) => void) => BaseModifiers;
};
export type ElementModifiers = Chainable & M>;
export type MaybeSignal = {
[P in keyof T]: T[P] | ISignal;
};
export type Chainable = {
[K in keyof T]: T[K] extends (...args: infer A) => any ? (...args: A) => Chainable : T[K];
};
export type ExtractProps = T extends ElementBuilder ? P : never;
export declare const NOOP: () => void;
export declare const EMPTY_PROPS: {};
export declare const EMPTY_CHILDREN: Children;
export declare const _activeRoots: Set>;
export declare const registerView: (key: string, view: any) => void;
export declare const unregisterView: (key: string) => void;
export declare function logVerbose(...messages: any): void;
/**
* Global environment variables for all views.
*/
export declare const env: ((key: string) => T | undefined) & {
readonly _data: Map;
set(key: string, value: any): void;
has(key: string): boolean;
get(key: string, defaultValue?: T): T | undefined;
};
/**
* Context variables for view hierarchies.
*/
export declare const context: ((key: string) => T | undefined) & {
set(key: string, value: any): void;
has(key: string): boolean | void;
get(key: string, defaultValue?: T): T | undefined;
};
/**
* Creates a new view factory.
*
* @example
*
* ```ts
* const MyView = view(() => {
* div("Hello, world!")
* })
* ```
*
* @param builder
* @returns
*/
export declare function view(builder: DomBuilder
): ViewFactory
;
export declare class View
{
private _builder;
[PulseView]: boolean;
readonly id: string;
readonly dom: DocumentFragment;
readonly parent: View | null;
readonly children: Set>;
readonly props: P;
protected _contextData?: Map;
context: {
set: (key: string, value: any) => void;
get: (key: string) => any;
has: (key: string) => boolean;
};
constructor(_builder: DomBuilder, args: any[]);
disposeCallbacks: Set | null;
hooks: {
onDispose: (callback: Function) => void;
};
dispose(): void;
static active: View | null;
static appendToActiveView(child: Node): void;
static activeElement: Node | null;
static appendToActiveElement(child: Node): void;
static appendToActiveElements(...children: Node[]): void;
static inNestedElement(el: Node, fn: () => T): T;
static inRenderContext(newView: View | null | undefined, newElement: Node | null | undefined, fn: () => T): T;
static create: ((builder: DomBuilder, ...args: any[]) => View) & {
styles(css: string): any;
};
static createBoundary(parent?: View | null, element?: Node | null): View;
}
/**
* Registers a callback to be called when the active view is disposed.
* @param callback
*/
export declare function onDispose(callback: Function): void;
export type Truthy = string | number | boolean | null | undefined;
export declare function isTruthy(value: Truthy): boolean;
/**
* Conditionally renders a view based on a boolean condition.
*
* @param condition A function that returns a boolean value (for use in a computation)
* @param thenBuilder When the condition is true, this function is called to build the view, otherwise it is skipped/torn down.
* @param elseBuilder (optional) When the condition is false, this function is called to build the view, otherwise it is skipped/torn down.
*/
export declare function when(condition: ISignal | Truthy | (() => Truthy | ISignal), thenBuilder: () => void, elseBuilder?: () => void): void;
export declare function processCondition(condition: string | number | boolean | ISignal | (() => Truthy | ISignal) | null | undefined): boolean;
/**
* Works kind of like `when`, but the whole block is evaluated and
* re-rendered when any observed signals change.
*
* @param builder The function that builds the view
* @returns void
*/
export declare function live(builder: () => void): void;
/**
* Renders an value as text.
* @param value The value to display
*/
export declare function text(value: string | number | ISignal): void;
export declare function raw(html: TemplateStringsArray | string, ...args: any[]): void;
export type KeyedView = {
key: any;
view: View;
markers: RenderMarker;
};
/**
* Iterates over an array or signal containing an array, rendering views for each item.
*
* @param list - An array or signal containing an array of items.
* @param itemBuilder - A function that receives each item and index, and builds the view.
* @param options - Optional configuration, including a key extractor function.
*/
export declare function each(list: T[] | ISignal | Iterable | ISignal>, itemBuilder: (item: T, index: number) => void, keyExtractor?: (item: T, index: number) => any): void;
/**
* Creates a new element with the given tag name.
* @usage
* ```ts
* const { a, div, button } = tags
*
* // elsewhere...
* const MyView = view(() => { div("Hello") })
* ```
*/
export declare const tags: {
[key in keyof HTMLElementTagNameMap]: ElementBuilder>> & Partial<{
class: string | ISignal;
style: Partial | string;
ref: (el: HTMLElement) => void;
on: (event: keyof HTMLElementEventMap, callback: (e: Event | CustomEvent) => void) => void;
use: (el: HTMLElement, helpers: ModifierBuilderContext) => void;
key: any;
switch: boolean | ISignal;
$value: ISignal;
$checked: ISignal;
$selected: ISignal;
}>, {}, HTMLElementTagNameMap[key]>;
};
export declare function getKeyForItem(index: number, keyExtractor: ((item: T, index: number) => any) | undefined, item: T): any;
export declare function createElement(tag: keyof HTMLElementTagNameMap, classNames?: string[], modifiers?: ModifierBuilder): ElementBuilder;
export declare function camelToKebab(str: string): string;
export declare function convertToStyles(styles: Partial): string;
export declare function convertToNestedCss(styles: Partial & CssRecord): string;
/**
* Renders a view instance into a target element.
*
* @param viewInstance The view instance to render
* @param target The target element to render the view into
* @returns A function that can be called to dispose of the view
*/
export declare function render(viewInstance: View, target: HTMLElement): () => void;
export declare function element(name: string, props?: any, children?: Children, customClasses?: string[], customModifiers?: ModifierBuilder): ElementModifiers;
export declare function createModifierContext(el: E): ModifierBuilderContext;
export declare function createBaseModifiers(el: T): {
className: (...args: any[]) => any;
css: (styles: CustomStyleCSS) => any;
inert(freeze?: ReactiveValue): any;
on(event: keyof HTMLElementEventMap, callback: (e: Event | CustomEvent) => void): any;
transitionName(name: string): any;
use(callback: (element: T, context: ModifierBuilderContext) => void): any;
};
export declare function setElAttr(el: Element, key: string, value: any): void;
export declare function setElProp(el: Element, key: string, value: any): void;
export declare function extractPropsAndChildren(args: any[]): [P, Children];
export declare class RenderMarker {
readonly id: string;
start: Comment;
end: Comment;
constructor(id: string);
appendToParent(parent: Node): this;
removeFromParent(): void;
insertBetween(node: Node): this;
removeBetween(): this;
extractAll(): DocumentFragment;
}
export declare function displayErrorWithinMarkers(markers: RenderMarker, error: any): void;
export declare function makeChainable(obj: T): Chainable;
/**
* A value, signal, or function that can be used to create a reactive value.
*/
export type ReactiveValue = T | ISignal | (() => T);
/**
* A callback that is called when a reactive value changes.
*/
export type ReactiveCallback = (unwrappedValue: T) => void;
/**
* Unwraps a reactive value to its base value. (untracked)
*/
export declare function getValue(value: ReactiveValue): T;
/**
* Binds a reactive value to a callback, executing whenever the value changes.
*/
export declare function bindValue(value: ReactiveValue, callback: ReactiveCallback): () => void;
export declare function bindEvent(element: HTMLElement, event: keyof HTMLElementEventMap, callback: (e: HTMLElementEventMap[typeof event]) => void): () => void;
export declare function isIterable(value: any): value is Iterable;
export declare function isFunction(source: any): source is Function;
export declare function isView(value: any): value is View;
export declare function iife(fn: () => T): T;
/**
* Defines a custom element tag that will render a Pulse view.
*
* @param tagName - The name of the custom element tag to define.
* @param observedProps - The names of the properties that will be observed for changes.
* @param viewFactory - A function that creates a Pulse view.
*/
export declare function customPulseElement(tagName: string, observedProps: string[], viewFactory: ViewFactory): void;