Remove CRA and use Vite instead

This commit is contained in:
Reece
2025-05-28 21:43:02 +01:00
parent d216811317
commit 15761ae743
21 changed files with 60136 additions and 15126 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+23
View File
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using Vite"
/>
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>Vite App</title>
<script type="module" crossorigin src="/assets/index-DAILjWej.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DxdJ27yt.css">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

+25
View File
@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
+58353
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
@@ -1,22 +1,22 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="UTF-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta <meta
name="description" name="description"
content="Web site created using create-react-app" content="Web site created using Vite"
/> />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="/manifest.json" />
<title>React App</title> <title>Vite App</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/index.jsx"></script>
</body> </body>
</html> </html>
+1497 -15008
View File
File diff suppressed because it is too large Load Diff
+9 -6
View File
@@ -11,23 +11,24 @@
"@mantine/hooks": "^8.0.1", "@mantine/hooks": "^8.0.1",
"@mui/icons-material": "^7.1.0", "@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0", "@mui/material": "^7.1.0",
"@tailwindcss/postcss": "^4.1.8",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3", "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0", "@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"autoprefixer": "^10.4.21",
"axios": "^1.9.0", "axios": "^1.9.0",
"pdfjs-dist": "^3.11.174", "pdfjs-dist": "^3.11.174",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-router-dom": "^7.6.0", "react-router-dom": "^7.6.0",
"react-scripts": "5.0.1", "tailwindcss": "^4.1.8",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "dev": "vite",
"build": "react-scripts build", "build": "vite build",
"test": "react-scripts test", "preview": "vite preview"
"eject": "react-scripts eject"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
@@ -50,10 +51,12 @@
"devDependencies": { "devDependencies": {
"@types/react": "^19.1.4", "@types/react": "^19.1.4",
"@types/react-dom": "^19.1.5", "@types/react-dom": "^19.1.5",
"@vitejs/plugin-react": "^4.5.0",
"postcss": "^8.5.3", "postcss": "^8.5.3",
"postcss-cli": "^11.0.1", "postcss-cli": "^11.0.1",
"postcss-preset-mantine": "^1.17.0", "postcss-preset-mantine": "^1.17.0",
"postcss-simple-vars": "^7.0.1", "postcss-simple-vars": "^7.0.1",
"typescript": "^5.8.3" "typescript": "^5.8.3",
"vite": "^6.3.5"
} }
} }
+5 -6
View File
@@ -1,7 +1,6 @@
module.exports = { module.exports = {
plugins: { plugins: [
tailwindcss: {}, require('@tailwindcss/postcss'),
autoprefixer: {}, require('autoprefixer'),
],
}, };
}
-6
View File
@@ -1,6 +0,0 @@
import './index.css';
import HomePage from './pages/HomePage';
export default function App({ colorScheme, toggleColorScheme }) {
return <HomePage colorScheme={colorScheme} toggleColorScheme={toggleColorScheme} />;
}
+6
View File
@@ -0,0 +1,6 @@
import './index.css';
import React from 'react';
import HomePage from './pages/HomePage';
export default function App() {
return <HomePage/>;
}
+2 -5
View File
@@ -1,13 +1,10 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Card, Group, Text, Stack, Image, Badge, Button, Box, Flex, ThemeIcon } from "@mantine/core"; import { Card, Group, Text, Stack, Image, Badge, Button, Box, Flex, ThemeIcon } from "@mantine/core";
import { Dropzone, MIME_TYPES } from "@mantine/dropzone"; import { Dropzone, MIME_TYPES } from "@mantine/dropzone";
import { GlobalWorkerOptions, getDocument } from "pdfjs-dist";
import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf"; import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf";
GlobalWorkerOptions.workerSrc = import { GlobalWorkerOptions } from "pdfjs-dist";
(import.meta as any).env?.PUBLIC_URL GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
? `${(import.meta as any).env.PUBLIC_URL}/pdf.worker.js`
: "/pdf.worker.js";
export interface FileWithUrl extends File { export interface FileWithUrl extends File {
url?: string; url?: string;
+6 -20
View File
@@ -1,5 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Box, Text, Stack, Button, TextInput } from "@mantine/core"; import { Box, Text, Stack, Button, TextInput, Group } from "@mantine/core";
type Tool = { type Tool = {
icon: React.ReactNode; icon: React.ReactNode;
@@ -24,23 +24,7 @@ const ToolPicker: React.FC<ToolPickerProps> = ({ selectedToolKey, onSelect, tool
); );
return ( return (
<Box <Box >
style={{
width: 220,
borderRight: "1px solid #e9ecef",
minHeight: "100vh",
padding: 16,
position: "fixed",
left: 0,
top: 0,
bottom: 0,
zIndex: 100,
overflowY: "auto",
}}
>
<Text size="lg" fw={500} mb="md">
Tools
</Text>
<TextInput <TextInput
placeholder="Search tools..." placeholder="Search tools..."
value={search} value={search}
@@ -48,7 +32,7 @@ const ToolPicker: React.FC<ToolPickerProps> = ({ selectedToolKey, onSelect, tool
mb="md" mb="md"
autoComplete="off" autoComplete="off"
/> />
<Stack gap="sm"> <Stack align="flex-start">
{filteredTools.length === 0 ? ( {filteredTools.length === 0 ? (
<Text c="dimmed" size="sm"> <Text c="dimmed" size="sm">
No tools found No tools found
@@ -59,9 +43,11 @@ const ToolPicker: React.FC<ToolPickerProps> = ({ selectedToolKey, onSelect, tool
key={id} key={id}
variant={selectedToolKey === id ? "filled" : "subtle"} variant={selectedToolKey === id ? "filled" : "subtle"}
onClick={() => onSelect(id)} onClick={() => onSelect(id)}
fullWidth
size="md" size="md"
radius="md" radius="md"
leftSection={icon}
fullWidth
justify="flex-start"
> >
{name} {name}
</Button> </Button>
+1 -1
View File
@@ -10,7 +10,7 @@ import ViewWeekIcon from "@mui/icons-material/ViewWeek"; // for dual page (book)
import DescriptionIcon from "@mui/icons-material/Description"; // for single page import DescriptionIcon from "@mui/icons-material/Description"; // for single page
import { useLocalStorage } from "@mantine/hooks"; import { useLocalStorage } from "@mantine/hooks";
GlobalWorkerOptions.workerSrc = `${process.env.PUBLIC_URL}/pdf.worker.js`; GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
export interface ViewerProps { export interface ViewerProps {
pdfFile: { file: File; url: string } | null; pdfFile: { file: File; url: string } | null;
@@ -5,14 +5,17 @@ import { ColorSchemeScript, MantineProvider, mantineHtmlProps } from '@mantine/c
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root')); // Finds the root DOM element const container = document.getElementById('root');
if (!container) {
throw new Error("Root container missing in index.html");
}
const root = ReactDOM.createRoot(container); // Finds the root DOM element
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<ColorSchemeScript /> <ColorSchemeScript />
<MantineProvider withGlobalStyles withNormalizeCSS> <MantineProvider defaultColorScheme="auto">
<BrowserRouter> <BrowserRouter>
<App /> <App />
</BrowserRouter> </BrowserRouter>
@@ -20,4 +23,3 @@ root.render(
</React.StrictMode> </React.StrictMode>
); );
reportWebVitals();
+46 -22
View File
@@ -154,6 +154,7 @@ const TOOL_PARAMS = {
export default function HomePage() { export default function HomePage() {
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const theme = useMantineTheme(); const theme = useMantineTheme();
const { colorScheme } = useMantineColorScheme(); // <-- Call hook ONCE at the top
// Core app state // Core app state
const [selectedToolKey, setSelectedToolKey] = useState<string>(searchParams.get("tool") || "split"); const [selectedToolKey, setSelectedToolKey] = useState<string>(searchParams.get("tool") || "split");
@@ -220,29 +221,51 @@ export default function HomePage() {
}; };
return ( return (
<Group align="flex-start" gap={0} style={{ minHeight: "100vh" }}> <Group
align="flex-start"
gap={0}
style={{
minHeight: "100vh",
width: "100vw",
overflow: "hidden",
flexWrap: "nowrap",
display: "flex",
}}
>
{/* Left: Tool Picker */} {/* Left: Tool Picker */}
{sidebarsVisible && ( {sidebarsVisible && (
<Box
style={{
minWidth: 180,
maxWidth: 240,
width: "16vw",
height: "100vh",
borderRight: `1px solid ${colorScheme === "dark" ? theme.colors.dark[4] : "#e9ecef"}`,
background: colorScheme === "dark" ? theme.colors.dark[7] : "#fff",
zIndex: 101,
display: "flex",
flexDirection: "column",
}}
>
<ToolPicker <ToolPicker
selectedToolKey={selectedToolKey} selectedToolKey={selectedToolKey}
onSelect={handleToolSelect} onSelect={handleToolSelect}
toolRegistry={toolRegistry} toolRegistry={toolRegistry}
/> />
</Box>
)} )}
{/* Middle: Main View (Viewer, Editor, Manager) */} {/* Middle: Main View */}
<Box <Box
style={{ style={{
width: sidebarsVisible flex: 1,
? "calc(100vw - 220px - 380px)"
: "100vw",
marginLeft: sidebarsVisible ? 220 : 0,
marginRight: sidebarsVisible ? 380 : 0,
position: "relative", // <-- important for absolute overlay
height: "100vh", height: "100vh",
minWidth:"20rem",
position: "relative",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
transition: "all 0.3s", transition: "all 0.3s",
background: colorScheme === "dark" ? theme.colors.dark[6] : "#f8f9fa",
}} }}
> >
{/* Overlayed View Switcher */} {/* Overlayed View Switcher */}
@@ -254,6 +277,7 @@ export default function HomePage() {
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
zIndex: 30, zIndex: 30,
pointerEvents: "none",
}} }}
> >
<div style={{ pointerEvents: "auto" }}> <div style={{ pointerEvents: "auto" }}>
@@ -268,7 +292,7 @@ export default function HomePage() {
/> />
</div> </div>
</div> </div>
{/* Main content area with matching Paper */} {/* Main content area */}
<Paper <Paper
radius="0 0 xl xl" radius="0 0 xl xl"
shadow="sm" shadow="sm"
@@ -316,35 +340,35 @@ export default function HomePage() {
</Box> </Box>
</Paper> </Paper>
</Box> </Box>
{/* Right: Tool Interaction */} {/* Right: Tool Interaction */}
{sidebarsVisible && ( {sidebarsVisible && (
<Box <Box
style={{ style={{
width: 380, minWidth: 260,
borderLeft: "1px solid #e9ecef", maxWidth: 400,
width: "22vw",
height: "100vh", height: "100vh",
borderLeft: `1px solid ${colorScheme === "dark" ? theme.colors.dark[4] : "#e9ecef"}`,
background: colorScheme === "dark" ? theme.colors.dark[7] : "#fff",
padding: 24, padding: 24,
gap: 16, gap: 16,
position: "fixed",
right: 0,
top: 0,
bottom: 0,
zIndex: 100, zIndex: 100,
display: "flex",
flexDirection: "column",
}} }}
> >
{selectedTool && selectedTool.component && ( {selectedTool && selectedTool.component && renderTool()}
<>
{renderTool()}
</>
)}
</Box> </Box>
)} )}
{/* Sidebar toggle button */}
<Button <Button
variant="light" variant="light"
color="blue" color="blue"
size="xs" size="xs"
style={{ position: "absolute", top: 16, right: 16, zIndex: 200 }} style={{ position: "fixed", top: 16, right: 16, zIndex: 200 }}
onClick={() => setSidebarsVisible(v => !v)} onClick={() => setSidebarsVisible((v) => !v)}
> >
{sidebarsVisible ? "Hide Sidebars" : "Show Sidebars"} {sidebarsVisible ? "Hide Sidebars" : "Show Sidebars"}
</Button> </Button>
+6
View File
@@ -0,0 +1,6 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});