{"version":3,"sources":["../src/useContextSelector.ts"],"sourcesContent":["'use client';\n\nimport { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { Context, ContextSelector, ContextValue } from './types';\n\n/**\n * This hook returns context selected value by selector.\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 * @internal\n */\nexport const useContextSelector = <Value, SelectedValue>(\n  context: Context<Value>,\n  selectorFn: ContextSelector<Value, SelectedValue>,\n): SelectedValue => {\n  const contextValue = React.useContext(context as unknown as Context<ContextValue<Value>>);\n  const { value: valueRef, listeners } = contextValue;\n\n  // Read valueRef during render and return selector(value) directly. This is analogous to `useSyncExternalStore`'s\n  // `getSnapshot` and is the only way to select a slice from a shared ref-based store without re-rendering every\n  // consumer on every provider update.\n  // eslint-disable-next-line react-hooks/refs\n  const valueAtRender = selectorFn(valueRef.current);\n  const [, forceUpdate] = React.useReducer((x: number) => x + 1, 0);\n\n  // Refs holding the current selector and the most-recently-returned slice.\n  // Updated in a layout effect (ordering: children first, then provider) so\n  // they are current by the time the provider's listener loop fires.\n  const selectorFnRef = React.useRef<ContextSelector<Value, SelectedValue>>(selectorFn);\n  const lastValueAtRender = React.useRef<SelectedValue>(valueAtRender);\n\n  useIsomorphicLayoutEffect(() => {\n    selectorFnRef.current = selectorFn;\n    lastValueAtRender.current = valueAtRender;\n  });\n\n  useIsomorphicLayoutEffect(() => {\n    const listener = (payload: Value) => {\n      // Selectors can throw on transiently-inconsistent inputs (stale props vs. newer context value). Swallow so a\n      // single consumer's throw doesn't abort the provider's `listeners.forEach`.\n      try {\n        const nextSelectedValue = selectorFnRef.current(payload);\n\n        if (!Object.is(lastValueAtRender.current, nextSelectedValue)) {\n          forceUpdate();\n        }\n      } catch {\n        // ignored (stale props or similar — heals on the next parent-driven render)\n      }\n    };\n\n    listeners.push(listener);\n\n    // Effect-fixup: catch updates that occurred between render and effect run (Relay's useFragmentInternal pattern).\n    listener(valueRef.current);\n\n    return () => {\n      const index = listeners.indexOf(listener);\n\n      if (index !== -1) {\n        listeners.splice(index, 1);\n      }\n    };\n  }, [listeners, valueRef]);\n\n  return valueAtRender;\n};\n"],"names":["useContextSelector","context","selectorFn","contextValue","React","useContext","value","valueRef","listeners","valueAtRender","current","forceUpdate","useReducer","x","selectorFnRef","useRef","lastValueAtRender","useIsomorphicLayoutEffect","listener","payload","nextSelectedValue","Object","is","push","index","indexOf","splice"],"mappings":"AAAA;;;;;+BAcaA;;;eAAAA;;;;gCAZ6B;iEACnB;AAWhB,MAAMA,qBAAqB,CAChCC,SACAC;IAEA,MAAMC,eAAeC,OAAMC,UAAU,CAACJ;IACtC,MAAM,EAAEK,OAAOC,QAAQ,EAAEC,SAAS,EAAE,GAAGL;IAEvC,iHAAiH;IACjH,+GAA+G;IAC/G,qCAAqC;IACrC,4CAA4C;IAC5C,MAAMM,gBAAgBP,WAAWK,SAASG,OAAO;IACjD,MAAM,GAAGC,YAAY,GAAGP,OAAMQ,UAAU,CAAC,CAACC,IAAcA,IAAI,GAAG;IAE/D,0EAA0E;IAC1E,0EAA0E;IAC1E,mEAAmE;IACnE,MAAMC,gBAAgBV,OAAMW,MAAM,CAAwCb;IAC1E,MAAMc,oBAAoBZ,OAAMW,MAAM,CAAgBN;IAEtDQ,IAAAA,yCAAyB,EAAC;QACxBH,cAAcJ,OAAO,GAAGR;QACxBc,kBAAkBN,OAAO,GAAGD;IAC9B;IAEAQ,IAAAA,yCAAyB,EAAC;QACxB,MAAMC,WAAW,CAACC;YAChB,6GAA6G;YAC7G,4EAA4E;YAC5E,IAAI;gBACF,MAAMC,oBAAoBN,cAAcJ,OAAO,CAACS;gBAEhD,IAAI,CAACE,OAAOC,EAAE,CAACN,kBAAkBN,OAAO,EAAEU,oBAAoB;oBAC5DT;gBACF;YACF,EAAE,OAAM;YACN,4EAA4E;YAC9E;QACF;QAEAH,UAAUe,IAAI,CAACL;QAEf,iHAAiH;QACjHA,SAASX,SAASG,OAAO;QAEzB,OAAO;YACL,MAAMc,QAAQhB,UAAUiB,OAAO,CAACP;YAEhC,IAAIM,UAAU,CAAC,GAAG;gBAChBhB,UAAUkB,MAAM,CAACF,OAAO;YAC1B;QACF;IACF,GAAG;QAAChB;QAAWD;KAAS;IAExB,OAAOE;AACT"}