one 1.2.57 → 1.2.58
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.
- package/dist/cjs/cli/buildPage.cjs +1 -1
- package/dist/cjs/cli/buildPage.js +1 -1
- package/dist/cjs/cli/buildPage.native.js +1 -1
- package/dist/cjs/cli/buildPage.native.js.map +1 -1
- package/dist/cjs/cli/dev.cjs +4 -4
- package/dist/cjs/cli/dev.js +4 -4
- package/dist/cjs/cli/dev.js.map +1 -1
- package/dist/cjs/cli/dev.native.js +4 -4
- package/dist/cjs/cli/dev.native.js.map +1 -1
- package/dist/cjs/createApp.cjs +2 -1
- package/dist/cjs/createApp.js +2 -2
- package/dist/cjs/createApp.js.map +1 -1
- package/dist/cjs/createHandleRequest.test.js +3 -1
- package/dist/cjs/createHandleRequest.test.js.map +1 -1
- package/dist/cjs/createHandleRequest.test.native.js.map +1 -1
- package/dist/cjs/devtools/registry.cjs +30 -0
- package/dist/cjs/devtools/registry.js +25 -0
- package/dist/cjs/devtools/registry.js.map +6 -0
- package/dist/cjs/devtools/registry.native.js +33 -0
- package/dist/cjs/devtools/registry.native.js.map +1 -0
- package/dist/cjs/fork/createMemoryHistory.cjs +20 -9
- package/dist/cjs/fork/createMemoryHistory.js +22 -4
- package/dist/cjs/fork/createMemoryHistory.js.map +1 -1
- package/dist/cjs/fork/createMemoryHistory.native.js +20 -9
- package/dist/cjs/fork/createMemoryHistory.native.js.map +1 -1
- package/dist/cjs/fork/useLinking.cjs +11 -5
- package/dist/cjs/fork/useLinking.js +6 -6
- package/dist/cjs/fork/useLinking.js.map +1 -1
- package/dist/cjs/index.cjs +17 -1
- package/dist/cjs/index.js +12 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.native.js +17 -1
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/layouts/withLayoutContext.cjs +34 -15
- package/dist/cjs/layouts/withLayoutContext.js +29 -13
- package/dist/cjs/layouts/withLayoutContext.js.map +1 -1
- package/dist/cjs/layouts/withLayoutContext.native.js +42 -19
- package/dist/cjs/layouts/withLayoutContext.native.js.map +1 -1
- package/dist/cjs/link/Link.cjs +5 -2
- package/dist/cjs/link/Link.js +3 -2
- package/dist/cjs/link/Link.js.map +1 -1
- package/dist/cjs/link/Link.native.js +6 -1
- package/dist/cjs/link/Link.native.js.map +1 -1
- package/dist/cjs/link/useLinkTo.cjs +11 -3
- package/dist/cjs/link/useLinkTo.js +6 -3
- package/dist/cjs/link/useLinkTo.js.map +1 -1
- package/dist/cjs/link/useLinkTo.native.js +11 -3
- package/dist/cjs/link/useLinkTo.native.js.map +1 -1
- package/dist/cjs/router/Route.js.map +1 -1
- package/dist/cjs/router/Route.native.js.map +1 -1
- package/dist/cjs/router/findRouteNode.cjs +70 -0
- package/dist/cjs/router/findRouteNode.js +72 -0
- package/dist/cjs/router/findRouteNode.js.map +6 -0
- package/dist/cjs/router/findRouteNode.native.js +104 -0
- package/dist/cjs/router/findRouteNode.native.js.map +1 -0
- package/dist/cjs/router/router.cjs +160 -11
- package/dist/cjs/router/router.js +142 -7
- package/dist/cjs/router/router.js.map +2 -2
- package/dist/cjs/router/router.native.js +241 -57
- package/dist/cjs/router/router.native.js.map +1 -1
- package/dist/cjs/router/useScreens.cjs +1 -1
- package/dist/cjs/router/useScreens.js +1 -1
- package/dist/cjs/router/useScreens.js.map +1 -1
- package/dist/cjs/router/useScreens.native.js +5 -2
- package/dist/cjs/router/useScreens.native.js.map +1 -1
- package/dist/cjs/server/oneServe.js.map +1 -1
- package/dist/cjs/server/oneServe.native.js.map +1 -1
- package/dist/cjs/useBlocker.cjs +158 -0
- package/dist/cjs/useBlocker.js +145 -0
- package/dist/cjs/useBlocker.js.map +6 -0
- package/dist/cjs/useBlocker.native.js +89 -0
- package/dist/cjs/useBlocker.native.js.map +1 -0
- package/dist/cjs/useLoader.cjs +69 -3
- package/dist/cjs/useLoader.js +57 -4
- package/dist/cjs/useLoader.js.map +2 -2
- package/dist/cjs/useLoader.native.js +90 -6
- package/dist/cjs/useLoader.native.js.map +1 -1
- package/dist/cjs/useScrollGroup.cjs +37 -0
- package/dist/cjs/useScrollGroup.js +30 -0
- package/dist/cjs/useScrollGroup.js.map +6 -0
- package/dist/cjs/useScrollGroup.native.js +29 -0
- package/dist/cjs/useScrollGroup.native.js.map +1 -0
- package/dist/cjs/validateParams.cjs +80 -0
- package/dist/cjs/validateParams.js +84 -0
- package/dist/cjs/validateParams.js.map +6 -0
- package/dist/cjs/validateParams.native.js +180 -0
- package/dist/cjs/validateParams.native.js.map +1 -0
- package/dist/cjs/validateSearch.cjs +104 -0
- package/dist/cjs/validateSearch.js +99 -0
- package/dist/cjs/validateSearch.js.map +6 -0
- package/dist/cjs/validateSearch.native.js +202 -0
- package/dist/cjs/validateSearch.native.js.map +1 -0
- package/dist/cjs/views/ErrorBoundary.cjs +293 -10
- package/dist/cjs/views/ErrorBoundary.js +328 -8
- package/dist/cjs/views/ErrorBoundary.js.map +2 -2
- package/dist/cjs/views/ErrorBoundary.native.js +159 -4
- package/dist/cjs/views/ErrorBoundary.native.js.map +1 -1
- package/dist/cjs/views/Navigator.cjs +10 -3
- package/dist/cjs/views/Navigator.js +7 -3
- package/dist/cjs/views/Navigator.js.map +1 -1
- package/dist/cjs/views/Navigator.native.js +12 -3
- package/dist/cjs/views/Navigator.native.js.map +1 -1
- package/dist/cjs/views/Protected.cjs +36 -0
- package/dist/cjs/views/Protected.js +27 -0
- package/dist/cjs/views/Protected.js.map +6 -0
- package/dist/cjs/views/Protected.native.js +44 -0
- package/dist/cjs/views/Protected.native.js.map +1 -0
- package/dist/cjs/views/RootErrorBoundary.cjs +193 -8
- package/dist/cjs/views/RootErrorBoundary.js +213 -8
- package/dist/cjs/views/RootErrorBoundary.js.map +1 -1
- package/dist/cjs/views/RootErrorBoundary.native.js +192 -8
- package/dist/cjs/views/RootErrorBoundary.native.js.map +1 -1
- package/dist/cjs/views/ScrollBehavior.cjs +49 -11
- package/dist/cjs/views/ScrollBehavior.js +47 -11
- package/dist/cjs/views/ScrollBehavior.js.map +1 -1
- package/dist/cjs/views/ScrollBehavior.native.js +68 -10
- package/dist/cjs/views/ScrollBehavior.native.js.map +1 -1
- package/dist/cjs/views/SourceInspector.cjs +28 -0
- package/dist/cjs/views/SourceInspector.js +23 -0
- package/dist/cjs/views/SourceInspector.js.map +6 -0
- package/dist/cjs/views/SourceInspector.native.js +32 -0
- package/dist/cjs/views/SourceInspector.native.js.map +1 -0
- package/dist/cjs/views/Try.cjs +40 -7
- package/dist/cjs/views/Try.js +38 -4
- package/dist/cjs/views/Try.js.map +1 -1
- package/dist/cjs/views/Try.native.js +42 -7
- package/dist/cjs/views/Try.native.js.map +1 -1
- package/dist/cjs/vite/DevHead.cjs +797 -43
- package/dist/cjs/vite/DevHead.js +802 -51
- package/dist/cjs/vite/DevHead.js.map +1 -1
- package/dist/cjs/vite/DevHead.native.js +783 -1
- package/dist/cjs/vite/DevHead.native.js.map +1 -1
- package/dist/cjs/vite/one.cjs +7 -1
- package/dist/cjs/vite/one.js +7 -2
- package/dist/cjs/vite/one.js.map +1 -1
- package/dist/cjs/vite/one.native.js +11 -1
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/cjs/vite/plugins/SSRCSSPlugin.cjs +44 -4
- package/dist/cjs/vite/plugins/SSRCSSPlugin.js +48 -4
- package/dist/cjs/vite/plugins/SSRCSSPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/SSRCSSPlugin.native.js +62 -5
- package/dist/cjs/vite/plugins/SSRCSSPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js +6 -3
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/generateFileSystemRouteTypesPlugin.cjs +5 -1
- package/dist/cjs/vite/plugins/generateFileSystemRouteTypesPlugin.js +11 -6
- package/dist/cjs/vite/plugins/generateFileSystemRouteTypesPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/generateFileSystemRouteTypesPlugin.native.js +1 -0
- package/dist/cjs/vite/plugins/generateFileSystemRouteTypesPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.cjs +155 -0
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.js +148 -0
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.js.map +6 -0
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.native.js +231 -0
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.native.js.map +1 -0
- package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +25 -6
- package/dist/cjs/vite/plugins/virtualEntryPlugin.js +16 -6
- package/dist/cjs/vite/plugins/virtualEntryPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +26 -7
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/esm/cli/buildPage.js +1 -1
- package/dist/esm/cli/buildPage.mjs +1 -1
- package/dist/esm/cli/buildPage.mjs.map +1 -1
- package/dist/esm/cli/buildPage.native.js +1 -1
- package/dist/esm/cli/buildPage.native.js.map +1 -1
- package/dist/esm/cli/dev.js +4 -4
- package/dist/esm/cli/dev.js.map +1 -1
- package/dist/esm/cli/dev.mjs +4 -4
- package/dist/esm/cli/dev.mjs.map +1 -1
- package/dist/esm/cli/dev.native.js +4 -4
- package/dist/esm/cli/dev.native.js.map +1 -1
- package/dist/esm/createApp.js +2 -2
- package/dist/esm/createApp.js.map +1 -1
- package/dist/esm/createApp.mjs +2 -1
- package/dist/esm/createApp.mjs.map +1 -1
- package/dist/esm/createHandleRequest.test.js +3 -1
- package/dist/esm/createHandleRequest.test.js.map +1 -1
- package/dist/esm/createHandleRequest.test.mjs.map +1 -1
- package/dist/esm/createHandleRequest.test.native.js.map +1 -1
- package/dist/esm/devtools/registry.js +9 -0
- package/dist/esm/devtools/registry.js.map +6 -0
- package/dist/esm/devtools/registry.mjs +6 -0
- package/dist/esm/devtools/registry.mjs.map +1 -0
- package/dist/esm/devtools/registry.native.js +6 -0
- package/dist/esm/devtools/registry.native.js.map +1 -0
- package/dist/esm/fork/createMemoryHistory.js +22 -4
- package/dist/esm/fork/createMemoryHistory.js.map +1 -1
- package/dist/esm/fork/createMemoryHistory.mjs +20 -9
- package/dist/esm/fork/createMemoryHistory.mjs.map +1 -1
- package/dist/esm/fork/createMemoryHistory.native.js +20 -9
- package/dist/esm/fork/createMemoryHistory.native.js.map +1 -1
- package/dist/esm/fork/useLinking.js +6 -5
- package/dist/esm/fork/useLinking.js.map +1 -1
- package/dist/esm/fork/useLinking.mjs +11 -5
- package/dist/esm/fork/useLinking.mjs.map +1 -1
- package/dist/esm/index.js +30 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +8 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +8 -2
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/layouts/withLayoutContext.js +30 -12
- package/dist/esm/layouts/withLayoutContext.js.map +1 -1
- package/dist/esm/layouts/withLayoutContext.mjs +34 -15
- package/dist/esm/layouts/withLayoutContext.mjs.map +1 -1
- package/dist/esm/layouts/withLayoutContext.native.js +42 -19
- package/dist/esm/layouts/withLayoutContext.native.js.map +1 -1
- package/dist/esm/link/Link.js +3 -2
- package/dist/esm/link/Link.js.map +1 -1
- package/dist/esm/link/Link.mjs +5 -2
- package/dist/esm/link/Link.mjs.map +1 -1
- package/dist/esm/link/Link.native.js +6 -1
- package/dist/esm/link/Link.native.js.map +1 -1
- package/dist/esm/link/useLinkTo.js +6 -3
- package/dist/esm/link/useLinkTo.js.map +1 -1
- package/dist/esm/link/useLinkTo.mjs +11 -3
- package/dist/esm/link/useLinkTo.mjs.map +1 -1
- package/dist/esm/link/useLinkTo.native.js +11 -3
- package/dist/esm/link/useLinkTo.native.js.map +1 -1
- package/dist/esm/router/Route.js.map +1 -1
- package/dist/esm/router/Route.mjs.map +1 -1
- package/dist/esm/router/Route.native.js.map +1 -1
- package/dist/esm/router/findRouteNode.js +56 -0
- package/dist/esm/router/findRouteNode.js.map +6 -0
- package/dist/esm/router/findRouteNode.mjs +44 -0
- package/dist/esm/router/findRouteNode.mjs.map +1 -0
- package/dist/esm/router/findRouteNode.native.js +75 -0
- package/dist/esm/router/findRouteNode.native.js.map +1 -0
- package/dist/esm/router/router.js +154 -6
- package/dist/esm/router/router.js.map +1 -1
- package/dist/esm/router/router.mjs +151 -10
- package/dist/esm/router/router.mjs.map +1 -1
- package/dist/esm/router/router.native.js +232 -56
- package/dist/esm/router/router.native.js.map +1 -1
- package/dist/esm/router/useScreens.js +1 -1
- package/dist/esm/router/useScreens.js.map +1 -1
- package/dist/esm/router/useScreens.mjs +1 -1
- package/dist/esm/router/useScreens.mjs.map +1 -1
- package/dist/esm/router/useScreens.native.js +5 -2
- package/dist/esm/router/useScreens.native.js.map +1 -1
- package/dist/esm/server/oneServe.js.map +1 -1
- package/dist/esm/server/oneServe.mjs.map +1 -1
- package/dist/esm/server/oneServe.native.js.map +1 -1
- package/dist/esm/useBlocker.js +122 -0
- package/dist/esm/useBlocker.js.map +6 -0
- package/dist/esm/useBlocker.mjs +123 -0
- package/dist/esm/useBlocker.mjs.map +1 -0
- package/dist/esm/useBlocker.native.js +51 -0
- package/dist/esm/useBlocker.native.js.map +1 -0
- package/dist/esm/useLoader.js +57 -3
- package/dist/esm/useLoader.js.map +2 -2
- package/dist/esm/useLoader.mjs +69 -4
- package/dist/esm/useLoader.mjs.map +1 -1
- package/dist/esm/useLoader.native.js +90 -7
- package/dist/esm/useLoader.native.js.map +1 -1
- package/dist/esm/useScrollGroup.js +16 -0
- package/dist/esm/useScrollGroup.js.map +6 -0
- package/dist/esm/useScrollGroup.mjs +14 -0
- package/dist/esm/useScrollGroup.mjs.map +1 -0
- package/dist/esm/useScrollGroup.native.js +3 -0
- package/dist/esm/useScrollGroup.native.js.map +1 -0
- package/dist/esm/validateParams.js +68 -0
- package/dist/esm/validateParams.js.map +6 -0
- package/dist/esm/validateParams.mjs +54 -0
- package/dist/esm/validateParams.mjs.map +1 -0
- package/dist/esm/validateParams.native.js +151 -0
- package/dist/esm/validateParams.native.js.map +1 -0
- package/dist/esm/validateSearch.js +83 -0
- package/dist/esm/validateSearch.js.map +6 -0
- package/dist/esm/validateSearch.mjs +77 -0
- package/dist/esm/validateSearch.mjs.map +1 -0
- package/dist/esm/validateSearch.native.js +172 -0
- package/dist/esm/validateSearch.native.js.map +1 -0
- package/dist/esm/views/ErrorBoundary.js +325 -7
- package/dist/esm/views/ErrorBoundary.js.map +2 -2
- package/dist/esm/views/ErrorBoundary.mjs +289 -6
- package/dist/esm/views/ErrorBoundary.mjs.map +1 -1
- package/dist/esm/views/ErrorBoundary.native.js +159 -4
- package/dist/esm/views/ErrorBoundary.native.js.map +1 -1
- package/dist/esm/views/Navigator.js +7 -2
- package/dist/esm/views/Navigator.js.map +1 -1
- package/dist/esm/views/Navigator.mjs +10 -3
- package/dist/esm/views/Navigator.mjs.map +1 -1
- package/dist/esm/views/Navigator.native.js +12 -3
- package/dist/esm/views/Navigator.native.js.map +1 -1
- package/dist/esm/views/Protected.js +14 -0
- package/dist/esm/views/Protected.js.map +6 -0
- package/dist/esm/views/Protected.mjs +11 -0
- package/dist/esm/views/Protected.mjs.map +1 -0
- package/dist/esm/views/Protected.native.js +16 -0
- package/dist/esm/views/Protected.native.js.map +1 -0
- package/dist/esm/views/RootErrorBoundary.js +214 -7
- package/dist/esm/views/RootErrorBoundary.js.map +1 -1
- package/dist/esm/views/RootErrorBoundary.mjs +192 -7
- package/dist/esm/views/RootErrorBoundary.mjs.map +1 -1
- package/dist/esm/views/RootErrorBoundary.native.js +191 -7
- package/dist/esm/views/RootErrorBoundary.native.js.map +1 -1
- package/dist/esm/views/ScrollBehavior.js +47 -11
- package/dist/esm/views/ScrollBehavior.js.map +1 -1
- package/dist/esm/views/ScrollBehavior.mjs +48 -11
- package/dist/esm/views/ScrollBehavior.mjs.map +1 -1
- package/dist/esm/views/ScrollBehavior.native.js +67 -10
- package/dist/esm/views/ScrollBehavior.native.js.map +1 -1
- package/dist/esm/views/SourceInspector.js +7 -0
- package/dist/esm/views/SourceInspector.js.map +6 -0
- package/dist/esm/views/SourceInspector.mjs +5 -0
- package/dist/esm/views/SourceInspector.mjs.map +1 -0
- package/dist/esm/views/SourceInspector.native.js +6 -0
- package/dist/esm/views/SourceInspector.native.js.map +1 -0
- package/dist/esm/views/Try.js +38 -4
- package/dist/esm/views/Try.js.map +1 -1
- package/dist/esm/views/Try.mjs +40 -7
- package/dist/esm/views/Try.mjs.map +1 -1
- package/dist/esm/views/Try.native.js +42 -7
- package/dist/esm/views/Try.native.js.map +1 -1
- package/dist/esm/vite/DevHead.js +802 -51
- package/dist/esm/vite/DevHead.js.map +1 -1
- package/dist/esm/vite/DevHead.mjs +797 -43
- package/dist/esm/vite/DevHead.mjs.map +1 -1
- package/dist/esm/vite/DevHead.native.js +782 -0
- package/dist/esm/vite/DevHead.native.js.map +1 -1
- package/dist/esm/vite/one.js +7 -1
- package/dist/esm/vite/one.js.map +1 -1
- package/dist/esm/vite/one.mjs +7 -1
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +11 -1
- package/dist/esm/vite/one.native.js.map +1 -1
- package/dist/esm/vite/plugins/SSRCSSPlugin.js +48 -4
- package/dist/esm/vite/plugins/SSRCSSPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/SSRCSSPlugin.mjs +44 -4
- package/dist/esm/vite/plugins/SSRCSSPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/SSRCSSPlugin.native.js +61 -4
- package/dist/esm/vite/plugins/SSRCSSPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js +6 -3
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/generateFileSystemRouteTypesPlugin.js +11 -6
- package/dist/esm/vite/plugins/generateFileSystemRouteTypesPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/generateFileSystemRouteTypesPlugin.mjs +5 -1
- package/dist/esm/vite/plugins/generateFileSystemRouteTypesPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/generateFileSystemRouteTypesPlugin.native.js +1 -0
- package/dist/esm/vite/plugins/generateFileSystemRouteTypesPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/sourceInspectorPlugin.js +126 -0
- package/dist/esm/vite/plugins/sourceInspectorPlugin.js.map +6 -0
- package/dist/esm/vite/plugins/sourceInspectorPlugin.mjs +121 -0
- package/dist/esm/vite/plugins/sourceInspectorPlugin.mjs.map +1 -0
- package/dist/esm/vite/plugins/sourceInspectorPlugin.native.js +194 -0
- package/dist/esm/vite/plugins/sourceInspectorPlugin.native.js.map +1 -0
- package/dist/esm/vite/plugins/virtualEntryPlugin.js +16 -6
- package/dist/esm/vite/plugins/virtualEntryPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +25 -6
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +26 -7
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/package.json +11 -9
- package/src/cli/buildPage.ts +1 -1
- package/src/cli/dev.ts +4 -4
- package/src/createApp.tsx +11 -1
- package/src/createHandleRequest.test.ts +3 -1
- package/src/devtools/registry.ts +21 -0
- package/src/fork/createMemoryHistory.tsx +43 -11
- package/src/fork/useLinking.ts +14 -4
- package/src/index.ts +34 -1
- package/src/interfaces/router.ts +48 -0
- package/src/layouts/withLayoutContext.tsx +48 -8
- package/src/link/Link.tsx +7 -2
- package/src/link/useLinkTo.tsx +7 -3
- package/src/router/Route.tsx +32 -3
- package/src/router/findRouteNode.ts +127 -0
- package/src/router/router.ts +286 -2
- package/src/router/useScreens.tsx +9 -3
- package/src/useBlocker.native.ts +153 -0
- package/src/useBlocker.ts +340 -0
- package/src/useLoader.ts +139 -1
- package/src/useScrollGroup.native.ts +7 -0
- package/src/useScrollGroup.ts +44 -0
- package/src/validateParams.ts +196 -0
- package/src/validateSearch.ts +241 -0
- package/src/views/ErrorBoundary.tsx +154 -156
- package/src/views/ErrorBoundary.web.tsx +321 -0
- package/src/views/Navigator.tsx +14 -2
- package/src/views/Protected.tsx +62 -0
- package/src/views/RootErrorBoundary.tsx +214 -17
- package/src/views/ScrollBehavior.tsx +82 -3
- package/src/views/SourceInspector.tsx +39 -0
- package/src/views/Try.tsx +81 -12
- package/src/vite/DevHead.tsx +819 -54
- package/src/vite/one.ts +13 -0
- package/src/vite/plugins/SSRCSSPlugin.ts +104 -0
- package/src/vite/plugins/fileSystemRouterPlugin.tsx +11 -8
- package/src/vite/plugins/generateFileSystemRouteTypesPlugin.tsx +4 -0
- package/src/vite/plugins/sourceInspectorPlugin.ts +246 -0
- package/src/vite/plugins/virtualEntryPlugin.ts +35 -10
- package/src/vite/types.ts +28 -0
- package/types/Route.d.ts.map +1 -0
- package/types/cleanUrl.d.ts.map +1 -0
- package/types/cli/run.d.ts.map +1 -0
- package/types/createApp.d.ts +5 -0
- package/types/createApp.d.ts.map +1 -1
- package/types/createRoute.d.ts.map +1 -0
- package/types/devtools/registry.d.ts +15 -0
- package/types/devtools/registry.d.ts.map +1 -0
- package/types/fork/NavigationContainer.native.d.ts.map +1 -0
- package/types/fork/createMemoryHistory.d.ts +8 -3
- package/types/fork/createMemoryHistory.d.ts.map +1 -1
- package/types/fork/useLinking.d.ts.map +1 -1
- package/types/getLinkingConfig.d.ts.map +1 -0
- package/types/getRoutes.d.ts.map +1 -0
- package/types/imperative-api.d.ts.map +1 -0
- package/types/index.d.ts +8 -1
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/router.d.ts +47 -0
- package/types/interfaces/router.d.ts.map +1 -1
- package/types/layouts/withLayoutContext.d.ts +2 -1
- package/types/layouts/withLayoutContext.d.ts.map +1 -1
- package/types/link/Link.d.ts.map +1 -1
- package/types/link/useLinkTo.d.ts +1 -0
- package/types/link/useLinkTo.d.ts.map +1 -1
- package/types/matchers.d.ts.map +1 -0
- package/types/platform.d.ts.map +1 -0
- package/types/router/Route.d.ts +32 -3
- package/types/router/Route.d.ts.map +1 -1
- package/types/router/findRouteNode.d.ts +31 -0
- package/types/router/findRouteNode.d.ts.map +1 -0
- package/types/router/router.d.ts +35 -0
- package/types/router/router.d.ts.map +1 -1
- package/types/router/useScreens.d.ts +2 -0
- package/types/router/useScreens.d.ts.map +1 -1
- package/types/server/oneServe.d.ts.map +1 -1
- package/types/sortRoutes.d.ts.map +1 -0
- package/types/useBlocker.d.ts +72 -0
- package/types/useBlocker.d.ts.map +1 -0
- package/types/useBlocker.native.d.ts +60 -0
- package/types/useBlocker.native.d.ts.map +1 -0
- package/types/useLoader.d.ts +10 -0
- package/types/useLoader.d.ts.map +1 -1
- package/types/useNavigation.d.ts.map +1 -0
- package/types/useScreens.d.ts.map +1 -0
- package/types/useScrollGroup.d.ts +27 -0
- package/types/useScrollGroup.d.ts.map +1 -0
- package/types/useScrollGroup.native.d.ts +6 -0
- package/types/useScrollGroup.native.d.ts.map +1 -0
- package/types/useSearch.d.ts.map +1 -0
- package/types/useViteRoutes.d.ts.map +1 -0
- package/types/validateParams.d.ts +85 -0
- package/types/validateParams.d.ts.map +1 -0
- package/types/validateSearch.d.ts +107 -0
- package/types/validateSearch.d.ts.map +1 -0
- package/types/views/ErrorBoundary.d.ts +11 -1
- package/types/views/ErrorBoundary.d.ts.map +1 -1
- package/types/views/ErrorBoundary.web.d.ts +13 -0
- package/types/views/ErrorBoundary.web.d.ts.map +1 -0
- package/types/views/Navigator.d.ts.map +1 -1
- package/types/views/Protected.d.ts +39 -0
- package/types/views/Protected.d.ts.map +1 -0
- package/types/views/RootErrorBoundary.d.ts +14 -8
- package/types/views/RootErrorBoundary.d.ts.map +1 -1
- package/types/views/ScrollBehavior.d.ts +8 -0
- package/types/views/ScrollBehavior.d.ts.map +1 -1
- package/types/views/ScrollRestoration.d.ts.map +1 -0
- package/types/views/SourceInspector.d.ts +35 -0
- package/types/views/SourceInspector.d.ts.map +1 -0
- package/types/views/Try.d.ts +29 -6
- package/types/views/Try.d.ts.map +1 -1
- package/types/vite/DevHead.d.ts.map +1 -1
- package/types/vite/build.d.ts.map +1 -0
- package/types/vite/headers.d.ts.map +1 -0
- package/types/vite/headers.native.d.ts.map +1 -0
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/plugins/SSRCSSPlugin.d.ts.map +1 -1
- package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
- package/types/vite/plugins/generateFileSystemRouteTypesPlugin.d.ts.map +1 -1
- package/types/vite/plugins/seoPreviewPlugin.d.ts.map +1 -0
- package/types/vite/plugins/sourceInspectorPlugin.d.ts +3 -0
- package/types/vite/plugins/sourceInspectorPlugin.d.ts.map +1 -0
- package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
- package/types/vite/resolveAPIRequest.d.ts.map +1 -0
- package/types/vite/server.d.ts.map +1 -0
- package/types/vite/types.d.ts +24 -0
- package/types/vite/types.d.ts.map +1 -1
package/src/router/router.ts
CHANGED
|
@@ -35,11 +35,75 @@ import { sortRoutes } from './sortRoutes'
|
|
|
35
35
|
import { getQualifiedRouteComponent } from './useScreens'
|
|
36
36
|
import { preloadRouteModules } from './useViteRoutes'
|
|
37
37
|
import { getNavigateAction } from './utils/getNavigateAction'
|
|
38
|
+
import {
|
|
39
|
+
findRouteNodeFromState,
|
|
40
|
+
extractParamsFromState,
|
|
41
|
+
extractSearchFromHref,
|
|
42
|
+
extractPathnameFromHref,
|
|
43
|
+
} from './findRouteNode'
|
|
44
|
+
import {
|
|
45
|
+
validateParams as runValidateParams,
|
|
46
|
+
RouteValidationError,
|
|
47
|
+
ParamValidationError,
|
|
48
|
+
} from '../validateParams'
|
|
49
|
+
import { checkBlocker } from '../useBlocker'
|
|
50
|
+
import { devtoolsRegistry } from '../devtools/registry'
|
|
38
51
|
|
|
39
52
|
// Module-scoped variables
|
|
40
53
|
export let routeNode: RouteNode | null = null
|
|
41
54
|
export let rootComponent: ComponentType
|
|
42
55
|
|
|
56
|
+
// Global registry for protected routes
|
|
57
|
+
// Key: contextKey (e.g., '/protected-test'), Value: Set of protected route names
|
|
58
|
+
const protectedRouteRegistry = new Map<string, Set<string>>()
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Register protected routes for a navigator context.
|
|
62
|
+
* Called by navigators when their protectedScreens changes.
|
|
63
|
+
*/
|
|
64
|
+
export function registerProtectedRoutes(contextKey: string, protectedScreens: Set<string>) {
|
|
65
|
+
if (protectedScreens.size === 0) {
|
|
66
|
+
protectedRouteRegistry.delete(contextKey)
|
|
67
|
+
} else {
|
|
68
|
+
protectedRouteRegistry.set(contextKey, protectedScreens)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Unregister protected routes for a navigator context.
|
|
74
|
+
* Called when a navigator unmounts.
|
|
75
|
+
*/
|
|
76
|
+
export function unregisterProtectedRoutes(contextKey: string) {
|
|
77
|
+
protectedRouteRegistry.delete(contextKey)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check if a route path is protected and should be blocked.
|
|
82
|
+
* Returns true if the route is protected.
|
|
83
|
+
*/
|
|
84
|
+
export function isRouteProtected(href: string): boolean {
|
|
85
|
+
// Normalize the href (remove leading/trailing slashes)
|
|
86
|
+
const normalizedHref = href.replace(/^\/+|\/+$/g, '')
|
|
87
|
+
|
|
88
|
+
// Check each navigator context to see if this route is protected
|
|
89
|
+
for (const [contextKey, protectedScreens] of protectedRouteRegistry) {
|
|
90
|
+
const normalizedContextKey = contextKey.replace(/^\/+|\/+$/g, '')
|
|
91
|
+
|
|
92
|
+
// Check if this href is under this context
|
|
93
|
+
if (normalizedHref.startsWith(normalizedContextKey)) {
|
|
94
|
+
// Get the route name relative to this context
|
|
95
|
+
const relativePath = normalizedHref.slice(normalizedContextKey.length).replace(/^\//, '')
|
|
96
|
+
const routeName = relativePath.split('/')[0] || 'index'
|
|
97
|
+
|
|
98
|
+
if (protectedScreens.has(routeName)) {
|
|
99
|
+
return true
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
|
|
43
107
|
export let hasAttemptedToHideSplash = false
|
|
44
108
|
export let initialState: OneRouter.ResultState | undefined
|
|
45
109
|
export let rootState: OneRouter.ResultState | undefined
|
|
@@ -56,6 +120,60 @@ const rootStateSubscribers = new Set<OneRouter.RootStateListener>()
|
|
|
56
120
|
const loadingStateSubscribers = new Set<OneRouter.LoadingStateListener>()
|
|
57
121
|
const storeSubscribers = new Set<() => void>()
|
|
58
122
|
|
|
123
|
+
// Validation state tracking
|
|
124
|
+
export type ValidationState = {
|
|
125
|
+
status: 'idle' | 'validating' | 'error' | 'valid'
|
|
126
|
+
error?: Error
|
|
127
|
+
lastValidatedHref?: string
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let validationState: ValidationState = { status: 'idle' }
|
|
131
|
+
const validationStateSubscribers = new Set<(state: ValidationState) => void>()
|
|
132
|
+
|
|
133
|
+
export function subscribeToValidationState(subscriber: (state: ValidationState) => void) {
|
|
134
|
+
validationStateSubscribers.add(subscriber)
|
|
135
|
+
return () => validationStateSubscribers.delete(subscriber)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function setValidationState(state: ValidationState) {
|
|
139
|
+
validationState = state
|
|
140
|
+
for (const subscriber of validationStateSubscribers) {
|
|
141
|
+
subscriber(state)
|
|
142
|
+
}
|
|
143
|
+
// Dispatch event for devtools
|
|
144
|
+
if (
|
|
145
|
+
process.env.TAMAGUI_TARGET !== 'native' &&
|
|
146
|
+
state.status === 'error' &&
|
|
147
|
+
state.error
|
|
148
|
+
) {
|
|
149
|
+
window.dispatchEvent(
|
|
150
|
+
new CustomEvent('one-validation-error', {
|
|
151
|
+
detail: {
|
|
152
|
+
error: {
|
|
153
|
+
message: state.error.message,
|
|
154
|
+
name: state.error.name,
|
|
155
|
+
stack: state.error.stack,
|
|
156
|
+
},
|
|
157
|
+
href: state.lastValidatedHref,
|
|
158
|
+
timestamp: Date.now(),
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function getValidationState(): ValidationState {
|
|
166
|
+
return validationState
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function useValidationState() {
|
|
170
|
+
return useSyncExternalStore(
|
|
171
|
+
subscribeToValidationState,
|
|
172
|
+
getValidationState,
|
|
173
|
+
getValidationState
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
|
|
59
177
|
// Initialize function
|
|
60
178
|
export function initialize(
|
|
61
179
|
context: One.RouteContext,
|
|
@@ -272,6 +390,23 @@ export function updateState(state: OneRouter.ResultState, nextStateParam = state
|
|
|
272
390
|
}
|
|
273
391
|
routeInfo = nextRouteInfo
|
|
274
392
|
}
|
|
393
|
+
|
|
394
|
+
// Expose devtools API in development
|
|
395
|
+
if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') {
|
|
396
|
+
// Use registry to avoid circular deps - useLoader registers its function there
|
|
397
|
+
;(window as any).__oneDevtools = {
|
|
398
|
+
routeInfo: nextRouteInfo,
|
|
399
|
+
rootState: state,
|
|
400
|
+
routeNode,
|
|
401
|
+
getRoutes: () => routeNode?.children || [],
|
|
402
|
+
getLoaderTimingHistory: () => devtoolsRegistry.getLoaderTimingHistory?.() ?? [],
|
|
403
|
+
getPreloadHistory,
|
|
404
|
+
}
|
|
405
|
+
// Dispatch event for devtools panels to listen
|
|
406
|
+
if (process.env.TAMAGUI_TARGET !== 'native') {
|
|
407
|
+
window.dispatchEvent(new CustomEvent('one-route-change', { detail: nextRouteInfo }))
|
|
408
|
+
}
|
|
409
|
+
}
|
|
275
410
|
}
|
|
276
411
|
|
|
277
412
|
// Subscription functions
|
|
@@ -397,6 +532,9 @@ async function doPreload(href: string) {
|
|
|
397
532
|
const preloadPath = getPreloadPath(href)
|
|
398
533
|
const loaderPath = getLoaderPath(href)
|
|
399
534
|
const cssPreloadPath = getPreloadCSSPath(href)
|
|
535
|
+
|
|
536
|
+
recordPreloadStart(href)
|
|
537
|
+
|
|
400
538
|
try {
|
|
401
539
|
const [_preload, cssPreloadModule, loader] = await Promise.all([
|
|
402
540
|
dynamicImport(preloadPath),
|
|
@@ -406,18 +544,24 @@ async function doPreload(href: string) {
|
|
|
406
544
|
])
|
|
407
545
|
|
|
408
546
|
// Store the CSS inject function for later use on navigation
|
|
409
|
-
|
|
547
|
+
const hasCss = !!cssPreloadModule?.injectCSS
|
|
548
|
+
if (hasCss) {
|
|
410
549
|
cssInjectFunctions[href] = cssPreloadModule.injectCSS
|
|
411
550
|
}
|
|
412
551
|
|
|
413
|
-
|
|
552
|
+
const hasLoader = !!loader?.loader
|
|
553
|
+
if (!hasLoader) {
|
|
554
|
+
recordPreloadComplete(href, false, hasCss)
|
|
414
555
|
return null
|
|
415
556
|
}
|
|
416
557
|
|
|
417
558
|
const result = await loader.loader()
|
|
559
|
+
recordPreloadComplete(href, true, hasCss)
|
|
418
560
|
return result ?? null
|
|
419
561
|
} catch (err) {
|
|
562
|
+
const errorMessage = err instanceof Error ? err.message : String(err)
|
|
420
563
|
console.error(`[one] preload error for ${href}:`, err)
|
|
564
|
+
recordPreloadError(href, errorMessage)
|
|
421
565
|
return null
|
|
422
566
|
}
|
|
423
567
|
}
|
|
@@ -428,6 +572,79 @@ export const preloadedLoaderData: Record<string, any> = {}
|
|
|
428
572
|
// Store CSS inject functions for calling on navigation
|
|
429
573
|
const cssInjectFunctions: Record<string, (() => Promise<void[]>) | undefined> = {}
|
|
430
574
|
|
|
575
|
+
// Preload status tracking for devtools
|
|
576
|
+
export type PreloadStatus = 'pending' | 'loading' | 'loaded' | 'error'
|
|
577
|
+
export type PreloadEntry = {
|
|
578
|
+
href: string
|
|
579
|
+
status: PreloadStatus
|
|
580
|
+
startTime: number
|
|
581
|
+
endTime?: number
|
|
582
|
+
error?: string
|
|
583
|
+
hasLoader: boolean
|
|
584
|
+
hasCss: boolean
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const preloadHistory: PreloadEntry[] = []
|
|
588
|
+
const MAX_PRELOAD_HISTORY = 30
|
|
589
|
+
|
|
590
|
+
// Preload tracking functions - only do work in development for devtools
|
|
591
|
+
function recordPreloadStart(href: string) {
|
|
592
|
+
if (process.env.NODE_ENV !== 'development') return
|
|
593
|
+
|
|
594
|
+
const existing = preloadHistory.find((p) => p.href === href)
|
|
595
|
+
if (existing) {
|
|
596
|
+
existing.status = 'loading'
|
|
597
|
+
existing.startTime = performance.now()
|
|
598
|
+
return
|
|
599
|
+
}
|
|
600
|
+
preloadHistory.unshift({
|
|
601
|
+
href,
|
|
602
|
+
status: 'loading',
|
|
603
|
+
startTime: performance.now(),
|
|
604
|
+
hasLoader: false,
|
|
605
|
+
hasCss: false,
|
|
606
|
+
})
|
|
607
|
+
if (preloadHistory.length > MAX_PRELOAD_HISTORY) {
|
|
608
|
+
preloadHistory.pop()
|
|
609
|
+
}
|
|
610
|
+
dispatchPreloadEvent()
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
function recordPreloadComplete(href: string, hasLoader: boolean, hasCss: boolean) {
|
|
614
|
+
if (process.env.NODE_ENV !== 'development') return
|
|
615
|
+
|
|
616
|
+
const entry = preloadHistory.find((p) => p.href === href)
|
|
617
|
+
if (entry) {
|
|
618
|
+
entry.status = 'loaded'
|
|
619
|
+
entry.endTime = performance.now()
|
|
620
|
+
entry.hasLoader = hasLoader
|
|
621
|
+
entry.hasCss = hasCss
|
|
622
|
+
}
|
|
623
|
+
dispatchPreloadEvent()
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
function recordPreloadError(href: string, error: string) {
|
|
627
|
+
if (process.env.NODE_ENV !== 'development') return
|
|
628
|
+
|
|
629
|
+
const entry = preloadHistory.find((p) => p.href === href)
|
|
630
|
+
if (entry) {
|
|
631
|
+
entry.status = 'error'
|
|
632
|
+
entry.endTime = performance.now()
|
|
633
|
+
entry.error = error
|
|
634
|
+
}
|
|
635
|
+
dispatchPreloadEvent()
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
function dispatchPreloadEvent() {
|
|
639
|
+
if (process.env.TAMAGUI_TARGET !== 'native') {
|
|
640
|
+
window.dispatchEvent(new CustomEvent('one-preload-update'))
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
export function getPreloadHistory(): PreloadEntry[] {
|
|
645
|
+
return preloadHistory
|
|
646
|
+
}
|
|
647
|
+
|
|
431
648
|
export function preloadRoute(href: string, injectCSS = false): Promise<any> | undefined {
|
|
432
649
|
if (process.env.TAMAGUI_TARGET === 'native') {
|
|
433
650
|
return
|
|
@@ -477,6 +694,16 @@ export async function linkTo(
|
|
|
477
694
|
return
|
|
478
695
|
}
|
|
479
696
|
|
|
697
|
+
// Check if any blocker wants to block this navigation (web only)
|
|
698
|
+
if (checkBlocker(href, event === 'REPLACE' ? 'replace' : 'push')) {
|
|
699
|
+
return
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Check if the route is protected and should be blocked
|
|
703
|
+
if (isRouteProtected(href)) {
|
|
704
|
+
return
|
|
705
|
+
}
|
|
706
|
+
|
|
480
707
|
assertIsReady(navigationRef)
|
|
481
708
|
const current = navigationRef.current
|
|
482
709
|
|
|
@@ -540,8 +767,65 @@ export async function linkTo(
|
|
|
540
767
|
|
|
541
768
|
setLoadingState('loading')
|
|
542
769
|
|
|
770
|
+
// Preload route modules first so loadRoute() won't throw Suspense promises
|
|
543
771
|
await preloadRoute(href, true)
|
|
544
772
|
|
|
773
|
+
// Run async route validation before navigation
|
|
774
|
+
const matchingRouteNode = findRouteNodeFromState(state, routeNode)
|
|
775
|
+
if (matchingRouteNode?.loadRoute) {
|
|
776
|
+
setValidationState({ status: 'validating', lastValidatedHref: href })
|
|
777
|
+
|
|
778
|
+
try {
|
|
779
|
+
const loadedRoute = matchingRouteNode.loadRoute()
|
|
780
|
+
const params = extractParamsFromState(state)
|
|
781
|
+
const search = extractSearchFromHref(href)
|
|
782
|
+
const pathname = extractPathnameFromHref(href)
|
|
783
|
+
|
|
784
|
+
// Run validateParams if exported
|
|
785
|
+
if (loadedRoute.validateParams) {
|
|
786
|
+
runValidateParams(loadedRoute.validateParams, params)
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// Run validateRoute if exported
|
|
790
|
+
if (loadedRoute.validateRoute) {
|
|
791
|
+
const validationResult = await loadedRoute.validateRoute({
|
|
792
|
+
params,
|
|
793
|
+
search,
|
|
794
|
+
pathname,
|
|
795
|
+
href,
|
|
796
|
+
})
|
|
797
|
+
|
|
798
|
+
// Check for explicit invalid result
|
|
799
|
+
if (validationResult && !validationResult.valid) {
|
|
800
|
+
const error = new RouteValidationError(
|
|
801
|
+
validationResult.error || 'Route validation failed',
|
|
802
|
+
validationResult.details
|
|
803
|
+
)
|
|
804
|
+
setValidationState({ status: 'error', error, lastValidatedHref: href })
|
|
805
|
+
throw error
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
setValidationState({ status: 'valid', lastValidatedHref: href })
|
|
810
|
+
} catch (error) {
|
|
811
|
+
// Handle Suspense promises thrown by loadRoute in dev mode
|
|
812
|
+
if (error && typeof (error as any).then === 'function') {
|
|
813
|
+
// Wait for the route to load and skip validation for this navigation
|
|
814
|
+
await (error as Promise<any>).catch(() => {})
|
|
815
|
+
setValidationState({ status: 'valid', lastValidatedHref: href })
|
|
816
|
+
} else if (
|
|
817
|
+
error instanceof ParamValidationError ||
|
|
818
|
+
error instanceof RouteValidationError
|
|
819
|
+
) {
|
|
820
|
+
setValidationState({ status: 'error', error, lastValidatedHref: href })
|
|
821
|
+
throw error
|
|
822
|
+
} else {
|
|
823
|
+
// Re-throw other errors
|
|
824
|
+
throw error
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
545
829
|
const rootState = navigationRef.getRootState()
|
|
546
830
|
|
|
547
831
|
const hash = href.indexOf('#')
|
|
@@ -224,7 +224,11 @@ function getSortedChildren(
|
|
|
224
224
|
*/
|
|
225
225
|
export function useSortedScreens(
|
|
226
226
|
order: ScreenProps[],
|
|
227
|
-
options?: {
|
|
227
|
+
options?: {
|
|
228
|
+
onlyMatching?: boolean
|
|
229
|
+
/** Set of route names to filter out (protected routes with guard=false) */
|
|
230
|
+
protectedScreens?: Set<string>
|
|
231
|
+
}
|
|
228
232
|
): React.ReactNode[] {
|
|
229
233
|
const node = useRouteNode()
|
|
230
234
|
|
|
@@ -233,8 +237,10 @@ export function useSortedScreens(
|
|
|
233
237
|
? getSortedChildren(node.children, order, node.initialRouteName, options)
|
|
234
238
|
: []
|
|
235
239
|
|
|
236
|
-
return sorted
|
|
237
|
-
|
|
240
|
+
return sorted
|
|
241
|
+
.filter((value) => !options?.protectedScreens?.has(value.route.route))
|
|
242
|
+
.map((value) => routeToScreen(value.route, value.props))
|
|
243
|
+
}, [node?.children, node?.initialRouteName, order, options?.protectedScreens])
|
|
238
244
|
|
|
239
245
|
return sortedScreens
|
|
240
246
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { useNavigation } from '@react-navigation/native'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
|
|
4
|
+
export type BlockerState = 'unblocked' | 'blocked' | 'proceeding'
|
|
5
|
+
|
|
6
|
+
export type BlockerFunction = (args: {
|
|
7
|
+
currentLocation: string
|
|
8
|
+
nextLocation: string
|
|
9
|
+
historyAction: 'push' | 'pop' | 'replace'
|
|
10
|
+
}) => boolean
|
|
11
|
+
|
|
12
|
+
export type Blocker =
|
|
13
|
+
| {
|
|
14
|
+
state: 'unblocked'
|
|
15
|
+
reset?: undefined
|
|
16
|
+
proceed?: undefined
|
|
17
|
+
location?: undefined
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
state: 'blocked'
|
|
21
|
+
reset: () => void
|
|
22
|
+
proceed: () => void
|
|
23
|
+
location: string
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
state: 'proceeding'
|
|
27
|
+
reset?: undefined
|
|
28
|
+
proceed?: undefined
|
|
29
|
+
location: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Block navigation when a condition is met.
|
|
34
|
+
*
|
|
35
|
+
* On native, this uses React Navigation's `beforeRemove` event to prevent navigation.
|
|
36
|
+
* Note that this only works for navigation within the app - it cannot prevent
|
|
37
|
+
* the app from being closed or backgrounded.
|
|
38
|
+
*
|
|
39
|
+
* @param shouldBlock - Either a boolean or a function that returns whether to block.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* function EditForm() {
|
|
44
|
+
* const [isDirty, setIsDirty] = useState(false)
|
|
45
|
+
* const blocker = useBlocker(isDirty)
|
|
46
|
+
*
|
|
47
|
+
* return (
|
|
48
|
+
* <>
|
|
49
|
+
* <TextInput onChange={() => setIsDirty(true)} />
|
|
50
|
+
*
|
|
51
|
+
* {blocker.state === 'blocked' && (
|
|
52
|
+
* <Modal>
|
|
53
|
+
* <Text>You have unsaved changes. Leave anyway?</Text>
|
|
54
|
+
* <Button title="Stay" onPress={blocker.reset} />
|
|
55
|
+
* <Button title="Leave" onPress={blocker.proceed} />
|
|
56
|
+
* </Modal>
|
|
57
|
+
* )}
|
|
58
|
+
* </>
|
|
59
|
+
* )
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function useBlocker(shouldBlock: BlockerFunction | boolean): Blocker {
|
|
64
|
+
const navigation = useNavigation()
|
|
65
|
+
const [state, setState] = React.useState<BlockerState>('unblocked')
|
|
66
|
+
const [pendingEvent, setPendingEvent] = React.useState<any>(null)
|
|
67
|
+
const [blockedLocation, setBlockedLocation] = React.useState<string | null>(null)
|
|
68
|
+
|
|
69
|
+
const shouldBlockRef = React.useRef(shouldBlock)
|
|
70
|
+
shouldBlockRef.current = shouldBlock
|
|
71
|
+
|
|
72
|
+
React.useEffect(() => {
|
|
73
|
+
const unsubscribe = navigation.addListener('beforeRemove', (e) => {
|
|
74
|
+
const currentShouldBlock = shouldBlockRef.current
|
|
75
|
+
|
|
76
|
+
// Get the next location from the action payload
|
|
77
|
+
const payload = e.data?.action?.payload as { name?: string } | undefined
|
|
78
|
+
const nextLocation = payload?.name || 'previous screen'
|
|
79
|
+
|
|
80
|
+
// Determine if we should block
|
|
81
|
+
const block =
|
|
82
|
+
typeof currentShouldBlock === 'function'
|
|
83
|
+
? currentShouldBlock({
|
|
84
|
+
currentLocation: '', // Not easily available on native
|
|
85
|
+
nextLocation,
|
|
86
|
+
historyAction: 'pop',
|
|
87
|
+
})
|
|
88
|
+
: currentShouldBlock
|
|
89
|
+
|
|
90
|
+
if (!block) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Prevent default behavior (leaving the screen)
|
|
95
|
+
e.preventDefault()
|
|
96
|
+
|
|
97
|
+
// Store the event to dispatch later if user confirms
|
|
98
|
+
setPendingEvent(e)
|
|
99
|
+
setBlockedLocation(nextLocation)
|
|
100
|
+
setState('blocked')
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
return unsubscribe
|
|
104
|
+
}, [navigation])
|
|
105
|
+
|
|
106
|
+
const reset = React.useCallback(() => {
|
|
107
|
+
setPendingEvent(null)
|
|
108
|
+
setBlockedLocation(null)
|
|
109
|
+
setState('unblocked')
|
|
110
|
+
}, [])
|
|
111
|
+
|
|
112
|
+
const proceed = React.useCallback(() => {
|
|
113
|
+
if (!pendingEvent) return
|
|
114
|
+
|
|
115
|
+
setState('proceeding')
|
|
116
|
+
|
|
117
|
+
// Dispatch the original action to complete navigation
|
|
118
|
+
navigation.dispatch(pendingEvent.data.action)
|
|
119
|
+
|
|
120
|
+
// Reset after navigation
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
setPendingEvent(null)
|
|
123
|
+
setBlockedLocation(null)
|
|
124
|
+
setState('unblocked')
|
|
125
|
+
}, 100)
|
|
126
|
+
}, [navigation, pendingEvent])
|
|
127
|
+
|
|
128
|
+
if (state === 'unblocked') {
|
|
129
|
+
return { state: 'unblocked' }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (state === 'proceeding') {
|
|
133
|
+
return { state: 'proceeding', location: blockedLocation! }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
state: 'blocked',
|
|
138
|
+
reset,
|
|
139
|
+
proceed,
|
|
140
|
+
location: blockedLocation!,
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* No-op on native - native uses React Navigation's beforeRemove event instead.
|
|
146
|
+
* This is only used by the router on web.
|
|
147
|
+
*/
|
|
148
|
+
export function checkBlocker(
|
|
149
|
+
_nextLocation: string,
|
|
150
|
+
_historyAction: 'push' | 'pop' | 'replace' = 'push'
|
|
151
|
+
): boolean {
|
|
152
|
+
return false
|
|
153
|
+
}
|