@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.140
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/AGENTS.md +17 -0
- package/README.md +432 -7
- package/dist/bin/rango.js +2073 -213
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +7258 -2714
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +140 -67
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +329 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +487 -0
- package/skills/caching/SKILL.md +357 -25
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +246 -0
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +16 -10
- package/skills/document-cache/SKILL.md +87 -62
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +557 -79
- package/skills/host-router/SKILL.md +320 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +207 -15
- package/skills/layout/SKILL.md +146 -6
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +616 -54
- package/skills/middleware/SKILL.md +217 -37
- package/skills/migrate-nextjs/SKILL.md +611 -0
- package/skills/migrate-react-router/SKILL.md +927 -0
- package/skills/mime-routes/SKILL.md +42 -11
- package/skills/observability/SKILL.md +194 -0
- package/skills/parallel/SKILL.md +284 -3
- package/skills/ppr/SKILL.md +426 -0
- package/skills/prerender/SKILL.md +437 -52
- package/skills/rango/SKILL.md +369 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +263 -121
- package/skills/route/SKILL.md +350 -21
- package/skills/router-setup/SKILL.md +246 -33
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +126 -222
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +131 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +85 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +532 -103
- package/skills/use-cache/SKILL.md +367 -0
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +77 -44
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +114 -0
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +293 -202
- package/src/browser/history-state.ts +101 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +11 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +385 -576
- package/src/browser/navigation-client.ts +245 -75
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +184 -118
- package/src/browser/navigation-transaction.ts +247 -0
- package/src/browser/network-error-handler.ts +88 -0
- package/src/browser/partial-update.ts +412 -364
- package/src/browser/prefetch/cache.ts +359 -0
- package/src/browser/prefetch/fetch.ts +452 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +209 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +194 -0
- package/src/browser/react/Link.tsx +275 -68
- package/src/browser/react/NavigationProvider.tsx +265 -109
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +70 -0
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +272 -60
- package/src/browser/react/location-state.ts +90 -20
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +35 -66
- package/src/browser/react/use-handle.ts +39 -126
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +39 -13
- package/src/browser/react/use-navigation.ts +53 -69
- package/src/browser/react/use-params.ts +75 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +98 -0
- package/src/browser/react/use-search-params.ts +51 -0
- package/src/browser/react/use-segments.ts +72 -99
- package/src/browser/response-adapter.ts +164 -0
- package/src/browser/rsc-router.tsx +300 -72
- package/src/browser/scroll-restoration.ts +138 -50
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +17 -1
- package/src/browser/server-action-bridge.ts +668 -613
- package/src/browser/types.ts +223 -51
- package/src/browser/validate-redirect-origin.ts +56 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +252 -161
- package/src/build/generate-route-types.ts +41 -1038
- package/src/build/index.ts +12 -7
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +225 -42
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +105 -0
- package/src/build/route-types/codegen.ts +113 -0
- package/src/build/route-types/include-resolution.ts +812 -0
- package/src/build/route-types/param-extraction.ts +51 -0
- package/src/build/route-types/per-module-writer.ts +144 -0
- package/src/build/route-types/router-processing.ts +695 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +223 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +60 -0
- package/src/cache/cache-policy.ts +199 -0
- package/src/cache/cache-runtime.ts +525 -0
- package/src/cache/cache-scope.ts +298 -332
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +2500 -158
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +17 -17
- package/src/cache/document-cache.ts +199 -92
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +111 -0
- package/src/cache/index.ts +29 -35
- package/src/cache/memory-segment-store.ts +363 -30
- package/src/cache/profile-registry.ts +88 -0
- package/src/cache/read-through-swr.ts +178 -0
- package/src/cache/segment-codec.ts +248 -0
- package/src/cache/shell-cache.ts +386 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +156 -211
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1102 -0
- package/src/client.rsc.tsx +43 -21
- package/src/client.tsx +131 -347
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +23 -4
- package/src/components/DefaultDocument.tsx +13 -3
- package/src/context-var.ts +168 -0
- package/src/debug.ts +19 -9
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +106 -10
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +110 -35
- package/src/handles/MetaTags.tsx +83 -59
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +93 -0
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +44 -53
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +20 -65
- package/src/host/errors.ts +21 -30
- package/src/host/index.ts +13 -9
- package/src/host/pattern-matcher.ts +50 -79
- package/src/host/router.ts +151 -121
- package/src/host/testing.ts +45 -32
- package/src/host/types.ts +52 -11
- package/src/host/utils.ts +2 -2
- package/src/href-client.ts +192 -57
- package/src/index.rsc.ts +177 -35
- package/src/index.ts +255 -71
- package/src/internal-debug.ts +9 -2
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +31 -99
- package/src/loader.ts +30 -12
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +41 -0
- package/src/prerender/param-hash.ts +16 -14
- package/src/prerender/store.ts +121 -21
- package/src/prerender.ts +460 -26
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +198 -128
- package/src/root-error-boundary.tsx +42 -48
- package/src/route-content-wrapper.tsx +22 -77
- package/src/route-definition/dsl-helpers.ts +1116 -0
- package/src/route-definition/helper-factories.ts +88 -0
- package/src/route-definition/helpers-types.ts +505 -0
- package/src/route-definition/index.ts +54 -0
- package/src/route-definition/redirect.ts +134 -0
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-definition.ts +1 -1481
- package/src/route-map-builder.ts +82 -144
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +71 -45
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +263 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +54 -27
- package/src/router/find-match.ts +245 -0
- package/src/router/handler-context.ts +377 -125
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +59 -28
- package/src/router/lazy-includes.ts +254 -0
- package/src/router/loader-resolution.ts +421 -157
- package/src/router/logging.ts +106 -6
- package/src/router/manifest.ts +131 -57
- package/src/router/match-api.ts +167 -246
- package/src/router/match-context.ts +4 -24
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +117 -93
- package/src/router/match-middleware/cache-lookup.ts +297 -150
- package/src/router/match-middleware/cache-store.ts +123 -51
- package/src/router/match-middleware/intercept-resolution.ts +44 -43
- package/src/router/match-middleware/segment-resolution.ts +64 -22
- package/src/router/match-pipelines.ts +11 -87
- package/src/router/match-result.ts +121 -50
- package/src/router/metrics.ts +219 -28
- package/src/router/middleware-types.ts +93 -0
- package/src/router/middleware.ts +505 -441
- package/src/router/navigation-snapshot.ts +133 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +311 -142
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +547 -0
- package/src/router/preview-match.ts +102 -0
- package/src/router/request-classification.ts +278 -0
- package/src/router/revalidation.ts +203 -62
- package/src/router/route-snapshot.ts +246 -0
- package/src/router/router-context.ts +45 -48
- package/src/router/router-interfaces.ts +554 -0
- package/src/router/router-options.ts +779 -0
- package/src/router/router-registry.ts +21 -0
- package/src/router/segment-resolution/fresh.ts +772 -0
- package/src/router/segment-resolution/helpers.ts +348 -0
- package/src/router/segment-resolution/loader-cache.ts +250 -0
- package/src/router/segment-resolution/loader-mask.ts +44 -0
- package/src/router/segment-resolution/revalidation.ts +1331 -0
- package/src/router/segment-resolution/static-store.ts +81 -0
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +56 -0
- package/src/router/segment-resolution.ts +25 -1354
- package/src/router/segment-wrappers.ts +292 -0
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +75 -0
- package/src/router/telemetry-otel.ts +261 -0
- package/src/router/telemetry.ts +377 -0
- package/src/router/timeout.ts +128 -0
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +240 -61
- package/src/router/types.ts +23 -70
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +781 -2378
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +46 -0
- package/src/rsc/handler.ts +905 -1142
- package/src/rsc/helpers.ts +275 -19
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +305 -0
- package/src/rsc/manifest-init.ts +77 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +155 -0
- package/src/rsc/progressive-enhancement.ts +502 -0
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +104 -0
- package/src/rsc/response-route-handler.ts +257 -0
- package/src/rsc/rsc-rendering.ts +337 -0
- package/src/rsc/runtime-warnings.ts +55 -0
- package/src/rsc/server-action.ts +522 -0
- package/src/rsc/shell-capture.ts +439 -0
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +95 -12
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +99 -82
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +349 -134
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +452 -85
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +310 -0
- package/src/server/fetchable-loader-store.ts +11 -6
- package/src/server/handle-store.ts +123 -42
- package/src/server/live.ts +130 -0
- package/src/server/loader-registry.ts +51 -100
- package/src/server/request-context.ts +842 -157
- package/src/server.ts +15 -8
- package/src/ssr/index.tsx +412 -136
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +45 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +701 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +199 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +584 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +40 -72
- package/src/theme/ThemeScript.tsx +12 -14
- package/src/theme/constants.ts +57 -15
- package/src/theme/index.ts +3 -20
- package/src/theme/theme-context.ts +5 -35
- package/src/theme/theme-script.ts +43 -39
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +123 -0
- package/src/types/cache-types.ts +207 -0
- package/src/types/error-types.ts +132 -0
- package/src/types/global-namespace.ts +113 -0
- package/src/types/handler-context.ts +839 -0
- package/src/types/index.ts +81 -0
- package/src/types/loader-types.ts +212 -0
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +138 -0
- package/src/types/route-entry.ts +114 -0
- package/src/types/segments.ts +271 -0
- package/src/types.ts +1 -1795
- package/src/urls/include-helper.ts +162 -0
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +43 -0
- package/src/urls/path-helper-types.ts +413 -0
- package/src/urls/path-helper.ts +275 -0
- package/src/urls/pattern-types.ts +124 -0
- package/src/urls/response-types.ts +109 -0
- package/src/urls/type-extraction.ts +316 -0
- package/src/urls/urls-function.ts +80 -0
- package/src/urls.ts +1 -1341
- package/src/use-loader.tsx +406 -141
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +182 -0
- package/src/vite/discovery/discover-routers.ts +389 -0
- package/src/vite/discovery/discovery-errors.ts +255 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +467 -0
- package/src/vite/discovery/route-types-writer.ts +214 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +161 -0
- package/src/vite/discovery/virtual-module-codegen.ts +183 -0
- package/src/vite/index.ts +23 -2255
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +303 -0
- package/src/vite/plugins/cjs-to-esm.ts +90 -0
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- package/src/vite/plugins/client-ref-hashing.ts +118 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
- package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
- package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +805 -0
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +313 -0
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +94 -0
- package/src/vite/plugins/version-plugin.ts +263 -0
- package/src/vite/plugins/virtual-entries.ts +234 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +560 -0
- package/src/vite/router-discovery.ts +1638 -0
- package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +132 -0
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +15 -0
- package/src/vite/utils/package-resolution.ts +89 -0
- package/src/vite/utils/prerender-utils.ts +249 -0
- package/src/vite/utils/shared-utils.ts +269 -0
- package/CLAUDE.md +0 -43
- package/dist/vite/index.named-routes.gen.ts +0 -103
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/react/use-client-cache.ts +0 -56
- package/src/browser/request-controller.ts +0 -164
- package/src/browser/shallow.ts +0 -35
- package/src/cache/memory-store.ts +0 -253
- package/src/handles/index.ts +0 -6
- package/src/href-context.ts +0 -33
- package/src/network-error-thrower.tsx +0 -21
- package/src/router.gen.ts +0 -6
- package/src/static-handler.gen.ts +0 -5
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-internal-ids.ts +0 -1167
- package/src/vite/package-resolution.ts +0 -125
- package/src/vite/virtual-entries.ts +0 -114
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -11,7 +11,13 @@
|
|
|
11
11
|
* - Handles SSR hydration by deferring system theme detection
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import React, {
|
|
14
|
+
import React, {
|
|
15
|
+
useCallback,
|
|
16
|
+
useEffect,
|
|
17
|
+
useMemo,
|
|
18
|
+
useState,
|
|
19
|
+
useRef,
|
|
20
|
+
} from "react";
|
|
15
21
|
import { ThemeContext } from "./theme-context.js";
|
|
16
22
|
import type {
|
|
17
23
|
ResolvedTheme,
|
|
@@ -20,11 +26,8 @@ import type {
|
|
|
20
26
|
ThemeContextValue,
|
|
21
27
|
ThemeProviderProps,
|
|
22
28
|
} from "./types.js";
|
|
23
|
-
import { THEME_COOKIE } from "./constants.js";
|
|
29
|
+
import { THEME_COOKIE, isValidTheme, warnInvalidTheme } from "./constants.js";
|
|
24
30
|
|
|
25
|
-
/**
|
|
26
|
-
* Get system preference for color scheme
|
|
27
|
-
*/
|
|
28
31
|
function getSystemTheme(): ResolvedTheme {
|
|
29
32
|
if (typeof window !== "undefined" && window.matchMedia) {
|
|
30
33
|
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
@@ -34,9 +37,6 @@ function getSystemTheme(): ResolvedTheme {
|
|
|
34
37
|
return "light";
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
/**
|
|
38
|
-
* Read theme from cookie
|
|
39
|
-
*/
|
|
40
40
|
function readThemeFromCookie(storageKey: string): string | null {
|
|
41
41
|
if (typeof document === "undefined") return null;
|
|
42
42
|
|
|
@@ -44,15 +44,17 @@ function readThemeFromCookie(storageKey: string): string | null {
|
|
|
44
44
|
for (const cookie of cookies) {
|
|
45
45
|
const [name, ...rest] = cookie.trim().split("=");
|
|
46
46
|
if (name === storageKey) {
|
|
47
|
-
|
|
47
|
+
const raw = rest.join("=");
|
|
48
|
+
try {
|
|
49
|
+
return decodeURIComponent(raw);
|
|
50
|
+
} catch {
|
|
51
|
+
return raw;
|
|
52
|
+
}
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
return null;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
/**
|
|
54
|
-
* Read theme from localStorage
|
|
55
|
-
*/
|
|
56
58
|
function readThemeFromStorage(storageKey: string): string | null {
|
|
57
59
|
if (typeof localStorage === "undefined") return null;
|
|
58
60
|
|
|
@@ -63,9 +65,6 @@ function readThemeFromStorage(storageKey: string): string | null {
|
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
/**
|
|
67
|
-
* Write theme to cookie
|
|
68
|
-
*/
|
|
69
68
|
function writeThemeToCookie(storageKey: string, theme: Theme): void {
|
|
70
69
|
if (typeof document === "undefined") return;
|
|
71
70
|
|
|
@@ -74,9 +73,6 @@ function writeThemeToCookie(storageKey: string, theme: Theme): void {
|
|
|
74
73
|
document.cookie = cookie;
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
/**
|
|
78
|
-
* Write theme to localStorage
|
|
79
|
-
*/
|
|
80
76
|
function writeThemeToStorage(storageKey: string, theme: Theme): void {
|
|
81
77
|
if (typeof localStorage === "undefined") return;
|
|
82
78
|
|
|
@@ -87,56 +83,41 @@ function writeThemeToStorage(storageKey: string, theme: Theme): void {
|
|
|
87
83
|
}
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
|
|
91
|
-
* Apply theme to HTML element
|
|
92
|
-
*/
|
|
93
|
-
function applyThemeToDocument(
|
|
94
|
-
theme: Theme,
|
|
95
|
-
config: ResolvedThemeConfig
|
|
96
|
-
): void {
|
|
86
|
+
function applyThemeToDocument(theme: Theme, config: ResolvedThemeConfig): void {
|
|
97
87
|
if (typeof document === "undefined") return;
|
|
98
88
|
|
|
99
|
-
const resolved =
|
|
100
|
-
|
|
101
|
-
|
|
89
|
+
const resolved =
|
|
90
|
+
theme === "system" && config.enableSystem
|
|
91
|
+
? getSystemTheme()
|
|
92
|
+
: (theme as ResolvedTheme);
|
|
102
93
|
|
|
103
94
|
const value = config.value[resolved] || resolved;
|
|
104
95
|
const el = document.documentElement;
|
|
105
96
|
|
|
106
|
-
// Apply attribute
|
|
107
97
|
if (config.attribute === "class") {
|
|
108
|
-
// Remove all theme classes
|
|
109
98
|
for (const t of config.themes) {
|
|
110
99
|
const v = config.value[t] || t;
|
|
111
100
|
el.classList.remove(v);
|
|
112
101
|
}
|
|
113
|
-
// Add current theme class
|
|
114
102
|
el.classList.add(value);
|
|
115
103
|
} else {
|
|
116
104
|
el.setAttribute(config.attribute, value);
|
|
117
105
|
}
|
|
118
106
|
|
|
119
|
-
// Set color-scheme for native dark mode support
|
|
120
107
|
if (config.enableColorScheme) {
|
|
121
108
|
el.style.colorScheme = resolved;
|
|
122
109
|
}
|
|
123
110
|
}
|
|
124
111
|
|
|
125
|
-
/**
|
|
126
|
-
* Get the resolved stored theme (validated against available themes)
|
|
127
|
-
*/
|
|
128
112
|
function getStoredTheme(config: ResolvedThemeConfig): Theme {
|
|
129
113
|
const { storageKey, themes, defaultTheme, enableSystem } = config;
|
|
130
114
|
|
|
131
|
-
// Try cookie first (for SSR consistency)
|
|
132
115
|
let stored = readThemeFromCookie(storageKey);
|
|
133
116
|
|
|
134
|
-
// Fall back to localStorage
|
|
135
117
|
if (!stored) {
|
|
136
118
|
stored = readThemeFromStorage(storageKey);
|
|
137
119
|
}
|
|
138
120
|
|
|
139
|
-
// Validate stored value
|
|
140
121
|
if (stored) {
|
|
141
122
|
if (stored === "system" && enableSystem) {
|
|
142
123
|
return "system";
|
|
@@ -149,49 +130,45 @@ function getStoredTheme(config: ResolvedThemeConfig): Theme {
|
|
|
149
130
|
return defaultTheme;
|
|
150
131
|
}
|
|
151
132
|
|
|
152
|
-
/**
|
|
153
|
-
* ThemeProvider component
|
|
154
|
-
*
|
|
155
|
-
* Provides theme state to the component tree via context.
|
|
156
|
-
* Handles theme persistence, system preference detection, and cross-tab sync.
|
|
157
|
-
*/
|
|
158
133
|
export function ThemeProvider({
|
|
159
134
|
config,
|
|
160
135
|
initialTheme,
|
|
161
136
|
children,
|
|
162
137
|
}: ThemeProviderProps): React.ReactNode {
|
|
163
|
-
// Track mount state to avoid hydration mismatches
|
|
164
|
-
// During SSR and initial hydration, mounted is false
|
|
165
138
|
const [mounted, setMounted] = useState(false);
|
|
166
139
|
|
|
167
|
-
// Initialize theme from prop, storage, or default
|
|
168
140
|
const [theme, setThemeState] = useState<Theme>(() => {
|
|
169
141
|
if (initialTheme) return initialTheme;
|
|
170
142
|
if (typeof window === "undefined") return config.defaultTheme;
|
|
171
143
|
return getStoredTheme(config);
|
|
172
144
|
});
|
|
173
145
|
|
|
174
|
-
// Track system preference - use stable default during SSR
|
|
175
146
|
const [systemTheme, setSystemTheme] = useState<ResolvedTheme>("light");
|
|
176
147
|
|
|
177
|
-
// Set mounted after hydration and detect actual system theme
|
|
178
148
|
useEffect(() => {
|
|
179
149
|
setMounted(true);
|
|
180
150
|
setSystemTheme(getSystemTheme());
|
|
181
151
|
}, []);
|
|
182
152
|
|
|
183
|
-
// Set theme and persist to storage
|
|
184
153
|
const setTheme = useCallback(
|
|
185
154
|
(newTheme: Theme) => {
|
|
155
|
+
// Shared guard (isValidTheme) used by the server ctx.setTheme too: reject
|
|
156
|
+
// any value not in the configured theme set, AND reject "system" when
|
|
157
|
+
// system detection is off (applyThemeToDocument would write a bogus
|
|
158
|
+
// class="system"). Keeps the cookie from holding a value the server would
|
|
159
|
+
// reinterpret as defaultTheme on the next SSR (desyncing markup).
|
|
160
|
+
if (!isValidTheme(newTheme, config)) {
|
|
161
|
+
warnInvalidTheme(newTheme, config);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
186
164
|
setThemeState(newTheme);
|
|
187
165
|
writeThemeToCookie(config.storageKey, newTheme);
|
|
188
166
|
writeThemeToStorage(config.storageKey, newTheme);
|
|
189
167
|
applyThemeToDocument(newTheme, config);
|
|
190
168
|
},
|
|
191
|
-
[config]
|
|
169
|
+
[config],
|
|
192
170
|
);
|
|
193
171
|
|
|
194
|
-
// Listen for system preference changes
|
|
195
172
|
useEffect(() => {
|
|
196
173
|
if (!config.enableSystem) return;
|
|
197
174
|
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
@@ -202,13 +179,11 @@ export function ThemeProvider({
|
|
|
202
179
|
const newSystemTheme = e.matches ? "dark" : "light";
|
|
203
180
|
setSystemTheme(newSystemTheme);
|
|
204
181
|
|
|
205
|
-
// If current theme is "system", re-apply to update document
|
|
206
182
|
if (theme === "system") {
|
|
207
183
|
applyThemeToDocument("system", config);
|
|
208
184
|
}
|
|
209
185
|
};
|
|
210
186
|
|
|
211
|
-
// Modern browsers
|
|
212
187
|
mediaQuery.addEventListener("change", handleChange);
|
|
213
188
|
|
|
214
189
|
return () => {
|
|
@@ -216,7 +191,6 @@ export function ThemeProvider({
|
|
|
216
191
|
};
|
|
217
192
|
}, [config, theme]);
|
|
218
193
|
|
|
219
|
-
// Cross-tab synchronization via localStorage storage event
|
|
220
194
|
useEffect(() => {
|
|
221
195
|
if (typeof window === "undefined") return;
|
|
222
196
|
|
|
@@ -226,14 +200,16 @@ export function ThemeProvider({
|
|
|
226
200
|
const newTheme = e.newValue;
|
|
227
201
|
if (!newTheme) return;
|
|
228
202
|
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
203
|
+
// A cross-tab storage event can carry any value (another tab, or stale
|
|
204
|
+
// localStorage). Reuse the shared validity rule: reject anything not a
|
|
205
|
+
// configured theme, AND reject "system" when system detection is off (it
|
|
206
|
+
// would apply a bogus class="system"). An invalid received value falls back
|
|
207
|
+
// to defaultTheme rather than applying as-is.
|
|
208
|
+
const applied: Theme = isValidTheme(newTheme, config)
|
|
209
|
+
? (newTheme as Theme)
|
|
210
|
+
: config.defaultTheme;
|
|
211
|
+
setThemeState(applied);
|
|
212
|
+
applyThemeToDocument(applied, config);
|
|
237
213
|
};
|
|
238
214
|
|
|
239
215
|
window.addEventListener("storage", handleStorageChange);
|
|
@@ -243,12 +219,8 @@ export function ThemeProvider({
|
|
|
243
219
|
};
|
|
244
220
|
}, [config]);
|
|
245
221
|
|
|
246
|
-
// Compute resolved theme
|
|
247
|
-
// During SSR (not mounted), use the initial theme or default to avoid hydration mismatch
|
|
248
222
|
const resolvedTheme: ResolvedTheme = useMemo(() => {
|
|
249
223
|
if (!mounted) {
|
|
250
|
-
// During SSR, return the initial theme if it's not "system", otherwise "light"
|
|
251
|
-
// The inline script will apply the correct class before hydration
|
|
252
224
|
if (initialTheme && initialTheme !== "system") {
|
|
253
225
|
return initialTheme as ResolvedTheme;
|
|
254
226
|
}
|
|
@@ -260,7 +232,6 @@ export function ThemeProvider({
|
|
|
260
232
|
return theme as ResolvedTheme;
|
|
261
233
|
}, [theme, systemTheme, config.enableSystem, mounted, initialTheme]);
|
|
262
234
|
|
|
263
|
-
// Build themes list (include "system" if enabled)
|
|
264
235
|
const themes = useMemo(() => {
|
|
265
236
|
if (config.enableSystem) {
|
|
266
237
|
return ["system", ...config.themes.filter((t) => t !== "system")];
|
|
@@ -268,19 +239,16 @@ export function ThemeProvider({
|
|
|
268
239
|
return config.themes;
|
|
269
240
|
}, [config.themes, config.enableSystem]);
|
|
270
241
|
|
|
271
|
-
// Context value
|
|
272
|
-
// During SSR (not mounted), return stable values to avoid hydration mismatch
|
|
273
242
|
const contextValue: ThemeContextValue = useMemo(
|
|
274
243
|
() => ({
|
|
275
244
|
theme,
|
|
276
245
|
setTheme,
|
|
277
246
|
resolvedTheme,
|
|
278
|
-
// Return stable "light" for systemTheme during SSR - actual value updates after mount
|
|
279
247
|
systemTheme: mounted ? systemTheme : "light",
|
|
280
248
|
themes,
|
|
281
249
|
config,
|
|
282
250
|
}),
|
|
283
|
-
[theme, setTheme, resolvedTheme, systemTheme, themes, config, mounted]
|
|
251
|
+
[theme, setTheme, resolvedTheme, systemTheme, themes, config, mounted],
|
|
284
252
|
);
|
|
285
253
|
|
|
286
254
|
return (
|
|
@@ -8,17 +8,21 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Must be placed in the <head> element of your document, before any stylesheets.
|
|
10
10
|
*
|
|
11
|
+
* Note: when theme is enabled in the router config, `<MetaTags />` ALREADY
|
|
12
|
+
* renders this FOUC script. Use `<ThemeScript />` only if you do NOT render
|
|
13
|
+
* `<MetaTags />`. Rendering both is safe — the inline script guards the
|
|
14
|
+
* matchMedia listener registration against double-running — but it is redundant.
|
|
15
|
+
*
|
|
11
16
|
* @example
|
|
12
17
|
* ```tsx
|
|
13
|
-
* // In your document component
|
|
18
|
+
* // In your document component. Use ThemeScript only when you do not render MetaTags.
|
|
14
19
|
* import { ThemeScript } from "@rangojs/router/theme";
|
|
15
20
|
*
|
|
16
21
|
* export function Document({ children }) {
|
|
17
22
|
* return (
|
|
18
23
|
* <html lang="en" suppressHydrationWarning>
|
|
19
24
|
* <head>
|
|
20
|
-
* <ThemeScript />
|
|
21
|
-
* <MetaTags />
|
|
25
|
+
* <ThemeScript config={config} />
|
|
22
26
|
* </head>
|
|
23
27
|
* <body>{children}</body>
|
|
24
28
|
* </html>
|
|
@@ -43,19 +47,13 @@ export interface ThemeScriptProps {
|
|
|
43
47
|
nonce?: string;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* to the HTML element before React hydration, preventing FOUC.
|
|
51
|
-
*/
|
|
52
|
-
export function ThemeScript({ config, nonce }: ThemeScriptProps): React.ReactNode {
|
|
50
|
+
export function ThemeScript({
|
|
51
|
+
config,
|
|
52
|
+
nonce,
|
|
53
|
+
}: ThemeScriptProps): React.ReactNode {
|
|
53
54
|
const scriptContent = generateThemeScript(config);
|
|
54
55
|
|
|
55
56
|
return (
|
|
56
|
-
<script
|
|
57
|
-
nonce={nonce}
|
|
58
|
-
dangerouslySetInnerHTML={{ __html: scriptContent }}
|
|
59
|
-
/>
|
|
57
|
+
<script nonce={nonce} dangerouslySetInnerHTML={{ __html: scriptContent }} />
|
|
60
58
|
);
|
|
61
59
|
}
|
package/src/theme/constants.ts
CHANGED
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
* Default values for theme configuration
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { ResolvedThemeConfig, ThemeConfig } from "./types.js";
|
|
5
|
+
import type { ResolvedThemeConfig, Theme, ThemeConfig } from "./types.js";
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Default theme configuration values
|
|
9
|
-
*/
|
|
10
7
|
export const THEME_DEFAULTS = {
|
|
11
8
|
defaultTheme: "system",
|
|
12
9
|
themes: ["light", "dark"],
|
|
@@ -16,9 +13,6 @@ export const THEME_DEFAULTS = {
|
|
|
16
13
|
enableColorScheme: true,
|
|
17
14
|
} as const;
|
|
18
15
|
|
|
19
|
-
/**
|
|
20
|
-
* Cookie configuration for theme persistence
|
|
21
|
-
*/
|
|
22
16
|
export const THEME_COOKIE: {
|
|
23
17
|
readonly maxAge: number;
|
|
24
18
|
readonly path: string;
|
|
@@ -30,30 +24,78 @@ export const THEME_COOKIE: {
|
|
|
30
24
|
};
|
|
31
25
|
|
|
32
26
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
27
|
+
* Single owner of the setTheme validity rule, shared by the client
|
|
28
|
+
* (ThemeProvider) and server (ctx.setTheme) guards so they cannot drift.
|
|
29
|
+
*
|
|
30
|
+
* A theme is valid when it is one of the configured concrete themes, OR
|
|
31
|
+
* "system" but only while system detection is enabled. Rejecting "system" when
|
|
32
|
+
* `enableSystem` is false is load-bearing: applyThemeToDocument would otherwise
|
|
33
|
+
* leave "system" unresolved and write a bogus class="system" / colorScheme
|
|
34
|
+
* ="system" on <html> (the same bogus value resolveThemeConfig coerces away for
|
|
35
|
+
* the default).
|
|
36
|
+
*/
|
|
37
|
+
export function isValidTheme(
|
|
38
|
+
theme: string,
|
|
39
|
+
config: Pick<ResolvedThemeConfig, "themes" | "enableSystem">,
|
|
40
|
+
): boolean {
|
|
41
|
+
if (theme === "system") return config.enableSystem;
|
|
42
|
+
return config.themes.includes(theme);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Emit the shared "[Theme] Invalid theme value" warning. One owner of the
|
|
47
|
+
* message string so the client and server guards stay byte-identical.
|
|
48
|
+
*
|
|
49
|
+
* The valid-values list mirrors isValidTheme: "system" is only listed when
|
|
50
|
+
* enableSystem is true, otherwise the message would advertise a value the guard
|
|
51
|
+
* itself rejects.
|
|
35
52
|
*/
|
|
36
|
-
export function
|
|
37
|
-
|
|
53
|
+
export function warnInvalidTheme(
|
|
54
|
+
theme: string,
|
|
55
|
+
config: Pick<ResolvedThemeConfig, "themes" | "enableSystem">,
|
|
56
|
+
): void {
|
|
57
|
+
const validValues = config.enableSystem
|
|
58
|
+
? ["system", ...config.themes]
|
|
59
|
+
: config.themes;
|
|
60
|
+
console.warn(
|
|
61
|
+
`[Theme] Invalid theme value: "${theme}". Valid values: ${validValues.join(", ")}`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function resolveThemeConfig(
|
|
66
|
+
config: ThemeConfig | true,
|
|
67
|
+
): ResolvedThemeConfig {
|
|
38
68
|
if (config === true) {
|
|
39
69
|
config = {};
|
|
40
70
|
}
|
|
41
71
|
|
|
42
72
|
const themes = config.themes ?? [...THEME_DEFAULTS.themes];
|
|
43
73
|
|
|
44
|
-
// Build value mapping - default to identity mapping
|
|
45
74
|
const value: Record<string, string> = {};
|
|
46
75
|
for (const theme of themes) {
|
|
47
76
|
value[theme] = config.value?.[theme] ?? theme;
|
|
48
77
|
}
|
|
49
78
|
|
|
79
|
+
const enableSystem = config.enableSystem ?? THEME_DEFAULTS.enableSystem;
|
|
80
|
+
|
|
81
|
+
// When system detection is disabled, "system" is not a valid resolved theme.
|
|
82
|
+
// Coerce both the unset default and an explicit defaultTheme:"system" to the
|
|
83
|
+
// first concrete theme, so the FOUC script / ThemeProvider never apply a bogus
|
|
84
|
+
// class="system" / colorScheme="system" on <html>.
|
|
85
|
+
const requestedDefault = config.defaultTheme ?? THEME_DEFAULTS.defaultTheme;
|
|
86
|
+
const defaultTheme =
|
|
87
|
+
!enableSystem && requestedDefault === "system"
|
|
88
|
+
? (themes[0] as Theme)
|
|
89
|
+
: requestedDefault;
|
|
90
|
+
|
|
50
91
|
return {
|
|
51
|
-
defaultTheme
|
|
92
|
+
defaultTheme,
|
|
52
93
|
themes,
|
|
53
94
|
attribute: config.attribute ?? THEME_DEFAULTS.attribute,
|
|
54
95
|
storageKey: config.storageKey ?? THEME_DEFAULTS.storageKey,
|
|
55
|
-
enableSystem
|
|
56
|
-
enableColorScheme:
|
|
96
|
+
enableSystem,
|
|
97
|
+
enableColorScheme:
|
|
98
|
+
config.enableColorScheme ?? THEME_DEFAULTS.enableColorScheme,
|
|
57
99
|
value,
|
|
58
100
|
};
|
|
59
101
|
}
|
package/src/theme/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme module exports for @rangojs/router/theme
|
|
3
3
|
*
|
|
4
|
-
* This module provides
|
|
4
|
+
* This module provides the public theme API:
|
|
5
5
|
* - useTheme: Hook for accessing theme state in client components
|
|
6
6
|
* - ThemeProvider: Component for manual theme provider setup (typically not needed)
|
|
7
|
+
* - ThemeScript: FOUC-prevention script component for document/head usage
|
|
7
8
|
* - Types for theme configuration
|
|
8
9
|
*
|
|
9
10
|
* @example
|
|
@@ -22,16 +23,10 @@
|
|
|
22
23
|
* ```
|
|
23
24
|
*/
|
|
24
25
|
|
|
25
|
-
// Main hook for accessing theme
|
|
26
26
|
export { useTheme } from "./use-theme.js";
|
|
27
|
-
|
|
28
|
-
// Provider (typically auto-included via NavigationProvider when theme is enabled)
|
|
29
27
|
export { ThemeProvider } from "./ThemeProvider.js";
|
|
30
|
-
|
|
31
|
-
// Script component for FOUC prevention (use in document head)
|
|
32
28
|
export { ThemeScript, type ThemeScriptProps } from "./ThemeScript.js";
|
|
33
29
|
|
|
34
|
-
// Types
|
|
35
30
|
export type {
|
|
36
31
|
Theme,
|
|
37
32
|
ResolvedTheme,
|
|
@@ -43,16 +38,4 @@ export type {
|
|
|
43
38
|
ThemeContextValue,
|
|
44
39
|
} from "./types.js";
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
export { THEME_DEFAULTS, THEME_COOKIE, resolveThemeConfig } from "./constants.js";
|
|
48
|
-
|
|
49
|
-
// Script generation (for advanced SSR use cases)
|
|
50
|
-
export { generateThemeScript, getNonceAttribute } from "./theme-script.js";
|
|
51
|
-
|
|
52
|
-
// Context (for advanced use cases)
|
|
53
|
-
export {
|
|
54
|
-
ThemeContext,
|
|
55
|
-
useThemeContext,
|
|
56
|
-
initThemeConfigSync,
|
|
57
|
-
getSSRThemeConfig,
|
|
58
|
-
} from "./theme-context.js";
|
|
41
|
+
export { THEME_DEFAULTS, THEME_COOKIE } from "./constants.js";
|
|
@@ -10,52 +10,22 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { createContext, useContext, type Context } from "react";
|
|
13
|
-
import type {
|
|
13
|
+
import type { ThemeContextValue } from "./types.js";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* React context for theme state
|
|
17
17
|
* null when theme is not enabled in router config
|
|
18
18
|
*/
|
|
19
|
-
export const ThemeContext: Context<ThemeContextValue | null> =
|
|
19
|
+
export const ThemeContext: Context<ThemeContextValue | null> =
|
|
20
|
+
createContext<ThemeContextValue | null>(null);
|
|
20
21
|
|
|
21
|
-
/**
|
|
22
|
-
* SSR module-level state for theme config.
|
|
23
|
-
* Populated by initThemeConfigSync before React renders.
|
|
24
|
-
* Used by MetaTags during SSR to render the theme script.
|
|
25
|
-
*/
|
|
26
|
-
let ssrThemeConfig: ResolvedThemeConfig | null = null;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Initialize theme config synchronously for SSR.
|
|
30
|
-
* Called before rendering to populate state for MetaTags.
|
|
31
|
-
*
|
|
32
|
-
* @param config - Theme config from router, or null if theme is disabled
|
|
33
|
-
*/
|
|
34
|
-
export function initThemeConfigSync(config: ResolvedThemeConfig | null): void {
|
|
35
|
-
ssrThemeConfig = config;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Get theme config for SSR/hydration.
|
|
40
|
-
* Used by MetaTags to render the theme script.
|
|
41
|
-
*
|
|
42
|
-
* @returns Theme config if available, null otherwise
|
|
43
|
-
*/
|
|
44
|
-
export function getSSRThemeConfig(): ResolvedThemeConfig | null {
|
|
45
|
-
return ssrThemeConfig;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get theme context (internal use)
|
|
50
|
-
* Returns null if theme is not enabled
|
|
51
|
-
*/
|
|
52
22
|
export function useThemeContext(): ThemeContextValue | null {
|
|
53
23
|
return useContext(ThemeContext);
|
|
54
24
|
}
|
|
55
25
|
|
|
56
26
|
/**
|
|
57
27
|
* Get theme context, throwing if not available
|
|
58
|
-
*
|
|
28
|
+
* Used by useTheme hook
|
|
59
29
|
*/
|
|
60
30
|
export function requireThemeContext(): ThemeContextValue {
|
|
61
31
|
const ctx = useContext(ThemeContext);
|
|
@@ -63,7 +33,7 @@ export function requireThemeContext(): ThemeContextValue {
|
|
|
63
33
|
throw new Error(
|
|
64
34
|
"useTheme must be used within a ThemeProvider. " +
|
|
65
35
|
"Make sure theme is enabled in your router config: " +
|
|
66
|
-
"createRouter({ theme: { ... } })"
|
|
36
|
+
"createRouter({ theme: { ... } })",
|
|
67
37
|
);
|
|
68
38
|
}
|
|
69
39
|
return ctx;
|