Skip to content

Instantly share code, notes, and snippets.

@christianhg
Last active June 21, 2021 11:29
Show Gist options
  • Save christianhg/505aee91664e951505979965dab9e364 to your computer and use it in GitHub Desktop.
Save christianhg/505aee91664e951505979965dab9e364 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const combobox = Machine({
id: 'combobox',
initial: 'enabled',
context: {
pointer: 0,
query: '',
results: []
},
states: {
disabled: {
on: {
ENABLE: {
target: 'enabled'
}
}
},
enabled: {
type: 'parallel',
on: {
DISABLE: {
target: 'disabled'
}
},
states: {
searchInput: {
initial: 'unfocused',
states: {
unfocused: {
on: {
FOCUS: {
target: 'focused'
}
}
},
focused: {
on: {
BLUR: {
target: 'unfocused'
}
}
}
}
},
searchList: {
initial: 'closed',
states: {
closed: {
on: {
FOCUS: {
target: 'opened'
}
}
},
opened: {
initial: 'idle',
on: {
QUERY_CHANGED: {
target: '.idle',
actions: ['updateQuery', 'updateResults']
},
BLUR: {
target: 'closed'
}
},
entry: ['resetPointer'],
states: {
idle: {
on: {
'': [
{
cond: 'hasResults',
target: 'hasResults'
},
{
cond: 'noResults',
target: 'noResults'
}
],
DOWN: {
target: 'focusingFooter'
},
}
},
focusingFooter: {
on: {
ENTER: {
actions: ['selectFooter', send('BLUR')]
}
}
},
noResults: {
initial: 'idle',
states: {
idle: {
on: {
DOWN: {
target: 'focusingFooter'
}
}
},
focusingFooter: {
on: {
ENTER: {
actions: ['selectFooter', send('BLUR')]
}
}
}
}
},
hasResults: {
initial: 'idle',
on: {
HOVER_RESULT: {
target: '.browsingList',
actions: ['setPointer']
}
},
states: {
idle: {
on: {
DOWN: {
target: 'browsingList'
}
}
},
browsingList: {
on: {
ENTER: {
actions: ['selectPointedItem', send('BLUR')]
},
UP: [
{
cond: 'firstResult',
target: 'browsingList'
},
{
actions: ['movePointerUp']
}
],
DOWN: [
{
cond: 'lastResult',
target: 'focusingFooter'
},
{
actions: 'movePointerDown'
}],
HOVER_FOOTER: {
target: 'focusingFooter'
}
}
},
focusingFooter: {
on: {
UP: {
target: 'browsingList'
},
ENTER: {
actions: ['selectFooter', send('BLUR')]
}
}
}
}
},
}
}
}
}
}
}
}
},
{
actions: {
resetPointer: assign({
pointer: 0
}),
pointAtTheTop: assign({
pointer: 0
}),
pointAtTheBottom: assign({
pointer: (context) => context.results.length - 1
}),
setPointer: assign({
pointer: (context, event) => event.pointer
}),
movePointerDown: assign({
pointer: (context) => context.pointer + 1
}),
movePointerUp: assign({
pointer: (context) => context.pointer - 1
}),
selectPointedItem: (context) => {
console.log(`Select ${context.results[context.pointer]}`)
},
selectFooter: () => {
console.log('Select footer')
},
updateQuery: assign({
query: (context, event) => event.query
}),
updateResults: assign({
results: (context, event) => event.results
})
},
guards: {
firstResult: (context) => context.pointer === 0,
lastResult: (context) =>context.results && context.results.length - 1 === context.pointer,
hasResults: (context) => context.results.length > 0,
noResults: (context) => context.query.length > 0 && context.results.length === 0,
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment