UNPKG

@zag-js/core

Version:

A minimal implementation of xstate fsm for UI machines

236 lines (234 loc) • 9.28 kB
type Dict = Record<string, any>; interface ComputedParams<T extends Dict> { context: BindableContext<T>; event: EventType<T["event"]>; prop: PropFn<T>; refs: BindableRefs<T>; scope: Scope; computed: ComputedFn<T>; } interface ContextParams<T extends Dict> { prop: PropFn<T>; bindable: BindableFn; scope: Scope; getContext: () => BindableContext<T>; getComputed: () => ComputedFn<T>; getRefs: () => BindableRefs<T>; getEvent: () => EventType<T["event"]>; flush: (fn: VoidFunction) => void; } interface PropFn<T extends Dict> { <K extends keyof T["props"]>(key: K): T["props"][K]; } interface ComputedFn<T extends Dict> { <K extends keyof T["computed"]>(key: K): T["computed"][K]; } type AnyFunction = () => string | number | boolean | null | undefined; type TrackFn = (deps: AnyFunction[], fn: VoidFunction) => void; interface BindableParams<T> { defaultValue?: T | undefined; value?: T | undefined; hash?: ((a: T) => string) | undefined; isEqual?: ((a: T, b: T | undefined) => boolean) | undefined; onChange?: ((value: T, prev: T | undefined) => void) | undefined; debug?: string | undefined; sync?: boolean | undefined; } type ValueOrFn<T> = T | ((prev: T) => T); interface Bindable<T> { initial: T | undefined; ref: any; get: () => T; set(value: ValueOrFn<T>): void; invoke(nextValue: T, prevValue: T): void; hash(value: T): string; } interface BindableRefs<T extends Dict> { set<K extends keyof T["refs"]>(key: K, value: T["refs"][K]): void; get<K extends keyof T["refs"]>(key: K): T["refs"][K]; } interface BindableContext<T extends Dict> { set<K extends keyof T["context"]>(key: K, value: ValueOrFn<T["context"][K]>): void; get<K extends keyof T["context"]>(key: K): T["context"][K]; initial<K extends keyof T["context"]>(key: K): T["context"][K]; hash<K extends keyof T["context"]>(key: K): string; } interface BindableRef<T> { get: () => T; set: (next: T) => void; } interface BindableFn { <K>(params: () => BindableParams<K>): Bindable<K>; cleanup: (fn: VoidFunction) => void; ref: <T>(defaultValue: T) => BindableRef<T>; } interface Scope { id?: string | undefined; ids?: Record<string, any> | undefined; getRootNode: () => ShadowRoot | Document | Element; getById: <T extends Element = HTMLElement>(id: string) => T | null; getActiveElement: () => HTMLElement | null; isActiveElement: (elem: HTMLElement | null) => boolean; getDoc: () => typeof document; getWin: () => typeof window; } type EventType<T = any> = T & { previousEvent?: (T & { [key: string]: any; }) | undefined; src?: string | undefined; [key: string]: any; }; type EventObject = EventType<{ type: string; }>; interface Params<T extends Dict> { prop: PropFn<T>; action: (action: T["action"][]) => void; context: BindableContext<T>; refs: BindableRefs<T>; track: TrackFn; flush: (fn: VoidFunction) => void; event: EventType<T["event"]> & { current: () => EventType<T["event"]>; previous: () => EventType<T["event"]>; }; send: (event: EventType<T["event"]>) => void; computed: ComputedFn<T>; scope: Scope; state: Bindable<T["state"]> & { matches: (...values: T["state"][]) => boolean; hasTag: (tag: T["tag"]) => boolean; }; choose: ChooseFn<T>; guard: (key: T["guard"] | GuardFn<T>) => boolean | undefined; } type GuardFn<T extends Dict> = (params: Params<T>) => boolean; type TopLevelState<S extends string> = S extends `${infer Top}.${string}` ? Top : S; type ChildStateKey<S extends string, Parent extends string> = S extends `${Parent}.${infer Rest}` ? Rest extends `${infer Child}.${string}` ? Child : Rest : never; type ParentPath<S extends string> = S extends `${infer Parent}.${string}` ? Parent : never; type AncestorPaths<S extends string> = S | (ParentPath<S> extends never ? never : AncestorPaths<ParentPath<S>>); type StateIdTarget = `#${string}`; type SiblingStateTarget<S extends string, Source extends string> = TopLevelState<S> | ChildStateKey<S, Exclude<AncestorPaths<Source>, Source>>; type ChildStateTarget<S extends string, Source extends string> = `.${ChildStateKey<S, Source>}`; interface Transition<T extends Dict, Source extends string | undefined = string | undefined> { target?: T["state"] | StateIdTarget | (Source extends string ? SiblingStateTarget<T["state"], Source> : never) | (Source extends string ? ChildStateTarget<T["state"], Source> : never) | undefined; actions?: T["action"][] | undefined; guard?: T["guard"] | GuardFn<T> | undefined; reenter?: boolean | undefined; } type TransitionSet<T extends Dict> = Transition<T> | Transition<T>[] | undefined; type TransitionMap<T extends Dict> = Record<string, TransitionSet<T>>; type TransitionMatch<T extends Dict> = { transitions: TransitionSet<T>; source: string | undefined; }; type MaybeArray<T> = T | T[]; type ChooseFn<T extends Dict> = (transitions: MaybeArray<Omit<Transition<T, string>, "target">> | null | undefined) => Transition<T> | undefined; interface PropsParams<T extends Dict> { props: Partial<T["props"]>; scope: Scope; } interface RefsParams<T extends Dict> { prop: PropFn<T>; context: BindableContext<T>; } type ActionsOrFn<T extends Dict> = T["action"][] | ((params: Params<T>) => T["action"][] | undefined); type EffectsOrFn<T extends Dict> = T["effect"][] | ((params: Params<T>) => T["effect"][] | undefined); interface MachineState<T extends Dict, Parent extends string = string> { id?: string | undefined; tags?: T["tag"][] | undefined; entry?: ActionsOrFn<T> | undefined; exit?: ActionsOrFn<T> | undefined; effects?: EffectsOrFn<T> | undefined; initial?: ChildStateKey<T["state"], Parent> | undefined; states?: { [K in ChildStateKey<T["state"], Parent>]?: MachineState<T, `${Parent}.${K}`>; } | undefined; on?: { [E in T["event"]["type"]]?: Transition<T, Parent> | Array<Transition<T, Parent>>; } | undefined; } interface Machine<T extends Dict> { debug?: boolean | undefined; props?: ((params: PropsParams<T>) => T["props"]) | undefined; context?: ((params: ContextParams<T>) => { [K in keyof T["context"]]: Bindable<T["context"][K]>; }) | undefined; computed?: { [K in keyof T["computed"]]: (params: ComputedParams<T>) => T["computed"][K]; } | undefined; initialState: (params: { prop: PropFn<T>; }) => T["state"]; entry?: ActionsOrFn<T> | undefined; exit?: ActionsOrFn<T> | undefined; effects?: EffectsOrFn<T> | undefined; refs?: ((params: RefsParams<T>) => T["refs"]) | undefined; watch?: ((params: Params<T>) => void) | undefined; on?: { [E in T["event"]["type"]]?: Transition<T, undefined> | Array<Transition<T, undefined>>; } | undefined; states: { [K in TopLevelState<T["state"]>]: MachineState<T, K>; }; implementations?: { guards?: { [K in T["guard"]]: (params: Params<T>) => boolean; } | undefined; actions?: { [K in T["action"]]: (params: Params<T>) => void; } | undefined; effects?: { [K in T["effect"]]: (params: Params<T>) => void | VoidFunction; } | undefined; } | undefined; } interface MachineBaseProps { id?: string | undefined; ids?: Record<string, any> | undefined; getRootNode?: (() => ShadowRoot | Document | Node) | undefined; [key: string]: any; } interface MachineSchema { props?: MachineBaseProps | undefined; context?: Record<string, any> | undefined; refs?: Record<string, any> | undefined; computed?: Record<string, any> | undefined; state?: string | undefined; tag?: string | undefined; guard?: string | undefined; action?: string | undefined; effect?: string | undefined; event?: ({ type: string; } & Dict) | undefined; } type State<T extends MachineSchema> = Bindable<T["state"]> & { hasTag: (tag: T["tag"]) => boolean; matches: (...values: T["state"][]) => boolean; }; type Service<T extends MachineSchema> = { getStatus: () => MachineStatus; state: State<T> & { matches: (...values: T["state"][]) => boolean; hasTag: (tag: T["tag"]) => boolean; }; context: BindableContext<T>; send: (event: EventType<T["event"]>) => void; prop: PropFn<T>; scope: Scope; computed: ComputedFn<T>; refs: BindableRefs<T>; event: EventType<T["event"]> & { current: () => EventType<T["event"]>; previous: () => EventType<T["event"]>; }; }; declare enum MachineStatus { NotStarted = "Not Started", Started = "Started", Stopped = "Stopped" } declare const INIT_STATE = "__init__"; export { type ActionsOrFn, type Bindable, type BindableContext, type BindableFn, type BindableParams, type BindableRefs, type ChooseFn, type ComputedFn, type EffectsOrFn, type EventObject, type GuardFn, INIT_STATE, type Machine, type MachineSchema, type MachineState, MachineStatus, type Params, type PropFn, type Scope, type Service, type Transition, type TransitionMap, type TransitionMatch, type TransitionSet, type ValueOrFn };