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

99
frontend/dist/assets/index-DAILjWej.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
frontend/dist/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

23
frontend/dist/index.html vendored Normal file
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
frontend/dist/logo192.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
frontend/dist/logo512.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

25
frontend/dist/manifest.json vendored Normal file
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
frontend/dist/pdf.worker.js vendored Normal file

File diff suppressed because one or more lines are too long

3
frontend/dist/robots.txt vendored Normal file
View File

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1,22 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<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 create-react-app"
content="Web site created using Vite"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>React App</title>
<title>Vite App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/index.jsx"></script>
</body>
</html>

16557
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,23 +11,24 @@
"@mantine/hooks": "^8.0.1",
"@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0",
"@tailwindcss/postcss": "^4.1.8",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0",
"autoprefixer": "^10.4.21",
"axios": "^1.9.0",
"pdfjs-dist": "^3.11.174",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.0",
"react-scripts": "5.0.1",
"tailwindcss": "^4.1.8",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"eslintConfig": {
"extends": [
@ -50,10 +51,12 @@
"devDependencies": {
"@types/react": "^19.1.4",
"@types/react-dom": "^19.1.5",
"@vitejs/plugin-react": "^4.5.0",
"postcss": "^8.5.3",
"postcss-cli": "^11.0.1",
"postcss-preset-mantine": "^1.17.0",
"postcss-simple-vars": "^7.0.1",
"typescript": "^5.8.3"
"typescript": "^5.8.3",
"vite": "^6.3.5"
}
}

View File

@ -1,7 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
plugins: [
require('@tailwindcss/postcss'),
require('autoprefixer'),
],
};

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
frontend/src/App.tsx Normal file
View File

@ -0,0 +1,6 @@
import './index.css';
import React from 'react';
import HomePage from './pages/HomePage';
export default function App() {
return <HomePage/>;
}

View File

@ -1,13 +1,10 @@
import React, { useState, useEffect } from "react";
import { Card, Group, Text, Stack, Image, Badge, Button, Box, Flex, ThemeIcon } from "@mantine/core";
import { Dropzone, MIME_TYPES } from "@mantine/dropzone";
import { GlobalWorkerOptions, getDocument } from "pdfjs-dist";
import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf";
GlobalWorkerOptions.workerSrc =
(import.meta as any).env?.PUBLIC_URL
? `${(import.meta as any).env.PUBLIC_URL}/pdf.worker.js`
: "/pdf.worker.js";
import { GlobalWorkerOptions } from "pdfjs-dist";
GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
export interface FileWithUrl extends File {
url?: string;

View File

@ -1,5 +1,5 @@
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 = {
icon: React.ReactNode;
@ -24,23 +24,7 @@ const ToolPicker: React.FC<ToolPickerProps> = ({ selectedToolKey, onSelect, tool
);
return (
<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>
<Box >
<TextInput
placeholder="Search tools..."
value={search}
@ -48,7 +32,7 @@ const ToolPicker: React.FC<ToolPickerProps> = ({ selectedToolKey, onSelect, tool
mb="md"
autoComplete="off"
/>
<Stack gap="sm">
<Stack align="flex-start">
{filteredTools.length === 0 ? (
<Text c="dimmed" size="sm">
No tools found
@ -59,9 +43,11 @@ const ToolPicker: React.FC<ToolPickerProps> = ({ selectedToolKey, onSelect, tool
key={id}
variant={selectedToolKey === id ? "filled" : "subtle"}
onClick={() => onSelect(id)}
fullWidth
size="md"
radius="md"
leftSection={icon}
fullWidth
justify="flex-start"
>
{name}
</Button>

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 { useLocalStorage } from "@mantine/hooks";
GlobalWorkerOptions.workerSrc = `${process.env.PUBLIC_URL}/pdf.worker.js`;
GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
export interface ViewerProps {
pdfFile: { file: File; url: string } | null;

View File

@ -5,14 +5,17 @@ import { ColorSchemeScript, MantineProvider, mantineHtmlProps } from '@mantine/c
import { BrowserRouter } from 'react-router-dom';
import './index.css';
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(
<React.StrictMode>
<ColorSchemeScript />
<MantineProvider withGlobalStyles withNormalizeCSS>
<MantineProvider defaultColorScheme="auto">
<BrowserRouter>
<App />
</BrowserRouter>
@ -20,4 +23,3 @@ root.render(
</React.StrictMode>
);
reportWebVitals();

View File

@ -154,6 +154,7 @@ const TOOL_PARAMS = {
export default function HomePage() {
const [searchParams, setSearchParams] = useSearchParams();
const theme = useMantineTheme();
const { colorScheme } = useMantineColorScheme(); // <-- Call hook ONCE at the top
// Core app state
const [selectedToolKey, setSelectedToolKey] = useState<string>(searchParams.get("tool") || "split");
@ -220,29 +221,51 @@ export default function HomePage() {
};
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 */}
{sidebarsVisible && (
<ToolPicker
selectedToolKey={selectedToolKey}
onSelect={handleToolSelect}
toolRegistry={toolRegistry}
/>
<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
selectedToolKey={selectedToolKey}
onSelect={handleToolSelect}
toolRegistry={toolRegistry}
/>
</Box>
)}
{/* Middle: Main View (Viewer, Editor, Manager) */}
{/* Middle: Main View */}
<Box
style={{
width: sidebarsVisible
? "calc(100vw - 220px - 380px)"
: "100vw",
marginLeft: sidebarsVisible ? 220 : 0,
marginRight: sidebarsVisible ? 380 : 0,
position: "relative", // <-- important for absolute overlay
flex: 1,
height: "100vh",
minWidth:"20rem",
position: "relative",
display: "flex",
flexDirection: "column",
transition: "all 0.3s",
background: colorScheme === "dark" ? theme.colors.dark[6] : "#f8f9fa",
}}
>
{/* Overlayed View Switcher */}
@ -254,21 +277,22 @@ export default function HomePage() {
display: "flex",
justifyContent: "center",
zIndex: 30,
pointerEvents: "none",
}}
>
<div style={{ pointerEvents: "auto" }}>
<SegmentedControl
data={VIEW_OPTIONS}
value={currentView}
onChange={setCurrentView}
color="blue"
radius="xl"
size="md"
fullWidth
/>
<SegmentedControl
data={VIEW_OPTIONS}
value={currentView}
onChange={setCurrentView}
color="blue"
radius="xl"
size="md"
fullWidth
/>
</div>
</div>
{/* Main content area with matching Paper */}
{/* Main content area */}
<Paper
radius="0 0 xl xl"
shadow="sm"
@ -316,35 +340,35 @@ export default function HomePage() {
</Box>
</Paper>
</Box>
{/* Right: Tool Interaction */}
{sidebarsVisible && (
<Box
style={{
width: 380,
borderLeft: "1px solid #e9ecef",
minWidth: 260,
maxWidth: 400,
width: "22vw",
height: "100vh",
borderLeft: `1px solid ${colorScheme === "dark" ? theme.colors.dark[4] : "#e9ecef"}`,
background: colorScheme === "dark" ? theme.colors.dark[7] : "#fff",
padding: 24,
gap: 16,
position: "fixed",
right: 0,
top: 0,
bottom: 0,
zIndex: 100,
display: "flex",
flexDirection: "column",
}}
>
{selectedTool && selectedTool.component && (
<>
{renderTool()}
</>
)}
{selectedTool && selectedTool.component && renderTool()}
</Box>
)}
{/* Sidebar toggle button */}
<Button
variant="light"
color="blue"
size="xs"
style={{ position: "absolute", top: 16, right: 16, zIndex: 200 }}
onClick={() => setSidebarsVisible(v => !v)}
style={{ position: "fixed", top: 16, right: 16, zIndex: 200 }}
onClick={() => setSidebarsVisible((v) => !v)}
>
{sidebarsVisible ? "Hide Sidebars" : "Show Sidebars"}
</Button>

View File

@ -0,0 +1,6 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});