{"version":3,"file":"index.modern.js","sources":["../src/index.ts"],"sourcesContent":["import {\n  ComponentType,\n  Context as ContextOrig,\n  MutableRefObject,\n  Provider,\n  ReactNode,\n  createElement,\n  createContext as createContextOrig,\n  useContext as useContextOrig,\n  useEffect,\n  useLayoutEffect,\n  useReducer,\n  useRef,\n  useState,\n} from 'react';\nimport {\n  unstable_NormalPriority as NormalPriority,\n  unstable_runWithPriority as runWithPriority,\n} from 'scheduler';\n\nimport { batchedUpdates } from './batchedUpdates';\n\nconst CONTEXT_VALUE = Symbol();\nconst ORIGINAL_PROVIDER = Symbol();\n\nconst isSSR = typeof window === 'undefined'\n  || /ServerSideRendering/.test(window.navigator && window.navigator.userAgent);\n\nconst useIsomorphicLayoutEffect = isSSR ? useEffect : useLayoutEffect;\n\n// for preact that doesn't have runWithPriority\nconst runWithNormalPriority = runWithPriority\n  ? (thunk: () => void) => runWithPriority(NormalPriority, thunk)\n  : (thunk: () => void) => thunk();\n\ntype Version = number;\ntype Listener<Value> = (\n  action: { n: Version, p?: Promise<Value>, v?: Value }\n) => void\n\ntype ContextValue<Value> = {\n  [CONTEXT_VALUE]: {\n    /* \"v\"alue     */ v: MutableRefObject<Value>;\n    /* versio\"n\"   */ n: MutableRefObject<Version>;\n    /* \"l\"isteners */ l: Set<Listener<Value>>;\n    /* \"u\"pdate    */ u: (thunk: () => void, options?: { suspense: boolean }) => void;\n  };\n};\n\nexport interface Context<Value> {\n  Provider: ComponentType<{ value: Value; children: ReactNode }>;\n  displayName?: string;\n}\n\nconst createProvider = <Value>(\n  ProviderOrig: Provider<ContextValue<Value>>,\n) => {\n  const ContextProvider = ({ value, children }: { value: Value; children: ReactNode }) => {\n    const valueRef = useRef(value);\n    const versionRef = useRef(0);\n    const [resolve, setResolve] = useState<((v: Value) => void) | null>(null);\n    if (resolve) {\n      resolve(value);\n      setResolve(null);\n    }\n    const contextValue = useRef<ContextValue<Value>>();\n    if (!contextValue.current) {\n      const listeners = new Set<Listener<Value>>();\n      const update = (thunk: () => void, options?: { suspense: boolean }) => {\n        batchedUpdates(() => {\n          versionRef.current += 1;\n          const action: Parameters<Listener<Value>>[0] = {\n            n: versionRef.current,\n          };\n          if (options?.suspense) {\n            action.n *= -1; // this is intentional to make it temporary version\n            action.p = new Promise<Value>((r) => {\n              setResolve(() => (v: Value) => {\n                action.v = v;\n                delete action.p;\n                r(v);\n              });\n            });\n          }\n          listeners.forEach((listener) => listener(action));\n          thunk();\n        });\n      };\n      contextValue.current = {\n        [CONTEXT_VALUE]: {\n          /* \"v\"alue     */ v: valueRef,\n          /* versio\"n\"   */ n: versionRef,\n          /* \"l\"isteners */ l: listeners,\n          /* \"u\"pdate    */ u: update,\n        },\n      };\n    }\n    useIsomorphicLayoutEffect(() => {\n      valueRef.current = value;\n      versionRef.current += 1;\n      runWithNormalPriority(() => {\n        (contextValue.current as ContextValue<Value>)[CONTEXT_VALUE].l.forEach((listener) => {\n          listener({ n: versionRef.current, v: value });\n        });\n      });\n    }, [value]);\n    return createElement(ProviderOrig, { value: contextValue.current }, children);\n  };\n  return ContextProvider;\n};\n\nconst identity = <T>(x: T) => x;\n\n/**\n * This creates a special context for `useContextSelector`.\n *\n * @example\n * import { createContext } from 'use-context-selector';\n *\n * const PersonContext = createContext({ firstName: '', familyName: '' });\n */\nexport function createContext<Value>(defaultValue: Value) {\n  const context = createContextOrig<ContextValue<Value>>({\n    [CONTEXT_VALUE]: {\n      /* \"v\"alue     */ v: { current: defaultValue },\n      /* versio\"n\"   */ n: { current: -1 },\n      /* \"l\"isteners */ l: new Set(),\n      /* \"u\"pdate    */ u: (f) => f(),\n    },\n  });\n  (context as unknown as {\n    [ORIGINAL_PROVIDER]: Provider<ContextValue<Value>>;\n  })[ORIGINAL_PROVIDER] = context.Provider;\n  (context as unknown as Context<Value>).Provider = createProvider(context.Provider);\n  delete (context as any).Consumer; // no support for Consumer\n  return context as unknown as Context<Value>;\n}\n\n/**\n * This hook returns context selected value by selector.\n *\n * It will only accept context created by `createContext`.\n * It will trigger re-render if only the selected value is referentially changed.\n *\n * The selector should return referentially equal result for same input for better performance.\n *\n * @example\n * import { useContextSelector } from 'use-context-selector';\n *\n * const firstName = useContextSelector(PersonContext, state => state.firstName);\n */\nexport function useContextSelector<Value, Selected>(\n  context: Context<Value>,\n  selector: (value: Value) => Selected,\n) {\n  const contextValue = useContextOrig(\n    context as unknown as ContextOrig<ContextValue<Value>>,\n  )[CONTEXT_VALUE];\n  if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {\n    if (!contextValue) {\n      throw new Error('useContextSelector requires special context');\n    }\n  }\n  const {\n    /* \"v\"alue     */ v: { current: value },\n    /* versio\"n\"   */ n: { current: version },\n    /* \"l\"isteners */ l: listeners,\n  } = contextValue;\n  const selected = selector(value);\n  const [state, dispatch] = useReducer((\n    prev: readonly [Value, Selected],\n    action?: Parameters<Listener<Value>>[0],\n  ) => {\n    if (!action) {\n      // case for `dispatch()` below\n      return [value, selected] as const;\n    }\n    if ('p' in action) {\n      throw action.p;\n    }\n    if (action.n === version) {\n      if (Object.is(prev[1], selected)) {\n        return prev; // bail out\n      }\n      return [value, selected] as const;\n    }\n    try {\n      if ('v' in action) {\n        if (Object.is(prev[0], action.v)) {\n          return prev; // do not update\n        }\n        const nextSelected = selector(action.v);\n        if (Object.is(prev[1], nextSelected)) {\n          return prev; // do not update\n        }\n        return [action.v, nextSelected] as const;\n      }\n    } catch (e) {\n      // ignored (stale props or some other reason)\n    }\n    return [...prev] as const; // schedule update\n  }, [value, selected] as const);\n  if (!Object.is(state[1], selected)) {\n    // schedule re-render\n    // this is safe because it's self contained\n    dispatch();\n  }\n  useIsomorphicLayoutEffect(() => {\n    listeners.add(dispatch);\n    return () => {\n      listeners.delete(dispatch);\n    };\n  }, [listeners]);\n  return state[1];\n}\n\n/**\n * This hook returns the entire context value.\n * Use this instead of React.useContext for consistent behavior.\n *\n * @example\n * import { useContext } from 'use-context-selector';\n *\n * const person = useContext(PersonContext);\n */\nexport function useContext<Value>(context: Context<Value>) {\n  return useContextSelector(context, identity);\n}\n\n/**\n * This hook returns an update function that accepts a thunk function\n *\n * Use this for a function that will change a value in\n * concurrent rendering in React 18.\n * Otherwise, there's no need to use this hook.\n *\n * @example\n * import { useContextUpdate } from 'use-context-selector';\n *\n * const update = useContextUpdate();\n *\n * // Wrap set state function\n * update(() => setState(...));\n *\n * // Experimental suspense mode\n * update(() => setState(...), { suspense: true });\n */\nexport function useContextUpdate<Value>(context: Context<Value>) {\n  const contextValue = useContextOrig(\n    context as unknown as ContextOrig<ContextValue<Value>>,\n  )[CONTEXT_VALUE];\n  if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {\n    if (!contextValue) {\n      throw new Error('useContextUpdate requires special context');\n    }\n  }\n  const { u: update } = contextValue;\n  return update;\n}\n\n/**\n * This is a Provider component for bridging multiple react roots\n *\n * @example\n * const valueToBridge = useBridgeValue(PersonContext);\n * return (\n *   <Renderer>\n *     <BridgeProvider context={PersonContext} value={valueToBridge}>\n *       {children}\n *     </BridgeProvider>\n *   </Renderer>\n * );\n */\nexport const BridgeProvider = ({ context, value, children }:{\n  context: Context<any>;\n  value: any;\n  children: ReactNode;\n}) => {\n  const { [ORIGINAL_PROVIDER]: ProviderOrig } = context as unknown as {\n    [ORIGINAL_PROVIDER]: Provider<unknown>;\n  };\n  if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {\n    if (!ProviderOrig) {\n      throw new Error('BridgeProvider requires special context');\n    }\n  }\n  return createElement(ProviderOrig, { value }, children);\n};\n\n/**\n * This hook return a value for BridgeProvider\n */\nexport const useBridgeValue = (context: Context<any>) => {\n  const bridgeValue = useContextOrig(context as unknown as ContextOrig<ContextValue<unknown>>);\n  if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {\n    if (!bridgeValue[CONTEXT_VALUE]) {\n      throw new Error('useBridgeValue requires special context');\n    }\n  }\n  return bridgeValue as any;\n};\n"],"names":["CONTEXT_VALUE","Symbol","ORIGINAL_PROVIDER","useIsomorphicLayoutEffect","window","test","navigator","userAgent","useEffect","useLayoutEffect","runWithNormalPriority","runWithPriority","thunk","NormalPriority","identity","x","createContext","defaultValue","context","createContextOrig","v","current","n","l","Set","u","f","ProviderOrig","Provider","value","children","valueRef","useRef","versionRef","resolve","setResolve","useState","contextValue","update","options","batchedUpdates","action","suspense","p","Promise","r","listeners","forEach","listener","createElement","Consumer","useContextSelector","selector","useContextOrig","process","env","NODE_ENV","Error","version","selected","state","dispatch","useReducer","prev","Object","is","nextSelected","e","add","delete","useContext","BridgeProvider","useBridgeValue","bridgeValue"],"mappings":"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"}