/*!
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
/**
 * A context for implicitly passing values along the call stack.
 *
 * If you need a global default value, use {@link DefaultContext} instead.
 */
declare class Context<T> {
	#private;
	/**
	 * @param defaultValue The default value. This is used if the {@link current} value is `null` or `undefined`.
	 */
	constructor(defaultValue: T);
	constructor(...defaultValue: T extends undefined ? [] : [T]);
	/**
	 * Get or set the default value.
	 *
	 * This is used if the {@link current} value is `null` or `undefined`.
	 */
	default: T;
	/**
	 * Get the current value for this context.
	 */
	get current(): T;
	/**
	 * Run a function while providing the specified value for this context.
	 *
	 * See {@link Provide `<Provide>`} when using JSX.
	 *
	 * @param value The value to provide.
	 * @param fn The function to run.
	 * @param args The function arguments.
	 * @returns The function's return value.
	 */
	provide<F extends (...args: any) => any>(value: T | null | undefined, fn: F, ...args: Parameters<F>): ReturnType<F>;
	/**
	 * Shorthand for creating a context-value pair for this context.
	 */
	with(value: T | null | undefined): ContextState<T>;
	/**
	 * Run a function in a new context window (ignoring all current contexts) while providing the specified states.
	 *
	 * @param states The states to provide.
	 * @param fn The function to run.
	 * @param args The function arguments.
	 * @returns The function's return value.
	 */
	static isolate<F extends (...args: any) => any>(states: ContextState<unknown>[], fn: F, ...args: Parameters<F>): ReturnType<F>;
	/**
	 * Run a function while providing the specified states.
	 *
	 * See {@link Provide `<Provide>`} when using JSX.
	 *
	 * @param states The states to provide. When providing multiple values for the same context, the last one is used.
	 * @param fn The function to run.
	 * @param args The function arguments.
	 * @returns The function's return value.
	 */
	static provide<F extends (...args: any) => any>(states: ContextState<unknown>[], fn: F, ...args: Parameters<F>): ReturnType<F>;
	/**
	 * Capture all current context states.
	 */
	static capture(): ContextState<unknown>[];
	/**
	 * Bind a function to the current context.
	 *
	 * @param fn The function to bind.
	 * @returns The bound function.
	 */
	static bind<T extends (...args: any) => any>(fn: T): T;
}
/**
 * A context-value pair.
 *
 * Fields are considered internal and not subject to semantic versioning.
 */
interface ContextState<T> {
	c: Context<T>;
	v: T | null | undefined;
}

/**
 * Component for providing context values while rendering.
 *
 * See {@link Context.provide} or {@link Context.prototype.provide} when not using JSX.
 */
declare function Provide<T>(props: {
	/** The context to provide a value for. */
	context: Context<T>;
	/** The value to provide. */
	value: T | null | undefined;
	children: () => unknown;
} | {
	/** The context states to provide. */
	states: ContextState<unknown>[];
	children: () => unknown;
}): unknown;

/**
 * A function that is called to dispose something.
 */
type TeardownHook = () => void;
/**
 * Run a function while capturing teardown hooks.
 *
 * + If an error is thrown by the specified function, teardown hooks are called in reverse registration order and the error is re-thrown.
 * + If an error is thrown by a teardown hook, remaining ones are not called and the error is re-thrown.
 *
 * @param fn The function to run.
 * @returns A function to run all captured teardown hooks in reverse registration order.
 */
declare function capture(fn: () => void): TeardownHook;
/**
 * Run a function while capturing teardown hooks.
 *
 * + When disposed before the specified function finishes, teardown hooks are called in reverse registration order immediately after the function finishes.
 * + If an error is thrown by the specified function, teardown hooks are called in reverse registration order and the error is re-thrown.
 * + If an error is thrown by a teardown hook, remaining ones are not called and the error is re-thrown.
 *
 * @param fn The function to run.
 * @returns The function's return value.
 */
declare function captureSelf<T>(fn: (dispose: TeardownHook) => T): T;
/**
 * Run a function while intentionally leaking teardown hooks.
 *
 * @param fn The function to run.
 * @returns The function's return value.
 */
declare function leak<T>(fn: () => T): T;
/**
 * Run a function and immediately call teardown hooks if it throws an error.
 *
 * + If an error is thrown, teardown hooks are immediately called in reverse registration order and the error is re-thrown.
 * + If no error is thrown, teardown hooks are registered in the outer context.
 *
 * @param fn The function to run.
 * @returns The function's return value.
 */
declare function teardownOnError<T>(fn: () => T): T;
/**
 * Register a teardown hook to be called when the current lifecycle is disposed.
 *
 * This has no effect if teardown hooks are not captured in the current context.
 *
 * @param hook The hook to register. This may be called multiple times.
 */
declare function teardown(hook: TeardownHook): void;
/**
 * Run a function in isolation from the following side effect causing APIs:
 * + Teardown hooks are leaked. To isolate only teardown hooks, use {@link leak} instead.
 * + Signal accesses are not tracked and the default tracking behavior is restored. To only isolate signal accesses, use {@link untrack} instead.
 *
 * Note, that batches and contexts are not isolated.
 *
 * @param fn The function to run.
 * @param args The function arguments.
 * @returns The function's return value.
 */
declare function isolate<F extends (...args: any) => any>(fn: F, ...args: Parameters<F>): ReturnType<F>;
/**
 * Represents the source that a signal has been derived from.
 *
 * When deriving a signal, the source should be passed via the signal constructor or shorthand.
 * This has no impact on how a signal behaves, but allows other APIs to locate metadata about a signal's source.
 *
 * @example
 * ```js
 * function trim(source: Signal<string>) {
 *   const input = $(source.value, source);
 *   ...
 *   return input;
 * }
 * ```
 */
type SignalSource = Signal<unknown> | undefined;
/**
 * Represents a value that changes over time.
 */
declare class Signal<T> {
	#private;
	/**
	 * The current value without access tracking or observer notifications when set.
	 */
	inert: T;
	/**
	 * Create a new signal.
	 *
	 * @param value The initial value.
	 * @param source The {@link SignalSource source} this signal has been derived from.
	 */
	constructor(value: T, source?: SignalSource);
	/**
	 * Reactively access the current value.
	 */
	get value(): T;
	/**
	 * Set the current value.
	 *
	 * If the new value is the same as the previous one, no observers are notified.
	 *
	 * @example
	 * ```tsx
	 * import { $, watch } from "rvx";
	 *
	 * const count = $(0);
	 *
	 * watch(count, count => {
	 *   console.log("Count:", count);
	 * });
	 *
	 * count.value++;
	 * ```
	 */
	set value(value: T);
	/**
	 * The {@link SignalSource source}, this signal has been derived from.
	 */
	get source(): SignalSource;
	/**
	 * The root {@link SignalSource source}, this signal has been derived from or this signal itself if it hasn't been derived.
	 */
	get root(): Signal<unknown>;
	/**
	 * Check if this signal has any active observers.
	 */
	get active(): boolean;
	/**
	 * Manually access this signal.
	 */
	access(): void;
	/**
	 * Manually notify observers.
	 *
	 * During batches, notifications are deferred.
	 */
	notify(): void;
	/**
	 * Pass this signal to a function and get its result.
	 *
	 * @example
	 * ```tsx
	 * const value = $(42);
	 *
	 * <TextInput value={
	 *   value
	 *     .pipe(parseInt)
	 *     .pipe(trim)
	 * } />
	 * ```
	 */
	pipe<A extends any[], R>(fn: (self: this, ...args: A) => R, ...args: A): R;
}
/**
 * Create a new signal.
 *
 * @param value The initial value.
 * @param source The {@link SignalSource source} this signal has been derived from.
 * @returns The signal.
 */
declare function $(): Signal<void>;
declare function $<T>(value: T, source?: SignalSource): Signal<T>;
/**
 * A value, signal or function to get a value.
 *
 * @example
 * ```tsx
 * import { $, watch } from "rvx";
 *
 * const message = $("Example");
 *
 * // Not reactive:
 * watch(message.value, message => {
 *   console.log("A:", message);
 * });
 *
 * // Reactive:
 * watch(message, message => {
 *   console.log("B:", message);
 * });
 *
 * // Reactive:
 * watch(() => message.value, message => {
 *   console.log("C:", message);
 * });
 *
 * message.value = "Hello World!";
 * ```
 */
type Expression<T> = T | Signal<T> | (() => T);
/**
 * Utility to get the result type of an expression.
 */
type ExpressionResult<T> = T extends Expression<infer R> ? R : never;
/**
 * Utility type for expressions that should never be static values.
 *
 * This can be used instead of the {@link Expression} type in places where accepting static values doesn't make sense.
 */
type Reactive<T> = Signal<T> | (() => T);
/**
 * Utility type to require `T` to not be reactive.
 */
type Static<T> = unknown extends T ? never : Exclude<T, Reactive<any>>;
/**
 * Watch an expression until the current lifecycle is disposed.
 *
 * + Both the expression and effect are called at least once immediately.
 * + Lifecycle hooks from the expression or effect are called before a signal update is processed or when the current lifecycle is disposed.
 *
 * @param expr The expression to watch.
 * @param effect An optional function to call with each expression result without tracking signal accesses.
 *
 * @example
 * ```tsx
 * import { $, watch } from "rvx";
 *
 * const count = $(0);
 *
 * // Capture teardown hooks registered by "watch":
 * const dispose = capture(() => {
 *   // Start watching:
 *   watch(count, count => {
 *     console.log("Count:", count);
 *   });
 * });
 *
 * count.value = 1;
 *
 * // Stop watching:
 * dispose();
 *
 * count.value = 2;
 * ```
 */
declare function watch<T>(expr: Reactive<T>, effect: (value: T) => void): void;
/**
 * @deprecated
 * This call can be removed because the expression is always static. You can call the effect directly.
 */
declare function watch<T>(expr: Static<T>, effect: (value: T) => void): void;
/**
 * Watch an expression until the current lifecycle is disposed.
 *
 * + Both the expression and effect are called at least once immediately.
 * + Lifecycle hooks from the expression or effect are called before a signal update is processed or when the current lifecycle is disposed.
 *
 * @param expr The expression to watch.
 * @param effect An optional function to call with each expression result without tracking signal accesses.
 *
 * @example
 * ```tsx
 * import { $, watch } from "rvx";
 *
 * const count = $(0);
 *
 * // Capture teardown hooks registered by "watch":
 * const dispose = capture(() => {
 *   // Start watching:
 *   watch(count, count => {
 *     console.log("Count:", count);
 *   });
 * });
 *
 * count.value = 1;
 *
 * // Stop watching:
 * dispose();
 *
 * count.value = 2;
 * ```
 */
declare function watch(expr: () => void): void;
declare function watch<T>(expr: Expression<T>, effect: (value: T) => void): void;
/**
 * Watch an expression until the current lifecycle is disposed.
 *
 * @param expr The expression to watch.
 * @param effect A function to call with each subsequent expression result without tracking signal accesses.
 * @returns The first expression result.
 */
declare function watchUpdates<T>(expr: Reactive<T>, effect: (value: T) => void): T;
/**
 * @deprecated
 * This call can be removed because the expression is always static.
 */
declare function watchUpdates<T>(expr: Static<T>, effect: (value: T) => void): T;
/**
 * Watch an expression until the current lifecycle is disposed.
 *
 * @param expr The expression to watch.
 * @param effect A function to call with each subsequent expression result without tracking signal accesses.
 * @returns The first expression result.
 */
declare function watchUpdates<T>(expr: Expression<T>, effect: (value: T) => void): T;
/**
 * Wrap an expression to re-run only when any accessed signal has been updated.
 *
 * + Lifecycle hooks in the expression are not supported.
 * + The context from where `lazy` was called is available within the expression.
 *
 * @param expr The expression to wrap.
 */
declare function lazy<T>(expr: () => T): () => T;
/**
 * Defer signal updates until a function finishes.
 *
 * + When nesting batches, updates are processed after the most outer batch has completed.
 * + When updates cause immediate side effects, these side effects will run as part of the batch.
 *
 * @param fn The function to run.
 * @returns The function's return value.
 *
 * @example
 * The example below outputs `5` and `9` once. Without batching the output would be `5, 7, 9`.
 * ```tsx
 * import { batch, $, watch } from "rvx";
 *
 * const a = $(2);
 * const b = $(3);
 *
 * watch(() => a.value + b.value, value => {
 *   console.log("Sum:", value);
 * });
 *
 * batch(() => {
 *   a.value = 4;
 *   b.value = 5;
 * });
 * ```
 */
declare function batch<T>(fn: () => T): T;
/**
 * {@link watch Watch} an expression and get a function to reactively access its result.
 *
 * @param expr The expression to watch.
 * @returns A function to reactively access the latest result.
 *
 * @example
 * ```tsx
 * import { $, memo, watch } from "rvx";
 *
 * const count = $(42);
 *
 * const computed = memo(() => someExpensiveComputation(count.value));
 *
 * watch(computed, count => {
 *   console.log("Count:", count);
 * });
 * ```
 */
declare function memo<T>(expr: Reactive<T>): () => T;
/**
 * @deprecated
 * This call can be removed because the expression is always static. You can use the value directly.
 */
declare function memo<T>(expr: Static<T>): () => T;
/**
 * {@link watch Watch} an expression and get a function to reactively access its result.
 *
 * @param expr The expression to watch.
 * @returns A function to reactively access the latest result.
 *
 * @example
 * ```tsx
 * import { $, memo, watch } from "rvx";
 *
 * const count = $(42);
 *
 * const computed = memo(() => someExpensiveComputation(count.value));
 *
 * watch(computed, count => {
 *   console.log("Count:", count);
 * });
 * ```
 */
declare function memo<T>(expr: Expression<T>): () => T;
/**
 * {@link get Evaluate an expression} without tracking signal accesses.
 *
 * @param expr The expression to evaluate.
 * @returns The function's return value.
 *
 * @example
 * ```tsx
 * import { $, untrack, watch } from "rvx";
 *
 * const a = $(2);
 * const b = $(3);
 *
 * watch(() => a.value + untrack(b), sum => {
 *   console.log("Sum:", sum);
 * });
 *
 * // This causes an update:
 * a.value = 4;
 *
 * // This has no effect:
 * b.value = 5;
 * ```
 */
declare function untrack<T>(expr: Reactive<T>): T;
/**
 * @deprecated
 * This call can be removed because the expression is always static. You can use the value directly.
 */
declare function untrack<T>(expr: Static<T>): T;
/**
 * {@link get Evaluate an expression} without tracking signal accesses.
 *
 * @param expr The expression to evaluate.
 * @returns The function's return value.
 *
 * @example
 * ```tsx
 * import { $, untrack, watch } from "rvx";
 *
 * const a = $(2);
 * const b = $(3);
 *
 * watch(() => a.value + untrack(b), sum => {
 *   console.log("Sum:", sum);
 * });
 *
 * // This causes an update:
 * a.value = 4;
 *
 * // This has no effect:
 * b.value = 5;
 * ```
 */
declare function untrack<T>(expr: Expression<T>): T;
/**
 * Check if signal accesses are currently tracked.
 */
declare function isTracking(): boolean;
/**
 * Run a function while tracking signal accesses to invoke the trigger callback when updated.
 *
 * See {@link trigger}.
 */
interface TriggerPipe {
	<T>(expr: Reactive<T>): T;
	/**
	 * @deprecated
	 * This call can be removed because the expression is always static. You can use the value directly.
	 */
	<T>(expr: Static<T>): T;
	<T>(expr: Expression<T>): T;
}
/**
 * Create an expression evaluator pipe that calls a function once when any accessed signals from the latest evaluated expression are updated.
 *
 * + When the lifecycle at which the pipe was created is disposed, the callback function will not be called anymore.
 * + It is guaranteed that the function is called before any other observers like {@link watch} or {@link effect} are notified.
 * + If pipes are nested, the callback for the most inner one is called first.
 *
 * @param callback The callback to invoke when a signal is updated.
 * @returns The pipe to evaluate expressions.
 */
declare function trigger(callback: () => void): TriggerPipe;
/**
 * Manually evaluate an expression in the current context.
 *
 * This can be used to access reactive and non reactive inputs.
 *
 * @param expr The expression to evaluate.
 * @returns The expression result.
 *
 * @example
 * ```tsx
 * import { $, get } from "rvx";
 *
 * const count = $(42);
 *
 * get(42) // 42
 * get(count) // 42
 * get(() => 42) // 42
 * ```
 */
declare function get<T>(expr: Reactive<T>): T;
/**
 * @deprecated
 * This call can be removed because the expression is always static. You can use the value directly.
 */
declare function get<T>(expr: Static<T>): T;
/**
 * Manually evaluate an expression in the current context.
 *
 * This can be used to access reactive and non reactive inputs.
 *
 * @param expr The expression to evaluate.
 * @returns The expression result.
 *
 * @example
 * ```tsx
 * import { $, get } from "rvx";
 *
 * const count = $(42);
 *
 * get(42) // 42
 * get(count) // 42
 * get(() => 42) // 42
 * ```
 */
declare function get<T>(expr: Expression<T>): T;
type MapFn<I, O> = (input: I) => O;
/**
 * Map an expression value while preserving if the expression is static or not.
 *
 * @example
 * ```tsx
 * import { $, map, get } from "rvx";
 *
 * const count = $(42);
 * const doubleCount = map(count, value => value * 2);
 *
 * get(doubleCount) // 84
 * ```
 */
declare function map<I, O>(input: Reactive<I>, mapFn: MapFn<I, O>): Expression<O>;
/**
 * @deprecated
 * This call can be removed because the input is always static. You can call the map function directly.
 */
declare function map<I, O>(input: Static<I>, mapFn: MapFn<I, O>): Expression<O>;
/**
 * Map an expression value while preserving if the expression is static or not.
 *
 * @example
 * ```tsx
 * import { $, map, get } from "rvx";
 *
 * const count = $(42);
 * const doubleCount = map(count, value => value * 2);
 *
 * get(doubleCount) // 84
 * ```
 */
declare function map<I, O>(input: Expression<I>, mapFn: MapFn<I, O>): Expression<O>;

/**
 * Utility type for any falsy value.
 */
type Falsy = null | undefined | false | 0 | 0n | "";
/**
 * Type alias for `unknown` to indicate rendered content.
 */
type Content = unknown;
/**
 * Common interface for components.
 */
interface Component<TProps = void, TContent = Content> {
	(props: TProps): TContent;
}

/**
 * Namespace URI for HTML elements.
 */
declare const HTML = "http://www.w3.org/1999/xhtml";
/**
 * Namespace URI for SVG elements.
 */
declare const SVG = "http://www.w3.org/2000/svg";
/**
 * Namespace URI for MathML elements.
 */
declare const MATHML = "http://www.w3.org/1998/Math/MathML";
type XMLNS = typeof HTML | typeof SVG | typeof MATHML;
/**
 * Context for setting the namespace URI for new elements.
 */
declare const XMLNS: Context<XMLNS>;
/**
 * Represents any supported "class" attribute value.
 */
type ClassValue = Expression<undefined | null | false | string | Record<string, Expression<boolean | undefined>> | ClassValue[]>;
type HyphenCase<T> = T extends `${infer A}${infer B}` ? `${A extends Capitalize<A> ? "-" : ""}${Lowercase<A>}${HyphenCase<B>}` : T;
/**
 * An object with css property expressions used in {@link StyleValue}.
 */
type StyleMap = {
	[K in keyof CSSStyleDeclaration as HyphenCase<K>]?: Expression<unknown>;
} & {
	[K in string]?: Expression<unknown>;
};
/**
 * Represents any supported "style" attribute value.
 */
type StyleValue = Expression<undefined | StyleMap | StyleValue[]>;
type EventListener<E extends Event> = (event: E) => void;
/**
 * Symbol for specifying a DOM node that is used as content.
 *
 * See {@link NodeTarget}.
 */
declare const NODE: unique symbol;
/**
 * If an object used as content has a {@link NODE} property, this node is inserted as content instead.
 */
interface NodeTarget<T extends Node = Node> {
	[NODE]: T;
}
/**
 * Represents an object with jsx element attributes.
 */
type Attributes<_T extends Element> = {
	children?: Content;
	class?: ClassValue;
	style?: StyleValue;
} & {
	[K in keyof HTMLElementEventMap as `on:${K}`]?: EventListener<HTMLElementEventMap[K]> | EventArgs<HTMLElementEventMap[K]>;
} & {
	[K in `prop:${string}`]?: Expression<unknown>;
} & {
	[K in `attr:${string}`]?: Expression<unknown>;
} & {
	[K in string]?: Expression<unknown>;
};
/**
 * Type for specifying a jsx event listener with options.
 */
type EventArgs<E extends Event> = [
	listener: EventListener<E>,
	options?: AddEventListenerOptions
];
/**
 * Type used for mapping tag names to element types.
 */
type TagNameMap = HTMLElementTagNameMap & SVGElementTagNameMap & MathMLElementTagNameMap;

declare class ElementBuilder<E extends Element> implements NodeTarget<E> {
	#private;
	/**
	 * The target element this builder is modifying.
	 */
	elem: E;
	get [NODE](): E;
	/**
	 * Create a new element builder for the specified element.
	 *
	 * For also creating an element, use the {@link e} shorthand.
	 *
	 * @param elem The element to modify.
	 */
	constructor(elem: E);
	/**
	 * Append an event listener.
	 *
	 * @param type The event type to listen for.
	 * @param listener The event listener function. The current context is available within this listener.
	 * @param options Optional add event listener options.
	 *
	 * @example
	 * ```tsx
	 * e("button").on("click", event => { ... })
	 *
	 * e("div").on("scroll", event => { ... }, { capture: true })
	 * ```
	 */
	on<K extends keyof HTMLElementEventMap>(type: K, listener: EventListener<HTMLElementEventMap[K]>, options?: AddEventListenerOptions): this;
	on<E extends Event>(type: string, listener: EventListener<E>, options?: AddEventListenerOptions): this;
	/**
	 * Set element styles.
	 *
	 * @param value Any combination of arrays, objects and expressions.
	 * + Properties use the same casing as in css. E.g. `font-family`, not `fontFamily`.
	 * + Properties specified later take precedence over earlier properties.
	 *
	 * @example
	 * ```tsx
	 * e("div").style({ color: "red" })
	 *
	 * e("div").style([
	 *   {
	 *     "color": "red",
	 *     "font-size": "1rem",
	 *   },
	 *   () => ({ "color": () => "blue" }),
	 *   { "color": someSignal },
	 *   [
	 *     { "width": "42px" },
	 *   ],
	 * ])
	 * ```
	 */
	style(value: StyleValue): Omit<this, "style">;
	/**
	 * Set element classes.
	 *
	 * @param value Any combination of class tokens, arrays and objects with boolean expressions to determine which classes are added. `undefined`, `null` and `false` is ignored.
	 *
	 * @example
	 * ```tsx
	 * e("div").class("example")
	 *
	 * e("div").class([
	 *   "foo",
	 *   () => "bar",
	 *   {
	 *     baz: true,
	 *     boo: () => false,
	 *   },
	 * ])
	 * ```
	 */
	class(value: ClassValue): Omit<this, "class">;
	/**
	 * Set an attribute.
	 *
	 * @param name The name.
	 * @param value An expression for the value.
	 *
	 * @example
	 * ```tsx
	 * e("img").set("src", someSignal).set("alt", "Example")
	 * ```
	 */
	set(name: string, value: Expression<unknown>): this;
	/**
	 * Set a property.
	 *
	 * @param name The name.
	 * @param value An expression for the value.
	 *
	 * @example
	 * ```tsx
	 * e("input").prop("value", someValue)
	 * ```
	 */
	prop<K extends keyof E>(name: K, value: Expression<E[K]>): this;
	/**
	 * Append content.
	 *
	 * + Any expression will be rendered as text.
	 * + DOM nodes.
	 * + Views.
	 * + Arrays, jsx fragments & any combination of the above.
	 *
	 * @example
	 * ```tsx
	 * e("h1").append("Hello World!")
	 *
	 * e("div").append([
	 *   ["Hello World!"],
	 *   e("div"),
	 *   ...
	 * ])
	 * ```
	 */
	append(...content: Content[]): this;
}
/**
 * Create a new element builder.
 *
 * This uses the current {@link XMLNS} value to determine the namespace.
 *
 * @param tagName The tag name.
 * @returns The builder.
 *
 * @example
 * ```tsx
 * e("h1").append("Hello World!")
 *
 * XMLNS.provide(SVG, () => {
 *   return e("svg").set("viewbox", "0 0 ...")
 * })
 * ```
 */
declare function e<K extends keyof TagNameMap>(tagName: K): ElementBuilder<TagNameMap[K]>;
declare function e<E extends Element>(tagName: string): ElementBuilder<E>;

interface EnvContext extends Context<unknown> {
	get current(): typeof globalThis;
}
/**
 * A context that is used to access all DOM related APIs.
 *
 * This can be used to run rvx applications in non browser environments.
 */
declare const ENV: EnvContext;

interface EventFn<T extends unknown[]> {
	(...args: T): void;
}
interface Event$1<T extends unknown[]> {
	/**
	 * Subscribe to this event until the current lifecycle is disposed.
	 */
	(listener: EventFn<T>): void;
}
/**
 * An emitter for a single event type.
 *
 * @example
 * ```tsx
 * import { Emitter } from "rvx";
 *
 * const emitter = new Emitter<[address: string, port: number]>();
 *
 * emitter.event((address, port) => {
 *   console.log("Connected:", address, port);
 * });
 *
 * emitter.emit("127.0.0.1", 12345);
 * ```
 */
declare class Emitter<T extends unknown[]> {
	#private;
	/**
	 * Subscribe to this event until the current lifecycle is disposed.
	 */
	event: Event$1<T>;
	/**
	 * Emit this event.
	 *
	 * Note, that listeners will run immediately in the current context.
	 */
	emit: EventFn<T>;
}

type MapArrayFn<I, O> = (input: I, index: () => number) => O;

/**
 * Run a function for each value in an iterable expression keyed by value.
 *
 * + The current context is available in the map function.
 * + Evaluation is stopped when the current lifecycle is disposed.
 * + Teardown hooks from within the map function are called when a value is removed or when the current lifecycle is disposed.
 * + Returns a function to reactively access the latest result.
 */
declare function mapArray<I, O>(inputs: Expression<Iterable<I>>, fn: MapArrayFn<I, O>): () => O[];

/**
 * Utility for modifying an existing element or {@link ElementBuilder element builder} returned from a component.
 *
 * + Event listeners are additive.
 * + Unique styles, classes, attributes and properties are additive.
 * + **Styles, classes, attributes and properties that are already set by the component may cause conflicts.**
 *
 * @example
 * ```tsx
 * override(
 *   SomeComponent(...)
 * ).class("some-class")
 * ```
 */
declare function override<E extends Element>(target: E | NodeTarget<E>): ElementBuilder<E>;

/**
 * Allocate an ID that is unique in the current thread.
 *
 * @returns The unique id in the form `rvx_123`.
 */
declare function uniqueId(): string;
/**
 * A component that provides a unique id in the form `rvx_123` to its children.
 *
 * See {@link UseUniqueId `<UseUniqueId>`} when using JSX.
 *
 * @example
 * ```tsx
 * import { useUniqueId, e } from "rvx";
 *
 * useUniqueId(id => [
 *   e("label").set("for", id).append("Text"),
 *   e("input").set("type", "text").set("id", id),
 * ])
 * ```
 */
declare function useUniqueId<T = Content>(component: Component<string, T>): T;
/**
 * A component that provides a unique id in the form `rvx_123` to its children.
 *
 * See {@link useUniqueId} when not using JSX.
 *
 * @example
 * ```tsx
 * import { UseUniqueId } from "rvx";
 *
 * <UseUniqueId>
 *   {id => <>
 *     <label for={id}>Text</label>
 *     <input type="text" id={id} />
 *   </>}
 * </UseUniqueId>
 * ```
 */
declare function UseUniqueId<T = Content>(props: {
	children: Component<string, T>;
}): T;
/**
 * Get a {@link uniqueId unique id} for the specified object.
 *
 * @param target The target object.
 * @returns The id. This is always the same id for the same object.
 */
declare function uniqueIdFor(target: object): string;

/**
 * Render arbitrary content.
 *
 * Supported content types are:
 * + Null and undefined (not displayed).
 * + Arbitrarily nested arrays/fragments of content.
 * + DOM nodes. Children will be removed from document fragments.
 * + {@link View Views}.
 * + Anything created with rvx's jsx runtime.
 * + Anything else is displayed as text.
 *
 * @param content The content to render.
 * @returns A view instance or the `content` parameter itself if its already a view.
 *
 * @example
 * ```tsx
 * import { $, render } from "rvx";
 *
 * // Not displayed:
 * render(null);
 * render(undefined);
 *
 * // Arbitrarily nested arrays/fragments of content:
 * render([["Hello"], " World!"]);
 * render(<>{<>"Hello"</>}{" World!"}</>);
 *
 * // DOM nodes:
 * render(<h1>Hello World!</h1>);
 * render(document.createElement("input"));
 * render(document.createTextNode("Hello World!"));
 * render(someTemplate.content.cloneNode(true));
 *
 * // Views:
 * render(render("Hello World!"));
 * render(when(true, () => "Hello World!"));
 * render(<Show when={true}>{() => "Hello World!"}</Show>);
 *
 * // Text:
 * render("Hello World!");
 * render(() => "Hello World!");
 * render(42);
 * render($(42));
 * ```
 */
declare function render(content: Content): View;
/**
 * Render arbitrary content and append it to the specified parent until the current lifecycle is disposed.
 *
 * @param parent The parent node.
 * @param content The content to render. See {@link render} for supported types.
 * @returns The view instance.
 *
 * @example
 * ```tsx
 * import { mount } from "rvx";
 *
 * mount(
 *   document.body,
 *   <h1>Hello World!</h1>
 * );
 * ```
 *
 * Since the content is removed when the current lifecycle is disposed, this can also be used to temporarily append
 * content to different elements while some component is rendered:
 * ```tsx
 * import { mount, Content } from "rvx";
 *
 * function Popover(props: { text: Content, children: Content }) {
 *   const visible = $(false);
 *
 *   mount(
 *     document.body,
 *     <Show when={visible}>
 *       {props.children}
 *     </Show>
 *   );
 *
 *   return <button on:click={() => { visible.value = !visible.value; }}>
 *     {props.text}
 *   </button>;
 * }
 *
 * mount(
 *   document.body,
 *   <Popover text="Click me!">
 *     Hello World!
 *   </Popover>
 * );
 * ```
 */
declare function mount(parent: Node, content: Content): View;
/**
 * A function that is called when the view boundary may have been changed.
 */
interface ViewBoundaryOwner {
	/**
	 * @param first The current first node.
	 * @param last The current last node.
	 */
	(first: Node, last: Node): void;
}
/**
 * A function that must be called after the view boundary has been changed.
 */
interface ViewSetBoundaryFn {
	/**
	 * @param first The first node if changed.
	 * @param last The last node if changed.
	 */
	(first: Node | undefined, last: Node | undefined): void;
}
interface UninitViewProps {
	/**
	 * The current first node of this view.
	 *
	 * + This may be undefined while the view is not fully initialized.
	 * + This property is not reactive.
	 */
	get first(): Node | undefined;
	/**
	 * The current last node of this view.
	 *
	 * + This may be undefined while the view is not fully initialized.
	 * + This property is not reactive.
	 */
	get last(): Node | undefined;
}
type UninitView = UninitViewProps & Omit<View, keyof UninitViewProps>;
/**
 * A function that is called once to initialize a view instance.
 *
 * View creation will fail if no first or last node has been set during initialization.
 */
interface ViewInitFn {
	/**
	 * @param setBoundary A function that must be called after the view boundary has been changed.
	 * @param self The current view itself. This can be used to keep track of the current boundary and parent nodes.
	 */
	(setBoundary: ViewSetBoundaryFn, self: UninitView): void;
}
/**
 * Represents a sequence of at least one DOM node.
 *
 * Consumers of the view API need to guarantee that:
 * + The sequence of nodes is not modified from the outside.
 * + If there are multiple nodes, all nodes must have a common parent node at all time.
 */
declare class View {
	#private;
	/**
	 * Create a new view.
	 *
	 * View implementations need to guarantee that:
	 * + The view doesn't break when the parent node is replaced or when a view consisting of only a single node is detached from its parent.
	 * + The boundary is updated immediately after the first or last node has been updated.
	 * + If there are multiple nodes, all nodes remain in the current parent.
	 * + If there are multiple nodes, the initial nodes must have a common parent.
	 */
	constructor(init: ViewInitFn);
	/**
	 * The current first node of this view.
	 *
	 * Note, that this property is not reactive.
	 */
	get first(): Node;
	/**
	 * The current last node of this view.
	 *
	 * Note, that this property is not reactive.
	 */
	get last(): Node;
	/**
	 * The current parent node or undefined if there is none.
	 *
	 * Note, that this property is not reactive.
	 */
	get parent(): Node | undefined;
	/**
	 * Set the boundary owner for this view until the current lifecycle is disposed.
	 *
	 * @throws An error if there currently is a boundary owner.
	 */
	setBoundaryOwner(owner: ViewBoundaryOwner): void;
	/**
	 * Append all nodes of this view to the specified parent.
	 *
	 * @param parent The parent to append to.
	 */
	appendTo(parent: Node): void;
	/**
	 * Insert all nodes of this view before a reference child of the specified parent.
	 *
	 * @param parent The parent to insert into.
	 * @param ref The reference child to insert before. If this is null, the nodes are appended to the parent.
	 */
	insertBefore(parent: Node, ref: Node | null): void;
	/**
	 * Detach all nodes of this view from the current parent if there is one.
	 *
	 * If there are multiple nodes, they are moved into a new document fragment to allow the view implementation to stay alive.
	 *
	 * @returns The single removed node or the document fragment they have been moved into.
	 */
	detach(): Node | DocumentFragment;
}
/**
 * Get an iterator over all current top level nodes of a view.
 *
 * @param view The view.
 * @returns The iterator.
 *
 * @example
 * ```tsx
 * import { render, viewNodes } from "rvx";
 *
 * const view = render(<>
 *   <h1>Hello World!</h1>
 * </>);
 *
 * for (const node of viewNodes(view)) {
 *   console.log(node);
 * }
 * ```
 */
declare function viewNodes(view: View): IterableIterator<Node>;
/**
 * Watch an expression and render content from its result.
 *
 * + If an error is thrown during initialization, the error is re-thrown.
 * + If an error is thrown during a signal update, the previously rendered content is kept in place and the error is re-thrown.
 * + Content returned from the component can be directly reused within the same `nest` instance.
 *
 * See {@link Nest `<Nest>`} when using JSX.
 *
 * @param expr The expression to watch.
 * @param component The component to render with the expression result. If the expression returns a component, null or undefined, this can be omitted.
 *
 * @example
 * ```tsx
 * import { $, nest, e } from "rvx";
 *
 * const count = $(0);
 *
 * // Using the expression result in a component:
 * nest(count, count => {
 *   switch (count) {
 *     case 0: return e("h1").append("Hello World!");
 *     case 1: return "Something else...";
 *   }
 * })
 *
 * // Or directly returning a component from the expression:
 * nest(() => {
 *   switch (count.value) {
 *     case 0: return () => e("h1").append("Hello World!");
 *     case 1: return () => "Something else...";
 *   }
 * })
 * ```
 */
declare function nest(expr: Expression<Component | null | undefined>): View;
declare function nest<T>(expr: Expression<T>, component: Component<T>): View;
/**
 * Render conditional content.
 *
 * + Content is only re-rendered if the expression result is not strictly equal to the previous one. If this behavior is undesired, use {@link nest} instead.
 * + If an error is thrown by the expression or component during initialization, the error is re-thrown.
 * + If an error is thrown by the expression or component during a signal update, the previously rendered content is kept and the error is re-thrown.
 *
 * See {@link Show `<Show>`} when using JSX.
 *
 * @param condition The condition to watch.
 * @param truthy The component to render when the condition result is truthy.
 * @param falsy An optional component to render when the condition is falsy.
 *
 * @example
 * ```tsx
 * import { $, when, e } from "rvx";
 *
 * const message = $<null | string>("Hello World!");
 *
 * when(message, value => e("h1").append(value), () => "No message...")
 * ```
 */
declare function when<T>(condition: Expression<T | Falsy>, truthy: Component<T>, falsy?: Component): View;
interface ForContentFn<T> {
	/**
	 * @param value The value.
	 * @param index An expression to get the current index.
	 * @returns The content.
	 */
	(value: T, index: () => number): Content;
}
/**
 * Render content for each value in an iterable.
 *
 * Errors thrown by the component or while updating an index result in undefined behavior.
 *
 * See {@link For `<For>`} for use with JSX.
 *
 * @param each The expression to watch. Note, that signals accessed during iteration will also trigger updates.
 * @param component The component to render for each value.
 *
 * @example
 * ```tsx
 * import { $, forEach, e } from "rvx";
 *
 * const items = $([1, 2, 3]);
 *
 * forEach(items, value => e("li").append(value))
 * ```
 */
declare function forEach<T>(each: Expression<Iterable<T>>, component: ForContentFn<T>): View;
interface IndexContentFn<T> {
	/**
	 * @param value An expression to get the current value.
	 * @param index The index.
	 * @returns The content.
	 */
	(value: () => T, index: number): Content;
}
/**
 * Render content for each index in an iterable.
 *
 * Errors thrown by the component or while updating a value result in undefined behavior.
 *
 * See {@link Index `<Index>`} when using JSX.
 *
 * @param each The expression to watch. Note, that signals accessed during iteration will also trigger updates.
 * @param component The component to render for each index.
 *
 * @example
 * ```tsx
 * import { $, indexEach, e } from "rvx";
 *
 * const items = $([1, 2, 3]);
 *
 * indexEach(items, value => e("li").append(value))
 * ```
 */
declare function indexEach<T>(each: Expression<Iterable<T>>, component: IndexContentFn<T>): View;
/**
 * A wrapper that can be used for moving and reusing views.
 */
declare class MovableView {
	#private;
	constructor(view: View);
	/**
	 * Create a new view that contains the wrapped view until it is moved again or detached.
	 *
	 * If the lifecycle in which `move` is called is disposed, the created view no longer updates its boundary and nodes may be silently removed.
	 */
	move: Component<void, View>;
	/**
	 * Detach content from the currently active view.
	 */
	detach(): void;
}
/**
 * Render and wrap arbitrary content so that it can be moved and reused.
 */
declare function movable(content: Content): MovableView;
/**
 * Attach or detach content depending on an expression.
 *
 * Content is kept alive when detached.
 *
 * See {@link Attach `<Attach>`} when using JSX.
 *
 * @param condition The condition to watch.
 * @param content The content to attach when the condition result is truthy.
 *
 * @example
 * ```tsx
 * import { $, attach } from "rvx";
 *
 * const showMessage = $(true);
 *
 * attachWhen(showMessage, e("h1").append("Hello World!"))
 * ```
 */
declare function attachWhen(condition: Expression<boolean>, content: Content): View;

/**
 * Set rvx jsx attributes.
 *
 * @param elem The element.
 * @param attrs The attributes to set.
 */
declare function applyElement<E extends Element>(elem: E, attrs: Attributes<E>): void;

/**
 * Utility for modifying an existing element or {@link ElementBuilder element builder} returned from a component.
 *
 * + Event listeners and the _ref_ attribute are additive.
 * + Unique styles, classes, attributes and properties are additive.
 * + **Styles, classes, attributes and properties that are already set by the component may cause conflicts.**
 *
 * @example
 * ```tsx
 * <Override class="some-class">
 *   <SomeComponent />
 * </Override>
 * ```
 */
declare function Override<E extends Element>(props: {
	children: unknown;
} & Attributes<E>): unknown;

/**
 * Watch an expression and render content from its result.
 *
 * + If an error is thrown during initialization, the error is re-thrown.
 * + If an error is thrown during a signal update, the previously rendered content is kept in place and the error is re-thrown.
 * + Content returned from the component can be directly reused within the same `<Nest>` instance.
 *
 * See {@link nest} when not using JSX.
 *
 * @example
 * ```tsx
 * import { $, Nest } from "rvx";
 *
 * const count = $(0);
 *
 * // Using the expression result in a component:
 * <Nest watch={count}>
 *   {count => {
 *     switch (count) {
 *       case 0: return <h1>Hello World!</h1>;
 *       case 1: return "Something else...";
 *     }
 *   }}
 * </Nest>
 *
 * // Or directly returning a component from the expression:
 * <Nest watch={() => {
 *   switch (count.value) {
 *     case 0: return () => <h1>Hello World!</h1>;
 *     case 1: return () => "Something else...";
 *   }
 * }} />
 * ```
 */
declare function Nest<T>(props: {
	/**
	 * The expression to watch.
	 */
	watch: T;
	/**
	 * The component to render with the expression result.
	 *
	 * If the expression returns a component, null or undefined, this can be omitted.
	 */
	children: Component<ExpressionResult<T>>;
} | {
	/**
	 * The expression to watch.
	 */
	watch: Expression<Component | null | undefined>;
}): View;
/**
 * Render conditional content.
 *
 * + Content is only re-rendered if the expression result is not strictly equal to the previous one. If this behavior is undesired, use {@link Nest} instead.
 * + If an error is thrown by the expression or component during initialization, the error is re-thrown.
 * + If an error is thrown by the expression or component during a signal update, the previously rendered content is kept and the error is re-thrown.
 *
 * See {@link when} when not using JSX.
 *
 * @example
 * ```tsx
 * import { $, Show } from "rvx";
 *
 * const message = $<null | string>("Hello World!");
 *
 * <Show when={message} else={() => <>No message...</>}>
 *   {value => <h1>{value}</h1>}
 * </Show>
 * ```
 */
declare function Show<T>(props: {
	/**
	 * The condition to watch.
	 */
	when: Expression<T | Falsy>;
	/**
	 * The component to render when the condition result is truthy.
	 */
	children: Component<T>;
	/**
	 * An optional component to render when the condition result is falsy.
	 */
	else?: Component;
}): View;
/**
 * Render content for each value in an iterable.
 *
 * Errors thrown by the component or while updating an index result in undefined behavior.
 *
 * See {@link forEach} when not using JSX.
 *
 * @example
 * ```tsx
 * import { $, For } from "rvx";
 *
 * const items = $([1, 2, 3]);
 *
 * <For each={items}>
 *   {value => <li>{value}</li>}
 * </For>
 * ```
 */
declare function For<T>(props: {
	/**
	 * The expression to watch. Note, that signals accessed during iteration will also trigger updates.
	 */
	each: Expression<Iterable<T>>;
	/**
	 * The component to render for each value.
	 */
	children: ForContentFn<T>;
}): View;
/**
 * Render content for each index in an iterable.
 *
 * Errors thrown by the component or while updating a value result in undefined behavior.
 *
 * See {@link indexEach} when not using JSX.
 *
 * @example
 * ```tsx
 * import { $, Index } from "rvx";
 *
 * const items = $([1, 2, 3]);
 *
 * <Index each={items}>
 *   {value => <li>{value}</li>}
 * </Index>
 * ```
 */
declare function Index<T>(props: {
	/**
	 * The expression to watch.
	 *
	 * Note, that signals accessed during iteration will also trigger updates.
	 */
	each: Expression<Iterable<T>>;
	/**
	 * The component to render for each index pair.
	 */
	children: IndexContentFn<T>;
}): View;
/**
 * Attach or detach content depending on an expression.
 *
 * Content is kept alive when detached.
 *
 * See {@link attachWhen} when not using JSX.
 *
 * @example
 * ```tsx
 * import { $, Attach } from "rvx";
 *
 * const showMessage = $(true);
 *
 * <Attach when={showMessage}>
 *   <h1>Hello World!</h1>
 * </Attach>
 * ```
 */
declare function Attach(props: {
	/**
	 * The condition to watch.
	 */
	when: Expression<boolean>;
	/**
	 * The content to attach when the condition result is truthy.
	 */
	children?: Content;
}): View;

export { $, Attach, Context, ENV, ElementBuilder, Emitter, For, HTML, Index, MATHML, MovableView, NODE, Nest, Override, Provide, SVG, Show, Signal, UseUniqueId, View, XMLNS, applyElement, attachWhen, batch, capture, captureSelf, e, forEach, get, indexEach, isTracking, isolate, lazy, leak, map, mapArray, memo, mount, movable, nest, override, render, teardown, teardownOnError, trigger, uniqueId, uniqueIdFor, untrack, useUniqueId, viewNodes, watch, watchUpdates, when };
export type { Attributes, ClassValue, Component, Content, ContextState, Event$1 as Event, EventArgs, EventFn, EventListener, Expression, ExpressionResult, Falsy, ForContentFn, IndexContentFn, MapArrayFn, MapFn, NodeTarget, Reactive, SignalSource, Static, StyleMap, StyleValue, TagNameMap, TeardownHook, TriggerPipe, UninitView, ViewBoundaryOwner, ViewInitFn, ViewSetBoundaryFn };
