@ramme-io/create-app 1.2.1 → 1.2.5

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 (102) hide show
  1. package/package.json +9 -15
  2. package/template/package.json +41 -0
  3. package/template/pkg.json +9 -7
  4. package/template/src/App.tsx +72 -31
  5. package/template/src/components/AIChatWidget.tsx +2 -2
  6. package/template/src/components/AppHeader.tsx +12 -12
  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/components/dashboard/ChartLine.tsx +28 -0
  13. package/template/src/components/dashboard/StatCard.tsx +61 -0
  14. package/template/src/config/app.manifest.ts +3 -1
  15. package/template/src/config/component-registry.tsx +69 -0
  16. package/template/src/config/navigation.ts +1 -1
  17. package/template/src/data/mock-charts.ts +32 -28
  18. package/template/src/{components → engine/renderers}/DynamicBlock.tsx +28 -8
  19. package/template/src/engine/renderers/DynamicPage.tsx +150 -0
  20. package/template/src/engine/runtime/ManifestContext.tsx +79 -0
  21. package/template/src/{contexts → engine/runtime}/MqttContext.tsx +23 -14
  22. package/template/src/{contexts → engine/runtime}/SitemapContext.tsx +1 -1
  23. package/template/src/engine/runtime/data-seeder.ts +47 -0
  24. package/template/src/{hooks → engine/runtime}/useAction.ts +11 -14
  25. package/template/src/{hooks → engine/runtime}/useCrudLocalStorage.ts +27 -8
  26. package/template/src/{hooks → engine/runtime}/useDataQuery.ts +15 -1
  27. package/template/src/engine/runtime/useDynamicSitemap.tsx +43 -0
  28. package/template/src/engine/runtime/useJustInTimeSeeder.ts +76 -0
  29. package/template/src/engine/runtime/useLiveBridge.ts +44 -0
  30. package/template/src/engine/runtime/useSignal.ts +40 -0
  31. package/template/src/{generated/hooks.ts → engine/runtime/useSignalStore.ts} +35 -8
  32. package/template/src/engine/runtime/useWorkflowEngine.ts +89 -0
  33. package/template/src/{core → engine/types}/manifest-types.ts +35 -3
  34. package/template/src/{types → engine/validation}/schema.ts +17 -0
  35. package/template/src/{pages → features/ai/pages}/AiChat.tsx +1 -1
  36. package/template/src/features/auth/AuthContext.tsx +118 -0
  37. package/template/src/features/auth/pages/AuthLayout.tsx +55 -0
  38. package/template/src/features/auth/pages/LoginPage.tsx +106 -0
  39. package/template/src/features/auth/pages/SignupPage.tsx +96 -0
  40. package/template/src/{blocks → features/datagrid}/SmartTable.tsx +41 -25
  41. package/template/src/features/developer/GhostOverlay.tsx +114 -0
  42. package/template/src/{pages → features/onboarding/pages}/Welcome.tsx +0 -1
  43. package/template/src/features/overview/index.ts +1 -0
  44. package/template/src/features/overview/pages/OverviewPage.tsx +127 -0
  45. package/template/src/{pages → features/playground/pages}/AccountingLedgerPage.tsx +1 -1
  46. package/template/src/{pages/prototypes → features/playground/pages}/ItemSelectorPage.tsx +1 -1
  47. package/template/src/{pages/settings → features/settings/pages}/BillingPage.tsx +1 -1
  48. package/template/src/features/settings/pages/ProfilePage.tsx +153 -0
  49. package/template/src/{pages/settings → features/settings/pages}/TeamPage.tsx +1 -1
  50. package/template/src/features/styleguide/Styleguide.tsx +75 -0
  51. package/template/src/features/users/components/UserDrawer.tsx +138 -0
  52. package/template/src/features/users/index.ts +2 -0
  53. package/template/src/features/users/pages/UsersPage.tsx +151 -0
  54. package/template/src/features/visualizations/SmartChart.tsx +178 -0
  55. package/template/src/index.css +1 -1
  56. package/template/src/main.tsx +27 -15
  57. package/template/src/templates/dashboard/DashboardLayout.tsx +77 -107
  58. package/template/src/templates/dashboard/dashboard.sitemap.ts +19 -22
  59. package/template/src/templates/docs/DocsLayout.tsx +49 -38
  60. package/template/src/templates/docs/docs.sitemap.ts +22 -34
  61. package/template/src/templates/settings/SettingsLayout.tsx +83 -143
  62. package/template/src/templates/settings/settings.sitemap.ts +6 -6
  63. package/template/tailwind.config.cjs +10 -9
  64. package/template/vite.config.ts +0 -11
  65. package/template/src/adaptors/.gitkeep +0 -0
  66. package/template/src/components/LocalSideNav.tsx +0 -120
  67. package/template/src/components/PageWithSideNav.tsx +0 -69
  68. package/template/src/components/dev/GhostOverlay.tsx +0 -68
  69. package/template/src/config/dashboard.layout.ts +0 -110
  70. package/template/src/contexts/AuthContext.tsx +0 -64
  71. package/template/src/core/component-registry.tsx +0 -56
  72. package/template/src/core/data-seeder.ts +0 -35
  73. package/template/src/data/mockUsers.ts +0 -18
  74. package/template/src/hooks/useSignal.ts +0 -83
  75. package/template/src/hooks/useWorkflowEngine.ts +0 -123
  76. package/template/src/layouts/DataLayout.tsx +0 -37
  77. package/template/src/layouts/SideNavLayout.tsx +0 -28
  78. package/template/src/pages/Dashboard.tsx +0 -60
  79. package/template/src/pages/DataGridPage.tsx +0 -184
  80. package/template/src/pages/DynamicPage.tsx +0 -95
  81. package/template/src/pages/LoginPage.tsx +0 -58
  82. package/template/src/pages/settings/ProfilePage.tsx +0 -10
  83. package/template/src/pages/styleguide/Styleguide.tsx +0 -40
  84. package/template/src/templates/docs/pages/Introduction.tsx +0 -13
  85. package/template/src/types/signal.ts +0 -23
  86. /package/template/src/{core → engine/renderers}/route-generator.tsx +0 -0
  87. /package/template/src/{core → engine/types}/sitemap-entry.ts +0 -0
  88. /package/template/src/{pages → features}/GenericContentPage.tsx +0 -0
  89. /package/template/src/{hooks → features/assistant}/useMockChat.ts +0 -0
  90. /package/template/src/{hooks → features/developer}/useDevTools.ts +0 -0
  91. /package/template/src/{pages → features}/styleguide/sections/charts/ChartsSection.tsx +0 -0
  92. /package/template/src/{pages → features}/styleguide/sections/colors/ColorsSection.tsx +0 -0
  93. /package/template/src/{pages → features}/styleguide/sections/elements/ElementsSection.tsx +0 -0
  94. /package/template/src/{pages → features}/styleguide/sections/feedback/FeedbackSection.tsx +0 -0
  95. /package/template/src/{pages → features}/styleguide/sections/forms/FormsSection.tsx +0 -0
  96. /package/template/src/{pages → features}/styleguide/sections/icons/IconsSection.tsx +0 -0
  97. /package/template/src/{pages → features}/styleguide/sections/layout/LayoutSection.tsx +0 -0
  98. /package/template/src/{pages → features}/styleguide/sections/navigation/NavigationSection.tsx +0 -0
  99. /package/template/src/{pages → features}/styleguide/sections/tables/TablesSection.tsx +0 -0
  100. /package/template/src/{pages → features}/styleguide/sections/templates/TemplatesSection.tsx +0 -0
  101. /package/template/src/{pages → features}/styleguide/sections/theming/ThemingSection.tsx +0 -0
  102. /package/template/src/{pages → features}/styleguide/sections/utilities/UtilitiesSection.tsx +0 -0
@@ -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
  },
@@ -1,18 +1,19 @@
1
- const path = require('path');
2
-
3
- // This finds the absolute path to the @ramme-io/ui package's directory
4
- const rammeUiPath = path.dirname(require.resolve('@ramme-io/ui/package.json'));
5
-
6
1
  /** @type {import('tailwindcss').Config} */
7
2
  module.exports = {
8
3
  presets: [
9
- // Load the preset from the absolute path we found
10
- require(path.join(rammeUiPath, 'tailwind.preset.js'))
4
+ // STANDARD: Directly require the preset from the package
5
+ require('@ramme-io/ui/tailwind.preset.js')
11
6
  ],
12
7
  content: [
13
8
  "./index.html",
14
9
  "./src/**/*.{js,ts,jsx,tsx}",
15
- // Scan the library's files for classes using the absolute path
16
- path.join(rammeUiPath, 'dist/**/*.js'),
10
+
11
+ // ✅ STANDARD: Point directly to node_modules relative to this config file
12
+ // This is the industry standard way (like how Flowbite or Shadcn work)
13
+ "./node_modules/@ramme-io/ui/dist/**/*.{js,ts,jsx,tsx}"
17
14
  ],
15
+ theme: {
16
+ extend: {},
17
+ },
18
+ plugins: [],
18
19
  }
@@ -2,7 +2,6 @@ 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: {
@@ -10,14 +9,4 @@ export default defineConfig({
10
9
  '@': path.resolve(__dirname, './src'),
11
10
  },
12
11
  },
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/],
21
- },
22
- },
23
12
  });
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;
@@ -1,69 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { Button, Drawer, Icon } from '@ramme-io/ui';
3
- import LocalSideNav from './LocalSideNav';
4
- import type { NavItem } from './LocalSideNav';
5
-
6
- interface PageWithSideNavProps {
7
- navItems: NavItem[];
8
- children: React.ReactNode;
9
- sideNavHeader?: React.ReactNode;
10
- contentWidth?: 'fixed' | 'full';
11
- }
12
-
13
- export const PageWithSideNav: React.FC<PageWithSideNavProps> = ({
14
- navItems,
15
- children,
16
- sideNavHeader,
17
- contentWidth = 'fixed',
18
- }) => {
19
- const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
20
-
21
- const contentContainerClass = contentWidth === 'fixed'
22
- ? 'max-w-7xl mx-auto'
23
- : '';
24
-
25
- return (
26
- <div className="flex flex-col md:flex-row h-full">
27
- {/* --- Mobile Header --- */}
28
- <div className="md:hidden p-4 bg-card border-b border-border flex items-center justify-between sticky top-[65px] z-10">
29
- {sideNavHeader}
30
- <Button onClick={() => setIsMobileNavOpen(true)} variant="ghost" size="icon">
31
- <Icon name="panel-left" />
32
- </Button>
33
- </div>
34
-
35
- {/* --- Desktop Sidebar --- */}
36
- <aside className="hidden md:flex flex-col w-64 border-r border-border p-4 sticky top-[65px] h-[calc(100vh-65px)]">
37
- {sideNavHeader}
38
- <LocalSideNav navItems={navItems} className="mt-1" />
39
- </aside>
40
-
41
- {/* --- Mobile Drawer --- */}
42
- <Drawer
43
- isOpen={isMobileNavOpen}
44
- onClose={() => setIsMobileNavOpen(false)}
45
- position="left"
46
- >
47
- <div className="p-4">
48
- <Button
49
- onClick={() => setIsMobileNavOpen(false)}
50
- variant="ghost"
51
- size="icon"
52
- className="absolute top-4 right-4"
53
- >
54
- <Icon name="x" />
55
- </Button>
56
- <div className="mt-2">{sideNavHeader}</div>
57
- <LocalSideNav navItems={navItems} onLinkClick={() => setIsMobileNavOpen(false)} />
58
- </div>
59
- </Drawer>
60
-
61
- {/* --- Main Content --- */}
62
- <main className="flex-1 p-6 overflow-y-auto">
63
- <div className={contentContainerClass}>
64
- {children}
65
- </div>
66
- </main>
67
- </div>
68
- );
69
- };