polen 0.10.0-next.5 → 0.10.0-next.6
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/build/template/components/ThemeToggle.d.ts +3 -0
- package/build/template/components/ThemeToggle.d.ts.map +1 -0
- package/build/template/components/ThemeToggle.jsx +10 -0
- package/build/template/components/ThemeToggle.jsx.map +1 -0
- package/build/template/contexts/ThemeContext.d.ts +12 -0
- package/build/template/contexts/ThemeContext.d.ts.map +1 -0
- package/build/template/contexts/ThemeContext.jsx +41 -0
- package/build/template/contexts/ThemeContext.jsx.map +1 -0
- package/build/template/routes/root.d.ts.map +1 -1
- package/build/template/routes/root.jsx +15 -9
- package/build/template/routes/root.jsx.map +1 -1
- package/package.json +1 -1
- package/src/template/components/ThemeToggle.tsx +21 -0
- package/src/template/contexts/ThemeContext.tsx +60 -0
- package/src/template/routes/root.tsx +15 -9
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../../src/template/components/ThemeToggle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAK7C,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAe/B,CAAA"}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { MoonIcon, SunIcon } from '@radix-ui/react-icons';
|
2
|
+
import { IconButton } from '@radix-ui/themes';
|
3
|
+
import { useTheme } from "../contexts/ThemeContext.jsx";
|
4
|
+
export const ThemeToggle = () => {
|
5
|
+
const { appearance, toggleTheme } = useTheme();
|
6
|
+
return (<IconButton size="2" variant="ghost" color="gray" onClick={toggleTheme} aria-label={`Switch to ${appearance === 'light' ? 'dark' : 'light'} theme`} style={{ cursor: 'pointer' }}>
|
7
|
+
{appearance === 'light' ? <MoonIcon width="18" height="18"/> : <SunIcon width="18" height="18"/>}
|
8
|
+
</IconButton>);
|
9
|
+
};
|
10
|
+
//# sourceMappingURL=ThemeToggle.jsx.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ThemeToggle.jsx","sourceRoot":"","sources":["../../../src/template/components/ThemeToggle.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAEvD,MAAM,CAAC,MAAM,WAAW,GAAa,GAAG,EAAE;IACxC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE9C,OAAO,CACL,CAAC,UAAU,CACT,IAAI,CAAC,GAAG,CACR,OAAO,CAAC,OAAO,CACf,KAAK,CAAC,MAAM,CACZ,OAAO,CAAC,CAAC,WAAW,CAAC,CACrB,UAAU,CAAC,CAAC,aAAa,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,QAAQ,CAAC,CAC3E,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAE7B;MAAA,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAG,CACpG;IAAA,EAAE,UAAU,CAAC,CACd,CAAA;AACH,CAAC,CAAA"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import type { React } from '#dep/react/index';
|
2
|
+
type ThemeAppearance = 'light' | 'dark';
|
3
|
+
interface ThemeContextValue {
|
4
|
+
appearance: ThemeAppearance;
|
5
|
+
toggleTheme: () => void;
|
6
|
+
}
|
7
|
+
export declare const ThemeProvider: React.FC<{
|
8
|
+
children: React.ReactNode;
|
9
|
+
}>;
|
10
|
+
export declare const useTheme: () => ThemeContextValue;
|
11
|
+
export {};
|
12
|
+
//# sourceMappingURL=ThemeContext.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ThemeContext.d.ts","sourceRoot":"","sources":["../../../src/template/contexts/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAG7C,KAAK,eAAe,GAAG,OAAO,GAAG,MAAM,CAAA;AAEvC,UAAU,iBAAiB;IACzB,UAAU,EAAE,eAAe,CAAA;IAC3B,WAAW,EAAE,MAAM,IAAI,CAAA;CACxB;AAMD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAqCjE,CAAA;AAED,eAAO,MAAM,QAAQ,yBAMpB,CAAA"}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { createContext, useContext, useEffect, useState } from 'react';
|
2
|
+
const ThemeContext = createContext(undefined);
|
3
|
+
const THEME_STORAGE_KEY = 'polen-theme-preference';
|
4
|
+
export const ThemeProvider = ({ children }) => {
|
5
|
+
const [appearance, setAppearance] = useState(() => {
|
6
|
+
// Check if we're in the browser
|
7
|
+
if (typeof window === 'undefined') {
|
8
|
+
return 'light';
|
9
|
+
}
|
10
|
+
// Check localStorage first
|
11
|
+
const stored = localStorage.getItem(THEME_STORAGE_KEY);
|
12
|
+
if (stored === 'light' || stored === 'dark') {
|
13
|
+
return stored;
|
14
|
+
}
|
15
|
+
// Check system preference
|
16
|
+
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
17
|
+
return 'dark';
|
18
|
+
}
|
19
|
+
return 'light';
|
20
|
+
});
|
21
|
+
useEffect(() => {
|
22
|
+
// Persist to localStorage
|
23
|
+
if (typeof window !== 'undefined') {
|
24
|
+
localStorage.setItem(THEME_STORAGE_KEY, appearance);
|
25
|
+
}
|
26
|
+
}, [appearance]);
|
27
|
+
const toggleTheme = () => {
|
28
|
+
setAppearance(prev => prev === 'light' ? 'dark' : 'light');
|
29
|
+
};
|
30
|
+
return (<ThemeContext.Provider value={{ appearance, toggleTheme }}>
|
31
|
+
{children}
|
32
|
+
</ThemeContext.Provider>);
|
33
|
+
};
|
34
|
+
export const useTheme = () => {
|
35
|
+
const context = useContext(ThemeContext);
|
36
|
+
if (!context) {
|
37
|
+
throw new Error('useTheme must be used within a ThemeProvider');
|
38
|
+
}
|
39
|
+
return context;
|
40
|
+
};
|
41
|
+
//# sourceMappingURL=ThemeContext.jsx.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ThemeContext.jsx","sourceRoot":"","sources":["../../../src/template/contexts/ThemeContext.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAStE,MAAM,YAAY,GAAG,aAAa,CAAgC,SAAS,CAAC,CAAA;AAE5E,MAAM,iBAAiB,GAAG,wBAAwB,CAAA;AAElD,MAAM,CAAC,MAAM,aAAa,GAA4C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IACrF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAkB,GAAG,EAAE;QACjE,gCAAgC;QAChC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,2BAA2B;QAC3B,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QACtD,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC5C,OAAO,MAAM,CAAA;QACf,CAAC;QAED,0BAA0B;QAC1B,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC,OAAO,EAAE,CAAC;YACnF,OAAO,MAAM,CAAA;QACf,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,0BAA0B;QAC1B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,YAAY,CAAC,OAAO,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAA;QACrD,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAA;IAEhB,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC,CAAA;IAED,OAAO,CACL,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CACxD;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,YAAY,CAAC,QAAQ,CAAC,CACzB,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE;IAC3B,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;IACxC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAiC1D,eAAO,MAAM,SAAS,mCAuBrB,CAAA;AAuLD,eAAO,MAAM,IAAI;;;;CAIf,CAAA"}
|
@@ -12,13 +12,15 @@ import projectDataNavbar from 'virtual:polen/project/data/navbar.jsonsuper';
|
|
12
12
|
import projectDataPages from 'virtual:polen/project/data/pages.jsonsuper';
|
13
13
|
import { pages } from 'virtual:polen/project/pages.jsx';
|
14
14
|
import { templateVariables } from 'virtual:polen/template/variables';
|
15
|
-
import { Link } from
|
16
|
-
import { Logo } from
|
17
|
-
import { Sidebar } from
|
15
|
+
import { Link } from "../components/Link.jsx";
|
16
|
+
import { Logo } from "../components/Logo.jsx";
|
17
|
+
import { Sidebar } from "../components/sidebar/Sidebar.jsx";
|
18
|
+
import { ThemeToggle } from "../components/ThemeToggle.jsx";
|
19
|
+
import { ThemeProvider, useTheme } from "../contexts/ThemeContext.jsx";
|
18
20
|
import entryClientUrl from '../entry.client.jsx?url';
|
19
|
-
import { changelog } from
|
20
|
-
import { index } from
|
21
|
-
import { reference } from
|
21
|
+
import { changelog } from "./changelog.jsx";
|
22
|
+
import { index } from "./index.jsx";
|
23
|
+
import { reference } from "./reference.jsx";
|
22
24
|
// todo: not needed anymore because not using hono dev vite plugin right?
|
23
25
|
const reactRefreshPreamble = `
|
24
26
|
import RefreshRuntime from "/@react-refresh";
|
@@ -41,7 +43,9 @@ export const Component = () => {
|
|
41
43
|
{/* <meta name='theme-color' content='#000000' /> */}
|
42
44
|
</head>
|
43
45
|
<body style={{ margin: 0 }}>
|
44
|
-
<
|
46
|
+
<ThemeProvider>
|
47
|
+
<Layout />
|
48
|
+
</ThemeProvider>
|
45
49
|
<ScrollRestoration />
|
46
50
|
{import.meta.env.DEV && <script type='module' src={entryClientUrl}></script>}
|
47
51
|
</body>
|
@@ -49,6 +53,7 @@ export const Component = () => {
|
|
49
53
|
};
|
50
54
|
const Layout = () => {
|
51
55
|
const location = useLocation();
|
56
|
+
const { appearance } = useTheme();
|
52
57
|
// Determine if we should show sidebar based on current path
|
53
58
|
const getCurrentNavPathExp = () => {
|
54
59
|
// todo: general path manipulation lib because we are duplicating logic here found in FileRouter
|
@@ -68,13 +73,14 @@ const Layout = () => {
|
|
68
73
|
<LinkReactRouter to='/' style={{ color: `inherit`, textDecoration: `none` }}>
|
69
74
|
<Logo src={logoSrc} title={templateVariables.title} height={30} showTitle={true}/>
|
70
75
|
</LinkReactRouter>
|
71
|
-
<Flex direction='row' gap='4'>
|
76
|
+
<Flex direction='row' gap='4' style={{ flex: 1 }}>
|
72
77
|
{projectDataNavbar.map((item, key) => (<Link key={key} color='gray' to={item.pathExp}>
|
73
78
|
{item.title}
|
74
79
|
</Link>))}
|
75
80
|
</Flex>
|
81
|
+
<ThemeToggle />
|
76
82
|
</Flex>);
|
77
|
-
return (<Theme asChild>
|
83
|
+
return (<Theme asChild appearance={appearance}>
|
78
84
|
<Grid width={{ initial: 'var(--container-4)' }} areas="'header header header header header header header header' 'sidebar sidebar . content content content content content'" rows='min-content auto' columns='repeat(8, 1fr)' gapX='2' my='8' mx='auto'>
|
79
85
|
<style>
|
80
86
|
{`
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"root.jsx","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,cAAc,MAAM,iCAAiC,CAAA;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACrE,OAAO,OAAO,MAAM,uCAAuC,CAAA;AAC3D,OAAO,YAAY,MAAM,sCAAsC,CAAA;AAC/D,OAAO,iBAAiB,MAAM,6CAA6C,CAAA;AAC3E,OAAO,gBAAgB,MAAM,4CAA4C,CAAA;AACzE,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAC3D,OAAO,cAAc,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,yEAAyE;AACzE,MAAM,oBAAoB,GAAG;;;;;;CAM5B,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE;IAC5B,OAAO,CACL,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACb;MAAA,CAAC,IAAI,CACH;QAAA,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAC7E;QAAA,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,CAC3E;QAAA,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EACrB;QAAA,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,qCAAqC,EACnE;QAAA,CAAC,KAAK,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,KAAK,CACvC;QAAA,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,EAAG,CACvE;QAAA,CAAC,qGAAqG,CACtG;QAAA,CAAC,sFAAsF,CACvF;QAAA,CAAC,mDAAmD,CACtD;MAAA,EAAE,IAAI,CACN;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CACzB;QAAA,CAAC,MAAM,CAAC,AAAD,
|
1
|
+
{"version":3,"file":"root.jsx","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
import type { React } from '#dep/react/index'
|
2
|
+
import { MoonIcon, SunIcon } from '@radix-ui/react-icons'
|
3
|
+
import { IconButton } from '@radix-ui/themes'
|
4
|
+
import { useTheme } from '../contexts/ThemeContext.tsx'
|
5
|
+
|
6
|
+
export const ThemeToggle: React.FC = () => {
|
7
|
+
const { appearance, toggleTheme } = useTheme()
|
8
|
+
|
9
|
+
return (
|
10
|
+
<IconButton
|
11
|
+
size="2"
|
12
|
+
variant="ghost"
|
13
|
+
color="gray"
|
14
|
+
onClick={toggleTheme}
|
15
|
+
aria-label={`Switch to ${appearance === 'light' ? 'dark' : 'light'} theme`}
|
16
|
+
style={{ cursor: 'pointer' }}
|
17
|
+
>
|
18
|
+
{appearance === 'light' ? <MoonIcon width="18" height="18" /> : <SunIcon width="18" height="18" />}
|
19
|
+
</IconButton>
|
20
|
+
)
|
21
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import type { React } from '#dep/react/index'
|
2
|
+
import { createContext, useContext, useEffect, useState } from 'react'
|
3
|
+
|
4
|
+
type ThemeAppearance = 'light' | 'dark'
|
5
|
+
|
6
|
+
interface ThemeContextValue {
|
7
|
+
appearance: ThemeAppearance
|
8
|
+
toggleTheme: () => void
|
9
|
+
}
|
10
|
+
|
11
|
+
const ThemeContext = createContext<ThemeContextValue | undefined>(undefined)
|
12
|
+
|
13
|
+
const THEME_STORAGE_KEY = 'polen-theme-preference'
|
14
|
+
|
15
|
+
export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
16
|
+
const [appearance, setAppearance] = useState<ThemeAppearance>(() => {
|
17
|
+
// Check if we're in the browser
|
18
|
+
if (typeof window === 'undefined') {
|
19
|
+
return 'light'
|
20
|
+
}
|
21
|
+
|
22
|
+
// Check localStorage first
|
23
|
+
const stored = localStorage.getItem(THEME_STORAGE_KEY)
|
24
|
+
if (stored === 'light' || stored === 'dark') {
|
25
|
+
return stored
|
26
|
+
}
|
27
|
+
|
28
|
+
// Check system preference
|
29
|
+
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
30
|
+
return 'dark'
|
31
|
+
}
|
32
|
+
|
33
|
+
return 'light'
|
34
|
+
})
|
35
|
+
|
36
|
+
useEffect(() => {
|
37
|
+
// Persist to localStorage
|
38
|
+
if (typeof window !== 'undefined') {
|
39
|
+
localStorage.setItem(THEME_STORAGE_KEY, appearance)
|
40
|
+
}
|
41
|
+
}, [appearance])
|
42
|
+
|
43
|
+
const toggleTheme = () => {
|
44
|
+
setAppearance(prev => prev === 'light' ? 'dark' : 'light')
|
45
|
+
}
|
46
|
+
|
47
|
+
return (
|
48
|
+
<ThemeContext.Provider value={{ appearance, toggleTheme }}>
|
49
|
+
{children}
|
50
|
+
</ThemeContext.Provider>
|
51
|
+
)
|
52
|
+
}
|
53
|
+
|
54
|
+
export const useTheme = () => {
|
55
|
+
const context = useContext(ThemeContext)
|
56
|
+
if (!context) {
|
57
|
+
throw new Error('useTheme must be used within a ThemeProvider')
|
58
|
+
}
|
59
|
+
return context
|
60
|
+
}
|
@@ -13,13 +13,15 @@ import projectDataNavbar from 'virtual:polen/project/data/navbar.jsonsuper'
|
|
13
13
|
import projectDataPages from 'virtual:polen/project/data/pages.jsonsuper'
|
14
14
|
import { pages } from 'virtual:polen/project/pages.jsx'
|
15
15
|
import { templateVariables } from 'virtual:polen/template/variables'
|
16
|
-
import { Link } from '../components/Link.
|
17
|
-
import { Logo } from '../components/Logo.
|
18
|
-
import { Sidebar } from '../components/sidebar/Sidebar.
|
16
|
+
import { Link } from '../components/Link.tsx'
|
17
|
+
import { Logo } from '../components/Logo.tsx'
|
18
|
+
import { Sidebar } from '../components/sidebar/Sidebar.tsx'
|
19
|
+
import { ThemeToggle } from '../components/ThemeToggle.tsx'
|
20
|
+
import { ThemeProvider, useTheme } from '../contexts/ThemeContext.tsx'
|
19
21
|
import entryClientUrl from '../entry.client.jsx?url'
|
20
|
-
import { changelog } from './changelog.
|
21
|
-
import { index } from './index.
|
22
|
-
import { reference } from './reference.
|
22
|
+
import { changelog } from './changelog.tsx'
|
23
|
+
import { index } from './index.tsx'
|
24
|
+
import { reference } from './reference.tsx'
|
23
25
|
|
24
26
|
// todo: not needed anymore because not using hono dev vite plugin right?
|
25
27
|
const reactRefreshPreamble = `
|
@@ -45,7 +47,9 @@ export const Component = () => {
|
|
45
47
|
{/* <meta name='theme-color' content='#000000' /> */}
|
46
48
|
</head>
|
47
49
|
<body style={{ margin: 0 }}>
|
48
|
-
<
|
50
|
+
<ThemeProvider>
|
51
|
+
<Layout />
|
52
|
+
</ThemeProvider>
|
49
53
|
<ScrollRestoration />
|
50
54
|
{import.meta.env.DEV && <script type='module' src={entryClientUrl}></script>}
|
51
55
|
</body>
|
@@ -55,6 +59,7 @@ export const Component = () => {
|
|
55
59
|
|
56
60
|
const Layout = () => {
|
57
61
|
const location = useLocation()
|
62
|
+
const { appearance } = useTheme()
|
58
63
|
|
59
64
|
// Determine if we should show sidebar based on current path
|
60
65
|
const getCurrentNavPathExp = (): string | null => {
|
@@ -88,18 +93,19 @@ const Layout = () => {
|
|
88
93
|
>
|
89
94
|
<Logo src={logoSrc} title={templateVariables.title} height={30} showTitle={true} />
|
90
95
|
</LinkReactRouter>
|
91
|
-
<Flex direction='row' gap='4'>
|
96
|
+
<Flex direction='row' gap='4' style={{ flex: 1 }}>
|
92
97
|
{projectDataNavbar.map((item, key) => (
|
93
98
|
<Link key={key} color='gray' to={item.pathExp}>
|
94
99
|
{item.title}
|
95
100
|
</Link>
|
96
101
|
))}
|
97
102
|
</Flex>
|
103
|
+
<ThemeToggle />
|
98
104
|
</Flex>
|
99
105
|
)
|
100
106
|
|
101
107
|
return (
|
102
|
-
<Theme asChild>
|
108
|
+
<Theme asChild appearance={appearance}>
|
103
109
|
<Grid
|
104
110
|
width={{ initial: 'var(--container-4)' }}
|
105
111
|
areas="'header header header header header header header header' 'sidebar sidebar . content content content content content'"
|