🤖 Robot

Fast 1kB functional library for creating Finite State Machines

# lit-robot

Table of Contents

The lit-robot package provides a class mixin, Robot, that adds state machines to element classes. This allows controlling the internal state of your element using the state machine.

import { createMachine, state, transition } from 'robot3';
import { LitElement, html } from 'lit-element';
import { Robot } from 'lit-robot';

const machine = createMachine({
off: state(
transition('toggle', 'on')
),
on: state(
transition('toggle', 'off')
)
});

class App extends Robot(LitElement) {
static machine = machine;

render() {
let { send } = this.service;
let current = this.machine.state;

return html`
<div>State: ${current.name}</div>
<button @click=${() => send('toggle')}>
Toggle
</button>
`
;
}
}

customElements.define('my-app', component(App));

# Installation

Available as lit-robot on npm:

npm install lit-robot --save

Or through Yarn:

yarn add lit-robot

# API

# Robot

Robot(BaseElement)

The Robot export from lit-robot (ie, import { Robot } from 'lit-robot';) is a function that takes a base class to apply its mixin on top of. LitElement must be part of the chain, lit-robot does not without LitElement.

import { LitElement } from 'lit-element';
import { Robot } from 'lit-robot';

const RobotElement = Robot(LitElement);

# static machine

static machine = machine;

Sets the static machine property on the element. This is the state machine that will be used as part of the element's lifecycle. It can be passed in like so:

const appMachine = createMachine({
one: state()
});

class MyApp extends Robot(LitElement) {
static machine = appMachine;
}

# machine

this.machine

Inside of the element instance there will be a this.machine property that is the extended state machine being interpreted. It contains all of the same API properties as Robot state machines.

Use it inside of render(), for example, to get the current state name:

render() {
let current = this.machine.state;

return html`
<div>State: ${current.name}</div>
`
;
}

# service

this.service

The state machine service created via interpret. This is used to send events into the state machine to cause transitions, actions to run, etc.

render() {
let { send } = this.service;

return html`
<button @click=${() => send('toggle')}>
Toggle
</button>
`
;
}

# Setting the element on context

Some times you might want to perform side-effects on the element instance within a state machine. The best way to do that is to have the element on the context object. The context function receives an event that contains an element property. Use that to establish your initial context.

Once the element is on your context you can use actions to perform side-effects.

import { createMachine, action, state, transition } from 'robot3';
import { Robot } from 'lit-robot';
import { LitElement } from 'lit-element';

const context = initialContext => ({
element: initialContext.element
});

const machine = createMachine({
idle: state(
transition('next-page',
action((ctx, ev) => {
ctx.element.setAttribute('page', ev.page);
})
)
)
}, context);

class MyApp extends Robot(LitElement) {
static machine = machine;
}

customElements.define('my-app', MyApp);

# License

BSD 2-Clause