UNPKG

alien-dom

Version:

Next-generation JSX client renderer with observable data primitives, immediate DOM references, and more.

1,039 lines (969 loc) 61.7 kB
import { g as ArrayRef, h as ArrayOperation, J as JSX, i as Disposable, E as EffectResult, C as ComputedRef, j as ForwardedContext, k as Context, V as VarArgs, l as DisposablePromise, m as EffectCallback, n as AnyElement, R as Ref, o as ElementProxy, p as ReadonlyRef, q as HTMLOrSVGElement, r as SpringAnimation, s as CSSAttributes, t as HTMLTagName, u as SVGTagName, f as FunctionComponent, P as Promisable, v as AnimatedProps, U as Unref, w as UnresolvedChild, x as ContextStore, y as AlienBoundEffect, z as AlienNode, B as ChildrenFragment, G as AlienEffectType } from './animate-b617067e.js'; export { aS as $, aU as $$, a2 as AlienEffect, a3 as AlienEffects, c as AlienElement, aK as AlienElementIterator, A as AlienElementList, aL as AlienEvent, a4 as AlienMountEffects, aT as AlienSelectable, X as AnimatedProp, bc as AnimationEventHandler, d as AnimationsParam, aV as AriaAttributes, aW as AriaRole, ag as ArrayObserver, aY as CSSAngle, aX as CSSLength, aZ as CSSTransformAttributes, b5 as ChangeEventHandler, b0 as ClipboardEventHandler, b1 as CompositionEventHandler, ax as ComputedInput, a_ as DOMAttributes, b2 as DragEventHandler, aD as EffectContext, a$ as EventHandler, aA as FlatReadonlyRef, b3 as FocusEventHandler, b4 as FormEventHandler, L as FrameCallback, F as FromElementProxy, bm as HTML, T as HTMLAnimatedProps, bl as HTMLAttributes, H as HTMLAttributesByTagName, be as HTMLClassArrayAttribute, bh as HTMLClassAttribute, bf as HTMLClassObjectAttribute, bg as HTMLClassPrimitiveAttribute, bk as HTMLDatasetAttribute, bi as HTMLStyleArrayAttribute, bj as HTMLStyleAttribute, b6 as KeyboardEventHandler, ah as LensRef, b7 as MouseEventHandler, aa as ObservableHooks, af as Observer, aR as OpenPromise, b9 as PointerEventHandler, ac as ReadonlyArrayRef, ae as RefMap, bp as SVG, W as SVGAnimatedProps, bn as SVGAttributes, S as SVGAttributesByTagName, bo as SVGElementLike, aI as ShadowRootNode, Q as SpringConfig, O as SpringConfigOption, I as SpringDelay, K as SpringDelayFn, N as StepAnimation, M as StepAnimationFn, aJ as TemplateNode, b8 as TouchEventHandler, bd as TransitionEventHandler, ba as UIEventHandler, bb as WheelEventHandler, Y as animate, ad as arrayRef, _ as attachDisposer, ai as collectAccessedRefs, al as computed, am as computedEvery, an as computedSome, a7 as createAsyncEffect, a0 as createDisposable, a5 as createEffect, aM as createElementProxy, a6 as createOnceEffect, Z as defineContext, a8 as defineEffectType, ay as evaluateInput, a9 as getCurrentEffect, au as guardRef, at as isArrayRef, aC as isChildrenFragment, $ as isDisposable, aN as isElementProxy, ar as isReadonlyRef, as as isRef, aG as isShadowRoot, aH as isTemplateNode, ao as lens, a1 as mergeDisposables, ap as observe, aq as observeArrayOperations, av as peek, aO as promiseEvent, aQ as promiseRace, aP as promiseTimeout, aj as ref, ak as refMap, ab as setObservableHooks, aw as unref, aB as useChildren, aE as useEffect, aF as useWrappedEffect, az as when } from './animate-b617067e.js'; import { A as AlienComponent, N as NodeStore } from './helpers-eb468bd5.js'; import { Falsy, AllKeys, Remap, Intersect } from '@alloc/types'; export { F as Fragment, S as SVGNamespace, c as createElement, a as createFragment } from './jsx-runtime-1947324d.js'; import { Key } from 'ts-key-enum'; export { Color, mixColor, parseColor } from 'linear-color'; import 'csstype'; /** * Returns a new `AbortController` instance. When the `deps` argument changes, * the previous `AbortController` instance is aborted and a new one is created. */ declare function useAbortController(deps: readonly any[]): AbortController; /** * The `signal` argument has its `abort `event propagated to the returned * `AbortController` instance. When the `deps` argument changes, the * `AbortController` instance is aborted and a new one is created. */ declare function useAbortController(signal: AbortSignal | undefined, deps: readonly any[]): AbortController; /** * The `signal` argument has its `abort `event propagated to the returned * `AbortController` instance. * * Note: The `signal` argument is captured on first render. It won't be updated * unless you use a dependency array. */ declare function useAbortController(signal?: AbortSignal): AbortController; /** * Observe the fine-grained changes to an `ArrayRef` object. * * 🪝 This hook adds 2 to the hook offset. */ declare function useArrayObserver<T>(arrayRef: ArrayRef<T> | Falsy, handler: ArrayOperation.Handler<T>): void; declare const useArrayRef: <T>(init?: readonly T[] | undefined, debugId?: string | number) => ArrayRef<T>; type ArrayViewRenderFn<T = any> = (item: T, key: JSX.ElementKey) => JSX.Children; interface ArrayViewOptions<T = any> { getItemKey?: (item: T) => JSX.ElementKey; } declare function useArrayView<T>(array: ArrayRef<T> | Falsy, render: ArrayViewRenderFn<T>, deps?: readonly any[]): JSX.Element | null; declare function useArrayView<T>(array: ArrayRef<T> | Falsy, options: ArrayViewOptions<T> | Falsy, render: ArrayViewRenderFn<T>, deps?: readonly any[]): JSX.Element | null; /** * Apply the properties of the `source` object to the `target` object. If a * `source` property has an undefined value, the initial value of the `target` * object is used instead. * * The `target` object is updated within a `useEffect` callback. * * Every possible property of the `target` object must exist. In other words, * you must explicitly define each property, even if `undefined` is used as the * initial value. This requirement allows the hook to “unset” a property when * it's undefined in the `source` object. It's also good for performance. * * 🪝 This hook adds 2 to the hook offset. */ declare function useAssign<T extends object>(target: T, source: Partial<T>): {} & T; type UseAsyncFn<T> = (state: UseAsync<T>) => PromiseLike<T> | T; declare function useAsync<T>(get: UseAsyncFn<UseAsyncAwaited<T>> | Falsy, deps?: readonly any[]): UseAsync<UseAsyncAwaited<T>>; declare class UseAsync<T> { private state; private abortCtrl; timestamp: number | null; promise: Promise<void> | null; effects: Disposable[]; numAttempts: number; stale: boolean; deps?: readonly any[]; /** @observable */ get status(): "error" | "loaded" | "idle" | "loading"; /** @observable */ get result(): T | undefined; /** @observable */ get error(): any; get abort(): () => void; get aborted(): boolean; get abortSignal(): AbortSignal; get retry(): (reset?: boolean) => void; markAttempt(): void; setPromise(promise: Promise<any>): void; /** * Track a disposable effect that will be disposed when the component unmounts * or the async getter is called again. */ get track(): { (effect: () => void): () => void; <E extends { dispose(): void; }>(effect: E): E; }; } /** * The result of a `useAsync` callback is processed such that an array * of promises, an array of objects with promise values, or an object * with promise values is awaited. If the callback's return value is a * promise, any resulting array or object **won't** be processed. */ type UseAsyncAwaited<T> = T extends readonly (infer Item)[] ? UseAsyncAwaitedItem<Item>[] : UseAsyncAwaitedItem<T>; type UseAsyncAwaitedItem<T> = T extends PromiseLike<infer Item> ? UseAsyncAwaited<Item> : T extends (...args: any[]) => any ? T : T extends object ? { [K in keyof T]: Awaited<T[K]>; } : T; declare function useAutoBind<T extends object>(target: T): Readonly<T>; declare function useClickOutside(handler: () => void): { setElement: (element: HTMLElement | null) => void; enabled: boolean; enable: (target: HTMLElement | Document) => EffectResult; dispose?: (() => void) | undefined; }; /** * Creates a `ComputedRef` that is updated when the dependencies change. * * Like `useMemo`, the ref is recreated when the component is hot reloaded. * * 🪝 This hook adds 2 to the hook offset. */ declare function useComputed<T>(get: () => T, deps?: readonly any[], debugId?: string | number): ComputedRef<T> & [value: T]; /** * Create a piece of state that persists between renders. The state is recreated * when its `params` change between renders. If the only argument is a plain * object, its properties will be used for dependency tracking. * * Use this over `useMemo` for state that needs to persist between hot reloads. * Note that if you define a `dispose` method on the state, it won't be * persisted between hot reloads anymore and the `dispose` method will be called * before the state is recreated (when its `params` change). * * 🪝 This hook adds 2 to the hook offset. */ declare function useConst<State extends object, Params extends any[]>(init: new (...params: Params) => State, ...params: Params): State; declare function useConst<State, Params extends any[]>(init: (...params: Params) => State, ...params: Params): State; /** * Capture the current context and return a Provider component that can * forward it to other components asynchronously. */ declare function useContext(): ForwardedContext; /** * Access the current value of the given Context type. */ declare function useContext<T>(context: Context<T>): T; /** * Set a timeout to run an effect after a delay, with proper cleanup on unmount. * * If no dependency array is given, the effect runs once (even if the `delay` * argument value is changed in a future render). * * 🪝 This hook adds 1 to the hook offset. */ declare function useDelayedEffect(delay: VarArgs<number | DisposablePromise<any>>, effect: EffectCallback | Falsy, deps?: readonly any[]): void; /** * Returns the result of `depsHaveChanged` with the current `deps` and the * previous `deps` from the last successful render. * * 🪝 This hook adds 1 to the hook offset. */ declare function useDepsArray(deps: readonly any[] | undefined): boolean; /** * An `ElementRef` is attached to a DOM element through a JSX element‘s `ref` * prop. It‘s most often used to enact side effects that are tied to the * lifecycle of the DOM element (i.e. the side effects will be active from the * time the DOM element is mounted to the time it is unmounted). * * Because the JSX `ref` prop accepts multiple “element refs” in the shape of an * array, they can be useful for component hooks that need to attach side * effects to DOM elements, removing the need to hoist your JSX elements just to * pass them into those hooks. */ declare class ElementRef<Element extends AnyElement = AnyElement> implements JSX.ElementRef { readonly element: Element | null; protected dispose: (() => void) | void; setElement(element: Element | null): void; /** * When this method is called, it means the “element ref” was passed into a JSX * element through its `ref` prop and that JSX element is now mounted to the * document. */ protected attach?(element: Element): (() => void) | void; /** * When this method is called, it means the DOM element that was attached to * this “element ref” is no longer in the document. */ protected detach?(element: Element): void; } /** * Same as `ElementRef` except a delegate (provided to the constructor) is * called for the `attach` and `detach` events. */ declare class DelegatedElementRef<Element extends AnyElement = AnyElement, Key = any> extends ElementRef<Element> { delegate: ElementRefDelegate<Element, Key>; key: Key; constructor(delegate: ElementRefDelegate<Element, Key>, key: Key); protected attach(element: Element): (() => void) | void; protected detach(element: Element): void; } /** * A delegate for `DelegatedElementRef`. */ interface ElementRefDelegate<Element extends AnyElement, Key> { /** * When this method is called, it means the “element ref” was passed into a JSX * element through its `ref` prop and that JSX element is now mounted to the * document. */ attach?(element: Element, ref: DelegatedElementRef<Element, Key>): (() => void) | void; /** * When this method is called, it means the DOM element that was attached to * this “element ref” is no longer in the document. */ detach?(element: Element, ref: DelegatedElementRef<Element, Key>): void; } declare const useElementArray: <T extends Element>(deps?: readonly any[]) => { new (arrayLength: number): ElementArray<T>; new (...items: (ElementRef<T> | undefined)[]): ElementArray<T>; isArray(arg: any): arg is any[]; from<T_1>(arrayLike: ArrayLike<T_1>): T_1[]; from<T_2, U>(arrayLike: ArrayLike<T_2>, mapfn: (v: T_2, k: number) => U, thisArg?: any): U[]; from<T_3>(iterable: Iterable<T_3> | ArrayLike<T_3>): T_3[]; from<T_4, U_1>(iterable: Iterable<T_4> | ArrayLike<T_4>, mapfn: (v: T_4, k: number) => U_1, thisArg?: any): U_1[]; of<T_5>(...items: T_5[]): T_5[]; readonly [Symbol.species]: ArrayConstructor; }; declare class ElementArray<T extends AnyElement = AnyElement> extends Array<ElementRef<T> | undefined> { /** * Get the element at the given index. Negative indices are allowed. */ get(index: number): T | null; /** * Get an element ref to hold an element for the given index. Pass the result * as the `ref` prop of the JSX element whose DOM node you need a reference * to. */ bind(index: number): ElementRef<T>; protected attach(_element: T, ref: DelegatedElementRef<T, number>): void; protected detach(_element: T, ref: DelegatedElementRef<T, number>): void; } /** * An observable object that tracks the bounds of an element. */ declare class ElementBounds implements JSX.ElementRef { constructor(element?: AnyElement | null); protected rectRef: Ref<DOMRectReadOnly | null>; protected resizeEffect: Disposable | undefined; protected observedElement: AnyElement | null; protected observer: ResizeObserver | null; protected locked: boolean; protected topRef: ComputedRef<number> | undefined; protected rightRef: ComputedRef<number> | undefined; protected bottomRef: ComputedRef<number> | undefined; protected leftRef: ComputedRef<number> | undefined; protected widthRef: ComputedRef<number> | undefined; protected heightRef: ComputedRef<number> | undefined; get x(): number; get y(): number; get top(): number; get right(): number; get bottom(): number; get left(): number; get width(): number; get height(): number; toJSON(): any; observe(key: Exclude<keyof DOMRectReadOnly, 'toJSON' | 'x' | 'y'>): ComputedRef<number>; setElement(element: AnyElement | null): void; /** * While locked, the current bounds won't be updated when the target element * changes. */ lock(flag: boolean): void; dispose(): void; protected setupResizeEffect(element: AnyElement): void; } declare function useElementBounds(deps?: readonly any[]): typeof ElementBounds; declare const useElementMap: <K, T extends Element = Element>(deps?: readonly any[]) => { new (delegate?: ElementRefDelegate<T, K> | undefined): ElementMap<K, T>; }; declare class ElementMap<Key, Element extends AnyElement = AnyElement> implements Iterable<[Key, Element]>, ElementRefDelegate<Element, Key> { delegate?: ElementRefDelegate<Element, Key> | undefined; private map; constructor(delegate?: ElementRefDelegate<Element, Key> | undefined); /** * Get the element at the given key. Returns `null` if the key is not found. */ get(key: Key): Element | null; /** * Get an element ref to hold an element for the given key. Pass the result as * the `ref` prop of the JSX element whose DOM node you need a reference to. */ bind(key: Key): ElementRef<Element>; /** @internal */ attach(element: Element, ref: DelegatedElementRef<Element>): void | (() => void) | undefined; /** @internal */ detach(element: Element, ref: DelegatedElementRef<Element>): void; [Symbol.iterator](): Iterator<[Key, Element]>; } /** * Create a `Proxy` that forwards access/invocations to the DOM node of the JSX * element that receives this proxy in its `ref` prop. * * 🪝 This hook adds 3 to the hook offset. */ declare function useElementProxy<T extends Element>(effect?: (element: T) => EffectResult, deps?: readonly any[]): ElementProxy<T>; type EventTargetEffect<Target extends EventTarget = EventTarget> = (target: Target | Document) => EffectResult; /** * Create an element ref that attaches an effect when the element is set. * * If the ref is not attached to a JSX element at render time, the effect will * be attached to the `document` instead. * * 🪝 This hook adds 2 to the hook offset. */ declare function useEventTarget<Target extends EventTarget>(effect: EventTargetEffect<Target>): { setElement: (element: HTMLElement | null) => void; enabled: boolean; enable: (target: HTMLElement | Document) => EffectResult; dispose?: (() => void) | undefined; }; /** * Create a function that forces the current component to rerender. */ declare function useForceUpdate(): any; /** * By default, this hook returns a stable guid. If the `reset` argument is true, * the guid will change on every render. If the `reset` argument is later * changed to false, the last used guid will remain stable. * * It can be used to conditionally bust caches (i.e. for debugging or * development purposes), but it's also good for generating a stable guid. * * The guid is guaranteed to be truthy. To avoid overflow issues, the guid * starts at `Number.MIN_SAFE_INTEGER` instead of 1, but 0 is always skipped. If * this approach isn't good enough, you can pass a custom `generateId` function. */ declare function useGlobalId(reset?: boolean): number; declare function useGlobalId<Id extends string | number = number>(reset: boolean | null | undefined, generateId: () => Id): Id; /** * For conditional hooks, the `useHookOffset` function can be used in the * alternate branch to ensure that the hook index is consistent between the two * branches. * * Note: This approach is **fragile** and should be used sparingly, but it's * very useful for custom hooks whose behavior is flexible based on input * parameters. * * Built-in hooks like `useConst`, `useMemo`, and `useComputed` require an * offset of 1, while `useRef`, `useEffect`, and `useObserver` require an offset * of 2. For other hooks, you must look at their implementation to calculate the * required offset. Statements like `component.nextHookIndex++` also increase * the required offset (see `useConst` for an example). */ declare function useHookOffset(offset: number): void; /** * Set up an effect that repeats at a fixed time interval. * * 🪝 This hook adds 1 to the hook offset. */ declare const useInterval: (callback: () => void, delay: number | null, deps?: readonly any[]) => void; interface KeyBindingEvent<Target extends Document | HTMLElement = any> { target: Target; repeat: boolean; stopPropagation(): void; preventDefault(): void; } type Split<T extends string> = T extends `${infer First}${infer Rest}` ? First | Split<Rest> : never; type LetterKey = Split<'ABCDEFGHIJKLMNOPQRSTUVWXYZ'>; type DigitKey = Split<'0123456789'>; type SymbolKey = Split<'!@#$%^&*()_+-=[]{}|\\;:,.?<>/\'" '>; type KeyCombo = readonly KeyCombo[] | `${Key}` | LetterKey | DigitKey | SymbolKey | false | null | undefined; declare function useKeyBinding<Target extends Document | HTMLElement>(combo: KeyCombo, onKeyDown?: (event: KeyBindingEvent<Target>) => EffectResult, options?: AddEventListenerOptions): { /** * Equals true when the key binding is activated. * @observable */ isActive: boolean; effect: { dispose(): void; } | null; combo: Set<string>; options: AddEventListenerOptions | undefined; onKeyDown: ((event: KeyBindingEvent<any>) => EffectResult) | undefined; onKeyUp: EffectResult | undefined; setElement: (element: HTMLElement | null) => void; enable: (target: HTMLElement | Document, options?: AddEventListenerOptions | undefined) => EffectResult; }; type KeyBinding = ReturnType<typeof initKeyBinding>; declare const initKeyBinding: () => { /** * Equals true when the key binding is activated. * @observable */ isActive: boolean; effect: Disposable | null; combo: Set<string>; options: AddEventListenerOptions | undefined; onKeyDown: ((event: KeyBindingEvent) => EffectResult) | undefined; onKeyUp: EffectResult | undefined; setElement: (element: HTMLElement | null) => void; enable: (target: Document | HTMLElement, options?: AddEventListenerOptions) => EffectResult; }; /** * @experimental */ declare function defineMachine<T extends MachineType>(setup: (params: Readonly<MachineParams<T>>, update: MachineUpdater<T>, machine: Machine<T>) => MachineState<T>): MachineClass<T>; interface MachineClass<T extends MachineType = any> { new (params: Readonly<MachineParams<T>>, onChange?: MachineCallback<T>): Machine<T>; } type MachineType<Params extends object | void = any, State extends { value: string; } = any> = (params: Params) => State; type MachineState<T extends MachineType, S extends MachineValue<T> = any> = T extends MachineType<any, infer State> ? Extract<State, { value: S; }> : never; type MachineValue<T extends MachineType> = T extends MachineType<any, infer State> ? State['value'] : never; type MachineValueWithKey<T extends MachineType, Key extends keyof any> = Extract<MachineState<T>, { [K in Key]: any; }>['value']; type MachineParams<T extends MachineType> = T extends MachineType<infer Params> ? Params : never; type MachineCallback<T extends MachineType> = (state: Readonly<MachineState<T>>, self: Machine<T>) => void; type VoidMachineValue<T extends MachineType> = MachineState<T> extends infer State ? State extends { value: MachineValue<T>; } ? { value: any; } extends State ? State['value'] : never : never : never; type MachineUpdater<T extends MachineType> = { <State extends MachineState<T>>(newState: State): State; <Value extends VoidMachineValue<T>>(value: Value): Extract<MachineState<T>, { value: Value; }>; <Value extends MachineValue<T>, State extends Extract<MachineState<T>, { value: Value; }>>(value: Value, newState: Omit<State, 'value'>): State; }; type MachineProxy<T extends MachineType, State extends MachineValue<T> = any> = ProxiedMachine<T, State> & Readonly<AssumedState<MachineState<T>>>; interface ProxiedMachine<T extends MachineType, State extends MachineValue<T>> extends Machine<T, State> { is<Value extends MachineValue<T>>(value: Value | Value[]): this is MachineProxy<T, Value>; has<Key extends AllKeys<MachineState<T>>>(key: Key): this is MachineProxy<T, MachineValueWithKey<T, Key>>; } type OmitValue<T> = T extends any ? Remap<Omit<T, 'value'>> : never; type AssumedState<T> = Remap<Intersect<[ T ] extends [{ value: infer V; }] ? { value: V; } & OmitValue<T> : never>>; declare class Machine<T extends MachineType, State extends MachineValue<T> = any> { readonly params: Readonly<MachineParams<T>>; readonly stateRef: ReadonlyRef<MachineState<T, State>>; constructor(params: Readonly<MachineParams<T>>, stateRef: ReadonlyRef<MachineState<T, State>>); get state(): Readonly<MachineState<T, State>>; get value(): Extract<MachineValue<T>, State>; peek(): any; is<Value extends MachineValue<T>>(value: Value | Value[]): this is Machine<T, Value>; has<Key extends AllKeys<MachineState<T>>>(key: Key): this is Machine<T, MachineValueWithKey<T, Key>>; assert<Value extends MachineValue<T>>(value: Value): Readonly<MachineState<T, Value>>; } declare function toMachineProxy<T extends MachineType>(machine: Machine<T>): MachineProxy<T>; declare function useMachineProxy<T extends MachineType<void>>(constructor: MachineClass<T>, onChange?: MachineCallback<T>): MachineProxy<T>; declare function useMachineProxy<T extends MachineType>(constructor: MachineClass<T>, params: MachineParams<T>, onChange?: MachineCallback<T>): MachineProxy<T>; /** * Save a value until its dependencies change. If a function is passed, it‘s * called with `peek()` and its result is saved as the value. * * The value is discarded when the component is hot-reloaded. * * 🪝 This hook adds 1 to the hook offset. */ declare function useMemo<T>(arg: T | (() => T), deps?: readonly any[]): T; /** * Return the same object reference unless its properties have changed. Strict * equality is used to determine if a property has changed. Property order does * not matter. Undefined values are identical to omitted properties. */ declare function useObjectMemo<T extends object>(o: T): T; /** * Observe a single ref. * * 🪝 This hook adds 2 to the hook offset. */ declare function useObserver<T>(ref: ReadonlyRef<T> | Falsy, onChange: (value: T, oldValue: T) => void): void; /** * Observe any refs accessed by the effect. * * 🪝 This hook adds 2 to the hook offset. */ declare function useObserver(effect: EffectCallback | Falsy, deps: readonly any[]): void; /** * Save the given `value` for the next render. * * 🪝 This hook adds 1 to the hook offset. */ declare function usePrevious<T>(value: T, deps?: readonly any[]): T | undefined; /** * Create an observable ref that persists between renders. Unlike the `useMemo` * hook, the ref is not recreated when the component is hot-reloaded. * * You may destructure the ref into a `[value, setValue]` tuple. * * 🪝 This hook adds 2 to the hook offset. */ declare function useRef<T>(): Ref<T | undefined> & [ value: T | undefined, set: Ref<T | undefined>[1] ]; declare function useRef<T>(init: T | (() => T)): Ref<T> & [value: T, set: Ref<T>[1]]; declare function useRef<T>(init: T | (() => T), deps: readonly any[]): Ref<T> & [value: T, set: Ref<T>[1]]; /** * An object with observable properties. * * The result type of `makeObjectObservable`. */ type Observable<T extends object> = T & { /** * Get the underlying `Ref` of an observable property. * * This method is useful for binding a property to a JSX attribute. */ bind<K extends keyof T>(key: K): Ref<T[K]>; }; /** * Make every property in a plain object observable. */ declare function makeObjectObservable<T extends object>(object: T): Observable<T>; /** * Create a plain object with observable properties. * * 🪝 This hook adds 2 to the hook offset. */ declare function useRefs<T extends object>(init: T | (() => T), deps?: readonly any[]): Observable<T>; /** * This hook is useful for generating a guid that changes on each render * where a particular condition is true or a dependency array has * changed. * * 🪝 This hook adds 4 to the hook offset. */ declare function useResetId(reset: ResetOption): number; declare function useResetId(reset: ResetOption | undefined): number | false; declare function useResetId(reset: string): string; declare function useResetId(reset: string | undefined): string | false; declare function useResetId(reset: string | ResetOption | undefined): string | number | false; declare function useResetId(compute: () => ResetOption, deps: readonly any[]): ReadonlyRef<number>; type ResetOption = boolean | readonly any[]; declare function useScrollStart(handler: (event: Event) => void): { setElement: (element: HTMLElement | null) => void; enabled: boolean; enable: (target: HTMLElement | Document) => EffectResult; dispose?: (() => void) | undefined; }; declare function useQuerySelector<Element extends AnyElement>(selector: string, context?: AnyElement): ReadonlyRef<Element | null> & Iterable<Element | null>; declare function useQuerySelectorAll<Element extends AnyElement>(selector: string, context?: HTMLElement): ReadonlyRef<Set<Element>> & Iterable<Set<Element>>; declare function useSpring<Element extends HTMLOrSVGElement>(element: Element, animations: SpringAnimation<Element> | readonly SpringAnimation<Element>[], shouldRun?: boolean | null): void; /** * This creates a stable callback (i.e. its reference never changes) whose * implementation is updated on every render. * * This is most beneficial for callbacks used in run-once effects. * * 🪝 This hook adds 1 to the hook offset. */ declare function useStableCallback<T extends (...args: any[]) => any>(callback: T): T; declare function useStableCallback<T extends (...args: any[]) => void>(callback: T | Falsy): T; type SetState<T> = Ref<T>[1]; /** * Identical to `useState` in React. The idiomatic way to declare UI state in * AlienDOM is through the `useRef` hook, which you can destructure into a tuple * just like `useState`. For this reason, you should avoid `useState` unless * you're migrating a project from React. * * 🪝 This hook adds 2 to the hook offset. */ declare const useState: { <T>(): [value: T | undefined, set: (arg: T | ((value: T | undefined) => T | undefined) | undefined) => T | undefined]; <T_1>(init: T_1 | (() => T_1), deps?: readonly any[]): [value: T_1, set: (arg: T_1 | ((value: T_1) => T_1)) => T_1]; }; /** * Update the style of an element during render. This hook is preferred * to calling `element.css` directly, because it updates the newest * version of the `element`. The style is applied through morphdom, * which means it won't interfere with animations. * * 🪝 This hook adds 1 to the hook offset. */ declare function useStyle(element: HTMLOrSVGElement | readonly HTMLOrSVGElement[], style: CSSAttributes | Falsy, deps?: readonly any[]): void; /** * Observable access within the useStyle callback does not trigger a * re-render. Instead, the element is updated directly. This is useful * for performance reasons when the style is updated frequently or the * component is expensive to re-render. * * 🪝 This hook adds 1 to the hook offset. */ declare function useStyle(element: HTMLOrSVGElement | readonly HTMLOrSVGElement[], style: () => CSSAttributes | Falsy, deps: readonly any[]): void; /** * Shorthand for `useEffect` with a `!isFirstRun` check inside the effect. */ declare function useUpdateEffect<State = {}>(effect: EffectCallback<State> | Falsy, deps?: readonly any[]): void; /** * This hook is useful whenever you have an externally managed DOM node (or a * collection of nodes) that need to be mounted and unmounted to/from a JSX * parent element. One example is `useArrayView` which uses this hook to * mount/unmount the nodes derived from the array to/from a parent element. * * Create a DOM node that notifies when it's mounted and unmounted. The given * `view` function is called whenever the node is mounted to the DOM, and the * function it returns is called whenever the node is unmounted. The node may be * mounted/unmounted multiple times and the `view` function will be called each * time. When the `deps` change, a new node is created and the old node is * unmounted. * * ⚠️ To receive an unmount notification, you need to use the `unmount` function * provided by AlienDOM (i.e. call `unmount` on the returned node or one of its * ancestors). * * 🪝 This hook adds 2 to the hook offset. */ declare function useView(view: (parentNode: ParentNode) => () => void, deps: readonly any[]): ChildNode; type UseVisibilityOptions = { root?: Element | ElementProxy | Document | null; rootMargin?: string; threshold?: number | number[]; onChange?: (visible: boolean, entry: IntersectionObserverEntry) => void; }; declare function useVisibility(target: HTMLOrSVGElement | ElementProxy, options?: UseVisibilityOptions, deps?: readonly any[]): ReadonlyRef<boolean>; type Yield = VarArgs<DisposablePromise<any> | Promise<any> | (() => void) | Falsy>; declare function useYieldingEffect(effect: () => Generator<any, EffectResult, Yield>, deps: readonly any[]): void; /** * Replace the children of the given `parent` node with the given `node`. * * ⚠️ You must use this in place of equivalent DOM methods, or else components * won't know when to run their side effects. */ declare function mount(parent: ParentNode, node: Node): void; /** * Append the given `node` to the end of the given `parent` node. * * ⚠️ You must use this in place of equivalent DOM methods, or else components * won't know when to run their side effects. */ declare function mountLastChild(parent: ParentNode, node: Node): void; /** * Insert the given `node` at the beginning of the given `parent` node. * * ⚠️ You must use this in place of equivalent DOM methods, or else components * won't know when to run their side effects. */ declare function mountFirstChild(parent: ParentNode, node: Node): void; /** * Insert the given `node` before the given `sibling` node. * * ⚠️ You must use this in place of equivalent DOM methods, or else components * won't know when to run their side effects. */ declare function mountBeforeNode(sibling: ChildNode, node: Node): void; /** * Insert the given `node` after the given `sibling` node. * * ⚠️ You must use this in place of equivalent DOM methods, or else components * won't know when to run their side effects. */ declare function mountAfterNode(sibling: ChildNode, node: Node): void; /** * Replace the given `oldNode` with the given `newNode`. * * ⚠️ You must use this in place of equivalent DOM methods, or else components won't know when to run their side effects. */ declare function mountReplacementNode(oldNode: ChildNode, newNode: Node): void; /** * Declare a template node, which can be used as a JSX element type. The JSX * runtime will use `cloneNode(true)` on the template. */ declare function template<T extends HTMLTagName | SVGTagName>(template: HTMLOrSVGElement): FunctionComponent<JSX.InferProps<T>>; /** * Any JSX element created outside of a component must be removed from the DOM * with this function if you don't plan to reuse it. If you only want to reuse * some or all of its descendants, be sure to remove those descendants (with * `node.remove()` not this method) before calling this. */ declare function unmount(node: ChildNode | DocumentFragment | null | undefined, skipRemove?: boolean, keepComponent?: AlienComponent | null): void; interface ArrayViewProps<T> extends ArrayViewOptions<T> { array: ArrayRef<T>; children: ArrayViewRenderFn<T>; /** * By default, the array items are re-rendered only if the `children` function * is changed. For explicit control of the re-rendering, you can provide a * `deps` array. */ deps?: readonly any[]; } declare function ArrayView<T>({ array, children: render, deps, ...options }: ArrayViewProps<T>): HTMLElement | null; interface ShadowRootProps extends ShadowRootInit { children: JSX.ChildrenProp; } declare function ShadowRoot(props: ShadowRootProps): JSX.Element; type TransitionData<Id> = { id: Id; element: JSX.Element; relatedId: Id | undefined; }; type TransitionDependency = PromiseLike<any> & { stop(): void; }; type TransitionAnimation = SpringAnimation<JSX.Element> | SpringAnimation<JSX.Element>[] | TransitionDependency; type TransitionProp<Id, Data = {}> = ((data: TransitionData<Id> & Data) => TransitionAnimation | Falsy) | TransitionAnimation | Falsy; type TransitionProps<Id> = { /** The unique identifier for the current entered element. */ id: Id; beforeEnter?: (data: TransitionData<Id> & { initial: boolean; }) => Promisable<any>; initial?: AnimatedProps<JSX.Element> | boolean; enter?: TransitionProp<Id, { initial: boolean; }>; leave?: TransitionProp<Id>; leaveClass?: JSX.HTMLClassProp; /** The element to be animated can be selected from the direct child. */ selector?: string; children: JSX.ChildrenProp; }; declare function Transition<Id>(props: TransitionProps<Id>): HTMLElement; declare const attachRef: (props: object, key: keyof any, ref: ReadonlyRef, didSet?: ((key: keyof any, newValue: any, oldValue: any) => void) | undefined) => ReadonlyRef<any>; /** * Attaches refs to an object. * * The `refs` object can override or extend the keys of `object`. The property * values of `refs` must be either an observable ref or undefined. */ declare const attachRefs: <T extends object, R extends object & { [K in keyof T]?: ReadonlyRef<T[K]> | undefined; }>(object: T, refs: R & Record<string, ReadonlyRef<unknown> | undefined>, didSet?: ((key: string, newValue: any, oldValue: any) => void) | undefined) => T & { [K_1 in Exclude<keyof R, keyof T>]: Unref<R[K_1]>; }; type Id<T> = T; /** * The return type of `attachRefs`. */ type AttachRefs<T extends object, R extends Record<string, ReadonlyRef | undefined> & { [K in keyof T]?: ReadonlyRef<T[K]>; }> = Id<T & { [K in Exclude<keyof R, keyof T>]: Unref<R[K]>; }>; /** * Returns `true` when the two dependency arrays have differing values, * according to `Object.is()`. * * ⚠️ If either argument is `undefined`, then `true` is returned. Even if both * are undefined. */ declare function depsHaveChanged(deps: readonly any[] | undefined, prevDeps: readonly any[] | undefined): boolean; declare function editClassList(ref: Ref<JSX.HTMLClassProp>, editor: (classList: DOMTokenList) => void): void; /** * If no element key was explicitly defined by user code and the compiler * couldn't assign a statically defined key, then the element's JSX position is * used, which might also be undefined if the element was added to the DOM * through a native DOM API. */ declare function getElementIdentity(element: object): JSX.ElementKey | undefined; /** * This is the exact same function used by JSX components to resolve their * return value into a single DOM node and apply updates across renders. */ declare function morphRootNode(rootNode: ChildNode | DocumentFragment | null, newRootNode: UnresolvedChild, rootKey: JSX.ElementKey | undefined, context?: ContextStore, nodeStore?: NodeStore | null): ChildNode | DocumentFragment; /** * Return a flat array of keys and values from an object, sorted by key, to be * used as a dependency array. Properties with an undefined value are skipped, * so that they're identical to omitted properties. */ declare function objectToDeps(object: object): any[]; /** * A decorator for class fields that makes the field observable. */ declare function observable<This, Value>(target: undefined, field: ClassFieldDecoratorContext<This, Value>): (this: This, value: Value) => Value; /** * A decorator for class getters that makes the getter observable. When * observed, the getter is only called when a dependency is changed. */ declare function observable<This, Return>(target: () => Return, field: ClassGetterDecoratorContext<This, Return>): (this: This) => Return; /** * A decorator for classes that makes every property observable. * * It also adds a `bind` method to the class, which can be used to bind a * property to a JSX attribute. To expose this in TypeScript, you need to extend * your class with this interface: * * import { Ref } from 'alien-dom' * interface MyClass { * bind<K extends keyof this>(key: K): Ref<this[K]> * } */ declare function observable<Class extends abstract new (...args: any) => any>(target: Class, context: ClassDecoratorContext<Class>): typeof target; /** * Like `observe` but with a `target` argument that can be retargeted later. */ declare const observeAs: <T extends void | object>(target: T, action: (target: T) => void) => Disposable<AlienBoundEffect<T, [action: (target: T) => void], boolean>>; interface ComponentNode<Props extends object = any> { get tag(): FunctionComponent<Props>; get props(): Readonly<Props>; get rootNode(): ChildNode | DocumentFragment; get firstChild(): ChildNode; get firstElementChild(): JSX.Element | null; get lastChild(): ChildNode; get lastElementChild(): JSX.Element | null; get childNodes(): readonly ChildNode[]; get ownerDocument(): Document | null; /** * Update the value of the given props. It's a partial update, so any props * not defined in `newProps` are left unchanged. Any object props are replaced * by any new object, rather than being merged. */ patchProps(newProps: Partial<Props>): void; /** * Same as `updateProps`, but any props which are not defined in `newProps` * are set to undefined. */ replaceProps(newProps: Props): void; } /** * Similar to rendering a component with JSX, but you get a `ComponentNode` * back, which keeps a reference to the root node of the component instance, * even if it gets replaced. */ declare function renderComponent<Props extends object = {}>(tag: FunctionComponent<Props>, initialProps?: Props): ComponentNode<Props>; /** * Restore a previous HTML element within a component's node references, so a * JSX element using the same key will be reuse the DOM node instead of * generating a new one. * * This function is meant to support JSX updates of DOM nodes that are removed * from or moved within the DOM tree, and then subsequently re-added to it. */ declare function restoreNodeReferences(node: ChildNode | DocumentFragment): void; declare function toElements<Element extends HTMLOrSVGElement>(node: Exclude<JSX.ElementLike, AlienNode | ChildrenFragment>): Element[]; declare function isNode(val: any): val is Node | ChildNode | ParentNode; type PossibleNode = object & { nodeType?: number; }; declare function isElement(node: PossibleNode): node is HTMLOrSVGElement; declare function isFragment(node: PossibleNode): node is DocumentFragment; declare function isTextNode(node: PossibleNode): node is Text; declare function isComment(node: PossibleNode): node is Comment; declare function isDocument(node: PossibleNode): node is Document; /** * ⚠️ This returns true for functions due to the possibility of element * thunking. */ declare function isJSXChild(value: any): value is JSX.Element | DocumentFragment | Comment; /** * Channels are strongly typed event buses. * * When an element is passed as the first argument, the channel will only send * messages to receivers that are bound to that element or to one of its * ancestors. * * The `Data` type must be a plain object. Use the `{}` type to represent a * message with no custom metadata. */ type Channel<Data extends object = Record<string, any>, Target extends object | void = any> = Channel.Signature<Data, Target> & Channel.FunctionTuple<Data, Target>; declare namespace Channel { interface Message<T extends Signature = Signature, Target extends InferTarget<T> = InferTarget<T>> { readonly target?: Target; currentTarget?: InferTarget<T>; stopPropagation(): void; stopImmediatePropagation(): void; } /** * A message that is sent to the target and its ancestors. This propagation * can be interrupted by `stopPropagation` or `stopImmediatePropagation`. */ interface BubblingMessage<T extends Signature = Signature, Target extends InferTarget<T> = InferTarget<T>> extends Message<T, Target> { readonly target: Target; currentTarget: InferTarget<T>; } /** A receiver is a function that receives messages from a channel. */ type Receiver<T extends Signature = Signature, Target extends InferTarget<T> | void = InferTarget<T>> = (message: (Target extends void ? Message<T, InferTarget<T>> : BubblingMessage<T, InferTarget<T>>) & InferData<T>, connection: Connection<Target>) => boolean | void; /** The signature of a channel. */ interface Signature<Data extends object = Record<string, any>, Target extends object | void = any> extends Send<Signature<Data, Target>>, Connect<Signature<Data, Target>> { } /** * Every channel returned by `defineChannel` can be divided into two functions * (`send` and `connect`) via array destructuring. */ type FunctionTuple<Data extends object = Record<string, any>, Target extends object | void = any> = [ send: Send<Signature<Data, Target>>, connect: Connect<Signature<Data, Target>> ]; /** The function that sends a message to a channel. */ type Send<T extends Signature = Signature> = { <Target extends InferTarget<T>>(target: Target, message: VoidIfEmpty<InferData<T>>): boolean; (message: VoidIfEmpty<InferData<T>>): boolean; }; /** The function that connects a receiver to a channel. */ type Connect<T extends Signature = Signature> = { <Target extends InferTarget<T>>(target: Target, receiver: Receiver<T>): Connection<Target>; (receiver: Receiver<Signature<InferData<T>, void>>): Connection<void>; }; /** A disposable connection of a receiver to a channel. */ type Connection<Target extends object | void = any> = Disposable<AlienBoundEffect<Target>>; } type InferData<T extends Channel.Signature> = T extends Channel.Signature<infer Data> ? Data : never; type InferTarget<T extends Channel.Signature> = T extends Channel.Signature<any, infer Target> ? Target : never; type VoidIfEmpty<Data extends object> = Data extends any ? ({} extends Data ? void : never) | ({} extends Required<Data> ? never : Data) : never; /** * Channels are strongly typed event buses. * * When an element is passed as the first argument, the channel will only send * messages to receivers that are bound to that element or to one of its * ancestors. * * The `Data` type must be a plain object. Use the `{}` type to represent a * message with no custom metadata. */ declare function defineChannel<Data extends object = {}, Target extends object = Node>({ isTarget, bubblingKey, }?: { isTarget?(node: any): node is Target; bubblingKey?: Extract<keyof Target, string> | false; }): Channel<Data, Target>; type Fn = (...args: any[]) => any; type FnPropertyOf<T extends object> = { [K in keyof T]: T[K] extends Fn ? K : never; }[keyof T]; declare class Controller<State extends object = any, Key = any> { protected singleton: boolean; protected instances: Map<any, any> | undefined; constructor(singleton?: boolean); exists(key: Key): boolean; /** * Set the entire state of an instance. Any properties not provided will be * set to `undefined`. */ set(arg1: [Key] extends [void] ? State : Key, arg2: [Key] extends [void] ? void : State): void; /** * Patch the state of an instance. Any properties not provided will be left * unchanged. */ patch(arg1: [Key] extends [void] ? Partial<State> : Key, arg2: [Key] extends [void] ? void : Partial<State>): void; protected call<P extends FnPropertyOf<State>>(key: Key, method: P, ...args: Parameters<Extract<State[P], Fn>>): ReturnType<Extract<State[P], Fn>>; } type ControllerProxy<State extends object, Key> = unknown & Controller<State, Key> & { [P in FnPropertyOf<State>]-?: (...args: Parameters<Extract<State[P], Fn>>) => ReturnType<Extract<State[P], Fn>>; }; declare function defineController<State extends object>(singleton: true): ControllerProxy<State, void>; declare function defineController<Key, State extends object>(singleton?: false): ControllerProxy<State, Key>; /** * Create the instance of a singleton controller. */ declare function useController<State extends object, Params extends any[]>(ctrl: Controller<State, void>, init: new (...params: Params) => State, ...params: Params): Observable<State>; /** * Create an instance of a controller for the given `key`. */ declare function useController<Key, State extends object, Params extends any[]>(ctrl: Controller<State, Key>, key: Key, init: new (...params: Params) => State, ...params: Params): Observable<State>; /** * Create the instance of a singleton controller. */ declare function useController<State extends object, Params extends any[]>(ctrl: Controller<State, void>, init: (...params: Params) => State, ...params: Params): Observable<State>; /** * Create an instance of a controller for the given `key`. */ declare function useController<Key, State extends object, Params extends any[]>(ctrl: Controller<State, Key>, key: Key, init: (...params: Params) => State, ...params: Params): Observable<State>; type NodeCallback = (node: ChildNode) => void; declare function matchDescendants<E extends Element>(target: Node, selector: string, effect: (node: E) => void): Disposable<AlienBoundEffect<Node, [callback: NodeCallback], boolean>>; declare function observeNewChildren(target: Node, listener: (childNode: ChildNode) => void): Disposable<AlienBoundEffect<Node, [callback: NodeCallback], boolean>>; declare function observeRemovedChildren(target: Node, listener: (childNode: ChildNode) => void): Disposable<AlienBoundEffect<Node, [callback: NodeCallback], boolean>>; declare const observeNewDescendants: AlienEffectType<[target: Node, callback: NodeCallback]>; declare const observeRemovedDescendants: AlienEffectType<[target: Node, callback: NodeCallback]>; /** * Runs the effect when the given target is mounted, then stops * observing the document. */ declare const onMount: (target: ChildNode, effect: () => void, rootNode?: Node) => Disposable<AlienBoundEffect<ChildNode, [key: "onAdded" | "onRemoved", effect: () => void, rootNode: Node], boolean>>; /** * Runs the effect when the given target is unmounted, then stops * observing the document. */ declare const onUnmount: (target: ChildNode, effect: () => void, rootNode?: Node) => Disposable<AlienBoundEffect<ChildNode, [key: "onAdded" | "onRemoved", effect: () => void, rootNode: Node], boolean>>; declare function patchAttributes<T extends HTMLOrSVGElement>(context: T, attributes: JSX.InferAttributes<T>): void; declare function hasClass(context: HTMLElement | SVGSVGElement, className: string): boolean; declare function addClass(context: HTMLElement | SVGSVGElement, classes: string | string[]): void; declare function removeClass(context: HTMLElement | SVGSVGElement, classes: string | string[]):