├── .browserslistrc ├── .changeset ├── README.md └── config.json ├── .eslintignore ├── .eslintrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── documentation_isse.yml ├── dependabot.yml └── workflows │ ├── deduplicate-lock-file.yml │ ├── format.yml │ ├── integration-full.yml │ ├── integration-pr-ubuntu.yml │ ├── integration-pr-windows-macos.yml │ ├── no-response.yml │ ├── release-comments.yml │ ├── release-experimental.yml │ ├── release-nightly.yml │ ├── release.yml │ ├── shared-build.yml │ ├── shared-integration.yml │ ├── support.yml │ └── test.yml ├── .gitignore ├── .npmrc ├── .nvmrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── CLA.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DEVELOPMENT.md ├── LICENSE.md ├── README.md ├── build.utils.ts ├── contributors.yml ├── decisions ├── 0001-use-blocker.md ├── 0001-use-npm-to-manage-npm-dependencies-for-deno-projects.md ├── 0002-do-not-clone-request.md ├── 0002-lazy-route-modules.md ├── 0003-data-strategy.md ├── 0003-infer-types-for-useloaderdata-and-useactiondata-from-loader-and-action-via-generics.md ├── 0004-streaming-apis.md ├── 0005-remixing-react-router.md ├── 0006-linear-workflow.md ├── 0007-remix-on-react-router-6-4-0.md ├── 0008-only-support-js-conversion-for-app-code.md ├── 0009-do-not-rely-on-treeshaking-for-correctness.md ├── 0010-splitting-up-client-and-server-code-in-vite.md ├── 0011-routes-ts.md ├── 0012-type-inference.md ├── 0013-react-router-config-ts.md └── template.md ├── docs ├── community │ ├── api-development-strategy.md │ ├── contributing.md │ └── index.md ├── elements.md ├── explanation │ ├── README │ ├── code-splitting.md │ ├── hot-module-replacement.md │ ├── hydration.md │ ├── index.md │ ├── location.md │ ├── picking-a-router.md │ ├── progressive-enhancement.md │ ├── race-conditions.md │ ├── route-matching.md │ ├── server-client-execution.md │ ├── sessions-and-cookies.md │ ├── special-files.md │ ├── state-management.md │ └── type-safety.md ├── how-to │ ├── README │ ├── client-data.md │ ├── error-boundary.md │ ├── error-reporting.md │ ├── fetchers.md │ ├── file-route-conventions.md │ ├── file-uploads.md │ ├── form-validation.md │ ├── headers.md │ ├── index.md │ ├── meta.md │ ├── optimize-revalidation.md │ ├── pre-rendering.md │ ├── react-server-components.md │ ├── resource-routes.md │ ├── route-module-type-safety.md │ ├── search-params.md │ ├── spa.md │ ├── status.md │ ├── suspense.md │ ├── view-transitions.md │ └── webhook.md ├── index.md ├── prettier.config.js ├── start │ ├── README │ ├── framework │ │ ├── actions.md │ │ ├── custom.md │ │ ├── data-loading.md │ │ ├── deploying.md │ │ ├── index.md │ │ ├── installation.md │ │ ├── navigating.md │ │ ├── pending-ui.md │ │ ├── rendering.md │ │ ├── route-module.md │ │ ├── routing.md │ │ └── testing.md │ ├── index.md │ └── library │ │ ├── data-routers.md │ │ ├── index.md │ │ ├── installation.md │ │ ├── navigating.md │ │ ├── routing.md │ │ └── url-values.md ├── tutorials │ ├── README │ ├── address-book.md │ ├── advanced-data-fetching.md │ └── index.md └── upgrading │ ├── README │ ├── component-routes.md │ ├── index.md │ ├── remix.md │ ├── router-provider.md │ └── v6.md ├── examples ├── README.md ├── auth-router-provider │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── auth.ts │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── auth │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── auth.ts │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── basic-data-router │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── basic │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── custom-filter-link │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ ├── snkrs.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── custom-link │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── custom-query-parsing │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── types │ │ └── jsurl.d.ts │ └── vite.config.ts ├── data-router │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ ├── todos.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── error-boundaries │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ ├── routes.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── lazy-loading-router-provider │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ ├── pages │ │ │ ├── About.tsx │ │ │ └── Dashboard.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── lazy-loading │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ ├── pages │ │ │ ├── About.tsx │ │ │ └── Dashboard.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── modal-route-with-outlet │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── images.ts │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── modal │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── images.ts │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── multi-app │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── home │ │ ├── App.jsx │ │ ├── index.css │ │ ├── main.jsx │ │ └── no-match.jsx │ ├── inbox │ │ ├── App.jsx │ │ ├── index.css │ │ ├── index.html │ │ ├── main.jsx │ │ ├── messages.js │ │ └── no-match.jsx │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── server.js │ └── vite.config.js ├── navigation-blocking │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app.tsx │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── notes │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app.jsx │ │ ├── index.css │ │ ├── main.jsx │ │ ├── notes.js │ │ ├── routes │ │ │ ├── new.jsx │ │ │ ├── note.jsx │ │ │ ├── notes.jsx │ │ │ └── root.jsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── route-objects │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── scroll-restoration │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── search-params │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── index.css │ │ ├── main.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── ssr-data-router │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── server.js │ ├── src │ │ ├── App.tsx │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── index.css │ │ ├── lazy.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.js ├── ssr │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── server.js │ ├── src │ │ ├── App.tsx │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── index.css │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.js └── view-transitions │ ├── .gitignore │ ├── .stackblitzrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── index.css │ ├── main.tsx │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── integration ├── CHANGELOG.md ├── abort-signal-test.ts ├── action-test.ts ├── assets │ ├── toupload.txt │ └── touploadtoobig.txt ├── blocking-test.ts ├── browser-entry-test.ts ├── bug-report-test.ts ├── catch-boundary-data-test.ts ├── catch-boundary-test.ts ├── client-data-test.ts ├── custom-entry-server-test.ts ├── defer-loader-test.ts ├── defer-test.ts ├── error-boundary-test.ts ├── error-boundary-v2-test.ts ├── error-data-request-test.ts ├── error-sanitization-test.ts ├── fetch-globals-test.ts ├── fetcher-layout-test.ts ├── fetcher-test.ts ├── fog-of-war-test.ts ├── form-data-test.ts ├── form-test.ts ├── fs-routes-test.ts ├── headers-test.ts ├── helpers │ ├── cleanup.mjs │ ├── create-fixture.ts │ ├── playwright-fixture.ts │ ├── vite-5-template │ │ ├── .gitignore │ │ ├── app │ │ │ ├── root.tsx │ │ │ ├── routes.ts │ │ │ └── routes │ │ │ │ └── _index.tsx │ │ ├── env.d.ts │ │ ├── package.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── vite-6-template │ │ ├── .gitignore │ │ ├── app │ │ │ ├── root.tsx │ │ │ ├── routes.ts │ │ │ └── routes │ │ │ │ └── _index.tsx │ │ ├── env.d.ts │ │ ├── package.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── vite-cloudflare-template │ │ ├── .gitignore │ │ ├── app │ │ │ ├── entry.server.tsx │ │ │ ├── root.tsx │ │ │ ├── routes.ts │ │ │ └── routes │ │ │ │ └── _index.tsx │ │ ├── package.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── tsconfig.json │ │ └── vite.config.ts │ └── vite.ts ├── hook-useSubmit-test.ts ├── layout-route-test.ts ├── link-test.ts ├── loader-test.ts ├── matches-test.ts ├── multiple-cookies-test.ts ├── navigation-state-test.ts ├── package.json ├── playwright.config.ts ├── prefetch-test.ts ├── redirects-test.ts ├── remix-serve-test.ts ├── rendering-test.ts ├── request-test.ts ├── resource-routes-test.ts ├── revalidate-test.ts ├── root-route-test.ts ├── route-collisions-test.ts ├── route-config-test.ts ├── scroll-test.ts ├── server-entry-test.ts ├── set-cookie-revalidation-test.ts ├── single-fetch-test.ts ├── splat-routes-test.ts ├── transition-test.ts ├── tsconfig.json ├── typegen-test.ts ├── vite-absolute-base-test.ts ├── vite-basename-test.ts ├── vite-build-test.ts ├── vite-cloudflare-test.ts ├── vite-css-test.ts ├── vite-dev-custom-entry-test.ts ├── vite-dev-test.ts ├── vite-dot-client-test.ts ├── vite-dot-server-test.ts ├── vite-dotenv-test.ts ├── vite-hmr-hdr-test.ts ├── vite-loader-context-test.ts ├── vite-manifests-test.ts ├── vite-node-env-test.ts ├── vite-plugin-order-validation-test.ts ├── vite-prerender-test.ts ├── vite-presets-test.ts ├── vite-route-added-test.ts ├── vite-route-exports-modified-offscreen-test.ts ├── vite-server-bundles-test.ts ├── vite-server-fs-allow-test.ts ├── vite-spa-mode-test.ts └── vite-unused-route-exports-test.ts ├── jest ├── jest.config.shared.js └── transform.js ├── package.json ├── packages ├── create-react-router │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── create-react-router-test.ts │ │ ├── fixtures │ │ │ ├── basic │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── app │ │ │ │ │ ├── root.tsx │ │ │ │ │ ├── routes.ts │ │ │ │ │ └── routes │ │ │ │ │ │ └── home.tsx │ │ │ │ ├── package.json │ │ │ │ ├── public │ │ │ │ │ └── favicon.ico │ │ │ │ ├── tsconfig.json │ │ │ │ └── vite.config.ts │ │ │ ├── blank │ │ │ │ └── package.json │ │ │ ├── nested-dir-repo.tar.gz │ │ │ ├── tar.js │ │ │ ├── template.tar.gz │ │ │ ├── template.tgz │ │ │ ├── templates-repo.tar.gz │ │ │ └── with-ignored-dir │ │ │ │ └── package.json │ │ ├── github-mocks.ts │ │ ├── msw-register.ts │ │ ├── msw.ts │ │ └── setupAfterEnv.ts │ ├── cli.ts │ ├── copy-template.ts │ ├── index.ts │ ├── jest.config.js │ ├── loading-indicator.ts │ ├── package.json │ ├── prompt.ts │ ├── prompts-confirm.ts │ ├── prompts-multi-select.ts │ ├── prompts-prompt-base.ts │ ├── prompts-select.ts │ ├── prompts-text.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── utils.ts ├── react-router-architect │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── 554828.jpeg │ │ ├── binaryTypes-test.ts │ │ └── server-test.ts │ ├── binaryTypes.ts │ ├── index.ts │ ├── jest.config.js │ ├── package.json │ ├── server.ts │ ├── sessions │ │ └── arcTableSessionStorage.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── react-router-cloudflare │ ├── CHANGELOG.md │ ├── README.md │ ├── index.ts │ ├── package.json │ ├── sessions │ │ └── workersKVStorage.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── typedoc.json │ └── worker.ts ├── react-router-dev │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── cli-reveal-test.ts │ │ ├── cli-routes-test.ts │ │ ├── cli-test.ts │ │ ├── fixtures │ │ │ └── basic │ │ │ │ ├── .gitignore │ │ │ │ ├── app │ │ │ │ ├── root.tsx │ │ │ │ ├── routes.ts │ │ │ │ └── routes │ │ │ │ │ └── _index.tsx │ │ │ │ ├── package.json │ │ │ │ ├── public │ │ │ │ └── favicon.ico │ │ │ │ └── tsconfig.json │ │ ├── route-config-test.ts │ │ ├── setupAfterEnv.ts │ │ ├── styles-test.ts │ │ └── utils │ │ │ ├── captureError.ts │ │ │ ├── cli.ts │ │ │ ├── eol.ts │ │ │ ├── git.ts │ │ │ └── withApp.ts │ ├── bin.js │ ├── cli │ │ ├── commands.ts │ │ ├── detectPackageManager.ts │ │ ├── index.ts │ │ ├── run.ts │ │ └── useJavascript.ts │ ├── config.ts │ ├── config │ │ ├── config.ts │ │ ├── defaults │ │ │ ├── entry.client.tsx │ │ │ └── entry.server.node.tsx │ │ ├── format.ts │ │ ├── is-react-router-repo.ts │ │ ├── routes.ts │ │ └── serverModes.ts │ ├── invariant.ts │ ├── jest.config.js │ ├── manifest.ts │ ├── module-sync-enabled │ │ ├── false.cjs │ │ ├── index.d.mts │ │ ├── index.mjs │ │ └── true.mjs │ ├── package.json │ ├── routes.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── typedoc.json │ ├── typegen │ │ ├── context.ts │ │ ├── generate.ts │ │ ├── index.ts │ │ └── paths.ts │ ├── vite.ts │ └── vite │ │ ├── babel.ts │ │ ├── build.ts │ │ ├── cloudflare-dev-proxy.ts │ │ ├── cloudflare.ts │ │ ├── combine-urls-test.ts │ │ ├── combine-urls.ts │ │ ├── dev.ts │ │ ├── node-adapter.ts │ │ ├── plugin.ts │ │ ├── profiler.ts │ │ ├── remove-exports-test.ts │ │ ├── remove-exports.ts │ │ ├── resolve-file-url.ts │ │ ├── static │ │ └── refresh-utils.cjs │ │ ├── styles.ts │ │ ├── virtual-module.ts │ │ ├── vite-node.ts │ │ ├── vite.ts │ │ └── with-props.ts ├── react-router-dom │ ├── CHANGELOG.md │ ├── README.md │ ├── index.ts │ ├── package.json │ ├── tsconfig.json │ └── tsup.config.ts ├── react-router-express │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ └── server-test.ts │ ├── index.ts │ ├── jest.config.js │ ├── package.json │ ├── server.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── react-router-fs-routes │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── flatRoutes-test.ts │ │ └── routeManifestToRouteConfig-test.ts │ ├── flatRoutes.ts │ ├── index.ts │ ├── jest.config.js │ ├── manifest.ts │ ├── normalizeSlashes.ts │ ├── package.json │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── react-router-node │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── sessions-test.ts │ │ └── utils.ts │ ├── index.ts │ ├── jest.config.js │ ├── package.json │ ├── server.ts │ ├── sessions │ │ └── fileStorage.ts │ ├── stream.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── react-router-remix-routes-option-adapter │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── defineRoutes-test.ts │ │ └── routeManifestToRouteConfig-test.ts │ ├── defineRoutes.ts │ ├── index.ts │ ├── jest.config.js │ ├── manifest.ts │ ├── normalizeSlashes.ts │ ├── package.json │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── react-router-serve │ ├── CHANGELOG.md │ ├── README.md │ ├── bin.js │ ├── cli.ts │ ├── package.json │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json └── react-router │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ ├── .eslintrc │ ├── Route-test.tsx │ ├── Router-basename-test.tsx │ ├── Router-test.tsx │ ├── Routes-location-test.tsx │ ├── Routes-test.tsx │ ├── __snapshots__ │ │ └── route-matching-test.tsx.snap │ ├── absolute-path-matching-test.tsx │ ├── createRoutesFromChildren-test.tsx │ ├── data-memory-router-test.tsx │ ├── data-router-no-dom-test.tsx │ ├── descendant-routes-params-test.tsx │ ├── descendant-routes-splat-matching-test.tsx │ ├── descendant-routes-warning-test.tsx │ ├── dom │ │ ├── components │ │ │ └── LazyComponent.tsx │ │ ├── concurrent-mode-navigations-test.tsx │ │ ├── data-browser-router-legacy-formdata-test.tsx │ │ ├── data-browser-router-test.tsx │ │ ├── data-static-router-test.tsx │ │ ├── flush-sync-navigations-test.tsx │ │ ├── link-click-test.tsx │ │ ├── link-href-test.tsx │ │ ├── link-push-test.tsx │ │ ├── nav-link-active-test.tsx │ │ ├── navigate-encode-params-test.tsx │ │ ├── partial-hydration-test.tsx │ │ ├── polyfills │ │ │ └── drop-FormData-submitter.ts │ │ ├── scroll-restoration-test.tsx │ │ ├── search-params-test.tsx │ │ ├── special-characters-test.tsx │ │ ├── ssr │ │ │ ├── components-test.tsx │ │ │ └── meta-test.tsx │ │ ├── static-link-test.tsx │ │ ├── static-location-test.tsx │ │ ├── static-navigate-test.tsx │ │ ├── stub-test.tsx │ │ ├── trailing-slashes-test.tsx │ │ ├── use-blocker-test.tsx │ │ ├── use-prompt-test.tsx │ │ └── useLinkClickHandler-test.tsx │ ├── generatePath-test.tsx │ ├── gh-issue-8127-test.tsx │ ├── gh-issue-8165-test.tsx │ ├── greedy-matching-test.tsx │ ├── index-routes-test.tsx │ ├── layout-routes-test.tsx │ ├── matchPath-test.tsx │ ├── matchRoutes-test.tsx │ ├── navigate-test.tsx │ ├── params-decode-test.tsx │ ├── path-matching-test.tsx │ ├── resolvePath-test.tsx │ ├── route-depth-order-matching-test.tsx │ ├── route-matching-test.tsx │ ├── router │ │ ├── TestSequences │ │ │ ├── EncodedReservedCharacters.ts │ │ │ ├── GoBack.ts │ │ │ ├── GoForward.ts │ │ │ ├── InitialLocationDefaultKey.ts │ │ │ ├── InitialLocationHasKey.ts │ │ │ ├── Listen.ts │ │ │ ├── ListenPopOnly.ts │ │ │ ├── PushMissingPathname.ts │ │ │ ├── PushNewLocation.ts │ │ │ ├── PushRelativePathname.ts │ │ │ ├── PushRelativePathnameWarning.ts │ │ │ ├── PushSamePath.ts │ │ │ ├── PushState.ts │ │ │ ├── PushStateInvalid.ts │ │ │ ├── ReplaceNewLocation.ts │ │ │ ├── ReplaceSamePath.ts │ │ │ └── ReplaceState.ts │ │ ├── browser-test.ts │ │ ├── create-path-test.ts │ │ ├── data-strategy-test.ts │ │ ├── fetchers-test.ts │ │ ├── flush-sync-test.ts │ │ ├── hash-base-test.ts │ │ ├── hash-test.ts │ │ ├── interruptions-test.ts │ │ ├── lazy-discovery-test.ts │ │ ├── lazy-test.ts │ │ ├── memory-test.ts │ │ ├── navigation-blocking-test.ts │ │ ├── navigation-test.ts │ │ ├── path-resolution-test.ts │ │ ├── redirects-test.ts │ │ ├── resolveTo-test.tsx │ │ ├── revalidate-test.ts │ │ ├── route-fallback-test.ts │ │ ├── router-memory-test.ts │ │ ├── router-test.ts │ │ ├── scroll-restoration-test.ts │ │ ├── should-revalidate-test.ts │ │ ├── ssr-test.ts │ │ ├── submission-test.ts │ │ ├── utils │ │ │ ├── custom-matchers.ts │ │ │ ├── data-router-setup.ts │ │ │ ├── urlDataStrategy.ts │ │ │ └── utils.ts │ │ └── view-transition-test.ts │ ├── same-component-lifecycle-test.tsx │ ├── server-runtime │ │ ├── cookies-test.ts │ │ ├── data-test.ts │ │ ├── handle-error-test.ts │ │ ├── handler-test.ts │ │ ├── markup-test.ts │ │ ├── responses-test.ts │ │ ├── server-test.ts │ │ ├── sessions-test.ts │ │ └── utils.ts │ ├── setup.ts │ ├── use-revalidator-test.tsx │ ├── useHref-basename-test.tsx │ ├── useHref-test.tsx │ ├── useLocation-test.tsx │ ├── useMatch-test.tsx │ ├── useNavigate-test.tsx │ ├── useOutlet-test.tsx │ ├── useParams-test.tsx │ ├── useResolvedPath-test.tsx │ ├── useRoutes-test.tsx │ └── utils │ │ ├── MemoryNavigate.tsx │ │ ├── getHtml.ts │ │ ├── renderStrict.tsx │ │ ├── tick.ts │ │ └── waitForRedirect.tsx │ ├── dom-export.ts │ ├── index.ts │ ├── jest.config.js │ ├── lib │ ├── components.tsx │ ├── context.ts │ ├── dom-export │ │ ├── dom-router-provider.tsx │ │ └── hydrated-router.tsx │ ├── dom │ │ ├── dom.ts │ │ ├── global.ts │ │ ├── lib.tsx │ │ ├── node-main.js │ │ ├── server.tsx │ │ └── ssr │ │ │ ├── components.tsx │ │ │ ├── data.ts │ │ │ ├── entry.ts │ │ │ ├── errorBoundaries.tsx │ │ │ ├── errors.ts │ │ │ ├── fallback.tsx │ │ │ ├── fog-of-war.ts │ │ │ ├── invariant.ts │ │ │ ├── links.ts │ │ │ ├── markup.ts │ │ │ ├── routeModules.ts │ │ │ ├── routes-test-stub.tsx │ │ │ ├── routes.tsx │ │ │ ├── server.tsx │ │ │ └── single-fetch.tsx │ ├── hooks.tsx │ ├── router │ │ ├── history.ts │ │ ├── links.ts │ │ ├── router.ts │ │ └── utils.ts │ ├── server-runtime │ │ ├── .eslintrc.js │ │ ├── build.ts │ │ ├── cookies.ts │ │ ├── crypto.ts │ │ ├── data.ts │ │ ├── dev.ts │ │ ├── entry.ts │ │ ├── errors.ts │ │ ├── headers.ts │ │ ├── invariant.ts │ │ ├── markup.ts │ │ ├── mode.ts │ │ ├── routeMatching.ts │ │ ├── routes.ts │ │ ├── server.ts │ │ ├── serverHandoff.ts │ │ ├── sessions.ts │ │ ├── sessions │ │ │ ├── cookieStorage.ts │ │ │ └── memoryStorage.ts │ │ ├── single-fetch.ts │ │ ├── typecheck.ts │ │ └── warnings.ts │ └── types │ │ ├── route-data.ts │ │ ├── route-module.ts │ │ └── utils.ts │ ├── node-main-dom-export.js │ ├── node-main.js │ ├── package.json │ ├── tsconfig.dom.json │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json ├── patches ├── @changesets__assemble-release-plan.patch └── @changesets__get-dependents-graph@1.3.6.patch ├── playground ├── framework-express │ ├── .gitignore │ ├── app │ │ ├── root.tsx │ │ ├── routes.ts │ │ └── routes │ │ │ └── _index.tsx │ ├── package.json │ ├── public │ │ └── favicon.ico │ ├── server.js │ ├── tsconfig.json │ └── vite.config.ts ├── framework-spa │ ├── .gitignore │ ├── app │ │ ├── root.tsx │ │ ├── routes.ts │ │ └── routes │ │ │ └── _index.tsx │ ├── package.json │ ├── public │ │ └── favicon.ico │ ├── react-router.config.ts │ ├── tsconfig.json │ └── vite.config.ts └── framework │ ├── .gitignore │ ├── app │ ├── root.tsx │ ├── routes.ts │ └── routes │ │ ├── _index.tsx │ │ └── product.tsx │ ├── package.json │ ├── public │ └── favicon.ico │ ├── tsconfig.json │ └── vite.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── prettier.config.js ├── scripts ├── clean-v6-artifacts.sh ├── constants.js ├── find-release-from-changeset.js ├── playground.js ├── publish.js ├── remove-prerelease-changelogs.mjs ├── utils.js └── version.js ├── static └── base-branch.png ├── tutorials └── address-book │ ├── .gitignore │ ├── README.md │ ├── app │ ├── app.css │ ├── data.ts │ ├── root.tsx │ └── routes.ts │ ├── package.json │ ├── public │ └── favicon.ico │ ├── react-router.config.ts │ ├── tsconfig.json │ └── vite.config.ts └── typedoc.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | # Browsers we support 2 | Chrome >= 73 3 | ChromeAndroid >= 75 4 | Firefox >= 67 5 | Edge >= 17 6 | Safari >= 12.1 7 | iOS >= 11.3 8 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /fixtures/ 2 | node_modules/ 3 | pnpm-lock.yaml 4 | /docs/api 5 | examples/**/dist/ 6 | /playground/ 7 | /playground-local/ 8 | packages/**/dist/ 9 | packages/react-router-dom/server.d.ts 10 | packages/react-router-dom/server.js 11 | packages/react-router-dom/server.mjs 12 | tutorial/dist/ 13 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["react-app"], 3 | "rules": { 4 | "import/first": "off", 5 | "@typescript-eslint/consistent-type-imports": "error" 6 | }, 7 | "overrides": [ 8 | { 9 | "files": ["**/__tests__/**"], 10 | "plugins": ["jest"], 11 | "extends": ["plugin:jest/recommended"] 12 | }, 13 | { 14 | "files": ["integration/**/*.*"], 15 | "rules": { 16 | "react-hooks/rules-of-hooks": "off" 17 | }, 18 | "env": { 19 | "jest/globals": false 20 | } 21 | } 22 | ], 23 | "reportUnusedDisableDirectives": true 24 | } 25 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: react-router 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 💡 Feature Request 4 | url: https://github.com/remix-run/react-router/discussions/new?category=proposals 5 | about: If you've got an idea for a new feature in React Router, please open a new Discussion with the `Proposals` label 6 | - name: 🤔 Usage Question (Github Discussions) 7 | url: https://github.com/remix-run/remix/discussions/new?category=q-a 8 | about: Open a Discussion in GitHub wih the `Q&A` label 9 | - name: 💬 Remix Discord Channel 10 | url: https://rmx.as/discord 11 | about: Interact with other people using React Router and Remix 📀 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_isse.yml: -------------------------------------------------------------------------------- 1 | name: 📚 Documentation Issue 2 | description: Something is wrong with the React Router docs 3 | title: "[Docs]: " 4 | labels: 5 | - docs 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thank you for contributing! 11 | 12 | For documentation updates - we would happily accept PRs, so feel free to update and 13 | open a PR to the `main` branch. Otherwise let us know in this issue what you felt 14 | was missing or incorrect. 15 | 16 | - type: textarea 17 | attributes: 18 | label: Describe what's incorrect/missing in the documentation 19 | description: A concise description of what you expected to see in the docs 20 | validations: 21 | required: true 22 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: daily 7 | -------------------------------------------------------------------------------- /.github/workflows/release-comments.yml: -------------------------------------------------------------------------------- 1 | name: 📝 Comment on Release 2 | 3 | on: 4 | workflow_call: 5 | 6 | jobs: 7 | comment: 8 | name: 📝 Comment on related issues and pull requests 9 | if: github.repository == 'remix-run/react-router' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: ⬇️ Checkout repo 13 | uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: 📝 Comment on related issues and pull requests 18 | uses: remix-run/release-comment-action@v0.4.1 19 | with: 20 | DIRECTORY_TO_CHECK: "./packages" 21 | PACKAGE_NAME: "react-router" 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | 4 | /docs/api/ 5 | /website/build/ 6 | node_modules/ 7 | 8 | /examples/*/yarn.lock 9 | /examples/*/pnpm-lock.yaml 10 | /examples/*/dist 11 | /tutorial/dist 12 | /playground-local/ 13 | /integration/playwright-report 14 | /integration/test-results 15 | 16 | # v5 build files 17 | /packages/*/cjs/ 18 | /packages/*/esm/ 19 | /packages/*/umd/ 20 | 21 | # v6 build files 22 | /build/ 23 | /packages/*/dist/ 24 | /packages/*/LICENSE.md 25 | 26 | # v7 build files 27 | .react-router 28 | 29 | .wireit 30 | .eslintcache 31 | .tmp 32 | tsup.config.bundled_*.mjs 33 | /.env 34 | /NOTES.md 35 | 36 | # v7 reference docs 37 | /public -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-workspace-cycles=true 2 | enable-pre-post-scripts=true 3 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "typescript.enablePromptUseWorkspaceTsdk": true 4 | } 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please see [our guide to contributing](docs/community/contributing.md). 2 | -------------------------------------------------------------------------------- /build.utils.ts: -------------------------------------------------------------------------------- 1 | export function createBanner(packageName: string, version: string) { 2 | return `/** 3 | * ${packageName} v${version} 4 | * 5 | * Copyright (c) Remix Software Inc. 6 | * 7 | * This source code is licensed under the MIT license found in the 8 | * LICENSE.md file in the root directory of this source tree. 9 | * 10 | * @license MIT 11 | */`; 12 | } 13 | -------------------------------------------------------------------------------- /decisions/template.md: -------------------------------------------------------------------------------- 1 | # Title 2 | 3 | Date: YYYY-MM-DD 4 | 5 | Status: proposed | rejected | accepted | deprecated | … | superseded by [0005](0005-example.md) 6 | 7 | ## Context 8 | 9 | ## Decision 10 | 11 | ## Consequences 12 | -------------------------------------------------------------------------------- /docs/community/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Community 3 | order: 6 4 | --- 5 | -------------------------------------------------------------------------------- /docs/explanation/README: -------------------------------------------------------------------------------- 1 | Explanations: 2 | 3 | - Theoretical Knowledge 4 | - Understanding Oriented 5 | - Useful when we're studying 6 | -------------------------------------------------------------------------------- /docs/explanation/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Explanations 3 | order: 5 4 | --- 5 | -------------------------------------------------------------------------------- /docs/explanation/location.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Location Object 3 | hidden: true 4 | --- 5 | 6 | 7 | -------------------------------------------------------------------------------- /docs/explanation/picking-a-router.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Picking a Router 3 | hidden: true 4 | --- 5 | 6 | ## TODO: 7 | -------------------------------------------------------------------------------- /docs/explanation/route-matching.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Route Matching 3 | hidden: true 4 | # want to explain how the matching algorithm works with any potential gotchas 5 | --- 6 | 7 | # Route Matching 8 | -------------------------------------------------------------------------------- /docs/explanation/server-client-execution.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Server vs. Client Code Execution 3 | hidden: true 4 | --- 5 | -------------------------------------------------------------------------------- /docs/how-to/README: -------------------------------------------------------------------------------- 1 | How-To: 2 | 3 | - Practical Steps 4 | - Problem Oriented 5 | - Useful when we're coding 6 | -------------------------------------------------------------------------------- /docs/how-to/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How-Tos 3 | order: 4 4 | --- 5 | -------------------------------------------------------------------------------- /docs/how-to/search-params.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Search Params 3 | hidden: true 4 | --- 5 | -------------------------------------------------------------------------------- /docs/prettier.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('prettier').Options} 3 | */ 4 | module.exports = { 5 | ...require("../prettier.config"), 6 | printWidth: 60, 7 | }; 8 | -------------------------------------------------------------------------------- /docs/start/README: -------------------------------------------------------------------------------- 1 | Get them off the ground and acquainted with basics. Docs here are a mix of: 2 | 3 | How-To: 4 | 5 | - Practical Steps 6 | - Problem Oriented 7 | - Useful when we're coding 8 | 9 | Explanation: 10 | 11 | - Theoretical Knowledge 12 | - Understanding Oriented 13 | - Useful when we're studying 14 | -------------------------------------------------------------------------------- /docs/start/framework/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Framework 3 | order: 1 4 | --- 5 | -------------------------------------------------------------------------------- /docs/start/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting Started 3 | order: 1 4 | --- 5 | -------------------------------------------------------------------------------- /docs/start/library/data-routers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Data Routers 3 | hidden: true 4 | --- 5 | -------------------------------------------------------------------------------- /docs/start/library/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Library 3 | order: 2 4 | --- 5 | -------------------------------------------------------------------------------- /docs/tutorials/README: -------------------------------------------------------------------------------- 1 | Tutorials: 2 | 3 | - Practical Steps 4 | - Learning Oriented 5 | - Useful when we're studying 6 | -------------------------------------------------------------------------------- /docs/tutorials/advanced-data-fetching.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Advanced Data Fetching 3 | hidden: true 4 | --- 5 | 6 | # Advanced Data Fetching 7 | 8 | 9 | This document is a work in progress. There's not much to see here (yet). 10 | 11 | -------------------------------------------------------------------------------- /docs/tutorials/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tutorials 3 | order: 3 4 | --- 5 | -------------------------------------------------------------------------------- /docs/upgrading/README: -------------------------------------------------------------------------------- 1 | How-To: 2 | 3 | - Practical Steps 4 | - Problem Oriented 5 | - Useful when we're coding 6 | -------------------------------------------------------------------------------- /docs/upgrading/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Upgrading 3 | order: 2 4 | --- 5 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Examples 3 | order: 6 4 | --- 5 | 6 | # React Router Examples 7 | 8 | Welcome to the examples for React Router. 9 | 10 | Here you'll find various examples of using React Router to accomplish certain tasks. Each example is a complete application including a build and even a button to preview a live instance of the app so you can play with it. You'll most often be interested in checking out the code in `src/App.tsx` (or `src/App.js`), but we included the entire source code for the app for completeness. 11 | 12 | Also, remember to check out the README! 13 | 14 | Enjoy! 15 | -------------------------------------------------------------------------------- /examples/auth-router-provider/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/auth-router-provider/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/auth-router-provider/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Auth Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/auth-router-provider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auth", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "^18.11.18", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/auth-router-provider/src/auth.ts: -------------------------------------------------------------------------------- 1 | interface AuthProvider { 2 | isAuthenticated: boolean; 3 | username: null | string; 4 | signin(username: string): Promise; 5 | signout(): Promise; 6 | } 7 | 8 | /** 9 | * This represents some generic auth provider API, like Firebase. 10 | */ 11 | export const fakeAuthProvider: AuthProvider = { 12 | isAuthenticated: false, 13 | username: null, 14 | async signin(username: string) { 15 | await new Promise((r) => setTimeout(r, 500)); // fake delay 16 | fakeAuthProvider.isAuthenticated = true; 17 | fakeAuthProvider.username = username; 18 | }, 19 | async signout() { 20 | await new Promise((r) => setTimeout(r, 500)); // fake delay 21 | fakeAuthProvider.isAuthenticated = false; 22 | fakeAuthProvider.username = ""; 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /examples/auth-router-provider/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/auth-router-provider/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | 4 | import "./index.css"; 5 | import App from "./App"; 6 | 7 | ReactDOM.createRoot(document.getElementById("root")!).render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /examples/auth-router-provider/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/auth-router-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/auth/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/auth/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/auth/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Auth Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auth", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "^18.11.18", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/auth/src/auth.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This represents some generic auth provider API, like Firebase. 3 | */ 4 | const fakeAuthProvider = { 5 | isAuthenticated: false, 6 | signin(callback: VoidFunction) { 7 | fakeAuthProvider.isAuthenticated = true; 8 | setTimeout(callback, 100); // fake async 9 | }, 10 | signout(callback: VoidFunction) { 11 | fakeAuthProvider.isAuthenticated = false; 12 | setTimeout(callback, 100); 13 | }, 14 | }; 15 | 16 | export { fakeAuthProvider }; 17 | -------------------------------------------------------------------------------- /examples/auth/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/auth/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")!).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/auth/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/basic-data-router/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/basic-data-router/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/basic-data-router/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Basic (Data Router) 3 | toc: false 4 | order: 1 5 | --- 6 | 7 | # Data Routers 8 | 9 | This example demonstrates a simple usage of a Data Router, using `createBrowserRouter` and ``. 10 | 11 | ## Preview 12 | 13 | Open this example on [StackBlitz](https://stackblitz.com): 14 | 15 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/basic-data-router?file=src/App.tsx) 16 | -------------------------------------------------------------------------------- /examples/basic-data-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Basic Data Router Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/basic-data-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic-data-router", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "18.2.0", 11 | "react-dom": "18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "5.0.2", 16 | "@types/node": "18.11.18", 17 | "@types/react": "18.0.27", 18 | "@types/react-dom": "18.0.10", 19 | "@vitejs/plugin-react": "3.0.1", 20 | "typescript": "4.9.5", 21 | "vite": "4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/basic-data-router/src/app.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | createBrowserRouter, 3 | RouterProvider, 4 | useLoaderData, 5 | } from "react-router-dom"; 6 | 7 | import "./index.css"; 8 | 9 | let router = createBrowserRouter([ 10 | { 11 | path: "/", 12 | loader: () => ({ message: "Hello Data Router!" }), 13 | Component() { 14 | let data = useLoaderData() as { message: string }; 15 | return

{data.message}

; 16 | }, 17 | }, 18 | ]); 19 | 20 | export default function App() { 21 | return Loading...

} />; 22 | } 23 | 24 | if (import.meta.hot) { 25 | import.meta.hot.dispose(() => router.dispose()); 26 | } 27 | -------------------------------------------------------------------------------- /examples/basic-data-router/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/basic-data-router/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import App from "./app"; 4 | 5 | ReactDOM.createRoot(document.getElementById("root")!).render( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /examples/basic-data-router/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/basic-data-router/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/basic/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/basic/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Basics 3 | toc: false 4 | order: 1 5 | --- 6 | 7 | # Basic Example 8 | 9 | This example demonstrates some of the basic features of React Router, including: 10 | 11 | - Layouts and nested ``s 12 | - Index ``s 13 | - Catch-all ``s 14 | - Using `` as a placeholder for child routes 15 | - Using ``s for navigation 16 | 17 | ## Preview 18 | 19 | Open this example on [StackBlitz](https://stackblitz.com): 20 | 21 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/basic?file=src/App.tsx) 22 | -------------------------------------------------------------------------------- /examples/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Basic Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "18.x", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/basic/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/basic/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")!).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/basic/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/basic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/custom-filter-link/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/custom-filter-link/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/custom-filter-link/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Filter Link 3 | toc: false 4 | --- 5 | 6 | # Custom Filter Link Example 7 | 8 | This example demonstrates how to use a query string parameter to mark a link as "active" or not. This is a common technique when implementing a filter in a sidebar where you're browsing products. 9 | 10 | ## Preview 11 | 12 | Open this example on [StackBlitz](https://stackblitz.com): 13 | 14 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/custom-filter-link?file=src/App.tsx) 15 | -------------------------------------------------------------------------------- /examples/custom-filter-link/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Custom Filter Link Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/custom-filter-link/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-filter-link", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "@reach/visually-hidden": "0.18.0", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-router-dom": "^6.15.0" 14 | }, 15 | "devDependencies": { 16 | "@rollup/plugin-replace": "^5.0.2", 17 | "@types/node": "^18.11.18", 18 | "@types/react": "^18.0.27", 19 | "@types/react-dom": "^18.0.10", 20 | "@vitejs/plugin-react": "^3.0.1", 21 | "typescript": "^4.9.5", 22 | "vite": "^4.0.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/custom-filter-link/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/custom-filter-link/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/custom-filter-link/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/custom-filter-link/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/custom-link/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/custom-link/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/custom-link/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Active Link 3 | toc: false 4 | --- 5 | 6 | # Custom Link Example 7 | 8 | This example demonstrates how to make a custom `` component to render something different when the link is "active" using the `useMatch()` and `useResolvedPath()` hooks. 9 | 10 | ## Preview 11 | 12 | Open this example on [StackBlitz](https://stackblitz.com): 13 | 14 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/custom-link?file=src/App.tsx) 15 | -------------------------------------------------------------------------------- /examples/custom-link/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Custom Link Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/custom-link/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-link", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "18.x", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/custom-link/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/custom-link/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/custom-link/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/custom-link/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Query Parsing 3 | toc: false 4 | --- 5 | 6 | # Custom Query Parsing Example 7 | 8 | This example demonstrates how to store a complex data structure in the URL query string using a custom hook. 9 | 10 | It's a good example of how React Router's low-level hooks provide you with all the flexibility you need to create your own custom hooks that fit the needs of your app. 11 | 12 | ## Preview 13 | 14 | Open this example on [StackBlitz](https://stackblitz.com): 15 | 16 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/custom-query-parsing?file=src/App.tsx) 17 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Custom Query Parsing Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-query-parse-serialization", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "jsurl": "0.1.5", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-router-dom": "^6.15.0" 14 | }, 15 | "devDependencies": { 16 | "@rollup/plugin-replace": "^5.0.2", 17 | "@types/node": "18.x", 18 | "@types/react": "^18.0.27", 19 | "@types/react-dom": "^18.0.10", 20 | "@vitejs/plugin-react": "^3.0.1", 21 | "typescript": "^4.9.5", 22 | "vite": "^4.0.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src", "./types"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/custom-query-parsing/types/jsurl.d.ts: -------------------------------------------------------------------------------- 1 | declare module "jsurl" { 2 | type Nullable = T | null | undefined; 3 | export function stringify(input: any): string; 4 | export function parse(input?: Nullable): Nullable; 5 | } 6 | -------------------------------------------------------------------------------- /examples/data-router/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/data-router/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/data-router/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Data Router 3 | toc: false 4 | order: 1 5 | --- 6 | 7 | # Data Routers 8 | 9 | This example demonstrates some of the basic features of Data Router, including: 10 | 11 | - Loader functions 12 | - Action functions 13 | - and
navigations 14 | - submissions 15 | 16 | ## Preview 17 | 18 | Open this example on [StackBlitz](https://stackblitz.com): 19 | 20 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/data-router?file=src/App.tsx) 21 | -------------------------------------------------------------------------------- /examples/data-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Basic Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/data-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "data-router", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "18.2.0", 11 | "react-dom": "18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "5.0.2", 16 | "@types/node": "18.11.18", 17 | "@types/react": "18.0.27", 18 | "@types/react-dom": "18.0.10", 19 | "@vitejs/plugin-react": "3.0.1", 20 | "typescript": "4.9.5", 21 | "vite": "4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/data-router/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/data-router/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import App from "./app"; 4 | 5 | ReactDOM.createRoot(document.getElementById("root")).render( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /examples/data-router/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/data-router/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/error-boundaries/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/error-boundaries/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/error-boundaries/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Error Boundaries 3 | toc: false 4 | order: 1 5 | --- 6 | 7 | # Error Boundaries 8 | 9 | This example demonstrates some of the basic features of React Router's `errorElement` boundaries, including: 10 | 11 | - Handling thrown `loader` errors 12 | - Handling render errors 13 | - Re-throwing errors from an `errorElement` 14 | 15 | ## Preview 16 | 17 | Open this example on [StackBlitz](https://stackblitz.com): 18 | 19 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/error-boundaries?file=src/App.tsx) 20 | -------------------------------------------------------------------------------- /examples/error-boundaries/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Error Boundaries Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/error-boundaries/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "error-boundaries", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "5.0.2", 16 | "@types/node": "18.11.18", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "3.0.1", 20 | "typescript": "4.9.5", 21 | "vite": "4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/error-boundaries/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | max-width: 600px; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | background-color: #eee; 14 | padding: 1px 3px; 15 | } 16 | 17 | li { 18 | padding: 10px 0; 19 | } 20 | -------------------------------------------------------------------------------- /examples/error-boundaries/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | 4 | import App from "./app"; 5 | 6 | ReactDOM.createRoot(document.getElementById("root")).render( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /examples/error-boundaries/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/error-boundaries/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Lazy Loading with RouterProvider 3 | toc: false 4 | --- 5 | 6 | # Lazy Loading Example using `RouterProvider` 7 | 8 | This example demonstrates how to lazily load individual route elements on demand `route.lazy()` and dynamic `import()`. Using this technique, pages that are not required on the home page can be split out into separate bundles, thereby decreasing load time on the initial page and improving performance. 9 | 10 | ## Preview 11 | 12 | Open this example on [StackBlitz](https://stackblitz.com): 13 | 14 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/lazy-loading-router-provider?file=src/App.tsx) 15 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Lazy Loading Example using RouterProvider 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lazy-loading-router-provider", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "18.x", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | 4 | import "./index.css"; 5 | import App from "./App"; 6 | 7 | ReactDOM.createRoot(document.getElementById("root")).render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/src/pages/About.tsx: -------------------------------------------------------------------------------- 1 | import { useLoaderData } from "react-router-dom"; 2 | 3 | export async function loader() { 4 | await new Promise((r) => setTimeout(r, 500)); 5 | return "I came from the About.tsx loader function!"; 6 | } 7 | 8 | export function Component() { 9 | let data = useLoaderData() as string; 10 | 11 | return ( 12 |
13 |

About

14 |

{data}

15 |
16 | ); 17 | } 18 | 19 | Component.displayName = "AboutPage"; 20 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/lazy-loading-router-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/lazy-loading/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/lazy-loading/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/lazy-loading/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Lazy Loading 3 | toc: false 4 | --- 5 | 6 | # Lazy Loading Example 7 | 8 | This example demonstrates how to lazily load both 9 | 10 | - individual route elements 11 | - entire portions of your route hierarchy 12 | 13 | on demand using `React.lazy()` and dynamic `import()`. Using this technique, 14 | pages that are not required on the home page can be split out into separate 15 | bundles, thereby decreasing load time on the initial page and improving 16 | performance. 17 | 18 | ## Preview 19 | 20 | Open this example on [StackBlitz](https://stackblitz.com): 21 | 22 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/lazy-loading?file=src/App.tsx) 23 | -------------------------------------------------------------------------------- /examples/lazy-loading/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Lazy Loading Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/lazy-loading/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lazy-loading", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "18.x", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/lazy-loading/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/lazy-loading/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/lazy-loading/src/pages/About.tsx: -------------------------------------------------------------------------------- 1 | function AboutPage() { 2 | return ( 3 |
4 |

About

5 |
6 | ); 7 | } 8 | 9 | export default AboutPage; 10 | -------------------------------------------------------------------------------- /examples/lazy-loading/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/lazy-loading/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Outlet Modal 3 | toc: false 4 | --- 5 | 6 | # Outlet Modal Example 7 | 8 | ## Preview 9 | 10 | Open this example on [StackBlitz](https://stackblitz.com): 11 | 12 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal-route-with-outlet?file=src/App.tsx) 13 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Modal Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modal-route-with-outlet", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "@reach/dialog": "0.18.0", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-router-dom": "^6.15.0" 14 | }, 15 | "devDependencies": { 16 | "@rollup/plugin-replace": "^5.0.2", 17 | "@types/node": "18.x", 18 | "@types/react": "^18.0.27", 19 | "@types/react-dom": "^18.0.10", 20 | "@vitejs/plugin-react": "^3.0.1", 21 | "typescript": "^4.9.5", 22 | "vite": "^4.0.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/src/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | } 4 | 5 | * { 6 | box-sizing: inherit; 7 | } 8 | 9 | body { 10 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 11 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 12 | sans-serif; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | } 16 | 17 | code { 18 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 19 | monospace; 20 | } 21 | 22 | [data-reach-dialog-content] { 23 | width: 90%; 24 | max-width: 500px; 25 | border-radius: 8px; 26 | } 27 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | 4 | import App from "./App"; 5 | import "./index.css"; 6 | 7 | const root = document.getElementById("root"); 8 | if (!root) throw new Error("Root element not found"); 9 | 10 | ReactDOM.createRoot(root).render( 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/modal-route-with-outlet/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/modal/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/modal/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/modal/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Modal 3 | toc: false 4 | --- 5 | 6 | # Modal Example 7 | 8 | ## Preview 9 | 10 | Open this example on [StackBlitz](https://stackblitz.com): 11 | 12 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal?file=src/App.tsx) 13 | -------------------------------------------------------------------------------- /examples/modal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Modal Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/modal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modal", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "@reach/dialog": "0.18.0", 11 | "react": "^17.0.2", 12 | "react-dom": "^17.0.2", 13 | "react-router-dom": "^6.15.0" 14 | }, 15 | "devDependencies": { 16 | "@rollup/plugin-replace": "^5.0.2", 17 | "@types/node": "18.x", 18 | "@types/react": "^17.0.59", 19 | "@types/react-dom": "^17.0.20", 20 | "@vitejs/plugin-react": "^3.0.1", 21 | "typescript": "^4.9.5", 22 | "vite": "^4.0.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/modal/src/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | } 4 | 5 | * { 6 | box-sizing: inherit; 7 | } 8 | 9 | body { 10 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 11 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 12 | sans-serif; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | } 16 | 17 | code { 18 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 19 | monospace; 20 | } 21 | 22 | [data-reach-dialog-content] { 23 | width: 90%; 24 | max-width: 500px; 25 | border-radius: 8px; 26 | } 27 | -------------------------------------------------------------------------------- /examples/modal/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import App from "./App"; 6 | import "./index.css"; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | 12 | 13 | , 14 | document.getElementById("root") 15 | ); 16 | -------------------------------------------------------------------------------- /examples/modal/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/modal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/multi-app/.gitignore: -------------------------------------------------------------------------------- 1 | public/build 2 | -------------------------------------------------------------------------------- /examples/multi-app/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/multi-app/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Multi App 3 | toc: false 4 | --- 5 | 6 | # Multi App Example 7 | 8 | This example demonstrates how to build a site with multiple React Router apps by mounting each at a URL pathname prefix using the `` prop. This essentially decouples the apps from each other and allows them to be portable and even deployed separately. 9 | 10 | ## Preview 11 | 12 | Open this example on [StackBlitz](https://stackblitz.com): 13 | 14 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/multi-app?file=home/App.jsx) 15 | -------------------------------------------------------------------------------- /examples/multi-app/home/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/multi-app/home/main.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import HomeApp from "./App"; 6 | 7 | ReactDOM.createRoot(document.getElementById("root")).render( 8 | 9 | {/* No basename for this router. This app renders at the root / URL. */} 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/multi-app/home/no-match.jsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | function NoMatch() { 4 | return ( 5 |
6 |

Nothing to see here!

7 |

8 | Go to the home page of the app 9 |

10 |
11 | ); 12 | } 13 | 14 | export { NoMatch }; 15 | -------------------------------------------------------------------------------- /examples/multi-app/inbox/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/multi-app/inbox/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Router - Multi App Example (Inbox App) 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/multi-app/inbox/main.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import InboxApp from "./App"; 6 | 7 | ReactDOM.createRoot(document.getElementById("root")).render( 8 | 9 | {/* "Mount" this app under the /inbox URL pathname. All routes and links 10 | are relative to this name. */} 11 | 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /examples/multi-app/inbox/no-match.jsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | function NoMatch() { 4 | return ( 5 |
6 |

Nothing to see here!

7 |

8 | Go to the home page of the app 9 |

10 |
11 | ); 12 | } 13 | 14 | export { NoMatch }; 15 | -------------------------------------------------------------------------------- /examples/multi-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Router - Multi App Example (Home App) 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/multi-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multi-app", 3 | "private": true, 4 | "scripts": { 5 | "dev": "cross-env NODE_ENV=development node server.js", 6 | "build": "vite build", 7 | "start": "cross-env NODE_ENV=production node server.js", 8 | "debug": "node --inspect-brk server.js" 9 | }, 10 | "dependencies": { 11 | "compression": "^1.7.4", 12 | "cross-env": "^7.0.3", 13 | "express": "^4.18.2", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0", 16 | "react-router-dom": "^6.15.0" 17 | }, 18 | "devDependencies": { 19 | "@rollup/plugin-replace": "^5.0.2", 20 | "@types/react": "^18.0.27", 21 | "@types/react-dom": "^18.0.10", 22 | "@vitejs/plugin-react": "^3.0.1", 23 | "vite": "^4.0.4" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/navigation-blocking/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/navigation-blocking/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/navigation-blocking/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Navigation Blocking 3 | toc: false 4 | order: 1 5 | --- 6 | 7 | # Navigation Blocking 8 | 9 | This example demonstrates using `useBlocker` to prevent navigating away from a page where you might lose user-entered form data. A potentially better UX for this is storing user-entered information in `sessionStorage` and pre-populating the form on return. 10 | 11 | ## Preview 12 | 13 | Open this example on [StackBlitz](https://stackblitz.com): 14 | 15 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/navigation-blocking?file=src/App.tsx) 16 | -------------------------------------------------------------------------------- /examples/navigation-blocking/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Navigation Blocking 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/navigation-blocking/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "navigation-blocking", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "18.2.0", 11 | "react-dom": "18.2.0", 12 | "react-router-dom": "^6.21.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "5.0.2", 16 | "@types/node": "18.11.18", 17 | "@types/react": "18.0.27", 18 | "@types/react-dom": "18.0.10", 19 | "@vitejs/plugin-react": "3.0.1", 20 | "typescript": "4.9.5", 21 | "vite": "4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/navigation-blocking/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import App from "./app"; 4 | 5 | ReactDOM.createRoot(document.getElementById("root")).render( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /examples/navigation-blocking/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/navigation-blocking/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/notes/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/notes/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/notes/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Notes CRUD 3 | toc: false 4 | order: 1 5 | --- 6 | 7 | # Data Routers 8 | 9 | This example demonstrates some of the basic features of Data Router, including: 10 | 11 | - Loader functions 12 | - Action functions 13 | - and navigations 14 | 15 | ## Preview 16 | 17 | Open this example on [StackBlitz](https://stackblitz.com): 18 | 19 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/dev/examples/notes?file=src/App.jsx) 20 | -------------------------------------------------------------------------------- /examples/notes/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Basic Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/notes/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notes", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "localforage": "^1.10.0", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-router-dom": "^6.15.0" 14 | }, 15 | "devDependencies": { 16 | "@rollup/plugin-replace": "5.0.2", 17 | "@types/node": "18.11.18", 18 | "@types/react": "^18.0.27", 19 | "@types/react-dom": "^18.0.10", 20 | "@vitejs/plugin-react": "3.0.1", 21 | "typescript": "4.9.5", 22 | "vite": "4.0.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/notes/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/notes/src/main.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | 4 | import App from "./app"; 5 | 6 | ReactDOM.createRoot(document.getElementById("root")).render( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /examples/notes/src/routes/note.jsx: -------------------------------------------------------------------------------- 1 | import { useLoaderData, Form, redirect } from "react-router-dom"; 2 | import { deleteNote, getNote } from "../notes"; 3 | 4 | export default function Note() { 5 | const note = useLoaderData(); 6 | return ( 7 |
8 |

{note.title}

9 |
{note.content}
10 | 11 | 12 | 13 |
14 | ); 15 | } 16 | 17 | export async function loader({ params }) { 18 | const note = await getNote(params.noteId); 19 | if (!note) throw new Response("", { status: 404 }); 20 | return note; 21 | } 22 | 23 | export async function action({ params }) { 24 | await deleteNote(params.noteId); 25 | return redirect("/new"); 26 | } 27 | -------------------------------------------------------------------------------- /examples/notes/src/routes/notes.jsx: -------------------------------------------------------------------------------- 1 | export default function Notes() { 2 | return
Notes
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/notes/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/notes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src", "../../build/node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/route-objects/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/route-objects/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/route-objects/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Route Objects Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/route-objects/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "18.x", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/route-objects/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/route-objects/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/route-objects/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/route-objects/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": false, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/scroll-restoration/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/scroll-restoration/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/scroll-restoration/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Scroll Restoration 3 | toc: false 4 | order: 1 5 | --- 6 | 7 | # Scroll Restoration 8 | 9 | This example demonstrates the basic usage of the `` component, including: 10 | 11 | - Restoring scroll position via `location.key` 12 | - Restoring scroll position via `location.pathname` 13 | - Preventing scroll resetting via `` 14 | 15 | ## Preview 16 | 17 | Open this example on [StackBlitz](https://stackblitz.com): 18 | 19 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/scroll-restoration?file=src/App.tsx) 20 | -------------------------------------------------------------------------------- /examples/scroll-restoration/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Basic Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/scroll-restoration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scroll-restoration", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "5.0.2", 16 | "@types/node": "18.11.18", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "3.0.1", 20 | "typescript": "4.9.5", 21 | "vite": "4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/scroll-restoration/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/scroll-restoration/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import App from "./app"; 4 | 5 | ReactDOM.createRoot(document.getElementById("root")).render( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /examples/scroll-restoration/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/scroll-restoration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/search-params/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/search-params/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/search-params/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Search Params 3 | toc: false 4 | --- 5 | 6 | # Search Params Example 7 | 8 | This example demonstrates how to read and write the URL query string using the `useSearchParams()` hook. This hook is similar to the `useNavigate()` hook, but just for the [`search` portion of the URL](https://developer.mozilla.org/en-US/docs/Web/API/Location/search). 9 | 10 | In this example, we have a form to search for a user on GitHub and display their user profile. 11 | 12 | ## Preview 13 | 14 | Open this example on [StackBlitz](https://stackblitz.com): 15 | 16 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/search-params?file=src/App.tsx) 17 | -------------------------------------------------------------------------------- /examples/search-params/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Search Params Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/search-params/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "search-params", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-router-dom": "^6.15.0" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "^5.0.2", 16 | "@types/node": "^18.11.18", 17 | "@types/react": "^18.0.27", 18 | "@types/react-dom": "^18.0.10", 19 | "@vitejs/plugin-react": "^3.0.1", 20 | "typescript": "^4.9.5", 21 | "vite": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/search-params/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/search-params/src/main.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import App from "./App"; 6 | import "./index.css"; 7 | 8 | ReactDOM.createRoot(document.getElementById("root")).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /examples/search-params/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/search-params/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/ssr-data-router/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/ssr-data-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Data Router SSR Example 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ssr-data-router/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/ssr-data-router/src/lazy.tsx: -------------------------------------------------------------------------------- 1 | import { useLoaderData } from "react-router-dom"; 2 | 3 | interface LazyLoaderData { 4 | date: string; 5 | } 6 | 7 | export const loader = async (): Promise => { 8 | await new Promise((r) => setTimeout(r, 500)); 9 | return { 10 | date: new Date().toISOString(), 11 | }; 12 | }; 13 | 14 | function LazyPage() { 15 | let data = useLoaderData() as LazyLoaderData; 16 | 17 | return ( 18 | <> 19 |

Lazy Route

20 |

Date from loader: {data.date}

21 | 22 | ); 23 | } 24 | 25 | export const element = ; 26 | -------------------------------------------------------------------------------- /examples/ssr-data-router/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/ssr-data-router/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "types": ["vite/client"], 18 | "importsNotUsedAsValues": "error" 19 | }, 20 | "include": ["./src"] 21 | } 22 | -------------------------------------------------------------------------------- /examples/ssr/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/ssr/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - SSR Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/ssr/src/entry.client.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import "./index.css"; 6 | import App from "./App"; 7 | 8 | ReactDOM.hydrateRoot( 9 | document.getElementById("app"), 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /examples/ssr/src/entry.server.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import ReactDOMServer from "react-dom/server"; 3 | import { StaticRouter } from "react-router-dom/server"; 4 | 5 | import App from "./App"; 6 | 7 | export function render(url: string) { 8 | return ReactDOMServer.renderToString( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /examples/ssr/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 3 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 4 | sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | -------------------------------------------------------------------------------- /examples/ssr/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/ssr/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "types": ["vite/client"], 18 | "importsNotUsedAsValues": "error" 19 | }, 20 | "include": ["./src"] 21 | } 22 | -------------------------------------------------------------------------------- /examples/view-transitions/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /examples/view-transitions/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm run dev" 4 | } 5 | -------------------------------------------------------------------------------- /examples/view-transitions/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: View Transitions 3 | toc: false 4 | --- 5 | 6 | # startViewTransition (Experimental) 7 | 8 | This example demonstrates a simple usage of a Data Router with `document.startViewTransition` enabled. 9 | 10 | ## Preview 11 | 12 | Open this example on [StackBlitz](https://stackblitz.com): 13 | 14 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router/tree/main/examples/view-transitions?file=src/App.tsx) 15 | -------------------------------------------------------------------------------- /examples/view-transitions/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Router - Basic Data Router Example 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/view-transitions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic-data-router", 3 | "private": true, 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview" 8 | }, 9 | "dependencies": { 10 | "react": "18.2.0", 11 | "react-dom": "18.2.0", 12 | "react-router-dom": "6.17.0-pre.2" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-replace": "5.0.2", 16 | "@types/node": "18.11.18", 17 | "@types/react": "18.0.27", 18 | "@types/react-dom": "18.0.10", 19 | "@vitejs/plugin-react": "3.0.1", 20 | "typescript": "4.9.5", 21 | "vite": "4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/view-transitions/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/view-transitions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "importsNotUsedAsValues": "error" 18 | }, 19 | "include": ["./src"] 20 | } 21 | -------------------------------------------------------------------------------- /integration/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # integration-tests 2 | 3 | ## 0.0.0 4 | 5 | ### Minor Changes 6 | 7 | - Unstable Vite support for Node-based Remix apps ([#7590](https://github.com/remix-run/remix/pull/7590)) 8 | 9 | - `remix build` 👉 `vite build && vite build --ssr` 10 | - `remix dev` 👉 `vite dev` 11 | 12 | Other runtimes (e.g. Deno, Cloudflare) not yet supported. 13 | Custom server (e.g. Express) not yet supported. 14 | 15 | See "Future > Vite" in the Remix Docs for details. 16 | -------------------------------------------------------------------------------- /integration/assets/toupload.txt: -------------------------------------------------------------------------------- 1 | Hello, World! -------------------------------------------------------------------------------- /integration/helpers/cleanup.mjs: -------------------------------------------------------------------------------- 1 | import * as path from "node:path"; 2 | import spawn from "cross-spawn"; 3 | 4 | if (process.env.CI) { 5 | console.log("Skipping cleanup in CI"); 6 | process.exit(); 7 | } 8 | 9 | const pathsToRemove = [path.resolve(process.cwd(), ".tmp/integration")]; 10 | 11 | for (let pathToRemove of pathsToRemove) { 12 | console.log(`Removing ${path.relative(process.cwd(), pathToRemove)}`); 13 | let childProcess; 14 | if (process.platform === "win32") { 15 | childProcess = spawn("rmdir", ["/s", "/q", pathToRemove], { 16 | stdio: "inherit", 17 | }); 18 | } else { 19 | childProcess = spawn("rm", ["-rf", pathToRemove], { 20 | stdio: "inherit", 21 | }); 22 | } 23 | childProcess.on("error", (err) => { 24 | console.error(err); 25 | process.exit(1); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | .env 6 | .react-router 7 | -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/app/routes.ts: -------------------------------------------------------------------------------- 1 | import { type RouteConfig } from "@react-router/dev/routes"; 2 | import { flatRoutes } from "@react-router/fs-routes"; 3 | 4 | export default flatRoutes() satisfies RouteConfig; 5 | -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/app/routes/_index.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from "react-router"; 2 | 3 | export const meta: MetaFunction = () => { 4 | return [ 5 | { title: "New React Router App" }, 6 | { name: "description", content: "Welcome to React Router!" }, 7 | ]; 8 | }; 9 | 10 | export default function Index() { 11 | return ( 12 |
13 |

Welcome to React Router

14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/integration/helpers/vite-5-template/public/favicon.ico -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "env.d.ts", 4 | "**/*.ts", 5 | "**/*.tsx", 6 | ".react-router/types/**/*.d.ts" 7 | ], 8 | "compilerOptions": { 9 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 10 | "verbatimModuleSyntax": true, 11 | "esModuleInterop": true, 12 | "jsx": "react-jsx", 13 | "module": "ESNext", 14 | "moduleResolution": "Bundler", 15 | "resolveJsonModule": true, 16 | "target": "ES2022", 17 | "strict": true, 18 | "allowJs": true, 19 | "skipLibCheck": true, 20 | "baseUrl": ".", 21 | "paths": { 22 | "~/*": ["./app/*"] 23 | }, 24 | "noEmit": true, 25 | "rootDirs": [".", ".react-router/types/"] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /integration/helpers/vite-5-template/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { defineConfig } from "vite"; 3 | import tsconfigPaths from "vite-tsconfig-paths"; 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | // @ts-expect-error `dev` depends on Vite 6, Plugin type is mismatched. 8 | reactRouter(), 9 | tsconfigPaths(), 10 | ], 11 | }); 12 | -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | .env 6 | .react-router 7 | -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/app/routes.ts: -------------------------------------------------------------------------------- 1 | import { type RouteConfig } from "@react-router/dev/routes"; 2 | import { flatRoutes } from "@react-router/fs-routes"; 3 | 4 | export default flatRoutes() satisfies RouteConfig; 5 | -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/app/routes/_index.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from "react-router"; 2 | 3 | export const meta: MetaFunction = () => { 4 | return [ 5 | { title: "New React Router App" }, 6 | { name: "description", content: "Welcome to React Router!" }, 7 | ]; 8 | }; 9 | 10 | export default function Index() { 11 | return ( 12 |
13 |

Welcome to React Router

14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/integration/helpers/vite-6-template/public/favicon.ico -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "env.d.ts", 4 | "**/*.ts", 5 | "**/*.tsx", 6 | ".react-router/types/**/*.d.ts" 7 | ], 8 | "compilerOptions": { 9 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 10 | "verbatimModuleSyntax": true, 11 | "esModuleInterop": true, 12 | "jsx": "react-jsx", 13 | "module": "ESNext", 14 | "moduleResolution": "Bundler", 15 | "resolveJsonModule": true, 16 | "target": "ES2022", 17 | "strict": true, 18 | "allowJs": true, 19 | "skipLibCheck": true, 20 | "baseUrl": ".", 21 | "paths": { 22 | "~/*": ["./app/*"] 23 | }, 24 | "noEmit": true, 25 | "rootDirs": [".", ".react-router/types/"] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /integration/helpers/vite-6-template/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { defineConfig } from "vite"; 3 | import tsconfigPaths from "vite-tsconfig-paths"; 4 | 5 | export default defineConfig({ 6 | plugins: [reactRouter(), tsconfigPaths()], 7 | }); 8 | -------------------------------------------------------------------------------- /integration/helpers/vite-cloudflare-template/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /build 4 | .env 5 | -------------------------------------------------------------------------------- /integration/helpers/vite-cloudflare-template/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export function Layout({ children }: { children: React.ReactNode }) { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {children} 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default function App() { 22 | return ; 23 | } 24 | -------------------------------------------------------------------------------- /integration/helpers/vite-cloudflare-template/app/routes.ts: -------------------------------------------------------------------------------- 1 | import { type RouteConfig } from "@react-router/dev/routes"; 2 | import { flatRoutes } from "@react-router/fs-routes"; 3 | 4 | export default flatRoutes() satisfies RouteConfig; 5 | -------------------------------------------------------------------------------- /integration/helpers/vite-cloudflare-template/app/routes/_index.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from "react-router"; 2 | 3 | export const meta: MetaFunction = () => { 4 | return [ 5 | { title: "New React Router App" }, 6 | { name: "description", content: "React Router + Cloudflare" }, 7 | ]; 8 | }; 9 | 10 | export default function Index() { 11 | return ( 12 |
13 |

Welcome to React Router + Cloudflare

14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /integration/helpers/vite-cloudflare-template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/integration/helpers/vite-cloudflare-template/public/favicon.ico -------------------------------------------------------------------------------- /integration/helpers/vite-cloudflare-template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["env.d.ts", "**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 5 | "types": ["vite/client"], 6 | "verbatimModuleSyntax": true, 7 | "esModuleInterop": true, 8 | "jsx": "react-jsx", 9 | "module": "ESNext", 10 | "moduleResolution": "Bundler", 11 | "resolveJsonModule": true, 12 | "target": "ES2022", 13 | "strict": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "baseUrl": ".", 17 | "noEmit": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /integration/helpers/vite-cloudflare-template/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare"; 3 | import { defineConfig } from "vite"; 4 | 5 | export default defineConfig({ 6 | plugins: [cloudflareDevProxy(), reactRouter()], 7 | }); 8 | -------------------------------------------------------------------------------- /integration/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["helpers/*-template"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "ES2022", 8 | "skipLibCheck": true, 9 | 10 | "moduleResolution": "Bundler", 11 | "allowSyntheticDefaultImports": true, 12 | "strict": true, 13 | "resolveJsonModule": true, 14 | 15 | "noEmit": true, 16 | 17 | "rootDir": "." 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /jest/transform.js: -------------------------------------------------------------------------------- 1 | let { default: babelJest } = require("babel-jest"); 2 | 3 | /** 4 | * Replace `import.meta` with `undefined` 5 | * 6 | * Needed to support server-side CJS in Jest 7 | * when `import.meta.hot` is used for HMR. 8 | */ 9 | let metaPlugin = ({ types: t }) => ({ 10 | visitor: { 11 | MetaProperty: (path) => { 12 | path.replaceWith(t.identifier("undefined")); 13 | }, 14 | }, 15 | }); 16 | 17 | module.exports = babelJest.createTransformer({ 18 | babelrc: false, 19 | presets: [ 20 | ["@babel/preset-env", { loose: true }], 21 | "@babel/preset-react", 22 | "@babel/preset-typescript", 23 | ], 24 | plugins: ["babel-plugin-dev-expression", metaPlugin], 25 | }); 26 | -------------------------------------------------------------------------------- /packages/create-react-router/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # `create-react-router` 2 | 3 | ## 7.1.5 4 | 5 | ## 7.1.4 6 | 7 | _No changes_ 8 | 9 | ## 7.1.3 10 | 11 | _No changes_ 12 | 13 | ## 7.1.2 14 | 15 | _No changes_ 16 | 17 | ## 7.1.1 18 | 19 | _No changes_ 20 | 21 | ## 7.1.0 22 | 23 | ### Patch Changes 24 | 25 | - Fix missing `fs-extra` dependency ([#12556](https://github.com/remix-run/react-router/pull/12556)) 26 | 27 | ## 7.0.2 28 | 29 | _No changes_ 30 | 31 | ## 7.0.1 32 | 33 | _No changes_ 34 | 35 | ## 7.0.0 36 | 37 | Initial release. 38 | -------------------------------------------------------------------------------- /packages/create-react-router/README.md: -------------------------------------------------------------------------------- 1 | Create a new React Router app. 2 | 3 | ```sh 4 | npm create react-router 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/basic/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | .env 6 | .react-router 7 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/basic/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export function Layout({ children }: { children: React.ReactNode }) { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {children} 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default function App() { 22 | return ; 23 | } 24 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/basic/app/routes.ts: -------------------------------------------------------------------------------- 1 | import type { RouteConfig } from "@react-router/dev/routes"; 2 | import { index } from "@react-router/dev/routes"; 3 | 4 | export default [index("routes/home.tsx")] satisfies RouteConfig; 5 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/basic/app/routes/home.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from "react-router"; 2 | 3 | export const meta: MetaFunction = () => { 4 | return [ 5 | { title: "New React Router App" }, 6 | { name: "description", content: "Welcome to React Router!" }, 7 | ]; 8 | }; 9 | 10 | export default function Index() { 11 | return

Welcome to React Router

; 12 | } 13 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "sideEffects": false, 4 | "type": "module", 5 | "scripts": { 6 | "dev": "react-router dev", 7 | "build": "react-router build", 8 | "start": "react-router-serve ./build/server/index.js" 9 | }, 10 | "dependencies": { 11 | "react-router": "*", 12 | "react-router-dom": "*", 13 | "@react-router/node": "*", 14 | "not-react-router": "*" 15 | }, 16 | "devDependencies": {}, 17 | "engines": { 18 | "node": ">=20.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/basic/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/packages/create-react-router/__tests__/fixtures/basic/public/favicon.ico -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/basic/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { defineConfig } from "vite"; 3 | 4 | export default defineConfig({ 5 | plugins: [reactRouter()], 6 | }); 7 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/blank/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/nested-dir-repo.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/packages/create-react-router/__tests__/fixtures/nested-dir-repo.tar.gz -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/tar.js: -------------------------------------------------------------------------------- 1 | const tar = require("tar-fs"); 2 | const fs = require("node:fs"); 3 | const path = require("node:path"); 4 | 5 | let files = fs.readdirSync(__dirname); 6 | let dirs = files.filter((file) => 7 | fs.statSync(path.join(__dirname, file)).isDirectory() 8 | ); 9 | 10 | for (let dir of dirs) { 11 | let fullPath = path.join(__dirname, dir); 12 | console.log(`Creating archive for ${fullPath}`); 13 | tar 14 | .pack(fullPath, { 15 | map(header) { 16 | header.name = dir + "/" + header.name; 17 | return header; 18 | }, 19 | }) 20 | .pipe(fs.createWriteStream(path.join(__dirname, `${dir}.tar.gz`))); 21 | } 22 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/template.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/packages/create-react-router/__tests__/fixtures/template.tar.gz -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/template.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/packages/create-react-router/__tests__/fixtures/template.tgz -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/templates-repo.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/packages/create-react-router/__tests__/fixtures/templates-repo.tar.gz -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/fixtures/with-ignored-dir/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/msw-register.ts: -------------------------------------------------------------------------------- 1 | import process from "node:process"; 2 | 3 | import { server } from "./msw"; 4 | 5 | server.listen({ onUnhandledRequest: "error" }); 6 | 7 | process.on("exit", () => { 8 | server.close(); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/create-react-router/__tests__/setupAfterEnv.ts: -------------------------------------------------------------------------------- 1 | export let jestTimeout = process.platform === "win32" ? 20_000 : 10_000; 2 | 3 | jest.setTimeout(jestTimeout); 4 | -------------------------------------------------------------------------------- /packages/create-react-router/cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import process from "node:process"; 3 | 4 | import { createReactRouter } from "./index"; 5 | 6 | process.on("SIGINT", () => process.exit(0)); 7 | process.on("SIGTERM", () => process.exit(0)); 8 | 9 | let argv = process.argv.slice(2).filter((arg) => arg !== "--"); 10 | 11 | createReactRouter(argv).then( 12 | () => process.exit(0), 13 | () => process.exit(1) 14 | ); 15 | -------------------------------------------------------------------------------- /packages/create-react-router/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | displayName: "create-react-router", 5 | setupFilesAfterEnv: ["/__tests__/setupAfterEnv.ts"], 6 | setupFiles: [], 7 | }; 8 | -------------------------------------------------------------------------------- /packages/create-react-router/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts", "./package.json"], 3 | "exclude": ["dist", "**/node_modules/**", "__tests__"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "ES2022", 8 | "skipLibCheck": true, 9 | "moduleResolution": "Bundler", 10 | "allowSyntheticDefaultImports": true, 11 | "strict": true, 12 | "resolveJsonModule": true, 13 | "declaration": true, 14 | "noEmit": true, 15 | "rootDir": ".", 16 | "outDir": "dist" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/create-react-router/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["cli.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-architect/README.md: -------------------------------------------------------------------------------- 1 | [Architect](https://arc.codes) server request handler for React Router. 2 | 3 | ```bash 4 | npm install @react-router/architect 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/react-router-architect/__tests__/554828.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/packages/react-router-architect/__tests__/554828.jpeg -------------------------------------------------------------------------------- /packages/react-router-architect/__tests__/binaryTypes-test.ts: -------------------------------------------------------------------------------- 1 | import { isBinaryType } from "../binaryTypes"; 2 | 3 | describe("architect isBinaryType", () => { 4 | it("should detect binary contentType correctly", () => { 5 | expect(isBinaryType(undefined)).toBe(false); 6 | expect(isBinaryType(null)).toBe(false); 7 | expect(isBinaryType("text/html; charset=utf-8")).toBe(false); 8 | expect(isBinaryType("application/octet-stream")).toBe(true); 9 | expect(isBinaryType("application/octet-stream; charset=test")).toBe(true); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/react-router-architect/index.ts: -------------------------------------------------------------------------------- 1 | export { createArcTableSessionStorage } from "./sessions/arcTableSessionStorage"; 2 | 3 | export type { GetLoadContextFunction, RequestHandler } from "./server"; 4 | export { createRequestHandler } from "./server"; 5 | -------------------------------------------------------------------------------- /packages/react-router-architect/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | displayName: "architect", 5 | }; 6 | -------------------------------------------------------------------------------- /packages/react-router-architect/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | 8 | "moduleResolution": "Bundler", 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "declaration": true, 12 | "emitDeclarationOnly": true, 13 | "rootDir": ".", 14 | "outDir": "./dist", 15 | 16 | // Avoid naming conflicts between history and react-router-dom relying on 17 | // lib.dom.d.ts Window and this being a WebWorker env. 18 | "skipLibCheck": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/react-router-architect/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["index.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs", "esm"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-architect/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./index.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router-cloudflare/README.md: -------------------------------------------------------------------------------- 1 | Cloudflare platform abstractions for React Router 2 | 3 | ```bash 4 | npm install @react-router/cloudflare @cloudflare/workers-types 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/react-router-cloudflare/index.ts: -------------------------------------------------------------------------------- 1 | export { createWorkersKVSessionStorage } from "./sessions/workersKVStorage"; 2 | 3 | export type { 4 | createPagesFunctionHandlerParams, 5 | GetLoadContextFunction, 6 | RequestHandler, 7 | } from "./worker"; 8 | export { createPagesFunctionHandler, createRequestHandler } from "./worker"; 9 | -------------------------------------------------------------------------------- /packages/react-router-cloudflare/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "__tests__", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["ES2022"], 6 | "target": "ES2022", 7 | "types": ["@cloudflare/workers-types"], 8 | 9 | "moduleResolution": "Bundler", 10 | "allowSyntheticDefaultImports": true, 11 | "strict": true, 12 | "declaration": true, 13 | "emitDeclarationOnly": true, 14 | "rootDir": ".", 15 | "outDir": "./dist", 16 | 17 | // Avoid naming conflicts between history and react-router-dom relying on 18 | // lib.dom.d.ts Window and this being a WebWorker env. 19 | "skipLibCheck": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/react-router-cloudflare/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["index.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs", "esm"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-cloudflare/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./index.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router-dev/.gitignore: -------------------------------------------------------------------------------- 1 | server-build.js 2 | server-build.d.ts 3 | -------------------------------------------------------------------------------- /packages/react-router-dev/README.md: -------------------------------------------------------------------------------- 1 | Dev tools and CLI for React Router that enables framework features through bundler integration like server rendering, code splitting, HMR, etc. 2 | 3 | ```sh 4 | npm install @react-router/dev 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/fixtures/basic/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /build 4 | .env 5 | 6 | .react-router/ 7 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/fixtures/basic/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/fixtures/basic/app/routes.ts: -------------------------------------------------------------------------------- 1 | // Note that since this is used in a unit test context, we don't have access to 2 | // the `dev` build yet, so we can't import from `@react-router/dev/routes`. 3 | const routes = [{ file: "routes/_index.tsx", index: true }]; 4 | 5 | export default routes; 6 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/fixtures/basic/app/routes/_index.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from "react-router"; 2 | 3 | export const meta: MetaFunction = () => { 4 | return [ 5 | { title: "New React Router App" }, 6 | { name: "description", content: "Welcome to React Router!" }, 7 | ]; 8 | }; 9 | 10 | export default function Index() { 11 | return ( 12 |
13 |

Welcome to React Router

14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/fixtures/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "sideEffects": false, 4 | "type": "module", 5 | "scripts": { 6 | "build": "react-router build", 7 | "dev": "react-router dev", 8 | "start": "react-router-serve build/index.js", 9 | "typecheck": "tsc" 10 | }, 11 | "dependencies": { 12 | "react-router": "*", 13 | "@react-router/node": "*", 14 | "@react-router/serve": "*", 15 | "isbot": "^5.1.11", 16 | "react": "^18.2.0", 17 | "react-dom": "^18.2.0" 18 | }, 19 | "devDependencies": { 20 | "@react-router/dev": "*", 21 | "@types/react": "^18.2.20", 22 | "@types/react-dom": "^18.2.7", 23 | "eslint": "^8.38.0", 24 | "typescript": "^5.1.6" 25 | }, 26 | "engines": { 27 | "node": ">=20.0.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/fixtures/basic/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/packages/react-router-dev/__tests__/fixtures/basic/public/favicon.ico -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/fixtures/basic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 5 | "types": ["@react-router/node", "vite/client"], 6 | "verbatimModuleSyntax": true, 7 | "esModuleInterop": true, 8 | "jsx": "react-jsx", 9 | "moduleResolution": "Bundler", 10 | "resolveJsonModule": true, 11 | "target": "ES2022", 12 | "strict": true, 13 | "allowJs": true, 14 | "baseUrl": ".", 15 | "paths": { 16 | "~/*": ["./app/*"] 17 | }, 18 | 19 | // Remix takes care of building everything in `remix build`. 20 | "noEmit": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/setupAfterEnv.ts: -------------------------------------------------------------------------------- 1 | export let jestTimeout = process.platform === "win32" ? 20_000 : 10_000; 2 | 3 | jest.setTimeout(jestTimeout); 4 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/utils/captureError.ts: -------------------------------------------------------------------------------- 1 | class NoErrorThrownError extends Error {} 2 | 3 | export default async function captureError( 4 | erroring: Promise | (() => Promise) 5 | ) { 6 | try { 7 | let promise = typeof erroring === "function" ? erroring() : erroring; 8 | await promise; 9 | throw new NoErrorThrownError(); 10 | } catch (error: unknown) { 11 | if (error instanceof NoErrorThrownError) throw error; 12 | return error; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/utils/eol.ts: -------------------------------------------------------------------------------- 1 | export const normalize = (text: string, normalized = "\n") => 2 | text.replace(/\r?\n/g, normalized); 3 | -------------------------------------------------------------------------------- /packages/react-router-dev/__tests__/utils/git.ts: -------------------------------------------------------------------------------- 1 | import execa from "execa"; 2 | 3 | export const initialCommit = async (projectDir: string) => { 4 | let run = (cmd: string, args: string[]) => 5 | execa(cmd, args, { cwd: projectDir }); 6 | let commands = [ 7 | ["init"], 8 | 9 | ["config", "user.name", '"github-actions[bot]"'], 10 | ["config", "user.email", '"github-actions[bot]@users.noreply.github.com"'], 11 | 12 | ["add", "."], 13 | ["commit", "--message", '"initial commit"'], 14 | ]; 15 | for (let command of commands) { 16 | await run("git", command); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /packages/react-router-dev/bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | let arg = require("arg"); 3 | 4 | // Minimal replication of our actual parsing in `run.ts`. If not already set, 5 | // default `NODE_ENV` so React loads the proper version in it's CJS entry script. 6 | // We have to do this before importing `run.ts` since that is what imports 7 | // `react` (indirectly via `react-router`) 8 | let args = arg({}, { argv: process.argv.slice(2), stopAtPositional: true }); 9 | if (args._[0] === "dev") { 10 | process.env.NODE_ENV = process.env.NODE_ENV ?? "development"; 11 | } else { 12 | process.env.NODE_ENV = process.env.NODE_ENV ?? "production"; 13 | } 14 | 15 | require("./dist/cli/index"); 16 | -------------------------------------------------------------------------------- /packages/react-router-dev/cli/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { run } from "./run"; 3 | 4 | run().then( 5 | () => { 6 | process.exit(0); 7 | }, 8 | (error: unknown) => { 9 | if (error) console.error(error); 10 | process.exit(1); 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /packages/react-router-dev/config.ts: -------------------------------------------------------------------------------- 1 | export type { 2 | ReactRouterConfig as Config, 3 | BuildManifest, 4 | Preset, 5 | ServerBundlesFunction, 6 | } from "./config/config"; 7 | -------------------------------------------------------------------------------- /packages/react-router-dev/config/defaults/entry.client.tsx: -------------------------------------------------------------------------------- 1 | import { startTransition, StrictMode } from "react"; 2 | import { hydrateRoot } from "react-dom/client"; 3 | import { HydratedRouter } from "react-router/dom"; 4 | 5 | startTransition(() => { 6 | hydrateRoot( 7 | document, 8 | 9 | 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/react-router-dev/config/is-react-router-repo.ts: -------------------------------------------------------------------------------- 1 | import path from "pathe"; 2 | 3 | export function isReactRouterRepo() { 4 | // We use '@react-router/node' for this check since it's a 5 | // dependency of this package and guaranteed to be in node_modules 6 | let serverRuntimePath = path.dirname( 7 | require.resolve("@react-router/node/package.json") 8 | ); 9 | let serverRuntimeParentDir = path.basename( 10 | path.resolve(serverRuntimePath, "..") 11 | ); 12 | return serverRuntimeParentDir === "packages"; 13 | } 14 | -------------------------------------------------------------------------------- /packages/react-router-dev/config/serverModes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The mode to use when running the server. 3 | */ 4 | export enum ServerMode { 5 | Development = "development", 6 | Production = "production", 7 | Test = "test", 8 | } 9 | 10 | export function isValidServerMode(mode: string): mode is ServerMode { 11 | return ( 12 | mode === ServerMode.Development || 13 | mode === ServerMode.Production || 14 | mode === ServerMode.Test 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/react-router-dev/invariant.ts: -------------------------------------------------------------------------------- 1 | export default function invariant( 2 | value: boolean, 3 | message?: string 4 | ): asserts value; 5 | 6 | export default function invariant( 7 | value: T | null | undefined, 8 | message?: string 9 | ): asserts value is T; 10 | 11 | export default function invariant(value: any, message?: string) { 12 | if (value === false || value === null || typeof value === "undefined") { 13 | console.error( 14 | "The following error is a bug in React Router; please open an issue! https://github.com/remix-run/react-router/issues/new/choose" 15 | ); 16 | throw new Error(message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/react-router-dev/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | displayName: "dev", 5 | setupFilesAfterEnv: ["/__tests__/setupAfterEnv.ts"], 6 | setupFiles: [], 7 | }; 8 | -------------------------------------------------------------------------------- /packages/react-router-dev/manifest.ts: -------------------------------------------------------------------------------- 1 | export type Manifest = { 2 | version: string; 3 | url?: string; 4 | entry: { 5 | module: string; 6 | imports: string[]; 7 | }; 8 | routes: { 9 | [routeId: string]: { 10 | id: string; 11 | parentId?: string; 12 | path?: string; 13 | index?: boolean; 14 | caseSensitive?: boolean; 15 | module: string; 16 | imports?: string[]; 17 | hasAction: boolean; 18 | hasLoader: boolean; 19 | hasClientAction: boolean; 20 | hasClientLoader: boolean; 21 | hasErrorBoundary: boolean; 22 | }; 23 | }; 24 | hmr?: { 25 | timestamp?: number; 26 | runtime: string; 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /packages/react-router-dev/module-sync-enabled/false.cjs: -------------------------------------------------------------------------------- 1 | exports.default = false; 2 | -------------------------------------------------------------------------------- /packages/react-router-dev/module-sync-enabled/index.d.mts: -------------------------------------------------------------------------------- 1 | declare const moduleSyncEnabled: boolean; 2 | export { moduleSyncEnabled }; 3 | -------------------------------------------------------------------------------- /packages/react-router-dev/module-sync-enabled/index.mjs: -------------------------------------------------------------------------------- 1 | import { createRequire } from "node:module"; 2 | const require = createRequire(import.meta.url); 3 | const moduleSyncEnabled = require("#module-sync-enabled").default; 4 | export { moduleSyncEnabled }; 5 | -------------------------------------------------------------------------------- /packages/react-router-dev/module-sync-enabled/true.mjs: -------------------------------------------------------------------------------- 1 | const moduleSyncEnabled = true; 2 | export default moduleSyncEnabled; 3 | -------------------------------------------------------------------------------- /packages/react-router-dev/routes.ts: -------------------------------------------------------------------------------- 1 | export type { RouteConfig, RouteConfigEntry } from "./config/routes"; 2 | 3 | export { 4 | route, 5 | index, 6 | layout, 7 | prefix, 8 | relative, 9 | getAppDirectory, 10 | } from "./config/routes"; 11 | -------------------------------------------------------------------------------- /packages/react-router-dev/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts", "package.json"], 3 | "exclude": ["dist", "__tests__", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "ES2022", 8 | "moduleResolution": "Bundler", 9 | 10 | "strict": true, 11 | "jsx": "react", 12 | 13 | "skipLibCheck": true, 14 | 15 | "outDir": "dist", 16 | "rootDir": ".", 17 | "noEmit": true, 18 | "resolveJsonModule": true, 19 | "allowSyntheticDefaultImports": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/react-router-dev/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": [ 3 | "./index.ts", 4 | "./config.ts", 5 | "./routes.ts", 6 | "./vite.ts", 7 | "./vite/cloudflare.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-router-dev/typegen/context.ts: -------------------------------------------------------------------------------- 1 | import type { ConfigLoader, ResolvedReactRouterConfig } from "../config/config"; 2 | 3 | export type Context = { 4 | rootDirectory: string; 5 | configLoader: ConfigLoader; 6 | config: ResolvedReactRouterConfig; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/react-router-dev/typegen/paths.ts: -------------------------------------------------------------------------------- 1 | import * as Path from "pathe"; 2 | import * as Pathe from "pathe/utils"; 3 | 4 | import type { RouteManifestEntry } from "../config/routes"; 5 | import type { Context } from "./context"; 6 | 7 | export function getTypesDir(ctx: Context) { 8 | return Path.join(ctx.rootDirectory, ".react-router/types"); 9 | } 10 | 11 | export function getTypesPath(ctx: Context, route: RouteManifestEntry) { 12 | return Path.join( 13 | getTypesDir(ctx), 14 | Path.relative(ctx.rootDirectory, ctx.config.appDirectory), 15 | Path.dirname(route.file), 16 | "+types/" + Pathe.filename(route.file) + ".ts" 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/react-router-dev/vite.ts: -------------------------------------------------------------------------------- 1 | export { reactRouterVitePlugin as reactRouter } from "./vite/plugin"; 2 | -------------------------------------------------------------------------------- /packages/react-router-dev/vite/babel.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/consistent-type-imports */ 2 | import type { NodePath } from "@babel/traverse"; 3 | import type { types as Babel } from "@babel/core"; 4 | import { parse, type ParseResult } from "@babel/parser"; 5 | import * as t from "@babel/types"; 6 | 7 | // These `require`s were needed to support building within vite-ecosystem-ci, 8 | // otherwise we get errors that `traverse` and `generate` are not functions. 9 | const traverse = require("@babel/traverse") 10 | .default as typeof import("@babel/traverse").default; 11 | const generate = require("@babel/generator") 12 | .default as typeof import("@babel/generator").default; 13 | 14 | export { traverse, generate, parse, t }; 15 | export type { Babel, NodePath, ParseResult }; 16 | -------------------------------------------------------------------------------- /packages/react-router-dev/vite/cloudflare.ts: -------------------------------------------------------------------------------- 1 | export { cloudflareDevProxyVitePlugin as cloudflareDevProxy } from "./cloudflare-dev-proxy"; 2 | -------------------------------------------------------------------------------- /packages/react-router-dev/vite/combine-urls.ts: -------------------------------------------------------------------------------- 1 | // Borrowed from axios: https://github.com/axios/axios/blob/0e4f9fa29077ebee4499facea6be1492b42e8a26/lib/helpers/combineURLs.js#L11-L15 2 | export function combineURLs(baseURL: string, relativeURL: string) { 3 | return relativeURL 4 | ? baseURL.replace(/\/+$/, "") + "/" + relativeURL.replace(/^\/+/, "") 5 | : baseURL; 6 | } 7 | -------------------------------------------------------------------------------- /packages/react-router-dev/vite/resolve-file-url.ts: -------------------------------------------------------------------------------- 1 | import * as path from "node:path"; 2 | 3 | import { getVite } from "./vite"; 4 | 5 | export const resolveFileUrl = ( 6 | { rootDirectory }: { rootDirectory: string }, 7 | filePath: string 8 | ) => { 9 | let vite = getVite(); 10 | let relativePath = path.relative(rootDirectory, filePath); 11 | let isWithinRoot = 12 | !relativePath.startsWith("..") && !path.isAbsolute(relativePath); 13 | 14 | if (!isWithinRoot) { 15 | // Vite will prevent serving files outside of the workspace 16 | // unless user explictly opts in with `server.fs.allow` 17 | // https://vitejs.dev/config/server-options.html#server-fs-allow 18 | return path.posix.join("/@fs", vite.normalizePath(filePath)); 19 | } 20 | 21 | return "/" + vite.normalizePath(relativePath); 22 | }; 23 | -------------------------------------------------------------------------------- /packages/react-router-dev/vite/virtual-module.ts: -------------------------------------------------------------------------------- 1 | export function create(name: string) { 2 | let id = `virtual:react-router/${name}`; 3 | return { 4 | id, 5 | resolvedId: `\0${id}`, 6 | url: `/@id/__x00__${id}`, 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /packages/react-router-dom/README.md: -------------------------------------------------------------------------------- 1 | This package simply re-exports everything from `react-router` to smooth the upgrade path for v6 applications. Once upgraded you can change all of your imports and remove it from your dependencies: 2 | 3 | ```diff 4 | -import { Routes } from "react-router-dom" 5 | +import { Routes } from "react-router" 6 | ``` 7 | -------------------------------------------------------------------------------- /packages/react-router-dom/index.ts: -------------------------------------------------------------------------------- 1 | import type { RouterProviderProps } from "react-router/dom"; 2 | import { HydratedRouter, RouterProvider } from "react-router/dom"; 3 | 4 | // TODO: Confirm if this causes tree-shaking issues and if so, convert to named exports 5 | export type * from "react-router"; 6 | export * from "react-router"; 7 | 8 | export type { RouterProviderProps }; 9 | export { HydratedRouter, RouterProvider }; 10 | -------------------------------------------------------------------------------- /packages/react-router-dom/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["index.ts"], 3 | "compilerOptions": { 4 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 5 | "target": "ES2020", 6 | "module": "Node16", 7 | "moduleResolution": "Node16", 8 | 9 | "strict": true, 10 | "jsx": "react", 11 | 12 | "declaration": true, 13 | "emitDeclarationOnly": true, 14 | 15 | "skipLibCheck": true, 16 | 17 | "outDir": "dist", 18 | "rootDir": "." 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/react-router-dom/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["index.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs", "esm"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-express/README.md: -------------------------------------------------------------------------------- 1 | [Express](https://expressjs.com) server request handler for React Router. 2 | 3 | ```sh 4 | npm install @react-router/express 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/react-router-express/index.ts: -------------------------------------------------------------------------------- 1 | export type { GetLoadContextFunction, RequestHandler } from "./server"; 2 | export { createRequestHandler } from "./server"; 3 | -------------------------------------------------------------------------------- /packages/react-router-express/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | displayName: "express", 5 | }; 6 | -------------------------------------------------------------------------------- /packages/react-router-express/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "__tests__", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "ES2022", 8 | "skipLibCheck": true, 9 | 10 | "moduleResolution": "Bundler", 11 | "allowSyntheticDefaultImports": true, 12 | "strict": true, 13 | "jsx": "react", 14 | "declaration": true, 15 | "emitDeclarationOnly": true, 16 | "rootDir": ".", 17 | "outDir": "./dist" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-router-express/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["index.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs", "esm"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-express/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./index.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router-fs-routes/README.md: -------------------------------------------------------------------------------- 1 | File system routing conventions for React Router 2 | 3 | ```sh 4 | npm install @react-router/fs-routes 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/react-router-fs-routes/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | displayName: "fs-routes", 5 | setupFiles: [], 6 | }; 7 | -------------------------------------------------------------------------------- /packages/react-router-fs-routes/normalizeSlashes.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | 3 | export function normalizeSlashes(file: string) { 4 | return file.split(path.win32.sep).join("/"); 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-router-fs-routes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "__tests__", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "ES2022", 8 | "skipLibCheck": true, 9 | 10 | "moduleResolution": "Bundler", 11 | "allowSyntheticDefaultImports": true, 12 | "strict": true, 13 | "jsx": "react", 14 | "declaration": true, 15 | "emitDeclarationOnly": true, 16 | "rootDir": ".", 17 | "outDir": "./dist" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-router-fs-routes/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["index.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-fs-routes/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./index.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router-node/.gitignore: -------------------------------------------------------------------------------- 1 | # TODO: Remove in v2 2 | globals.d.ts -------------------------------------------------------------------------------- /packages/react-router-node/README.md: -------------------------------------------------------------------------------- 1 | Node.js platform abstractions for React Router 2 | 3 | ```sh 4 | npm install @react-router/node 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/react-router-node/__tests__/utils.ts: -------------------------------------------------------------------------------- 1 | import prettier from "prettier"; 2 | 3 | export function prettyHtml(source: string): string { 4 | return prettier.format(source, { parser: "html" }); 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-router-node/index.ts: -------------------------------------------------------------------------------- 1 | export { type RequestListenerOptions, createRequestListener } from "./server"; 2 | 3 | export { createFileSessionStorage } from "./sessions/fileStorage"; 4 | 5 | export { 6 | createReadableStreamFromReadable, 7 | readableStreamToString, 8 | writeAsyncIterableToWritable, 9 | writeReadableStreamToWritable, 10 | } from "./stream"; 11 | -------------------------------------------------------------------------------- /packages/react-router-node/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | displayName: "node", 5 | }; 6 | -------------------------------------------------------------------------------- /packages/react-router-node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "__tests__", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "Node16", 8 | "moduleResolution": "Node16", 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "jsx": "react", 12 | "declaration": true, 13 | "emitDeclarationOnly": true, 14 | "rootDir": ".", 15 | "outDir": "./dist", 16 | "noEmit": true, 17 | "resolveJsonModule": true, 18 | 19 | // Avoid naming conflicts between lib.dom.d.ts and globals.ts 20 | "skipLibCheck": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-router-node/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["index.ts", "install.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs", "esm"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-node/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./index.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router-remix-routes-option-adapter/README.md: -------------------------------------------------------------------------------- 1 | # @react-router/remix-routes-option-adapter 2 | 3 | Adapter for [Remix's](https://remix.run) `routes` config option, for use within `routes.ts`. 4 | 5 | ```sh 6 | npm install @react-router/remix-routes-option-adapter 7 | ``` 8 | -------------------------------------------------------------------------------- /packages/react-router-remix-routes-option-adapter/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | displayName: "remix-routes-option-adapter", 5 | setupFiles: [], 6 | }; 7 | -------------------------------------------------------------------------------- /packages/react-router-remix-routes-option-adapter/normalizeSlashes.ts: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | 3 | export function normalizeSlashes(file: string) { 4 | return file.split(path.win32.sep).join("/"); 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-router-remix-routes-option-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "__tests__", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "ES2022", 8 | "skipLibCheck": true, 9 | 10 | "moduleResolution": "Bundler", 11 | "allowSyntheticDefaultImports": true, 12 | "strict": true, 13 | "jsx": "react", 14 | "declaration": true, 15 | "emitDeclarationOnly": true, 16 | "rootDir": ".", 17 | "outDir": "./dist" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-router-remix-routes-option-adapter/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["index.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-remix-routes-option-adapter/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./index.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router-serve/README.md: -------------------------------------------------------------------------------- 1 | Node.js application server for React Router 2 | 3 | ```sh 4 | npm install @react-router/serve 5 | ``` 6 | -------------------------------------------------------------------------------- /packages/react-router-serve/bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // If not already set, default `NODE_ENV=production` so React loads the proper 4 | // version in it's CJS entry script 5 | process.env.NODE_ENV = process.env.NODE_ENV ?? "production"; 6 | 7 | require("./dist/cli"); 8 | -------------------------------------------------------------------------------- /packages/react-router-serve/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 6 | "target": "ES2022", 7 | "module": "ES2022", 8 | "skipLibCheck": true, 9 | 10 | "moduleResolution": "Bundler", 11 | "allowSyntheticDefaultImports": true, 12 | "strict": true, 13 | "jsx": "react", 14 | "declaration": true, 15 | "emitDeclarationOnly": true, 16 | "rootDir": ".", 17 | "outDir": "./dist" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-router-serve/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | // @ts-ignore - out of scope 4 | import { createBanner } from "../../build.utils.js"; 5 | 6 | import pkg from "./package.json"; 7 | 8 | const entry = ["cli.ts"]; 9 | 10 | export default defineConfig([ 11 | { 12 | clean: true, 13 | entry, 14 | format: ["cjs"], 15 | outDir: "dist", 16 | dts: true, 17 | banner: { 18 | js: createBanner(pkg.name, pkg.version), 19 | }, 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /packages/react-router-serve/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./cli.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router/.eslintrc.js: -------------------------------------------------------------------------------- 1 | let restrictedGlobalsError = `Node globals are not allowed in this package.`; 2 | 3 | module.exports = { 4 | env: { 5 | browser: true, 6 | commonjs: true, 7 | }, 8 | rules: { 9 | strict: 0, 10 | "no-restricted-syntax": ["error", "LogicalExpression[operator='??']"], 11 | "no-restricted-globals": [ 12 | "error", 13 | { name: "__dirname", message: restrictedGlobalsError }, 14 | { name: "__filename", message: restrictedGlobalsError }, 15 | { name: "Buffer", message: restrictedGlobalsError }, 16 | ], 17 | "import/no-nodejs-modules": "error", 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/react-router/README.md: -------------------------------------------------------------------------------- 1 | `react-router` is the primary package in the React Router project. 2 | 3 | ## Installation 4 | 5 | ```sh 6 | npm i react-router 7 | ``` 8 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | }, 5 | "rules": { 6 | "no-console": 0, 7 | "no-restricted-globals": "off", 8 | "import/no-nodejs-modules": "off" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/dom/components/LazyComponent.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | export default function LazyComponent() { 4 | return

Lazy

; 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/dom/polyfills/drop-FormData-submitter.ts: -------------------------------------------------------------------------------- 1 | // Drop support for the submitter parameter, as in a legacy browser. This needs 2 | // to be a standalone module due to how jest requires things (i.e. we can't 3 | // just do this inline in data-browser-router-legacy-formdata-test.tsx) 4 | window.FormData = class FormData extends window["FormData"] { 5 | constructor(form?: HTMLFormElement) { 6 | super(form, undefined); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/EncodedReservedCharacters.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function EncodeReservedCharacters(history: History) { 4 | let pathname; 5 | 6 | // encoded string 7 | pathname = "/view/%23abc"; 8 | history.replace(pathname); 9 | expect(history.location).toMatchObject({ 10 | pathname: "/view/%23abc", 11 | }); 12 | 13 | // encoded object 14 | pathname = "/view/%23abc"; 15 | history.replace({ pathname }); 16 | expect(history.location).toMatchObject({ 17 | pathname: "/view/%23abc", 18 | }); 19 | 20 | // unencoded string 21 | pathname = "/view/#abc"; 22 | history.replace(pathname); 23 | expect(history.location).toMatchObject({ 24 | pathname: "/view/", 25 | hash: "#abc", 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/InitialLocationDefaultKey.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function InitialLocationDefaultKey(history: History) { 4 | expect(history.location.key).toBe("default"); 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/InitialLocationHasKey.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function InitialLocationHasKey(history: History) { 4 | expect(history.location.key).toBeTruthy(); 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/Listen.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function Listen(history: History) { 4 | let spy = jest.fn(); 5 | let unlisten = history.listen(spy); 6 | 7 | expect(spy).not.toHaveBeenCalled(); 8 | 9 | unlisten(); 10 | } 11 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/ListenPopOnly.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function ListenPopOnly(history: History) { 4 | let spy = jest.fn(); 5 | let unlisten = history.listen(spy); 6 | 7 | history.push("/2"); 8 | expect(history.location.pathname).toBe("/2"); 9 | history.replace("/3"); 10 | expect(history.location.pathname).toBe("/3"); 11 | 12 | expect(spy).not.toHaveBeenCalled(); 13 | unlisten(); 14 | } 15 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/PushMissingPathname.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function PushMissingPathname(history: History) { 4 | expect(history.location).toMatchObject({ 5 | pathname: "/", 6 | }); 7 | 8 | history.push("/home?the=query#the-hash"); 9 | expect(history.action).toBe("PUSH"); 10 | expect(history.location).toMatchObject({ 11 | pathname: "/home", 12 | search: "?the=query", 13 | hash: "#the-hash", 14 | }); 15 | 16 | history.push("?another=query#another-hash"); 17 | expect(history.action).toBe("PUSH"); 18 | expect(history.location).toMatchObject({ 19 | pathname: "/home", 20 | search: "?another=query", 21 | hash: "#another-hash", 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/PushNewLocation.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function PushNewLocation(history: History) { 4 | expect(history.location).toMatchObject({ 5 | pathname: "/", 6 | }); 7 | 8 | history.push("/home?the=query#the-hash"); 9 | expect(history.action).toBe("PUSH"); 10 | expect(history.location).toMatchObject({ 11 | pathname: "/home", 12 | search: "?the=query", 13 | hash: "#the-hash", 14 | state: null, 15 | key: expect.any(String), 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/PushRelativePathname.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function PushRelativePathname(history: History) { 4 | expect(history.location).toMatchObject({ 5 | pathname: "/", 6 | }); 7 | 8 | history.push("/the/path?the=query#the-hash"); 9 | expect(history.action).toBe("PUSH"); 10 | expect(history.location).toMatchObject({ 11 | pathname: "/the/path", 12 | search: "?the=query", 13 | hash: "#the-hash", 14 | }); 15 | 16 | history.push("../other/path?another=query#another-hash"); 17 | expect(history.action).toBe("PUSH"); 18 | expect(history.location).toMatchObject({ 19 | pathname: "/other/path", 20 | search: "?another=query", 21 | hash: "#another-hash", 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/PushState.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function PushState(history: History) { 4 | expect(history.location).toMatchObject({ 5 | pathname: "/", 6 | }); 7 | 8 | history.push("/home?the=query#the-hash", { the: "state" }); 9 | expect(history.action).toBe("PUSH"); 10 | expect(history.location).toMatchObject({ 11 | pathname: "/home", 12 | search: "?the=query", 13 | hash: "#the-hash", 14 | state: { the: "state" }, 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/PushStateInvalid.ts: -------------------------------------------------------------------------------- 1 | import type { DOMWindow } from "jsdom"; 2 | import type { History } from "../../../lib/router/history"; 3 | 4 | export default function PushState(history: History, window: DOMWindow) { 5 | let err = new DOMException("ERROR", "DataCloneError"); 6 | jest.spyOn(window.history, "pushState").mockImplementation(() => { 7 | throw err; 8 | }); 9 | 10 | expect(history.location).toMatchObject({ 11 | pathname: "/", 12 | }); 13 | 14 | expect(() => 15 | history.push("/home?the=query#the-hash", { invalid: () => {} }) 16 | ).toThrow(err); 17 | 18 | expect(history.location.pathname).toBe("/"); 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/ReplaceNewLocation.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function ReplaceNewLocation(history: History) { 4 | expect(history.location).toMatchObject({ 5 | pathname: "/", 6 | }); 7 | 8 | history.replace("/home?the=query#the-hash"); 9 | expect(history.action).toBe("REPLACE"); 10 | expect(history.location).toMatchObject({ 11 | pathname: "/home", 12 | search: "?the=query", 13 | hash: "#the-hash", 14 | state: null, 15 | key: expect.any(String), 16 | }); 17 | 18 | history.replace("/"); 19 | expect(history.action).toBe("REPLACE"); 20 | expect(history.location).toMatchObject({ 21 | pathname: "/", 22 | search: "", 23 | state: null, 24 | key: expect.any(String), 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/ReplaceSamePath.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function ReplaceSamePath(history: History) { 4 | expect(history.location).toMatchObject({ 5 | pathname: "/", 6 | }); 7 | 8 | history.replace("/home"); 9 | expect(history.action).toBe("REPLACE"); 10 | expect(history.location).toMatchObject({ 11 | pathname: "/home", 12 | }); 13 | 14 | let prevLocation = history.location; 15 | 16 | history.replace("/home"); 17 | expect(history.action).toBe("REPLACE"); 18 | expect(history.location).toMatchObject({ 19 | pathname: "/home", 20 | }); 21 | 22 | expect(history.location).not.toBe(prevLocation); 23 | } 24 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/TestSequences/ReplaceState.ts: -------------------------------------------------------------------------------- 1 | import type { History } from "../../../lib/router/history"; 2 | 3 | export default function ReplaceState(history: History) { 4 | expect(history.location).toMatchObject({ 5 | pathname: "/", 6 | }); 7 | 8 | history.replace("/home?the=query#the-hash", { the: "state" }); 9 | expect(history.action).toBe("REPLACE"); 10 | expect(history.location).toMatchObject({ 11 | pathname: "/home", 12 | search: "?the=query", 13 | hash: "#the-hash", 14 | state: { the: "state" }, 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/resolveTo-test.tsx: -------------------------------------------------------------------------------- 1 | import { resolveTo } from "../../lib/router/utils"; 2 | 3 | describe("resolveTo", () => { 4 | it('resolve path without mutating the "to" argument', () => { 5 | const toArg = { 6 | pathname: "../../create", 7 | }; 8 | 9 | const routePathnames = ["/", "/user", "/user/1", "/user/1/edit"]; 10 | const locationPathname = "/user/1/edit/"; 11 | 12 | let resolvedPath = resolveTo(toArg, routePathnames, locationPathname); 13 | expect(resolvedPath).toEqual({ 14 | pathname: "/user/create", 15 | search: "", 16 | hash: "", 17 | }); 18 | 19 | resolvedPath = resolveTo(toArg, routePathnames, locationPathname); 20 | expect(resolvedPath).toEqual({ 21 | pathname: "/user/create", 22 | search: "", 23 | hash: "", 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/router/utils/custom-matchers.ts: -------------------------------------------------------------------------------- 1 | interface CustomMatchers { 2 | URL(url: string); 3 | trackedPromise(data?: any, error?: any, aborted?: boolean): R; 4 | deferredData( 5 | done: boolean, 6 | status?: number, 7 | headers?: Record 8 | ): R; 9 | } 10 | 11 | declare global { 12 | namespace jest { 13 | interface Expect extends CustomMatchers {} 14 | interface Matchers extends CustomMatchers {} 15 | interface InverseAsymmetricMatchers extends CustomMatchers {} 16 | } 17 | } 18 | 19 | // Custom matcher for asserting against URLs 20 | export function urlMatch(received, url) { 21 | return { 22 | message: () => `expected URL ${received.toString()} to equal URL ${url}`, 23 | pass: received instanceof URL && received.toString() === url, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/utils/getHtml.ts: -------------------------------------------------------------------------------- 1 | import { prettyDOM } from "@testing-library/react"; 2 | 3 | export default function getHtml(container: HTMLElement) { 4 | return prettyDOM(container, undefined, { 5 | highlight: false, 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/utils/renderStrict.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom"; 3 | 4 | let StrictMode: React.FC = function (props) { 5 | return props.children || (null as any); 6 | }; 7 | 8 | if (React.StrictMode) { 9 | StrictMode = React.StrictMode; 10 | } 11 | 12 | function renderStrict( 13 | element: 14 | | React.FunctionComponentElement 15 | | React.FunctionComponentElement[], 16 | node: ReactDOM.Container 17 | ): void { 18 | ReactDOM.render({element}, node); 19 | } 20 | 21 | export default renderStrict; 22 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/utils/tick.ts: -------------------------------------------------------------------------------- 1 | export default async function tick() { 2 | await new Promise((r) => setTimeout(r, 0)); 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-router/__tests__/utils/waitForRedirect.tsx: -------------------------------------------------------------------------------- 1 | export default function waitForRedirect(fn: (...args: any[]) => void) { 2 | // TODO: Hook into so we can know when 3 | // the redirect actually happens instead of guessing. 4 | setTimeout(fn, 100); 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-router/dom-export.ts: -------------------------------------------------------------------------------- 1 | export type { RouterProviderProps } from "./lib/dom-export/dom-router-provider"; 2 | export { RouterProvider } from "./lib/dom-export/dom-router-provider"; 3 | export { HydratedRouter } from "./lib/dom-export/hydrated-router"; 4 | -------------------------------------------------------------------------------- /packages/react-router/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | ...require("../../jest/jest.config.shared"), 4 | setupFiles: ["/__tests__/setup.ts"], 5 | setupFilesAfterEnv: ["@testing-library/jest-dom"], 6 | testEnvironment: "jsdom", 7 | }; 8 | -------------------------------------------------------------------------------- /packages/react-router/lib/dom-export/dom-router-provider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom"; 3 | 4 | import type { RouterProviderProps as BaseRouterProviderProps } from "react-router"; 5 | import { RouterProvider as BaseRouterProvider } from "react-router"; 6 | 7 | export type RouterProviderProps = Omit; 8 | 9 | export function RouterProvider(props: Omit) { 10 | return ; 11 | } 12 | -------------------------------------------------------------------------------- /packages/react-router/lib/dom/node-main.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | if (process.env.NODE_ENV === "production") { 4 | module.exports = require("./umd/react-router-dom.production.min.js"); 5 | } else { 6 | module.exports = require("./umd/react-router-dom.development.js"); 7 | } 8 | -------------------------------------------------------------------------------- /packages/react-router/lib/dom/ssr/invariant.ts: -------------------------------------------------------------------------------- 1 | export default function invariant( 2 | value: boolean, 3 | message?: string 4 | ): asserts value; 5 | export default function invariant( 6 | value: T | null | undefined, 7 | message?: string 8 | ): asserts value is T; 9 | export default function invariant(value: any, message?: string) { 10 | if (value === false || value === null || typeof value === "undefined") { 11 | throw new Error(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | "no-restricted-syntax": "off", 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/dev.ts: -------------------------------------------------------------------------------- 1 | import type { ServerBuild } from "./build"; 2 | 3 | type DevServerHooks = { 4 | getCriticalCss?: ( 5 | build: ServerBuild, 6 | pathname: string 7 | ) => Promise; 8 | processRequestError?: (error: unknown) => void; 9 | }; 10 | 11 | const globalDevServerHooksKey = "__reactRouterDevServerHooks"; 12 | 13 | export function setDevServerHooks(devServerHooks: DevServerHooks) { 14 | // @ts-expect-error 15 | globalThis[globalDevServerHooksKey] = devServerHooks; 16 | } 17 | 18 | export function getDevServerHooks(): DevServerHooks | undefined { 19 | // @ts-expect-error 20 | return globalThis[globalDevServerHooksKey]; 21 | } 22 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/entry.ts: -------------------------------------------------------------------------------- 1 | import type { ServerRouteManifest } from "./routes"; 2 | import type { RouteModules, EntryRouteModule } from "./routeModules"; 3 | 4 | export function createEntryRouteModules( 5 | manifest: ServerRouteManifest 6 | ): RouteModules { 7 | return Object.keys(manifest).reduce((memo, routeId) => { 8 | let route = manifest[routeId]; 9 | if (route) { 10 | memo[routeId] = route.module; 11 | } 12 | return memo; 13 | }, {} as RouteModules); 14 | } 15 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/invariant.ts: -------------------------------------------------------------------------------- 1 | export default function invariant( 2 | value: boolean, 3 | message?: string 4 | ): asserts value; 5 | export default function invariant( 6 | value: T | null | undefined, 7 | message?: string 8 | ): asserts value is T; 9 | export default function invariant(value: any, message?: string) { 10 | if (value === false || value === null || typeof value === "undefined") { 11 | console.error( 12 | "The following error is a bug in React Router; please open an issue! https://github.com/remix-run/react-router/issues/new/choose" 13 | ); 14 | throw new Error(message); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/markup.ts: -------------------------------------------------------------------------------- 1 | // This escapeHtml utility is based on https://github.com/zertosh/htmlescape 2 | // License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE 3 | 4 | // We've chosen to inline the utility here to reduce the number of npm dependencies we have, 5 | // slightly decrease the code size compared the original package and make it esm compatible. 6 | 7 | const ESCAPE_LOOKUP: { [match: string]: string } = { 8 | "&": "\\u0026", 9 | ">": "\\u003e", 10 | "<": "\\u003c", 11 | "\u2028": "\\u2028", 12 | "\u2029": "\\u2029", 13 | }; 14 | 15 | const ESCAPE_REGEX = /[&><\u2028\u2029]/g; 16 | 17 | export function escapeHtml(html: string) { 18 | return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/mode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The mode to use when running the server. 3 | */ 4 | export enum ServerMode { 5 | Development = "development", 6 | Production = "production", 7 | Test = "test", 8 | } 9 | 10 | export function isServerMode(value: any): value is ServerMode { 11 | return ( 12 | value === ServerMode.Development || 13 | value === ServerMode.Production || 14 | value === ServerMode.Test 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/routeMatching.ts: -------------------------------------------------------------------------------- 1 | import type { Params, AgnosticRouteObject } from "../router/utils"; 2 | import { matchRoutes } from "../router/utils"; 3 | import type { ServerRoute } from "./routes"; 4 | 5 | export interface RouteMatch { 6 | params: Params; 7 | pathname: string; 8 | route: Route; 9 | } 10 | 11 | export function matchServerRoutes( 12 | routes: ServerRoute[], 13 | pathname: string, 14 | basename?: string 15 | ): RouteMatch[] | null { 16 | let matches = matchRoutes( 17 | routes as unknown as AgnosticRouteObject[], 18 | pathname, 19 | basename 20 | ); 21 | if (!matches) return null; 22 | 23 | return matches.map((match) => ({ 24 | params: match.params, 25 | pathname: match.pathname, 26 | route: match.route as unknown as ServerRoute, 27 | })); 28 | } 29 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/typecheck.ts: -------------------------------------------------------------------------------- 1 | // typecheck that expression is assignable to type 2 | export function expectType(_expression: T) {} 3 | 4 | // prettier-ignore 5 | // adapted from https://github.com/type-challenges/type-challenges/blob/main/utils/index.d.ts 6 | export type Equal = 7 | (() => T extends X ? 1 : 2) extends 8 | (() => T extends Y ? 1 : 2) ? true : false 9 | 10 | // adapted from https://github.com/type-challenges/type-challenges/blob/main/utils/index.d.ts 11 | export type Expect = T; 12 | 13 | // looser, lazy equality check for recursive types 14 | // prettier-ignore 15 | export type MutualExtends = [A] extends [B] ? [B] extends [A] ? true : false : false 16 | -------------------------------------------------------------------------------- /packages/react-router/lib/server-runtime/warnings.ts: -------------------------------------------------------------------------------- 1 | const alreadyWarned: { [message: string]: boolean } = {}; 2 | 3 | export function warnOnce(condition: boolean, message: string): void { 4 | if (!condition && !alreadyWarned[message]) { 5 | alreadyWarned[message] = true; 6 | console.warn(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/react-router/lib/types/utils.ts: -------------------------------------------------------------------------------- 1 | export type Expect = T; 2 | 3 | // prettier-ignore 4 | export type Equal = 5 | (() => T extends X ? 1 : 2) extends 6 | (() => T extends Y ? 1 : 2) ? true : false 7 | 8 | export type IsAny = 0 extends 1 & T ? true : false; 9 | 10 | export type Func = (...args: any[]) => unknown; 11 | 12 | export type Pretty = { [K in keyof T]: T[K] } & {}; 13 | -------------------------------------------------------------------------------- /packages/react-router/node-main-dom-export.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | if (process.env.NODE_ENV === "production") { 4 | module.exports = require("./umd/react-router-dom.production.min.js"); 5 | } else { 6 | module.exports = require("./umd/react-router-dom.development.js"); 7 | } 8 | -------------------------------------------------------------------------------- /packages/react-router/node-main.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | if (process.env.NODE_ENV === "production") { 4 | module.exports = require("./umd/react-router.production.min.js"); 5 | } else { 6 | module.exports = require("./umd/react-router.development.js"); 7 | } 8 | -------------------------------------------------------------------------------- /packages/react-router/tsconfig.dom.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["./dom-export.tsx"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/react-router/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts"], 3 | "exclude": ["dist", "__tests__", "node_modules"], 4 | "compilerOptions": { 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "target": "ES2020", 7 | "module": "Node16", 8 | "moduleResolution": "Node16", 9 | 10 | "strict": true, 11 | "jsx": "react", 12 | 13 | "declaration": true, 14 | "emitDeclarationOnly": true, 15 | 16 | "skipLibCheck": true, 17 | 18 | "outDir": "dist", 19 | "rootDir": ".", 20 | "noEmit": true, 21 | "resolveJsonModule": true, 22 | "paths": { 23 | "react-router": ["./index.ts"] 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/react-router/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./index.ts"], 3 | "categoryOrder": [ 4 | "Components", 5 | "Hooks", 6 | "Data Routers", 7 | "Component Routers", 8 | "Utils", 9 | "Types", 10 | "*" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /playground/framework-express/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /build 4 | .env 5 | 6 | .react-router/ 7 | -------------------------------------------------------------------------------- /playground/framework-express/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export function Layout({ children }: { children: React.ReactNode }) { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {children} 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default function App() { 22 | return ; 23 | } 24 | -------------------------------------------------------------------------------- /playground/framework-express/app/routes.ts: -------------------------------------------------------------------------------- 1 | import { type RouteConfig, index } from "@react-router/dev/routes"; 2 | 3 | export default [index("routes/_index.tsx")] satisfies RouteConfig; 4 | -------------------------------------------------------------------------------- /playground/framework-express/app/routes/_index.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from "react-router"; 2 | 3 | export const meta: MetaFunction = () => { 4 | return [ 5 | { title: "New React Router App" }, 6 | { name: "description", content: "Welcome to React Router!" }, 7 | ]; 8 | }; 9 | 10 | export default function Index() { 11 | return ( 12 |
13 |

Welcome to React Router

14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /playground/framework-express/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/playground/framework-express/public/favicon.ico -------------------------------------------------------------------------------- /playground/framework-express/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { defineConfig } from "vite"; 3 | import tsconfigPaths from "vite-tsconfig-paths"; 4 | 5 | export default defineConfig({ 6 | plugins: [reactRouter(), tsconfigPaths()], 7 | }); 8 | -------------------------------------------------------------------------------- /playground/framework-spa/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /build 4 | .env 5 | 6 | .react-router/ 7 | -------------------------------------------------------------------------------- /playground/framework-spa/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export function Layout({ children }: { children: React.ReactNode }) { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {children} 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default function App() { 22 | return ; 23 | } 24 | 25 | export function HydrateFallback() { 26 | return

Loading...

; 27 | } 28 | -------------------------------------------------------------------------------- /playground/framework-spa/app/routes.ts: -------------------------------------------------------------------------------- 1 | import { type RouteConfig, index } from "@react-router/dev/routes"; 2 | 3 | export default [index("routes/_index.tsx")] satisfies RouteConfig; 4 | -------------------------------------------------------------------------------- /playground/framework-spa/app/routes/_index.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from "react-router"; 2 | 3 | export const meta: MetaFunction = () => { 4 | return [ 5 | { title: "New React Router App" }, 6 | { name: "description", content: "Welcome to React Router!" }, 7 | ]; 8 | }; 9 | 10 | export default function Index() { 11 | return ( 12 |
13 |

Welcome to React Router

14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /playground/framework-spa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@playground/framework-spa", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": false, 6 | "type": "module", 7 | "scripts": { 8 | "build": "react-router build", 9 | "dev": "react-router dev", 10 | "preview": "vite preview", 11 | "typecheck": "react-router typegen && tsc" 12 | }, 13 | "dependencies": { 14 | "@react-router/node": "workspace:*", 15 | "react": "^18.2.0", 16 | "react-dom": "^18.2.0", 17 | "react-router": "workspace:*" 18 | }, 19 | "devDependencies": { 20 | "@react-router/dev": "workspace:*", 21 | "@types/react": "^18.2.20", 22 | "@types/react-dom": "^18.2.7", 23 | "typescript": "^5.1.6", 24 | "vite": "^6.0.0", 25 | "vite-tsconfig-paths": "^4.2.1" 26 | }, 27 | "engines": { 28 | "node": ">=20.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /playground/framework-spa/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/playground/framework-spa/public/favicon.ico -------------------------------------------------------------------------------- /playground/framework-spa/react-router.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "@react-router/dev/config"; 2 | 3 | export default { 4 | ssr: false, 5 | } satisfies Config; 6 | -------------------------------------------------------------------------------- /playground/framework-spa/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts", "**/*.tsx", "./.react-router/types/**/*"], 3 | "compilerOptions": { 4 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 5 | "types": ["@react-router/node", "vite/client"], 6 | "verbatimModuleSyntax": true, 7 | "esModuleInterop": true, 8 | "jsx": "react-jsx", 9 | "module": "ESNext", 10 | "moduleResolution": "Bundler", 11 | "resolveJsonModule": true, 12 | "target": "ES2022", 13 | "strict": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "~/*": ["./app/*"] 19 | }, 20 | "noEmit": true, 21 | "rootDirs": [".", "./.react-router/types"] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /playground/framework-spa/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { defineConfig } from "vite"; 3 | import tsconfigPaths from "vite-tsconfig-paths"; 4 | 5 | export default defineConfig({ 6 | plugins: [reactRouter(), tsconfigPaths()], 7 | }); 8 | -------------------------------------------------------------------------------- /playground/framework/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /build 4 | .env 5 | 6 | .react-router/ -------------------------------------------------------------------------------- /playground/framework/app/root.tsx: -------------------------------------------------------------------------------- 1 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; 2 | 3 | export function Layout({ children }: { children: React.ReactNode }) { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {children} 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default function App() { 22 | return ; 23 | } 24 | -------------------------------------------------------------------------------- /playground/framework/app/routes.ts: -------------------------------------------------------------------------------- 1 | import { type RouteConfig, index, route } from "@react-router/dev/routes"; 2 | 3 | export default [ 4 | index("routes/_index.tsx"), 5 | route("products/:id", "routes/product.tsx"), 6 | ] satisfies RouteConfig; 7 | -------------------------------------------------------------------------------- /playground/framework/app/routes/_index.tsx: -------------------------------------------------------------------------------- 1 | import type { Route } from "./+types/_index"; 2 | 3 | export function loader({ params }: Route.LoaderArgs) { 4 | return { planet: "world", date: new Date(), fn: () => 1 }; 5 | } 6 | 7 | export default function Index({ loaderData }: Route.ComponentProps) { 8 | return

Hello, {loaderData.planet}!

; 9 | } 10 | -------------------------------------------------------------------------------- /playground/framework/app/routes/product.tsx: -------------------------------------------------------------------------------- 1 | import type { Route } from "./+types/product"; 2 | 3 | export function loader({ params }: Route.LoaderArgs) { 4 | return { name: `Super cool product #${params.id}` }; 5 | } 6 | 7 | export default function Component({ loaderData }: Route.ComponentProps) { 8 | return

{loaderData.name}

; 9 | } 10 | -------------------------------------------------------------------------------- /playground/framework/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/playground/framework/public/favicon.ico -------------------------------------------------------------------------------- /playground/framework/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { defineConfig } from "vite"; 3 | import tsconfigPaths from "vite-tsconfig-paths"; 4 | 5 | export default defineConfig({ 6 | plugins: [reactRouter(), tsconfigPaths()], 7 | }); 8 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "integration" 3 | - "integration/helpers/*" 4 | - "packages/*" 5 | - "playground/*" 6 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('prettier').Options} 3 | */ 4 | module.exports = {}; 5 | -------------------------------------------------------------------------------- /scripts/clean-v6-artifacts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | pnpm clean 6 | 7 | echo "Removing v6 artifacts..." 8 | set -x 9 | rm -rf packages/react-router-dom-v5-compat/ 10 | rm -f packages/react-router-dom/server.* 11 | set +x 12 | 13 | echo "Installing and building..." 14 | pnpm install --frozen-lockfile 15 | pnpm build -------------------------------------------------------------------------------- /scripts/constants.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const ROOT_DIR = path.resolve(__dirname, ".."); 4 | const EXAMPLES_DIR = path.resolve(ROOT_DIR, "examples"); 5 | 6 | module.exports = { 7 | ROOT_DIR, 8 | EXAMPLES_DIR, 9 | }; 10 | -------------------------------------------------------------------------------- /static/base-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/static/base-branch.png -------------------------------------------------------------------------------- /tutorials/address-book/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules/ 3 | 4 | # React Router 5 | /.react-router/ 6 | /build/ 7 | -------------------------------------------------------------------------------- /tutorials/address-book/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to React Router! 2 | 3 | - [React Router Docs](https://reactrouter.com/home) 4 | 5 | ## Development 6 | 7 | From your terminal: 8 | 9 | ```sh 10 | npm run dev 11 | ``` 12 | 13 | This starts your app in development mode, rebuilding assets on file changes. 14 | 15 | ## Deployment 16 | 17 | First, build your app for production: 18 | 19 | ```sh 20 | npm run build 21 | ``` 22 | 23 | Then run the app in production mode: 24 | 25 | ```sh 26 | npm start 27 | ``` 28 | 29 | Now you'll need to pick a host to deploy it to. 30 | 31 | ### DIY 32 | 33 | If you're familiar with deploying node applications, the built-in React Router app server is production-ready. 34 | 35 | Make sure to deploy the output of `react-router build` 36 | 37 | - `build/server` 38 | - `build/client` 39 | -------------------------------------------------------------------------------- /tutorials/address-book/app/routes.ts: -------------------------------------------------------------------------------- 1 | import type { RouteConfig } from "@react-router/dev/routes"; 2 | 3 | export default [] satisfies RouteConfig; 4 | -------------------------------------------------------------------------------- /tutorials/address-book/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AaqibhafeezKhan/react-router/595bed36ebb7e01b7cbda283589867cce5cb0318/tutorials/address-book/public/favicon.ico -------------------------------------------------------------------------------- /tutorials/address-book/react-router.config.ts: -------------------------------------------------------------------------------- 1 | import { type Config } from "@react-router/dev/config"; 2 | 3 | export default { 4 | ssr: false, 5 | } satisfies Config; 6 | -------------------------------------------------------------------------------- /tutorials/address-book/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "**/*", 4 | "**/.server/**/*", 5 | "**/.client/**/*", 6 | ".react-router/types/**/*" 7 | ], 8 | "compilerOptions": { 9 | "lib": ["DOM", "DOM.Iterable", "ES2022"], 10 | "types": ["node", "vite/client"], 11 | "target": "ES2022", 12 | "module": "ES2022", 13 | "moduleResolution": "bundler", 14 | "jsx": "react-jsx", 15 | "rootDirs": [".", "./.react-router/types"], 16 | "baseUrl": ".", 17 | "esModuleInterop": true, 18 | "verbatimModuleSyntax": true, 19 | "noEmit": true, 20 | "resolveJsonModule": true, 21 | "skipLibCheck": true, 22 | "strict": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tutorials/address-book/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { reactRouter } from "@react-router/dev/vite"; 2 | import { defineConfig } from "vite"; 3 | 4 | export default defineConfig({ 5 | plugins: [reactRouter()], 6 | }); 7 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "React Router API Reference", 3 | "entryPoints": ["packages/*"], 4 | "entryPointStrategy": "packages", 5 | "includeVersion": false, 6 | "json": "./public/dev/api.json", 7 | "out": "./public/dev", 8 | "hostedBaseUrl": "https://api.reactrouter.com/dev/" 9 | } 10 | --------------------------------------------------------------------------------