polen 0.10.0-next.6 → 0.10.0-next.8
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/api/content/$$.d.ts +1 -0
- package/build/api/content/$$.d.ts.map +1 -1
- package/build/api/content/$$.js +1 -0
- package/build/api/content/$$.js.map +1 -1
- package/build/api/content/navbar.d.ts +10 -0
- package/build/api/content/navbar.d.ts.map +1 -0
- package/build/api/content/navbar.js +45 -0
- package/build/api/content/navbar.js.map +1 -0
- package/build/api/content/sidebar.d.ts +85 -5
- package/build/api/content/sidebar.d.ts.map +1 -1
- package/build/api/content/sidebar.js +151 -75
- package/build/api/content/sidebar.js.map +1 -1
- package/build/api/vite/plugins/pages.d.ts +1 -4
- package/build/api/vite/plugins/pages.d.ts.map +1 -1
- package/build/api/vite/plugins/pages.js +4 -42
- package/build/api/vite/plugins/pages.js.map +1 -1
- package/build/lib/file-router/scan.d.ts.map +1 -1
- package/build/lib/file-router/scan.js +6 -1
- package/build/lib/file-router/scan.js.map +1 -1
- package/build/sandbox.js +17 -2
- package/build/sandbox.js.map +1 -1
- package/build/template/components/HamburgerMenu.d.ts +9 -0
- package/build/template/components/HamburgerMenu.d.ts.map +1 -0
- package/build/template/components/HamburgerMenu.jsx +53 -0
- package/build/template/components/HamburgerMenu.jsx.map +1 -0
- package/build/template/components/NotFound.d.ts +2 -0
- package/build/template/components/NotFound.d.ts.map +1 -0
- package/build/template/components/NotFound.jsx +26 -0
- package/build/template/components/NotFound.jsx.map +1 -0
- package/build/template/components/ThemeToggle.jsx +2 -2
- package/build/template/routes/root.d.ts.map +1 -1
- package/build/template/routes/root.jsx +40 -30
- package/build/template/routes/root.jsx.map +1 -1
- package/package.json +1 -1
- package/src/api/content/$$.ts +1 -0
- package/src/api/content/navbar.test.ts +55 -0
- package/src/api/content/navbar.ts +61 -0
- package/src/api/content/sidebar.test.ts +297 -0
- package/src/api/content/sidebar.ts +235 -88
- package/src/api/vite/plugins/pages.ts +5 -51
- package/src/lib/file-router/scan.ts +7 -1
- package/src/lib/version-history/index.test.ts +12 -4
- package/src/sandbox.ts +20 -1
- package/src/template/components/HamburgerMenu.tsx +96 -0
- package/src/template/components/NotFound.tsx +28 -0
- package/src/template/components/ThemeToggle.tsx +5 -5
- package/src/template/contexts/ThemeContext.tsx +4 -4
- package/src/template/routes/root.tsx +59 -42
@@ -1,5 +1,6 @@
|
|
1
1
|
import type { Config } from '#api/config/index'
|
2
2
|
import { Content } from '#api/content/$'
|
3
|
+
import { createNavbar } from '#api/content/navbar'
|
3
4
|
import type { NavbarDataRegistry } from '#api/vite/data/navbar'
|
4
5
|
import { polenVirtual } from '#api/vite/vi'
|
5
6
|
import type { Vite } from '#dep/vite/index'
|
@@ -9,7 +10,6 @@ import { debugPolen } from '#singletons/debug'
|
|
9
10
|
import { superjson } from '#singletons/superjson'
|
10
11
|
import mdx from '@mdx-js/rollup'
|
11
12
|
import rehypeShiki from '@shikijs/rehype'
|
12
|
-
import { Tree } from '@wollybeard/kit'
|
13
13
|
import { Arr, Cache, Path, Str } from '@wollybeard/kit'
|
14
14
|
import remarkFrontmatter from 'remark-frontmatter'
|
15
15
|
import remarkGfm from 'remark-gfm'
|
@@ -26,14 +26,10 @@ export interface Options {
|
|
26
26
|
}
|
27
27
|
|
28
28
|
export interface ProjectDataPages {
|
29
|
-
sidebarIndex: SidebarIndex
|
29
|
+
sidebarIndex: Content.SidebarIndex
|
30
30
|
pages: Content.Page[]
|
31
31
|
}
|
32
32
|
|
33
|
-
export interface SidebarIndex {
|
34
|
-
[pathExpression: string]: Content.Sidebar
|
35
|
-
}
|
36
|
-
|
37
33
|
/**
|
38
34
|
* Pages plugin with tree support
|
39
35
|
*/
|
@@ -204,57 +200,15 @@ export const Pages = ({
|
|
204
200
|
const navbarPages = navbarData.get('pages')
|
205
201
|
navbarPages.length = 0 // Clear existing
|
206
202
|
|
207
|
-
|
208
|
-
|
209
|
-
for (const child of scanResult.tree.root.children) {
|
210
|
-
// Now we have Page objects in the tree
|
211
|
-
const page = child.value
|
212
|
-
const pathExp = FileRouter.routeToPathExpression(page.route)
|
213
|
-
|
214
|
-
// Skip hidden pages and index files at root level
|
215
|
-
if (page.metadata.hidden || page.route.logical.path.slice(-1)[0] === 'index') {
|
216
|
-
continue
|
217
|
-
}
|
218
|
-
|
219
|
-
// Only include top-level pages (files directly in pages directory)
|
220
|
-
if (page.route.logical.path.length === 1) {
|
221
|
-
const title = Str.titlizeSlug(page.route.logical.path[0]!)
|
222
|
-
navbarPages.push({
|
223
|
-
// IMPORTANT: Always ensure paths start with '/' for React Router compatibility.
|
224
|
-
pathExp: pathExp.startsWith('/') ? pathExp : '/' + pathExp,
|
225
|
-
title,
|
226
|
-
})
|
227
|
-
}
|
228
|
-
}
|
229
|
-
}
|
203
|
+
const navbarItems = createNavbar(scanResult.list)
|
204
|
+
navbarPages.push(...navbarItems)
|
230
205
|
}
|
231
206
|
|
232
207
|
//
|
233
208
|
// ━━ Build Sidebar
|
234
209
|
//
|
235
210
|
|
236
|
-
const sidebarIndex
|
237
|
-
|
238
|
-
// Build sidebar for each top-level directory using the page tree
|
239
|
-
if (scanResult.tree.root) {
|
240
|
-
Tree.visit(scanResult.tree, (node) => {
|
241
|
-
if (!node.value) return
|
242
|
-
const page = node.value as any
|
243
|
-
// Only process top-level directories (pages with logical path length > 1 indicate nested structure)
|
244
|
-
if (page.route.logical.path.length === 1 && node.children.length > 0) {
|
245
|
-
const topLevelDir = page.route.logical.path[0]!
|
246
|
-
const pathExp = `/${topLevelDir}`
|
247
|
-
|
248
|
-
// Create a subtree for this directory
|
249
|
-
const subtree = Tree.Tree(Tree.Node(page, node.children)) as Tree.Tree<any>
|
250
|
-
|
251
|
-
// Build sidebar using the new page tree builder
|
252
|
-
const sidebar = Content.buildFromPageTree(subtree, [topLevelDir])
|
253
|
-
debug(`Built sidebar for ${pathExp}:`, sidebar)
|
254
|
-
sidebarIndex[pathExp] = sidebar
|
255
|
-
}
|
256
|
-
})
|
257
|
-
}
|
211
|
+
const sidebarIndex = Content.buildSidebarIndex(scanResult)
|
258
212
|
|
259
213
|
//
|
260
214
|
// ━━ Put It All together
|
@@ -87,7 +87,13 @@ export const filePathToRoute = (filePathExpression: string, rootDir: string): Ro
|
|
87
87
|
}
|
88
88
|
|
89
89
|
export const filePathToRouteLogical = (filePath: Path.Parsed): RouteLogical => {
|
90
|
-
const
|
90
|
+
const dirSegments = Str.split(Str.removeSurrounding(filePath.dir, Path.sep), Path.sep)
|
91
|
+
|
92
|
+
// Parse numbered prefixes from directory segments
|
93
|
+
const dirPath = dirSegments.map(segment => {
|
94
|
+
const prefixMatch = Str.match(segment, conventions.numberedPrefix.pattern)
|
95
|
+
return prefixMatch?.groups.name ?? segment
|
96
|
+
})
|
91
97
|
|
92
98
|
// Parse numbered prefix from filename
|
93
99
|
const prefixMatch = Str.match(filePath.name, conventions.numberedPrefix.pattern)
|
@@ -3,6 +3,11 @@ import type { SimpleGit } from 'simple-git'
|
|
3
3
|
import { beforeEach, describe, expect, it, type Mock, vi } from 'vitest'
|
4
4
|
import { VersionHistory } from './index.ts'
|
5
5
|
|
6
|
+
// Mock the simple-git module
|
7
|
+
vi.mock('simple-git', () => ({
|
8
|
+
simpleGit: vi.fn(),
|
9
|
+
}))
|
10
|
+
|
6
11
|
describe('VersionHistory', () => {
|
7
12
|
describe('parseSemver', () => {
|
8
13
|
it('parses standard semver tags', () => {
|
@@ -99,16 +104,19 @@ describe('VersionHistory', () => {
|
|
99
104
|
tag: Mock
|
100
105
|
}
|
101
106
|
|
102
|
-
beforeEach(() => {
|
107
|
+
beforeEach(async () => {
|
108
|
+
vi.clearAllMocks()
|
109
|
+
|
103
110
|
mockGit = {
|
104
111
|
tags: vi.fn(),
|
105
112
|
show: vi.fn(),
|
106
113
|
revparse: vi.fn(),
|
107
114
|
tag: vi.fn(),
|
108
115
|
}
|
109
|
-
|
110
|
-
//
|
111
|
-
|
116
|
+
|
117
|
+
// Mock the simpleGit function to return our mock git instance
|
118
|
+
const { simpleGit } = await import('simple-git')
|
119
|
+
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit)
|
112
120
|
})
|
113
121
|
|
114
122
|
it('returns latest stable and newer prereleases', async () => {
|
package/src/sandbox.ts
CHANGED
@@ -1 +1,20 @@
|
|
1
|
-
|
1
|
+
import { filePathToRouteLogical } from '#lib/file-router/scan'
|
2
|
+
import { Path } from '@wollybeard/kit'
|
3
|
+
|
4
|
+
// Test parsing of numbered directory
|
5
|
+
const testPath1 = Path.parse('a/10_b/index.md')
|
6
|
+
const logical1 = filePathToRouteLogical(testPath1)
|
7
|
+
console.log('Path 1:', testPath1)
|
8
|
+
console.log('Logical 1:', logical1)
|
9
|
+
|
10
|
+
// Test parsing of numbered file
|
11
|
+
const testPath2 = Path.parse('a/10_b/g.md')
|
12
|
+
const logical2 = filePathToRouteLogical(testPath2)
|
13
|
+
console.log('\nPath 2:', testPath2)
|
14
|
+
console.log('Logical 2:', logical2)
|
15
|
+
|
16
|
+
// Test directory structure
|
17
|
+
const testPath3 = Path.parse('a/30_d/index.md')
|
18
|
+
const logical3 = filePathToRouteLogical(testPath3)
|
19
|
+
console.log('\nPath 3:', testPath3)
|
20
|
+
console.log('Logical 3:', logical3)
|
@@ -0,0 +1,96 @@
|
|
1
|
+
import type { Content } from '#api/content/$'
|
2
|
+
import { Cross2Icon, HamburgerMenuIcon } from '@radix-ui/react-icons'
|
3
|
+
import { Box, Flex, IconButton, Text } from '@radix-ui/themes'
|
4
|
+
import { useEffect } from 'react'
|
5
|
+
import { Sidebar } from '../components/sidebar/Sidebar.tsx'
|
6
|
+
|
7
|
+
export interface HamburgerMenuProps {
|
8
|
+
isOpen: boolean
|
9
|
+
onToggle: () => void
|
10
|
+
onClose: () => void
|
11
|
+
sidebarData: Content.Item[]
|
12
|
+
}
|
13
|
+
|
14
|
+
export const HamburgerMenu: React.FC<HamburgerMenuProps> = ({
|
15
|
+
isOpen,
|
16
|
+
onToggle,
|
17
|
+
onClose,
|
18
|
+
sidebarData,
|
19
|
+
}) => {
|
20
|
+
// Prevent body scroll when mobile menu is open
|
21
|
+
useEffect(() => {
|
22
|
+
if (isOpen) {
|
23
|
+
document.body.style.overflow = 'hidden'
|
24
|
+
} else {
|
25
|
+
document.body.style.overflow = ''
|
26
|
+
}
|
27
|
+
|
28
|
+
// Cleanup
|
29
|
+
return () => {
|
30
|
+
document.body.style.overflow = ''
|
31
|
+
}
|
32
|
+
}, [isOpen])
|
33
|
+
|
34
|
+
return (
|
35
|
+
<>
|
36
|
+
{/* Mobile menu button - show on mobile/tablet, hide on desktop */}
|
37
|
+
<Box display={{ initial: 'block', xs: 'block', sm: 'block', md: 'none', lg: 'none', xl: 'none' }}>
|
38
|
+
<IconButton
|
39
|
+
size='2'
|
40
|
+
variant='ghost'
|
41
|
+
onClick={onToggle}
|
42
|
+
aria-label='Toggle navigation menu'
|
43
|
+
>
|
44
|
+
{isOpen ? <Cross2Icon width='18' height='18' /> : <HamburgerMenuIcon width='18' height='18' />}
|
45
|
+
</IconButton>
|
46
|
+
</Box>
|
47
|
+
|
48
|
+
{/* Mobile Sidebar Drawer */}
|
49
|
+
{isOpen && (
|
50
|
+
<>
|
51
|
+
{/* Backdrop */}
|
52
|
+
<Box
|
53
|
+
position='fixed'
|
54
|
+
inset='0'
|
55
|
+
style={{
|
56
|
+
backgroundColor: 'var(--black-a9)',
|
57
|
+
zIndex: 50,
|
58
|
+
}}
|
59
|
+
onClick={onClose}
|
60
|
+
display={{ initial: 'block', xs: 'block', sm: 'block', md: 'none', lg: 'none', xl: 'none' }}
|
61
|
+
/>
|
62
|
+
|
63
|
+
{/* Drawer */}
|
64
|
+
<Box
|
65
|
+
position='fixed'
|
66
|
+
top='0'
|
67
|
+
left='0'
|
68
|
+
bottom='0'
|
69
|
+
width='280px'
|
70
|
+
style={{
|
71
|
+
backgroundColor: 'var(--color-background)',
|
72
|
+
boxShadow: 'var(--shadow-6)',
|
73
|
+
zIndex: 100,
|
74
|
+
overflowY: 'auto',
|
75
|
+
}}
|
76
|
+
p='4'
|
77
|
+
display={{ initial: 'block', xs: 'block', sm: 'block', md: 'none', lg: 'none', xl: 'none' }}
|
78
|
+
>
|
79
|
+
<Flex justify='between' align='center' mb='4'>
|
80
|
+
<Text size='5' weight='bold'>Navigation</Text>
|
81
|
+
<IconButton
|
82
|
+
size='2'
|
83
|
+
variant='ghost'
|
84
|
+
onClick={onClose}
|
85
|
+
aria-label='Close navigation menu'
|
86
|
+
>
|
87
|
+
<Cross2Icon width='18' height='18' />
|
88
|
+
</IconButton>
|
89
|
+
</Flex>
|
90
|
+
<Sidebar data={sidebarData} />
|
91
|
+
</Box>
|
92
|
+
</>
|
93
|
+
)}
|
94
|
+
</>
|
95
|
+
)
|
96
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import { Box, Button, Flex, Heading, Text } from '@radix-ui/themes'
|
2
|
+
import { Link as LinkReactRouter } from 'react-router'
|
3
|
+
|
4
|
+
export const NotFound: React.FC = () => {
|
5
|
+
return (
|
6
|
+
<Flex direction='column' align='center' gap='6' style={{ textAlign: `center`, paddingTop: `4rem` }}>
|
7
|
+
<Heading size='9' style={{ color: `var(--gray-12)` }}>404</Heading>
|
8
|
+
<Box>
|
9
|
+
<Heading size='5' mb='2'>Page Not Found</Heading>
|
10
|
+
<Text size='3' color='gray'>
|
11
|
+
The page you're looking for doesn't exist or has been moved.
|
12
|
+
</Text>
|
13
|
+
</Box>
|
14
|
+
<Flex gap='3'>
|
15
|
+
<LinkReactRouter to='/'>
|
16
|
+
<Button variant='soft' size='3'>
|
17
|
+
Go Home
|
18
|
+
</Button>
|
19
|
+
</LinkReactRouter>
|
20
|
+
<LinkReactRouter to='/reference'>
|
21
|
+
<Button variant='outline' size='3'>
|
22
|
+
View API Reference
|
23
|
+
</Button>
|
24
|
+
</LinkReactRouter>
|
25
|
+
</Flex>
|
26
|
+
</Flex>
|
27
|
+
)
|
28
|
+
}
|
@@ -8,14 +8,14 @@ export const ThemeToggle: React.FC = () => {
|
|
8
8
|
|
9
9
|
return (
|
10
10
|
<IconButton
|
11
|
-
size=
|
12
|
-
variant=
|
13
|
-
color=
|
11
|
+
size='2'
|
12
|
+
variant='ghost'
|
13
|
+
color='gray'
|
14
14
|
onClick={toggleTheme}
|
15
15
|
aria-label={`Switch to ${appearance === 'light' ? 'dark' : 'light'} theme`}
|
16
16
|
style={{ cursor: 'pointer' }}
|
17
17
|
>
|
18
|
-
{appearance === 'light' ? <MoonIcon width=
|
18
|
+
{appearance === 'light' ? <MoonIcon width='18' height='18' /> : <SunIcon width='18' height='18' />}
|
19
19
|
</IconButton>
|
20
20
|
)
|
21
|
-
}
|
21
|
+
}
|
@@ -18,18 +18,18 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ childre
|
|
18
18
|
if (typeof window === 'undefined') {
|
19
19
|
return 'light'
|
20
20
|
}
|
21
|
-
|
21
|
+
|
22
22
|
// Check localStorage first
|
23
23
|
const stored = localStorage.getItem(THEME_STORAGE_KEY)
|
24
24
|
if (stored === 'light' || stored === 'dark') {
|
25
25
|
return stored
|
26
26
|
}
|
27
|
-
|
27
|
+
|
28
28
|
// Check system preference
|
29
29
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
30
30
|
return 'dark'
|
31
31
|
}
|
32
|
-
|
32
|
+
|
33
33
|
return 'light'
|
34
34
|
})
|
35
35
|
|
@@ -57,4 +57,4 @@ export const useTheme = () => {
|
|
57
57
|
throw new Error('useTheme must be used within a ThemeProvider')
|
58
58
|
}
|
59
59
|
return context
|
60
|
-
}
|
60
|
+
}
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import { assetUrl } from '#api/utils/asset-url/index'
|
2
1
|
import type { ReactRouter } from '#dep/react-router/index'
|
3
2
|
import { createRoute } from '#lib/react-router-aid/react-router-aid'
|
4
|
-
import { Box,
|
3
|
+
import { Box, Grid } from '@radix-ui/themes'
|
5
4
|
import { Flex, Theme } from '@radix-ui/themes'
|
6
5
|
import radixStylesUrl from '@radix-ui/themes/styles.css?url'
|
7
6
|
import { Arr } from '@wollybeard/kit'
|
7
|
+
import { useEffect, useState } from 'react'
|
8
8
|
import { Link as LinkReactRouter } from 'react-router'
|
9
9
|
import { Outlet, ScrollRestoration, useLocation } from 'react-router'
|
10
10
|
import logoSrc from 'virtual:polen/project/assets/logo.svg'
|
@@ -13,8 +13,10 @@ 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 { HamburgerMenu } from '../components/HamburgerMenu.tsx'
|
16
17
|
import { Link } from '../components/Link.tsx'
|
17
18
|
import { Logo } from '../components/Logo.tsx'
|
19
|
+
import { NotFound } from '../components/NotFound.tsx'
|
18
20
|
import { Sidebar } from '../components/sidebar/Sidebar.tsx'
|
19
21
|
import { ThemeToggle } from '../components/ThemeToggle.tsx'
|
20
22
|
import { ThemeProvider, useTheme } from '../contexts/ThemeContext.tsx'
|
@@ -60,6 +62,12 @@ export const Component = () => {
|
|
60
62
|
const Layout = () => {
|
61
63
|
const location = useLocation()
|
62
64
|
const { appearance } = useTheme()
|
65
|
+
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
66
|
+
|
67
|
+
// Close mobile menu on route change
|
68
|
+
useEffect(() => {
|
69
|
+
setMobileMenuOpen(false)
|
70
|
+
}, [location.pathname])
|
63
71
|
|
64
72
|
// Determine if we should show sidebar based on current path
|
65
73
|
const getCurrentNavPathExp = (): string | null => {
|
@@ -80,18 +88,30 @@ const Layout = () => {
|
|
80
88
|
<Flex
|
81
89
|
gridArea={'header'}
|
82
90
|
align='center'
|
83
|
-
gap='8'
|
91
|
+
gap={{ initial: '4', md: '8' }}
|
84
92
|
pb='4'
|
85
|
-
mb='8'
|
93
|
+
mb={{ initial: '4', md: '8' }}
|
86
94
|
style={{
|
87
95
|
borderBottom: `1px solid var(--gray-3)`,
|
88
96
|
}}
|
89
97
|
>
|
98
|
+
{/* Mobile menu - only show when sidebar exists */}
|
99
|
+
{isShowSidebar && (
|
100
|
+
<HamburgerMenu
|
101
|
+
isOpen={mobileMenuOpen}
|
102
|
+
onToggle={() => setMobileMenuOpen(!mobileMenuOpen)}
|
103
|
+
onClose={() => setMobileMenuOpen(false)}
|
104
|
+
sidebarData={sidebar.items}
|
105
|
+
/>
|
106
|
+
)}
|
107
|
+
|
90
108
|
<LinkReactRouter
|
91
109
|
to='/'
|
92
110
|
style={{ color: `inherit`, textDecoration: `none` }}
|
93
111
|
>
|
94
|
-
<
|
112
|
+
<Box display={{ initial: 'block', md: 'block' }}>
|
113
|
+
<Logo src={logoSrc} title={templateVariables.title} height={30} showTitle={true} />
|
114
|
+
</Box>
|
95
115
|
</LinkReactRouter>
|
96
116
|
<Flex direction='row' gap='4' style={{ flex: 1 }}>
|
97
117
|
{projectDataNavbar.map((item, key) => (
|
@@ -107,16 +127,36 @@ const Layout = () => {
|
|
107
127
|
return (
|
108
128
|
<Theme asChild appearance={appearance}>
|
109
129
|
<Grid
|
110
|
-
width={{ initial: 'var(--container-4)' }}
|
111
|
-
|
130
|
+
width={{ initial: '100%', sm: '100%', md: 'var(--container-4)' }}
|
131
|
+
maxWidth='100vw'
|
132
|
+
areas={{
|
133
|
+
initial: "'header' 'content'",
|
134
|
+
sm: "'header' 'content'",
|
135
|
+
md:
|
136
|
+
"'header header header header header header header header' 'sidebar sidebar . content content content content content'",
|
137
|
+
}}
|
112
138
|
rows='min-content auto'
|
113
|
-
columns='repeat(8, 1fr)'
|
114
|
-
gapX='2'
|
115
|
-
my='8'
|
139
|
+
columns={{ initial: '1fr', sm: '1fr', md: 'repeat(8, 1fr)' }}
|
140
|
+
gapX={{ initial: '0', sm: '0', md: '2' }}
|
141
|
+
my={{ initial: '0', sm: '0', md: '8' }}
|
116
142
|
mx='auto'
|
143
|
+
px={{ initial: '4', sm: '4', md: '0' }}
|
144
|
+
py={{ initial: '4', sm: '4', md: '0' }}
|
117
145
|
>
|
118
146
|
<style>
|
119
147
|
{`
|
148
|
+
/* Responsive container fixes */
|
149
|
+
@media (max-width: 768px) {
|
150
|
+
body {
|
151
|
+
overflow-x: hidden;
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
/* Ensure proper centering on all screen sizes */
|
156
|
+
.rt-Grid {
|
157
|
+
box-sizing: border-box;
|
158
|
+
}
|
159
|
+
|
120
160
|
/* Shiki code blocks */
|
121
161
|
pre.shiki {
|
122
162
|
margin: 1rem 0;
|
@@ -150,15 +190,18 @@ const Layout = () => {
|
|
150
190
|
`}
|
151
191
|
</style>
|
152
192
|
{header}
|
193
|
+
|
194
|
+
{/* Desktop Sidebar */}
|
153
195
|
{isShowSidebar && (
|
154
|
-
<
|
196
|
+
<Box
|
197
|
+
display={{ initial: 'none', xs: 'none', sm: 'none', md: 'block' }}
|
155
198
|
gridColumn='1 / 3'
|
156
199
|
gridRow='2 / auto'
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
/>
|
200
|
+
>
|
201
|
+
<Sidebar data={sidebar.items} />
|
202
|
+
</Box>
|
161
203
|
)}
|
204
|
+
|
162
205
|
<Box gridArea='content / content / auto / 8'>
|
163
206
|
<Outlet />
|
164
207
|
</Box>
|
@@ -195,36 +238,10 @@ if (PROJECT_DATA.schema) {
|
|
195
238
|
//
|
196
239
|
//
|
197
240
|
|
198
|
-
const NotFoundComponent = () => {
|
199
|
-
return (
|
200
|
-
<Flex direction='column' align='center' gap='6' style={{ textAlign: `center`, paddingTop: `4rem` }}>
|
201
|
-
<Heading size='9' style={{ color: `var(--gray-12)` }}>404</Heading>
|
202
|
-
<Box>
|
203
|
-
<Heading size='5' mb='2'>Page Not Found</Heading>
|
204
|
-
<Text size='3' color='gray'>
|
205
|
-
The page you're looking for doesn't exist or has been moved.
|
206
|
-
</Text>
|
207
|
-
</Box>
|
208
|
-
<Flex gap='3'>
|
209
|
-
<LinkReactRouter to='/'>
|
210
|
-
<Button variant='soft' size='3'>
|
211
|
-
Go Home
|
212
|
-
</Button>
|
213
|
-
</LinkReactRouter>
|
214
|
-
<LinkReactRouter to='/reference'>
|
215
|
-
<Button variant='outline' size='3'>
|
216
|
-
View API Reference
|
217
|
-
</Button>
|
218
|
-
</LinkReactRouter>
|
219
|
-
</Flex>
|
220
|
-
</Flex>
|
221
|
-
)
|
222
|
-
}
|
223
|
-
|
224
241
|
const notFoundRoute = createRoute({
|
225
242
|
id: `*_not_found`,
|
226
243
|
path: `*`,
|
227
|
-
Component:
|
244
|
+
Component: NotFound,
|
228
245
|
handle: {
|
229
246
|
statusCode: 404,
|
230
247
|
},
|