From 06e9bd0b79f27c2fb3673aae0d5007855c372ddd Mon Sep 17 00:00:00 2001 From: Kyle Fang Date: Thu, 3 Jul 2025 10:26:33 +0800 Subject: [PATCH] feat: add React Router example with MemoryRouter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Install react-router-dom dependency - Create react-router-experiment.tsx demonstrating React Router usage - Implement navigation with Routes, nested routes, and navigation hooks - Add example pages: Homepage, BlogsIndex, and BlogPage with params - Use MemoryRouter for in-memory routing suitable for Telegram bots 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- bun.lock | 11 ++ packages/examples/package.json | 3 +- .../examples/src/react-router-experiment.tsx | 138 ++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 packages/examples/src/react-router-experiment.tsx diff --git a/bun.lock b/bun.lock index c5dc895..fc4fd34 100644 --- a/bun.lock +++ b/bun.lock @@ -33,6 +33,7 @@ "@react-telegram/core": "workspace:*", "@react-telegram/mtcute-adapter": "workspace:*", "react": "^19.1.0", + "react-router-dom": "^7.6.3", }, "devDependencies": { "@types/react": "npm:pure-react-types@^0.1.4", @@ -166,6 +167,8 @@ "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], + "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="], @@ -278,8 +281,14 @@ "react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="], + "react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="], + "react-reconciler": ["react-reconciler@0.32.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ=="], + "react-router": ["react-router@7.6.3", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-zf45LZp5skDC6I3jDLXQUu0u26jtuP4lEGbc7BbdyxenBN1vJSTA18czM2D+h5qyMBuMrD+9uB+mU37HIoKGRA=="], + + "react-router-dom": ["react-router-dom@7.6.3", "", { "dependencies": { "react-router": "7.6.3" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-DiWJm9qdUAmiJrVWaeJdu4TKu13+iB/8IEi0EW/XgaHCjW/vWGrwzup0GVvaMteuZjKnh5bEvJP/K0MDnzawHw=="], + "read-yaml-file": ["read-yaml-file@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", "pify": "^4.0.1", "strip-bom": "^3.0.0" } }, "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA=="], "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], @@ -294,6 +303,8 @@ "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="], + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], diff --git a/packages/examples/package.json b/packages/examples/package.json index 0e4aa7c..218f959 100644 --- a/packages/examples/package.json +++ b/packages/examples/package.json @@ -16,7 +16,8 @@ "dependencies": { "@react-telegram/core": "workspace:*", "@react-telegram/mtcute-adapter": "workspace:*", - "react": "^19.1.0" + "react": "^19.1.0", + "react-router-dom": "^7.6.3" }, "devDependencies": { "@types/react": "npm:pure-react-types@^0.1.4", diff --git a/packages/examples/src/react-router-experiment.tsx b/packages/examples/src/react-router-experiment.tsx new file mode 100644 index 0000000..451be13 --- /dev/null +++ b/packages/examples/src/react-router-experiment.tsx @@ -0,0 +1,138 @@ +/// + +import React, { PropsWithChildren } from "react"; +import { MemoryRouter, Outlet, Route, Routes, To, useLocation, useNavigate, useParams } from "react-router-dom"; +import { MtcuteAdapter } from "@react-telegram/mtcute-adapter"; + +export const ReactRouterExperiment = () => { + return ( + + + }> + } /> + } /> + } /> + + + + ); +}; + +export const Layout = () => { + const location = useLocation(); + + return ( + <> + path: {location.pathname} +
+
+ + + ); +}; + +export const BackButton = () => { + const navigate = useNavigate(); + + return ( + + ); +}; + +export const NavigateButton = ({ + to, + children, +}: PropsWithChildren<{ + to: To +}>) => { + const navigate = useNavigate(); + + return ( + + ); +}; + +export const Homepage = () => { + return ( + <> + This is the homepage +
+
+ + + 📝 Blogs + + + + ); +}; + +export const BlogsIndex = () => { + const navigate = useNavigate(); + + return ( + <> + + + +
+ Please select a post :3 +
+
+ + + + + + + + + + ); +}; + +export const BlogPage = () => { + const { id = "unknown" } = useParams(); + + return ( + <> + + + +
+ Blog page for: {id} +
+
+ This is the content for blog post #{id} + + ); +}; + +// Bot setup +async function main() { + const config = { + apiId: parseInt(process.env.API_ID || '0'), + apiHash: process.env.API_HASH || '', + botToken: process.env.BOT_TOKEN || '', + storage: process.env.STORAGE_PATH || '.mtcute' + }; + + if (!config.apiId || !config.apiHash || !config.botToken) { + console.error('Please set API_ID, API_HASH, and BOT_TOKEN environment variables'); + process.exit(1); + } + + const adapter = new MtcuteAdapter(config); + + adapter.onCommand('router', () => ); + + await adapter.start(config.botToken); + + console.log('Bot is running! Send /router to see React Router example.'); +} + +main().catch(console.error); \ No newline at end of file