@ramme-io/create-app 1.2.1 → 1.2.2

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 (89) hide show
  1. package/package.json +1 -2
  2. package/template/package.json +41 -0
  3. package/template/pkg.json +1 -1
  4. package/template/src/App.tsx +62 -31
  5. package/template/src/components/AIChatWidget.tsx +2 -2
  6. package/template/src/components/AppHeader.tsx +2 -2
  7. package/template/src/components/AutoForm.tsx +13 -0
  8. package/template/src/{pages/styleguide → components}/NotFound.tsx +1 -1
  9. package/template/src/components/PageTitleUpdater.tsx +2 -2
  10. package/template/src/components/ProtectedRoute.tsx +18 -1
  11. package/template/src/components/ScrollToTop.tsx +19 -0
  12. package/template/src/config/app.manifest.ts +3 -1
  13. package/template/src/{core → config}/component-registry.tsx +1 -1
  14. package/template/src/config/navigation.ts +1 -1
  15. package/template/src/data/mock-charts.ts +32 -28
  16. package/template/src/{components → engine/renderers}/DynamicBlock.tsx +27 -7
  17. package/template/src/{pages → engine/renderers}/DynamicPage.tsx +23 -4
  18. package/template/src/{contexts → engine/runtime}/MqttContext.tsx +25 -11
  19. package/template/src/{contexts → engine/runtime}/SitemapContext.tsx +1 -1
  20. package/template/src/{core → engine/runtime}/data-seeder.ts +15 -5
  21. package/template/src/{hooks → engine/runtime}/useAction.ts +19 -8
  22. package/template/src/{hooks → engine/runtime}/useCrudLocalStorage.ts +27 -8
  23. package/template/src/{hooks → engine/runtime}/useDataQuery.ts +15 -1
  24. package/template/src/engine/runtime/useSignal.ts +51 -0
  25. package/template/src/{generated/hooks.ts → engine/runtime/useSignalStore.ts} +35 -8
  26. package/template/src/{hooks → engine/runtime}/useWorkflowEngine.ts +34 -13
  27. package/template/src/{core → engine/types}/manifest-types.ts +35 -3
  28. package/template/src/{types → engine/validation}/schema.ts +17 -0
  29. package/template/src/{pages → features/ai/pages}/AiChat.tsx +1 -1
  30. package/template/src/features/auth/AuthContext.tsx +118 -0
  31. package/template/src/features/auth/pages/AuthLayout.tsx +55 -0
  32. package/template/src/features/auth/pages/LoginPage.tsx +106 -0
  33. package/template/src/features/auth/pages/SignupPage.tsx +96 -0
  34. package/template/src/{blocks → features/datagrid}/SmartTable.tsx +4 -6
  35. package/template/src/{pages → features/onboarding/pages}/Welcome.tsx +0 -1
  36. package/template/src/features/overview/index.ts +1 -0
  37. package/template/src/features/overview/pages/OverviewPage.tsx +127 -0
  38. package/template/src/{pages → features/playground/pages}/AccountingLedgerPage.tsx +1 -1
  39. package/template/src/{pages/prototypes → features/playground/pages}/ItemSelectorPage.tsx +1 -1
  40. package/template/src/{pages/settings → features/settings/pages}/BillingPage.tsx +1 -1
  41. package/template/src/features/settings/pages/ProfilePage.tsx +153 -0
  42. package/template/src/{pages/settings → features/settings/pages}/TeamPage.tsx +1 -1
  43. package/template/src/features/styleguide/Styleguide.tsx +75 -0
  44. package/template/src/features/users/components/UserDrawer.tsx +138 -0
  45. package/template/src/features/users/index.ts +2 -0
  46. package/template/src/features/users/pages/UsersPage.tsx +151 -0
  47. package/template/src/index.css +1 -1
  48. package/template/src/main.tsx +3 -3
  49. package/template/src/templates/dashboard/DashboardLayout.tsx +75 -106
  50. package/template/src/templates/dashboard/dashboard.sitemap.ts +26 -22
  51. package/template/src/templates/docs/DocsLayout.tsx +49 -38
  52. package/template/src/templates/docs/docs.sitemap.ts +22 -34
  53. package/template/src/templates/settings/SettingsLayout.tsx +83 -143
  54. package/template/src/templates/settings/settings.sitemap.ts +6 -6
  55. package/template/vite.config.ts +12 -9
  56. package/template/src/adaptors/.gitkeep +0 -0
  57. package/template/src/components/LocalSideNav.tsx +0 -120
  58. package/template/src/components/PageWithSideNav.tsx +0 -69
  59. package/template/src/config/dashboard.layout.ts +0 -110
  60. package/template/src/contexts/AuthContext.tsx +0 -64
  61. package/template/src/data/mockUsers.ts +0 -18
  62. package/template/src/hooks/useSignal.ts +0 -83
  63. package/template/src/layouts/DataLayout.tsx +0 -37
  64. package/template/src/layouts/SideNavLayout.tsx +0 -28
  65. package/template/src/pages/Dashboard.tsx +0 -60
  66. package/template/src/pages/DataGridPage.tsx +0 -184
  67. package/template/src/pages/LoginPage.tsx +0 -58
  68. package/template/src/pages/settings/ProfilePage.tsx +0 -10
  69. package/template/src/pages/styleguide/Styleguide.tsx +0 -40
  70. package/template/src/templates/docs/pages/Introduction.tsx +0 -13
  71. package/template/src/types/signal.ts +0 -23
  72. /package/template/src/{core → engine/renderers}/route-generator.tsx +0 -0
  73. /package/template/src/{core → engine/types}/sitemap-entry.ts +0 -0
  74. /package/template/src/{pages → features}/GenericContentPage.tsx +0 -0
  75. /package/template/src/{hooks → features/assistant}/useMockChat.ts +0 -0
  76. /package/template/src/{components/dev → features/developer}/GhostOverlay.tsx +0 -0
  77. /package/template/src/{hooks → features/developer}/useDevTools.ts +0 -0
  78. /package/template/src/{pages → features}/styleguide/sections/charts/ChartsSection.tsx +0 -0
  79. /package/template/src/{pages → features}/styleguide/sections/colors/ColorsSection.tsx +0 -0
  80. /package/template/src/{pages → features}/styleguide/sections/elements/ElementsSection.tsx +0 -0
  81. /package/template/src/{pages → features}/styleguide/sections/feedback/FeedbackSection.tsx +0 -0
  82. /package/template/src/{pages → features}/styleguide/sections/forms/FormsSection.tsx +0 -0
  83. /package/template/src/{pages → features}/styleguide/sections/icons/IconsSection.tsx +0 -0
  84. /package/template/src/{pages → features}/styleguide/sections/layout/LayoutSection.tsx +0 -0
  85. /package/template/src/{pages → features}/styleguide/sections/navigation/NavigationSection.tsx +0 -0
  86. /package/template/src/{pages → features}/styleguide/sections/tables/TablesSection.tsx +0 -0
  87. /package/template/src/{pages → features}/styleguide/sections/templates/TemplatesSection.tsx +0 -0
  88. /package/template/src/{pages → features}/styleguide/sections/theming/ThemingSection.tsx +0 -0
  89. /package/template/src/{pages → features}/styleguide/sections/utilities/UtilitiesSection.tsx +0 -0
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Outlet, NavLink } from 'react-router-dom';
3
3
  import { docsSitemap } from './docs.sitemap';
4
- import { SitemapProvider } from '../../contexts/SitemapContext';
4
+ import { SitemapProvider } from '../../engine/runtime/SitemapContext';
5
5
  import AppHeader from '../../components/AppHeader';
6
6
  import AppFooter from '../../components/AppFooter';
7
7
  import { Icon } from '@ramme-io/ui';
@@ -9,44 +9,55 @@ import PageTitleUpdater from '../../components/PageTitleUpdater';
9
9
 
10
10
  const DocsLayout: React.FC = () => {
11
11
  return (
12
- // Add a wrapper div with the correct theme classes
13
- <div className="bg-background text-foreground">
14
- <div className="flex flex-col min-h-screen">
15
- <AppHeader />
16
- <main className="flex-grow">
17
- <div className="bg-background border-b border-border sticky top-16 z-30">
18
- <nav className="container mx-auto px-4">
19
- <ul className="flex items-center gap-4 h-12">
20
- {docsSitemap.map((item) => (
21
- <li key={item.id}>
22
- <NavLink
23
- to={item.path || ''}
24
- end={!item.children || item.children.length === 0}
25
- className={({ isActive }) =>
26
- `flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md transition-colors ${
27
- isActive
28
- ? 'bg-primary text-primary-foreground'
29
- : 'text-muted-foreground hover:bg-muted'
30
- }`
31
- }
32
- >
33
- {item.icon && <Icon name={item.icon} className="h-4 w-4" />}
34
- <span>{item.title}</span>
35
- </NavLink>
36
- </li>
37
- ))}
38
- </ul>
39
- </nav>
40
- </div>
41
- <div className="container mx-auto p-4 md:p-8">
42
- <SitemapProvider value={docsSitemap}>
43
- <PageTitleUpdater />
12
+ <div className="bg-background text-foreground min-h-screen flex flex-col font-sans">
13
+ <AppHeader />
14
+
15
+ <main className="flex-grow flex flex-col">
16
+ {/* --- TOP NAVIGATION BAR --- */}
17
+ <div className="bg-card border-b border-border sticky top-16 z-30 w-full">
18
+ <nav className="w-full px-6">
19
+ <ul className="flex items-center gap-6 h-12">
20
+ {docsSitemap.map((item) => (
21
+ <li key={item.id}>
22
+ <NavLink
23
+ to={item.path || ''}
24
+ end={!item.children || item.children.length === 0}
25
+ className={({ isActive }) =>
26
+ `flex items-center gap-2 px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${
27
+ isActive
28
+ ? 'bg-primary/10 text-primary'
29
+ : 'text-muted-foreground hover:text-foreground hover:bg-muted/50'
30
+ }`
31
+ }
32
+ >
33
+ {item.icon && <Icon name={item.icon} className="h-4 w-4" />}
34
+ <span>{item.title}</span>
35
+ </NavLink>
36
+ </li>
37
+ ))}
38
+ </ul>
39
+ </nav>
40
+ </div>
41
+
42
+ {/* --- MAIN CONTENT WRAPPER --- */}
43
+ <div className="w-full flex-1 flex flex-col">
44
+ <SitemapProvider value={docsSitemap}>
45
+ <PageTitleUpdater />
46
+
47
+ {/* Page Content */}
48
+ <div className="flex-1">
44
49
  <Outlet />
45
- </SitemapProvider>
46
- </div>
47
- </main>
48
- <AppFooter />
49
- </div>
50
+ </div>
51
+
52
+ {/* Footer - Now part of the content flow */}
53
+ <div className="border-t border-border mt-auto w-full bg-background">
54
+ <div className="max-w-7xl mx-auto px-6">
55
+ <AppFooter />
56
+ </div>
57
+ </div>
58
+ </SitemapProvider>
59
+ </div>
60
+ </main>
50
61
  </div>
51
62
  );
52
63
  };
@@ -1,34 +1,33 @@
1
- import { type SitemapEntry } from '../../core/sitemap-entry';
1
+ import { type SitemapEntry } from '../../engine/types/sitemap-entry';
2
2
 
3
- // Component Imports from the main /pages directory
4
- import Dashboard from '../../pages/Dashboard';
5
- import AiChat from '../../pages/AiChat';
6
- import DataGridPage from '../../pages/DataGridPage';
7
- import AccountingLedgerPage from '../../pages/AccountingLedgerPage';
8
- import Styleguide from '../../pages/styleguide/Styleguide';
9
- import DataLayout from '../../layouts/DataLayout';
3
+ // --- PAGE IMPORTS ---
4
+ // ✅ Corrected: Kept named import for OverviewPage based on your index.ts export
5
+ import { OverviewPage } from '../../features/overview';
6
+ import AiChat from '../../features/ai/pages/AiChat';
10
7
 
11
- // Style Guide Section Imports
12
- import TemplatesSection from '../../pages/styleguide/sections/templates/TemplatesSection';
13
- import LayoutSection from '../../pages/styleguide/sections/layout/LayoutSection';
14
- import ThemingSection from '../../pages/styleguide/sections/theming/ThemingSection';
15
- import NavigationSection from '../../pages/styleguide/sections/navigation/NavigationSection';
16
- import TablesSection from '../../pages/styleguide/sections/tables/TablesSection';
17
- import ChartsSection from '../../pages/styleguide/sections/charts/ChartsSection';
18
- import ElementsSection from '../../pages/styleguide/sections/elements/ElementsSection';
19
- import FormsSection from '../../pages/styleguide/sections/forms/FormsSection';
20
- import FeedbackSection from '../../pages/styleguide/sections/feedback/FeedbackSection';
21
- import UtilitiesSection from '../../pages/styleguide/sections/utilities/UtilitiesSection';
22
- import ColorsSection from '../../pages/styleguide/sections/colors/ColorsSection';
23
- import IconsSection from '../../pages/styleguide/sections/icons/IconsSection';
8
+ import Styleguide from '../../features/styleguide/Styleguide';
9
+
10
+ // --- SECTION IMPORTS ---
11
+ import TemplatesSection from '../../features/styleguide/sections/templates/TemplatesSection';
12
+ import LayoutSection from '../../features/styleguide/sections/layout/LayoutSection';
13
+ import ThemingSection from '../../features/styleguide/sections/theming/ThemingSection';
14
+ import NavigationSection from '../../features/styleguide/sections/navigation/NavigationSection';
15
+ import TablesSection from '../../features/styleguide/sections/tables/TablesSection';
16
+ import ChartsSection from '../../features/styleguide/sections/charts/ChartsSection';
17
+ import ElementsSection from '../../features/styleguide/sections/elements/ElementsSection';
18
+ import FormsSection from '../../features/styleguide/sections/forms/FormsSection';
19
+ import FeedbackSection from '../../features/styleguide/sections/feedback/FeedbackSection';
20
+ import UtilitiesSection from '../../features/styleguide/sections/utilities/UtilitiesSection';
21
+ import ColorsSection from '../../features/styleguide/sections/colors/ColorsSection';
22
+ import IconsSection from '../../features/styleguide/sections/icons/IconsSection';
24
23
 
25
24
  export const docsSitemap: SitemapEntry[] = [
26
25
  {
27
26
  id: 'dashboard',
28
- path: '', // Index route for the /docs/ layout
27
+ path: '', // Index route
29
28
  title: 'Dashboard',
30
29
  icon: 'home',
31
- component: Dashboard,
30
+ component: OverviewPage,
32
31
  },
33
32
  {
34
33
  id: 'ai-chat',
@@ -37,17 +36,6 @@ export const docsSitemap: SitemapEntry[] = [
37
36
  icon: 'bot',
38
37
  component: AiChat,
39
38
  },
40
- {
41
- id: 'data',
42
- path: 'data',
43
- title: 'Data',
44
- icon: 'database',
45
- component: DataLayout,
46
- children: [
47
- { id: 'grid', path: 'grid', title: 'Data Grid', component: DataGridPage, icon: 'table' },
48
- { id: 'ledger', path: 'ledger', title: 'Ledger', component: AccountingLedgerPage, icon: 'book-open' },
49
- ],
50
- },
51
39
  {
52
40
  id: 'styleguide',
53
41
  path: 'styleguide',
@@ -1,170 +1,110 @@
1
- /**
2
- * @file SettingsLayout.tsx
3
- * @repository ramme-app-starter
4
- * @description
5
- * Sidebar-Only layout. Moved TemplateSwitcher to SidebarContent.
6
- * Includes all previous fixes (href, icons, conditional branding, providers, etc.).
7
- * Confirmed handleResetData is included.
8
- */
9
- import React from 'react';
10
- import { Outlet, NavLink, Link } from 'react-router-dom';
1
+ import React, { useMemo } from 'react';
2
+ import { Outlet, useNavigate, useLocation } from 'react-router-dom';
11
3
  import {
12
4
  Sidebar,
13
- SidebarProvider,
14
- SidebarHeader,
15
- SidebarContent,
16
- SidebarFooter,
17
- SidebarMenu,
18
- SidebarMenuItem,
19
- useSidebar,
20
- Button,
21
- Icon,
22
- Avatar,
23
- Menu,
24
- MenuItem,
25
- MenuDivider,
26
- useTheme,
27
- type ThemeName,
5
+ type SidebarItem,
6
+ type IconName,
28
7
  } from '@ramme-io/ui';
29
8
  import { settingsSitemap } from './settings.sitemap';
30
9
  import rammeLogo from '../../assets/orange.png';
31
- import { useAuth } from '../../contexts/AuthContext';
32
- import { appManifest } from '../../config/navigation';
33
- import type { ManifestLink } from '../../core/manifest-types';
34
- import { SitemapProvider } from '../../contexts/SitemapContext';
10
+ import { useAuth } from '../../features/auth/AuthContext';
11
+ import { SitemapProvider } from '../../engine/runtime/SitemapContext';
35
12
  import PageTitleUpdater from '../../components/PageTitleUpdater';
36
- // --- Import TemplateSwitcher ---
37
13
  import TemplateSwitcher from '../../components/TemplateSwitcher';
38
14
 
39
- // NavLink wrapper - Correctly maps href to 'to'
40
- const SidebarNavLink = React.forwardRef<HTMLAnchorElement, any>(
41
- ({ end, href, ...props }, ref) => {
42
- return <NavLink ref={ref} to={href || ''} {...props} end={end} />;
43
- },
44
- );
45
- SidebarNavLink.displayName = 'SidebarNavLink';
46
-
47
- // Sidebar Content Component
48
- const AppSidebarContent: React.FC = () => {
49
- const { isOpen, toggle } = useSidebar();
50
- const { theme, availableThemes, setTheme } = useTheme();
15
+ const SettingsLayout: React.FC = () => {
16
+ const navigate = useNavigate();
17
+ const location = useLocation();
51
18
  const { user, logout } = useAuth();
52
- const userNavLinks = appManifest.userMenu;
53
19
 
54
- // --- handleResetData function remains here ---
20
+ // --- Actions ---
55
21
  const handleResetData = () => {
56
- if (
57
- window.confirm(
58
- 'Are you sure you want to reset all user data? This cannot be undone.',
59
- )
60
- ) {
22
+ if (window.confirm('Are you sure you want to reset all user data? This cannot be undone.')) {
61
23
  localStorage.removeItem('users');
62
24
  window.location.reload();
63
25
  }
64
26
  };
65
27
 
66
- return (
67
- <>
68
- <SidebarHeader>
69
- {/* Header now only contains Branding and Toggle */}
70
- <div className={`flex items-center w-full h-full ${isOpen ? 'justify-between' : 'justify-end'}`}>
71
- {/* Branding Link */}
72
- <Link
73
- to="/settings"
74
- className={`flex items-center gap-2 transition-opacity duration-200 ${!isOpen ? 'opacity-0 hidden' : 'opacity-100'}`}
75
- aria-hidden={!isOpen} tabIndex={!isOpen ? -1 : undefined}
76
- >
77
- <img src={rammeLogo} alt="Ramme Logo" className="h-7 w-auto" />
78
- <span className="text-xl font-bold text-text">Ramme</span>
79
- </Link>
80
-
81
- {/* TemplateSwitcher REMOVED from here */}
28
+ // --- Data Mapping ---
29
+ // We combine the Sitemap navigation with the System Actions (Reset/Logout)
30
+ // so they all live harmoniously in the new "Zero Jank" sidebar list.
31
+ const sidebarItems: SidebarItem[] = useMemo(() => {
32
+ // 1. Navigation Items
33
+ const navItems: SidebarItem[] = settingsSitemap.map((item) => ({
34
+ id: item.id,
35
+ label: item.title,
36
+ icon: (item.icon as IconName) || 'settings',
37
+ href: item.path ? `/settings/${item.path}` : '/settings',
38
+ }));
82
39
 
83
- {/* Toggle Button */}
84
- <Button
85
- variant="ghost" size="icon" onClick={toggle}
86
- className="hidden md:flex"
87
- aria-label={isOpen ? 'Collapse sidebar' : 'Expand sidebar'}
88
- >
89
- <Icon name={isOpen ? 'panel-left-close' : 'panel-left-open'} />
90
- </Button>
91
- </div>
92
- </SidebarHeader>
40
+ // 2. System Actions (Appended to bottom)
41
+ const actionItems: SidebarItem[] = [
42
+ {
43
+ id: 'action-reset',
44
+ label: 'Reset Data',
45
+ icon: 'refresh-cw' as IconName,
46
+ onClick: handleResetData,
47
+ },
48
+ {
49
+ id: 'action-logout',
50
+ label: 'Logout',
51
+ icon: 'log-out' as IconName,
52
+ onClick: logout,
53
+ }
54
+ ];
93
55
 
94
- <SidebarContent>
95
- {/* --- MOVED TemplateSwitcher HERE --- */}
96
- {/* Only visible when sidebar is open */}
97
- <div className={`mb-4 transition-opacity duration-200 ${!isOpen ? 'opacity-0 hidden' : 'opacity-100'}`}>
98
- <TemplateSwitcher />
99
- </div>
56
+ return [...navItems, ...actionItems];
57
+ }, [logout]);
100
58
 
101
- {/* --- Sitemap Menu --- */}
102
- <SidebarMenu>
103
- {settingsSitemap.map((item) => (
104
- <SidebarMenuItem
105
- key={item.id} as={SidebarNavLink}
106
- href={item.path ? `/settings/${item.path}` : '/settings'} end
107
- icon={item.icon ? <Icon name={item.icon} /> : undefined}
108
- tooltip={item.title}
109
- >
110
- {item.title}
111
- </SidebarMenuItem>
112
- ))}
113
- </SidebarMenu>
114
- </SidebarContent>
59
+ // Determine active item (only for nav items, actions don't stay active)
60
+ const activeItemId = useMemo(() => {
61
+ const active = sidebarItems.find(item =>
62
+ item.href && item.href !== '/settings' && location.pathname.startsWith(item.href)
63
+ );
64
+ return active?.id || (location.pathname === '/settings' ? sidebarItems[0]?.id : undefined);
65
+ }, [location.pathname, sidebarItems]);
115
66
 
116
- <SidebarFooter>
117
- {user && (
118
- <Menu position="top-right" trigger={
119
- <button className="flex items-center gap-3 w-full text-left rounded-md p-2 hover:bg-muted focus:outline-none focus:ring-2 focus:ring-primary">
120
- <Avatar name={user.name} size="sm" />
121
- <div className={`flex-1 transition-opacity duration-200 ${!isOpen ? 'opacity-0 hidden' : 'opacity-100'}`}>
122
- <p className="font-semibold text-sm text-text">{user.name}</p>
123
- <p className="text-xs text-muted-foreground">{user.email}</p>
124
- </div>
125
- </button>
126
- }>
127
- {/* User Menu Content */}
128
- {userNavLinks.map((link: ManifestLink) => (
129
- <MenuItem key={link.id} asChild icon={link.icon ? <Icon name={link.icon} /> : undefined}>
130
- <Link to={link.path}>{link.title}</Link>
131
- </MenuItem>
132
- ))}
133
- <MenuDivider />
134
- {availableThemes.map((themeName: string) => (
135
- <MenuItem key={themeName} onClick={() => setTheme(themeName as ThemeName)}>
136
- {themeName.charAt(0).toUpperCase() + themeName.slice(1)}
137
- </MenuItem>
138
- ))}
139
- <MenuDivider />
140
- {/* Calls handleResetData */}
141
- <MenuItem onClick={handleResetData} icon={<Icon name="refresh-cw" />}> Reset Data </MenuItem>
142
- {/* Calls logout */}
143
- <MenuItem onClick={logout} icon={<Icon name="log-out" />}> Logout </MenuItem>
144
- </Menu>
145
- )}
146
- </SidebarFooter>
147
- </>
148
- );
149
- };
150
-
151
- // Main layout component
152
- const SettingsLayout: React.FC = () => {
153
67
  return (
154
68
  <SitemapProvider value={settingsSitemap}>
155
69
  <PageTitleUpdater />
156
- <SidebarProvider>
157
- <div className="flex h-screen bg-background text-foreground">
158
- <Sidebar>
159
- <AppSidebarContent />
160
- </Sidebar>
161
- <div className="flex flex-col flex-1 overflow-y-auto">
162
- <main className="p-8">
163
- <Outlet />
164
- </main>
165
- </div>
70
+
71
+ <div className="flex h-screen bg-background text-foreground">
72
+ <Sidebar
73
+ className="relative border-border"
74
+ items={sidebarItems}
75
+ activeItemId={activeItemId}
76
+ // Handle both Navigation (href) and Actions (onClick)
77
+ onNavigate={(item) => {
78
+ if (item.href) {
79
+ navigate(item.href);
80
+ }
81
+ // item.onClick is handled automatically by the Sidebar component if present
82
+ }}
83
+ user={user ? {
84
+ name: user.name,
85
+ email: user.email,
86
+ avatarUrl: undefined // Add avatar URL if available in user object
87
+ } : undefined}
88
+ logo={
89
+ <div className="flex items-center gap-2 px-2">
90
+ <img src={rammeLogo} alt="Ramme" className="h-7 w-auto" />
91
+ <span className="text-xl font-bold">Ramme</span>
92
+ </div>
93
+ }
94
+ // Inject the TemplateSwitcher into the footer slot (above the user profile)
95
+ footerSlot={
96
+ <div className="mb-2">
97
+ <TemplateSwitcher />
98
+ </div>
99
+ }
100
+ />
101
+
102
+ <div className="flex flex-col flex-1 overflow-hidden">
103
+ <main className="flex-1 overflow-y-auto p-8 bg-muted/20">
104
+ <Outlet />
105
+ </main>
166
106
  </div>
167
- </SidebarProvider>
107
+ </div>
168
108
  </SitemapProvider>
169
109
  );
170
110
  };
@@ -5,19 +5,19 @@
5
5
  * Defines the Information Architecture (IA) for the "Settings" layout.
6
6
  * Imports components from the /pages/settings/ directory.
7
7
  */
8
- import type { SitemapEntry } from '../../core/sitemap-entry';
8
+ import type { SitemapEntry } from '../../engine/types/sitemap-entry';
9
9
 
10
10
  // --- 1. Import from the new /pages/settings/ directory ---
11
- import ProfilePage from '../../pages/settings/ProfilePage';
12
- import BillingPage from '../../pages/settings/BillingPage';
13
- import TeamPage from '../../pages/settings/TeamPage';
11
+ import ProfilePage from '../../features/settings/pages/ProfilePage';
12
+ import BillingPage from '../../features/settings/pages/BillingPage';
13
+ import TeamPage from '../../features/settings/pages/TeamPage';
14
14
 
15
15
  // --- 2. Export with the correct name ---
16
16
  export const settingsSitemap: SitemapEntry[] = [
17
17
  {
18
- id: 'settings.profile',
18
+ id: 'profile',
19
19
  path: 'profile',
20
- title: 'Profile',
20
+ title: 'My Profile',
21
21
  icon: 'user',
22
22
  component: ProfilePage,
23
23
  },
@@ -2,22 +2,25 @@ import { defineConfig } from 'vite';
2
2
  import react from '@vitejs/plugin-react';
3
3
  import path from 'path';
4
4
 
5
- // https://vitejs.dev/config/
6
5
  export default defineConfig({
7
6
  plugins: [react()],
8
7
  resolve: {
9
8
  alias: {
10
9
  '@': path.resolve(__dirname, './src'),
10
+
11
+ // ✅ FIX: Go up 2 levels to find the sibling 'ramme-ui' folder
12
+ '@ramme-io/ui': path.resolve(__dirname, '../../ramme-ui/src'),
11
13
  },
12
14
  },
13
- // ADD THIS SECTION to ensure the linked dependency is correctly
14
- // processed and watched for changes by the Vite dev server.
15
- optimizeDeps: {
16
- include: ['@ramme-io/ui'],
17
- },
18
- build: {
19
- commonjsOptions: {
20
- include: [/@ramme\/ui/, /node_modules/],
15
+ // CRITICAL: Allow Vite to serve files outside the current project folder
16
+ server: {
17
+ fs: {
18
+ allow: [
19
+ // Allow serving files from the project root
20
+ '.',
21
+ // Allow serving files from the sibling UI library
22
+ '../../ramme-ui',
23
+ ],
21
24
  },
22
25
  },
23
26
  });
File without changes
@@ -1,120 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { NavLink, useLocation } from 'react-router-dom';
3
- import { Icon, type IconName } from '@ramme-io/ui';
4
- import { motion, AnimatePresence } from 'framer-motion';
5
-
6
- export interface NavItem {
7
- label: string;
8
- href: string;
9
- icon?: IconName;
10
- children?: NavItem[];
11
- }
12
-
13
- interface LocalSideNavProps {
14
- navItems: NavItem[];
15
- className?: string;
16
- onLinkClick?: () => void; // 1. Add the optional prop
17
- }
18
-
19
- const LocalSideNav: React.FC<LocalSideNavProps> = ({ navItems, className, onLinkClick }) => { // 2. Destructure prop
20
- const location = useLocation();
21
- const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>({});
22
-
23
- useEffect(() => {
24
- const currentParent = navItems.find(item =>
25
- item.children?.some(child => location.pathname === child.href)
26
- );
27
- if (currentParent) {
28
- setExpandedItems(prev => ({ ...prev, [currentParent.href]: true }));
29
- }
30
- }, [location.pathname, navItems]);
31
-
32
- const handleToggle = (href: string) => {
33
- setExpandedItems(prev => ({ ...prev, [href]: !prev[href] }));
34
- };
35
-
36
- const childNavLinkClasses = ({ isActive }: { isActive: boolean }) =>
37
- `flex items-center gap-2 text-sm transition-colors duration-200 py-1 ${
38
- isActive
39
- ? 'text-primary font-medium'
40
- : 'text-muted-foreground hover:text-text'
41
- }`;
42
-
43
- const renderNavLinks = (items: NavItem[]) => {
44
- return items.map(item => {
45
- const isExpanded = !!expandedItems[item.href];
46
-
47
- if (item.children) {
48
- return (
49
- //Section link
50
- <li key={item.href}>
51
- <button
52
- onClick={() => handleToggle(item.href)}
53
- className="flex w-full items-center justify-between gap-2 py-1 font-normal text-text transition-colors duration-200 hover:text-primary"
54
- >
55
- <span className="flex items-center gap-2">
56
- {item.icon && <Icon name={item.icon} className="h-4 w-4" />}
57
- <span className="text-md">{item.label}</span>
58
- </span>
59
- <Icon
60
- name="chevron-right"
61
- className={`h-4 w-4 transition-transform duration-200 ${isExpanded ? 'rotate-90' : ''}`}
62
- />
63
- </button>
64
- <AnimatePresence initial={false}>
65
- {isExpanded && (
66
- <motion.ul
67
- key="content"
68
- initial="collapsed"
69
- animate="open"
70
- exit="collapsed"
71
- variants={{
72
- open: { opacity: 1, height: 'auto' },
73
- collapsed: { opacity: 0, height: 0 },
74
- }}
75
- transition={{ duration: 0.3, ease: 'easeInOut' }}
76
- className="space-y-1 overflow-hidden border-l border-border pl-5 mt-1 ml-1"
77
- >
78
- {item.children.map(child => (
79
- <li key={child.href}>
80
- <NavLink
81
- to={child.href}
82
- className={childNavLinkClasses}
83
- onClick={onLinkClick} // 3. Add onClick to child NavLink
84
- >
85
- {child.label}
86
- </NavLink>
87
- </li>
88
- ))}
89
- </motion.ul>
90
- )}
91
- </AnimatePresence>
92
- </li>
93
- );
94
- }
95
-
96
- return (
97
- <li key={item.href}>
98
- <NavLink
99
- to={item.href}
100
- className="flex items-center gap-2 py-1 text-lg font-semibold"
101
- onClick={onLinkClick} // 3. Add onClick to top-level NavLink
102
- >
103
- {item.icon && <Icon name={item.icon} className="h-4 w-4" />}
104
- {item.label}
105
- </NavLink>
106
- </li>
107
- );
108
- });
109
- };
110
-
111
- return (
112
- <nav className={`w-full ${className || ''}`}>
113
- <ul className="space-y-1">
114
- {renderNavLinks(navItems)}
115
- </ul>
116
- </nav>
117
- );
118
- };
119
-
120
- export default LocalSideNav;