@yoltra/react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/context/StoreContext.ts","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/cjs/react-jsx-runtime.production.js","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/cjs/react-jsx-runtime.development.js","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/jsx-runtime.js","../src/context/StoreProvider.tsx","../src/utils/path.ts","../src/hooks/hooks.ts","../src/hooks/suspense.ts","../src/hooks/createHooks.ts"],"sourcesContent":["/**\n * @module @yoltra/react\n */\n\nimport { createContext } from \"react\";\nimport type { StoreInstance } from \"@yoltra/core\";\n\n/**\n * React Context carrying a {@link StoreInstance} for yoltra React bindings.\n *\n * @remarks\n * - The default value is `null`. Consumers should either:\n * 1) Be wrapped with {@link StoreProvider}, or\n * 2) Use a helper hook that throws a friendly error when the context is `null`.\n * - You can scope multiple independent stores by nesting multiple providers.\n *\n * @example Basic usage\n * ```tsx\n * import { useContext } from \"react\";\n * import { StoreContext } from \"@yoltra/react\";\n *\n * export function Counter() {\n * const store = useContext(StoreContext);\n * if (!store) throw new Error(\"StoreProvider is missing\");\n * const state = store.getState();\n * return <span>{state.counter.value}</span>;\n * }\n * ```\n *\n * @public\n */\nexport const StoreContext = createContext<StoreInstance<any, any, any> | null>(null);","/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return (type.displayName || \"Context\") + \".Provider\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(\n type,\n key,\n self,\n source,\n owner,\n props,\n debugStack,\n debugTask\n ) {\n self = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== self ? self : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n source,\n self,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n self,\n source,\n getOwner(),\n maybeKey,\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_ELEMENT_TYPE &&\n node._store &&\n (node._store.validated = 1);\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\");\n Symbol.for(\"react.provider\");\n var REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n react_stack_bottom_frame: function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","/**\n * @module @yoltra/react\n */\n\nimport type { StoreInstance } from \"@yoltra/core\";\nimport React, { type ReactNode } from \"react\";\n\nimport { StoreContext } from \"./StoreContext\";\n\n/**\n * React provider that places a {@link StoreInstance} into {@link StoreContext}.\n *\n * @param props.store - The yoltra store instance to expose to descendant components.\n * @param props.children - React subtree that will consume the store.\n *\n * @remarks\n * - Wrap your app (or a subtree) to make the store available via `useContext(StoreContext)`\n * or any higher-level hooks you expose (e.g., `useAtomicProp`, `useEmit`).\n * - You may nest multiple `StoreProvider`s to scope different stores to different subtrees.\n * - In Next.js App Router, this component must be used in a **client** boundary.\n *\n * @example App wrapper with createHooks (recommended)\n * ```tsx\n * // store.ts\n * import { createStore, eventKeys } from '@yoltra/core';\n * import { createContext } from 'react';\n * import { createHooks, StoreProvider } from '@yoltra/react';\n *\n * type AppEM = { ui: { increment: number } };\n * type AppState = { counter: { value: number } };\n *\n * export const store = createStore<AppState, AppEM>({\n * name: 'App',\n * reducer: {\n * counter: {\n * state: { value: 0 },\n * when: { keys: eventKeys<AppEM>()([['ui', 'increment']]) },\n * reducer: (s, evt) => evt.type === 'increment'\n * ? { value: s.value + evt.payload }\n * : s,\n * },\n * },\n * });\n *\n * const AppStoreContext = createContext<typeof store | null>(null);\n * export const { useAtomicProp, useEmit } = createHooks(AppStoreContext);\n *\n * // App.tsx\n * export function App({ children }: { children: React.ReactNode }) {\n * return <StoreProvider store={store}>{children}</StoreProvider>;\n * }\n * ```\n *\n * @public\n */\nexport const StoreProvider: React.FC<{\n /** yoltra store instance placed into context. */\n store: StoreInstance<any, any, any>;\n /** Descendant subtree that can consume the store. */\n children: ReactNode;\n}> = ({ store, children }) => (\n <StoreContext.Provider value={store}>{children}</StoreContext.Provider>\n);\n","/** @internal */\nexport function hasWildcard(p: string): boolean {\n return p.includes(\"*\");\n}\n\n/** @internal */\nexport function normalizePath(p: string): string {\n return p.replace(/^\\./, \"\");\n}\n\n/** @internal */\nexport function splitPath(p: string): string[] {\n return normalizePath(p).split(\".\").filter(Boolean);\n}\n\n/**\n * Reads a dotted path from an object; returns `undefined` when a segment is missing.\n * @internal\n */\nexport function getAtPath(obj: any, path: string): any {\n if (!path) return obj;\n\n let cur = obj;\n for (const seg of splitPath(path)) {\n if (cur == null) return undefined;\n cur = cur[seg];\n }\n\n return cur;\n}\n","/**\n * @module @yoltra/react\n */\n\nimport type {\n DeepReadonly,\n Dotted,\n Emit,\n Event,\n EventMapBase,\n EventPhase,\n PathValue,\n StoreInstance,\n WithGlob,\n} from \"@yoltra/core\";\nimport { useContext, useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport { StoreContext } from \"../context/StoreContext\";\nimport { getAtPath, hasWildcard, normalizePath } from \"../utils/path\";\n\n/**\n * Re-export of {@link PathValue} from `@yoltra/core`.\n *\n * Resolves the TypeScript type at a dotted path `P` within object type `T`.\n * See the core definition for full documentation.\n *\n * @public\n */\nexport type { PathValue };\n\n/**\n * Accepts either a single value or a readonly array of that value.\n * Useful for APIs that take one-or-many keys.\n *\n * @example\n * ```ts\n * function takeIds(ids: OneOrMany<string>) { /* ... *\\/ }\n * takeIds('a');\n * takeIds(['a','b'] as const);\n * ```\n *\n * @public\n */\nexport type OneOrMany<T> = T | readonly T[];\n\n/**\n * Returns the current {@link StoreInstance} from {@link StoreContext}.\n * Throws if used outside of a `<StoreProvider>`.\n *\n * @typeParam EM - Event map type.\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n *\n * @example\n * ```tsx\n * const store = useStore<MyEM, 'counter' | 'todos', AppState>();\n * const state = store.getState();\n * ```\n *\n * @public\n */\nexport function useStore<\n EM extends EventMapBase,\n R extends string,\n S extends Record<R, any>,\n>(): StoreInstance<R, S, EM> {\n const ctx = useContext(StoreContext);\n if (!ctx) throw new Error(\"useStore must be used inside <StoreProvider>\");\n\n return ctx as StoreInstance<R, S, EM>;\n}\n\n/**\n * Returns the store's `emit` function (stable reference).\n *\n * @typeParam EM - Event map type.\n *\n * @example\n * ```tsx\n * const emit = useEmit<MyEM>();\n * await emit('ui', 'toggle', true);\n * ```\n *\n * @public\n */\nexport function useEmit<EM extends EventMapBase>(): Emit<EM> {\n return useStore<EM, any, any>().emit;\n}\n\n/**\n * Shallow object equality using `Object.is` per-key.\n *\n * Useful as the `isEqual` argument for `useAtomicProp` and `useAtomicProps`\n * when the derived value is a plain object. Also available from the object\n * returned by {@link createHooks}.\n *\n * @example\n * ```ts\n * shallowEqual({ a: 1 }, { a: 1 }); // true\n * shallowEqual({ a: 1 }, { a: 2 }); // false\n * ```\n *\n * @public\n */\nexport function shallowEqual<T extends Record<string, any>>(a: T, b: T) {\n if (Object.is(a, b)) return true;\n if (!a || !b) return false;\n\n const ka = Object.keys(a),\n kb = Object.keys(b);\n if (ka.length !== kb.length) return false;\n\n for (const k of ka) {\n if (!Object.is(a[k], (b as any)[k])) return false;\n }\n\n return true;\n}\n\n/**\n * Selects a derived value from the store using an external-store subscription.\n * Re-renders when the selected value changes per `isEqual`.\n *\n * @typeParam S - State type returned by `getState()`.\n * @typeParam T - Selected value type.\n * @param selector - `(state) => value` derived from the current state.\n * @param isEqual - Optional equality comparator (defaults to `Object.is`).\n *\n * @example\n * ```tsx\n * const total = useSelector((s: AppState) => s.todos.items.length);\n * ```\n *\n * @public\n */\nexport function useSelector<S extends Record<any, any>, T>(\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n const store = useStore<any, any, S>();\n\n const subscribe = useMemo(() => (notify: () => void) => store.subscribe(notify), [store]);\n\n const getSnapshot = useMemo(() => {\n let last = selector(store.getState() as DeepReadonly<S>);\n return () => {\n const next = selector(store.getState() as DeepReadonly<S>);\n return isEqual(last, next) ? last : (last = next);\n };\n }, [store, selector, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// Strongly-typed implementation for the common case\nfunction useAtomicPropImpl<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends Dotted<S[R1]>,\n>(spec: { reducer: R1; property: P }): PathValue<S[R1], P> {\n const store = useStore<any, R, S>();\n\n const normalizedSpec = useMemo(() => {\n const prop = normalizePath(spec.property);\n return { reducer: spec.reducer, property: prop } as const;\n }, [spec.reducer, spec.property]);\n\n const subscribe = useMemo(\n () => (notify: () => void) =>\n store.connect(\n { reducer: normalizedSpec.reducer, property: normalizedSpec.property },\n () => notify(),\n ),\n [store, normalizedSpec],\n );\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(normalizedSpec.property);\n const read = () => {\n const full = store.getState() as S;\n const slice = (full as any)[normalizedSpec.reducer];\n const source = isGlob ? slice : getAtPath(slice, normalizedSpec.property);\n return source;\n };\n\n let last = read();\n return () => {\n const next = read();\n return Object.is(last, next) ? last : (last = next);\n };\n }, [store, normalizedSpec]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot) as PathValue<S[R1], P>;\n}\n\n/** @internal */\nfunction _useAtomicPropImpl<R extends string, S extends Record<R, any>, T = any>(\n spec: { reducer: R; property: string },\n map?: (value: any) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n const store = useStore<any, R, S>();\n\n const normalizedSpec = useMemo(() => {\n const prop = normalizePath(spec.property);\n return { reducer: spec.reducer, property: prop } as const;\n }, [spec.reducer, spec.property]);\n\n const subscribe = useMemo(\n () => (notify: () => void) =>\n store.connect(\n { reducer: normalizedSpec.reducer, property: normalizedSpec.property },\n () => notify(),\n ),\n [store, normalizedSpec],\n );\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(normalizedSpec.property);\n const read = () => {\n const full = store.getState() as S;\n const slice = (full as any)[normalizedSpec.reducer];\n const source = isGlob ? slice : getAtPath(slice, normalizedSpec.property);\n return map ? map(source) : (source as unknown as T);\n };\n\n let last = read();\n return () => {\n const next = read();\n return isEqual(last, next) ? last : (last = next);\n };\n }, [store, normalizedSpec, map, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot) as any;\n}\n\n/**\n * Fine-grained **single-path** selector for a reducer's state.\n *\n * Re-renders only when the specified `reducer.property` (dotted path) actually changes.\n * For most applications, prefer using the typed version from {@link createHooks}\n * which infers all type parameters automatically.\n *\n * **Supports**\n * - Exact root prop: `{ reducer: \"todo\", property: \"data\" }`\n * - Exact deep path: `{ reducer: \"todo\", property: \"data.123.title\" }`\n * - Wildcards (pattern): `{ reducer: \"todo\", property: \"data.*\" }` or `\"data.**\"`\n *\n * **Overloads**\n * - Exact path (no `*`): returns the precise `PathValue` when `map` is omitted\n * - Exact path + `map`: returns `T` from `map(value)`\n * - Glob path (with `*`/`**`): requires `map` and returns `T` from `map(state)`\n *\n * @example Via createHooks (recommended)\n * ```tsx\n * const { useAtomicProp } = createHooks(AppStoreContext);\n *\n * function TodoTitle({ index }: { index: number }) {\n * // Types are inferred — no explicit generics needed\n * const title = useAtomicProp({\n * reducer: 'todos',\n * property: `items.${index}.title`,\n * });\n * return <span>{title}</span>;\n * }\n * ```\n *\n * @example Standalone with explicit generics\n * ```tsx\n * const title = useAtomicProp<'todos', AppState, 'todos', 'items.0.title'>(\n * { reducer: 'todos', property: 'items.0.title' }\n * );\n * ```\n *\n * @example Map over exact path\n * ```tsx\n * const len = useAtomicProp(\n * { reducer: 'todos', property: 'items' },\n * items => items.length\n * );\n * ```\n *\n * @example Glob pattern over state\n * ```tsx\n * const titles = useAtomicProp(\n * { reducer: 'todos', property: 'items.**' },\n * state => state.items.map(x => x.title),\n * shallowEqual\n * );\n * ```\n *\n * @public\n */\nexport function useAtomicProp<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends Dotted<S[R1]>,\n>(spec: { reducer: R1; property: P }): PathValue<S[R1], P>;\nexport function useAtomicProp<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends Dotted<S[R1]>,\n T,\n>(\n spec: { reducer: R1; property: P },\n map: (value: PathValue<S[R1], P>) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProp<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends WithGlob<Dotted<S[R1]>>,\n T,\n>(\n spec: { reducer: R1; property: P },\n map: (value: any) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProp<R extends string, S extends Record<R, any>>(spec: {\n reducer: R;\n property: string;\n}): unknown;\nexport function useAtomicProp<R extends string, S extends Record<R, any>, T>(\n spec: { reducer: R; property: string },\n map: (value: any) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProp<R extends string, S extends Record<R, any>, T = any>(\n spec: { reducer: R; property: string },\n map?: (value: any) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n if (!map && !hasWildcard(spec.property)) {\n return useAtomicPropImpl<R, S, any, any>(spec) as any;\n }\n return _useAtomicPropImpl<R, S, T>(spec, map, isEqual);\n}\n\n/**\n * **Multi-path** fine-grained selector.\n *\n * Subscribes to several `reducer.property` paths (supports deep & wildcard)\n * and recomputes `selector(state)` when any of them change.\n *\n * @typeParam R - Slice name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam T - Derived value type.\n *\n * @param specs - Array of `{ reducer, property }`, where `property` can be a string or array of strings. Supports `*`/`**`.\n * @param selector - `(state) => T` function run against the full state.\n * @param isEqual - Equality comparator for the derived value (defaults to `Object.is`).\n *\n * @example\n * ```tsx\n * const total = useAtomicProps<'todos' | 'filter', AppState, number>(\n * [\n * { reducer: 'todos', property: 'items.**' },\n * { reducer: 'filter', property: 'q' }\n * ],\n * (s) => s.todos.items.filter(x => x.title.includes(s.filter.q)).length\n * );\n * ```\n *\n * @public\n */\nexport function useAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{ reducer: R; property: OneOrMany<WithGlob<Dotted<S[R]>>> }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{ reducer: R; property: OneOrMany<string> }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property: OneOrMany<string> | OneOrMany<WithGlob<Dotted<S[R]>>>;\n }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n return _useAtomicPropsImpl<R, S, T>(specs as any, selector, isEqual);\n}\n\n/** @internal */\nfunction _useAtomicPropsImpl<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property: OneOrMany<string> | OneOrMany<WithGlob<Dotted<S[R]>>>;\n }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n const store = useStore<EventMapBase, R, S>();\n\n const versionRef = useRef(0);\n const lastSelRef = useRef<T | undefined>(undefined);\n const lastVerRef = useRef<number>(-1);\n\n const normalizedSpecs = useMemo(() => {\n return specs.map((sp) => ({\n reducer: sp.reducer,\n property: Array.isArray(sp.property)\n ? (sp.property as readonly string[]).map((p) => normalizePath(p as string))\n : normalizePath(sp.property as string),\n }));\n }, [JSON.stringify(specs)]);\n\n const subscribe = useMemo(\n () => (notify: () => void) => {\n const tick = () => {\n versionRef.current++;\n notify();\n };\n\n const unsubs = normalizedSpecs.flatMap((sp) => {\n const props = Array.isArray(sp.property) ? sp.property : [sp.property];\n return props.map((p) => store.connect({ reducer: sp.reducer, property: p }, tick));\n });\n\n return () => {\n for (const u of unsubs) u();\n };\n },\n [store, normalizedSpecs],\n );\n\n const getSnapshot = useMemo(() => {\n return () => {\n if (lastVerRef.current !== versionRef.current) {\n const next = selector(store.getState() as DeepReadonly<S>);\n const prev = lastSelRef.current as T | undefined;\n\n if (prev === undefined || !isEqual(prev, next)) {\n lastSelRef.current = next;\n }\n\n lastVerRef.current = versionRef.current;\n }\n\n return lastSelRef.current as T;\n };\n }, [store, selector, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Subscribe to store events from a React component.\n *\n * This hook enables reactive UI patterns by allowing components to respond\n * to specific events without selecting state. Useful for:\n * - Showing notifications on certain events\n * - Triggering animations\n * - Logging/analytics\n * - Responding to rejected (uncommitted) events\n *\n * **Phases:**\n * - `'committed'` (default): Events that passed middleware and reached reducers\n * - `'uncommitted'`: Events rejected by middleware\n * - `'all'`: Both committed and uncommitted events (handler receives phase parameter)\n *\n * @typeParam EM - Event map type.\n * @typeParam C - Channel key within `EM`.\n * @typeParam T - Event type key within channel `C`.\n *\n * @param channel - Event channel to subscribe to.\n * @param type - Event type to subscribe to.\n * @param handler - Handler called when the event fires. Receives `(event, getState, emit, phase)`.\n * @param phase - Event phase to subscribe to (default: `'committed'`).\n *\n * @example Committed events (default)\n * ```tsx\n * useEvent('ui', 'save', (event, getState, emit, phase) => {\n * showToast('Saved successfully!');\n * });\n * ```\n *\n * @example Rejected events\n * ```tsx\n * useEvent('ui', 'delete', (event, getState, emit, phase) => {\n * showToast('Delete was blocked by middleware');\n * }, 'uncommitted');\n * ```\n *\n * @example All events\n * ```tsx\n * useEvent('ui', 'action', (event, getState, emit, phase) => {\n * console.log('Action:', phase); // 'committed' or 'uncommitted'\n * }, 'all');\n * ```\n *\n * @public\n */\nexport function useEvent<\n EM extends EventMapBase,\n C extends keyof EM & string,\n T extends keyof EM[C] & string,\n>(\n channel: C,\n type: T,\n handler: (\n event: Event<EM, C, T>,\n getState: () => DeepReadonly<any>,\n emit: Emit<EM>,\n phase: \"committed\" | \"uncommitted\",\n ) => void | Promise<void>,\n phase: EventPhase = \"committed\",\n): void {\n const store = useStore<EM, any, any>();\n const handlerRef = useRef(handler);\n handlerRef.current = handler; // Always keep latest handler (solves stale closures)\n\n useEffect(() => {\n return store.onEvent(\n channel,\n type,\n (event, getState, emit, eventPhase) => {\n handlerRef.current(event as Event<EM, C, T>, getState, emit, eventPhase);\n },\n phase,\n );\n }, [store, channel, type, phase]);\n}\n","/**\n * @module @yoltra/react\n */\n\nimport { useMemo, useSyncExternalStore } from \"react\";\nimport type { EventMapBase, StoreInstance, Dotted, WithGlob } from \"@yoltra/core\";\n\nimport { useStore } from \"./hooks\";\nimport { hasWildcard, normalizePath, getAtPath } from \"../utils/path\";\n\n/** @internal */\ntype CacheKey = string;\n\n/** @internal */\ntype CacheEntry<T> =\n | { status: \"ready\"; value: T; expiresAt: number | null }\n | { status: \"pending\"; promise: Promise<void>; expiresAt: number | null }\n | { status: \"error\"; error: any; expiresAt: number | null };\n\n/** @internal */\nclass SuspenseCache {\n private store = new Map<CacheKey, CacheEntry<any>>();\n\n read<T>(key: CacheKey, load: () => T | Promise<T>, staleTime: number | null): T {\n const now = Date.now();\n const entry = this.store.get(key);\n\n if (entry && entry.status === \"ready\" && (entry.expiresAt == null || entry.expiresAt > now)) {\n return entry.value as T;\n }\n if (\n entry &&\n entry.status === \"pending\" &&\n (entry.expiresAt == null || entry.expiresAt > now)\n ) {\n throw entry.promise;\n }\n if (entry && entry.status === \"error\" && (entry.expiresAt == null || entry.expiresAt > now)) {\n throw entry.error;\n }\n\n const promise = Promise.resolve()\n .then(load)\n .then((value) => {\n this.store.set(key, {\n status: \"ready\",\n value,\n expiresAt: staleTime == null ? null : Date.now() + staleTime,\n });\n })\n .catch((err) => {\n this.store.set(key, {\n status: \"error\",\n error: err,\n expiresAt: staleTime == null ? null : Date.now() + staleTime,\n });\n });\n\n this.store.set(key, {\n status: \"pending\",\n promise,\n expiresAt: staleTime == null ? null : Date.now() + staleTime,\n });\n throw promise;\n }\n\n invalidate(key: CacheKey) {\n this.store.delete(key);\n }\n invalidatePrefix(prefix: string) {\n for (const k of this.store.keys()) {\n if (k.startsWith(prefix)) this.store.delete(k);\n }\n }\n clear() {\n this.store.clear();\n }\n}\n\n/**\n * Default Suspense cache instance shared by all `useSuspense*` hooks.\n *\n * Use {@link invalidateAtomicProp}, {@link invalidateAtomicPropsByReducer},\n * or {@link clearSuspenseCache} to manage the cache from outside hooks.\n *\n * @public\n */\nexport const suspenseCache = new SuspenseCache();\n\n/** @internal */\nfunction buildKey(reducer: string, props: string[] | string, extraKey?: string): string {\n const p = Array.isArray(props) ? props.map(normalizePath).sort().join(\"|\") : normalizePath(props);\n return extraKey ? `${reducer}::${p}::${extraKey}` : `${reducer}::${p}`;\n}\n\n/**\n * Options for {@link useSuspenseAtomicProp}.\n *\n * @typeParam T - The resolved value type after loading.\n * @typeParam S - Store state record.\n *\n * @example\n * ```ts\n * const options: SuspenseAtomicPropOptions<User, AppState> = {\n * load: async (userId) => fetchUser(userId),\n * staleTime: 30_000, // cache for 30 seconds\n * key: 'user-detail',\n * };\n * ```\n *\n * @public\n */\nexport interface SuspenseAtomicPropOptions<T, S> {\n /** Async loader that receives the value at the path and the full slice. */\n load: (valueAtPath: any, slice: S[keyof S]) => Promise<T> | T;\n /** Time in ms before the cached value is considered stale (default: 0). */\n staleTime?: number;\n /** Optional extra key to differentiate cache entries for the same path. */\n key?: string;\n}\n\n/**\n * Suspense-compatible version of `useAtomicProp` that throws a promise while loading.\n *\n * Subscribes to a single dotted path and calls `options.load` to produce the\n * resolved value. While the promise is pending, React Suspense catches it and\n * renders the nearest `<Suspense>` fallback.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam P - Dotted path within `S[R]`.\n * @typeParam T - Resolved value type.\n *\n * @param storeSpec - `{ reducer, property }` identifying the path to subscribe to.\n * @param options - Loading options (see {@link SuspenseAtomicPropOptions}).\n * @returns The resolved value of type `T`.\n *\n * @throws A `Promise` while loading (caught by React Suspense).\n * @throws If called outside a `<StoreProvider>`.\n *\n * @example\n * ```tsx\n * function UserName({ userId }: { userId: string }) {\n * const name = useSuspenseAtomicProp(\n * { reducer: 'users', property: `byId.${userId}.name` },\n * { load: async (name) => name ?? (await fetchUser(userId)).name },\n * );\n * return <span>{name}</span>;\n * }\n *\n * // Wrap with Suspense\n * <Suspense fallback={<Spinner />}>\n * <UserName userId=\"123\" />\n * </Suspense>\n * ```\n *\n * @public\n */\nexport function useSuspenseAtomicProp<\n R extends string,\n S extends Record<R, any>,\n P extends Dotted<S[R]>,\n T,\n>(storeSpec: { reducer: R; property: P }, options: SuspenseAtomicPropOptions<T, S>): T;\nexport function useSuspenseAtomicProp<R extends string, S extends Record<R, any>, T>(\n storeSpec: { reducer: R; property: string },\n options: SuspenseAtomicPropOptions<T, S>,\n): T;\nexport function useSuspenseAtomicProp<R extends string, S extends Record<R, any>, T>(\n storeSpec: { reducer: R; property: string },\n options: SuspenseAtomicPropOptions<T, S>,\n): T {\n return _useSuspenseAtomicPropImpl<R, S, any, T>(storeSpec as any, options);\n}\n\n/** @internal */\nfunction _useSuspenseAtomicPropImpl<\n R extends string,\n S extends Record<R, any>,\n P extends Dotted<S[R]>,\n T,\n>(storeSpec: { reducer: R; property: P }, options: SuspenseAtomicPropOptions<T, S>): T {\n const store = useStore<EventMapBase, R, S>() as StoreInstance<R, S, EventMapBase>;\n const reducer = storeSpec.reducer;\n const path = normalizePath(storeSpec.property as string);\n const key = buildKey(reducer, path, options.key);\n\n const subscribe = useMemo(() => {\n return (notify: () => void) =>\n store.connect({ reducer, property: path }, () => {\n suspenseCache.invalidate(key);\n notify();\n });\n }, [store, reducer, path, key]);\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(path);\n return () => {\n const state = store.getState() as S;\n const slice = state[reducer];\n const val = isGlob ? slice : getAtPath(slice, path);\n return suspenseCache.read<T>(key, () => options.load(val, slice), options.staleTime ?? 0);\n };\n }, [store, reducer, path, key, options]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Options for {@link useSuspenseAtomicProps}.\n *\n * @typeParam T - The resolved value type after loading.\n * @typeParam S - Store state record.\n *\n * @public\n */\nexport interface SuspenseAtomicPropsOptions<T, S> {\n /** Async loader that receives the full store state. */\n load: (state: S) => Promise<T> | T;\n /** Time in ms before the cached value is considered stale (default: 0). */\n staleTime?: number;\n /** Optional extra key to differentiate cache entries. */\n key?: string;\n}\n\n/**\n * Suspense-compatible version of `useAtomicProps` that throws a promise while loading.\n *\n * Subscribes to multiple dotted paths and calls `options.load` with the full state\n * to produce the resolved value. While the promise is pending, React Suspense\n * renders the nearest `<Suspense>` fallback.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam T - Resolved value type.\n *\n * @param specs - Array of `{ reducer, property }` paths to subscribe to.\n * @param options - Loading options (see {@link SuspenseAtomicPropsOptions}).\n * @returns The resolved value of type `T`.\n *\n * @throws A `Promise` while loading (caught by React Suspense).\n * @throws If called outside a `<StoreProvider>`.\n *\n * @example\n * ```tsx\n * function Dashboard() {\n * const stats = useSuspenseAtomicProps(\n * [\n * { reducer: 'orders', property: 'items.**' },\n * { reducer: 'users', property: 'active' },\n * ],\n * { load: async (state) => computeDashboardStats(state) },\n * );\n * return <StatsGrid data={stats} />;\n * }\n * ```\n *\n * @public\n */\nexport function useSuspenseAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property: Dotted<S[R]> | WithGlob<Dotted<S[R]>> | ReadonlyArray<WithGlob<Dotted<S[R]>>>;\n }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T;\nexport function useSuspenseAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{ reducer: R; property: string | readonly string[] }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T;\nexport function useSuspenseAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property:\n | string\n | readonly string[]\n | Dotted<S[R]>\n | WithGlob<Dotted<S[R]>>\n | ReadonlyArray<WithGlob<Dotted<S[R]>>>;\n }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T {\n return _useSuspenseAtomicPropsImpl<R, S, T>(specs as any, options);\n}\n\n/** @internal */\nfunction _useSuspenseAtomicPropsImpl<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property:\n | string\n | readonly string[]\n | Dotted<S[R]>\n | WithGlob<Dotted<S[R]>>\n | ReadonlyArray<WithGlob<Dotted<S[R]>>>;\n }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T {\n const store = useStore<EventMapBase, R, S>() as StoreInstance<R, S, EventMapBase>;\n\n const normalized = useMemo(\n () =>\n specs.map((sp) => ({\n reducer: sp.reducer,\n property: Array.isArray(sp.property)\n ? (sp.property as readonly string[]).map((p) => normalizePath(p as string))\n : normalizePath(sp.property as string),\n })),\n [JSON.stringify(specs)],\n );\n\n const key = useMemo(() => {\n const parts = normalized\n .map((sp) => buildKey(sp.reducer, sp.property))\n .sort()\n .join(\"||\");\n return options.key ? `${parts}::${options.key}` : parts;\n }, [normalized, options.key]);\n\n const subscribe = useMemo(() => {\n return (notify: () => void) => {\n const wrapped = () => {\n suspenseCache.invalidate(key);\n notify();\n };\n const unsubs = normalized.map((sp) => store.connect(sp as any, wrapped));\n return () => {\n for (const u of unsubs) u();\n };\n };\n }, [store, normalized, key]);\n\n const getSnapshot = useMemo(() => {\n return () => {\n const state = store.getState() as S;\n return suspenseCache.read<T>(key, () => options.load(state), options.staleTime ?? 0);\n };\n }, [store, key, options]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Invalidates the Suspense cache entry for a specific `reducer.property` path.\n *\n * @param reducer - Reducer (slice) name.\n * @param property - Dotted property path.\n * @param extraKey - Optional extra key if the hook was created with `options.key`.\n *\n * @example\n * ```ts\n * invalidateAtomicProp('users', 'byId.123.name');\n * ```\n *\n * @public\n */\nexport function invalidateAtomicProp(reducer: string, property: string, extraKey?: string) {\n suspenseCache.invalidate(buildKey(reducer, property, extraKey));\n}\n\n/**\n * Invalidates all Suspense cache entries for a given reducer (slice).\n *\n * @param reducer - Reducer (slice) name whose cache entries should be cleared.\n *\n * @example\n * ```ts\n * invalidateAtomicPropsByReducer('users');\n * ```\n *\n * @public\n */\nexport function invalidateAtomicPropsByReducer(reducer: string) {\n suspenseCache.invalidatePrefix(`${reducer}::`);\n}\n\n/**\n * Clears the entire Suspense cache, forcing all `useSuspense*` hooks to re-load.\n *\n * @example\n * ```ts\n * // After a logout, clear all cached data\n * clearSuspenseCache();\n * ```\n *\n * @public\n */\nexport function clearSuspenseCache() {\n suspenseCache.clear();\n}","/**\n * @module @yoltra/react\n */\n\nimport type {\n DeepReadonly,\n Dotted,\n Emit,\n Event,\n EventMapBase,\n EventPhase,\n PathValue,\n StoreInstance,\n WithGlob,\n} from \"@yoltra/core\";\nimport * as React from \"react\";\nimport { useContext, useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport { getAtPath, hasWildcard, normalizePath } from \"../utils/path\";\n\n/**\n * Call signature for the typed `useAtomicProp` hook returned by {@link createHooks}.\n *\n * Subscribes to a specific dotted path in a reducer's state and re-renders\n * only when that path changes. All type parameters are inferred automatically\n * from the store context — no explicit generics needed.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n *\n * @example\n * ```tsx\n * const { useAtomicProp } = createHooks(AppStoreContext);\n *\n * function TodoTitle({ index }: { index: number }) {\n * const title = useAtomicProp({\n * reducer: 'todos',\n * property: `items.${index}.title`,\n * });\n * return <span>{title}</span>;\n * }\n * ```\n *\n * @public\n */\nexport type UseAtomicProp<R extends string, S extends Record<R, any>> = {\n <R1 extends R, P extends Dotted<S[R1]>>(spec: {\n reducer: R1;\n property: P;\n }): PathValue<S[R1], P>;\n <R1 extends R, P extends Dotted<S[R1]>, T>(\n spec: { reducer: R1; property: P },\n map: (value: PathValue<S[R1], P>) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n <R1 extends R, P extends WithGlob<Dotted<S[R1]>>, T>(\n spec: { reducer: R1; property: P },\n map: (value: unknown) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n <R1 extends R>(spec: { reducer: R1; property: string }): unknown;\n <R1 extends R, T>(\n spec: { reducer: R1; property: string },\n map: (value: unknown) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n};\n\n/**\n * Call signature for the typed `useAtomicProps` hook returned by {@link createHooks}.\n *\n * Subscribes to multiple dotted paths across one or more reducers and recomputes\n * a derived value when any of them change.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n *\n * @example\n * ```tsx\n * const { useAtomicProps } = createHooks(AppStoreContext);\n *\n * function FilteredCount() {\n * const count = useAtomicProps(\n * [\n * { reducer: 'todos', property: 'items.**' },\n * { reducer: 'filter', property: 'q' },\n * ],\n * (s) => s.todos.items.filter(x => x.title.includes(s.filter.q)).length,\n * );\n * return <span>{count}</span>;\n * }\n * ```\n *\n * @public\n */\nexport type UseAtomicProps<R extends string, S extends Record<R, any>> = {\n <R1 extends R, T>(\n specs: Array<{\n reducer: R1;\n property: WithGlob<Dotted<S[R1]>> | readonly WithGlob<Dotted<S[R1]>>[];\n }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n <R1 extends R, T>(\n specs: Array<{ reducer: R1; property: string | readonly string[] }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n};\n\n/**\n * Call signature for the typed `useEvent` hook returned by {@link createHooks}.\n *\n * Subscribes to store events from a React component. Useful for notifications,\n * animations, analytics, and responding to rejected (uncommitted) events.\n *\n * @typeParam EM - Event map type.\n * @typeParam S - Store state type.\n *\n * @example\n * ```tsx\n * const { useEvent } = createHooks(AppStoreContext);\n *\n * function SaveNotifier() {\n * useEvent('ui', 'save', (event) => {\n * showToast('Saved!');\n * });\n * return null;\n * }\n * ```\n *\n * @public\n */\nexport type UseEvent<EM extends EventMapBase, S> = <\n C extends keyof EM & string,\n T extends keyof EM[C] & string,\n>(\n channel: C,\n type: T,\n handler: (\n event: Event<EM, C, T>,\n getState: () => DeepReadonly<S>,\n emit: Emit<EM>,\n phase: \"committed\" | \"uncommitted\",\n ) => void | Promise<void>,\n phase?: EventPhase,\n) => void;\n\n/**\n * Shallow object equality using `Object.is` per-key.\n *\n * Useful as the `isEqual` argument for `useAtomicProp` and `useAtomicProps`\n * when the derived value is a plain object. Also available as a standalone\n * export from `@yoltra/react` via {@link shallowEqual | hooks.shallowEqual}.\n *\n * @example\n * ```ts\n * shallowEqual({ a: 1 }, { a: 1 }); // true\n * shallowEqual({ a: 1 }, { a: 2 }); // false\n * ```\n *\n * @public\n */\nexport function shallowEqual<T extends Record<string, unknown>>(a: T, b: T) {\n if (Object.is(a, b)) return true;\n if (!a || !b) return false;\n const ka = Object.keys(a),\n kb = Object.keys(b);\n if (ka.length !== kb.length) return false;\n for (const k of ka) {\n if (!Object.is(a[k], (b as Record<string, unknown>)[k])) return false;\n }\n return true;\n}\n\n/**\n * Factory that creates fully-typed React hooks bound to a specific store context.\n *\n * This is the **recommended** setup pattern for yoltra + React. It eliminates\n * the need for explicit type parameters on every hook call — all types are\n * inferred from the store context once, at creation time.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam EM - Event map.\n *\n * @param StoreContext - A React context carrying a `StoreInstance<R, S, EM>`.\n * @returns An object with typed hooks: `useStore`, `useEmit`, `useSelector`,\n * `useAtomicProp`, `useAtomicProps`, `useEvent`, and `shallowEqual`.\n *\n * @throws If any returned hook is called outside a `<StoreProvider>`.\n *\n * @example Complete setup\n * ```tsx\n * // 1. Define your event map and state\n * type AppEM = { ui: { increment: number; decrement: number } };\n * type AppState = { counter: { value: number } };\n *\n * // 2. Create a typed context\n * import { createContext } from 'react';\n * import { StoreInstance } from '@yoltra/core';\n * const AppStoreContext = createContext<\n * StoreInstance<'counter', AppState, AppEM> | null\n * >(null);\n *\n * // 3. Create typed hooks (do this once, export from a shared module)\n * const { useAtomicProp, useEmit, useEvent } = createHooks(AppStoreContext);\n *\n * // 4. Use in components — no explicit generics needed\n * function Counter() {\n * const value = useAtomicProp({ reducer: 'counter', property: 'value' });\n * const emit = useEmit();\n * return (\n * <button onClick={() => emit('ui', 'increment', 1)}>\n * Count: {value}\n * </button>\n * );\n * }\n * ```\n *\n * @public\n */\nexport function createHooks<\n R extends string,\n S extends Record<R, any>,\n EM extends EventMapBase,\n>(StoreContext: React.Context<StoreInstance<R, S, EM> | null>) {\n function useStore(): StoreInstance<R, S, EM> {\n const ctx = useContext(StoreContext);\n if (!ctx) throw new Error(\"useStore must be used inside <StoreProvider>\");\n return ctx;\n }\n\n function useEmit(): Emit<EM> {\n return useStore().emit;\n }\n\n function useSelector<T>(\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n ): T {\n const store = useStore();\n const subscribe = useMemo(() => (notify: () => void) => store.subscribe(notify), [store]);\n const getSnapshot = useMemo(() => {\n let last = selector(store.getState());\n return () => {\n const next = selector(store.getState());\n return isEqual(last, next) ? last : (last = next);\n };\n }, [store, selector, isEqual]);\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n type UseAtomicPropOverloads = UseAtomicProp<R, S>;\n\n const useAtomicPropImpl = (\n spec: { reducer: R; property: string },\n map?: (value: unknown) => unknown,\n isEqual?: (a: unknown, b: unknown) => boolean,\n ): unknown => {\n const store = useStore();\n const normalizedSpec = useMemo(() => {\n const prop = normalizePath(spec.property);\n return { reducer: spec.reducer, property: prop } as const;\n }, [spec.reducer, spec.property]);\n\n const subscribe = useMemo(\n () => (notify: () => void) =>\n store.connect(\n { reducer: normalizedSpec.reducer, property: normalizedSpec.property },\n () => notify(),\n ),\n [store, normalizedSpec],\n );\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(normalizedSpec.property);\n const read = () => {\n const full = store.getState() as DeepReadonly<S>;\n const slice = (full as any)[normalizedSpec.reducer];\n const source = isGlob ? slice : getAtPath(slice, normalizedSpec.property);\n return map ? map(source) : source;\n };\n const eq = isEqual ?? Object.is;\n let last = read();\n return () => {\n const next = read();\n return eq(last, next) ? last : (last = next);\n };\n }, [store, normalizedSpec, map, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n };\n\n const useAtomicProp = useAtomicPropImpl as unknown as UseAtomicPropOverloads;\n\n type OneOrMany<T> = T | readonly T[];\n type UseAtomicPropsOverloads = UseAtomicProps<R, S>;\n\n const useAtomicPropsImpl = <T>(\n specs: Array<{ reducer: R; property: OneOrMany<string> }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n ): T => {\n const store = useStore();\n const versionRef = useRef(0);\n const lastSelRef = useRef<T | undefined>(undefined);\n const lastVerRef = useRef<number>(-1);\n\n const normalizedSpecs = useMemo(() => {\n return specs.map((sp) => ({\n reducer: sp.reducer,\n property: Array.isArray(sp.property)\n ? (sp.property as readonly string[]).map((p) => normalizePath(p))\n : normalizePath(sp.property as string),\n }));\n }, [JSON.stringify(specs)]);\n\n const subscribe = useMemo(\n () => (notify: () => void) => {\n const tick = () => {\n versionRef.current++;\n notify();\n };\n const unsubs = normalizedSpecs.flatMap((sp) => {\n const props = Array.isArray(sp.property) ? sp.property : [sp.property];\n return props.map((p) => store.connect({ reducer: sp.reducer, property: p }, tick));\n });\n return () => {\n for (const u of unsubs) u();\n };\n },\n [store, normalizedSpecs],\n );\n\n const getSnapshot = useMemo(() => {\n return () => {\n if (lastVerRef.current !== versionRef.current) {\n const next = selector(store.getState());\n const prev = lastSelRef.current;\n if (prev === undefined || !isEqual(prev, next)) lastSelRef.current = next;\n lastVerRef.current = versionRef.current;\n }\n return lastSelRef.current as T;\n };\n }, [store, selector, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n };\n\n const useAtomicProps = useAtomicPropsImpl as unknown as UseAtomicPropsOverloads;\n\n type UseEventOverloads = UseEvent<EM, S>;\n\n const useEvent: UseEventOverloads = <\n C extends keyof EM & string,\n T extends keyof EM[C] & string,\n >(\n channel: C,\n type: T,\n handler: (\n event: Event<EM, C, T>,\n getState: () => DeepReadonly<S>,\n emit: Emit<EM>,\n phase: \"committed\" | \"uncommitted\",\n ) => void | Promise<void>,\n phase: EventPhase = \"committed\",\n ): void => {\n const store = useStore();\n const handlerRef = useRef(handler);\n handlerRef.current = handler; // Always keep latest handler (solves stale closures)\n\n useEffect(() => {\n return store.onEvent(\n channel,\n type,\n (event, getState, emit, eventPhase) => {\n handlerRef.current(\n event as Event<EM, C, T>,\n getState as () => DeepReadonly<S>,\n emit,\n eventPhase,\n );\n },\n phase,\n );\n }, [store, channel, type, phase]);\n };\n\n return {\n useStore,\n useEmit,\n useSelector,\n useAtomicProp,\n useAtomicProps,\n useEvent,\n shallowEqual,\n };\n}\n"],"names":["require$$0","createContext","useRef","useEffect","useMemo","useSyncExternalStore","useContext","StoreContext","jsxRuntime","reactJsxRuntime_production","REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","self","source","owner","debugStack","debugTask","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","k","didWarnAboutKeySpread","node","React","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","StoreProvider","store","jsx","hasWildcard","p","normalizePath","splitPath","getAtPath","obj","path","cur","seg","useStore","ctx","useEmit","shallowEqual","a","b","ka","kb","useSelector","selector","isEqual","subscribe","notify","getSnapshot","last","next","useAtomicPropImpl","spec","normalizedSpec","prop","isGlob","read","slice","_useAtomicPropImpl","map","useAtomicProp","useAtomicProps","specs","_useAtomicPropsImpl","versionRef","lastSelRef","lastVerRef","normalizedSpecs","sp","tick","unsubs","u","prev","useEvent","channel","handler","phase","handlerRef","event","getState","emit","eventPhase","SuspenseCache","__publicField","load","staleTime","now","entry","promise","err","prefix","suspenseCache","buildKey","reducer","extraKey","useSuspenseAtomicProp","storeSpec","options","_useSuspenseAtomicPropImpl","_a","val","useSuspenseAtomicProps","_useSuspenseAtomicPropsImpl","normalized","parts","wrapped","state","invalidateAtomicProp","property","invalidateAtomicPropsByReducer","clearSuspenseCache","createHooks","eq"],"mappings":";;;AA+BO,OAAAA,MAAA,iBAAAC,IAAA,UAAAC,GAAA,aAAAC,IAAA,WAAAC,GAAA,wBAAAC,GAAA,cAAAC,UAAA;AAAA,MAAMC,KAAeN,GAAmD,IAAI;AAAA,IAAAO,IAAA,EAAA,SAAA,CAAA,EAAA,GAAAC,IAAA,CAAA;;;;;ACpBnF,MAAIC,IAAqB,uBAAO,IAAI,4BAA4B,GAC9DC,IAAsB,uBAAO,IAAI,gBAAgB;AACnD,WAASC,EAAQC,GAAMC,GAAQC,GAAU;AACvC,QAAIC,IAAM;AAGV,QAFWD,MAAX,WAAwBC,IAAM,KAAKD,IACxBD,EAAO,QAAlB,WAA0BE,IAAM,KAAKF,EAAO,MACxC,SAASA,GAAQ;AACnB,MAAAC,IAAW,CAAA;AACX,eAASE,KAAYH;AACnB,QAAUG,MAAV,UAAuBF,EAASE,CAAQ,IAAIH,EAAOG,CAAQ;AAAA,IACjE,MAAS,CAAAF,IAAWD;AAClB,WAAAA,IAASC,EAAS,KACX;AAAA,MACL,UAAUL;AAAA,MACV,MAAMG;AAAA,MACN,KAAKG;AAAA,MACL,KAAgBF,MAAX,SAAoBA,IAAS;AAAA,MAClC,OAAOC;AAAA;EAEX;AACA,SAAAN,EAAA,WAAmBE,GACnBF,EAAA,MAAcG,GACdH,EAAA,OAAeG;;;;;wBCtBE,QAAQ,IAAI,aAA7B,iBACG,WAAY;AACX,aAASM,EAAyBL,GAAM;AACtC,UAAYA,KAAR,KAAc,QAAO;AACzB,UAAmB,OAAOA,KAAtB;AACF,eAAOA,EAAK,aAAaM,KACrB,OACAN,EAAK,eAAeA,EAAK,QAAQ;AACvC,UAAiB,OAAOA,KAApB,SAA0B,QAAOA;AACrC,cAAQA,GAAI;AAAA,QACV,KAAKF;AACH,iBAAO;AAAA,QACT,KAAKS;AACH,iBAAO;AAAA,QACT,KAAKC;AACH,iBAAO;AAAA,QACT,KAAKC;AACH,iBAAO;AAAA,QACT,KAAKC;AACH,iBAAO;AAAA,QACT,KAAKC;AACH,iBAAO;AAAA,MACjB;AACM,UAAiB,OAAOX,KAApB;AACF,gBACgB,OAAOA,EAAK,OAAzB,YACC,QAAQ;AAAA,UACN;AAAA,WAEJA,EAAK,UACf;AAAA,UACU,KAAKY;AACH,mBAAO;AAAA,UACT,KAAKC;AACH,oBAAQb,EAAK,eAAe,aAAa;AAAA,UAC3C,KAAKc;AACH,oBAAQd,EAAK,SAAS,eAAe,aAAa;AAAA,UACpD,KAAKe;AACH,gBAAIC,IAAYhB,EAAK;AACrB,mBAAAA,IAAOA,EAAK,aACZA,MACIA,IAAOgB,EAAU,eAAeA,EAAU,QAAQ,IACnDhB,IAAcA,MAAP,KAAc,gBAAgBA,IAAO,MAAM,eAC9CA;AAAA,UACT,KAAKiB;AACH,mBACGD,IAAYhB,EAAK,eAAe,MACxBgB,MAAT,OACIA,IACAX,EAAyBL,EAAK,IAAI,KAAK;AAAA,UAE/C,KAAKkB;AACH,YAAAF,IAAYhB,EAAK,UACjBA,IAAOA,EAAK;AACZ,gBAAI;AACF,qBAAOK,EAAyBL,EAAKgB,CAAS,CAAC;AAAA,YAC7D,QAAwB;AAAA,YAAA;AAAA,QACxB;AACM,aAAO;AAAA,IACb;AACI,aAASG,EAAmBC,GAAO;AACjC,aAAO,KAAKA;AAAA,IAClB;AACI,aAASC,EAAuBD,GAAO;AACrC,UAAI;AACF,QAAAD,EAAmBC,CAAK;AACxB,YAAIE,IAA2B;AAAA,MACvC,QAAkB;AACV,QAAAA,IAA2B;AAAA,MACnC;AACM,UAAIA,GAA0B;AAC5B,QAAAA,IAA2B;AAC3B,YAAIC,IAAwBD,EAAyB,OACjDE,IACc,OAAO,UAAtB,cACC,OAAO,eACPJ,EAAM,OAAO,WAAW,KAC1BA,EAAM,YAAY,QAClB;AACF,eAAAG,EAAsB;AAAA,UACpBD;AAAA,UACA;AAAA,UACAE;AAAA,WAEKL,EAAmBC,CAAK;AAAA,MACvC;AAAA,IACA;AACI,aAASK,EAAYzB,GAAM;AACzB,UAAIA,MAASF,EAAqB,QAAO;AACzC,UACe,OAAOE,KAApB,YACSA,MAAT,QACAA,EAAK,aAAakB;AAElB,eAAO;AACT,UAAI;AACF,YAAIQ,IAAOrB,EAAyBL,CAAI;AACxC,eAAO0B,IAAO,MAAMA,IAAO,MAAM;AAAA,MACzC,QAAkB;AACV,eAAO;AAAA,MACf;AAAA,IACA;AACI,aAASC,IAAW;AAClB,UAAIC,IAAaC,EAAqB;AACtC,aAAgBD,MAAT,OAAsB,OAAOA,EAAW,SAAQ;AAAA,IAC7D;AACI,aAASE,IAAe;AACtB,aAAO,MAAM,uBAAuB;AAAA,IAC1C;AACI,aAASC,EAAY9B,GAAQ;AAC3B,UAAI+B,EAAe,KAAK/B,GAAQ,KAAK,GAAG;AACtC,YAAIgC,IAAS,OAAO,yBAAyBhC,GAAQ,KAAK,EAAE;AAC5D,YAAIgC,KAAUA,EAAO,eAAgB,QAAO;AAAA,MACpD;AACM,aAAkBhC,EAAO,QAAlB;AAAA,IACb;AACI,aAASiC,EAA2BC,GAAOC,GAAa;AACtD,eAASC,IAAwB;AAC/B,QAAAC,MACIA,IAA6B,IAC/B,QAAQ;AAAA,UACN;AAAA,UACAF;AAAA,QACZ;AAAA,MACA;AACM,MAAAC,EAAsB,iBAAiB,IACvC,OAAO,eAAeF,GAAO,OAAO;AAAA,QAClC,KAAKE;AAAA,QACL,cAAc;AAAA,MACtB,CAAO;AAAA,IACP;AACI,aAASE,IAAyC;AAChD,UAAIC,IAAgBnC,EAAyB,KAAK,IAAI;AACtD,aAAAoC,EAAuBD,CAAa,MAChCC,EAAuBD,CAAa,IAAI,IAC1C,QAAQ;AAAA,QACN;AAAA,MACV,IACMA,IAAgB,KAAK,MAAM,KACTA,MAAX,SAA2BA,IAAgB;AAAA,IACxD;AACI,aAASE,EACP1C,GACAG,GACAwC,GACAC,GACAC,GACAV,GACAW,GACAC,GACA;AACA,aAAAJ,IAAOR,EAAM,KACbnC,IAAO;AAAA,QACL,UAAUH;AAAA,QACV,MAAMG;AAAA,QACN,KAAKG;AAAA,QACL,OAAOgC;AAAA,QACP,QAAQU;AAAA,UAEWF,MAAX,SAAkBA,IAAO,UAAnC,OACI,OAAO,eAAe3C,GAAM,OAAO;AAAA,QACjC,YAAY;AAAA,QACZ,KAAKuC;AAAA,OACN,IACD,OAAO,eAAevC,GAAM,OAAO,EAAE,YAAY,IAAI,OAAO,MAAM,GACtEA,EAAK,SAAS,CAAA,GACd,OAAO,eAAeA,EAAK,QAAQ,aAAa;AAAA,QAC9C,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,OAAO;AAAA,MACf,CAAO,GACD,OAAO,eAAeA,GAAM,cAAc;AAAA,QACxC,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,OAAO;AAAA,MACf,CAAO,GACD,OAAO,eAAeA,GAAM,eAAe;AAAA,QACzC,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,OAAO8C;AAAA,MACf,CAAO,GACD,OAAO,eAAe9C,GAAM,cAAc;AAAA,QACxC,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,OAAO+C;AAAA,MACf,CAAO,GACD,OAAO,WAAW,OAAO,OAAO/C,EAAK,KAAK,GAAG,OAAO,OAAOA,CAAI,IACxDA;AAAA,IACb;AACI,aAASgD,EACPhD,GACAC,GACAC,GACA+C,GACAL,GACAD,GACAG,GACAC,GACA;AACA,UAAIG,IAAWjD,EAAO;AACtB,UAAeiD,MAAX;AACF,YAAID;AACF,cAAIE,GAAYD,CAAQ,GAAG;AACzB,iBACED,IAAmB,GACnBA,IAAmBC,EAAS,QAC5BD;AAEA,cAAAG,EAAkBF,EAASD,CAAgB,CAAC;AAC9C,mBAAO,UAAU,OAAO,OAAOC,CAAQ;AAAA,UACnD;AACY,oBAAQ;AAAA,cACN;AAAA;YAED,CAAAE,EAAkBF,CAAQ;AACjC,UAAIlB,EAAe,KAAK/B,GAAQ,KAAK,GAAG;AACtC,QAAAiD,IAAW7C,EAAyBL,CAAI;AACxC,YAAIqD,IAAO,OAAO,KAAKpD,CAAM,EAAE,OAAO,SAAUqD,IAAG;AACjD,iBAAiBA,OAAV;AAAA,QACjB,CAAS;AACD,QAAAL,IACE,IAAII,EAAK,SACL,oBAAoBA,EAAK,KAAK,SAAS,IAAI,WAC3C,kBACNE,GAAsBL,IAAWD,CAAgB,MAC7CI,IACA,IAAIA,EAAK,SAAS,MAAMA,EAAK,KAAK,SAAS,IAAI,WAAW,MAC5D,QAAQ;AAAA,UACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UACAJ;AAAA,UACAC;AAAA,UACAG;AAAA,UACAH;AAAA,WAEDK,GAAsBL,IAAWD,CAAgB,IAAI;AAAA,MAChE;AAMM,UALAC,IAAW,MACAhD,MAAX,WACGmB,EAAuBnB,CAAQ,GAAIgD,IAAW,KAAKhD,IACtD6B,EAAY9B,CAAM,MACfoB,EAAuBpB,EAAO,GAAG,GAAIiD,IAAW,KAAKjD,EAAO,MAC3D,SAASA,GAAQ;AACnB,QAAAC,IAAW,CAAA;AACX,iBAASE,KAAYH;AACnB,UAAUG,MAAV,UAAuBF,EAASE,CAAQ,IAAIH,EAAOG,CAAQ;AAAA,MACrE,MAAa,CAAAF,IAAWD;AAClB,aAAAiD,KACEhB;AAAA,QACEhC;AAAA,QACe,OAAOF,KAAtB,aACIA,EAAK,eAAeA,EAAK,QAAQ,YACjCA;AAAA,SAED0C;AAAA,QACL1C;AAAA,QACAkD;AAAA,QACAP;AAAA,QACAC;AAAA,QACAjB,EAAQ;AAAA,QACRzB;AAAA,QACA4C;AAAA,QACAC;AAAA;IAER;AACI,aAASK,EAAkBI,GAAM;AAC/B,MAAa,OAAOA,KAApB,YACWA,MAAT,QACAA,EAAK,aAAa3D,KAClB2D,EAAK,WACJA,EAAK,OAAO,YAAY;AAAA,IACjC;AACI,QAAIC,IAAQtE,IACVU,IAAqB,uBAAO,IAAI,4BAA4B,GAC5De,IAAoB,uBAAO,IAAI,cAAc,GAC7Cd,IAAsB,uBAAO,IAAI,gBAAgB,GACjDU,IAAyB,uBAAO,IAAI,mBAAmB,GACvDD,IAAsB,uBAAO,IAAI,gBAAgB,GAE/CO,IAAsB,uBAAO,IAAI,gBAAgB,GACnDD,IAAqB,uBAAO,IAAI,eAAe,GAC/CE,IAAyB,uBAAO,IAAI,mBAAmB,GACvDN,IAAsB,uBAAO,IAAI,gBAAgB,GACjDC,IAA2B,uBAAO,IAAI,qBAAqB,GAC3DO,IAAkB,uBAAO,IAAI,YAAY,GACzCC,IAAkB,uBAAO,IAAI,YAAY,GACzCP,KAAsB,uBAAO,IAAI,gBAAgB,GACjDL,KAAyB,uBAAO,IAAI,wBAAwB,GAC5DuB,IACE4B,EAAM,iEACRzB,IAAiB,OAAO,UAAU,gBAClCmB,KAAc,MAAM,SACpBO,IAAa,QAAQ,aACjB,QAAQ,aACR,WAAY;AACV,aAAO;AAAA,IACnB;AACI,IAAAD,IAAQ;AAAA,MACN,0BAA0B,SAAUE,GAAmB;AACrD,eAAOA,EAAiB;AAAA,MAChC;AAAA;AAEI,QAAIrB,GACAG,IAAyB,CAAA,GACzBmB,IAAyBH,EAAM,yBAAyB;AAAA,MAC1DA;AAAA,MACA3B;AAAA,IACN,EAAK,GACG+B,KAAwBH,EAAWjC,EAAYK,CAAY,CAAC,GAC5DyB,KAAwB,CAAA;AAC5B,IAAAO,EAAA,WAAmBhE,GACnBgE,EAAA,MAAc,SAAU9D,GAAMC,GAAQC,GAAU0C,GAAQD,GAAM;AAC5D,UAAIoB,IACF,MAAMlC,EAAqB;AAC7B,aAAOmB;AAAA,QACLhD;AAAA,QACAC;AAAA,QACAC;AAAA,QACA;AAAA,QACA0C;AAAA,QACAD;AAAA,QACAoB,IACI,MAAM,uBAAuB,IAC7BH;AAAA,QACJG,IAAmBL,EAAWjC,EAAYzB,CAAI,CAAC,IAAI6D;AAAA;IAE3D,GACIC,EAAA,OAAe,SAAU9D,GAAMC,GAAQC,GAAU0C,GAAQD,GAAM;AAC7D,UAAIoB,IACF,MAAMlC,EAAqB;AAC7B,aAAOmB;AAAA,QACLhD;AAAA,QACAC;AAAA,QACAC;AAAA,QACA;AAAA,QACA0C;AAAA,QACAD;AAAA,QACAoB,IACI,MAAM,uBAAuB,IAC7BH;AAAA,QACJG,IAAmBL,EAAWjC,EAAYzB,CAAI,CAAC,IAAI6D;AAAA;IAE3D;AAAA,EACA,GAAG;;;;wBCnWC,QAAQ,IAAI,aAAa,eAC3BG,EAAA,UAAiB7E,GAAA,IAEjB6E,EAAA,UAAiBC,GAAA;;;ACkDZ,MAAMC,KAKR,CAAC,EAAE,OAAAC,GAAO,UAAAjB,EAAA,MACbkB,gBAAAA,GAAAA,IAAC1E,GAAa,UAAb,EAAsB,OAAOyE,GAAQ,UAAAjB,EAAA,CAAS;AC5D1C,SAASmB,EAAYC,GAAoB;AAC9C,SAAOA,EAAE,SAAS,GAAG;AACvB;AAGO,SAASC,EAAcD,GAAmB;AAC/C,SAAOA,EAAE,QAAQ,OAAO,EAAE;AAC5B;AAGO,SAASE,GAAUF,GAAqB;AAC7C,SAAOC,EAAcD,CAAC,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AACnD;AAMO,SAASG,EAAUC,GAAUC,GAAmB;AACrD,MAAI,CAACA,EAAM,QAAOD;AAElB,MAAIE,IAAMF;AACV,aAAWG,KAAOL,GAAUG,CAAI,GAAG;AACjC,QAAIC,KAAO,KAAM;AACjB,IAAAA,IAAMA,EAAIC,CAAG;AAAA,EACf;AAEA,SAAOD;AACT;AC+BO,SAASE,IAIa;AAC3B,QAAMC,IAAMtF,GAAWC,EAAY;AACnC,MAAI,CAACqF,EAAK,OAAM,IAAI,MAAM,8CAA8C;AAExE,SAAOA;AACT;AAeO,SAASC,KAA6C;AAC3D,SAAOF,IAAyB;AAClC;AAiBO,SAASG,GAA4CC,GAAMC,GAAM;AACtE,MAAI,OAAO,GAAGD,GAAGC,CAAC,EAAG,QAAO;AAC5B,MAAI,CAACD,KAAK,CAACC,EAAG,QAAO;AAErB,QAAMC,IAAK,OAAO,KAAKF,CAAC,GACtBG,IAAK,OAAO,KAAKF,CAAC;AACpB,MAAIC,EAAG,WAAWC,EAAG,OAAQ,QAAO;AAEpC,aAAW/B,KAAK8B;AACd,QAAI,CAAC,OAAO,GAAGF,EAAE5B,CAAC,GAAI6B,EAAU7B,CAAC,CAAC,EAAG,QAAO;AAG9C,SAAO;AACT;AAkBO,SAASgC,GACdC,GACAC,IAAmC,OAAO,IACvC;AACH,QAAMrB,IAAQW,EAAA,GAERW,IAAYlG,EAAQ,MAAM,CAACmG,MAAuBvB,EAAM,UAAUuB,CAAM,GAAG,CAACvB,CAAK,CAAC,GAElFwB,IAAcpG,EAAQ,MAAM;AAChC,QAAIqG,IAAOL,EAASpB,EAAM,SAAA,CAA6B;AACvD,WAAO,MAAM;AACX,YAAM0B,IAAON,EAASpB,EAAM,SAAA,CAA6B;AACzD,aAAOqB,EAAQI,GAAMC,CAAI,IAAID,IAAQA,IAAOC;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC1B,GAAOoB,GAAUC,CAAO,CAAC;AAE7B,SAAOhG,EAAqBiG,GAAWE,GAAaA,CAAW;AACjE;AAGA,SAASG,GAKPC,GAAyD;AACzD,QAAM5B,IAAQW,EAAA,GAERkB,IAAiBzG,EAAQ,MAAM;AACnC,UAAM0G,IAAO1B,EAAcwB,EAAK,QAAQ;AACxC,WAAO,EAAE,SAASA,EAAK,SAAS,UAAUE,EAAA;AAAA,EAC5C,GAAG,CAACF,EAAK,SAASA,EAAK,QAAQ,CAAC,GAE1BN,IAAYlG;AAAA,IAChB,MAAM,CAACmG,MACLvB,EAAM;AAAA,MACJ,EAAE,SAAS6B,EAAe,SAAS,UAAUA,EAAe,SAAA;AAAA,MAC5D,MAAMN,EAAA;AAAA,IAAO;AAAA,IAEjB,CAACvB,GAAO6B,CAAc;AAAA,EAAA,GAGlBL,IAAcpG,EAAQ,MAAM;AAChC,UAAM2G,IAAS7B,EAAY2B,EAAe,QAAQ,GAC5CG,IAAO,MAAM;AAEjB,YAAMC,IADOjC,EAAM,SAAA,EACS6B,EAAe,OAAO;AAElD,aADeE,IAASE,IAAQ3B,EAAU2B,GAAOJ,EAAe,QAAQ;AAAA,IAE1E;AAEA,QAAIJ,IAAOO,EAAA;AACX,WAAO,MAAM;AACX,YAAMN,IAAOM,EAAA;AACb,aAAO,OAAO,GAAGP,GAAMC,CAAI,IAAID,IAAQA,IAAOC;AAAA,IAChD;AAAA,EACF,GAAG,CAAC1B,GAAO6B,CAAc,CAAC;AAE1B,SAAOxG,EAAqBiG,GAAWE,GAAaA,CAAW;AACjE;AAGA,SAASU,GACPN,GACAO,GACAd,IAAmC,OAAO,IACvC;AACH,QAAMrB,IAAQW,EAAA,GAERkB,IAAiBzG,EAAQ,MAAM;AACnC,UAAM0G,IAAO1B,EAAcwB,EAAK,QAAQ;AACxC,WAAO,EAAE,SAASA,EAAK,SAAS,UAAUE,EAAA;AAAA,EAC5C,GAAG,CAACF,EAAK,SAASA,EAAK,QAAQ,CAAC,GAE1BN,IAAYlG;AAAA,IAChB,MAAM,CAACmG,MACLvB,EAAM;AAAA,MACJ,EAAE,SAAS6B,EAAe,SAAS,UAAUA,EAAe,SAAA;AAAA,MAC5D,MAAMN,EAAA;AAAA,IAAO;AAAA,IAEjB,CAACvB,GAAO6B,CAAc;AAAA,EAAA,GAGlBL,IAAcpG,EAAQ,MAAM;AAChC,UAAM2G,IAAS7B,EAAY2B,EAAe,QAAQ,GAC5CG,IAAO,MAAM;AAEjB,YAAMC,IADOjC,EAAM,SAAA,EACS6B,EAAe,OAAO,GAC5CpD,IAASsD,IAASE,IAAQ3B,EAAU2B,GAAOJ,EAAe,QAAQ;AACxE,aAAOM,IAAMA,EAAI1D,CAAM,IAAKA;AAAA,IAC9B;AAEA,QAAIgD,IAAOO,EAAA;AACX,WAAO,MAAM;AACX,YAAMN,IAAOM,EAAA;AACb,aAAOX,EAAQI,GAAMC,CAAI,IAAID,IAAQA,IAAOC;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC1B,GAAO6B,GAAgBM,GAAKd,CAAO,CAAC;AAExC,SAAOhG,EAAqBiG,GAAWE,GAAaA,CAAW;AACjE;AAgGO,SAASY,GACdR,GACAO,GACAd,IAAmC,OAAO,IACvC;AACH,SAAI,CAACc,KAAO,CAACjC,EAAY0B,EAAK,QAAQ,IAC7BD,GAAkCC,CAAI,IAExCM,GAA4BN,GAAMO,GAAKd,CAAO;AACvD;AAuCO,SAASgB,GACdC,GAIAlB,GACAC,IAAmC,OAAO,IACvC;AACH,SAAOkB,GAA6BD,GAAclB,GAAUC,CAAO;AACrE;AAGA,SAASkB,GACPD,GAIAlB,GACAC,IAAmC,OAAO,IACvC;AACH,QAAMrB,IAAQW,EAAA,GAER6B,IAAatH,EAAO,CAAC,GACrBuH,IAAavH,EAAsB,MAAS,GAC5CwH,IAAaxH,EAAe,EAAE,GAE9ByH,IAAkBvH,EAAQ,MACvBkH,EAAM,IAAI,CAACM,OAAQ;AAAA,IACxB,SAASA,EAAG;AAAA,IACZ,UAAU,MAAM,QAAQA,EAAG,QAAQ,IAC9BA,EAAG,SAA+B,IAAI,CAACzC,MAAMC,EAAcD,CAAW,CAAC,IACxEC,EAAcwC,EAAG,QAAkB;AAAA,EAAA,EACvC,GACD,CAAC,KAAK,UAAUN,CAAK,CAAC,CAAC,GAEpBhB,IAAYlG;AAAA,IAChB,MAAM,CAACmG,MAAuB;AAC5B,YAAMsB,IAAO,MAAM;AACjB,QAAAL,EAAW,WACXjB,EAAA;AAAA,MACF,GAEMuB,IAASH,EAAgB,QAAQ,CAACC,OACxB,MAAM,QAAQA,EAAG,QAAQ,IAAIA,EAAG,WAAW,CAACA,EAAG,QAAQ,GACxD,IAAI,CAACzC,MAAMH,EAAM,QAAQ,EAAE,SAAS4C,EAAG,SAAS,UAAUzC,EAAA,GAAK0C,CAAI,CAAC,CAClF;AAED,aAAO,MAAM;AACX,mBAAWE,KAAKD,EAAQ,CAAAC,EAAA;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,CAAC/C,GAAO2C,CAAe;AAAA,EAAA,GAGnBnB,IAAcpG,EAAQ,MACnB,MAAM;AACX,QAAIsH,EAAW,YAAYF,EAAW,SAAS;AAC7C,YAAMd,IAAON,EAASpB,EAAM,SAAA,CAA6B,GACnDgD,IAAOP,EAAW;AAExB,OAAIO,MAAS,UAAa,CAAC3B,EAAQ2B,GAAMtB,CAAI,OAC3Ce,EAAW,UAAUf,IAGvBgB,EAAW,UAAUF,EAAW;AAAA,IAClC;AAEA,WAAOC,EAAW;AAAA,EACpB,GACC,CAACzC,GAAOoB,GAAUC,CAAO,CAAC;AAE7B,SAAOhG,EAAqBiG,GAAWE,GAAaA,CAAW;AACjE;AAiDO,SAASyB,GAKdC,GACArH,GACAsH,GAMAC,IAAoB,aACd;AACN,QAAMpD,IAAQW,EAAA,GACR0C,IAAanI,EAAOiI,CAAO;AACjC,EAAAE,EAAW,UAAUF,GAErBhI,GAAU,MACD6E,EAAM;AAAA,IACXkD;AAAA,IACArH;AAAA,IACA,CAACyH,GAAOC,GAAUC,GAAMC,MAAe;AACrC,MAAAJ,EAAW,QAAQC,GAA0BC,GAAUC,GAAMC,CAAU;AAAA,IACzE;AAAA,IACAL;AAAA,EAAA,GAED,CAACpD,GAAOkD,GAASrH,GAAMuH,CAAK,CAAC;AAClC;AC5fA,MAAMM,GAAc;AAAA,EAApB;AACU,IAAAC,GAAA,mCAAY,IAAA;AAAA;AAAA,EAEpB,KAAQ3H,GAAe4H,GAA4BC,GAA6B;AAC9E,UAAMC,IAAM,KAAK,IAAA,GACXC,IAAQ,KAAK,MAAM,IAAI/H,CAAG;AAEhC,QAAI+H,KAASA,EAAM,WAAW,YAAYA,EAAM,aAAa,QAAQA,EAAM,YAAYD;AACrF,aAAOC,EAAM;AAEf,QACEA,KACAA,EAAM,WAAW,cAChBA,EAAM,aAAa,QAAQA,EAAM,YAAYD;AAE9C,YAAMC,EAAM;AAEd,QAAIA,KAASA,EAAM,WAAW,YAAYA,EAAM,aAAa,QAAQA,EAAM,YAAYD;AACrF,YAAMC,EAAM;AAGd,UAAMC,IAAU,QAAQ,QAAA,EACrB,KAAKJ,CAAI,EACT,KAAK,CAAC3G,MAAU;AACf,WAAK,MAAM,IAAIjB,GAAK;AAAA,QAClB,QAAQ;AAAA,QACR,OAAAiB;AAAA,QACA,WAAW4G,KAAa,OAAO,OAAO,KAAK,QAAQA;AAAA,MAAA,CACpD;AAAA,IACH,CAAC,EACA,MAAM,CAACI,MAAQ;AACd,WAAK,MAAM,IAAIjI,GAAK;AAAA,QAClB,QAAQ;AAAA,QACR,OAAOiI;AAAA,QACP,WAAWJ,KAAa,OAAO,OAAO,KAAK,QAAQA;AAAA,MAAA,CACpD;AAAA,IACH,CAAC;AAEH,eAAK,MAAM,IAAI7H,GAAK;AAAA,MAClB,QAAQ;AAAA,MACR,SAAAgI;AAAA,MACA,WAAWH,KAAa,OAAO,OAAO,KAAK,QAAQA;AAAA,IAAA,CACpD,GACKG;AAAA,EACR;AAAA,EAEA,WAAWhI,GAAe;AACxB,SAAK,MAAM,OAAOA,CAAG;AAAA,EACvB;AAAA,EACA,iBAAiBkI,GAAgB;AAC/B,eAAW/E,KAAK,KAAK,MAAM,KAAA;AACzB,MAAIA,EAAE,WAAW+E,CAAM,KAAG,KAAK,MAAM,OAAO/E,CAAC;AAAA,EAEjD;AAAA,EACA,QAAQ;AACN,SAAK,MAAM,MAAA;AAAA,EACb;AACF;AAUO,MAAMgF,IAAgB,IAAIT,GAAA;AAGjC,SAASU,EAASC,GAAiBrG,GAA0BsG,GAA2B;AACtF,QAAMnE,IAAI,MAAM,QAAQnC,CAAK,IAAIA,EAAM,IAAIoC,CAAa,EAAE,OAAO,KAAK,GAAG,IAAIA,EAAcpC,CAAK;AAChG,SAAOsG,IAAW,GAAGD,CAAO,KAAKlE,CAAC,KAAKmE,CAAQ,KAAK,GAAGD,CAAO,KAAKlE,CAAC;AACtE;AA2EO,SAASoE,GACdC,GACAC,GACG;AACH,SAAOC,GAAyCF,GAAkBC,CAAO;AAC3E;AAGA,SAASC,GAKPF,GAAwCC,GAA6C;AACrF,QAAMzE,IAAQW,EAAA,GACR0D,IAAUG,EAAU,SACpBhE,IAAOJ,EAAcoE,EAAU,QAAkB,GACjDxI,IAAMoI,EAASC,GAAS7D,GAAMiE,EAAQ,GAAG,GAEzCnD,IAAYlG,EAAQ,MACjB,CAACmG,MACNvB,EAAM,QAAQ,EAAE,SAAAqE,GAAS,UAAU7D,EAAA,GAAQ,MAAM;AAC/C,IAAA2D,EAAc,WAAWnI,CAAG,GAC5BuF,EAAA;AAAA,EACF,CAAC,GACF,CAACvB,GAAOqE,GAAS7D,GAAMxE,CAAG,CAAC,GAExBwF,IAAcpG,EAAQ,MAAM;AAChC,UAAM2G,IAAS7B,EAAYM,CAAI;AAC/B,WAAO,MAAM;APtKV,UAAAmE;AOwKD,YAAM1C,IADQjC,EAAM,SAAA,EACAqE,CAAO,GACrBO,IAAM7C,IAASE,IAAQ3B,EAAU2B,GAAOzB,CAAI;AAClD,aAAO2D,EAAc,KAAQnI,GAAK,MAAMyI,EAAQ,KAAKG,GAAK3C,CAAK,IAAG0C,IAAAF,EAAQ,cAAR,OAAAE,IAAqB,CAAC;AAAA,IAC1F;AAAA,EACF,GAAG,CAAC3E,GAAOqE,GAAS7D,GAAMxE,GAAKyI,CAAO,CAAC;AAEvC,SAAOpJ,EAAqBiG,GAAWE,GAAaA,CAAW;AACjE;AAgEO,SAASqD,GACdvC,GASAmC,GACG;AACH,SAAOK,GAAqCxC,GAAcmC,CAAO;AACnE;AAGA,SAASK,GACPxC,GASAmC,GACG;AACH,QAAMzE,IAAQW,EAAA,GAERoE,IAAa3J;AAAA,IACjB,MACEkH,EAAM,IAAI,CAACM,OAAQ;AAAA,MACjB,SAASA,EAAG;AAAA,MACZ,UAAU,MAAM,QAAQA,EAAG,QAAQ,IAC9BA,EAAG,SAA+B,IAAI,CAACzC,MAAMC,EAAcD,CAAW,CAAC,IACxEC,EAAcwC,EAAG,QAAkB;AAAA,IAAA,EACvC;AAAA,IACJ,CAAC,KAAK,UAAUN,CAAK,CAAC;AAAA,EAAA,GAGlBtG,IAAMZ,EAAQ,MAAM;AACxB,UAAM4J,IAAQD,EACX,IAAI,CAACnC,MAAOwB,EAASxB,EAAG,SAASA,EAAG,QAAQ,CAAC,EAC7C,KAAA,EACA,KAAK,IAAI;AACZ,WAAO6B,EAAQ,MAAM,GAAGO,CAAK,KAAKP,EAAQ,GAAG,KAAKO;AAAA,EACpD,GAAG,CAACD,GAAYN,EAAQ,GAAG,CAAC,GAEtBnD,IAAYlG,EAAQ,MACjB,CAACmG,MAAuB;AAC7B,UAAM0D,IAAU,MAAM;AACpB,MAAAd,EAAc,WAAWnI,CAAG,GAC5BuF,EAAA;AAAA,IACF,GACMuB,IAASiC,EAAW,IAAI,CAACnC,MAAO5C,EAAM,QAAQ4C,GAAWqC,CAAO,CAAC;AACvE,WAAO,MAAM;AACX,iBAAWlC,KAAKD,EAAQ,CAAAC,EAAA;AAAA,IAC1B;AAAA,EACF,GACC,CAAC/C,GAAO+E,GAAY/I,CAAG,CAAC,GAErBwF,IAAcpG,EAAQ,MACnB,MAAM;AP9SV,QAAAuJ;AO+SD,UAAMO,IAAQlF,EAAM,SAAA;AACpB,WAAOmE,EAAc,KAAQnI,GAAK,MAAMyI,EAAQ,KAAKS,CAAK,IAAGP,IAAAF,EAAQ,cAAR,OAAAE,IAAqB,CAAC;AAAA,EACrF,GACC,CAAC3E,GAAOhE,GAAKyI,CAAO,CAAC;AAExB,SAAOpJ,EAAqBiG,GAAWE,GAAaA,CAAW;AACjE;AAgBO,SAAS2D,GAAqBd,GAAiBe,GAAkBd,GAAmB;AACzF,EAAAH,EAAc,WAAWC,EAASC,GAASe,GAAUd,CAAQ,CAAC;AAChE;AAcO,SAASe,GAA+BhB,GAAiB;AAC9D,EAAAF,EAAc,iBAAiB,GAAGE,CAAO,IAAI;AAC/C;AAaO,SAASiB,KAAqB;AACnC,EAAAnB,EAAc,MAAA;AAChB;AClOO,SAASrD,GAAgDC,GAAMC,GAAM;AAC1E,MAAI,OAAO,GAAGD,GAAGC,CAAC,EAAG,QAAO;AAC5B,MAAI,CAACD,KAAK,CAACC,EAAG,QAAO;AACrB,QAAMC,IAAK,OAAO,KAAKF,CAAC,GACtBG,IAAK,OAAO,KAAKF,CAAC;AACpB,MAAIC,EAAG,WAAWC,EAAG,OAAQ,QAAO;AACpC,aAAW/B,KAAK8B;AACd,QAAI,CAAC,OAAO,GAAGF,EAAE5B,CAAC,GAAI6B,EAA8B7B,CAAC,CAAC,EAAG,QAAO;AAElE,SAAO;AACT;AAiDO,SAASoG,GAIdhK,GAA6D;AAC7D,WAASoF,IAAoC;AAC3C,UAAMC,IAAMtF,GAAWC,CAAY;AACnC,QAAI,CAACqF,EAAK,OAAM,IAAI,MAAM,8CAA8C;AACxE,WAAOA;AAAA,EACT;AAEA,WAASC,IAAoB;AAC3B,WAAOF,IAAW;AAAA,EACpB;AAEA,WAASQ,EACPC,GACAC,IAAmC,OAAO,IACvC;AACH,UAAMrB,IAAQW,EAAA,GACRW,IAAYlG,EAAQ,MAAM,CAACmG,MAAuBvB,EAAM,UAAUuB,CAAM,GAAG,CAACvB,CAAK,CAAC,GAClFwB,IAAcpG,EAAQ,MAAM;AAChC,UAAIqG,IAAOL,EAASpB,EAAM,SAAA,CAAU;AACpC,aAAO,MAAM;AACX,cAAM0B,IAAON,EAASpB,EAAM,SAAA,CAAU;AACtC,eAAOqB,EAAQI,GAAMC,CAAI,IAAID,IAAQA,IAAOC;AAAA,MAC9C;AAAA,IACF,GAAG,CAAC1B,GAAOoB,GAAUC,CAAO,CAAC;AAC7B,WAAOhG,EAAqBiG,GAAWE,GAAaA,CAAW;AAAA,EACjE;AA0IA,SAAO;AAAA,IACL,UAAAb;AAAA,IACA,SAAAE;AAAA,IACA,aAAAM;AAAA,IACA,eA1IwB,CACxBS,GACAO,GACAd,MACY;AACZ,YAAMrB,IAAQW,EAAA,GACRkB,IAAiBzG,EAAQ,MAAM;AACnC,cAAM0G,IAAO1B,EAAcwB,EAAK,QAAQ;AACxC,eAAO,EAAE,SAASA,EAAK,SAAS,UAAUE,EAAA;AAAA,MAC5C,GAAG,CAACF,EAAK,SAASA,EAAK,QAAQ,CAAC,GAE1BN,IAAYlG;AAAA,QAChB,MAAM,CAACmG,MACLvB,EAAM;AAAA,UACJ,EAAE,SAAS6B,EAAe,SAAS,UAAUA,EAAe,SAAA;AAAA,UAC5D,MAAMN,EAAA;AAAA,QAAO;AAAA,QAEjB,CAACvB,GAAO6B,CAAc;AAAA,MAAA,GAGlBL,IAAcpG,EAAQ,MAAM;AAChC,cAAM2G,IAAS7B,EAAY2B,EAAe,QAAQ,GAC5CG,IAAO,MAAM;AAEjB,gBAAMC,IADOjC,EAAM,SAAA,EACS6B,EAAe,OAAO,GAC5CpD,IAASsD,IAASE,IAAQ3B,EAAU2B,GAAOJ,EAAe,QAAQ;AACxE,iBAAOM,IAAMA,EAAI1D,CAAM,IAAIA;AAAA,QAC7B,GACM+G,IAAKnE,KAAA,OAAAA,IAAW,OAAO;AAC7B,YAAII,IAAOO,EAAA;AACX,eAAO,MAAM;AACX,gBAAMN,IAAOM,EAAA;AACb,iBAAOwD,EAAG/D,GAAMC,CAAI,IAAID,IAAQA,IAAOC;AAAA,QACzC;AAAA,MACF,GAAG,CAAC1B,GAAO6B,GAAgBM,GAAKd,CAAO,CAAC;AAExC,aAAOhG,EAAqBiG,GAAWE,GAAaA,CAAW;AAAA,IACjE;AAAA,IAsGE,gBA/FyB,CACzBc,GACAlB,GACAC,IAAmC,OAAO,OACpC;AACN,YAAMrB,IAAQW,EAAA,GACR6B,IAAatH,EAAO,CAAC,GACrBuH,IAAavH,EAAsB,MAAS,GAC5CwH,IAAaxH,EAAe,EAAE,GAE9ByH,IAAkBvH,EAAQ,MACvBkH,EAAM,IAAI,CAACM,OAAQ;AAAA,QACxB,SAASA,EAAG;AAAA,QACZ,UAAU,MAAM,QAAQA,EAAG,QAAQ,IAC9BA,EAAG,SAA+B,IAAI,CAACzC,MAAMC,EAAcD,CAAC,CAAC,IAC9DC,EAAcwC,EAAG,QAAkB;AAAA,MAAA,EACvC,GACD,CAAC,KAAK,UAAUN,CAAK,CAAC,CAAC,GAEpBhB,IAAYlG;AAAA,QAChB,MAAM,CAACmG,MAAuB;AAC5B,gBAAMsB,IAAO,MAAM;AACjB,YAAAL,EAAW,WACXjB,EAAA;AAAA,UACF,GACMuB,IAASH,EAAgB,QAAQ,CAACC,OACxB,MAAM,QAAQA,EAAG,QAAQ,IAAIA,EAAG,WAAW,CAACA,EAAG,QAAQ,GACxD,IAAI,CAACzC,MAAMH,EAAM,QAAQ,EAAE,SAAS4C,EAAG,SAAS,UAAUzC,EAAA,GAAK0C,CAAI,CAAC,CAClF;AACD,iBAAO,MAAM;AACX,uBAAWE,KAAKD,EAAQ,CAAAC,EAAA;AAAA,UAC1B;AAAA,QACF;AAAA,QACA,CAAC/C,GAAO2C,CAAe;AAAA,MAAA,GAGnBnB,IAAcpG,EAAQ,MACnB,MAAM;AACX,YAAIsH,EAAW,YAAYF,EAAW,SAAS;AAC7C,gBAAMd,IAAON,EAASpB,EAAM,SAAA,CAAU,GAChCgD,IAAOP,EAAW;AACxB,WAAIO,MAAS,UAAa,CAAC3B,EAAQ2B,GAAMtB,CAAI,SAAc,UAAUA,IACrEgB,EAAW,UAAUF,EAAW;AAAA,QAClC;AACA,eAAOC,EAAW;AAAA,MACpB,GACC,CAACzC,GAAOoB,GAAUC,CAAO,CAAC;AAE7B,aAAOhG,EAAqBiG,GAAWE,GAAaA,CAAW;AAAA,IACjE;AAAA,IA+CE,UAzCkC,CAIlC0B,GACArH,GACAsH,GAMAC,IAAoB,gBACX;AACT,YAAMpD,IAAQW,EAAA,GACR0C,IAAanI,EAAOiI,CAAO;AACjC,MAAAE,EAAW,UAAUF,GAErBhI,GAAU,MACD6E,EAAM;AAAA,QACXkD;AAAA,QACArH;AAAA,QACA,CAACyH,GAAOC,GAAUC,GAAMC,MAAe;AACrC,UAAAJ,EAAW;AAAA,YACTC;AAAA,YACAC;AAAA,YACAC;AAAA,YACAC;AAAA,UAAA;AAAA,QAEJ;AAAA,QACAL;AAAA,MAAA,GAED,CAACpD,GAAOkD,GAASrH,GAAMuH,CAAK,CAAC;AAAA,IAClC;AAAA,IASE,cAAAtC;AAAA,EAAA;AAEJ;","x_google_ignoreList":[1,2,3]}
@@ -0,0 +1,26 @@
1
+ import { StoreInstance } from '@yoltra/core';
2
+ /**
3
+ * React Context carrying a {@link StoreInstance} for yoltra React bindings.
4
+ *
5
+ * @remarks
6
+ * - The default value is `null`. Consumers should either:
7
+ * 1) Be wrapped with {@link StoreProvider}, or
8
+ * 2) Use a helper hook that throws a friendly error when the context is `null`.
9
+ * - You can scope multiple independent stores by nesting multiple providers.
10
+ *
11
+ * @example Basic usage
12
+ * ```tsx
13
+ * import { useContext } from "react";
14
+ * import { StoreContext } from "@yoltra/react";
15
+ *
16
+ * export function Counter() {
17
+ * const store = useContext(StoreContext);
18
+ * if (!store) throw new Error("StoreProvider is missing");
19
+ * const state = store.getState();
20
+ * return <span>{state.counter.value}</span>;
21
+ * }
22
+ * ```
23
+ *
24
+ * @public
25
+ */
26
+ export declare const StoreContext: import('react').Context<StoreInstance<any, any, any>>;
@@ -0,0 +1,54 @@
1
+ import { StoreInstance } from '@yoltra/core';
2
+ import { default as React, ReactNode } from 'react';
3
+ /**
4
+ * React provider that places a {@link StoreInstance} into {@link StoreContext}.
5
+ *
6
+ * @param props.store - The yoltra store instance to expose to descendant components.
7
+ * @param props.children - React subtree that will consume the store.
8
+ *
9
+ * @remarks
10
+ * - Wrap your app (or a subtree) to make the store available via `useContext(StoreContext)`
11
+ * or any higher-level hooks you expose (e.g., `useAtomicProp`, `useEmit`).
12
+ * - You may nest multiple `StoreProvider`s to scope different stores to different subtrees.
13
+ * - In Next.js App Router, this component must be used in a **client** boundary.
14
+ *
15
+ * @example App wrapper with createHooks (recommended)
16
+ * ```tsx
17
+ * // store.ts
18
+ * import { createStore, eventKeys } from '@yoltra/core';
19
+ * import { createContext } from 'react';
20
+ * import { createHooks, StoreProvider } from '@yoltra/react';
21
+ *
22
+ * type AppEM = { ui: { increment: number } };
23
+ * type AppState = { counter: { value: number } };
24
+ *
25
+ * export const store = createStore<AppState, AppEM>({
26
+ * name: 'App',
27
+ * reducer: {
28
+ * counter: {
29
+ * state: { value: 0 },
30
+ * when: { keys: eventKeys<AppEM>()([['ui', 'increment']]) },
31
+ * reducer: (s, evt) => evt.type === 'increment'
32
+ * ? { value: s.value + evt.payload }
33
+ * : s,
34
+ * },
35
+ * },
36
+ * });
37
+ *
38
+ * const AppStoreContext = createContext<typeof store | null>(null);
39
+ * export const { useAtomicProp, useEmit } = createHooks(AppStoreContext);
40
+ *
41
+ * // App.tsx
42
+ * export function App({ children }: { children: React.ReactNode }) {
43
+ * return <StoreProvider store={store}>{children}</StoreProvider>;
44
+ * }
45
+ * ```
46
+ *
47
+ * @public
48
+ */
49
+ export declare const StoreProvider: React.FC<{
50
+ /** yoltra store instance placed into context. */
51
+ store: StoreInstance<any, any, any>;
52
+ /** Descendant subtree that can consume the store. */
53
+ children: ReactNode;
54
+ }>;
@@ -0,0 +1,182 @@
1
+ import { DeepReadonly, Dotted, Emit, Event, EventMapBase, EventPhase, PathValue, StoreInstance, WithGlob } from '@yoltra/core';
2
+ import * as React from "react";
3
+ /**
4
+ * Call signature for the typed `useAtomicProp` hook returned by {@link createHooks}.
5
+ *
6
+ * Subscribes to a specific dotted path in a reducer's state and re-renders
7
+ * only when that path changes. All type parameters are inferred automatically
8
+ * from the store context — no explicit generics needed.
9
+ *
10
+ * @typeParam R - Reducer name union.
11
+ * @typeParam S - State record keyed by `R`.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const { useAtomicProp } = createHooks(AppStoreContext);
16
+ *
17
+ * function TodoTitle({ index }: { index: number }) {
18
+ * const title = useAtomicProp({
19
+ * reducer: 'todos',
20
+ * property: `items.${index}.title`,
21
+ * });
22
+ * return <span>{title}</span>;
23
+ * }
24
+ * ```
25
+ *
26
+ * @public
27
+ */
28
+ export type UseAtomicProp<R extends string, S extends Record<R, any>> = {
29
+ <R1 extends R, P extends Dotted<S[R1]>>(spec: {
30
+ reducer: R1;
31
+ property: P;
32
+ }): PathValue<S[R1], P>;
33
+ <R1 extends R, P extends Dotted<S[R1]>, T>(spec: {
34
+ reducer: R1;
35
+ property: P;
36
+ }, map: (value: PathValue<S[R1], P>) => T, isEqual?: (a: T, b: T) => boolean): T;
37
+ <R1 extends R, P extends WithGlob<Dotted<S[R1]>>, T>(spec: {
38
+ reducer: R1;
39
+ property: P;
40
+ }, map: (value: unknown) => T, isEqual?: (a: T, b: T) => boolean): T;
41
+ <R1 extends R>(spec: {
42
+ reducer: R1;
43
+ property: string;
44
+ }): unknown;
45
+ <R1 extends R, T>(spec: {
46
+ reducer: R1;
47
+ property: string;
48
+ }, map: (value: unknown) => T, isEqual?: (a: T, b: T) => boolean): T;
49
+ };
50
+ /**
51
+ * Call signature for the typed `useAtomicProps` hook returned by {@link createHooks}.
52
+ *
53
+ * Subscribes to multiple dotted paths across one or more reducers and recomputes
54
+ * a derived value when any of them change.
55
+ *
56
+ * @typeParam R - Reducer name union.
57
+ * @typeParam S - State record keyed by `R`.
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * const { useAtomicProps } = createHooks(AppStoreContext);
62
+ *
63
+ * function FilteredCount() {
64
+ * const count = useAtomicProps(
65
+ * [
66
+ * { reducer: 'todos', property: 'items.**' },
67
+ * { reducer: 'filter', property: 'q' },
68
+ * ],
69
+ * (s) => s.todos.items.filter(x => x.title.includes(s.filter.q)).length,
70
+ * );
71
+ * return <span>{count}</span>;
72
+ * }
73
+ * ```
74
+ *
75
+ * @public
76
+ */
77
+ export type UseAtomicProps<R extends string, S extends Record<R, any>> = {
78
+ <R1 extends R, T>(specs: Array<{
79
+ reducer: R1;
80
+ property: WithGlob<Dotted<S[R1]>> | readonly WithGlob<Dotted<S[R1]>>[];
81
+ }>, selector: (state: DeepReadonly<S>) => T, isEqual?: (a: T, b: T) => boolean): T;
82
+ <R1 extends R, T>(specs: Array<{
83
+ reducer: R1;
84
+ property: string | readonly string[];
85
+ }>, selector: (state: DeepReadonly<S>) => T, isEqual?: (a: T, b: T) => boolean): T;
86
+ };
87
+ /**
88
+ * Call signature for the typed `useEvent` hook returned by {@link createHooks}.
89
+ *
90
+ * Subscribes to store events from a React component. Useful for notifications,
91
+ * animations, analytics, and responding to rejected (uncommitted) events.
92
+ *
93
+ * @typeParam EM - Event map type.
94
+ * @typeParam S - Store state type.
95
+ *
96
+ * @example
97
+ * ```tsx
98
+ * const { useEvent } = createHooks(AppStoreContext);
99
+ *
100
+ * function SaveNotifier() {
101
+ * useEvent('ui', 'save', (event) => {
102
+ * showToast('Saved!');
103
+ * });
104
+ * return null;
105
+ * }
106
+ * ```
107
+ *
108
+ * @public
109
+ */
110
+ export type UseEvent<EM extends EventMapBase, S> = <C extends keyof EM & string, T extends keyof EM[C] & string>(channel: C, type: T, handler: (event: Event<EM, C, T>, getState: () => DeepReadonly<S>, emit: Emit<EM>, phase: "committed" | "uncommitted") => void | Promise<void>, phase?: EventPhase) => void;
111
+ /**
112
+ * Shallow object equality using `Object.is` per-key.
113
+ *
114
+ * Useful as the `isEqual` argument for `useAtomicProp` and `useAtomicProps`
115
+ * when the derived value is a plain object. Also available as a standalone
116
+ * export from `@yoltra/react` via {@link shallowEqual | hooks.shallowEqual}.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * shallowEqual({ a: 1 }, { a: 1 }); // true
121
+ * shallowEqual({ a: 1 }, { a: 2 }); // false
122
+ * ```
123
+ *
124
+ * @public
125
+ */
126
+ export declare function shallowEqual<T extends Record<string, unknown>>(a: T, b: T): boolean;
127
+ /**
128
+ * Factory that creates fully-typed React hooks bound to a specific store context.
129
+ *
130
+ * This is the **recommended** setup pattern for yoltra + React. It eliminates
131
+ * the need for explicit type parameters on every hook call — all types are
132
+ * inferred from the store context once, at creation time.
133
+ *
134
+ * @typeParam R - Reducer name union.
135
+ * @typeParam S - State record keyed by `R`.
136
+ * @typeParam EM - Event map.
137
+ *
138
+ * @param StoreContext - A React context carrying a `StoreInstance<R, S, EM>`.
139
+ * @returns An object with typed hooks: `useStore`, `useEmit`, `useSelector`,
140
+ * `useAtomicProp`, `useAtomicProps`, `useEvent`, and `shallowEqual`.
141
+ *
142
+ * @throws If any returned hook is called outside a `<StoreProvider>`.
143
+ *
144
+ * @example Complete setup
145
+ * ```tsx
146
+ * // 1. Define your event map and state
147
+ * type AppEM = { ui: { increment: number; decrement: number } };
148
+ * type AppState = { counter: { value: number } };
149
+ *
150
+ * // 2. Create a typed context
151
+ * import { createContext } from 'react';
152
+ * import { StoreInstance } from '@yoltra/core';
153
+ * const AppStoreContext = createContext<
154
+ * StoreInstance<'counter', AppState, AppEM> | null
155
+ * >(null);
156
+ *
157
+ * // 3. Create typed hooks (do this once, export from a shared module)
158
+ * const { useAtomicProp, useEmit, useEvent } = createHooks(AppStoreContext);
159
+ *
160
+ * // 4. Use in components — no explicit generics needed
161
+ * function Counter() {
162
+ * const value = useAtomicProp({ reducer: 'counter', property: 'value' });
163
+ * const emit = useEmit();
164
+ * return (
165
+ * <button onClick={() => emit('ui', 'increment', 1)}>
166
+ * Count: {value}
167
+ * </button>
168
+ * );
169
+ * }
170
+ * ```
171
+ *
172
+ * @public
173
+ */
174
+ export declare function createHooks<R extends string, S extends Record<R, any>, EM extends EventMapBase>(StoreContext: React.Context<StoreInstance<R, S, EM> | null>): {
175
+ useStore: () => StoreInstance<R, S, EM>;
176
+ useEmit: () => Emit<EM>;
177
+ useSelector: <T>(selector: (state: DeepReadonly<S>) => T, isEqual?: (a: T, b: T) => boolean) => T;
178
+ useAtomicProp: UseAtomicProp<R, S>;
179
+ useAtomicProps: UseAtomicProps<R, S>;
180
+ useEvent: UseEvent<EM, S>;
181
+ shallowEqual: typeof shallowEqual;
182
+ };