Skip to content

Instantly share code, notes, and snippets.

@zerobias
Created June 18, 2019 11:01
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 zerobias/0521b5a0e450ad7bdd40950a731c5e53 to your computer and use it in GitHub Desktop.
Save zerobias/0521b5a0e450ad7bdd40950a731c5e53 to your computer and use it in GitHub Desktop.
import {createEvent, createStore, Event, forward, Store} from 'effector'
export class Iteration<T> {
index: number
item: T
list: T[]
constructor(index: number, item: T, list: T[]) {
this.index = index
this.item = item
this.list = list
}
}
export function storeList<T>({
list,
handler,
}: {
handler?: (item: T) => any
list?: Store<T[]>
} = {}): Event<void> & {
installStore: Event<Store<T[]>>
trigger: Event<void>
start: Event<T[]>
end: Event<T[]>
step: Event<Iteration<T>>
item: Event<T>
} {
const {start, end, step, item} = eventList<T>()
const trigger = createEvent<void>()
const noop = createStore<T[]>([])
const installStore = createEvent<Store<T[]>>()
const installedStore = createStore({
store: noop,
dispose: noop.watch(trigger, list => {
start(list)
}),
})
installedStore.on(installStore, (state, store) => {
if (state.store === store) return state
state.dispose()
return {
store,
dispose: store.watch(trigger, list => {
start(list)
}),
}
})
if (list) {
installStore(list)
}
if (handler) {
item.watch(handler)
}
const result = trigger as any
result.installStore = installStore
result.trigger = trigger
result.start = start
result.end = end
result.step = step
result.item = item
return result
}
export function eventList<T>() {
const start = createEvent<T[]>()
const end = createEvent<T[]>()
const step = createEvent<Iteration<T>>()
const item = step.map(step => step.item)
const nonEmptyList = start.filter({
fn: list => list.length > 0,
})
forward({
from: nonEmptyList.map(list => new Iteration(0, list[0], list)),
to: step,
})
forward({
from: step.filter(({index, list}) => {
if (index + 1 < list.length)
return new Iteration(index + 1, list[index + 1], list)
}),
to: step,
})
forward({
from: step.filter(({index, list}) => {
if (index + 1 === list.length) return list
}),
to: end,
})
forward({
from: start.filter({
fn: list => list.length === 0,
}),
to: end,
})
return {
start,
end,
step,
item,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment