UNPKG

mini-state-machine

Version:
114 lines (113 loc) 3.84 kB
import { find } from "./array.js"; var EventType; (function (EventType) { EventType["State"] = "s"; EventType["Transition"] = "t"; })(EventType || (EventType = {})); const EVENT_TYPE_STATE_REXP = /^(enter|leave)/; const EVENT_TYPE_TRANSITION_REXP = /^(before|after)/; function callbackToPromise(callback, options) { let output, uncaught = null; try { output = callback(options); } catch (err) { uncaught = err; output = false; } return Promise.resolve(output) .catch(err => { uncaught = err; return false; }) .then(result => { if (uncaught !== null) { setTimeout(function __throwUnhandledException() { throw uncaught; }, 0); } return result; }); } export function createEventsInterface() { const handlers = []; const idleCallbacks = []; const events = { "@@handlers": handlers, add: (event, stateOrTransition, callback, { once = false } = {}) => { handlers.push({ event, type: resolveEventType(event), value: stateOrTransition, callback, once }); return { remove: () => events.remove(event, stateOrTransition, callback) }; }, addIdle: callback => { idleCallbacks.push(callback); return { remove: () => { const ind = idleCallbacks.indexOf(callback); if (ind >= 0) { idleCallbacks.splice(ind, 1); } } }; }, emitIdle: (target) => { if (target) { return callbackToPromise(target).then(() => { }); } if (idleCallbacks.length <= 0) return Promise.resolve(); return Promise.all(idleCallbacks.map(callback => callbackToPromise(callback))).then(() => { }); }, execute: (event, stateOrTransition, options) => { const type = resolveEventType(event); const work = handlers.filter(item => item.type === type && item.event === event && (item.value === stateOrTransition || item.value === "*")); return (function doNext() { const item = work.shift(); if (!item) { return Promise.resolve(); } return callbackToPromise(item.callback, options).then(result => { if (item.once === true) { events.remove(event, stateOrTransition, item.callback); } if (result === false) { // cancel transition return false; } return doNext(); }); })(); }, remove: (event, stateOrTransition, callback) => { const type = resolveEventType(event); const handerInd = find(handlers, item => { return (item.event === event && item.type === type && (item.value === stateOrTransition || item.value === "*") && item.callback === callback); }, { index: true }); if (handerInd >= 0) { handlers.splice(handerInd, 1); } } }; return events; } function resolveEventType(event) { if (EVENT_TYPE_STATE_REXP.test(event)) { return EventType.State; } else if (EVENT_TYPE_TRANSITION_REXP.test(event)) { return EventType.Transition; } throw new Error(`Failed resolving event type: unrecognised prefix: ${event}`); }