@zag-js/solid
Version:
The solid.js wrapper for zag
276 lines (274 loc) • 8.93 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/machine.ts
var machine_exports = {};
__export(machine_exports, {
useMachine: () => useMachine
});
module.exports = __toCommonJS(machine_exports);
var import_core = require("@zag-js/core");
var import_utils = require("@zag-js/utils");
var import_solid_js = require("solid-js");
var import_bindable = require("./bindable.js");
var import_refs = require("./refs.js");
var import_track = require("./track.js");
function useMachine(machine, userProps = {}) {
const scope = (0, import_solid_js.createMemo)(() => {
const { id, ids, getRootNode } = access(userProps);
return (0, import_core.createScope)({ id, ids, getRootNode });
});
const debug = (...args) => {
if (machine.debug) console.log(...args);
};
const props = (0, import_solid_js.createMemo)(
() => machine.props?.({
props: (0, import_utils.compact)(access(userProps)),
scope: scope()
}) ?? access(userProps)
);
const prop = createProp(props);
const context = machine.context?.({
prop,
bindable: import_bindable.createBindable,
get scope() {
return scope();
},
flush,
getContext() {
return ctx;
},
getComputed() {
return computed;
},
getRefs() {
return refs;
},
getEvent() {
return getEvent();
}
});
const ctx = {
get(key) {
return context?.[key].get();
},
set(key, value) {
context?.[key].set(value);
},
initial(key) {
return context?.[key].initial;
},
hash(key) {
const current = context?.[key].get();
return context?.[key].hash(current);
}
};
const effects = { current: /* @__PURE__ */ new Map() };
const transitionRef = { current: null };
const previousEventRef = { current: null };
const eventRef = { current: { type: "" } };
const getEvent = () => (0, import_solid_js.mergeProps)(eventRef.current, {
current() {
return eventRef.current;
},
previous() {
return previousEventRef.current;
}
});
const getState = () => (0, import_solid_js.mergeProps)(state, {
matches(...values) {
const current = state.get();
return values.some((value) => (0, import_core.matchesState)(current, value));
},
hasTag(tag) {
const current = state.get();
return (0, import_core.hasTag)(machine, current, tag);
}
});
const refs = (0, import_refs.createRefs)(machine.refs?.({ prop, context: ctx }) ?? {});
const getParams = () => ({
state: getState(),
context: ctx,
event: getEvent(),
prop,
send,
action,
guard,
track: import_track.createTrack,
refs,
computed,
flush,
get scope() {
return scope();
},
choose
});
const action = (keys) => {
const strs = (0, import_utils.isFunction)(keys) ? keys(getParams()) : keys;
if (!strs) return;
const fns = strs.map((s) => {
const fn = machine.implementations?.actions?.[s];
if (!fn) (0, import_utils.warn)(`[zag-js] No implementation found for action "${JSON.stringify(s)}"`);
return fn;
});
for (const fn of fns) {
fn?.(getParams());
}
};
const guard = (str) => {
if ((0, import_utils.isFunction)(str)) return str(getParams());
const fn = machine.implementations?.guards?.[str];
if (!fn) (0, import_utils.warn)(`[zag-js] No implementation found for guard "${JSON.stringify(str)}"`);
return fn?.(getParams());
};
const effect = (keys) => {
const strs = (0, import_utils.isFunction)(keys) ? keys(getParams()) : keys;
if (!strs) return;
const fns = strs.map((s) => {
const fn = machine.implementations?.effects?.[s];
if (!fn) (0, import_utils.warn)(`[zag-js] No implementation found for effect "${JSON.stringify(s)}"`);
return fn;
});
const cleanups = [];
for (const fn of fns) {
const cleanup = fn?.(getParams());
if (cleanup) cleanups.push(cleanup);
}
return () => cleanups.forEach((fn) => fn?.());
};
const choose = (transitions) => {
return (0, import_utils.toArray)(transitions).find((t) => {
let result = !t.guard;
if ((0, import_utils.isString)(t.guard)) result = !!guard(t.guard);
else if ((0, import_utils.isFunction)(t.guard)) result = t.guard(getParams());
return result;
});
};
const computed = (key) => {
(0, import_utils.ensure)(machine.computed, () => `[zag-js] No computed object found on machine`);
const fn = machine.computed[key];
return fn({
context: ctx,
event: eventRef.current,
prop,
refs,
scope: scope(),
computed
});
};
const state = (0, import_bindable.createBindable)(() => ({
defaultValue: (0, import_core.resolveStateValue)(machine, machine.initialState({ prop })),
onChange(nextState, prevState) {
const { exiting, entering } = (0, import_core.getExitEnterStates)(machine, prevState, nextState, transitionRef.current?.reenter);
exiting.forEach((item) => {
const exitEffects = effects.current.get(item.path);
exitEffects?.();
effects.current.delete(item.path);
});
exiting.forEach((item) => {
action(item.state?.exit);
});
action(transitionRef.current?.actions);
entering.forEach((item) => {
const cleanup = effect(item.state?.effects);
if (cleanup) {
const existing = effects.current.get(item.path);
effects.current.set(item.path, existing ? (0, import_utils.callAll)(existing, cleanup) : cleanup);
}
});
if (prevState === import_core.INIT_STATE) {
action(machine.entry);
const cleanup = effect(machine.effects);
if (cleanup) {
const existing = effects.current.get(import_core.INIT_STATE);
effects.current.set(import_core.INIT_STATE, existing ? (0, import_utils.callAll)(existing, cleanup) : cleanup);
}
}
entering.forEach((item) => {
action(item.state?.entry);
});
}
}));
let status = import_core.MachineStatus.NotStarted;
(0, import_solid_js.onMount)(() => {
const started = status === import_core.MachineStatus.Started;
status = import_core.MachineStatus.Started;
debug(started ? "rehydrating..." : "initializing...");
state.invoke(state.initial, import_core.INIT_STATE);
});
(0, import_solid_js.onCleanup)(() => {
debug("unmounting...");
status = import_core.MachineStatus.Stopped;
const fns = effects.current;
fns.forEach((fn) => fn?.());
effects.current = /* @__PURE__ */ new Map();
transitionRef.current = null;
action(machine.exit);
});
const send = (event) => {
queueMicrotask(() => {
if (status !== import_core.MachineStatus.Started) return;
previousEventRef.current = eventRef.current;
eventRef.current = event;
let currentState = (0, import_solid_js.untrack)(() => state.get());
const { transitions, source } = (0, import_core.findTransition)(machine, currentState, event.type);
const transition = choose(transitions);
if (!transition) return;
transitionRef.current = transition;
const target = (0, import_core.resolveStateValue)(machine, transition.target ?? currentState, source);
debug("transition", event.type, transition.target || currentState, `(${transition.actions})`);
const changed = target !== currentState;
if (changed) {
state.set(target);
} else if (transition.reenter) {
state.invoke(currentState, currentState);
} else {
action(transition.actions);
}
});
};
machine.watch?.(getParams());
return {
state: getState(),
send,
context: ctx,
prop,
get scope() {
return scope();
},
refs,
computed,
event: getEvent(),
getStatus: () => status
};
}
function flush(fn) {
fn();
}
function access(value) {
return (0, import_utils.isFunction)(value) ? value() : value;
}
function createProp(value) {
return function get(key) {
return value()[key];
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
useMachine
});