diff --git a/core/index.ts b/core/index.ts new file mode 100644 index 0000000..ecdfd6a --- /dev/null +++ b/core/index.ts @@ -0,0 +1,9 @@ +export type { + Observable, + Observer, + Subscription, + RatyStore, + RatyStoreOptions, +} from "./store" +export { create } from "./store" +export * as Raty from './store' \ No newline at end of file diff --git a/core/store.ts b/core/store.ts new file mode 100644 index 0000000..4b16d98 --- /dev/null +++ b/core/store.ts @@ -0,0 +1,64 @@ +export interface Observable { + subscribe(observer: Observer): Subscription +} + +export interface Observer { + (value: A): void +} + +export interface Subscription { + unsubscribe(): void +} + +export interface RatyStore extends Observable { + get(): number + set(value: number): void + set(modifier: ()=> number): void + cancel(): void +} + +export interface RatyStoreOptions { + value: (() => number) | number +} + +export function create(options: RatyStoreOptions): RatyStore { + const initialValue = typeof options.value === 'function' ? options.value() : options.value + let value = initialValue + + const listeners = new Set>() + + const notify = () => { + for (const listener of listeners) { + listener(value) + } + } + + const set = (fa: (() => number) | number) => { + const newValue = typeof fa === 'function' ? fa() : value + + if (newValue !== value) { + value = newValue + + notify() + } + } + + const get = () => value + + const subscribe = (observer: Observer): Subscription => { + listeners.add(observer) + + return { + unsubscribe: () => listeners.delete(observer) + } + } + + const cancel = () => set(initialValue) + + return { + get, + set, + subscribe, + cancel, + } +} \ No newline at end of file