polen 0.10.0-next.5 → 0.10.0-next.7

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.
Files changed (54) hide show
  1. package/build/api/content/$$.d.ts +1 -0
  2. package/build/api/content/$$.d.ts.map +1 -1
  3. package/build/api/content/$$.js +1 -0
  4. package/build/api/content/$$.js.map +1 -1
  5. package/build/api/content/navbar.d.ts +10 -0
  6. package/build/api/content/navbar.d.ts.map +1 -0
  7. package/build/api/content/navbar.js +45 -0
  8. package/build/api/content/navbar.js.map +1 -0
  9. package/build/api/content/sidebar.d.ts +85 -5
  10. package/build/api/content/sidebar.d.ts.map +1 -1
  11. package/build/api/content/sidebar.js +151 -75
  12. package/build/api/content/sidebar.js.map +1 -1
  13. package/build/api/vite/plugins/pages.d.ts +1 -4
  14. package/build/api/vite/plugins/pages.d.ts.map +1 -1
  15. package/build/api/vite/plugins/pages.js +4 -42
  16. package/build/api/vite/plugins/pages.js.map +1 -1
  17. package/build/lib/file-router/scan.d.ts.map +1 -1
  18. package/build/lib/file-router/scan.js +6 -1
  19. package/build/lib/file-router/scan.js.map +1 -1
  20. package/build/sandbox.js +17 -2
  21. package/build/sandbox.js.map +1 -1
  22. package/build/template/components/HamburgerMenu.d.ts +9 -0
  23. package/build/template/components/HamburgerMenu.d.ts.map +1 -0
  24. package/build/template/components/HamburgerMenu.jsx +53 -0
  25. package/build/template/components/HamburgerMenu.jsx.map +1 -0
  26. package/build/template/components/NotFound.d.ts +2 -0
  27. package/build/template/components/NotFound.d.ts.map +1 -0
  28. package/build/template/components/NotFound.jsx +26 -0
  29. package/build/template/components/NotFound.jsx.map +1 -0
  30. package/build/template/components/ThemeToggle.d.ts +3 -0
  31. package/build/template/components/ThemeToggle.d.ts.map +1 -0
  32. package/build/template/components/ThemeToggle.jsx +10 -0
  33. package/build/template/components/ThemeToggle.jsx.map +1 -0
  34. package/build/template/contexts/ThemeContext.d.ts +12 -0
  35. package/build/template/contexts/ThemeContext.d.ts.map +1 -0
  36. package/build/template/contexts/ThemeContext.jsx +41 -0
  37. package/build/template/contexts/ThemeContext.jsx.map +1 -0
  38. package/build/template/routes/root.d.ts.map +1 -1
  39. package/build/template/routes/root.jsx +55 -39
  40. package/build/template/routes/root.jsx.map +1 -1
  41. package/package.json +1 -1
  42. package/src/api/content/$$.ts +1 -0
  43. package/src/api/content/navbar.test.ts +55 -0
  44. package/src/api/content/navbar.ts +61 -0
  45. package/src/api/content/sidebar.test.ts +297 -0
  46. package/src/api/content/sidebar.ts +235 -88
  47. package/src/api/vite/plugins/pages.ts +5 -51
  48. package/src/lib/file-router/scan.ts +7 -1
  49. package/src/sandbox.ts +20 -1
  50. package/src/template/components/HamburgerMenu.tsx +96 -0
  51. package/src/template/components/NotFound.tsx +28 -0
  52. package/src/template/components/ThemeToggle.tsx +21 -0
  53. package/src/template/contexts/ThemeContext.tsx +60 -0
  54. package/src/template/routes/root.tsx +74 -51
@@ -59,7 +59,12 @@ export const filePathToRoute = (filePathExpression, rootDir) => {
59
59
  };
60
60
  };
61
61
  export const filePathToRouteLogical = (filePath) => {
62
- const dirPath = Str.split(Str.removeSurrounding(filePath.dir, Path.sep), Path.sep);
62
+ const dirSegments = Str.split(Str.removeSurrounding(filePath.dir, Path.sep), Path.sep);
63
+ // Parse numbered prefixes from directory segments
64
+ const dirPath = dirSegments.map(segment => {
65
+ const prefixMatch = Str.match(segment, conventions.numberedPrefix.pattern);
66
+ return prefixMatch?.groups.name ?? segment;
67
+ });
63
68
  // Parse numbered prefix from filename
64
69
  const prefixMatch = Str.match(filePath.name, conventions.numberedPrefix.pattern);
65
70
  const order = prefixMatch ? parseInt(prefixMatch.groups.order, 10) : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/lib/file-router/scan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/lib/file-router/scan.ts"],"names":[],"mappings":"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"}
package/build/sandbox.js CHANGED
@@ -1,3 +1,18 @@
1
- export {};
2
- // Sandbox file for temporary testing
1
+ import { filePathToRouteLogical } from '#lib/file-router/scan';
2
+ import { Path } from '@wollybeard/kit';
3
+ // Test parsing of numbered directory
4
+ const testPath1 = Path.parse('a/10_b/index.md');
5
+ const logical1 = filePathToRouteLogical(testPath1);
6
+ console.log('Path 1:', testPath1);
7
+ console.log('Logical 1:', logical1);
8
+ // Test parsing of numbered file
9
+ const testPath2 = Path.parse('a/10_b/g.md');
10
+ const logical2 = filePathToRouteLogical(testPath2);
11
+ console.log('\nPath 2:', testPath2);
12
+ console.log('Logical 2:', logical2);
13
+ // Test directory structure
14
+ const testPath3 = Path.parse('a/30_d/index.md');
15
+ const logical3 = filePathToRouteLogical(testPath3);
16
+ console.log('\nPath 3:', testPath3);
17
+ console.log('Logical 3:', logical3);
3
18
  //# sourceMappingURL=sandbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":";AAAA,qCAAqC"}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEtC,qCAAqC;AACrC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;AAC/C,MAAM,QAAQ,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;AACjC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AAEnC,gCAAgC;AAChC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;AAC3C,MAAM,QAAQ,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;AACnC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AAEnC,2BAA2B;AAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;AAC/C,MAAM,QAAQ,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;AACnC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ import type { Content } from '#api/content/$';
2
+ export interface HamburgerMenuProps {
3
+ isOpen: boolean;
4
+ onToggle: () => void;
5
+ onClose: () => void;
6
+ sidebarData: Content.Item[];
7
+ }
8
+ export declare const HamburgerMenu: React.FC<HamburgerMenuProps>;
9
+ //# sourceMappingURL=HamburgerMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HamburgerMenu.d.ts","sourceRoot":"","sources":["../../../src/template/components/HamburgerMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAM7C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,CAAA;CAC5B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkFtD,CAAA"}
@@ -0,0 +1,53 @@
1
+ import { Cross2Icon, HamburgerMenuIcon } from '@radix-ui/react-icons';
2
+ import { Box, Flex, IconButton, Text } from '@radix-ui/themes';
3
+ import { useEffect } from 'react';
4
+ import { Sidebar } from "../components/sidebar/Sidebar.jsx";
5
+ export const HamburgerMenu = ({ isOpen, onToggle, onClose, sidebarData, }) => {
6
+ // Prevent body scroll when mobile menu is open
7
+ useEffect(() => {
8
+ if (isOpen) {
9
+ document.body.style.overflow = 'hidden';
10
+ }
11
+ else {
12
+ document.body.style.overflow = '';
13
+ }
14
+ // Cleanup
15
+ return () => {
16
+ document.body.style.overflow = '';
17
+ };
18
+ }, [isOpen]);
19
+ return (<>
20
+ {/* Mobile menu button - show on mobile/tablet, hide on desktop */}
21
+ <Box display={{ initial: 'block', xs: 'block', sm: 'block', md: 'none', lg: 'none', xl: 'none' }}>
22
+ <IconButton size='2' variant='ghost' onClick={onToggle} aria-label='Toggle navigation menu'>
23
+ {isOpen ? <Cross2Icon width='18' height='18'/> : <HamburgerMenuIcon width='18' height='18'/>}
24
+ </IconButton>
25
+ </Box>
26
+
27
+ {/* Mobile Sidebar Drawer */}
28
+ {isOpen && (<>
29
+ {/* Backdrop */}
30
+ <Box position='fixed' inset='0' style={{
31
+ backgroundColor: 'var(--black-a9)',
32
+ zIndex: 50,
33
+ }} onClick={onClose} display={{ initial: 'block', xs: 'block', sm: 'block', md: 'none', lg: 'none', xl: 'none' }}/>
34
+
35
+ {/* Drawer */}
36
+ <Box position='fixed' top='0' left='0' bottom='0' width='280px' style={{
37
+ backgroundColor: 'var(--color-background)',
38
+ boxShadow: 'var(--shadow-6)',
39
+ zIndex: 100,
40
+ overflowY: 'auto',
41
+ }} p='4' display={{ initial: 'block', xs: 'block', sm: 'block', md: 'none', lg: 'none', xl: 'none' }}>
42
+ <Flex justify='between' align='center' mb='4'>
43
+ <Text size='5' weight='bold'>Navigation</Text>
44
+ <IconButton size='2' variant='ghost' onClick={onClose} aria-label='Close navigation menu'>
45
+ <Cross2Icon width='18' height='18'/>
46
+ </IconButton>
47
+ </Flex>
48
+ <Sidebar data={sidebarData}/>
49
+ </Box>
50
+ </>)}
51
+ </>);
52
+ };
53
+ //# sourceMappingURL=HamburgerMenu.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HamburgerMenu.jsx","sourceRoot":"","sources":["../../../src/template/components/HamburgerMenu.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const NotFound: React.FC;
2
+ //# sourceMappingURL=NotFound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotFound.d.ts","sourceRoot":"","sources":["../../../src/template/components/NotFound.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAwB5B,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { Box, Button, Flex, Heading, Text } from '@radix-ui/themes';
2
+ import { Link as LinkReactRouter } from 'react-router';
3
+ export const NotFound = () => {
4
+ return (<Flex direction='column' align='center' gap='6' style={{ textAlign: `center`, paddingTop: `4rem` }}>
5
+ <Heading size='9' style={{ color: `var(--gray-12)` }}>404</Heading>
6
+ <Box>
7
+ <Heading size='5' mb='2'>Page Not Found</Heading>
8
+ <Text size='3' color='gray'>
9
+ The page you're looking for doesn't exist or has been moved.
10
+ </Text>
11
+ </Box>
12
+ <Flex gap='3'>
13
+ <LinkReactRouter to='/'>
14
+ <Button variant='soft' size='3'>
15
+ Go Home
16
+ </Button>
17
+ </LinkReactRouter>
18
+ <LinkReactRouter to='/reference'>
19
+ <Button variant='outline' size='3'>
20
+ View API Reference
21
+ </Button>
22
+ </LinkReactRouter>
23
+ </Flex>
24
+ </Flex>);
25
+ };
26
+ //# sourceMappingURL=NotFound.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotFound.jsx","sourceRoot":"","sources":["../../../src/template/components/NotFound.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,cAAc,CAAA;AAEtD,MAAM,CAAC,MAAM,QAAQ,GAAa,GAAG,EAAE;IACrC,OAAO,CACL,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CACjG;MAAA,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,CAClE;MAAA,CAAC,GAAG,CACF;QAAA,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAChD;QAAA,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CACzB;;QACF,EAAE,IAAI,CACR;MAAA,EAAE,GAAG,CACL;MAAA,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CACX;QAAA,CAAC,eAAe,CAAC,EAAE,CAAC,GAAG,CACrB;UAAA,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAC7B;;UACF,EAAE,MAAM,CACV;QAAA,EAAE,eAAe,CACjB;QAAA,CAAC,eAAe,CAAC,EAAE,CAAC,YAAY,CAC9B;UAAA,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAChC;;UACF,EAAE,MAAM,CACV;QAAA,EAAE,eAAe,CACnB;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { React } from '#dep/react/index';
2
+ export declare const ThemeToggle: React.FC;
3
+ //# sourceMappingURL=ThemeToggle.d.ts.map
@@ -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;AA+B1D,eAAO,MAAM,SAAS,mCAqBrB,CAAA;AAqLD,eAAO,MAAM,IAAI;;;;CAIf,CAAA"}
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAoC1D,eAAO,MAAM,SAAS,mCAuBrB,CAAA;AAsMD,eAAO,MAAM,IAAI;;;;CAIf,CAAA"}
@@ -1,9 +1,9 @@
1
- import { assetUrl } from '#api/utils/asset-url/index';
2
1
  import { createRoute } from '#lib/react-router-aid/react-router-aid';
3
- import { Box, Button, Grid, Heading, Text } from '@radix-ui/themes';
2
+ import { Box, Grid } from '@radix-ui/themes';
4
3
  import { Flex, Theme } from '@radix-ui/themes';
5
4
  import radixStylesUrl from '@radix-ui/themes/styles.css?url';
6
5
  import { Arr } from '@wollybeard/kit';
6
+ import { useEffect, useState } from 'react';
7
7
  import { Link as LinkReactRouter } from 'react-router';
8
8
  import { Outlet, ScrollRestoration, useLocation } from 'react-router';
9
9
  import logoSrc from 'virtual:polen/project/assets/logo.svg';
@@ -12,13 +12,17 @@ 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 '../components/Link.jsx';
16
- import { Logo } from '../components/Logo.jsx';
17
- import { Sidebar } from '../components/sidebar/Sidebar.jsx';
15
+ import { HamburgerMenu } from "../components/HamburgerMenu.jsx";
16
+ import { Link } from "../components/Link.jsx";
17
+ import { Logo } from "../components/Logo.jsx";
18
+ import { NotFound } from "../components/NotFound.jsx";
19
+ import { Sidebar } from "../components/sidebar/Sidebar.jsx";
20
+ import { ThemeToggle } from "../components/ThemeToggle.jsx";
21
+ import { ThemeProvider, useTheme } from "../contexts/ThemeContext.jsx";
18
22
  import entryClientUrl from '../entry.client.jsx?url';
19
- import { changelog } from './changelog.jsx';
20
- import { index } from './index.jsx';
21
- import { reference } from './reference.jsx';
23
+ import { changelog } from "./changelog.jsx";
24
+ import { index } from "./index.jsx";
25
+ import { reference } from "./reference.jsx";
22
26
  // todo: not needed anymore because not using hono dev vite plugin right?
23
27
  const reactRefreshPreamble = `
24
28
  import RefreshRuntime from "/@react-refresh";
@@ -41,7 +45,9 @@ export const Component = () => {
41
45
  {/* <meta name='theme-color' content='#000000' /> */}
42
46
  </head>
43
47
  <body style={{ margin: 0 }}>
44
- <Layout />
48
+ <ThemeProvider>
49
+ <Layout />
50
+ </ThemeProvider>
45
51
  <ScrollRestoration />
46
52
  {import.meta.env.DEV && <script type='module' src={entryClientUrl}></script>}
47
53
  </body>
@@ -49,6 +55,12 @@ export const Component = () => {
49
55
  };
50
56
  const Layout = () => {
51
57
  const location = useLocation();
58
+ const { appearance } = useTheme();
59
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
60
+ // Close mobile menu on route change
61
+ useEffect(() => {
62
+ setMobileMenuOpen(false);
63
+ }, [location.pathname]);
52
64
  // Determine if we should show sidebar based on current path
53
65
  const getCurrentNavPathExp = () => {
54
66
  // todo: general path manipulation lib because we are duplicating logic here found in FileRouter
@@ -62,22 +74,44 @@ const Layout = () => {
62
74
  const currentNavPathExp = getCurrentNavPathExp();
63
75
  const sidebar = currentNavPathExp && projectDataPages.sidebarIndex[currentNavPathExp];
64
76
  const isShowSidebar = sidebar && sidebar.items.length > 0;
65
- const header = (<Flex gridArea={'header'} align='center' gap='8' pb='4' mb='8' style={{
77
+ const header = (<Flex gridArea={'header'} align='center' gap={{ initial: '4', md: '8' }} pb='4' mb={{ initial: '4', md: '8' }} style={{
66
78
  borderBottom: `1px solid var(--gray-3)`,
67
79
  }}>
80
+ {/* Mobile menu - only show when sidebar exists */}
81
+ {isShowSidebar && (<HamburgerMenu isOpen={mobileMenuOpen} onToggle={() => setMobileMenuOpen(!mobileMenuOpen)} onClose={() => setMobileMenuOpen(false)} sidebarData={sidebar.items}/>)}
82
+
68
83
  <LinkReactRouter to='/' style={{ color: `inherit`, textDecoration: `none` }}>
69
- <Logo src={logoSrc} title={templateVariables.title} height={30} showTitle={true}/>
84
+ <Box display={{ initial: 'block', md: 'block' }}>
85
+ <Logo src={logoSrc} title={templateVariables.title} height={30} showTitle={true}/>
86
+ </Box>
70
87
  </LinkReactRouter>
71
- <Flex direction='row' gap='4'>
88
+ <Flex direction='row' gap='4' style={{ flex: 1 }}>
72
89
  {projectDataNavbar.map((item, key) => (<Link key={key} color='gray' to={item.pathExp}>
73
90
  {item.title}
74
91
  </Link>))}
75
92
  </Flex>
93
+ <ThemeToggle />
76
94
  </Flex>);
77
- return (<Theme asChild>
78
- <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'>
95
+ return (<Theme asChild appearance={appearance}>
96
+ <Grid width={{ initial: '100%', sm: '100%', md: 'var(--container-4)' }} maxWidth='100vw' areas={{
97
+ initial: "'header' 'content'",
98
+ sm: "'header' 'content'",
99
+ md: "'header header header header header header header header' 'sidebar sidebar . content content content content content'",
100
+ }} rows='min-content auto' columns={{ initial: '1fr', sm: '1fr', md: 'repeat(8, 1fr)' }} gapX={{ initial: '0', sm: '0', md: '2' }} my={{ initial: '0', sm: '0', md: '8' }} mx='auto' px={{ initial: '4', sm: '4', md: '0' }} py={{ initial: '4', sm: '4', md: '0' }}>
79
101
  <style>
80
102
  {`
103
+ /* Responsive container fixes */
104
+ @media (max-width: 768px) {
105
+ body {
106
+ overflow-x: hidden;
107
+ }
108
+ }
109
+
110
+ /* Ensure proper centering on all screen sizes */
111
+ .rt-Grid {
112
+ box-sizing: border-box;
113
+ }
114
+
81
115
  /* Shiki code blocks */
82
116
  pre.shiki {
83
117
  margin: 1rem 0;
@@ -111,7 +145,12 @@ const Layout = () => {
111
145
  `}
112
146
  </style>
113
147
  {header}
114
- {isShowSidebar && (<Sidebar gridColumn='1 / 3' gridRow='2 / auto' data={sidebar.items}/>)}
148
+
149
+ {/* Desktop Sidebar */}
150
+ {isShowSidebar && (<Box display={{ initial: 'none', xs: 'none', sm: 'none', md: 'block' }} gridColumn='1 / 3' gridRow='2 / auto'>
151
+ <Sidebar data={sidebar.items}/>
152
+ </Box>)}
153
+
115
154
  <Box gridArea='content / content / auto / 8'>
116
155
  <Outlet />
117
156
  </Box>
@@ -142,33 +181,10 @@ if (PROJECT_DATA.schema) {
142
181
  //
143
182
  //
144
183
  //
145
- const NotFoundComponent = () => {
146
- return (<Flex direction='column' align='center' gap='6' style={{ textAlign: `center`, paddingTop: `4rem` }}>
147
- <Heading size='9' style={{ color: `var(--gray-12)` }}>404</Heading>
148
- <Box>
149
- <Heading size='5' mb='2'>Page Not Found</Heading>
150
- <Text size='3' color='gray'>
151
- The page you're looking for doesn't exist or has been moved.
152
- </Text>
153
- </Box>
154
- <Flex gap='3'>
155
- <LinkReactRouter to='/'>
156
- <Button variant='soft' size='3'>
157
- Go Home
158
- </Button>
159
- </LinkReactRouter>
160
- <LinkReactRouter to='/reference'>
161
- <Button variant='outline' size='3'>
162
- View API Reference
163
- </Button>
164
- </LinkReactRouter>
165
- </Flex>
166
- </Flex>);
167
- };
168
184
  const notFoundRoute = createRoute({
169
185
  id: `*_not_found`,
170
186
  path: `*`,
171
- Component: NotFoundComponent,
187
+ Component: NotFound,
172
188
  handle: {
173
189
  statusCode: 404,
174
190
  },
@@ -1 +1 @@
1
- {"version":3,"file":"root.jsx","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"root.jsx","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polen",
3
- "version": "0.10.0-next.5",
3
+ "version": "0.10.0-next.7",
4
4
  "type": "module",
5
5
  "description": "A framework for delightful GraphQL developer portals",
6
6
  "author": {
@@ -1,4 +1,5 @@
1
1
  export * from './metadata.ts'
2
+ export * from './navbar.ts'
2
3
  export * from './page.ts'
3
4
  export * from './scan.ts'
4
5
  export * from './sidebar.ts'
@@ -0,0 +1,55 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { createNavbar } from './navbar.ts'
3
+ import type { Page } from './page.ts'
4
+
5
+ const createPage = (path: string[], fileName = 'index', hidden = false): Page => ({
6
+ route: {
7
+ id: path.join('/'),
8
+ parentId: path.length > 1 ? path.slice(0, -1).join('/') : null,
9
+ logical: { path },
10
+ file: {
11
+ path: {
12
+ absolute: { root: '/', dir: `/pages/${path.join('/')}`, base: `${fileName}.md`, ext: '.md', name: fileName },
13
+ relative: { root: '', dir: path.join('/'), base: `${fileName}.md`, ext: '.md', name: fileName },
14
+ },
15
+ },
16
+ },
17
+ metadata: { description: undefined, hidden },
18
+ })
19
+
20
+ describe('createNavbar', () => {
21
+ it('returns empty for empty input', () => {
22
+ expect(createNavbar([])).toEqual([])
23
+ })
24
+
25
+ it('excludes hidden pages', () => {
26
+ const pages = [createPage(['visible'], 'index', false), createPage(['hidden'], 'index', true)]
27
+ const result = createNavbar(pages)
28
+ expect(result).toEqual([{ pathExp: '/visible', title: 'Visible' }])
29
+ })
30
+
31
+ it('includes directories with index pages', () => {
32
+ const pages = [createPage(['guide'], 'index'), createPage(['guide', 'intro'], 'intro')]
33
+ const result = createNavbar(pages)
34
+ expect(result).toEqual([{ pathExp: '/guide', title: 'Guide' }])
35
+ })
36
+
37
+ it('excludes directories without index pages', () => {
38
+ const pages = [createPage(['guide', 'intro'], 'intro')]
39
+ const result = createNavbar(pages)
40
+ expect(result).toEqual([])
41
+ })
42
+
43
+ it('includes single top-level pages', () => {
44
+ const pages = [createPage(['about'], 'about')]
45
+ const result = createNavbar(pages)
46
+ expect(result).toEqual([{ pathExp: '/about', title: 'About' }])
47
+ })
48
+
49
+ it('sorts results alphabetically', () => {
50
+ const pages = [createPage(['zebra'], 'zebra'), createPage(['alpha'], 'alpha')]
51
+ const result = createNavbar(pages)
52
+ expect(result[0]!.title).toBe('Alpha')
53
+ expect(result[1]!.title).toBe('Zebra')
54
+ })
55
+ })
@@ -0,0 +1,61 @@
1
+ import { Str } from '@wollybeard/kit'
2
+ import type { Page } from './page.ts'
3
+
4
+ export interface NavbarItem {
5
+ pathExp: string
6
+ title: string
7
+ }
8
+
9
+ /**
10
+ * Generate navbar items from a list of pages
11
+ */
12
+ export const createNavbar = (pages: Page[]): NavbarItem[] => {
13
+ const navbarItems: NavbarItem[] = []
14
+
15
+ // Group pages by their top-level directory/segment
16
+ const topLevelGroups = new Map<string, Page[]>()
17
+
18
+ pages.forEach(page => {
19
+ // Skip hidden pages
20
+ if (page.metadata.hidden) return
21
+
22
+ const firstSegment = page.route.logical.path[0]
23
+ if (firstSegment) {
24
+ if (!topLevelGroups.has(firstSegment)) {
25
+ topLevelGroups.set(firstSegment, [])
26
+ }
27
+ topLevelGroups.get(firstSegment)!.push(page)
28
+ }
29
+ })
30
+
31
+ // Add each top-level group to navbar
32
+ topLevelGroups.forEach((pages, segment) => {
33
+ // For directories, check if there's an index page
34
+ const indexPage = pages.find(p =>
35
+ p.route.logical.path.length === 1
36
+ && p.route.file.path.relative.name === 'index'
37
+ )
38
+
39
+ // For single non-index files at top level
40
+ const singlePage = pages.length === 1 && pages[0]!.route.logical.path.length === 1
41
+ && pages[0]!.route.file.path.relative.name !== 'index'
42
+
43
+ // Include in navbar if:
44
+ // 1. It's a directory with an index page, OR
45
+ // 2. It's a single top-level page (not index)
46
+ if (indexPage || singlePage) {
47
+ const title = Str.titlizeSlug(segment)
48
+ const pathExp = `/${segment}`
49
+
50
+ navbarItems.push({
51
+ pathExp,
52
+ title,
53
+ })
54
+ }
55
+ })
56
+
57
+ // Sort navbar items alphabetically for consistency
58
+ navbarItems.sort((a, b) => a.title.localeCompare(b.title))
59
+
60
+ return navbarItems
61
+ }