Date: Tue, 10 Dec 2024 12:04:11 +0100
Subject: [PATCH 1/4] chore(examples): migrate remix to react-router 7
---
examples/remix-ts/.gitignore | 1 +
.../remix-ts/app/components/AppShellBar.tsx | 2 +-
examples/remix-ts/app/components/TodoList.tsx | 2 +-
examples/remix-ts/app/entry.client.tsx | 22 -
examples/remix-ts/app/entry.server.tsx | 130 -
examples/remix-ts/app/root.tsx | 46 +-
examples/remix-ts/app/routes.ts | 3 +
.../app/routes/{_index.tsx => index.tsx} | 18 +-
.../app/routes/{todos.$id.tsx => todo.tsx} | 15 +-
examples/remix-ts/package-lock.json | 9091 +++++------------
examples/remix-ts/package.json | 34 +-
examples/remix-ts/react-router.config.ts | 7 +
examples/remix-ts/tsconfig.json | 12 +-
examples/remix-ts/vite.config.ts | 7 +-
14 files changed, 2874 insertions(+), 6516 deletions(-)
delete mode 100644 examples/remix-ts/app/entry.client.tsx
delete mode 100644 examples/remix-ts/app/entry.server.tsx
create mode 100644 examples/remix-ts/app/routes.ts
rename examples/remix-ts/app/routes/{_index.tsx => index.tsx} (63%)
rename examples/remix-ts/app/routes/{todos.$id.tsx => todo.tsx} (80%)
create mode 100644 examples/remix-ts/react-router.config.ts
diff --git a/examples/remix-ts/.gitignore b/examples/remix-ts/.gitignore
index 80ec311f4ff..0ba31df338b 100644
--- a/examples/remix-ts/.gitignore
+++ b/examples/remix-ts/.gitignore
@@ -3,3 +3,4 @@ node_modules
/.cache
/build
.env
+.react-router/
diff --git a/examples/remix-ts/app/components/AppShellBar.tsx b/examples/remix-ts/app/components/AppShellBar.tsx
index eb86cb82b54..c21159fadc3 100644
--- a/examples/remix-ts/app/components/AppShellBar.tsx
+++ b/examples/remix-ts/app/components/AppShellBar.tsx
@@ -1,4 +1,4 @@
-import { useLocation, useNavigate } from '@remix-run/react';
+import { useLocation, useNavigate } from 'react-router';
import { getTheme, setTheme } from '@ui5/webcomponents-base/dist/config/Theme.js';
import navBackIcon from '@ui5/webcomponents-icons/dist/nav-back.js';
import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js';
diff --git a/examples/remix-ts/app/components/TodoList.tsx b/examples/remix-ts/app/components/TodoList.tsx
index 67f3668c82c..c23d3ea8b79 100644
--- a/examples/remix-ts/app/components/TodoList.tsx
+++ b/examples/remix-ts/app/components/TodoList.tsx
@@ -1,4 +1,4 @@
-import { useNavigate } from '@remix-run/react';
+import { useNavigate } from 'react-router';
import ValueState from '@ui5/webcomponents-base/dist/types/ValueState.js';
import { List, ListItemStandard, ListPropTypes } from '@ui5/webcomponents-react';
import ListItemType from '@ui5/webcomponents/dist/types/ListItemType.js';
diff --git a/examples/remix-ts/app/entry.client.tsx b/examples/remix-ts/app/entry.client.tsx
deleted file mode 100644
index 966fbc13309..00000000000
--- a/examples/remix-ts/app/entry.client.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * By default, Remix will handle hydrating your app on the client for you.
- * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
- * For more information, see https://remix.run/file-conventions/entry.client
- */
-
-import { RemixBrowser } from '@remix-run/react';
-import { startTransition, StrictMode } from 'react';
-import { hydrateRoot } from 'react-dom/client';
-
-import './globals.css';
-import '@ui5/webcomponents-react/styles.css';
-import '@ui5/webcomponents-icons/dist/Assets.js';
-
-startTransition(() => {
- hydrateRoot(
- document.getElementById('root')!,
-
-
-
- );
-});
diff --git a/examples/remix-ts/app/entry.server.tsx b/examples/remix-ts/app/entry.server.tsx
deleted file mode 100644
index 206cc4ebe4b..00000000000
--- a/examples/remix-ts/app/entry.server.tsx
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * By default, Remix will handle generating the HTTP Response for you.
- * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
- * For more information, see https://remix.run/file-conventions/entry.server
- */
-
-import { PassThrough } from 'node:stream';
-
-import type { AppLoadContext, EntryContext } from '@remix-run/node';
-import { createReadableStreamFromReadable } from '@remix-run/node';
-import { RemixServer } from '@remix-run/react';
-import { isbot } from 'isbot';
-import { renderToPipeableStream } from 'react-dom/server';
-import { renderHeadToString } from 'remix-island';
-import { Head } from './root';
-
-const ABORT_DELAY = 5_000;
-
-export default function handleRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext,
- // This is ignored so we can keep it in the template for visibility. Feel
- // free to delete this parameter in your app if you're not using it!
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- loadContext: AppLoadContext
-) {
- return isbot(request.headers.get('user-agent') || '')
- ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext)
- : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext);
-}
-
-function handleBotRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext
-) {
- return new Promise((resolve, reject) => {
- let shellRendered = false;
- const { pipe, abort } = renderToPipeableStream(
- ,
- {
- onAllReady() {
- const head = renderHeadToString({ request, remixContext, Head });
- shellRendered = true;
- const body = new PassThrough();
- const stream = createReadableStreamFromReadable(body);
-
- resolve(
- new Response(stream, {
- headers: responseHeaders,
- status: responseStatusCode
- })
- );
-
- responseHeaders.set('Content-Type', 'text/html');
- body.write(`${head}`);
- pipe(body);
- body.write('
');
- },
- onShellError(error: unknown) {
- reject(error);
- },
- onError(error: unknown) {
- responseStatusCode = 500;
- // Log streaming rendering errors from inside the shell. Don't log
- // errors encountered during initial shell rendering since they'll
- // reject and get logged in handleDocumentRequest.
- if (shellRendered) {
- console.error(error);
- }
- }
- }
- );
-
- setTimeout(abort, ABORT_DELAY);
- });
-}
-
-function handleBrowserRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext
-) {
- return new Promise((resolve, reject) => {
- let shellRendered = false;
- const { pipe, abort } = renderToPipeableStream(
- ,
- {
- onShellReady() {
- const head = renderHeadToString({ request, remixContext, Head });
- shellRendered = true;
- const body = new PassThrough();
- const stream = createReadableStreamFromReadable(body);
-
- responseHeaders.set('Content-Type', 'text/html');
-
- resolve(
- new Response(stream, {
- headers: responseHeaders,
- status: responseStatusCode
- })
- );
-
- body.write(`${head}`);
-
- pipe(body);
- body.write('
');
- },
- onShellError(error: unknown) {
- reject(error);
- },
- onError(error: unknown) {
- responseStatusCode = 500;
- // Log streaming rendering errors from inside the shell. Don't log
- // errors encountered during initial shell rendering since they'll
- // reject and get logged in handleDocumentRequest.
- if (shellRendered) {
- console.error(error);
- }
- }
- }
- );
-
- setTimeout(abort, ABORT_DELAY);
- });
-}
diff --git a/examples/remix-ts/app/root.tsx b/examples/remix-ts/app/root.tsx
index fc5d7b3b373..d8c9a74a1cf 100644
--- a/examples/remix-ts/app/root.tsx
+++ b/examples/remix-ts/app/root.tsx
@@ -1,28 +1,36 @@
-import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
-import { createHead } from 'remix-island';
+import wcrStyles from '@ui5/webcomponents-react/styles.css?url';
+import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router';
+import type { Route } from './+types/root';
import { AppShell } from './components/AppShell';
+import appStyles from './globals.css?url';
-export const Head = createHead(() => {
+export const links: Route.LinksFunction = () => [
+ { rel: 'stylesheet', href: appStyles },
+ { rel: 'stylesheet', href: wcrStyles }
+];
+
+export function Layout({ children }: { children: React.ReactNode }) {
return (
- <>
-
-
-
-
- >
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
);
-});
+}
export default function App() {
- // this will be rendered inside a node
return (
- <>
-
-