@xstate/store
Advanced tools
Comparing version 3.0.1 to 3.1.0
export { shallowEqual } from "./shallowEqual.js"; | ||
export { fromStore } from "./fromStore.js"; | ||
export { createStore, createStoreWithProducer } from "./store.js"; | ||
export { createStore, createStoreWithProducer, createStoreConfig } from "./store.js"; | ||
export * from "./types.js"; |
@@ -1,2 +0,2 @@ | ||
import { SnapshotFromStore, AnyStore } from "./types.js"; | ||
import { SnapshotFromStore, AnyStore, StoreContext, EventPayloadMap, StoreConfig, Store, ExtractEvents } from "./types.js"; | ||
/** | ||
@@ -24,1 +24,5 @@ * A React hook that subscribes to the `store` and selects a value from the | ||
export declare function useSelector<TStore extends AnyStore, T>(store: TStore, selector: (snapshot: SnapshotFromStore<TStore>) => T, compare?: (a: T | undefined, b: T) => boolean): T; | ||
export declare const useStore: { | ||
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmitted>>; | ||
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmitted>>; | ||
}; |
@@ -1,2 +0,2 @@ | ||
import { EnqueueObject, EventObject, EventPayloadMap, ExtractEvents, Store, StoreAssigner, StoreContext, StoreEffect, StoreSnapshot } from "./types.js"; | ||
import { EnqueueObject, EventObject, EventPayloadMap, ExtractEvents, Store, StoreAssigner, StoreContext, StoreConfig, StoreEffect, StoreSnapshot } from "./types.js"; | ||
export type TransitionsFromEventPayloadMap<TEventPayloadMap extends EventPayloadMap, TContext extends StoreContext, TEmitted extends EventObject> = { | ||
@@ -7,20 +7,44 @@ [K in keyof TEventPayloadMap & string]: StoreAssigner<TContext, { | ||
}; | ||
type CreateStoreParameterTypes<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = [ | ||
definition: { | ||
context: TContext; | ||
emits?: { | ||
[K in keyof TEmitted & string]: (payload: TEmitted[K]) => void; | ||
}; | ||
on: { | ||
[K in keyof TEventPayloadMap & string]: StoreAssigner<NoInfer<TContext>, { | ||
type: K; | ||
} & TEventPayloadMap[K], ExtractEvents<TEmitted>>; | ||
}; | ||
} | ||
]; | ||
type CreateStoreParameterTypes<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = [definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>]; | ||
type CreateStoreReturnType<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmitted>>; | ||
export declare const createStore: { | ||
/** | ||
* Creates a **store** that has its own internal state and can be sent events | ||
* that update its internal state based on transitions. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const store = createStore({ | ||
* context: { count: 0, name: 'Ada' }, | ||
* on: { | ||
* inc: (context, event: { by: number }) => ({ | ||
* ...context, | ||
* count: context.count + event.by | ||
* }) | ||
* } | ||
* }); | ||
* | ||
* store.subscribe((snapshot) => { | ||
* console.log(snapshot); | ||
* }); | ||
* | ||
* store.send({ type: 'inc', by: 5 }); | ||
* // Logs { context: { count: 5, name: 'Ada' }, status: 'active', ... } | ||
* ``` | ||
* | ||
* @param config - The store configuration object | ||
* @param config.context - The initial state of the store | ||
* @param config.on - An object mapping event types to transition functions | ||
* @param config.emits - An object mapping emitted event types to handlers | ||
* @returns A store instance with methods to send events and subscribe to | ||
* state changes | ||
*/ | ||
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(...args: CreateStoreParameterTypes<TContext, TEventPayloadMap, TEmitted>): CreateStoreReturnType<TContext, TEventPayloadMap, TEmitted>; | ||
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(...args: CreateStoreParameterTypes<TContext, TEventPayloadMap, TEmitted>): CreateStoreReturnType<TContext, TEventPayloadMap, TEmitted>; | ||
}; | ||
export declare const createStoreConfig: { | ||
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): StoreConfig<TContext, TEventPayloadMap, TEmitted>; | ||
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): StoreConfig<TContext, TEventPayloadMap, TEmitted>; | ||
}; | ||
/** | ||
@@ -59,2 +83,5 @@ * Creates a `Store` with a provided producer (such as Immer's `producer(…)` A | ||
}; | ||
emits?: { | ||
[K in keyof TEmittedPayloadMap & string]: (payload: TEmittedPayloadMap[K]) => void; | ||
}; | ||
}): Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmittedPayloadMap>>; | ||
@@ -61,0 +88,0 @@ declare global { |
@@ -76,2 +76,13 @@ export type EventPayloadMap = Record<string, {} | null | undefined>; | ||
} | ||
export type StoreConfig<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = { | ||
context: TContext; | ||
emits?: { | ||
[K in keyof TEmitted & string]: (payload: TEmitted[K]) => void; | ||
}; | ||
on: { | ||
[K in keyof TEventPayloadMap & string]: StoreAssigner<TContext, { | ||
type: K; | ||
} & TEventPayloadMap[K], ExtractEvents<TEmitted>>; | ||
}; | ||
}; | ||
export type IsEmptyObject<T> = T extends Record<string, never> ? true : false; | ||
@@ -78,0 +89,0 @@ export type AnyStore = Store<any, any, any>; |
@@ -5,2 +5,4 @@ 'use strict'; | ||
var store = require('./store-5c2c0abc.cjs.js'); | ||
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts | ||
@@ -30,282 +32,3 @@ function is(x, y) { | ||
const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')(); | ||
function toObserver(nextHandler, errorHandler, completionHandler) { | ||
const isObserver = typeof nextHandler === 'object'; | ||
const self = isObserver ? nextHandler : undefined; | ||
return { | ||
next: (isObserver ? nextHandler.next : nextHandler)?.bind(self), | ||
error: (isObserver ? nextHandler.error : errorHandler)?.bind(self), | ||
complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self) | ||
}; | ||
} | ||
/** | ||
* Updates a context object using a recipe function. | ||
* | ||
* @param context - The current context | ||
* @param recipe - A function that describes how to update the context | ||
* @returns The updated context | ||
*/ | ||
function setter(context, recipe) { | ||
return recipe(context); | ||
} | ||
const inspectionObservers = new WeakMap(); | ||
function createStoreCore(initialContext, transitions, producer) { | ||
let observers; | ||
let listeners; | ||
const initialSnapshot = { | ||
context: initialContext, | ||
status: 'active', | ||
output: undefined, | ||
error: undefined | ||
}; | ||
let currentSnapshot = initialSnapshot; | ||
const emit = ev => { | ||
if (!listeners) { | ||
return; | ||
} | ||
const type = ev.type; | ||
const typeListeners = listeners.get(type); | ||
if (typeListeners) { | ||
typeListeners.forEach(listener => listener(ev)); | ||
} | ||
}; | ||
const transition = createStoreTransition(transitions, producer); | ||
function receive(event) { | ||
let effects; | ||
[currentSnapshot, effects] = transition(currentSnapshot, event); | ||
inspectionObservers.get(store)?.forEach(observer => { | ||
observer.next?.({ | ||
type: '@xstate.snapshot', | ||
event, | ||
snapshot: currentSnapshot, | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
}); | ||
observers?.forEach(o => o.next?.(currentSnapshot)); | ||
for (const effect of effects) { | ||
if (typeof effect === 'function') { | ||
effect(); | ||
} else { | ||
emit(effect); | ||
} | ||
} | ||
} | ||
const store = { | ||
on(emittedEventType, handler) { | ||
if (!listeners) { | ||
listeners = new Map(); | ||
} | ||
let eventListeners = listeners.get(emittedEventType); | ||
if (!eventListeners) { | ||
eventListeners = new Set(); | ||
listeners.set(emittedEventType, eventListeners); | ||
} | ||
const wrappedHandler = handler.bind(undefined); | ||
eventListeners.add(wrappedHandler); | ||
return { | ||
unsubscribe() { | ||
eventListeners.delete(wrappedHandler); | ||
} | ||
}; | ||
}, | ||
sessionId: uniqueId(), | ||
send(event) { | ||
inspectionObservers.get(store)?.forEach(observer => { | ||
observer.next?.({ | ||
type: '@xstate.event', | ||
event, | ||
sourceRef: undefined, | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
}); | ||
receive(event); | ||
}, | ||
getSnapshot() { | ||
return currentSnapshot; | ||
}, | ||
getInitialSnapshot() { | ||
return initialSnapshot; | ||
}, | ||
subscribe(observerOrFn) { | ||
const observer = toObserver(observerOrFn); | ||
observers ??= new Set(); | ||
observers.add(observer); | ||
return { | ||
unsubscribe() { | ||
return observers?.delete(observer); | ||
} | ||
}; | ||
}, | ||
[symbolObservable]() { | ||
return this; | ||
}, | ||
inspect: observerOrFn => { | ||
const observer = toObserver(observerOrFn); | ||
inspectionObservers.set(store, inspectionObservers.get(store) ?? new Set()); | ||
inspectionObservers.get(store).add(observer); | ||
observer.next?.({ | ||
type: '@xstate.actor', | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
observer.next?.({ | ||
type: '@xstate.snapshot', | ||
snapshot: initialSnapshot, | ||
event: { | ||
type: '@xstate.init' | ||
}, | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
return { | ||
unsubscribe() { | ||
return inspectionObservers.get(store)?.delete(observer); | ||
} | ||
}; | ||
}, | ||
trigger: new Proxy({}, { | ||
get: (_, eventType) => { | ||
return payload => { | ||
store.send({ | ||
type: eventType, | ||
...payload | ||
}); | ||
}; | ||
} | ||
}) | ||
}; | ||
return store; | ||
} | ||
/** | ||
* Creates a **store** that has its own internal state and can be sent events | ||
* that update its internal state based on transitions. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const store = createStore({ | ||
* context: { count: 0 }, | ||
* on: { | ||
* inc: (context, event: { by: number }) => ({ | ||
* count: context.count + event.by | ||
* }) | ||
* } | ||
* }); | ||
* | ||
* store.subscribe((snapshot) => { | ||
* console.log(snapshot); | ||
* }); | ||
* | ||
* store.send({ type: 'inc', by: 5 }); | ||
* // Logs { context: { count: 5 }, status: 'active', ... } | ||
* ``` | ||
* | ||
* @param config - The store configuration object | ||
* @param config.context - The initial state of the store | ||
* @param config.on - An object mapping event types to transition functions | ||
* @returns A store instance with methods to send events and subscribe to state | ||
* changes | ||
*/ | ||
function _createStore(...[{ | ||
context, | ||
on | ||
}]) { | ||
return createStoreCore(context, on); | ||
} | ||
const createStore = _createStore; | ||
/** | ||
* Creates a `Store` with a provided producer (such as Immer's `producer(…)` A | ||
* store has its own internal state and can receive events. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* import { produce } from 'immer'; | ||
* | ||
* const store = createStoreWithProducer(produce, { | ||
* context: { count: 0 }, | ||
* on: { | ||
* inc: (context, event: { by: number }) => { | ||
* context.count += event.by; | ||
* } | ||
* } | ||
* }); | ||
* | ||
* store.subscribe((snapshot) => { | ||
* console.log(snapshot); | ||
* }); | ||
* | ||
* store.send({ type: 'inc', by: 5 }); | ||
* // Logs { context: { count: 5 }, status: 'active', ... } | ||
* ``` | ||
*/ | ||
function createStoreWithProducer(producer, config) { | ||
return createStoreCore(config.context, config.on, producer); | ||
} | ||
/** | ||
* Creates a store transition function that handles state updates based on | ||
* events. | ||
* | ||
* @param transitions - An object mapping event types to transition functions | ||
* @param producer - Optional producer function (e.g., Immer's produce) for | ||
* immutable updates | ||
* @returns A transition function that takes a snapshot and event and returns a | ||
* new snapshot with effects | ||
*/ | ||
function createStoreTransition(transitions, producer) { | ||
return (snapshot, event) => { | ||
let currentContext = snapshot.context; | ||
const assigner = transitions?.[event.type]; | ||
const effects = []; | ||
const enqueue = { | ||
emit: new Proxy({}, { | ||
get: (_, eventType) => { | ||
return payload => { | ||
effects.push({ | ||
...payload, | ||
type: eventType | ||
}); | ||
}; | ||
} | ||
}), | ||
effect: fn => { | ||
effects.push(fn); | ||
} | ||
}; | ||
if (!assigner) { | ||
return [snapshot, effects]; | ||
} | ||
if (typeof assigner === 'function') { | ||
currentContext = producer ? producer(currentContext, draftContext => assigner(draftContext, event, enqueue)) : setter(currentContext, draftContext => Object.assign({}, currentContext, assigner?.(draftContext, event, | ||
// TODO: help me | ||
enqueue))); | ||
} else { | ||
const partialUpdate = {}; | ||
for (const key of Object.keys(assigner)) { | ||
const propAssignment = assigner[key]; | ||
partialUpdate[key] = typeof propAssignment === 'function' ? propAssignment(currentContext, event, enqueue) : propAssignment; | ||
} | ||
currentContext = Object.assign({}, currentContext, partialUpdate); | ||
} | ||
return [{ | ||
...snapshot, | ||
context: currentContext | ||
}, effects]; | ||
}; | ||
} | ||
/** | ||
* Generates a unique 6-character identifier. | ||
* | ||
* @returns A random string identifier | ||
*/ | ||
function uniqueId() { | ||
return Math.random().toString(36).slice(6); | ||
} | ||
/** | ||
* An actor logic creator which creates store [actor | ||
@@ -324,3 +47,3 @@ * logic](https://stately.ai/docs/actors#actor-logic) for use with XState. | ||
const transitionsObj = config.on; | ||
const transition = createStoreTransition(transitionsObj); | ||
const transition = store.createStoreTransition(transitionsObj); | ||
return { | ||
@@ -351,5 +74,6 @@ transition: (snapshot, event, actorScope) => { | ||
exports.createStore = createStore; | ||
exports.createStoreWithProducer = createStoreWithProducer; | ||
exports.createStore = store.createStore; | ||
exports.createStoreConfig = store.createStoreConfig; | ||
exports.createStoreWithProducer = store.createStoreWithProducer; | ||
exports.fromStore = fromStore; | ||
exports.shallowEqual = shallowEqual; |
@@ -0,1 +1,4 @@ | ||
import { c as createStoreTransition } from './store-d1bc1e92.esm.js'; | ||
export { a as createStore, d as createStoreConfig, b as createStoreWithProducer } from './store-d1bc1e92.esm.js'; | ||
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts | ||
@@ -25,282 +28,3 @@ function is(x, y) { | ||
const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')(); | ||
function toObserver(nextHandler, errorHandler, completionHandler) { | ||
const isObserver = typeof nextHandler === 'object'; | ||
const self = isObserver ? nextHandler : undefined; | ||
return { | ||
next: (isObserver ? nextHandler.next : nextHandler)?.bind(self), | ||
error: (isObserver ? nextHandler.error : errorHandler)?.bind(self), | ||
complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self) | ||
}; | ||
} | ||
/** | ||
* Updates a context object using a recipe function. | ||
* | ||
* @param context - The current context | ||
* @param recipe - A function that describes how to update the context | ||
* @returns The updated context | ||
*/ | ||
function setter(context, recipe) { | ||
return recipe(context); | ||
} | ||
const inspectionObservers = new WeakMap(); | ||
function createStoreCore(initialContext, transitions, producer) { | ||
let observers; | ||
let listeners; | ||
const initialSnapshot = { | ||
context: initialContext, | ||
status: 'active', | ||
output: undefined, | ||
error: undefined | ||
}; | ||
let currentSnapshot = initialSnapshot; | ||
const emit = ev => { | ||
if (!listeners) { | ||
return; | ||
} | ||
const type = ev.type; | ||
const typeListeners = listeners.get(type); | ||
if (typeListeners) { | ||
typeListeners.forEach(listener => listener(ev)); | ||
} | ||
}; | ||
const transition = createStoreTransition(transitions, producer); | ||
function receive(event) { | ||
let effects; | ||
[currentSnapshot, effects] = transition(currentSnapshot, event); | ||
inspectionObservers.get(store)?.forEach(observer => { | ||
observer.next?.({ | ||
type: '@xstate.snapshot', | ||
event, | ||
snapshot: currentSnapshot, | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
}); | ||
observers?.forEach(o => o.next?.(currentSnapshot)); | ||
for (const effect of effects) { | ||
if (typeof effect === 'function') { | ||
effect(); | ||
} else { | ||
emit(effect); | ||
} | ||
} | ||
} | ||
const store = { | ||
on(emittedEventType, handler) { | ||
if (!listeners) { | ||
listeners = new Map(); | ||
} | ||
let eventListeners = listeners.get(emittedEventType); | ||
if (!eventListeners) { | ||
eventListeners = new Set(); | ||
listeners.set(emittedEventType, eventListeners); | ||
} | ||
const wrappedHandler = handler.bind(undefined); | ||
eventListeners.add(wrappedHandler); | ||
return { | ||
unsubscribe() { | ||
eventListeners.delete(wrappedHandler); | ||
} | ||
}; | ||
}, | ||
sessionId: uniqueId(), | ||
send(event) { | ||
inspectionObservers.get(store)?.forEach(observer => { | ||
observer.next?.({ | ||
type: '@xstate.event', | ||
event, | ||
sourceRef: undefined, | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
}); | ||
receive(event); | ||
}, | ||
getSnapshot() { | ||
return currentSnapshot; | ||
}, | ||
getInitialSnapshot() { | ||
return initialSnapshot; | ||
}, | ||
subscribe(observerOrFn) { | ||
const observer = toObserver(observerOrFn); | ||
observers ??= new Set(); | ||
observers.add(observer); | ||
return { | ||
unsubscribe() { | ||
return observers?.delete(observer); | ||
} | ||
}; | ||
}, | ||
[symbolObservable]() { | ||
return this; | ||
}, | ||
inspect: observerOrFn => { | ||
const observer = toObserver(observerOrFn); | ||
inspectionObservers.set(store, inspectionObservers.get(store) ?? new Set()); | ||
inspectionObservers.get(store).add(observer); | ||
observer.next?.({ | ||
type: '@xstate.actor', | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
observer.next?.({ | ||
type: '@xstate.snapshot', | ||
snapshot: initialSnapshot, | ||
event: { | ||
type: '@xstate.init' | ||
}, | ||
actorRef: store, | ||
rootId: store.sessionId | ||
}); | ||
return { | ||
unsubscribe() { | ||
return inspectionObservers.get(store)?.delete(observer); | ||
} | ||
}; | ||
}, | ||
trigger: new Proxy({}, { | ||
get: (_, eventType) => { | ||
return payload => { | ||
store.send({ | ||
type: eventType, | ||
...payload | ||
}); | ||
}; | ||
} | ||
}) | ||
}; | ||
return store; | ||
} | ||
/** | ||
* Creates a **store** that has its own internal state and can be sent events | ||
* that update its internal state based on transitions. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const store = createStore({ | ||
* context: { count: 0 }, | ||
* on: { | ||
* inc: (context, event: { by: number }) => ({ | ||
* count: context.count + event.by | ||
* }) | ||
* } | ||
* }); | ||
* | ||
* store.subscribe((snapshot) => { | ||
* console.log(snapshot); | ||
* }); | ||
* | ||
* store.send({ type: 'inc', by: 5 }); | ||
* // Logs { context: { count: 5 }, status: 'active', ... } | ||
* ``` | ||
* | ||
* @param config - The store configuration object | ||
* @param config.context - The initial state of the store | ||
* @param config.on - An object mapping event types to transition functions | ||
* @returns A store instance with methods to send events and subscribe to state | ||
* changes | ||
*/ | ||
function _createStore(...[{ | ||
context, | ||
on | ||
}]) { | ||
return createStoreCore(context, on); | ||
} | ||
const createStore = _createStore; | ||
/** | ||
* Creates a `Store` with a provided producer (such as Immer's `producer(…)` A | ||
* store has its own internal state and can receive events. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* import { produce } from 'immer'; | ||
* | ||
* const store = createStoreWithProducer(produce, { | ||
* context: { count: 0 }, | ||
* on: { | ||
* inc: (context, event: { by: number }) => { | ||
* context.count += event.by; | ||
* } | ||
* } | ||
* }); | ||
* | ||
* store.subscribe((snapshot) => { | ||
* console.log(snapshot); | ||
* }); | ||
* | ||
* store.send({ type: 'inc', by: 5 }); | ||
* // Logs { context: { count: 5 }, status: 'active', ... } | ||
* ``` | ||
*/ | ||
function createStoreWithProducer(producer, config) { | ||
return createStoreCore(config.context, config.on, producer); | ||
} | ||
/** | ||
* Creates a store transition function that handles state updates based on | ||
* events. | ||
* | ||
* @param transitions - An object mapping event types to transition functions | ||
* @param producer - Optional producer function (e.g., Immer's produce) for | ||
* immutable updates | ||
* @returns A transition function that takes a snapshot and event and returns a | ||
* new snapshot with effects | ||
*/ | ||
function createStoreTransition(transitions, producer) { | ||
return (snapshot, event) => { | ||
let currentContext = snapshot.context; | ||
const assigner = transitions?.[event.type]; | ||
const effects = []; | ||
const enqueue = { | ||
emit: new Proxy({}, { | ||
get: (_, eventType) => { | ||
return payload => { | ||
effects.push({ | ||
...payload, | ||
type: eventType | ||
}); | ||
}; | ||
} | ||
}), | ||
effect: fn => { | ||
effects.push(fn); | ||
} | ||
}; | ||
if (!assigner) { | ||
return [snapshot, effects]; | ||
} | ||
if (typeof assigner === 'function') { | ||
currentContext = producer ? producer(currentContext, draftContext => assigner(draftContext, event, enqueue)) : setter(currentContext, draftContext => Object.assign({}, currentContext, assigner?.(draftContext, event, | ||
// TODO: help me | ||
enqueue))); | ||
} else { | ||
const partialUpdate = {}; | ||
for (const key of Object.keys(assigner)) { | ||
const propAssignment = assigner[key]; | ||
partialUpdate[key] = typeof propAssignment === 'function' ? propAssignment(currentContext, event, enqueue) : propAssignment; | ||
} | ||
currentContext = Object.assign({}, currentContext, partialUpdate); | ||
} | ||
return [{ | ||
...snapshot, | ||
context: currentContext | ||
}, effects]; | ||
}; | ||
} | ||
/** | ||
* Generates a unique 6-character identifier. | ||
* | ||
* @returns A random string identifier | ||
*/ | ||
function uniqueId() { | ||
return Math.random().toString(36).slice(6); | ||
} | ||
/** | ||
* An actor logic creator which creates store [actor | ||
@@ -345,2 +69,2 @@ * logic](https://stately.ai/docs/actors#actor-logic) for use with XState. | ||
export { createStore, createStoreWithProducer, fromStore, shallowEqual }; | ||
export { fromStore, shallowEqual }; |
{ | ||
"name": "@xstate/store", | ||
"version": "3.0.1", | ||
"version": "3.1.0", | ||
"description": "Simple stores", | ||
@@ -67,4 +67,4 @@ "keywords": [ | ||
"solid-testing-library": "^0.3.0", | ||
"@xstate/vue": "^4.0.2", | ||
"@xstate/react": "^5.0.2", | ||
"@xstate/vue": "^4.0.2", | ||
"xstate": "^5.19.2" | ||
@@ -71,0 +71,0 @@ }, |
@@ -6,2 +6,3 @@ 'use strict'; | ||
var react = require('react'); | ||
var store = require('../../dist/store-5c2c0abc.cjs.js'); | ||
@@ -44,3 +45,11 @@ function defaultCompare(a, b) { | ||
} | ||
const useStore = function useStoreImpl(definition) { | ||
const storeRef = react.useRef(); | ||
if (!storeRef.current) { | ||
storeRef.current = store.createStore(definition); | ||
} | ||
return storeRef.current; | ||
}; | ||
exports.useSelector = useSelector; | ||
exports.useStore = useStore; |
import { useSyncExternalStore, useCallback, useRef } from 'react'; | ||
import { a as createStore } from '../../dist/store-d1bc1e92.esm.js'; | ||
@@ -39,3 +40,10 @@ function defaultCompare(a, b) { | ||
} | ||
const useStore = function useStoreImpl(definition) { | ||
const storeRef = useRef(); | ||
if (!storeRef.current) { | ||
storeRef.current = createStore(definition); | ||
} | ||
return storeRef.current; | ||
}; | ||
export { useSelector }; | ||
export { useSelector, useStore }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
58809
29
1389