{"version":3,"file":"Transitioner.cjs","names":[],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["import * as React from 'react'\nimport { batch, useStore } from '@tanstack/react-store'\nimport {\n  getLocationChangeInfo,\n  handleHashScroll,\n  trimPathRight,\n} from '@tanstack/router-core'\nimport { useLayoutEffect, usePrevious } from './utils'\nimport { useRouter } from './useRouter'\n\nexport function Transitioner() {\n  const router = useRouter()\n  const mountLoadForRouter = React.useRef({ router, mounted: false })\n\n  const [isTransitioning, setIsTransitioning] = React.useState(false)\n  // Track pending state changes\n  const isLoading = useStore(router.stores.isLoading, (value) => value)\n  const hasPendingMatches = useStore(\n    router.stores.hasPendingMatches,\n    (value) => value,\n  )\n\n  const previousIsLoading = usePrevious(isLoading)\n\n  const isAnyPending = isLoading || isTransitioning || hasPendingMatches\n  const previousIsAnyPending = usePrevious(isAnyPending)\n\n  const isPagePending = isLoading || hasPendingMatches\n  const previousIsPagePending = usePrevious(isPagePending)\n\n  router.startTransition = (fn: () => void) => {\n    setIsTransitioning(true)\n    React.startTransition(() => {\n      fn()\n      setIsTransitioning(false)\n    })\n  }\n\n  // Subscribe to location changes\n  // and try to load the new location\n  React.useEffect(() => {\n    const unsub = router.history.subscribe(router.load)\n\n    const nextLocation = router.buildLocation({\n      to: router.latestLocation.pathname,\n      search: true,\n      params: true,\n      hash: true,\n      state: true,\n      _includeValidateSearch: true,\n    })\n\n    // Check if the current URL matches the canonical form.\n    // Compare publicHref (browser-facing URL) for consistency with\n    // the server-side redirect check in router.beforeLoad.\n    if (\n      trimPathRight(router.latestLocation.publicHref) !==\n      trimPathRight(nextLocation.publicHref)\n    ) {\n      router.commitLocation({ ...nextLocation, replace: true })\n    }\n\n    return () => {\n      unsub()\n    }\n  }, [router, router.history])\n\n  // Try to load the initial location\n  useLayoutEffect(() => {\n    if (\n      // if we are hydrating from SSR, loading is triggered in ssr-client\n      (typeof window !== 'undefined' && router.ssr) ||\n      (mountLoadForRouter.current.router === router &&\n        mountLoadForRouter.current.mounted)\n    ) {\n      return\n    }\n    mountLoadForRouter.current = { router, mounted: true }\n\n    const tryLoad = async () => {\n      try {\n        await router.load()\n      } catch (err) {\n        console.error(err)\n      }\n    }\n\n    tryLoad()\n  }, [router])\n\n  useLayoutEffect(() => {\n    // The router was loading and now it's not\n    if (previousIsLoading && !isLoading) {\n      router.emit({\n        type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches\n        ...getLocationChangeInfo(\n          router.stores.location.state,\n          router.stores.resolvedLocation.state,\n        ),\n      })\n    }\n  }, [previousIsLoading, router, isLoading])\n\n  useLayoutEffect(() => {\n    // emit onBeforeRouteMount\n    if (previousIsPagePending && !isPagePending) {\n      router.emit({\n        type: 'onBeforeRouteMount',\n        ...getLocationChangeInfo(\n          router.stores.location.state,\n          router.stores.resolvedLocation.state,\n        ),\n      })\n    }\n  }, [isPagePending, previousIsPagePending, router])\n\n  useLayoutEffect(() => {\n    if (previousIsAnyPending && !isAnyPending) {\n      const changeInfo = getLocationChangeInfo(\n        router.stores.location.state,\n        router.stores.resolvedLocation.state,\n      )\n      router.emit({\n        type: 'onResolved',\n        ...changeInfo,\n      })\n\n      batch(() => {\n        router.stores.status.setState(() => 'idle')\n        router.stores.resolvedLocation.setState(\n          () => router.stores.location.state,\n        )\n      })\n\n      if (changeInfo.hrefChanged) {\n        handleHashScroll(router)\n      }\n    }\n  }, [isAnyPending, previousIsAnyPending, router])\n\n  return null\n}\n"],"mappings":";;;;;;;;AAUA,SAAgB,eAAe;CAC7B,MAAM,SAAS,kBAAA,WAAW;CAC1B,MAAM,qBAAqB,MAAM,OAAO;EAAE;EAAQ,SAAS;EAAO,CAAC;CAEnE,MAAM,CAAC,iBAAiB,sBAAsB,MAAM,SAAS,MAAM;CAEnE,MAAM,aAAA,GAAA,sBAAA,UAAqB,OAAO,OAAO,YAAY,UAAU,MAAM;CACrE,MAAM,qBAAA,GAAA,sBAAA,UACJ,OAAO,OAAO,oBACb,UAAU,MACZ;CAED,MAAM,oBAAoB,cAAA,YAAY,UAAU;CAEhD,MAAM,eAAe,aAAa,mBAAmB;CACrD,MAAM,uBAAuB,cAAA,YAAY,aAAa;CAEtD,MAAM,gBAAgB,aAAa;CACnC,MAAM,wBAAwB,cAAA,YAAY,cAAc;AAExD,QAAO,mBAAmB,OAAmB;AAC3C,qBAAmB,KAAK;AACxB,QAAM,sBAAsB;AAC1B,OAAI;AACJ,sBAAmB,MAAM;IACzB;;AAKJ,OAAM,gBAAgB;EACpB,MAAM,QAAQ,OAAO,QAAQ,UAAU,OAAO,KAAK;EAEnD,MAAM,eAAe,OAAO,cAAc;GACxC,IAAI,OAAO,eAAe;GAC1B,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;GACP,wBAAwB;GACzB,CAAC;AAKF,OAAA,GAAA,sBAAA,eACgB,OAAO,eAAe,WAAW,MAAA,GAAA,sBAAA,eACjC,aAAa,WAAW,CAEtC,QAAO,eAAe;GAAE,GAAG;GAAc,SAAS;GAAM,CAAC;AAG3D,eAAa;AACX,UAAO;;IAER,CAAC,QAAQ,OAAO,QAAQ,CAAC;AAG5B,eAAA,sBAAsB;AACpB,MAEG,OAAO,WAAW,eAAe,OAAO,OACxC,mBAAmB,QAAQ,WAAW,UACrC,mBAAmB,QAAQ,QAE7B;AAEF,qBAAmB,UAAU;GAAE;GAAQ,SAAS;GAAM;EAEtD,MAAM,UAAU,YAAY;AAC1B,OAAI;AACF,UAAM,OAAO,MAAM;YACZ,KAAK;AACZ,YAAQ,MAAM,IAAI;;;AAItB,WAAS;IACR,CAAC,OAAO,CAAC;AAEZ,eAAA,sBAAsB;AAEpB,MAAI,qBAAqB,CAAC,UACxB,QAAO,KAAK;GACV,MAAM;GACN,IAAA,GAAA,sBAAA,uBACE,OAAO,OAAO,SAAS,OACvB,OAAO,OAAO,iBAAiB,MAChC;GACF,CAAC;IAEH;EAAC;EAAmB;EAAQ;EAAU,CAAC;AAE1C,eAAA,sBAAsB;AAEpB,MAAI,yBAAyB,CAAC,cAC5B,QAAO,KAAK;GACV,MAAM;GACN,IAAA,GAAA,sBAAA,uBACE,OAAO,OAAO,SAAS,OACvB,OAAO,OAAO,iBAAiB,MAChC;GACF,CAAC;IAEH;EAAC;EAAe;EAAuB;EAAO,CAAC;AAElD,eAAA,sBAAsB;AACpB,MAAI,wBAAwB,CAAC,cAAc;GACzC,MAAM,cAAA,GAAA,sBAAA,uBACJ,OAAO,OAAO,SAAS,OACvB,OAAO,OAAO,iBAAiB,MAChC;AACD,UAAO,KAAK;IACV,MAAM;IACN,GAAG;IACJ,CAAC;AAEF,IAAA,GAAA,sBAAA,aAAY;AACV,WAAO,OAAO,OAAO,eAAe,OAAO;AAC3C,WAAO,OAAO,iBAAiB,eACvB,OAAO,OAAO,SAAS,MAC9B;KACD;AAEF,OAAI,WAAW,YACb,EAAA,GAAA,sBAAA,kBAAiB,OAAO;;IAG3B;EAAC;EAAc;EAAsB;EAAO,CAAC;AAEhD,QAAO"}