Files
headlessui/packages/@headlessui-react/src/utils/store.ts
T
Jordan Pittman 2f99644ed7 Don't break overflow when multiple dialogs are open at the same time (#2215)
* Fix overflow when swapping dialogs that use transition

* Refactor

* refactor

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Inline shim for ESM support

Until the official package adds an ESM version with a wildcard import we can’t use it. This version was copied from Remix Router

* Add dialog shadow root examples

* Fix SSR error

* Add repro for iOS scrolling issue

* Try to fix vercel build

idk what’s wrong here

* Update repro

A transition is required to delay closing enough to demonstrate the bug

* Port global dialog state to Vue

* Add dialog test to Vue

* wip

* wip

* Workaround bug

This shouldn’t happen at all and we need to find the source of the bug but this should “fix” things for the time being

* wip

* Rebuild overflow locking with simpler API

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update deps

* wip

* simplify

* Port to Vue

* wip

* wip

* Tweak tests

* Update changelog

* Ensure meta callbacks are cleaned up

* cleanup

* wip
2023-02-01 16:08:34 -05:00

40 lines
959 B
TypeScript

type ChangeFn = () => void
type UnsubscribeFn = () => void
type ActionFn<T> = (this: T, ...args: any[]) => T | void
type StoreActions<Key extends string, T> = Record<Key, ActionFn<T>>
export interface Store<T, ActionKey extends string> {
getSnapshot(): T
subscribe(onChange: ChangeFn): UnsubscribeFn
dispatch(action: ActionKey, ...args: any[]): void
}
export function createStore<T, ActionKey extends string>(
initial: () => T,
actions: StoreActions<ActionKey, T>
): Store<T, ActionKey> {
let state: T = initial()
let listeners = new Set<ChangeFn>()
return {
getSnapshot() {
return state
},
subscribe(onChange) {
listeners.add(onChange)
return () => listeners.delete(onChange)
},
dispatch(key: ActionKey, ...args: any[]) {
let newState = actions[key].call(state, ...args)
if (newState) {
state = newState
listeners.forEach((listener) => listener())
}
},
}
}