@menapo/machine 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ import { f as DEV } from "../instance-BM2UqeXW.js";
2
+ import { n as same } from "../source-DdFTPjID.js";
3
+ import { a as component, o as objectProps, t as jsx } from "../naming-Csj5186j.js";
4
+ import { useId, useLayoutEffect, useState } from "preact/hooks";
5
+ //#region ../glue/src/preact.ts
6
+ /**
7
+ * Preact (machine PLAN §5.5): React's shape on `preact/hooks`, which has no
8
+ * `useSyncExternalStore`: a state update when the snapshot moved, checked
9
+ * again once subscribed so a change between render and subscription is not
10
+ * lost. Side effects start in a layout effect, props are taken after each
11
+ * commit.
12
+ */
13
+ function useSource(create, props) {
14
+ const id = useId();
15
+ const [binding] = useState(() => ({
16
+ source: create(id, props),
17
+ seen: 0,
18
+ props
19
+ }));
20
+ const [, render] = useState(0);
21
+ const { source } = binding;
22
+ binding.seen = source.snapshot();
23
+ useLayoutEffect(() => {
24
+ const check = () => {
25
+ const now = source.snapshot();
26
+ if (now !== binding.seen) render(now);
27
+ };
28
+ const off = source.subscribe(check);
29
+ source.mount();
30
+ check();
31
+ return () => {
32
+ off();
33
+ source.unmount();
34
+ };
35
+ }, [source]);
36
+ useLayoutEffect(() => {
37
+ if (props && !same(props, binding.props)) source.setProps(binding.props = props);
38
+ source.commit();
39
+ });
40
+ return source;
41
+ }
42
+ //#endregion
43
+ //#region src/glue/preact.ts
44
+ /**
45
+ * `useMachine` in Preact (PLAN §4.7, §5.5): React's shape on `preact/hooks`.
46
+ * Preact takes the DOM's attribute names (`class`, `for`) and lowercases
47
+ * event names itself (`onDblClick`).
48
+ */
49
+ function useMachine(machine, props) {
50
+ if (DEV) objectProps(machine, props, "Preact");
51
+ return useSource(component(machine, jsx), props).view();
52
+ }
53
+ //#endregion
54
+ export { useMachine };
@@ -0,0 +1,4 @@
1
+ import { t as View } from "../component-DDXOyYUI.js";
2
+ //#region src/glue/react.d.ts
3
+ export declare function useMachine(machine: object, props?: object): View;
4
+ //#endregion
@@ -0,0 +1,50 @@
1
+ import { f as DEV } from "../instance-BM2UqeXW.js";
2
+ import { n as same } from "../source-DdFTPjID.js";
3
+ import { a as component, o as objectProps, r as react } from "../naming-Csj5186j.js";
4
+ import { useId, useLayoutEffect, useState, useSyncExternalStore } from "react";
5
+ //#region ../glue/src/react.ts
6
+ /**
7
+ * React (machine PLAN §5.5, spike S3): the source lives in `useState`, so a
8
+ * render React throws away (StrictMode, a concurrent render) never mutates
9
+ * a live one; `useSyncExternalStore` renders once per snapshot move and
10
+ * never tears; side effects start in a layout effect, after the DOM is
11
+ * committed, and stop on unmount (StrictMode's mount, unmount and mount
12
+ * leave one running). Props are taken after each commit, so a render that
13
+ * never commits never changes the source. No `flushSync`.
14
+ */
15
+ function useSource(create, props) {
16
+ const id = useId();
17
+ const [binding] = useState(() => {
18
+ const source = create(id, props);
19
+ return {
20
+ source,
21
+ subscribe: (listener) => source.subscribe(listener),
22
+ snapshot: () => source.snapshot(),
23
+ props
24
+ };
25
+ });
26
+ const { source } = binding;
27
+ useSyncExternalStore(binding.subscribe, binding.snapshot, binding.snapshot);
28
+ useLayoutEffect(() => {
29
+ source.mount();
30
+ return () => source.unmount();
31
+ }, [source]);
32
+ useLayoutEffect(() => {
33
+ if (props && !same(props, binding.props)) source.setProps(binding.props = props);
34
+ source.commit();
35
+ });
36
+ return source;
37
+ }
38
+ //#endregion
39
+ //#region src/glue/react.ts
40
+ /**
41
+ * `useMachine` in React: what the plugin resolves `@menapo/machine`'s
42
+ * `useMachine` to in a React module (PLAN §4.7, §5.5). Attribute names stay
43
+ * as written (`onClick`, `tabIndex`).
44
+ */
45
+ function useMachine(machine, props) {
46
+ if (DEV) objectProps(machine, props, "React");
47
+ return useSource(component(machine, react), props).view();
48
+ }
49
+ //#endregion
50
+ export { useMachine };
@@ -0,0 +1,4 @@
1
+ import { t as View } from "../component-DDXOyYUI.js";
2
+ //#region src/glue/solid.d.ts
3
+ export declare function useMachine(machine: object, props?: object | (() => object)): View;
4
+ //#endregion
@@ -0,0 +1,42 @@
1
+ import { a as component, s as viewOf, t as jsx } from "../naming-Csj5186j.js";
2
+ import { createComputed, createSignal, createUniqueId, onCleanup, onMount, untrack } from "solid-js";
3
+ //#region ../glue/src/solid.ts
4
+ /**
5
+ * Solid (machine PLAN §5.5): a signal holding the snapshot, read through
6
+ * the returned tracker, so only the computations that read it re-run, and
7
+ * Solid's own spread applies only the attributes that changed. Props given
8
+ * as a function are read in a computation; side effects start in `onMount`
9
+ * and run after each change, once Solid has updated the DOM.
10
+ */
11
+ function useSource(create, props) {
12
+ const read = typeof props === "function" ? props : void 0;
13
+ const source = create(createUniqueId(), read ? untrack(read) : props);
14
+ const [version, set] = createSignal(source.snapshot());
15
+ const commit = () => source.commit();
16
+ const off = source.subscribe(() => {
17
+ set(source.snapshot());
18
+ queueMicrotask(commit);
19
+ });
20
+ if (read) createComputed(() => {
21
+ const next = read();
22
+ untrack(() => source.setProps(next));
23
+ });
24
+ onMount(() => source.mount());
25
+ onCleanup(() => {
26
+ off();
27
+ source.unmount();
28
+ });
29
+ return [source, version];
30
+ }
31
+ //#endregion
32
+ //#region src/glue/solid.ts
33
+ /**
34
+ * `useMachine` in Solid (PLAN §4.7, §5.5). Solid takes the DOM's attribute
35
+ * names (`class`, `for`) and lowercases event names itself (`onDblClick`).
36
+ */
37
+ function useMachine(machine, props) {
38
+ const [source, track] = useSource(component(machine, jsx), props);
39
+ return viewOf(source, track);
40
+ }
41
+ //#endregion
42
+ export { useMachine };
@@ -0,0 +1,4 @@
1
+ import { t as View } from "../component-DDXOyYUI.js";
2
+ //#region src/glue/svelte.svelte.d.ts
3
+ export declare function useMachine(machine: object, props?: object | (() => object)): View;
4
+ //#endregion
@@ -0,0 +1,57 @@
1
+ import { t as nextId } from "../source-DdFTPjID.js";
2
+ import { a as component, n as lower, s as viewOf } from "../naming-Csj5186j.js";
3
+ import { onMount, tick, untrack } from "svelte";
4
+ import { createSubscriber } from "svelte/reactivity";
5
+ //#region ../glue/src/svelte.svelte.ts
6
+ /**
7
+ * Svelte 5 (machine PLAN §5.5): `createSubscriber` re-runs the effects and
8
+ * deriveds that read the tracker when the snapshot moves; props given as a
9
+ * getter are taken in `$effect.pre`, before the DOM updates. Side effects
10
+ * start in `onMount` and run after each update that follows a change.
11
+ * Svelte gives a module no id of its own, so ids come from a counter (or
12
+ * the owner's `id`, which SSR needs).
13
+ */
14
+ function useSource(create, props) {
15
+ const read = typeof props === "function" ? props : void 0;
16
+ const source = create(nextId(), read ? read() : props);
17
+ let update;
18
+ let seen = source.snapshot();
19
+ const track = createSubscriber((u) => {
20
+ update = u;
21
+ return () => update = void 0;
22
+ });
23
+ const commit = () => source.commit();
24
+ const off = source.subscribe(() => {
25
+ const now = source.snapshot();
26
+ if (now !== seen) {
27
+ seen = now;
28
+ update?.();
29
+ }
30
+ tick().then(commit);
31
+ });
32
+ if (read) $effect.pre(() => {
33
+ const next = read();
34
+ untrack(() => source.setProps(next));
35
+ });
36
+ onMount(() => {
37
+ source.mount();
38
+ return () => {
39
+ off();
40
+ source.unmount();
41
+ };
42
+ });
43
+ return [source, track];
44
+ }
45
+ //#endregion
46
+ //#region src/glue/svelte.svelte.ts
47
+ /**
48
+ * `useMachine` in Svelte 5 (PLAN §4.7, §5.5): attributes are lowercase, as
49
+ * Svelte spreads them onto elements (`onclick`, `tabindex`). A rune module,
50
+ * so Svelte compiles the adapter it carries wherever the module is.
51
+ */
52
+ function useMachine(machine, props) {
53
+ const [source, track] = useSource(component(machine, lower), props);
54
+ return viewOf(source, track);
55
+ }
56
+ //#endregion
57
+ export { useMachine };
@@ -0,0 +1,4 @@
1
+ import { t as View } from "../component-DDXOyYUI.js";
2
+ //#region src/glue/vanilla.d.ts
3
+ export declare function useMachine(machine: object, props?: object): View;
4
+ //#endregion
@@ -0,0 +1,83 @@
1
+ import { f as DEV } from "../instance-BM2UqeXW.js";
2
+ import { t as nextId } from "../source-DdFTPjID.js";
3
+ import { a as component, n as lower, o as objectProps, s as viewOf } from "../naming-Csj5186j.js";
4
+ //#region ../glue/src/vanilla.ts
5
+ /**
6
+ * No framework (machine PLAN §5.5): listeners hear when the snapshot moves,
7
+ * and deferred side effects run right after them, so they find the DOM the
8
+ * listeners updated (D13: in vanilla, right after the event). Sources mount
9
+ * on the next microtask, after the code that created them has had a chance
10
+ * to render them once, and `stop()` is the unmount plain code has none of.
11
+ * A class, so each source costs one object and one closure.
12
+ */
13
+ /** Sources waiting for the microtask that mounts them. */
14
+ let waiting;
15
+ function mountWaiting() {
16
+ const sources = waiting;
17
+ waiting = void 0;
18
+ for (const source of sources) source.mount();
19
+ }
20
+ var Vanilla = class {
21
+ source;
22
+ /** The snapshot listeners last heard; nothing is computed while none listens. */
23
+ seen = -1;
24
+ /** Copied on write: a change being told keeps the listeners it started with. */
25
+ listeners;
26
+ /** Unsubscribes from the source. */
27
+ off;
28
+ constructor(source) {
29
+ this.source = source;
30
+ this.off = source.subscribe(() => this.tell());
31
+ }
32
+ tell() {
33
+ const { source, listeners } = this;
34
+ if (listeners) {
35
+ const now = source.snapshot();
36
+ if (now !== this.seen) {
37
+ this.seen = now;
38
+ for (const listener of listeners) listener();
39
+ }
40
+ }
41
+ source.commit();
42
+ }
43
+ /** Calls `listener` after each change the snapshot shows; returns the unsubscribe. */
44
+ subscribe(listener) {
45
+ if (!this.listeners) this.seen = this.source.snapshot();
46
+ this.listeners = this.listeners ? [...this.listeners, listener] : [listener];
47
+ return () => {
48
+ this.listeners = this.listeners?.filter((l) => l !== listener);
49
+ };
50
+ }
51
+ /** What a framework does on unmount: listeners go, side effects stop, and a source not mounted yet never is. */
52
+ stop() {
53
+ this.listeners = void 0;
54
+ this.off();
55
+ const at = waiting ? waiting.indexOf(this.source) : -1;
56
+ if (at >= 0) waiting.splice(at, 1);
57
+ this.source.unmount();
58
+ }
59
+ };
60
+ function useSource(create, props) {
61
+ const source = create(nextId(), props);
62
+ if (!waiting) {
63
+ waiting = [];
64
+ queueMicrotask(mountWaiting);
65
+ }
66
+ waiting.push(source);
67
+ return new Vanilla(source);
68
+ }
69
+ //#endregion
70
+ //#region src/glue/vanilla.ts
71
+ /**
72
+ * `useMachine` without a framework (PLAN §4.7, §5.5): `api.subscribe`
73
+ * hears every visible change, and `spread` from `/dom` puts a part's
74
+ * attributes on its element. Attributes are lowercase, as the DOM names
75
+ * them (`onclick`, `tabindex`).
76
+ */
77
+ function useMachine(machine, props) {
78
+ if (DEV) objectProps(machine, props, "plain code");
79
+ const vanilla = useSource(component(machine, lower), props);
80
+ return viewOf(vanilla.source, void 0, vanilla);
81
+ }
82
+ //#endregion
83
+ export { useMachine };
@@ -0,0 +1,4 @@
1
+ import { t as View } from "../component-DDXOyYUI.js";
2
+ //#region src/glue/vue.d.ts
3
+ export declare function useMachine(machine: object, props?: object | (() => object)): View;
4
+ //#endregion
@@ -0,0 +1,41 @@
1
+ import { t as nextId } from "../source-DdFTPjID.js";
2
+ import { a as component, i as vue, s as viewOf } from "../naming-Csj5186j.js";
3
+ import { nextTick, onBeforeUnmount, onMounted, shallowRef, useId, watch } from "vue";
4
+ //#region ../glue/src/vue.ts
5
+ /**
6
+ * Vue 3.5 (machine PLAN §5.5): a `shallowRef` holding the snapshot, which a
7
+ * render reads through the returned tracker and which a change replaces,
8
+ * so only views that read it update. Props given as a function are watched
9
+ * before each render; side effects start once mounted and run after each
10
+ * flush that follows a change (`nextTick`, queued after Vue's own).
11
+ */
12
+ /** Returns the tracker: call it in a render or `computed` to update with the source. */
13
+ function useSource(create, props) {
14
+ const read = typeof props === "function" ? props : void 0;
15
+ const source = create(useId() ?? nextId(), read ? read() : props);
16
+ const version = shallowRef(source.snapshot());
17
+ const commit = () => source.commit();
18
+ const off = source.subscribe(() => {
19
+ version.value = source.snapshot();
20
+ nextTick(commit);
21
+ });
22
+ if (read) watch(read, (next) => source.setProps(next), { flush: "pre" });
23
+ onMounted(() => source.mount());
24
+ onBeforeUnmount(() => {
25
+ off();
26
+ source.unmount();
27
+ });
28
+ return [source, () => version.value];
29
+ }
30
+ //#endregion
31
+ //#region src/glue/vue.ts
32
+ /**
33
+ * `useMachine` in Vue (PLAN §4.7, §5.5): handlers named `onKeydown`, the
34
+ * DOM's attribute names (`../parts/naming.ts`).
35
+ */
36
+ function useMachine(machine, props) {
37
+ const [source, track] = useSource(component(machine, vue), props);
38
+ return viewOf(source, track);
39
+ }
40
+ //#endregion
41
+ export { useMachine };
@@ -0,0 +1,95 @@
1
+ import { a as provide, i as payload, r as defineMachine, s as start } from "./machine-BstWHtWL.js";
2
+ import { A as StateConfig, B as PartProps, C as OwnerProps, D as PropsOf, E as Payload, F as ViewOf, H as UseProps, I as Api, L as PartBase, M as Transitions, O as Send, P as View, R as PartConfig, V as PartsConfig, _ as InstanceOf, a as Bindable, b as MachineConfig, c as Effect, d as EventUnion, f as Guard, g as Instance, h as Implementations, i as AnyMachine, j as Transition, k as StartOptions, l as EffectResult, m as HistoryState, n as AnyEvent, o as DerivedView, p as History, s as DoneEvent, t as Action, u as EventOf, w as Parallel, x as MachineEvent, y as Machine, z as PartEvent } from "./types-Bk8svtO6.js";
3
+ import { n as inspect, t as Step } from "./inspect-C3qosuCm.js";
4
+ //#region src/core/bindable.d.ts
5
+ interface BindableOptions {
6
+ /**
7
+ * For a boolean bound to the state: the state it is `true` in and the
8
+ * state to go to when it turns `false`, as paths from the root.
9
+ */
10
+ readonly states?: {
11
+ readonly true: string;
12
+ readonly false: string;
13
+ };
14
+ /** For a value bound to data: the event the machine receives when the owner changes it. */
15
+ readonly changed?: string;
16
+ }
17
+ /**
18
+ * A controlled-or-uncontrolled prop: `open: bindable(false, { states: {
19
+ * true: "open", false: "closed" } })` gives the owner `open`, `defaultOpen`
20
+ * and `onOpenChange`; `value: bindable("")` is data that actions write as
21
+ * `props.value = next`.
22
+ */
23
+ export declare const bindable: <V>(value: V, options?: BindableOptions) => Bindable<V>;
24
+ //#endregion
25
+ //#region src/features/history.d.ts
26
+ /**
27
+ * A history pseudo-state: `resume: history()` returns to the child its
28
+ * parent was last in, `history("deep")` to the very states inside it.
29
+ */
30
+ export declare const history: (type?: "deep") => HistoryState;
31
+ //#endregion
32
+ //#region src/features/job.d.ts
33
+ /** The platform's `AbortSignal` where its types are loaded. */
34
+ type JobSignal = typeof globalThis extends {
35
+ AbortSignal: {
36
+ prototype: infer S;
37
+ };
38
+ } ? S : {
39
+ readonly aborted: boolean;
40
+ };
41
+ /** A started machine, as `start` returns it. */
42
+ interface Child {
43
+ readonly context: unknown;
44
+ readonly done: PromiseLike<void>;
45
+ stop(): void;
46
+ }
47
+ /** What `run` may return: a promise, a started child machine, a cleanup, or nothing. */
48
+ type Work = PromiseLike<unknown> | Child | (() => void) | void | undefined;
49
+ /** What `done` sends as `data`: a promise's value, a child machine's context. */
50
+ type JobData<R> = R extends PromiseLike<infer T> ? T : R extends Child ? R["context"] : never;
51
+ /** The events of `All` whose payload has `key`: `SAVED: payload<{ data: Draft }>()` for `"data"`. */
52
+ type Carrying<All extends AnyEvent, Key extends string> = { [K in All["type"]]: Key extends keyof Extract<All, {
53
+ type: K;
54
+ }> ? K : never; }[All["type"]];
55
+ /** What event `D` of `All` carries as `data`. */
56
+ type DataOf<All extends AnyEvent, D> = Extract<All, {
57
+ type: D;
58
+ }> extends {
59
+ readonly data: infer T;
60
+ } ? T : never;
61
+ /**
62
+ * The cleanup, or, when `done`'s event cannot carry what the work produces,
63
+ * the fix: an effect may not return a string, so the message is the error.
64
+ */
65
+ type JobCleanup<All extends AnyEvent, R, D> = [D] extends [never] ? () => void : [JobData<R>] extends [DataOf<All, D>] ? () => void : `${D & string} cannot carry what the job's work returns: declare it payload<{ data: T }>() with T its result`;
66
+ /** The events that may carry a job's outcome back: `done` takes `{ data }`, `error` `{ error }`. */
67
+ interface JobEvents<D extends string = string, X extends string = string> {
68
+ /** Sent with `{ data }` when the work is done. */
69
+ readonly done?: D;
70
+ /** Sent with `{ error }` when a promise rejects. */
71
+ readonly error?: X;
72
+ }
73
+ /**
74
+ * Starts `run(signal)` for the state whose effect calls it and returns the
75
+ * cleanup that cancels it. `view` is the effect's view; `done` and
76
+ * `error` name events the machine declares.
77
+ */
78
+ export declare function job<All extends AnyEvent, R extends Work, const D extends Carrying<All, "data"> = never, const X extends Carrying<All, "error"> = never>(view: {
79
+ readonly send: Send<All>;
80
+ }, run: (signal: JobSignal) => R, events?: JobEvents<D, X>): JobCleanup<All, R, D>;
81
+ //#endregion
82
+ //#region src/features/parallel.d.ts
83
+ /** Marks a state whose regions are all active at once: `editor: { type: parallel, states: { … } }`. */
84
+ export declare const parallel: Parallel;
85
+ //#endregion
86
+ //#region src/parts/use.d.ts
87
+ /**
88
+ * Runs `machine` in a component: `api.parts.<part>` spreads onto each
89
+ * element, `api.state`, `api.is`, `api.send`, `api.context` and what
90
+ * `expose` returns read and drive it. Vue, Svelte and Solid also take
91
+ * `props` as a function, read reactively.
92
+ */
93
+ export declare function useMachine<M extends AnyMachine>(machine: M, props?: UseProps<M> | (() => UseProps<M>)): Api<M>;
94
+ //#endregion
95
+ export { type Action, type AnyEvent, type AnyMachine, type Api, type Bindable, type BindableOptions, type DerivedView, type DoneEvent, type Effect, type EffectResult, type EventOf, type EventUnion, type Guard, type History, type HistoryState, type Implementations, type Instance, type InstanceOf, type JobCleanup, type JobData, type JobEvents, type JobSignal, type Machine, type MachineConfig, type MachineEvent, type OwnerProps, type Parallel, type PartBase, type PartConfig, type PartEvent, type PartProps, type PartsConfig, type Payload, type PropsOf, type Send, type StartOptions, type StateConfig, type Step, type Transition, type Transitions, type UseProps, type View, type ViewOf, type Work, defineMachine, inspect, payload, provide, start };