Skip to content

Instantly share code, notes, and snippets.

@kaze
Last active September 3, 2020 13:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaze/86b601bcc01bc03c6d4c75f322b561c8 to your computer and use it in GitHub Desktop.
Save kaze/86b601bcc01bc03c6d4c75f322b561c8 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const validate = async () => null;
// validation helpers ------------------------------------------------------ //
const should_validate = (context) => {
return (context.value &&
((context.leaving && context.validate) ||
(!context.leaving && context.validated))
)
};
const check = async (context) => {
if (should_validate(context)) {
let validated = true;
let valid = true;
let errors = null;
let result = await validate(context.value, context.validators);
if (result && result.length > 0) {
errors = result;
valid = false;
}
return { valid, validated, errors };
}
return {};
};
// machine actions --------------------------------------------------- //
const update_value = assign({ value: (context, event) => event.data });
const update_validation_results = assign((context, event) => event.data);
const set_leaving = assign({ leaving: true });
const unset_leaving = assign({ leaving: false });
// machine parts ----------------------------------------------------- //
const validatable = {
id: 'validatable',
initial: 'checking',
states: {
checking: {
invoke: {
src: 'check',
onDone: {
actions: ['update_validation_results'],
target: 'selection',
},
},
},
selection: {
on: {
'': [{
target: '#input.idle',
cond: 'should_leave',
},
{
target: 'invalid',
cond: 'is_invalid',
},
{
target: 'valid',
cond: 'is_valid',
}],
}
},
invalid: {
on: {
change: {
actions: ['update_value'],
target: 'checking',
},
blur: {
actions: ['set_leaving'],
target: 'checking',
},
},
},
valid: {
on: {
change: {
actions: ['update_value'],
target: 'checking',
},
blur: {
actions: ['set_leaving'],
target: 'checking',
},
},
},
},
};
const fillable = {
id: 'fillable',
initial: 'empty',
states: {
empty: {
always: {
target: 'filled',
cond: 'has_value',
},
on: {
change: {
target: 'filled',
},
},
},
filled: {
on: {
change: {
target: 'empty',
cond: 'is_empty',
},
},
...validatable,
},
hist: {
type: 'history',
history: 'deep',
target: 'empty',
},
},
};
const input_machine = Machine(
{
id: 'input',
initial: 'idle',
context: {
value: null,
valid: true,
validate: false,
validated: false,
validators: {},
errors: null,
options: {
id: null,
name: null,
label: null,
field_type: null,
disabled: false,
required: false,
},
// utility states for the machine
leaving: false,
},
states: {
idle: {
on: {
focus: {
actions: ['unset_leaving'],
target: 'focused.hist'
},
},
},
focused: {
...fillable,
},
},
},
{
actions: {
update_value,
update_validation_results,
set_leaving,
unset_leaving,
},
guards: {
is_empty: context => context.value === null,
has_value: context => context.value !== null,
is_valid: context => context.valid === true && context.errors === null,
is_invalid: context => context.valid === false || !context.errors !== null,
should_leave: context => context.leaving === true,
},
services: {
check,
}
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment