info-site-generator 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +9 -0
- package/package.json +38 -0
- package/public/arrow-left.svg +1 -0
- package/public/dark-theme-white.svg +1 -0
- package/public/dark-theme.svg +1 -0
- package/public/favicon.ico +0 -0
- package/public/home-image.jpg +0 -0
- package/public/homebackground.jpg +0 -0
- package/public/index.html +44 -0
- package/public/light-theme-white.svg +1 -0
- package/public/light-theme.svg +1 -0
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +25 -0
- package/public/quote.svg +1 -0
- package/public/robots.txt +3 -0
- package/src/App.tsx +76 -0
- package/src/components/ArrowBack.tsx +14 -0
- package/src/components/Footer.tsx +50 -0
- package/src/components/Navbar.tsx +100 -0
- package/src/components/Wrapper.tsx +21 -0
- package/src/content.json +20 -0
- package/src/contentDefaults.json +47 -0
- package/src/declarations.d.ts +40 -0
- package/src/index.css +25 -0
- package/src/index.js +3 -0
- package/src/pages/Content.tsx +30 -0
- package/src/pages/Home.tsx +93 -0
- package/src/pages/Page.tsx +20 -0
- package/src/pages/Search.tsx +53 -0
- package/src/styles/Home.css +3 -0
- package/src/styles/hamburgers.min.css +7 -0
- package/src/styles/navbar.css +21 -0
- package/src/theme.ts +17 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 Enderfarmer
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "info-site-generator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"author": "Enderfarmer",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"types": "declarations.d.ts",
|
|
8
|
+
"repository": "Enderfarmer/info-site-template",
|
|
9
|
+
"private": false,
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"react": "^19.1.0",
|
|
12
|
+
"react-dom": "^19.1.0",
|
|
13
|
+
"react-router-dom": "^7.6.2",
|
|
14
|
+
"react-scripts": "5.0.1"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"start": "react-scripts start",
|
|
18
|
+
"build": "react-scripts build"
|
|
19
|
+
},
|
|
20
|
+
"eslintConfig": {
|
|
21
|
+
"extends": [
|
|
22
|
+
"react-app",
|
|
23
|
+
"react-app/jest"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"browserslist": {
|
|
27
|
+
"production": [
|
|
28
|
+
">0.2%",
|
|
29
|
+
"not dead",
|
|
30
|
+
"not op_mini all"
|
|
31
|
+
],
|
|
32
|
+
"development": [
|
|
33
|
+
"last 1 chrome version",
|
|
34
|
+
"last 1 firefox version",
|
|
35
|
+
"last 1 safari version"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" id="mdi-arrow-left-thin" viewBox="0 0 24 24"><path d="M10.05 16.94V12.94H18.97L19 10.93H10.05V6.94L5.05 11.94Z" /></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="35" height="35" fill="white" viewBox="0 0 24 24"><path d="M14.768 3.96v.001l-.002-.005a9.08 9.08 0 0 0-.218-.779c-.13-.394.21-.8.602-.67.29.096.575.205.855.328l.01.005A10.002 10.002 0 0 1 12 22a10.002 10.002 0 0 1-9.162-5.985l-.004-.01a9.722 9.722 0 0 1-.329-.855c-.13-.392.277-.732.67-.602.257.084.517.157.78.218l.004.002A9 9 0 0 0 14.999 6a9.09 9.09 0 0 0-.231-2.04ZM16.5 6c0 5.799-4.701 10.5-10.5 10.5-.426 0-.847-.026-1.26-.075A8.5 8.5 0 1 0 16.425 4.74c.05.413.075.833.075 1.259Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="35" height="35" fill="black" viewBox="0 0 24 24"><path d="M14.768 3.96v.001l-.002-.005a9.08 9.08 0 0 0-.218-.779c-.13-.394.21-.8.602-.67.29.096.575.205.855.328l.01.005A10.002 10.002 0 0 1 12 22a10.002 10.002 0 0 1-9.162-5.985l-.004-.01a9.722 9.722 0 0 1-.329-.855c-.13-.392.277-.732.67-.602.257.084.517.157.78.218l.004.002A9 9 0 0 0 14.999 6a9.09 9.09 0 0 0-.231-2.04ZM16.5 6c0 5.799-4.701 10.5-10.5 10.5-.426 0-.847-.026-1.26-.075A8.5 8.5 0 1 0 16.425 4.74c.05.413.075.833.075 1.259Z"/></svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<meta name="theme-color" content="#000000" />
|
|
8
|
+
<meta
|
|
9
|
+
name="description"
|
|
10
|
+
content="Web site created using create-react-app"
|
|
11
|
+
/>
|
|
12
|
+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
13
|
+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
14
|
+
<link
|
|
15
|
+
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
|
16
|
+
rel="stylesheet"
|
|
17
|
+
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
|
|
18
|
+
crossorigin="anonymous"
|
|
19
|
+
/>
|
|
20
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
21
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
22
|
+
<link
|
|
23
|
+
href="https://fonts.googleapis.com/css2?family=Nunito:wght@300&display=swap"
|
|
24
|
+
rel="stylesheet"
|
|
25
|
+
/>
|
|
26
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
27
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
28
|
+
<link
|
|
29
|
+
href="https://fonts.googleapis.com/css2?family=Gotu&display=swap"
|
|
30
|
+
rel="stylesheet"
|
|
31
|
+
/>
|
|
32
|
+
<link rel="stylesheet" href="/hamburgers.min.css" />
|
|
33
|
+
<title>React App</title>
|
|
34
|
+
</head>
|
|
35
|
+
<body>
|
|
36
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
37
|
+
<div id="root"></div>
|
|
38
|
+
<script
|
|
39
|
+
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
|
|
40
|
+
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
|
|
41
|
+
crossorigin="anonymous"
|
|
42
|
+
></script>
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="white" width="24" height="24" viewBox="0 0 24 24"><path d="M12 19a7 7 0 1 1 0-14 7 7 0 0 1 0 14Zm0-1.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 1 0 0 11Zm-5.657.157a.75.75 0 0 1 0 1.06l-1.768 1.768a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l1.767-1.768a.75.75 0 0 1 1.061 0ZM3.515 3.515a.75.75 0 0 1 1.06 0l1.768 1.768a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L3.515 4.575a.75.75 0 0 1 0-1.06ZM12 0a.75.75 0 0 1 .75.75v2.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 12 0ZM4 12a.75.75 0 0 1-.75.75H.75a.75.75 0 0 1 0-1.5h2.5A.75.75 0 0 1 4 12Zm8 8a.75.75 0 0 1 .75.75v2.5a.75.75 0 0 1-1.5 0v-2.5A.75.75 0 0 1 12 20Zm12-8a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h2.5A.75.75 0 0 1 24 12Zm-6.343 5.657a.75.75 0 0 1 1.06 0l1.768 1.768a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-1.768-1.767a.75.75 0 0 1 0-1.061Zm2.828-14.142a.75.75 0 0 1 0 1.06l-1.768 1.768a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l1.767-1.768a.75.75 0 0 1 1.061 0Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="black" width="35" height="35" viewBox="0 0 24 24"><path d="M12 19a7 7 0 1 1 0-14 7 7 0 0 1 0 14Zm0-1.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 1 0 0 11Zm-5.657.157a.75.75 0 0 1 0 1.06l-1.768 1.768a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l1.767-1.768a.75.75 0 0 1 1.061 0ZM3.515 3.515a.75.75 0 0 1 1.06 0l1.768 1.768a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L3.515 4.575a.75.75 0 0 1 0-1.06ZM12 0a.75.75 0 0 1 .75.75v2.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 12 0ZM4 12a.75.75 0 0 1-.75.75H.75a.75.75 0 0 1 0-1.5h2.5A.75.75 0 0 1 4 12Zm8 8a.75.75 0 0 1 .75.75v2.5a.75.75 0 0 1-1.5 0v-2.5A.75.75 0 0 1 12 20Zm12-8a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h2.5A.75.75 0 0 1 24 12Zm-6.343 5.657a.75.75 0 0 1 1.06 0l1.768 1.768a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-1.768-1.767a.75.75 0 0 1 0-1.061Zm2.828-14.142a.75.75 0 0 1 0 1.06l-1.768 1.768a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l1.767-1.768a.75.75 0 0 1 1.061 0Z"/></svg>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"short_name": "React App",
|
|
3
|
+
"name": "Create React App Sample",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "favicon.ico",
|
|
7
|
+
"sizes": "64x64 32x32 24x24 16x16",
|
|
8
|
+
"type": "image/x-icon"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"src": "logo192.png",
|
|
12
|
+
"type": "image/png",
|
|
13
|
+
"sizes": "192x192"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"src": "logo512.png",
|
|
17
|
+
"type": "image/png",
|
|
18
|
+
"sizes": "512x512"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"start_url": ".",
|
|
22
|
+
"display": "standalone",
|
|
23
|
+
"theme_color": "#000000",
|
|
24
|
+
"background_color": "#ffffff"
|
|
25
|
+
}
|
package/public/quote.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24"><path d="M3.691 6.292C5.094 4.771 7.217 4 10 4h1v2.819l-.804.161c-1.37.274-2.323.813-2.833 1.604A2.902 2.902 0 0 0 6.925 10H10a1 1 0 0 1 1 1v7c0 1.103-.897 2-2 2H3a1 1 0 0 1-1-1v-5l.003-2.919c-.009-.111-.199-2.741 1.688-4.789zM20 20h-6a1 1 0 0 1-1-1v-5l.003-2.919c-.009-.111-.199-2.741 1.688-4.789C16.094 4.771 18.217 4 21 4h1v2.819l-.804.161c-1.37.274-2.323.813-2.833 1.604A2.902 2.902 0 0 0 17.925 10H21a1 1 0 0 1 1 1v7c0 1.103-.897 2-2 2z"/></svg>
|
package/src/App.tsx
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { HashRouter, Routes, Route } from "react-router-dom";
|
|
2
|
+
import Home from "./pages/Home.tsx";
|
|
3
|
+
import defaults from "./contentDefaults.json";
|
|
4
|
+
import { ThemeContext } from "./theme.ts";
|
|
5
|
+
import Wrapper from "./components/Wrapper.tsx";
|
|
6
|
+
import { SiteData } from "./declarations";
|
|
7
|
+
import "./index.css";
|
|
8
|
+
import Content from "./pages/Content.tsx";
|
|
9
|
+
import PageGen from "./pages/Page.tsx";
|
|
10
|
+
import Search from "./pages/Search.tsx";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The info site generator
|
|
14
|
+
* @param data {SiteData} The data of the site in SiteData format
|
|
15
|
+
* @returns A ready app based on the data provided
|
|
16
|
+
*/
|
|
17
|
+
function SiteGen({ data }: { data: SiteData }) {
|
|
18
|
+
// loop through the possible site data and set defaults
|
|
19
|
+
let dataSecond = data;
|
|
20
|
+
Object.keys(defaults).forEach((key: string) => {
|
|
21
|
+
dataSecond[key] = data[key] || defaults[key];
|
|
22
|
+
});
|
|
23
|
+
let validData: SiteData = dataSecond as unknown as SiteData;
|
|
24
|
+
validData.pages?.forEach((page) => {
|
|
25
|
+
page.withLink = page.withLink ?? true;
|
|
26
|
+
// page.withLink = page.withLink === undefined ? false : page.withLink;
|
|
27
|
+
});
|
|
28
|
+
return (
|
|
29
|
+
<ThemeContext.Provider value={localStorage.getItem("theme") || "light"}>
|
|
30
|
+
<HashRouter>
|
|
31
|
+
<Routes>
|
|
32
|
+
<Route
|
|
33
|
+
index
|
|
34
|
+
element={
|
|
35
|
+
<Wrapper
|
|
36
|
+
data={validData}
|
|
37
|
+
component={<Home data={validData} />}
|
|
38
|
+
/>
|
|
39
|
+
}
|
|
40
|
+
/>
|
|
41
|
+
<Route
|
|
42
|
+
path="all-content"
|
|
43
|
+
element={
|
|
44
|
+
<Wrapper
|
|
45
|
+
data={validData}
|
|
46
|
+
component={<Content data={validData} />}
|
|
47
|
+
/>
|
|
48
|
+
}
|
|
49
|
+
/>
|
|
50
|
+
<Route
|
|
51
|
+
path="search"
|
|
52
|
+
element={
|
|
53
|
+
<Wrapper
|
|
54
|
+
data={validData}
|
|
55
|
+
component={<Search data={validData} />}
|
|
56
|
+
/>
|
|
57
|
+
}
|
|
58
|
+
/>
|
|
59
|
+
{validData.pages?.map((page) => (
|
|
60
|
+
<Route
|
|
61
|
+
element={
|
|
62
|
+
<Wrapper
|
|
63
|
+
data={validData}
|
|
64
|
+
component={<PageGen page={page} />}
|
|
65
|
+
/>
|
|
66
|
+
}
|
|
67
|
+
path={page.slug}
|
|
68
|
+
/>
|
|
69
|
+
))}
|
|
70
|
+
</Routes>
|
|
71
|
+
</HashRouter>
|
|
72
|
+
</ThemeContext.Provider>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default SiteGen;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SiteData } from "../declarations";
|
|
2
|
+
import { useCurrentTheme } from "../theme.ts";
|
|
3
|
+
|
|
4
|
+
export default function Footer({ data }: { data: SiteData }) {
|
|
5
|
+
const [theme] = useCurrentTheme();
|
|
6
|
+
return (
|
|
7
|
+
<footer
|
|
8
|
+
className="bg-gray-800 text-white py-4 m-0"
|
|
9
|
+
style={
|
|
10
|
+
theme === "light"
|
|
11
|
+
? { backgroundColor: data.brandColor }
|
|
12
|
+
: { backgroundColor: data.brandColorDark }
|
|
13
|
+
}
|
|
14
|
+
>
|
|
15
|
+
<div className="container mx-auto">
|
|
16
|
+
<h3>{data.siteTitle}</h3>
|
|
17
|
+
<p className="sm">{data.siteDescription}</p>
|
|
18
|
+
{data.socialMedia && (
|
|
19
|
+
<div>
|
|
20
|
+
Follow us on <br />
|
|
21
|
+
<ul className="d-flex flex-wrap w-100 mw-100 list-unstyled link-underline-opacity-0 link-underline-opactiy-100">
|
|
22
|
+
{Object.entries(data.socialMedia).map(
|
|
23
|
+
([key, value]) => (
|
|
24
|
+
<li className="p-2 m-3" key={key}>
|
|
25
|
+
{value.image && value.imageDark && (
|
|
26
|
+
<img
|
|
27
|
+
src={
|
|
28
|
+
theme === "light"
|
|
29
|
+
? value.image
|
|
30
|
+
: value.imageDark
|
|
31
|
+
}
|
|
32
|
+
alt={key}
|
|
33
|
+
/>
|
|
34
|
+
)}
|
|
35
|
+
<a href={value.href} className="p-1">
|
|
36
|
+
{key}
|
|
37
|
+
</a>
|
|
38
|
+
</li>
|
|
39
|
+
)
|
|
40
|
+
)}
|
|
41
|
+
</ul>
|
|
42
|
+
</div>
|
|
43
|
+
)}
|
|
44
|
+
<div className="text-center">
|
|
45
|
+
© {new Date().getFullYear()} All rights reserved.
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</footer>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { oppositeTheme, useCurrentTheme } from "../theme.ts";
|
|
2
|
+
import { SiteData, Theme } from "../declarations";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Link } from "react-router-dom";
|
|
5
|
+
import "../styles/hamburgers.min.css";
|
|
6
|
+
import "../styles/navbar.css";
|
|
7
|
+
|
|
8
|
+
export default function Navbar({ data }: { data: SiteData }) {
|
|
9
|
+
const [theme, setTheme]: [Theme, Function] = useCurrentTheme();
|
|
10
|
+
const [active, setActive] = useState(false);
|
|
11
|
+
document.documentElement.setAttribute("data-bs-theme", theme);
|
|
12
|
+
return (
|
|
13
|
+
<nav
|
|
14
|
+
className={`navbar border-bottom border-1 border-dark mb-2 d-flex justify-content-between align-items-center ${
|
|
15
|
+
theme === "dark" && "navbar-dark"
|
|
16
|
+
} `}
|
|
17
|
+
style={
|
|
18
|
+
theme === "light"
|
|
19
|
+
? { backgroundColor: data.brandColor }
|
|
20
|
+
: { backgroundColor: data.brandColorDark }
|
|
21
|
+
}
|
|
22
|
+
>
|
|
23
|
+
<Link className="navbar-brand px-2" to="/">
|
|
24
|
+
{data.siteTitle}
|
|
25
|
+
</Link>
|
|
26
|
+
<span>
|
|
27
|
+
<span>
|
|
28
|
+
<button
|
|
29
|
+
className="p-2 border border-0 bg-transparent"
|
|
30
|
+
id="theme-toggle"
|
|
31
|
+
type="button"
|
|
32
|
+
onClick={() => {
|
|
33
|
+
setTheme(oppositeTheme(theme));
|
|
34
|
+
}}
|
|
35
|
+
aria-label="Toggle theme"
|
|
36
|
+
title="Toggle theme"
|
|
37
|
+
>
|
|
38
|
+
<img
|
|
39
|
+
src={
|
|
40
|
+
data.brandColorIsDark || theme === "dark"
|
|
41
|
+
? `/${theme}-theme-white.svg`
|
|
42
|
+
: `/${theme}-theme.svg`
|
|
43
|
+
}
|
|
44
|
+
className="d-inline"
|
|
45
|
+
alt={`${theme} theme`}
|
|
46
|
+
/>
|
|
47
|
+
</button>
|
|
48
|
+
</span>
|
|
49
|
+
<button
|
|
50
|
+
className={`hamburger hamburger--spin ${
|
|
51
|
+
active ? "is-active" : ""
|
|
52
|
+
}`}
|
|
53
|
+
type="button"
|
|
54
|
+
onClick={() => setActive(!active)}
|
|
55
|
+
aria-label="Toggle navigation"
|
|
56
|
+
title="Toggle navigation"
|
|
57
|
+
aria-controls="navbarSupportedContent"
|
|
58
|
+
aria-expanded={active}
|
|
59
|
+
aria-haspopup="true"
|
|
60
|
+
data-bs-toggle="collapse"
|
|
61
|
+
data-bs-target="#navbarSupportedContent"
|
|
62
|
+
>
|
|
63
|
+
<span className="hamburger-box">
|
|
64
|
+
<span
|
|
65
|
+
className={`hamburger-inner ${
|
|
66
|
+
theme === "dark" && "bg-light"
|
|
67
|
+
}`}
|
|
68
|
+
></span>
|
|
69
|
+
</span>
|
|
70
|
+
</button>
|
|
71
|
+
</span>
|
|
72
|
+
<div
|
|
73
|
+
className="collapse navbar-collapse border-top border-1 border-dark"
|
|
74
|
+
id="navbarSupportedContent"
|
|
75
|
+
>
|
|
76
|
+
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
|
|
77
|
+
{data.pages?.map((page) => (
|
|
78
|
+
<li className="nav-item" key={page.slug}>
|
|
79
|
+
<Link className="nav-link" to={page.slug}>
|
|
80
|
+
{page.linkText || page.title}
|
|
81
|
+
</Link>
|
|
82
|
+
</li>
|
|
83
|
+
))}
|
|
84
|
+
{data.customNavLinks?.map((link) => (
|
|
85
|
+
<li className="nav-item" key={link.href}>
|
|
86
|
+
<a
|
|
87
|
+
className="nav-link"
|
|
88
|
+
href={link.href}
|
|
89
|
+
target="_blank"
|
|
90
|
+
rel="noopener noreferrer"
|
|
91
|
+
>
|
|
92
|
+
{link.text}
|
|
93
|
+
</a>
|
|
94
|
+
</li>
|
|
95
|
+
))}
|
|
96
|
+
</ul>
|
|
97
|
+
</div>
|
|
98
|
+
</nav>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SiteData } from "../declarations";
|
|
2
|
+
import Footer from "./Footer.tsx";
|
|
3
|
+
import Navbar from "./Navbar.tsx";
|
|
4
|
+
|
|
5
|
+
export default function Wrapper({
|
|
6
|
+
data,
|
|
7
|
+
component,
|
|
8
|
+
}: {
|
|
9
|
+
data: SiteData;
|
|
10
|
+
component: any;
|
|
11
|
+
}) {
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<Navbar data={data} />
|
|
15
|
+
<div className="container" id="all-content">
|
|
16
|
+
{component}
|
|
17
|
+
</div>
|
|
18
|
+
<Footer data={data} />
|
|
19
|
+
</>
|
|
20
|
+
);
|
|
21
|
+
}
|
package/src/content.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"siteTitle": "My very informational Site",
|
|
3
|
+
"startUpPages": ["Custom Page"],
|
|
4
|
+
"pages": [
|
|
5
|
+
{
|
|
6
|
+
"title": "Custom Page",
|
|
7
|
+
"slug": "custom-page",
|
|
8
|
+
"description": "This is a custom page for the info site.",
|
|
9
|
+
"content": "Welcome to the custom page of the info site!"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"socialMedia": {
|
|
13
|
+
"facebook": ["https://www.facebook.com"],
|
|
14
|
+
"x": ["https://x.com"],
|
|
15
|
+
"instagram": ["https://www.instagram.com"],
|
|
16
|
+
"linkedin": ["https://www.linkedin.com"],
|
|
17
|
+
"youtube": ["https://www.youtube.com"],
|
|
18
|
+
"github": ["https://github.com"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"siteTitle": "Default Title",
|
|
3
|
+
"siteDescription": "Doing something is better than doing nothing.",
|
|
4
|
+
"motto": "Let's <br /> make it juicy!",
|
|
5
|
+
"keywords": ["default"],
|
|
6
|
+
"author": "Default Author",
|
|
7
|
+
"language": "en-US",
|
|
8
|
+
"themeColor": "#ffffff",
|
|
9
|
+
"brandColor": "skyblue",
|
|
10
|
+
"brandColorDark": "#00008B",
|
|
11
|
+
"brandColorIsDark": false,
|
|
12
|
+
"contactEmail": "",
|
|
13
|
+
"commonFont": "Gotu",
|
|
14
|
+
"answeredQuestions": [
|
|
15
|
+
"What is this?",
|
|
16
|
+
"How does it work?",
|
|
17
|
+
"Why should I use it?",
|
|
18
|
+
"What are the benefits?"
|
|
19
|
+
],
|
|
20
|
+
"startUpPages": ["Dummy", "About"],
|
|
21
|
+
"pages": [
|
|
22
|
+
{
|
|
23
|
+
"title": "Dummy",
|
|
24
|
+
"slug": "dummy",
|
|
25
|
+
"description": "This is a dummy page for the default info site.",
|
|
26
|
+
"content": "Welcome to the default info site dummy!"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"title": "About",
|
|
30
|
+
"slug": "about",
|
|
31
|
+
"description": "Learn more about this default info site.",
|
|
32
|
+
"content": "This is the about page of the default info site."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"title": "Contact",
|
|
36
|
+
"slug": "contact",
|
|
37
|
+
"description": "Get in touch with us.",
|
|
38
|
+
"content": "This is the contact page of the default info site."
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"title": "lorem-ipsum",
|
|
42
|
+
"slug": "lorem-ipsum",
|
|
43
|
+
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
44
|
+
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
interface Page {
|
|
2
|
+
title: string;
|
|
3
|
+
shortTitle?: string;
|
|
4
|
+
linkText?: string;
|
|
5
|
+
slug: string;
|
|
6
|
+
content: string;
|
|
7
|
+
description: string;
|
|
8
|
+
withLink?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface SocialMediaLinkWithImage {
|
|
11
|
+
href: string;
|
|
12
|
+
image?: string;
|
|
13
|
+
imageDark?: string;
|
|
14
|
+
}
|
|
15
|
+
type SocialMediaName = string;
|
|
16
|
+
export interface SiteData {
|
|
17
|
+
siteTitle?: string;
|
|
18
|
+
siteDescription?: string;
|
|
19
|
+
motto?: string;
|
|
20
|
+
answeredQuestions?: string[];
|
|
21
|
+
startUpPages?: string[];
|
|
22
|
+
keywords?: string[];
|
|
23
|
+
author?: string;
|
|
24
|
+
language?: string;
|
|
25
|
+
url?: string;
|
|
26
|
+
customNavLinks?: { text: string; href: string }[];
|
|
27
|
+
brandColor?: string;
|
|
28
|
+
brandColorDark?: string;
|
|
29
|
+
brandColorIsDark?: boolean;
|
|
30
|
+
socialMedia?: {
|
|
31
|
+
[key: SocialMediaName]: SocialMediaLinkWithImage;
|
|
32
|
+
};
|
|
33
|
+
contactEmail?: string;
|
|
34
|
+
pages?: Page[];
|
|
35
|
+
}
|
|
36
|
+
type Theme = "light" | "dark";
|
|
37
|
+
declare module "contentDefaults.json" {
|
|
38
|
+
const data: SiteData;
|
|
39
|
+
export default data;
|
|
40
|
+
}
|
package/src/index.css
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
body {
|
|
2
|
+
margin: 0;
|
|
3
|
+
font-family: "Gotu", "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
|
|
4
|
+
"Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
|
5
|
+
-webkit-font-smoothing: antialiased;
|
|
6
|
+
-moz-osx-font-smoothing: grayscale;
|
|
7
|
+
}
|
|
8
|
+
html,
|
|
9
|
+
body,
|
|
10
|
+
#root {
|
|
11
|
+
height: 100%;
|
|
12
|
+
}
|
|
13
|
+
#all-content {
|
|
14
|
+
min-height: 100%;
|
|
15
|
+
}
|
|
16
|
+
code {
|
|
17
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
|
18
|
+
monospace;
|
|
19
|
+
}
|
|
20
|
+
footer a {
|
|
21
|
+
text-decoration: none;
|
|
22
|
+
&:hover {
|
|
23
|
+
text-decoration: underline;
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import { SiteData } from "../declarations";
|
|
3
|
+
|
|
4
|
+
export default function Content({ data }: { data: SiteData }) {
|
|
5
|
+
return (
|
|
6
|
+
<div className="container">
|
|
7
|
+
<h2>{data.siteTitle} content</h2>
|
|
8
|
+
<div className="row">
|
|
9
|
+
{data.pages.map((page, index) => (
|
|
10
|
+
<div key={index} className="col-md-4 mb-4 mx-2">
|
|
11
|
+
<div className="card h-100">
|
|
12
|
+
<div className="card-body">
|
|
13
|
+
<h5 className="card-title">{page.title}</h5>
|
|
14
|
+
<p className="card-text">{page.description}</p>
|
|
15
|
+
{page.withLink && (
|
|
16
|
+
<Link
|
|
17
|
+
to={`/${page.slug}`}
|
|
18
|
+
className="btn btn-primary"
|
|
19
|
+
>
|
|
20
|
+
Read more
|
|
21
|
+
</Link>
|
|
22
|
+
)}
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
))}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import { Page, SiteData } from "../declarations";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import "../styles/Home.css";
|
|
5
|
+
export default function Home({ data }: { data: SiteData }) {
|
|
6
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
7
|
+
return (
|
|
8
|
+
<div>
|
|
9
|
+
<section className="d-flex">
|
|
10
|
+
<div className="w-50 d-flex flex-column justify-content-center align-items-center">
|
|
11
|
+
<h1
|
|
12
|
+
className="fw-bolder center"
|
|
13
|
+
id="hero-title"
|
|
14
|
+
dangerouslySetInnerHTML={{
|
|
15
|
+
__html: data.motto || data.siteTitle,
|
|
16
|
+
}}
|
|
17
|
+
></h1>
|
|
18
|
+
<span>{data.siteDescription}</span>
|
|
19
|
+
</div>
|
|
20
|
+
<div className="w-50 p-2">
|
|
21
|
+
<img
|
|
22
|
+
src="/home-image.jpg"
|
|
23
|
+
alt="Eye-catcher"
|
|
24
|
+
className="w-100"
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
</section>
|
|
28
|
+
<br />
|
|
29
|
+
<section>
|
|
30
|
+
<div className="form-group w-50 d-inline-block me-3">
|
|
31
|
+
<input
|
|
32
|
+
type="search"
|
|
33
|
+
id="search"
|
|
34
|
+
list="searchdata"
|
|
35
|
+
value={searchQuery}
|
|
36
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
37
|
+
className="form-control"
|
|
38
|
+
placeholder="Search for content"
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
<Link
|
|
42
|
+
to={{ pathname: "/search", search: `?q=${searchQuery}` }}
|
|
43
|
+
className="d-inline-block"
|
|
44
|
+
>
|
|
45
|
+
<button className="btn btn-primary p-2">Search</button>
|
|
46
|
+
</Link>
|
|
47
|
+
<datalist id="searchdata">
|
|
48
|
+
{data.pages?.map((page, index) => (
|
|
49
|
+
<option key={index} value={page.title}>
|
|
50
|
+
{page.title}
|
|
51
|
+
</option>
|
|
52
|
+
))}
|
|
53
|
+
</datalist>
|
|
54
|
+
</section>
|
|
55
|
+
<hr />
|
|
56
|
+
<section>
|
|
57
|
+
<h2>We answer these questions and more: </h2>
|
|
58
|
+
<ul>
|
|
59
|
+
{data.answeredQuestions?.map((question, index) => (
|
|
60
|
+
<li key={index}>{question}</li>
|
|
61
|
+
))}
|
|
62
|
+
</ul>
|
|
63
|
+
<Link to="all-content">Descover more content</Link>
|
|
64
|
+
</section>
|
|
65
|
+
<hr />
|
|
66
|
+
<section>
|
|
67
|
+
<h2>Dive in with those pages:</h2>
|
|
68
|
+
<ul>
|
|
69
|
+
{data.startUpPages?.map((page, index) => {
|
|
70
|
+
const pageData: Page | undefined = data.pages.find(
|
|
71
|
+
(p) => p.title === page
|
|
72
|
+
);
|
|
73
|
+
if (!pageData) {
|
|
74
|
+
console.warn(
|
|
75
|
+
`Page with title "${page}" not found in data.pages`
|
|
76
|
+
);
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return (
|
|
80
|
+
<li key={index}>
|
|
81
|
+
{
|
|
82
|
+
<Link to={`/${pageData.slug}`}>
|
|
83
|
+
{pageData.shortTitle || pageData.title}
|
|
84
|
+
</Link>
|
|
85
|
+
}
|
|
86
|
+
</li>
|
|
87
|
+
);
|
|
88
|
+
})}
|
|
89
|
+
</ul>
|
|
90
|
+
</section>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import ArrowBack from "../components/ArrowBack.tsx";
|
|
2
|
+
import { Page } from "../declarations";
|
|
3
|
+
|
|
4
|
+
export default function PageGen({ page }: { page: Page }) {
|
|
5
|
+
return (
|
|
6
|
+
<div className="container mt-3">
|
|
7
|
+
<ArrowBack />
|
|
8
|
+
<h2>{page.title}</h2>
|
|
9
|
+
<blockquote>
|
|
10
|
+
{page.shortTitle || page.title} - {page.description}
|
|
11
|
+
</blockquote>
|
|
12
|
+
<hr />
|
|
13
|
+
<br />
|
|
14
|
+
<div
|
|
15
|
+
className="content"
|
|
16
|
+
dangerouslySetInnerHTML={{ __html: page.content }}
|
|
17
|
+
></div>
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Link, useLocation } from "react-router-dom";
|
|
3
|
+
import { SiteData } from "../declarations";
|
|
4
|
+
|
|
5
|
+
export default function Search({ data }: { data: SiteData }) {
|
|
6
|
+
const searchParams = new URLSearchParams(useLocation().search);
|
|
7
|
+
const query = searchParams.get("q") || "";
|
|
8
|
+
const [searchQuery, setSearchQuery] = useState(query);
|
|
9
|
+
return (
|
|
10
|
+
<div>
|
|
11
|
+
<h1>Search</h1>
|
|
12
|
+
<div className="form-group w-50 d-inline-block me-3">
|
|
13
|
+
<input
|
|
14
|
+
type="search"
|
|
15
|
+
id="search"
|
|
16
|
+
list="search-data"
|
|
17
|
+
value={searchQuery}
|
|
18
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
19
|
+
className="form-control"
|
|
20
|
+
placeholder="Search for content"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
<Link
|
|
24
|
+
to={{ pathname: "/search", search: `?q=${searchQuery}` }}
|
|
25
|
+
className="d-inline-block"
|
|
26
|
+
>
|
|
27
|
+
<button className="btn btn-primary p-2">Search</button>
|
|
28
|
+
</Link>
|
|
29
|
+
<datalist id="search-data">
|
|
30
|
+
{data.pages?.map((page, index) => (
|
|
31
|
+
<option key={index} value={page.title}>
|
|
32
|
+
{page.title}
|
|
33
|
+
</option>
|
|
34
|
+
))}
|
|
35
|
+
</datalist>
|
|
36
|
+
<hr />
|
|
37
|
+
<h2>Results for "{query}"</h2>
|
|
38
|
+
{data.pages?.map((page, index) => {
|
|
39
|
+
if (
|
|
40
|
+
page.title.toLowerCase().includes(searchQuery.toLowerCase())
|
|
41
|
+
)
|
|
42
|
+
return (
|
|
43
|
+
<div key={index} className="mb-3">
|
|
44
|
+
<h3>
|
|
45
|
+
<Link to={page.slug}>{page.title}</Link>
|
|
46
|
+
</h3>
|
|
47
|
+
<p>{page.description}</p>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
})}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Hamburgers
|
|
3
|
+
* @description Tasty CSS-animated hamburgers
|
|
4
|
+
* @author Jonathan Suh @jonsuh
|
|
5
|
+
* @site https://jonsuh.com/hamburgers
|
|
6
|
+
* @link https://github.com/jonsuh/hamburgers
|
|
7
|
+
*/.hamburger{font:inherit;display:inline-block;overflow:visible;margin:0;padding:15px;cursor:pointer;transition-timing-function:linear;transition-duration:.15s;transition-property:opacity,filter;text-transform:none;color:inherit;border:0;background-color:transparent}.hamburger.is-active:hover,.hamburger:hover{opacity:.7}.hamburger.is-active .hamburger-inner,.hamburger.is-active .hamburger-inner:after,.hamburger.is-active .hamburger-inner:before{background-color:#000}.hamburger-box{position:relative;display:inline-block;width:40px;height:24px}.hamburger-inner{top:50%;display:block;margin-top:-2px}.hamburger-inner,.hamburger-inner:after,.hamburger-inner:before{position:absolute;width:40px;height:4px;transition-timing-function:ease;transition-duration:.15s;transition-property:transform;border-radius:4px;background-color:#000}.hamburger-inner:after,.hamburger-inner:before{display:block;content:""}.hamburger-inner:before{top:-10px}.hamburger-inner:after{bottom:-10px}.hamburger--3dx .hamburger-box{perspective:80px}.hamburger--3dx .hamburger-inner{transition:transform .15s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx .hamburger-inner:after,.hamburger--3dx .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx.is-active .hamburger-inner{transform:rotateY(180deg);background-color:transparent!important}.hamburger--3dx.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dx.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dx-r .hamburger-box{perspective:80px}.hamburger--3dx-r .hamburger-inner{transition:transform .15s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx-r .hamburger-inner:after,.hamburger--3dx-r .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx-r.is-active .hamburger-inner{transform:rotateY(-180deg);background-color:transparent!important}.hamburger--3dx-r.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dx-r.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dy .hamburger-box{perspective:80px}.hamburger--3dy .hamburger-inner{transition:transform .15s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy .hamburger-inner:after,.hamburger--3dy .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy.is-active .hamburger-inner{transform:rotateX(-180deg);background-color:transparent!important}.hamburger--3dy.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dy.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dy-r .hamburger-box{perspective:80px}.hamburger--3dy-r .hamburger-inner{transition:transform .15s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy-r .hamburger-inner:after,.hamburger--3dy-r .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy-r.is-active .hamburger-inner{transform:rotateX(180deg);background-color:transparent!important}.hamburger--3dy-r.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dy-r.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dxy .hamburger-box{perspective:80px}.hamburger--3dxy .hamburger-inner{transition:transform .15s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dxy .hamburger-inner:after,.hamburger--3dxy .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dxy.is-active .hamburger-inner{transform:rotateX(180deg) rotateY(180deg);background-color:transparent!important}.hamburger--3dxy.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dxy.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dxy-r .hamburger-box{perspective:80px}.hamburger--3dxy-r .hamburger-inner{transition:transform .15s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dxy-r .hamburger-inner:after,.hamburger--3dxy-r .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dxy-r.is-active .hamburger-inner{transform:rotateX(180deg) rotateY(180deg) rotate(-180deg);background-color:transparent!important}.hamburger--3dxy-r.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dxy-r.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--arrow.is-active .hamburger-inner:before{transform:translate3d(-8px,0,0) rotate(-45deg) scaleX(.7)}.hamburger--arrow.is-active .hamburger-inner:after{transform:translate3d(-8px,0,0) rotate(45deg) scaleX(.7)}.hamburger--arrow-r.is-active .hamburger-inner:before{transform:translate3d(8px,0,0) rotate(45deg) scaleX(.7)}.hamburger--arrow-r.is-active .hamburger-inner:after{transform:translate3d(8px,0,0) rotate(-45deg) scaleX(.7)}.hamburger--arrowalt .hamburger-inner:before{transition:top .1s ease .1s,transform .1s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt .hamburger-inner:after{transition:bottom .1s ease .1s,transform .1s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt.is-active .hamburger-inner:before{top:0;transition:top .1s ease,transform .1s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(-8px,-10px,0) rotate(-45deg) scaleX(.7)}.hamburger--arrowalt.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease,transform .1s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(-8px,10px,0) rotate(45deg) scaleX(.7)}.hamburger--arrowalt-r .hamburger-inner:before{transition:top .1s ease .1s,transform .1s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt-r .hamburger-inner:after{transition:bottom .1s ease .1s,transform .1s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt-r.is-active .hamburger-inner:before{top:0;transition:top .1s ease,transform .1s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(8px,-10px,0) rotate(45deg) scaleX(.7)}.hamburger--arrowalt-r.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease,transform .1s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(8px,10px,0) rotate(-45deg) scaleX(.7)}.hamburger--arrowturn.is-active .hamburger-inner{transform:rotate(-180deg)}.hamburger--arrowturn.is-active .hamburger-inner:before{transform:translate3d(8px,0,0) rotate(45deg) scaleX(.7)}.hamburger--arrowturn.is-active .hamburger-inner:after{transform:translate3d(8px,0,0) rotate(-45deg) scaleX(.7)}.hamburger--arrowturn-r.is-active .hamburger-inner{transform:rotate(-180deg)}.hamburger--arrowturn-r.is-active .hamburger-inner:before{transform:translate3d(-8px,0,0) rotate(-45deg) scaleX(.7)}.hamburger--arrowturn-r.is-active .hamburger-inner:after{transform:translate3d(-8px,0,0) rotate(45deg) scaleX(.7)}.hamburger--boring .hamburger-inner,.hamburger--boring .hamburger-inner:after,.hamburger--boring .hamburger-inner:before{transition-property:none}.hamburger--boring.is-active .hamburger-inner{transform:rotate(45deg)}.hamburger--boring.is-active .hamburger-inner:before{top:0;opacity:0}.hamburger--boring.is-active .hamburger-inner:after{bottom:0;transform:rotate(-90deg)}.hamburger--collapse .hamburger-inner{top:auto;bottom:0;transition-delay:.13s;transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.13s}.hamburger--collapse .hamburger-inner:after{top:-20px;transition:top .2s cubic-bezier(.33333,.66667,.66667,1) .2s,opacity .1s linear}.hamburger--collapse .hamburger-inner:before{transition:top .12s cubic-bezier(.33333,.66667,.66667,1) .2s,transform .13s cubic-bezier(.55,.055,.675,.19)}.hamburger--collapse.is-active .hamburger-inner{transition-delay:.22s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--collapse.is-active .hamburger-inner:after{top:0;transition:top .2s cubic-bezier(.33333,0,.66667,.33333),opacity .1s linear .22s;opacity:0}.hamburger--collapse.is-active .hamburger-inner:before{top:0;transition:top .1s cubic-bezier(.33333,0,.66667,.33333) .16s,transform .13s cubic-bezier(.215,.61,.355,1) .25s;transform:rotate(-90deg)}.hamburger--collapse-r .hamburger-inner{top:auto;bottom:0;transition-delay:.13s;transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.13s}.hamburger--collapse-r .hamburger-inner:after{top:-20px;transition:top .2s cubic-bezier(.33333,.66667,.66667,1) .2s,opacity .1s linear}.hamburger--collapse-r .hamburger-inner:before{transition:top .12s cubic-bezier(.33333,.66667,.66667,1) .2s,transform .13s cubic-bezier(.55,.055,.675,.19)}.hamburger--collapse-r.is-active .hamburger-inner{transition-delay:.22s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:translate3d(0,-10px,0) rotate(45deg)}.hamburger--collapse-r.is-active .hamburger-inner:after{top:0;transition:top .2s cubic-bezier(.33333,0,.66667,.33333),opacity .1s linear .22s;opacity:0}.hamburger--collapse-r.is-active .hamburger-inner:before{top:0;transition:top .1s cubic-bezier(.33333,0,.66667,.33333) .16s,transform .13s cubic-bezier(.215,.61,.355,1) .25s;transform:rotate(90deg)}.hamburger--elastic .hamburger-inner{top:2px;transition-timing-function:cubic-bezier(.68,-.55,.265,1.55);transition-duration:.275s}.hamburger--elastic .hamburger-inner:before{top:10px;transition:opacity .125s ease .275s}.hamburger--elastic .hamburger-inner:after{top:20px;transition:transform .275s cubic-bezier(.68,-.55,.265,1.55)}.hamburger--elastic.is-active .hamburger-inner{transition-delay:75ms;transform:translate3d(0,10px,0) rotate(135deg)}.hamburger--elastic.is-active .hamburger-inner:before{transition-delay:0s;opacity:0}.hamburger--elastic.is-active .hamburger-inner:after{transition-delay:75ms;transform:translate3d(0,-20px,0) rotate(-270deg)}.hamburger--elastic-r .hamburger-inner{top:2px;transition-timing-function:cubic-bezier(.68,-.55,.265,1.55);transition-duration:.275s}.hamburger--elastic-r .hamburger-inner:before{top:10px;transition:opacity .125s ease .275s}.hamburger--elastic-r .hamburger-inner:after{top:20px;transition:transform .275s cubic-bezier(.68,-.55,.265,1.55)}.hamburger--elastic-r.is-active .hamburger-inner{transition-delay:75ms;transform:translate3d(0,10px,0) rotate(-135deg)}.hamburger--elastic-r.is-active .hamburger-inner:before{transition-delay:0s;opacity:0}.hamburger--elastic-r.is-active .hamburger-inner:after{transition-delay:75ms;transform:translate3d(0,-20px,0) rotate(270deg)}.hamburger--emphatic{overflow:hidden}.hamburger--emphatic .hamburger-inner{transition:background-color .125s ease-in .175s}.hamburger--emphatic .hamburger-inner:before{left:0;transition:transform .125s cubic-bezier(.6,.04,.98,.335),top .05s linear .125s,left .125s ease-in .175s}.hamburger--emphatic .hamburger-inner:after{top:10px;right:0;transition:transform .125s cubic-bezier(.6,.04,.98,.335),top .05s linear .125s,right .125s ease-in .175s}.hamburger--emphatic.is-active .hamburger-inner{transition-delay:0s;transition-timing-function:ease-out;background-color:transparent!important}.hamburger--emphatic.is-active .hamburger-inner:before{top:-80px;left:-80px;transition:left .125s ease-out,top .05s linear .125s,transform .125s cubic-bezier(.075,.82,.165,1) .175s;transform:translate3d(80px,80px,0) rotate(45deg)}.hamburger--emphatic.is-active .hamburger-inner:after{top:-80px;right:-80px;transition:right .125s ease-out,top .05s linear .125s,transform .125s cubic-bezier(.075,.82,.165,1) .175s;transform:translate3d(-80px,80px,0) rotate(-45deg)}.hamburger--emphatic-r{overflow:hidden}.hamburger--emphatic-r .hamburger-inner{transition:background-color .125s ease-in .175s}.hamburger--emphatic-r .hamburger-inner:before{left:0;transition:transform .125s cubic-bezier(.6,.04,.98,.335),top .05s linear .125s,left .125s ease-in .175s}.hamburger--emphatic-r .hamburger-inner:after{top:10px;right:0;transition:transform .125s cubic-bezier(.6,.04,.98,.335),top .05s linear .125s,right .125s ease-in .175s}.hamburger--emphatic-r.is-active .hamburger-inner{transition-delay:0s;transition-timing-function:ease-out;background-color:transparent!important}.hamburger--emphatic-r.is-active .hamburger-inner:before{top:80px;left:-80px;transition:left .125s ease-out,top .05s linear .125s,transform .125s cubic-bezier(.075,.82,.165,1) .175s;transform:translate3d(80px,-80px,0) rotate(-45deg)}.hamburger--emphatic-r.is-active .hamburger-inner:after{top:80px;right:-80px;transition:right .125s ease-out,top .05s linear .125s,transform .125s cubic-bezier(.075,.82,.165,1) .175s;transform:translate3d(-80px,-80px,0) rotate(45deg)}.hamburger--minus .hamburger-inner:after,.hamburger--minus .hamburger-inner:before{transition:bottom .08s ease-out 0s,top .08s ease-out 0s,opacity 0s linear}.hamburger--minus.is-active .hamburger-inner:after,.hamburger--minus.is-active .hamburger-inner:before{transition:bottom .08s ease-out,top .08s ease-out,opacity 0s linear .08s;opacity:0}.hamburger--minus.is-active .hamburger-inner:before{top:0}.hamburger--minus.is-active .hamburger-inner:after{bottom:0}.hamburger--slider .hamburger-inner{top:2px}.hamburger--slider .hamburger-inner:before{top:10px;transition-timing-function:ease;transition-duration:.15s;transition-property:transform,opacity}.hamburger--slider .hamburger-inner:after{top:20px}.hamburger--slider.is-active .hamburger-inner{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--slider.is-active .hamburger-inner:before{transform:rotate(-45deg) translate3d(-5.71429px,-6px,0);opacity:0}.hamburger--slider.is-active .hamburger-inner:after{transform:translate3d(0,-20px,0) rotate(-90deg)}.hamburger--slider-r .hamburger-inner{top:2px}.hamburger--slider-r .hamburger-inner:before{top:10px;transition-timing-function:ease;transition-duration:.15s;transition-property:transform,opacity}.hamburger--slider-r .hamburger-inner:after{top:20px}.hamburger--slider-r.is-active .hamburger-inner{transform:translate3d(0,10px,0) rotate(-45deg)}.hamburger--slider-r.is-active .hamburger-inner:before{transform:rotate(45deg) translate3d(5.71429px,-6px,0);opacity:0}.hamburger--slider-r.is-active .hamburger-inner:after{transform:translate3d(0,-20px,0) rotate(90deg)}.hamburger--spin .hamburger-inner{transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.22s}.hamburger--spin .hamburger-inner:before{transition:top .1s ease-in .25s,opacity .1s ease-in}.hamburger--spin .hamburger-inner:after{transition:bottom .1s ease-in .25s,transform .22s cubic-bezier(.55,.055,.675,.19)}.hamburger--spin.is-active .hamburger-inner{transition-delay:.12s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:rotate(225deg)}.hamburger--spin.is-active .hamburger-inner:before{top:0;transition:top .1s ease-out,opacity .1s ease-out .12s;opacity:0}.hamburger--spin.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease-out,transform .22s cubic-bezier(.215,.61,.355,1) .12s;transform:rotate(-90deg)}.hamburger--spin-r .hamburger-inner{transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.22s}.hamburger--spin-r .hamburger-inner:before{transition:top .1s ease-in .25s,opacity .1s ease-in}.hamburger--spin-r .hamburger-inner:after{transition:bottom .1s ease-in .25s,transform .22s cubic-bezier(.55,.055,.675,.19)}.hamburger--spin-r.is-active .hamburger-inner{transition-delay:.12s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:rotate(-225deg)}.hamburger--spin-r.is-active .hamburger-inner:before{top:0;transition:top .1s ease-out,opacity .1s ease-out .12s;opacity:0}.hamburger--spin-r.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease-out,transform .22s cubic-bezier(.215,.61,.355,1) .12s;transform:rotate(90deg)}.hamburger--spring .hamburger-inner{top:2px;transition:background-color 0s linear .13s}.hamburger--spring .hamburger-inner:before{top:10px;transition:top .1s cubic-bezier(.33333,.66667,.66667,1) .2s,transform .13s cubic-bezier(.55,.055,.675,.19)}.hamburger--spring .hamburger-inner:after{top:20px;transition:top .2s cubic-bezier(.33333,.66667,.66667,1) .2s,transform .13s cubic-bezier(.55,.055,.675,.19)}.hamburger--spring.is-active .hamburger-inner{transition-delay:.22s;background-color:transparent!important}.hamburger--spring.is-active .hamburger-inner:before{top:0;transition:top .1s cubic-bezier(.33333,0,.66667,.33333) .15s,transform .13s cubic-bezier(.215,.61,.355,1) .22s;transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--spring.is-active .hamburger-inner:after{top:0;transition:top .2s cubic-bezier(.33333,0,.66667,.33333),transform .13s cubic-bezier(.215,.61,.355,1) .22s;transform:translate3d(0,10px,0) rotate(-45deg)}.hamburger--spring-r .hamburger-inner{top:auto;bottom:0;transition-delay:0s;transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.13s}.hamburger--spring-r .hamburger-inner:after{top:-20px;transition:top .2s cubic-bezier(.33333,.66667,.66667,1) .2s,opacity 0s linear}.hamburger--spring-r .hamburger-inner:before{transition:top .1s cubic-bezier(.33333,.66667,.66667,1) .2s,transform .13s cubic-bezier(.55,.055,.675,.19)}.hamburger--spring-r.is-active .hamburger-inner{transition-delay:.22s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--spring-r.is-active .hamburger-inner:after{top:0;transition:top .2s cubic-bezier(.33333,0,.66667,.33333),opacity 0s linear .22s;opacity:0}.hamburger--spring-r.is-active .hamburger-inner:before{top:0;transition:top .1s cubic-bezier(.33333,0,.66667,.33333) .15s,transform .13s cubic-bezier(.215,.61,.355,1) .22s;transform:rotate(90deg)}.hamburger--stand .hamburger-inner{transition:transform 75ms cubic-bezier(.55,.055,.675,.19) .15s,background-color 0s linear 75ms}.hamburger--stand .hamburger-inner:before{transition:top 75ms ease-in 75ms,transform 75ms cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand .hamburger-inner:after{transition:bottom 75ms ease-in 75ms,transform 75ms cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand.is-active .hamburger-inner{transition:transform 75ms cubic-bezier(.215,.61,.355,1) 0s,background-color 0s linear .15s;transform:rotate(90deg);background-color:transparent!important}.hamburger--stand.is-active .hamburger-inner:before{top:0;transition:top 75ms ease-out .1s,transform 75ms cubic-bezier(.215,.61,.355,1) .15s;transform:rotate(-45deg)}.hamburger--stand.is-active .hamburger-inner:after{bottom:0;transition:bottom 75ms ease-out .1s,transform 75ms cubic-bezier(.215,.61,.355,1) .15s;transform:rotate(45deg)}.hamburger--stand-r .hamburger-inner{transition:transform 75ms cubic-bezier(.55,.055,.675,.19) .15s,background-color 0s linear 75ms}.hamburger--stand-r .hamburger-inner:before{transition:top 75ms ease-in 75ms,transform 75ms cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand-r .hamburger-inner:after{transition:bottom 75ms ease-in 75ms,transform 75ms cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand-r.is-active .hamburger-inner{transition:transform 75ms cubic-bezier(.215,.61,.355,1) 0s,background-color 0s linear .15s;transform:rotate(-90deg);background-color:transparent!important}.hamburger--stand-r.is-active .hamburger-inner:before{top:0;transition:top 75ms ease-out .1s,transform 75ms cubic-bezier(.215,.61,.355,1) .15s;transform:rotate(-45deg)}.hamburger--stand-r.is-active .hamburger-inner:after{bottom:0;transition:bottom 75ms ease-out .1s,transform 75ms cubic-bezier(.215,.61,.355,1) .15s;transform:rotate(45deg)}.hamburger--squeeze .hamburger-inner{transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:75ms}.hamburger--squeeze .hamburger-inner:before{transition:top 75ms ease .12s,opacity 75ms ease}.hamburger--squeeze .hamburger-inner:after{transition:bottom 75ms ease .12s,transform 75ms cubic-bezier(.55,.055,.675,.19)}.hamburger--squeeze.is-active .hamburger-inner{transition-delay:.12s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:rotate(45deg)}.hamburger--squeeze.is-active .hamburger-inner:before{top:0;transition:top 75ms ease,opacity 75ms ease .12s;opacity:0}.hamburger--squeeze.is-active .hamburger-inner:after{bottom:0;transition:bottom 75ms ease,transform 75ms cubic-bezier(.215,.61,.355,1) .12s;transform:rotate(-90deg)}.hamburger--vortex .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transition-duration:.2s}.hamburger--vortex .hamburger-inner:after,.hamburger--vortex .hamburger-inner:before{transition-delay:.1s;transition-timing-function:linear;transition-duration:0s}.hamburger--vortex .hamburger-inner:before{transition-property:top,opacity}.hamburger--vortex .hamburger-inner:after{transition-property:bottom,transform}.hamburger--vortex.is-active .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transform:rotate(765deg)}.hamburger--vortex.is-active .hamburger-inner:after,.hamburger--vortex.is-active .hamburger-inner:before{transition-delay:0s}.hamburger--vortex.is-active .hamburger-inner:before{top:0;opacity:0}.hamburger--vortex.is-active .hamburger-inner:after{bottom:0;transform:rotate(90deg)}.hamburger--vortex-r .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transition-duration:.2s}.hamburger--vortex-r .hamburger-inner:after,.hamburger--vortex-r .hamburger-inner:before{transition-delay:.1s;transition-timing-function:linear;transition-duration:0s}.hamburger--vortex-r .hamburger-inner:before{transition-property:top,opacity}.hamburger--vortex-r .hamburger-inner:after{transition-property:bottom,transform}.hamburger--vortex-r.is-active .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transform:rotate(-765deg)}.hamburger--vortex-r.is-active .hamburger-inner:after,.hamburger--vortex-r.is-active .hamburger-inner:before{transition-delay:0s}.hamburger--vortex-r.is-active .hamburger-inner:before{top:0;opacity:0}.hamburger--vortex-r.is-active .hamburger-inner:after{bottom:0;transform:rotate(-90deg)}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.navbar {
|
|
2
|
+
&.navbar-dark {
|
|
3
|
+
--bs-navbar-color: rgba(255, 255, 255, 0.7);
|
|
4
|
+
}
|
|
5
|
+
.navbar-brand {
|
|
6
|
+
font-family: "Nunito", sans-serif;
|
|
7
|
+
font-optical-sizing: auto;
|
|
8
|
+
font-weight: 300;
|
|
9
|
+
font-style: normal;
|
|
10
|
+
}
|
|
11
|
+
#theme-toggle {
|
|
12
|
+
background-color: transparent;
|
|
13
|
+
border: none;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
}
|
|
16
|
+
.hamburger-inner,
|
|
17
|
+
.hamburger-inner:after,
|
|
18
|
+
.hamburger-inner:before {
|
|
19
|
+
background-color: var(--bs-body-color) !important;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/theme.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext, useContext, useState } from "react";
|
|
2
|
+
import { Theme } from "./declarations";
|
|
3
|
+
|
|
4
|
+
export const ThemeContext = createContext("light");
|
|
5
|
+
export const oppositeTheme = (theme: Theme) => {
|
|
6
|
+
return theme === "light" ? "dark" : "light";
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const useCurrentTheme: () => [Theme, Function] = () => {
|
|
10
|
+
const theme = useContext(ThemeContext);
|
|
11
|
+
const [themeState, setThemeState]: [Theme, Function] = useState(theme);
|
|
12
|
+
const setTheme = (new_theme: Theme) => {
|
|
13
|
+
localStorage.setItem("theme", new_theme);
|
|
14
|
+
setThemeState(new_theme);
|
|
15
|
+
};
|
|
16
|
+
return [themeState, setTheme];
|
|
17
|
+
};
|