@timber-js/app 0.2.0-alpha.12 → 0.2.0-alpha.120
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/_chunks/actions-Cw-7NfJJ.js +1101 -0
- package/dist/_chunks/actions-Cw-7NfJJ.js.map +1 -0
- package/dist/_chunks/build-output-helper-DhxiT18k.js +61 -0
- package/dist/_chunks/build-output-helper-DhxiT18k.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-XV0I47Gj.js +2 -0
- package/dist/_chunks/cli-schema-sync-q2wB0DyJ.js +358 -0
- package/dist/_chunks/cli-schema-sync-q2wB0DyJ.js.map +1 -0
- package/dist/_chunks/codec-registry-V7ARyeLN.js +21 -0
- package/dist/_chunks/codec-registry-V7ARyeLN.js.map +1 -0
- package/dist/_chunks/define-8zQ8Vm7x.js +195 -0
- package/dist/_chunks/define-8zQ8Vm7x.js.map +1 -0
- package/dist/_chunks/define-zQX6e1tN.js +124 -0
- package/dist/_chunks/define-zQX6e1tN.js.map +1 -0
- package/dist/_chunks/format-CR6v1pWE.js +14 -0
- package/dist/_chunks/format-CR6v1pWE.js.map +1 -0
- package/dist/_chunks/handler-store-iqnt2ghN.js +54 -0
- package/dist/_chunks/handler-store-iqnt2ghN.js.map +1 -0
- package/dist/_chunks/logger-DDmK5skc.js +291 -0
- package/dist/_chunks/logger-DDmK5skc.js.map +1 -0
- package/dist/_chunks/merge-search-params-CwxJzBLS.js +41 -0
- package/dist/_chunks/merge-search-params-CwxJzBLS.js.map +1 -0
- package/dist/_chunks/navigation-root-DKsJ5Di7.js +96 -0
- package/dist/_chunks/navigation-root-DKsJ5Di7.js.map +1 -0
- package/dist/_chunks/registry-Dp_hJL4s.js +20 -0
- package/dist/_chunks/registry-Dp_hJL4s.js.map +1 -0
- package/dist/_chunks/resolve-schema-23Mc8aLi.js +65 -0
- package/dist/_chunks/resolve-schema-23Mc8aLi.js.map +1 -0
- package/dist/_chunks/router-ref-sektkr-t.js +28 -0
- package/dist/_chunks/router-ref-sektkr-t.js.map +1 -0
- package/dist/_chunks/scanner-DmfoB7iK.js +336 -0
- package/dist/_chunks/scanner-DmfoB7iK.js.map +1 -0
- package/dist/_chunks/schema-bridge-eL5vQDSA.js +86 -0
- package/dist/_chunks/schema-bridge-eL5vQDSA.js.map +1 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js +137 -0
- package/dist/_chunks/segment-classify-CnfLLvir.js.map +1 -0
- package/dist/_chunks/segment-context-Bg0pFbLT.js +34 -0
- package/dist/_chunks/segment-context-Bg0pFbLT.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BO5OvEvg.js} +1 -1
- package/dist/_chunks/ssr-data-BO5OvEvg.js.map +1 -0
- package/dist/_chunks/stale-reload-BCPRG0Cv.js +64 -0
- package/dist/_chunks/stale-reload-BCPRG0Cv.js.map +1 -0
- package/dist/_chunks/tracing-DvKLzCFa.js +329 -0
- package/dist/_chunks/tracing-DvKLzCFa.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-D9SBlAfp.js} +7 -20
- package/dist/_chunks/use-query-states-D9SBlAfp.js.map +1 -0
- package/dist/_chunks/use-segment-params-CskiK-59.js +185 -0
- package/dist/_chunks/use-segment-params-CskiK-59.js.map +1 -0
- package/dist/_chunks/validation-Bm3Je-09.js +84 -0
- package/dist/_chunks/validation-Bm3Je-09.js.map +1 -0
- package/dist/_chunks/walkers-DgOXkTts.js +609 -0
- package/dist/_chunks/walkers-DgOXkTts.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → warnings-B30wpfaS.js} +6 -45
- package/dist/_chunks/warnings-B30wpfaS.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +28 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +95 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +142 -38
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +143 -45
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +16 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +23 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +151 -81
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli-schema-sync.d.ts +37 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +42 -6
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +34 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +30 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +23 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +19 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +29 -6
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +54 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +16 -27
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +9 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +172 -1100
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +19 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +964 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +63 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +62 -55
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router.d.ts +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/state.d.ts +1 -1
- package/dist/client/top-loader.d.ts +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts +12 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.d.ts.map +1 -1
- package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +51 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +46 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +294 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-validation.d.ts +51 -0
- package/dist/config-validation.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +58 -25
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -1
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +251 -36
- package/dist/cookies/index.js.map +1 -1
- package/dist/cookies/json-cookie.d.ts +64 -0
- package/dist/cookies/json-cookie.d.ts.map +1 -0
- package/dist/cookies/validation.d.ts +46 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +46 -0
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/dev-tools/browser-logs.d.ts +84 -0
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/dev-tools/error-page.d.ts +58 -0
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/dev-tools/holding-server.d.ts +54 -0
- package/dist/dev-tools/holding-server.d.ts.map +1 -0
- package/dist/dev-tools/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
- package/dist/dev-tools/instrumentation.d.ts.map +1 -0
- package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
- package/dist/dev-tools/logger.d.ts.map +1 -0
- package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/dev-tools/overlay.d.ts +91 -0
- package/dist/dev-tools/overlay.d.ts.map +1 -0
- package/dist/dev-tools/stack-classifier.d.ts +34 -0
- package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
- package/dist/dev-tools/terminal.d.ts +28 -0
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +2 -22
- package/dist/dev-tools/warnings.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +98 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +48 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/local.d.ts +1 -1
- package/dist/fonts/pipeline.d.ts +167 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +78 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +45 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +94 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -190
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4799 -12730
- package/dist/index.js.map +1 -1
- package/dist/params/codec-registry.d.ts +26 -0
- package/dist/params/codec-registry.d.ts.map +1 -0
- package/dist/params/define-schema.d.ts +53 -0
- package/dist/params/define-schema.d.ts.map +1 -0
- package/dist/params/index.d.ts +5 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +34 -0
- package/dist/params/index.js.map +1 -0
- package/dist/params/resolve-schema.d.ts +34 -0
- package/dist/params/resolve-schema.d.ts.map +1 -0
- package/dist/plugin-context.d.ts +107 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +9 -7
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +17 -73
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +6 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +5 -26
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +63 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +60 -0
- package/dist/routing/codegen-types.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts +7 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts +41 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- package/dist/routing/index.d.ts +5 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-codegen.d.ts.map +1 -0
- package/dist/routing/scanner.d.ts +1 -10
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +75 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/segment-codegen.d.ts +38 -0
- package/dist/routing/segment-codegen.d.ts.map +1 -0
- package/dist/routing/types.d.ts +77 -25
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +51 -0
- package/dist/routing/walkers.d.ts.map +1 -0
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +76 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +157 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +34 -441
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/registry.d.ts +2 -2
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +95 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +8 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +41 -6
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts +35 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +53 -5
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +1 -15
- package/dist/server/asset-headers.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/coalesce-tick.d.ts +40 -0
- package/dist/server/coalesce-tick.d.ts.map +1 -0
- package/dist/server/cookie-context.d.ts +170 -0
- package/dist/server/cookie-context.d.ts.map +1 -0
- package/dist/server/cookie-parsing.d.ts +51 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/debug.d.ts +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +90 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-source-map.d.ts +22 -0
- package/dist/server/dev-source-map.d.ts.map +1 -0
- package/dist/server/early-hints-sender.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -5
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +12 -7
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/flush.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +213 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +81 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +10 -46
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +155 -2905
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +48 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2947 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +39 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +36 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +112 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +54 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +95 -0
- package/dist/server/pipeline-helpers.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts +49 -0
- package/dist/server/pipeline-outcome.d.ts.map +1 -0
- package/dist/server/pipeline-phases.d.ts +52 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +118 -23
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/port-resolution.d.ts +117 -0
- package/dist/server/port-resolution.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +69 -18
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +21 -34
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts +2 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +49 -6
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +19 -8
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +50 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +17 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +30 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +16 -11
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +5 -5
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +62 -30
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/tree-match.d.ts +41 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +49 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/escape-html.d.ts +14 -0
- package/dist/server/utils/escape-html.d.ts.map +1 -0
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/headers.d.ts +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +3 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +11 -5
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +56 -16
- package/src/adapters/build-output-helper.ts +77 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +350 -76
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +142 -59
- package/src/adapters/shared.ts +40 -0
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +81 -18
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/timber-cache.ts +25 -20
- package/src/cli-schema-sync.ts +207 -0
- package/src/cli.ts +65 -8
- package/src/client/browser-dev.ts +153 -1
- package/src/client/browser-entry/action-dispatch.ts +126 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +149 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +193 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- package/src/client/error-boundary.tsx +99 -22
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +69 -44
- package/src/client/internal.ts +58 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +366 -113
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +31 -6
- package/src/client/navigation-root.tsx +342 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +300 -73
- package/src/client/rsc-fetch.ts +112 -8
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +18 -6
- package/src/client/use-cookie.ts +31 -2
- package/src/client/use-link-status.ts +7 -7
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
- package/src/client/use-query-states.ts +9 -3
- package/src/client/use-router.ts +1 -1
- package/src/client/{use-params.ts → use-segment-params.ts} +8 -6
- package/src/codec.ts +97 -0
- package/src/config-types.ts +292 -0
- package/src/config-validation.ts +303 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +233 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +134 -0
- package/src/dev-tools/404-page.ts +387 -0
- package/src/dev-tools/browser-logs.ts +291 -0
- package/src/dev-tools/error-page.ts +506 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/index.ts +90 -0
- package/src/dev-tools/instrumentation.ts +176 -0
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +183 -0
- package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +5 -50
- package/src/fonts/ast.ts +525 -16
- package/src/fonts/bundle.ts +142 -0
- package/src/fonts/dev-middleware.ts +74 -0
- package/src/fonts/local.ts +1 -1
- package/src/fonts/pipeline.ts +314 -0
- package/src/fonts/transform.ts +317 -0
- package/src/fonts/types.ts +50 -1
- package/src/fonts/virtual-modules.ts +233 -0
- package/src/index.ts +409 -357
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +73 -0
- package/src/params/index.ts +11 -0
- package/src/params/resolve-schema.ts +88 -0
- package/src/plugin-context.ts +240 -0
- package/src/plugins/adapter-build.ts +12 -4
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +16 -25
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +175 -35
- package/src/plugins/entries.ts +111 -9
- package/src/plugins/fonts.ts +157 -654
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/routing.ts +374 -45
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +136 -35
- package/src/plugins/static-build.ts +15 -89
- package/src/routing/codegen-shared.ts +109 -0
- package/src/routing/codegen-types.ts +61 -0
- package/src/routing/codegen.ts +269 -179
- package/src/routing/convention-lint.ts +357 -0
- package/src/routing/index.ts +5 -1
- package/src/routing/interception.ts +1 -1
- package/src/routing/link-codegen.ts +308 -0
- package/src/routing/scanner.ts +107 -110
- package/src/routing/segment-classify.ts +188 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +78 -25
- package/src/routing/walkers.ts +90 -0
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +538 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +92 -0
- package/src/segment-params/define.ts +336 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +76 -34
- package/src/server/action-client.ts +88 -15
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +112 -14
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +55 -7
- package/src/server/asset-headers.ts +8 -34
- package/src/server/build-manifest.ts +10 -4
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +25 -7
- package/src/server/cookie-context.ts +468 -0
- package/src/server/cookie-parsing.ts +135 -0
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +218 -0
- package/src/server/deny-renderer.ts +31 -50
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +74 -102
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injector-core.ts +417 -0
- package/src/server/html-injectors.ts +235 -223
- package/src/server/index.ts +29 -183
- package/src/server/internal.ts +176 -0
- package/src/server/logger.ts +67 -36
- package/src/server/middleware-runner.ts +75 -4
- package/src/server/node-stream-transforms.ts +361 -0
- package/src/server/param-coercion.ts +206 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline-outcome.ts +176 -0
- package/src/server/pipeline-phases.ts +460 -0
- package/src/server/pipeline.ts +154 -394
- package/src/server/port-resolution.ts +215 -0
- package/src/server/primitives.ts +111 -28
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +168 -333
- package/src/server/route-element-builder.ts +309 -195
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +50 -231
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +16 -17
- package/src/server/rsc-entry/error-renderer.ts +305 -89
- package/src/server/rsc-entry/helpers.ts +137 -12
- package/src/server/rsc-entry/index.ts +316 -352
- package/src/server/rsc-entry/render-route.ts +307 -0
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +85 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +187 -38
- package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +126 -0
- package/src/server/slot-resolver.ts +228 -246
- package/src/server/ssr-entry.ts +229 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/state-tree-diff.ts +4 -1
- package/src/server/status-code-resolver.ts +112 -128
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +21 -10
- package/src/server/tree-builder.ts +202 -90
- package/src/server/tree-match.ts +198 -0
- package/src/server/types.ts +55 -6
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/version-skew.ts +104 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +5 -1
- package/src/shims/navigation-client.ts +4 -3
- package/src/shims/navigation.ts +14 -7
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js +0 -108
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js +0 -187
- package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/client/use-params.d.ts.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dev-error-overlay.d.ts +0 -60
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-logs.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/plugins/server-action-exports.d.ts +0 -26
- package/dist/plugins/server-action-exports.d.ts.map +0 -1
- package/dist/routing/status-file-lint.d.ts +0 -33
- package/dist/routing/status-file-lint.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
- package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
- package/dist/server/dev-logger.d.ts.map +0 -1
- package/dist/server/dev-span-processor.d.ts.map +0 -1
- package/dist/server/dev-warnings.d.ts.map +0 -1
- package/dist/server/manifest-status-resolver.d.ts +0 -58
- package/dist/server/manifest-status-resolver.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/server/response-cache.d.ts +0 -54
- package/dist/server/response-cache.d.ts.map +0 -1
- package/dist/utils/directive-parser.d.ts +0 -70
- package/dist/utils/directive-parser.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -166
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dev-error-overlay.ts +0 -230
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/plugins/server-action-exports.ts +0 -220
- package/src/routing/status-file-lint.ts +0 -112
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/create.ts +0 -321
- package/src/server/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -410
- package/src/utils/directive-parser.ts +0 -529
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
package/src/client/link.tsx
CHANGED
|
@@ -18,10 +18,47 @@
|
|
|
18
18
|
// - params and fully-resolved string href are mutually exclusive
|
|
19
19
|
// - searchParams and inline query string are mutually exclusive
|
|
20
20
|
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
import {
|
|
22
|
+
useOptimistic,
|
|
23
|
+
useEffect,
|
|
24
|
+
useRef,
|
|
25
|
+
type AnchorHTMLAttributes,
|
|
26
|
+
type ReactNode,
|
|
27
|
+
type MouseEvent as ReactMouseEvent,
|
|
28
|
+
} from 'react';
|
|
29
|
+
import type { SearchParamsDefinition } from '../search-params/define.js';
|
|
30
|
+
import { getSearchParamsDefinition } from '../search-params/registry.js';
|
|
31
|
+
import type { LinkFunction } from './index.js';
|
|
32
|
+
import { classifyUrlSegment, type UrlSegment } from '../routing/segment-classify.js';
|
|
33
|
+
import { LinkStatusContext } from './use-link-status.js';
|
|
24
34
|
import { getRouterOrNull } from './router-ref.js';
|
|
35
|
+
import { getSsrData } from './ssr-data.js';
|
|
36
|
+
import { mergePreservedSearchParams } from '../shared/merge-search-params.js';
|
|
37
|
+
import {
|
|
38
|
+
setLinkForCurrentNavigation,
|
|
39
|
+
unmountLinkForCurrentNavigation,
|
|
40
|
+
LINK_IDLE,
|
|
41
|
+
type LinkPendingInstance,
|
|
42
|
+
} from './link-pending-store.js';
|
|
43
|
+
import { setNavLinkMetadata } from './nav-link-store.js';
|
|
44
|
+
import { hasNavigationApi } from './navigation-api.js';
|
|
45
|
+
import { getLinkCodec } from '../params/codec-registry.js';
|
|
46
|
+
|
|
47
|
+
// ─── Current Search Params ────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Read the current URL's search string without requiring a React hook.
|
|
51
|
+
* On the client, reads window.location.search. During SSR, reads from
|
|
52
|
+
* the request context (getSsrData). Returns empty string if unavailable.
|
|
53
|
+
*/
|
|
54
|
+
function getCurrentSearch(): string {
|
|
55
|
+
if (typeof window !== 'undefined') return window.location.search;
|
|
56
|
+
const data = getSsrData();
|
|
57
|
+
if (!data) return '';
|
|
58
|
+
const sp = new URLSearchParams(data.searchParams);
|
|
59
|
+
const str = sp.toString();
|
|
60
|
+
return str ? `?${str}` : '';
|
|
61
|
+
}
|
|
25
62
|
|
|
26
63
|
// ─── Types ───────────────────────────────────────────────────────
|
|
27
64
|
|
|
@@ -33,8 +70,12 @@ export type OnNavigateHandler = (e: OnNavigateEvent) => void;
|
|
|
33
70
|
|
|
34
71
|
/**
|
|
35
72
|
* Base props shared by all Link variants.
|
|
73
|
+
*
|
|
74
|
+
* Exported so the public `LinkFunction` interface (declared in
|
|
75
|
+
* `./index.ts`, where module augmentation can merge into it) can
|
|
76
|
+
* compose this without duplication.
|
|
36
77
|
*/
|
|
37
|
-
interface LinkBaseProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
78
|
+
export interface LinkBaseProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
38
79
|
/** Prefetch the RSC payload on hover */
|
|
39
80
|
prefetch?: boolean;
|
|
40
81
|
/**
|
|
@@ -42,6 +83,20 @@ interface LinkBaseProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'h
|
|
|
42
83
|
* Set to false for tabbed interfaces where content changes within a fixed layout.
|
|
43
84
|
*/
|
|
44
85
|
scroll?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Preserve search params from the current URL across navigation.
|
|
88
|
+
*
|
|
89
|
+
* - `true` — preserve ALL current search params (target params take precedence)
|
|
90
|
+
* - `string[]` — preserve only the named params (e.g. `['private', 'token']`)
|
|
91
|
+
*
|
|
92
|
+
* Useful for route-group gating where a search param (e.g. `?private=access`)
|
|
93
|
+
* must persist across internal navigations. The target href's own search params
|
|
94
|
+
* always take precedence over preserved ones.
|
|
95
|
+
*
|
|
96
|
+
* During SSR, reads search params from the request context. On the client,
|
|
97
|
+
* reads from the current URL and updates reactively when the URL changes.
|
|
98
|
+
*/
|
|
99
|
+
preserveSearchParams?: true | string[];
|
|
45
100
|
/**
|
|
46
101
|
* Called before client-side navigation commits. Call `e.preventDefault()`
|
|
47
102
|
* to cancel the default navigation — the caller is then responsible for
|
|
@@ -54,48 +109,67 @@ interface LinkBaseProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'h
|
|
|
54
109
|
children?: ReactNode;
|
|
55
110
|
}
|
|
56
111
|
|
|
112
|
+
// ─── Typed Link Props ────────────────────────────────────────────
|
|
113
|
+
|
|
57
114
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* the params prop is not available.
|
|
115
|
+
* Widen server-side string params to string | number for Link convenience.
|
|
116
|
+
* Exported for use by codegen-generated overloads.
|
|
61
117
|
*/
|
|
62
|
-
export
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
118
|
+
export type LinkSegmentParams<T> = {
|
|
119
|
+
[K in keyof T]: [string] extends [T[K]] ? string | number : T[K];
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// ─── External Href Types ─────────────────────────────────────────
|
|
123
|
+
//
|
|
124
|
+
// `ExternalHref` and the public `LinkFunction` interface live in
|
|
125
|
+
// `./index.ts` rather than this file. They MUST be originally declared
|
|
126
|
+
// in the same module that the codegen augments (`@timber-js/app/client`)
|
|
127
|
+
// so that codegen-generated per-route call signatures merge with the
|
|
128
|
+
// same interface that types the `Link` constant. Re-exporting an
|
|
129
|
+
// interface via `export type {}` does NOT participate in module
|
|
130
|
+
// augmentation merging — only originally-declared interfaces do.
|
|
131
|
+
// See TIM-624.
|
|
132
|
+
|
|
133
|
+
// ─── searchParams prop shapes ────────────────────────────────────
|
|
134
|
+
//
|
|
135
|
+
// Per-route Link overloads (emitted by codegen) pass the flat values shape:
|
|
136
|
+
// searchParams={{ page: 2, q: 'boots' }}
|
|
137
|
+
// The framework looks up the route's SearchParamsDefinition from the
|
|
138
|
+
// search-params registry at runtime (see TIM-830).
|
|
139
|
+
//
|
|
140
|
+
// The catch-all overload in client/index.ts (external/computed hrefs)
|
|
141
|
+
// additionally accepts the legacy wrapped shape:
|
|
142
|
+
// searchParams={{ definition: def, values: { page: 2 } }}
|
|
143
|
+
// because there is no way to look up a definition from a computed string.
|
|
144
|
+
//
|
|
145
|
+
// `resolveHref` discriminates at runtime by presence of a `definition` key.
|
|
146
|
+
type WrappedSearchParamsProp = {
|
|
147
|
+
definition: SearchParamsDefinition<Record<string, unknown>>;
|
|
148
|
+
values: Record<string, unknown>;
|
|
149
|
+
};
|
|
150
|
+
type FlatSearchParamsProp = Record<string, unknown>;
|
|
151
|
+
type LinkSearchParamsProp = WrappedSearchParamsProp | FlatSearchParamsProp;
|
|
74
152
|
|
|
75
153
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* <Link href="/products/[id]" params={{ id: 123 }}>
|
|
154
|
+
* Runtime-only loose props used internally by the Link implementation.
|
|
155
|
+
* Not exposed to callers — the public API uses LinkFunction.
|
|
79
156
|
*/
|
|
80
|
-
|
|
81
|
-
/** Route pattern with dynamic segments (e.g. "/products/[id]") */
|
|
157
|
+
interface LinkRuntimeProps extends LinkBaseProps {
|
|
82
158
|
href: string;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* Single dynamic segments accept string | number (numbers are stringified).
|
|
86
|
-
* Catch-all segments accept string[].
|
|
87
|
-
*/
|
|
88
|
-
params: Record<string, string | number | string[]>;
|
|
89
|
-
/**
|
|
90
|
-
* Typed search params — serialized via the route's SearchParamsDefinition.
|
|
91
|
-
*/
|
|
92
|
-
searchParams?: {
|
|
93
|
-
definition: SearchParamsDefinition<Record<string, unknown>>;
|
|
94
|
-
values: Record<string, unknown>;
|
|
95
|
-
};
|
|
159
|
+
segmentParams?: Record<string, string | number | string[]>;
|
|
160
|
+
searchParams?: LinkSearchParamsProp;
|
|
96
161
|
}
|
|
97
162
|
|
|
98
|
-
|
|
163
|
+
// Legacy exports for backward compat (used by buildLinkProps, tests, etc.)
|
|
164
|
+
export type LinkPropsWithHref = LinkBaseProps & {
|
|
165
|
+
href: string;
|
|
166
|
+
segmentParams?: never;
|
|
167
|
+
searchParams?: LinkSearchParamsProp;
|
|
168
|
+
};
|
|
169
|
+
export type LinkPropsWithParams = LinkRuntimeProps & {
|
|
170
|
+
segmentParams: Record<string, string | number | string[]>;
|
|
171
|
+
};
|
|
172
|
+
export type LinkProps = LinkRuntimeProps;
|
|
99
173
|
|
|
100
174
|
// ─── Dangerous URL Scheme Detection ──────────────────────────────
|
|
101
175
|
|
|
@@ -141,57 +215,114 @@ export function isInternalHref(href: string): boolean {
|
|
|
141
215
|
* - [...param] → catch-all (joined with /)
|
|
142
216
|
* - [[...param]] → optional catch-all (omitted if undefined/empty)
|
|
143
217
|
*/
|
|
218
|
+
/**
|
|
219
|
+
* Parse a route pattern's path portion into classified segments.
|
|
220
|
+
* Exported for testing. Uses the shared character-based classifier.
|
|
221
|
+
*/
|
|
222
|
+
export function parseSegments(pattern: string): UrlSegment[] {
|
|
223
|
+
return pattern.split('/').filter(Boolean).map(classifyUrlSegment);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Resolve a single classified segment into its string representation.
|
|
228
|
+
* Returns null for optional catch-all with no value (filtered out before join).
|
|
229
|
+
*
|
|
230
|
+
* When schema codecs are registered (via virtual:timber-schema), uses
|
|
231
|
+
* codec.serialize() for URL construction instead of plain String().
|
|
232
|
+
*/
|
|
233
|
+
function resolveSegment(
|
|
234
|
+
seg: UrlSegment,
|
|
235
|
+
params: Record<string, string | number | string[]>,
|
|
236
|
+
pattern: string
|
|
237
|
+
): string | null {
|
|
238
|
+
switch (seg.kind) {
|
|
239
|
+
case 'static':
|
|
240
|
+
return seg.value;
|
|
241
|
+
|
|
242
|
+
case 'optional-catch-all': {
|
|
243
|
+
const value = params[seg.name];
|
|
244
|
+
if (value === undefined || (Array.isArray(value) && value.length === 0)) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const codec = getLinkCodec(`[[...${seg.name}]]`);
|
|
248
|
+
if (codec) {
|
|
249
|
+
const serialized = codec.serialize(value);
|
|
250
|
+
if (!serialized) return null;
|
|
251
|
+
// Codec returns a path string (may contain '/') — encode each segment
|
|
252
|
+
return serialized.split('/').map(encodeURIComponent).join('/');
|
|
253
|
+
}
|
|
254
|
+
const segments = Array.isArray(value) ? value : [value];
|
|
255
|
+
return segments.map(encodeURIComponent).join('/');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
case 'catch-all': {
|
|
259
|
+
const value = params[seg.name];
|
|
260
|
+
if (value === undefined) {
|
|
261
|
+
throw new Error(
|
|
262
|
+
`<Link> missing required catch-all param "${seg.name}" for pattern "${pattern}".`
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
const codec = getLinkCodec(`[...${seg.name}]`);
|
|
266
|
+
if (codec) {
|
|
267
|
+
const serialized = codec.serialize(value);
|
|
268
|
+
if (!serialized) {
|
|
269
|
+
throw new Error(
|
|
270
|
+
`<Link> catch-all param "${seg.name}" codec returned null for pattern "${pattern}".`
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
// Codec returns a path string (may contain '/') — encode each segment
|
|
274
|
+
return serialized.split('/').map(encodeURIComponent).join('/');
|
|
275
|
+
}
|
|
276
|
+
const segments = Array.isArray(value) ? value : [value];
|
|
277
|
+
if (segments.length === 0) {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`<Link> catch-all param "${seg.name}" must have at least one segment for pattern "${pattern}".`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
return segments.map(encodeURIComponent).join('/');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
case 'dynamic': {
|
|
286
|
+
const value = params[seg.name];
|
|
287
|
+
if (value === undefined) {
|
|
288
|
+
throw new Error(`<Link> missing required param "${seg.name}" for pattern "${pattern}".`);
|
|
289
|
+
}
|
|
290
|
+
if (Array.isArray(value)) {
|
|
291
|
+
throw new Error(
|
|
292
|
+
`<Link> param "${seg.name}" expected a string but received an array for pattern "${pattern}".`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
const codec = getLinkCodec(`[${seg.name}]`);
|
|
296
|
+
const str = codec ? (codec.serialize(value) ?? String(value)) : String(value);
|
|
297
|
+
return encodeURIComponent(str);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Split a URL pattern into the path portion and any trailing ?query/#hash suffix.
|
|
304
|
+
* Uses URL parsing for correctness rather than manual index arithmetic.
|
|
305
|
+
*/
|
|
306
|
+
function splitPatternSuffix(pattern: string): [path: string, suffix: string] {
|
|
307
|
+
if (!pattern.includes('?') && !pattern.includes('#')) {
|
|
308
|
+
return [pattern, ''];
|
|
309
|
+
}
|
|
310
|
+
const url = new URL(pattern, 'http://x');
|
|
311
|
+
const suffix = url.search + url.hash;
|
|
312
|
+
const path = pattern.slice(0, pattern.length - suffix.length);
|
|
313
|
+
return [path, suffix];
|
|
314
|
+
}
|
|
315
|
+
|
|
144
316
|
export function interpolateParams(
|
|
145
317
|
pattern: string,
|
|
146
318
|
params: Record<string, string | number | string[]>
|
|
147
319
|
): string {
|
|
148
|
-
|
|
149
|
-
pattern
|
|
150
|
-
.replace(
|
|
151
|
-
/\[\[\.\.\.(\w+)\]\]|\[\.\.\.(\w+)\]|\[(\w+)\]/g,
|
|
152
|
-
(_match, optionalCatchAll, catchAll, single) => {
|
|
153
|
-
if (optionalCatchAll) {
|
|
154
|
-
const value = params[optionalCatchAll];
|
|
155
|
-
if (value === undefined || (Array.isArray(value) && value.length === 0)) {
|
|
156
|
-
return '';
|
|
157
|
-
}
|
|
158
|
-
const segments = Array.isArray(value) ? value : [value];
|
|
159
|
-
return segments.map(encodeURIComponent).join('/');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (catchAll) {
|
|
163
|
-
const value = params[catchAll];
|
|
164
|
-
if (value === undefined) {
|
|
165
|
-
throw new Error(
|
|
166
|
-
`<Link> missing required catch-all param "${catchAll}" for pattern "${pattern}".`
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
const segments = Array.isArray(value) ? value : [value];
|
|
170
|
-
if (segments.length === 0) {
|
|
171
|
-
throw new Error(
|
|
172
|
-
`<Link> catch-all param "${catchAll}" must have at least one segment for pattern "${pattern}".`
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
return segments.map(encodeURIComponent).join('/');
|
|
176
|
-
}
|
|
320
|
+
const [pathPart, suffix] = splitPatternSuffix(pattern);
|
|
177
321
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
if (Array.isArray(value)) {
|
|
184
|
-
throw new Error(
|
|
185
|
-
`<Link> param "${single}" expected a string but received an array for pattern "${pattern}".`
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
// Accept numbers — coerce to string for URL interpolation
|
|
189
|
-
return encodeURIComponent(String(value));
|
|
190
|
-
}
|
|
191
|
-
)
|
|
192
|
-
// Clean up trailing slash from empty optional catch-all
|
|
193
|
-
.replace(/\/+$/, '') || '/'
|
|
194
|
-
);
|
|
322
|
+
const resolved = parseSegments(pathPart)
|
|
323
|
+
.map((seg) => resolveSegment(seg, params, pattern))
|
|
324
|
+
.filter((s): s is string => s !== null);
|
|
325
|
+
return ('/' + resolved.join('/') || '/') + suffix;
|
|
195
326
|
}
|
|
196
327
|
|
|
197
328
|
// ─── Resolve Href ───────────────────────────────────────────────
|
|
@@ -204,13 +335,19 @@ export function interpolateParams(
|
|
|
204
335
|
* - searchParams serialization via SearchParamsDefinition
|
|
205
336
|
* - Validation that searchParams and inline query strings are exclusive
|
|
206
337
|
*/
|
|
338
|
+
/**
|
|
339
|
+
* Runtime discriminator: treat `searchParams` as the legacy wrapped shape
|
|
340
|
+
* only when it literally has a `definition` key. Everything else is the
|
|
341
|
+
* flat `Partial<T>` values shape (TIM-830).
|
|
342
|
+
*/
|
|
343
|
+
function isWrappedSearchParamsProp(sp: LinkSearchParamsProp): sp is WrappedSearchParamsProp {
|
|
344
|
+
return 'definition' in sp;
|
|
345
|
+
}
|
|
346
|
+
|
|
207
347
|
export function resolveHref(
|
|
208
348
|
href: string,
|
|
209
349
|
params?: Record<string, string | number | string[]>,
|
|
210
|
-
searchParams?:
|
|
211
|
-
definition: SearchParamsDefinition<Record<string, unknown>>;
|
|
212
|
-
values: Record<string, unknown>;
|
|
213
|
-
}
|
|
350
|
+
searchParams?: LinkSearchParamsProp
|
|
214
351
|
): string {
|
|
215
352
|
let resolvedPath = href;
|
|
216
353
|
|
|
@@ -229,7 +366,36 @@ export function resolveHref(
|
|
|
229
366
|
);
|
|
230
367
|
}
|
|
231
368
|
|
|
232
|
-
|
|
369
|
+
let definition: SearchParamsDefinition<Record<string, unknown>> | undefined;
|
|
370
|
+
let values: Record<string, unknown>;
|
|
371
|
+
|
|
372
|
+
if (isWrappedSearchParamsProp(searchParams)) {
|
|
373
|
+
// Legacy wrapped shape — used by the catch-all overload for
|
|
374
|
+
// computed/external hrefs where no route lookup is possible.
|
|
375
|
+
definition = searchParams.definition;
|
|
376
|
+
values = searchParams.values;
|
|
377
|
+
} else {
|
|
378
|
+
// Flat shape (TIM-830): look up the definition from the runtime
|
|
379
|
+
// registry using the un-interpolated href pattern (e.g. '/products/[id]').
|
|
380
|
+
// The search-params registry is populated eagerly at startup by the
|
|
381
|
+
// virtual:timber-search-params-registry module generated by the
|
|
382
|
+
// timber-routing Vite plugin.
|
|
383
|
+
definition = getSearchParamsDefinition(href) as
|
|
384
|
+
| SearchParamsDefinition<Record<string, unknown>>
|
|
385
|
+
| undefined;
|
|
386
|
+
values = searchParams;
|
|
387
|
+
if (!definition) {
|
|
388
|
+
throw new Error(
|
|
389
|
+
`<Link> received a flat searchParams object for href "${href}", but no ` +
|
|
390
|
+
`SearchParamsDefinition is registered for that route. ` +
|
|
391
|
+
`Either the route does not export \`searchParams\` from its \`params.ts\`/\`page.tsx\`, ` +
|
|
392
|
+
`or the search-params registry module was not loaded. ` +
|
|
393
|
+
`For external or computed hrefs, pass the legacy \`{ definition, values }\` shape instead.`
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const qs = definition.serialize(values);
|
|
233
399
|
if (qs) {
|
|
234
400
|
resolvedPath = `${resolvedPath}?${qs}`;
|
|
235
401
|
}
|
|
@@ -251,10 +417,7 @@ interface LinkOutputProps {
|
|
|
251
417
|
export function buildLinkProps(
|
|
252
418
|
props: Pick<LinkPropsWithHref, 'href'> & {
|
|
253
419
|
params?: Record<string, string | number | string[]>;
|
|
254
|
-
searchParams?:
|
|
255
|
-
definition: SearchParamsDefinition<Record<string, unknown>>;
|
|
256
|
-
values: Record<string, unknown>;
|
|
257
|
-
};
|
|
420
|
+
searchParams?: LinkSearchParamsProp;
|
|
258
421
|
}
|
|
259
422
|
): LinkOutputProps {
|
|
260
423
|
const resolvedHref = resolveHref(props.href, props.params, props.searchParams);
|
|
@@ -302,23 +465,76 @@ function shouldInterceptClick(
|
|
|
302
465
|
* navigation via the router. No global event delegation — each Link owns
|
|
303
466
|
* its own click handling.
|
|
304
467
|
*
|
|
305
|
-
* Supports typed routes via
|
|
306
|
-
*
|
|
468
|
+
* Supports typed routes via the Routes interface (populated by codegen).
|
|
469
|
+
* At runtime:
|
|
470
|
+
* - `segmentParams` prop interpolates dynamic segments in the href pattern
|
|
307
471
|
* - `searchParams` prop serializes query parameters via a SearchParamsDefinition
|
|
472
|
+
*
|
|
473
|
+
* Typed via the LinkFunction callable interface. The base call signature
|
|
474
|
+
* forbids segmentParams; per-route signatures are added by codegen via
|
|
475
|
+
* interface merging. See TIM-624.
|
|
308
476
|
*/
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
477
|
+
// Cast to LinkFunction — the callable interface provides the public type,
|
|
478
|
+
// but the implementation destructures LinkRuntimeProps internally.
|
|
479
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
480
|
+
export const Link: LinkFunction = function LinkImpl(props: any) {
|
|
481
|
+
const {
|
|
482
|
+
href,
|
|
483
|
+
prefetch,
|
|
484
|
+
scroll,
|
|
485
|
+
segmentParams,
|
|
486
|
+
searchParams,
|
|
487
|
+
preserveSearchParams,
|
|
488
|
+
onNavigate,
|
|
489
|
+
onClick: userOnClick,
|
|
490
|
+
onMouseEnter: userOnMouseEnter,
|
|
491
|
+
children,
|
|
492
|
+
...rest
|
|
493
|
+
} = props as LinkRuntimeProps;
|
|
494
|
+
const { href: baseHref } = buildLinkProps({ href, params: segmentParams, searchParams });
|
|
495
|
+
|
|
496
|
+
// ─── Per-link pending state (useOptimistic) ────────────────────────
|
|
497
|
+
// Each Link has its own pending state. Only the clicked link's
|
|
498
|
+
// setter is invoked during navigation — zero other links re-render.
|
|
499
|
+
//
|
|
500
|
+
// Link click stores the instance; NavigationRoot activates inside startTransition.
|
|
501
|
+
// useOptimistic auto-reverts to LINK_IDLE when the navigation
|
|
502
|
+
// startTransition — batched with the new tree commit.
|
|
503
|
+
//
|
|
504
|
+
// See design/19-client-navigation.md §"Per-Link Pending State"
|
|
505
|
+
const [linkStatus, setIsPending] = useOptimistic(LINK_IDLE);
|
|
506
|
+
|
|
507
|
+
// Build the link instance ref for the pending store.
|
|
508
|
+
// The ref is stable across renders — we update the setter on each
|
|
509
|
+
// render to keep it current.
|
|
510
|
+
const linkInstanceRef = useRef<LinkPendingInstance | null>(null);
|
|
511
|
+
if (!linkInstanceRef.current) {
|
|
512
|
+
linkInstanceRef.current = { setIsPending };
|
|
513
|
+
} else {
|
|
514
|
+
linkInstanceRef.current.setIsPending = setIsPending;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Clean up if this link unmounts while it's the current navigation link.
|
|
518
|
+
// Prevents calling setOptimistic on an unmounted component.
|
|
519
|
+
useEffect(() => {
|
|
520
|
+
const instance = linkInstanceRef.current;
|
|
521
|
+
return () => {
|
|
522
|
+
if (instance) {
|
|
523
|
+
unmountLinkForCurrentNavigation(instance);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}, []);
|
|
527
|
+
|
|
528
|
+
// Preserve search params from the current URL when requested.
|
|
529
|
+
// useSearchParams() works during both SSR (reads from request context)
|
|
530
|
+
// and on the client (reads from window.location, reactive to URL changes).
|
|
531
|
+
// We read current search params directly to avoid unconditional hook calls.
|
|
532
|
+
// On the client, window.location.search is always current; during SSR,
|
|
533
|
+
// getSsrData() provides the request's search params.
|
|
534
|
+
const resolvedHref = preserveSearchParams
|
|
535
|
+
? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
|
|
536
|
+
: baseHref;
|
|
537
|
+
|
|
322
538
|
const internal = isInternalHref(resolvedHref);
|
|
323
539
|
|
|
324
540
|
// ─── Click handler ───────────────────────────────────────────
|
|
@@ -349,9 +565,42 @@ export function Link({
|
|
|
349
565
|
const router = getRouterOrNull();
|
|
350
566
|
if (!router) return; // SSR or pre-hydration — fall through to browser nav
|
|
351
567
|
|
|
352
|
-
event.preventDefault();
|
|
353
568
|
const shouldScroll = scroll !== false;
|
|
354
|
-
|
|
569
|
+
|
|
570
|
+
// Register this link in the pending store. The actual
|
|
571
|
+
// setIsPending(LINK_PENDING) call happens inside NavigationRoot's
|
|
572
|
+
// async startTransition via activateLinkPending().
|
|
573
|
+
|
|
574
|
+
setLinkForCurrentNavigation(linkInstanceRef.current);
|
|
575
|
+
|
|
576
|
+
// When Navigation API is active, let the <a> click propagate
|
|
577
|
+
// naturally — do NOT call preventDefault(). The navigate event
|
|
578
|
+
// handler intercepts it and runs the RSC pipeline. This is a
|
|
579
|
+
// user-initiated navigation, so Chrome shows the native loading
|
|
580
|
+
// indicator (tab spinner). Metadata (scroll, link instance) is
|
|
581
|
+
// passed via nav-link-store so the handler can configure the nav.
|
|
582
|
+
//
|
|
583
|
+
// Without Navigation API (fallback), preventDefault and drive
|
|
584
|
+
// navigation through the router as before.
|
|
585
|
+
if (hasNavigationApi()) {
|
|
586
|
+
setNavLinkMetadata({
|
|
587
|
+
scroll: shouldScroll,
|
|
588
|
+
linkInstance: linkInstanceRef.current,
|
|
589
|
+
});
|
|
590
|
+
// Don't preventDefault — let the <a> click fire the navigate event
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// History API fallback — prevent default and navigate via router
|
|
595
|
+
event.preventDefault();
|
|
596
|
+
|
|
597
|
+
// Re-merge preserved search params at click time to pick up any
|
|
598
|
+
// URL changes since render (e.g. from other navigations or pushState).
|
|
599
|
+
const navHref = preserveSearchParams
|
|
600
|
+
? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
|
|
601
|
+
: resolvedHref;
|
|
602
|
+
|
|
603
|
+
void router.navigate(navHref, { scroll: shouldScroll });
|
|
355
604
|
}
|
|
356
605
|
: userOnClick; // External links — just pass through user's onClick
|
|
357
606
|
|
|
@@ -362,14 +611,18 @@ export function Link({
|
|
|
362
611
|
userOnMouseEnter?.(event);
|
|
363
612
|
const router = getRouterOrNull();
|
|
364
613
|
if (router) {
|
|
365
|
-
|
|
614
|
+
// Re-merge preserved search params at hover time for fresh prefetch URL
|
|
615
|
+
const prefetchHref = preserveSearchParams
|
|
616
|
+
? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
|
|
617
|
+
: resolvedHref;
|
|
618
|
+
router.prefetch(prefetchHref);
|
|
366
619
|
}
|
|
367
620
|
}
|
|
368
621
|
: userOnMouseEnter;
|
|
369
622
|
|
|
370
623
|
return (
|
|
371
624
|
<a {...rest} href={resolvedHref} onClick={handleClick} onMouseEnter={handleMouseEnter}>
|
|
372
|
-
<
|
|
625
|
+
<LinkStatusContext.Provider value={linkStatus}>{children}</LinkStatusContext.Provider>
|
|
373
626
|
</a>
|
|
374
627
|
);
|
|
375
|
-
}
|
|
628
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navigation Link Store — passes per-link metadata from Link's onClick
|
|
3
|
+
* to the Navigation API's navigate event handler.
|
|
4
|
+
*
|
|
5
|
+
* When the Navigation API is active, Link does NOT call event.preventDefault()
|
|
6
|
+
* or router.navigate(). Instead it stores metadata (scroll option, link
|
|
7
|
+
* pending instance) here, and lets the <a> click propagate naturally.
|
|
8
|
+
* The navigate event handler reads this metadata to configure the RSC
|
|
9
|
+
* navigation with the correct options.
|
|
10
|
+
*
|
|
11
|
+
* This store is consumed once per navigation — after reading, the metadata
|
|
12
|
+
* is cleared. If no metadata is present (e.g., a plain <a> tag without
|
|
13
|
+
* our Link component), the navigate handler uses default options.
|
|
14
|
+
*
|
|
15
|
+
* See design/19-client-navigation.md §"Navigation API Integration"
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { LinkPendingInstance } from './link-pending-store.js';
|
|
19
|
+
|
|
20
|
+
export interface NavLinkMetadata {
|
|
21
|
+
/** Whether to scroll to top after navigation. Default: true. */
|
|
22
|
+
scroll: boolean;
|
|
23
|
+
/** The Link's pending state instance for per-link status tracking. */
|
|
24
|
+
linkInstance: LinkPendingInstance | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let pendingMetadata: NavLinkMetadata | null = null;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Store metadata from Link's onClick for the next navigate event.
|
|
31
|
+
* Called synchronously in the click handler — the navigate event
|
|
32
|
+
* fires synchronously after onClick returns.
|
|
33
|
+
*/
|
|
34
|
+
export function setNavLinkMetadata(metadata: NavLinkMetadata): void {
|
|
35
|
+
pendingMetadata = metadata;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Consume the stored metadata. Returns null if no Link onClick
|
|
40
|
+
* preceded this navigation (e.g., plain <a> tag, programmatic nav).
|
|
41
|
+
* Clears the store after reading.
|
|
42
|
+
*/
|
|
43
|
+
export function consumeNavLinkMetadata(): NavLinkMetadata | null {
|
|
44
|
+
const metadata = pendingMetadata;
|
|
45
|
+
pendingMetadata = null;
|
|
46
|
+
return metadata;
|
|
47
|
+
}
|