diff --git a/package-lock.json b/package-lock.json index bb2f490..88b9035 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "react-day-picker": "^8.9.1", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", + "react-helmet": "^6.1.0", "react-router-dom": "^6.20.0", "sort-by": "^1.2.0", "tailwind-merge": "^2.0.0", @@ -41,6 +42,7 @@ "@types/node": "^20.10.1", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", + "@types/react-helmet": "^6.1.9", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "@vitejs/plugin-react-swc": "^3.5.0", @@ -1826,6 +1828,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-helmet": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.9.tgz", + "integrity": "sha512-nuOeTefP4yPTWHvjGksCBKb/4hsgJxSX7aSTjTIDFXJIkZ6Wo2Y4/cmE1FO9OlYBrHjKOer/0zLwY7s4qiQBtw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", @@ -3876,6 +3887,25 @@ "react": ">= 16.8 || 18.0.0" } }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-helmet": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "dependencies": { + "object-assign": "^4.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.1.1", + "react-side-effect": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.3.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -3956,6 +3986,14 @@ "react-dom": ">=16.8" } }, + "node_modules/react-side-effect": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz", + "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==", + "peerDependencies": { + "react": "^16.3.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -5571,6 +5609,15 @@ "@types/react": "*" } }, + "@types/react-helmet": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.9.tgz", + "integrity": "sha512-nuOeTefP4yPTWHvjGksCBKb/4hsgJxSX7aSTjTIDFXJIkZ6Wo2Y4/cmE1FO9OlYBrHjKOer/0zLwY7s4qiQBtw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", @@ -6959,6 +7006,22 @@ "prop-types": "^15.8.1" } }, + "react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "react-helmet": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.1.1", + "react-side-effect": "^2.1.0" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -7002,6 +7065,12 @@ "react-router": "6.20.0" } }, + "react-side-effect": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz", + "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==", + "requires": {} + }, "react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", diff --git a/package.json b/package.json index d542df4..d807202 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "react-day-picker": "^8.9.1", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", + "react-helmet": "^6.1.0", "react-router-dom": "^6.20.0", "sort-by": "^1.2.0", "tailwind-merge": "^2.0.0", @@ -43,6 +44,7 @@ "@types/node": "^20.10.1", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", + "@types/react-helmet": "^6.1.9", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "@vitejs/plugin-react-swc": "^3.5.0", diff --git a/src/App.tsx b/src/App.tsx index ab3cd27..e651964 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,11 @@ +import { useMemo } from "react"; import { Tooltip, TooltipContent, TooltipTrigger, } from "./components/ui/tooltip"; +import { Helmet } from "react-helmet"; +import { useFormData } from "./lib/hooks"; import { Title } from "./components/title"; import { Counter } from "./components/counter"; import { Toaster } from "./components/ui/toaster"; @@ -11,8 +14,17 @@ import { SettingsToggle } from "./components/settings-toggle"; import { BackgroundImage } from "./components/background-image"; export default function App() { + const [{ title: _title }] = useFormData(); + const title = useMemo( + () => "Event Horizon" + (_title ? ` - ${_title}` : ""), + [_title] + ); + return ( <> + + {title} +