JSFiddle - React, Tailwind, and code Playground

by amindunited

JavaScript

class StateMachine {

	static DEBUG = false;

  constructor() {
    this.states = {};
    this.currentState = null;
  }

  addState(name, config) {
    this.states[name] = config;
  }

  setState(name) {
    if (!this.states[name]) {
      console.error(`State "${name}" not found.`);
      return;
    }

    if (this.currentState && this.states[this.currentState].onExit) {
      this.states[this.currentState].onExit();
    }

    this.currentState = name;

    if (this.states[name].onEnter) {
      this.states[name].onEnter();
    }
  }

  trigger(event) {
    if (!this.currentState) {
      console.error('No initial state set.');
      return;
    }

    const transition = this.states[this.currentState].transitions[event];

    if (!transition) {
      console.error(`No transition for event "${event}" in state "${this.currentState}".`);
      return;
    }

    this.setState(transition);
  }
}

// Example Usage:

const myStateMachine = new StateMachine();

myStateMachine.addState('idle', {
  onEnter: () => console.log('Entering Idle State'),
  onExit: () => console.log('Exiting Idle State'),
  transitions: {
    start: 'active',
  },
});

myStateMachine.addState('active', {
  onEnter: () => console.log('Entering Active State'),
  onExit: () => console.log('Exiting Active State'),
  transitions: {
    pause: 'paused',
    stop: 'idle',
  },
});

myStateMachine.addState('paused', {
  onEnter: () => console.log('Entering Paused State'),
  onExit: () => console.log('Exiting Paused State'),
  transitions: {
    resume: 'active',
    stop: 'idle',
  },
});

// Set the initial state
myStateMachine.setState('idle');

// Trigger some transitions
myStateMachine.trigger('start'); // Enters "active" state
myStateMachine.trigger('pause'); // Enters "paused" state
myStateMachine.trigger('resume'); // Enters "active" state
myStateMachine.trigger('stop'); // Enters "idle" state